From 5a20d342adbe771fd348e46b5c51726749124493 Mon Sep 17 00:00:00 2001 From: Mathias Herberts Date: Sun, 8 Oct 2023 12:23:46 +0100 Subject: [PATCH 001/241] Fr.fixes.v4.9.2 (#1116) * Fixed typo * Fixes of French localization --- res/values/strings_en.arb | 2 +- res/values/strings_fr.arb | 86 +++++++++++++++++++-------------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 9ba95dd44..b981c0177 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -689,7 +689,7 @@ "support_title_guides": "Cake Wallet guides", "support_description_guides": "Documentation and support for common issues", "support_title_other_links": "Other support links", - "support_description_other_links": "Join our communities or reach us our our partners through other methods", + "support_description_other_links": "Join our communities or reach us or our partners through other methods", "choose_derivation": "Choose Wallet Derivation", "new_first_wallet_text": "Keep your crypto safe, piece of cake", "select_destination": "Please select destination for the backup file.", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 0b39ef4ff..f2e336040 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -21,7 +21,7 @@ "contact_name": "Nom de Contact", "reset": "Réinitialiser", "save": "Sauvegarder", - "address_remove_contact": "Supprimer contact", + "address_remove_contact": "Supprimer le contact", "address_remove_content": "Êtes vous certain de vouloir supprimer le contact sélectionné ?", "authenticated": "Authentifié", "authentication": "Authentification", @@ -67,8 +67,8 @@ "min_value": "Min: ${value} ${currency}", "max_value": "Max: ${value} ${currency}", "change_currency": "Changer de Devise", - "overwrite_amount": "Écraser montant", - "qr_payment_amount": "Ce QR code contient un montant de paiement. Voulez-vous écraser la valeur actuelle ?", + "overwrite_amount": "Remplacer le montant", + "qr_payment_amount": "Ce QR code contient un montant de paiement. Voulez-vous remplacer la valeur actuelle ?", "copy_id": "Copier l'ID", "exchange_result_write_down_trade_id": "Merci de copier ou d'écrire l'ID d'échange pour continuer.", "trade_id": "ID d'échange :", @@ -109,7 +109,7 @@ "nodes": "Nœuds", "node_reset_settings_title": "Réinitialisation des réglages", "nodes_list_reset_to_default_message": "Êtes vous certain de vouloir revenir aux réglages par défaut ?", - "change_current_node": "Êtes vous certain de vouloir changer le nœud actuel vers ${node} ?", + "change_current_node": "Êtes vous certain de vouloir changer le nœud actuel pour ${node} ?", "change": "Changer", "remove_node": "Supprimer le nœud", "remove_node_message": "Êtes vous certain de vouloir supprimer le nœud sélectionné ?", @@ -269,7 +269,7 @@ "error_text_address": "L'adresse du portefeuille (wallet) doit correspondre au type de\ncryptomonnaie", "error_text_node_address": "Merci d'entrer une adresse IPv4", "error_text_node_port": "Le port d'un nœud doit être un nombre compris entre 0 et 65535", - "error_text_node_proxy_address": "Veuillez saisir :, par exemple 127.0.0.1:9050", + "error_text_node_proxy_address": "Veuillez saisir :, par exemple 127.0.0.1:9050", "error_text_payment_id": "Un ID de paiement ne peut être constitué que de 16 à 64 caractères hexadécimaux", "error_text_xmr": "La valeur de XMR dépasse le solde disponible.\nLa partie décimale doit comporter au plus 12 chiffres", "error_text_fiat": "La valeur du montant ne peut dépasser le solde disponible.\nLa partie décimale doit comporter au plus 2 chiffres", @@ -350,7 +350,7 @@ "seed_alert_yes": "Oui, je suis sûr", "exchange_sync_alert_content": "Merci d'attendre que votre portefeuille (wallet) soit synchronisé", "pre_seed_title": "IMPORTANT", - "pre_seed_description": "Sur la page suivante vous allez voir une série de ${words} mots. Ils constituent votre phrase secrète (seed) unique et privé et sont le SEUL moyen de restaurer votre portefeuille (wallet) en cas de perte ou de dysfonctionnement. Il est de VOTRE responsabilité d'écrire cette série de mots et de les stocker dans un lieu sûr en dehors de l'application Cake Wallet.", + "pre_seed_description": "Sur la page suivante vous allez voir une série de ${words} mots. Ils constituent votre phrase secrète (seed) unique et privée et sont le SEUL moyen de restaurer votre portefeuille (wallet) en cas de perte ou de dysfonctionnement. Il est de VOTRE responsabilité d'écrire cette série de mots et de la stocker dans un lieu sûr en dehors de l'application Cake Wallet.", "pre_seed_button_text": "J'ai compris. Montrez moi ma phrase secrète (seed)", "xmr_to_error": "Erreur XMR.TO", "xmr_to_error_description": "Montant invalide. La partie décimale doit contenir au plus 8 chiffres", @@ -409,15 +409,15 @@ "unspent_coins_details_title": "Détails des pièces (coins) non dépensées", "freeze": "Geler", "frozen": "Gelées", - "coin_control": "Contrôle des pièces (optionnel)", + "coin_control": "Contrôle optionnel des pièces (coins)", "address_detected": "Adresse détectée", "address_from_domain": "Cette adresse est issue de ${domain} sur Unstoppable Domains", "add_receiver": "Ajouter un autre bénéficiaire (optionnel)", "manage_yats": "Gérer les Yats", "yat_alert_title": "Envoyez et recevez des cryptos plus facilement avec Yat", - "yat_alert_content": "Les utilisateurs de Cake Wallet peuvent maintenant envoyer et recevoir leurs monnaies favories avec un utilisateur unique en son genre basé sur les emojis.", - "get_your_yat": "Obtenez votre Yat", - "connect_an_existing_yat": "Connectez un Yat existant", + "yat_alert_content": "Les utilisateurs de Cake Wallet peuvent maintenant envoyer et recevoir leurs monnaies favorites avec un utilisateur unique en son genre basé sur les emojis.", + "get_your_yat": "Obtenir votre Yat", + "connect_an_existing_yat": "Connecter un Yat existant", "connect_yats": "Connecter Yats", "yat_address": "Adresse Yat", "yat": "Yat", @@ -427,13 +427,13 @@ "choose_address": "\n\nMerci de choisir l'adresse :", "yat_popup_title": "L'adresse de votre portefeuille (wallet) peut être emojifiée.", "yat_popup_content": "Vous pouvez à présent envoyer et recevoir des cryptos dans Cake Wallet à l'aide de votre Yat - un nom d'utilisateur court à base d'emoji. Gérér les Yats à tout moment depuis l'écran de paramétrage", - "second_intro_title": "Une adresse emoji pour les gouverner tous", + "second_intro_title": "Une adresse emoji pour les gouverner toutes", "second_intro_content": "Votre Yat est une seule et unique adresse emoji qui remplace toutes vos longues adresses hexadécimales pour toutes vos cryptomonnaies.", - "third_intro_title": "Yat joue bien avec les autres", + "third_intro_title": "Yat est universel", "third_intro_content": "Les Yats existent aussi en dehors de Cake Wallet. Toute adresse sur terre peut être remplacée par un Yat !", "learn_more": "En savoir plus", "search": "Chercher", - "search_language": "Recherche une langue", + "search_language": "Rechercher une langue", "search_currency": "Rechercher une devise", "new_template": "Nouveau Modèle", "electrum_address_disclaimer": "Nous générons de nouvelles adresses à chaque fois que vous en utilisez une, mais les adresses précédentes continuent à fonctionner", @@ -514,8 +514,8 @@ "active_cards": "Cartes actives", "delete_account": "Supprimer le compte", "cards": "Cartes", - "active": "Actif", - "redeemed": "racheté", + "active": "Actives, + "redeemed": "Converties", "gift_card_balance_note": "Les cartes-cadeaux avec un solde restant apparaîtront ici", "gift_card_redeemed_note": "Les cartes-cadeaux que vous avez utilisées apparaîtront ici", "logout": "Déconnexion", @@ -523,7 +523,7 @@ "percentageOf": "sur ${amount}", "is_percentage": "est", "search_category": "Catégorie de recherche", - "mark_as_redeemed": "Marquer comme échangé", + "mark_as_redeemed": "Marquer comme convertie", "more_options": "Plus d'options", "awaiting_payment_confirmation": "En attente de confirmation de paiement", "transaction_sent_notice": "Si l'écran ne continue pas après 1 minute, vérifiez un explorateur de blocs et votre e-mail.", @@ -544,7 +544,7 @@ "cake_pay_learn_more": "Achetez et utilisez instantanément des cartes-cadeaux dans l'application !\nBalayer de gauche à droite pour en savoir plus.", "automatic": "Automatique", "fixed_pair_not_supported": "Cette paire fixe n'est pas prise en charge avec les échanges sélectionnés", - "variable_pair_not_supported": "Cette paire de variables n'est pas prise en charge avec les échanges sélectionnés", + "variable_pair_not_supported": "Cette paire variable n'est pas prise en charge avec les échanges sélectionnés", "none_of_selected_providers_can_exchange": "Aucun des prestataires sélectionnés ne peut effectuer cet échange", "choose_one": "Choisissez-en un", "choose_from_available_options": "Choisissez parmi les options disponibles :", @@ -634,7 +634,7 @@ "setup_totp_recommended": "Configurer TOTP (recommandé)", "disable_buy": "Désactiver l'action d'achat", "disable_sell": "Désactiver l'action de vente", - "cake_2fa_preset": "Gâteau 2FA prédéfini", + "cake_2fa_preset": "Cake 2FA prédéfini", "monero_dark_theme": "Thème sombre Monero", "bitcoin_dark_theme": "Thème sombre Bitcoin", "bitcoin_light_theme": "Thème léger Bitcoin", @@ -644,33 +644,33 @@ "auto_generate_subaddresses": "Générer automatiquement des sous-adresses", "narrow": "Étroit", "normal": "Normal", - "aggressive": "Trop zélé", + "aggressive": "Agressif", "require_for_assessing_wallet": "Nécessaire pour accéder au portefeuille", - "require_for_sends_to_non_contacts": "Exiger pour les envois à des non-contacts", + "require_for_sends_to_non_contacts": "Exiger pour les envois hors contacts", "require_for_sends_to_contacts": "Exiger pour les envois aux contacts", - "require_for_sends_to_internal_wallets": "Exiger pour les envois vers des portefeuilles internes", - "require_for_exchanges_to_internal_wallets": "Exiger pour les échanges vers des portefeuilles internes", + "require_for_sends_to_internal_wallets": "Exiger pour les envois vers des portefeuilles (wallets) internes", + "require_for_exchanges_to_internal_wallets": "Exiger pour les échanges vers des portefeuilles (wallets) internes", "require_for_adding_contacts": "Requis pour ajouter des contacts", - "require_for_creating_new_wallets": "Nécessaire pour créer de nouveaux portefeuilles", + "require_for_creating_new_wallets": "Nécessaire pour créer de nouveaux portefeuilles (wallets)", "require_for_all_security_and_backup_settings": "Exiger pour tous les paramètres de sécurité et de sauvegarde", "available_balance_description": "Le solde disponible est le montant que vous pouvez dépenser immédiatement. Il est calculé en soustrayant le solde gelé du solde total.", - "syncing_wallet_alert_title": "Votre portefeuille est en cours de synchronisation", - "syncing_wallet_alert_content": "Votre solde et votre liste de transactions peuvent ne pas être complets tant qu'il n'y a pas « SYNCHRONISÉ » en haut. Cliquez/appuyez pour en savoir plus.", + "syncing_wallet_alert_title": "Votre portefeuille (wallet) est en cours de synchronisation", + "syncing_wallet_alert_content": "Votre solde et votre liste de transactions peuvent ne pas être à jour tant que la mention « SYNCHRONISÉ » n'apparaît en haut de l'écran. Cliquez/appuyez pour en savoir plus.", "home_screen_settings": "Paramètres de l'écran d'accueil", "sort_by": "Trier par", - "search_add_token": "Rechercher / Ajouter un jeton", - "edit_token": "Modifier le jeton", + "search_add_token": "Rechercher / Ajouter un token", + "edit_token": "Modifier le token", "warning": "Avertissement", - "add_token_warning": "Ne modifiez pas ou n'ajoutez pas de jetons comme indiqué par les escrocs.\nConfirmez toujours les adresses de jeton auprès de sources fiables !", - "add_token_disclaimer_check": "J'ai confirmé l'adresse et les informations du contrat de jeton en utilisant une source fiable. L'ajout d'informations malveillantes ou incorrectes peut entraîner une perte de fonds.", - "token_contract_address": "Adresse du contrat de jeton", - "token_name": "Nom du jeton, par exemple : Tether", - "token_symbol": "Symbole de jeton, par exemple : USDT", - "token_decimal": "Décimal de jeton", + "add_token_warning": "Ne modifiez pas ou n'ajoutez pas de tokens comme pourraient vous le suggérer des escrocs.\nConfirmez toujours les adresses de token auprès de sources fiables !", + "add_token_disclaimer_check": "J'ai confirmé l'adresse et les informations du contrat de token en utilisant une source fiable. L'ajout d'informations malveillantes ou incorrectes peut entraîner une perte de fonds.", + "token_contract_address": "Adresse du contrat de token", + "token_name": "Nom du token, par exemple : Tether", + "token_symbol": "Symbole de token, par exemple : USDT", + "token_decimal": "Décimales de token", "field_required": "Ce champ est obligatoire", "pin_at_top": "épingler ${token} en haut", "invalid_input": "Entrée invalide", - "fiat_balance": "Fiat Balance", + "fiat_balance": "Solde fiat", "gross_balance": "Solde brut", "alphabetical": "Alphabétique", "generate_name": "Générer un nom", @@ -685,19 +685,19 @@ "unsupported_asset": "Nous ne prenons pas en charge cette action pour cet élément. Veuillez créer ou passer à un portefeuille d'un type d'actif pris en charge.", "manage_pow_nodes": "Gérer les nœuds PoW", "support_title_live_chat": "Support en direct", - "support_description_live_chat": "GRATUIT ET RAPIDE! Des représentants de soutien formé sont disponibles pour aider", - "support_title_guides": "Guides de portefeuille à gâteau", - "support_description_guides": "Documentation et soutien aux problèmes communs", + "support_description_live_chat": "GRATUIT ET RAPIDE ! Des représentants de soutien formé sont disponibles pour aider", + "support_title_guides": "Guides de Cake Wallet", + "support_description_guides": "Documentation et support pour les problèmes communs", "support_title_other_links": "Autres liens d'assistance", - "support_description_other_links": "Rejoignez nos communautés ou contactez-nous nos partenaires à travers d'autres méthodes", - "choose_derivation": "Choisissez la dérivation du portefeuille", + "support_description_other_links": "Rejoignez nos communautés ou contactez-nous ou nos partenaires à travers d'autres méthodes", + "choose_derivation": "Choisissez le chemin de dérivation du portefeuille", "new_first_wallet_text": "Gardez facilement votre crypto-monnaie en sécurité", "select_destination": "Veuillez sélectionner la destination du fichier de sauvegarde.", "save_to_downloads": "Enregistrer dans les téléchargements", "select_buy_provider_notice": "Sélectionnez un fournisseur d'achat ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur d'achat par défaut dans les paramètres de l'application.", - "onramper_option_description": "Achetez rapidement la crypto avec de nombreux méthodes de paiement. Disponible dans la plupart des pays. Les écarts et les frais varient.", + "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.", "default_buy_provider": "Fournisseur d'achat par défaut", - "ask_each_time": "Demandez à chaque fois", + "ask_each_time": "Demander à chaque fois", "buy_provider_unavailable": "Fournisseur actuellement indisponible.", "signTransaction": "Signer une transaction", "errorGettingCredentials": "Échec : erreur lors de l'obtention des informations d'identification", @@ -709,9 +709,9 @@ "reject": "Rejeter", "approve": "Approuver", "expiresOn": "Expire le", - "walletConnect": "PortefeuilleConnect", + "walletConnect": "WalletConnect", "nullURIError": "L'URI est nul", - "connectWalletPrompt": "Connectez votre portefeuille avec WalletConnect pour effectuer des transactions", + "connectWalletPrompt": "Connectez votre portefeuille (wallet) avec WalletConnect pour effectuer des transactions", "newConnection": "Nouvelle connexion", "activeConnectionsPrompt": "Les connexions actives apparaîtront ici", "deleteConnectionConfirmationPrompt": "Êtes-vous sûr de vouloir supprimer la connexion à", From e5408a388e31b6fa3c669c9516034d4ef2d2e38f Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Mon, 9 Oct 2023 18:18:59 +0300 Subject: [PATCH 002/241] v4.10.0 & v1.7.0 (#1113) * New versions * update the new version text after macos [skip ci] * add cake-wallet headers * add nano/banano to getAddressFromStringPattern * Revert "Exolix integration (#1080)" This reverts commit 9eb6867ab98dbb3a5fec64e0c940c716cf1fd43c. * fix: Bug in conditions check and clean up of repeated code in switch cases (#1117) * update build numbers [skip ci] --------- Co-authored-by: fosse Co-authored-by: Adegoke David <64401859+Blazebrain@users.noreply.github.com> --- .github/workflows/pr_test_build.yml | 1 - assets/images/exolix.png | Bin 1203 -> 0 bytes assets/text/Monerocom_Release_Notes.txt | 2 +- assets/text/Release_Notes.txt | 5 +- cw_nano/lib/nano_client.dart | 24 +- lib/core/address_validator.dart | 4 + lib/core/backup_service.dart | 3 +- lib/di.dart | 8 - lib/entities/cake_2fa_preset_options.dart | 3 + .../exchange_provider_description.dart | 7 +- .../exolix/exolix_exchange_provider.dart | 294 ------------------ lib/exchange/exolix/exolix_request.dart | 20 -- lib/exchange/trade_state.dart | 27 -- lib/nano/cw_nano.dart | 18 +- .../screens/dashboard/widgets/trade_row.dart | 3 - .../screens/nano/nano_change_rep_page.dart | 3 +- .../settings/connection_sync_page.dart | 2 +- lib/store/app_store.dart | 7 + lib/store/dashboard/trade_filter_store.dart | 18 +- .../dashboard/dashboard_view_model.dart | 5 - .../dashboard/transaction_list_item.dart | 5 +- .../exchange/exchange_trade_view_model.dart | 4 - .../exchange/exchange_view_model.dart | 14 - lib/view_model/send/send_view_model.dart | 12 +- lib/view_model/set_up_2fa_viewmodel.dart | 169 ++++------ lib/view_model/support_view_model.dart | 5 - lib/view_model/trade_details_view_model.dart | 10 - scripts/android/app_env.sh | 8 +- scripts/ios/app_env.sh | 8 +- scripts/macos/app_env.sh | 4 +- tool/configure.dart | 6 +- tool/utils/secret_key.dart | 1 - 32 files changed, 146 insertions(+), 554 deletions(-) delete mode 100644 assets/images/exolix.png delete mode 100644 lib/exchange/exolix/exolix_exchange_provider.dart delete mode 100644 lib/exchange/exolix/exolix_request.dart diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index af03c5e30..6b12911b6 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -128,7 +128,6 @@ jobs: echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_ethereum/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 robinhoodCIdApiSecret = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> lib/.secrets.g.dart echo "const walletConnectProjectId = '${{ secrets.WALLET_CONNECT_PROJECT_ID }}';" >> lib/.secrets.g.dart diff --git a/assets/images/exolix.png b/assets/images/exolix.png deleted file mode 100644 index 29e5f2db1d659dc3ca64858d800287c29b0a49fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1203 zcmV;k1WfyhP)Px(ZAnByRA@upT3t+3M-={MH7sigx|iVHa%-9*rD;eiDv(r5E2W5NYg6q{jN0l$ z+cY7PkiIm<#56^T51O>5sXnx%8dB;{OlVT-Pg|@HO{iU3kPSPJ+FaGHkbfx&^k z^U0W+*a2}bR6Yd3mjrNH!J)t?D0U3qQ4d+sXF8S$NDGx?AlPViQUkrCey{p204jnj zL?B02KBK@FA`^(p5}?87RU3KrI0+OuB{?t%z{Lw}Q!e25y4*nbs2PqafgF#gl+rnW znE_45_k=jgeEqloPK2G1Ku)f*jXLn%bQs5rNkZ7}8&I2#jWP5vwM_4iM4r#J+(13SXI#i^9@dtI5a2YU(uNmhna7;QxP2mD@jUbK>q zKq}(AsKv4JvG;_IfFvtIx1e2Ptm^x{YQ*lyACj#62;gn2pefa(IPSlrzNO2B?5;lB zx_!mZizPA!tl6s8U+PSlsD*by+X0qU5`u$vSFs=~3#Tf|?ZTk^%@542F2Ng5=2<3jsJjPET~|%@St>s0RWmgLcHJj-wyt&6a5@~OM#KvE zM#oTk>MXY&b0aeOlKO*Ni$icOA-MM18V*UlNPgSTLOL`=%ZVf_tpMH;(&P|cEz9_( zY#E2-gh<8N4%{4Occ{>4C2m>q8NFeJpeW#3RgC_QOA)oUmsX-^ezqx0bI%QYex=J) zE>=K$V<*f1i+62D{-#%Pvgmz;#>cg}C^KCF-w0xpk)nvSnD z%usM#BM}bb?u-mvtgeh}Ad4VR3;KO5kbMG_V#Bo-9d6(03;45kf8?{e!UEJi`^*#) zRll9X^#>0vuRc?>O`x)^3G)jVO)=uvjXN=PxhL}Zh3ZO385xoPTW;J!!@pN-8E>1w z6P3&H!q@fjjUd2@!Y#TgN$=}5TB>m`7({Wqb-$0E(DDuthXZeR9ZtA{!TZB#EBPQI zQzM01@^42+sqOSoJs97cZtz$#+g zV@bn%SiH5GTfV)b4#RzSx#a}}TZL1J%v?9to9bh|=%%LT743IaSe&ytDEO_oI%QkfGIfCwHv4qWNGF>{&^PuspT8b41Ke23l zSdm2~7M<)4-Gj!|jVMLQ-jB81#`d5T7eBTA_=E0AsS%i-n!jzn1^}#=pgjR*Pg#Yr zN&CXqr)3ePQ%{CSH#56U!b+I8_%}Z`CA*$vtl7DczP<+U={jod Rkx~Ev002ovPDHLkV1hCPI;#Kx diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 9393f7768..46a62494b 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,3 +1,3 @@ -Fix 2FA code issue +Support getting Addresses from ENS and Mastodon Bug fixes Minor enhancements \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 1fd86c9ca..50c88833d 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,4 +1,5 @@ -Ethereum enhancements and bug fixes -Fix 2FA code issue +Add Nano wallet +Add WalletConnect to connect your ETH wallet with your favorite dApp +Support getting Addresses from ENS and Mastodon Bug fixes Minor enhancements \ No newline at end of file diff --git a/cw_nano/lib/nano_client.dart b/cw_nano/lib/nano_client.dart index 29f47cc2d..2866c4653 100644 --- a/cw_nano/lib/nano_client.dart +++ b/cw_nano/lib/nano_client.dart @@ -13,6 +13,11 @@ class NanoClient { static const String DEFAULT_REPRESENTATIVE = "nano_38713x95zyjsqzx6nm1dsom1jmm668owkeb9913ax6nfgj15az3nu8xkx579"; + static const Map CAKE_HEADERS = { + "Content-Type": "application/json", + "nano-app": "cake-wallet" + }; + Node? _node; Node? _powNode; @@ -37,7 +42,7 @@ class NanoClient { Future getBalance(String address) async { final response = await http.post( _node!.uri, - headers: {"Content-Type": "application/json"}, + headers: CAKE_HEADERS, body: jsonEncode( { "action": "account_balance", @@ -57,7 +62,7 @@ class NanoClient { try { final response = await http.post( _node!.uri, - headers: {"Content-Type": "application/json"}, + headers: CAKE_HEADERS, body: jsonEncode( { "action": "account_info", @@ -123,7 +128,7 @@ class NanoClient { Future requestWork(String hash) async { final response = await http.post( _powNode!.uri, - headers: {'Content-type': 'application/json'}, + headers: CAKE_HEADERS, body: json.encode( { "action": "work_generate", @@ -157,7 +162,6 @@ class NanoClient { } Future processBlock(Map block, String subtype) async { - final headers = {"Content-Type": "application/json"}; final processBody = jsonEncode({ "action": "process", "json_block": "true", @@ -167,7 +171,7 @@ class NanoClient { final processResponse = await http.post( _node!.uri, - headers: headers, + headers: CAKE_HEADERS, body: processBody, ); @@ -260,10 +264,6 @@ class NanoClient { }) async { bool openBlock = false; - final headers = { - "Content-Type": "application/json", - }; - // first check if the account is open: // get the account info (we need the frontier and representative): AccountInfoResponse? infoData = await getAccountInfo(destinationAddress); @@ -335,7 +335,7 @@ class NanoClient { }); final processResponse = await http.post( _node!.uri, - headers: headers, + headers: CAKE_HEADERS, body: processBody, ); @@ -351,7 +351,7 @@ class NanoClient { required String privateKey, }) async { final receivableResponse = await http.post(_node!.uri, - headers: {"Content-Type": "application/json"}, + headers: CAKE_HEADERS, body: jsonEncode({ "action": "receivable", "account": destinationAddress, @@ -401,7 +401,7 @@ class NanoClient { Future> fetchTransactions(String address) async { try { final response = await http.post(_node!.uri, - headers: {"Content-Type": "application/json"}, + headers: CAKE_HEADERS, body: jsonEncode({ "action": "account_history", "account": address, diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 5f5b004ba..d039a40a7 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -267,6 +267,10 @@ class AddressValidator extends TextValidator { '|([^0-9a-zA-Z]|^)ltc[a-zA-Z0-9]{26,45}([^0-9a-zA-Z]|\$)'; case CryptoCurrency.eth: return '0x[0-9a-zA-Z]{42}'; + case CryptoCurrency.nano: + return 'nano_[0-9a-zA-Z]{60}'; + case CryptoCurrency.banano: + return 'ban_[0-9a-zA-Z]{60}'; default: return null; } diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 24b5558d5..ad4fe9623 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; +import 'package:cake_wallet/utils/device_info.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; @@ -308,7 +309,7 @@ class BackupService { if (currentPinLength != null) await _sharedPreferences.setInt(PreferencesKey.currentPinLength, currentPinLength); - if (currentTheme != null) + if (currentTheme != null && DeviceInfo.instance.isMobile) await _sharedPreferences.setInt(PreferencesKey.currentTheme, currentTheme); if (exchangeStatus != null) diff --git a/lib/di.dart b/lib/di.dart index b572c4b98..b871e6a6b 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -417,10 +417,6 @@ Future setup({ } if (appStore.wallet != null) { authStore.allowed(); - - if (appStore.wallet!.type == WalletType.ethereum) { - getIt.get().init(); - } return; } @@ -441,10 +437,6 @@ Future setup({ } else { if (appStore.wallet != null) { authStore.allowed(); - - if (appStore.wallet!.type == WalletType.ethereum) { - getIt.get().init(); - } return; } diff --git a/lib/entities/cake_2fa_preset_options.dart b/lib/entities/cake_2fa_preset_options.dart index 2aa6c4215..417af2b98 100644 --- a/lib/entities/cake_2fa_preset_options.dart +++ b/lib/entities/cake_2fa_preset_options.dart @@ -6,6 +6,7 @@ class Cake2FAPresetsOptions extends EnumerableItem with Serializable { static const narrow = Cake2FAPresetsOptions(title: 'Narrow', raw: 0); static const normal = Cake2FAPresetsOptions(title: 'Normal', raw: 1); static const aggressive = Cake2FAPresetsOptions(title: 'Aggressive', raw: 2); + static const none = Cake2FAPresetsOptions(title: 'None', raw: 3); static Cake2FAPresetsOptions deserialize({required int raw}) { switch (raw) { @@ -15,6 +16,8 @@ class Cake2FAPresetsOptions extends EnumerableItem with Serializable { return Cake2FAPresetsOptions.normal; case 2: return Cake2FAPresetsOptions.aggressive; + case 3: + return Cake2FAPresetsOptions.none; default: throw Exception( 'Incorrect Cake 2FA Preset $raw for Cake2FAPresetOptions deserialize', diff --git a/lib/exchange/exchange_provider_description.dart b/lib/exchange/exchange_provider_description.dart index 151d018e0..e545f69ce 100644 --- a/lib/exchange/exchange_provider_description.dart +++ b/lib/exchange/exchange_provider_description.dart @@ -24,10 +24,7 @@ class ExchangeProviderDescription extends EnumerableItem with Serializable< static const trocador = ExchangeProviderDescription(title: 'Trocador', raw: 5, image: 'assets/images/trocador.png'); - static const exolix = - ExchangeProviderDescription(title: 'Exolix', raw: 6, image: 'assets/images/exolix.png'); - - static const all = ExchangeProviderDescription(title: 'All trades', raw: 7, image: ''); + static const all = ExchangeProviderDescription(title: 'All trades', raw: 6, image: ''); static ExchangeProviderDescription deserialize({required int raw}) { switch (raw) { @@ -44,8 +41,6 @@ class ExchangeProviderDescription extends EnumerableItem with Serializable< case 5: return trocador; case 6: - return exolix; - case 7: return all; default: throw Exception('Unexpected token: $raw for ExchangeProviderDescription deserialize'); diff --git a/lib/exchange/exolix/exolix_exchange_provider.dart b/lib/exchange/exolix/exolix_exchange_provider.dart deleted file mode 100644 index 0768f1160..000000000 --- a/lib/exchange/exolix/exolix_exchange_provider.dart +++ /dev/null @@ -1,294 +0,0 @@ -import 'dart:convert'; -import 'package:cake_wallet/exchange/trade_not_found_exeption.dart'; -import 'package:http/http.dart'; -import 'package:cake_wallet/.secrets.g.dart' as secrets; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/exchange/exchange_pair.dart'; -import 'package:cake_wallet/exchange/exchange_provider.dart'; -import 'package:cake_wallet/exchange/limits.dart'; -import 'package:cake_wallet/exchange/trade.dart'; -import 'package:cake_wallet/exchange/trade_request.dart'; -import 'package:cake_wallet/exchange/trade_state.dart'; -import 'package:cake_wallet/exchange/exolix/exolix_request.dart'; -import 'package:cake_wallet/exchange/exchange_provider_description.dart'; - -class ExolixExchangeProvider extends ExchangeProvider { - ExolixExchangeProvider() : super(pairList: _supportedPairs()); - - static final apiKey = secrets.exolixApiKey; - static const apiBaseUrl = 'exolix.com'; - static const transactionsPath = '/api/v2/transactions'; - static const ratePath = '/api/v2/rate'; - - static const List _notSupported = [ - CryptoCurrency.usdt, - CryptoCurrency.xhv, - CryptoCurrency.btt, - CryptoCurrency.firo, - CryptoCurrency.zaddr, - CryptoCurrency.xvg, - CryptoCurrency.kmd, - CryptoCurrency.paxg, - CryptoCurrency.rune, - CryptoCurrency.scrt, - CryptoCurrency.btcln, - CryptoCurrency.cro, - CryptoCurrency.ftm, - CryptoCurrency.frax, - CryptoCurrency.gusd, - CryptoCurrency.gtc, - CryptoCurrency.weth, - ]; - - static List _supportedPairs() { - final supportedCurrencies = - CryptoCurrency.all.where((element) => !_notSupported.contains(element)).toList(); - - return supportedCurrencies - .map((i) => supportedCurrencies.map((k) => ExchangePair(from: i, to: k, reverse: true))) - .expand((i) => i) - .toList(); - } - - @override - String get title => 'Exolix'; - - @override - bool get isAvailable => true; - - @override - bool get isEnabled => true; - - @override - bool get supportsFixedRate => true; - - @override - ExchangeProviderDescription get description => ExchangeProviderDescription.exolix; - - @override - Future checkIsAvailable() async => true; - - static String getRateType(bool isFixedRate) => isFixedRate ? 'fixed' : 'float'; - - @override - Future fetchLimits( - {required CryptoCurrency from, - required CryptoCurrency to, - required bool isFixedRateMode}) async { - final params = { - 'rateType': getRateType(isFixedRateMode), - 'amount': '1', - }; - if (isFixedRateMode) { - params['coinFrom'] = _normalizeCurrency(to); - params['coinTo'] = _normalizeCurrency(from); - params['networkFrom'] = _networkFor(to); - params['networkTo'] = _networkFor(from); - } else { - params['coinFrom'] = _normalizeCurrency(from); - params['coinTo'] = _normalizeCurrency(to); - 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}'); - } - - final responseJSON = json.decode(response.body) as Map; - return Limits(min: responseJSON['minAmount'] as double?); - } - - @override - Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { - final _request = request as ExolixRequest; - - final headers = {'Content-Type': 'application/json'}; - final body = { - 'coinFrom': _normalizeCurrency(_request.from), - 'coinTo': _normalizeCurrency(_request.to), - 'networkFrom': _networkFor(_request.from), - 'networkTo': _networkFor(_request.to), - 'withdrawalAddress': _request.address, - 'refundAddress': _request.refundAddress, - 'rateType': getRateType(isFixedRateMode), - 'apiToken': apiKey, - }; - - if (isFixedRateMode) { - body['withdrawalAmount'] = _request.toAmount; - } else { - body['amount'] = _request.fromAmount; - } - - final uri = Uri.https(apiBaseUrl, transactionsPath); - final response = await post(uri, headers: headers, body: json.encode(body)); - - if (response.statusCode == 400) { - final responseJSON = json.decode(response.body) as Map; - final errors = responseJSON['errors'] as Map; - final errorMessage = errors.values.join(', '); - throw Exception(errorMessage); - } - - if (response.statusCode != 200 && response.statusCode != 201) { - throw Exception('Unexpected http status: ${response.statusCode}'); - } - - final responseJSON = json.decode(response.body) as Map; - final id = responseJSON['id'] as String; - final inputAddress = responseJSON['depositAddress'] as String; - final refundAddress = responseJSON['refundAddress'] as String?; - final extraId = responseJSON['depositExtraId'] as String?; - final payoutAddress = responseJSON['withdrawalAddress'] as String; - final amount = responseJSON['amount'].toString(); - - return Trade( - id: id, - from: _request.from, - to: _request.to, - provider: description, - inputAddress: inputAddress, - refundAddress: refundAddress, - extraId: extraId, - createdAt: DateTime.now(), - amount: amount, - state: TradeState.created, - payoutAddress: payoutAddress); - } - - @override - Future findTradeById({required String id}) async { - final findTradeByIdPath = transactionsPath + '/$id'; - final uri = Uri.https(apiBaseUrl, findTradeByIdPath); - final response = await get(uri); - - if (response.statusCode == 404) { - throw TradeNotFoundException(id, provider: description); - } - - if (response.statusCode == 400) { - final responseJSON = json.decode(response.body) as Map; - final errors = responseJSON['errors'] as Map; - final errorMessage = errors.values.join(', '); - - throw TradeNotFoundException(id, provider: description, description: errorMessage); - } - - if (response.statusCode != 200) { - throw Exception('Unexpected http status: ${response.statusCode}'); - } - - final responseJSON = json.decode(response.body) as Map; - final coinFrom = responseJSON['coinFrom']['coinCode'] as String; - final from = CryptoCurrency.fromString(coinFrom); - final coinTo = responseJSON['coinTo']['coinCode'] as String; - final to = CryptoCurrency.fromString(coinTo); - final inputAddress = responseJSON['depositAddress'] as String; - final amount = responseJSON['amount'].toString(); - final status = responseJSON['status'] as String; - final state = TradeState.deserialize(raw: _prepareStatus(status)); - final extraId = responseJSON['depositExtraId'] as String?; - final outputTransaction = responseJSON['hashOut']['hash'] as String?; - final payoutAddress = responseJSON['withdrawalAddress'] as String; - - return Trade( - id: id, - from: from, - to: to, - provider: description, - inputAddress: inputAddress, - amount: amount, - state: state, - extraId: extraId, - outputTransaction: outputTransaction, - payoutAddress: payoutAddress); - } - - @override - Future fetchRate( - {required CryptoCurrency from, - required CryptoCurrency to, - required double amount, - required bool isFixedRateMode, - required bool isReceiveAmount}) async { - try { - if (amount == 0) { - return 0.0; - } - - final params = { - 'coinFrom': _normalizeCurrency(from), - 'coinTo': _normalizeCurrency(to), - 'networkFrom': _networkFor(from), - 'networkTo': _networkFor(to), - 'rateType': getRateType(isFixedRateMode), - }; - - if (isReceiveAmount) { - params['withdrawalAmount'] = amount.toString(); - } else { - params['amount'] = amount.toString(); - } - - final uri = Uri.https(apiBaseUrl, ratePath, params); - final response = await get(uri); - final responseJSON = json.decode(response.body) as Map; - - if (response.statusCode != 200) { - final message = responseJSON['message'] as String?; - throw Exception(message); - } - - final rate = responseJSON['rate'] as double; - - return rate; - } catch (e) { - print(e.toString()); - return 0.0; - } - } - - String _prepareStatus(String status) { - switch (status) { - case 'deleted': - case 'error': - return 'overdue'; - default: - return status; - } - } - - String _networkFor(CryptoCurrency currency) { - switch (currency) { - case CryptoCurrency.arb: - return 'ARBITRUM'; - default: - return currency.tag != null ? _normalizeTag(currency.tag!) : currency.title; - } - } - - String _normalizeCurrency(CryptoCurrency currency) { - switch (currency) { - case CryptoCurrency.nano: - return 'XNO'; - case CryptoCurrency.bttc: - return 'BTT'; - case CryptoCurrency.zec: - return 'ZEC'; - default: - return currency.title; - } - } - - String _normalizeTag(String tag) { - switch (tag) { - case 'POLY': - return 'Polygon'; - default: - return tag; - } - } -} diff --git a/lib/exchange/exolix/exolix_request.dart b/lib/exchange/exolix/exolix_request.dart deleted file mode 100644 index e97ffa386..000000000 --- a/lib/exchange/exolix/exolix_request.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/exchange/trade_request.dart'; - -class ExolixRequest extends TradeRequest { - ExolixRequest( - {required this.from, - required this.to, - required this.address, - required this.fromAmount, - required this.toAmount, - required this.refundAddress}); - - CryptoCurrency from; - CryptoCurrency to; - String address; - String fromAmount; - String toAmount; - String refundAddress; -} diff --git a/lib/exchange/trade_state.dart b/lib/exchange/trade_state.dart index ebf74ce7a..98737339c 100644 --- a/lib/exchange/trade_state.dart +++ b/lib/exchange/trade_state.dart @@ -35,15 +35,6 @@ class TradeState extends EnumerableItem with Serializable { static const completed = TradeState(raw: 'completed', title: 'Completed'); static const settling = TradeState(raw: 'settling', title: 'Settlement in progress'); static const settled = TradeState(raw: 'settled', title: 'Settlement completed'); - static const wait = TradeState(raw: 'wait', title: 'Waiting'); - static const overdue = TradeState(raw: 'overdue', title: 'Overdue'); - static const refund = TradeState(raw: 'refund', title: 'Refund'); - static const refunded = TradeState(raw: 'refunded', title: 'Refunded'); - static const confirmation = TradeState(raw: 'confirmation', title: 'Confirmation'); - static const confirmed = TradeState(raw: 'confirmed', title: 'Confirmed'); - static const exchanging = TradeState(raw: 'exchanging', title: 'Exchanging'); - static const sending = TradeState(raw: 'sending', title: 'Sending'); - static const success = TradeState(raw: 'success', title: 'Success'); static TradeState deserialize({required String raw}) { switch (raw) { case 'pending': @@ -86,24 +77,6 @@ class TradeState extends EnumerableItem with Serializable { return failed; case 'completed': return completed; - case 'wait': - return wait; - case 'overdue': - return overdue; - case 'refund': - return refund; - case 'refunded': - return refunded; - case 'confirmation': - return confirmation; - case 'confirmed': - return confirmed; - case 'exchanging': - return exchanging; - case 'sending': - return sending; - case 'success': - return success; default: throw Exception('Unexpected token: $raw in TradeState deserialize'); } diff --git a/lib/nano/cw_nano.dart b/lib/nano/cw_nano.dart index 0c52a24d6..cd0f0ca8a 100644 --- a/lib/nano/cw_nano.dart +++ b/lib/nano/cw_nano.dart @@ -178,6 +178,11 @@ class CWNano extends Nano { BigInt getTransactionAmountRaw(TransactionInfo transactionInfo) { return (transactionInfo as NanoTransactionInfo).amountRaw; } + + @override + String getRepresentative(Object wallet) { + return (wallet as NanoWallet).representative; + } } class CWNanoUtil extends NanoUtil { @@ -308,14 +313,19 @@ class CWNanoUtil extends NanoUtil { /// @param raw 100000000000000000000000000000 /// @return Decimal value 1.000000000000000000000000000000 /// - @override - Decimal getRawAsDecimal(String? raw, BigInt? rawPerCur) { + Decimal _getRawAsDecimal(String? raw, BigInt? rawPerCur) { rawPerCur ??= rawPerNano; final Decimal amount = Decimal.parse(raw.toString()); final Decimal result = (amount / Decimal.parse(rawPerCur.toString())).toDecimal(); return result; } + @override + String getRawAsDecimalString(String? raw, BigInt? rawPerCur) { + final Decimal result = _getRawAsDecimal(raw, rawPerCur); + return result.toString(); + } + @override String truncateDecimal(Decimal input, {int digits = maxDecimalDigits}) { Decimal bigger = input.shift(digits); @@ -332,7 +342,7 @@ class CWNanoUtil extends NanoUtil { @override String getRawAsUsableString(String? raw, BigInt rawPerCur) { final String res = - truncateDecimal(getRawAsDecimal(raw, rawPerCur), digits: maxDecimalDigits + 9); + truncateDecimal(_getRawAsDecimal(raw, rawPerCur), digits: maxDecimalDigits + 9); if (raw == null || raw == "0" || raw == "00000000000000000000000000000000") { return "0"; @@ -361,7 +371,7 @@ class CWNanoUtil extends NanoUtil { @override String getRawAccuracy(String? raw, BigInt rawPerCur) { final String rawString = getRawAsUsableString(raw, rawPerCur); - final String rawDecimalString = getRawAsDecimal(raw, rawPerCur).toString(); + final String rawDecimalString = _getRawAsDecimal(raw, rawPerCur).toString(); if (raw == null || raw.isEmpty || raw == "0") { return ""; diff --git a/lib/src/screens/dashboard/widgets/trade_row.dart b/lib/src/screens/dashboard/widgets/trade_row.dart index 7f570b98e..a42593f24 100644 --- a/lib/src/screens/dashboard/widgets/trade_row.dart +++ b/lib/src/screens/dashboard/widgets/trade_row.dart @@ -94,9 +94,6 @@ class TradeRow extends StatelessWidget { borderRadius: BorderRadius.circular(50), child: Image.asset('assets/images/trocador.png', width: 36, height: 36)); break; - case ExchangeProviderDescription.exolix: - image = Image.asset('assets/images/exolix.png', width: 36, height: 36); - break; default: image = null; } diff --git a/lib/src/screens/nano/nano_change_rep_page.dart b/lib/src/screens/nano/nano_change_rep_page.dart index b11b82257..bf541c39a 100644 --- a/lib/src/screens/nano/nano_change_rep_page.dart +++ b/lib/src/screens/nano/nano_change_rep_page.dart @@ -6,7 +6,6 @@ import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/wallet_base.dart'; -import 'package:cw_nano/nano_wallet.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -18,7 +17,7 @@ class NanoChangeRepPage extends BasePage { NanoChangeRepPage(WalletBase wallet) : _wallet = wallet, _addressController = TextEditingController() { - _addressController.text = (wallet as NanoWallet).representative; + _addressController.text = nano!.getRepresentative(wallet); } final TextEditingController _addressController; diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart index 573778ed2..98ca9342c 100644 --- a/lib/src/screens/settings/connection_sync_page.dart +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -85,7 +85,7 @@ class ConnectionSyncPage extends BasePage { ); }, ), - if (dashboardViewModel.wallet.type == WalletType.ethereum) ...[ + if (dashboardViewModel.wallet.type == WalletType.ethereum && DeviceInfo.instance.isMobile) ...[ WalletConnectTile( onTap: () async { Navigator.of(context).push( diff --git a/lib/store/app_store.dart b/lib/store/app_store.dart index 639efacb6..e814ff44b 100644 --- a/lib/store/app_store.dart +++ b/lib/store/app_store.dart @@ -1,5 +1,8 @@ +import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart'; +import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/utils/exception_handler.dart'; import 'package:cw_core/transaction_info.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/wallet_base.dart'; @@ -40,5 +43,9 @@ abstract class AppStoreBase with Store { this.wallet?.close(); this.wallet = wallet; this.wallet!.setExceptionHandler(ExceptionHandler.onError); + + if (wallet.type == WalletType.ethereum) { + getIt.get().init(); + } } } diff --git a/lib/store/dashboard/trade_filter_store.dart b/lib/store/dashboard/trade_filter_store.dart index 799e8b951..c772a35d6 100644 --- a/lib/store/dashboard/trade_filter_store.dart +++ b/lib/store/dashboard/trade_filter_store.dart @@ -13,8 +13,7 @@ abstract class TradeFilterStoreBase with Store { displaySideShift = true, displayMorphToken = true, displaySimpleSwap = true, - displayTrocador = true, - displayExolix = true; + displayTrocador = true; @observable bool displayXMRTO; @@ -34,11 +33,8 @@ abstract class TradeFilterStoreBase with Store { @observable bool displayTrocador; - @observable - bool displayExolix; - @computed - bool get displayAllTrades => displayChangeNow && displaySideShift && displaySimpleSwap && displayTrocador && displayExolix; + bool get displayAllTrades => displayChangeNow && displaySideShift && displaySimpleSwap && displayTrocador; @action void toggleDisplayExchange(ExchangeProviderDescription provider) { @@ -60,10 +56,7 @@ abstract class TradeFilterStoreBase with Store { break; case ExchangeProviderDescription.trocador: displayTrocador = !displayTrocador; - break; - case ExchangeProviderDescription.exolix: - displayExolix = !displayExolix; - break; + break; case ExchangeProviderDescription.all: if (displayAllTrades) { displayChangeNow = false; @@ -72,7 +65,6 @@ abstract class TradeFilterStoreBase with Store { displayMorphToken = false; displaySimpleSwap = false; displayTrocador = false; - displayExolix = false; } else { displayChangeNow = true; displaySideShift = true; @@ -80,7 +72,6 @@ abstract class TradeFilterStoreBase with Store { displayMorphToken = true; displaySimpleSwap = true; displayTrocador = true; - displayExolix = true; } break; } @@ -107,8 +98,7 @@ abstract class TradeFilterStoreBase with Store { ||(displaySimpleSwap && item.trade.provider == ExchangeProviderDescription.simpleSwap) - ||(displayTrocador && item.trade.provider == ExchangeProviderDescription.trocador) - ||(displayExolix && item.trade.provider == ExchangeProviderDescription.exolix)) + ||(displayTrocador && item.trade.provider == ExchangeProviderDescription.trocador)) .toList() : _trades; } diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 03f0aa9a8..f6eb7f244 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -98,11 +98,6 @@ abstract class DashboardViewModelBase with Store { caption: ExchangeProviderDescription.trocador.title, onChanged: () => tradeFilterStore .toggleDisplayExchange(ExchangeProviderDescription.trocador)), - FilterItem( - value: () => tradeFilterStore.displayExolix, - caption: ExchangeProviderDescription.exolix.title, - onChanged: () => tradeFilterStore - .toggleDisplayExchange(ExchangeProviderDescription.exolix)), ] }, subname = '', diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart index e5fe354a0..e7e640afc 100644 --- a/lib/view_model/dashboard/transaction_list_item.dart +++ b/lib/view_model/dashboard/transaction_list_item.dart @@ -92,9 +92,8 @@ class TransactionListItem extends ActionListItem with Keyable { break; case WalletType.nano: amount = calculateFiatAmountRaw( - cryptoAmount: nanoUtil! - .getRawAsDecimal(nano!.getTransactionAmountRaw(transaction).toString(), nanoUtil!.rawPerNano) - .toDouble(), + cryptoAmount: double.parse(nanoUtil!.getRawAsDecimalString( + nano!.getTransactionAmountRaw(transaction).toString(), nanoUtil!.rawPerNano)), price: price); break; case WalletType.ethereum: diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index 346844171..cfabd994f 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'package:cake_wallet/exchange/exolix/exolix_exchange_provider.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'; import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart'; import 'package:cake_wallet/exchange/trocador/trocador_exchange_provider.dart'; @@ -54,9 +53,6 @@ abstract class ExchangeTradeViewModelBase with Store { case ExchangeProviderDescription.trocador: _provider = TrocadorExchangeProvider(); break; - case ExchangeProviderDescription.exolix: - _provider = ExolixExchangeProvider(); - break; } _updateItems(); diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 47b408bc2..b438e9b74 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -6,8 +6,6 @@ import 'package:cake_wallet/core/wallet_change_listener_view_model.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/wallet_contact.dart'; -import 'package:cake_wallet/exchange/exolix/exolix_exchange_provider.dart'; -import 'package:cake_wallet/exchange/exolix/exolix_request.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_request.dart'; import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart'; @@ -152,7 +150,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with SideShiftExchangeProvider(), SimpleSwapExchangeProvider(), TrocadorExchangeProvider(useTorOnly: _useTorOnly), - ExolixExchangeProvider(), ]; @observable @@ -549,17 +546,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with amount = isFixedRateMode ? receiveAmount : depositAmount; } - if (provider is ExolixExchangeProvider) { - request = ExolixRequest( - from: depositCurrency, - to: receiveCurrency, - fromAmount: depositAmount.replaceAll(',', '.'), - toAmount: receiveAmount.replaceAll(',', '.'), - refundAddress: depositAddress, - address: receiveAddress); - amount = isFixedRateMode ? receiveAmount : depositAmount; - } - amount = amount.replaceAll(',', '.'); if (limitsState is LimitsLoadedSuccessfully) { diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index faebed11f..2ba6dc784 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -278,7 +278,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor List conditionsList = []; for (var output in outputs) { - final show = checkThroughChecksToDisplayTOTP(output.address); + + final show = checkThroughChecksToDisplayTOTP(output.extractedAddress); conditionsList.add(show); } @@ -427,9 +428,14 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor } } - String translateErrorMessage(String error, WalletType walletType, CryptoCurrency currency,) { + String translateErrorMessage( + String error, + WalletType walletType, + CryptoCurrency currency, + ) { if (walletType == WalletType.ethereum || walletType == WalletType.haven) { - if (error.contains('gas required exceeds allowance') || error.contains('insufficient funds for')) { + if (error.contains('gas required exceeds allowance') || + error.contains('insufficient funds for')) { return S.current.do_not_have_enough_gas_asset(currency.toString()); } } diff --git a/lib/view_model/set_up_2fa_viewmodel.dart b/lib/view_model/set_up_2fa_viewmodel.dart index eacd3128d..b8fc40f23 100644 --- a/lib/view_model/set_up_2fa_viewmodel.dart +++ b/lib/view_model/set_up_2fa_viewmodel.dart @@ -201,38 +201,15 @@ abstract class Setup2FAViewModelBase with Store { @observable ObservableList selected2FASettings; - //! The code here works, but can be improved - //! Still trying out various ways to improve it - @action - void selectCakePreset(Cake2FAPresetsOptions cake2FAPreset) { - // The tabs are ordered in the format [Narrow || Normal || Verbose] - // Where Narrow = 0, Normal = 1 and Verbose = 2 - switch (cake2FAPreset) { - case Cake2FAPresetsOptions.narrow: - activateCake2FANarrowPreset(); - break; - case Cake2FAPresetsOptions.normal: - activateCake2FANormalPreset(); - break; - case Cake2FAPresetsOptions.aggressive: - activateCake2FAAggressivePreset(); - break; - default: - activateCake2FANormalPreset(); - } - } - @action void checkIfTheCurrentSettingMatchesAnyOfThePresets() { final hasNormalPreset = checkIfTheNormalPresetIsPresent(); final hasNarrowPreset = checkIfTheNarrowPresetIsPresent(); final hasVerbosePreset = checkIfTheVerbosePresetIsPresent(); - if (hasNormalPreset || hasNarrowPreset || hasVerbosePreset) { - unhighlightTabs = false; - } else { - unhighlightTabs = true; - } + if (hasNormalPreset || hasNarrowPreset || hasVerbosePreset) return; + + noCake2FAPresetSelected(); } @action @@ -288,32 +265,8 @@ abstract class Setup2FAViewModelBase with Store { } @action - void activateCake2FANormalPreset() { - _settingsStore.selectedCake2FAPreset = Cake2FAPresetsOptions.normal; - setAllControlsToFalse(); - switchShouldRequireTOTP2FAForSendsToNonContact(true); - switchShouldRequireTOTP2FAForSendsToContact(true); - switchShouldRequireTOTP2FAForSendsToInternalWallets(true); - switchShouldRequireTOTP2FAForExchangesToInternalWallets(true); - switchShouldRequireTOTP2FAForAllSecurityAndBackupSettings(true); - } - - @action - void activateCake2FANarrowPreset() { - _settingsStore.selectedCake2FAPreset = Cake2FAPresetsOptions.narrow; - setAllControlsToFalse(); - switchShouldRequireTOTP2FAForSendsToNonContact(true); - switchShouldRequireTOTP2FAForAddingContacts(true); - switchShouldRequireTOTP2FAForCreatingNewWallet(true); - switchShouldRequireTOTP2FAForAllSecurityAndBackupSettings(true); - } - - @action - void activateCake2FAAggressivePreset() { - _settingsStore.selectedCake2FAPreset = Cake2FAPresetsOptions.aggressive; - setAllControlsToFalse(); - switchShouldRequireTOTP2FAForAccessingWallet(true); - switchShouldRequireTOTP2FAForAllSecurityAndBackupSettings(true); + void noCake2FAPresetSelected() { + _settingsStore.selectedCake2FAPreset = Cake2FAPresetsOptions.none; } @action @@ -330,90 +283,106 @@ abstract class Setup2FAViewModelBase with Store { unhighlightTabs = false; } + final Map> presetsMap = { + Cake2FAPresetsOptions.normal: [ + VerboseControlSettings.sendsToContacts, + VerboseControlSettings.sendsToNonContacts, + VerboseControlSettings.sendsToInternalWallets, + VerboseControlSettings.securityAndBackupSettings, + VerboseControlSettings.exchangesToInternalWallets + ], + Cake2FAPresetsOptions.narrow: [ + VerboseControlSettings.addingContacts, + VerboseControlSettings.sendsToNonContacts, + VerboseControlSettings.creatingNewWallets, + VerboseControlSettings.securityAndBackupSettings, + ], + Cake2FAPresetsOptions.aggressive: [ + VerboseControlSettings.accessWallet, + VerboseControlSettings.securityAndBackupSettings, + ], + Cake2FAPresetsOptions.none: [], + }; + @action - void switchShouldRequireTOTP2FAForAccessingWallet(bool value) { - _settingsStore.shouldRequireTOTP2FAForAccessingWallet = value; - if (value) { - selected2FASettings.add(VerboseControlSettings.accessWallet); - } else { - selected2FASettings.remove(VerboseControlSettings.accessWallet); - } - checkIfTheCurrentSettingMatchesAnyOfThePresets(); + void selectCakePreset(Cake2FAPresetsOptions preset) { + presetsMap[preset]?.forEach(toggleControl); + _settingsStore.selectedCake2FAPreset = preset; + } + + @action + void toggleControl(VerboseControlSettings control, [bool value = true]) { + final methodsMap = { + VerboseControlSettings.sendsToContacts: switchShouldRequireTOTP2FAForSendsToContact, + VerboseControlSettings.accessWallet: switchShouldRequireTOTP2FAForAccessingWallet, + VerboseControlSettings.addingContacts: switchShouldRequireTOTP2FAForAddingContacts, + VerboseControlSettings.creatingNewWallets: switchShouldRequireTOTP2FAForCreatingNewWallet, + VerboseControlSettings.sendsToNonContacts: switchShouldRequireTOTP2FAForSendsToNonContact, + VerboseControlSettings.sendsToInternalWallets: + switchShouldRequireTOTP2FAForSendsToInternalWallets, + VerboseControlSettings.securityAndBackupSettings: + switchShouldRequireTOTP2FAForAllSecurityAndBackupSettings, + VerboseControlSettings.exchangesToInternalWallets: + switchShouldRequireTOTP2FAForExchangesToInternalWallets, + }; + + methodsMap[control]?.call(value); } @action void switchShouldRequireTOTP2FAForSendsToContact(bool value) { _settingsStore.shouldRequireTOTP2FAForSendsToContact = value; - if (value) { - selected2FASettings.add(VerboseControlSettings.sendsToContacts); - } else { - selected2FASettings.remove(VerboseControlSettings.sendsToContacts); - } - checkIfTheCurrentSettingMatchesAnyOfThePresets(); + updateSelectedSettings(VerboseControlSettings.sendsToContacts, value); + } + + @action + void switchShouldRequireTOTP2FAForAccessingWallet(bool value) { + _settingsStore.shouldRequireTOTP2FAForAccessingWallet = value; + updateSelectedSettings(VerboseControlSettings.accessWallet, value); } @action void switchShouldRequireTOTP2FAForSendsToNonContact(bool value) { _settingsStore.shouldRequireTOTP2FAForSendsToNonContact = value; - if (value) { - selected2FASettings.add(VerboseControlSettings.sendsToNonContacts); - } else { - selected2FASettings.remove(VerboseControlSettings.sendsToNonContacts); - } - checkIfTheCurrentSettingMatchesAnyOfThePresets(); + updateSelectedSettings(VerboseControlSettings.sendsToNonContacts, value); } @action void switchShouldRequireTOTP2FAForSendsToInternalWallets(bool value) { _settingsStore.shouldRequireTOTP2FAForSendsToInternalWallets = value; - if (value) { - selected2FASettings.add(VerboseControlSettings.sendsToInternalWallets); - } else { - selected2FASettings.remove(VerboseControlSettings.sendsToInternalWallets); - } - checkIfTheCurrentSettingMatchesAnyOfThePresets(); + updateSelectedSettings(VerboseControlSettings.sendsToInternalWallets, value); } @action void switchShouldRequireTOTP2FAForExchangesToInternalWallets(bool value) { _settingsStore.shouldRequireTOTP2FAForExchangesToInternalWallets = value; - if (value) { - selected2FASettings.add(VerboseControlSettings.exchangesToInternalWallets); - } else { - selected2FASettings.remove(VerboseControlSettings.exchangesToInternalWallets); - } - checkIfTheCurrentSettingMatchesAnyOfThePresets(); + updateSelectedSettings(VerboseControlSettings.exchangesToInternalWallets, value); } @action void switchShouldRequireTOTP2FAForAddingContacts(bool value) { _settingsStore.shouldRequireTOTP2FAForAddingContacts = value; - if (value) - selected2FASettings.add(VerboseControlSettings.addingContacts); - else { - selected2FASettings.remove(VerboseControlSettings.addingContacts); - } - checkIfTheCurrentSettingMatchesAnyOfThePresets(); + updateSelectedSettings(VerboseControlSettings.addingContacts, value); } @action void switchShouldRequireTOTP2FAForCreatingNewWallet(bool value) { _settingsStore.shouldRequireTOTP2FAForCreatingNewWallets = value; - if (value) { - selected2FASettings.add(VerboseControlSettings.creatingNewWallets); - } else { - selected2FASettings.remove(VerboseControlSettings.creatingNewWallets); - } - checkIfTheCurrentSettingMatchesAnyOfThePresets(); + updateSelectedSettings(VerboseControlSettings.creatingNewWallets, value); } @action void switchShouldRequireTOTP2FAForAllSecurityAndBackupSettings(bool value) { _settingsStore.shouldRequireTOTP2FAForAllSecurityAndBackupSettings = value; - if (value) - selected2FASettings.add(VerboseControlSettings.securityAndBackupSettings); - else { - selected2FASettings.remove(VerboseControlSettings.securityAndBackupSettings); + updateSelectedSettings(VerboseControlSettings.securityAndBackupSettings, value); + } + + @action + void updateSelectedSettings(VerboseControlSettings control, bool value) { + if (value) { + selected2FASettings.add(control); + } else { + selected2FASettings.remove(control); } checkIfTheCurrentSettingMatchesAnyOfThePresets(); } diff --git a/lib/view_model/support_view_model.dart b/lib/view_model/support_view_model.dart index ccef76154..d3b14c59b 100644 --- a/lib/view_model/support_view_model.dart +++ b/lib/view_model/support_view_model.dart @@ -53,11 +53,6 @@ abstract class SupportViewModelBase with Store { icon: 'assets/images/simpleSwap.png', linkTitle: 'support@simpleswap.io', link: 'mailto:support@simpleswap.io'), - LinkListItem( - title: 'Exolix', - icon: 'assets/images/exolix.png', - linkTitle: 'support@exolix.com', - link: 'mailto:support@exolix.com'), if (!isMoneroOnly) ... [ LinkListItem( title: 'Wyre', diff --git a/lib/view_model/trade_details_view_model.dart b/lib/view_model/trade_details_view_model.dart index 393629237..c0b1ac461 100644 --- a/lib/view_model/trade_details_view_model.dart +++ b/lib/view_model/trade_details_view_model.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:cake_wallet/exchange/changenow/changenow_exchange_provider.dart'; import 'package:cake_wallet/exchange/exchange_provider.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; -import 'package:cake_wallet/exchange/exolix/exolix_exchange_provider.dart'; import 'package:cake_wallet/exchange/morphtoken/morphtoken_exchange_provider.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'; import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart'; @@ -55,9 +54,6 @@ abstract class TradeDetailsViewModelBase with Store { case ExchangeProviderDescription.trocador: _provider = TrocadorExchangeProvider(); break; - case ExchangeProviderDescription.exolix: - _provider = ExolixExchangeProvider(); - break; } _updateItems(); @@ -161,12 +157,6 @@ abstract class TradeDetailsViewModelBase with Store { items.add(StandartListItem( title: '${trade.providerName} ${S.current.password}', value: trade.password ?? '')); } - - if (trade.provider == ExchangeProviderDescription.exolix) { - final buildURL = 'https://exolix.com/transaction/${trade.id.toString()}'; - items.add( - TrackTradeListItem(title: 'Track', value: buildURL, onTap: () => _launchUrl(buildURL))); - } } void _launchUrl(String url) { diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 92c8a0559..771c1f89a 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.6.2" -MONERO_COM_BUILD_NUMBER=58 +MONERO_COM_VERSION="1.7.0" +MONERO_COM_BUILD_NUMBER=61 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.9.2" -CAKEWALLET_BUILD_NUMBER=171 +CAKEWALLET_VERSION="4.10.0" +CAKEWALLET_BUILD_NUMBER=175 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 078688918..aa3116418 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.6.2" -MONERO_COM_BUILD_NUMBER=56 +MONERO_COM_VERSION="1.7.0" +MONERO_COM_BUILD_NUMBER=59 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.9.2" -CAKEWALLET_BUILD_NUMBER=185 +CAKEWALLET_VERSION="4.10.0" +CAKEWALLET_BUILD_NUMBER=189 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 5103d42b2..d649d752d 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -15,8 +15,8 @@ if [ -n "$1" ]; then fi CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.2.2" -CAKEWALLET_BUILD_NUMBER=33 +CAKEWALLET_VERSION="1.3.0" +CAKEWALLET_BUILD_NUMBER=36 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then diff --git a/tool/configure.dart b/tool/configure.dart index eff75eeae..f7b9dc126 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -639,6 +639,7 @@ abstract class Nano { Future changeRep(Object wallet, String address); Future updateTransactions(Object wallet); BigInt getTransactionAmountRaw(TransactionInfo transactionInfo); + String getRepresentative(Object wallet); } abstract class NanoAccountList { @@ -672,8 +673,7 @@ abstract class NanoUtil { BigInt rawPerBanano = BigInt.parse("100000000000000000000000000000"); BigInt rawPerXMR = BigInt.parse("1000000000000"); BigInt convertXMRtoNano = BigInt.parse("1000000000000000000"); - Decimal getRawAsDecimal(String? raw, BigInt? rawPerCur); - String truncateDecimal(Decimal input, {int digits = maxDecimalDigits}); + String getRawAsDecimalString(String? raw, BigInt? rawPerCur); String getRawAsUsableString(String? raw, BigInt rawPerCur); String getRawAccuracy(String? raw, BigInt rawPerCur); String getAmountAsRaw(String amount, BigInt rawPerCur); @@ -693,7 +693,7 @@ abstract class NanoUtil { } """; - const nanoEmptyDefinition = 'Nano? nano;\nNanoUtil? nanoUtil = CWNanoUtil();\n'; + const nanoEmptyDefinition = 'Nano? nano;\nNanoUtil? nanoUtil;\n'; const nanoCWDefinition = 'Nano? nano = CWNano();\nNanoUtil? nanoUtil = CWNanoUtil();\n'; final output = '$nanoCommonHeaders\n' + diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index a8c6a6166..fc2cc7fa8 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -32,7 +32,6 @@ class SecretKey { SecretKey('fiatApiKey', () => ''), SecretKey('payfuraApiKey', () => ''), SecretKey('chatwootWebsiteToken', () => ''), - SecretKey('exolixApiKey', () => ''), SecretKey('robinhoodApplicationId', () => ''), SecretKey('robinhoodCIdApiSecret', () => ''), SecretKey('walletConnectProjectId', () => ''), From dd81db74e8b7571d4163bc151767a428354f9821 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Mon, 9 Oct 2023 14:34:15 -0400 Subject: [PATCH 003/241] fix in strings_fr.arb (#1119) --- res/values/strings_fr.arb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index f2e336040..f171cbb68 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -514,7 +514,7 @@ "active_cards": "Cartes actives", "delete_account": "Supprimer le compte", "cards": "Cartes", - "active": "Actives, + "active": "Actives", "redeemed": "Converties", "gift_card_balance_note": "Les cartes-cadeaux avec un solde restant apparaîtront ici", "gift_card_redeemed_note": "Les cartes-cadeaux que vous avez utilisées apparaîtront ici", From 9afb8c230f21eface442b9755119718bca472f16 Mon Sep 17 00:00:00 2001 From: JanekGOOGLE140 <109436710+JanekGOOGLE140@users.noreply.github.com> Date: Tue, 10 Oct 2023 23:59:10 +0200 Subject: [PATCH 004/241] Update of strings_pl.arb (#1121) * Update strings_pl.arb * Update strings_pl.arb --- res/values/strings_pl.arb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 6e8e863a7..f243a2343 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -292,7 +292,7 @@ "available_balance": "Dostępne środki", "hidden_balance": "Ukryte saldo", "sync_status_syncronizing": "SYNCHRONIZACJA", - "sync_status_syncronized": "SYNCHRONIZOWANIE", + "sync_status_syncronized": "ZSYNCHRONIZOWANO", "sync_status_not_connected": "NIE POŁĄCZONY", "sync_status_starting_sync": "ROZPOCZĘCIE SYNCHRONIZACJI", "sync_status_failed_connect": "POŁĄCZENIE NIEUDANE", From a035872fc99c3f2e8eac4438ef0628fb3644f995 Mon Sep 17 00:00:00 2001 From: Procyon Lotor <110021993+ProcyonLotor123@users.noreply.github.com> Date: Thu, 12 Oct 2023 03:20:19 +0300 Subject: [PATCH 005/241] Exolix integration: bugfix apiToken on fetchRates (#1120) * Add Exolix exchange integration * update tx payload * remove import * Improve mapping * Additional fixes * fix apiBaseUrl * Update trade_details_view_model.dart * Update exolix_exchange_provider.dart * Fix status URL * Fix fetch rates API error handling update limits API to use a valid amount and validate on success status code * bugfix added apiToken for fetchRate --------- Co-authored-by: Justin Ehrenhofer Co-authored-by: Omar Hatem --- .github/workflows/pr_test_build.yml | 1 + assets/images/exolix.png | Bin 0 -> 1203 bytes .../exchange_provider_description.dart | 7 +- .../exolix/exolix_exchange_provider.dart | 295 ++++++++++++++++++ lib/exchange/exolix/exolix_request.dart | 20 ++ lib/exchange/trade_state.dart | 27 ++ .../screens/dashboard/widgets/trade_row.dart | 3 + lib/store/dashboard/trade_filter_store.dart | 18 +- .../dashboard/dashboard_view_model.dart | 5 + .../exchange/exchange_trade_view_model.dart | 4 + .../exchange/exchange_view_model.dart | 14 + lib/view_model/support_view_model.dart | 5 + lib/view_model/trade_details_view_model.dart | 10 + tool/utils/secret_key.dart | 1 + 14 files changed, 405 insertions(+), 5 deletions(-) create mode 100644 assets/images/exolix.png create mode 100644 lib/exchange/exolix/exolix_exchange_provider.dart create mode 100644 lib/exchange/exolix/exolix_request.dart diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 6b12911b6..af03c5e30 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -128,6 +128,7 @@ jobs: echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_ethereum/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 robinhoodCIdApiSecret = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> lib/.secrets.g.dart echo "const walletConnectProjectId = '${{ secrets.WALLET_CONNECT_PROJECT_ID }}';" >> lib/.secrets.g.dart diff --git a/assets/images/exolix.png b/assets/images/exolix.png new file mode 100644 index 0000000000000000000000000000000000000000..29e5f2db1d659dc3ca64858d800287c29b0a49fa GIT binary patch literal 1203 zcmV;k1WfyhP)Px(ZAnByRA@upT3t+3M-={MH7sigx|iVHa%-9*rD;eiDv(r5E2W5NYg6q{jN0l$ z+cY7PkiIm<#56^T51O>5sXnx%8dB;{OlVT-Pg|@HO{iU3kPSPJ+FaGHkbfx&^k z^U0W+*a2}bR6Yd3mjrNH!J)t?D0U3qQ4d+sXF8S$NDGx?AlPViQUkrCey{p204jnj zL?B02KBK@FA`^(p5}?87RU3KrI0+OuB{?t%z{Lw}Q!e25y4*nbs2PqafgF#gl+rnW znE_45_k=jgeEqloPK2G1Ku)f*jXLn%bQs5rNkZ7}8&I2#jWP5vwM_4iM4r#J+(13SXI#i^9@dtI5a2YU(uNmhna7;QxP2mD@jUbK>q zKq}(AsKv4JvG;_IfFvtIx1e2Ptm^x{YQ*lyACj#62;gn2pefa(IPSlrzNO2B?5;lB zx_!mZizPA!tl6s8U+PSlsD*by+X0qU5`u$vSFs=~3#Tf|?ZTk^%@542F2Ng5=2<3jsJjPET~|%@St>s0RWmgLcHJj-wyt&6a5@~OM#KvE zM#oTk>MXY&b0aeOlKO*Ni$icOA-MM18V*UlNPgSTLOL`=%ZVf_tpMH;(&P|cEz9_( zY#E2-gh<8N4%{4Occ{>4C2m>q8NFeJpeW#3RgC_QOA)oUmsX-^ezqx0bI%QYex=J) zE>=K$V<*f1i+62D{-#%Pvgmz;#>cg}C^KCF-w0xpk)nvSnD z%usM#BM}bb?u-mvtgeh}Ad4VR3;KO5kbMG_V#Bo-9d6(03;45kf8?{e!UEJi`^*#) zRll9X^#>0vuRc?>O`x)^3G)jVO)=uvjXN=PxhL}Zh3ZO385xoPTW;J!!@pN-8E>1w z6P3&H!q@fjjUd2@!Y#TgN$=}5TB>m`7({Wqb-$0E(DDuthXZeR9ZtA{!TZB#EBPQI zQzM01@^42+sqOSoJs97cZtz$#+g zV@bn%SiH5GTfV)b4#RzSx#a}}TZL1J%v?9to9bh|=%%LT743IaSe&ytDEO_oI%QkfGIfCwHv4qWNGF>{&^PuspT8b41Ke23l zSdm2~7M<)4-Gj!|jVMLQ-jB81#`d5T7eBTA_=E0AsS%i-n!jzn1^}#=pgjR*Pg#Yr zN&CXqr)3ePQ%{CSH#56U!b+I8_%}Z`CA*$vtl7DczP<+U={jod Rkx~Ev002ovPDHLkV1hCPI;#Kx literal 0 HcmV?d00001 diff --git a/lib/exchange/exchange_provider_description.dart b/lib/exchange/exchange_provider_description.dart index e545f69ce..151d018e0 100644 --- a/lib/exchange/exchange_provider_description.dart +++ b/lib/exchange/exchange_provider_description.dart @@ -24,7 +24,10 @@ class ExchangeProviderDescription extends EnumerableItem with Serializable< static const trocador = ExchangeProviderDescription(title: 'Trocador', raw: 5, image: 'assets/images/trocador.png'); - static const all = ExchangeProviderDescription(title: 'All trades', raw: 6, image: ''); + static const exolix = + ExchangeProviderDescription(title: 'Exolix', raw: 6, image: 'assets/images/exolix.png'); + + static const all = ExchangeProviderDescription(title: 'All trades', raw: 7, image: ''); static ExchangeProviderDescription deserialize({required int raw}) { switch (raw) { @@ -41,6 +44,8 @@ class ExchangeProviderDescription extends EnumerableItem with Serializable< case 5: return trocador; case 6: + return exolix; + case 7: return all; default: throw Exception('Unexpected token: $raw for ExchangeProviderDescription deserialize'); diff --git a/lib/exchange/exolix/exolix_exchange_provider.dart b/lib/exchange/exolix/exolix_exchange_provider.dart new file mode 100644 index 000000000..01b8ecc2b --- /dev/null +++ b/lib/exchange/exolix/exolix_exchange_provider.dart @@ -0,0 +1,295 @@ +import 'dart:convert'; +import 'package:cake_wallet/exchange/trade_not_found_exeption.dart'; +import 'package:http/http.dart'; +import 'package:cake_wallet/.secrets.g.dart' as secrets; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cake_wallet/exchange/exchange_pair.dart'; +import 'package:cake_wallet/exchange/exchange_provider.dart'; +import 'package:cake_wallet/exchange/limits.dart'; +import 'package:cake_wallet/exchange/trade.dart'; +import 'package:cake_wallet/exchange/trade_request.dart'; +import 'package:cake_wallet/exchange/trade_state.dart'; +import 'package:cake_wallet/exchange/exolix/exolix_request.dart'; +import 'package:cake_wallet/exchange/exchange_provider_description.dart'; + +class ExolixExchangeProvider extends ExchangeProvider { + ExolixExchangeProvider() : super(pairList: _supportedPairs()); + + static final apiKey = secrets.exolixApiKey; + static const apiBaseUrl = 'exolix.com'; + static const transactionsPath = '/api/v2/transactions'; + static const ratePath = '/api/v2/rate'; + + static const List _notSupported = [ + CryptoCurrency.usdt, + CryptoCurrency.xhv, + CryptoCurrency.btt, + CryptoCurrency.firo, + CryptoCurrency.zaddr, + CryptoCurrency.xvg, + CryptoCurrency.kmd, + CryptoCurrency.paxg, + CryptoCurrency.rune, + CryptoCurrency.scrt, + CryptoCurrency.btcln, + CryptoCurrency.cro, + CryptoCurrency.ftm, + CryptoCurrency.frax, + CryptoCurrency.gusd, + CryptoCurrency.gtc, + CryptoCurrency.weth, + ]; + + static List _supportedPairs() { + final supportedCurrencies = + CryptoCurrency.all.where((element) => !_notSupported.contains(element)).toList(); + + return supportedCurrencies + .map((i) => supportedCurrencies.map((k) => ExchangePair(from: i, to: k, reverse: true))) + .expand((i) => i) + .toList(); + } + + @override + String get title => 'Exolix'; + + @override + bool get isAvailable => true; + + @override + bool get isEnabled => true; + + @override + bool get supportsFixedRate => true; + + @override + ExchangeProviderDescription get description => ExchangeProviderDescription.exolix; + + @override + Future checkIsAvailable() async => true; + + static String getRateType(bool isFixedRate) => isFixedRate ? 'fixed' : 'float'; + + @override + Future fetchLimits( + {required CryptoCurrency from, + required CryptoCurrency to, + required bool isFixedRateMode}) async { + final params = { + 'rateType': getRateType(isFixedRateMode), + 'amount': '1', + }; + if (isFixedRateMode) { + params['coinFrom'] = _normalizeCurrency(to); + params['coinTo'] = _normalizeCurrency(from); + params['networkFrom'] = _networkFor(to); + params['networkTo'] = _networkFor(from); + } else { + params['coinFrom'] = _normalizeCurrency(from); + params['coinTo'] = _normalizeCurrency(to); + 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}'); + } + + final responseJSON = json.decode(response.body) as Map; + return Limits(min: responseJSON['minAmount'] as double?); + } + + @override + Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { + final _request = request as ExolixRequest; + + final headers = {'Content-Type': 'application/json'}; + final body = { + 'coinFrom': _normalizeCurrency(_request.from), + 'coinTo': _normalizeCurrency(_request.to), + 'networkFrom': _networkFor(_request.from), + 'networkTo': _networkFor(_request.to), + 'withdrawalAddress': _request.address, + 'refundAddress': _request.refundAddress, + 'rateType': getRateType(isFixedRateMode), + 'apiToken': apiKey, + }; + + if (isFixedRateMode) { + body['withdrawalAmount'] = _request.toAmount; + } else { + body['amount'] = _request.fromAmount; + } + + final uri = Uri.https(apiBaseUrl, transactionsPath); + final response = await post(uri, headers: headers, body: json.encode(body)); + + if (response.statusCode == 400) { + final responseJSON = json.decode(response.body) as Map; + final errors = responseJSON['errors'] as Map; + final errorMessage = errors.values.join(', '); + throw Exception(errorMessage); + } + + if (response.statusCode != 200 && response.statusCode != 201) { + throw Exception('Unexpected http status: ${response.statusCode}'); + } + + final responseJSON = json.decode(response.body) as Map; + final id = responseJSON['id'] as String; + final inputAddress = responseJSON['depositAddress'] as String; + final refundAddress = responseJSON['refundAddress'] as String?; + final extraId = responseJSON['depositExtraId'] as String?; + final payoutAddress = responseJSON['withdrawalAddress'] as String; + final amount = responseJSON['amount'].toString(); + + return Trade( + id: id, + from: _request.from, + to: _request.to, + provider: description, + inputAddress: inputAddress, + refundAddress: refundAddress, + extraId: extraId, + createdAt: DateTime.now(), + amount: amount, + state: TradeState.created, + payoutAddress: payoutAddress); + } + + @override + Future findTradeById({required String id}) async { + final findTradeByIdPath = transactionsPath + '/$id'; + final uri = Uri.https(apiBaseUrl, findTradeByIdPath); + final response = await get(uri); + + if (response.statusCode == 404) { + throw TradeNotFoundException(id, provider: description); + } + + if (response.statusCode == 400) { + final responseJSON = json.decode(response.body) as Map; + final errors = responseJSON['errors'] as Map; + final errorMessage = errors.values.join(', '); + + throw TradeNotFoundException(id, provider: description, description: errorMessage); + } + + if (response.statusCode != 200) { + throw Exception('Unexpected http status: ${response.statusCode}'); + } + + final responseJSON = json.decode(response.body) as Map; + final coinFrom = responseJSON['coinFrom']['coinCode'] as String; + final from = CryptoCurrency.fromString(coinFrom); + final coinTo = responseJSON['coinTo']['coinCode'] as String; + final to = CryptoCurrency.fromString(coinTo); + final inputAddress = responseJSON['depositAddress'] as String; + final amount = responseJSON['amount'].toString(); + final status = responseJSON['status'] as String; + final state = TradeState.deserialize(raw: _prepareStatus(status)); + final extraId = responseJSON['depositExtraId'] as String?; + final outputTransaction = responseJSON['hashOut']['hash'] as String?; + final payoutAddress = responseJSON['withdrawalAddress'] as String; + + return Trade( + id: id, + from: from, + to: to, + provider: description, + inputAddress: inputAddress, + amount: amount, + state: state, + extraId: extraId, + outputTransaction: outputTransaction, + payoutAddress: payoutAddress); + } + + @override + Future fetchRate( + {required CryptoCurrency from, + required CryptoCurrency to, + required double amount, + required bool isFixedRateMode, + required bool isReceiveAmount}) async { + try { + if (amount == 0) { + return 0.0; + } + + final params = { + 'coinFrom': _normalizeCurrency(from), + 'coinTo': _normalizeCurrency(to), + 'networkFrom': _networkFor(from), + 'networkTo': _networkFor(to), + 'rateType': getRateType(isFixedRateMode), + 'apiToken': apiKey, + }; + + if (isReceiveAmount) { + params['withdrawalAmount'] = amount.toString(); + } else { + params['amount'] = amount.toString(); + } + + final uri = Uri.https(apiBaseUrl, ratePath, params); + final response = await get(uri); + final responseJSON = json.decode(response.body) as Map; + + if (response.statusCode != 200) { + final message = responseJSON['message'] as String?; + throw Exception(message); + } + + final rate = responseJSON['rate'] as double; + + return rate; + } catch (e) { + print(e.toString()); + return 0.0; + } + } + + String _prepareStatus(String status) { + switch (status) { + case 'deleted': + case 'error': + return 'overdue'; + default: + return status; + } + } + + String _networkFor(CryptoCurrency currency) { + switch (currency) { + case CryptoCurrency.arb: + return 'ARBITRUM'; + default: + return currency.tag != null ? _normalizeTag(currency.tag!) : currency.title; + } + } + + String _normalizeCurrency(CryptoCurrency currency) { + switch (currency) { + case CryptoCurrency.nano: + return 'XNO'; + case CryptoCurrency.bttc: + return 'BTT'; + case CryptoCurrency.zec: + return 'ZEC'; + default: + return currency.title; + } + } + + String _normalizeTag(String tag) { + switch (tag) { + case 'POLY': + return 'Polygon'; + default: + return tag; + } + } +} diff --git a/lib/exchange/exolix/exolix_request.dart b/lib/exchange/exolix/exolix_request.dart new file mode 100644 index 000000000..e97ffa386 --- /dev/null +++ b/lib/exchange/exolix/exolix_request.dart @@ -0,0 +1,20 @@ +import 'package:flutter/foundation.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cake_wallet/exchange/trade_request.dart'; + +class ExolixRequest extends TradeRequest { + ExolixRequest( + {required this.from, + required this.to, + required this.address, + required this.fromAmount, + required this.toAmount, + required this.refundAddress}); + + CryptoCurrency from; + CryptoCurrency to; + String address; + String fromAmount; + String toAmount; + String refundAddress; +} diff --git a/lib/exchange/trade_state.dart b/lib/exchange/trade_state.dart index 98737339c..ebf74ce7a 100644 --- a/lib/exchange/trade_state.dart +++ b/lib/exchange/trade_state.dart @@ -35,6 +35,15 @@ class TradeState extends EnumerableItem with Serializable { static const completed = TradeState(raw: 'completed', title: 'Completed'); static const settling = TradeState(raw: 'settling', title: 'Settlement in progress'); static const settled = TradeState(raw: 'settled', title: 'Settlement completed'); + static const wait = TradeState(raw: 'wait', title: 'Waiting'); + static const overdue = TradeState(raw: 'overdue', title: 'Overdue'); + static const refund = TradeState(raw: 'refund', title: 'Refund'); + static const refunded = TradeState(raw: 'refunded', title: 'Refunded'); + static const confirmation = TradeState(raw: 'confirmation', title: 'Confirmation'); + static const confirmed = TradeState(raw: 'confirmed', title: 'Confirmed'); + static const exchanging = TradeState(raw: 'exchanging', title: 'Exchanging'); + static const sending = TradeState(raw: 'sending', title: 'Sending'); + static const success = TradeState(raw: 'success', title: 'Success'); static TradeState deserialize({required String raw}) { switch (raw) { case 'pending': @@ -77,6 +86,24 @@ class TradeState extends EnumerableItem with Serializable { return failed; case 'completed': return completed; + case 'wait': + return wait; + case 'overdue': + return overdue; + case 'refund': + return refund; + case 'refunded': + return refunded; + case 'confirmation': + return confirmation; + case 'confirmed': + return confirmed; + case 'exchanging': + return exchanging; + case 'sending': + return sending; + case 'success': + return success; default: throw Exception('Unexpected token: $raw in TradeState deserialize'); } diff --git a/lib/src/screens/dashboard/widgets/trade_row.dart b/lib/src/screens/dashboard/widgets/trade_row.dart index a42593f24..7f570b98e 100644 --- a/lib/src/screens/dashboard/widgets/trade_row.dart +++ b/lib/src/screens/dashboard/widgets/trade_row.dart @@ -94,6 +94,9 @@ class TradeRow extends StatelessWidget { borderRadius: BorderRadius.circular(50), child: Image.asset('assets/images/trocador.png', width: 36, height: 36)); break; + case ExchangeProviderDescription.exolix: + image = Image.asset('assets/images/exolix.png', width: 36, height: 36); + break; default: image = null; } diff --git a/lib/store/dashboard/trade_filter_store.dart b/lib/store/dashboard/trade_filter_store.dart index c772a35d6..799e8b951 100644 --- a/lib/store/dashboard/trade_filter_store.dart +++ b/lib/store/dashboard/trade_filter_store.dart @@ -13,7 +13,8 @@ abstract class TradeFilterStoreBase with Store { displaySideShift = true, displayMorphToken = true, displaySimpleSwap = true, - displayTrocador = true; + displayTrocador = true, + displayExolix = true; @observable bool displayXMRTO; @@ -33,8 +34,11 @@ abstract class TradeFilterStoreBase with Store { @observable bool displayTrocador; + @observable + bool displayExolix; + @computed - bool get displayAllTrades => displayChangeNow && displaySideShift && displaySimpleSwap && displayTrocador; + bool get displayAllTrades => displayChangeNow && displaySideShift && displaySimpleSwap && displayTrocador && displayExolix; @action void toggleDisplayExchange(ExchangeProviderDescription provider) { @@ -56,7 +60,10 @@ abstract class TradeFilterStoreBase with Store { break; case ExchangeProviderDescription.trocador: displayTrocador = !displayTrocador; - break; + break; + case ExchangeProviderDescription.exolix: + displayExolix = !displayExolix; + break; case ExchangeProviderDescription.all: if (displayAllTrades) { displayChangeNow = false; @@ -65,6 +72,7 @@ abstract class TradeFilterStoreBase with Store { displayMorphToken = false; displaySimpleSwap = false; displayTrocador = false; + displayExolix = false; } else { displayChangeNow = true; displaySideShift = true; @@ -72,6 +80,7 @@ abstract class TradeFilterStoreBase with Store { displayMorphToken = true; displaySimpleSwap = true; displayTrocador = true; + displayExolix = true; } break; } @@ -98,7 +107,8 @@ abstract class TradeFilterStoreBase with Store { ||(displaySimpleSwap && item.trade.provider == ExchangeProviderDescription.simpleSwap) - ||(displayTrocador && item.trade.provider == ExchangeProviderDescription.trocador)) + ||(displayTrocador && item.trade.provider == ExchangeProviderDescription.trocador) + ||(displayExolix && item.trade.provider == ExchangeProviderDescription.exolix)) .toList() : _trades; } diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index f6eb7f244..03f0aa9a8 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -98,6 +98,11 @@ abstract class DashboardViewModelBase with Store { caption: ExchangeProviderDescription.trocador.title, onChanged: () => tradeFilterStore .toggleDisplayExchange(ExchangeProviderDescription.trocador)), + FilterItem( + value: () => tradeFilterStore.displayExolix, + caption: ExchangeProviderDescription.exolix.title, + onChanged: () => tradeFilterStore + .toggleDisplayExchange(ExchangeProviderDescription.exolix)), ] }, subname = '', diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index cfabd994f..346844171 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'package:cake_wallet/exchange/exolix/exolix_exchange_provider.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'; import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart'; import 'package:cake_wallet/exchange/trocador/trocador_exchange_provider.dart'; @@ -53,6 +54,9 @@ abstract class ExchangeTradeViewModelBase with Store { case ExchangeProviderDescription.trocador: _provider = TrocadorExchangeProvider(); break; + case ExchangeProviderDescription.exolix: + _provider = ExolixExchangeProvider(); + break; } _updateItems(); diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index b438e9b74..47b408bc2 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -6,6 +6,8 @@ import 'package:cake_wallet/core/wallet_change_listener_view_model.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/wallet_contact.dart'; +import 'package:cake_wallet/exchange/exolix/exolix_exchange_provider.dart'; +import 'package:cake_wallet/exchange/exolix/exolix_request.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_request.dart'; import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart'; @@ -150,6 +152,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with SideShiftExchangeProvider(), SimpleSwapExchangeProvider(), TrocadorExchangeProvider(useTorOnly: _useTorOnly), + ExolixExchangeProvider(), ]; @observable @@ -546,6 +549,17 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with amount = isFixedRateMode ? receiveAmount : depositAmount; } + if (provider is ExolixExchangeProvider) { + request = ExolixRequest( + from: depositCurrency, + to: receiveCurrency, + fromAmount: depositAmount.replaceAll(',', '.'), + toAmount: receiveAmount.replaceAll(',', '.'), + refundAddress: depositAddress, + address: receiveAddress); + amount = isFixedRateMode ? receiveAmount : depositAmount; + } + amount = amount.replaceAll(',', '.'); if (limitsState is LimitsLoadedSuccessfully) { diff --git a/lib/view_model/support_view_model.dart b/lib/view_model/support_view_model.dart index d3b14c59b..ccef76154 100644 --- a/lib/view_model/support_view_model.dart +++ b/lib/view_model/support_view_model.dart @@ -53,6 +53,11 @@ abstract class SupportViewModelBase with Store { icon: 'assets/images/simpleSwap.png', linkTitle: 'support@simpleswap.io', link: 'mailto:support@simpleswap.io'), + LinkListItem( + title: 'Exolix', + icon: 'assets/images/exolix.png', + linkTitle: 'support@exolix.com', + link: 'mailto:support@exolix.com'), if (!isMoneroOnly) ... [ LinkListItem( title: 'Wyre', diff --git a/lib/view_model/trade_details_view_model.dart b/lib/view_model/trade_details_view_model.dart index c0b1ac461..393629237 100644 --- a/lib/view_model/trade_details_view_model.dart +++ b/lib/view_model/trade_details_view_model.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:cake_wallet/exchange/changenow/changenow_exchange_provider.dart'; import 'package:cake_wallet/exchange/exchange_provider.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; +import 'package:cake_wallet/exchange/exolix/exolix_exchange_provider.dart'; import 'package:cake_wallet/exchange/morphtoken/morphtoken_exchange_provider.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'; import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart'; @@ -54,6 +55,9 @@ abstract class TradeDetailsViewModelBase with Store { case ExchangeProviderDescription.trocador: _provider = TrocadorExchangeProvider(); break; + case ExchangeProviderDescription.exolix: + _provider = ExolixExchangeProvider(); + break; } _updateItems(); @@ -157,6 +161,12 @@ abstract class TradeDetailsViewModelBase with Store { items.add(StandartListItem( title: '${trade.providerName} ${S.current.password}', value: trade.password ?? '')); } + + if (trade.provider == ExchangeProviderDescription.exolix) { + final buildURL = 'https://exolix.com/transaction/${trade.id.toString()}'; + items.add( + TrackTradeListItem(title: 'Track', value: buildURL, onTap: () => _launchUrl(buildURL))); + } } void _launchUrl(String url) { diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index fc2cc7fa8..a8c6a6166 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -32,6 +32,7 @@ class SecretKey { SecretKey('fiatApiKey', () => ''), SecretKey('payfuraApiKey', () => ''), SecretKey('chatwootWebsiteToken', () => ''), + SecretKey('exolixApiKey', () => ''), SecretKey('robinhoodApplicationId', () => ''), SecretKey('robinhoodCIdApiSecret', () => ''), SecretKey('walletConnectProjectId', () => ''), From acb05178713e2d4b0bad2ac84f410fb69e2e5f67 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Wed, 11 Oct 2023 20:32:11 -0400 Subject: [PATCH 006/241] fix , bug and swapping for nano (#1123) --- cw_nano/lib/nano_wallet.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cw_nano/lib/nano_wallet.dart b/cw_nano/lib/nano_wallet.dart index da50f4ebb..bf7cc6bca 100644 --- a/cw_nano/lib/nano_wallet.dart +++ b/cw_nano/lib/nano_wallet.dart @@ -169,8 +169,8 @@ abstract class NanoWalletBase if (txOut.sendAll) { amt = balance[currency]?.currentBalance ?? BigInt.zero; } else { - amt = BigInt.tryParse( - NanoUtil.getAmountAsRaw(txOut.cryptoAmount ?? "0", NanoUtil.rawPerNano)) ?? + amt = BigInt.tryParse(NanoUtil.getAmountAsRaw( + txOut.cryptoAmount?.replaceAll(',', '.') ?? "0", NanoUtil.rawPerNano)) ?? BigInt.zero; } @@ -182,7 +182,9 @@ abstract class NanoWalletBase final block = await _client.constructSendBlock( amountRaw: amt.toString(), - destinationAddress: txOut.extractedAddress ?? txOut.address, + destinationAddress: credentials.outputs.first.isParsedAddress + ? credentials.outputs.first.extractedAddress! + : credentials.outputs.first.address, privateKey: _privateKey!, balanceAfterTx: runningBalance, previousHash: previousHash, From 66301ff2478c1879859b5a20d4deff0559f7af25 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 13 Oct 2023 01:50:16 +0300 Subject: [PATCH 007/241] CW-432-Add-Bitcoin-Cash-BCH (#1041) * initial commit * creating and restoring a wallet * [skip ci] add transaction priority * fix send and unspent screen * fix transaction priority type * replace Unspend with BitcoinUnspent * add transaction creation * fix transaction details screen * minor fix * fix create side wallet * basic transaction creation flow * fix fiat amount calculation * edit wallet * minor fix * fix address book parsing * merge commit fixes * minor fixes * Update gradle.properties * fix bch unspent coins * minor fix * fix BitcoinCashTransactionPriority * Fetch tags first before switching to one of them * Update build_haven.sh * Update build_haven.sh * Update build_haven.sh * Update build_haven.sh * update transaction build function * Update build_haven.sh * add ability to rename and delete * fix address format * Update pubspec.lock * Revert "fix address format" This reverts commit 1549bf4d8c3bdb0addbd6e3c5f049ebc3799ff8f. * fix address format for exange * restore from qr * Update configure.dart * [skip ci] minor fix * fix default fee rate * Update onramper_buy_provider.dart * Update wallet_address_list_view_model.dart * PR comments fixes * Update exchange_view_model.dart * fix merge conflict * Update address_validator.dart * merge fixes * update initialMigrationVersion * move cw_bitbox to Cake tech * PR fixes * PR fixes * Fix configure.dart brackets * update the new version text after macos * dummy change to run workflow * Fix Nano restore from QR issue Fix Conflicts with main * PR fixes * Update app_config.sh --------- Co-authored-by: Omar Hatem --- .github/workflows/pr_test_build.yml | 26 +- .gitignore | 1 + android/gradle.properties | 2 +- assets/bitcoin_cash_electrum_server_list.yml | 3 + configure_cake_wallet_android.sh | 1 + .../lib/bitcoin_transaction_priority.dart | 52 ++- cw_bitcoin/lib/bitcoin_unspent.dart | 23 +- cw_bitcoin/lib/bitcoin_wallet_addresses.dart | 45 ++- cw_bitcoin/lib/electrum_wallet.dart | 251 +++++++-------- cw_bitcoin/lib/electrum_wallet_addresses.dart | 17 +- cw_bitcoin/pubspec.lock | 9 + cw_bitcoin/pubspec.yaml | 4 + cw_bitcoin_cash/.gitignore | 30 ++ cw_bitcoin_cash/.metadata | 10 + cw_bitcoin_cash/CHANGELOG.md | 3 + cw_bitcoin_cash/LICENSE | 1 + cw_bitcoin_cash/README.md | 39 +++ cw_bitcoin_cash/analysis_options.yaml | 4 + cw_bitcoin_cash/lib/cw_bitcoin_cash.dart | 9 + .../lib/src/bitcoin_cash_address_utils.dart | 5 + .../lib/src/bitcoin_cash_base.dart | 7 + .../lib/src/bitcoin_cash_wallet.dart | 297 ++++++++++++++++++ .../src/bitcoin_cash_wallet_addresses.dart | 34 ++ ...coin_cash_wallet_creation_credentials.dart | 26 ++ .../lib/src/bitcoin_cash_wallet_service.dart | 107 +++++++ ..._cash_mnemonic_is_incorrect_exception.dart | 5 + .../lib/src/exceptions/exceptions.dart | 1 + cw_bitcoin_cash/lib/src/mnemonic.dart | 11 + .../src/pending_bitcoin_cash_transaction.dart | 62 ++++ .../.plugin_symlinks/path_provider_linux | 1 + .../flutter/generated_plugin_registrant.cc | 11 + .../flutter/generated_plugin_registrant.h | 15 + .../linux/flutter/generated_plugins.cmake | 23 ++ .../Flutter/GeneratedPluginRegistrant.swift | 12 + .../ephemeral/Flutter-Generated.xcconfig | 11 + .../ephemeral/flutter_export_environment.sh | 12 + cw_bitcoin_cash/pubspec.yaml | 76 +++++ .../test/cw_bitcoin_cash_test.dart | 12 + .../flutter/generated_plugin_registrant.cc | 11 + .../flutter/generated_plugin_registrant.h | 15 + .../windows/flutter/generated_plugins.cmake | 23 ++ cw_core/lib/amount_converter.dart | 1 + cw_core/lib/currency_for_wallet_type.dart | 2 + cw_core/lib/node.dart | 4 + .../lib}/unspent_transaction_output.dart | 0 cw_core/lib/wallet_type.dart | 15 + lib/bitcoin/cw_bitcoin.dart | 12 +- lib/bitcoin_cash/cw_bitcoin_cash.dart | 45 +++ lib/buy/onramper/onramper_buy_provider.dart | 2 + lib/core/address_validator.dart | 9 + lib/core/seed_validator.dart | 2 + lib/di.dart | 3 + lib/entities/default_settings_migration.dart | 87 +++-- lib/entities/main_actions.dart | 2 + lib/entities/node_list.dart | 23 +- lib/entities/preferences_key.dart | 2 + lib/entities/priority_for_wallet_type.dart | 3 + lib/ethereum/cw_ethereum.dart | 3 + lib/main.dart | 2 +- .../desktop_wallet_selection_dropdown.dart | 3 + .../dashboard/widgets/menu_widget.dart | 7 +- lib/src/screens/seed/pre_seed_page.dart | 1 + .../unspent_coins_list_page.dart | 7 +- .../screens/wallet_list/wallet_list_page.dart | 3 + lib/store/settings_store.dart | 195 +++++++----- .../dashboard/transaction_list_item.dart | 1 + .../exchange/exchange_view_model.dart | 29 +- .../node_list/node_list_view_model.dart | 3 + .../restore/restore_from_qr_vm.dart | 4 + .../restore/wallet_restore_from_qr_code.dart | 6 + lib/view_model/send/output.dart | 10 +- lib/view_model/send/send_view_model.dart | 46 +-- .../settings/other_settings_view_model.dart | 4 +- .../transaction_details_view_model.dart | 4 + .../unspent_coins_details_view_model.dart | 25 +- .../unspent_coins_list_view_model.dart | 37 +-- ...let_address_edit_or_create_view_model.dart | 3 +- .../wallet_address_list_view_model.dart | 26 +- lib/view_model/wallet_keys_view_model.dart | 6 +- lib/view_model/wallet_new_vm.dart | 5 +- lib/view_model/wallet_restore_view_model.dart | 19 +- model_generator.sh | 1 + pubspec_base.yaml | 1 + scripts/android/app_config.sh | 2 +- scripts/android/pubspec_gen.sh | 2 +- scripts/ios/app_config.sh | 4 +- scripts/macos/app_config.sh | 2 +- tool/configure.dart | 121 +++++-- 88 files changed, 1685 insertions(+), 416 deletions(-) create mode 100644 assets/bitcoin_cash_electrum_server_list.yml create mode 100644 cw_bitcoin_cash/.gitignore create mode 100644 cw_bitcoin_cash/.metadata create mode 100644 cw_bitcoin_cash/CHANGELOG.md create mode 100644 cw_bitcoin_cash/LICENSE create mode 100644 cw_bitcoin_cash/README.md create mode 100644 cw_bitcoin_cash/analysis_options.yaml create mode 100644 cw_bitcoin_cash/lib/cw_bitcoin_cash.dart create mode 100644 cw_bitcoin_cash/lib/src/bitcoin_cash_address_utils.dart create mode 100644 cw_bitcoin_cash/lib/src/bitcoin_cash_base.dart create mode 100644 cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart create mode 100644 cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart create mode 100644 cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_creation_credentials.dart create mode 100644 cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart create mode 100644 cw_bitcoin_cash/lib/src/exceptions/bitcoin_cash_mnemonic_is_incorrect_exception.dart create mode 100644 cw_bitcoin_cash/lib/src/exceptions/exceptions.dart create mode 100644 cw_bitcoin_cash/lib/src/mnemonic.dart create mode 100644 cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart create mode 120000 cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux create mode 100644 cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.cc create mode 100644 cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.h create mode 100644 cw_bitcoin_cash/linux/flutter/generated_plugins.cmake create mode 100644 cw_bitcoin_cash/macos/Flutter/GeneratedPluginRegistrant.swift create mode 100644 cw_bitcoin_cash/macos/Flutter/ephemeral/Flutter-Generated.xcconfig create mode 100644 cw_bitcoin_cash/macos/Flutter/ephemeral/flutter_export_environment.sh create mode 100644 cw_bitcoin_cash/pubspec.yaml create mode 100644 cw_bitcoin_cash/test/cw_bitcoin_cash_test.dart create mode 100644 cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.cc create mode 100644 cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.h create mode 100644 cw_bitcoin_cash/windows/flutter/generated_plugins.cmake rename {lib/entities => cw_core/lib}/unspent_transaction_output.dart (100%) create mode 100644 lib/bitcoin_cash/cw_bitcoin_cash.dart mode change 100755 => 100644 model_generator.sh mode change 100755 => 100644 scripts/ios/app_config.sh diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index af03c5e30..5434429b2 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -42,6 +42,7 @@ jobs: cd cake_wallet/scripts/android/ ./install_ndk.sh source ./app_env.sh cakewallet + chmod +x pubspec_gen.sh ./app_config.sh - name: Cache Externals @@ -92,6 +93,7 @@ jobs: cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_ethereum && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. + cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs @@ -141,18 +143,18 @@ jobs: cd /opt/android/cake_wallet flutter build apk --release - # - name: Push to App Center - # run: | - # echo 'Installing App Center CLI tools' - # npm install -g appcenter-cli - # echo "Publishing test to App Center" - # appcenter distribute release \ - # --group "Testers" \ - # --file "/opt/android/cake_wallet/build/app/outputs/apk/release/app-release.apk" \ - # --release-notes ${GITHUB_HEAD_REF} \ - # --app Cake-Labs/Cake-Wallet \ - # --token ${{ secrets.APP_CENTER_TOKEN }} \ - # --quiet +# - name: Push to App Center +# run: | +# echo 'Installing App Center CLI tools' +# npm install -g appcenter-cli +# echo "Publishing test to App Center" +# appcenter distribute release \ +# --group "Testers" \ +# --file "/opt/android/cake_wallet/build/app/outputs/apk/release/app-release.apk" \ +# --release-notes ${GITHUB_HEAD_REF} \ +# --app Cake-Labs/Cake-Wallet \ +# --token ${{ secrets.APP_CENTER_TOKEN }} \ +# --quiet - name: Rename apk file run: | diff --git a/.gitignore b/.gitignore index e8fb0048c..c735d4058 100644 --- a/.gitignore +++ b/.gitignore @@ -124,6 +124,7 @@ lib/bitcoin/bitcoin.dart lib/monero/monero.dart lib/haven/haven.dart lib/ethereum/ethereum.dart +lib/bitcoin_cash/bitcoin_cash.dart lib/nano/nano.dart ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_180.png diff --git a/android/gradle.properties b/android/gradle.properties index a5965ab8d..38c8d4544 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,4 +1,4 @@ org.gradle.jvmargs=-Xmx1536M android.enableR8=true android.useAndroidX=true -android.enableJetifier=true \ No newline at end of file +android.enableJetifier=true diff --git a/assets/bitcoin_cash_electrum_server_list.yml b/assets/bitcoin_cash_electrum_server_list.yml new file mode 100644 index 000000000..d76668169 --- /dev/null +++ b/assets/bitcoin_cash_electrum_server_list.yml @@ -0,0 +1,3 @@ +- + uri: bitcoincash.stackwallet.com:50002 + is_default: true \ No newline at end of file diff --git a/configure_cake_wallet_android.sh b/configure_cake_wallet_android.sh index 792159f29..b8aa433de 100755 --- a/configure_cake_wallet_android.sh +++ b/configure_cake_wallet_android.sh @@ -8,4 +8,5 @@ cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_ethereum && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs diff --git a/cw_bitcoin/lib/bitcoin_transaction_priority.dart b/cw_bitcoin/lib/bitcoin_transaction_priority.dart index d82ea429e..10953a2e0 100644 --- a/cw_bitcoin/lib/bitcoin_transaction_priority.dart +++ b/cw_bitcoin/lib/bitcoin_transaction_priority.dart @@ -1,5 +1,4 @@ import 'package:cw_core/transaction_priority.dart'; -//import 'package:cake_wallet/generated/i18n.dart'; class BitcoinTransactionPriority extends TransactionPriority { const BitcoinTransactionPriority({required String title, required int raw}) @@ -100,4 +99,55 @@ class LitecoinTransactionPriority extends BitcoinTransactionPriority { return label; } + } +class BitcoinCashTransactionPriority extends BitcoinTransactionPriority { + const BitcoinCashTransactionPriority({required String title, required int raw}) + : super(title: title, raw: raw); + + static const List all = [fast, medium, slow]; + static const BitcoinCashTransactionPriority slow = + BitcoinCashTransactionPriority(title: 'Slow', raw: 0); + static const BitcoinCashTransactionPriority medium = + BitcoinCashTransactionPriority(title: 'Medium', raw: 1); + static const BitcoinCashTransactionPriority fast = + BitcoinCashTransactionPriority(title: 'Fast', raw: 2); + + static BitcoinCashTransactionPriority deserialize({required int raw}) { + switch (raw) { + case 0: + return slow; + case 1: + return medium; + case 2: + return fast; + default: + throw Exception('Unexpected token: $raw for BitcoinCashTransactionPriority deserialize'); + } + } + + @override + String get units => 'Satoshi'; + + @override + String toString() { + var label = ''; + + switch (this) { + case BitcoinCashTransactionPriority.slow: + label = 'Slow'; // S.current.transaction_priority_slow; + break; + case BitcoinCashTransactionPriority.medium: + label = 'Medium'; // S.current.transaction_priority_medium; + break; + case BitcoinCashTransactionPriority.fast: + label = 'Fast'; // S.current.transaction_priority_fast; + break; + default: + break; + } + + return label; + } +} + diff --git a/cw_bitcoin/lib/bitcoin_unspent.dart b/cw_bitcoin/lib/bitcoin_unspent.dart index e5a0e8cac..9c198c27c 100644 --- a/cw_bitcoin/lib/bitcoin_unspent.dart +++ b/cw_bitcoin/lib/bitcoin_unspent.dart @@ -1,24 +1,15 @@ import 'package:cw_bitcoin/bitcoin_address_record.dart'; +import 'package:cw_core/unspent_transaction_output.dart'; -class BitcoinUnspent { - BitcoinUnspent(this.address, this.hash, this.value, this.vout) - : isSending = true, - isFrozen = false, - note = ''; +class BitcoinUnspent extends Unspent { + BitcoinUnspent(BitcoinAddressRecord addressRecord, String hash, int value, int vout) + : bitcoinAddressRecord = addressRecord, + super(addressRecord.address, hash, value, vout, null); factory BitcoinUnspent.fromJSON( - BitcoinAddressRecord address, Map json) => + BitcoinAddressRecord address, Map json) => BitcoinUnspent(address, json['tx_hash'] as String, json['value'] as int, json['tx_pos'] as int); - final BitcoinAddressRecord address; - final String hash; - final int value; - final int vout; - - bool get isP2wpkh => - address.address.startsWith('bc') || address.address.startsWith('ltc'); - bool isSending; - bool isFrozen; - String note; + final BitcoinAddressRecord bitcoinAddressRecord; } diff --git a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart index de3fdfbca..36d37127d 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart @@ -1,39 +1,34 @@ import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:cw_bitcoin/electrum.dart'; -import 'package:cw_bitcoin/utils.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; +import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; +import 'package:cw_bitcoin/utils.dart'; import 'package:cw_core/wallet_info.dart'; -import 'package:flutter/foundation.dart'; import 'package:mobx/mobx.dart'; part 'bitcoin_wallet_addresses.g.dart'; -class BitcoinWalletAddresses = BitcoinWalletAddressesBase - with _$BitcoinWalletAddresses; +class BitcoinWalletAddresses = BitcoinWalletAddressesBase with _$BitcoinWalletAddresses; -abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses - with Store { - BitcoinWalletAddressesBase( - WalletInfo walletInfo, +abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with Store { + BitcoinWalletAddressesBase(WalletInfo walletInfo, {required bitcoin.HDWallet mainHd, - required bitcoin.HDWallet sideHd, - required bitcoin.NetworkType networkType, - required ElectrumClient electrumClient, - List? initialAddresses, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) - : super( - walletInfo, - initialAddresses: initialAddresses, - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex, - mainHd: mainHd, - sideHd: sideHd, - electrumClient: electrumClient, - networkType: networkType); + required bitcoin.HDWallet sideHd, + required bitcoin.NetworkType networkType, + required ElectrumClient electrumClient, + List? initialAddresses, + int initialRegularAddressIndex = 0, + int initialChangeAddressIndex = 0}) + : super(walletInfo, + initialAddresses: initialAddresses, + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + mainHd: mainHd, + sideHd: sideHd, + electrumClient: electrumClient, + networkType: networkType); @override String getAddress({required int index, required bitcoin.HDWallet hd}) => generateP2WPKHAddress(hd: hd, index: index, networkType: networkType); -} \ No newline at end of file +} diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 1c0a1e4e3..804b53379 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -2,7 +2,9 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:math'; +import 'package:cw_core/pending_transaction.dart'; import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:mobx/mobx.dart'; @@ -34,45 +36,52 @@ import 'package:cw_bitcoin/electrum.dart'; import 'package:hex/hex.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:collection/collection.dart'; +import 'package:bip32/bip32.dart'; part 'electrum_wallet.g.dart'; class ElectrumWallet = ElectrumWalletBase with _$ElectrumWallet; -abstract class ElectrumWalletBase extends WalletBase with Store { +abstract class ElectrumWalletBase + extends WalletBase + with Store { ElectrumWalletBase( {required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - required this.networkType, - required this.mnemonic, - required Uint8List seedBytes, - List? initialAddresses, - ElectrumClient? electrumClient, - ElectrumBalance? initialBalance, - CryptoCurrency? currency}) - : hd = bitcoin.HDWallet.fromSeed(seedBytes, network: networkType) - .derivePath("m/0'/0"), + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required this.networkType, + required this.mnemonic, + required Uint8List seedBytes, + List? initialAddresses, + ElectrumClient? electrumClient, + ElectrumBalance? initialBalance, + CryptoCurrency? currency}) + : hd = currency == CryptoCurrency.bch + ? bitcoinCashHDWallet(seedBytes) + : bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/0"), syncStatus = NotConnectedSyncStatus(), _password = password, _feeRates = [], _isTransactionUpdating = false, unspentCoins = [], _scripthashesUpdateSubject = {}, - balance = ObservableMap.of( - currency != null - ? {currency: initialBalance ?? const ElectrumBalance(confirmed: 0, unconfirmed: 0, - frozen: 0)} - : {}), + balance = ObservableMap.of(currency != null + ? { + currency: + initialBalance ?? const ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0) + } + : {}), this.unspentCoinsInfo = unspentCoinsInfo, super(walletInfo) { this.electrumClient = electrumClient ?? ElectrumClient(); this.walletInfo = walletInfo; - transactionHistory = - ElectrumTransactionHistory(walletInfo: walletInfo, password: password); + transactionHistory = ElectrumTransactionHistory(walletInfo: walletInfo, password: password); } + static bitcoin.HDWallet bitcoinCashHDWallet(Uint8List seedBytes) => + bitcoin.HDWallet.fromSeed(seedBytes) + .derivePath("m/44'/145'/0'/0"); + static int estimatedTransactionSize(int inputsCount, int outputsCounts) => inputsCount * 146 + outputsCounts * 33 + 8; @@ -98,9 +107,9 @@ abstract class ElectrumWalletBase extends WalletBase get publicScriptHashes => walletAddresses.addresses - .where((addr) => !addr.isHidden) - .map((addr) => scriptHash(addr.address, networkType: networkType)) - .toList(); + .where((addr) => !addr.isHidden) + .map((addr) => scriptHash(addr.address, networkType: networkType)) + .toList(); String get xpub => hd.base58!; @@ -110,8 +119,8 @@ abstract class ElectrumWalletBase extends WalletBase BitcoinWalletKeys( - wif: hd.wif!, privateKey: hd.privKey!, publicKey: hd.pubKey!); + BitcoinWalletKeys get keys => + BitcoinWalletKeys(wif: hd.wif!, privateKey: hd.privKey!, publicKey: hd.pubKey!); String _password; List unspentCoins; @@ -139,8 +148,8 @@ abstract class ElectrumWalletBase extends WalletBase _feeRates = await electrumClient.feeRates()); + Timer.periodic( + const Duration(minutes: 1), (timer) async => _feeRates = await electrumClient.feeRates()); syncStatus = SyncedSyncStatus(); } catch (e, stacktrace) { @@ -169,8 +178,7 @@ abstract class ElectrumWalletBase extends WalletBase createTransaction( - Object credentials) async { + Future createTransaction(Object credentials) async { const minAmount = 546; final transactionCredentials = credentials as BitcoinTransactionCredentials; final inputs = []; @@ -204,13 +212,11 @@ abstract class ElectrumWalletBase extends WalletBase item.sendAll - || item.formattedCryptoAmount! <= 0)) { + if (outputs.any((item) => item.sendAll || item.formattedCryptoAmount! <= 0)) { throw BitcoinTransactionWrongBalanceException(currency); } - credentialsAmount = outputs.fold(0, (acc, value) => - acc + value.formattedCryptoAmount!); + credentialsAmount = outputs.fold(0, (acc, value) => acc + value.formattedCryptoAmount!); if (allAmount - credentialsAmount < minAmount) { throw BitcoinTransactionWrongBalanceException(currency); @@ -227,9 +233,7 @@ abstract class ElectrumWalletBase extends WalletBase allAmount) { throw BitcoinTransactionWrongBalanceException(currency); @@ -291,8 +295,8 @@ abstract class ElectrumWalletBase extends WalletBase json.encode({ - 'mnemonic': mnemonic, - 'account_index': walletAddresses.currentReceiveAddressIndex.toString(), - 'change_address_index': walletAddresses.currentChangeAddressIndex.toString(), - 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), - 'balance': balance[currency]?.toJSON() - }); + 'mnemonic': mnemonic, + 'account_index': walletAddresses.currentReceiveAddressIndex.toString(), + 'change_address_index': walletAddresses.currentChangeAddressIndex.toString(), + 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), + 'balance': balance[currency]?.toJSON() + }); int feeRate(TransactionPriority priority) { try { @@ -364,34 +361,29 @@ abstract class ElectrumWalletBase extends WalletBase + int feeAmountForPriority( + BitcoinTransactionPriority priority, int inputsCount, int outputsCount) => feeRate(priority) * estimatedTransactionSize(inputsCount, outputsCount); - int feeAmountWithFeeRate(int feeRate, int inputsCount, - int outputsCount) => + int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount) => feeRate * estimatedTransactionSize(inputsCount, outputsCount); @override - int calculateEstimatedFee(TransactionPriority? priority, int? amount, - {int? outputsCount}) { + int calculateEstimatedFee(TransactionPriority? priority, int? amount, {int? outputsCount}) { if (priority is BitcoinTransactionPriority) { - return calculateEstimatedFeeWithFeeRate( - feeRate(priority), - amount, - outputsCount: outputsCount); + return calculateEstimatedFeeWithFeeRate(feeRate(priority), amount, + outputsCount: outputsCount); } return 0; } - int calculateEstimatedFeeWithFeeRate(int feeRate, int? amount, - {int? outputsCount}) { + int calculateEstimatedFeeWithFeeRate(int feeRate, int? amount, {int? outputsCount}) { int inputsCount = 0; if (amount != null) { @@ -420,8 +412,7 @@ abstract class ElectrumWalletBase extends WalletBase makePath() async => - pathForWallet(name: walletInfo.name, type: walletInfo.type); + Future makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); Future updateUnspent() async { final unspent = await Future.wait(walletAddresses .addresses.map((address) => electrumClient .getListUnspentWithAddress(address.address, networkType) .then((unspent) => unspent - .map((unspent) { - try { - return BitcoinUnspent.fromJSON(address, unspent); - } catch(_) { - return null; - } - }).whereNotNull()))); + .map((unspent) { + try { + return BitcoinUnspent.fromJSON(address, unspent); + } catch(_) { + return null; + } + }).whereNotNull()))); unspentCoins = unspent.expand((e) => e).toList(); if (unspentCoinsInfo.isEmpty) { @@ -498,8 +487,8 @@ abstract class ElectrumWalletBase extends WalletBase - element.walletId.contains(id) && element.hash.contains(coin.hash)); + final coinInfoList = unspentCoinsInfo.values + .where((element) => element.walletId.contains(id) && element.hash.contains(coin.hash)); if (coinInfoList.isNotEmpty) { final coinInfo = coinInfoList.first; @@ -518,14 +507,14 @@ abstract class ElectrumWalletBase extends WalletBase _addCoinInfo(BitcoinUnspent coin) async { final newInfo = UnspentCoinsInfo( - walletId: id, - hash: coin.hash, - isFrozen: coin.isFrozen, - isSending: coin.isSending, - noteRaw: coin.note, - address: coin.address.address, - value: coin.value, - vout: coin.vout, + walletId: id, + hash: coin.hash, + isFrozen: coin.isFrozen, + isSending: coin.isSending, + noteRaw: coin.note, + address: coin.bitcoinAddressRecord.address, + value: coin.value, + vout: coin.vout, ); await unspentCoinsInfo.add(newInfo); @@ -534,8 +523,8 @@ abstract class ElectrumWalletBase extends WalletBase _refreshUnspentCoinsInfo() async { try { final List keys = []; - final currentWalletUnspentCoins = unspentCoinsInfo.values - .where((element) => element.walletId.contains(id)); + final currentWalletUnspentCoins = + unspentCoinsInfo.values.where((element) => element.walletId.contains(id)); if (currentWalletUnspentCoins.isNotEmpty) { currentWalletUnspentCoins.forEach((element) { @@ -571,27 +560,19 @@ abstract class ElectrumWalletBase extends WalletBase fetchTransactionInfo( {required String hash, required int height}) async { - try { - final tx = await getTransactionExpanded(hash: hash, height: height); - final addresses = walletAddresses.addresses.map((addr) => addr.address).toSet(); - return ElectrumTransactionInfo.fromElectrumBundle( - tx, - walletInfo.type, - networkType, - addresses: addresses, - height: height); - } catch(_) { - return null; - } + try { + final tx = await getTransactionExpanded(hash: hash, height: height); + final addresses = walletAddresses.addresses.map((addr) => addr.address).toSet(); + return ElectrumTransactionInfo.fromElectrumBundle(tx, walletInfo.type, networkType, + addresses: addresses, height: height); + } catch (_) { + return null; + } } @override @@ -602,10 +583,8 @@ abstract class ElectrumWalletBase extends WalletBase electrumClient - .getHistory(scriptHash) - .then((history) => {scriptHash: history})); + final histories = addressHashes.keys.map((scriptHash) => + electrumClient.getHistory(scriptHash).then((history) => {scriptHash: history})); final historyResults = await Future.wait(histories); historyResults.forEach((history) { history.entries.forEach((historyItem) { @@ -616,19 +595,16 @@ abstract class ElectrumWalletBase extends WalletBase>( - {}, (acc, tx) { + final historiesWithDetails = await Future.wait(normalizedHistories.map((transaction) { + try { + return fetchTransactionInfo( + hash: transaction['tx_hash'] as String, height: transaction['height'] as int); + } catch (_) { + return Future.value(null); + } + })); + return historiesWithDetails + .fold>({}, (acc, tx) { if (tx == null) { return acc; } @@ -680,9 +656,8 @@ abstract class ElectrumWalletBase extends WalletBase _fetchBalances() async { final addresses = walletAddresses.addresses.toList(); final balanceFutures = >>[]; - for (var i = 0; i < addresses.length; i++) { - final addressRecord = addresses[i]; + final addressRecord = addresses[i] ; final sh = scriptHash(addressRecord.address, networkType: networkType); final balanceFuture = electrumClient.getBalance(sh); balanceFutures.add(balanceFuture); @@ -691,8 +666,10 @@ abstract class ElectrumWalletBase extends WalletBase updateBalance() async { @@ -727,9 +704,7 @@ abstract class ElectrumWalletBase extends WalletBase addr.isHidden) - .toList(); + var addresses = walletAddresses.addresses.where((addr) => addr.isHidden).toList(); if (addresses.length < minCountOfHiddenAddresses) { addresses = walletAddresses.addresses.toList(); diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 741c2fe1c..ab99a875c 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -1,9 +1,11 @@ import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:bitbox/bitbox.dart' as bitbox; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/script_hash.dart'; import 'package:cw_core/wallet_addresses.dart'; import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; part 'electrum_wallet_addresses.g.dart'; @@ -38,6 +40,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { static const defaultChangeAddressesCount = 17; static const gap = 20; + static String toCashAddr(String address) => bitbox.Address.toCashAddress(address); + final ObservableList addresses; final ObservableList receiveAddresses; final ObservableList changeAddresses; @@ -50,10 +54,12 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @computed String get address { if (receiveAddresses.isEmpty) { - return generateNewAddress().address; + final address = generateNewAddress().address; + return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(address) : address; } + final receiveAddress = receiveAddresses.first.address; - return receiveAddresses.first.address; + return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(receiveAddress) : receiveAddress; } @override @@ -105,10 +111,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @action Future getChangeAddress() async { updateChangeAddresses(); - + if (changeAddresses.isEmpty) { - final newAddresses = await _createNewAddresses( - gap, + final newAddresses = await _createNewAddresses(gap, hd: sideHd, startIndex: totalCountOfChangeAddresses > 0 ? totalCountOfChangeAddresses - 1 @@ -179,7 +184,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } else { addrs = await _createNewAddresses( isHidden - ? defaultChangeAddressesCount + ? defaultChangeAddressesCount : defaultReceiveAddressesCount, startIndex: 0, hd: hd, diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 843daa771..eb75227b6 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -66,6 +66,15 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" + bitbox: + dependency: "direct main" + description: + path: "." + ref: master + resolved-ref: ea65073efbaf395a5557e8cd7bd72f195cd7eb11 + url: "https://github.com/cake-tech/bitbox-flutter.git" + source: git + version: "1.0.1" bitcoin_flutter: dependency: "direct main" description: diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index dae0af39b..693d5af7a 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -23,6 +23,10 @@ dependencies: git: url: https://github.com/cake-tech/bitcoin_flutter.git ref: cake-update-v3 + bitbox: + git: + url: https://github.com/cake-tech/bitbox-flutter.git + ref: master rxdart: ^0.27.5 unorm_dart: ^0.2.0 cryptography: ^2.0.5 diff --git a/cw_bitcoin_cash/.gitignore b/cw_bitcoin_cash/.gitignore new file mode 100644 index 000000000..96486fd93 --- /dev/null +++ b/cw_bitcoin_cash/.gitignore @@ -0,0 +1,30 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/cw_bitcoin_cash/.metadata b/cw_bitcoin_cash/.metadata new file mode 100644 index 000000000..4161da6ea --- /dev/null +++ b/cw_bitcoin_cash/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: b06b8b2710955028a6b562f5aa6fe62941d6febf + channel: stable + +project_type: package diff --git a/cw_bitcoin_cash/CHANGELOG.md b/cw_bitcoin_cash/CHANGELOG.md new file mode 100644 index 000000000..41cc7d819 --- /dev/null +++ b/cw_bitcoin_cash/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/cw_bitcoin_cash/LICENSE b/cw_bitcoin_cash/LICENSE new file mode 100644 index 000000000..ba75c69f7 --- /dev/null +++ b/cw_bitcoin_cash/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/cw_bitcoin_cash/README.md b/cw_bitcoin_cash/README.md new file mode 100644 index 000000000..02fe8ecab --- /dev/null +++ b/cw_bitcoin_cash/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/cw_bitcoin_cash/analysis_options.yaml b/cw_bitcoin_cash/analysis_options.yaml new file mode 100644 index 000000000..a5744c1cf --- /dev/null +++ b/cw_bitcoin_cash/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/cw_bitcoin_cash/lib/cw_bitcoin_cash.dart b/cw_bitcoin_cash/lib/cw_bitcoin_cash.dart new file mode 100644 index 000000000..732474ac4 --- /dev/null +++ b/cw_bitcoin_cash/lib/cw_bitcoin_cash.dart @@ -0,0 +1,9 @@ +library cw_bitcoin_cash; + +export 'src/bitcoin_cash_base.dart'; + +/// A Calculator. +class Calculator { + /// Returns [value] plus 1. + int addOne(int value) => value + 1; +} diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_address_utils.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_address_utils.dart new file mode 100644 index 000000000..ca47ea9f6 --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_address_utils.dart @@ -0,0 +1,5 @@ +import 'package:bitbox/bitbox.dart' as bitbox; + +class AddressUtils { + static String getCashAddrFormat(String address) => bitbox.Address.toCashAddress(address); +} diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_base.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_base.dart new file mode 100644 index 000000000..4699b1649 --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_base.dart @@ -0,0 +1,7 @@ +export 'bitcoin_cash_wallet.dart'; +export 'bitcoin_cash_wallet_addresses.dart'; +export 'bitcoin_cash_wallet_creation_credentials.dart'; +export 'bitcoin_cash_wallet_service.dart'; +export 'exceptions/exceptions.dart'; +export 'mnemonic.dart'; +export 'bitcoin_cash_address_utils.dart'; diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart new file mode 100644 index 000000000..b4924e2db --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -0,0 +1,297 @@ +import 'package:bitbox/bitbox.dart' as bitbox; +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:cw_bitcoin/bitcoin_address_record.dart'; +import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; +import 'package:cw_bitcoin/bitcoin_transaction_no_inputs_exception.dart'; +import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; +import 'package:cw_bitcoin/bitcoin_transaction_wrong_balance_exception.dart'; +import 'package:cw_bitcoin/bitcoin_unspent.dart'; +import 'package:cw_bitcoin/electrum_balance.dart'; +import 'package:cw_bitcoin/electrum_wallet.dart'; +import 'package:cw_bitcoin/electrum_wallet_snapshot.dart'; +import 'package:cw_bitcoin_cash/src/pending_bitcoin_cash_transaction.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:flutter/foundation.dart'; +import 'package:hive/hive.dart'; +import 'package:mobx/mobx.dart'; + +import 'bitcoin_cash_base.dart'; + +part 'bitcoin_cash_wallet.g.dart'; + +class BitcoinCashWallet = BitcoinCashWalletBase with _$BitcoinCashWallet; + +abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { + BitcoinCashWalletBase( + {required String mnemonic, + required String password, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required Uint8List seedBytes, + List? initialAddresses, + ElectrumBalance? initialBalance, + int initialRegularAddressIndex = 0, + int initialChangeAddressIndex = 0}) + : super( + mnemonic: mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + networkType: bitcoin.bitcoin, + initialAddresses: initialAddresses, + initialBalance: initialBalance, + seedBytes: seedBytes, + currency: CryptoCurrency.bch) { + walletAddresses = BitcoinCashWalletAddresses(walletInfo, + electrumClient: electrumClient, + initialAddresses: initialAddresses, + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + mainHd: hd, + sideHd: bitcoin.HDWallet.fromSeed(seedBytes) + .derivePath("m/44'/145'/0'/1"), + networkType: networkType); + } + + + static Future create( + {required String mnemonic, + required String password, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + List? initialAddresses, + ElectrumBalance? initialBalance, + int initialRegularAddressIndex = 0, + int initialChangeAddressIndex = 0}) async { + return BitcoinCashWallet( + mnemonic: mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: initialAddresses, + initialBalance: initialBalance, + seedBytes: await Mnemonic.toSeed(mnemonic), + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex); + } + + static Future open({ + required String name, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required String password, + }) async { + final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password); + return BitcoinCashWallet( + mnemonic: snp.mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: snp.addresses, + initialBalance: snp.balance, + seedBytes: await Mnemonic.toSeed(snp.mnemonic), + initialRegularAddressIndex: snp.regularAddressIndex, + initialChangeAddressIndex: snp.changeAddressIndex); + } + + @override + Future createTransaction(Object credentials) async { + const minAmount = 546; + final transactionCredentials = credentials as BitcoinTransactionCredentials; + final inputs = []; + final outputs = transactionCredentials.outputs; + final hasMultiDestination = outputs.length > 1; + + var allInputsAmount = 0; + + if (unspentCoins.isEmpty) await updateUnspent(); + + for (final utx in unspentCoins) { + if (utx.isSending) { + allInputsAmount += utx.value; + inputs.add(utx); + } + } + + if (inputs.isEmpty) throw BitcoinTransactionNoInputsException(); + + final allAmountFee = transactionCredentials.feeRate != null + ? feeAmountWithFeeRate(transactionCredentials.feeRate!, inputs.length, outputs.length) + : feeAmountForPriority(transactionCredentials.priority!, inputs.length, outputs.length); + + final allAmount = allInputsAmount - allAmountFee; + + var credentialsAmount = 0; + var amount = 0; + var fee = 0; + + if (hasMultiDestination) { + if (outputs.any((item) => item.sendAll || item.formattedCryptoAmount! <= 0)) { + throw BitcoinTransactionWrongBalanceException(currency); + } + + credentialsAmount = outputs.fold(0, (acc, value) => acc + value.formattedCryptoAmount!); + + if (allAmount - credentialsAmount < minAmount) { + throw BitcoinTransactionWrongBalanceException(currency); + } + + amount = credentialsAmount; + + if (transactionCredentials.feeRate != null) { + fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate!, amount, + outputsCount: outputs.length + 1); + } else { + fee = calculateEstimatedFee(transactionCredentials.priority, amount, + outputsCount: outputs.length + 1); + } + } else { + final output = outputs.first; + credentialsAmount = !output.sendAll ? output.formattedCryptoAmount! : 0; + + if (credentialsAmount > allAmount) { + throw BitcoinTransactionWrongBalanceException(currency); + } + + amount = output.sendAll || allAmount - credentialsAmount < minAmount + ? allAmount + : credentialsAmount; + + if (output.sendAll || amount == allAmount) { + fee = allAmountFee; + } else if (transactionCredentials.feeRate != null) { + fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate!, amount); + } else { + fee = calculateEstimatedFee(transactionCredentials.priority, amount); + } + } + + if (fee == 0) { + throw BitcoinTransactionWrongBalanceException(currency); + } + + final totalAmount = amount + fee; + + if (totalAmount > balance[currency]!.confirmed || totalAmount > allInputsAmount) { + throw BitcoinTransactionWrongBalanceException(currency); + } + final txb = bitbox.Bitbox.transactionBuilder(testnet: false); + + final changeAddress = await walletAddresses.getChangeAddress(); + var leftAmount = totalAmount; + var totalInputAmount = 0; + + inputs.clear(); + + for (final utx in unspentCoins) { + if (utx.isSending) { + leftAmount = leftAmount - utx.value; + totalInputAmount += utx.value; + inputs.add(utx); + + if (leftAmount <= 0) { + break; + } + } + } + + if (inputs.isEmpty) throw BitcoinTransactionNoInputsException(); + + if (amount <= 0 || totalInputAmount < totalAmount) { + throw BitcoinTransactionWrongBalanceException(currency); + } + + inputs.forEach((input) { + txb.addInput(input.hash, input.vout); + }); + + outputs.forEach((item) { + final outputAmount = hasMultiDestination ? item.formattedCryptoAmount : amount; + final outputAddress = item.isParsedAddress ? item.extractedAddress! : item.address; + txb.addOutput(outputAddress, outputAmount!); + }); + + final estimatedSize = bitbox.BitcoinCash.getByteCount(inputs.length, outputs.length + 1); + + var feeAmount = 0; + + if (transactionCredentials.feeRate != null) { + feeAmount = transactionCredentials.feeRate! * estimatedSize; + } else { + feeAmount = feeRate(transactionCredentials.priority!) * estimatedSize; + } + + final changeValue = totalInputAmount - amount - feeAmount; + + if (changeValue > minAmount) { + txb.addOutput(changeAddress, changeValue); + } + + for (var i = 0; i < inputs.length; i++) { + final input = inputs[i]; + final keyPair = generateKeyPair( + hd: input.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, + index: input.bitcoinAddressRecord.index); + txb.sign(i, keyPair, input.value); + } + + // Build the transaction + final tx = txb.build(); + + return PendingBitcoinCashTransaction(tx, type, + electrumClient: electrumClient, amount: amount, fee: fee); + } + + bitbox.ECPair generateKeyPair( + {required bitcoin.HDWallet hd, + required int index}) => + bitbox.ECPair.fromWIF(hd.derive(index).wif!); + + @override + int feeAmountForPriority( + BitcoinTransactionPriority priority, int inputsCount, int outputsCount) => + feeRate(priority) * bitbox.BitcoinCash.getByteCount(inputsCount, outputsCount); + + int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount) => + feeRate * bitbox.BitcoinCash.getByteCount(inputsCount, outputsCount); + + int calculateEstimatedFeeWithFeeRate(int feeRate, int? amount, {int? outputsCount}) { + int inputsCount = 0; + int totalValue = 0; + + for (final input in unspentCoins) { + if (input.isSending) { + inputsCount++; + totalValue += input.value; + } + if (amount != null && totalValue >= amount) { + break; + } + } + + if (amount != null && totalValue < amount) return 0; + + final _outputsCount = outputsCount ?? (amount != null ? 2 : 1); + + return feeAmountWithFeeRate(feeRate, inputsCount, _outputsCount); + } + + @override + int feeRate(TransactionPriority priority) { + if (priority is BitcoinCashTransactionPriority) { + switch (priority) { + case BitcoinCashTransactionPriority.slow: + return 1; + case BitcoinCashTransactionPriority.medium: + return 5; + case BitcoinCashTransactionPriority.fast: + return 10; + } + } + + return 0; + } +} diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart new file mode 100644 index 000000000..1709c4d8f --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart @@ -0,0 +1,34 @@ +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:cw_bitcoin/bitcoin_address_record.dart'; +import 'package:cw_bitcoin/electrum.dart'; +import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; +import 'package:cw_bitcoin/utils.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:mobx/mobx.dart'; + +part 'bitcoin_cash_wallet_addresses.g.dart'; + +class BitcoinCashWalletAddresses = BitcoinCashWalletAddressesBase with _$BitcoinCashWalletAddresses; + +abstract class BitcoinCashWalletAddressesBase extends ElectrumWalletAddresses with Store { + BitcoinCashWalletAddressesBase(WalletInfo walletInfo, + {required bitcoin.HDWallet mainHd, + required bitcoin.HDWallet sideHd, + required bitcoin.NetworkType networkType, + required ElectrumClient electrumClient, + List? initialAddresses, + int initialRegularAddressIndex = 0, + int initialChangeAddressIndex = 0}) + : super(walletInfo, + initialAddresses: initialAddresses, + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + mainHd: mainHd, + sideHd: sideHd, + electrumClient: electrumClient, + networkType: networkType); + + @override + String getAddress({required int index, required bitcoin.HDWallet hd}) => + generateP2PKHAddress(hd: hd, index: index, networkType: networkType); +} diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_creation_credentials.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_creation_credentials.dart new file mode 100644 index 000000000..72caa6c58 --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_creation_credentials.dart @@ -0,0 +1,26 @@ +import 'package:cw_core/wallet_credentials.dart'; +import 'package:cw_core/wallet_info.dart'; + +class BitcoinCashNewWalletCredentials extends WalletCredentials { + BitcoinCashNewWalletCredentials({required String name, WalletInfo? walletInfo}) + : super(name: name, walletInfo: walletInfo); +} + +class BitcoinCashRestoreWalletFromSeedCredentials extends WalletCredentials { + BitcoinCashRestoreWalletFromSeedCredentials( + {required String name, + required String password, + required this.mnemonic, + WalletInfo? walletInfo}) + : super(name: name, password: password, walletInfo: walletInfo); + + final String mnemonic; +} + +class BitcoinCashRestoreWalletFromWIFCredentials extends WalletCredentials { + BitcoinCashRestoreWalletFromWIFCredentials( + {required String name, required String password, required this.wif, WalletInfo? walletInfo}) + : super(name: name, password: password, walletInfo: walletInfo); + + final String wif; +} diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart new file mode 100644 index 000000000..fa572b38b --- /dev/null +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart @@ -0,0 +1,107 @@ +import 'dart:io'; + +import 'package:bip39/bip39.dart'; +import 'package:cw_bitcoin_cash/cw_bitcoin_cash.dart'; +import 'package:cw_core/balance.dart'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/transaction_history.dart'; +import 'package:cw_core/transaction_info.dart'; +import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_service.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:collection/collection.dart'; +import 'package:hive/hive.dart'; + +class BitcoinCashWalletService extends WalletService { + BitcoinCashWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); + + final Box walletInfoSource; + final Box unspentCoinsInfoSource; + + @override + WalletType getType() => WalletType.bitcoinCash; + + @override + Future isWalletExit(String name) async => + File(await pathForWallet(name: name, type: getType())).existsSync(); + + @override + Future create( + credentials) async { + final wallet = await BitcoinCashWalletBase.create( + mnemonic: await Mnemonic.generate(), + password: credentials.password!, + walletInfo: credentials.walletInfo!, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.save(); + await wallet.init(); + return wallet; + } + + @override + Future openWallet(String name, String password) async { + final walletInfo = walletInfoSource.values.firstWhereOrNull( + (info) => info.id == WalletBase.idFor(name, getType()))!; + final wallet = await BitcoinCashWalletBase.open( + password: password, name: name, walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.init(); + return wallet; + } + + @override + Future remove(String wallet) async { + File(await pathForWalletDir(name: wallet, type: getType())) + .delete(recursive: true); + final walletInfo = walletInfoSource.values.firstWhereOrNull( + (info) => info.id == WalletBase.idFor(wallet, getType()))!; + await walletInfoSource.delete(walletInfo.key); + } + + @override + Future rename(String currentName, String password, String newName) async { + final currentWalletInfo = walletInfoSource.values.firstWhereOrNull( + (info) => info.id == WalletBase.idFor(currentName, getType()))!; + final currentWallet = await BitcoinCashWalletBase.open( + password: password, + name: currentName, + walletInfo: currentWalletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); + + await currentWallet.renameWalletFiles(newName); + + final newWalletInfo = currentWalletInfo; + newWalletInfo.id = WalletBase.idFor(newName, getType()); + newWalletInfo.name = newName; + + await walletInfoSource.put(currentWalletInfo.key, newWalletInfo); + } + + @override + Future + restoreFromKeys(credentials) { + // TODO: implement restoreFromKeys + throw UnimplementedError('restoreFromKeys() is not implemented'); + } + + @override + Future restoreFromSeed( + BitcoinCashRestoreWalletFromSeedCredentials credentials) async { + if (!validateMnemonic(credentials.mnemonic)) { + throw BitcoinCashMnemonicIsIncorrectException(); + } + + final wallet = await BitcoinCashWalletBase.create( + password: credentials.password!, + mnemonic: credentials.mnemonic, + walletInfo: credentials.walletInfo!, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.save(); + await wallet.init(); + return wallet; + } +} diff --git a/cw_bitcoin_cash/lib/src/exceptions/bitcoin_cash_mnemonic_is_incorrect_exception.dart b/cw_bitcoin_cash/lib/src/exceptions/bitcoin_cash_mnemonic_is_incorrect_exception.dart new file mode 100644 index 000000000..7cce59085 --- /dev/null +++ b/cw_bitcoin_cash/lib/src/exceptions/bitcoin_cash_mnemonic_is_incorrect_exception.dart @@ -0,0 +1,5 @@ +class BitcoinCashMnemonicIsIncorrectException implements Exception { + @override + String toString() => + 'Bitcoin Cash mnemonic has incorrect format. Mnemonic should contain 12 or 24 words separated by space.'; +} diff --git a/cw_bitcoin_cash/lib/src/exceptions/exceptions.dart b/cw_bitcoin_cash/lib/src/exceptions/exceptions.dart new file mode 100644 index 000000000..746e3248a --- /dev/null +++ b/cw_bitcoin_cash/lib/src/exceptions/exceptions.dart @@ -0,0 +1 @@ +export 'bitcoin_cash_mnemonic_is_incorrect_exception.dart'; \ No newline at end of file diff --git a/cw_bitcoin_cash/lib/src/mnemonic.dart b/cw_bitcoin_cash/lib/src/mnemonic.dart new file mode 100644 index 000000000..b1f1ee984 --- /dev/null +++ b/cw_bitcoin_cash/lib/src/mnemonic.dart @@ -0,0 +1,11 @@ +import 'dart:typed_data'; + +import 'package:bip39/bip39.dart' as bip39; + +class Mnemonic { + /// Generate bip39 mnemonic + static String generate({int strength = 128}) => bip39.generateMnemonic(strength: strength); + + /// Create root seed from mnemonic + static Uint8List toSeed(String mnemonic) => bip39.mnemonicToSeed(mnemonic); +} diff --git a/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart b/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart new file mode 100644 index 000000000..d5ac36ce2 --- /dev/null +++ b/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart @@ -0,0 +1,62 @@ +import 'package:cw_bitcoin/bitcoin_commit_transaction_exception.dart'; +import 'package:bitbox/bitbox.dart' as bitbox; +import 'package:cw_core/pending_transaction.dart'; +import 'package:cw_bitcoin/electrum.dart'; +import 'package:cw_bitcoin/bitcoin_amount_format.dart'; +import 'package:cw_bitcoin/electrum_transaction_info.dart'; +import 'package:cw_core/transaction_direction.dart'; +import 'package:cw_core/wallet_type.dart'; + +class PendingBitcoinCashTransaction with PendingTransaction { + PendingBitcoinCashTransaction(this._tx, this.type, + {required this.electrumClient, + required this.amount, + required this.fee}) + : _listeners = []; + + final WalletType type; + final bitbox.Transaction _tx; + final ElectrumClient electrumClient; + final int amount; + final int fee; + + @override + String get id => _tx.getId(); + + @override + String get hex => _tx.toHex(); + + @override + String get amountFormatted => bitcoinAmountToString(amount: amount); + + @override + String get feeFormatted => bitcoinAmountToString(amount: fee); + + final List _listeners; + + @override + Future commit() async { + final result = + await electrumClient.broadcastTransaction(transactionRaw: _tx.toHex()); + + if (result.isEmpty) { + throw BitcoinCommitTransactionException(); + } + + _listeners?.forEach((listener) => listener(transactionInfo())); + } + + void addListener( + void Function(ElectrumTransactionInfo transaction) listener) => + _listeners.add(listener); + + ElectrumTransactionInfo transactionInfo() => ElectrumTransactionInfo(type, + id: id, + height: 0, + amount: amount, + direction: TransactionDirection.outgoing, + date: DateTime.now(), + isPending: true, + confirmations: 0, + fee: fee); +} diff --git a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux new file mode 120000 index 000000000..7d9244fbe --- /dev/null +++ b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux @@ -0,0 +1 @@ +C:/Users/borod/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_linux-2.2.0/ \ No newline at end of file diff --git a/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.cc b/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 000000000..e71a16d23 --- /dev/null +++ b/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void fl_register_plugins(FlPluginRegistry* registry) { +} diff --git a/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.h b/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 000000000..e0f0a47bc --- /dev/null +++ b/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake b/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake new file mode 100644 index 000000000..2e1de87a7 --- /dev/null +++ b/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/cw_bitcoin_cash/macos/Flutter/GeneratedPluginRegistrant.swift b/cw_bitcoin_cash/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 000000000..e777c67df --- /dev/null +++ b/cw_bitcoin_cash/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,12 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import path_provider_foundation + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) +} diff --git a/cw_bitcoin_cash/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/cw_bitcoin_cash/macos/Flutter/ephemeral/Flutter-Generated.xcconfig new file mode 100644 index 000000000..2f46994d3 --- /dev/null +++ b/cw_bitcoin_cash/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -0,0 +1,11 @@ +// This is a generated file; do not edit or check into version control. +FLUTTER_ROOT=C:\Users\borod\flutter +FLUTTER_APPLICATION_PATH=C:\cake_wallet\cw_bitcoin_cash +COCOAPODS_PARALLEL_CODE_SIGN=true +FLUTTER_BUILD_DIR=build +FLUTTER_BUILD_NAME=0.0.1 +FLUTTER_BUILD_NUMBER=0.0.1 +DART_OBFUSCATION=false +TRACK_WIDGET_CREATION=true +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=.dart_tool/package_config.json diff --git a/cw_bitcoin_cash/macos/Flutter/ephemeral/flutter_export_environment.sh b/cw_bitcoin_cash/macos/Flutter/ephemeral/flutter_export_environment.sh new file mode 100644 index 000000000..2a3bcca5a --- /dev/null +++ b/cw_bitcoin_cash/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=C:\Users\borod\flutter" +export "FLUTTER_APPLICATION_PATH=C:\cake_wallet\cw_bitcoin_cash" +export "COCOAPODS_PARALLEL_CODE_SIGN=true" +export "FLUTTER_BUILD_DIR=build" +export "FLUTTER_BUILD_NAME=0.0.1" +export "FLUTTER_BUILD_NUMBER=0.0.1" +export "DART_OBFUSCATION=false" +export "TRACK_WIDGET_CREATION=true" +export "TREE_SHAKE_ICONS=false" +export "PACKAGE_CONFIG=.dart_tool/package_config.json" diff --git a/cw_bitcoin_cash/pubspec.yaml b/cw_bitcoin_cash/pubspec.yaml new file mode 100644 index 000000000..30ed49e80 --- /dev/null +++ b/cw_bitcoin_cash/pubspec.yaml @@ -0,0 +1,76 @@ +name: cw_bitcoin_cash +description: A new Flutter package project. +version: 0.0.1 +publish_to: none +author: Cake Wallet +homepage: https://cakewallet.com + +environment: + sdk: '>=2.19.0 <3.0.0' + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + bip39: ^1.0.6 + bip32: ^2.0.0 + path_provider: ^2.0.11 + mobx: ^2.0.7+4 + flutter_mobx: ^2.0.6+1 + cw_core: + path: ../cw_core + cw_bitcoin: + path: ../cw_bitcoin + bitcoin_flutter: + git: + url: https://github.com/cake-tech/bitcoin_flutter.git + ref: cake-update-v3 + bitbox: + git: + url: https://github.com/cake-tech/bitbox-flutter.git + ref: master + + + +dev_dependencies: + flutter_test: + sdk: flutter + build_runner: ^2.1.11 + mobx_codegen: ^2.0.7 + hive_generator: ^1.1.3 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + +# To add assets to your package, add an assets section, like this: +# assets: +# - images/a_dot_burr.jpeg +# - images/a_dot_ham.jpeg +# +# For details regarding assets in packages, see +# https://flutter.dev/assets-and-images/#from-packages +# +# An image asset can refer to one or more resolution-specific "variants", see +# https://flutter.dev/assets-and-images/#resolution-aware + +# To add custom fonts to your package, add a fonts section here, +# in this "flutter" section. Each entry in this list should have a +# "family" key with the font family name, and a "fonts" key with a +# list giving the asset and other descriptors for the font. For +# example: +# fonts: +# - family: Schyler +# fonts: +# - asset: fonts/Schyler-Regular.ttf +# - asset: fonts/Schyler-Italic.ttf +# style: italic +# - family: Trajan Pro +# fonts: +# - asset: fonts/TrajanPro.ttf +# - asset: fonts/TrajanPro_Bold.ttf +# weight: 700 +# + diff --git a/cw_bitcoin_cash/test/cw_bitcoin_cash_test.dart b/cw_bitcoin_cash/test/cw_bitcoin_cash_test.dart new file mode 100644 index 000000000..f06646a8f --- /dev/null +++ b/cw_bitcoin_cash/test/cw_bitcoin_cash_test.dart @@ -0,0 +1,12 @@ +import 'package:flutter_test/flutter_test.dart'; + +import 'package:cw_bitcoin_cash/cw_bitcoin_cash.dart'; + +void main() { + test('adds one to input values', () { + final calculator = Calculator(); + expect(calculator.addOne(2), 3); + expect(calculator.addOne(-7), -6); + expect(calculator.addOne(0), 1); + }); +} diff --git a/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.cc b/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 000000000..8b6d4680a --- /dev/null +++ b/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void RegisterPlugins(flutter::PluginRegistry* registry) { +} diff --git a/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.h b/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 000000000..dc139d85a --- /dev/null +++ b/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/cw_bitcoin_cash/windows/flutter/generated_plugins.cmake b/cw_bitcoin_cash/windows/flutter/generated_plugins.cmake new file mode 100644 index 000000000..b93c4c30c --- /dev/null +++ b/cw_bitcoin_cash/windows/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/cw_core/lib/amount_converter.dart b/cw_core/lib/amount_converter.dart index a11907ef2..6fd43dd82 100644 --- a/cw_core/lib/amount_converter.dart +++ b/cw_core/lib/amount_converter.dart @@ -80,6 +80,7 @@ class AmountConverter { case CryptoCurrency.xmr: return _moneroAmountToString(amount); case CryptoCurrency.btc: + case CryptoCurrency.bch: return _bitcoinAmountToString(amount); case CryptoCurrency.xhv: case CryptoCurrency.xag: diff --git a/cw_core/lib/currency_for_wallet_type.dart b/cw_core/lib/currency_for_wallet_type.dart index 2db858b30..4c330b073 100644 --- a/cw_core/lib/currency_for_wallet_type.dart +++ b/cw_core/lib/currency_for_wallet_type.dart @@ -13,6 +13,8 @@ CryptoCurrency currencyForWalletType(WalletType type) { return CryptoCurrency.xhv; case WalletType.ethereum: return CryptoCurrency.eth; + case WalletType.bitcoinCash: + return CryptoCurrency.bch; case WalletType.nano: return CryptoCurrency.nano; case WalletType.banano: diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index a07030d64..dc3620ec2 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -78,6 +78,8 @@ class Node extends HiveObject with Keyable { return Uri.http(uriRaw, ''); case WalletType.ethereum: return Uri.https(uriRaw, ''); + case WalletType.bitcoinCash: + return createUriFromElectrumAddress(uriRaw); case WalletType.nano: case WalletType.banano: if (isSSL) { @@ -138,6 +140,8 @@ class Node extends HiveObject with Keyable { return requestMoneroNode(); case WalletType.ethereum: return requestElectrumServer(); + case WalletType.bitcoinCash: + return requestElectrumServer(); case WalletType.nano: case WalletType.banano: return requestNanoNode(); diff --git a/lib/entities/unspent_transaction_output.dart b/cw_core/lib/unspent_transaction_output.dart similarity index 100% rename from lib/entities/unspent_transaction_output.dart rename to cw_core/lib/unspent_transaction_output.dart diff --git a/cw_core/lib/wallet_type.dart b/cw_core/lib/wallet_type.dart index 0125facaf..debf92e11 100644 --- a/cw_core/lib/wallet_type.dart +++ b/cw_core/lib/wallet_type.dart @@ -10,6 +10,7 @@ const walletTypes = [ WalletType.litecoin, WalletType.haven, WalletType.ethereum, + WalletType.bitcoinCash, WalletType.nano, WalletType.banano, ]; @@ -39,6 +40,10 @@ enum WalletType { @HiveField(7) banano, + + @HiveField(8) + bitcoinCash, + } int serializeToInt(WalletType type) { @@ -57,6 +62,8 @@ int serializeToInt(WalletType type) { return 5; case WalletType.banano: return 6; + case WalletType.bitcoinCash: + return 7; default: return -1; } @@ -78,6 +85,8 @@ WalletType deserializeFromInt(int raw) { return WalletType.nano; case 6: return WalletType.banano; + case 7: + return WalletType.bitcoinCash; default: throw Exception('Unexpected token: $raw for WalletType deserializeFromInt'); } @@ -95,6 +104,8 @@ String walletTypeToString(WalletType type) { return 'Haven'; case WalletType.ethereum: return 'Ethereum'; + case WalletType.bitcoinCash: + return 'Bitcoin Cash'; case WalletType.nano: return 'Nano'; case WalletType.banano: @@ -116,6 +127,8 @@ String walletTypeToDisplayName(WalletType type) { return 'Haven (XHV)'; case WalletType.ethereum: return 'Ethereum (ETH)'; + case WalletType.bitcoinCash: + return 'Bitcoin Cash (BCH)'; case WalletType.nano: return 'Nano (XNO)'; case WalletType.banano: @@ -137,6 +150,8 @@ CryptoCurrency walletTypeToCryptoCurrency(WalletType type) { return CryptoCurrency.xhv; case WalletType.ethereum: return CryptoCurrency.eth; + case WalletType.bitcoinCash: + return CryptoCurrency.bch; case WalletType.nano: return CryptoCurrency.nano; case WalletType.banano: diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 353458937..dd713fd15 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -44,6 +44,7 @@ class CWBitcoin extends Bitcoin { List getTransactionPriorities() => BitcoinTransactionPriority.all; + @override List getLitecoinTransactionPriorities() => LitecoinTransactionPriority.all; @@ -121,16 +122,9 @@ class CWBitcoin extends Bitcoin { => (priority as BitcoinTransactionPriority).labelWithRate(rate); @override - List getUnspents(Object wallet) { + List getUnspents(Object wallet) { final bitcoinWallet = wallet as ElectrumWallet; - return bitcoinWallet.unspentCoins - .map((BitcoinUnspent bitcoinUnspent) => Unspent( - bitcoinUnspent.address.address, - bitcoinUnspent.hash, - bitcoinUnspent.value, - bitcoinUnspent.vout, - null)) - .toList(); + return bitcoinWallet.unspentCoins; } void updateUnspents(Object wallet) async { diff --git a/lib/bitcoin_cash/cw_bitcoin_cash.dart b/lib/bitcoin_cash/cw_bitcoin_cash.dart new file mode 100644 index 000000000..7dbb8614f --- /dev/null +++ b/lib/bitcoin_cash/cw_bitcoin_cash.dart @@ -0,0 +1,45 @@ +part of 'bitcoin_cash.dart'; + +class CWBitcoinCash extends BitcoinCash { + @override + String getMnemonic(int? strength) => Mnemonic.generate(); + + @override + Uint8List getSeedFromMnemonic(String seed) => Mnemonic.toSeed(seed); + + @override + String getCashAddrFormat(String address) => AddressUtils.getCashAddrFormat(address); + + @override + WalletService createBitcoinCashWalletService( + Box walletInfoSource, Box unspentCoinSource) { + return BitcoinCashWalletService(walletInfoSource, unspentCoinSource); + } + + @override + WalletCredentials createBitcoinCashNewWalletCredentials({ + required String name, + WalletInfo? walletInfo, + }) => + BitcoinCashNewWalletCredentials(name: name, walletInfo: walletInfo); + + @override + WalletCredentials createBitcoinCashRestoreWalletFromSeedCredentials( + {required String name, required String mnemonic, required String password}) => + BitcoinCashRestoreWalletFromSeedCredentials( + name: name, mnemonic: mnemonic, password: password); + + @override + TransactionPriority deserializeBitcoinCashTransactionPriority(int raw) => + BitcoinCashTransactionPriority.deserialize(raw: raw); + + @override + TransactionPriority getDefaultTransactionPriority() => BitcoinCashTransactionPriority.medium; + + @override + List getTransactionPriorities() => BitcoinCashTransactionPriority.all; + + @override + TransactionPriority getBitcoinCashTransactionPrioritySlow() => + BitcoinCashTransactionPriority.slow; +} diff --git a/lib/buy/onramper/onramper_buy_provider.dart b/lib/buy/onramper/onramper_buy_provider.dart index 91309a2ca..872fcebf5 100644 --- a/lib/buy/onramper/onramper_buy_provider.dart +++ b/lib/buy/onramper/onramper_buy_provider.dart @@ -27,6 +27,8 @@ class OnRamperBuyProvider { return "LTC_LITECOIN"; case CryptoCurrency.xmr: return "XMR_MONERO"; + case CryptoCurrency.bch: + return "BCH_BITCOINCASH"; case CryptoCurrency.nano: return "XNO_NANO"; default: diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index d039a40a7..fcb881943 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -88,7 +88,9 @@ class AddressValidator extends TextValidator { case CryptoCurrency.dai: case CryptoCurrency.dash: case CryptoCurrency.eos: + return '[0-9a-zA-Z]'; case CryptoCurrency.bch: + return '^(?!bitcoincash:)[0-9a-zA-Z]*\$|^(?!bitcoincash:)q[0-9a-zA-Z]{41}\$|^(?!bitcoincash:)q[0-9a-zA-Z]{42}\$|^bitcoincash:q[0-9a-zA-Z]{41}\$|^bitcoincash:q[0-9a-zA-Z]{42}\$'; case CryptoCurrency.bnb: return '[0-9a-zA-Z]'; case CryptoCurrency.ltc: @@ -172,7 +174,9 @@ class AddressValidator extends TextValidator { case CryptoCurrency.steth: case CryptoCurrency.shib: case CryptoCurrency.avaxc: + return [42]; case CryptoCurrency.bch: + return [42, 43, 44, 54, 55]; case CryptoCurrency.bnb: return [42]; case CryptoCurrency.ltc: @@ -271,6 +275,11 @@ class AddressValidator extends TextValidator { return 'nano_[0-9a-zA-Z]{60}'; case CryptoCurrency.banano: return 'ban_[0-9a-zA-Z]{60}'; + case CryptoCurrency.bch: + return 'bitcoincash:q[0-9a-zA-Z]{41}([^0-9a-zA-Z]|\$)' + '|bitcoincash:q[0-9a-zA-Z]{42}([^0-9a-zA-Z]|\$)' + '|([^0-9a-zA-Z]|^)q[0-9a-zA-Z]{41}([^0-9a-zA-Z]|\$)' + '|([^0-9a-zA-Z]|^)q[0-9a-zA-Z]{42}([^0-9a-zA-Z]|\$)'; default: return null; } diff --git a/lib/core/seed_validator.dart b/lib/core/seed_validator.dart index 1c6e7cd20..95ccf89ac 100644 --- a/lib/core/seed_validator.dart +++ b/lib/core/seed_validator.dart @@ -29,6 +29,8 @@ class SeedValidator extends Validator { return haven!.getMoneroWordList(language); case WalletType.ethereum: return ethereum!.getEthereumWordList(language); + case WalletType.bitcoinCash: + return getBitcoinWordList(language); case WalletType.nano: case WalletType.banano: return nano!.getNanoWordList(language); diff --git a/lib/di.dart b/lib/di.dart index b871e6a6b..1576c378b 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -2,6 +2,7 @@ import 'package:cake_wallet/anonpay/anonpay_api.dart'; import 'package:cake_wallet/anonpay/anonpay_info_base.dart'; import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart'; import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; +import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/buy/payfura/payfura_buy_provider.dart'; import 'package:cake_wallet/core/wallet_connect/wallet_connect_key_service.dart'; import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart'; @@ -820,6 +821,8 @@ Future setup({ return bitcoin!.createLitecoinWalletService(_walletInfoSource, _unspentCoinsInfoSource); case WalletType.ethereum: return ethereum!.createEthereumWalletService(_walletInfoSource); + case WalletType.bitcoinCash: + return bitcoinCash!.createBitcoinCashWalletService(_walletInfoSource, _unspentCoinsInfoSource!); case WalletType.nano: return nano!.createNanoWalletService(_walletInfoSource); default: diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 690a5e9eb..94283302d 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -26,6 +26,7 @@ const cakeWalletBitcoinElectrumUri = 'electrum.cakewallet.com:50002'; const cakeWalletLitecoinElectrumUri = 'ltc-electrum.cakewallet.com:50002'; const havenDefaultNodeUri = 'nodes.havenprotocol.org:443'; const ethereumDefaultNodeUri = 'ethereum.publicnode.com'; +const cakeWalletBitcoinCashDefaultNodeUri = 'bitcoincash.stackwallet.com:50002'; const nanoDefaultNodeUri = 'rpc.nano.to'; const nanoDefaultPowNodeUri = 'rpc.nano.to'; @@ -81,7 +82,10 @@ Future defaultSettingsMigration( sharedPreferences: sharedPreferences, nodes: nodes); await changeLitecoinCurrentElectrumServerToDefault( sharedPreferences: sharedPreferences, nodes: nodes); - await changeHavenCurrentNodeToDefault(sharedPreferences: sharedPreferences, nodes: nodes); + await changeHavenCurrentNodeToDefault( + sharedPreferences: sharedPreferences, nodes: nodes); + await changeBitcoinCashCurrentNodeToDefault( + sharedPreferences: sharedPreferences, nodes: nodes); break; case 2: @@ -166,6 +170,11 @@ Future defaultSettingsMigration( await changeNanoCurrentPowNodeToDefault( sharedPreferences: sharedPreferences, nodes: powNodes); break; + case 23: + await addBitcoinCashElectrumServerList(nodes: nodes); + await changeBitcoinCurrentElectrumServerToDefault( + sharedPreferences: sharedPreferences, nodes: nodes); + break; default: break; @@ -323,6 +332,12 @@ Node? getNanoDefaultPowNode({required Box nodes}) { nodes.values.firstWhereOrNull((node) => (node.type == WalletType.nano)); } +Node? getBitcoinCashDefaultElectrumServer({required Box nodes}) { + return nodes.values.firstWhereOrNull( + (Node node) => node.uriRaw == cakeWalletBitcoinCashDefaultNodeUri) + ?? nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoinCash); +} + Node getMoneroDefaultNode({required Box nodes}) { final timeZone = DateTime.now().timeZoneOffset.inHours; var nodeUri = ''; @@ -358,6 +373,15 @@ Future changeLitecoinCurrentElectrumServerToDefault( await sharedPreferences.setInt(PreferencesKey.currentLitecoinElectrumSererIdKey, serverId); } +Future changeBitcoinCashCurrentNodeToDefault( + {required SharedPreferences sharedPreferences, + required Box nodes}) async { + final server = getBitcoinCashDefaultElectrumServer(nodes: nodes); + final serverId = server?.key as int ?? 0; + + await sharedPreferences.setInt(PreferencesKey.currentBitcoinCashNodeIdKey, serverId); +} + Future changeHavenCurrentNodeToDefault( {required SharedPreferences sharedPreferences, required Box nodes}) async { final node = getHavenDefaultNode(nodes: nodes); @@ -411,6 +435,15 @@ Future addLitecoinElectrumServerList({required Box nodes}) async { } } +Future addBitcoinCashElectrumServerList({required Box nodes}) async { + final serverList = await loadBitcoinCashElectrumServerList(); + for (var node in serverList) { + if (nodes.values.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) { + await nodes.add(node); + } + } +} + Future addHavenNodeList({required Box nodes}) async { final nodeList = await loadDefaultHavenNodes(); for (var node in nodeList) { @@ -497,27 +530,34 @@ Future checkCurrentNodes( final currentMoneroNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey); final currentBitcoinElectrumSeverId = sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); - final currentLitecoinElectrumSeverId = - sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); - final currentHavenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey); - final currentEthereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey); - final currentNanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); - final currentNanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey); - final currentMoneroNode = - nodeSource.values.firstWhereOrNull((node) => node.key == currentMoneroNodeId); - final currentBitcoinElectrumServer = - nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinElectrumSeverId); - final currentLitecoinElectrumServer = - nodeSource.values.firstWhereOrNull((node) => node.key == currentLitecoinElectrumSeverId); - final currentHavenNodeServer = - nodeSource.values.firstWhereOrNull((node) => node.key == currentHavenNodeId); - final currentEthereumNodeServer = - nodeSource.values.firstWhereOrNull((node) => node.key == currentEthereumNodeId); + final currentLitecoinElectrumSeverId = sharedPreferences + .getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); + final currentHavenNodeId = sharedPreferences + .getInt(PreferencesKey.currentHavenNodeIdKey); + final currentEthereumNodeId = sharedPreferences + .getInt(PreferencesKey.currentEthereumNodeIdKey); + final currentNanoNodeId = sharedPreferences + .getInt(PreferencesKey.currentNanoNodeIdKey); + final currentNanoPowNodeId = sharedPreferences + .getInt(PreferencesKey.currentNanoPowNodeIdKey); + final currentBitcoinCashNodeId = sharedPreferences + .getInt(PreferencesKey.currentBitcoinCashNodeIdKey); + final currentMoneroNode = nodeSource.values.firstWhereOrNull( + (node) => node.key == currentMoneroNodeId); + final currentBitcoinElectrumServer = nodeSource.values.firstWhereOrNull( + (node) => node.key == currentBitcoinElectrumSeverId); + final currentLitecoinElectrumServer = nodeSource.values.firstWhereOrNull( + (node) => node.key == currentLitecoinElectrumSeverId); + final currentHavenNodeServer = nodeSource.values.firstWhereOrNull( + (node) => node.key == currentHavenNodeId); + final currentEthereumNodeServer = nodeSource.values.firstWhereOrNull( + (node) => node.key == currentEthereumNodeId); final currentNanoNodeServer = - nodeSource.values.firstWhereOrNull((node) => node.key == currentNanoNodeId); + nodeSource.values.firstWhereOrNull((node) => node.key == currentNanoNodeId); final currentNanoPowNodeServer = - powNodeSource.values.firstWhereOrNull((node) => node.key == currentNanoPowNodeId); - + powNodeSource.values.firstWhereOrNull((node) => node.key == currentNanoPowNodeId); + final currentBitcoinCashNodeServer = nodeSource.values.firstWhereOrNull( + (node) => node.key == currentBitcoinCashNodeId); if (currentMoneroNode == null) { final newCakeWalletNode = Node(uri: newCakeWalletMoneroUri, type: WalletType.monero); await nodeSource.add(newCakeWalletNode); @@ -565,6 +605,13 @@ Future checkCurrentNodes( } await sharedPreferences.setInt(PreferencesKey.currentNanoPowNodeIdKey, node.key as int); } + + if (currentBitcoinCashNodeServer == null) { + final node = Node(uri: cakeWalletBitcoinCashDefaultNodeUri, type: WalletType.bitcoinCash); + await nodeSource.add(node); + await sharedPreferences.setInt( + PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int); + } } Future resetBitcoinElectrumServer( diff --git a/lib/entities/main_actions.dart b/lib/entities/main_actions.dart index 48beab32b..d2c67ef95 100644 --- a/lib/entities/main_actions.dart +++ b/lib/entities/main_actions.dart @@ -52,6 +52,7 @@ class MainActions { case WalletType.bitcoin: case WalletType.litecoin: case WalletType.ethereum: + case WalletType.bitcoinCash: case WalletType.nano: case WalletType.banano: switch (defaultBuyProvider) { @@ -123,6 +124,7 @@ class MainActions { case WalletType.bitcoin: case WalletType.litecoin: case WalletType.ethereum: + case WalletType.bitcoinCash: if (viewModel.isEnabledSellAction) { final moonPaySellProvider = MoonPaySellProvider(); final uri = await moonPaySellProvider.requestUrl( diff --git a/lib/entities/node_list.dart b/lib/entities/node_list.dart index 0641c0846..53facf18c 100644 --- a/lib/entities/node_list.dart +++ b/lib/entities/node_list.dart @@ -84,6 +84,23 @@ Future> loadDefaultEthereumNodes() async { return nodes; } +Future> loadBitcoinCashElectrumServerList() async { + final serverListRaw = + await rootBundle.loadString('assets/bitcoin_cash_electrum_server_list.yml'); + final loadedServerList = loadYaml(serverListRaw) as YamlList; + final serverList = []; + + for (final raw in loadedServerList) { + if (raw is Map) { + final node = Node.fromMap(Map.from(raw)); + node.type = WalletType.bitcoinCash; + serverList.add(node); + } + } + + return serverList; +} + Future> loadDefaultNanoNodes() async { final nodesRaw = await rootBundle.loadString('assets/nano_node_list.yml'); final loadedNodes = loadYaml(nodesRaw) as YamlList; @@ -116,10 +133,11 @@ Future> loadDefaultNanoPowNodes() async { return nodes; } -Future resetToDefault(Box nodeSource) async { +Future resetToDefault(Box nodeSource) async { final moneroNodes = await loadDefaultNodes(); final bitcoinElectrumServerList = await loadBitcoinElectrumServerList(); final litecoinElectrumServerList = await loadLitecoinElectrumServerList(); + final bitcoinCashElectrumServerList = await loadBitcoinCashElectrumServerList(); final havenNodes = await loadDefaultHavenNodes(); final ethereumNodes = await loadDefaultEthereumNodes(); final nanoNodes = await loadDefaultNanoNodes(); @@ -129,13 +147,14 @@ Future resetToDefault(Box nodeSource) async { litecoinElectrumServerList + havenNodes + ethereumNodes + + bitcoinCashElectrumServerList + nanoNodes; await nodeSource.clear(); await nodeSource.addAll(nodes); } -Future resetPowToDefault(Box powNodeSource) async { +Future resetPowToDefault(Box powNodeSource) async { final nanoPowNodes = await loadDefaultNanoPowNodes(); final nodes = nanoPowNodes; await powNodeSource.clear(); diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index ce2db7cdf..cbd12d777 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -11,6 +11,7 @@ class PreferencesKey { static const currentBananoNodeIdKey = 'current_node_id_banano'; static const currentBananoPowNodeIdKey = 'current_node_id_banano_pow'; static const currentFiatCurrencyKey = 'current_fiat_currency'; + static const currentBitcoinCashNodeIdKey = 'current_node_id_bch'; static const currentTransactionPriorityKeyLegacy = 'current_fee_priority'; static const currentBalanceDisplayModeKey = 'current_balance_display_mode'; static const shouldSaveRecipientAddressKey = 'save_recipient_address'; @@ -36,6 +37,7 @@ class PreferencesKey { static const havenTransactionPriority = 'current_fee_priority_haven'; static const litecoinTransactionPriority = 'current_fee_priority_litecoin'; static const ethereumTransactionPriority = 'current_fee_priority_ethereum'; + static const bitcoinCashTransactionPriority = 'current_fee_priority_bitcoin_cash'; static const shouldShowReceiveWarning = 'should_show_receive_warning'; static const shouldShowYatPopup = 'should_show_yat_popup'; static const moneroWalletPasswordUpdateV1Base = 'monero_wallet_update_v1'; diff --git a/lib/entities/priority_for_wallet_type.dart b/lib/entities/priority_for_wallet_type.dart index 378cf0ea2..bf6f8157d 100644 --- a/lib/entities/priority_for_wallet_type.dart +++ b/lib/entities/priority_for_wallet_type.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/haven/haven.dart'; import 'package:cake_wallet/monero/monero.dart'; @@ -17,6 +18,8 @@ List priorityForWalletType(WalletType type) { return haven!.getTransactionPriorities(); case WalletType.ethereum: return ethereum!.getTransactionPriorities(); + case WalletType.bitcoinCash: + return bitcoinCash!.getTransactionPriorities(); // no such thing for nano/banano: case WalletType.nano: case WalletType.banano: diff --git a/lib/ethereum/cw_ethereum.dart b/lib/ethereum/cw_ethereum.dart index 602db2d49..abafc2f26 100644 --- a/lib/ethereum/cw_ethereum.dart +++ b/lib/ethereum/cw_ethereum.dart @@ -50,6 +50,9 @@ class CWEthereum extends Ethereum { @override TransactionPriority getDefaultTransactionPriority() => EthereumTransactionPriority.medium; + @override + TransactionPriority getEthereumTransactionPrioritySlow() => EthereumTransactionPriority.slow; + @override List getTransactionPriorities() => EthereumTransactionPriority.all; diff --git a/lib/main.dart b/lib/main.dart index c50c16f61..2d76196c3 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -159,7 +159,7 @@ Future initializeAppConfigs() async { transactionDescriptions: transactionDescriptions, secureStorage: secureStorage, anonpayInvoiceInfo: anonpayInvoiceInfo, - initialMigrationVersion: 22); + initialMigrationVersion: 23); } Future initialSetup( diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart index b22acdc8b..1aa7f6c4a 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart @@ -33,6 +33,7 @@ class _DesktopWalletSelectionDropDownState extends State { this.havenIcon = Image.asset('assets/images/haven_menu.png'), this.ethereumIcon = Image.asset('assets/images/eth_icon.png'), this.nanoIcon = Image.asset('assets/images/nano_icon.png'), - this.bananoIcon = Image.asset('assets/images/nano_icon.png'); + this.bananoIcon = Image.asset('assets/images/nano_icon.png'), + this.bitcoinCashIcon = Image.asset('assets/images/bch_icon.png'); final largeScreen = 731; @@ -50,10 +51,10 @@ class MenuWidgetState extends State { Image litecoinIcon; Image havenIcon; Image ethereumIcon; + Image bitcoinCashIcon; Image nanoIcon; Image bananoIcon; - @override void initState() { menuWidth = 0; @@ -212,6 +213,8 @@ class MenuWidgetState extends State { return havenIcon; case WalletType.ethereum: return ethereumIcon; + case WalletType.bitcoinCash: + return bitcoinCashIcon; case WalletType.nano: return nanoIcon; case WalletType.banano: diff --git a/lib/src/screens/seed/pre_seed_page.dart b/lib/src/screens/seed/pre_seed_page.dart index a73e7bbff..7e6bfb1de 100644 --- a/lib/src/screens/seed/pre_seed_page.dart +++ b/lib/src/screens/seed/pre_seed_page.dart @@ -73,6 +73,7 @@ class PreSeedPage extends BasePage { case WalletType.monero: return 25; case WalletType.ethereum: + case WalletType.bitcoinCash: return 12; default: return 24; 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 1c1fbfa5d..1a173f62a 100644 --- a/lib/src/screens/unspent_coins/unspent_coins_list_page.dart +++ b/lib/src/screens/unspent_coins/unspent_coins_list_page.dart @@ -1,8 +1,10 @@ +import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_list_view_model.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; @@ -79,6 +81,9 @@ class UnspentCoinsListFormState extends State { itemBuilder: (_, int index) { return Observer(builder: (_) { final item = unspentCoinsListViewModel.items[index]; + final address = unspentCoinsListViewModel.wallet.type == WalletType.bitcoinCash + ? bitcoinCash!.getCashAddrFormat(item.address) + : item.address; return GestureDetector( onTap: () => @@ -88,7 +93,7 @@ class UnspentCoinsListFormState extends State { child: UnspentCoinsListItem( note: item.note, amount: item.amount, - address: item.address, + address: address, isSending: item.isSending, isFrozen: item.isFrozen, onCheckBoxTap: item.isFrozen diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index a0b44f375..11b394460 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -48,6 +48,7 @@ class WalletListBodyState extends State { final nonWalletTypeIcon = Image.asset('assets/images/close.png', height: 24, width: 24); final havenIcon = Image.asset('assets/images/haven_logo.png', height: 24, width: 24); final ethereumIcon = Image.asset('assets/images/eth_icon.png', height: 24, width: 24); + final bitcoinCashIcon = Image.asset('assets/images/bch_icon.png', height: 24, width: 24); final nanoIcon = Image.asset('assets/images/nano_icon.png', height: 24, width: 24); final scrollController = ScrollController(); final double tileHeight = 60; @@ -243,6 +244,8 @@ class WalletListBodyState extends State { return havenIcon; case WalletType.ethereum: return ethereumIcon; + case WalletType.bitcoinCash: + return bitcoinCashIcon; case WalletType.nano: return nanoIcon; default: diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 939d724d6..a2e2570e0 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/buy_provider_types.dart'; import 'package:cake_wallet/entities/cake_2fa_preset_options.dart'; @@ -85,7 +86,8 @@ abstract class SettingsStoreBase with Store { TransactionPriority? initialMoneroTransactionPriority, TransactionPriority? initialHavenTransactionPriority, TransactionPriority? initialLitecoinTransactionPriority, - TransactionPriority? initialEthereumTransactionPriority}) + TransactionPriority? initialEthereumTransactionPriority, + TransactionPriority? initialBitcoinCashTransactionPriority}) : nodes = ObservableMap.of(nodes), powNodes = ObservableMap.of(powNodes), _sharedPreferences = sharedPreferences, @@ -146,6 +148,10 @@ abstract class SettingsStoreBase with Store { priority[WalletType.ethereum] = initialEthereumTransactionPriority; } + if (initialBitcoinCashTransactionPriority != null) { + priority[WalletType.bitcoinCash] = initialBitcoinCashTransactionPriority; + } + reaction( (_) => fiatCurrency, (FiatCurrency fiatCurrency) => sharedPreferences.setString( @@ -174,6 +180,9 @@ abstract class SettingsStoreBase with Store { case WalletType.ethereum: key = PreferencesKey.ethereumTransactionPriority; break; + case WalletType.bitcoinCash: + key = PreferencesKey.bitcoinCashTransactionPriority; + break; default: key = null; } @@ -526,12 +535,13 @@ abstract class SettingsStoreBase with Store { TransactionPriority? moneroTransactionPriority = monero?.deserializeMoneroTransactionPriority( raw: sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!); TransactionPriority? bitcoinTransactionPriority = - bitcoin?.deserializeBitcoinTransactionPriority( - sharedPreferences.getInt(PreferencesKey.bitcoinTransactionPriority)!); + bitcoin?.deserializeBitcoinTransactionPriority( + sharedPreferences.getInt(PreferencesKey.bitcoinTransactionPriority)!); TransactionPriority? havenTransactionPriority; TransactionPriority? litecoinTransactionPriority; TransactionPriority? ethereumTransactionPriority; + TransactionPriority? bitcoinCashTransactionPriority; if (sharedPreferences.getInt(PreferencesKey.havenTransactionPriority) != null) { havenTransactionPriority = monero?.deserializeMoneroTransactionPriority( @@ -545,12 +555,17 @@ abstract class SettingsStoreBase with Store { ethereumTransactionPriority = bitcoin?.deserializeLitecoinTransactionPriority( sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority)!); } + if (sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority) != null) { + bitcoinCashTransactionPriority = bitcoinCash?.deserializeBitcoinCashTransactionPriority( + sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority)!); + } moneroTransactionPriority ??= monero?.getDefaultTransactionPriority(); bitcoinTransactionPriority ??= bitcoin?.getMediumTransactionPriority(); havenTransactionPriority ??= monero?.getDefaultTransactionPriority(); litecoinTransactionPriority ??= bitcoin?.getLitecoinTransactionPriorityMedium(); ethereumTransactionPriority ??= ethereum?.getDefaultTransactionPriority(); + bitcoinCashTransactionPriority ??= bitcoinCash?.getDefaultTransactionPriority(); final currentBalanceDisplayMode = BalanceDisplayMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey)!); @@ -560,7 +575,8 @@ abstract class SettingsStoreBase with Store { final isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? false; final disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? false; final disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? false; - final defaultBuyProvider = BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0]; + final defaultBuyProvider = BuyProviderType.values[sharedPreferences.getInt( + PreferencesKey.defaultBuyProvider) ?? 0]; final currentFiatApiMode = FiatApiMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey) ?? FiatApiMode.enabled.raw); @@ -579,7 +595,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToInternalWallets) ?? false; final shouldRequireTOTP2FAForExchangesToInternalWallets = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ?? + .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ?? false; final shouldRequireTOTP2FAForAddingContacts = sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForAddingContacts) ?? false; @@ -587,7 +603,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets) ?? false; final shouldRequireTOTP2FAForAllSecurityAndBackupSettings = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ?? + .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ?? false; final useTOTP2FA = sharedPreferences.getBool(PreferencesKey.useTOTP2FA) ?? false; final totpSecretKey = sharedPreferences.getString(PreferencesKey.totpSecretKey) ?? ''; @@ -612,7 +628,7 @@ abstract class SettingsStoreBase with Store { ? PinCodeRequiredDuration.deserialize(raw: timeOutDuration) : defaultPinCodeTimeOutDuration; final sortBalanceBy = - SortBalanceBy.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? 0]; + SortBalanceBy.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? 0]; final pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true; final useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true; @@ -626,9 +642,11 @@ abstract class SettingsStoreBase with Store { await LanguageService.localeDetection(); final nodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey); final bitcoinElectrumServerId = - sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); + sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); final litecoinElectrumServerId = - sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); + sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); + final bitcoinCashElectrumServerId = + sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); final havenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey); final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey); final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); @@ -638,13 +656,14 @@ abstract class SettingsStoreBase with Store { final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId); final havenNode = nodeSource.get(havenNodeId); final ethereumNode = nodeSource.get(ethereumNodeId); + final bitcoinCashElectrumServer = nodeSource.get(bitcoinCashElectrumServerId); final nanoNode = nodeSource.get(nanoNodeId); final nanoPowNode = powNodeSource.get(nanoPowNodeId); final packageInfo = await PackageInfo.fromPlatform(); final deviceName = await _getDeviceName() ?? ''; final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true; final generateSubaddresses = - sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); + sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); final autoGenerateSubaddressStatus = generateSubaddresses != null ? AutoGenerateSubaddressStatus.deserialize(raw: generateSubaddresses) @@ -672,70 +691,76 @@ abstract class SettingsStoreBase with Store { nodes[WalletType.ethereum] = ethereumNode; } + if (bitcoinCashElectrumServer != null) { + nodes[WalletType.bitcoinCash] = bitcoinCashElectrumServer; + } + if (nanoNode != null) { nodes[WalletType.nano] = nanoNode; } + if (nanoPowNode != null) { powNodes[WalletType.nano] = nanoPowNode; } - final savedSyncMode = SyncMode.all.firstWhere((element) { - return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 1); - }); - final savedSyncAll = sharedPreferences.getBool(PreferencesKey.syncAllKey) ?? true; + final savedSyncMode = SyncMode.all.firstWhere((element) { + return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 1); + }); + final savedSyncAll = sharedPreferences.getBool(PreferencesKey.syncAllKey) ?? true; - return SettingsStore( - sharedPreferences: sharedPreferences, - initialShouldShowMarketPlaceInDashboard: shouldShowMarketPlaceInDashboard, - nodes: nodes, - powNodes: powNodes, - appVersion: packageInfo.version, - deviceName: deviceName, - isBitcoinBuyEnabled: isBitcoinBuyEnabled, - initialFiatCurrency: currentFiatCurrency, - initialBalanceDisplayMode: currentBalanceDisplayMode, - initialSaveRecipientAddress: shouldSaveRecipientAddress, - initialAutoGenerateSubaddressStatus: autoGenerateSubaddressStatus, - initialAppSecure: isAppSecure, - initialDisableBuy: disableBuy, - initialDisableSell: disableSell, - initialDefaultBuyProvider: defaultBuyProvider, - initialFiatMode: currentFiatApiMode, - initialAllowBiometricalAuthentication: allowBiometricalAuthentication, - initialCake2FAPresetOptions: selectedCake2FAPreset, - initialUseTOTP2FA: useTOTP2FA, - initialTotpSecretKey: totpSecretKey, - initialFailedTokenTrial: tokenTrialNumber, - initialExchangeStatus: exchangeStatus, - initialTheme: savedTheme, - actionlistDisplayMode: actionListDisplayMode, - initialPinLength: pinLength, - pinTimeOutDuration: pinCodeTimeOutDuration, - initialLanguageCode: savedLanguageCode, - sortBalanceBy: sortBalanceBy, - pinNativeTokenAtTop: pinNativeTokenAtTop, - useEtherscan: useEtherscan, - initialMoneroTransactionPriority: moneroTransactionPriority, - initialBitcoinTransactionPriority: bitcoinTransactionPriority, - initialHavenTransactionPriority: havenTransactionPriority, - initialLitecoinTransactionPriority: litecoinTransactionPriority, - initialShouldRequireTOTP2FAForAccessingWallet: shouldRequireTOTP2FAForAccessingWallet, - initialShouldRequireTOTP2FAForSendsToContact: shouldRequireTOTP2FAForSendsToContact, - initialShouldRequireTOTP2FAForSendsToNonContact: shouldRequireTOTP2FAForSendsToNonContact, - initialShouldRequireTOTP2FAForSendsToInternalWallets: - shouldRequireTOTP2FAForSendsToInternalWallets, - initialShouldRequireTOTP2FAForExchangesToInternalWallets: - shouldRequireTOTP2FAForExchangesToInternalWallets, - initialShouldRequireTOTP2FAForAddingContacts: shouldRequireTOTP2FAForAddingContacts, - initialShouldRequireTOTP2FAForCreatingNewWallets: shouldRequireTOTP2FAForCreatingNewWallets, - initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings: - shouldRequireTOTP2FAForAllSecurityAndBackupSettings, - initialEthereumTransactionPriority: ethereumTransactionPriority, - backgroundTasks: backgroundTasks, - initialSyncMode: savedSyncMode, - initialSyncAll: savedSyncAll, - shouldShowYatPopup: shouldShowYatPopup); - } + return SettingsStore( + sharedPreferences: sharedPreferences, + initialShouldShowMarketPlaceInDashboard: shouldShowMarketPlaceInDashboard, + nodes: nodes, + powNodes: powNodes, + appVersion: packageInfo.version, + deviceName: deviceName, + isBitcoinBuyEnabled: isBitcoinBuyEnabled, + initialFiatCurrency: currentFiatCurrency, + initialBalanceDisplayMode: currentBalanceDisplayMode, + initialSaveRecipientAddress: shouldSaveRecipientAddress, + initialAutoGenerateSubaddressStatus: autoGenerateSubaddressStatus, + initialAppSecure: isAppSecure, + initialDisableBuy: disableBuy, + initialDisableSell: disableSell, + initialDefaultBuyProvider: defaultBuyProvider, + initialFiatMode: currentFiatApiMode, + initialAllowBiometricalAuthentication: allowBiometricalAuthentication, + initialCake2FAPresetOptions: selectedCake2FAPreset, + initialUseTOTP2FA: useTOTP2FA, + initialTotpSecretKey: totpSecretKey, + initialFailedTokenTrial: tokenTrialNumber, + initialExchangeStatus: exchangeStatus, + initialTheme: savedTheme, + actionlistDisplayMode: actionListDisplayMode, + initialPinLength: pinLength, + pinTimeOutDuration: pinCodeTimeOutDuration, + initialLanguageCode: savedLanguageCode, + sortBalanceBy: sortBalanceBy, + pinNativeTokenAtTop: pinNativeTokenAtTop, + useEtherscan: useEtherscan, + initialMoneroTransactionPriority: moneroTransactionPriority, + initialBitcoinTransactionPriority: bitcoinTransactionPriority, + initialHavenTransactionPriority: havenTransactionPriority, + initialLitecoinTransactionPriority: litecoinTransactionPriority, + initialBitcoinCashTransactionPriority: bitcoinCashTransactionPriority, + initialShouldRequireTOTP2FAForAccessingWallet: shouldRequireTOTP2FAForAccessingWallet, + initialShouldRequireTOTP2FAForSendsToContact: shouldRequireTOTP2FAForSendsToContact, + initialShouldRequireTOTP2FAForSendsToNonContact: shouldRequireTOTP2FAForSendsToNonContact, + initialShouldRequireTOTP2FAForSendsToInternalWallets: + shouldRequireTOTP2FAForSendsToInternalWallets, + initialShouldRequireTOTP2FAForExchangesToInternalWallets: + shouldRequireTOTP2FAForExchangesToInternalWallets, + initialShouldRequireTOTP2FAForAddingContacts: shouldRequireTOTP2FAForAddingContacts, + initialShouldRequireTOTP2FAForCreatingNewWallets: shouldRequireTOTP2FAForCreatingNewWallets, + initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings: + shouldRequireTOTP2FAForAllSecurityAndBackupSettings, + initialEthereumTransactionPriority: ethereumTransactionPriority, + backgroundTasks: backgroundTasks, + initialSyncMode: savedSyncMode, + initialSyncAll: savedSyncAll, + shouldShowYatPopup: shouldShowYatPopup); + } Future reload({required Box nodeSource}) async { final sharedPreferences = await getIt.getAsync(); @@ -744,30 +769,35 @@ abstract class SettingsStoreBase with Store { raw: sharedPreferences.getString(PreferencesKey.currentFiatCurrencyKey)!); priority[WalletType.monero] = monero?.deserializeMoneroTransactionPriority( - raw: sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ?? + raw: sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ?? priority[WalletType.monero]!; priority[WalletType.bitcoin] = bitcoin?.deserializeBitcoinTransactionPriority( - sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ?? + sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ?? priority[WalletType.bitcoin]!; if (sharedPreferences.getInt(PreferencesKey.havenTransactionPriority) != null) { priority[WalletType.haven] = monero?.deserializeMoneroTransactionPriority( - raw: sharedPreferences.getInt(PreferencesKey.havenTransactionPriority)!) ?? + raw: sharedPreferences.getInt(PreferencesKey.havenTransactionPriority)!) ?? priority[WalletType.haven]!; } if (sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority) != null) { priority[WalletType.litecoin] = bitcoin?.deserializeLitecoinTransactionPriority( - sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority)!) ?? + sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority)!) ?? priority[WalletType.litecoin]!; } if (sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority) != null) { priority[WalletType.ethereum] = ethereum?.deserializeEthereumTransactionPriority( - sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority)!) ?? + sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority)!) ?? priority[WalletType.ethereum]!; } + if (sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority) != null) { + priority[WalletType.bitcoinCash] = bitcoinCash?.deserializeBitcoinCashTransactionPriority( + sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority)!) ?? + priority[WalletType.bitcoinCash]!; + } final generateSubaddresses = - sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); + sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); autoGenerateSubaddressStatus = generateSubaddresses != null ? AutoGenerateSubaddressStatus.deserialize(raw: generateSubaddresses) @@ -785,7 +815,8 @@ abstract class SettingsStoreBase with Store { isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? isAppSecure; disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? disableBuy; disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? disableSell; - defaultBuyProvider = BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0]; + defaultBuyProvider = + BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0]; allowBiometricalAuthentication = sharedPreferences.getBool(PreferencesKey.allowBiometricalAuthenticationKey) ?? allowBiometricalAuthentication; @@ -802,7 +833,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToInternalWallets) ?? false; shouldRequireTOTP2FAForExchangesToInternalWallets = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ?? + .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ?? false; shouldRequireTOTP2FAForAddingContacts = sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForAddingContacts) ?? false; @@ -810,7 +841,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets) ?? false; shouldRequireTOTP2FAForAllSecurityAndBackupSettings = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ?? + .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ?? false; shouldShowMarketPlaceInDashboard = sharedPreferences.getBool(PreferencesKey.shouldShowMarketPlaceInDashboard) ?? @@ -846,9 +877,11 @@ abstract class SettingsStoreBase with Store { final nodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey); final bitcoinElectrumServerId = - sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); + sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); final litecoinElectrumServerId = - sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); + sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); + final bitcoinCashElectrumServerId = + sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); final havenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey); final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey); final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); @@ -858,6 +891,7 @@ abstract class SettingsStoreBase with Store { final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId); final havenNode = nodeSource.get(havenNodeId); final ethereumNode = nodeSource.get(ethereumNodeId); + final bitcoinCashNode = nodeSource.get(bitcoinCashElectrumServerId); final nanoNode = nodeSource.get(nanoNodeId); if (moneroNode != null) { @@ -880,6 +914,10 @@ abstract class SettingsStoreBase with Store { nodes[WalletType.ethereum] = ethereumNode; } + if (bitcoinCashNode != null) { + nodes[WalletType.bitcoinCash] = bitcoinCashNode; + } + if (nanoNode != null) { nodes[WalletType.nano] = nanoNode; } @@ -904,6 +942,9 @@ abstract class SettingsStoreBase with Store { case WalletType.ethereum: await _sharedPreferences.setInt(PreferencesKey.currentEthereumNodeIdKey, node.key as int); break; + case WalletType.bitcoinCash: + await _sharedPreferences.setInt(PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int); + break; case WalletType.nano: await _sharedPreferences.setInt(PreferencesKey.currentNanoNodeIdKey, node.key as int); break; diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart index e7e640afc..4e1c1aae0 100644 --- a/lib/view_model/dashboard/transaction_list_item.dart +++ b/lib/view_model/dashboard/transaction_list_item.dart @@ -72,6 +72,7 @@ class TransactionListItem extends ActionListItem with Keyable { break; case WalletType.bitcoin: case WalletType.litecoin: + case WalletType.bitcoinCash: amount = calculateFiatAmountRaw( cryptoAmount: bitcoin!.formatterBitcoinAmountToDouble(amount: transaction.amount), price: price); diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 47b408bc2..7bc7927df 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -2,10 +2,12 @@ import 'dart:async'; import 'dart:collection'; import 'dart:convert'; +import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/core/wallet_change_listener_view_model.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/wallet_contact.dart'; +import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/exchange/exolix/exolix_exchange_provider.dart'; import 'package:cake_wallet/exchange/exolix/exolix_request.dart'; import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'; @@ -265,8 +267,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with } bool get hasAllAmount => - (wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin) && - depositCurrency == wallet.currency; + (wallet.type == WalletType.bitcoin || + wallet.type == WalletType.litecoin || + wallet.type == WalletType.bitcoinCash) && + depositCurrency == wallet.currency; bool get isMoneroWallet => wallet.type == WalletType.monero; @@ -278,7 +282,14 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with case WalletType.bitcoin: return transactionPriority == bitcoin!.getBitcoinTransactionPrioritySlow(); case WalletType.litecoin: - return transactionPriority == bitcoin!.getLitecoinTransactionPrioritySlow(); + return transactionPriority == + bitcoin!.getLitecoinTransactionPrioritySlow(); + case WalletType.ethereum: + return transactionPriority == + ethereum!.getEthereumTransactionPrioritySlow(); + case WalletType.bitcoinCash: + return transactionPriority == + bitcoinCash!.getBitcoinCashTransactionPrioritySlow(); default: return false; } @@ -619,7 +630,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with @action void calculateDepositAllAmount() { - if (wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin) { + if (wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin || wallet.type == WalletType.bitcoinCash) { final availableBalance = wallet.balance[wallet.currency]!.available; final priority = _settingsStore.priority[wallet.type]!; final fee = wallet.calculateEstimatedFee(priority, null); @@ -694,6 +705,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with depositCurrency = CryptoCurrency.ltc; receiveCurrency = CryptoCurrency.xmr; break; + case WalletType.bitcoinCash: + depositCurrency = CryptoCurrency.bch; + receiveCurrency = CryptoCurrency.xmr; + break; case WalletType.haven: depositCurrency = CryptoCurrency.xhv; receiveCurrency = CryptoCurrency.btc; @@ -789,6 +804,12 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with case WalletType.litecoin: _settingsStore.priority[wallet.type] = bitcoin!.getLitecoinTransactionPriorityMedium(); break; + case WalletType.ethereum: + _settingsStore.priority[wallet.type] = ethereum!.getDefaultTransactionPriority(); + break; + case WalletType.bitcoinCash: + _settingsStore.priority[wallet.type] = bitcoinCash!.getDefaultTransactionPriority(); + break; default: break; } diff --git a/lib/view_model/node_list/node_list_view_model.dart b/lib/view_model/node_list/node_list_view_model.dart index fb1198c41..ae0edba30 100644 --- a/lib/view_model/node_list/node_list_view_model.dart +++ b/lib/view_model/node_list/node_list_view_model.dart @@ -66,6 +66,9 @@ abstract class NodeListViewModelBase with Store { case WalletType.ethereum: node = getEthereumDefaultNode(nodes: _nodeSource)!; break; + case WalletType.bitcoinCash: + node = getBitcoinCashDefaultElectrumServer(nodes: _nodeSource)!; + break; case WalletType.nano: node = getNanoDefaultNode(nodes: _nodeSource)!; break; diff --git a/lib/view_model/restore/restore_from_qr_vm.dart b/lib/view_model/restore/restore_from_qr_vm.dart index 39a7b682f..2bc595469 100644 --- a/lib/view_model/restore/restore_from_qr_vm.dart +++ b/lib/view_model/restore/restore_from_qr_vm.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/view_model/restore/restore_mode.dart'; import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; @@ -84,6 +85,9 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store case WalletType.litecoin: return bitcoin!.createBitcoinRestoreWalletFromSeedCredentials( name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); + case WalletType.bitcoinCash: + return bitcoinCash!.createBitcoinCashRestoreWalletFromSeedCredentials( + name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); case WalletType.ethereum: return ethereum!.createEthereumRestoreWalletFromSeedCredentials( name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); diff --git a/lib/view_model/restore/wallet_restore_from_qr_code.dart b/lib/view_model/restore/wallet_restore_from_qr_code.dart index e9aed55c6..dd138b66c 100644 --- a/lib/view_model/restore/wallet_restore_from_qr_code.dart +++ b/lib/view_model/restore/wallet_restore_from_qr_code.dart @@ -72,8 +72,13 @@ class WalletRestoreFromQRCode { case 'litecoin': case 'litecoin-wallet': return WalletType.litecoin; + case 'bitcoincash': + case 'bitcoinCash-wallet': + return WalletType.bitcoinCash; case 'ethereum-wallet': return WalletType.ethereum; + case 'nano-wallet': + return WalletType.nano; default: throw Exception('Unexpected wallet type: ${scheme.toString()}'); } @@ -107,6 +112,7 @@ class WalletRestoreFromQRCode { case WalletType.bitcoin: case WalletType.litecoin: case WalletType.ethereum: + case WalletType.bitcoinCash: RegExp regex24 = RegExp(r'\b(\S+\b\s+){23}\S+\b'); RegExp regex18 = RegExp(r'\b(\S+\b\s+){17}\S+\b'); RegExp regex12 = RegExp(r'\b(\S+\b\s+){11}\S+\b'); diff --git a/lib/view_model/send/output.dart b/lib/view_model/send/output.dart index 8008812ba..2e696e16f 100644 --- a/lib/view_model/send/output.dart +++ b/lib/view_model/send/output.dart @@ -81,10 +81,8 @@ abstract class OutputBase with Store { _amount = monero!.formatterMoneroParseAmount(amount: _cryptoAmount); break; case WalletType.bitcoin: - _amount = - bitcoin!.formatterStringDoubleToBitcoinAmount(_cryptoAmount); - break; case WalletType.litecoin: + case WalletType.bitcoinCash: _amount = bitcoin!.formatterStringDoubleToBitcoinAmount(_cryptoAmount); break; @@ -116,7 +114,8 @@ abstract class OutputBase with Store { _settingsStore.priority[_wallet.type]!, formattedCryptoAmount); if (_wallet.type == WalletType.bitcoin || - _wallet.type == WalletType.litecoin) { + _wallet.type == WalletType.litecoin || + _wallet.type == WalletType.bitcoinCash) { return bitcoin!.formatterBitcoinAmountToDouble(amount: fee); } @@ -234,6 +233,9 @@ abstract class OutputBase with Store { case WalletType.litecoin: maximumFractionDigits = 8; break; + case WalletType.bitcoinCash: + maximumFractionDigits = 8; + break; case WalletType.haven: maximumFractionDigits = 12; break; diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 2ba6dc784..719298675 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -185,12 +185,15 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor @computed bool get hasCoinControl => wallet.type == WalletType.bitcoin || - wallet.type == WalletType.litecoin || - wallet.type == WalletType.monero; + wallet.type == WalletType.litecoin || + wallet.type == WalletType.monero || + wallet.type == WalletType.bitcoinCash; @computed bool get isElectrumWallet => - wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin; + wallet.type == WalletType.bitcoin || + wallet.type == WalletType.litecoin || + wallet.type == WalletType.bitcoinCash; @computed bool get hasFees => wallet.type != WalletType.nano && wallet.type != WalletType.banano; @@ -345,41 +348,24 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor _settingsStore.priority[wallet.type] = priority; Object _credentials() { + final priority = _settingsStore.priority[wallet.type]; + + if (priority == null) throw Exception('Priority is null for wallet type: ${wallet.type}'); + switch (wallet.type) { case WalletType.bitcoin: - final priority = _settingsStore.priority[wallet.type]; - - if (priority == null) { - throw Exception('Priority is null for wallet type: ${wallet.type}'); - } - - return bitcoin!.createBitcoinTransactionCredentials(outputs, priority: priority); case WalletType.litecoin: - final priority = _settingsStore.priority[wallet.type]; - - if (priority == null) { - throw Exception('Priority is null for wallet type: ${wallet.type}'); - } - + case WalletType.bitcoinCash: return bitcoin!.createBitcoinTransactionCredentials(outputs, priority: priority); + case WalletType.monero: - final priority = _settingsStore.priority[wallet.type]; - - if (priority == null) { - throw Exception('Priority is null for wallet type: ${wallet.type}'); - } - return monero! .createMoneroTransactionCreationCredentials(outputs: outputs, priority: priority); + case WalletType.haven: - final priority = _settingsStore.priority[wallet.type]; - - if (priority == null) { - throw Exception('Priority is null for wallet type: ${wallet.type}'); - } - return haven!.createHavenTransactionCreationCredentials( outputs: outputs, priority: priority, assetType: selectedCryptoCurrency.title); + case WalletType.ethereum: final priority = _settingsStore.priority[wallet.type]; @@ -390,9 +376,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor return ethereum!.createEthereumTransactionCredentials(outputs, priority: priority, currency: selectedCryptoCurrency); case WalletType.nano: - return nano!.createNanoTransactionCredentials( - outputs, - ); + return nano!.createNanoTransactionCredentials(outputs); default: throw Exception('Unexpected wallet type: ${wallet.type}'); } diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart index 587e8723b..b4ca46f70 100644 --- a/lib/view_model/settings/other_settings_view_model.dart +++ b/lib/view_model/settings/other_settings_view_model.dart @@ -63,7 +63,9 @@ abstract class OtherSettingsViewModelBase with Store { String getDisplayPriority(dynamic priority) { final _priority = priority as TransactionPriority; - if (_wallet.type == WalletType.bitcoin || _wallet.type == WalletType.litecoin) { + if (_wallet.type == WalletType.bitcoin || + _wallet.type == WalletType.litecoin || + _wallet.type == WalletType.bitcoinCash) { final rate = bitcoin!.getFeeRate(_wallet, _priority); return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate); } diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index fd001125f..a8c892284 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -39,6 +39,7 @@ abstract class TransactionDetailsViewModelBase with Store { break; case WalletType.bitcoin: case WalletType.litecoin: + case WalletType.bitcoinCash: _addElectrumListItems(tx, dateFormat); break; case WalletType.haven: @@ -115,6 +116,8 @@ abstract class TransactionDetailsViewModelBase with Store { return 'https://mempool.space/tx/${txId}'; case WalletType.litecoin: return 'https://blockchair.com/litecoin/transaction/${txId}'; + case WalletType.bitcoinCash: + return 'https://blockchair.com/bitcoin-cash/transaction/${txId}'; case WalletType.haven: return 'https://explorer.havenprotocol.org/search?value=${txId}'; case WalletType.ethereum: @@ -135,6 +138,7 @@ abstract class TransactionDetailsViewModelBase with Store { case WalletType.bitcoin: return S.current.view_transaction_on + 'mempool.space'; case WalletType.litecoin: + case WalletType.bitcoinCash: return S.current.view_transaction_on + 'Blockchair.com'; case WalletType.haven: return S.current.view_transaction_on + 'explorer.havenprotocol.org'; diff --git a/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart b/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart index 992991147..4da43c241 100644 --- a/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart +++ b/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart @@ -1,9 +1,10 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/src/screens/transaction_details/blockexplorer_list_item.dart'; import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; import 'package:cake_wallet/src/screens/transaction_details/textfield_list_item.dart'; import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_item.dart'; -import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_list_view_model.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_switch_item.dart'; import 'package:cw_core/wallet_type.dart'; @@ -19,12 +20,14 @@ abstract class UnspentCoinsDetailsViewModelBase with Store { UnspentCoinsDetailsViewModelBase( {required this.unspentCoinsItem, required this.unspentCoinsListViewModel}) : items = [], + _type = unspentCoinsListViewModel.wallet.type, isFrozen = unspentCoinsItem.isFrozen, note = unspentCoinsItem.note { items = [ StandartListItem(title: S.current.transaction_details_amount, value: unspentCoinsItem.amount), - StandartListItem(title: S.current.transaction_details_transaction_id, value: unspentCoinsItem.hash), - StandartListItem(title: S.current.widgets_address, value: unspentCoinsItem.address), + StandartListItem( + title: S.current.transaction_details_transaction_id, value: unspentCoinsItem.hash), + StandartListItem(title: S.current.widgets_address, value: formattedAddress), TextFieldListItem( title: S.current.note_tap_to_change, value: note, @@ -46,14 +49,13 @@ abstract class UnspentCoinsDetailsViewModelBase with Store { }) ]; - if ([WalletType.bitcoin, WalletType.litecoin].contains(unspentCoinsListViewModel.wallet.type)) { + if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(_type)) { items.add(BlockExplorerListItem( title: S.current.view_in_block_explorer, - value: _explorerDescription(unspentCoinsListViewModel.wallet.type), + value: _explorerDescription(_type), onTap: () { try { - final url = Uri.parse( - _explorerUrl(unspentCoinsListViewModel.wallet.type, unspentCoinsItem.hash)); + final url = Uri.parse(_explorerUrl(_type, unspentCoinsItem.hash)); return launchUrl(url); } catch (e) {} }, @@ -67,6 +69,8 @@ abstract class UnspentCoinsDetailsViewModelBase with Store { return 'https://ordinals.com/tx/${txId}'; case WalletType.litecoin: return 'https://litecoin.earlyordies.com/tx/${txId}'; + case WalletType.bitcoinCash: + return 'https://blockchair.com/bitcoin-cash/transaction/${txId}'; default: return ''; } @@ -78,6 +82,8 @@ abstract class UnspentCoinsDetailsViewModelBase with Store { return S.current.view_transaction_on + 'Ordinals.com'; case WalletType.litecoin: return S.current.view_transaction_on + 'Earlyordies.com'; + case WalletType.bitcoinCash: + return S.current.view_transaction_on + 'Blockchair.com'; default: return ''; } @@ -91,5 +97,10 @@ abstract class UnspentCoinsDetailsViewModelBase with Store { final UnspentCoinsItem unspentCoinsItem; final UnspentCoinsListViewModel unspentCoinsListViewModel; + final WalletType _type; List items; + + String get formattedAddress => WalletType.bitcoinCash == _type + ? bitcoinCash!.getCashAddrFormat(unspentCoinsItem.address) + : unspentCoinsItem.address; } diff --git a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart index 657a0cb74..709c50562 100644 --- a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart +++ b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart @@ -1,9 +1,10 @@ import 'package:collection/collection.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; -import 'package:cake_wallet/entities/unspent_transaction_output.dart'; +import 'package:cw_core/unspent_transaction_output.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_item.dart'; import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/wallet_addresses.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; @@ -24,11 +25,11 @@ abstract class UnspentCoinsListViewModelBase with Store { final Box _unspentCoinsInfo; @computed - ObservableList get items => - ObservableList.of(_getUnspents().map((elem) { + ObservableList get items => ObservableList.of(_getUnspents().map((elem) { final amount = formatAmountToString(elem.value) + ' ${wallet.currency.title}'; - final info = getUnspentCoinInfo(elem.hash, elem.address, elem.value, elem.vout, elem.keyImage); + final info = + getUnspentCoinInfo(elem.hash, elem.address, elem.value, elem.vout, elem.keyImage); return UnspentCoinsItem( address: elem.address, @@ -39,13 +40,13 @@ abstract class UnspentCoinsListViewModelBase with Store { isSending: info?.isSending ?? true, amountRaw: elem.value, vout: elem.vout, - keyImage: elem.keyImage - ); + keyImage: elem.keyImage); })); Future saveUnspentCoinInfo(UnspentCoinsItem item) async { try { - final info = getUnspentCoinInfo(item.hash, item.address, item.amountRaw, item.vout, item.keyImage); + final info = + getUnspentCoinInfo(item.hash, item.address, item.amountRaw, item.vout, item.keyImage); if (info == null) { final newInfo = UnspentCoinsInfo( walletId: wallet.id, @@ -56,8 +57,7 @@ abstract class UnspentCoinsListViewModelBase with Store { isFrozen: item.isFrozen, isSending: item.isSending, noteRaw: item.note, - keyImage: item.keyImage - ); + keyImage: item.keyImage); await _unspentCoinsInfo.add(newInfo); _updateUnspents(); @@ -76,37 +76,34 @@ abstract class UnspentCoinsListViewModelBase with Store { } } - UnspentCoinsInfo? getUnspentCoinInfo(String hash, String address, int value, int vout, String? keyImage) { + UnspentCoinsInfo? getUnspentCoinInfo( + String hash, String address, int value, int vout, String? keyImage) { return _unspentCoinsInfo.values.firstWhereOrNull((element) => element.walletId == wallet.id && element.hash == hash && element.address == address && element.value == value && element.vout == vout && - element.keyImage == keyImage - ); + element.keyImage == keyImage); } String formatAmountToString(int fullBalance) { if (wallet.type == WalletType.monero) return monero!.formatterMoneroAmountToString(amount: fullBalance); - if ([WalletType.bitcoin, WalletType.litecoin].contains(wallet.type)) + if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(wallet.type)) return bitcoin!.formatterBitcoinAmountToString(amount: fullBalance); return ''; } - void _updateUnspents() { - if (wallet.type == WalletType.monero) - return monero!.updateUnspents(wallet); - if ([WalletType.bitcoin, WalletType.litecoin].contains(wallet.type)) + if (wallet.type == WalletType.monero) return monero!.updateUnspents(wallet); + if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(wallet.type)) return bitcoin!.updateUnspents(wallet); } List _getUnspents() { - if (wallet.type == WalletType.monero) - return monero!.getUnspents(wallet); - if ([WalletType.bitcoin, WalletType.litecoin].contains(wallet.type)) + if (wallet.type == WalletType.monero) return monero!.getUnspents(wallet); + if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(wallet.type)) return bitcoin!.getUnspents(wallet); return List.empty(); } diff --git a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart index a4eb3d386..9e2aa7187 100644 --- a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart @@ -66,7 +66,8 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store { final wallet = _wallet; if (wallet.type == WalletType.bitcoin - || wallet.type == WalletType.litecoin) { + || wallet.type == WalletType.litecoin + || wallet.type == WalletType.bitcoinCash) { await bitcoin!.generateNewAddress(wallet); await wallet.save(); } diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index a24e1635f..4d5eefdb7 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -107,6 +107,23 @@ class EthereumURI extends PaymentURI { } } +class BitcoinCashURI extends PaymentURI { + BitcoinCashURI({required String amount, required String address}) + : super(amount: amount, address: address); + @override + String toString() { + var base = address; + + if (amount.isNotEmpty) { + base += '?amount=${amount.replaceAll(',', '.')}'; + } + + return base; + } + } + + + class NanoURI extends PaymentURI { NanoURI({required String amount, required String address}) : super(amount: amount, address: address); @@ -114,7 +131,6 @@ class NanoURI extends PaymentURI { @override String toString() { var base = 'nano:' + address; - if (amount.isNotEmpty) { base += '?amount=${amount.replaceAll(',', '.')}'; } @@ -192,6 +208,10 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo return EthereumURI(amount: amount, address: address.address); } + if (wallet.type == WalletType.bitcoinCash) { + return BitcoinCashURI(amount: amount, address: address.address); + } + if (wallet.type == WalletType.nano) { return NanoURI(amount: amount, address: address.address); } @@ -280,7 +300,9 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo @computed bool get showElectrumAddressDisclaimer => - wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin; + wallet.type == WalletType.bitcoin || + wallet.type == WalletType.litecoin || + wallet.type == WalletType.bitcoinCash; List _baseItems; diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart index e2938c74e..e106126bc 100644 --- a/lib/view_model/wallet_keys_view_model.dart +++ b/lib/view_model/wallet_keys_view_model.dart @@ -19,6 +19,7 @@ abstract class WalletKeysViewModelBase with Store { WalletKeysViewModelBase(this._appStore) : title = _appStore.wallet!.type == WalletType.bitcoin || _appStore.wallet!.type == WalletType.litecoin || + _appStore.wallet!.type == WalletType.bitcoinCash || _appStore.wallet!.type == WalletType.ethereum ? S.current.wallet_seed : S.current.wallet_keys, @@ -91,7 +92,8 @@ abstract class WalletKeysViewModelBase with Store { } if (_appStore.wallet!.type == WalletType.bitcoin || - _appStore.wallet!.type == WalletType.litecoin) { + _appStore.wallet!.type == WalletType.litecoin || + _appStore.wallet!.type == WalletType.bitcoinCash) { items.addAll([ StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!), ]); @@ -145,6 +147,8 @@ abstract class WalletKeysViewModelBase with Store { return 'haven-wallet'; case WalletType.ethereum: return 'ethereum-wallet'; + case WalletType.bitcoinCash: + return 'bitcoinCash-wallet'; case WalletType.nano: return 'nano-wallet'; case WalletType.banano: diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart index 04da7190e..9b1f0834d 100644 --- a/lib/view_model/wallet_new_vm.dart +++ b/lib/view_model/wallet_new_vm.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:flutter/foundation.dart'; +import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/monero/monero.dart'; @@ -46,10 +47,12 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { name: name, language: options as String); case WalletType.ethereum: return ethereum!.createEthereumNewWalletCredentials(name: name); + case WalletType.bitcoinCash: + return bitcoinCash!.createBitcoinCashNewWalletCredentials(name: name); case WalletType.nano: return nano!.createNanoNewWalletCredentials(name: name); default: - throw Exception('Unexpected type: ${type.toString()}');; + throw Exception('Unexpected type: ${type.toString()}'); } } diff --git a/lib/view_model/wallet_restore_view_model.dart b/lib/view_model/wallet_restore_view_model.dart index 4eb69e48f..058948c2f 100644 --- a/lib/view_model/wallet_restore_view_model.dart +++ b/lib/view_model/wallet_restore_view_model.dart @@ -2,6 +2,7 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; +import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/store/app_store.dart'; @@ -92,14 +93,20 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { name: name, height: height, mnemonic: seed, password: password); case WalletType.ethereum: return ethereum!.createEthereumRestoreWalletFromSeedCredentials( - name: name, mnemonic: seed, password: password); + name: name, + mnemonic: seed, + password: password); + case WalletType.bitcoinCash: + return bitcoinCash!.createBitcoinCashRestoreWalletFromSeedCredentials( + name: name, + mnemonic: seed, + password: password); case WalletType.nano: return nano!.createNanoRestoreWalletFromSeedCredentials( name: name, mnemonic: seed, password: password, - derivationType: derivationType, - ); + derivationType: derivationType); default: break; } @@ -145,8 +152,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { name: name, password: password, seedKey: options['private_key'] as String, - derivationType: options["derivationType"] as DerivationType, - ); + derivationType: options["derivationType"] as DerivationType); default: break; } @@ -167,8 +173,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { return nanoUtil!.compareDerivationMethods( mnemonic: mnemonic, privateKey: seedKey, - node: node, - ); + node: node); default: break; } diff --git a/model_generator.sh b/model_generator.sh old mode 100755 new mode 100644 index 0e4345c25..50cb3d353 --- a/model_generator.sh +++ b/model_generator.sh @@ -4,4 +4,5 @@ cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_ethereum && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs \ No newline at end of file diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 1e5a2df26..6f8d51615 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -129,6 +129,7 @@ flutter: - assets/bitcoin_electrum_server_list.yml - assets/litecoin_electrum_server_list.yml - assets/ethereum_server_list.yml + - assets/bitcoin_cash_electrum_server_list.yml - assets/nano_node_list.yml - assets/nano_pow_node_list.yml - assets/text/ diff --git a/scripts/android/app_config.sh b/scripts/android/app_config.sh index 01edb14a4..e2cbd72da 100755 --- a/scripts/android/app_config.sh +++ b/scripts/android/app_config.sh @@ -9,4 +9,4 @@ fi ./app_icon.sh ./pubspec_gen.sh ./manifest.sh -./inject_app_details.sh \ No newline at end of file +./inject_app_details.sh diff --git a/scripts/android/pubspec_gen.sh b/scripts/android/pubspec_gen.sh index c74108bf1..dd9852072 100755 --- a/scripts/android/pubspec_gen.sh +++ b/scripts/android/pubspec_gen.sh @@ -10,7 +10,7 @@ case $APP_ANDROID_TYPE in CONFIG_ARGS="--monero" ;; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --haven --ethereum --nano" + CONFIG_ARGS="--monero --bitcoin --haven --ethereum --nano --bitcoinCash" ;; $HAVEN) CONFIG_ARGS="--haven" diff --git a/scripts/ios/app_config.sh b/scripts/ios/app_config.sh old mode 100755 new mode 100644 index e62b06548..8d999f594 --- a/scripts/ios/app_config.sh +++ b/scripts/ios/app_config.sh @@ -28,9 +28,11 @@ case $APP_IOS_TYPE in CONFIG_ARGS="--monero" ;; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --haven --ethereum --nano" + CONFIG_ARGS="--monero --bitcoin --haven --ethereum --nano --bitcoinCash" ;; $HAVEN) + + CONFIG_ARGS="--haven" ;; esac diff --git a/scripts/macos/app_config.sh b/scripts/macos/app_config.sh index 2af101485..48b680330 100755 --- a/scripts/macos/app_config.sh +++ b/scripts/macos/app_config.sh @@ -23,7 +23,7 @@ CONFIG_ARGS="" case $APP_MACOS_TYPE in $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --ethereum --nano";; #--haven + CONFIG_ARGS="--monero --bitcoin --ethereum --nano --bitcoinCash";; #--haven esac cp -rf pubspec_description.yaml pubspec.yaml diff --git a/tool/configure.dart b/tool/configure.dart index f7b9dc126..534aeef57 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -4,6 +4,7 @@ const bitcoinOutputPath = 'lib/bitcoin/bitcoin.dart'; const moneroOutputPath = 'lib/monero/monero.dart'; const havenOutputPath = 'lib/haven/haven.dart'; const ethereumOutputPath = 'lib/ethereum/ethereum.dart'; +const bitcoinCashOutputPath = 'lib/bitcoin_cash/bitcoin_cash.dart'; const nanoOutputPath = 'lib/nano/nano.dart'; const walletTypesPath = 'lib/wallet_types.g.dart'; const pubspecDefaultPath = 'pubspec_default.yaml'; @@ -15,6 +16,7 @@ Future main(List args) async { final hasMonero = args.contains('${prefix}monero'); final hasHaven = args.contains('${prefix}haven'); final hasEthereum = args.contains('${prefix}ethereum'); + final hasBitcoinCash = args.contains('${prefix}bitcoinCash'); final hasNano = args.contains('${prefix}nano'); final hasBanano = args.contains('${prefix}banano'); @@ -22,6 +24,7 @@ Future main(List args) async { await generateMonero(hasMonero); await generateHaven(hasHaven); await generateEthereum(hasEthereum); + await generateBitcoinCash(hasBitcoinCash); await generateNano(hasNano); // await generateBanano(hasEthereum); @@ -32,6 +35,7 @@ Future main(List args) async { hasEthereum: hasEthereum, hasNano: hasNano, hasBanano: hasBanano, + hasBitcoinCash: hasBitcoinCash, ); await generateWalletTypes( hasMonero: hasMonero, @@ -40,13 +44,13 @@ Future main(List args) async { hasEthereum: hasEthereum, hasNano: hasNano, hasBanano: hasBanano, + hasBitcoinCash: hasBitcoinCash, ); } Future generateBitcoin(bool hasImplementation) async { final outputFile = File(bitcoinOutputPath); const bitcoinCommonHeaders = """ -import 'package:cake_wallet/entities/unspent_transaction_output.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/transaction_priority.dart'; @@ -60,7 +64,6 @@ import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; -import 'package:cw_bitcoin/bitcoin_wallet.dart'; import 'package:cw_bitcoin/bitcoin_wallet_service.dart'; import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart'; import 'package:cw_bitcoin/bitcoin_amount_format.dart'; @@ -80,8 +83,8 @@ abstract class Bitcoin { Map getWalletKeys(Object wallet); List getTransactionPriorities(); List getLitecoinTransactionPriorities(); - TransactionPriority deserializeBitcoinTransactionPriority(int raw); - TransactionPriority deserializeLitecoinTransactionPriority(int raw); + TransactionPriority deserializeBitcoinTransactionPriority(int raw); + TransactionPriority deserializeLitecoinTransactionPriority(int raw); int getFeeRate(Object wallet, TransactionPriority priority); Future generateNewAddress(Object wallet); Object createBitcoinTransactionCredentials(List outputs, {required TransactionPriority priority, int? feeRate}); @@ -95,7 +98,7 @@ abstract class Bitcoin { int formatterStringDoubleToBitcoinAmount(String amount); String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate); - List getUnspents(Object wallet); + List getUnspents(Object wallet); void updateUnspents(Object wallet); WalletService createBitcoinWalletService(Box walletInfoSource, Box unspentCoinSource); WalletService createLitecoinWalletService(Box walletInfoSource, Box unspentCoinSource); @@ -126,7 +129,7 @@ abstract class Bitcoin { Future generateMonero(bool hasImplementation) async { final outputFile = File(moneroOutputPath); const moneroCommonHeaders = """ -import 'package:cake_wallet/entities/unspent_transaction_output.dart'; +import 'package:cw_core/unspent_transaction_output.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_monero/monero_unspent.dart'; import 'package:mobx/mobx.dart'; @@ -521,6 +524,7 @@ abstract class Ethereum { String getPrivateKey(WalletBase wallet); String getPublicKey(WalletBase wallet); TransactionPriority getDefaultTransactionPriority(); + TransactionPriority getEthereumTransactionPrioritySlow(); List getTransactionPriorities(); TransactionPriority deserializeEthereumTransactionPriority(int raw); @@ -568,6 +572,67 @@ abstract class Ethereum { await outputFile.writeAsString(output); } +Future generateBitcoinCash(bool hasImplementation) async { + final outputFile = File(bitcoinCashOutputPath); + const bitcoinCashCommonHeaders = """ +import 'dart:typed_data'; + +import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/wallet_credentials.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_service.dart'; +import 'package:hive/hive.dart'; +"""; + const bitcoinCashCWHeaders = """ +import 'package:cw_bitcoin_cash/cw_bitcoin_cash.dart'; +"""; + const bitcoinCashCwPart = "part 'cw_bitcoin_cash.dart';"; + const bitcoinCashContent = """ +abstract class BitcoinCash { + String getMnemonic(int? strength); + + Uint8List getSeedFromMnemonic(String seed); + + String getCashAddrFormat(String address); + + WalletService createBitcoinCashWalletService( + Box walletInfoSource, Box unspentCoinSource); + + WalletCredentials createBitcoinCashNewWalletCredentials( + {required String name, WalletInfo? walletInfo}); + + WalletCredentials createBitcoinCashRestoreWalletFromSeedCredentials( + {required String name, required String mnemonic, required String password}); + + TransactionPriority deserializeBitcoinCashTransactionPriority(int raw); + + TransactionPriority getDefaultTransactionPriority(); + + List getTransactionPriorities(); + + TransactionPriority getBitcoinCashTransactionPrioritySlow(); +} + """; + + const bitcoinCashEmptyDefinition = 'BitcoinCash? bitcoinCash;\n'; + const bitcoinCashCWDefinition = 'BitcoinCash? bitcoinCash = CWBitcoinCash();\n'; + + final output = '$bitcoinCashCommonHeaders\n' + + (hasImplementation ? '$bitcoinCashCWHeaders\n' : '\n') + + (hasImplementation ? '$bitcoinCashCwPart\n\n' : '\n') + + (hasImplementation ? bitcoinCashCWDefinition : bitcoinCashEmptyDefinition) + + '\n' + + bitcoinCashContent; + + if (outputFile.existsSync()) { + await outputFile.delete(); + } + + await outputFile.writeAsString(output); +} + Future generateNano(bool hasImplementation) async { final outputFile = File(nanoOutputPath); const nanoCommonHeaders = """ @@ -710,14 +775,14 @@ abstract class NanoUtil { await outputFile.writeAsString(output); } -Future generatePubspec({ - required bool hasMonero, - required bool hasBitcoin, - required bool hasHaven, - required bool hasEthereum, - required bool hasNano, - required bool hasBanano, -}) async { +Future generatePubspec( + {required bool hasMonero, + required bool hasBitcoin, + required bool hasHaven, + required bool hasEthereum, + required bool hasNano, + required bool hasBanano, + required bool hasBitcoinCash}) async { const cwCore = """ cw_core: path: ./cw_core @@ -742,6 +807,10 @@ Future generatePubspec({ cw_ethereum: path: ./cw_ethereum """; + const cwBitcoinCash = """ + cw_bitcoin_cash: + path: ./cw_bitcoin_cash + """; const cwNano = """ cw_nano: path: ./cw_nano @@ -776,6 +845,10 @@ Future generatePubspec({ output += '\n$cwBanano'; } + if (hasBitcoinCash) { + output += '\n$cwBitcoinCash'; + } + if (hasHaven && !hasMonero) { output += '\n$cwSharedExternal\n$cwHaven'; } else if (hasHaven) { @@ -794,14 +867,14 @@ Future generatePubspec({ await outputFile.writeAsString(outputContent); } -Future generateWalletTypes({ - required bool hasMonero, - required bool hasBitcoin, - required bool hasHaven, - required bool hasEthereum, - required bool hasNano, - required bool hasBanano, -}) async { +Future generateWalletTypes( + {required bool hasMonero, + required bool hasBitcoin, + required bool hasHaven, + required bool hasEthereum, + required bool hasNano, + required bool hasBanano, + required bool hasBitcoinCash}) async { final walletTypesFile = File(walletTypesPath); if (walletTypesFile.existsSync()) { @@ -828,6 +901,10 @@ Future generateWalletTypes({ outputContent += '\tWalletType.litecoin,\n'; } + if (hasBitcoinCash) { + outputContent += '\tWalletType.bitcoinCash,\n'; + } + if (hasNano) { outputContent += '\tWalletType.nano,\n'; } From 426ac99e34334e25c29c25325b74fa21ef1a4c2e Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Fri, 13 Oct 2023 14:49:00 +0300 Subject: [PATCH 008/241] Generic Fixes (#1122) * Fix Hive issue * Disable RobinHood for Nano * Validate context is still mounted [skip ci] * Disable Exolix for new exchanges Remove duplicate ethereum case * add nano/banano to manifest/info.plist * fix qr code issues for nano * Add Nano-wallet to restore form qr Add iOS keychain accessibility config * support app links for ethereum and nano [skip ci] * catch exceptions from gas price and estimated gas * Add bitcoin cash to app links Fix restore from QR for bitcoin cash * Fixate bottom buttons for create/restore wallet in wallet list page --------- Co-authored-by: fosse --- android/app/src/main/AndroidManifestBase.xml | 9 + cw_ethereum/lib/ethereum_client.dart | 16 +- ios/Runner/InfoBase.plist | 60 ++++ lib/entities/main_actions.dart | 4 +- lib/main.dart | 11 +- .../screens/dashboard/edit_token_page.dart | 4 +- .../exchange_trade/exchange_trade_page.dart | 8 +- .../screens/wallet_list/wallet_list_page.dart | 322 +++++++++--------- lib/utils/exception_handler.dart | 2 +- lib/utils/feature_flag.dart | 1 + lib/utils/payment_request.dart | 10 +- .../dashboard/transaction_list_item.dart | 7 - .../exchange/exchange_view_model.dart | 3 +- .../restore/wallet_restore_from_qr_code.dart | 4 +- lib/view_model/wallet_keys_view_model.dart | 2 +- 15 files changed, 275 insertions(+), 188 deletions(-) diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index f22ba9c4f..77a555db8 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -52,6 +52,15 @@ + + + + + + + + + getGasUnitPrice() async { - final gasPrice = await _client!.getGasPrice(); - return gasPrice.getInWei.toInt(); + try { + final gasPrice = await _client!.getGasPrice(); + return gasPrice.getInWei.toInt(); + } catch (_) { + return 0; + } } Future getEstimatedGas() async { - final estimatedGas = await _client!.estimateGas(); - return estimatedGas.toInt(); + try { + final estimatedGas = await _client!.estimateGas(); + return estimatedGas.toInt(); + } catch (_) { + return 0; + } } Future signTransaction({ diff --git a/ios/Runner/InfoBase.plist b/ios/Runner/InfoBase.plist index e4d07c717..6cea7a730 100644 --- a/ios/Runner/InfoBase.plist +++ b/ios/Runner/InfoBase.plist @@ -100,6 +100,66 @@ litecoin-wallet + + CFBundleTypeRole + Editor + CFBundleURLName + ethereum + CFBundleURLSchemes + + ethereum + + + + CFBundleTypeRole + Viewer + CFBundleURLName + ethereum-wallet + CFBundleURLSchemes + + ethereum-wallet + + + + CFBundleTypeRole + Editor + CFBundleURLName + nano + CFBundleURLSchemes + + nano + + + + CFBundleTypeRole + Viewer + CFBundleURLName + nano-wallet + CFBundleURLSchemes + + nano-wallet + + + + CFBundleTypeRole + Editor + CFBundleURLName + bitcoincash + CFBundleURLSchemes + + bitcoincash + + + + CFBundleTypeRole + Viewer + CFBundleURLName + bitcoincash-wallet + CFBundleURLSchemes + + bitcoincash-wallet + + CFBundleVersion $(CURRENT_PROJECT_VERSION) diff --git a/lib/entities/main_actions.dart b/lib/entities/main_actions.dart index d2c67ef95..46865cbcc 100644 --- a/lib/entities/main_actions.dart +++ b/lib/entities/main_actions.dart @@ -53,8 +53,6 @@ class MainActions { case WalletType.litecoin: case WalletType.ethereum: case WalletType.bitcoinCash: - case WalletType.nano: - case WalletType.banano: switch (defaultBuyProvider) { case BuyProviderType.AskEachTime: Navigator.pushNamed(context, Routes.buy); @@ -67,6 +65,8 @@ class MainActions { break; } break; + case WalletType.nano: + case WalletType.banano: case WalletType.monero: await getIt.get().launchProvider(context); break; diff --git a/lib/main.dart b/lib/main.dart index 2d76196c3..98ba1e195 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -97,10 +97,10 @@ Future initializeAppConfigs() async { CakeHive.registerAdapter(WalletInfoAdapter()); } - if (!Hive.isAdapterRegistered(DERIVATION_TYPE_TYPE_ID)) { + if (!CakeHive.isAdapterRegistered(DERIVATION_TYPE_TYPE_ID)) { CakeHive.registerAdapter(DerivationTypeAdapter()); } - + if (!CakeHive.isAdapterRegistered(WALLET_TYPE_TYPE_ID)) { CakeHive.registerAdapter(WalletTypeAdapter()); } @@ -125,14 +125,17 @@ Future initializeAppConfigs() async { CakeHive.registerAdapter(AnonpayInvoiceInfoAdapter()); } - final secureStorage = FlutterSecureStorage(); + final secureStorage = FlutterSecureStorage( + iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock), + ); final transactionDescriptionsBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: TransactionDescription.boxKey); final tradesBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Trade.boxKey); final ordersBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Order.boxKey); final contacts = await CakeHive.openBox(Contact.boxName); final nodes = await CakeHive.openBox(Node.boxName); - final powNodes = await CakeHive.openBox(Node.boxName + "pow");// must be different from Node.boxName + final powNodes = + await CakeHive.openBox(Node.boxName + "pow"); // must be different from Node.boxName final transactionDescriptions = await CakeHive.openBox( TransactionDescription.boxName, encryptionKey: transactionDescriptionsBoxKey); diff --git a/lib/src/screens/dashboard/edit_token_page.dart b/lib/src/screens/dashboard/edit_token_page.dart index 50bcb24e1..df6d3bd09 100644 --- a/lib/src/screens/dashboard/edit_token_page.dart +++ b/lib/src/screens/dashboard/edit_token_page.dart @@ -194,7 +194,9 @@ class _EditTokenPageBodyState extends State { contractAddress: _contractAddressController.text, decimal: int.parse(_tokenDecimalController.text), )); - Navigator.pop(context); + if (context.mounted) { + Navigator.pop(context); + } } }, text: S.of(context).save, diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index dbf6676a1..22606c21e 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -5,7 +5,6 @@ import 'package:cake_wallet/utils/request_review_handler.dart'; import 'package:mobx/mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/core/execution_state.dart'; @@ -26,16 +25,15 @@ import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; void showInformation( ExchangeTradeViewModel exchangeTradeViewModel, BuildContext context) { - final fetchingLabel = S.current.fetching; final trade = exchangeTradeViewModel.trade; final walletName = exchangeTradeViewModel.wallet.name; final information = exchangeTradeViewModel.isSendable ? S.current.exchange_result_confirm( - trade.amount ?? fetchingLabel, trade.from.toString(), walletName) + + trade.amount, trade.from.toString(), walletName) + exchangeTradeViewModel.extraInfo : S.current.exchange_result_description( - trade.amount ?? fetchingLabel, trade.from.toString()) + + trade.amount, trade.from.toString()) + exchangeTradeViewModel.extraInfo; showPopUp( @@ -177,7 +175,7 @@ class ExchangeTradeState extends State { ), itemBuilder: (context, index) { final item = widget.exchangeTradeViewModel.items[index]; - final value = item.data ?? fetchingLabel; + final value = item.data; final content = ListRow( title: item.title, diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index 11b394460..cce4a2581 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -13,7 +13,6 @@ import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; @@ -65,169 +64,178 @@ class WalletListBodyState extends State { return Container( padding: EdgeInsets.only(top: 16), - child: ScrollableWithBottomSection( - contentPadding: EdgeInsets.only(bottom: 20), - content: Container( - child: Observer( - builder: (_) => ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - separatorBuilder: (_, index) => - Divider(color: Theme.of(context).colorScheme.background, height: 32), - itemCount: widget.walletListViewModel.wallets.length, - itemBuilder: (__, index) { - final wallet = widget.walletListViewModel.wallets[index]; - final currentColor = wallet.isCurrent - ? Theme.of(context) - .extension()! - .createNewWalletButtonBackgroundColor - : Theme.of(context).colorScheme.background; - final row = GestureDetector( - onTap: () => wallet.isCurrent ? null : _loadWallet(wallet), - child: Container( - height: tileHeight, - width: double.infinity, - child: Row( - children: [ - Container( - height: tileHeight, - width: 4, - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - topRight: Radius.circular(4), bottomRight: Radius.circular(4)), - color: currentColor), - ), - Expanded( - child: Container( - height: tileHeight, - padding: EdgeInsets.only(left: 20, right: 20), - color: Theme.of(context).colorScheme.background, - alignment: Alignment.centerLeft, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - wallet.isEnabled ? _imageFor(type: wallet.type) : nonWalletTypeIcon, - SizedBox(width: 10), - Flexible( - child: Text( - wallet.name, - maxLines: null, - softWrap: true, - style: TextStyle( - fontSize: 22, - fontWeight: FontWeight.w500, - color: - Theme.of(context).extension()!.titleColor, - ), - ), - ), - ], + child: Column( + children: [ + Expanded( + child: Container( + child: Observer( + builder: (_) => ListView.separated( + physics: const BouncingScrollPhysics(), + separatorBuilder: (_, index) => + Divider(color: Theme.of(context).colorScheme.background, height: 32), + itemCount: widget.walletListViewModel.wallets.length, + itemBuilder: (__, index) { + final wallet = widget.walletListViewModel.wallets[index]; + final currentColor = wallet.isCurrent + ? Theme.of(context) + .extension()! + .createNewWalletButtonBackgroundColor + : Theme.of(context).colorScheme.background; + final row = GestureDetector( + onTap: () => wallet.isCurrent ? null : _loadWallet(wallet), + child: Container( + height: tileHeight, + width: double.infinity, + child: Row( + children: [ + Container( + height: tileHeight, + width: 4, + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topRight: Radius.circular(4), + bottomRight: Radius.circular(4)), + color: currentColor), ), - ), - ), - ], - ), - ), - ); - - return wallet.isCurrent - ? row - : Row( - children: [ - Expanded(child: row), - GestureDetector( - onTap: () => Navigator.of(context).pushNamed(Routes.walletEdit, - arguments: [widget.walletListViewModel, wallet]), - child: Container( - padding: EdgeInsets.only(right: 20), - child: Center( - child: Container( - height: 40, - width: 44, - padding: EdgeInsets.all(10), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Theme.of(context) - .extension()! - .iconsBackgroundColor, - ), - child: Icon( - Icons.edit, - size: 14, - color: - Theme.of(context).extension()!.iconsColor, - ), + Expanded( + child: Container( + height: tileHeight, + padding: EdgeInsets.only(left: 20, right: 20), + color: Theme.of(context).colorScheme.background, + alignment: Alignment.centerLeft, + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + wallet.isEnabled + ? _imageFor(type: wallet.type) + : nonWalletTypeIcon, + SizedBox(width: 10), + Flexible( + child: Text( + wallet.name, + maxLines: null, + softWrap: true, + style: TextStyle( + fontSize: 22, + fontWeight: FontWeight.w500, + color: Theme.of(context) + .extension()! + .titleColor, + ), + ), + ), + ], ), ), ), - ), - ], - ); - }, + ], + ), + ), + ); + + return wallet.isCurrent + ? row + : Row( + children: [ + Expanded(child: row), + GestureDetector( + onTap: () => Navigator.of(context).pushNamed(Routes.walletEdit, + arguments: [widget.walletListViewModel, wallet]), + child: Container( + padding: EdgeInsets.only(right: 20), + child: Center( + child: Container( + height: 40, + width: 44, + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Theme.of(context) + .extension()! + .iconsBackgroundColor, + ), + child: Icon( + Icons.edit, + size: 14, + color: Theme.of(context) + .extension()! + .iconsColor, + ), + ), + ), + ), + ), + ], + ); + }, + ), + ), ), ), - ), - bottomSectionPadding: EdgeInsets.only(bottom: 24, right: 24, left: 24), - bottomSection: Column( - children: [ - PrimaryImageButton( - onPressed: () { - //TODO(David): Find a way to optimize this - if (isSingleCoin) { - if (widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets) { - widget.authService.authenticateAction( - context, - route: Routes.newWallet, - arguments: widget.walletListViewModel.currentWalletType, - conditionToDetermineIfToUse2FA: - widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets, - ); - } else { - Navigator.of(context).pushNamed( - Routes.newWallet, - arguments: widget.walletListViewModel.currentWalletType, - ); - } - } else { - if (widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets) { - widget.authService.authenticateAction( - context, - route: Routes.newWalletType, - conditionToDetermineIfToUse2FA: - widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets, - ); - } else { - Navigator.of(context).pushNamed(Routes.newWalletType); - } - } - }, - image: newWalletImage, - text: S.of(context).wallet_list_create_new_wallet, - color: Theme.of(context).primaryColor, - textColor: Colors.white, + Padding( + padding: const EdgeInsets.all(24), + child: Column( + children: [ + PrimaryImageButton( + onPressed: () { + //TODO(David): Find a way to optimize this + if (isSingleCoin) { + if (widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets) { + widget.authService.authenticateAction( + context, + route: Routes.newWallet, + arguments: widget.walletListViewModel.currentWalletType, + conditionToDetermineIfToUse2FA: + widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets, + ); + } else { + Navigator.of(context).pushNamed( + Routes.newWallet, + arguments: widget.walletListViewModel.currentWalletType, + ); + } + } else { + if (widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets) { + widget.authService.authenticateAction( + context, + route: Routes.newWalletType, + conditionToDetermineIfToUse2FA: + widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets, + ); + } else { + Navigator.of(context).pushNamed(Routes.newWalletType); + } + } + }, + image: newWalletImage, + text: S.of(context).wallet_list_create_new_wallet, + color: Theme.of(context).primaryColor, + textColor: Colors.white, + ), + SizedBox(height: 10.0), + PrimaryImageButton( + 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( - 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/utils/exception_handler.dart b/lib/utils/exception_handler.dart index b9c659872..bea43a6c6 100644 --- a/lib/utils/exception_handler.dart +++ b/lib/utils/exception_handler.dart @@ -161,7 +161,7 @@ class ExceptionHandler { "Handshake error in client", "Error while launching http", "OS Error: Network is unreachable", - "ClientException: Write failed, uri=https:", + "ClientException: Write failed, uri=http", ]; static Future _addDeviceInfo(File file) async { diff --git a/lib/utils/feature_flag.dart b/lib/utils/feature_flag.dart index 2b0d5a2b9..628023f85 100644 --- a/lib/utils/feature_flag.dart +++ b/lib/utils/feature_flag.dart @@ -1,3 +1,4 @@ class FeatureFlag { static const bool isCakePayEnabled = false; + static const bool isExolixEnabled = false; } \ No newline at end of file diff --git a/lib/utils/payment_request.dart b/lib/utils/payment_request.dart index 6f82c3b94..00093b413 100644 --- a/lib/utils/payment_request.dart +++ b/lib/utils/payment_request.dart @@ -17,10 +17,12 @@ class PaymentRequest { } if (nano != null) { - if (address.contains("nano")) { - amount = nanoUtil!.getRawAsUsableString(amount, nanoUtil!.rawPerNano); - } else if (address.contains("ban")) { - amount = nanoUtil!.getRawAsUsableString(amount, nanoUtil!.rawPerBanano); + if (amount.isNotEmpty) { + if (address.contains("nano")) { + amount = nanoUtil!.getRawAsUsableString(amount, nanoUtil!.rawPerNano); + } else if (address.contains("ban")) { + amount = nanoUtil!.getRawAsUsableString(amount, nanoUtil!.rawPerBanano); + } } } diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart index 4e1c1aae0..fd7971001 100644 --- a/lib/view_model/dashboard/transaction_list_item.dart +++ b/lib/view_model/dashboard/transaction_list_item.dart @@ -97,13 +97,6 @@ class TransactionListItem extends ActionListItem with Keyable { nano!.getTransactionAmountRaw(transaction).toString(), nanoUtil!.rawPerNano)), price: price); break; - case WalletType.ethereum: - final asset = ethereum!.assetOfTransaction(balanceViewModel.wallet, transaction); - final price = balanceViewModel.fiatConvertationStore.prices[asset]; - amount = calculateFiatAmountRaw( - cryptoAmount: ethereum!.formatterEthereumAmountToDouble(transaction: transaction), - price: price); - break; default: break; } diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 7bc7927df..f7db98245 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -16,6 +16,7 @@ import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dar import 'package:cake_wallet/exchange/simpleswap/simpleswap_request.dart'; import 'package:cake_wallet/exchange/trocador/trocador_exchange_provider.dart'; import 'package:cake_wallet/exchange/trocador/trocador_request.dart'; +import 'package:cake_wallet/utils/feature_flag.dart'; import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cake_wallet/store/app_store.dart'; @@ -154,7 +155,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with SideShiftExchangeProvider(), SimpleSwapExchangeProvider(), TrocadorExchangeProvider(useTorOnly: _useTorOnly), - ExolixExchangeProvider(), + if (FeatureFlag.isExolixEnabled) ExolixExchangeProvider(), ]; @observable diff --git a/lib/view_model/restore/wallet_restore_from_qr_code.dart b/lib/view_model/restore/wallet_restore_from_qr_code.dart index dd138b66c..bc100f9fe 100644 --- a/lib/view_model/restore/wallet_restore_from_qr_code.dart +++ b/lib/view_model/restore/wallet_restore_from_qr_code.dart @@ -73,10 +73,12 @@ class WalletRestoreFromQRCode { case 'litecoin-wallet': return WalletType.litecoin; case 'bitcoincash': - case 'bitcoinCash-wallet': + case 'bitcoincash-wallet': return WalletType.bitcoinCash; + case 'ethereum': case 'ethereum-wallet': return WalletType.ethereum; + case 'nano': case 'nano-wallet': return WalletType.nano; default: diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart index e106126bc..81f521d27 100644 --- a/lib/view_model/wallet_keys_view_model.dart +++ b/lib/view_model/wallet_keys_view_model.dart @@ -148,7 +148,7 @@ abstract class WalletKeysViewModelBase with Store { case WalletType.ethereum: return 'ethereum-wallet'; case WalletType.bitcoinCash: - return 'bitcoinCash-wallet'; + return 'bitcoincash-wallet'; case WalletType.nano: return 'nano-wallet'; case WalletType.banano: From 69a77d4f71a4d4c0615b679779aa146638f4d7ac Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Mon, 16 Oct 2023 16:44:20 +0300 Subject: [PATCH 009/241] New versions 4.10.1 and 1.7.1 (#1127) --- assets/text/Release_Notes.txt | 6 ++---- ios/Podfile.lock | 2 +- scripts/android/app_env.sh | 8 ++++---- scripts/ios/app_config.sh | 0 scripts/ios/app_env.sh | 8 ++++---- scripts/macos/app_env.sh | 4 ++-- tool/configure.dart | 6 ++++-- 7 files changed, 17 insertions(+), 17 deletions(-) mode change 100644 => 100755 scripts/ios/app_config.sh diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 50c88833d..795ec3427 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,5 +1,3 @@ -Add Nano wallet -Add WalletConnect to connect your ETH wallet with your favorite dApp -Support getting Addresses from ENS and Mastodon +Add BitcoinCash (BCH) Bug fixes -Minor enhancements \ No newline at end of file +Accessibility enhancements \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 6f441c587..acc3b8824 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -272,7 +272,7 @@ SPEC CHECKSUMS: DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 file_picker: ce3938a0df3cc1ef404671531facef740d03f920 Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 - flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721 + flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83 flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 771c1f89a..356cf03cd 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.7.0" -MONERO_COM_BUILD_NUMBER=61 +MONERO_COM_VERSION="1.7.1" +MONERO_COM_BUILD_NUMBER=62 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.10.0" -CAKEWALLET_BUILD_NUMBER=175 +CAKEWALLET_VERSION="4.10.1" +CAKEWALLET_BUILD_NUMBER=176 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_config.sh b/scripts/ios/app_config.sh old mode 100644 new mode 100755 diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index aa3116418..ae5a90bc3 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.7.0" -MONERO_COM_BUILD_NUMBER=59 +MONERO_COM_VERSION="1.7.1" +MONERO_COM_BUILD_NUMBER=60 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.10.0" -CAKEWALLET_BUILD_NUMBER=189 +CAKEWALLET_VERSION="4.10.1" +CAKEWALLET_BUILD_NUMBER=190 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index d649d752d..37c2b3441 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -15,8 +15,8 @@ if [ -n "$1" ]; then fi CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.3.0" -CAKEWALLET_BUILD_NUMBER=36 +CAKEWALLET_VERSION="1.3.1" +CAKEWALLET_BUILD_NUMBER=37 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then diff --git a/tool/configure.dart b/tool/configure.dart index 534aeef57..90e275994 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -51,6 +51,7 @@ Future main(List args) async { Future generateBitcoin(bool hasImplementation) async { final outputFile = File(bitcoinOutputPath); const bitcoinCommonHeaders = """ +import 'package:cw_core/unspent_transaction_output.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/transaction_priority.dart'; @@ -98,7 +99,7 @@ abstract class Bitcoin { int formatterStringDoubleToBitcoinAmount(String amount); String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate); - List getUnspents(Object wallet); + List getUnspents(Object wallet); void updateUnspents(Object wallet); WalletService createBitcoinWalletService(Box walletInfoSource, Box unspentCoinSource); WalletService createLitecoinWalletService(Box walletInfoSource, Box unspentCoinSource); @@ -577,7 +578,7 @@ Future generateBitcoinCash(bool hasImplementation) async { const bitcoinCashCommonHeaders = """ import 'dart:typed_data'; -import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; +import 'package:cw_core/unspent_transaction_output.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_credentials.dart'; @@ -587,6 +588,7 @@ import 'package:hive/hive.dart'; """; const bitcoinCashCWHeaders = """ import 'package:cw_bitcoin_cash/cw_bitcoin_cash.dart'; +import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; """; const bitcoinCashCwPart = "part 'cw_bitcoin_cash.dart';"; const bitcoinCashContent = """ From 98a9edc656b98ea4373a7265c9a973780b903c87 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Tue, 17 Oct 2023 11:59:41 -0400 Subject: [PATCH 010/241] fix nano sending, update restore page wording, and other minor fixes (#1130) * fix nano sending, update restore page wording, and other minor fixes * fix bch address parsing * minor code enhancement [skip ci] * Register the main secure storage as the long lived instance of secure storage throughout the app session --------- Co-authored-by: Serhii Co-authored-by: OmarHatem --- .../lib/nano_wallet_creation_credentials.dart | 13 +++++---- lib/di.dart | 3 +- lib/entities/parse_address_from_domain.dart | 8 ++++- lib/main.dart | 5 ++-- lib/nano/cw_nano.dart | 18 ++++++++++-- .../wallet_restore_from_keys_form.dart | 9 +++++- lib/src/widgets/seed_widget.dart | 3 +- lib/view_model/send/send_view_model.dart | 29 ++++++++----------- res/values/strings_ar.arb | 6 ++-- res/values/strings_bg.arb | 6 ++-- res/values/strings_cs.arb | 6 ++-- res/values/strings_de.arb | 6 ++-- res/values/strings_en.arb | 6 ++-- res/values/strings_es.arb | 6 ++-- res/values/strings_fr.arb | 6 ++-- res/values/strings_ha.arb | 6 ++-- res/values/strings_hi.arb | 6 ++-- res/values/strings_hr.arb | 6 ++-- res/values/strings_id.arb | 6 ++-- res/values/strings_it.arb | 6 ++-- res/values/strings_ja.arb | 6 ++-- res/values/strings_ko.arb | 6 ++-- res/values/strings_my.arb | 6 ++-- res/values/strings_nl.arb | 6 ++-- res/values/strings_pl.arb | 6 ++-- res/values/strings_pt.arb | 6 ++-- res/values/strings_ru.arb | 6 ++-- res/values/strings_th.arb | 6 ++-- res/values/strings_tl.arb | 6 ++-- res/values/strings_tr.arb | 6 ++-- res/values/strings_uk.arb | 6 ++-- res/values/strings_ur.arb | 6 ++-- res/values/strings_yo.arb | 6 ++-- res/values/strings_zh.arb | 6 ++-- 34 files changed, 160 insertions(+), 84 deletions(-) diff --git a/cw_nano/lib/nano_wallet_creation_credentials.dart b/cw_nano/lib/nano_wallet_creation_credentials.dart index 84531e24a..3616fcf44 100644 --- a/cw_nano/lib/nano_wallet_creation_credentials.dart +++ b/cw_nano/lib/nano_wallet_creation_credentials.dart @@ -10,13 +10,11 @@ class NanoRestoreWalletFromSeedCredentials extends WalletCredentials { NanoRestoreWalletFromSeedCredentials({ required String name, required this.mnemonic, - int height = 0, String? password, DerivationType? derivationType, }) : super( name: name, password: password, - height: height, derivationType: derivationType, ); @@ -33,9 +31,12 @@ class NanoRestoreWalletFromKeysCredentials extends WalletCredentials { required String name, required String password, required this.seedKey, - this.derivationType, - }) : super(name: name, password: password); + DerivationType? derivationType, + }) : super( + name: name, + password: password, + derivationType: derivationType, + ); final String seedKey; - final DerivationType? derivationType; -} \ No newline at end of file +} diff --git a/lib/di.dart b/lib/di.dart index 1576c378b..cfe2cfdc5 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -248,6 +248,7 @@ Future setup({ required Box ordersSource, required Box unspentCoinsInfoSource, required Box anonpayInvoiceInfoSource, + required FlutterSecureStorage secureStorage, }) async { _walletInfoSource = walletInfoSource; _nodeSource = nodeSource; @@ -289,7 +290,7 @@ Future setup({ getIt.registerFactory>(() => _nodeSource); getIt.registerFactory>(() => _powNodeSource, instanceName: Node.boxName + "pow"); - getIt.registerSingleton(FlutterSecureStorage()); + getIt.registerSingleton(secureStorage); getIt.registerSingleton(AuthenticationStore()); getIt.registerSingleton(WalletListStore()); getIt.registerSingleton(NodeListStoreBase.instance); diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart index 14bfe2f7f..9d274fbcc 100644 --- a/lib/entities/parse_address_from_domain.dart +++ b/lib/entities/parse_address_from_domain.dart @@ -46,7 +46,13 @@ class AddressResolver { } final match = RegExp(addressPattern).firstMatch(raw); - return match?.group(0)?.replaceAll(RegExp('[^0-9a-zA-Z]'), ''); + return match?.group(0)?.replaceAllMapped(RegExp('[^0-9a-zA-Z]|bitcoincash:|nano_'), (Match match) { + String group = match.group(0)!; + if (group.startsWith('bitcoincash:') || group.startsWith('nano_')) { + return group; + } + return ''; + }); } Future resolve(String text, String ticker) async { diff --git a/lib/main.dart b/lib/main.dart index 98ba1e195..d5b0e2f81 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -163,7 +163,7 @@ Future initializeAppConfigs() async { secureStorage: secureStorage, anonpayInvoiceInfo: anonpayInvoiceInfo, initialMigrationVersion: 23); - } +} Future initialSetup( {required SharedPreferences sharedPreferences, @@ -202,7 +202,8 @@ Future initialSetup( transactionDescriptionBox: transactionDescriptions, ordersSource: ordersSource, anonpayInvoiceInfoSource: anonpayInvoiceInfo, - unspentCoinsInfoSource: unspentCoinsInfoSource); + unspentCoinsInfoSource: unspentCoinsInfoSource, + secureStorage: secureStorage); await bootstrap(navigatorKey); monero?.onStartup(); } diff --git a/lib/nano/cw_nano.dart b/lib/nano/cw_nano.dart index cd0f0ca8a..778b2584a 100644 --- a/lib/nano/cw_nano.dart +++ b/lib/nano/cw_nano.dart @@ -406,6 +406,13 @@ class CWNanoUtil extends NanoUtil { late String publicAddress; if (seedKey != null) { + if (seedKey.length == 64) { + try { + mnemonic = nanoUtil!.seedToMnemonic(seedKey); + } catch (e) { + print("not a valid 'nano' seed key"); + } + } if (derivationType == DerivationType.bip39) { publicAddress = await hdSeedToAddress(seedKey, 0); } else if (derivationType == DerivationType.nano) { @@ -429,7 +436,8 @@ class CWNanoUtil extends NanoUtil { AccountInfoResponse? accountInfo = await nanoClient.getAccountInfo(publicAddress); if (accountInfo == null) { - accountInfo = AccountInfoResponse(frontier: "", balance: "0", representative: "", confirmationHeight: 0); + accountInfo = AccountInfoResponse( + frontier: "", balance: "0", representative: "", confirmationHeight: 0); } accountInfo.address = publicAddress; return accountInfo; @@ -449,7 +457,11 @@ class CWNanoUtil extends NanoUtil { if (seedKey?.length == 128) { return [DerivationType.bip39]; } else if (seedKey?.length == 64) { - return [DerivationType.nano]; + try { + mnemonic = nanoUtil!.seedToMnemonic(seedKey!); + } catch (e) { + print("not a valid 'nano' seed key"); + } } late String publicAddressStandard; @@ -503,7 +515,7 @@ class CWNanoUtil extends NanoUtil { // we don't know for sure: return [DerivationType.nano, DerivationType.bip39]; } catch (e) { - return [DerivationType.unknown]; + return [DerivationType.nano, DerivationType.bip39]; } } } diff --git a/lib/src/screens/restore/wallet_restore_from_keys_form.dart b/lib/src/screens/restore/wallet_restore_from_keys_form.dart index e42488183..2c0dfa53f 100644 --- a/lib/src/screens/restore/wallet_restore_from_keys_form.dart +++ b/lib/src/screens/restore/wallet_restore_from_keys_form.dart @@ -124,9 +124,16 @@ class WalletRestoreFromKeysFromState extends State { Widget _restoreFromKeysFormFields() { if (widget.displayPrivateKeyField) { + // the term "private key" isn't actually what we're accepting here, and it's confusing to + // users of the nano community, what this form actually accepts (when importing for nano) is a nano seed in it's hex form, referred to in code as a "seed key" + // so we should change the placeholder text to reflect this + // supporting actual nano private keys is possible, but it's super niche in the nano community / they're not really used + + bool nanoBased = widget.walletRestoreViewModel.type == WalletType.nano || + widget.walletRestoreViewModel.type == WalletType.banano; return AddressTextField( controller: privateKeyController, - placeholder: S.of(context).private_key, + placeholder: nanoBased ? S.of(context).seed_key : S.of(context).private_key, options: [AddressTextFieldOption.paste], buttonColor: Theme.of(context).hintColor, onPushPasteButton: (_) { diff --git a/lib/src/widgets/seed_widget.dart b/lib/src/widgets/seed_widget.dart index 7015e0acf..bf9a85b32 100644 --- a/lib/src/widgets/seed_widget.dart +++ b/lib/src/widgets/seed_widget.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/src/widgets/validable_annotated_editable_text.dart'; @@ -75,7 +76,7 @@ class SeedWidgetState extends State { Positioned( top: 10, left: 0, - child: Text('Enter your seed', + child: Text(S.of(context).enter_seed_phrase, style: TextStyle( fontSize: 16.0, color: Theme.of(context).hintColor))), Padding( diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 719298675..be822aff3 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -185,15 +185,15 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor @computed bool get hasCoinControl => wallet.type == WalletType.bitcoin || - wallet.type == WalletType.litecoin || - wallet.type == WalletType.monero || - wallet.type == WalletType.bitcoinCash; + wallet.type == WalletType.litecoin || + wallet.type == WalletType.monero || + wallet.type == WalletType.bitcoinCash; @computed bool get isElectrumWallet => wallet.type == WalletType.bitcoin || - wallet.type == WalletType.litecoin || - wallet.type == WalletType.bitcoinCash; + wallet.type == WalletType.litecoin || + wallet.type == WalletType.bitcoinCash; @computed bool get hasFees => wallet.type != WalletType.nano && wallet.type != WalletType.banano; @@ -281,7 +281,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor List conditionsList = []; for (var output in outputs) { - final show = checkThroughChecksToDisplayTOTP(output.extractedAddress); conditionsList.add(show); } @@ -350,31 +349,27 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor Object _credentials() { final priority = _settingsStore.priority[wallet.type]; - if (priority == null) throw Exception('Priority is null for wallet type: ${wallet.type}'); + if (priority == null && wallet.type != WalletType.nano) { + throw Exception('Priority is null for wallet type: ${wallet.type}'); + } switch (wallet.type) { case WalletType.bitcoin: case WalletType.litecoin: case WalletType.bitcoinCash: - return bitcoin!.createBitcoinTransactionCredentials(outputs, priority: priority); + return bitcoin!.createBitcoinTransactionCredentials(outputs, priority: priority!); case WalletType.monero: return monero! - .createMoneroTransactionCreationCredentials(outputs: outputs, priority: priority); + .createMoneroTransactionCreationCredentials(outputs: outputs, priority: priority!); case WalletType.haven: return haven!.createHavenTransactionCreationCredentials( - outputs: outputs, priority: priority, assetType: selectedCryptoCurrency.title); + outputs: outputs, priority: priority!, assetType: selectedCryptoCurrency.title); case WalletType.ethereum: - final priority = _settingsStore.priority[wallet.type]; - - if (priority == null) { - throw Exception('Priority is null for wallet type: ${wallet.type}'); - } - return ethereum!.createEthereumTransactionCredentials(outputs, - priority: priority, currency: selectedCryptoCurrency); + priority: priority!, currency: selectedCryptoCurrency); case WalletType.nano: return nano!.createNanoTransactionCredentials(outputs); default: diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index a730a9dd8..fcb1b090c 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -717,5 +717,7 @@ "message": "ﺔﻟﺎﺳﺭ", "do_not_have_enough_gas_asset": "ليس لديك ما يكفي من ${currency} لإجراء معاملة وفقًا لشروط شبكة blockchain الحالية. أنت بحاجة إلى المزيد من ${currency} لدفع رسوم شبكة blockchain، حتى لو كنت ترسل أصلًا مختلفًا.", "totp_auth_url": "TOTP ﺔﻗﺩﺎﺼﻤﻟ URL ﻥﺍﻮﻨﻋ", - "awaitDAppProcessing": ".ﺔﺠﻟﺎﻌﻤﻟﺍ ﻦﻣ dApp ﻲﻬﺘﻨﻳ ﻰﺘﺣ ﺭﺎﻈﺘﻧﻻﺍ ﻰﺟﺮﻳ" -} + "awaitDAppProcessing": ".ﺔﺠﻟﺎﻌﻤﻟﺍ ﻦﻣ dApp ﻲﻬﺘﻨﻳ ﻰﺘﺣ ﺭﺎﻈﺘﻧﻻﺍ ﻰﺟﺮﻳ", + "seed_key": "مفتاح البذور", + "enter_seed_phrase": "أدخل عبارة البذور الخاصة بك" +} \ No newline at end of file diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 212f7f2a8..d85b30118 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -713,5 +713,7 @@ "message": "Съобщение", "do_not_have_enough_gas_asset": "Нямате достатъчно ${currency}, за да извършите транзакция с текущите условия на блокчейн мрежата. Имате нужда от повече ${currency}, за да платите таксите за блокчейн мрежа, дори ако изпращате различен актив.", "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Моля, изчакайте dApp да завърши обработката." -} + "awaitDAppProcessing": "Моля, изчакайте dApp да завърши обработката.", + "seed_key": "Ключ за семена", + "enter_seed_phrase": "Въведете вашата фраза за семена" +} \ No newline at end of file diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 3042cadfe..998f0b915 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -713,5 +713,7 @@ "message": "Zpráva", "do_not_have_enough_gas_asset": "Nemáte dostatek ${currency} k provedení transakce s aktuálními podmínkami blockchainové sítě. K placení poplatků za blockchainovou síť potřebujete více ${currency}, i když posíláte jiné aktivum.", "totp_auth_url": "URL AUTH TOTP", - "awaitDAppProcessing": "Počkejte, až dApp dokončí zpracování." -} + "awaitDAppProcessing": "Počkejte, až dApp dokončí zpracování.", + "seed_key": "Klíč semen", + "enter_seed_phrase": "Zadejte svou frázi semen" +} \ No newline at end of file diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 9971aff0e..82575200f 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -721,5 +721,7 @@ "message": "Nachricht", "do_not_have_enough_gas_asset": "Sie verfügen nicht über genügend ${currency}, um eine Transaktion unter den aktuellen Bedingungen des Blockchain-Netzwerks durchzuführen. Sie benötigen mehr ${currency}, um die Gebühren für das Blockchain-Netzwerk zu bezahlen, auch wenn Sie einen anderen Vermögenswert senden.", "totp_auth_url": "TOTP-Auth-URL", - "awaitDAppProcessing": "Bitte warten Sie, bis die dApp die Verarbeitung abgeschlossen hat." -} + "awaitDAppProcessing": "Bitte warten Sie, bis die dApp die Verarbeitung abgeschlossen hat.", + "seed_key": "Samenschlüssel", + "enter_seed_phrase": "Geben Sie Ihre Samenphrase ein" +} \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index b981c0177..f30d224c0 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -722,5 +722,7 @@ "message": "Message", "do_not_have_enough_gas_asset": "You do not have enough ${currency} to make a transaction with the current blockchain network conditions. You need more ${currency} to pay blockchain network fees, even if you are sending a different asset.", "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Kindly wait for the dApp to finish processing." -} + "awaitDAppProcessing": "Kindly wait for the dApp to finish processing.", + "seed_key": "Seed key", + "enter_seed_phrase": "Enter your seed phrase" +} \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 01bd3207e..049a83e40 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -721,5 +721,7 @@ "message": "Mensaje", "do_not_have_enough_gas_asset": "No tienes suficiente ${currency} para realizar una transacción con las condiciones actuales de la red blockchain. Necesita más ${currency} para pagar las tarifas de la red blockchain, incluso si envía un activo diferente.", "totp_auth_url": "URL de autenticación TOTP", - "awaitDAppProcessing": "Espere a que la dApp termine de procesarse." -} + "awaitDAppProcessing": "Espere a que la dApp termine de procesarse.", + "seed_key": "Llave de semilla", + "enter_seed_phrase": "Ingrese su frase de semillas" +} \ No newline at end of file diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index f171cbb68..e6516fb87 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -721,5 +721,7 @@ "message": "Message", "do_not_have_enough_gas_asset": "Vous n'avez pas assez de ${currency} pour effectuer une transaction avec les conditions actuelles du réseau blockchain. Vous avez besoin de plus de ${currency} pour payer les frais du réseau blockchain, même si vous envoyez un actif différent.", "totp_auth_url": "URL D'AUTORISATION TOTP", - "awaitDAppProcessing": "Veuillez attendre que le dApp termine le traitement." -} + "awaitDAppProcessing": "Veuillez attendre que le dApp termine le traitement.", + "seed_key": "Clé de graines", + "enter_seed_phrase": "Entrez votre phrase de semence" +} \ No newline at end of file diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 917cad8a9..7d8e8969c 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -699,5 +699,7 @@ "message": "Sako", "do_not_have_enough_gas_asset": "Ba ku da isassun ${currency} don yin ma'amala tare da yanayin cibiyar sadarwar blockchain na yanzu. Kuna buƙatar ƙarin ${currency} don biyan kuɗaɗen cibiyar sadarwar blockchain, koda kuwa kuna aika wata kadara daban.", "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Da fatan za a jira dApp ya gama aiki." -} + "awaitDAppProcessing": "Da fatan za a jira dApp ya gama aiki.", + "seed_key": "Maɓallin iri", + "enter_seed_phrase": "Shigar da Sert Sentarku" +} \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 104c871bf..4a9e6b284 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -721,5 +721,7 @@ "message": "संदेश", "do_not_have_enough_gas_asset": "वर्तमान ब्लॉकचेन नेटवर्क स्थितियों में लेनदेन करने के लिए आपके पास पर्याप्त ${currency} नहीं है। ब्लॉकचेन नेटवर्क शुल्क का भुगतान करने के लिए आपको अधिक ${currency} की आवश्यकता है, भले ही आप एक अलग संपत्ति भेज रहे हों।", "totp_auth_url": "TOTP प्रामाणिक यूआरएल", - "awaitDAppProcessing": "कृपया डीएपी की प्रोसेसिंग पूरी होने तक प्रतीक्षा करें।" -} + "awaitDAppProcessing": "कृपया डीएपी की प्रोसेसिंग पूरी होने तक प्रतीक्षा करें।", + "seed_key": "बीज कुंजी", + "enter_seed_phrase": "अपना बीज वाक्यांश दर्ज करें" +} \ No newline at end of file diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 93ab87319..17391a6d7 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -719,5 +719,7 @@ "message": "Poruka", "do_not_have_enough_gas_asset": "Nemate dovoljno ${currency} da izvršite transakciju s trenutačnim uvjetima blockchain mreže. Trebate više ${currency} da platite naknade za blockchain mrežu, čak i ako šaljete drugu imovinu.", "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Molimo pričekajte da dApp završi obradu." -} + "awaitDAppProcessing": "Molimo pričekajte da dApp završi obradu.", + "seed_key": "Sjemenski ključ", + "enter_seed_phrase": "Unesite svoju sjemensku frazu" +} \ No newline at end of file diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index f6b20c213..5330ec96c 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -709,5 +709,7 @@ "message": "Pesan", "do_not_have_enough_gas_asset": "Anda tidak memiliki cukup ${currency} untuk melakukan transaksi dengan kondisi jaringan blockchain saat ini. Anda memerlukan lebih banyak ${currency} untuk membayar biaya jaringan blockchain, meskipun Anda mengirimkan aset yang berbeda.", "totp_auth_url": "URL Otentikasi TOTP", - "awaitDAppProcessing": "Mohon tunggu hingga dApp menyelesaikan pemrosesan." -} + "awaitDAppProcessing": "Mohon tunggu hingga dApp menyelesaikan pemrosesan.", + "seed_key": "Kunci benih", + "enter_seed_phrase": "Masukkan frasa benih Anda" +} \ No newline at end of file diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 946deb91c..d0c5a1a87 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -721,5 +721,7 @@ "message": "Messaggio", "do_not_have_enough_gas_asset": "Non hai abbastanza ${currency} per effettuare una transazione con le attuali condizioni della rete blockchain. Hai bisogno di più ${currency} per pagare le commissioni della rete blockchain, anche se stai inviando una risorsa diversa.", "totp_auth_url": "URL DI AUT. TOTP", - "awaitDAppProcessing": "Attendi gentilmente che la dApp termini l'elaborazione." -} + "awaitDAppProcessing": "Attendi gentilmente che la dApp termini l'elaborazione.", + "seed_key": "Chiave di semi", + "enter_seed_phrase": "Inserisci la tua frase di semi" +} \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index f74f853d4..1d8012237 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -721,5 +721,7 @@ "message": "メッセージ", "do_not_have_enough_gas_asset": "現在のブロックチェーン ネットワークの状況では、トランザクションを行うのに十分な ${currency} がありません。別のアセットを送信する場合でも、ブロックチェーン ネットワーク料金を支払うにはさらに ${currency} が必要です。", "totp_auth_url": "TOTP認証URL", - "awaitDAppProcessing": "dAppの処理が完了するまでお待ちください。" -} + "awaitDAppProcessing": "dAppの処理が完了するまでお待ちください。", + "seed_key": "シードキー", + "enter_seed_phrase": "シードフレーズを入力してください" +} \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 5762822e1..df5d6f8ea 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -719,5 +719,7 @@ "message": "메시지", "do_not_have_enough_gas_asset": "현재 블록체인 네트워크 조건으로 거래를 하기에는 ${currency}이(가) 충분하지 않습니다. 다른 자산을 보내더라도 블록체인 네트워크 수수료를 지불하려면 ${currency}가 더 필요합니다.", "totp_auth_url": "TOTP 인증 URL", - "awaitDAppProcessing": "dApp이 처리를 마칠 때까지 기다려주세요." -} + "awaitDAppProcessing": "dApp이 처리를 마칠 때까지 기다려주세요.", + "seed_key": "시드 키", + "enter_seed_phrase": "시드 문구를 입력하십시오" +} \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 33ec70494..e2c4a55f9 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -719,5 +719,7 @@ "message": "မက်ဆေ့ချ်", "do_not_have_enough_gas_asset": "လက်ရှိ blockchain ကွန်ရက်အခြေအနေများနှင့် အရောင်းအဝယ်ပြုလုပ်ရန် သင့်တွင် ${currency} လုံလောက်မှုမရှိပါ။ သင်သည် မတူညီသော ပိုင်ဆိုင်မှုတစ်ခုကို ပေးပို့နေသော်လည်း blockchain ကွန်ရက်အခကြေးငွေကို ပေးဆောင်ရန် သင်သည် နောက်ထပ် ${currency} လိုအပ်ပါသည်။", "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "ကျေးဇူးပြု၍ dApp ကို စီမံလုပ်ဆောင်ခြင်း အပြီးသတ်ရန် စောင့်ပါ။" -} + "awaitDAppProcessing": "ကျေးဇူးပြု၍ dApp ကို စီမံလုပ်ဆောင်ခြင်း အပြီးသတ်ရန် စောင့်ပါ။", + "seed_key": "မျိုးစေ့သော့", + "enter_seed_phrase": "သင့်ရဲ့မျိုးစေ့စကားစုကိုရိုက်ထည့်ပါ" +} \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 767959855..fd95f5299 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -721,5 +721,7 @@ "message": "Bericht", "do_not_have_enough_gas_asset": "U heeft niet genoeg ${currency} om een transactie uit te voeren met de huidige blockchain-netwerkomstandigheden. U heeft meer ${currency} nodig om blockchain-netwerkkosten te betalen, zelfs als u een ander item verzendt.", "totp_auth_url": "TOTP AUTH-URL", - "awaitDAppProcessing": "Wacht tot de dApp klaar is met verwerken." -} + "awaitDAppProcessing": "Wacht tot de dApp klaar is met verwerken.", + "seed_key": "Zaadsleutel", + "enter_seed_phrase": "Voer uw zaadzin in" +} \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index f243a2343..561d0a731 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -721,5 +721,7 @@ "message": "Wiadomość", "do_not_have_enough_gas_asset": "Nie masz wystarczającej ilości ${currency}, aby dokonać transakcji przy bieżących warunkach sieci blockchain. Potrzebujesz więcej ${currency}, aby uiścić opłaty za sieć blockchain, nawet jeśli wysyłasz inny zasób.", "totp_auth_url": "Adres URL TOTP AUTH", - "awaitDAppProcessing": "Poczekaj, aż dApp zakończy przetwarzanie." -} + "awaitDAppProcessing": "Poczekaj, aż dApp zakończy przetwarzanie.", + "seed_key": "Klucz nasion", + "enter_seed_phrase": "Wprowadź swoją frazę nasienną" +} \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 49a446f92..21378e9ba 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -720,5 +720,7 @@ "message": "Mensagem", "do_not_have_enough_gas_asset": "Você não tem ${currency} suficiente para fazer uma transação com as condições atuais da rede blockchain. Você precisa de mais ${currency} para pagar as taxas da rede blockchain, mesmo se estiver enviando um ativo diferente.", "totp_auth_url": "URL de autenticação TOTP", - "awaitDAppProcessing": "Aguarde até que o dApp termine o processamento." -} + "awaitDAppProcessing": "Aguarde até que o dApp termine o processamento.", + "seed_key": "Chave de semente", + "enter_seed_phrase": "Digite sua frase de semente" +} \ No newline at end of file diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 305ce68f2..e12b010dd 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -721,5 +721,7 @@ "message": "Сообщение", "do_not_have_enough_gas_asset": "У вас недостаточно ${currency} для совершения транзакции при текущих условиях сети блокчейн. Вам нужно больше ${currency} для оплаты комиссий за сеть блокчейна, даже если вы отправляете другой актив.", "totp_auth_url": "URL-адрес TOTP-АВТОРИЗАЦИИ", - "awaitDAppProcessing": "Пожалуйста, подождите, пока dApp завершит обработку." -} + "awaitDAppProcessing": "Пожалуйста, подождите, пока dApp завершит обработку.", + "seed_key": "Ключ семян", + "enter_seed_phrase": "Введите свою семенную фразу" +} \ No newline at end of file diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 95ba4ef6f..7ac83fc00 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -719,5 +719,7 @@ "message": "ข้อความ", "do_not_have_enough_gas_asset": "คุณมี ${currency} ไม่เพียงพอที่จะทำธุรกรรมกับเงื่อนไขเครือข่ายบล็อคเชนในปัจจุบัน คุณต้องมี ${currency} เพิ่มขึ้นเพื่อชำระค่าธรรมเนียมเครือข่ายบล็อคเชน แม้ว่าคุณจะส่งสินทรัพย์อื่นก็ตาม", "totp_auth_url": "URL การตรวจสอบสิทธิ์ TOTP", - "awaitDAppProcessing": "โปรดรอให้ dApp ประมวลผลเสร็จสิ้น" -} + "awaitDAppProcessing": "โปรดรอให้ dApp ประมวลผลเสร็จสิ้น", + "seed_key": "คีย์เมล็ดพันธุ์", + "enter_seed_phrase": "ป้อนวลีเมล็ดพันธุ์ของคุณ" +} \ No newline at end of file diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 8072eee61..9981469a8 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -716,5 +716,7 @@ "message": "Mensahe", "do_not_have_enough_gas_asset": "Wala kang sapat na ${currency} para gumawa ng transaksyon sa kasalukuyang kundisyon ng network ng blockchain. Kailangan mo ng higit pang ${currency} upang magbayad ng mga bayarin sa network ng blockchain, kahit na nagpapadala ka ng ibang asset.", "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Pakihintay na matapos ang pagproseso ng dApp." -} + "awaitDAppProcessing": "Pakihintay na matapos ang pagproseso ng dApp.", + "seed_key": "Seed Key", + "enter_seed_phrase": "Ipasok ang iyong pariralang binhi" +} \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 596b6b000..6c838b036 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -719,5 +719,7 @@ "message": "İleti", "do_not_have_enough_gas_asset": "Mevcut blockchain ağ koşullarıyla işlem yapmak için yeterli ${currency} paranız yok. Farklı bir varlık gönderiyor olsanız bile blockchain ağ ücretlerini ödemek için daha fazla ${currency} miktarına ihtiyacınız var.", "totp_auth_url": "TOTP YETKİ URL'si", - "awaitDAppProcessing": "Lütfen dApp'in işlemeyi bitirmesini bekleyin." -} + "awaitDAppProcessing": "Lütfen dApp'in işlemeyi bitirmesini bekleyin.", + "seed_key": "Tohum", + "enter_seed_phrase": "Tohum ifadenizi girin" +} \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index bdc950faa..b7720fb99 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -721,5 +721,7 @@ "message": "повідомлення", "do_not_have_enough_gas_asset": "У вас недостатньо ${currency}, щоб здійснити трансакцію з поточними умовами мережі блокчейн. Вам потрібно більше ${currency}, щоб сплатити комісію мережі блокчейн, навіть якщо ви надсилаєте інший актив.", "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Зачекайте, доки dApp завершить обробку." -} + "awaitDAppProcessing": "Зачекайте, доки dApp завершить обробку.", + "seed_key": "Насіннєвий ключ", + "enter_seed_phrase": "Введіть свою насіннєву фразу" +} \ No newline at end of file diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 73c528b69..f7cbdd5e4 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -713,5 +713,7 @@ "message": "ﻡﺎﻐﯿﭘ", "do_not_have_enough_gas_asset": "آپ کے پاس موجودہ بلاکچین نیٹ ورک کی شرائط کے ساتھ لین دین کرنے کے لیے کافی ${currency} نہیں ہے۔ آپ کو بلاکچین نیٹ ورک کی فیس ادا کرنے کے لیے مزید ${currency} کی ضرورت ہے، چاہے آپ کوئی مختلف اثاثہ بھیج رہے ہوں۔", "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "۔ﮟﯾﺮﮐ ﺭﺎﻈﺘﻧﺍ ﺎﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﮓﻨﺴﯿﺳﻭﺮﭘ ﮯﮐ dApp ﻡﺮﮐ ﮦﺍﺮﺑ" -} + "awaitDAppProcessing": "۔ﮟﯾﺮﮐ ﺭﺎﻈﺘﻧﺍ ﺎﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﮓﻨﺴﯿﺳﻭﺮﭘ ﮯﮐ dApp ﻡﺮﮐ ﮦﺍﺮﺑ", + "seed_key": "بیج کی کلید", + "enter_seed_phrase": "اپنے بیج کا جملہ درج کریں" +} \ No newline at end of file diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index f885c2493..a5e3ca263 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -715,5 +715,7 @@ "message": "Ifiranṣẹ", "do_not_have_enough_gas_asset": "O ko ni to ${currency} lati ṣe idunadura kan pẹlu awọn ipo nẹtiwọki blockchain lọwọlọwọ. O nilo diẹ sii ${currency} lati san awọn owo nẹtiwọọki blockchain, paapaa ti o ba nfi dukia miiran ranṣẹ.", "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Fi inurere duro fun dApp lati pari sisẹ." -} + "awaitDAppProcessing": "Fi inurere duro fun dApp lati pari sisẹ.", + "seed_key": "Bọtini Ose", + "enter_seed_phrase": "Tẹ ọrọ-iru irugbin rẹ" +} \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 91642ec73..a2ea6b73f 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -720,5 +720,7 @@ "message": "信息", "do_not_have_enough_gas_asset": "您没有足够的 ${currency} 来在当前的区块链网络条件下进行交易。即使您发送的是不同的资产,您也需要更多的 ${currency} 来支付区块链网络费用。", "totp_auth_url": "TOTP 授权 URL", - "awaitDAppProcessing": "请等待 dApp 处理完成。" -} + "awaitDAppProcessing": "请等待 dApp 处理完成。", + "seed_key": "种子钥匙", + "enter_seed_phrase": "输入您的种子短语" +} \ No newline at end of file From 29bc234dab9986852c20336c81919bafec248a06 Mon Sep 17 00:00:00 2001 From: Serhii Date: Tue, 17 Oct 2023 21:55:54 +0300 Subject: [PATCH 011/241] fix Twiter APiI (#1132) Co-authored-by: Omar Hatem --- lib/entities/parse_address_from_domain.dart | 13 ++---- lib/twitter/twitter_api.dart | 46 +++++++++++++++------ lib/twitter/twitter_user.dart | 12 ++---- 3 files changed, 42 insertions(+), 29 deletions(-) diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart index 9d274fbcc..6e52a93c7 100644 --- a/lib/entities/parse_address_from_domain.dart +++ b/lib/entities/parse_address_from_domain.dart @@ -65,16 +65,11 @@ class AddressResolver { if (addressFromBio != null) { return ParsedAddress.fetchTwitterAddress(address: addressFromBio, name: text); } - final tweets = twitterUser.tweets; - if (tweets != null) { - var subString = StringBuffer(); - tweets.forEach((item) { - subString.writeln(item.text); - }); - final userTweetsText = subString.toString(); - final addressFromPinnedTweet = - extractAddressByType(raw: userTweetsText, type: CryptoCurrency.fromString(ticker)); + final pinnedTweet = twitterUser.pinnedTweet?.text; + if (pinnedTweet != null) { + final addressFromPinnedTweet = + extractAddressByType(raw: pinnedTweet, type: CryptoCurrency.fromString(ticker)); if (addressFromPinnedTweet != null) { return ParsedAddress.fetchTwitterAddress(address: addressFromPinnedTweet, name: text); } diff --git a/lib/twitter/twitter_api.dart b/lib/twitter/twitter_api.dart index 41f5df61d..24121c9c0 100644 --- a/lib/twitter/twitter_api.dart +++ b/lib/twitter/twitter_api.dart @@ -1,7 +1,8 @@ import 'dart:convert'; + +import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/twitter/twitter_user.dart'; import 'package:http/http.dart' as http; -import 'package:cake_wallet/.secrets.g.dart' as secrets; class TwitterApi { static const twitterBearerToken = secrets.twitterBearerToken; @@ -10,28 +11,49 @@ class TwitterApi { static const userPath = '/2/users/by/username/'; static Future lookupUserByName({required String userName}) async { - final queryParams = {'user.fields': 'description', 'expansions': 'pinned_tweet_id'}; - + final queryParams = { + 'user.fields': 'description', + 'expansions': 'pinned_tweet_id', + 'tweet.fields': 'note_tweet' + }; final headers = {'authorization': 'Bearer $twitterBearerToken'}; - final uri = Uri( - scheme: httpsScheme, - host: apiHost, - path: userPath + userName, - queryParameters: queryParams, - ); + scheme: httpsScheme, + host: apiHost, + path: userPath + userName, + queryParameters: queryParams); - var response = await http.get(uri, headers: headers); + final response = await http.get(uri, headers: headers).catchError((error) { + throw Exception('HTTP request failed: $error'); + }); if (response.statusCode != 200) { throw Exception('Unexpected http status: ${response.statusCode}'); } - final responseJSON = json.decode(response.body) as Map; + final Map responseJSON = jsonDecode(response.body) as Map; if (responseJSON['errors'] != null) { throw Exception(responseJSON['errors'][0]['detail']); } - return TwitterUser.fromJson(responseJSON); + return TwitterUser.fromJson(responseJSON, _getPinnedTweet(responseJSON)); + } + + static Tweet? _getPinnedTweet(Map responseJSON) { + final tweetId = responseJSON['data']['pinned_tweet_id'] as String?; + if (tweetId == null || responseJSON['includes'] == null) return null; + + final tweetIncludes = List.from(responseJSON['includes']['tweets'] as List); + final pinnedTweetData = tweetIncludes.firstWhere( + (tweet) => tweet['id'] == tweetId, + orElse: () => null, + ) as Map?; + + if (pinnedTweetData == null) return null; + + final pinnedTweetText = + (pinnedTweetData['note_tweet']?['text'] ?? pinnedTweetData['text']) as String; + + return Tweet(id: tweetId, text: pinnedTweetText); } } diff --git a/lib/twitter/twitter_user.dart b/lib/twitter/twitter_user.dart index ac373fd62..c0eb5431c 100644 --- a/lib/twitter/twitter_user.dart +++ b/lib/twitter/twitter_user.dart @@ -4,25 +4,21 @@ class TwitterUser { required this.username, required this.name, required this.description, - this.tweets}); + this.pinnedTweet}); final String id; final String username; final String name; final String description; - final List? tweets; + final Tweet? pinnedTweet; - factory TwitterUser.fromJson(Map json) { + factory TwitterUser.fromJson(Map json, [Tweet? pinnedTweet]) { return TwitterUser( id: json['data']['id'] as String, username: json['data']['username'] as String, name: json['data']['name'] as String, description: json['data']['description'] as String? ?? '', - tweets: json['includes'] != null - ? List.from(json['includes']['tweets'] as List) - .map((e) => Tweet.fromJson(e as Map)) - .toList() - : null, + pinnedTweet: pinnedTweet, ); } } From 2a3b5644d71ab5d895a1e92643f7fda78e2a2406 Mon Sep 17 00:00:00 2001 From: hundehausen <25672277+hundehausen@users.noreply.github.com> Date: Wed, 18 Oct 2023 23:26:05 +0200 Subject: [PATCH 012/241] use working port for seths node (#1133) * use working port for seths node * use ssl for Seth's node --- assets/node_list.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assets/node_list.yml b/assets/node_list.yml index 2cbd7f780..bc7a9dc4a 100644 --- a/assets/node_list.yml +++ b/assets/node_list.yml @@ -5,7 +5,8 @@ uri: cakexmrl7bonq7ovjka5kuwuyd3f7qnkz6z6s6dmsy3uckwra7bvggyd.onion:18081 is_default: false - - uri: node.sethforprivacy.com:18089 + uri: node.sethforprivacy.com:443 + useSSL: true is_default: false - uri: nodes.hashvault.pro:18081 From 8889f09509045531c3fb9f4c5aed172c1930f69d Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 19 Oct 2023 01:08:29 +0300 Subject: [PATCH 013/241] Accessibility fixes (#1128) --- .../dashboard/widgets/address_page.dart | 29 ++-- .../screens/dashboard/widgets/header_row.dart | 38 +++--- .../present_receive_option_picker.dart | 126 ++++++++---------- .../exchange/widgets/exchange_card.dart | 98 +++++++------- lib/src/widgets/alert_close_button.dart | 19 ++- 5 files changed, 163 insertions(+), 147 deletions(-) diff --git a/lib/src/screens/dashboard/widgets/address_page.dart b/lib/src/screens/dashboard/widgets/address_page.dart index 84100464c..d584ce95b 100644 --- a/lib/src/screens/dashboard/widgets/address_page.dart +++ b/lib/src/screens/dashboard/widgets/address_page.dart @@ -99,19 +99,22 @@ class AddressPage extends BasePage { Widget? trailing(BuildContext context) { return Material( color: Colors.transparent, - child: IconButton( - padding: EdgeInsets.zero, - constraints: BoxConstraints(), - highlightColor: Colors.transparent, - splashColor: Colors.transparent, - iconSize: 25, - onPressed: () { - ShareUtil.share( - text: addressListViewModel.uri.toString(), - context: context, - ); - }, - icon: Icon(Icons.share, size: 20, color: pageIconColor(context)), + child: Semantics( + label: S.of(context).share, + child: IconButton( + padding: EdgeInsets.zero, + constraints: BoxConstraints(), + highlightColor: Colors.transparent, + splashColor: Colors.transparent, + iconSize: 25, + onPressed: () { + ShareUtil.share( + text: addressListViewModel.uri.toString(), + context: context, + ); + }, + icon: Icon(Icons.share, size: 20, color: pageIconColor(context)), + ), ), ); } diff --git a/lib/src/screens/dashboard/widgets/header_row.dart b/lib/src/screens/dashboard/widgets/header_row.dart index 79b7b3fe6..2093a238f 100644 --- a/lib/src/screens/dashboard/widgets/header_row.dart +++ b/lib/src/screens/dashboard/widgets/header_row.dart @@ -31,21 +31,29 @@ class HeaderRow extends StatelessWidget { fontWeight: FontWeight.w500, color: Theme.of(context).extension()!.pageTitleTextColor), ), - GestureDetector( - onTap: () { - showPopUp( - context: context, - builder: (context) => - FilterWidget(dashboardViewModel: dashboardViewModel) - ); - }, - child: Container( - height: 36, - width: 36, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Theme.of(context).extension()!.buttonColor), - child: filterIcon, + Semantics( + container: true, + child: GestureDetector( + onTap: () { + showPopUp( + context: context, + builder: (context) => FilterWidget(dashboardViewModel: dashboardViewModel), + ); + }, + child: Semantics( + label: 'Transaction Filter', + button: true, + enabled: true, + child: Container( + height: 36, + width: 36, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Theme.of(context).extension()!.buttonColor, + ), + child: filterIcon, + ), + ), ), ) ], diff --git a/lib/src/screens/dashboard/widgets/present_receive_option_picker.dart b/lib/src/screens/dashboard/widgets/present_receive_option_picker.dart index aae42049b..33bceeb5c 100644 --- a/lib/src/screens/dashboard/widgets/present_receive_option_picker.dart +++ b/lib/src/screens/dashboard/widgets/present_receive_option_picker.dart @@ -1,5 +1,5 @@ +import 'package:cake_wallet/src/widgets/alert_close_button.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; -import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/src/screens/ionia/widgets/rounded_checkbox.dart'; import 'package:cake_wallet/src/widgets/alert_background.dart'; import 'package:cake_wallet/typography.dart'; @@ -71,77 +71,69 @@ class PresentReceiveOptionPicker extends StatelessWidget { builder: (BuildContext popUpContext) => Scaffold( resizeToAvoidBottomInset: false, backgroundColor: Colors.transparent, - body: AlertBackground( - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Spacer(), - Container( - margin: EdgeInsets.symmetric(horizontal: 24), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(30), - color: Theme.of(context).colorScheme.background, - ), - child: Padding( - padding: const EdgeInsets.only(top: 24, bottom: 24), - child: (ListView.separated( - padding: EdgeInsets.zero, - shrinkWrap: true, - itemCount: receiveOptionViewModel.options.length, - itemBuilder: (_, index) { - final option = receiveOptionViewModel.options[index]; - return InkWell( - onTap: () { - Navigator.pop(popUpContext); + body: Stack( + alignment: AlignmentDirectional.center, + children:[ AlertBackground( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Spacer(), + Container( + margin: EdgeInsets.symmetric(horizontal: 24), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: Theme.of(context).colorScheme.background, + ), + child: Padding( + padding: const EdgeInsets.only(top: 24, bottom: 24), + child: (ListView.separated( + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount: receiveOptionViewModel.options.length, + itemBuilder: (_, index) { + final option = receiveOptionViewModel.options[index]; + return InkWell( + onTap: () { + Navigator.pop(popUpContext); - receiveOptionViewModel.selectReceiveOption(option); - }, - child: Padding( - padding: const EdgeInsets.only(left: 24, right: 24), - child: Observer(builder: (_) { - final value = receiveOptionViewModel.selectedReceiveOption; + receiveOptionViewModel.selectReceiveOption(option); + }, + child: Padding( + padding: const EdgeInsets.only(left: 24, right: 24), + child: Observer(builder: (_) { + final value = receiveOptionViewModel.selectedReceiveOption; - return Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(option.toString(), - textAlign: TextAlign.left, - style: textSmall( - color: Theme.of(context).extension()!.titleColor, - ).copyWith( - fontWeight: - value == option ? FontWeight.w800 : FontWeight.w500, - )), - RoundedCheckbox( - value: value == option, - ) - ], - ); - }), - ), - ); - }, - separatorBuilder: (_, index) => SizedBox(height: 30), - )), - ), - ), - Spacer(), - Container( - margin: EdgeInsets.only(bottom: 40), - child: InkWell( - onTap: () => Navigator.pop(popUpContext), - child: CircleAvatar( - child: Icon( - Icons.close, - color: Palette.darkBlueCraiola, - ), - backgroundColor: Colors.white, + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(option.toString(), + textAlign: TextAlign.left, + style: textSmall( + color: Theme.of(context).extension()!.titleColor, + ).copyWith( + fontWeight: + value == option ? FontWeight.w800 : FontWeight.w500, + )), + RoundedCheckbox( + value: value == option, + ) + ], + ); + }), + ), + ); + }, + separatorBuilder: (_, index) => SizedBox(height: 30), + )), ), ), - ) - ], + Spacer() + ], + ), ), + AlertCloseButton(onTap: () => Navigator.of(popUpContext).pop(), bottom: 40) + ], ), ), context: context, diff --git a/lib/src/screens/exchange/widgets/exchange_card.dart b/lib/src/screens/exchange/widgets/exchange_card.dart index 9c4707529..b55e96e85 100644 --- a/lib/src/screens/exchange/widgets/exchange_card.dart +++ b/lib/src/screens/exchange/widgets/exchange_card.dart @@ -416,37 +416,40 @@ class ExchangeCardState extends State { width: 34, height: 34, padding: EdgeInsets.only(top: 0), - child: InkWell( - onTap: () async { - final contact = - await Navigator.of(context) - .pushNamed( - Routes.pickerAddressBook, - arguments: widget.initialCurrency, - ); + child: Semantics( + label: S.of(context).address_book, + child: InkWell( + onTap: () async { + final contact = + await Navigator.of(context) + .pushNamed( + Routes.pickerAddressBook, + arguments: widget.initialCurrency, + ); - if (contact is ContactBase && - contact.address != null) { - setState(() => - addressController.text = - contact.address); - widget.onPushAddressBookButton - ?.call(context); - } - }, - child: Container( - padding: EdgeInsets.all(8), - decoration: BoxDecoration( - color: widget - .addressButtonsColor, - borderRadius: - BorderRadius.all( - Radius.circular( - 6))), - child: Image.asset( - 'assets/images/open_book.png', - color: Theme.of(context).extension()!.textFieldButtonIconColor, - )), + if (contact is ContactBase && + contact.address != null) { + setState(() => + addressController.text = + contact.address); + widget.onPushAddressBookButton + ?.call(context); + } + }, + child: Container( + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + color: widget + .addressButtonsColor, + borderRadius: + BorderRadius.all( + Radius.circular( + 6))), + child: Image.asset( + 'assets/images/open_book.png', + color: Theme.of(context).extension()!.textFieldButtonIconColor, + )), + ), )), ), Padding( @@ -455,22 +458,25 @@ class ExchangeCardState extends State { width: 34, height: 34, padding: EdgeInsets.only(top: 0), - child: InkWell( - onTap: () { - Clipboard.setData(ClipboardData( - text: addressController - .text)); - showBar( - context, - S - .of(context) - .copied_to_clipboard); - }, - child: Container( - padding: EdgeInsets.fromLTRB( - 8, 8, 0, 8), - color: Colors.transparent, - child: copyImage), + child: Semantics( + label: S.of(context).copy_address, + child: InkWell( + onTap: () { + Clipboard.setData(ClipboardData( + text: addressController + .text)); + showBar( + context, + S + .of(context) + .copied_to_clipboard); + }, + child: Container( + padding: EdgeInsets.fromLTRB( + 8, 8, 0, 8), + color: Colors.transparent, + child: copyImage), + ), ))) ]))) ])), diff --git a/lib/src/widgets/alert_close_button.dart b/lib/src/widgets/alert_close_button.dart index 925756933..e3ff037a9 100644 --- a/lib/src/widgets/alert_close_button.dart +++ b/lib/src/widgets/alert_close_button.dart @@ -1,8 +1,10 @@ +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/palette.dart'; import 'package:flutter/material.dart'; class AlertCloseButton extends StatelessWidget { AlertCloseButton({this.image, this.bottom, this.onTap}); + final VoidCallback? onTap; final Image? image; @@ -19,12 +21,17 @@ class AlertCloseButton extends StatelessWidget { bottom: bottom ?? 60, child: GestureDetector( onTap: onTap ?? () => Navigator.of(context).pop(), - child: Container( - height: 42, - width: 42, - decoration: BoxDecoration(color: Colors.white, shape: BoxShape.circle), - child: Center( - child: image ?? closeButton, + child: Semantics( + label: S.of(context).close, + button: true, + enabled: true, + child: Container( + height: 42, + width: 42, + decoration: BoxDecoration(color: Colors.white, shape: BoxShape.circle), + child: Center( + child: image ?? closeButton, + ), ), ), ), From 8ca9fa0a821eecc532cde5a9ae2e3d30b9e1fbf1 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Thu, 19 Oct 2023 08:28:12 -0400 Subject: [PATCH 014/241] fix (#1136) --- model_generator.sh | 0 scripts/macos/build_sodium.sh | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 model_generator.sh diff --git a/model_generator.sh b/model_generator.sh old mode 100644 new mode 100755 diff --git a/scripts/macos/build_sodium.sh b/scripts/macos/build_sodium.sh index b50d3c2ee..19aad3c97 100755 --- a/scripts/macos/build_sodium.sh +++ b/scripts/macos/build_sodium.sh @@ -10,7 +10,7 @@ echo "============================ SODIUM ============================" echo "Cloning SODIUM from - $SODIUM_URL" git clone $SODIUM_URL $SODIUM_PATH --branch stable cd $SODIUM_PATH -./dist-build/osx.sh +./dist-build/macos.sh mv ${SODIUM_PATH}/libsodium-osx/include/* $EXTERNAL_MACOS_INCLUDE_DIR mv ${SODIUM_PATH}/libsodium-osx/lib/* $EXTERNAL_MACOS_LIB_DIR \ No newline at end of file From 374110db5476444a7d50ae598fd7766e8346ee36 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Thu, 19 Oct 2023 17:25:44 +0100 Subject: [PATCH 015/241] Cw 497 wallet connect for desktop (#1134) * feat: Implement WalletConnect for Desktop * feat: WalletConnect for Desktop * fix: Properly handle and dispose textEditingController for URI * chore: Move BottomSheetListener to Sidebar for desktop app * Remove unused variable and imports * Update desktop_settings_page.dart --------- Co-authored-by: Omar Hatem --- lib/di.dart | 6 +- lib/router.dart | 2 +- .../dashboard/desktop_dashboard_page.dart | 53 +++---- .../desktop_sidebar_wrapper.dart | 143 +++++++++--------- .../settings/connection_sync_page.dart | 2 +- .../desktop_settings_page.dart | 1 + .../wc_connections_listing_view.dart | 20 ++- .../enter_wallet_connect_uri_widget.dart | 140 +++++++++++++++++ macos/Podfile.lock | 2 +- 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_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_yo.arb | 4 +- res/values/strings_zh.arb | 4 +- 35 files changed, 344 insertions(+), 129 deletions(-) create mode 100644 lib/src/screens/wallet_connect/widgets/enter_wallet_connect_uri_widget.dart diff --git a/lib/di.dart b/lib/di.dart index cfe2cfdc5..0434f2d2f 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -220,6 +220,7 @@ import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/entities/qr_view_data.dart'; import 'core/totp_request_details.dart'; +import 'src/screens/settings/desktop_settings/desktop_settings_page.dart'; final getIt = GetIt.instance; @@ -488,6 +489,7 @@ Future setup({ getIt.registerFactory(() { final GlobalKey _navigatorKey = GlobalKey(); return DesktopSidebarWrapper( + bottomSheetService: getIt.get(), dashboardViewModel: getIt.get(), desktopSidebarViewModel: getIt.get(), child: getIt.get(param1: _navigatorKey), @@ -496,7 +498,6 @@ Future setup({ }); getIt.registerFactoryParam, void>( (desktopKey, _) => DesktopDashboardPage( - bottomSheetService: getIt.get(), balancePage: getIt.get(), dashboardViewModel: getIt.get(), addressListViewModel: getIt.get(), @@ -515,6 +516,9 @@ Future setup({ getIt.registerFactory( () => Modify2FAPage(setup2FAViewModel: getIt.get())); + getIt.registerFactory( + () => DesktopSettingsPage()); + getIt.registerFactoryParam( (pageOption, _) => ReceiveOptionViewModel(getIt.get().wallet!, pageOption)); diff --git a/lib/router.dart b/lib/router.dart index 126830308..f9a42ffc6 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -544,7 +544,7 @@ Route createRoute(RouteSettings settings) { ); case Routes.desktop_settings_page: - return CupertinoPageRoute(builder: (_) => DesktopSettingsPage()); + return CupertinoPageRoute(builder: (_) => getIt.get()); case Routes.empty_no_route: return MaterialPageRoute(builder: (_) => SizedBox.shrink()); diff --git a/lib/src/screens/dashboard/desktop_dashboard_page.dart b/lib/src/screens/dashboard/desktop_dashboard_page.dart index b22e6e2b9..ed9fa6912 100644 --- a/lib/src/screens/dashboard/desktop_dashboard_page.dart +++ b/lib/src/screens/dashboard/desktop_dashboard_page.dart @@ -1,10 +1,8 @@ import 'dart:async'; -import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/release_notes/release_notes_screen.dart'; -import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/bottom_sheet_listener.dart'; import 'package:cake_wallet/src/screens/yat_emoji_id.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; @@ -21,14 +19,12 @@ import 'package:shared_preferences/shared_preferences.dart'; class DesktopDashboardPage extends StatelessWidget { DesktopDashboardPage({ required this.balancePage, - required this.bottomSheetService, required this.dashboardViewModel, required this.addressListViewModel, required this.desktopKey, }); final BalancePage balancePage; - final BottomSheetService bottomSheetService; final DashboardViewModel dashboardViewModel; final WalletAddressListViewModel addressListViewModel; final GlobalKey desktopKey; @@ -40,34 +36,31 @@ class DesktopDashboardPage extends StatelessWidget { Widget build(BuildContext context) { _setEffects(context); - return BottomSheetListener( - bottomSheetService: bottomSheetService, - child: Container( - color: Theme.of(context).colorScheme.background, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 400, - child: balancePage, - ), - Flexible( - child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: 500), - child: Navigator( - key: desktopKey, - initialRoute: Routes.desktop_actions, - onGenerateRoute: (settings) => Router.createRoute(settings), - onGenerateInitialRoutes: (NavigatorState navigator, String initialRouteName) { - return [ - navigator.widget.onGenerateRoute!(RouteSettings(name: initialRouteName))! - ]; - }, - ), + return Container( + color: Theme.of(context).colorScheme.background, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 400, + child: balancePage, + ), + Flexible( + child: ConstrainedBox( + constraints: BoxConstraints(maxWidth: 500), + child: Navigator( + key: desktopKey, + initialRoute: Routes.desktop_actions, + onGenerateRoute: (settings) => Router.createRoute(settings), + onGenerateInitialRoutes: (NavigatorState navigator, String initialRouteName) { + return [ + navigator.widget.onGenerateRoute!(RouteSettings(name: initialRouteName))! + ]; + }, ), ), - ], - ), + ), + ], ), ); } diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart index c08b80785..f73570048 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; @@ -7,6 +8,7 @@ import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sideba import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator.dart'; +import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/bottom_sheet_listener.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart'; import 'package:flutter/cupertino.dart'; @@ -16,6 +18,7 @@ import 'package:cake_wallet/router.dart' as Router; import 'package:mobx/mobx.dart'; class DesktopSidebarWrapper extends BasePage { + final BottomSheetService bottomSheetService; final Widget child; final DesktopSidebarViewModel desktopSidebarViewModel; final DashboardViewModel dashboardViewModel; @@ -23,6 +26,7 @@ class DesktopSidebarWrapper extends BasePage { DesktopSidebarWrapper({ required this.child, + required this.bottomSheetService, required this.desktopSidebarViewModel, required this.dashboardViewModel, required this.desktopNavigatorKey, @@ -67,63 +71,75 @@ class DesktopSidebarWrapper extends BasePage { Widget body(BuildContext context) { _setEffects(); - return Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Observer(builder: (_) { - return SideMenu( - width: sideMenuWidth, - topItems: [ - SideMenuItem( - imagePath: 'assets/images/wallet_outline.png', - isSelected: desktopSidebarViewModel.currentPage == SidebarItem.dashboard, - onTap: () { - desktopSidebarViewModel.onPageChange(SidebarItem.dashboard); - desktopNavigatorKey.currentState - ?.pushNamedAndRemoveUntil(Routes.desktop_actions, (route) => false); - }, - ), - SideMenuItem( - onTap: () { - if (desktopSidebarViewModel.currentPage == SidebarItem.transactions) { + return BottomSheetListener( + bottomSheetService: bottomSheetService, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Observer(builder: (_) { + return SideMenu( + width: sideMenuWidth, + topItems: [ + SideMenuItem( + imagePath: 'assets/images/wallet_outline.png', + isSelected: desktopSidebarViewModel.currentPage == SidebarItem.dashboard, + onTap: () { + desktopSidebarViewModel.onPageChange(SidebarItem.dashboard); desktopNavigatorKey.currentState ?.pushNamedAndRemoveUntil(Routes.desktop_actions, (route) => false); - desktopSidebarViewModel.resetSidebar(); - } else { - desktopSidebarViewModel.onPageChange(SidebarItem.transactions); - desktopNavigatorKey.currentState?.pushNamed(Routes.transactionsPage); - } - }, - isSelected: desktopSidebarViewModel.currentPage == SidebarItem.transactions, - imagePath: desktopSidebarViewModel.currentPage == SidebarItem.transactions - ? selectedIconPath - : unselectedIconPath, - ), - ], - bottomItems: [ - SideMenuItem( - imagePath: 'assets/images/support_icon.png', - isSelected: desktopSidebarViewModel.currentPage == SidebarItem.support, - onTap: () => desktopSidebarViewModel.onPageChange(SidebarItem.support)), - SideMenuItem( - imagePath: 'assets/images/settings_outline.png', - isSelected: desktopSidebarViewModel.currentPage == SidebarItem.settings, - onTap: () => desktopSidebarViewModel.onPageChange(SidebarItem.settings), - ), - ], - ); - }), - Expanded( - child: PageView( - controller: pageController, - physics: NeverScrollableScrollPhysics(), - children: [ - child, - Container( - color: Theme.of(context).colorScheme.background, - padding: EdgeInsets.all(20), - child: Navigator( - initialRoute: Routes.support, + }, + ), + SideMenuItem( + onTap: () { + if (desktopSidebarViewModel.currentPage == SidebarItem.transactions) { + desktopNavigatorKey.currentState + ?.pushNamedAndRemoveUntil(Routes.desktop_actions, (route) => false); + desktopSidebarViewModel.resetSidebar(); + } else { + desktopSidebarViewModel.onPageChange(SidebarItem.transactions); + desktopNavigatorKey.currentState?.pushNamed(Routes.transactionsPage); + } + }, + isSelected: desktopSidebarViewModel.currentPage == SidebarItem.transactions, + imagePath: desktopSidebarViewModel.currentPage == SidebarItem.transactions + ? selectedIconPath + : unselectedIconPath, + ), + ], + bottomItems: [ + SideMenuItem( + imagePath: 'assets/images/support_icon.png', + isSelected: desktopSidebarViewModel.currentPage == SidebarItem.support, + onTap: () => desktopSidebarViewModel.onPageChange(SidebarItem.support)), + SideMenuItem( + imagePath: 'assets/images/settings_outline.png', + isSelected: desktopSidebarViewModel.currentPage == SidebarItem.settings, + onTap: () => desktopSidebarViewModel.onPageChange(SidebarItem.settings), + ), + ], + ); + }), + Expanded( + child: PageView( + controller: pageController, + physics: NeverScrollableScrollPhysics(), + children: [ + child, + Container( + color: Theme.of(context).colorScheme.background, + padding: EdgeInsets.all(20), + child: Navigator( + initialRoute: Routes.support, + onGenerateRoute: (settings) => Router.createRoute(settings), + onGenerateInitialRoutes: (NavigatorState navigator, String initialRouteName) { + return [ + navigator.widget.onGenerateRoute!(RouteSettings(name: initialRouteName))! + ]; + }, + ), + ), + Navigator( + initialRoute: Routes.desktop_settings_page, onGenerateRoute: (settings) => Router.createRoute(settings), onGenerateInitialRoutes: (NavigatorState navigator, String initialRouteName) { return [ @@ -131,20 +147,11 @@ class DesktopSidebarWrapper extends BasePage { ]; }, ), - ), - Navigator( - initialRoute: Routes.desktop_settings_page, - onGenerateRoute: (settings) => Router.createRoute(settings), - onGenerateInitialRoutes: (NavigatorState navigator, String initialRouteName) { - return [ - navigator.widget.onGenerateRoute!(RouteSettings(name: initialRouteName))! - ]; - }, - ), - ], + ], + ), ), - ), - ], + ], + ), ); } diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart index 98ca9342c..573778ed2 100644 --- a/lib/src/screens/settings/connection_sync_page.dart +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -85,7 +85,7 @@ class ConnectionSyncPage extends BasePage { ); }, ), - if (dashboardViewModel.wallet.type == WalletType.ethereum && DeviceInfo.instance.isMobile) ...[ + if (dashboardViewModel.wallet.type == WalletType.ethereum) ...[ WalletConnectTile( onTap: () async { Navigator.of(context).push( diff --git a/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart b/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart index bcdb89aec..1d6168e4a 100644 --- a/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart +++ b/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart @@ -12,6 +12,7 @@ final _settingsNavigatorKey = GlobalKey(); class DesktopSettingsPage extends StatefulWidget { const DesktopSettingsPage({super.key}); + @override State createState() => _DesktopSettingsPageState(); } diff --git a/lib/src/screens/wallet_connect/wc_connections_listing_view.dart b/lib/src/screens/wallet_connect/wc_connections_listing_view.dart index ead50db07..6a3171a78 100644 --- a/lib/src/screens/wallet_connect/wc_connections_listing_view.dart +++ b/lib/src/screens/wallet_connect/wc_connections_listing_view.dart @@ -2,8 +2,10 @@ import 'dart:developer'; import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/wallet_connect/widgets/enter_wallet_connect_uri_widget.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/utils/device_info.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; @@ -36,7 +38,13 @@ class WCPairingsWidget extends BasePage { String get title => S.current.walletConnect; Future _onScanQrCode(BuildContext context, Web3Wallet web3Wallet) async { - final String? uri = await presentQRScanner(); + final String? uri; + + if (DeviceInfo.instance.isMobile) { + uri = await presentQRScanner(); + } else { + uri = await _showEnterWalletConnectURIPopUp(context); + } if (uri == null) return _invalidUriToast(context, S.current.nullURIError); @@ -51,6 +59,16 @@ class WCPairingsWidget extends BasePage { } } + Future _showEnterWalletConnectURIPopUp(BuildContext context) async { + final walletConnectURI = await showPopUp( + context: context, + builder: (BuildContext context) { + return EnterWalletConnectURIWrapperWidget(); + }, + ); + return walletConnectURI; + } + Future _invalidUriToast(BuildContext context, String message) async { await showPopUp( context: context, diff --git a/lib/src/screens/wallet_connect/widgets/enter_wallet_connect_uri_widget.dart b/lib/src/screens/wallet_connect/widgets/enter_wallet_connect_uri_widget.dart new file mode 100644 index 000000000..927e7fb02 --- /dev/null +++ b/lib/src/screens/wallet_connect/widgets/enter_wallet_connect_uri_widget.dart @@ -0,0 +1,140 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/widgets/base_alert_dialog.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class EnterWalletConnectURIWrapperWidget extends StatefulWidget { + const EnterWalletConnectURIWrapperWidget({super.key}); + + @override + State createState() => + _EnterWallectConnectURIWrapperWidgetState(); +} + +class _EnterWallectConnectURIWrapperWidgetState extends State { + late final TextEditingController controller; + + @override + void initState() { + super.initState(); + controller = TextEditingController(); + } + + @override + void dispose() { + controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return _EnterWalletConnectURIWidget( + controller: controller, + ); + } +} + +class _EnterWalletConnectURIWidget extends BaseAlertDialog { + _EnterWalletConnectURIWidget({ + required this.controller, + }); + + final TextEditingController controller; + + @override + String get titleText => S.current.enterWalletConnectURI; + + Future _pasteWalletConnectURI() async { + final clipboard = await Clipboard.getData('text/plain'); + final totpURI = clipboard?.text ?? ''; + + if (totpURI.isNotEmpty) { + controller.text = totpURI; + } + } + + @override + Widget content(BuildContext context) { + return Card( + margin: EdgeInsets.zero, + child: Column( + children: [ + SizedBox(height: 8), + Text( + S.current.copyWalletConnectLink, + style: Theme.of(context).textTheme.bodySmall, + ), + SizedBox(height: 16), + TextField( + controller: controller, + style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white), + decoration: InputDecoration( + suffixIcon: Container( + width: 24, + height: 24, + padding: EdgeInsets.only(top: 0), + child: Semantics( + label: S.of(context).paste, + child: InkWell( + onTap: () => _pasteWalletConnectURI(), + child: Container( + padding: EdgeInsets.all(8), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(6)), + ), + child: Image.asset( + 'assets/images/paste_ios.png', + color: + Theme.of(context).extension()!.textFieldButtonIconColor, + ), + ), + ), + ), + ), + hintText: S.current.enterWalletConnectURI, + border: OutlineInputBorder( + borderSide: BorderSide( + color: Theme.of(context).extension()!.textFieldBorderColor, + ), + ), + hintStyle: TextStyle( + color: Theme.of(context).extension()!.textFieldHintColor, + fontWeight: FontWeight.w500, + fontSize: 14, + ), + ), + ), + ], + ), + ); + } + + @override + Widget actionButtons(BuildContext context) { + return Container( + width: 300, + height: 52, + padding: EdgeInsets.only(left: 12, right: 12), + color: Theme.of(context).dialogBackgroundColor, + child: ButtonTheme( + minWidth: double.infinity, + child: TextButton( + onPressed: () { + Navigator.pop(context, controller.text); + }, + child: Text( + S.current.confirm, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w600, + color: Theme.of(context).primaryColor, + decoration: TextDecoration.none, + ), + ), + ), + ), + ); + } +} diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 664a5231b..421dc204c 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -103,7 +103,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308 - cw_monero: ec03de55a19c4a2b174ea687e0f4202edc716fa4 + cw_monero: f8b7f104508efba2591548e76b5c058d05cba3f0 device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225 flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index fcb1b090c..ac3a7d821 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -718,6 +718,8 @@ "do_not_have_enough_gas_asset": "ليس لديك ما يكفي من ${currency} لإجراء معاملة وفقًا لشروط شبكة blockchain الحالية. أنت بحاجة إلى المزيد من ${currency} لدفع رسوم شبكة blockchain، حتى لو كنت ترسل أصلًا مختلفًا.", "totp_auth_url": "TOTP ﺔﻗﺩﺎﺼﻤﻟ URL ﻥﺍﻮﻨﻋ", "awaitDAppProcessing": ".ﺔﺠﻟﺎﻌﻤﻟﺍ ﻦﻣ dApp ﻲﻬﺘﻨﻳ ﻰﺘﺣ ﺭﺎﻈﺘﻧﻻﺍ ﻰﺟﺮﻳ", + "copyWalletConnectLink": "ﺎﻨﻫ ﻪﻘﺼﻟﺍﻭ dApp ﻦﻣ WalletConnect ﻂﺑﺍﺭ ﺦﺴﻧﺍ", + "enterWalletConnectURI": "WalletConnect ـﻟ URI ﻞﺧﺩﺃ", "seed_key": "مفتاح البذور", "enter_seed_phrase": "أدخل عبارة البذور الخاصة بك" -} \ No newline at end of file +} diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index d85b30118..efe823cbf 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -714,6 +714,8 @@ "do_not_have_enough_gas_asset": "Нямате достатъчно ${currency}, за да извършите транзакция с текущите условия на блокчейн мрежата. Имате нужда от повече ${currency}, за да платите таксите за блокчейн мрежа, дори ако изпращате различен актив.", "totp_auth_url": "TOTP AUTH URL", "awaitDAppProcessing": "Моля, изчакайте dApp да завърши обработката.", + "copyWalletConnectLink": "Копирайте връзката WalletConnect от dApp и я поставете тук", + "enterWalletConnectURI": "Въведете URI на WalletConnect", "seed_key": "Ключ за семена", "enter_seed_phrase": "Въведете вашата фраза за семена" -} \ No newline at end of file +} diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 998f0b915..8e7697103 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -714,6 +714,8 @@ "do_not_have_enough_gas_asset": "Nemáte dostatek ${currency} k provedení transakce s aktuálními podmínkami blockchainové sítě. K placení poplatků za blockchainovou síť potřebujete více ${currency}, i když posíláte jiné aktivum.", "totp_auth_url": "URL AUTH TOTP", "awaitDAppProcessing": "Počkejte, až dApp dokončí zpracování.", + "copyWalletConnectLink": "Zkopírujte odkaz WalletConnect z dApp a vložte jej sem", + "enterWalletConnectURI": "Zadejte identifikátor URI WalletConnect", "seed_key": "Klíč semen", "enter_seed_phrase": "Zadejte svou frázi semen" -} \ No newline at end of file +} diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 82575200f..baea36b28 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -722,6 +722,8 @@ "do_not_have_enough_gas_asset": "Sie verfügen nicht über genügend ${currency}, um eine Transaktion unter den aktuellen Bedingungen des Blockchain-Netzwerks durchzuführen. Sie benötigen mehr ${currency}, um die Gebühren für das Blockchain-Netzwerk zu bezahlen, auch wenn Sie einen anderen Vermögenswert senden.", "totp_auth_url": "TOTP-Auth-URL", "awaitDAppProcessing": "Bitte warten Sie, bis die dApp die Verarbeitung abgeschlossen hat.", + "copyWalletConnectLink": "Kopieren Sie den WalletConnect-Link von dApp und fügen Sie ihn hier ein", + "enterWalletConnectURI": "Geben Sie den WalletConnect-URI ein", "seed_key": "Samenschlüssel", "enter_seed_phrase": "Geben Sie Ihre Samenphrase ein" -} \ No newline at end of file +} diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index f30d224c0..5c93c7030 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -723,6 +723,8 @@ "do_not_have_enough_gas_asset": "You do not have enough ${currency} to make a transaction with the current blockchain network conditions. You need more ${currency} to pay blockchain network fees, even if you are sending a different asset.", "totp_auth_url": "TOTP AUTH URL", "awaitDAppProcessing": "Kindly wait for the dApp to finish processing.", + "copyWalletConnectLink": "Copy the WalletConnect link from dApp and paste here", + "enterWalletConnectURI": "Enter WalletConnect URI", "seed_key": "Seed key", "enter_seed_phrase": "Enter your seed phrase" -} \ No newline at end of file +} diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 049a83e40..20393c775 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -722,6 +722,8 @@ "do_not_have_enough_gas_asset": "No tienes suficiente ${currency} para realizar una transacción con las condiciones actuales de la red blockchain. Necesita más ${currency} para pagar las tarifas de la red blockchain, incluso si envía un activo diferente.", "totp_auth_url": "URL de autenticación TOTP", "awaitDAppProcessing": "Espere a que la dApp termine de procesarse.", + "copyWalletConnectLink": "Copie el enlace de WalletConnect de dApp y péguelo aquí", + "enterWalletConnectURI": "Ingrese el URI de WalletConnect", "seed_key": "Llave de semilla", "enter_seed_phrase": "Ingrese su frase de semillas" -} \ No newline at end of file +} diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index e6516fb87..c4418c289 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -722,6 +722,8 @@ "do_not_have_enough_gas_asset": "Vous n'avez pas assez de ${currency} pour effectuer une transaction avec les conditions actuelles du réseau blockchain. Vous avez besoin de plus de ${currency} pour payer les frais du réseau blockchain, même si vous envoyez un actif différent.", "totp_auth_url": "URL D'AUTORISATION TOTP", "awaitDAppProcessing": "Veuillez attendre que le dApp termine le traitement.", + "copyWalletConnectLink": "Copiez le lien WalletConnect depuis dApp et collez-le ici", + "enterWalletConnectURI": "Saisissez l'URI de WalletConnect.", "seed_key": "Clé de graines", "enter_seed_phrase": "Entrez votre phrase de semence" -} \ No newline at end of file +} diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 7d8e8969c..1c0037bff 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -700,6 +700,8 @@ "do_not_have_enough_gas_asset": "Ba ku da isassun ${currency} don yin ma'amala tare da yanayin cibiyar sadarwar blockchain na yanzu. Kuna buƙatar ƙarin ${currency} don biyan kuɗaɗen cibiyar sadarwar blockchain, koda kuwa kuna aika wata kadara daban.", "totp_auth_url": "TOTP AUTH URL", "awaitDAppProcessing": "Da fatan za a jira dApp ya gama aiki.", + "copyWalletConnectLink": "Kwafi hanyar haɗin WalletConnect daga dApp kuma liƙa a nan", + "enterWalletConnectURI": "Shigar da WalletConnect URI", "seed_key": "Maɓallin iri", "enter_seed_phrase": "Shigar da Sert Sentarku" -} \ No newline at end of file +} diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 4a9e6b284..94e7b425e 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -722,6 +722,8 @@ "do_not_have_enough_gas_asset": "वर्तमान ब्लॉकचेन नेटवर्क स्थितियों में लेनदेन करने के लिए आपके पास पर्याप्त ${currency} नहीं है। ब्लॉकचेन नेटवर्क शुल्क का भुगतान करने के लिए आपको अधिक ${currency} की आवश्यकता है, भले ही आप एक अलग संपत्ति भेज रहे हों।", "totp_auth_url": "TOTP प्रामाणिक यूआरएल", "awaitDAppProcessing": "कृपया डीएपी की प्रोसेसिंग पूरी होने तक प्रतीक्षा करें।", + "copyWalletConnectLink": "dApp से वॉलेटकनेक्ट लिंक को कॉपी करें और यहां पेस्ट करें", + "enterWalletConnectURI": "वॉलेटकनेक्ट यूआरआई दर्ज करें", "seed_key": "बीज कुंजी", "enter_seed_phrase": "अपना बीज वाक्यांश दर्ज करें" -} \ No newline at end of file +} diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 17391a6d7..50eba6555 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -720,6 +720,8 @@ "do_not_have_enough_gas_asset": "Nemate dovoljno ${currency} da izvršite transakciju s trenutačnim uvjetima blockchain mreže. Trebate više ${currency} da platite naknade za blockchain mrežu, čak i ako šaljete drugu imovinu.", "totp_auth_url": "TOTP AUTH URL", "awaitDAppProcessing": "Molimo pričekajte da dApp završi obradu.", + "copyWalletConnectLink": "Kopirajte vezu WalletConnect iz dApp-a i zalijepite je ovdje", + "enterWalletConnectURI": "Unesite WalletConnect URI", "seed_key": "Sjemenski ključ", "enter_seed_phrase": "Unesite svoju sjemensku frazu" -} \ No newline at end of file +} diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 5330ec96c..ea54897d4 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -710,6 +710,8 @@ "do_not_have_enough_gas_asset": "Anda tidak memiliki cukup ${currency} untuk melakukan transaksi dengan kondisi jaringan blockchain saat ini. Anda memerlukan lebih banyak ${currency} untuk membayar biaya jaringan blockchain, meskipun Anda mengirimkan aset yang berbeda.", "totp_auth_url": "URL Otentikasi TOTP", "awaitDAppProcessing": "Mohon tunggu hingga dApp menyelesaikan pemrosesan.", + "copyWalletConnectLink": "Salin tautan WalletConnect dari dApp dan tempel di sini", + "enterWalletConnectURI": "Masukkan URI WalletConnect", "seed_key": "Kunci benih", "enter_seed_phrase": "Masukkan frasa benih Anda" -} \ No newline at end of file +} diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index d0c5a1a87..affd673a3 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -722,6 +722,8 @@ "do_not_have_enough_gas_asset": "Non hai abbastanza ${currency} per effettuare una transazione con le attuali condizioni della rete blockchain. Hai bisogno di più ${currency} per pagare le commissioni della rete blockchain, anche se stai inviando una risorsa diversa.", "totp_auth_url": "URL DI AUT. TOTP", "awaitDAppProcessing": "Attendi gentilmente che la dApp termini l'elaborazione.", + "copyWalletConnectLink": "Copia il collegamento WalletConnect dalla dApp e incollalo qui", + "enterWalletConnectURI": "Inserisci l'URI di WalletConnect", "seed_key": "Chiave di semi", "enter_seed_phrase": "Inserisci la tua frase di semi" -} \ No newline at end of file +} diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 1d8012237..dbbb91f55 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -722,6 +722,8 @@ "do_not_have_enough_gas_asset": "現在のブロックチェーン ネットワークの状況では、トランザクションを行うのに十分な ${currency} がありません。別のアセットを送信する場合でも、ブロックチェーン ネットワーク料金を支払うにはさらに ${currency} が必要です。", "totp_auth_url": "TOTP認証URL", "awaitDAppProcessing": "dAppの処理が完了するまでお待ちください。", + "copyWalletConnectLink": "dApp から WalletConnect リンクをコピーし、ここに貼り付けます", + "enterWalletConnectURI": "WalletConnect URI を入力してください", "seed_key": "シードキー", "enter_seed_phrase": "シードフレーズを入力してください" -} \ No newline at end of file +} diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index df5d6f8ea..c4c1a337a 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -720,6 +720,8 @@ "do_not_have_enough_gas_asset": "현재 블록체인 네트워크 조건으로 거래를 하기에는 ${currency}이(가) 충분하지 않습니다. 다른 자산을 보내더라도 블록체인 네트워크 수수료를 지불하려면 ${currency}가 더 필요합니다.", "totp_auth_url": "TOTP 인증 URL", "awaitDAppProcessing": "dApp이 처리를 마칠 때까지 기다려주세요.", + "copyWalletConnectLink": "dApp에서 WalletConnect 링크를 복사하여 여기에 붙여넣으세요.", + "enterWalletConnectURI": "WalletConnect URI를 입력하세요.", "seed_key": "시드 키", "enter_seed_phrase": "시드 문구를 입력하십시오" -} \ No newline at end of file +} diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index e2c4a55f9..929740c93 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -720,6 +720,8 @@ "do_not_have_enough_gas_asset": "လက်ရှိ blockchain ကွန်ရက်အခြေအနေများနှင့် အရောင်းအဝယ်ပြုလုပ်ရန် သင့်တွင် ${currency} လုံလောက်မှုမရှိပါ။ သင်သည် မတူညီသော ပိုင်ဆိုင်မှုတစ်ခုကို ပေးပို့နေသော်လည်း blockchain ကွန်ရက်အခကြေးငွေကို ပေးဆောင်ရန် သင်သည် နောက်ထပ် ${currency} လိုအပ်ပါသည်။", "totp_auth_url": "TOTP AUTH URL", "awaitDAppProcessing": "ကျေးဇူးပြု၍ dApp ကို စီမံလုပ်ဆောင်ခြင်း အပြီးသတ်ရန် စောင့်ပါ။", + "copyWalletConnectLink": "dApp မှ WalletConnect လင့်ခ်ကို ကူးယူပြီး ဤနေရာတွင် ကူးထည့်ပါ။", + "enterWalletConnectURI": "WalletConnect URI ကိုရိုက်ထည့်ပါ။", "seed_key": "မျိုးစေ့သော့", "enter_seed_phrase": "သင့်ရဲ့မျိုးစေ့စကားစုကိုရိုက်ထည့်ပါ" -} \ No newline at end of file +} diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index fd95f5299..fab3fd6d0 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -722,6 +722,8 @@ "do_not_have_enough_gas_asset": "U heeft niet genoeg ${currency} om een transactie uit te voeren met de huidige blockchain-netwerkomstandigheden. U heeft meer ${currency} nodig om blockchain-netwerkkosten te betalen, zelfs als u een ander item verzendt.", "totp_auth_url": "TOTP AUTH-URL", "awaitDAppProcessing": "Wacht tot de dApp klaar is met verwerken.", + "copyWalletConnectLink": "Kopieer de WalletConnect-link van dApp en plak deze hier", + "enterWalletConnectURI": "Voer WalletConnect-URI in", "seed_key": "Zaadsleutel", "enter_seed_phrase": "Voer uw zaadzin in" -} \ No newline at end of file +} diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 561d0a731..54f760c05 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -722,6 +722,8 @@ "do_not_have_enough_gas_asset": "Nie masz wystarczającej ilości ${currency}, aby dokonać transakcji przy bieżących warunkach sieci blockchain. Potrzebujesz więcej ${currency}, aby uiścić opłaty za sieć blockchain, nawet jeśli wysyłasz inny zasób.", "totp_auth_url": "Adres URL TOTP AUTH", "awaitDAppProcessing": "Poczekaj, aż dApp zakończy przetwarzanie.", + "copyWalletConnectLink": "Skopiuj link do WalletConnect z dApp i wklej tutaj", + "enterWalletConnectURI": "Wprowadź identyfikator URI WalletConnect", "seed_key": "Klucz nasion", "enter_seed_phrase": "Wprowadź swoją frazę nasienną" -} \ No newline at end of file +} diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 21378e9ba..5ac12896b 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -721,6 +721,8 @@ "do_not_have_enough_gas_asset": "Você não tem ${currency} suficiente para fazer uma transação com as condições atuais da rede blockchain. Você precisa de mais ${currency} para pagar as taxas da rede blockchain, mesmo se estiver enviando um ativo diferente.", "totp_auth_url": "URL de autenticação TOTP", "awaitDAppProcessing": "Aguarde até que o dApp termine o processamento.", + "copyWalletConnectLink": "Copie o link WalletConnect do dApp e cole aqui", + "enterWalletConnectURI": "Insira o URI do WalletConnect", "seed_key": "Chave de semente", "enter_seed_phrase": "Digite sua frase de semente" -} \ No newline at end of file +} diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index e12b010dd..ef3e11fb4 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -722,6 +722,8 @@ "do_not_have_enough_gas_asset": "У вас недостаточно ${currency} для совершения транзакции при текущих условиях сети блокчейн. Вам нужно больше ${currency} для оплаты комиссий за сеть блокчейна, даже если вы отправляете другой актив.", "totp_auth_url": "URL-адрес TOTP-АВТОРИЗАЦИИ", "awaitDAppProcessing": "Пожалуйста, подождите, пока dApp завершит обработку.", + "copyWalletConnectLink": "Скопируйте ссылку WalletConnect из dApp и вставьте сюда.", + "enterWalletConnectURI": "Введите URI WalletConnect", "seed_key": "Ключ семян", "enter_seed_phrase": "Введите свою семенную фразу" -} \ No newline at end of file +} diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 7ac83fc00..f49133249 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -720,6 +720,8 @@ "do_not_have_enough_gas_asset": "คุณมี ${currency} ไม่เพียงพอที่จะทำธุรกรรมกับเงื่อนไขเครือข่ายบล็อคเชนในปัจจุบัน คุณต้องมี ${currency} เพิ่มขึ้นเพื่อชำระค่าธรรมเนียมเครือข่ายบล็อคเชน แม้ว่าคุณจะส่งสินทรัพย์อื่นก็ตาม", "totp_auth_url": "URL การตรวจสอบสิทธิ์ TOTP", "awaitDAppProcessing": "โปรดรอให้ dApp ประมวลผลเสร็จสิ้น", + "copyWalletConnectLink": "คัดลอกลิงก์ WalletConnect จาก dApp แล้ววางที่นี่", + "enterWalletConnectURI": "เข้าสู่ WalletConnect URI", "seed_key": "คีย์เมล็ดพันธุ์", "enter_seed_phrase": "ป้อนวลีเมล็ดพันธุ์ของคุณ" -} \ No newline at end of file +} diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 9981469a8..893d0ff4b 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -717,6 +717,8 @@ "do_not_have_enough_gas_asset": "Wala kang sapat na ${currency} para gumawa ng transaksyon sa kasalukuyang kundisyon ng network ng blockchain. Kailangan mo ng higit pang ${currency} upang magbayad ng mga bayarin sa network ng blockchain, kahit na nagpapadala ka ng ibang asset.", "totp_auth_url": "TOTP AUTH URL", "awaitDAppProcessing": "Pakihintay na matapos ang pagproseso ng dApp.", + "copyWalletConnectLink": "Kopyahin ang link ng WalletConnect mula sa dApp at i-paste dito", + "enterWalletConnectURI": "Ilagay ang WalletConnect URI", "seed_key": "Seed Key", "enter_seed_phrase": "Ipasok ang iyong pariralang binhi" -} \ No newline at end of file +} diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 6c838b036..44f2aad44 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -720,6 +720,8 @@ "do_not_have_enough_gas_asset": "Mevcut blockchain ağ koşullarıyla işlem yapmak için yeterli ${currency} paranız yok. Farklı bir varlık gönderiyor olsanız bile blockchain ağ ücretlerini ödemek için daha fazla ${currency} miktarına ihtiyacınız var.", "totp_auth_url": "TOTP YETKİ URL'si", "awaitDAppProcessing": "Lütfen dApp'in işlemeyi bitirmesini bekleyin.", + "copyWalletConnectLink": "WalletConnect bağlantısını dApp'ten kopyalayıp buraya yapıştırın", + "enterWalletConnectURI": "WalletConnect URI'sini girin", "seed_key": "Tohum", "enter_seed_phrase": "Tohum ifadenizi girin" -} \ No newline at end of file +} diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index b7720fb99..dc20fd1b0 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -722,6 +722,8 @@ "do_not_have_enough_gas_asset": "У вас недостатньо ${currency}, щоб здійснити трансакцію з поточними умовами мережі блокчейн. Вам потрібно більше ${currency}, щоб сплатити комісію мережі блокчейн, навіть якщо ви надсилаєте інший актив.", "totp_auth_url": "TOTP AUTH URL", "awaitDAppProcessing": "Зачекайте, доки dApp завершить обробку.", + "copyWalletConnectLink": "Скопіюйте посилання WalletConnect із dApp і вставте сюди", + "enterWalletConnectURI": "Введіть URI WalletConnect", "seed_key": "Насіннєвий ключ", "enter_seed_phrase": "Введіть свою насіннєву фразу" -} \ No newline at end of file +} diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index f7cbdd5e4..c4be0af9e 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -714,6 +714,8 @@ "do_not_have_enough_gas_asset": "آپ کے پاس موجودہ بلاکچین نیٹ ورک کی شرائط کے ساتھ لین دین کرنے کے لیے کافی ${currency} نہیں ہے۔ آپ کو بلاکچین نیٹ ورک کی فیس ادا کرنے کے لیے مزید ${currency} کی ضرورت ہے، چاہے آپ کوئی مختلف اثاثہ بھیج رہے ہوں۔", "totp_auth_url": "TOTP AUTH URL", "awaitDAppProcessing": "۔ﮟﯾﺮﮐ ﺭﺎﻈﺘﻧﺍ ﺎﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﮓﻨﺴﯿﺳﻭﺮﭘ ﮯﮐ dApp ﻡﺮﮐ ﮦﺍﺮﺑ", + "copyWalletConnectLink": "dApp ﮯﺳ WalletConnect ۔ﮟﯾﺮﮐ ﭧﺴﯿﭘ ﮞﺎﮩﯾ ﺭﻭﺍ ﮟﯾﺮﮐ ﯽﭘﺎﮐ ﻮﮐ ﮏﻨﻟ", + "enterWalletConnectURI": "WalletConnect URI ۔ﮟﯾﺮﮐ ﺝﺭﺩ", "seed_key": "بیج کی کلید", "enter_seed_phrase": "اپنے بیج کا جملہ درج کریں" -} \ No newline at end of file +} diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index a5e3ca263..14cc4f086 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -716,6 +716,8 @@ "do_not_have_enough_gas_asset": "O ko ni to ${currency} lati ṣe idunadura kan pẹlu awọn ipo nẹtiwọki blockchain lọwọlọwọ. O nilo diẹ sii ${currency} lati san awọn owo nẹtiwọọki blockchain, paapaa ti o ba nfi dukia miiran ranṣẹ.", "totp_auth_url": "TOTP AUTH URL", "awaitDAppProcessing": "Fi inurere duro fun dApp lati pari sisẹ.", + "copyWalletConnectLink": "Daakọ ọna asopọ WalletConnect lati dApp ki o si lẹẹmọ nibi", + "enterWalletConnectURI": "Tẹ WalletConnect URI sii", "seed_key": "Bọtini Ose", "enter_seed_phrase": "Tẹ ọrọ-iru irugbin rẹ" -} \ No newline at end of file +} diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index a2ea6b73f..75b16b0f7 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -721,6 +721,8 @@ "do_not_have_enough_gas_asset": "您没有足够的 ${currency} 来在当前的区块链网络条件下进行交易。即使您发送的是不同的资产,您也需要更多的 ${currency} 来支付区块链网络费用。", "totp_auth_url": "TOTP 授权 URL", "awaitDAppProcessing": "请等待 dApp 处理完成。", + "copyWalletConnectLink": "从 dApp 复制 WalletConnect 链接并粘贴到此处", + "enterWalletConnectURI": "输入 WalletConnect URI", "seed_key": "种子钥匙", "enter_seed_phrase": "输入您的种子短语" -} \ No newline at end of file +} From 759b7a5a04bbd1eda486be15d89f946dd51992ac Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Thu, 19 Oct 2023 21:24:54 -0400 Subject: [PATCH 016/241] disable bio auth for macos (#1138) * disable bio auth for macos * Disable for Linux as well --------- Co-authored-by: fossephate Co-authored-by: Omar Hatem --- lib/core/backup_service.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index ad4fe9623..d439969f5 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -285,7 +285,7 @@ class BackupService { await _sharedPreferences.setInt( PreferencesKey.currentTransactionPriorityKeyLegacy, currentTransactionPriorityKeyLegacy); - if (allowBiometricalAuthentication != null) + if (allowBiometricalAuthentication != null && !Platform.isMacOS && !Platform.isLinux) await _sharedPreferences.setBool( PreferencesKey.allowBiometricalAuthenticationKey, allowBiometricalAuthentication); From 6c178593a9731bb31b772a8c229b0f25875b7106 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Tue, 24 Oct 2023 04:46:48 +0300 Subject: [PATCH 017/241] V4.10.2 v1.7.2 (#1144) * new versions update add semantics for adding new contact * update macos build number * Fix translation strings --- assets/text/Monerocom_Release_Notes.txt | 7 ++- assets/text/Release_Notes.txt | 5 +- .../screens/contact/contact_list_page.dart | 62 ++++++++++--------- res/values/strings_ar.arb | 3 +- res/values/strings_bg.arb | 3 +- res/values/strings_cs.arb | 3 +- res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 3 +- res/values/strings_es.arb | 3 +- res/values/strings_fr.arb | 3 +- res/values/strings_ha.arb | 3 +- res/values/strings_hi.arb | 3 +- res/values/strings_hr.arb | 3 +- res/values/strings_id.arb | 3 +- res/values/strings_it.arb | 3 +- res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 3 +- res/values/strings_nl.arb | 3 +- res/values/strings_pl.arb | 3 +- res/values/strings_pt.arb | 3 +- res/values/strings_ru.arb | 3 +- res/values/strings_th.arb | 3 +- res/values/strings_tl.arb | 3 +- res/values/strings_tr.arb | 3 +- res/values/strings_uk.arb | 3 +- res/values/strings_ur.arb | 3 +- res/values/strings_yo.arb | 3 +- res/values/strings_zh.arb | 3 +- scripts/android/app_env.sh | 8 +-- scripts/ios/app_env.sh | 8 +-- scripts/macos/app_env.sh | 4 +- 32 files changed, 102 insertions(+), 70 deletions(-) diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 46a62494b..fb2cd98fe 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,3 +1,4 @@ -Support getting Addresses from ENS and Mastodon -Bug fixes -Minor enhancements \ No newline at end of file +BirdPay enhancements +Nano fixes and improvements +Minor bug fixes +Accessibility enhancements \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 795ec3427..fb2cd98fe 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,3 +1,4 @@ -Add BitcoinCash (BCH) -Bug fixes +BirdPay enhancements +Nano fixes and improvements +Minor bug fixes Accessibility enhancements \ No newline at end of file diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index b551875f9..d9e3c0c85 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -35,35 +35,39 @@ class ContactListPage extends BasePage { decoration: BoxDecoration( shape: BoxShape.circle, color: Theme.of(context).extension()!.buttonBackgroundColor), - child: Stack( - alignment: Alignment.center, - children: [ - Icon( - Icons.add, - color: Theme.of(context).appBarTheme.titleTextStyle!.color, - size: 22.0, - ), - ButtonTheme( - minWidth: 32.0, - height: 32.0, - child: TextButton( - // FIX-ME: Style - //shape: CircleBorder(), - onPressed: () async { - if (contactListViewModel.shouldRequireTOTP2FAForAddingContacts) { - authService.authenticateAction( - context, - route: Routes.addressBookAddContact, - conditionToDetermineIfToUse2FA: - contactListViewModel.shouldRequireTOTP2FAForAddingContacts, - ); - } else { - await Navigator.of(context).pushNamed(Routes.addressBookAddContact); - } - }, - child: Offstage()), - ) - ], + child: Semantics( + label: S.of(context).add_contact, + button: true, + child: Stack( + alignment: Alignment.center, + children: [ + Icon( + Icons.add, + color: Theme.of(context).appBarTheme.titleTextStyle!.color, + size: 22.0, + ), + ButtonTheme( + minWidth: 32.0, + height: 32.0, + child: TextButton( + // FIX-ME: Style + //shape: CircleBorder(), + onPressed: () async { + if (contactListViewModel.shouldRequireTOTP2FAForAddingContacts) { + authService.authenticateAction( + context, + route: Routes.addressBookAddContact, + conditionToDetermineIfToUse2FA: + contactListViewModel.shouldRequireTOTP2FAForAddingContacts, + ); + } else { + await Navigator.of(context).pushNamed(Routes.addressBookAddContact); + } + }, + child: Offstage()), + ) + ], + ), ), ), ); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index ac3a7d821..4f6778456 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -721,5 +721,6 @@ "copyWalletConnectLink": "ﺎﻨﻫ ﻪﻘﺼﻟﺍﻭ dApp ﻦﻣ WalletConnect ﻂﺑﺍﺭ ﺦﺴﻧﺍ", "enterWalletConnectURI": "WalletConnect ـﻟ URI ﻞﺧﺩﺃ", "seed_key": "مفتاح البذور", - "enter_seed_phrase": "أدخل عبارة البذور الخاصة بك" + "enter_seed_phrase": "أدخل عبارة البذور الخاصة بك", + "add_contact": "ﻝﺎﺼﺗﺍ ﺔﻬﺟ ﺔﻓﺎﺿﺇ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index efe823cbf..419b800ba 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -717,5 +717,6 @@ "copyWalletConnectLink": "Копирайте връзката WalletConnect от dApp и я поставете тук", "enterWalletConnectURI": "Въведете URI на WalletConnect", "seed_key": "Ключ за семена", - "enter_seed_phrase": "Въведете вашата фраза за семена" + "enter_seed_phrase": "Въведете вашата фраза за семена", + "add_contact": "Добави контакт" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 8e7697103..9b0d94cda 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -717,5 +717,6 @@ "copyWalletConnectLink": "Zkopírujte odkaz WalletConnect z dApp a vložte jej sem", "enterWalletConnectURI": "Zadejte identifikátor URI WalletConnect", "seed_key": "Klíč semen", - "enter_seed_phrase": "Zadejte svou frázi semen" + "enter_seed_phrase": "Zadejte svou frázi semen", + "add_contact": "Přidat kontakt" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index baea36b28..bb0fc0541 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -725,5 +725,6 @@ "copyWalletConnectLink": "Kopieren Sie den WalletConnect-Link von dApp und fügen Sie ihn hier ein", "enterWalletConnectURI": "Geben Sie den WalletConnect-URI ein", "seed_key": "Samenschlüssel", - "enter_seed_phrase": "Geben Sie Ihre Samenphrase ein" + "enter_seed_phrase": "Geben Sie Ihre Samenphrase ein", + "add_contact": "Kontakt hinzufügen" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 5c93c7030..bd821fa2b 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -726,5 +726,6 @@ "copyWalletConnectLink": "Copy the WalletConnect link from dApp and paste here", "enterWalletConnectURI": "Enter WalletConnect URI", "seed_key": "Seed key", - "enter_seed_phrase": "Enter your seed phrase" + "enter_seed_phrase": "Enter your seed phrase", + "add_contact": "Add contact" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 20393c775..3810331eb 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -725,5 +725,6 @@ "copyWalletConnectLink": "Copie el enlace de WalletConnect de dApp y péguelo aquí", "enterWalletConnectURI": "Ingrese el URI de WalletConnect", "seed_key": "Llave de semilla", - "enter_seed_phrase": "Ingrese su frase de semillas" + "enter_seed_phrase": "Ingrese su frase de semillas", + "add_contact": "Agregar contacto" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index c4418c289..f7b30158c 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -725,5 +725,6 @@ "copyWalletConnectLink": "Copiez le lien WalletConnect depuis dApp et collez-le ici", "enterWalletConnectURI": "Saisissez l'URI de WalletConnect.", "seed_key": "Clé de graines", - "enter_seed_phrase": "Entrez votre phrase de semence" + "enter_seed_phrase": "Entrez votre phrase de semence", + "add_contact": "Ajouter le contact" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 1c0037bff..eeeaa0e2c 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -703,5 +703,6 @@ "copyWalletConnectLink": "Kwafi hanyar haɗin WalletConnect daga dApp kuma liƙa a nan", "enterWalletConnectURI": "Shigar da WalletConnect URI", "seed_key": "Maɓallin iri", - "enter_seed_phrase": "Shigar da Sert Sentarku" + "enter_seed_phrase": "Shigar da Sert Sentarku", + "add_contact": "Ƙara lamba" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 94e7b425e..1d87df54a 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -725,5 +725,6 @@ "copyWalletConnectLink": "dApp से वॉलेटकनेक्ट लिंक को कॉपी करें और यहां पेस्ट करें", "enterWalletConnectURI": "वॉलेटकनेक्ट यूआरआई दर्ज करें", "seed_key": "बीज कुंजी", - "enter_seed_phrase": "अपना बीज वाक्यांश दर्ज करें" + "enter_seed_phrase": "अपना बीज वाक्यांश दर्ज करें", + "add_contact": "संपर्क जोड़ें" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 50eba6555..cadf79772 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -723,5 +723,6 @@ "copyWalletConnectLink": "Kopirajte vezu WalletConnect iz dApp-a i zalijepite je ovdje", "enterWalletConnectURI": "Unesite WalletConnect URI", "seed_key": "Sjemenski ključ", - "enter_seed_phrase": "Unesite svoju sjemensku frazu" + "enter_seed_phrase": "Unesite svoju sjemensku frazu", + "add_contact": "Dodaj kontakt" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index ea54897d4..903199b42 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -713,5 +713,6 @@ "copyWalletConnectLink": "Salin tautan WalletConnect dari dApp dan tempel di sini", "enterWalletConnectURI": "Masukkan URI WalletConnect", "seed_key": "Kunci benih", - "enter_seed_phrase": "Masukkan frasa benih Anda" + "enter_seed_phrase": "Masukkan frasa benih Anda", + "add_contact": "Tambah kontak" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index affd673a3..e12eba3cb 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -725,5 +725,6 @@ "copyWalletConnectLink": "Copia il collegamento WalletConnect dalla dApp e incollalo qui", "enterWalletConnectURI": "Inserisci l'URI di WalletConnect", "seed_key": "Chiave di semi", - "enter_seed_phrase": "Inserisci la tua frase di semi" + "enter_seed_phrase": "Inserisci la tua frase di semi", + "add_contact": "Aggiungi contatto" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index dbbb91f55..6df16d142 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -725,5 +725,6 @@ "copyWalletConnectLink": "dApp から WalletConnect リンクをコピーし、ここに貼り付けます", "enterWalletConnectURI": "WalletConnect URI を入力してください", "seed_key": "シードキー", - "enter_seed_phrase": "シードフレーズを入力してください" + "enter_seed_phrase": "シードフレーズを入力してください", + "add_contact": "連絡先を追加" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index c4c1a337a..6386abfde 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -723,5 +723,6 @@ "copyWalletConnectLink": "dApp에서 WalletConnect 링크를 복사하여 여기에 붙여넣으세요.", "enterWalletConnectURI": "WalletConnect URI를 입력하세요.", "seed_key": "시드 키", - "enter_seed_phrase": "시드 문구를 입력하십시오" + "enter_seed_phrase": "시드 문구를 입력하십시오", + "add_contact": "주소록에 추가" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 929740c93..d2f584b22 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -723,5 +723,6 @@ "copyWalletConnectLink": "dApp မှ WalletConnect လင့်ခ်ကို ကူးယူပြီး ဤနေရာတွင် ကူးထည့်ပါ။", "enterWalletConnectURI": "WalletConnect URI ကိုရိုက်ထည့်ပါ။", "seed_key": "မျိုးစေ့သော့", - "enter_seed_phrase": "သင့်ရဲ့မျိုးစေ့စကားစုကိုရိုက်ထည့်ပါ" + "enter_seed_phrase": "သင့်ရဲ့မျိုးစေ့စကားစုကိုရိုက်ထည့်ပါ", + "add_contact": "အဆက်အသွယ်ထည့်ပါ။" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index fab3fd6d0..c05ec8fba 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -725,5 +725,6 @@ "copyWalletConnectLink": "Kopieer de WalletConnect-link van dApp en plak deze hier", "enterWalletConnectURI": "Voer WalletConnect-URI in", "seed_key": "Zaadsleutel", - "enter_seed_phrase": "Voer uw zaadzin in" + "enter_seed_phrase": "Voer uw zaadzin in", + "add_contact": "Contactpersoon toevoegen" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 54f760c05..2137ce464 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -725,5 +725,6 @@ "copyWalletConnectLink": "Skopiuj link do WalletConnect z dApp i wklej tutaj", "enterWalletConnectURI": "Wprowadź identyfikator URI WalletConnect", "seed_key": "Klucz nasion", - "enter_seed_phrase": "Wprowadź swoją frazę nasienną" + "enter_seed_phrase": "Wprowadź swoją frazę nasienną", + "add_contact": "Dodaj kontakt" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 5ac12896b..96bb7f355 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -724,5 +724,6 @@ "copyWalletConnectLink": "Copie o link WalletConnect do dApp e cole aqui", "enterWalletConnectURI": "Insira o URI do WalletConnect", "seed_key": "Chave de semente", - "enter_seed_phrase": "Digite sua frase de semente" + "enter_seed_phrase": "Digite sua frase de semente", + "add_contact": "Adicionar contato" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index ef3e11fb4..503a7898b 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -725,5 +725,6 @@ "copyWalletConnectLink": "Скопируйте ссылку WalletConnect из dApp и вставьте сюда.", "enterWalletConnectURI": "Введите URI WalletConnect", "seed_key": "Ключ семян", - "enter_seed_phrase": "Введите свою семенную фразу" + "enter_seed_phrase": "Введите свою семенную фразу", + "add_contact": "Добавить контакт" } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index f49133249..6fc6a40ff 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -723,5 +723,6 @@ "copyWalletConnectLink": "คัดลอกลิงก์ WalletConnect จาก dApp แล้ววางที่นี่", "enterWalletConnectURI": "เข้าสู่ WalletConnect URI", "seed_key": "คีย์เมล็ดพันธุ์", - "enter_seed_phrase": "ป้อนวลีเมล็ดพันธุ์ของคุณ" + "enter_seed_phrase": "ป้อนวลีเมล็ดพันธุ์ของคุณ", + "add_contact": "เพิ่มผู้ติดต่อ" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 893d0ff4b..9087d2f7c 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -720,5 +720,6 @@ "copyWalletConnectLink": "Kopyahin ang link ng WalletConnect mula sa dApp at i-paste dito", "enterWalletConnectURI": "Ilagay ang WalletConnect URI", "seed_key": "Seed Key", - "enter_seed_phrase": "Ipasok ang iyong pariralang binhi" + "enter_seed_phrase": "Ipasok ang iyong pariralang binhi", + "add_contact": "Magdagdag ng contact" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 44f2aad44..353ef0184 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -723,5 +723,6 @@ "copyWalletConnectLink": "WalletConnect bağlantısını dApp'ten kopyalayıp buraya yapıştırın", "enterWalletConnectURI": "WalletConnect URI'sini girin", "seed_key": "Tohum", - "enter_seed_phrase": "Tohum ifadenizi girin" + "enter_seed_phrase": "Tohum ifadenizi girin", + "add_contact": "Kişi ekle" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index dc20fd1b0..9c67c532a 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -725,5 +725,6 @@ "copyWalletConnectLink": "Скопіюйте посилання WalletConnect із dApp і вставте сюди", "enterWalletConnectURI": "Введіть URI WalletConnect", "seed_key": "Насіннєвий ключ", - "enter_seed_phrase": "Введіть свою насіннєву фразу" + "enter_seed_phrase": "Введіть свою насіннєву фразу", + "add_contact": "Додати контакт" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index c4be0af9e..a1bf60aeb 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -717,5 +717,6 @@ "copyWalletConnectLink": "dApp ﮯﺳ WalletConnect ۔ﮟﯾﺮﮐ ﭧﺴﯿﭘ ﮞﺎﮩﯾ ﺭﻭﺍ ﮟﯾﺮﮐ ﯽﭘﺎﮐ ﻮﮐ ﮏﻨﻟ", "enterWalletConnectURI": "WalletConnect URI ۔ﮟﯾﺮﮐ ﺝﺭﺩ", "seed_key": "بیج کی کلید", - "enter_seed_phrase": "اپنے بیج کا جملہ درج کریں" + "enter_seed_phrase": "اپنے بیج کا جملہ درج کریں", + "add_contact": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮧﻄﺑﺍﺭ" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 14cc4f086..a2b3e7979 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -719,5 +719,6 @@ "copyWalletConnectLink": "Daakọ ọna asopọ WalletConnect lati dApp ki o si lẹẹmọ nibi", "enterWalletConnectURI": "Tẹ WalletConnect URI sii", "seed_key": "Bọtini Ose", - "enter_seed_phrase": "Tẹ ọrọ-iru irugbin rẹ" + "enter_seed_phrase": "Tẹ ọrọ-iru irugbin rẹ", + "add_contact": "Fi olubasọrọ kun" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 75b16b0f7..1c47ca2ba 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -724,5 +724,6 @@ "copyWalletConnectLink": "从 dApp 复制 WalletConnect 链接并粘贴到此处", "enterWalletConnectURI": "输入 WalletConnect URI", "seed_key": "种子钥匙", - "enter_seed_phrase": "输入您的种子短语" + "enter_seed_phrase": "输入您的种子短语", + "add_contact": "增加联系人" } diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 356cf03cd..5705fbe51 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.7.1" -MONERO_COM_BUILD_NUMBER=62 +MONERO_COM_VERSION="1.7.2" +MONERO_COM_BUILD_NUMBER=63 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.10.1" -CAKEWALLET_BUILD_NUMBER=176 +CAKEWALLET_VERSION="4.10.2" +CAKEWALLET_BUILD_NUMBER=177 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index ae5a90bc3..7c9852243 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.7.1" -MONERO_COM_BUILD_NUMBER=60 +MONERO_COM_VERSION="1.7.2" +MONERO_COM_BUILD_NUMBER=61 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.10.1" -CAKEWALLET_BUILD_NUMBER=190 +CAKEWALLET_VERSION="4.10.2" +CAKEWALLET_BUILD_NUMBER=191 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 37c2b3441..88f1c9774 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -15,8 +15,8 @@ if [ -n "$1" ]; then fi CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.3.1" -CAKEWALLET_BUILD_NUMBER=37 +CAKEWALLET_VERSION="1.3.2" +CAKEWALLET_BUILD_NUMBER=39 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From db7f025b71643776f933d6a6816783d8f4ddfc78 Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 25 Oct 2023 03:19:59 +0300 Subject: [PATCH 018/241] CW-472-QR-code-restore-If-a-user-scans-a-wallet-seed-that-does-NOT-include (#1081) * add restor from qr option * minor fixes * merge OR fixes * add restoring nano from QR seed mode --- lib/router.dart | 5 + lib/routes.dart | 1 + .../restore/restore_from_qr_vm.dart | 4 + .../restore/wallet_restore_from_qr_code.dart | 217 +++++++++--------- 4 files changed, 113 insertions(+), 114 deletions(-) diff --git a/lib/router.dart b/lib/router.dart index f9a42ffc6..26a37c900 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -189,6 +189,11 @@ Route createRoute(RouteSettings settings) { param2: false)); } + case Routes.restoreWalletTypeFromQR: + return CupertinoPageRoute( + builder: (_) => getIt.get( + param1: (BuildContext context, WalletType type) => Navigator.of(context).pop(type))); + case Routes.seed: return MaterialPageRoute( fullscreenDialog: true, diff --git a/lib/routes.dart b/lib/routes.dart index 2ccc2c765..ec7ad8ae8 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -6,6 +6,7 @@ class Routes { static const seed = '/seed'; static const restoreOptions = '/restore_options'; static const restoreWalletFromSeedKeys = '/restore_wallet_from_seeds_keys'; + static const restoreWalletTypeFromQR = '/restore_wallet_from_qr_code'; static const restoreWalletChooseDerivation = '/restore_wallet_choose_derivation'; static const dashboard = '/dashboard'; static const send = '/send'; diff --git a/lib/view_model/restore/restore_from_qr_vm.dart b/lib/view_model/restore/restore_from_qr_vm.dart index 2bc595469..4ffc81cef 100644 --- a/lib/view_model/restore/restore_from_qr_vm.dart +++ b/lib/view_model/restore/restore_from_qr_vm.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; +import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/view_model/restore/restore_mode.dart'; import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; import 'package:hive/hive.dart'; @@ -91,6 +92,9 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store case WalletType.ethereum: return ethereum!.createEthereumRestoreWalletFromSeedCredentials( name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); + case WalletType.nano: + return nano!.createNanoRestoreWalletFromSeedCredentials( + name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); default: throw Exception('Unexpected type: ${type.toString()}'); } diff --git a/lib/view_model/restore/wallet_restore_from_qr_code.dart b/lib/view_model/restore/wallet_restore_from_qr_code.dart index bc100f9fe..077675d1f 100644 --- a/lib/view_model/restore/wallet_restore_from_qr_code.dart +++ b/lib/view_model/restore/wallet_restore_from_qr_code.dart @@ -1,44 +1,106 @@ import 'package:cake_wallet/core/seed_validator.dart'; import 'package:cake_wallet/entities/parse_address_from_domain.dart'; import 'package:cake_wallet/entities/qr_scanner.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/restore/restore_mode.dart'; import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/cupertino.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:collection/collection.dart'; class WalletRestoreFromQRCode { WalletRestoreFromQRCode(); + static const Map _walletTypeMap = { + 'monero': WalletType.monero, + 'monero-wallet': WalletType.monero, + 'monero_wallet': WalletType.monero, + 'bitcoin': WalletType.bitcoin, + 'bitcoin-wallet': WalletType.bitcoin, + 'bitcoin_wallet': WalletType.bitcoin, + 'litecoin': WalletType.litecoin, + 'litecoin-wallet': WalletType.litecoin, + 'litecoin_wallet': WalletType.litecoin, + 'ethereum-wallet': WalletType.ethereum, + 'nano-wallet': WalletType.nano, + 'nano_wallet': WalletType.nano, + 'bitcoincash': WalletType.bitcoinCash, + 'bitcoincash-wallet': WalletType.bitcoinCash, + 'bitcoincash_wallet': WalletType.bitcoinCash, + }; + + static bool _containsAssetSpecifier(String code) => _extractWalletType(code) != null; + + static WalletType? _extractWalletType(String code) { + final sortedKeys = _walletTypeMap.keys.toList()..sort((a, b) => b.length.compareTo(a.length)); + + final extracted = sortedKeys.firstWhereOrNull((key) => code.toLowerCase().contains(key)); + + return _walletTypeMap[extracted]; + } + + static String? _extractAddressFromUrl(String rawString, WalletType type) { + return AddressResolver.extractAddressByType( + raw: rawString, type: walletTypeToCryptoCurrency(type)); + } + + static String? _extractSeedPhraseFromUrl(String rawString, WalletType walletType) { + RegExp _getPattern(int wordCount) => + RegExp(r'(?<=\W|^)((?:\w+\s+){' + (wordCount - 1).toString() + r'}\w+)(?=\W|$)'); + + List patternCounts = walletType == WalletType.monero ? [25, 14, 13] : [24, 18, 12]; + + for (final count in patternCounts) { + final pattern = _getPattern(count); + final match = pattern.firstMatch(rawString); + if (match != null) { + return match.group(1)?.trim(); + } + } + return null; + } + static Future scanQRCodeForRestoring(BuildContext context) async { String code = await presentQRScanner(); - Map credentials = {}; + if (code.isEmpty) throw Exception('Unexpected scan QR code value: value is empty'); - if (code.isEmpty) { - throw Exception('Unexpected scan QR code value: value is empty'); - } - final formattedUri = getFormattedUri(code); - final uri = Uri.parse(formattedUri); - final queryParameters = uri.queryParameters; - credentials['type'] = getWalletTypeFromUrl(uri.scheme); + WalletType? walletType; + String formattedUri = ''; - final address = getAddressFromUrl( - type: credentials['type'] as WalletType, - rawString: queryParameters.toString(), - ); - if (address != null) { - credentials['address'] = address; - } + if (!_containsAssetSpecifier(code)) { + await _specifyWalletAssets(context, "Can't determine wallet type, please pick it manually"); + walletType = + await Navigator.pushNamed(context, Routes.restoreWalletTypeFromQR) as WalletType?; + if (walletType == null) throw Exception("Failed to determine wallet type."); - final seed = - getSeedPhraseFromUrl(queryParameters.toString(), credentials['type'] as WalletType); - if (seed != null) { - credentials['seed'] = seed; + final seedPhrase = _extractSeedPhraseFromUrl(code, walletType); + + formattedUri = seedPhrase != null + ? '$walletType:?seed=$seedPhrase' + : throw Exception('Failed to determine valid seed phrase'); } else { - credentials['private_key'] = queryParameters['private_key']; + walletType = _extractWalletType(code); + final index = code.indexOf(':'); + final query = code.substring(index + 1).replaceAll('?', '&'); + formattedUri = '$walletType:?$query'; } - credentials.addAll(queryParameters); - credentials['mode'] = getWalletRestoreMode(credentials); + final uri = Uri.parse(formattedUri); + Map queryParameters = {...uri.queryParameters}; + + if (queryParameters['seed'] == null) { + queryParameters['seed'] = _extractSeedPhraseFromUrl(code, walletType!); + } + if (queryParameters['address'] == null) { + queryParameters['address'] = _extractAddressFromUrl(code, walletType!); + } + + Map credentials = {'type': walletType, ...queryParameters}; + + credentials['mode'] = _determineWalletRestoreMode(credentials); switch (credentials['mode']) { case WalletRestoreMode.txids: @@ -52,106 +114,21 @@ class WalletRestoreFromQRCode { } } - static String getFormattedUri(String code) { - final index = code.indexOf(':'); - if (index == -1) return throw Exception('Unexpected wallet type: $code, try to scan again'); - final scheme = code.substring(0, index).replaceAll('_', '-'); - final query = code.substring(index + 1).replaceAll('?', '&'); - final formattedUri = '$scheme:?$query'; - return formattedUri; - } - - static WalletType getWalletTypeFromUrl(String scheme) { - switch (scheme) { - case 'monero': - case 'monero-wallet': - return WalletType.monero; - case 'bitcoin': - case 'bitcoin-wallet': - return WalletType.bitcoin; - case 'litecoin': - case 'litecoin-wallet': - return WalletType.litecoin; - case 'bitcoincash': - case 'bitcoincash-wallet': - return WalletType.bitcoinCash; - case 'ethereum': - case 'ethereum-wallet': - return WalletType.ethereum; - case 'nano': - case 'nano-wallet': - return WalletType.nano; - default: - throw Exception('Unexpected wallet type: ${scheme.toString()}'); - } - } - - static String? getAddressFromUrl({required WalletType type, required String rawString}) { - return AddressResolver.extractAddressByType( - raw: rawString, type: walletTypeToCryptoCurrency(type)); - } - - static String? getSeedPhraseFromUrl(String rawString, WalletType walletType) { - switch (walletType) { - case WalletType.monero: - RegExp regex25 = RegExp(r'\b(\S+\b\s+){24}\S+\b'); - RegExp regex14 = RegExp(r'\b(\S+\b\s+){13}\S+\b'); - RegExp regex13 = RegExp(r'\b(\S+\b\s+){12}\S+\b'); - - if (regex25.firstMatch(rawString) == null) { - if (regex14.firstMatch(rawString) == null) { - if (regex13.firstMatch(rawString) == null) { - return null; - } else { - return regex13.firstMatch(rawString)!.group(0)!; - } - } else { - return regex14.firstMatch(rawString)!.group(0)!; - } - } else { - return regex25.firstMatch(rawString)!.group(0)!; - } - case WalletType.bitcoin: - case WalletType.litecoin: - case WalletType.ethereum: - case WalletType.bitcoinCash: - RegExp regex24 = RegExp(r'\b(\S+\b\s+){23}\S+\b'); - RegExp regex18 = RegExp(r'\b(\S+\b\s+){17}\S+\b'); - RegExp regex12 = RegExp(r'\b(\S+\b\s+){11}\S+\b'); - - if (regex24.firstMatch(rawString) == null) { - if (regex18.firstMatch(rawString) == null) { - if (regex12.firstMatch(rawString) == null) { - return null; - } else { - return regex12.firstMatch(rawString)!.group(0)!; - } - } else { - return regex18.firstMatch(rawString)!.group(0)!; - } - } else { - return regex24.firstMatch(rawString)!.group(0)!; - } - default: - return null; - } - } - - static WalletRestoreMode getWalletRestoreMode(Map credentials) { + static WalletRestoreMode _determineWalletRestoreMode(Map credentials) { final type = credentials['type'] as WalletType; if (credentials.containsKey('tx_payment_id')) { final txIdValue = credentials['tx_payment_id'] as String? ?? ''; - return txIdValue.isNotEmpty - ? WalletRestoreMode.txids - : throw Exception('Unexpected restore mode: tx_payment_id is invalid'); + if (txIdValue.isNotEmpty) return WalletRestoreMode.txids; + throw Exception('Unexpected restore mode: tx_payment_id is invalid'); } - if (credentials.containsKey('seed')) { - final seedValue = credentials['seed'] as String; + if (credentials['seed'] != null) { + final seedValue = credentials['seed']; final words = SeedValidator.getWordList(type: type, language: 'english'); seedValue.split(' ').forEach((element) { if (!words.contains(element)) { - throw Exception('Unexpected restore mode: mnemonic_seed is invalid'); + throw Exception( + 'Unexpected restore mode: mnemonic_seed is invalid or does\'t match wallet type'); } }); return WalletRestoreMode.seed; @@ -177,3 +154,15 @@ class WalletRestoreFromQRCode { throw Exception('Unexpected restore mode: restore params are invalid'); } } + +Future _specifyWalletAssets(BuildContext context, String error) async { + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: S.current.error, + alertContent: error, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop()); + }); +} From cef3029f6f9be44d6838f60f205e4fb925d3fc56 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Wed, 25 Oct 2023 22:58:25 +0200 Subject: [PATCH 019/241] Cw 473 exchange refactoring (#1126) * CW-473 Remove deprecated Exchanges * CW-473 Clean up Exchange Code * CW-473 Add Decimals to Crypto Enums * CW-473 Fix minor merge error * CW-473 Fix minor merge error * CW-473 Fix FAQ Locals * CW-473 Apply requested changes * CW-473 Show Error if Exchange Provider is not supported anymore * CW-473 Implement Requested Changes --- assets/faq/faq_de.json | 26 +- assets/faq/faq_en.json | 4 +- assets/faq/faq_es.json | 4 +- assets/faq/faq_fr.json | 2 +- assets/faq/faq_hi.json | 4 +- assets/faq/faq_ja.json | 4 +- assets/faq/faq_ko.json | 4 +- assets/faq/faq_nl.json | 4 +- assets/faq/faq_pl.json | 4 +- assets/faq/faq_pt.json | 4 +- assets/faq/faq_ru.json | 4 +- assets/faq/faq_uk.json | 4 +- assets/faq/faq_zh.json | 4 +- cw_core/lib/crypto_currency.dart | 180 +++++----- cw_core/lib/erc20_token.dart | 2 + lib/exchange/changenow/changenow_request.dart | 22 -- lib/exchange/exchange_pair.dart | 5 +- .../exchange_provider_description.dart | 4 - lib/exchange/exchange_trade_state.dart | 3 +- lib/exchange/exolix/exolix_request.dart | 20 -- lib/exchange/limits.dart | 4 +- lib/exchange/limits_state.dart | 1 - .../morphtoken_exchange_provider.dart | 225 ------------- .../morphtoken/morphtoken_request.dart | 18 - .../changenow_exchange_provider.dart | 194 +++++------ .../{ => provider}/exchange_provider.dart | 36 +- .../exolix_exchange_provider.dart | 170 ++++------ .../sideshift_exchange_provider.dart | 318 ++++++++---------- .../simpleswap_exchange_provider.dart | 220 ++++++------ .../trocador_exchange_provider.dart | 244 ++++++-------- lib/exchange/sideshift/sideshift_request.dart | 17 - .../simpleswap/simpleswap_request.dart | 21 -- lib/exchange/trade.dart | 21 +- ....dart => trade_not_created_exception.dart} | 9 +- lib/exchange/trade_not_found_exception.dart | 13 + lib/exchange/trade_not_found_exeption.dart | 20 -- lib/exchange/trade_request.dart | 21 +- lib/exchange/trade_state.dart | 13 +- lib/exchange/trocador/trocador_request.dart | 21 -- lib/exchange/utils/currency_pairs_utils.dart | 12 + .../xmrto/xmrto_exchange_provider.dart | 236 ------------- lib/exchange/xmrto/xmrto_trade_request.dart | 22 -- .../exchange/exchange_template_page.dart | 50 ++- .../trade_details/trade_details_page.dart | 73 ++-- .../trade_provider_unsupported_item.dart | 5 + .../exchange/exchange_trade_view_model.dart | 49 ++- .../exchange/exchange_view_model.dart | 224 ++++-------- lib/view_model/trade_details_view_model.dart | 51 ++- res/values/strings_ar.arb | 4 +- res/values/strings_bg.arb | 4 +- res/values/strings_cs.arb | 4 +- res/values/strings_de.arb | 8 +- 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_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_yo.arb | 4 +- res/values/strings_zh.arb | 4 +- 74 files changed, 941 insertions(+), 1783 deletions(-) delete mode 100644 lib/exchange/changenow/changenow_request.dart delete mode 100644 lib/exchange/exolix/exolix_request.dart delete mode 100644 lib/exchange/morphtoken/morphtoken_exchange_provider.dart delete mode 100644 lib/exchange/morphtoken/morphtoken_request.dart rename lib/exchange/{changenow => provider}/changenow_exchange_provider.dart (79%) rename lib/exchange/{ => provider}/exchange_provider.dart (71%) rename lib/exchange/{exolix => provider}/exolix_exchange_provider.dart (76%) rename lib/exchange/{sideshift => provider}/sideshift_exchange_provider.dart (75%) rename lib/exchange/{simpleswap => provider}/simpleswap_exchange_provider.dart (72%) rename lib/exchange/{trocador => provider}/trocador_exchange_provider.dart (78%) delete mode 100644 lib/exchange/sideshift/sideshift_request.dart delete mode 100644 lib/exchange/simpleswap/simpleswap_request.dart rename lib/exchange/{trade_not_created_exeption.dart => trade_not_created_exception.dart} (61%) create mode 100644 lib/exchange/trade_not_found_exception.dart delete mode 100644 lib/exchange/trade_not_found_exeption.dart delete mode 100644 lib/exchange/trocador/trocador_request.dart create mode 100644 lib/exchange/utils/currency_pairs_utils.dart delete mode 100644 lib/exchange/xmrto/xmrto_exchange_provider.dart delete mode 100644 lib/exchange/xmrto/xmrto_trade_request.dart create mode 100644 lib/src/screens/trade_details/trade_provider_unsupported_item.dart diff --git a/assets/faq/faq_de.json b/assets/faq/faq_de.json index be9b567b7..14d703e4f 100644 --- a/assets/faq/faq_de.json +++ b/assets/faq/faq_de.json @@ -1,7 +1,7 @@ [ { "question" : "Was ist der Unterschied zwischen verfügbarem Guthaben und vollständigem Guthaben?", - "answer" : "Nachdem Sie eine Transaktion getätigt oder Monero erhalten haben, muss die Transaktion noch bestätigt werden. In ungefähr 20 Minuten sollte Ihr \"verfügbares Guthaben\" aktualisiert werden!\nWenn Sie Monero senden, verringert sich manchmal Ihr verfügbares Guthaben um mehr als den Betrag, den Sie gesendet haben. Dies ist normal und zum Schutz Ihrer Privatsphäre erforderlich. Ihr \"vollständiges Gleichgewicht\" sollte in 20 Minuten wieder normal sein.\n" + "answer" : "Nachdem Sie eine Transaktion getätigt oder Monero erhalten haben, muss die Transaktion noch bestätigt werden. In ungefähr 20 Minuten sollte Ihr \"verfügbares Guthaben\" aktualisiert werden!\nWenn Sie Monero senden, verringert sich manchmal Ihr verfügbares Guthaben um mehr als den Betrag, den Sie gesendet haben. Dies ist normal und zum Schutz Ihrer Privatsphäre erforderlich. Ihr \"vollständiges Guthaben\" sollte in 20 Minuten wieder normal sein.\n" }, { "question" : "Wie sende ich Monero an eine Börse, für die eine Zahlungs-ID erforderlich ist?", @@ -12,24 +12,24 @@ "answer" : "Obwohl unser Support Sie bei diesem Problem nicht direkt unterstützen kann, ist es ein sehr häufiges Problem, mit dem die meisten Börsen vertraut sind. Wenden Sie sich einfach an den Support der Börse, erklären Sie, dass Sie vergessen haben, Ihre Zahlungs-ID anzugeben, und senden Sie ihnen dann Ihre Transaktions-ID als Nachweis. Sie finden die Transaktions-ID, indem Sie auf die Transaktion in Ihrem Wallet-Bildschirm tippen.\n" }, { - "question" : "Was bedeuten \"Samen\" und \"Schlüssel\"?", - "answer" : "Ihre Schlüssel verschlüsseln die privaten Informationen in Ihrer Brieftasche und ermöglichen es Ihnen, Münzen auszugeben und eingehende Transaktionen anzuzeigen.\nIhr Startwert ist nur eine Version Ihres privaten Schlüssels, die so geschrieben wurde, dass Sie sie leichter notieren können. Ihr Same und Schlüssel sind tatsächlich dasselbe, nur in verschiedenen Formen!\nGeben Sie niemals Ihren Samen oder Schlüssel an jemanden weiter. Ihr Geld wird gestohlen, wenn Sie Ihren Samen oder Schlüssel herausgeben. Bitte notieren Sie sich jedoch Ihren Samen und bewahren Sie ihn an einem sicheren Ort auf (so können Sie Ihre Brieftasche wiederherstellen, wenn Sie Ihr Telefon verlieren.)\n" + "question" : "Was bedeuten \"Seed\" und \"Schlüssel\"?", + "answer" : "Ihre Schlüssel verschlüsseln die privaten Informationen in Ihrer Brieftasche und ermöglichen es Ihnen, Münzen auszugeben und eingehende Transaktionen anzuzeigen.\nIhr Startwert ist nur eine Version Ihres privaten Schlüssels, die so geschrieben wurde, dass Sie sie leichter notieren können. Ihr Same und Schlüssel sind tatsächlich dasselbe, nur in verschiedenen Formen!\nGeben Sie niemals Ihren Seed oder Schlüssel an jemanden weiter. Ihr Geld wird gestohlen, wenn Sie Ihren Seed oder Schlüssel herausgeben. Bitte notieren Sie sich jedoch Ihren Seed und bewahren Sie ihn an einem sicheren Ort auf (so können Sie Ihr Wallet wiederherstellen, wenn Sie Ihr Telefon verlieren.)\n" }, { "question" : "Wie viele Geldbörsen kann ich erstellen?", "answer" : "Es gibt keine Grenzen! Sie können so viele Brieftaschen erstellen, wie Sie möchten.\n" }, { - "question" : "Wie kann ich meine Brieftasche wiederherstellen?", - "answer" : "Tippen Sie auf das Menü •••, wählen Sie „Brieftaschen“ und dann „Brieftasche wiederherstellen“. Geben Sie dann Ihren Startwert (oder Ihre Schlüssel) und optional ein Datum vor der ersten Transaktion in Ihrer Brieftasche ein (dies beschleunigt den Synchronisierungsvorgang) .) Möglicherweise müssen Sie die App 15 bis 30 Minuten geöffnet lassen, um Ihr Portemonnaie vollständig wiederherzustellen.\n" + "question" : "Wie kann ich mein Wallet wiederherstellen?", + "answer" : "Tippen Sie auf das Menü •••, wählen Sie „Wallest“ und dann „Wallet wiederherstellen“. Geben Sie dann Ihren Seed (oder Ihre Schlüssel) und optional ein Datum vor der ersten Transaktion in Ihrem Wallet ein (dies beschleunigt den Synchronisierungsvorgang) .) Möglicherweise müssen Sie die App 15 bis 30 Minuten geöffnet lassen, um Ihr Wallet vollständig wiederherzustellen.\n" }, { - "question" : "Was kann ich tun, wenn ich meinen Samen verliere?", - "answer" : "Wenn Sie Ihren Samen vergessen haben, haben Sie ihn wahrscheinlich irgendwo aufgeschrieben. Bitte überprüfen Sie Ihre Notizen und schauen Sie sich auf Ihrem Computer um. Wenn Sie es nirgendwo finden, haben Sie möglicherweise Cake Wallet gesichert (in diesem Fall können Sie es aus diesem Backup wiederherstellen.) Wenn keines dieser Probleme auftritt, können wir leider nichts tun.\n" + "question" : "Was kann ich tun, wenn ich meinen Seed verliere?", + "answer" : "Wenn Sie Ihren Seed vergessen haben, haben Sie ihn wahrscheinlich irgendwo aufgeschrieben. Bitte überprüfen Sie Ihre Notizen und schauen Sie sich auf Ihrem Computer um. Wenn Sie es nirgendwo finden, haben Sie möglicherweise Cake Wallet gesichert (in diesem Fall können Sie es aus diesem Backup wiederherstellen.) Wenn keines dieser Probleme auftritt, können wir leider nichts tun.\n" }, { - "question" : "Sammeln Sie Informationen zu meiner Brieftasche?", - "answer" : "Cake Wallet sammelt oder zeichnet keine Informationen über Ihre Brieftasche auf. Ihre Privatsphäre ist uns wichtig.\n" + "question" : "Sammeln Sie Informationen zu meinem Wallet?", + "answer" : "Cake Wallet sammelt oder zeichnet keine Informationen über Ihr Wallet auf. Ihre Privatsphäre ist uns wichtig.\n" }, { "question" : "Kann ich eine Transaktion stornieren?", @@ -37,7 +37,7 @@ }, { "question" : "Was sind Subadressen und wie verwende ich sie?", - "answer" : "Eine Unteradresse ist im Grunde eine eindeutige Adresse, die Sie jederzeit generieren können. An sie gesendete Münzen landen weiterhin in Ihrer Hauptbrieftasche, aber die Person, die die Münzen sendet, kann Ihre Hauptadresse nicht ermitteln. Unteradressen beginnen immer mit „8“.\nSie können eine neue Unteradresse im Empfangsbildschirm erstellen, indem Sie auf das „+“ neben der Schaltfläche Unteradressen tippen. Geben Sie einen Namen für die Unteradresse ein und tippen Sie auf \"Hinzufügen\". Dann tippen Sie einfach auf den Namen der Subadresse, wenn Sie ihn verwenden möchten!\nWenn Sie paranoid sind, sollten Sie wahrscheinlich jedes Mal, wenn Sie Monero erhalten, eine neue Unteradresse erstellen.\n" + "answer" : "Eine Unteradresse ist im Grunde eine eindeutige Adresse, die Sie jederzeit generieren können. An sie gesendete Münzen landen weiterhin in Ihrer Hauptwallet, aber die Person, die die Coins sendet, kann Ihre Hauptadresse nicht ermitteln. Unteradressen beginnen immer mit „8“.\nSie können eine neue Unteradresse im Empfangsbildschirm erstellen, indem Sie auf das „+“ neben der Schaltfläche Unteradressen tippen. Geben Sie einen Namen für die Unteradresse ein und tippen Sie auf \"Hinzufügen\". Dann tippen Sie einfach auf den Namen der Subadresse, wenn Sie ihn verwenden möchten!\nWenn Sie paranoid sind, sollten Sie wahrscheinlich jedes Mal, wenn Sie Monero erhalten, eine neue Unteradresse erstellen.\n" }, { "question" : "Was ist eine Transaktions-ID?", @@ -48,11 +48,11 @@ "answer" : "Wenn Sie Ihren Monero nicht erhalten haben, möchten Sie möglicherweise auf das Menü ••• tippen und auf Reconnect (Neu verbinden) klicken. Wenn dies nicht funktioniert, gehen Sie in das Einstellungsmenü, tippen Sie auf das Feld \"Aktueller Knoten\" und wählen Sie einen Knoten mit einem grünen Punkt daneben aus.\n" }, { - "question" : "Ich habe in der App keine Münzen aus dem Umtausch erhalten. Was kann ich tun?", - "answer" : "Wenn Sie Probleme mit einem Austausch haben, wenden Sie sich am besten an den Austausch. Wir sind eine Partnerschaft mit XMR.TO, Morph und ChangeNow eingegangen. Rufen Sie daher am besten http://xmr.to, http://changenow.io oder http://morphtoken.com auf und wenden Sie sich an deren Support.\n" + "question" : "Ich habe in der App keine Coins aus dem Umtausch erhalten. Was kann ich tun?", + "answer" : "Wenn Sie Probleme mit einem Austausch haben, besteht die beste Option, den Austausch selbst zu kontaktieren. Wir haben uns mit Chechenow, Simpleswap, Sideshift und Trocador zusammengetan. Am besten wechseln Sie zu https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ und kontaktieren Sie ihre Unterstützung.\n" }, { "question" : "Wie kontaktiere ich den Cake Wallet-Support?", "answer" : "Senden Sie eine E-Mail an support@cakewallet.com, schließen Sie sich dem Telegramm unter @cakewallet_bot an oder twittern Sie @CakeWalletXMR!\n" } -] \ No newline at end of file +] diff --git a/assets/faq/faq_en.json b/assets/faq/faq_en.json index aae40802c..741d31798 100644 --- a/assets/faq/faq_en.json +++ b/assets/faq/faq_en.json @@ -49,10 +49,10 @@ }, { "question" : "I didn't receive my coins from the exchange in the app. What can I do?", - "answer" : "If you're having issues with an exchange, the best option is to contact the exchange itself. We're partnered with XMR.TO, Morph and ChangeNow, so your best bet is to go to http://xmr.to, http://changenow.io, or http://morphtoken.com and contact their support.\n" + "answer" : "If you're having issues with an exchange, the best option is to contact the exchange itself. We're partnered with ChangeNow, SimpleSwap, SideShift and Trocador. So your best bet is to go to https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ and contact their support.\n" }, { "question" : "How do I contact Cake Wallet support?", "answer" : "Email support@cakewallet.com, join the Telegram at @cakewallet_bot, or tweet @CakeWalletXMR!\n" } -] \ No newline at end of file +] diff --git a/assets/faq/faq_es.json b/assets/faq/faq_es.json index 28074662c..968853a0b 100644 --- a/assets/faq/faq_es.json +++ b/assets/faq/faq_es.json @@ -49,10 +49,10 @@ }, { "question" : "No recibí mis monedas del intercambio en la aplicación. ¿Que puedo hacer?", - "answer" : "Si tiene problemas con un intercambio, la mejor opción es ponerse en contacto con el intercambio en sí. Estamos asociados con XMR.TO, Morph y ChangeNow, por lo que su mejor opción es ir a http://xmr.to, http://changenow.io o http://morphtoken.com y contactar a su soporte.\n" + "answer" : "Si tiene problemas con un intercambio, la mejor opción es comunicarse con el intercambio en sí. Estamos asociados con ChangeNow, SimpleSwap, SideShift y Trocador. Entonces, su mejor opción es ir a https://changenow.io, https://simplewap.io/, https://sideshift.ai/, https://trocador.app/ y contactar su soporte.\n" }, { "question" : "¿Cómo contacto al soporte de Cake Wallet?", "answer" : "¡Envíe un correo electrónico a support@cakewallet.com, únase al Telegram en @cakewallet_bot o envíe un tweet a @CakeWalletXMR!\n" } -] \ No newline at end of file +] diff --git a/assets/faq/faq_fr.json b/assets/faq/faq_fr.json index cc4e52873..6b6ac5227 100644 --- a/assets/faq/faq_fr.json +++ b/assets/faq/faq_fr.json @@ -50,7 +50,7 @@ }, { "question" : "Je n'ai pas reçu mes fonds en provenance de la plateforme d'échange dans l'application. Que puis-je faire ?", - "answer" : "Si vous avez des soucis avec une plateforme d'échange, le mieux est de contacter la plateforme d'échange directement. Nous avons des partenariats avec XMR.TO, Morph et ChangeNow, donc essayez http://xmr.to, http://changenow.io, ou http://morphtoken.com et contactez leur support.\n" + "answer" : "Si vous rencontrez des problèmes avec un échange, la meilleure option est de contacter l'échange lui-même. Nous sommes en partenariat avec Changenow, Simpleswap, Sideshift et le Trocador. Donc, votre meilleur pari est d'aller sur https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ et contactez leur support.\n" }, { "question" : "Comment puis-je contacter le support de Cake Wallet ?", diff --git a/assets/faq/faq_hi.json b/assets/faq/faq_hi.json index cd9eb3fb9..f1ede3374 100644 --- a/assets/faq/faq_hi.json +++ b/assets/faq/faq_hi.json @@ -49,10 +49,10 @@ }, { "question" : "मुझे ऐप में एक्सचेंज से मेरे सिक्के नहीं मिले। मैं क्या कर सकता हूँ?", - "answer" : "यदि आप एक एक्सचेंज के साथ समस्या कर रहे हैं, तो सबसे अच्छा विकल्प एक्सचेंज से संपर्क करना है। हम XMR.TO, Morph और ChangeNow के साथ भागीदारी कर रहे हैं, इसलिए आपका सबसे अच्छा दांव http://xmr.to, http://changenow.io, या http://morphtoken.com पर जाना है और उनके समर्थन से संपर्क करना है।\n" + "answer" : "यदि आप एक एक्सचेंज के साथ समस्याएं कर रहे हैं, तो सबसे अच्छा विकल्प एक्सचेंज से संपर्क करना है। हम चंगेनो, सिम्प्लेवैप, सिडशिफ्ट और ट्रोकैडर के साथ भागीदारी कर रहे हैं। तो आपका सबसे अच्छा दांव https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ पर जाना और उनके समर्थन से संपर्क करना है।\n" }, { "question" : "मैं केक वॉलेट से कैसे संपर्क करूं?", "answer" : "ईमेल support@cakewallet.com, @cakewallet_bot पर टेलीग्राम में शामिल हों, या @CakeWalletXMR पर ट्वीट करें!\n" } -] \ No newline at end of file +] diff --git a/assets/faq/faq_ja.json b/assets/faq/faq_ja.json index 8a5b48763..6d83e61d3 100644 --- a/assets/faq/faq_ja.json +++ b/assets/faq/faq_ja.json @@ -49,10 +49,10 @@ }, { "question" : "アプリの取引所からコインを受け取りませんでした。 私に何ができる?", - "answer" : "取引所に問題がある場合、最良の選択肢は取引所自体に連絡することです。 XMR.TO、Morph、ChangeNowと提携しているため、最善の策はhttp://xmr.to、http://changenow.io、またはhttp://morphtoken.comにアクセスしてサポートに連絡することです。\n" + "answer" : "交換に問題がある場合、最良の選択肢は、交換自体に連絡することです。 Changenow、SimpleSwap、Sideshift、Trocadorと提携しています。したがって、あなたの最善の策は、https://changenow.io、https://simpleswap.io/、https://sideshift.ai/、https://trocador.app/に行くことです。\n" }, { "question" : "Cake Walletサポートに連絡するにはどうすればよいですか?", "answer" : "support@cakewallet.comにメールを送信するか、@cakewallet_botで電報に参加するか、@CakeWalletXMRにツイートしてください。\n" } -] \ No newline at end of file +] diff --git a/assets/faq/faq_ko.json b/assets/faq/faq_ko.json index 7d6f36589..640567284 100644 --- a/assets/faq/faq_ko.json +++ b/assets/faq/faq_ko.json @@ -49,10 +49,10 @@ }, { "question" : "앱의 거래소에서 동전을받지 못했습니다. 내가 무엇을 할 수 있을지?", - "answer" : "교환에 문제가있는 경우 교환기에 연락하는 것이 가장 좋습니다. 우리는 XMR.TO, Morph 및 ChangeNow와 파트너 관계를 맺고 있으므로 가장 좋은 방법은 http://xmr.to, http://changenow.io 또는 http://morphtoken.com으로 이동하여 지원 부서에 문의하는 것입니다.\n" + "answer" : "교환에 문제가있는 경우 가장 좋은 선택은 Exchange 자체에 연락하는 것입니다. 우리는 Changenow, Simpleswap, Sideshift 및 Trocador와 파트너 관계를 맺고 있습니다. 따라서 가장 좋은 방법은 https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/로 이동하여 지원에 연락하는 것입니다.\n" }, { "question" : "Cake Wallet 지원팀에 연락하려면 어떻게해야합니까?", "answer" : "support@cakewallet.com로 이메일을 보내거나 @cakewallet_bot에서 전보에 가입하거나 @CakeWalletXMR을 트윗하십시오!\n" } -] \ No newline at end of file +] diff --git a/assets/faq/faq_nl.json b/assets/faq/faq_nl.json index bb4f70216..47cf8fdf0 100644 --- a/assets/faq/faq_nl.json +++ b/assets/faq/faq_nl.json @@ -49,10 +49,10 @@ }, { "question" : "Ik heb mijn munten niet ontvangen van de beurs in de app. Wat kan ik doen?", - "answer" : "Als u problemen ondervindt met een uitwisseling, kunt u het beste contact opnemen met de uitwisseling zelf. We werken samen met XMR.TO, Morph en ChangeNow, dus u kunt het beste naar http://xmr.to, http://changenow.io of http://morphtoken.com gaan en contact opnemen met hun ondersteuning.\n" + "answer" : "Als u problemen heeft met een uitwisseling, is de beste optie om contact op te nemen met de uitwisseling zelf. We werken samen met ChangeNow, SimpleSwap, SideShift en Trocador. Dus het beste is om naar https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ te gaan en contact op te nemen met hun ondersteuning.\n" }, { "question" : "Hoe neem ik contact op met Cake Wallet-ondersteuning?", "answer" : "E-mail support@cakewallet.com, word lid van het Telegram op @cakewallet_bot of tweet @CakeWalletXMR!\n" } -] \ No newline at end of file +] diff --git a/assets/faq/faq_pl.json b/assets/faq/faq_pl.json index 1934f4d1a..a38d79068 100644 --- a/assets/faq/faq_pl.json +++ b/assets/faq/faq_pl.json @@ -49,10 +49,10 @@ }, { "question" : "Nie otrzymałem moich monet z wymiany w aplikacji. Co mogę zrobić?", - "answer" : "Jeśli masz problemy z wymianą, najlepszym rozwiązaniem jest skontaktowanie się z samą giełdą. Współpracujemy z XMR.TO, Morph i ChangeNow, więc najlepiej postawić się na stronie http://xmr.to, http://changenow.io lub http://morphtoken.com i skontaktować się z ich wsparciem.\n" + "answer" : "Jeśli masz problemy z wymianą, najlepszą opcją jest skontaktowanie się z samą wymianą. Współpracujemy z Changenow, Simpleswap, Sideshift i Trocador. Więc najlepszym rozwiązaniem jest przejście na https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ i skontaktować się z ich obsługą.\n" }, { "question" : "Jak skontaktować się z obsługą Cake Wallet?", "answer" : "Wyślij e-mail na adres support@cakewallet.com, dołącz do telegramu na @cakewallet_bot lub tweet @CakeWalletXMR!\n" } -] \ No newline at end of file +] diff --git a/assets/faq/faq_pt.json b/assets/faq/faq_pt.json index 06ddab25e..66d3a6aaf 100644 --- a/assets/faq/faq_pt.json +++ b/assets/faq/faq_pt.json @@ -49,10 +49,10 @@ }, { "question" : "Não recebi minhas moedas da troca no aplicativo. O que eu posso fazer?", - "answer" : "Se você estiver tendo problemas com uma troca, a melhor opção é entrar em contato com a troca. Somos parceiros do XMR.TO, Morph e ChangeNow, portanto, sua melhor aposta é ir para http://xmr.to, http://changenow.io ou http://morphtoken.com e entrar em contato com o suporte deles.\n" + "answer" : "Se você estiver com problemas com uma troca, a melhor opção é entrar em contato com a própria troca. Estamos em parceria com ChangeNow, SimpleSwap, Sideshift e Trocador. Portanto, sua melhor aposta é ir para https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ e entre em contato com seu suporte.\n" }, { "question" : "Como entro em contato com o suporte da Cake Wallet?", "answer" : "Envie um e-mail para support@cakewallet.com, participe do Telegram em @cakewallet_bot ou envie um tweet para @CakeWalletXMR!\n" } -] \ No newline at end of file +] diff --git a/assets/faq/faq_ru.json b/assets/faq/faq_ru.json index 4b8b18e32..af5ba32a6 100644 --- a/assets/faq/faq_ru.json +++ b/assets/faq/faq_ru.json @@ -49,10 +49,10 @@ }, { "question" : "Я не получил свои монеты после обмена в приложении. Что я могу сделать?", - "answer" : "Если у вас возникли проблемы с обменом, лучше всего связаться с провайдером обмена. Мы сотрудничаем с XMR.TO, Morph и ChangeNow, поэтому вам лучше всего зайти на http://xmr.to, http://changenow.io или http://morphtoken.com и связаться с их поддержкой.\n" + "answer" : "Если у вас есть проблемы с обменом, лучший вариант - связаться с самой биржей. Мы сотрудничаем с Changenow, Simpleswap, SideShift и Trocador. Так что лучше всего пойти по адресу https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ и свяжитесь с их поддержкой.\n" }, { "question" : "Как мне связаться со службой поддержки Cake Wallet?", "answer" : "По электронной почте support@cakewallet.com, присоединитесь к Telegram по адресу @cakewallet_bot или отправьте твит @CakeWalletXMR!\n" } -] \ No newline at end of file +] diff --git a/assets/faq/faq_uk.json b/assets/faq/faq_uk.json index c481e0538..3e209d2ad 100644 --- a/assets/faq/faq_uk.json +++ b/assets/faq/faq_uk.json @@ -49,10 +49,10 @@ }, { "question" : "Я не отримав свої монети після обміну в додатку. Що я можу зробити?", - "answer" : "Якщо у вас виникли проблеми з обміном, найкраще зв'язатися з провайдером обміну. Ми співпрацюємо з XMR.TO, Morph і ChangeNow, тому вам найкраще зайти на http://xmr.to, http://changenow.io або http://morphtoken.com і зв'язатися з їх підтримкою.\n" + "answer" : "Якщо у вас є проблеми з обміном, найкращим варіантом є зв’язок із самою біржею. Ми співпрацюємо з Changenow, Simplewap, Sideshift та Trocador. Тож найкраща ставка - перейти на https://changenow.io, https://simpleswap.io/, https://sideshift.ai/, https://trocador.app/ та звернутися до їх підтримки.\n" }, { "question" : "Як мені зв'язатися зі службою підтримки Cake Wallet?", "answer" : "По електронній пошті support@cakewallet.com, приєднайтеся до Telegram за адресою @cakewallet_bot або надішліть твіт @CakeWalletXMR!\n" } -] \ No newline at end of file +] diff --git a/assets/faq/faq_zh.json b/assets/faq/faq_zh.json index 22977f22c..8debe1873 100644 --- a/assets/faq/faq_zh.json +++ b/assets/faq/faq_zh.json @@ -49,10 +49,10 @@ }, { "question" : "我没有从应用程序中的交易所收到硬币。 我能做什么?", - "answer" : "如果您对交易所有疑问,最好的选择是与交易所本身联系。 我们与XMR.TO,Morph和ChangeNow合作,因此最好的选择是访问http://xmr.to、http://changenow.io或http://morphtoken.com,并与他们的支持部门联系。\n" + "answer" : "如果您对交易所有问题,最好的选择是与交易所本身联系。我们与ChangeNow,SimplesWap,SideShift和Trocador合作。因此,最好的选择是访问https://changenow.io,https://simpleswap.io/,https://sideshift.ai/,https://trocador.app/并联系他们的支持。\n" }, { "question" : "如何联系蛋糕钱包支持?", "answer" : "电子邮件support@cakewallet.com,通过@cakewallet_bot加入电报,或在@CakeWalletXMR上发布推文!\n" } -] \ No newline at end of file +] diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index f6ffcdc8b..1936a87cf 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -6,6 +6,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen String title = '', int raw = -1, required this.name, + required this.decimals, this.fullName, this.iconPath, this.tag}) @@ -15,6 +16,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen final String? tag; final String? fullName; final String? iconPath; + final int decimals; static const all = [ CryptoCurrency.xmr, @@ -110,96 +112,96 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen ]; // title, tag (if applicable), fullName (if unique), raw, name, iconPath - static const xmr = CryptoCurrency(title: 'XMR', fullName: 'Monero', raw: 0, name: 'xmr', iconPath: 'assets/images/monero_icon.png'); - static const ada = CryptoCurrency(title: 'ADA', fullName: 'Cardano', raw: 1, name: 'ada', iconPath: 'assets/images/ada_icon.png'); - static const bch = CryptoCurrency(title: 'BCH', fullName: 'Bitcoin Cash', raw: 2, name: 'bch', iconPath: 'assets/images/bch_icon.png'); - static const bnb = CryptoCurrency(title: 'BNB', tag: 'BSC', fullName: 'Binance Coin', raw: 3, name: 'bnb', iconPath: 'assets/images/bnb_icon.png'); - static const btc = CryptoCurrency(title: 'BTC', fullName: 'Bitcoin', raw: 4, name: 'btc', iconPath: 'assets/images/btc.png'); - static const dai = CryptoCurrency(title: 'DAI', tag: 'ETH', fullName: 'Dai', raw: 5, name: 'dai', iconPath: 'assets/images/dai_icon.png'); - static const dash = CryptoCurrency(title: 'DASH', fullName: 'Dash', raw: 6, name: 'dash', iconPath: 'assets/images/dash_icon.png'); - static const eos = CryptoCurrency(title: 'EOS', fullName: 'EOS', raw: 7, name: 'eos', iconPath: 'assets/images/eos_icon.png'); - static const eth = CryptoCurrency(title: 'ETH', fullName: 'Ethereum', raw: 8, name: 'eth', iconPath: 'assets/images/eth_icon.png'); - static const ltc = CryptoCurrency(title: 'LTC', fullName: 'Litecoin', raw: 9, name: 'ltc', iconPath: 'assets/images/litecoin-ltc_icon.png'); - static const nano = CryptoCurrency(title: 'XNO', raw: 10, fullName: 'Nano', name: 'xno', iconPath: 'assets/images/nano_icon.png'); - static const trx = CryptoCurrency(title: 'TRX', fullName: 'TRON', raw: 11, name: 'trx', iconPath: 'assets/images/trx_icon.png'); - static const usdt = CryptoCurrency(title: 'USDT', tag: 'OMNI', fullName: 'USDT Tether', raw: 12, name: 'usdt', iconPath: 'assets/images/usdt_icon.png'); - static const usdterc20 = CryptoCurrency(title: 'USDT', tag: 'ETH', fullName: 'USDT Tether', raw: 13, name: 'usdterc20', iconPath: 'assets/images/usdterc20_icon.png'); - static const xlm = CryptoCurrency(title: 'XLM', fullName: 'Stellar', raw: 14, name: 'xlm', iconPath: 'assets/images/xlm_icon.png'); - static const xrp = CryptoCurrency(title: 'XRP', fullName: 'Ripple', raw: 15, name: 'xrp', iconPath: 'assets/images/xrp_icon.png'); - static const xhv = CryptoCurrency(title: 'XHV', fullName: 'Haven Protocol', raw: 16, name: 'xhv', iconPath: 'assets/images/xhv_logo.png'); + static const xmr = CryptoCurrency(title: 'XMR', fullName: 'Monero', raw: 0, name: 'xmr', iconPath: 'assets/images/monero_icon.png', decimals: 12); + static const ada = CryptoCurrency(title: 'ADA', fullName: 'Cardano', raw: 1, name: 'ada', iconPath: 'assets/images/ada_icon.png', decimals: 6); + static const bch = CryptoCurrency(title: 'BCH', fullName: 'Bitcoin Cash', raw: 2, name: 'bch', iconPath: 'assets/images/bch_icon.png', decimals: 8); + static const bnb = CryptoCurrency(title: 'BNB', tag: 'BSC', fullName: 'Binance Coin', raw: 3, name: 'bnb', iconPath: 'assets/images/bnb_icon.png', decimals: 8); + static const btc = CryptoCurrency(title: 'BTC', fullName: 'Bitcoin', raw: 4, name: 'btc', iconPath: 'assets/images/btc.png', decimals: 8); + static const dai = CryptoCurrency(title: 'DAI', tag: 'ETH', fullName: 'Dai', raw: 5, name: 'dai', iconPath: 'assets/images/dai_icon.png', decimals: 18); + static const dash = CryptoCurrency(title: 'DASH', fullName: 'Dash', raw: 6, name: 'dash', iconPath: 'assets/images/dash_icon.png', decimals: 8); + static const eos = CryptoCurrency(title: 'EOS', fullName: 'EOS', raw: 7, name: 'eos', iconPath: 'assets/images/eos_icon.png', decimals: 4); + static const eth = CryptoCurrency(title: 'ETH', fullName: 'Ethereum', raw: 8, name: 'eth', iconPath: 'assets/images/eth_icon.png', decimals: 18); + static const ltc = CryptoCurrency(title: 'LTC', fullName: 'Litecoin', raw: 9, name: 'ltc', iconPath: 'assets/images/litecoin-ltc_icon.png', decimals: 8); + static const nano = CryptoCurrency(title: 'XNO', fullName: 'Nano', raw: 10, name: 'xno', iconPath: 'assets/images/nano_icon.png', decimals: 30); + static const trx = CryptoCurrency(title: 'TRX', fullName: 'TRON', raw: 11, name: 'trx', iconPath: 'assets/images/trx_icon.png', decimals: 6); + static const usdt = CryptoCurrency(title: 'USDT', tag: 'OMNI', fullName: 'USDT Tether', raw: 12, name: 'usdt', iconPath: 'assets/images/usdt_icon.png', decimals: 6); + static const usdterc20 = CryptoCurrency(title: 'USDT', tag: 'ETH', fullName: 'USDT Tether', raw: 13, name: 'usdterc20', iconPath: 'assets/images/usdterc20_icon.png', decimals: 6); + static const xlm = CryptoCurrency(title: 'XLM', fullName: 'Stellar', raw: 14, name: 'xlm', iconPath: 'assets/images/xlm_icon.png', decimals: 7); + static const xrp = CryptoCurrency(title: 'XRP', fullName: 'Ripple', raw: 15, name: 'xrp', iconPath: 'assets/images/xrp_icon.png', decimals: 6); + static const xhv = CryptoCurrency(title: 'XHV', fullName: 'Haven Protocol', raw: 16, name: 'xhv', iconPath: 'assets/images/xhv_logo.png', decimals: 12); - static const xag = CryptoCurrency(title: 'XAG', tag: 'XHV', raw: 17, name: 'xag'); - static const xau = CryptoCurrency(title: 'XAU', tag: 'XHV', raw: 18, name: 'xau'); - static const xaud = CryptoCurrency(title: 'XAUD', tag: 'XHV', raw: 19, name: 'xaud'); - static const xbtc = CryptoCurrency(title: 'XBTC', tag: 'XHV', raw: 20, name: 'xbtc'); - static const xcad = CryptoCurrency(title: 'XCAD', tag: 'XHV', raw: 21, name: 'xcad'); - static const xchf = CryptoCurrency(title: 'XCHF', tag: 'XHV', raw: 22, name: 'xchf'); - static const xcny = CryptoCurrency(title: 'XCNY', tag: 'XHV', raw: 23, name: 'xcny'); - static const xeur = CryptoCurrency(title: 'XEUR', tag: 'XHV', raw: 24, name: 'xeur'); - static const xgbp = CryptoCurrency(title: 'XGBP', tag: 'XHV', raw: 25, name: 'xgbp'); - static const xjpy = CryptoCurrency(title: 'XJPY', tag: 'XHV', raw: 26, name: 'xjpy'); - static const xnok = CryptoCurrency(title: 'XNOK', tag: 'XHV', raw: 27, name: 'xnok'); - static const xnzd = CryptoCurrency(title: 'XNZD', tag: 'XHV', raw: 28, name: 'xnzd'); - static const xusd = CryptoCurrency(title: 'XUSD', tag: 'XHV', raw: 29, name: 'xusd'); + static const xag = CryptoCurrency(title: 'XAG', tag: 'XHV', raw: 17, name: 'xag', decimals: 12); + static const xau = CryptoCurrency(title: 'XAU', tag: 'XHV', raw: 18, name: 'xau', decimals: 12); + static const xaud = CryptoCurrency(title: 'XAUD', tag: 'XHV', raw: 19, name: 'xaud', decimals: 12); + static const xbtc = CryptoCurrency(title: 'XBTC', tag: 'XHV', raw: 20, name: 'xbtc', decimals: 12); + static const xcad = CryptoCurrency(title: 'XCAD', tag: 'XHV', raw: 21, name: 'xcad', decimals: 12); + static const xchf = CryptoCurrency(title: 'XCHF', tag: 'XHV', raw: 22, name: 'xchf', decimals: 12); + static const xcny = CryptoCurrency(title: 'XCNY', tag: 'XHV', raw: 23, name: 'xcny', decimals: 12); + static const xeur = CryptoCurrency(title: 'XEUR', tag: 'XHV', raw: 24, name: 'xeur', decimals: 12); + static const xgbp = CryptoCurrency(title: 'XGBP', tag: 'XHV', raw: 25, name: 'xgbp', decimals: 12); + static const xjpy = CryptoCurrency(title: 'XJPY', tag: 'XHV', raw: 26, name: 'xjpy', decimals: 12); + static const xnok = CryptoCurrency(title: 'XNOK', tag: 'XHV', raw: 27, name: 'xnok', decimals: 12); + static const xnzd = CryptoCurrency(title: 'XNZD', tag: 'XHV', raw: 28, name: 'xnzd', decimals: 12); + static const xusd = CryptoCurrency(title: 'XUSD', tag: 'XHV', raw: 29, name: 'xusd', decimals: 12); - static const ape = CryptoCurrency(title: 'APE', tag: 'ETH', fullName: 'ApeCoin', raw: 30, name: 'ape', iconPath: 'assets/images/ape_icon.png'); - static const avaxc = CryptoCurrency(title: 'AVAX', tag: 'AVAXC', raw: 31, name: 'avaxc', iconPath: 'assets/images/avaxc_icon.png'); - static const btt = CryptoCurrency(title: 'BTT', tag: 'ETH', fullName: 'BitTorrent', raw: 32, name: 'btt', iconPath: 'assets/images/btt_icon.png'); - static const bttc = CryptoCurrency(title: 'BTTC', tag: 'TRX', fullName: 'BitTorrent-NEW', raw: 33, name: 'bttc', iconPath: 'assets/images/btt_icon.png'); - static const doge = CryptoCurrency(title: 'DOGE', fullName: 'Dogecoin', raw: 34, name: 'doge', iconPath: 'assets/images/doge_icon.png'); - static const firo = CryptoCurrency(title: 'FIRO', raw: 35, name: 'firo', iconPath: 'assets/images/firo_icon.png'); - static const usdttrc20 = CryptoCurrency(title: 'USDT', tag: 'TRX', fullName: 'USDT Tether', raw: 36, name: 'usdttrc20', iconPath: 'assets/images/usdttrc20_icon.png'); - static const hbar = CryptoCurrency(title: 'HBAR', fullName: 'Hedera', raw: 37, name: 'hbar', iconPath: 'assets/images/hbar_icon.png', ); - static const sc = CryptoCurrency(title: 'SC', fullName: 'Siacoin', raw: 38, name: 'sc', iconPath: 'assets/images/sc_icon.png'); - static const sol = CryptoCurrency(title: 'SOL', fullName: 'Solana', raw: 39, name: 'sol', iconPath: 'assets/images/sol_icon.png'); - static const usdc = CryptoCurrency(title: 'USDC', tag: 'ETH', fullName: 'USD Coin', raw: 40, name: 'usdc', iconPath: 'assets/images/usdc_icon.png'); - static const usdcsol = CryptoCurrency(title: 'USDC', tag: 'SOL', fullName: 'USDC Coin', raw: 41, name: 'usdcsol', iconPath: 'assets/images/usdc_icon.png'); - static const zaddr = CryptoCurrency(title: 'ZZEC', tag: 'ZEC', fullName: 'Shielded Zcash', raw: 42, name: 'zaddr', iconPath: 'assets/images/zec_icon.png'); - static const zec = CryptoCurrency(title: 'TZEC', tag: 'ZEC', fullName: 'Transparent Zcash', raw: 43, name: 'zec', iconPath: 'assets/images/zec_icon.png'); - static const zen = CryptoCurrency(title: 'ZEN', fullName: 'Horizen', raw: 44, name: 'zen', iconPath: 'assets/images/zen_icon.png'); - static const xvg = CryptoCurrency(title: 'XVG', fullName: 'Verge', raw: 45, name: 'xvg', iconPath: 'assets/images/xvg_icon.png'); + static const ape = CryptoCurrency(title: 'APE', tag: 'ETH', fullName: 'ApeCoin', raw: 30, name: 'ape', iconPath: 'assets/images/ape_icon.png', decimals: 18); + static const avaxc = CryptoCurrency(title: 'AVAX', tag: 'AVAXC', fullName: 'Avalanche', raw: 31, name: 'avaxc', iconPath: 'assets/images/avaxc_icon.png', decimals: 9); + static const btt = CryptoCurrency(title: 'BTT', tag: 'ETH', fullName: 'BitTorrent', raw: 32, name: 'btt', iconPath: 'assets/images/btt_icon.png', decimals: 18); + static const bttc = CryptoCurrency(title: 'BTTC', tag: 'TRX', fullName: 'BitTorrent-NEW', raw: 33, name: 'bttc', iconPath: 'assets/images/btt_icon.png', decimals: 18); + static const doge = CryptoCurrency(title: 'DOGE', fullName: 'Dogecoin', raw: 34, name: 'doge', iconPath: 'assets/images/doge_icon.png', decimals: 8); + static const firo = CryptoCurrency(title: 'FIRO', raw: 35, name: 'firo', iconPath: 'assets/images/firo_icon.png', decimals: 8); + static const usdttrc20 = CryptoCurrency(title: 'USDT', tag: 'TRX', fullName: 'USDT Tether', raw: 36, name: 'usdttrc20', iconPath: 'assets/images/usdttrc20_icon.png', decimals: 6); + static const hbar = CryptoCurrency(title: 'HBAR', fullName: 'Hedera', raw: 37, name: 'hbar', iconPath: 'assets/images/hbar_icon.png', decimals: 8); + static const sc = CryptoCurrency(title: 'SC', fullName: 'Siacoin', raw: 38, name: 'sc', iconPath: 'assets/images/sc_icon.png', decimals: 16); + static const sol = CryptoCurrency(title: 'SOL', fullName: 'Solana', raw: 39, name: 'sol', iconPath: 'assets/images/sol_icon.png', decimals: 9); + static const usdc = CryptoCurrency(title: 'USDC', tag: 'ETH', fullName: 'USD Coin', raw: 40, name: 'usdc', iconPath: 'assets/images/usdc_icon.png', decimals: 6); + static const usdcsol = CryptoCurrency(title: 'USDC', tag: 'SOL', fullName: 'USDC Coin', raw: 41, name: 'usdcsol', iconPath: 'assets/images/usdc_icon.png', decimals: 6); + static const zaddr = CryptoCurrency(title: 'ZZEC', tag: 'ZEC', fullName: 'Shielded Zcash', raw: 42, name: 'zaddr', iconPath: 'assets/images/zec_icon.png', decimals: 8); + static const zec = CryptoCurrency(title: 'TZEC', tag: 'ZEC', fullName: 'Transparent Zcash', raw: 43, name: 'zec', iconPath: 'assets/images/zec_icon.png', decimals: 8); + static const zen = CryptoCurrency(title: 'ZEN', fullName: 'Horizen', raw: 44, name: 'zen', iconPath: 'assets/images/zen_icon.png', decimals: 8); + static const xvg = CryptoCurrency(title: 'XVG', fullName: 'Verge', raw: 45, name: 'xvg', iconPath: 'assets/images/xvg_icon.png', decimals: 8); - static const usdcpoly = CryptoCurrency(title: 'USDC', tag: 'POLY', fullName: 'USD Coin', raw: 46, name: 'usdcpoly', iconPath: 'assets/images/usdc_icon.png'); - static const dcr = CryptoCurrency(title: 'DCR', fullName: 'Decred', raw: 47, name: 'dcr', iconPath: 'assets/images/dcr_icon.png'); - static const kmd = CryptoCurrency(title: 'KMD', fullName: 'Komodo', raw: 48, name: 'kmd', iconPath: 'assets/images/kmd_icon.png'); - static const mana = CryptoCurrency(title: 'MANA', tag: 'ETH', fullName: 'Decentraland', raw: 49, name: 'mana', iconPath: 'assets/images/mana_icon.png'); - static const maticpoly = CryptoCurrency(title: 'MATIC', tag: 'POLY', fullName: 'Polygon', raw: 50, name: 'maticpoly', iconPath: 'assets/images/matic_icon.png'); - static const matic = CryptoCurrency(title: 'MATIC', tag: 'ETH', fullName: 'Polygon', raw: 51, name: 'matic', iconPath: 'assets/images/matic_icon.png'); - static const mkr = CryptoCurrency(title: 'MKR', tag: 'ETH', fullName: 'Maker', raw: 52, name: 'mkr', iconPath: 'assets/images/mkr_icon.png'); - static const near = CryptoCurrency(title: 'NEAR', fullName: 'NEAR Protocol', raw: 53, name: 'near', iconPath: 'assets/images/near_icon.png'); - static const oxt = CryptoCurrency(title: 'OXT', tag: 'ETH', fullName: 'Orchid', raw: 54, name: 'oxt', iconPath: 'assets/images/oxt_icon.png'); - static const paxg = CryptoCurrency(title: 'PAXG', tag: 'ETH', fullName: 'Pax Gold', raw: 55, name: 'paxg', iconPath: 'assets/images/paxg_icon.png'); - static const pivx = CryptoCurrency(title: 'PIVX', raw: 56, name: 'pivx', iconPath: 'assets/images/pivx_icon.png'); - static const rune = CryptoCurrency(title: 'RUNE', fullName: 'Thorchain', raw: 57, name: 'rune', iconPath: 'assets/images/rune_icon.png'); - static const rvn = CryptoCurrency(title: 'RVN', fullName: 'Ravencoin', raw: 58, name: 'rvn', iconPath: 'assets/images/rvn_icon.png'); - static const scrt = CryptoCurrency(title: 'SCRT', fullName: 'Secret Network', raw: 59, name: 'scrt', iconPath: 'assets/images/scrt_icon.png'); - static const uni = CryptoCurrency(title: 'UNI', tag: 'ETH', fullName: 'Uniswap', raw: 60, name: 'uni', iconPath: 'assets/images/uni_icon.png'); - static const stx = CryptoCurrency(title: 'STX', fullName: 'Stacks', raw: 61, name: 'stx', iconPath: 'assets/images/stx_icon.png'); - static const btcln = CryptoCurrency(title: 'BTC', tag: 'LN', fullName: 'Bitcoin Lightning Network', raw: 62, name: 'btcln', iconPath: 'assets/images/btc.png'); - static const shib = CryptoCurrency(title: 'SHIB', tag: 'ETH', fullName: 'Shiba Inu', raw: 63, name: 'shib', iconPath: 'assets/images/shib_icon.png'); - static const aave = CryptoCurrency(title: 'AAVE', tag: 'ETH', fullName: 'Aave', raw: 64, name: 'aave', iconPath: 'assets/images/aave_icon.png'); - static const arb = CryptoCurrency(title: 'ARB', fullName: 'Arbitrum', raw: 65, name: 'arb', iconPath: 'assets/images/arb_icon.png'); - static const bat = CryptoCurrency(title: 'BAT', tag: 'ETH', fullName: 'Basic Attention Token', raw: 66, name: 'bat', iconPath: 'assets/images/bat_icon.png'); - static const comp = CryptoCurrency(title: 'COMP', tag: 'ETH', fullName: 'Compound', raw: 67, name: 'comp', iconPath: 'assets/images/comp_icon.png'); - static const cro = CryptoCurrency(title: 'CRO', tag: 'ETH', fullName: 'Crypto.com Cronos', raw: 68, name: 'cro', iconPath: 'assets/images/cro_icon.png'); - static const ens = CryptoCurrency(title: 'ENS', tag: 'ETH', fullName: 'Ethereum Name Service', raw: 69, name: 'ens', iconPath: 'assets/images/ens_icon.png'); - static const ftm = CryptoCurrency(title: 'FTM', tag: 'ETH', fullName: 'Fantom', raw: 70, name: 'ftm', iconPath: 'assets/images/ftm_icon.png'); - static const frax = CryptoCurrency(title: 'FRAX', tag: 'ETH', fullName: 'Frax', raw: 71, name: 'frax', iconPath: 'assets/images/frax_icon.png'); - static const gusd = CryptoCurrency(title: 'GUSD', tag: 'ETH', fullName: 'Gemini USD', raw: 72, name: 'gusd', iconPath: 'assets/images/gusd_icon.png'); - static const gtc = CryptoCurrency(title: 'GTC', tag: 'ETH', fullName: 'Gitcoin', raw: 73, name: 'gtc', iconPath: 'assets/images/gtc_icon.png'); - static const grt = CryptoCurrency(title: 'GRT', tag: 'ETH', fullName: 'The Graph', raw: 74, name: 'grt', iconPath: 'assets/images/grt_icon.png'); - static const ldo = CryptoCurrency(title: 'LDO', tag: 'ETH', fullName: 'Lido DAO', raw: 75, name: 'ldo', iconPath: 'assets/images/ldo_icon.png'); - static const nexo = CryptoCurrency(title: 'NEXO', tag: 'ETH', fullName: 'Nexo', raw: 76, name: 'nexo', iconPath: 'assets/images/nexo_icon.png'); - static const cake = CryptoCurrency(title: 'CAKE', tag: 'BSC', fullName: 'PancakeSwap', raw: 77, name: 'cake', iconPath: 'assets/images/cake_icon.png'); - static const pepe = CryptoCurrency(title: 'PEPE', tag: 'ETH', fullName: 'Pepe', raw: 78, name: 'pepe', iconPath: 'assets/images/pepe_icon.png'); - static const storj = CryptoCurrency(title: 'STORJ', tag: 'ETH', fullName: 'Storj', raw: 79, name: 'storj', iconPath: 'assets/images/storj_icon.png'); - static const tusd = CryptoCurrency(title: 'TUSD', tag: 'ETH', fullName: 'TrueUSD', raw: 80, name: 'tusd', iconPath: 'assets/images/tusd_icon.png'); - static const wbtc = CryptoCurrency(title: 'WBTC', tag: 'ETH', fullName: 'Wrapped Bitcoin', raw: 81, name: 'wbtc', iconPath: 'assets/images/wbtc_icon.png'); - static const weth = CryptoCurrency(title: 'WETH', tag: 'ETH', fullName: 'Wrapped Ethereum', raw: 82, name: 'weth', iconPath: 'assets/images/weth_icon.png'); - static const zrx = CryptoCurrency(title: 'ZRX', tag: 'ETH', fullName: '0x Protocol', raw: 83, name: 'zrx', iconPath: 'assets/images/zrx_icon.png'); - static const dydx = CryptoCurrency(title: 'DYDX', tag: 'ETH', fullName: 'dYdX', raw: 84, name: 'dydx', iconPath: 'assets/images/dydx_icon.png'); - static const steth = CryptoCurrency(title: 'STETH', tag: 'ETH', fullName: 'Lido Staked Ethereum', raw: 85, name: 'steth', iconPath: 'assets/images/steth_icon.png'); - static const banano = CryptoCurrency(title: 'BAN', raw: 86, name: 'banano', iconPath: 'assets/images/nano_icon.png'); + static const usdcpoly = CryptoCurrency(title: 'USDC', tag: 'POLY', fullName: 'USD Coin', raw: 46, name: 'usdcpoly', iconPath: 'assets/images/usdc_icon.png', decimals: 6); + static const dcr = CryptoCurrency(title: 'DCR', fullName: 'Decred', raw: 47, name: 'dcr', iconPath: 'assets/images/dcr_icon.png', decimals: 8); + static const kmd = CryptoCurrency(title: 'KMD', fullName: 'Komodo', raw: 48, name: 'kmd', iconPath: 'assets/images/kmd_icon.png', decimals: 8); + static const mana = CryptoCurrency(title: 'MANA', tag: 'ETH', fullName: 'Decentraland', raw: 49, name: 'mana', iconPath: 'assets/images/mana_icon.png', decimals: 18); + static const maticpoly = CryptoCurrency(title: 'MATIC', tag: 'POLY', fullName: 'Polygon', raw: 50, name: 'maticpoly', iconPath: 'assets/images/matic_icon.png', decimals: 18); + static const matic = CryptoCurrency(title: 'MATIC', tag: 'ETH', fullName: 'Polygon', raw: 51, name: 'matic', iconPath: 'assets/images/matic_icon.png', decimals: 18); + static const mkr = CryptoCurrency(title: 'MKR', tag: 'ETH', fullName: 'Maker', raw: 52, name: 'mkr', iconPath: 'assets/images/mkr_icon.png', decimals: 18); + static const near = CryptoCurrency(title: 'NEAR', fullName: 'NEAR Protocol', raw: 53, name: 'near', iconPath: 'assets/images/near_icon.png', decimals: 24); + static const oxt = CryptoCurrency(title: 'OXT', tag: 'ETH', fullName: 'Orchid', raw: 54, name: 'oxt', iconPath: 'assets/images/oxt_icon.png', decimals: 18); + static const paxg = CryptoCurrency(title: 'PAXG', tag: 'ETH', fullName: 'Pax Gold', raw: 55, name: 'paxg', iconPath: 'assets/images/paxg_icon.png', decimals: 18); + static const pivx = CryptoCurrency(title: 'PIVX', raw: 56, name: 'pivx', iconPath: 'assets/images/pivx_icon.png', decimals: 8); + static const rune = CryptoCurrency(title: 'RUNE', fullName: 'Thorchain', raw: 57, name: 'rune', iconPath: 'assets/images/rune_icon.png', decimals: 18); + static const rvn = CryptoCurrency(title: 'RVN', fullName: 'Ravencoin', raw: 58, name: 'rvn', iconPath: 'assets/images/rvn_icon.png', decimals: 8); + static const scrt = CryptoCurrency(title: 'SCRT', fullName: 'Secret Network', raw: 59, name: 'scrt', iconPath: 'assets/images/scrt_icon.png', decimals: 6); + static const uni = CryptoCurrency(title: 'UNI', tag: 'ETH', fullName: 'Uniswap', raw: 60, name: 'uni', iconPath: 'assets/images/uni_icon.png', decimals: 18); + static const stx = CryptoCurrency(title: 'STX', fullName: 'Stacks', raw: 61, name: 'stx', iconPath: 'assets/images/stx_icon.png', decimals: 8); + static const btcln = CryptoCurrency(title: 'BTC', tag: 'LN', fullName: 'Bitcoin Lightning Network', raw: 62, name: 'btcln', iconPath: 'assets/images/btc.png', decimals: 8); + static const shib = CryptoCurrency(title: 'SHIB', tag: 'ETH', fullName: 'Shiba Inu', raw: 63, name: 'shib', iconPath: 'assets/images/shib_icon.png', decimals: 18); + static const aave = CryptoCurrency(title: 'AAVE', tag: 'ETH', fullName: 'Aave', raw: 64, name: 'aave', iconPath: 'assets/images/aave_icon.png', decimals: 18); + static const arb = CryptoCurrency(title: 'ARB', fullName: 'Arbitrum', raw: 65, name: 'arb', iconPath: 'assets/images/arb_icon.png', decimals: 18); + static const bat = CryptoCurrency(title: 'BAT', tag: 'ETH', fullName: 'Basic Attention Token', raw: 66, name: 'bat', iconPath: 'assets/images/bat_icon.png', decimals: 18); + static const comp = CryptoCurrency(title: 'COMP', tag: 'ETH', fullName: 'Compound', raw: 67, name: 'comp', iconPath: 'assets/images/comp_icon.png', decimals: 18); + static const cro = CryptoCurrency(title: 'CRO', tag: 'ETH', fullName: 'Crypto.com Cronos', raw: 68, name: 'cro', iconPath: 'assets/images/cro_icon.png', decimals: 8); + static const ens = CryptoCurrency(title: 'ENS', tag: 'ETH', fullName: 'Ethereum Name Service', raw: 69, name: 'ens', iconPath: 'assets/images/ens_icon.png', decimals: 18); + static const ftm = CryptoCurrency(title: 'FTM', tag: 'ETH', fullName: 'Fantom', raw: 70, name: 'ftm', iconPath: 'assets/images/ftm_icon.png', decimals: 18); + static const frax = CryptoCurrency(title: 'FRAX', tag: 'ETH', fullName: 'Frax', raw: 71, name: 'frax', iconPath: 'assets/images/frax_icon.png', decimals: 18); + static const gusd = CryptoCurrency(title: 'GUSD', tag: 'ETH', fullName: 'Gemini USD', raw: 72, name: 'gusd', iconPath: 'assets/images/gusd_icon.png', decimals: 2); + static const gtc = CryptoCurrency(title: 'GTC', tag: 'ETH', fullName: 'Gitcoin', raw: 73, name: 'gtc', iconPath: 'assets/images/gtc_icon.png', decimals: 18); + static const grt = CryptoCurrency(title: 'GRT', tag: 'ETH', fullName: 'The Graph', raw: 74, name: 'grt', iconPath: 'assets/images/grt_icon.png', decimals: 18); + static const ldo = CryptoCurrency(title: 'LDO', tag: 'ETH', fullName: 'Lido DAO', raw: 75, name: 'ldo', iconPath: 'assets/images/ldo_icon.png', decimals: 18); + static const nexo = CryptoCurrency(title: 'NEXO', tag: 'ETH', fullName: 'Nexo', raw: 76, name: 'nexo', iconPath: 'assets/images/nexo_icon.png', decimals: 18); + static const cake = CryptoCurrency(title: 'CAKE', tag: 'BSC', fullName: 'PancakeSwap', raw: 77, name: 'cake', iconPath: 'assets/images/cake_icon.png', decimals: 18); + static const pepe = CryptoCurrency(title: 'PEPE', tag: 'ETH', fullName: 'Pepe', raw: 78, name: 'pepe', iconPath: 'assets/images/pepe_icon.png', decimals: 18); + static const storj = CryptoCurrency(title: 'STORJ', tag: 'ETH', fullName: 'Storj', raw: 79, name: 'storj', iconPath: 'assets/images/storj_icon.png', decimals: 8); + static const tusd = CryptoCurrency(title: 'TUSD', tag: 'ETH', fullName: 'TrueUSD', raw: 80, name: 'tusd', iconPath: 'assets/images/tusd_icon.png', decimals: 18); + static const wbtc = CryptoCurrency(title: 'WBTC', tag: 'ETH', fullName: 'Wrapped Bitcoin', raw: 81, name: 'wbtc', iconPath: 'assets/images/wbtc_icon.png', decimals: 8); + static const weth = CryptoCurrency(title: 'WETH', tag: 'ETH', fullName: 'Wrapped Ethereum', raw: 82, name: 'weth', iconPath: 'assets/images/weth_icon.png', decimals: 18); + static const zrx = CryptoCurrency(title: 'ZRX', tag: 'ETH', fullName: '0x Protocol', raw: 83, name: 'zrx', iconPath: 'assets/images/zrx_icon.png', decimals: 18); + static const dydx = CryptoCurrency(title: 'DYDX', tag: 'ETH', fullName: 'dYdX', raw: 84, name: 'dydx', iconPath: 'assets/images/dydx_icon.png', decimals: 18); + static const steth = CryptoCurrency(title: 'STETH', tag: 'ETH', fullName: 'Lido Staked Ethereum', raw: 85, name: 'steth', iconPath: 'assets/images/steth_icon.png', decimals: 18); + static const banano = CryptoCurrency(title: 'BAN', fullName: 'Banano', raw: 86, name: 'banano', iconPath: 'assets/images/nano_icon.png', decimals: 29); static final Map _rawCurrencyMap = @@ -223,7 +225,6 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen }); static CryptoCurrency deserialize({required int raw}) { - if (CryptoCurrency._rawCurrencyMap[raw] == null) { final s = 'Unexpected token: $raw for CryptoCurrency deserialize'; throw ArgumentError.value(raw, 'raw', s); @@ -232,7 +233,6 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen } static CryptoCurrency fromString(String name) { - if (CryptoCurrency._nameCurrencyMap[name.toLowerCase()] == null) { final s = 'Unexpected token: $name for CryptoCurrency fromString'; throw ArgumentError.value(name, 'name', s); @@ -241,14 +241,12 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen } static CryptoCurrency fromFullName(String name) { - if (CryptoCurrency._fullNameCurrencyMap[name.toLowerCase()] == null) { final s = 'Unexpected token: $name for CryptoCurrency fromFullName'; throw ArgumentError.value(name, 'Fullname', s); } return CryptoCurrency._fullNameCurrencyMap[name.toLowerCase()]!; } - @override String toString() => title; diff --git a/cw_core/lib/erc20_token.dart b/cw_core/lib/erc20_token.dart index fd27aaba6..011fdef1d 100644 --- a/cw_core/lib/erc20_token.dart +++ b/cw_core/lib/erc20_token.dart @@ -37,6 +37,7 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin { fullName: name, tag: "ETH", iconPath: iconPath, + decimals: decimal ); Erc20Token.copyWith(Erc20Token other, String? icon) @@ -52,6 +53,7 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin { fullName: other.name, tag: "ETH", iconPath: icon, + decimals: other.decimal ); static const typeId = ERC20_TOKEN_TYPE_ID; diff --git a/lib/exchange/changenow/changenow_request.dart b/lib/exchange/changenow/changenow_request.dart deleted file mode 100644 index 7806dff55..000000000 --- a/lib/exchange/changenow/changenow_request.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/exchange/trade_request.dart'; - -class ChangeNowRequest extends TradeRequest { - ChangeNowRequest( - {required this.from, - required this.to, - required this.address, - required this.fromAmount, - required this.toAmount, - required this.refundAddress, - required this.isReverse}); - - CryptoCurrency from; - CryptoCurrency to; - String address; - String fromAmount; - String toAmount; - String refundAddress; - bool isReverse; -} diff --git a/lib/exchange/exchange_pair.dart b/lib/exchange/exchange_pair.dart index bb43498b1..686de21ee 100644 --- a/lib/exchange/exchange_pair.dart +++ b/lib/exchange/exchange_pair.dart @@ -1,10 +1,7 @@ import 'package:cw_core/crypto_currency.dart'; class ExchangePair { - ExchangePair({ - required this.from, - required this.to, - this.reverse = true}); + ExchangePair({required this.from, required this.to, this.reverse = true}); final CryptoCurrency from; final CryptoCurrency to; diff --git a/lib/exchange/exchange_provider_description.dart b/lib/exchange/exchange_provider_description.dart index 151d018e0..abfac3a6b 100644 --- a/lib/exchange/exchange_provider_description.dart +++ b/lib/exchange/exchange_provider_description.dart @@ -14,16 +14,12 @@ class ExchangeProviderDescription extends EnumerableItem with Serializable< ExchangeProviderDescription(title: 'ChangeNOW', raw: 1, image: 'assets/images/changenow.png'); static const morphToken = ExchangeProviderDescription(title: 'MorphToken', raw: 2, image: 'assets/images/morph.png'); - static const sideShift = ExchangeProviderDescription(title: 'SideShift', raw: 3, image: 'assets/images/sideshift.png'); - static const simpleSwap = ExchangeProviderDescription( title: 'SimpleSwap', raw: 4, image: 'assets/images/simpleSwap.png'); - static const trocador = ExchangeProviderDescription(title: 'Trocador', raw: 5, image: 'assets/images/trocador.png'); - static const exolix = ExchangeProviderDescription(title: 'Exolix', raw: 6, image: 'assets/images/exolix.png'); diff --git a/lib/exchange/exchange_trade_state.dart b/lib/exchange/exchange_trade_state.dart index d2f2840bc..44f66a33d 100644 --- a/lib/exchange/exchange_trade_state.dart +++ b/lib/exchange/exchange_trade_state.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:cake_wallet/exchange/trade.dart'; abstract class ExchangeTradeState {} @@ -18,4 +17,4 @@ class TradeIsCreatedFailure extends ExchangeTradeState { final String title; final String error; -} \ No newline at end of file +} diff --git a/lib/exchange/exolix/exolix_request.dart b/lib/exchange/exolix/exolix_request.dart deleted file mode 100644 index e97ffa386..000000000 --- a/lib/exchange/exolix/exolix_request.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/exchange/trade_request.dart'; - -class ExolixRequest extends TradeRequest { - ExolixRequest( - {required this.from, - required this.to, - required this.address, - required this.fromAmount, - required this.toAmount, - required this.refundAddress}); - - CryptoCurrency from; - CryptoCurrency to; - String address; - String fromAmount; - String toAmount; - String refundAddress; -} diff --git a/lib/exchange/limits.dart b/lib/exchange/limits.dart index 7e077c3cd..4b76f0206 100644 --- a/lib/exchange/limits.dart +++ b/lib/exchange/limits.dart @@ -1,6 +1,6 @@ class Limits { const Limits({this.min, this.max}); - + final double? min; final double? max; -} \ No newline at end of file +} diff --git a/lib/exchange/limits_state.dart b/lib/exchange/limits_state.dart index 1a551e7ee..993933d88 100644 --- a/lib/exchange/limits_state.dart +++ b/lib/exchange/limits_state.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:cake_wallet/exchange/limits.dart'; abstract class LimitsState {} diff --git a/lib/exchange/morphtoken/morphtoken_exchange_provider.dart b/lib/exchange/morphtoken/morphtoken_exchange_provider.dart deleted file mode 100644 index a2a72b24f..000000000 --- a/lib/exchange/morphtoken/morphtoken_exchange_provider.dart +++ /dev/null @@ -1,225 +0,0 @@ -import 'dart:convert'; -import 'package:cw_core/amount_converter.dart'; -import 'package:hive/hive.dart'; -import 'package:cake_wallet/exchange/trade_not_found_exeption.dart'; -import 'package:flutter/foundation.dart'; -import 'package:http/http.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/exchange/exchange_pair.dart'; -import 'package:cake_wallet/exchange/exchange_provider.dart'; -import 'package:cake_wallet/exchange/limits.dart'; -import 'package:cake_wallet/exchange/trade.dart'; -import 'package:cake_wallet/exchange/trade_request.dart'; -import 'package:cake_wallet/exchange/trade_state.dart'; -import 'package:cake_wallet/exchange/morphtoken/morphtoken_request.dart'; -import 'package:cake_wallet/exchange/exchange_provider_description.dart'; -import 'package:cake_wallet/exchange/trade_not_created_exeption.dart'; - -class MorphTokenExchangeProvider extends ExchangeProvider { - MorphTokenExchangeProvider({required this.trades}) - : super(pairList: [ - ExchangePair(from: CryptoCurrency.xmr, to: CryptoCurrency.eth), - ExchangePair(from: CryptoCurrency.xmr, to: CryptoCurrency.bch), - ExchangePair(from: CryptoCurrency.xmr, to: CryptoCurrency.ltc), - ExchangePair(from: CryptoCurrency.xmr, to: CryptoCurrency.dash), - ExchangePair(from: CryptoCurrency.dash, to: CryptoCurrency.btc), - ExchangePair(from: CryptoCurrency.dash, to: CryptoCurrency.eth), - ExchangePair(from: CryptoCurrency.dash, to: CryptoCurrency.bch), - ExchangePair(from: CryptoCurrency.dash, to: CryptoCurrency.ltc), - ExchangePair(from: CryptoCurrency.dash, to: CryptoCurrency.xmr), - ExchangePair(from: CryptoCurrency.ltc, to: CryptoCurrency.btc), - ExchangePair(from: CryptoCurrency.ltc, to: CryptoCurrency.eth), - ExchangePair(from: CryptoCurrency.ltc, to: CryptoCurrency.bch), - ExchangePair(from: CryptoCurrency.ltc, to: CryptoCurrency.dash), - ExchangePair(from: CryptoCurrency.ltc, to: CryptoCurrency.xmr), - ExchangePair(from: CryptoCurrency.bch, to: CryptoCurrency.btc), - ExchangePair(from: CryptoCurrency.bch, to: CryptoCurrency.eth), - ExchangePair(from: CryptoCurrency.bch, to: CryptoCurrency.ltc), - ExchangePair(from: CryptoCurrency.bch, to: CryptoCurrency.dash), - ExchangePair(from: CryptoCurrency.bch, to: CryptoCurrency.xmr), - ExchangePair(from: CryptoCurrency.eth, to: CryptoCurrency.btc), - ExchangePair(from: CryptoCurrency.eth, to: CryptoCurrency.bch), - ExchangePair(from: CryptoCurrency.eth, to: CryptoCurrency.ltc), - ExchangePair(from: CryptoCurrency.eth, to: CryptoCurrency.dash), - ExchangePair(from: CryptoCurrency.eth, to: CryptoCurrency.xmr), - ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.eth), - ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.bch), - ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.ltc), - ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.dash), - ExchangePair(from: CryptoCurrency.btc, to: CryptoCurrency.xmr) - ]); - - Box trades; - - static const apiUri = 'https://api.morphtoken.com'; - static const _morphURISuffix = '/morph'; - static const _limitsURISuffix = '/limits'; - static const _ratesURISuffix = '/rates'; - static const weight = 10000; - - @override - String get title => 'MorphToken'; - - @override - bool get isAvailable => true; - - @override - bool get isEnabled => true; - - @override - bool get supportsFixedRate => false; - - @override - ExchangeProviderDescription get description => - ExchangeProviderDescription.morphToken; - - @override - Future checkIsAvailable() async => true; - - @override - Future fetchLimits({ - required CryptoCurrency from, - required CryptoCurrency to, - required bool isFixedRateMode}) async { - final url = apiUri + _limitsURISuffix; - final uri = Uri.parse(url); - final headers = {'Content-type': 'application/json'}; - final body = json.encode({ - "input": {"asset": from.toString()}, - "output": [ - {"asset": to.toString(), "weight": weight} - ] - }); - final response = await post(uri, headers: headers, body: body); - final responseJSON = json.decode(response.body) as Map; - - final min = responseJSON['input']['limits']['min'] as int; - int max = 0; - double ethMax; - - if (from == CryptoCurrency.eth) { - ethMax = responseJSON['input']['limits']['max'] as double; - } else { - max = responseJSON['input']['limits']['max'] as int; - } - - final minFormatted = AmountConverter.amountIntToDouble(from, min); - final maxFormatted = AmountConverter.amountIntToDouble(from, max); - - return Limits(min: minFormatted, max: maxFormatted); - } - - @override - Future createTrade({ - required TradeRequest request, - required bool isFixedRateMode}) async { - const url = apiUri + _morphURISuffix; - final _request = request as MorphTokenRequest; - final body = { - "input": { - "asset": _request.from.toString(), - "refund": _request.refundAddress - }, - "output": [ - { - "asset": _request.to.toString(), - "weight": weight, - "address": _request.address - } - ], - "tag": "cakewallet" - }; - final uri = Uri.parse(url); - final response = await post(uri, - headers: {'Content-Type': 'application/json'}, body: json.encode(body)); - - if (response.statusCode != 200) { - if (response.statusCode == 400) { - final responseJSON = json.decode(response.body) as Map; - final error = responseJSON['description'] as String; - - throw TradeNotCreatedException(description, description: error); - } - - throw TradeNotCreatedException(description); - } - - final responseJSON = json.decode(response.body) as Map; - final id = responseJSON['id'] as String; - - return Trade( - id: id, - provider: description, - from: _request.from, - to: _request.to, - state: TradeState.created, - amount: _request.amount, - createdAt: DateTime.now()); - } - - @override - Future findTradeById({required String id}) async { - final url = apiUri + _morphURISuffix + '/' + id; - final uri = Uri.parse(url); - final response = await get(uri); - - if (response.statusCode != 200) { - if (response.statusCode == 400) { - final responseJSON = json.decode(response.body) as Map; - final error = responseJSON['description'] as String; - - throw TradeNotFoundException(id, - provider: description, description: error); - } - - throw TradeNotFoundException(id, provider: description); - } - - final responseJSON = json.decode(response.body) as Map; - final fromCurrency = responseJSON['input']['asset'] as String; - final from = CryptoCurrency.fromString(fromCurrency.toLowerCase()); - final toCurrency = responseJSON['output'][0]['asset'] as String; - final to = CryptoCurrency.fromString(toCurrency.toLowerCase()); - final inputAddress = responseJSON['input']['deposit_address'] as String; - final status = responseJSON['state'] as String; - final state = TradeState.deserialize(raw: status.toLowerCase()); - - String amount = ""; - for (final trade in trades.values) { - if (trade.id == id) { - amount = trade.amount; - break; - } - } - - return Trade( - id: id, - from: from, - to: to, - provider: description, - inputAddress: inputAddress, - amount: amount, - state: state); - } - - @override - Future fetchRate( - {required CryptoCurrency from, - required CryptoCurrency to, - required double amount, - required bool isFixedRateMode, - required bool isReceiveAmount}) async { - final url = apiUri + _ratesURISuffix; - final uri = Uri.parse(url); - final response = await get(uri); - final responseJSON = json.decode(response.body) as Map; - final rate = responseJSON['data'][from.toString()][to.toString()] as String; - - try { - final estimatedAmount = double.parse(rate) * amount; - return estimatedAmount; - } catch (_) { - return 0.0; - } - } -} diff --git a/lib/exchange/morphtoken/morphtoken_request.dart b/lib/exchange/morphtoken/morphtoken_request.dart deleted file mode 100644 index 7698755ec..000000000 --- a/lib/exchange/morphtoken/morphtoken_request.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/exchange/trade_request.dart'; - -class MorphTokenRequest extends TradeRequest { - MorphTokenRequest( - {required this.from, - required this.to, - required this.address, - required this.amount, - required this.refundAddress}); - - CryptoCurrency from; - CryptoCurrency to; - String address; - String amount; - String refundAddress; -} diff --git a/lib/exchange/changenow/changenow_exchange_provider.dart b/lib/exchange/provider/changenow_exchange_provider.dart similarity index 79% rename from lib/exchange/changenow/changenow_exchange_provider.dart rename to lib/exchange/provider/changenow_exchange_provider.dart index 6166a8875..300741a08 100644 --- a/lib/exchange/changenow/changenow_exchange_provider.dart +++ b/lib/exchange/provider/changenow_exchange_provider.dart @@ -1,33 +1,32 @@ import 'dart:convert'; import 'dart:io'; -import 'package:cake_wallet/exchange/trade_not_found_exeption.dart'; + +import 'package:cake_wallet/.secrets.g.dart' as secrets; +import 'package:cake_wallet/exchange/exchange_provider_description.dart'; +import 'package:cake_wallet/exchange/limits.dart'; +import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; +import 'package:cake_wallet/exchange/trade.dart'; +import 'package:cake_wallet/exchange/trade_not_found_exception.dart'; +import 'package:cake_wallet/exchange/trade_request.dart'; +import 'package:cake_wallet/exchange/trade_state.dart'; +import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/distribution_info.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; -import 'package:http/http.dart'; -import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/exchange/exchange_pair.dart'; -import 'package:cake_wallet/exchange/exchange_provider.dart'; -import 'package:cake_wallet/exchange/limits.dart'; -import 'package:cake_wallet/exchange/trade.dart'; -import 'package:cake_wallet/exchange/trade_request.dart'; -import 'package:cake_wallet/exchange/trade_state.dart'; -import 'package:cake_wallet/exchange/changenow/changenow_request.dart'; -import 'package:cake_wallet/exchange/exchange_provider_description.dart'; +import 'package:http/http.dart'; class ChangeNowExchangeProvider extends ExchangeProvider { - ChangeNowExchangeProvider({required this.settingsStore}) - : _lastUsedRateId = '', - super( - pairList: CryptoCurrency.all - .where((i) => i != CryptoCurrency.xhv) - .map((i) => CryptoCurrency.all - .where((i) => i != CryptoCurrency.xhv) - .map((k) => ExchangePair(from: i, to: k, reverse: true))) - .expand((i) => i) - .toList()); + ChangeNowExchangeProvider({required SettingsStore settingsStore}) + : _settingsStore = settingsStore, + _lastUsedRateId = '', + super(pairList: supportedPairs(_notSupported)); + + static const List _notSupported = [ + CryptoCurrency.zaddr, + CryptoCurrency.xhv, + ]; static final apiKey = DeviceInfo.instance.isMobile ? secrets.changeNowApiKey : secrets.changeNowApiKeyDesktop; @@ -38,6 +37,9 @@ class ChangeNowExchangeProvider extends ExchangeProvider { static const rangePath = '/v2/exchange/range'; static const apiHeaderKey = 'x-changenow-api-key'; + final SettingsStore _settingsStore; + String _lastUsedRateId; + @override String get title => 'ChangeNOW'; @@ -56,25 +58,18 @@ class ChangeNowExchangeProvider extends ExchangeProvider { @override Future checkIsAvailable() async => true; - final SettingsStore settingsStore; - - String _lastUsedRateId; - - static String getFlow(bool isFixedRate) => isFixedRate ? 'fixed-rate' : 'standard'; - @override Future fetchLimits( {required CryptoCurrency from, required CryptoCurrency to, required bool isFixedRateMode}) async { final headers = {apiHeaderKey: apiKey}; - final flow = getFlow(isFixedRateMode); final params = { 'fromCurrency': _normalizeCurrency(from), 'toCurrency': _normalizeCurrency(to), 'fromNetwork': _networkFor(from), 'toNetwork': _networkFor(to), - 'flow': flow + 'flow': _getFlow(isFixedRateMode) }; final uri = Uri.https(apiAuthority, rangePath, params); final response = await get(uri, headers: headers); @@ -86,20 +81,61 @@ class ChangeNowExchangeProvider extends ExchangeProvider { throw Exception('${error}\n$message'); } - if (response.statusCode != 200) { + if (response.statusCode != 200) throw Exception('Unexpected http status: ${response.statusCode}'); - } final responseJSON = json.decode(response.body) as Map; return Limits( min: responseJSON['minAmount'] as double?, max: responseJSON['maxAmount'] as double?); } + @override + Future fetchRate( + {required CryptoCurrency from, + required CryptoCurrency to, + required double amount, + required bool isFixedRateMode, + required bool isReceiveAmount}) async { + try { + if (amount == 0) return 0.0; + + final headers = {apiHeaderKey: apiKey}; + final isReverse = isReceiveAmount; + final type = isReverse ? 'reverse' : 'direct'; + final params = { + 'fromCurrency': _normalizeCurrency(from), + 'toCurrency': _normalizeCurrency(to), + 'fromNetwork': _networkFor(from), + 'toNetwork': _networkFor(to), + 'type': type, + 'flow': _getFlow(isFixedRateMode) + }; + + if (isReverse) + params['toAmount'] = amount.toString(); + else + params['fromAmount'] = amount.toString(); + + final uri = Uri.https(apiAuthority, estimatedAmountPath, params); + final response = await get(uri, headers: headers); + final responseJSON = json.decode(response.body) as Map; + final fromAmount = double.parse(responseJSON['fromAmount'].toString()); + final toAmount = double.parse(responseJSON['toAmount'].toString()); + final rateId = responseJSON['rateId'] as String? ?? ''; + + if (rateId.isNotEmpty) _lastUsedRateId = rateId; + + return isReverse ? (amount / fromAmount) : (toAmount / amount); + } catch (e) { + print(e.toString()); + return 0.0; + } + } + @override Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { - final _request = request as ChangeNowRequest; final distributionPath = await DistributionInfo.instance.getDistributionPath(); - final formattedAppVersion = int.tryParse(settingsStore.appVersion.replaceAll('.', '')) ?? 0; + final formattedAppVersion = int.tryParse(_settingsStore.appVersion.replaceAll('.', '')) ?? 0; final payload = { 'app': isMoneroOnly ? 'monerocom' : 'cakewallet', 'device': Platform.operatingSystem, @@ -107,19 +143,18 @@ class ChangeNowExchangeProvider extends ExchangeProvider { 'version': formattedAppVersion }; final headers = {apiHeaderKey: apiKey, 'Content-Type': 'application/json'}; - final flow = getFlow(isFixedRateMode); final type = isFixedRateMode ? 'reverse' : 'direct'; final body = { - 'fromCurrency': _normalizeCurrency(_request.from), - 'toCurrency': _normalizeCurrency(_request.to), - 'fromNetwork': _networkFor(_request.from), - 'toNetwork': _networkFor(_request.to), - if (!isFixedRateMode) 'fromAmount': _request.fromAmount, - if (isFixedRateMode) 'toAmount': _request.toAmount, - 'address': _request.address, - 'flow': flow, + 'fromCurrency': _normalizeCurrency(request.fromCurrency), + 'toCurrency': _normalizeCurrency(request.toCurrency), + 'fromNetwork': _networkFor(request.fromCurrency), + 'toNetwork': _networkFor(request.toCurrency), + if (!isFixedRateMode) 'fromAmount': request.fromAmount, + if (isFixedRateMode) 'toAmount': request.toAmount, + 'address': request.toAddress, + 'flow': _getFlow(isFixedRateMode), 'type': type, - 'refundAddress': _request.refundAddress, + 'refundAddress': request.refundAddress, 'payload': payload, }; @@ -127,9 +162,9 @@ class ChangeNowExchangeProvider extends ExchangeProvider { // since we schedule to calculate the rate every 5 seconds we need to ensure that // we have the latest rate id with the given inputs before creating the trade await fetchRate( - from: _request.from, - to: _request.to, - amount: double.tryParse(_request.toAmount) ?? 0, + from: request.fromCurrency, + to: request.toCurrency, + amount: double.tryParse(request.toAmount) ?? 0, isFixedRateMode: true, isReceiveAmount: true, ); @@ -146,9 +181,8 @@ class ChangeNowExchangeProvider extends ExchangeProvider { throw Exception('${error}\n$message'); } - if (response.statusCode != 200) { + if (response.statusCode != 200) throw Exception('Unexpected http status: ${response.statusCode}'); - } final responseJSON = json.decode(response.body) as Map; final id = responseJSON['id'] as String; @@ -159,14 +193,14 @@ class ChangeNowExchangeProvider extends ExchangeProvider { return Trade( id: id, - from: _request.from, - to: _request.to, + from: request.fromCurrency, + to: request.toCurrency, provider: description, inputAddress: inputAddress, refundAddress: refundAddress, extraId: extraId, createdAt: DateTime.now(), - amount: responseJSON['fromAmount']?.toString() ?? _request.fromAmount, + amount: responseJSON['fromAmount']?.toString() ?? request.fromAmount, state: TradeState.created, payoutAddress: payoutAddress); } @@ -178,9 +212,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider { final uri = Uri.https(apiAuthority, findTradeByIdPath, params); final response = await get(uri, headers: headers); - if (response.statusCode == 404) { - throw TradeNotFoundException(id, provider: description); - } + if (response.statusCode == 404) throw TradeNotFoundException(id, provider: description); if (response.statusCode == 400) { final responseJSON = json.decode(response.body) as Map; @@ -189,9 +221,8 @@ class ChangeNowExchangeProvider extends ExchangeProvider { throw TradeNotFoundException(id, provider: description, description: error); } - if (response.statusCode != 200) { + if (response.statusCode != 200) throw Exception('Unexpected http status: ${response.statusCode}'); - } final responseJSON = json.decode(response.body) as Map; final fromCurrency = responseJSON['fromCurrency'] as String; @@ -222,54 +253,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider { payoutAddress: payoutAddress); } - @override - Future fetchRate( - {required CryptoCurrency from, - required CryptoCurrency to, - required double amount, - required bool isFixedRateMode, - required bool isReceiveAmount}) async { - try { - if (amount == 0) { - return 0.0; - } - - final headers = {apiHeaderKey: apiKey}; - final isReverse = isReceiveAmount; - final type = isReverse ? 'reverse' : 'direct'; - final flow = getFlow(isFixedRateMode); - final params = { - 'fromCurrency': _normalizeCurrency(from), - 'toCurrency': _normalizeCurrency(to), - 'fromNetwork': _networkFor(from), - 'toNetwork': _networkFor(to), - 'type': type, - 'flow': flow - }; - - if (isReverse) { - params['toAmount'] = amount.toString(); - } else { - params['fromAmount'] = amount.toString(); - } - - final uri = Uri.https(apiAuthority, estimatedAmountPath, params); - final response = await get(uri, headers: headers); - final responseJSON = json.decode(response.body) as Map; - final fromAmount = double.parse(responseJSON['fromAmount'].toString()); - final toAmount = double.parse(responseJSON['toAmount'].toString()); - final rateId = responseJSON['rateId'] as String? ?? ''; - - if (rateId.isNotEmpty) { - _lastUsedRateId = rateId; - } - - return isReverse ? (amount / fromAmount) : (toAmount / amount); - } catch (e) { - print(e.toString()); - return 0.0; - } - } + String _getFlow(bool isFixedRate) => isFixedRate ? 'fixed-rate' : 'standard'; String _networkFor(CryptoCurrency currency) { switch (currency) { @@ -301,4 +285,4 @@ class ChangeNowExchangeProvider extends ExchangeProvider { return tag.toLowerCase(); } } -} \ No newline at end of file +} diff --git a/lib/exchange/exchange_provider.dart b/lib/exchange/provider/exchange_provider.dart similarity index 71% rename from lib/exchange/exchange_provider.dart rename to lib/exchange/provider/exchange_provider.dart index cc81a21f6..d1f69689d 100644 --- a/lib/exchange/exchange_provider.dart +++ b/lib/exchange/provider/exchange_provider.dart @@ -1,37 +1,43 @@ -import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/exchange/exchange_pair.dart'; +import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/exchange/limits.dart'; import 'package:cake_wallet/exchange/trade.dart'; -import 'package:cake_wallet/exchange/exchange_provider_description.dart'; +import 'package:cake_wallet/exchange/trade_request.dart'; +import 'package:cw_core/crypto_currency.dart'; abstract class ExchangeProvider { ExchangeProvider({required this.pairList}); - + String get title; + List pairList; + ExchangeProviderDescription get description; + bool get isAvailable; + bool get isEnabled; + bool get supportsFixedRate; + bool get supportsOnionAddress => false; @override String toString() => title; Future fetchLimits( + {required CryptoCurrency from, required CryptoCurrency to, required bool isFixedRateMode}); + + Future createTrade({required TradeRequest request, required bool isFixedRateMode}); + + Future findTradeById({required String id}); + + Future fetchRate( {required CryptoCurrency from, required CryptoCurrency to, - required bool isFixedRateMode}); - Future createTrade({ - required TradeRequest request, - required bool isFixedRateMode}); - Future findTradeById({required String id}); - Future fetchRate({ - required CryptoCurrency from, - required CryptoCurrency to, - required double amount, - required bool isFixedRateMode, - required bool isReceiveAmount}); + required double amount, + required bool isFixedRateMode, + required bool isReceiveAmount}); + Future checkIsAvailable(); } diff --git a/lib/exchange/exolix/exolix_exchange_provider.dart b/lib/exchange/provider/exolix_exchange_provider.dart similarity index 76% rename from lib/exchange/exolix/exolix_exchange_provider.dart rename to lib/exchange/provider/exolix_exchange_provider.dart index 01b8ecc2b..eb40aff73 100644 --- a/lib/exchange/exolix/exolix_exchange_provider.dart +++ b/lib/exchange/provider/exolix_exchange_provider.dart @@ -1,19 +1,19 @@ import 'dart:convert'; -import 'package:cake_wallet/exchange/trade_not_found_exeption.dart'; -import 'package:http/http.dart'; + import 'package:cake_wallet/.secrets.g.dart' as secrets; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/exchange/exchange_pair.dart'; -import 'package:cake_wallet/exchange/exchange_provider.dart'; +import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/exchange/limits.dart'; +import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; import 'package:cake_wallet/exchange/trade.dart'; +import 'package:cake_wallet/exchange/trade_not_found_exception.dart'; import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; -import 'package:cake_wallet/exchange/exolix/exolix_request.dart'; -import 'package:cake_wallet/exchange/exchange_provider_description.dart'; +import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:http/http.dart'; class ExolixExchangeProvider extends ExchangeProvider { - ExolixExchangeProvider() : super(pairList: _supportedPairs()); + ExolixExchangeProvider() : super(pairList: supportedPairs(_notSupported)); static final apiKey = secrets.exolixApiKey; static const apiBaseUrl = 'exolix.com'; @@ -40,16 +40,6 @@ class ExolixExchangeProvider extends ExchangeProvider { CryptoCurrency.weth, ]; - static List _supportedPairs() { - final supportedCurrencies = - CryptoCurrency.all.where((element) => !_notSupported.contains(element)).toList(); - - return supportedCurrencies - .map((i) => supportedCurrencies.map((k) => ExchangePair(from: i, to: k, reverse: true))) - .expand((i) => i) - .toList(); - } - @override String get title => 'Exolix'; @@ -68,15 +58,13 @@ class ExolixExchangeProvider extends ExchangeProvider { @override Future checkIsAvailable() async => true; - static String getRateType(bool isFixedRate) => isFixedRate ? 'fixed' : 'float'; - @override Future fetchLimits( {required CryptoCurrency from, required CryptoCurrency to, required bool isFixedRateMode}) async { final params = { - 'rateType': getRateType(isFixedRateMode), + 'rateType': _getRateType(isFixedRateMode), 'amount': '1', }; if (isFixedRateMode) { @@ -93,35 +81,71 @@ class ExolixExchangeProvider extends ExchangeProvider { final uri = Uri.https(apiBaseUrl, ratePath, params); final response = await get(uri); - if (response.statusCode != 200) { + if (response.statusCode != 200) throw Exception('Unexpected http status: ${response.statusCode}'); - } final responseJSON = json.decode(response.body) as Map; return Limits(min: responseJSON['minAmount'] as double?); } @override - Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { - final _request = request as ExolixRequest; + Future fetchRate( + {required CryptoCurrency from, + required CryptoCurrency to, + required double amount, + required bool isFixedRateMode, + required bool isReceiveAmount}) async { + try { + if (amount == 0) return 0.0; + final params = { + 'coinFrom': _normalizeCurrency(from), + 'coinTo': _normalizeCurrency(to), + 'networkFrom': _networkFor(from), + 'networkTo': _networkFor(to), + 'rateType': _getRateType(isFixedRateMode), + 'apiToken': apiKey, + }; + + if (isReceiveAmount) + params['withdrawalAmount'] = amount.toString(); + else + params['amount'] = amount.toString(); + + final uri = Uri.https(apiBaseUrl, ratePath, params); + final response = await get(uri); + final responseJSON = json.decode(response.body) as Map; + + if (response.statusCode != 200) { + final message = responseJSON['message'] as String?; + throw Exception(message); + } + + return responseJSON['rate'] as double; + } catch (e) { + print(e.toString()); + return 0.0; + } + } + + @override + Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { final headers = {'Content-Type': 'application/json'}; - final body = { - 'coinFrom': _normalizeCurrency(_request.from), - 'coinTo': _normalizeCurrency(_request.to), - 'networkFrom': _networkFor(_request.from), - 'networkTo': _networkFor(_request.to), - 'withdrawalAddress': _request.address, - 'refundAddress': _request.refundAddress, - 'rateType': getRateType(isFixedRateMode), + final body = { + 'coinFrom': _normalizeCurrency(request.fromCurrency), + 'coinTo': _normalizeCurrency(request.toCurrency), + 'networkFrom': _networkFor(request.fromCurrency), + 'networkTo': _networkFor(request.toCurrency), + 'withdrawalAddress': request.toAddress, + 'refundAddress': request.refundAddress, + 'rateType': _getRateType(isFixedRateMode), 'apiToken': apiKey, }; - if (isFixedRateMode) { - body['withdrawalAmount'] = _request.toAmount; - } else { - body['amount'] = _request.fromAmount; - } + if (isFixedRateMode) + body['withdrawalAmount'] = request.toAmount; + else + body['amount'] = request.fromAmount; final uri = Uri.https(apiBaseUrl, transactionsPath); final response = await post(uri, headers: headers, body: json.encode(body)); @@ -133,9 +157,8 @@ class ExolixExchangeProvider extends ExchangeProvider { throw Exception(errorMessage); } - if (response.statusCode != 200 && response.statusCode != 201) { + if (response.statusCode != 200 && response.statusCode != 201) throw Exception('Unexpected http status: ${response.statusCode}'); - } final responseJSON = json.decode(response.body) as Map; final id = responseJSON['id'] as String; @@ -147,8 +170,8 @@ class ExolixExchangeProvider extends ExchangeProvider { return Trade( id: id, - from: _request.from, - to: _request.to, + from: request.fromCurrency, + to: request.toCurrency, provider: description, inputAddress: inputAddress, refundAddress: refundAddress, @@ -161,13 +184,11 @@ class ExolixExchangeProvider extends ExchangeProvider { @override Future findTradeById({required String id}) async { - final findTradeByIdPath = transactionsPath + '/$id'; + final findTradeByIdPath = '$transactionsPath/$id'; final uri = Uri.https(apiBaseUrl, findTradeByIdPath); final response = await get(uri); - if (response.statusCode == 404) { - throw TradeNotFoundException(id, provider: description); - } + if (response.statusCode == 404) throw TradeNotFoundException(id, provider: description); if (response.statusCode == 400) { final responseJSON = json.decode(response.body) as Map; @@ -177,80 +198,33 @@ class ExolixExchangeProvider extends ExchangeProvider { throw TradeNotFoundException(id, provider: description, description: errorMessage); } - if (response.statusCode != 200) { + if (response.statusCode != 200) throw Exception('Unexpected http status: ${response.statusCode}'); - } final responseJSON = json.decode(response.body) as Map; final coinFrom = responseJSON['coinFrom']['coinCode'] as String; - final from = CryptoCurrency.fromString(coinFrom); final coinTo = responseJSON['coinTo']['coinCode'] as String; - final to = CryptoCurrency.fromString(coinTo); final inputAddress = responseJSON['depositAddress'] as String; final amount = responseJSON['amount'].toString(); final status = responseJSON['status'] as String; - final state = TradeState.deserialize(raw: _prepareStatus(status)); final extraId = responseJSON['depositExtraId'] as String?; final outputTransaction = responseJSON['hashOut']['hash'] as String?; final payoutAddress = responseJSON['withdrawalAddress'] as String; return Trade( id: id, - from: from, - to: to, + from: CryptoCurrency.fromString(coinFrom), + to: CryptoCurrency.fromString(coinTo), provider: description, inputAddress: inputAddress, amount: amount, - state: state, + state: TradeState.deserialize(raw: _prepareStatus(status)), extraId: extraId, outputTransaction: outputTransaction, payoutAddress: payoutAddress); } - @override - Future fetchRate( - {required CryptoCurrency from, - required CryptoCurrency to, - required double amount, - required bool isFixedRateMode, - required bool isReceiveAmount}) async { - try { - if (amount == 0) { - return 0.0; - } - - final params = { - 'coinFrom': _normalizeCurrency(from), - 'coinTo': _normalizeCurrency(to), - 'networkFrom': _networkFor(from), - 'networkTo': _networkFor(to), - 'rateType': getRateType(isFixedRateMode), - 'apiToken': apiKey, - }; - - if (isReceiveAmount) { - params['withdrawalAmount'] = amount.toString(); - } else { - params['amount'] = amount.toString(); - } - - final uri = Uri.https(apiBaseUrl, ratePath, params); - final response = await get(uri); - final responseJSON = json.decode(response.body) as Map; - - if (response.statusCode != 200) { - final message = responseJSON['message'] as String?; - throw Exception(message); - } - - final rate = responseJSON['rate'] as double; - - return rate; - } catch (e) { - print(e.toString()); - return 0.0; - } - } + String _getRateType(bool isFixedRate) => isFixedRate ? 'fixed' : 'float'; String _prepareStatus(String status) { switch (status) { diff --git a/lib/exchange/sideshift/sideshift_exchange_provider.dart b/lib/exchange/provider/sideshift_exchange_provider.dart similarity index 75% rename from lib/exchange/sideshift/sideshift_exchange_provider.dart rename to lib/exchange/provider/sideshift_exchange_provider.dart index 84b4cd4e0..7a466e213 100644 --- a/lib/exchange/sideshift/sideshift_exchange_provider.dart +++ b/lib/exchange/provider/sideshift_exchange_provider.dart @@ -1,28 +1,20 @@ import 'dart:convert'; -import 'package:cake_wallet/exchange/exchange_pair.dart'; -import 'package:cake_wallet/exchange/exchange_provider.dart'; -import 'package:cake_wallet/exchange/exchange_provider_description.dart'; -import 'package:cake_wallet/exchange/sideshift/sideshift_request.dart'; -import 'package:cake_wallet/exchange/trade_not_created_exeption.dart'; -import 'package:cake_wallet/exchange/trade_not_found_exeption.dart'; -import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/exchange/trade_request.dart'; -import 'package:cake_wallet/exchange/trade.dart'; +import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; +import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/exchange/limits.dart'; +import 'package:cake_wallet/exchange/trade.dart'; +import 'package:cake_wallet/exchange/trade_not_created_exception.dart'; +import 'package:cake_wallet/exchange/trade_not_found_exception.dart'; +import 'package:cake_wallet/exchange/trade_request.dart'; +import 'package:cake_wallet/exchange/trade_state.dart'; +import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; +import 'package:cw_core/crypto_currency.dart'; import 'package:http/http.dart'; class SideShiftExchangeProvider extends ExchangeProvider { - SideShiftExchangeProvider() : super(pairList: _supportedPairs()); - - static const affiliateId = secrets.sideShiftAffiliateId; - static const apiBaseUrl = 'https://sideshift.ai/api'; - static const rangePath = '/v2/pair'; - static const orderPath = '/v2/shifts'; - static const quotePath = '/v2/quotes'; - static const permissionPath = '/v2/permissions'; + SideShiftExchangeProvider() : super(pairList: supportedPairs(_notSupported)); static const List _notSupported = [ CryptoCurrency.xhv, @@ -39,49 +31,28 @@ class SideShiftExchangeProvider extends ExchangeProvider { CryptoCurrency.eos, ]; - static List _supportedPairs() { - final supportedCurrencies = - CryptoCurrency.all.where((element) => !_notSupported.contains(element)).toList(); + static const affiliateId = secrets.sideShiftAffiliateId; + static const apiBaseUrl = 'https://sideshift.ai/api'; + static const rangePath = '/v2/pair'; + static const orderPath = '/v2/shifts'; + static const quotePath = '/v2/quotes'; + static const permissionPath = '/v2/permissions'; - return supportedCurrencies - .map((i) => supportedCurrencies.map((k) => ExchangePair(from: i, to: k, reverse: true))) - .expand((i) => i) - .toList(); - } + @override + String get title => 'SideShift'; + + @override + bool get isAvailable => true; + + @override + bool get isEnabled => true; + + @override + bool get supportsFixedRate => true; @override ExchangeProviderDescription get description => ExchangeProviderDescription.sideShift; - @override - Future fetchRate( - {required CryptoCurrency from, - required CryptoCurrency to, - required double amount, - required bool isFixedRateMode, - required bool isReceiveAmount}) async { - try { - if (amount == 0) { - return 0.0; - } - - final fromCurrency = from.title.toLowerCase(); - final toCurrency = to.title.toLowerCase(); - final depositNetwork = _networkFor(from); - final settleNetwork = _networkFor(to); - - final url = "$apiBaseUrl$rangePath/$fromCurrency-$depositNetwork/$toCurrency-$settleNetwork?amount=$amount"; - - final uri = Uri.parse(url); - final response = await get(uri); - final responseJSON = json.decode(response.body) as Map; - final rate = double.parse(responseJSON['rate'] as String); - - return rate; - } catch (_) { - return 0.00; - } - } - @override Future checkIsAvailable() async { const url = apiBaseUrl + permissionPath; @@ -95,110 +66,10 @@ class SideShiftExchangeProvider extends ExchangeProvider { throw Exception('$error'); } - if (response.statusCode != 200) { - return false; - } + if (response.statusCode != 200) return false; final responseJSON = json.decode(response.body) as Map; - final cancreateShift = responseJSON['createShift'] as bool; - return cancreateShift; - } - - @override - Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { - final _request = request as SideShiftRequest; - String url = ''; - final depositCoin = request.depositMethod.title.toLowerCase(); - final settleCoin = request.settleMethod.title.toLowerCase(); - final body = { - 'affiliateId': affiliateId, - 'settleAddress': _request.settleAddress, - 'refundAddress': _request.refundAddress, - }; - - if (isFixedRateMode) { - final quoteId = await _createQuote(_request); - body['quoteId'] = quoteId; - - url = apiBaseUrl + orderPath + '/fixed'; - } else { - url = apiBaseUrl + orderPath + '/variable'; - final depositNetwork = _networkFor(request.depositMethod); - final settleNetwork = _networkFor(request.settleMethod); - body["depositCoin"] = depositCoin; - body["settleCoin"] = settleCoin; - body["settleNetwork"] = settleNetwork; - body["depositNetwork"] = depositNetwork; - } - final headers = {'Content-Type': 'application/json'}; - - final uri = Uri.parse(url); - final response = await post(uri, headers: headers, body: json.encode(body)); - - if (response.statusCode != 201) { - if (response.statusCode == 400) { - final responseJSON = json.decode(response.body) as Map; - final error = responseJSON['error']['message'] as String; - - throw TradeNotCreatedException(description, description: error); - } - - throw TradeNotCreatedException(description); - } - - final responseJSON = json.decode(response.body) as Map; - final id = responseJSON['id'] as String; - final inputAddress = responseJSON['depositAddress'] as String; - final settleAddress = responseJSON['settleAddress'] as String; - final depositAmount = responseJSON['depositAmount'] as String?; - - return Trade( - id: id, - provider: description, - from: _request.depositMethod, - to: _request.settleMethod, - inputAddress: inputAddress, - refundAddress: settleAddress, - state: TradeState.created, - amount: depositAmount ?? _request.depositAmount, - payoutAddress: settleAddress, - createdAt: DateTime.now(), - ); - } - - Future _createQuote(SideShiftRequest request) async { - final url = apiBaseUrl + quotePath; - final headers = {'Content-Type': 'application/json'}; - final depositMethod = request.depositMethod.title.toLowerCase(); - final settleMethod = request.settleMethod.title.toLowerCase(); - final depositNetwork = _networkFor(request.depositMethod); - final settleNetwork = _networkFor(request.settleMethod); - final body = { - 'depositCoin': depositMethod, - 'settleCoin': settleMethod, - 'affiliateId': affiliateId, - 'settleAmount': request.depositAmount, - 'settleNetwork': settleNetwork, - 'depositNetwork': depositNetwork, - }; - final uri = Uri.parse(url); - final response = await post(uri, headers: headers, body: json.encode(body)); - - if (response.statusCode != 201) { - if (response.statusCode == 400) { - final responseJSON = json.decode(response.body) as Map; - final error = responseJSON['error']['message'] as String; - - throw TradeNotCreatedException(description, description: error); - } - - throw TradeNotCreatedException(description); - } - - final responseJSON = json.decode(response.body) as Map; - final quoteId = responseJSON['id'] as String; - - return quoteId; + return responseJSON['createShift'] as bool; } @override @@ -244,6 +115,91 @@ class SideShiftExchangeProvider extends ExchangeProvider { return Limits(min: min, max: max); } + @override + Future fetchRate( + {required CryptoCurrency from, + required CryptoCurrency to, + required double amount, + required bool isFixedRateMode, + required bool isReceiveAmount}) async { + try { + if (amount == 0) return 0.0; + + final fromCurrency = from.title.toLowerCase(); + final toCurrency = to.title.toLowerCase(); + final depositNetwork = _networkFor(from); + final settleNetwork = _networkFor(to); + + final url = + "$apiBaseUrl$rangePath/$fromCurrency-$depositNetwork/$toCurrency-$settleNetwork?amount=$amount"; + + final uri = Uri.parse(url); + final response = await get(uri); + final responseJSON = json.decode(response.body) as Map; + + return double.parse(responseJSON['rate'] as String); + } catch (_) { + return 0.00; + } + } + + @override + Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { + String url = ''; + final body = { + 'affiliateId': affiliateId, + 'settleAddress': request.toAddress, + 'refundAddress': request.refundAddress, + }; + + if (isFixedRateMode) { + final quoteId = await _createQuote(request); + body['quoteId'] = quoteId; + + url = apiBaseUrl + orderPath + '/fixed'; + } else { + url = apiBaseUrl + orderPath + '/variable'; + body["depositCoin"] = request.fromCurrency.title.toLowerCase(); + body["settleCoin"] = request.toCurrency.title.toLowerCase(); + body["settleNetwork"] = _networkFor(request.toCurrency); + body["depositNetwork"] = _networkFor(request.fromCurrency); + } + final headers = {'Content-Type': 'application/json'}; + + final uri = Uri.parse(url); + final response = await post(uri, headers: headers, body: json.encode(body)); + + if (response.statusCode != 201) { + if (response.statusCode == 400) { + final responseJSON = json.decode(response.body) as Map; + final error = responseJSON['error']['message'] as String; + + throw TradeNotCreatedException(description, description: error); + } + + throw TradeNotCreatedException(description); + } + + final responseJSON = json.decode(response.body) as Map; + final id = responseJSON['id'] as String; + final inputAddress = responseJSON['depositAddress'] as String; + final settleAddress = responseJSON['settleAddress'] as String; + final depositAmount = responseJSON['depositAmount'] as String?; + + return Trade( + id: id, + provider: description, + from: request.fromCurrency, + to: request.toCurrency, + inputAddress: inputAddress, + refundAddress: settleAddress, + state: TradeState.created, + amount: depositAmount ?? request.fromAmount, + payoutAddress: settleAddress, + createdAt: DateTime.now(), + ); + } + @override Future findTradeById({required String id}) async { final url = apiBaseUrl + orderPath + '/' + id; @@ -267,44 +223,56 @@ class SideShiftExchangeProvider extends ExchangeProvider { final responseJSON = json.decode(response.body) as Map; final fromCurrency = responseJSON['depositCoin'] as String; - final from = CryptoCurrency.fromString(fromCurrency); final toCurrency = responseJSON['settleCoin'] as String; - final to = CryptoCurrency.fromString(toCurrency); final inputAddress = responseJSON['depositAddress'] as String; final expectedSendAmount = responseJSON['depositAmount'] as String?; final status = responseJSON['status'] as String?; final settleAddress = responseJSON['settleAddress'] as String; - TradeState? state; - - state = TradeState.deserialize(raw: status ?? 'created'); final isVariable = (responseJSON['type'] as String) == 'variable'; - final expiredAtRaw = responseJSON['expiresAt'] as String; final expiredAt = isVariable ? null : DateTime.tryParse(expiredAtRaw)?.toLocal(); return Trade( id: id, - from: from, - to: to, + from: CryptoCurrency.fromString(fromCurrency), + to: CryptoCurrency.fromString(toCurrency), provider: description, inputAddress: inputAddress, amount: expectedSendAmount ?? '', - state: state, + state: TradeState.deserialize(raw: status ?? 'created'), expiredAt: expiredAt, payoutAddress: settleAddress); } - @override - bool get isAvailable => true; + Future _createQuote(TradeRequest request) async { + final url = apiBaseUrl + quotePath; + final headers = {'Content-Type': 'application/json'}; + final body = { + 'depositCoin': request.fromCurrency.title.toLowerCase(), + 'settleCoin': request.toCurrency.title.toLowerCase(), + 'affiliateId': affiliateId, + 'settleAmount': request.toAmount, + 'settleNetwork': _networkFor(request.toCurrency), + 'depositNetwork': _networkFor(request.fromCurrency), + }; + final uri = Uri.parse(url); + final response = await post(uri, headers: headers, body: json.encode(body)); - @override - bool get isEnabled => true; + if (response.statusCode != 201) { + if (response.statusCode == 400) { + final responseJSON = json.decode(response.body) as Map; + final error = responseJSON['error']['message'] as String; - @override - bool get supportsFixedRate => true; + throw TradeNotCreatedException(description, description: error); + } - @override - String get title => 'SideShift'; + throw TradeNotCreatedException(description); + } + + final responseJSON = json.decode(response.body) as Map; + + return responseJSON['id'] as String; + } String _networkFor(CryptoCurrency currency) => currency.tag != null ? _normalizeTag(currency.tag!) : 'mainnet'; diff --git a/lib/exchange/simpleswap/simpleswap_exchange_provider.dart b/lib/exchange/provider/simpleswap_exchange_provider.dart similarity index 72% rename from lib/exchange/simpleswap/simpleswap_exchange_provider.dart rename to lib/exchange/provider/simpleswap_exchange_provider.dart index 4c1072d11..091c3a913 100644 --- a/lib/exchange/simpleswap/simpleswap_exchange_provider.dart +++ b/lib/exchange/provider/simpleswap_exchange_provider.dart @@ -1,71 +1,49 @@ import 'dart:convert'; -import 'package:cake_wallet/exchange/exchange_pair.dart'; -import 'package:cake_wallet/exchange/exchange_provider.dart'; + +import 'package:cake_wallet/.secrets.g.dart' as secrets; +import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; -import 'package:cake_wallet/exchange/simpleswap/simpleswap_request.dart'; -import 'package:cake_wallet/exchange/trade_not_created_exeption.dart'; -import 'package:cake_wallet/exchange/trade_not_found_exeption.dart'; +import 'package:cake_wallet/exchange/limits.dart'; +import 'package:cake_wallet/exchange/trade.dart'; +import 'package:cake_wallet/exchange/trade_not_created_exception.dart'; +import 'package:cake_wallet/exchange/trade_not_found_exception.dart'; +import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; +import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/exchange/trade_request.dart'; -import 'package:cake_wallet/exchange/trade.dart'; -import 'package:cake_wallet/exchange/limits.dart'; -import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:http/http.dart'; class SimpleSwapExchangeProvider extends ExchangeProvider { - SimpleSwapExchangeProvider() - : super( - pairList: CryptoCurrency.all - .where((i) => i != CryptoCurrency.zaddr) - .map((i) => CryptoCurrency.all - .where((i) => i != CryptoCurrency.zaddr) - .map((k) => ExchangePair(from: i, to: k, reverse: true))) - .expand((i) => i) - .toList()); + SimpleSwapExchangeProvider() : super(pairList: supportedPairs(_notSupported)); + static const List _notSupported = [ + CryptoCurrency.zaddr, + CryptoCurrency.xhv, + ]; + + static final apiKey = + DeviceInfo.instance.isMobile ? secrets.simpleSwapApiKey : secrets.simpleSwapApiKeyDesktop; static const apiAuthority = 'api.simpleswap.io'; static const getEstimatePath = '/v1/get_estimated'; static const rangePath = '/v1/get_ranges'; static const getExchangePath = '/v1/get_exchange'; static const createExchangePath = '/v1/create_exchange'; - static final apiKey = DeviceInfo.instance.isMobile ? secrets.simpleSwapApiKey : secrets.simpleSwapApiKeyDesktop; @override - ExchangeProviderDescription get description => - ExchangeProviderDescription.simpleSwap; + String get title => 'SimpleSwap'; @override - Future fetchRate( - {required CryptoCurrency from, - required CryptoCurrency to, - required double amount, - required bool isFixedRateMode, - required bool isReceiveAmount}) async { - try { - if (amount == 0) { - return 0.0; - } - final fromCurrency = _normalizeCryptoCurrency(from); - final toCurrency = _normalizeCryptoCurrency(to); - final params = { - 'api_key': apiKey, - 'currency_from': fromCurrency, - 'currency_to': toCurrency, - 'amount': amount.toString(), - 'fixed': isFixedRateMode.toString() - }; - final uri = Uri.https(apiAuthority, getEstimatePath, params); - final response = await get(uri); + bool get isAvailable => true; - if (response.body == "null") return 0.00; - final data = json.decode(response.body) as String; - return double.parse(data) / amount; - } catch (_) { - return 0.00; - } - } + @override + bool get isEnabled => true; + + @override + bool get supportsFixedRate => false; + + @override + ExchangeProviderDescription get description => ExchangeProviderDescription.simpleSwap; @override Future checkIsAvailable() async { @@ -76,20 +54,79 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { } @override - Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { - final _request = request as SimpleSwapRequest; - final headers = { - 'Content-Type': 'application/json'}; - final params = { + Future fetchLimits( + {required CryptoCurrency from, + required CryptoCurrency to, + required bool isFixedRateMode}) async { + final params = { 'api_key': apiKey, + 'fixed': isFixedRateMode.toString(), + 'currency_from': _normalizeCurrency(from), + 'currency_to': _normalizeCurrency(to), }; + final uri = Uri.https(apiAuthority, rangePath, params); + + final response = await get(uri); + + if (response.statusCode == 500) { + final responseJSON = json.decode(response.body) as Map; + final error = responseJSON['message'] as String; + + throw Exception('$error'); + } + + if (response.statusCode != 200) { + throw Exception('Unexpected http status: ${response.statusCode}'); + } + + final responseJSON = json.decode(response.body) as Map; + final min = double.tryParse(responseJSON['min'] as String? ?? ''); + final max = double.tryParse(responseJSON['max'] as String? ?? ''); + + return Limits(min: min, max: max); + } + + @override + Future fetchRate( + {required CryptoCurrency from, + required CryptoCurrency to, + required double amount, + required bool isFixedRateMode, + required bool isReceiveAmount}) async { + try { + if (amount == 0) return 0.0; + + final params = { + 'api_key': apiKey, + 'currency_from': _normalizeCurrency(from), + 'currency_to': _normalizeCurrency(to), + 'amount': amount.toString(), + 'fixed': isFixedRateMode.toString() + }; + final uri = Uri.https(apiAuthority, getEstimatePath, params); + final response = await get(uri); + + if (response.body == "null") return 0.00; + + final data = json.decode(response.body) as String; + + return double.parse(data) / amount; + } catch (_) { + return 0.00; + } + } + + @override + Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { + final headers = {'Content-Type': 'application/json'}; + final params = {'api_key': apiKey}; final body = { - "currency_from": _normalizeCryptoCurrency(_request.from), - "currency_to": _normalizeCryptoCurrency(_request.to), - "amount": _request.amount, + "currency_from": _normalizeCurrency(request.fromCurrency), + "currency_to": _normalizeCurrency(request.toCurrency), + "amount": request.fromAmount, "fixed": isFixedRateMode, - "user_refund_address": _request.refundAddress, - "address_to": _request.address + "user_refund_address": request.refundAddress, + "address_to": request.toAddress }; final uri = Uri.https(apiAuthority, createExchangePath, params); @@ -112,56 +149,22 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { final payoutAddress = responseJSON['address_to'] as String; final settleAddress = responseJSON['user_refund_address'] as String; final extraId = responseJSON['extra_id_from'] as String?; + return Trade( id: id, provider: description, - from: _request.from, - to: _request.to, + from: request.fromCurrency, + to: request.toCurrency, inputAddress: inputAddress, refundAddress: settleAddress, extraId: extraId, state: TradeState.created, - amount: _request.amount, + amount: request.fromAmount, payoutAddress: payoutAddress, createdAt: DateTime.now(), ); } - @override - Future fetchLimits({ - required CryptoCurrency from, - required CryptoCurrency to, - required bool isFixedRateMode}) async { - final fromCurrency = _normalizeCryptoCurrency(from); - final toCurrency = _normalizeCryptoCurrency(to); - final params = { - 'api_key': apiKey, - 'fixed': isFixedRateMode.toString(), - 'currency_from': fromCurrency, - 'currency_to': toCurrency, - }; - final uri = Uri.https(apiAuthority, rangePath, params); - - final response = await get(uri); - - if (response.statusCode == 500) { - final responseJSON = json.decode(response.body) as Map; - final error = responseJSON['message'] as String; - - throw Exception('$error'); - } - - if (response.statusCode != 200) { - throw Exception('Unexpected http status: ${response.statusCode}'); - } - - final responseJSON = json.decode(response.body) as Map; - final min = double.tryParse(responseJSON['min'] as String? ?? ''); - final max = double.tryParse(responseJSON['max'] as String? ?? ''); - - return Limits(min: min, max: max); - } - @override Future findTradeById({required String id}) async { final params = {'api_key': apiKey, 'id': id}; @@ -185,42 +188,27 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { final responseJSON = json.decode(response.body) as Map; final fromCurrency = responseJSON['currency_from'] as String; - final from = CryptoCurrency.fromString(fromCurrency); final toCurrency = responseJSON['currency_to'] as String; - final to = CryptoCurrency.fromString(toCurrency); final inputAddress = responseJSON['address_from'] as String; final expectedSendAmount = responseJSON['expected_amount'].toString(); final extraId = responseJSON['extra_id_from'] as String?; final status = responseJSON['status'] as String; final payoutAddress = responseJSON['address_to'] as String; - final state = TradeState.deserialize(raw: status); return Trade( id: id, - from: from, - to: to, + from: CryptoCurrency.fromString(fromCurrency), + to: CryptoCurrency.fromString(toCurrency), extraId: extraId, provider: description, inputAddress: inputAddress, amount: expectedSendAmount, - state: state, + state: TradeState.deserialize(raw: status), payoutAddress: payoutAddress, ); } - @override - bool get isAvailable => true; - - @override - bool get isEnabled => true; - - @override - bool get supportsFixedRate => false; - - @override - String get title => 'SimpleSwap'; - - static String _normalizeCryptoCurrency(CryptoCurrency currency) { + static String _normalizeCurrency(CryptoCurrency currency) { switch (currency) { case CryptoCurrency.zaddr: return 'zec'; diff --git a/lib/exchange/trocador/trocador_exchange_provider.dart b/lib/exchange/provider/trocador_exchange_provider.dart similarity index 78% rename from lib/exchange/trocador/trocador_exchange_provider.dart rename to lib/exchange/provider/trocador_exchange_provider.dart index b42291ed7..3d08bbd37 100644 --- a/lib/exchange/trocador/trocador_exchange_provider.dart +++ b/lib/exchange/provider/trocador_exchange_provider.dart @@ -1,21 +1,20 @@ import 'dart:convert'; -import 'package:cake_wallet/exchange/exchange_pair.dart'; -import 'package:cake_wallet/exchange/exchange_provider.dart'; -import 'package:cake_wallet/exchange/trade_state.dart'; -import 'package:cake_wallet/exchange/trocador/trocador_request.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/exchange/trade_request.dart'; -import 'package:cake_wallet/exchange/trade.dart'; -import 'package:cake_wallet/exchange/limits.dart'; -import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; +import 'package:cake_wallet/exchange/exchange_provider_description.dart'; +import 'package:cake_wallet/exchange/limits.dart'; +import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; +import 'package:cake_wallet/exchange/trade.dart'; +import 'package:cake_wallet/exchange/trade_request.dart'; +import 'package:cake_wallet/exchange/trade_state.dart'; +import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; +import 'package:cw_core/crypto_currency.dart'; import 'package:http/http.dart'; class TrocadorExchangeProvider extends ExchangeProvider { TrocadorExchangeProvider({this.useTorOnly = false}) : _lastUsedRateId = '', - super(pairList: _supportedPairs()); + super(pairList: supportedPairs(_notSupported)); bool useTorOnly; @@ -24,135 +23,58 @@ class TrocadorExchangeProvider extends ExchangeProvider { CryptoCurrency.zaddr, ]; - static List _supportedPairs() { - final supportedCurrencies = - CryptoCurrency.all.where((element) => !_notSupported.contains(element)).toList(); - - return supportedCurrencies - .map((i) => supportedCurrencies.map((k) => ExchangePair(from: i, to: k, reverse: true))) - .expand((i) => i) - .toList(); - } - + static const apiKey = secrets.trocadorApiKey; static const onionApiAuthority = 'trocadorfyhlu27aefre5u7zri66gudtzdyelymftvr4yjwcxhfaqsid.onion'; static const clearNetAuthority = 'trocador.app'; - static const apiKey = secrets.trocadorApiKey; static const markup = secrets.trocadorExchangeMarkup; static const newRatePath = '/api/new_rate'; static const createTradePath = 'api/new_trade'; static const tradePath = 'api/trade'; static const coinPath = 'api/coin'; + String _lastUsedRateId; @override - Future checkIsAvailable() async => true; + String get title => 'Trocador'; @override - Future createTrade({required TradeRequest request, required bool isFixedRateMode}) { - final _request = request as TrocadorRequest; - return _createTrade(request: _request, isFixedRateMode: isFixedRateMode); - } + bool get isAvailable => true; - Future _createTrade({ - required TrocadorRequest request, - required bool isFixedRateMode, - }) async { - final params = { - 'api_key': apiKey, - 'ticker_from': _normalizeCurrency(request.from), - 'ticker_to': _normalizeCurrency(request.to), - 'network_from': _networkFor(request.from), - 'network_to': _networkFor(request.to), - 'payment': isFixedRateMode ? 'True' : 'False', - 'min_kycrating': 'C', - 'markup': markup, - 'best_only': 'True', - if (!isFixedRateMode) 'amount_from': request.fromAmount, - if (isFixedRateMode) 'amount_to': request.toAmount, - 'address': request.address, - 'refund': request.refundAddress - }; + @override + bool get isEnabled => true; - if (isFixedRateMode) { - await fetchRate( - from: request.from, - to: request.to, - amount: double.tryParse(request.toAmount) ?? 0, - isFixedRateMode: true, - isReceiveAmount: true, - ); - params['id'] = _lastUsedRateId; - } + @override + bool get supportsFixedRate => true; - final uri = await _getUri(createTradePath, params); - final response = await get(uri); - - if (response.statusCode == 400) { - final responseJSON = json.decode(response.body) as Map; - final error = responseJSON['error'] as String; - final message = responseJSON['message'] as String; - throw Exception('${error}\n$message'); - } - - if (response.statusCode != 200) { - throw Exception('Unexpected http status: ${response.statusCode}'); - } - - final responseJSON = json.decode(response.body) as Map; - final id = responseJSON['trade_id'] as String; - final inputAddress = responseJSON['address_provider'] as String; - final refundAddress = responseJSON['refund_address'] as String; - final status = responseJSON['status'] as String; - final state = TradeState.deserialize(raw: status); - final payoutAddress = responseJSON['address_user'] as String; - final date = responseJSON['date'] as String; - final password = responseJSON['password'] as String; - final providerId = responseJSON['id_provider'] as String; - final providerName = responseJSON['provider'] as String; - - return Trade( - id: id, - from: request.from, - to: request.to, - provider: description, - inputAddress: inputAddress, - refundAddress: refundAddress, - state: state, - password: password, - providerId: providerId, - providerName: providerName, - createdAt: DateTime.tryParse(date)?.toLocal(), - amount: responseJSON['amount_from']?.toString() ?? request.fromAmount, - payoutAddress: payoutAddress); - } + @override + bool get supportsOnionAddress => true; @override ExchangeProviderDescription get description => ExchangeProviderDescription.trocador; + @override + Future checkIsAvailable() async => true; + @override Future fetchLimits( {required CryptoCurrency from, required CryptoCurrency to, required bool isFixedRateMode}) async { - final params = { + final params = { 'api_key': apiKey, 'ticker': _normalizeCurrency(from), 'name': from.name, }; final uri = await _getUri(coinPath, params); - final response = await get(uri); - if (response.statusCode != 200) { + if (response.statusCode != 200) throw Exception('Unexpected http status: ${response.statusCode}'); - } final responseJSON = json.decode(response.body) as List; - if (responseJSON.isEmpty) { - throw Exception('No data'); - } + if (responseJSON.isEmpty) throw Exception('No data'); final coinJson = responseJSON.first as Map; @@ -170,9 +92,7 @@ class TrocadorExchangeProvider extends ExchangeProvider { required bool isFixedRateMode, required bool isReceiveAmount}) async { try { - if (amount == 0) { - return 0.0; - } + if (amount == 0) return 0.0; final params = { 'api_key': apiKey, @@ -195,9 +115,7 @@ class TrocadorExchangeProvider extends ExchangeProvider { final toAmount = double.parse(responseJSON['amount_to'].toString()); final rateId = responseJSON['trade_id'] as String? ?? ''; - if (rateId.isNotEmpty) { - _lastUsedRateId = rateId; - } + if (rateId.isNotEmpty) _lastUsedRateId = rateId; return isReceiveAmount ? (amount / fromAmount) : (toAmount / amount); } catch (e) { @@ -206,40 +124,103 @@ class TrocadorExchangeProvider extends ExchangeProvider { } } + @override + Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { + final params = { + 'api_key': apiKey, + 'ticker_from': _normalizeCurrency(request.fromCurrency), + 'ticker_to': _normalizeCurrency(request.toCurrency), + 'network_from': _networkFor(request.fromCurrency), + 'network_to': _networkFor(request.toCurrency), + 'payment': isFixedRateMode ? 'True' : 'False', + 'min_kycrating': 'C', + 'markup': markup, + 'best_only': 'True', + if (!isFixedRateMode) 'amount_from': request.fromAmount, + if (isFixedRateMode) 'amount_to': request.toAmount, + 'address': request.toAddress, + 'refund': request.refundAddress + }; + + if (isFixedRateMode) { + await fetchRate( + from: request.fromCurrency, + to: request.toCurrency, + amount: double.tryParse(request.toAmount) ?? 0, + isFixedRateMode: true, + isReceiveAmount: true, + ); + params['id'] = _lastUsedRateId; + } + + final uri = await _getUri(createTradePath, params); + final response = await get(uri); + + if (response.statusCode == 400) { + final responseJSON = json.decode(response.body) as Map; + final error = responseJSON['error'] as String; + final message = responseJSON['message'] as String; + throw Exception('${error}\n$message'); + } + + if (response.statusCode != 200) + throw Exception('Unexpected http status: ${response.statusCode}'); + + final responseJSON = json.decode(response.body) as Map; + final id = responseJSON['trade_id'] as String; + final inputAddress = responseJSON['address_provider'] as String; + final refundAddress = responseJSON['refund_address'] as String; + final status = responseJSON['status'] as String; + final payoutAddress = responseJSON['address_user'] as String; + final date = responseJSON['date'] as String; + final password = responseJSON['password'] as String; + final providerId = responseJSON['id_provider'] as String; + final providerName = responseJSON['provider'] as String; + + return Trade( + id: id, + from: request.fromCurrency, + to: request.toCurrency, + provider: description, + inputAddress: inputAddress, + refundAddress: refundAddress, + state: TradeState.deserialize(raw: status), + password: password, + providerId: providerId, + providerName: providerName, + createdAt: DateTime.tryParse(date)?.toLocal(), + amount: responseJSON['amount_from']?.toString() ?? request.fromAmount, + payoutAddress: payoutAddress); + } + @override Future findTradeById({required String id}) async { final uri = await _getUri(tradePath, {'api_key': apiKey, 'id': id}); return get(uri).then((response) { - if (response.statusCode != 200) { + if (response.statusCode != 200) throw Exception('Unexpected http status: ${response.statusCode}'); - } final responseListJson = json.decode(response.body) as List; - final responseJSON = responseListJson.first; final id = responseJSON['trade_id'] as String; final payoutAddress = responseJSON['address_user'] as String; final refundAddress = responseJSON['refund_address'] as String; final inputAddress = responseJSON['address_provider'] as String; final fromAmount = responseJSON['amount_from']?.toString() ?? '0'; - final from = CryptoCurrency.fromString(responseJSON['ticker_from'] as String); - final to = CryptoCurrency.fromString(responseJSON['ticker_to'] as String); - final state = TradeState.deserialize(raw: responseJSON['status'] as String); - final date = DateTime.parse(responseJSON['date'] as String); final password = responseJSON['password'] as String; final providerId = responseJSON['id_provider'] as String; final providerName = responseJSON['provider'] as String; return Trade( id: id, - from: from, - to: to, + from: CryptoCurrency.fromString(responseJSON['ticker_from'] as String), + to: CryptoCurrency.fromString(responseJSON['ticker_to'] as String), provider: description, inputAddress: inputAddress, refundAddress: refundAddress, - createdAt: date, + createdAt: DateTime.parse(responseJSON['date'] as String), amount: fromAmount, - state: state, + state: TradeState.deserialize(raw: responseJSON['status'] as String), payoutAddress: payoutAddress, password: password, providerId: providerId, @@ -248,21 +229,6 @@ class TrocadorExchangeProvider extends ExchangeProvider { }); } - @override - bool get isAvailable => true; - - @override - bool get isEnabled => true; - - @override - bool get supportsFixedRate => true; - - @override - bool get supportsOnionAddress => true; - - @override - String get title => 'Trocador'; - String _networkFor(CryptoCurrency currency) { switch (currency) { case CryptoCurrency.eth: @@ -301,15 +267,9 @@ class TrocadorExchangeProvider extends ExchangeProvider { } Future _getUri(String path, Map queryParams) async { - if (!supportsOnionAddress) { - return Uri.https(clearNetAuthority, path, queryParams); - } - final uri = Uri.http(onionApiAuthority, path, queryParams); - if (useTorOnly) { - return uri; - } + if (useTorOnly) return uri; try { await get(uri); diff --git a/lib/exchange/sideshift/sideshift_request.dart b/lib/exchange/sideshift/sideshift_request.dart deleted file mode 100644 index 2f468a6aa..000000000 --- a/lib/exchange/sideshift/sideshift_request.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:cake_wallet/exchange/trade_request.dart'; -import 'package:cw_core/crypto_currency.dart'; - -class SideShiftRequest extends TradeRequest { - SideShiftRequest( - {required this.depositMethod, - required this.settleMethod, - required this.depositAmount, - required this.settleAddress, - required this.refundAddress}); - - final CryptoCurrency depositMethod; - final CryptoCurrency settleMethod; - final String depositAmount; - final String settleAddress; - final String refundAddress; -} diff --git a/lib/exchange/simpleswap/simpleswap_request.dart b/lib/exchange/simpleswap/simpleswap_request.dart deleted file mode 100644 index 9dc81bb2d..000000000 --- a/lib/exchange/simpleswap/simpleswap_request.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:cake_wallet/exchange/trade_request.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:flutter/material.dart'; - -class SimpleSwapRequest extends TradeRequest { - SimpleSwapRequest({ - required this.from, - required this.to, - required this.address, - required this.amount, - required this.refundAddress, - this.toAmount = '' - }); - - CryptoCurrency from; - CryptoCurrency to; - String address; - String amount; - String toAmount; - String refundAddress; -} diff --git a/lib/exchange/trade.dart b/lib/exchange/trade.dart index db8c8fb3b..3e557d39e 100644 --- a/lib/exchange/trade.dart +++ b/lib/exchange/trade.dart @@ -1,6 +1,6 @@ -import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; +import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/format_amount.dart'; import 'package:cw_core/hive_type_ids.dart'; import 'package:hive/hive.dart'; @@ -28,18 +28,13 @@ class Trade extends HiveObject { this.providerId, this.providerName, }) { - if (provider != null) { - providerRaw = provider.raw; - } - if (from != null) { - fromRaw = from.raw; - } - if (to != null) { - toRaw = to.raw; - } - if (state != null) { - stateRaw = state.raw; - } + if (provider != null) providerRaw = provider.raw; + + if (from != null) fromRaw = from.raw; + + if (to != null) toRaw = to.raw; + + if (state != null) stateRaw = state.raw; } static const typeId = TRADE_TYPE_ID; diff --git a/lib/exchange/trade_not_created_exeption.dart b/lib/exchange/trade_not_created_exception.dart similarity index 61% rename from lib/exchange/trade_not_created_exeption.dart rename to lib/exchange/trade_not_created_exception.dart index 181d05397..2c4a36d5f 100644 --- a/lib/exchange/trade_not_created_exeption.dart +++ b/lib/exchange/trade_not_created_exception.dart @@ -8,12 +8,5 @@ class TradeNotCreatedException implements Exception { String description; @override - String toString() { - var text = provider != null - ? S.current.trade_for_not_created(provider.title) - : S.current.trade_not_created; - text += ' $description'; - - return text; - } + String toString() => '${S.current.trade_for_not_created(provider.title)} $description'; } diff --git a/lib/exchange/trade_not_found_exception.dart b/lib/exchange/trade_not_found_exception.dart new file mode 100644 index 000000000..cad8afd78 --- /dev/null +++ b/lib/exchange/trade_not_found_exception.dart @@ -0,0 +1,13 @@ +import 'package:cake_wallet/exchange/exchange_provider_description.dart'; +import 'package:cake_wallet/generated/i18n.dart'; + +class TradeNotFoundException implements Exception { + TradeNotFoundException(this.tradeId, {required this.provider, this.description = ''}); + + String tradeId; + ExchangeProviderDescription provider; + String description; + + @override + String toString() => '${S.current.trade_id_not_found(tradeId, provider.title)} $description'; +} diff --git a/lib/exchange/trade_not_found_exeption.dart b/lib/exchange/trade_not_found_exeption.dart deleted file mode 100644 index 17e38627a..000000000 --- a/lib/exchange/trade_not_found_exeption.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'package:cake_wallet/exchange/exchange_provider_description.dart'; -import 'package:cake_wallet/generated/i18n.dart'; - -class TradeNotFoundException implements Exception { - TradeNotFoundException(this.tradeId, {this.provider, this.description = ''}); - - String? tradeId; - ExchangeProviderDescription? provider; - String description; - - @override - String toString() { - var text = tradeId != null && provider != null - ? S.current.trade_id_not_found(tradeId!, provider!.title) - : S.current.trade_not_found; - text += ' $description'; - - return text; - } -} diff --git a/lib/exchange/trade_request.dart b/lib/exchange/trade_request.dart index fb75ef14c..826bd8733 100644 --- a/lib/exchange/trade_request.dart +++ b/lib/exchange/trade_request.dart @@ -1 +1,20 @@ -abstract class TradeRequest {} \ No newline at end of file +import 'package:cw_core/crypto_currency.dart'; + +class TradeRequest { + TradeRequest( + {required this.fromCurrency, + required this.toCurrency, + required this.toAddress, + required this.refundAddress, + required this.fromAmount, + this.toAmount = '', + this.isFixedRate = false}); + + final CryptoCurrency fromCurrency; + final CryptoCurrency toCurrency; + final String toAddress; + final String refundAddress; + final String fromAmount; + final String toAmount; + final bool isFixedRate; +} diff --git a/lib/exchange/trade_state.dart b/lib/exchange/trade_state.dart index ebf74ce7a..ed56d9845 100644 --- a/lib/exchange/trade_state.dart +++ b/lib/exchange/trade_state.dart @@ -1,9 +1,7 @@ -import 'package:flutter/foundation.dart'; import 'package:cw_core/enumerable_item.dart'; class TradeState extends EnumerableItem with Serializable { - const TradeState({required String raw, required String title}) - : super(raw: raw, title: title); + const TradeState({required String raw, required String title}) : super(raw: raw, title: title); @override bool operator ==(Object other) => other is TradeState && other.raw == raw; @@ -13,12 +11,10 @@ class TradeState extends EnumerableItem with Serializable { static const trading = TradeState(raw: 'trading', title: 'Trading'); static const traded = TradeState(raw: 'traded', title: 'Traded'); static const complete = TradeState(raw: 'complete', title: 'Complete'); - static const toBeCreated = - TradeState(raw: 'TO_BE_CREATED', title: 'To be created'); + static const toBeCreated = TradeState(raw: 'TO_BE_CREATED', title: 'To be created'); static const unpaid = TradeState(raw: 'UNPAID', title: 'Unpaid'); static const underpaid = TradeState(raw: 'UNDERPAID', title: 'Underpaid'); - static const paidUnconfirmed = - TradeState(raw: 'PAID_UNCONFIRMED', title: 'Paid unconfirmed'); + static const paidUnconfirmed = TradeState(raw: 'PAID_UNCONFIRMED', title: 'Paid unconfirmed'); static const paid = TradeState(raw: 'PAID', title: 'Paid'); static const btcSent = TradeState(raw: 'BTC_SENT', title: 'Btc sent'); static const timeout = TradeState(raw: 'TIMED_OUT', title: 'Timeout'); @@ -27,8 +23,7 @@ class TradeState extends EnumerableItem with Serializable { static const finished = TradeState(raw: 'finished', title: 'Finished'); static const waiting = TradeState(raw: 'waiting', title: 'Waiting'); static const processing = TradeState(raw: 'processing', title: 'Processing'); - static const waitingPayment = - TradeState(raw: 'waitingPayment', title: 'Waiting payment'); + static const waitingPayment = TradeState(raw: 'waitingPayment', title: 'Waiting payment'); static const waitingAuthorization = TradeState(raw: 'waitingAuthorization', title: 'Waiting authorization'); static const failed = TradeState(raw: 'failed', title: 'Failed'); diff --git a/lib/exchange/trocador/trocador_request.dart b/lib/exchange/trocador/trocador_request.dart deleted file mode 100644 index fbb8fdc84..000000000 --- a/lib/exchange/trocador/trocador_request.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:cake_wallet/exchange/trade_request.dart'; -import 'package:cw_core/crypto_currency.dart'; - -class TrocadorRequest extends TradeRequest { - TrocadorRequest( - {required this.from, - required this.to, - required this.address, - required this.fromAmount, - required this.toAmount, - required this.refundAddress, - required this.isReverse}); - - CryptoCurrency from; - CryptoCurrency to; - String address; - String fromAmount; - String toAmount; - String refundAddress; - bool isReverse; -} diff --git a/lib/exchange/utils/currency_pairs_utils.dart b/lib/exchange/utils/currency_pairs_utils.dart new file mode 100644 index 000000000..eeb1b5232 --- /dev/null +++ b/lib/exchange/utils/currency_pairs_utils.dart @@ -0,0 +1,12 @@ +import 'package:cake_wallet/exchange/exchange_pair.dart'; +import 'package:cw_core/crypto_currency.dart'; + +List supportedPairs(List notSupported) { + final supportedCurrencies = + CryptoCurrency.all.where((element) => !notSupported.contains(element)).toList(); + + return supportedCurrencies + .map((i) => supportedCurrencies.map((k) => ExchangePair(from: i, to: k, reverse: true))) + .expand((i) => i) + .toList(); +} diff --git a/lib/exchange/xmrto/xmrto_exchange_provider.dart b/lib/exchange/xmrto/xmrto_exchange_provider.dart deleted file mode 100644 index 536754e18..000000000 --- a/lib/exchange/xmrto/xmrto_exchange_provider.dart +++ /dev/null @@ -1,236 +0,0 @@ -import 'dart:convert'; -import 'package:flutter/foundation.dart'; -import 'package:http/http.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/exchange/exchange_pair.dart'; -import 'package:cake_wallet/exchange/exchange_provider.dart'; -import 'package:cake_wallet/exchange/limits.dart'; -import 'package:cake_wallet/exchange/trade.dart'; -import 'package:cake_wallet/exchange/trade_request.dart'; -import 'package:cake_wallet/exchange/trade_state.dart'; -import 'package:cake_wallet/exchange/xmrto/xmrto_trade_request.dart'; -import 'package:cake_wallet/exchange/trade_not_created_exeption.dart'; -import 'package:cake_wallet/exchange/exchange_provider_description.dart'; -import 'package:cake_wallet/exchange/trade_not_found_exeption.dart'; -import 'package:cake_wallet/generated/i18n.dart'; - -class XMRTOExchangeProvider extends ExchangeProvider { - XMRTOExchangeProvider() - : _isAvailable = false, - super(pairList: [ - ExchangePair( - from: CryptoCurrency.xmr, to: CryptoCurrency.btc, reverse: false) - ]); - - static const userAgent = 'CakeWallet/XMR iOS'; - static const originalApiUri = 'https://xmr.to/api/v3/xmr2btc'; - static const _orderParameterUriSuffix = '/order_parameter_query'; - static const _orderStatusUriSuffix = '/order_status_query/'; - static const _orderCreateUriSuffix = '/order_create/'; - static const _headers = { - 'Content-Type': 'application/json', - 'User-Agent': userAgent - }; - - static Future _checkIsAvailable() async { - const url = originalApiUri + _orderParameterUriSuffix; - final uri = Uri.parse(url); - final response = await get(uri, headers: _headers); - return !(response.statusCode == 403); - } - - @override - String get title => 'XMR.TO'; - - @override - bool get isAvailable => _isAvailable; - - @override - bool get isEnabled => true; - - @override - bool get supportsFixedRate => false; - - @override - ExchangeProviderDescription get description => - ExchangeProviderDescription.xmrto; - - double _rate = 0; - bool _isAvailable; - - @override - Future checkIsAvailable() async { - _isAvailable = await _checkIsAvailable(); - return isAvailable; - } - - @override - Future fetchLimits({ - required CryptoCurrency from, - required CryptoCurrency to, - required bool isFixedRateMode}) async { - final url = originalApiUri + _orderParameterUriSuffix; - final uri = Uri.parse(url); - final response = await get(uri); - final correction = 0.001; - - if (response.statusCode != 200) { - return Limits(min: 0, max: 0); - } - - final responseJSON = json.decode(response.body) as Map; - double min = double.parse(responseJSON['lower_limit'] as String); - double max = double.parse(responseJSON['upper_limit'] as String); - final price = double.parse(responseJSON['price'] as String); - - if (price > 0) { - try { - min = min / price + correction; - min = _limitsFormat(min); - max = max / price - correction; - max = _limitsFormat(max); - } catch (e) { - min = 0; - max = 0; - } - } else { - min = 0; - max = 0; - } - - return Limits(min: min, max: max); - } - - @override - Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { - final _request = request as XMRTOTradeRequest; - final url = originalApiUri + _orderCreateUriSuffix; - final _amount = - _request.isBTCRequest ? _request.receiveAmount : _request.amount; - final _amountCurrency = _request.isBTCRequest - ? _request.to.toString() - : _request.from.toString(); - final pattern = '^([0-9]+([.\,][0-9]{0,8})?|[.\,][0-9]{1,8})\$'; - final isValid = RegExp(pattern).hasMatch(_amount); - - if (!isValid) { - throw TradeNotCreatedException(description, - description: S.current.xmr_to_error_description); - } - - final body = { - 'amount': _amount, - 'amount_currency': _amountCurrency, - 'btc_dest_address': _request.address}; - final uri = Uri.parse(url); - final response = - await post(uri, headers: _headers, body: json.encode(body)); - - if (response.statusCode != 201) { - if (response.statusCode == 400) { - final responseJSON = json.decode(response.body) as Map; - final error = responseJSON['error_msg'] as String; - - throw TradeNotCreatedException(description, description: error); - } - - throw TradeNotCreatedException(description); - } - - final responseJSON = json.decode(response.body) as Map; - final uuid = responseJSON["uuid"] as String; - - return Trade( - id: uuid, - provider: description, - from: _request.from, - to: _request.to, - state: TradeState.created, - amount: _request.amount, - createdAt: DateTime.now()); - } - - @override - Future findTradeById({required String id}) async { - final url = originalApiUri + _orderStatusUriSuffix; - final uri = Uri.parse(url); - final body = {'uuid': id}; - final response = - await post(uri, headers: _headers, body: json.encode(body)); - - if (response.statusCode != 200) { - if (response.statusCode == 400) { - final responseJSON = json.decode(response.body) as Map; - final error = responseJSON['error_msg'] as String; - - throw TradeNotFoundException(id, - provider: description, description: error); - } - - throw TradeNotFoundException(id, provider: description); - } - - final responseJSON = json.decode(response.body) as Map; - final address = responseJSON['receiving_subaddress'] as String; - final paymentId = responseJSON['xmr_required_payment_id_short'] as String; - final amount = responseJSON['incoming_amount_total'].toString(); - final stateRaw = responseJSON['state'] as String; - final expiredAtRaw = responseJSON['expires_at'] as String; - final expiredAt = DateTime.parse(expiredAtRaw).toLocal(); - final outputTransaction = responseJSON['btc_transaction_id'] as String; - final state = TradeState.deserialize(raw: stateRaw); - - return Trade( - id: id, - provider: description, - from: CryptoCurrency.xmr, - to: CryptoCurrency.btc, - inputAddress: address, - extraId: paymentId, - expiredAt: expiredAt, - amount: amount, - state: state, - outputTransaction: outputTransaction); - } - - @override - Future fetchRate( - {required CryptoCurrency from, - required CryptoCurrency to, - required double amount, - required bool isFixedRateMode, - required bool isReceiveAmount}) async { - if (from != CryptoCurrency.xmr && to != CryptoCurrency.btc) { - return 0; - } - - if (_rate == 0) { - _rate = await _fetchRates(); - } - - final double result = isReceiveAmount - ? _rate == 0 - ? 0 - : amount / _rate - : _rate * amount; - - return double.parse(result.toStringAsFixed(12)); - } - - Future _fetchRates() async { - try { - final url = originalApiUri + _orderParameterUriSuffix; - final uri = Uri.parse(url); - final response = await get(uri, headers: _headers); - final responseJSON = json.decode(response.body) as Map; - final price = double.parse(responseJSON['price'] as String); - - return price; - } catch (e) { - print(e.toString()); - return 0.0; - } - } - - double _limitsFormat(double limit) => double.parse(limit.toStringAsFixed(3)); -} diff --git a/lib/exchange/xmrto/xmrto_trade_request.dart b/lib/exchange/xmrto/xmrto_trade_request.dart deleted file mode 100644 index 4ff8d6645..000000000 --- a/lib/exchange/xmrto/xmrto_trade_request.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/exchange/trade_request.dart'; - -class XMRTOTradeRequest extends TradeRequest { - XMRTOTradeRequest( - {required this.from, - required this.to, - required this.amount, - required this.receiveAmount, - required this.address, - required this.refundAddress, - required this.isBTCRequest}); - - final CryptoCurrency from; - final CryptoCurrency to; - final String amount; - final String receiveAmount; - final String address; - final String refundAddress; - final bool isBTCRequest; -} diff --git a/lib/src/screens/exchange/exchange_template_page.dart b/lib/src/screens/exchange/exchange_template_page.dart index 62f36a3fd..31f35661d 100644 --- a/lib/src/screens/exchange/exchange_template_page.dart +++ b/lib/src/screens/exchange/exchange_template_page.dart @@ -1,6 +1,6 @@ import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; -import 'package:cake_wallet/exchange/exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:flutter/material.dart'; @@ -9,9 +9,6 @@ import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/exchange/xmrto/xmrto_exchange_provider.dart'; -// import 'package:cake_wallet/exchange/exchange_trade_state.dart'; -// import 'package:cake_wallet/exchange/limits_state.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/exchange_card.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; @@ -176,9 +173,7 @@ class ExchangeTemplatePage extends BasePage { exchangeViewModel.wallet.currency ? exchangeViewModel.wallet.walletAddresses.address : exchangeViewModel.receiveAddress, - initialIsAmountEditable: - exchangeViewModel.provider is - XMRTOExchangeProvider ? true : false, + initialIsAmountEditable: false, initialIsAddressEditable: exchangeViewModel.isReceiveAddressEnabled, isAmountEstimated: true, @@ -205,26 +200,25 @@ class ExchangeTemplatePage extends BasePage { bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), bottomSection: Column(children: [ - Padding( - padding: EdgeInsets.only(bottom: 15), - child: Observer(builder: (_) { - final description = - exchangeViewModel.provider is XMRTOExchangeProvider - ? S.of(context).amount_is_guaranteed - : S.of(context).amount_is_estimate; - return Center( - child: Text( - description, - textAlign: TextAlign.center, - style: TextStyle( - color: Theme.of(context).extension()!.receiveAmountColor, - fontWeight: FontWeight.w500, - fontSize: 12), + Padding( + padding: EdgeInsets.only(bottom: 15), + child: Observer( + builder: (_) => Center( + child: Text( + S.of(context).amount_is_estimate, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context) + .extension()! + .receiveAmountColor, + fontWeight: FontWeight.w500, + fontSize: 12, + ), + ), + ), ), - ); - }), - ), - PrimaryButton( + ), + PrimaryButton( onPressed: () { if (_formKey.currentState != null && _formKey.currentState!.validate()) { exchangeViewModel.addTemplate( @@ -340,9 +334,7 @@ class ExchangeTemplatePage extends BasePage { }); reaction((_) => exchangeViewModel.provider, (ExchangeProvider? provider) { - provider is XMRTOExchangeProvider - ? receiveKey.currentState!.isAmountEditable(isEditable: true) - : receiveKey.currentState!.isAmountEditable(isEditable: false); + receiveKey.currentState!.isAmountEditable(isEditable: false); }); /*reaction((_) => exchangeViewModel.limitsState, (LimitsState state) { diff --git a/lib/src/screens/trade_details/trade_details_page.dart b/lib/src/screens/trade_details/trade_details_page.dart index 1bb8872e8..1028c3939 100644 --- a/lib/src/screens/trade_details/trade_details_page.dart +++ b/lib/src/screens/trade_details/trade_details_page.dart @@ -1,18 +1,19 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/trade_details/track_trade_list_item.dart'; +import 'package:cake_wallet/src/screens/trade_details/trade_details_list_card.dart'; +import 'package:cake_wallet/src/screens/trade_details/trade_details_status_item.dart'; +import 'package:cake_wallet/src/screens/trade_details/trade_provider_unsupported_item.dart'; +import 'package:cake_wallet/src/widgets/list_row.dart'; import 'package:cake_wallet/src/widgets/standard_list.dart'; import 'package:cake_wallet/src/widgets/standard_list_card.dart'; import 'package:cake_wallet/src/widgets/standard_list_status_row.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/view_model/trade_details_view_model.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/widgets/list_row.dart'; -import 'package:cake_wallet/src/screens/trade_details/track_trade_list_item.dart'; -import 'package:cake_wallet/src/screens/trade_details/trade_details_list_card.dart'; -import 'package:cake_wallet/src/screens/trade_details/trade_details_status_item.dart'; class TradeDetailsPage extends BasePage { TradeDetailsPage(this.tradeDetailsViewModel); @@ -23,8 +24,7 @@ class TradeDetailsPage extends BasePage { final TradeDetailsViewModel tradeDetailsViewModel; @override - Widget body(BuildContext context) => - TradeDetailsPageBody(tradeDetailsViewModel); + Widget body(BuildContext context) => TradeDetailsPageBody(tradeDetailsViewModel); } class TradeDetailsPageBody extends StatefulWidget { @@ -33,8 +33,7 @@ class TradeDetailsPageBody extends StatefulWidget { final TradeDetailsViewModel tradeDetailsViewModel; @override - TradeDetailsPageBodyState createState() => - TradeDetailsPageBodyState(tradeDetailsViewModel); + TradeDetailsPageBodyState createState() => TradeDetailsPageBodyState(tradeDetailsViewModel); } class TradeDetailsPageBodyState extends State { @@ -51,7 +50,7 @@ class TradeDetailsPageBodyState extends State { @override Widget build(BuildContext context) { return Observer(builder: (_) { - int itemsCount = tradeDetailsViewModel.items.length; + final itemsCount = tradeDetailsViewModel.items.length; return SectionStandardList( sectionCount: 1, @@ -59,37 +58,39 @@ class TradeDetailsPageBodyState extends State { itemBuilder: (__, index) { final item = tradeDetailsViewModel.items[index]; - if (item is TrackTradeListItem) { + if (item is TrackTradeListItem) return GestureDetector( onTap: item.onTap, - child: ListRow( - title: '${item.title}', value: '${item.value}')); - } + child: ListRow(title: '${item.title}', value: '${item.value}')); - if (item is DetailsListStatusItem) { - return StandardListStatusRow( - title: item.title, - value: item.value); - } + if (item is DetailsListStatusItem) + return StandardListStatusRow(title: item.title, value: item.value); - if (item is TradeDetailsListCardItem) { + if (item is TradeDetailsListCardItem) return TradeDetailsStandardListCard( - id: item.id, - create: item.createdAt, - pair: item.pair, - currentTheme: tradeDetailsViewModel.settingsStore.currentTheme.type, - onTap: item.onTap,); - } + id: item.id, + create: item.createdAt, + pair: item.pair, + currentTheme: tradeDetailsViewModel.settingsStore.currentTheme.type, + onTap: item.onTap, + ); - return GestureDetector( - onTap: () { - Clipboard.setData(ClipboardData(text: '${item.value}')); - showBar(context, S.of(context).copied_to_clipboard); - }, - child: ListRow( - title: '${item.title}', value: '${item.value}')); + if (item is TradeProviderUnsupportedItem) + return AutoSizeText(item.value, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.red, + )); + + return GestureDetector( + onTap: () { + Clipboard.setData(ClipboardData(text: '${item.value}')); + showBar(context, S.of(context).copied_to_clipboard); + }, + child: ListRow(title: '${item.title}', value: '${item.value}')); }); }); } - } diff --git a/lib/src/screens/trade_details/trade_provider_unsupported_item.dart b/lib/src/screens/trade_details/trade_provider_unsupported_item.dart new file mode 100644 index 000000000..2c4e96c84 --- /dev/null +++ b/lib/src/screens/trade_details/trade_provider_unsupported_item.dart @@ -0,0 +1,5 @@ +import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; + +class TradeProviderUnsupportedItem extends StandartListItem { + TradeProviderUnsupportedItem({required String error}) : super(title: '', value: error); +} diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index 346844171..bc7f53af0 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -1,22 +1,21 @@ import 'dart:async'; -import 'package:cake_wallet/exchange/exolix/exolix_exchange_provider.dart'; -import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'; -import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart'; -import 'package:cake_wallet/exchange/trocador/trocador_exchange_provider.dart'; -import 'package:cw_core/wallet_base.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/exchange/changenow/changenow_exchange_provider.dart'; -import 'package:cake_wallet/exchange/exchange_provider.dart'; + import 'package:cake_wallet/exchange/exchange_provider_description.dart'; -import 'package:cake_wallet/exchange/morphtoken/morphtoken_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/changenow_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/exolix_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/sideshift_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/simpleswap_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; import 'package:cake_wallet/exchange/trade.dart'; -import 'package:cake_wallet/exchange/xmrto/xmrto_exchange_provider.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_item.dart'; import 'package:cake_wallet/store/dashboard/trades_store.dart'; import 'package:cake_wallet/view_model/send/send_view_model.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/wallet_base.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_item.dart'; -import 'package:cake_wallet/generated/i18n.dart'; part 'exchange_trade_view_model.g.dart'; @@ -35,16 +34,10 @@ abstract class ExchangeTradeViewModelBase with Store { tradesStore.trade!.from.tag == CryptoCurrency.eth.title), items = ObservableList() { switch (trade.provider) { - case ExchangeProviderDescription.xmrto: - _provider = XMRTOExchangeProvider(); - break; case ExchangeProviderDescription.changeNow: _provider = ChangeNowExchangeProvider(settingsStore: sendViewModel.balanceViewModel.settingsStore); break; - case ExchangeProviderDescription.morphToken: - _provider = MorphTokenExchangeProvider(trades: trades); - break; case ExchangeProviderDescription.sideShift: _provider = SideShiftExchangeProvider(); break; @@ -60,8 +53,11 @@ abstract class ExchangeTradeViewModelBase with Store { } _updateItems(); - _updateTrade(); - timer = Timer.periodic(Duration(seconds: 20), (_) async => _updateTrade()); + + if (_provider != null) { + _updateTrade(); + timer = Timer.periodic(Duration(seconds: 20), (_) async => _updateTrade()); + } } final WalletBase wallet; @@ -100,10 +96,8 @@ abstract class ExchangeTradeViewModelBase with Store { Timer? timer; @action - Future confirmSending() async { - if (!isSendable) { - return; - } + Future confirmSending() async { + if (!isSendable) return; sendViewModel.clearOutputs(); final output = sendViewModel.outputs.first; @@ -118,13 +112,10 @@ abstract class ExchangeTradeViewModelBase with Store { try { final updatedTrade = await _provider!.findTradeById(id: trade.id); - if (updatedTrade.createdAt == null && trade.createdAt != null) { + if (updatedTrade.createdAt == null && trade.createdAt != null) updatedTrade.createdAt = trade.createdAt; - } - if (updatedTrade.amount.isEmpty) { - updatedTrade.amount = trade.amount; - } + if (updatedTrade.amount.isEmpty) updatedTrade.amount = trade.amount; trade = updatedTrade; diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index f7db98245..8692b193b 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -3,48 +3,39 @@ import 'dart:collection'; import 'dart:convert'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; +import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/core/wallet_change_listener_view_model.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/wallet_contact.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; -import 'package:cake_wallet/exchange/exolix/exolix_exchange_provider.dart'; -import 'package:cake_wallet/exchange/exolix/exolix_request.dart'; -import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'; -import 'package:cake_wallet/exchange/sideshift/sideshift_request.dart'; -import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart'; -import 'package:cake_wallet/exchange/simpleswap/simpleswap_request.dart'; -import 'package:cake_wallet/exchange/trocador/trocador_exchange_provider.dart'; -import 'package:cake_wallet/exchange/trocador/trocador_request.dart'; -import 'package:cake_wallet/utils/feature_flag.dart'; -import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart'; -import 'package:cw_core/transaction_priority.dart'; -import 'package:cake_wallet/store/app_store.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/sync_status.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:cake_wallet/bitcoin/bitcoin.dart'; -import 'package:cake_wallet/monero/monero.dart'; -import 'package:cake_wallet/exchange/exchange_provider.dart'; +import 'package:cake_wallet/exchange/exchange_template.dart'; +import 'package:cake_wallet/exchange/exchange_trade_state.dart'; import 'package:cake_wallet/exchange/limits.dart'; -import 'package:cake_wallet/exchange/trade.dart'; import 'package:cake_wallet/exchange/limits_state.dart'; +import 'package:cake_wallet/exchange/provider/changenow_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/exolix_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/sideshift_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/simpleswap_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; +import 'package:cake_wallet/exchange/trade.dart'; +import 'package:cake_wallet/exchange/trade_request.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/monero/monero.dart'; +import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/dashboard/trades_store.dart'; import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/store/templates/exchange_template_store.dart'; +import 'package:cake_wallet/utils/feature_flag.dart'; +import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/sync_status.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:hive/hive.dart'; import 'package:intl/intl.dart'; import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:hive/hive.dart'; -import 'package:cake_wallet/exchange/exchange_trade_state.dart'; -import 'package:cake_wallet/exchange/changenow/changenow_exchange_provider.dart'; -import 'package:cake_wallet/exchange/changenow/changenow_request.dart'; -import 'package:cake_wallet/exchange/trade_request.dart'; -import 'package:cake_wallet/exchange/xmrto/xmrto_exchange_provider.dart'; -import 'package:cake_wallet/exchange/xmrto/xmrto_trade_request.dart'; -import 'package:cake_wallet/exchange/morphtoken/morphtoken_exchange_provider.dart'; -import 'package:cake_wallet/exchange/morphtoken/morphtoken_request.dart'; -import 'package:cake_wallet/store/templates/exchange_template_store.dart'; -import 'package:cake_wallet/exchange/exchange_template.dart'; import 'package:shared_preferences/shared_preferences.dart'; part 'exchange_view_model.g.dart'; @@ -144,6 +135,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with _calculateBestRate(); }); } + bool _useTorOnly; final Box trades; final ExchangeTemplateStore _exchangeTemplateStore; @@ -384,13 +376,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with double minLimit = limits.min ?? 0; double? maxLimit = limits.max; - if (_enteredAmount < minLimit) { - return false; - } + if (_enteredAmount < minLimit) return false; - if (maxLimit != null && _enteredAmount > maxLimit) { - return false; - } + if (maxLimit != null && _enteredAmount > maxLimit) return false; return true; } @@ -422,16 +410,12 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with } } } - if (_sortedAvailableProviders.isNotEmpty) { - _bestRate = _sortedAvailableProviders.keys.first; - } + if (_sortedAvailableProviders.isNotEmpty) _bestRate = _sortedAvailableProviders.keys.first; } @action Future loadLimits() async { - if (selectedProviders.isEmpty) { - return; - } + if (selectedProviders.isEmpty) return; limitsState = LimitsIsLoading(); @@ -444,20 +428,16 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with try { for (var provider in selectedProviders) { /// if this provider is not valid for the current pair, skip it - if (!providersForCurrentPair().contains(provider)) { - continue; - } + if (!providersForCurrentPair().contains(provider)) continue; try { final tempLimits = await provider.fetchLimits(from: from, to: to, isFixedRateMode: isFixedRateMode); - if (lowestMin != null && (tempLimits.min ?? -1) < lowestMin) { - lowestMin = tempLimits.min; - } - if (highestMax != null && (tempLimits.max ?? double.maxFinite) > highestMax) { + if (lowestMin != null && (tempLimits.min ?? -1) < lowestMin) lowestMin = tempLimits.min; + + if (highestMax != null && (tempLimits.max ?? double.maxFinite) > highestMax) highestMax = tempLimits.max; - } } catch (e) { continue; } @@ -482,111 +462,34 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with @action Future createTrade() async { - TradeRequest? request; - String amount = ''; - try { for (var provider in _sortedAvailableProviders.values) { - if (!(await provider.checkIsAvailable())) { - continue; - } + if (!(await provider.checkIsAvailable())) continue; - if (provider is SideShiftExchangeProvider) { - request = SideShiftRequest( - depositMethod: depositCurrency, - settleMethod: receiveCurrency, - depositAmount: isFixedRateMode - ? receiveAmount.replaceAll(',', '.') - : depositAmount.replaceAll(',', '.'), - settleAddress: receiveAddress, + final request = TradeRequest( + fromCurrency: depositCurrency, + toCurrency: receiveCurrency, + fromAmount: depositAmount.replaceAll(',', '.'), + toAmount: receiveAmount.replaceAll(',', '.'), refundAddress: depositAddress, - ); - amount = isFixedRateMode ? receiveAmount : depositAmount; - } - - if (provider is SimpleSwapExchangeProvider) { - request = SimpleSwapRequest( - from: depositCurrency, - to: receiveCurrency, - amount: depositAmount.replaceAll(',', '.'), - address: receiveAddress, - refundAddress: depositAddress, - ); - amount = isFixedRateMode ? receiveAmount : depositAmount; - } - - if (provider is XMRTOExchangeProvider) { - request = XMRTOTradeRequest( - from: depositCurrency, - to: receiveCurrency, - amount: depositAmount.replaceAll(',', '.'), - receiveAmount: receiveAmount.replaceAll(',', '.'), - address: receiveAddress, - refundAddress: depositAddress, - isBTCRequest: isReceiveAmountEntered); - amount = isFixedRateMode ? receiveAmount : depositAmount; - } - - if (provider is ChangeNowExchangeProvider) { - request = ChangeNowRequest( - from: depositCurrency, - to: receiveCurrency, - fromAmount: depositAmount.replaceAll(',', '.'), - toAmount: receiveAmount.replaceAll(',', '.'), - refundAddress: depositAddress, - address: receiveAddress, - isReverse: isFixedRateMode); - amount = isFixedRateMode ? receiveAmount : depositAmount; - } - - if (provider is MorphTokenExchangeProvider) { - request = MorphTokenRequest( - from: depositCurrency, - to: receiveCurrency, - amount: depositAmount.replaceAll(',', '.'), - refundAddress: depositAddress, - address: receiveAddress); - amount = isFixedRateMode ? receiveAmount : depositAmount; - } - - if (provider is TrocadorExchangeProvider) { - request = TrocadorRequest( - from: depositCurrency, - to: receiveCurrency, - fromAmount: depositAmount.replaceAll(',', '.'), - toAmount: receiveAmount.replaceAll(',', '.'), - refundAddress: depositAddress, - address: receiveAddress, - isReverse: isFixedRateMode); - amount = isFixedRateMode ? receiveAmount : depositAmount; - } - - if (provider is ExolixExchangeProvider) { - request = ExolixRequest( - from: depositCurrency, - to: receiveCurrency, - fromAmount: depositAmount.replaceAll(',', '.'), - toAmount: receiveAmount.replaceAll(',', '.'), - refundAddress: depositAddress, - address: receiveAddress); - amount = isFixedRateMode ? receiveAmount : depositAmount; - } + toAddress: receiveAddress, + isFixedRate: isFixedRateMode); + var amount = isFixedRateMode ? receiveAmount : depositAmount; amount = amount.replaceAll(',', '.'); if (limitsState is LimitsLoadedSuccessfully) { - if (double.tryParse(amount) == null) { + if (double.tryParse(amount) == null) continue; + + if (limits.max != null && double.parse(amount) < limits.min!) continue; - } - if (limits.max != null && double.parse(amount) < limits.min!) { + else if (limits.max != null && double.parse(amount) > limits.max!) continue; - } else if (limits.max != null && double.parse(amount) > limits.max!) { - continue; - } else { + else { try { tradeState = TradeIsCreating(); final trade = - await provider.createTrade(request: request!, isFixedRateMode: isFixedRateMode); + await provider.createTrade(request: request, isFixedRateMode: isFixedRateMode); trade.walletId = wallet.id; tradesStore.setTrade(trade); await trades.add(trade); @@ -636,9 +539,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with final priority = _settingsStore.priority[wallet.type]!; final fee = wallet.calculateEstimatedFee(priority, null); - if (availableBalance < fee || availableBalance == 0) { - return; - } + if (availableBalance < fee || availableBalance == 0) return; final amount = availableBalance - fee; changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount)); @@ -669,19 +570,15 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with void removeTemplate({required ExchangeTemplate template}) => _exchangeTemplateStore.remove(template: template); - List providersForCurrentPair() { - return _providersForPair(from: depositCurrency, to: receiveCurrency); - } + List providersForCurrentPair() => + _providersForPair(from: depositCurrency, to: receiveCurrency); List _providersForPair( - {required CryptoCurrency from, required CryptoCurrency to}) { - final providers = providerList - .where((provider) => - provider.pairList.where((pair) => pair.from == from && pair.to == to).isNotEmpty) - .toList(); - - return providers; - } + {required CryptoCurrency from, required CryptoCurrency to}) => + providerList + .where((provider) => + provider.pairList.where((pair) => pair.from == from && pair.to == to).isNotEmpty) + .toList(); void _onPairChange() { depositAmount = ''; @@ -744,9 +641,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with @action void addExchangeProvider(ExchangeProvider provider) { selectedProviders.add(provider); - if (providersForCurrentPair().contains(provider)) { - _tradeAvailableProviders.add(provider); - } + if (providersForCurrentPair().contains(provider)) _tradeAvailableProviders.add(provider); } @action @@ -817,14 +712,13 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with } void _setProviders() { - if (_settingsStore.exchangeStatus == ExchangeApiMode.torOnly) { + if (_settingsStore.exchangeStatus == ExchangeApiMode.torOnly) providerList = _allProviders.where((provider) => provider.supportsOnionAddress).toList(); - } else { + else providerList = _allProviders; - } } - int get depositMaxDigits => depositCurrency == CryptoCurrency.btc ? 8 : 12; + int get depositMaxDigits => depositCurrency.decimals; - int get receiveMaxDigits => receiveCurrency == CryptoCurrency.btc ? 8 : 12; + int get receiveMaxDigits => receiveCurrency.decimals; } diff --git a/lib/view_model/trade_details_view_model.dart b/lib/view_model/trade_details_view_model.dart index 393629237..45502fd74 100644 --- a/lib/view_model/trade_details_view_model.dart +++ b/lib/view_model/trade_details_view_model.dart @@ -1,28 +1,28 @@ import 'dart:async'; -import 'package:cake_wallet/exchange/changenow/changenow_exchange_provider.dart'; -import 'package:cake_wallet/exchange/exchange_provider.dart'; + import 'package:cake_wallet/exchange/exchange_provider_description.dart'; -import 'package:cake_wallet/exchange/exolix/exolix_exchange_provider.dart'; -import 'package:cake_wallet/exchange/morphtoken/morphtoken_exchange_provider.dart'; -import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart'; -import 'package:cake_wallet/exchange/simpleswap/simpleswap_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/changenow_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/exolix_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/sideshift_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/simpleswap_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; import 'package:cake_wallet/exchange/trade.dart'; -import 'package:cake_wallet/exchange/trocador/trocador_exchange_provider.dart'; -import 'package:cake_wallet/exchange/xmrto/xmrto_exchange_provider.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/trade_details/track_trade_list_item.dart'; +import 'package:cake_wallet/src/screens/trade_details/trade_details_list_card.dart'; +import 'package:cake_wallet/src/screens/trade_details/trade_details_status_item.dart'; +import 'package:cake_wallet/src/screens/trade_details/trade_provider_unsupported_item.dart'; +import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/utils/date_formatter.dart'; import 'package:cake_wallet/utils/show_bar.dart'; +import 'package:collection/collection.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; -import 'package:cake_wallet/src/screens/trade_details/track_trade_list_item.dart'; -import 'package:cake_wallet/src/screens/trade_details/trade_details_list_card.dart'; -import 'package:cake_wallet/src/screens/trade_details/trade_details_status_item.dart'; import 'package:url_launcher/url_launcher.dart'; -import 'package:collection/collection.dart'; part 'trade_details_view_model.g.dart'; @@ -37,15 +37,9 @@ abstract class TradeDetailsViewModelBase with Store { trade = trades.values.firstWhereOrNull((element) => element.id == tradeForDetails.id) ?? tradeForDetails { switch (trade.provider) { - case ExchangeProviderDescription.xmrto: - _provider = XMRTOExchangeProvider(); - break; case ExchangeProviderDescription.changeNow: _provider = ChangeNowExchangeProvider(settingsStore: settingsStore); break; - case ExchangeProviderDescription.morphToken: - _provider = MorphTokenExchangeProvider(trades: trades); - break; case ExchangeProviderDescription.sideShift: _provider = SideShiftExchangeProvider(); break; @@ -62,9 +56,10 @@ abstract class TradeDetailsViewModelBase with Store { _updateItems(); - _updateTrade(); - - timer = Timer.periodic(Duration(seconds: 20), (_) async => _updateTrade()); + if (_provider != null) { + _updateTrade(); + timer = Timer.periodic(Duration(seconds: 20), (_) async => _updateTrade()); + } } final Box trades; @@ -86,9 +81,9 @@ abstract class TradeDetailsViewModelBase with Store { try { final updatedTrade = await _provider!.findTradeById(id: trade.id); - if (updatedTrade.createdAt == null && trade.createdAt != null) { + if (updatedTrade.createdAt == null && trade.createdAt != null) updatedTrade.createdAt = trade.createdAt; - } + Trade? foundElement = trades.values.firstWhereOrNull((element) => element.id == trade.id); if (foundElement != null) { final editedTrade = trades.get(foundElement.key); @@ -109,6 +104,10 @@ abstract class TradeDetailsViewModelBase with Store { items.clear(); + if (_provider == null) + items.add(TradeProviderUnsupportedItem( + error: S.current.exchange_provider_unsupported(trade.provider.title))); + items.add( DetailsListStatusItem(title: S.current.trade_details_state, value: trade.state.toString())); @@ -165,7 +164,7 @@ abstract class TradeDetailsViewModelBase with Store { if (trade.provider == ExchangeProviderDescription.exolix) { final buildURL = 'https://exolix.com/transaction/${trade.id.toString()}'; items.add( - TrackTradeListItem(title: 'Track', value: buildURL, onTap: () => _launchUrl(buildURL))); + TrackTradeListItem(title: 'Track', value: buildURL, onTap: () => _launchUrl(buildURL))); } } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 4f6778456..f38709bd7 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -339,7 +339,6 @@ "template": "قالب", "confirm_delete_template": "سيؤدي هذا الإجراء إلى حذف هذا القالب. هل ترغب في الاستمرار؟", "confirm_delete_wallet": "سيؤدي هذا الإجراء إلى حذف هذه المحفظة. هل ترغب في الاستمرار؟", - "picker_description": "لاختيار ChangeNOW أو MorphToken ، يرجى تغيير زوج التداول الخاص بك أولاً", "change_wallet_alert_title": "تغيير المحفظة الحالية", "change_wallet_alert_content": "هل تريد تغيير المحفظة الحالية إلى ${wallet_name}؟", "creating_new_wallet": "يتم إنشاء محفظة جديدة", @@ -722,5 +721,6 @@ "enterWalletConnectURI": "WalletConnect ـﻟ URI ﻞﺧﺩﺃ", "seed_key": "مفتاح البذور", "enter_seed_phrase": "أدخل عبارة البذور الخاصة بك", - "add_contact": "ﻝﺎﺼﺗﺍ ﺔﻬﺟ ﺔﻓﺎﺿﺇ" + "add_contact": "ﻝﺎﺼﺗﺍ ﺔﻬﺟ ﺔﻓﺎﺿﺇ", + "exchange_provider_unsupported": "${providerName} لم يعد مدعومًا!" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 419b800ba..f39fd9dcb 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -339,7 +339,6 @@ "template": "Шаблон", "confirm_delete_template": "Този шаблон ще бъде изтрит. Искате ли да продължите?", "confirm_delete_wallet": "Този портфейл ще бъде изтрит. Искате ли да продължите?", - "picker_description": "За да изберете ChangeNOW или MorphToken, моля, първо променете своя trading pair", "change_wallet_alert_title": "Смяна на сегашния портфейл", "change_wallet_alert_content": "Искате ли да смените сегашния портфейл на ${wallet_name}?", "creating_new_wallet": "Създаване на нов портфейл", @@ -718,5 +717,6 @@ "enterWalletConnectURI": "Въведете URI на WalletConnect", "seed_key": "Ключ за семена", "enter_seed_phrase": "Въведете вашата фраза за семена", - "add_contact": "Добави контакт" + "add_contact": "Добави контакт", + "exchange_provider_unsupported": "${providerName} вече не се поддържа!" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 9b0d94cda..5571db694 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -339,7 +339,6 @@ "template": "Šablona", "confirm_delete_template": "Tato akce smaže tuto šablonu. Přejete si pokračovat?", "confirm_delete_wallet": "Tato akce smaže tuto peněženku. Přejete si pokračovat?", - "picker_description": "Pro volbu ChangeNOW, nebo MorphToken si prosím vyberte nejprve pár pro obchodování", "change_wallet_alert_title": "Přepnout peněženku", "change_wallet_alert_content": "Opravdu chcete změnit aktivní peněženku na ${wallet_name}?", "creating_new_wallet": "Vytvářím novou peněženku", @@ -718,5 +717,6 @@ "enterWalletConnectURI": "Zadejte identifikátor URI WalletConnect", "seed_key": "Klíč semen", "enter_seed_phrase": "Zadejte svou frázi semen", - "add_contact": "Přidat kontakt" + "add_contact": "Přidat kontakt", + "exchange_provider_unsupported": "${providerName} již není podporováno!" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index bb0fc0541..0248e8906 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -339,7 +339,6 @@ "template": "Vorlage", "confirm_delete_template": "Diese Aktion löscht diese Vorlage. Möchten Sie fortfahren?", "confirm_delete_wallet": "Diese Aktion löscht diese Wallet. Möchten Sie fortfahren?", - "picker_description": "Um ChangeNOW oder MorphToken zu wählen, ändern Sie bitte zuerst Ihr Handelspaar", "change_wallet_alert_title": "Aktuelle Wallet ändern", "change_wallet_alert_content": "Möchten Sie die aktuelle Wallet zu ${wallet_name} ändern?", "creating_new_wallet": "Neue Wallet erstellen", @@ -724,7 +723,8 @@ "awaitDAppProcessing": "Bitte warten Sie, bis die dApp die Verarbeitung abgeschlossen hat.", "copyWalletConnectLink": "Kopieren Sie den WalletConnect-Link von dApp und fügen Sie ihn hier ein", "enterWalletConnectURI": "Geben Sie den WalletConnect-URI ein", - "seed_key": "Samenschlüssel", - "enter_seed_phrase": "Geben Sie Ihre Samenphrase ein", - "add_contact": "Kontakt hinzufügen" + "seed_key": "Seed-Schlüssel", + "enter_seed_phrase": "Geben Sie Ihre Seed-Phrase ein", + "add_contact": "Kontakt hinzufügen", + "exchange_provider_unsupported": "${providerName} wird nicht mehr unterstützt!" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index bd821fa2b..2c7979be6 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -339,7 +339,6 @@ "template": "Template", "confirm_delete_template": "This action will delete this template. Do you wish to continue?", "confirm_delete_wallet": "This action will delete this wallet. Do you wish to continue?", - "picker_description": "To choose ChangeNOW or MorphToken, please change your trading pair first", "change_wallet_alert_title": "Change current wallet", "change_wallet_alert_content": "Do you want to change current wallet to ${wallet_name}?", "creating_new_wallet": "Creating new wallet", @@ -727,5 +726,6 @@ "enterWalletConnectURI": "Enter WalletConnect URI", "seed_key": "Seed key", "enter_seed_phrase": "Enter your seed phrase", - "add_contact": "Add contact" + "add_contact": "Add contact", + "exchange_provider_unsupported": "${providerName} is no longer supported!" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 3810331eb..8f226ba8a 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -339,7 +339,6 @@ "template": "Plantilla", "confirm_delete_template": "Esta acción eliminará esta plantilla. ¿Desea continuar?", "confirm_delete_wallet": "Esta acción eliminará esta billetera. ¿Desea continuar?", - "picker_description": "Para elegir ChangeNOW o MorphToken, primero cambie su par comercial", "change_wallet_alert_title": "Cambiar billetera actual", "change_wallet_alert_content": "¿Quieres cambiar la billetera actual a ${wallet_name}?", "creating_new_wallet": "Creando nueva billetera", @@ -726,5 +725,6 @@ "enterWalletConnectURI": "Ingrese el URI de WalletConnect", "seed_key": "Llave de semilla", "enter_seed_phrase": "Ingrese su frase de semillas", - "add_contact": "Agregar contacto" + "add_contact": "Agregar contacto", + "exchange_provider_unsupported": "¡${providerName} ya no es compatible!" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index f7b30158c..e29a62643 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -339,7 +339,6 @@ "template": "Modèle", "confirm_delete_template": "Cette action va supprimer ce modèle. Souhaitez-vous continuer ?", "confirm_delete_wallet": "Cette action va supprimer ce portefeuille (wallet). Souhaitez-vous contnuer ?", - "picker_description": "Pour choisir ChangeNOW ou MorphToken, merci de modifier d'abord la paire de votre échange", "change_wallet_alert_title": "Changer le portefeuille (wallet) actuel", "change_wallet_alert_content": "Souhaitez-vous changer le portefeuille (wallet) actuel vers ${wallet_name} ?", "creating_new_wallet": "Création d'un nouveau portefeuille (wallet)", @@ -726,5 +725,6 @@ "enterWalletConnectURI": "Saisissez l'URI de WalletConnect.", "seed_key": "Clé de graines", "enter_seed_phrase": "Entrez votre phrase de semence", - "add_contact": "Ajouter le contact" + "add_contact": "Ajouter le contact", + "exchange_provider_unsupported": "${providerName} n'est plus pris en charge!" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index eeeaa0e2c..62083df30 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -340,7 +340,6 @@ "template": "Samfura", "confirm_delete_template": "Wannan aikin zai share wannan samfuri. Kuna so ku ci gaba?", "confirm_delete_wallet": "Wannan aikin zai share wannan walat. Kuna so ku ci gaba?", - "picker_description": "Don zaɓar ChangeNOW ko MorphToken, da farko canja kasuwancin pair din ku", "change_wallet_alert_title": "Canja walat yanzu", "change_wallet_alert_content": "Kana so ka canja walat yanzu zuwa ${wallet_name}?", "creating_new_wallet": "Haliccin walat sabuwa", @@ -704,5 +703,6 @@ "enterWalletConnectURI": "Shigar da WalletConnect URI", "seed_key": "Maɓallin iri", "enter_seed_phrase": "Shigar da Sert Sentarku", - "add_contact": "Ƙara lamba" + "add_contact": "Ƙara lamba", + "exchange_provider_unsupported": "${providerName}" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 1d87df54a..367f704b0 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -339,7 +339,6 @@ "template": "खाका", "confirm_delete_template": "यह क्रिया इस टेम्पलेट को हटा देगी। क्या आप जारी रखना चाहते हैं?", "confirm_delete_wallet": "यह क्रिया इस वॉलेट को हटा देगी। क्या आप जारी रखना चाहते हैं?", - "picker_description": "ChangeNOW या MorphToken चुनने के लिए, कृपया अपनी ट्रेडिंग जोड़ी को पहले बदलें", "change_wallet_alert_title": "वर्तमान बटुआ बदलें", "change_wallet_alert_content": "क्या आप करंट वॉलेट को बदलना चाहते हैं ${wallet_name}?", "creating_new_wallet": "नया बटुआ बनाना", @@ -726,5 +725,6 @@ "enterWalletConnectURI": "वॉलेटकनेक्ट यूआरआई दर्ज करें", "seed_key": "बीज कुंजी", "enter_seed_phrase": "अपना बीज वाक्यांश दर्ज करें", - "add_contact": "संपर्क जोड़ें" + "add_contact": "संपर्क जोड़ें", + "exchange_provider_unsupported": "${providerName} अब समर्थित नहीं है!" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index cadf79772..5db06889e 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -339,7 +339,6 @@ "template": "Predložak", "confirm_delete_template": "Ovom ćete radnjom izbrisati ovaj predložak. Želite li nastaviti?", "confirm_delete_wallet": "Ovom ćete radnjom izbrisati ovaj novčanik. Želite li nastaviti?", - "picker_description": "Da biste odabrali ChangeNOW ili MorphToken, molimo da prvo odabete dvije valute za trgovanje", "change_wallet_alert_title": "Izmijeni trenutni novčanik", "change_wallet_alert_content": "Želite li promijeniti trenutni novčanik u ${wallet_name}?", "creating_new_wallet": "Stvaranje novog novčanika", @@ -724,5 +723,6 @@ "enterWalletConnectURI": "Unesite WalletConnect URI", "seed_key": "Sjemenski ključ", "enter_seed_phrase": "Unesite svoju sjemensku frazu", - "add_contact": "Dodaj kontakt" + "add_contact": "Dodaj kontakt", + "exchange_provider_unsupported": "${providerName} više nije podržan!" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 903199b42..bae6e1e64 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -340,7 +340,6 @@ "template": "Template", "confirm_delete_template": "Tindakan ini akan menghapus template ini. Apakah Anda ingin melanjutkan?", "confirm_delete_wallet": "Tindakan ini akan menghapus dompet ini. Apakah Anda ingin melanjutkan?", - "picker_description": "Untuk memilih ChangeNOW atau MorphToken, silakan ubah pasangan perdagangan Anda terlebih dahulu", "change_wallet_alert_title": "Ganti dompet saat ini", "change_wallet_alert_content": "Apakah Anda ingin mengganti dompet saat ini ke ${wallet_name}?", "creating_new_wallet": "Membuat dompet baru", @@ -714,5 +713,6 @@ "enterWalletConnectURI": "Masukkan URI WalletConnect", "seed_key": "Kunci benih", "enter_seed_phrase": "Masukkan frasa benih Anda", - "add_contact": "Tambah kontak" + "add_contact": "Tambah kontak", + "exchange_provider_unsupported": "${providerName} tidak lagi didukung!" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index e12eba3cb..9a9e19493 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -339,7 +339,6 @@ "template": "Modello", "confirm_delete_template": "Questa azione cancellerà questo modello. Desideri continuare?", "confirm_delete_wallet": "Questa azione cancellerà questo portafoglio. Desideri continuare?", - "picker_description": "Per scegliere ChangeNOW o MorphToken, gentilmente cambia prima la tua coppia di valute", "change_wallet_alert_title": "Cambia portafoglio attuale", "change_wallet_alert_content": "Sei sicuro di voler cambiare il portafoglio attuale con ${wallet_name}?", "creating_new_wallet": "Creazione nuovo portafoglio", @@ -726,5 +725,6 @@ "enterWalletConnectURI": "Inserisci l'URI di WalletConnect", "seed_key": "Chiave di semi", "enter_seed_phrase": "Inserisci la tua frase di semi", - "add_contact": "Aggiungi contatto" + "add_contact": "Aggiungi contatto", + "exchange_provider_unsupported": "${providerName} non è più supportato!" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 6df16d142..f9c1c47df 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -339,7 +339,6 @@ "template": "テンプレート", "confirm_delete_template": "この操作により、このテンプレートが削除されます。 続行しますか?", "confirm_delete_wallet": "このアクションにより、このウォレットが削除されます。 続行しますか?", - "picker_description": "ChangeNOWまたはMorphTokenを選択するには、最初にトレーディングペアを変更してください", "change_wallet_alert_title": "現在のウォレットを変更する", "change_wallet_alert_content": "現在のウォレットをに変更しますか ${wallet_name}?", "creating_new_wallet": "新しいウォレットの作成", @@ -726,5 +725,6 @@ "enterWalletConnectURI": "WalletConnect URI を入力してください", "seed_key": "シードキー", "enter_seed_phrase": "シードフレーズを入力してください", - "add_contact": "連絡先を追加" + "add_contact": "連絡先を追加", + "exchange_provider_unsupported": "${providerName}はサポートされなくなりました!" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 6386abfde..0d48a3dcb 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -339,7 +339,6 @@ "template": "주형", "confirm_delete_template": "이 작업은이 템플릿을 삭제합니다. 계속 하시겠습니까?", "confirm_delete_wallet": "이 작업은이 지갑을 삭제합니다. 계속 하시겠습니까?", - "picker_description": "ChangeNOW 또는 MorphToken을 선택하려면 먼저 거래 쌍을 변경하십시오.", "change_wallet_alert_title": "현재 지갑 변경", "change_wallet_alert_content": "현재 지갑을 다음으로 변경 하시겠습니까 ${wallet_name}?", "creating_new_wallet": "새 지갑 생성", @@ -724,5 +723,6 @@ "enterWalletConnectURI": "WalletConnect URI를 입력하세요.", "seed_key": "시드 키", "enter_seed_phrase": "시드 문구를 입력하십시오", - "add_contact": "주소록에 추가" + "add_contact": "주소록에 추가", + "exchange_provider_unsupported": "${providerName}은 더 이상 지원되지 않습니다!" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index d2f584b22..9c2a9aa89 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -339,7 +339,6 @@ "template": "ပုံစံခွက်", "confirm_delete_template": "ဤလုပ်ဆောင်ချက်သည် ဤပုံစံပြားကို ဖျက်လိုက်ပါမည်။ ဆက်လုပ်လိုပါသလား။", "confirm_delete_wallet": "ဤလုပ်ဆောင်ချက်သည် ဤပိုက်ဆံအိတ်ကို ဖျက်လိုက်ပါမည်။ ဆက်လုပ်လိုပါသလား။", - "picker_description": "ChangeNOW သို့မဟုတ် MorphToken ကိုရွေးချယ်ရန်၊ ကျေးဇူးပြု၍ သင်၏ကုန်သွယ်မှုအတွဲကို ဦးစွာပြောင်းလဲပါ။", "change_wallet_alert_title": "လက်ရှိပိုက်ဆံအိတ်ကို ပြောင်းပါ။", "change_wallet_alert_content": "လက်ရှိပိုက်ဆံအိတ်ကို ${wallet_name} သို့ ပြောင်းလိုပါသလား။", "creating_new_wallet": "ပိုက်ဆံအိတ်အသစ်ဖန်တီးခြင်း။", @@ -724,5 +723,6 @@ "enterWalletConnectURI": "WalletConnect URI ကိုရိုက်ထည့်ပါ။", "seed_key": "မျိုးစေ့သော့", "enter_seed_phrase": "သင့်ရဲ့မျိုးစေ့စကားစုကိုရိုက်ထည့်ပါ", - "add_contact": "အဆက်အသွယ်ထည့်ပါ။" + "add_contact": "အဆက်အသွယ်ထည့်ပါ။", + "exchange_provider_unsupported": "${providerName} မရှိတော့ပါ!" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index c05ec8fba..e0ab4568d 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -339,7 +339,6 @@ "template": "Sjabloon", "confirm_delete_template": "Met deze actie wordt deze sjabloon verwijderd. Wilt u doorgaan?", "confirm_delete_wallet": "Met deze actie wordt deze portemonnee verwijderd. Wilt u doorgaan?", - "picker_description": "Om ChangeNOW of MorphToken te kiezen, moet u eerst uw handelspaar wijzigen", "change_wallet_alert_title": "Wijzig huidige portemonnee", "change_wallet_alert_content": "Wilt u de huidige portemonnee wijzigen in ${wallet_name}?", "creating_new_wallet": "Nieuwe portemonnee aanmaken", @@ -726,5 +725,6 @@ "enterWalletConnectURI": "Voer WalletConnect-URI in", "seed_key": "Zaadsleutel", "enter_seed_phrase": "Voer uw zaadzin in", - "add_contact": "Contactpersoon toevoegen" + "add_contact": "Contactpersoon toevoegen", + "exchange_provider_unsupported": "${providerName} wordt niet langer ondersteund!" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 2137ce464..683981eb8 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -339,7 +339,6 @@ "template": "Szablon", "confirm_delete_template": "Ta czynność usunie ten szablon. Czy chcesz kontynuować?", "confirm_delete_wallet": "Ta czynność usunie ten portfel. Czy chcesz kontynuować?", - "picker_description": "Aby wybrać ChangeNOW lub MorphToken, najpierw zmień swoją parę handlową", "change_wallet_alert_title": "Zmień obecny portfel", "change_wallet_alert_content": "Czy chcesz zmienić obecny portfel na ${wallet_name}?", "creating_new_wallet": "Tworzenie nowego portfela", @@ -726,5 +725,6 @@ "enterWalletConnectURI": "Wprowadź identyfikator URI WalletConnect", "seed_key": "Klucz nasion", "enter_seed_phrase": "Wprowadź swoją frazę nasienną", - "add_contact": "Dodaj kontakt" + "add_contact": "Dodaj kontakt", + "exchange_provider_unsupported": "${providerName} nie jest już obsługiwany!" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 96bb7f355..6c67a1fce 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -339,7 +339,6 @@ "template": "Modelo", "confirm_delete_template": "Esta ação excluirá este modelo. Você deseja continuar?", "confirm_delete_wallet": "Esta ação excluirá esta carteira. Você deseja continuar?", - "picker_description": "Para escolher ChangeNOW ou MorphToken, altere primeiro o seu par de negociação", "change_wallet_alert_title": "Alterar carteira atual", "change_wallet_alert_content": "Quer mudar a carteira atual para ${wallet_name}?", "creating_new_wallet": "Criando nova carteira", @@ -725,5 +724,6 @@ "enterWalletConnectURI": "Insira o URI do WalletConnect", "seed_key": "Chave de semente", "enter_seed_phrase": "Digite sua frase de semente", - "add_contact": "Adicionar contato" + "add_contact": "Adicionar contato", + "exchange_provider_unsupported": "${providerName} não é mais suportado!" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 503a7898b..a8be5852d 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -339,7 +339,6 @@ "template": "Шаблон", "confirm_delete_template": "Это действие удалит шаблон. Вы хотите продолжить?", "confirm_delete_wallet": "Это действие удалит кошелек. Вы хотите продолжить?", - "picker_description": "Чтобы выбрать ChangeNOW или MorphToken, сначала смените пару для обмена", "change_wallet_alert_title": "Изменить текущий кошелек", "change_wallet_alert_content": "Вы хотите изменить текущий кошелек на ${wallet_name}?", "creating_new_wallet": "Создание нового кошелька", @@ -726,5 +725,6 @@ "enterWalletConnectURI": "Введите URI WalletConnect", "seed_key": "Ключ семян", "enter_seed_phrase": "Введите свою семенную фразу", - "add_contact": "Добавить контакт" + "add_contact": "Добавить контакт", + "exchange_provider_unsupported": "${providerName} больше не поддерживается!" } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 6fc6a40ff..f54e7e340 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -339,7 +339,6 @@ "template": "แบบฟอร์ม", "confirm_delete_template": "การดำเนินการนี้จะลบแบบฟอร์มนี้ คุณต้องการดำเนินการต่อหรือไม่?", "confirm_delete_wallet": "การดำเนินการนี้จะลบกระเป๋านี้ คุณต้องการดำเนินการต่อหรือไม่?", - "picker_description": "ในการเลือก ChangeNOW หรือ MorphToken โปรดเปลี่ยนคู่แลกเปลี่ยนก่อน", "change_wallet_alert_title": "เปลี่ยนกระเป๋าปัจจุบัน", "change_wallet_alert_content": "คุณต้องการเปลี่ยนกระเป๋าปัจจุบันเป็น ${wallet_name} หรือไม่?", "creating_new_wallet": "กำลังสร้างกระเป๋าใหม่", @@ -724,5 +723,6 @@ "enterWalletConnectURI": "เข้าสู่ WalletConnect URI", "seed_key": "คีย์เมล็ดพันธุ์", "enter_seed_phrase": "ป้อนวลีเมล็ดพันธุ์ของคุณ", - "add_contact": "เพิ่มผู้ติดต่อ" + "add_contact": "เพิ่มผู้ติดต่อ", + "exchange_provider_unsupported": "${providerName} ไม่ได้รับการสนับสนุนอีกต่อไป!" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 9087d2f7c..0cd38e036 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -339,7 +339,6 @@ "template": "Template", "confirm_delete_template": "Ang pagkilos na ito ay tatanggalin ang template na ito. Nais mo bang magpatuloy?", "confirm_delete_wallet": "Ang pagkilos na ito ay tatanggalin ang pitaka na ito. Nais mo bang magpatuloy?", - "picker_description": "Upang pumili ng Changenow o MorphToken, mangyaring baguhin muna ang iyong pares ng kalakalan", "change_wallet_alert_title": "Baguhin ang kasalukuyang pitaka", "change_wallet_alert_content": "Nais mo bang baguhin ang kasalukuyang pitaka sa ${wallet_name}?", "creating_new_wallet": "Lumilikha ng bagong pitaka", @@ -721,5 +720,6 @@ "enterWalletConnectURI": "Ilagay ang WalletConnect URI", "seed_key": "Seed Key", "enter_seed_phrase": "Ipasok ang iyong pariralang binhi", - "add_contact": "Magdagdag ng contact" + "add_contact": "Magdagdag ng contact", + "exchange_provider_unsupported": "Ang ${providerName} ay hindi na suportado!" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 353ef0184..fb45bc93f 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -339,7 +339,6 @@ "template": "Şablon", "confirm_delete_template": "Bu eylem, bu şablonu silecek. Devam etmek istiyor musun?", "confirm_delete_wallet": "Bu eylem, bu cüzdanı silecek. Devam etmek istiyor musun?", - "picker_description": "ChangeNOW veya MorphToken'ı seçmek için lütfen önce işlem paritenizi değiştirin", "change_wallet_alert_title": "Şimdiki cüzdanı değiştir", "change_wallet_alert_content": "Şimdiki cüzdanı ${wallet_name} cüzdanı ile değiştirmek istediğinden emin misin?", "creating_new_wallet": "Cüzdan oluşturuluyor", @@ -724,5 +723,6 @@ "enterWalletConnectURI": "WalletConnect URI'sini girin", "seed_key": "Tohum", "enter_seed_phrase": "Tohum ifadenizi girin", - "add_contact": "Kişi ekle" + "add_contact": "Kişi ekle", + "exchange_provider_unsupported": "${providerName} artık desteklenmiyor!" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 9c67c532a..ff3be410a 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -339,7 +339,6 @@ "template": "Шаблон", "confirm_delete_template": "Ця дія видалить шаблон. Ви хочете продовжити?", "confirm_delete_wallet": "Ця дія видалить гаманець. Ви хочете продовжити?", - "picker_description": "Щоб вибрати ChangeNOW або MorphToken, спочатку змініть пару для обміну", "change_wallet_alert_title": "Змінити поточний гаманець", "change_wallet_alert_content": "Ви хочете змінити поточний гаманець на ${wallet_name}?", "creating_new_wallet": "Створення нового гаманця", @@ -726,5 +725,6 @@ "enterWalletConnectURI": "Введіть URI WalletConnect", "seed_key": "Насіннєвий ключ", "enter_seed_phrase": "Введіть свою насіннєву фразу", - "add_contact": "Додати контакт" + "add_contact": "Додати контакт", + "exchange_provider_unsupported": "${providerName} більше не підтримується!" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index a1bf60aeb..e25e4f4a2 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -340,7 +340,6 @@ "template": "سانچے", "confirm_delete_template": "یہ عمل اس ٹیمپلیٹ کو حذف کر دے گا۔ کیا آپ جاری رکھنا چاہتے ہیں؟", "confirm_delete_wallet": "اس کارروائی سے یہ پرس حذف ہو جائے گا۔ کیا آپ جاری رکھنا چاہتے ہیں؟", - "picker_description": "ChangeNOW یا MorphToken کو منتخب کرنے کے لیے، براہ کرم پہلے اپنا تجارتی جوڑا تبدیل کریں۔", "change_wallet_alert_title": "موجودہ پرس تبدیل کریں۔", "change_wallet_alert_content": "کیا آپ موجودہ والیٹ کو ${wallet_name} میں تبدیل کرنا چاہتے ہیں؟", "creating_new_wallet": "نیا پرس بنانا", @@ -718,5 +717,6 @@ "enterWalletConnectURI": "WalletConnect URI ۔ﮟﯾﺮﮐ ﺝﺭﺩ", "seed_key": "بیج کی کلید", "enter_seed_phrase": "اپنے بیج کا جملہ درج کریں", - "add_contact": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮧﻄﺑﺍﺭ" + "add_contact": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮧﻄﺑﺍﺭ", + "exchange_provider_unsupported": "${providerName} اب تعاون نہیں کیا جاتا ہے!" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index a2b3e7979..8d8f99725 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -339,7 +339,6 @@ "template": "Àwòṣe", "confirm_delete_template": "Ìṣe yìí máa yọ àwòṣe yìí kúrò. Ṣé ẹ fẹ́ tẹ̀síwájú?", "confirm_delete_wallet": "Ìṣe yìí máa yọ àpamọ́wọ́ yìí kúrò. Ṣé ẹ fẹ́ tẹ̀síwájú?", - "picker_description": "Ẹ jọ̀wọ́ pààrọ̀ owó tí ẹ pàṣípààrọ̀ jọ yín lákọ̀ọ́kọ́ kí ẹ yán ChangeNOW tàbí MorphToken", "change_wallet_alert_title": "Ẹ pààrọ̀ àpamọ́wọ́ yìí", "change_wallet_alert_content": "Ṣe ẹ fẹ́ pààrọ̀ àpamọ́wọ́ yìí sí ${wallet_name}?", "creating_new_wallet": "Ń dá àpamọ́wọ́ títun", @@ -720,5 +719,6 @@ "enterWalletConnectURI": "Tẹ WalletConnect URI sii", "seed_key": "Bọtini Ose", "enter_seed_phrase": "Tẹ ọrọ-iru irugbin rẹ", - "add_contact": "Fi olubasọrọ kun" + "add_contact": "Fi olubasọrọ kun", + "exchange_provider_unsupported": "${providerName} ko ni atilẹyin mọ!" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 1c47ca2ba..ec85b4521 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -338,7 +338,6 @@ "template": "模板", "confirm_delete_template": "此操作将刪除此模板。确定吗?", "confirm_delete_wallet": "此操作将刪除此钱包。确定吗?", - "picker_description": "要选择ChangeNOW或MorphToken,请先更改您的交易币", "change_wallet_alert_title": "更换当前钱包", "change_wallet_alert_content": "您是否想将当前钱包改为 ${wallet_name}?", "creating_new_wallet": "创建新钱包", @@ -725,5 +724,6 @@ "enterWalletConnectURI": "输入 WalletConnect URI", "seed_key": "种子钥匙", "enter_seed_phrase": "输入您的种子短语", - "add_contact": "增加联系人" + "add_contact": "增加联系人", + "exchange_provider_unsupported": "${providerName}不再支持!" } From 745607aa731862b4fe0e93a2033de5b06228898b Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Thu, 2 Nov 2023 15:41:11 +0100 Subject: [PATCH 020/241] CW-515-WalletConnect-deeplink (#1153) * feat: WalletConnect deeplink WIP * fix: Handle cases where a non ethereum address is in use when the trigger is made * fix: edgecases fixes for walletconect * fix: edgecases fixes for walletconect * Update pubspec_base.yaml * remove unused dependency * remove unused dependency --------- Co-authored-by: Omar Hatem --- .../.plugin_symlinks/path_provider_linux | 2 +- ios/Podfile.lock | 10 ++++ .../wallet_connect/evm_chain_service.dart | 2 +- .../wallet_connect/web3wallet_service.dart | 20 ++++++- lib/di.dart | 5 ++ lib/router.dart | 8 +++ lib/routes.dart | 2 +- lib/src/screens/root/root.dart | 53 ++++++++++++++++--- .../settings/connection_sync_page.dart | 10 +--- .../wc_connections_listing_view.dart | 31 +++++++---- ...idget.dart => message_display_widget.dart} | 20 ++++--- pubspec_base.yaml | 1 + res/values/strings_ar.arb | 3 +- res/values/strings_bg.arb | 3 +- res/values/strings_cs.arb | 3 +- res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 3 +- res/values/strings_es.arb | 3 +- res/values/strings_fr.arb | 3 +- res/values/strings_ha.arb | 3 +- res/values/strings_hi.arb | 3 +- res/values/strings_hr.arb | 3 +- res/values/strings_id.arb | 3 +- res/values/strings_it.arb | 3 +- res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 3 +- res/values/strings_nl.arb | 3 +- res/values/strings_pl.arb | 3 +- res/values/strings_pt.arb | 3 +- res/values/strings_ru.arb | 3 +- res/values/strings_th.arb | 3 +- res/values/strings_tl.arb | 3 +- res/values/strings_tr.arb | 3 +- res/values/strings_uk.arb | 3 +- res/values/strings_ur.arb | 3 +- res/values/strings_yo.arb | 3 +- res/values/strings_zh.arb | 3 +- 38 files changed, 180 insertions(+), 62 deletions(-) rename lib/src/screens/wallet_connect/widgets/{error_display_widget.dart => message_display_widget.dart} (70%) diff --git a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux index 7d9244fbe..0ed52b295 120000 --- a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux +++ b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux @@ -1 +1 @@ -C:/Users/borod/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_linux-2.2.0/ \ No newline at end of file +/Users/blazebrain/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index acc3b8824..f09ad4561 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -115,6 +115,9 @@ PODS: - Flutter - flutter_secure_storage (6.0.0): - Flutter + - fluttertoast (0.0.2): + - Flutter + - Toast - in_app_review (0.2.0): - Flutter - local_auth_ios (0.0.1): @@ -143,6 +146,7 @@ PODS: - FlutterMacOS - SwiftProtobuf (1.22.0) - SwiftyGif (5.4.4) + - Toast (4.0.0) - uni_links (0.0.1): - Flutter - UnstoppableDomainsResolution (4.0.0): @@ -171,6 +175,7 @@ DEPENDENCIES: - flutter_inappwebview (from `.symlinks/plugins/flutter_inappwebview/ios`) - flutter_mailer (from `.symlinks/plugins/flutter_mailer/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) + - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - in_app_review (from `.symlinks/plugins/in_app_review/ios`) - local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`) - package_info (from `.symlinks/plugins/package_info/ios`) @@ -198,6 +203,7 @@ SPEC REPOS: - SDWebImage - SwiftProtobuf - SwiftyGif + - Toast - UnstoppableDomainsResolution EXTERNAL SOURCES: @@ -229,6 +235,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flutter_mailer/ios" flutter_secure_storage: :path: ".symlinks/plugins/flutter_secure_storage/ios" + fluttertoast: + :path: ".symlinks/plugins/fluttertoast/ios" in_app_review: :path: ".symlinks/plugins/in_app_review/ios" local_auth_ios: @@ -275,6 +283,7 @@ SPEC CHECKSUMS: flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83 flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be + fluttertoast: fafc4fa4d01a6a9e4f772ecd190ffa525e9e2d9c in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605 MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb @@ -290,6 +299,7 @@ SPEC CHECKSUMS: shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 SwiftProtobuf: 40bd808372cb8706108f22d28f8ab4a6b9bc6989 SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f + Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 uni_links: d97da20c7701486ba192624d99bffaaffcfc298a UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841 url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4 diff --git a/lib/core/wallet_connect/evm_chain_service.dart b/lib/core/wallet_connect/evm_chain_service.dart index bcc6622fa..dc22e3dda 100644 --- a/lib/core/wallet_connect/evm_chain_service.dart +++ b/lib/core/wallet_connect/evm_chain_service.dart @@ -6,7 +6,7 @@ import 'package:cake_wallet/core/wallet_connect/eth_transaction_model.dart'; import 'package:cake_wallet/core/wallet_connect/evm_chain_id.dart'; import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/screens/wallet_connect/widgets/error_display_widget.dart'; +import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_widget.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart'; import 'package:cake_wallet/core/wallet_connect/models/connection_model.dart'; diff --git a/lib/core/wallet_connect/web3wallet_service.dart b/lib/core/wallet_connect/web3wallet_service.dart index 0a7716b71..c69692c9d 100644 --- a/lib/core/wallet_connect/web3wallet_service.dart +++ b/lib/core/wallet_connect/web3wallet_service.dart @@ -10,7 +10,7 @@ import 'package:cake_wallet/core/wallet_connect/models/auth_request_model.dart'; import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart'; import 'package:cake_wallet/core/wallet_connect/models/session_request_model.dart'; import 'package:cake_wallet/src/screens/wallet_connect/widgets/connection_request_widget.dart'; -import 'package:cake_wallet/src/screens/wallet_connect/widgets/error_display_widget.dart'; +import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_widget.dart'; import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/web3_request_modal.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:eth_sig_util/eth_sig_util.dart'; @@ -200,6 +200,24 @@ abstract class Web3WalletServiceBase with Store { ); } + @action + Future pairWithUri(Uri uri) async { + try { + log('Pairing with URI: $uri'); + await _web3Wallet.pair(uri: uri); + } on WalletConnectError catch (e) { + _bottomSheetHandler.queueBottomSheet( + isModalDismissible: true, + widget: BottomSheetMessageDisplayWidget(message: e.message), + ); + } catch (e) { + _bottomSheetHandler.queueBottomSheet( + isModalDismissible: true, + widget: BottomSheetMessageDisplayWidget(message: e.toString()), + ); + } + } + void _onPairingCreate(PairingEvent? args) { log('Pairing Create Event: $args'); } diff --git a/lib/di.dart b/lib/di.dart index 0434f2d2f..b0caf5899 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -51,6 +51,7 @@ import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart import 'package:cake_wallet/src/screens/support_chat/support_chat_page.dart'; import 'package:cake_wallet/src/screens/support_other_links/support_other_links_page.dart'; import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart'; +import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart'; import 'package:cake_wallet/themes/theme_list.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart'; @@ -1153,5 +1154,9 @@ Future setup({ return ManageNodesPage(isPow, nodeListViewModel: getIt.get()); }); + getIt.registerFactory( + () => WalletConnectConnectionsView(web3walletService: getIt.get())); + + _isSetupFinished = true; } diff --git a/lib/router.dart b/lib/router.dart index 26a37c900..90f0355a6 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/anonpay/anonpay_info_base.dart'; import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart'; import 'package:cake_wallet/core/totp_request_details.dart'; +import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart'; import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/entities/qr_view_data.dart'; @@ -49,6 +50,7 @@ import 'package:cake_wallet/src/screens/support_chat/support_chat_page.dart'; import 'package:cake_wallet/src/screens/support_other_links/support_other_links_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart'; +import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart'; import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; @@ -594,6 +596,12 @@ Route createRoute(RouteSettings settings) { case Routes.managePowNodes: return MaterialPageRoute(builder: (_) => getIt.get(param1: true)); + case Routes.walletConnectConnectionsListing: + return MaterialPageRoute( + builder: (_) => WalletConnectConnectionsView( + web3walletService: getIt.get(), + launchUri: settings.arguments as Uri?, + )); default: return MaterialPageRoute( builder: (_) => Scaffold( diff --git a/lib/routes.dart b/lib/routes.dart index ec7ad8ae8..832795a2b 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -98,5 +98,5 @@ class Routes { static const editToken = '/edit_token'; static const manageNodes = '/manage_nodes'; static const managePowNodes = '/manage_pow_nodes'; - + static const walletConnectConnectionsListing = '/wallet-connect-connections-listing'; } diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index 7a903bb69..72aed6a97 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -1,15 +1,17 @@ import 'dart:async'; import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/core/totp_request_details.dart'; -import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/payment_request.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/authentication_store.dart'; import 'package:cake_wallet/entities/qr_scanner.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:uni_links/uni_links.dart'; import '../setup_2fa/setup_2fa_enter_code_page.dart'; @@ -139,8 +141,9 @@ class RootState extends State with WidgetsBindingObserver { } _reset(); totpAuth.close( - route: _isValidPaymentUri() ? Routes.send : null, - arguments: PaymentRequest.fromUri(launchUri), + route: _getRouteToGo(), + arguments: + isWalletConnectLink ? launchUri : PaymentRequest.fromUri(launchUri), ); launchUri = null; }, @@ -151,8 +154,8 @@ class RootState extends State with WidgetsBindingObserver { } else { _reset(); auth.close( - route: _isValidPaymentUri() ? Routes.send : null, - arguments: PaymentRequest.fromUri(launchUri), + route: _getRouteToGo(), + arguments: isWalletConnectLink ? launchUri : PaymentRequest.fromUri(launchUri), ); launchUri = null; } @@ -166,8 +169,19 @@ class RootState extends State with WidgetsBindingObserver { arguments: PaymentRequest.fromUri(launchUri), ); launchUri = null; + } else if (isWalletConnectLink) { + if (widget.appStore.wallet!.type == WalletType.ethereum) { + widget.navigatorKey.currentState?.pushNamed( + Routes.walletConnectConnectionsListing, + arguments: launchUri, + ); + launchUri = null; + } else { + _nonETHWalletErrorToast(S.current.switchToETHWallet); + } } - + + launchUri = null; return WillPopScope( onWillPop: () async => false, child: widget.child, @@ -187,4 +201,31 @@ class RootState extends State with WidgetsBindingObserver { } bool _isValidPaymentUri() => launchUri?.path.isNotEmpty ?? false; + + bool get isWalletConnectLink => launchUri?.authority == 'wc'; + + String? _getRouteToGo() { + if (isWalletConnectLink) { + if (widget.appStore.wallet!.type != WalletType.ethereum) { + _nonETHWalletErrorToast(S.current.switchToETHWallet); + return null; + } + return Routes.walletConnectConnectionsListing; + } else if (_isValidPaymentUri()) { + return Routes.send; + } else { + return null; + } + } + + Future _nonETHWalletErrorToast(String message) async { + Fluttertoast.showToast( + msg: message, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.SNACKBAR, + backgroundColor: Colors.black, + textColor: Colors.white, + fontSize: 16.0, + ); + } } diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart index 573778ed2..e4763653b 100644 --- a/lib/src/screens/settings/connection_sync_page.dart +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -87,15 +87,7 @@ class ConnectionSyncPage extends BasePage { ), if (dashboardViewModel.wallet.type == WalletType.ethereum) ...[ WalletConnectTile( - onTap: () async { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) { - return WalletConnectConnectionsView(web3walletService: web3walletService!); - }, - ), - ); - }, + onTap: () => Navigator.of(context).pushNamed(Routes.walletConnectConnectionsListing), ), const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), ] diff --git a/lib/src/screens/wallet_connect/wc_connections_listing_view.dart b/lib/src/screens/wallet_connect/wc_connections_listing_view.dart index 6a3171a78..bb60dc4ad 100644 --- a/lib/src/screens/wallet_connect/wc_connections_listing_view.dart +++ b/lib/src/screens/wallet_connect/wc_connections_listing_view.dart @@ -19,7 +19,24 @@ import 'wc_pairing_detail_page.dart'; class WalletConnectConnectionsView extends StatelessWidget { final Web3WalletService web3walletService; - WalletConnectConnectionsView({required this.web3walletService, Key? key}) : super(key: key); + WalletConnectConnectionsView({required this.web3walletService, Uri? launchUri, Key? key}) + : super(key: key) { + _triggerPairingFromDeeplink(launchUri); + } + + void _triggerPairingFromDeeplink(Uri? launchUri) async { + if (launchUri == null) return; + + final actualLinkList = launchUri.query.split("uri="); + + final query = actualLinkList[1]; + + final uri = Uri.decodeComponent(query); + + final uriData = Uri.parse(uri); + + await web3walletService.pairWithUri(uriData); + } @override Widget build(BuildContext context) { @@ -48,15 +65,9 @@ class WCPairingsWidget extends BasePage { if (uri == null) return _invalidUriToast(context, S.current.nullURIError); - try { - log('_onFoundUri: $uri'); - final Uri uriData = Uri.parse(uri); - await web3Wallet.pair(uri: uriData); - } on WalletConnectError catch (e) { - await _invalidUriToast(context, e.message); - } catch (e) { - await _invalidUriToast(context, e.toString()); - } + log('_onFoundUri: $uri'); + final Uri uriData = Uri.parse(uri); + await web3walletService.pairWithUri(uriData); } Future _showEnterWalletConnectURIPopUp(BuildContext context) async { diff --git a/lib/src/screens/wallet_connect/widgets/error_display_widget.dart b/lib/src/screens/wallet_connect/widgets/message_display_widget.dart similarity index 70% rename from lib/src/screens/wallet_connect/widgets/error_display_widget.dart rename to lib/src/screens/wallet_connect/widgets/message_display_widget.dart index 0fbbda5c7..044915511 100644 --- a/lib/src/screens/wallet_connect/widgets/error_display_widget.dart +++ b/lib/src/screens/wallet_connect/widgets/message_display_widget.dart @@ -22,13 +22,19 @@ class BottomSheetMessageDisplayWidget extends StatelessWidget { ), ), SizedBox(height: 8), - Text( - message, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.normal, - color: Colors.white, - ), + Row( + children: [ + Expanded( + child: Text( + message, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + color: Colors.white, + ), + ), + ), + ], ), ], ); diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 6f8d51615..82cb697f5 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -92,6 +92,7 @@ dependencies: git: url: https://github.com/cake-tech/bitcoin_flutter.git ref: cake-update-v3 + fluttertoast: 8.1.4 dev_dependencies: flutter_test: diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index f38709bd7..96b237783 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -722,5 +722,6 @@ "seed_key": "مفتاح البذور", "enter_seed_phrase": "أدخل عبارة البذور الخاصة بك", "add_contact": "ﻝﺎﺼﺗﺍ ﺔﻬﺟ ﺔﻓﺎﺿﺇ", - "exchange_provider_unsupported": "${providerName} لم يعد مدعومًا!" + "exchange_provider_unsupported": "${providerName} لم يعد مدعومًا!", + "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index f39fd9dcb..11eb30e8f 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -718,5 +718,6 @@ "seed_key": "Ключ за семена", "enter_seed_phrase": "Въведете вашата фраза за семена", "add_contact": "Добави контакт", - "exchange_provider_unsupported": "${providerName} вече не се поддържа!" + "exchange_provider_unsupported": "${providerName} вече не се поддържа!", + "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 5571db694..6de65a921 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -718,5 +718,6 @@ "seed_key": "Klíč semen", "enter_seed_phrase": "Zadejte svou frázi semen", "add_contact": "Přidat kontakt", - "exchange_provider_unsupported": "${providerName} již není podporováno!" + "exchange_provider_unsupported": "${providerName} již není podporováno!", + "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 0248e8906..2cfbd8e21 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -726,5 +726,6 @@ "seed_key": "Seed-Schlüssel", "enter_seed_phrase": "Geben Sie Ihre Seed-Phrase ein", "add_contact": "Kontakt hinzufügen", - "exchange_provider_unsupported": "${providerName} wird nicht mehr unterstützt!" + "exchange_provider_unsupported": "${providerName} wird nicht mehr unterstützt!", + "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 2c7979be6..aad508e2e 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -727,5 +727,6 @@ "seed_key": "Seed key", "enter_seed_phrase": "Enter your seed phrase", "add_contact": "Add contact", - "exchange_provider_unsupported": "${providerName} is no longer supported!" + "exchange_provider_unsupported": "${providerName} is no longer supported!", + "switchToETHWallet": "Please switch to an Ethereum wallet and try again" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 8f226ba8a..4dc954599 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -726,5 +726,6 @@ "seed_key": "Llave de semilla", "enter_seed_phrase": "Ingrese su frase de semillas", "add_contact": "Agregar contacto", - "exchange_provider_unsupported": "¡${providerName} ya no es compatible!" + "exchange_provider_unsupported": "¡${providerName} ya no es compatible!", + "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente." } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index e29a62643..13671d986 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -726,5 +726,6 @@ "seed_key": "Clé de graines", "enter_seed_phrase": "Entrez votre phrase de semence", "add_contact": "Ajouter le contact", - "exchange_provider_unsupported": "${providerName} n'est plus pris en charge!" + "exchange_provider_unsupported": "${providerName} n'est plus pris en charge!", + "switchToETHWallet": "Veuillez passer à un portefeuille Ethereum et réessayer" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 62083df30..6430986be 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -704,5 +704,6 @@ "seed_key": "Maɓallin iri", "enter_seed_phrase": "Shigar da Sert Sentarku", "add_contact": "Ƙara lamba", - "exchange_provider_unsupported": "${providerName}" + "exchange_provider_unsupported": "${providerName}", + "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 367f704b0..047d3a0d6 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -726,5 +726,6 @@ "seed_key": "बीज कुंजी", "enter_seed_phrase": "अपना बीज वाक्यांश दर्ज करें", "add_contact": "संपर्क जोड़ें", - "exchange_provider_unsupported": "${providerName} अब समर्थित नहीं है!" + "exchange_provider_unsupported": "${providerName} अब समर्थित नहीं है!", + "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 5db06889e..e532703da 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -724,5 +724,6 @@ "seed_key": "Sjemenski ključ", "enter_seed_phrase": "Unesite svoju sjemensku frazu", "add_contact": "Dodaj kontakt", - "exchange_provider_unsupported": "${providerName} više nije podržan!" + "exchange_provider_unsupported": "${providerName} više nije podržan!", + "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index bae6e1e64..1ba4d7978 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -714,5 +714,6 @@ "seed_key": "Kunci benih", "enter_seed_phrase": "Masukkan frasa benih Anda", "add_contact": "Tambah kontak", - "exchange_provider_unsupported": "${providerName} tidak lagi didukung!" + "exchange_provider_unsupported": "${providerName} tidak lagi didukung!", + "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 9a9e19493..0f137971b 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -726,5 +726,6 @@ "seed_key": "Chiave di semi", "enter_seed_phrase": "Inserisci la tua frase di semi", "add_contact": "Aggiungi contatto", - "exchange_provider_unsupported": "${providerName} non è più supportato!" + "exchange_provider_unsupported": "${providerName} non è più supportato!", + "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index f9c1c47df..aa8fee600 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -726,5 +726,6 @@ "seed_key": "シードキー", "enter_seed_phrase": "シードフレーズを入力してください", "add_contact": "連絡先を追加", - "exchange_provider_unsupported": "${providerName}はサポートされなくなりました!" + "exchange_provider_unsupported": "${providerName}はサポートされなくなりました!", + "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 0d48a3dcb..6b2a12929 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -724,5 +724,6 @@ "seed_key": "시드 키", "enter_seed_phrase": "시드 문구를 입력하십시오", "add_contact": "주소록에 추가", - "exchange_provider_unsupported": "${providerName}은 더 이상 지원되지 않습니다!" + "exchange_provider_unsupported": "${providerName}은 더 이상 지원되지 않습니다!", + "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요." } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 9c2a9aa89..0268d0375 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -724,5 +724,6 @@ "seed_key": "မျိုးစေ့သော့", "enter_seed_phrase": "သင့်ရဲ့မျိုးစေ့စကားစုကိုရိုက်ထည့်ပါ", "add_contact": "အဆက်အသွယ်ထည့်ပါ။", - "exchange_provider_unsupported": "${providerName} မရှိတော့ပါ!" + "exchange_provider_unsupported": "${providerName} မရှိတော့ပါ!", + "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index e0ab4568d..8706fb8ab 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -726,5 +726,6 @@ "seed_key": "Zaadsleutel", "enter_seed_phrase": "Voer uw zaadzin in", "add_contact": "Contactpersoon toevoegen", - "exchange_provider_unsupported": "${providerName} wordt niet langer ondersteund!" + "exchange_provider_unsupported": "${providerName} wordt niet langer ondersteund!", + "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 683981eb8..9c09cb520 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -726,5 +726,6 @@ "seed_key": "Klucz nasion", "enter_seed_phrase": "Wprowadź swoją frazę nasienną", "add_contact": "Dodaj kontakt", - "exchange_provider_unsupported": "${providerName} nie jest już obsługiwany!" + "exchange_provider_unsupported": "${providerName} nie jest już obsługiwany!", + "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 6c67a1fce..0e3206549 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -725,5 +725,6 @@ "seed_key": "Chave de semente", "enter_seed_phrase": "Digite sua frase de semente", "add_contact": "Adicionar contato", - "exchange_provider_unsupported": "${providerName} não é mais suportado!" + "exchange_provider_unsupported": "${providerName} não é mais suportado!", + "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index a8be5852d..2f9d4846f 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -726,5 +726,6 @@ "seed_key": "Ключ семян", "enter_seed_phrase": "Введите свою семенную фразу", "add_contact": "Добавить контакт", - "exchange_provider_unsupported": "${providerName} больше не поддерживается!" + "exchange_provider_unsupported": "${providerName} больше не поддерживается!", + "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку." } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index f54e7e340..fc38e69df 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -724,5 +724,6 @@ "seed_key": "คีย์เมล็ดพันธุ์", "enter_seed_phrase": "ป้อนวลีเมล็ดพันธุ์ของคุณ", "add_contact": "เพิ่มผู้ติดต่อ", - "exchange_provider_unsupported": "${providerName} ไม่ได้รับการสนับสนุนอีกต่อไป!" + "exchange_provider_unsupported": "${providerName} ไม่ได้รับการสนับสนุนอีกต่อไป!", + "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 0cd38e036..4c847c84e 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -721,5 +721,6 @@ "seed_key": "Seed Key", "enter_seed_phrase": "Ipasok ang iyong pariralang binhi", "add_contact": "Magdagdag ng contact", - "exchange_provider_unsupported": "Ang ${providerName} ay hindi na suportado!" + "exchange_provider_unsupported": "Ang ${providerName} ay hindi na suportado!", + "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index fb45bc93f..7ac1546f5 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -724,5 +724,6 @@ "seed_key": "Tohum", "enter_seed_phrase": "Tohum ifadenizi girin", "add_contact": "Kişi ekle", - "exchange_provider_unsupported": "${providerName} artık desteklenmiyor!" + "exchange_provider_unsupported": "${providerName} artık desteklenmiyor!", + "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index ff3be410a..ad5fb22c7 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -726,5 +726,6 @@ "seed_key": "Насіннєвий ключ", "enter_seed_phrase": "Введіть свою насіннєву фразу", "add_contact": "Додати контакт", - "exchange_provider_unsupported": "${providerName} більше не підтримується!" + "exchange_provider_unsupported": "${providerName} більше не підтримується!", + "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index e25e4f4a2..027f4e052 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -718,5 +718,6 @@ "seed_key": "بیج کی کلید", "enter_seed_phrase": "اپنے بیج کا جملہ درج کریں", "add_contact": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮧﻄﺑﺍﺭ", - "exchange_provider_unsupported": "${providerName} اب تعاون نہیں کیا جاتا ہے!" + "exchange_provider_unsupported": "${providerName} اب تعاون نہیں کیا جاتا ہے!", + "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 8d8f99725..98c80bc48 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -720,5 +720,6 @@ "seed_key": "Bọtini Ose", "enter_seed_phrase": "Tẹ ọrọ-iru irugbin rẹ", "add_contact": "Fi olubasọrọ kun", - "exchange_provider_unsupported": "${providerName} ko ni atilẹyin mọ!" + "exchange_provider_unsupported": "${providerName} ko ni atilẹyin mọ!", + "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index ec85b4521..ac46a3fc6 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -725,5 +725,6 @@ "seed_key": "种子钥匙", "enter_seed_phrase": "输入您的种子短语", "add_contact": "增加联系人", - "exchange_provider_unsupported": "${providerName}不再支持!" + "exchange_provider_unsupported": "${providerName}不再支持!", + "switchToETHWallet": "请切换到以太坊钱包并重试" } From 5bd382f186a2cb2ddbd18529cd66f7cb55b9d904 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 2 Nov 2023 16:54:32 +0200 Subject: [PATCH 021/241] CW-507-Center-icon-Android (#1151) * update icons * update monero.com icons * Revert "update monero.com icons" This reverts commit b23e984e1acaa589e80cc1f0cf211f555e36bb61. * fix file names --- .../drawable/ic_launcher_adaptive_back.xml | 74 ++++++++++++++++++ assets/images/cakewallet_android_icon.png | Bin 5377 -> 31276 bytes .../mipmap-anydpi-v26/ic_launcher.xml | 4 +- .../mipmap-hdpi/ic_launcher.png | Bin 5736 -> 2552 bytes .../mipmap-hdpi/ic_launcher_adaptive_back.png | Bin 932 -> 509 bytes .../mipmap-hdpi/ic_launcher_adaptive_fore.png | Bin 7954 -> 3709 bytes .../mipmap-mdpi/ic_launcher.png | Bin 3673 -> 1697 bytes .../mipmap-mdpi/ic_launcher_adaptive_back.png | Bin 539 -> 327 bytes .../mipmap-mdpi/ic_launcher_adaptive_fore.png | Bin 4328 -> 2215 bytes .../mipmap-xhdpi/ic_launcher.png | Bin 8733 -> 3184 bytes .../ic_launcher_adaptive_back.png | Bin 1397 -> 677 bytes .../ic_launcher_adaptive_fore.png | Bin 10558 -> 5481 bytes .../mipmap-xxhdpi/ic_launcher.png | Bin 13862 -> 5104 bytes .../ic_launcher_adaptive_back.png | Bin 2648 -> 1017 bytes .../ic_launcher_adaptive_fore.png | Bin 19736 -> 9464 bytes .../mipmap-xxxhdpi/ic_launcher.png | Bin 20601 -> 7289 bytes .../ic_launcher_adaptive_back.png | Bin 4312 -> 1703 bytes .../ic_launcher_adaptive_fore.png | Bin 27709 -> 13870 bytes assets/images/cakewallet_app_logo.png | Bin 98397 -> 31276 bytes assets/images/monero.com_android_icon.png | Bin 3814 -> 28773 bytes assets/images/monero.com_logo.png | Bin 21375 -> 28773 bytes .../mipmap-anydpi-v26/ic_launcher.xml | 4 +- .../mipmap-hdpi/ic_launcher.png | Bin 5353 -> 2463 bytes .../mipmap-hdpi/ic_launcher_adaptive_back.png | Bin 932 -> 509 bytes .../mipmap-hdpi/ic_launcher_adaptive_fore.png | Bin 7009 -> 3630 bytes .../mipmap-mdpi/ic_launcher.png | Bin 3509 -> 1684 bytes .../mipmap-mdpi/ic_launcher_adaptive_back.png | Bin 539 -> 327 bytes .../mipmap-mdpi/ic_launcher_adaptive_fore.png | Bin 3890 -> 2254 bytes .../mipmap-xhdpi/ic_launcher.png | Bin 8114 -> 3340 bytes .../ic_launcher_adaptive_back.png | Bin 1397 -> 677 bytes .../ic_launcher_adaptive_fore.png | Bin 8996 -> 5143 bytes .../mipmap-xxhdpi/ic_launcher.png | Bin 12529 -> 5090 bytes .../ic_launcher_adaptive_back.png | Bin 2648 -> 1017 bytes .../ic_launcher_adaptive_fore.png | Bin 16705 -> 8688 bytes .../mipmap-xxxhdpi/ic_launcher.png | Bin 18470 -> 7015 bytes .../ic_launcher_adaptive_back.png | Bin 4312 -> 1703 bytes .../ic_launcher_adaptive_fore.png | Bin 21803 -> 12745 bytes 37 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 android/app/src/main/res/drawable/ic_launcher_adaptive_back.xml diff --git a/android/app/src/main/res/drawable/ic_launcher_adaptive_back.xml b/android/app/src/main/res/drawable/ic_launcher_adaptive_back.xml new file mode 100644 index 000000000..ca3826a46 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_launcher_adaptive_back.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/cakewallet_android_icon.png b/assets/images/cakewallet_android_icon.png index a96724f1c5924345370051a92fbc49f8a3fc9b6b..59cc69414eda4a03dbc47324c80c790f242334f2 100755 GIT binary patch literal 31276 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 literal 5377 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 diff --git a/assets/images/cakewallet_android_icon/mipmap-anydpi-v26/ic_launcher.xml b/assets/images/cakewallet_android_icon/mipmap-anydpi-v26/ic_launcher.xml index 90f958096..00d924171 100644 --- a/assets/images/cakewallet_android_icon/mipmap-anydpi-v26/ic_launcher.xml +++ b/assets/images/cakewallet_android_icon/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +1,5 @@ - - + + \ No newline at end of file diff --git a/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher.png b/assets/images/cakewallet_android_icon/mipmap-hdpi/ic_launcher.png index 2bcdb4427416663af173d6293e51d4b01022fee7..10d0a1a82d448275f5ac6f69e4fd5ff4e7f80490 100644 GIT binary patch delta 2543 zcmVb}a`uO|Y-p*~F+i<&kw|89To|*6LXDVDJ&{P%yJht~l*>M4p$-D8vW6jORy-d6JB!Uk zf{;lD1pOOX!w@uQY;5d)XEFT(rNRj_t%gse)vjZf+8(#mHbMVUOTBU2Qi+sY+vA)P zAwy6s7F&U=VF`MG#Y#!ggb)%F0#^RdRJX-a>Z(pdU4OdKP#3ltYJOW%o!gpJ=gaZp z4nuwFMMEv$no{??YN{6wTk2pkf4w5$5VR6mLlHDOI{F}s6-y9WFd|y=$Uajwb{py( zAz{|qq^b*mw?CUypV?%nJ6|?4+Gbe!*9nLWL4AFF4XV`kK}neo z=ZS{>bbn_`y*gnj)8m>xQCWgadBUAXEcLmr(h;NM{q2VOmymzl%)h=5RE{9j|Ie?P z>g?z8g(@}XtV^n|ZcC{HC#<~tD1gckbW|eGx5W9*U6(IRl)!`s5`jo6KS7Z56?vLG zRb7CnffIj7BBOp!Z-Vj?loYf2Mqg#fIZI5rd4I^v+=G5!Z-Vj>ghT$5o^eY(Gis?n>`AFbFB$6W4f*FgVmfXWb#azzetkIzrAj%aepIsP0EairDUm!QiGe{6MrQ! zx9AAs3Et3~%DZ_T^lu#PLF34MJ}6O$wBX}nX6|HgwtQYF+O=5B_C2jr*P(yJISrfa zb8hcX6&t}obOh1k!H?*K==hC#ee98xN)jz%erjjIV^-aWRMn+2VruwQ=R$O_1I*B z4#|ValKFm~9Ldzt+PhxKnKhx_L+Bugj-V}))YVUu{yU(*OzFV<@K`Ur{IqQ=>U$)UE^l~w~!$K$xe98`I{U7egMaGbbjv$`sS+2C-3x8+~Em7t} zi2Hxv7c)bH=-<#j#mBssolB0y@#llKcKu+7ty$D)_%LUU8@Cqihbl|ZMM97x^ahQf zOT^5EC({|fa_weA%*)8kds*iHc&AMsq@txxf=J=&UgJv=B#NlRKy(DXc(`y5gpa~k zF~56!DnXdpno--NC^%{AV}CAx6d!};#l>fVn?y_4A0sGST3HY5WI_)I#xr6q3o5$^_2Ei1%?(-qmL+Bug zj-b5~jz3(WNJUUK2bqs4E$yCaBGgxVkLMCTc2%9c=-Wb`yBPi5?tiICDK*^Ic+tsX zbOd4hln^>8I&R*UGXpAlcW!g4knz-rO(5pgvEYg>x>s4MnRy zZ#s}5k}#IQ@3;{yL4cMiEe%~D9hlnEZX>g?=$uQUi22cO)qm$Zp!fVmIgg~#bX~Vi z{L*A`Ng{}zAfD)QA8ijXd#&wnobm&pg+!~TC7S(KDu0|d`|N1T18mU#IV)}_pNX2eoo+n&m6q5+~PMJs(I{d^xN4?%!e z2IVIRJbx`d!^>Yp4N4GtNjQ1^o~A)% z2m(YLzgyC!fb*6|z!Ic#1Oa+HRP%a`Rcf%iLdP;7IiRux0m65S)L!m_vs9qQV|!@d zWPaY{6O|_@b8gyx3*@guX6DWLVl;|qMJty~o2Xgj8y;^Bg4`IDvVwPj=qIC9YyeV% z=tQ_dS${zTjau%0Ni6pq3uR7TC<#F&|E&fd}Pha?0>9UwF-jfEnBv1Q7jhg8y_E6hG8fcu4Z6X@pxQycX!7c8yl}d z#-^qw|K{Z$ix)3GO%CS?KGEFVe8-wKYg#%wI-YE8ZC%~o-u{FeZEbB+KI?z`ofE~H z*=XZx?j0GB1(}eop`qdQsZs|Ubqg0RJVTD>3N8|SRB&090~wIzoCOOOoGHg(rsXw+ zq`9I^^W<1Bi@vv-fecw${5$0U1GZ-ZYNIx4qc*By{2!aq6qac%Fd_f|002ovPDHLk FV1hv!<%0kK literal 5736 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⪻i#nY9@|l@fry|ar}GS2gbNZSxZcN z<~Krd9*bz2xNN^|;S&NF_IqTBprtqZgiaK+O_NG`}gms0>wy% zJ@=4?5Weo3IR51l_b4kXD+70h-UfqkZ_lFR&yxO#v5u8DA~tQ27#;EI3~_#VsVf9- zI`_Lx?~&O9tLuf2=svV$pWc7}{eQ!gmJ>0wgq3>^61>O|I&|nzChinR;pa|$qN5|p zdBLd>G_=(frVvK%r!X!S4?-_mFPxi~`xqm5|1 z1PBKFX2Xvnun+7D`t%`QsT^PHA$_Dt5bFTt41sAOeo}OF`0(LRUP&cS}l6ueE*bEsWI&2{#@K)nSr84|! zh&l2Yyl>u>=A?|DAY{&&Gv`(O2>3g&yN|>X;?=C(T1gee3L&`TcM%FX|KyWT{yqF7 z#PTB-LH@?{4UBchrFmIOT9>EYGBXy^tIP`*R=0>3?)`Yib^x2%1js|>AX1o(1!pSK zepJ1S#G$3xx;Mj;D2O#FFPVj~k-Y^AI*-fOPcd$UJ2fm11M2O02si=1u=!6ocCJH? zA{9eMQEEX+6-07TQo-)s zyKg*v`0yxxG}{}NRNc>!q&3Y(wC^e0qF)KmSwf|L3h={=uthzqz_I)cVU*<^VpU!1 z^c5!*3crHBK5yQ<*B35a_!a8kK`OCw*k0rqA=V#A&*gx>Z%Blb)dVIx2O*NDv9aav zv3zTCM}GywZW6+$yaJ;`c@)zJ^UI1K#i+K};mgHzPR7`Pa<$q%Wy+Mfi1S=QdmL5_ zW6&8aag(K05O^C(rR6b}%B#XP7A;!zEZp^(b?VfqjbVrVPtk0-TR(^SX~oq7wH7x& z9){}+Ed7B;%Rj+M>_6jLOlvF(Jam-SIM*O-s($$4huhdDEt)xVCIeu!8Y+hqa;cO9 zdYd=%r2)!Bb75S8fwk)R)l9tw3l_YJUqX+AD-cITl>~V5!O-j-h<_I^x3PWU=?3R5 zMhmHcCy;pjTobMFH}Y~iqVuO>?%lhW19xNLIm31YkG<|DRxD%)>lYNFVBP0eQ0xw#7EtHf6A6p-hxb3=G--8=wFja&btB zNDYzNKlj{oBjInXhC_yE=G{X4*Oo%;p3AK(@*pqrByYCCw%DfCHf5msQl@e%r`!x6 zgaECHNhWdLR;z}2DG?K84?utH=Xxh5Cf4Vw$9)~=Do*TrA~R01dg9!|<(lCM#Bca- zC-xsac<`I0OP3zRe8V}09x;a!eH(^MxrA59aH>cJK_&xqMbWDGHM#2XclPo4El86= zg9dek;-0|4KoWkdm4rE~7JMrsfkt82q%&boNylzG4c3wdMcjgWacaYc4Oc)yMR2*6 z#5txy6$5?-JPrlvys0djI<1NmI_CsQd?%jel1NXW1-KIxz(i$;LPRN#Z32Fr3PL{& zU>lM|VN{4%8uKjYyU4@g!A|Q*R~XCngxALdBGBXE?#)${#ZqZsp6(hlkLXXyyJ;WG a`~L!*d3T*RVY?&%0000gTe~DWM4f!a|i9 literal 932 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 G2K^t96B8Q% diff --git a/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher.png b/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher.png index 4c41310656b570e3b3c7d4364326365ecaa5797b..8c59ec33ee3f63fff344318d76c925b7799e0a03 100644 GIT binary patch delta 1682 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 T_VaxrC}KQa{an^LB{Ts5BU!L= diff --git a/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_adaptive_fore.png b/assets/images/cakewallet_android_icon/mipmap-mdpi/ic_launcher_adaptive_fore.png index af6a1e312c587b56fc0ddb7a99bea31c36f4c0bd..021fe65deadd7943e2365784cd5ecb467011f5c1 100644 GIT binary patch delta 2204 zcmV;N2xIr?A*T_LBYy~PNkl0`TgcUxHUyHRQ-As^e;9Wn8+|u1r+KMLgoD7s8HwsMeR) zH~D=FPF$zQP(92D($S-=xD*p<&#I%?afPN_?CkkOs8ugZ~|qprNa)mQV-==2)Q zFmUMF-nNJWW9Qsar&=q(4DI$zvF8>v_%?1)vf!S|#099SBCd0AaFuU9dIzNXA!>8qr{Hi=p{UKMZ=ALB%epaNyky~j) zCi3`Jye7-C$cTycx!mfCOjYWvK@&VdV zxkzxX2Rq4B|LN2Z|neO4A%+rqBg z0>AyRC+=EaVDPWO-@CSBv#zl9w8KMyu}eFRNdr&)GTM;;C(zLEPfzMvThG{}Iu&Mu-_Wu{ z5r2$Rj`QWQwmv2Uvo`34vK*(`P=3dh)b7c)9_S_4K`-s2Wpfey3Q+Hfb8Wp0q0W<6 z(}w#$Y4GJmwvJj~UQ?RKkeW%r=&HdJXWRN2iz-KS(niZB@ZRdSKjAkg)qHGZTCNa5 zzieVkOttTmDfxFT2KYXI(gw>WVIR12;Ny=&@#gzIHBRS9fX!OYA$W4Y*Gai z1N*CQ%u_dEIv9Otm7}(y!2dgFJ(Lj42EoVrBm`w>9ts$KhtUB&>@Q41C)~c@z*Fn? zzkBv+yuqZ#Q@5GAi@`~*aMX584>=-k(kCV53A7#HoC1bTdpYBrSuEdw;(I zcp%`x_z2UWm#sH?nUelc)MK>avPrWqXPLUqYt+dm9Sor6cIhTe$6*Y5*^hR;YIoqb zD|DRgeDuY1y63j1#E~W)eM4O1Xx9xiRdKPJ8f7rS2>W8oxvlZV5<5TU$tz4=#FJ0k zc`&P7Wb%+YS6*f3V>rs>MI3Rboqt!KkeAqX0}VXs?@_}HCNNBWJh1M-P!{$YlZT)0 zO*;BkvwL*CU3W&8Zn1~Ou?ckwrep7f>uj<0hAd+S9(d6Y`BMrsWXi4!4f&3pkAY)+ zKVjZNm_3%IXP+2pH+AN8>v86Pj4xt7E<(k)Bc@GE$z$ksL#}$s)CoLbgnut-17#7{ zt{cg)LEZyffpE0>$Js3-2-N2e!Nnf$<0NDqVG z>uH&4S9Y2FdQV;oy-Z^03xDGz1t$?EvVU}s9*=A48+~y;{>I@DmuP3ux!0h9r;vA8 z*i$QL8H^uzxii!o=b!EMvO{kd`p-H(Z)P^`S(4agQkl-q+F7C?4FPuVBXivsDrn2+UX9!yNO(&YzCn&J534886o z6WJ(KaBbqGq-eMGGZr&8>c)K5bW9{`I>vZvHtv+9WpfeeSzE>>dZ*ZWnGEE+YKrbX zp4z2bF!q=0k~ws^qu^K{zh2ka`j|n;cU>Y(F1j$reBc?5-7EFJ=*V^V z3J$B;cCYm7c7J3l)9@Q;hIN0KD<8rAVY7SmczT@y`@>wh9M>UI9hn4%)wkP{x{>M& zG$XnLvr}#W{N)u>BLq2Bd;6#iM#v_(0yyNzk1&?mn&MNn_bb@g_PO==IR($H zulo1g`egsP^{#pmcct{7Tc7AVozJaj7=~dOhG7_nVHk#C7=~dOhG7_nVHk#C7=~dO ehG7m${uKco=~BM|4+c#D0000 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%0AcKhp^?*(ZH!vvOR$yLjT{GJY+zZ7`3i|!~C+gt- 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 literal 8733 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 Hu0mjff%SBk diff --git a/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_adaptive_back.png b/assets/images/cakewallet_android_icon/mipmap-xhdpi/ic_launcher_adaptive_back.png index 65a3f3a1c9554fa5f8ba06e70ce0bd821dbd9355..c4b66dc58bf56a9d50d7315cd062d24c34e9b4ab 100644 GIT binary patch literal 677 zcmeAS@N?(olHy`uVBq!ia0vp^H$a$!4M=t>=)PrOV9N1yaSW-5dwY2yBZC1?!-jwV zOI|N;_g0w~sbHMX@Xt`9g@;YC+3`ezfYB&(G#n^N1PhsYr31S!YD$IylOKbptDnm{ Hr-UW|syexb literal 1397 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 diff --git a/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_back.png index 66e3bf6b943013dbed0038a974fdcbb721cff609..75dc0219d798e9a16c6b26138a20c88be3078fea 100644 GIT binary patch literal 1017 zcmeAS@N?(olHy`uVBq!ia0y~yU~~at4mO}j{44ik3=GT%JY5_^D&pQ=G2~@1;5o42 zllorI&~H9o%dp?br9nc;fk#lGjYGhhr9+YFhyY_!2ZQ0L@MxHfCWwK~ a4SF@p%dC1en zF{Fa=?UhDO1_c4;jo1H{haHqwmQ|b*{XDmafsu(N%~-*qfuT`fp<^D1W?{J~$|0aI zp+R966Hr!2z$F|g@4(dbf{TSiz{5cxwh^d{lVg##fP#Ypqhkpx6AOomLdUvM&7%P} wnn*@7#%N(MT6&Jw7^Ai1Xv=^qO{oK{zJJ(Set((U0&3NHy85}Sb4q9e09br9WdHyG diff --git a/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/assets/images/cakewallet_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_fore.png index 2c0ecc4924c5e4d86b8731da11bef6fc109e63c2..90afb19e8ed3014edaf406cbfd4a6b6250726611 100644 GIT binary patch literal 9464 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 I`10-l006%*Bme*a literal 19736 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 Vr{~4MSdEZM=4j_?TaOK({15zeYCZq} diff --git a/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher.png b/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher.png index 7f632717c145a02da5da1fdf6c21eb9742a521ff..671422b96e84ff18e235276f21296f92c5bec72d 100644 GIT binary patch literal 7289 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 B;$Q#( literal 20601 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 aVhm$-vpB008VIa_7(8A5T-G@yGywok5_;wU literal 4312 zcmeAS@N?(olHy`uVBq!ia0y~yVB7%09Be?56MhC-K#H+A$lZxy-8q?;K#oglglC$s zF9S$|gMqO0ZUq)atA zqxUs66QBr(gn>OsKa(dT^RzX-89)&MgM>Pe2+JfUHl4`X7eH1e9QXqg;ZR}aiP&Ve zkP~R|frg(T5djY_i47^aPQpNgfevFHb=YW#ji#~DTsc}?j25t?Rnll(Ioi4yZI6vM q6i1uZqn(k_Ueaj4k|sUz2TU)@*<%i~?^+ESRq%B6b6Mw<&;$SzoI(r$ diff --git a/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/assets/images/cakewallet_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png index a2104217c43d2032eac66da159f4b736de1ba0ad..0a20252201c73cf5d6d66449c65acee426d911f5 100644 GIT binary patch literal 13870 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 literal 27709 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 diff --git a/assets/images/cakewallet_app_logo.png b/assets/images/cakewallet_app_logo.png index 64682cd1da10b917cbf3ee7b7b7ab5e7200ac96b..59cc69414eda4a03dbc47324c80c790f242334f2 100644 GIT binary patch literal 31276 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 literal 98397 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

ln1FD7F9F< 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

ln1FD7F9F< zp3-B(>gP=v;*)^?mK^Xc7+_!YnRb5!6k&}dpoa?f#qKR3J2w))q3S`ZK)iuTX#t99 zKxc|z;?CqM7Fm`V)CozzoQ**o( zN5~mcU%nt9Zx6Dso)>jsh%=%b?i>uO%zp-b7#lqdJtCl^@3m*b`Uh<>uAnckGQ{0* z$DYOK-~-^bdmmRHy2XP$5=`)61o$Wb?LgCLyL!_IYi2#kq}iL|=i#tns43>E>bZkL zK!*9Mzck9+=mTAtIUr6OyHqiFNtRB(Z<3dl%rsxAGXDgH~T$2Ca{+EoiE!KQKknP?-`3Gu6QuWK4=;zuFlq2>!%N z`;gr4C+E`{o;pxo$g5Akje}klr}o~n_1XacX*FL#rd54d&Jwd=<3)V=j9lfy3W>=+ zt!t4Og#pduSPgwF*8JbW8)ICZkBdy-{OzQ^c`~boQ|GqfcpObK6tAfMF3AWF*vaY0 z4EXNq7bEK1c+@x(6!LUnNCQh!;r8&J*KO~1$5@=<&vddSm*;Pcr0IAmU0P(FsiRvl z0CXX$ytF@2bd@tOt`&NL+{N5s7pLTKHu(tmZM34}5e1p3Em5^~o=c zH56{EnYNJ!P9Qvi`6mn|j&&UAHW5;+4k~)YC}he=pe~B5eacqy*|c_YJ@xbG9~1NgBFH-Q;aI+_LT6?hwo4%sO;M?bN=Tpw z$l6`g4}td+ubQzB5MIYih=b1*^7fnx8pWT}WJ)4%uE!@SiU$4Jw^DS=>LNaV^k2BT zIV`WiIz3&S)&1*G+5+&~I!cPQf^-RWUnm|4e2eD)+QaS$mHW#sLd5&q7d1S&_`)Wl z;>2-I$4Y-Hna#6r_$Yqg9^i*oBMo^G*Bh8kXVO#|MANOKJeMR@^=1x?@-}n3f>qXS_0#TU$w@&xe zEaxT6xT$a+N4QN98=*kraIts#UOW^L1R&}ehWuzE(n4c=AW|;zH*DcXS3_ctyQyxU z_Yvf00Q(0pUG^2uM3CgYXyI_ISL1n$I?&DvH@5G*29d0b9X#)J+b342 ziYtam&o!#4dpa3FcfYoTrp-7R8Y;EFo*%6}w1h0lCT-m5PnT5N7c0eFmZs#w2x-4zYO$Q`FVsw#p15WI1n_1cy4?f_4Carz?`X&r6)axITSUVR0!Z(SOrr_mPs zkFq`#BHVN7Y0U_{o%bgWRh|B_ihniLTT3Q*`>-vEgK;?({jE6tbYm7y2uQXZA9k75 zb}X4Q%q`;-EgX;J&r-ZSVLkp;S6Sn3*Ea}@a4A+OT{O}5#omyxcQcJDfBav;eF{(3 z_d`r)Fan3$CF9Gjj>W@UnwN14K?XcJVK0;~N752GJw9c@9guHl$kw&es;nr7k0@-3 z(7`wxH0gc@tTpTFVPdJo#e^TfC^u3I1e@2S-mf@aj;CGzF|aQjGrAIwlM80?&aDsi zs>awQ5F?zmO02OA;=@`0_8zDtE^{q_C&Bx~{AC|9NDF!tmhqM(K1*mV{(v=>hVW=%d zcDvMcqp1(d=34(3?EMkCJZY0}_@{n)(w@_BDjs+LNb{>jEpUH%q0ys-i6?qH&c3%C z->5+;hprR#P#qBx$Ec<|jQe?|tc!}Hw5^ZzXB}ZSkGFpd&n#>n<$PJdSKQxSyk}5z z2-_Mx7!+waEWA3S*zvvWKnVv*-Aq?ot#lADEprrYHBi`<;!4h}_HHqtP)>c_Em8kkRU zi|2b0clBZLAn{Q-Ja7#Cgp=p&249BLfIoXh)6dv2+ zi|lr(piSL=g7_ za-2fc+xZeXhj#l}SQ846+;F{pcme4@a*Wn~p_!HQS!q6uG+yl06Su}2^cl5KX}=!Y zU)MOkDXP(j9a776b=igAt}f}ZIgd?(nrXYP=2Fc#7w4lU?2Hesmxm9sGmE18yFT?qMYd^s7wVdgrrj(zYU5LV& zRP9fKt8k)7_a&6rZ}Mh_>H37Pm5=5>b(`*Dv1QS<#g`Y)y{|#+LIDwiShVuNsc| zIWjRm^!HpX84WBSmD4FJNMPIUPaF1}b!*{|I=qx__Kc#g==jbu+}{7m6PQ+{%4t<` zkD0gW6Sj<8P;@C6aC{Po9RC?6`Xh6W%c*ph3mk{FOK;4c{~%E%xSj`85!A9(Feru+ zoq_mC(dR`G1y7Gx1cO4Wx?}B}tiMBblK;F>RJ=~OuqrH4l4UE-C=~WTBbHoXEJ`~6h}tj#5~_V&bn1Vh@bfO41JL#+|kzRxvQf~E%cD4 zb(}0kq30cW)p2T%4N9?Dk#2LxJG{HCg3x=3Acr|1-E=@uWb<4Rkq)6K_tt?#TQd0$ zT7RS&S^t``oH(ECMMK-&@yI&rgov6e{k zILzI6=c}&!eig4Y<$EN)1L$tndcQPxfefFzjSy%Eh$O>AZHN0cSV-{ICGb(#d5 zOG0F)D5S+XD?ExajGkFFhHGc+C8-VR>wU2@u2r~`rh9+8dgKO0ReeK~X2?1>DC|HSdv_!eP}BcQs(x>y z_r{Flk&pRb?jaiZ6*YrgW*>z{BeU~UGmD= zY-2@;Vi9dO=j0r}-rv{R)6zd(pQWSw`+l0ysJ=*(h9Ba=QEY9vzlz;U-B`ltq6@F3 zSZ4|vRAv4%_y4p2r)9XrcK{;=V87jz<7ac7~^P25X3WcE4yXRdn zF|hAWRMM>%Z$-+?pCb>&dByjtuL4JOXZ>dkKD9JxFZ)8+5@ELPoXO!7+C!R`=~rsZK|cSAlQ|1yq9LG6FTC%<(qb8eTS%-pEGKl`QfI zMphE_`D;$gUF01$A5~danXC*`JPBqQS!{V$)VtRz^gy@?f@BqMzZzA|+8j0yIuY>v z@ZIy`XF{$yn@{CdyLJWTs_u-K{PdPt!CJaIhB zMdnRfTlets`p_C)gXrX+Y!S$LnpT#r`h}Cg#mcnCOz!q1MkX9i1|h?l@YcG1?V&f) z90@Rpj(&nW4F4g$?9z#V{Y0h&vq=BsuEp+TWQ0-gllcez5P0Cq(IBK~^W1t70QQ2-Jqmf4FfXrc1G1_GmOyEv;h+)RN@;P}~XLv`@w*o!Mnn(OqpVA(wcJ%YhJs~_R zl)#1lknNqLJ!grP_R`y8_0T6(xM`RFMY>0RuzEaHHP3f-Z}O`twyLg7>A-cEfnS+U zWzV*fuF;7OWCsLWlbSSi{Um$sAX(m$&UPefJfH zN1uWfn>?Wil|8$j7K=f%z~a_>Mn9SA6A2rAXay`U5Zp|WpWEEuaif!njf|BV-HT%9 z(U;aW`O}Z?<#pY)>=cj8%7Q8-2UPv@zMy;E;Q7^ zRV)T>#@t`Ag(4H{-S3bJ9qtsZ>dvSx-gpU^_v%X z(1@1hf!Mu~pQ1C|zsuDfLZl*)K#FJ!UPBK_WJjnFcg4Fg$`1muRBIUG7$H++bHIxh_ZA}x0}*n#eik)lxyEC8axSDuLQUm1DMUe<_kBmp%#b`i-U{J z^3+wh$!FR6xMlXVtb2#+a+-8Eg%tLh9n;sACpW%+$87NM8*~D>QipFlQJD_IyPIQd zoT{nhom>*g9cMysK6u=2rw@K6d9}+LS2)?@e9;}aDRW86LH4PScJ3grq`k`t`RUha z*V=N`JSr(1&JA%SnGhec7Id~(3bIwJST&cwbTHCnmJz=_9R0T36ghs32pUARpteod zrJO&y><~VlMBe$g2+he6BkaM=%lJC`R;TX>uNBa{sxPy62TMNS)LX)r>bf8;9w~Ra zhelaVFV@Eqo7f{odo)wbUwY1+Y^(jx-E6j-i7lOy#>CZ1e?z3yCHzElcj`|8Yq>t$ z!y3wY1vv}RXZPH4dv{ZhyGGh)`1z5#fWi0a{SH!xwWQEX{S7M;G&6;T-btC|yB(sxN{sN94$M&+xzQ5Ql!kAb15<@f(oJkWBlgX<$|QEy-o+E^ zhTvPdhb)m-=7;u2Hljb1+NP*6fkAbzHt6Bt+aa!Ef$Z+ha=r9N^}lA`Rxxtn?aKTgy{{dbg$|EQ5pJor3dzM2P zu_6tXGcxN)0=`Af5L$QEu3uz}6^ioHSpv7kg5PO$H)O!gXuGpC4ND<3Vn1S4KK-;# zT+fcat2?PxXB-rI7$!V=pryF+)UPc+_E-|6J2^EYB5F53&{r`j!6esL~~Lj6-({TnxT}nauSwJzIM{JiHN=D%jRhrLOxEc=pin# zVIqn+i0Sc+pRJuahB$Id8}1WB8yG9aR8qp3^@)Lsh1AQmB66-j`^*zR;y<0zJT`eI>FIBLUIOphDm)75> zb}c^(SMEK>6#pM6!5^hNS3{Q@b>4s>mW;p)pTy#gWFpxwkAEH?^j_dCoH$B9k-Q(6 zm`P9F>^Q%8xJL~+X`4WjX2oRqGh`fiw&H&jgDL=zqA~@8%4mzkMrRLgO!(?6GA8g; zsJ^I*tg@>YG{4Xo>8S~@$e0WGrT$Lzn4)&@D&bZZeDprYNUu5=JOt2iMVLkMBuema=b6V>|Uray)Gt&N9H4}5$5L?fEg9fprqw<91 zn*10`#>t%aM91seSd2U8XFa?x0xHB4{>Ko4dTKmiaPP9NeR(@YQ`IAG^%fN}LPzxu zW)s6q!;awMF@w!HL#mZ^7_OqODtWVHU8_>x54=9wu^)B(neYt!h*ygLa8~cRM3Z>R zIryZ{ga#hOOW@CQE~V;v-Z_X2|FDktC!*;L=%FxH{rWqBbyU=)MYr;wuEE&Y4>M;7 zv7>6(ejXc?SQ)ki7b}6iq`e^YFA%kOdk5^%Okr{F^EV9Cu+RGTH02sPG#mav4i3Yf zP*v})4Hu{9=vHu&3zz|cXrXd1Cv3KpCItf>KMbp`A=ue>dq&a}B3fYxa`t|#pzfr< zF6QY3bFgAZ$S0BPh{r!3Ocz5H^jnw8-SHBO3`^i(Q>Yxt1S=n5S6;#u+91~qW;R^V z#z3$=@z(PfUuXq4-*@lXcoaI;R_#aKyA>IarA{_JNF{j_ESE>hLHJ zzow+V)vUJMJER@4NwGiRd#fXIOq&-!Vq@j=iU)Vb zY621Ug`@i~MZ}NGK68fLl)omxys2E)kxph7BE1ZfTY9llmpVy)TtUmUZO0xwZG8i}RE|BT2#o3s|P z7oJ37JN%n)jo0eScbSOSC4D>xzpQu{;(v#oz>-HVrO z#;>BWIhTCP0#Njo9!+V`g|WakKg3f{1UH?ceSN=pQCXEiGq*T*>(8)zMN@IGUdR*` zwg{*UeB17}7HRe53#0UFl^`y4xpto)6NfWNAr2I_2kZ% zWh}GSks@lN`horl@jQy36E<~V^A|!rbvqSpdJ5}wD-TXz{75B}t=jem!+r-s?oN4#NXRi{`~=&f*t+NE zkldfj>(X$y{O-5d@tu%QQe3&SI)*!>HPxwFiiyU2zS?3hnJWS(hBN+?#wsssW1c!* zjz}zQ4*F96RcW-Cd_yOLxrVxajOb;>8jwdt<*i}+4$hydsfg|8#}V}1?|N1TL-{T= zjz%BuPhrWDdf3oZI4>wCn*2D6^?kf4rbNIK)NoCc+tZ`FcxGO91!-YT{HT(hes1PT z)$rwOLWlji+u!f^ZZmImNcM?OC$07-d4tMEMs|?rQf^%iih6q0IBdaFkaK@d`Qa+= zWBb88d7;W+#Y{DgGr^wrG;x|!$2-c-id-AQGMxtOneE+cph0pMVal-Nd|!BH;w~xFli$9~MBe*S7j5f%mSZp!v{pJGx$9DB&T!kk4d(8v_( zfXBO*n_R4(&|I*@HRjY4UF-atyVA~$s9L%Pr{fu@^*_6nMJ|HnnL!GnyB!sBX<=pY z`oY)}vdOEPyGyWrh{k1_xtK`$ZT-BcTVYj}8&C0i=$WPw`V6;~c4(pL|4(^XIEq9ne&g z{X5m(zwkg<%-B2M(UzxVdZxwKQK==;r6|^=8?)&)fz*_aVQh<*5quXdQv0*qKc>9Q z$N%jHIHcj1<{z7we-N7*PG9&O_3U3s^%veXOjN(s# z0qgbE!CJ`G&6WL&-)HYZH0m|g*kwAL{fW)%w&Y1*&m!^rY(r~1G)jc!ooSXQgzd#{ zxV?|?!H9SK76&&Xc0wn)-M#(cdW~+ZY#g?)B>_w`;_4jGXC}Jone_CARG+`gvc-f1 z(wh3f#C1b)+DUTi3^4fKNoErVx4J#tO9guP?au2j`!#4 zt0vddf`*ZOo!ITnWnH|c^l~qch$RKG^4%ll8XJHnKqmDt$E$tynoD<${aFC~OTaZd zbX*T%hzjUTSkGcG`i+<#@sp%JJHIEL`tfdJw7JDquna>(u8PEMV1UFZU4zr*1vpR8 zxy!K7*mEHBmKz|^fuZtp49N#SrK%x8Mqq&Nr}0rDofWD}G4b3VAGG?bdXDXrHLE5! z{Ycb^PXGr0_vX>)#9NG#5@S&Yl>O0k>zba5sC$CZcguyJ^Az{_l8FB!rAh zw?8OrU2U*oUWSf=MGW|P0cB{jWX}d8~`_#;y-GbNs@JF zAII!19>mIo5C>k|4n>?Uz_xoDNcCT_$B;SNuEO?jh&2Y5s8ZGLKQL5B<}j((#5LT- zx_vK%4LEs;2L$Dzf>u>EnFxVS5VG$_8S^sU^%0O-gWlwfOZz%T%9(?_g)7-JRU`<& z^%~$4C~pSR{8U=HtezK!-X+JrqIBr>eVJ1eHaUg^PDMRei0zNSBYTg*kbo_NMZ&fr zcXng^**uJ_b$2@A6F7;9GGt!$^R(ZI|Yv$CK%a^ zili{M4l4}N&$JCAV;sUpQ?!nlsc2cGFQrTZ6YPwVuPK`cOmq`bY4@h}rbo+tpwW+M>CHUAuWJ~> z!~T#Gi4mkD8j{qw2|g7~qPph(896*O9rwZy7)?nRA2{6a%JsAh|FPemA;hOtl+~+^ z#~&&Db9sk>6wJHz>6=n#``2g^B1zvQ!JV#u@zerweg~KuC-!_>^{alaGy#@C&O{Db zq%%n+;La$_4JNV&ApJ4Xj(#*4H`za{t(8Y**k$(Dfmq;2A;2+=T{n?tj6^DR${C6U&z$@rcndTt3*vIfA?54$L4Nd zSLf6kXW2CyvTj8hyu!Ts)%cb0M{+2zhEEmr$jljEC@12zU8z8 z8}fe!s37R(PIBny$~)1>s6^dVjMkt%k+>d9T$a?JZ5v%eF;mTDK<=u1Xh3se|0AyP zU&3YTVR05;yw`Vsi|IJTZ8S?z;9h6ev~(DV>@&t-`VOX3Y9Qm0dhvzSdaYwJmKIC2 z)TCP_>+dbadY84ZUZHUgwR(*;O4h&gmWz!#-3qyLj|R4+TjzdZWEDbi*Gy*~HCk*% zKF?K>&$P^s#D4ecpQ#Jd8z&uk<_Ibuc9u;xLU}Oa)gzd_2eZtEnJw>~Uh6(l1}%Oy zzGjo{m~vbN>^_C&Vt*mb+OFc?Y8Y88Pe7*83xs**LlK@54T+~;h$ba^9fiK7S5UBs z4PGs8UNnA8&l86?zr%24g*opK#&2#Gc0S3tm{)-Y8uJVf>ZO?62I8Uz8FF2|ig|Ck zI8gRcv>|8XSQL6Z;%~X;Pvr^T$NshHRKT8y4LO+dV#nP5jV`lmecpji8ObfF(ix7Q zPA#iVB0D#uWB9Co5c_h*R8!j%qgxi!M?HyJym55Kh0k+p7VLup*}Xr zb!B>%=K&_lHyq`UkewTukLEi|a-Q>$hB@P_MCY8k!wKrKfn&>-%_Os#*7r6myhw!5 zEMY8~yKCo@xLKyTS}F(d_?g+q-Ozd_`g(4E7oCaT7oPgJj4&NlX$OdGiLkrW2tUwB zOX$M8&NnG=ar+T(&IASr;??r!9r&~x)#)Qz#4(t4H+UG)q}+&^x%-h`@|VlfaaW1x zWouA6Hs5Y!-=1H!vkFjB{ud*fX>xB8`P`pE+7?^c5*fW(lLX@d02FtHbxMmsqWT0K zUyM%Ko!&iT`SaJ>+IE5tOdDq*G@qkk!c-l}_mu71zVi;ql)e;9p8ysh8*O)UGP?Wx z`_P2*OoxiNP2BozP#rH8BLPOs?~GLfa?WwU6R>(oTfm+CDOpSDM`P0@d z)AC?&!3GogE}8%xjn_p{d4r}Hq$Se!06UOza2+%=HfgFM=re3F$mV&HDn!TJa=mxR zw}Xt*6OTfs7}e%p{0lC`Dap~S6c1{6(jn9dCq;XGGgmFu~lsX zw(oVU45_rcfi@Z<26E zR96(IX?MkhFHCmr|7qtT3PR>rCs}`sHJ9EHR&6jP6jmv)Ml(#$yUW_>q#O`TKH$8JCxDaHsSWA9`Qq_}!i$&|nG`XP-CM`&m>p~qFCz%isB=l~_0 zaaFwU%2=aN-k2&1jiZ0@g=z6@UWdS0T030;G~%W9wG67tq7Mvf@cZt4Dl?wV1vlXC z)&$SO?6CjD1GR*x=%>R|Rjp+7u-^SwQv&I?!87E*7cVgiMTT(I(|olm%a$#!Iw(ef z+n|G-_4=LsqWkOqt4R$RqM{5W?`tf$L~Pkh%6)0NdiHD3E}iUpnH5erBMj_Wro*^5 zy#UhYYig~|l?#5ohtI4QIw{}28P-Sa?zlSR^5r6;$U$P3VhI#%fd=HWz;d;ts|6WF zDB58S;w?%O+fP$&*-RaRk2$G@Ke(!FJ9^c;l@HHoF3OWT*5fNPoN=ZPQIoa@={UG` z4>X?IQR$~{ZcjF6=-+}NU`7C(7dmpWg6&~g6s;%V^1guzM`e-|LbW0)^cRX>ctT5$ z_san#i-b!!iWk3U;f&<$`?I)7zfdlA&#|XGtp5z4W7PB5q>R66C5pb|@W+9hICmU?I>Cl(_XsgcM7zWI9f`-v6@@apCB9zM?_7FOLT zsaJxTgfxF_idam5=5mDTmkc~ypx$hWq{;e4xrv7F$Gm80w)XngE>f2h<0Fs()&x3U z0u?yQzFH!9Hmbm``3YM%aeZ95$mGKp@jOiI(s(#Ns7nK5fHxT}AUW!EZ3P@yjrJuj zLXbx~!zs1WcS~-vN3!o%I-jS8%)e}6N0`ka(~1&3a)Ws14_(yrG>KCS*vkvtgpH5$ zLNbdXNe+Wo>JRVug>$oQIt$n7Jfb!Dy_#8E$t_#yCwwpN%LPtD;9~`ja{dAxy4)V_X+UQOqP( zV6}H-vTo>e15B5qujeyg`;=cBJSEKZ{62S%*?c0anX4-(FR)TAY=2xo_qq@loAhmf zDv-?=0A{y8ed4F8s4gkCF)fQQN6x0LagSAdZ*?N5&v6_6C>!LF?HeSr#2Eh=Bzu<; zn0+Z#a9i-Sej0FQ`(W`j_atiVNc!NPNg^)z!-WrIhdTHz)klDhiPt$`e$?26A2zz1 zRa))J6Kd*6+1lUXC(rFnuJp2RE*6J+x65f?D~(@+@!9g+DOgUdQ*TCMP70(AekEZFbYguNDrZ$m8U@NIyB4$E!3LkdNf- zvMxZt);I|adERk-D&7s*kBT^yW~ppHxZ_}eZ`cV{?$QUGQn8(voi$eM8HGM-@C4q! zr(>yqMoXmy zJHaVotBd*Y93{vt!9=H^4oZ}H{66Ubs7=36%3H*|J-zDMKy8)hmk*A@Y2Wl?!r%>o z<{C@7)v+JUT(c}MV?<~LK zc%nBC!w@vVHNjnj1PMC0ySux)Ymne>!QCOaOM<(*hT!f5-{!mfJNqZ>n>}Y<>o? zs=j^e-skxg4^a;(Drd64GTHUDcq@m9F~x5q!hj*TrOLNatV7rrc;*E=)zt_Q!mGdi zi>mLLr=+2`q*CI|%KIFl_a#DX^kap)J=TC}0@WTFsI|Asx`@}ZOfWm!=!-|ChGzPT zw~f9l8!jM?55YZpUy=K91gDZa(cc-`2LgIN5I2>a7eA#;Wk|?{I-gSGWlQkq*$W!kNS>I~R~}mdy#t@wNx^ zjqY+JKB`OGS2h>1&re3Vu#LCk{?8ri?C}8H0B34Di!oYsvuP>C*EgAo%%Jnzt{|74Jrd;~g- z+zI~m{6DT#JyV{jP`D>6PRDNQKX?f7Q>O+S}n#-rIzj^KYtZ0w9Kd;QuN zLzsEU_j2|y%d7Fqx7|8;4Fr#=rQs*fKJAH{LzPyJ;ja_#)#jzT_EC&=}nYtk0 zk-D}cIJTIl796S(hK7d?_zN%2J&YSy@dUTdlHEPZ!{@A5IKON?^o+qPRV7=zk;Z^? z3CYO?pIVl-hv=`%dzP4ifuHp} zJqQMT(asSRux?EXOy6(;7dBgle?7F03Z{)XdLP@*5Vrt+#8l_lR|}J{WRu4IUi*g4 znXF-W2OI#_5St81+|SOwQJx6DqAr}KMd;I(fE=osy@JUtYx2|%xudgI`?Bf;T_@Zp z4yl%B{KVT@dJw5&X|MtSPkPodVRco!Bn>qTDA0cv+DDybJYQ>0s*AT*?v;7MtrhF? z%%<|?ZzN{x@Bh;Rx7SeOIyzMy{+j~^v7pC#5^o!=&bVhSXnj}eO1{plVkWmcA(q34 z$=mc!?_Q~_GT0lYY`;2rg>n=0+I z0GB1Bg1Hi`#r25+Uq7M~;F#prJ*#-qIQ%S2*9|G60AKt5Q#3Q-32dSGM=~o1QiO9} z3%SClnR%**?L#I$Kjgbjg&upD+in=+wUZVv-XJY`3`Pn@Cb#!-+9{v1$f|yi8BioZ z40LDUuBS?kJ-;}9hCSI2VQ1=!y?dZta8nREg3~&SsyZw*E1ur@)%fj!cv2n&upGKN z*G2F)CLc=R-d+-XIT88NBKe93+I9YraUz7(&NLt0<2m$7eT+g{l^M@+GOoT&?^dj* zHAYs}tke67Vn^44GUc{R*yEIJ|7&O+F;2=T*=@cVo0ik&x`CbkxPo<2lfZ(@iZT8a=# zFYMQHG9UQ0Zd#OPsjBq}-4p3*3#^l+9mWxZ%1nes(wyQDIuFuvG~1}UpT%?G->fj^ z>+H(d7^Z32PHix5uM-Fo{YXo+cA(t`=N=dM`*xVs3PQso?c5>Vd|+#|NtX;Y4kfB( zxN=rD9fe`7E-(KLi$WKahASR=+r!#zY;L-f5bG=W@A@wja4Q~!Y;vUJ0T6TeMbn>3 zr!!mAyB38in&!x2bnnRk8EzQ|%56cIR|SKPTDxUp)dkNb@n0)!n3%x)kJHb>?z zO-Vmy&FKxd5pDYNNY~dSd5Kp#!Tm*3E!j7U6H)R>_>Y>|G$jbj#_GW7dz+Dfrey5gZN|gB17cfDZOd|+;%*s{C{%P# zHSGghzIPMdgFHd${io+nT}a`%c;d<%ar=CpGuTW-~qM4!2X(a@z(?vM7h0 z&*?ryoi*8dCJl_SpE-ajpdkuBwpb{ieVXldObBpwrPOaj^DGc6?X0KCv^Lw9o$e5{ zCc*F0eXJV(jbs*msf;zOdsL?DWaSiC9+){hBxpWjm(o9JrgyT{g8hppNPj936Kst$ z>0+tIp|TzyNSMeesPBPb@w&-=8;{J1S$3}0=2_L!0-I*tc0h#(#ib6{!Ot@%;IVsl z@|)24XByL3AK3bF{HUdb-OcB##j)Xrgh}gq9N$T)wxxYw6JuWpE*5#Js~`_Pr@pov6@}O(rkkq z;%VHLUH`mGMp5Q+jm#|+9Tr$|#MsA>yRE`4X#|WiD{_;J?r%~{qnX4BYwixz_KgDT z+(EHH3af^*kq*rYdc?-4TkGtE!rOfUF~>8&U0S{g=;Y$vzoB|5j7V5E~LB#-4M`XD`eap`8tb_vL*46*hfI_hv` zUZ{j{v3$56je?DuFC@`l@vp*YFK)PO{z9HR=!YOZ^vCFIRr#?|THKIV@;;RJcfWU1 zu66-cYMcbeKDy?cM(Tb6Z@BO52EL6+QDyUJa!bSt9pmSXf8Rj!vO!#vu^dHMTxt!S zN`9W%a~o^NQKPCs_3*n*{f7DD%ZBCAV37hiTeRdc?q3H^4n|y$-v|#yn73dUo0H`~ zf{))6wazhu4e9B0il0(yvyY<|s6aYT`k59U29m=f#~_d|N!12?mWX z1@Bi~i|4`)QoF3PExQFJH_jJFiVlVEpt+uwMM2Zvdi1`JvUYfVbL?F zikpH#kk{GB>7h!Az}T(r!}q5Hvx-SoJHR_JXg-2hdbld{ji(fFDCtJs4VI8Nm&HH= z&lmDf_NAmAy_QK*^RxY-NE(T9k7Rk&$9^b@m&CQz#r-|0@H zajt3ECuTqewHQizJ#pPOWOebxdYUHNpyz&i;-mBa$Gw)gGV^;Z5n1B}brQzIXv(W| zRG#s^#B32@eZ0sE;c=kZ3quwND5uLhHz@~}rshTZ3idqce2}iJ>P1L|R54J+rf79frHR(~7BTz`j3#jYV+9eDL5l%fC4HaB(oCHDaKHh} zi62xaJHO+rz3**{>$~dn&dzWTCAzw77RhSi04Z&< z<1V7jlo;GlYTQVJNbQ8+(20-vf;=c1FZT$F)`z}mOi=IM;FEx*xgS%*x(1E&P?Jxh z!JjfstFlevARESoR{q+|4wk=6{6anBEyUtkIc4r2!=S&mFhz|&i^1(wG1eSDOd>KB zHE8z#9@pD>{4?O~*sp-l6F(G4^iYzY$77kqtT;sr{}kt+4{EhtKl1WHS#3$gkBG6L?L1^ceS{OT_^`GX4vs!Vwb(Nv~ zjBRSFm1)xW+0mo&Yjd2xOST-`R$myl%7vb4!yfNDkRses+79drJ0C{O?9tbpwE(Mv zh{bTCy-Lko@f2emt^1;5<28g$t~4f}li}CvjM&hy^mRpTJezUbx3}LqZEU)|f1zdZ zeI6lTbPh?b!c>p@eEi6eWl+iLL6AAMiQo|1azFrYX6-Pqas6#y}P!I5^2=fET5j> z`&)w&@L`Hvuc8#?1oLRgnyB)%#3HLX+TD^d`}`LA)~p8lXG^9HLg6V4#=-4{%mG{q zd+u4GXi2EhQe&Ep4a1$wS39h9GTGTLH)>U>!L$!8*+1sk@n_CnScF=-5ja_Lj&QTq z54>)3PmTk+<8nfh!12G~Jt`v{$CAc)h_p(@N{p*N&$K=(cMpuwZRY!8A61wr615{H z&2=?kP>F8!DD791#UE5mMeWbtG9M;SN-}jdNGx?8ovr>}XRz%)0Y~+Oo&C)k9;{R3 zy&7BiguVs=+*KVvlM5SlH%FXikY;HJRL>G$&8vAX?7b%b%GO9U<^LWq^rPS0dx{aOnAY*TUpDI;*=v1vNkMG0@Uh*zl?PqfCnf7xl&84xKg+KBIwCz( z6VFFIg1wIeNqrxH6lNnDXJH?~2B--Z3dQeF?0r{opWtj2&6Q+gmgCyE$5kU*-1WNJ z;e9HS$1Un|2IP&pE+(ulwa)#5Bw85u&Jdgw?gAI}5&~M+sV~KqUVjl1iIOCDBaCeR zDw6WR%GRBzdzE?9TYAt;XsiC7!1TM*QI!rkE!|>fS*rNnBob<_nTRHrV%DF4C6us# z=d*Rd;!v7k+7R9NSbAQu~(^c?P+W@*SEjm>h>R(fGd3xNS*M zLrc6cROr{PU(}I~c0qzxd6dOb(~*lZz;6x>_DDo1S_d8=e8U> z!`pxse0?6`g@^EctbT~YdX_KS;d?gP@1dB4A7yt(#oW_kuk-B35_oA4sz+3N5y-+C zvtgQB)T00F2wzn|(G8k8wt(gOahWzxQO%x~JSadOD0&QXoHoi>$E%P3+)f@s7~9{g zc2lW}xhdJntwlI#j_|hvJ+y;123eEqmP~zI+R8ts*;TGP^d;q<@vJDczIMOA?zqn9)9rrHFLRpHY1=Q(X^k)W)*C9n>c6#~l6I$x@^fysc?>$*L`nbB zzWY7u%_8h=?5*}^rhuz)zlzXM&PoSs@{!Wh_gRYWA(~eQw(^Kfo>o>sPJM!pu)e@` z=Gc1!J{A;^fQIU`J^E{;er&-;|CQ=UCVqpE(hM1g=p#2>{fBc(_?AI1Pn zkI2&8c$@2tUNLvaD&U7XD9=pN+Ul8AEM7r;e4>)ynnOQb{=NQ6oem_NiY*(G5nj-P zfIVvhD4ctC(dFh?Av9YCRe5Q2X+3;qI8ds(X+}bRWlGmuH>z>njQF&{iIa+i@l1T~ z5q)-<711D+XSYb1dStp2hJ0b9YK8OxU`IVOVTfqUcDs-{uWgv<63!UpHXX||I21nH z9$uM|&!}Lu(WJP2S7>S(vR!=m7;u86S**owkv+yh+;K8mp!0Iw-4>epc^!M7x6aR4!32vrB5@pjQ2kK3j?|dvQ)fF zx*c5-1&)IhrftKctCp1)J=}}shM7-_GW3ZnCY7stR0qY*MYoEK9~XLA=Qg;g_Xt5% zANE7b8cf%)t(H9Fk$6stbKKk=?7sRHWI9enjU_FRsq7V+x`a~s*_kBu|6b?qKJ|2@ z@{+FL=6+~atCt*X@|lezQ=I*3d(CEDmF-^+(;B_g0n@2vx7fWdOa;_yI{r3A=3&V- z6m#gLo!x1l-IK@I3JJ(ndj7r79_NNn5<_6#VX6=$R zfS@x#$oqWw>QdOGvq5T|$G@Y{e-B{kf@2nvEz?N*4iSCE-p6Pm$j6~%U^s;MO!u73 zifM|_c&$kanzr33TiU#~MDQ|1XY1e(YoD{Mc(bfs>x@;q=H9)us4PmkHb8rZMgu%U zf{`xkTi^3#T|N?L^Qm|pg#Glr{x3zWc6OyaygV8@=4#v-1$R$^Hs@V;wF9P~cFE8N z{mwL=DPEM}9=11Df_V?gvwM=e0R-LxGX}?CAF|%AR#RSL{rgX3mYhkD7|z<);i6$~ zqmOji&XEePTywH`C(D#oyjUJX)fpK*wgB4f$8br$G?&g=*3s7=)EYzq6n)DUXGEKBGTgn4jK7(ubGX9)Z9Ywe@+LaO(N0&t zgPjgZLYs_n`q7`tVqa=^bcsH_9`X`2Oo_3NEmb?frpiZscvhvPGdPOrB^Zn$ZwJ38+W|bhAb~C2o7*nzgg+4x{|1*}t*=jM&Geu!z-6(@ zW06#korjelZ15_#dPT**4{yMOJbC#%9h%NA9-C?h?Biu#Wa-O8NOMJ}JOHwYoE#-< z2>FxiuT`y@~ z^w@JFScdD}ogfZ-HJrPH(AxT_yNOCQXDtt1*7zBg+&ooKsflZMZcOJw;$;?{)cyAc zllF~a#drWOz|pfK&Egpo&py>|tXj0JMh|0?q9C-7i4Tl-@#a5(KX&U;UZ18ehawXy zM0bNR=@%JACN6VC-CAsexkU4_o<=Bf2k?vAX2=F#iU1IEzWooP(rJ9Muc}t`g5;bM zeA-g@W@>fGaAgt$$N1Bha#(hNB+(hwuW6`~BK)sn8Xkg5VB^PN43>_jX*>B^vlj3n z1QrIsSUy7E1XKc<-^!TXO+IzFzrO)E`bE93=Ic6nAa+4WocF~Utk`QWbv?Z#1s17; zSRwqwmLu9Y8J1@0tIk--Af(@-K{T%%H>`A4+!~h5p-(qnaeIeGgfBi`PfF3zs<+Fl zv>BX&p+k5Zi@Pf;g&%!~%AyoG3rAT>N3Q@S_#QxYp2Dr8S0~3_L?lP)wD@)lq5++g zQiR^{>+%`a*<3Ouhsv7SXiI;`hqV`XSpi6eRkHW86am%;&3!rmH^ojR&uIJm698a1 zcM4!1+%1AU|Ai+OzF(qvpel=4KN7WrV&V_T#RXtk_2BCnI3qQyh|aIuA1Ny1<>~c7 z-{qi*+gNyyJJK~LY1E71q42{4q2R?Oa)eiJegEL!_LO_IyGfQ3CnBao87lb?B3d;h zu6O;+c%IW<-H-Z@6Lu^EK>^9tt7W+tbnH2JX@O3d1yO#YkcXDTZrmw6gpm<1LVY6U z#su(fu`&KHq+ZT&UdJyC>nS@kAMjxXp~$Ww<^)Qv3b}5JgIG^yt3h)R|B`nAZIK}0 zX!;=W^{7l5UMbF3g=_C$E~@ChFN8}W?$?mPmEM8$nWetV8;cO=48gZ&j}64=Rgaa- z*TWwqeiJMP7?ck*XqoNZ&2#H5Gbk4`%&&yx;>vHg5$I2dIWAim(Ro~%MR20f+b8UP z4B!@d#pQP9%q@yPFQ{76Q!xZuBhCo`KtKpS$gDUvSjnq=@9556JRcMDD-A$KLUl%U z*l>w>k*c>@n&V*skL4n~^}J#OA)-8M_t|{Iv6OL^(U^z=VF~En_@3}w;+_SyuSdux zKrK-b4dso)#u@BCSh65H3aMJxDs6BGmyvCRf#wxnACs0(@tysqi>+3kuxIb@iPVdZp6g=0lX^YrxjSs zmkc|aYWEE;)gj+`-~D?DdB1LPMzHx8*&JU6m}P%|6CnCh-?Izh@lb2%Sf`<*YJUb8 zf-qcSmHod5s;02VNB=(CXN*C0zfthISwIiExl2BCGw&$Nx-^Tx;OtmHKPW(uKRU8C zp?<2>)}C0;E)M?jA23Y{{!29R@`Q$E^|-^Ks1&CEBnB`Fz_-a5rD>i?MrJ;fWgT<; z-*0~^BRR}5Sq{Mq^~TZ4g9;+eNne9g{GHT}hnHm_V;`2cv=5k|Al>?)U|m5*%^p5K zkC;1>Zz8!K{0RC%r&J{&*j9Lj$Jk3t@5o7(EQQeW2!TIX0B&9+cRs^@nbmsqzLPA= zE1wmFaQs^HLFbY38&-S==&we>4ye%oap2GK7@bItU5aq~DGN$4Vu*JukJ3Pi|5&#A%D;VRn*;y{c8i0e zek0s7elukcKi|fqfwNhVgHk%hzKKo??a2SEHPFRyp-}+U`!;hBfQS7o07TR2Cbd8_ zk?%i*S>F@;I~c;`1m_Kx)c-u=I}#D|I+wsg%m5&&kZw|t0cp7Rv=m;jzHJ;#G+Kne zZ7zx^8{*^3U&3J*_(Nh5WGQtjp_XwnI)Zl)3RD1L^lZNTR)cBcbV;IvUhFoH1h}J$cbqN_sndru>_3#n zO9+)gK(`t%z;&wNvY5UBC9q{RdH`O>@D+2mRurf5c1%ZIxYekFu_iwUAD%O{d(ybo z!qd*g-LX0R<0knXtLQ#DxA;Wyi%^kScQd6iduKbjD<%+`LeZO>5uPnfivYZlEeaf2 zj?`(fd5q$PhTKF+S7YugRZE%t+o~o3UqknP+seGMkaJN^EK~m4OFxhv5Re_E{j~0T zM$lxlTm1)w|MBblvOxbac;W8`>*+d)ZPiwPJo-$_+H`fm&gm`z0N1pRQDeju%hRTa za~60CW3wQVxFkwmQ*{&K?;jOBO>#GhfS2CNPbF)Hh1SdtMXlEA@Lv78jQ0faNdgc- zP$hs}MM;x1-BX`85E^*P3&xmyOg}G^o;TCxO71#F37*tyI*YxmOW24)LrUlX zrkaA(3p16fwn3*pWQ?)j^s5&qGQi&m2BY`wayV#=YV;`a)G;W-p|5o? zK4?mx(YX=J0{mgY*KWUAfmWZ)$a%&T3*ylZc5}CVockF-CBui-+kU8Ob%1$n2Di*r zIzSZ!`U``vX>Q$Gr|4d1$*seMEd`QL0mMHFvwYf*6^&e%RzreES3qJ#oS-`i3k)L< z=ow>hoTg*eX+@-bWi$a%LKPLjsAA2^#4j<5uC@Nmo_>yVy*5GNTa(WFz)VaG2mQ?P zYR>(z9O#=>1;6X~uh*R6{0GO6pX4W>8Rp;Vwa7kBL`$Mmg-HS$I!HG$h#=2mXFF@S z#5atVeF(o-z2B5sFlCDF-To{<#;$kFDFy&+*HYencu=@9f&O6d^~UY{v4a%4cV!0v z>Xx(D7z-$Q;58#}b)w@;0R`KRY#pII<4HI!;0*?rBj$}iU*Mus)1B?Tk~pu-h2;k3 zsVRR!Fvlq@h2q7foc$sbW}8Jec8dZmJ_QC;BmUt{|76Av_9omE?IM8&d@?n3uHqX5 z`uF>J8fH2f8Y5?0+}_GNHh;-zQva0Z{M98U zqgxeAo9dIjn3`wc2r{mdC@!u(Is#U8CpOVy? zm=Pg7gFsqPk`1H9A3C+a z1xe29EupQ{YezxX@;iW(Nwg?IE4uG`nJm(3OF!eu-xSJwaUkFufHQNB?E!7LCQK~d zo>pxx+11kZ-lswRJSdrY5frd6ldsrtym-b0{OTz1vC^i z;eNm;NK*npdlviR@D;VfhBhxGFTV#8KFr76j6;(}EJVCKQP4L0}M`X?#Be#CI5XvfOJzQGf;V8l21{fkOq37UyLeqXI2S|%Tf&_e9&4C_pT zGR;$dAOI*Q5bP`C$)KmqT%)=5c9q5~#`)@qq6ierqvJA&ZcjKD_?;5&Xyam7M>#|!oP?1v3y=tZk1j=y&ar1o`}h{z^e53 ze+7v2ciC8yA+g=jh?OH+k4w))rdL*19VFJcG6DWWV8tH5n=i}XS{Qs;?aF*;n$Rco z3H}Lqg>!LzD+B{z&1a1dZ3-DCe%@NJ67|Y>@NfX5*EyUdcnkR+BL(P5hbbqOL6zlE z!{ffO%26xKzsQ5weqdjS0G)?jU)PE1z5=718wEn}C~-~~6C8Q`NmG-uZgX?Zr9pGq z><>V*4e2HVHi0klf_O>@71Z;xUb@C^>8{^ndb!$4_em-UK@ZV44p9f%HGD7Ts)1(A zkN^NxfjVh&jp)oJxCu#`_v|;|dpYWP+R8@q_)Nq;m1~wN4w(?)qffKN6q_gt<0oQ^ zQFKeECd`8Xm<;%RXfh#KI{4!SwO>Ja~#*9g530!M9pksfNRgu^we&Jugb5Ooe) zEPZ*>pt0aiHNWbZ{guLcmm|)!p%1OQ- z%GwLsY3?2v53YblqV1bZumvMAuq6ahajywSF}tYXopEqy$E53YPdpT+-a(>Wi@iDw zZi6Fo|K$j`{)xnV$j1%yTcXNhRKS95LgzrHvXlT8qYg_bBy$sfpX@GBGyb-Zgk4~j z$nPLfFzZhrqPe}ijV`w|_`*QKd1tZzTI#t(Lo+De$SEO*4?Y9P=()H;jDWtTl$B&U}b@g6WD<*8Gimq2PT#7%Wxl5Det%vcH&cn_9!vjNqBs-CiL&F$>aC3V3 zVH5l6W>dE`Zn2QUd$S$H?y5_I*8rSVP%7x}CXDl45#azs%7B=Md<*P$#YqwmTHV#{dELv_A*#@bEDrS3 zljyLSSpoHiSQ+L*^>UBTTbz?c7->jrA;uRe>@TmJGhSv?e%a2yL&t> z3TL1Y#TSfzWepz1Pb!nPLMz;TG4`+`ZHvqi{X|hY;uicW`?{@P#7{ z;>%z~KflJhkbIG=MJJweW72-t@3>y8&8mSG8WwSbI?WJrdW0sX<`zw&)!G|dh<7m@ zUKBU%8=8jb1nHIsE)=pQ@>iCMn0&L(*uu30F_LHhG!|e)^Uerxd5OBuOXOP!~ z%nrGg7R4DY`)UJD{(~(yt%qh5ypF7HI!^kG_>p+l22F@9dj1K6;nni4ZH=)8gui$A%W~e)jKZR+E!>S)US|2EdUxzjB_VlhLu+^byk77# z7PQ`YY;_kCu+>CEkiJY8i+^SyJJ7vwYy4MNZiBft$ry49G(+yn5)FH!_)tKUK(@qz z$Jrau4aCm$3roBh>T`6oMUQ+#qOi{w@xACo5*U7pBW#3vr(`u)_+e;!hxt~VVI}AT zXT8B+l>OUhRhT8l{EhL5O~kzpzl6v{uJ{V-2b?k_12 ztguKKD66L*7eYkmCFfv19^5Dd>>vDJBX@)8>O&NLR`3Cx=v#&1|9}1;j(`-x6TiEt X0ZY>kbtG_nAe4lNtZ@v=A|+@-9S_B{3rvtrQ^@Dr*Uq?92$MWGSUp$d+U&WM87P z?+MvO*6iyrGtYUA_xtmEuHW@s*Ykb;=<4P5y64vP(3DH%zuGBj-IjG|gdX?wap-=CB-AfDV|fFx{UE|=I5}JM`3S@VsUKF8uy9) zBK&_MvYv5$SdWp2uu2m9IsEZEJx@hJxH|Cgtt&Zq0UKiO{_q3WW>a%E zU+WskJrxA+FL}ui&+xetfzcty=65U<-Zv~%EUi_4{UWbf_Q$!c6J%^&_RrzTVW;+; zwAsm9F0q#feZ3ct2H>$dgv2)Zl1Ix(a~n*mSv)wcb7(r$i4Q0!qCW7-S0fyY*V7il zOztqL7}H4yV)z?I4YRRRb1IPE{}dtB3KP=Y`=0>mMt|k!z`Ph^EBs`!g5P4f_2rgn zm`WW#pIG`-_IE{?CapX&^h$lPe)_~i3mh4tscLhQ>y>i=f_mV+VsC{(Ue0DpmPMUJ zp~;H}ep$4=W@nZThPK#y+i(5VpQo3$r~oz_f;Vi4ljf!(RHt@r)+P2=vhBCb zmtvgT>K7c0o<9h)%G(2>tFk;vphNy)I-+9UN(BYTUzY)RRKV@%gR~S{8fH25h34+;N29iMa@%= z$!k(I0W)H-LFVtNxZRYpgy#6o!t87)M5O|vVmjrWW!(l=qXcJg*<%rbMMo@xz_7fcvB6nc0|WMp1wmy=uGTS z!c*C{$_UjqF6GEGd!$K*MlRo7H2|6WvUJ1u*8>@3L&wit($)8H@UC3%`qxUsUr&>a zhWH)TIHgYRyAq01_=)$+Q8EU>jeGh5$muo zwDUAs%9x9|nOV(=BbBxHF|fxdWCBo29^$`;qaySV9k&PmM6o0y=gOa7F})!eCzc)` zIYuG!?lH6YET^;s`*^@tDxW%f!&8VG72$upyfic}6H5x|5lWp(i@JYF2iT)aQz|)@ zk^iZ_plL>qDlH<;cRaSZ;e-YO>}BejMRdN$;UWG$DNbo-daC{|mvux$F3|tn8$0{+ zNJ%J~dZ$m2O4H=kQ{*IqYK7oy=Gg}wjQ@eh8+?nng*~P0TM!a9kC!dlJ<5LsA^F(6 zRue{EQir&iGsxL1Io0I{!wjU9(LThRYC49EIaB`41o`*$%E9ZCugCZuTl6e=9qi5u7mi791Gjn56nLxC zs3MmHLiuM~A8eG(w4LM74w~%IRo{~?XR#C5Gx+|hgvoN1r76{Szk=}72-&K2-#{>t zBJD8M!;TL~$tn6uBIg+K0Q!72@VMz5_BdA!kH1zPE8tO)H9#!tCxLh4`5g@0r@kt4 zeU<)X0M@PbdXhin>=-t!ApR#I;MsX`yG0zEd8?G(=|$gI7*dws^w(uFjU|t=f-`%b zM2NqPNMA=q$TcIq)5|LQuL|m`I3HVF@gW>23sC^8oxHhprX!e-7!1y{U(hdm&v6{# z`8FQUPoL`F6xN-gDyP@Uk|JcpTVyYNGV&Vi?vz2FES+~w6pcg3gU z>q*Ac$jbfKN$)9WZqPtaRlw7N1LYiP<468cn?Y&~=1F3;rgD?~MNtp={hK!WU)XR& z#|C$2w^6Hg#Qqc-S9hx2zLJFL-MrD6A5c+LRv$0b#NnI}8`@THtY(teUZ6iO!4|p1 zqL1S*8R%a3G|6T1(`Rv(ay-!?$ebugj-hJEK>%zvW&e;kRV=rOkYeI^@Sls89B8ie zTm+hlkil^yIiZ&foY1=SYyv2|MVSon@I#5(`WJzh{yB=!j2~P8ieSGdBJ5ql4t@86STZlX?)i0>| z2G52@gJlX)O!JHKcQ-3On~7ClUDFOO33%KvGU^24JbT^c(ImG4BC>NaP{{fq&fZ5K z5c!>L0s~ieucn^-R7N51z?1c8Dmky!>$d_nXy3S+snLO}@1Jo^WDuLfex79_^G1<~ zjAtn>rIW}2mC2TRvW2(?aUDiffrIb%mGt)i^ruPS%DfHZ-cGG5_1TI-#)rFZM1T&0 z&CVVcrn-;f$g})N*f{}2Y~A$Q*&mTRKQ#T$o<7+`LW@=C*1)T4CU>lHTMe5EO8_;M zX5Td*P$Z3ux;%J6&~h^wQ6Ju_mqp7&eAX`I+H~~j#%>x1mFwnN2fM`|pp0a({K<2< zc|$Tg5p`G`nS+(+((zOR*aR>m1Y)CEB#V^PaYCxcw>AaY*KCL4q)qJdDIJEJ5MS@? z&^wRIWw*)>NTGKO91!Nhbjx$e?pNW)&_Kcl>mztuJ(|&)>E(i3>8AWxt*K0L|@6& z`ceikHA3SP7nPA<`z^)9)|GDs*plcH9)LY2^9s;)uigDtiOGls!Ot&1k-^5o-@~Y& zK|L4j5IB0@j34D&{FYrA#4ADp#_BX!+4tP*iz*&9QSsg&l+qI z2hK~N5dN`cHh8@%p5tEfxsD)H+M$tuam6KJypdd=j_NlXGck;IEriu`7&EsR)|}|f z4RXA!>@k0};l<_WJH_VW8m>wtD;Cg6&BHhTiih%k7uILitv9ABOD8cy_Qb-NBl7`E z*`?8^PRo;oxA)0j=m^r}29Yi8C=g%!KF}q)r%`j3AA*3vwYy-WvKO@z6hh~D=rw(w zhH(>IiD}fjMJq`mBPCFOHq?>s@Nu>$EJYxOY-K`W+_&!4el8L)Ry#7FVU=W-B-T83 zw<+byH4cpF`u3uAEYEhm7Wa6l%6zZFTG;qZ8H|lft^MFBXgF@P9aCfEo@x+0AgjE{ z_4w=w*sa{UGXKDf-@Ne3uU|@&#%dqzN}mmPKEwcaYyGLo%#*m3`rW@|**tzQ_;H%1 zk_cpp8E%kKr`VNR?#Eb5HZry^Op99N;*8WMK&l^}L;5S?)cE#S)-!g4!q2WOOUmwR z*U_Ef#TTzAUvYLsol?q)!}F>h2Ljo1x+MDK_F{%-{^AxXD*o8FRJpUyBOY#uTSvD! z)B3kc_}g(L|@XT1Ns?jAmdln#^kmtdXbB7qSw?Vu3J=RF8RMaUF010(I;+^Yc5%z0NVuvalQ|Y zo6R4XRd?Qgb0|KD9B-^2B1JAm~)W z=gMXo?sp6g6e+uxS+pCn+~9RkB`Wq#S>}DJ|9mi!#)YFM!ydV+HO`RN z(RxPm1wP|1jy3V6Uw};W56$=)Q?KO6`iN~(_Me}THsbY}MC8B?8^Gfc)(nlIlo>4o z%X#uaKp*pHlwyx9Y!KhGq7$hevGk?d&C9_J;$K(1O_8yh`fZbG{$msY{EFG~F|>yG zFR%F0na3`_6{<;n+5;CT{_c-m!||FOBH*iWRPh2a(Pf?FytBKcnfgOI1>YATm2y@* zF(Z1l-RMPz@jck1Kt#$u|K_!e#V+F)GFjEnJYa7aJNx;S314^qz$_1h)-8MtNlDgL zVf`P;rwpOF-?6iEu{oKAEI<5GwQFhu&;={a>hmLDne!ATi@Qkmg!fP^~t_~%e zw~xP((yt}BQ%d-y#bn^A@a$BhEDpF6qF*j5UxZI}y@{BQ8u< z*QCT2X6iG|8x|ZEDiflbObH2$o=27s>W5|TcDfhHja`s#B4uCVAjY>Z9XC+v73BMV zItnue`I`Jfb8Pc!@l%E5@J|i*8G0yJL9eTR=Z~?YKbOa{i+{=b>oXm+r$g)E$!q?? zsY-kkNd-VTU#*sNF37H**jC2<$}?)?%`6q8Ssky1w*xiDGLmSLB0#6O6|dsbL0Lyd zF6IqI*;hVinSBq|Q#}%}fW*h#!h2#_v&%&Eg((k^s8lev_{rm2esIj2`;@`>Dp~MJ z03@h9PjP#Guf-6E^1(T7R;d!(ztc@4O{(J^5=LudDHf}x75j= zRNC7sU&(NwcU6K>UJ7gMdp#G*V>s>`ZXkNlsB5u@x%Obz4JD7;^WDq{lIykuo^Uu7 z%y+m{YmB}$I>^u5_;{yxJU#&&K-tDdX3V|L_Cu{Ueu>V#;ZE^c{D$KmDZS!Zr^J-i z*9P+W{g$|t?l9hU^d9WZ?SBg1n2iA+M)f$CSQ=mRiXq977sWO9r^8{ouy;1xp1D2N zQmaIdxlZkNUmN8Tbv$yB7vH(o%oc|uI{zWrgm=vKJa&{UecQA#gFe$n`@1kqxtr+R zaB*y0ZLO&Is#2y(m3o}OD4c{;nOd*DdK`0@)OJ?n{W?QBI!|-dSC6uf7EkV6HKID% zqo`RnmMuh9p-JO%4SIA^QEoDXO1>f_>;PVnw`h! zq2f{-4%%$1Qr}P=WGp(Eq;9`Tm+pf?wBndYl_lv?G{JX*cwcX^p*9(o%eq+s3mbqY z?MxZ4%W+lmFb;0E_tzQmTIiT8Hrl&nvDXf^{;+ctS&ey4$5%s?$5mlnyNB1& zDT$^2D$WrdYOdRsm&Gp?H7e)5vEwzsRy2hbKd@5tCT7%VdU5=$i>KuB-&a}na|dYg zM%*OIftQO*xyeEZeL79u^tCwDE3>YCobXmPcoMZ^e;^F7tmoDS`*cE3Gsr)(I&jJ7nj--Xds zdC1YNxK(3`wZA;jJsF8D|1b(xxG+23k>@;cbu#;9$&$jsYjp*%!C2&7szFDD1dtp( zc$oBbzaE1^KbEM&xt_PDkYu9~DJfjU4ZA3q9)=md{-wCVj=Wd1ZIfDUPV;|?d9T!0 zhB|SxJmCe~@%{%861b7C87;#1EHjz*t0UWZ`I$)0@~we#iJqo-2~UmOmdbsXFr2uz z__7Qpj(M6c*>OtBBR#22a(ut1hOADGW;aoo6-wtF=l8GIr8{?2=SJO>aEg=c3dDgJ zj9q@sQ9aFBi?v^&i8oQEjx%rVE0N}Rayv+9(c_dWrlO+E6U=CuAx(nQToo^LiHy44 zfB&v({qto^2iJs!FXEyw(bvouk_USkQyV7ZmfE*>jHiryxEIxE3%dk?8+oWozhr35 zMhK`T>1MB?^zAjt>FY1I?y-^Nz_Fn&!%o}6$rnQueWs5ree>8+S!KC(0%#%XMer+; z)xo$XCNaAqz~q*v5Cl^l3n{PJw~eIJbp9%kaINY0=COtSb^K}3mwJY*=l1M@1FM_1 zjL@IwI=&N%;oNYkzwX4ILce?A1%wCmFH}&^YqJYKTpO8$I9l!E$=6Rse$j17?ae9a#znJu~VyFsCMP(&$~v^#k8I-zF5f^{NRqyOU=933o44aszr1IR=7(aMKb~ao4^B3F$7oZfsS%4k3 z>QqPAatku;re!@JXG$=e?MufmC`{_at>f)Ux-!Ot#6EPdiMcaGq0u~5A4Ly??0T7L zQ8dYGoBmEv6nps#iY7H7Lwz|Xc@RLA&b9Y#A`uvw#7Z3k;u^C zM01sUBJV3W7u-%5(~PQ=cO4r5&&!C)eBd{cXcgTk7{ujw;v-v#bkmU!wD=MD9zQHj zi>!D02>LVg9C+#1A7S~oU8jjO6G}kB(H#GrvsAaU+k1dB2R4T3w15-)nC}>uh@G#0 z^0Es29T#nSxEcWo$cQ-I{;4SP)Rdg`G%rlxaJm1SRiej^VhCz$q25zW$t4WxI0_XN!=M2$r9`hyHmH~V=L1D65pCNc2p?^RXdj zqH}RXp{^i#_wpjI61xu~bFa7Bc1yXkHrAcS)M?IOXqxQ()uYo)@74hIc+D)?0@l)` zMDd*P`$;K#2DZetfey|*%~&A|Juflx+WoDtU1wxcE2!ws@}hNHH3+%yIi9TYP+x~R zo?aZG=*ip?4YS#JfxPvU#JBXw<#M0S$#SNQRBe_yaApQ_63HMR^bU zJs|5b;O$SF-k8jZ#}P+rjB#d6Q0|5k@LAkr=$EV+<|n(4+aD1?pN=#6xzhA^ogl=I z*P0Y==6AYLXzk*&ciE_>3G|^e7`s)P*c_l0y_eBS$x-i?T}}x;QhLP0vwKZYpsy*v zTZr(21EeQvyhstHVi8#3+YAR4+-;(U_=J)%xBW97c{FN5FTA+xAz#jhg<-pQ?Gq0G z>i}ESjT%~5j2tn%zwkMjuN+Oh8>alThEio(cvA*eei6;|$17u3&#^aYBo%jx1=9AK z6+dX5F2hCzZj!kJ8ix`YTm|!noYWs@nVX&Pkl|({Gdx;)(ok8*cwHt)H%Hnovk`qb zc6P*P{a3_i(^Ba7%0i&;n)6y(W;qI(7$*5T{0++WhCR`VS<_(qeQKO@lDFF^5V~Z` z?RuW#bm@}WwDE~+G!a%Rz-}MWTs^7t=sZ&zJccj-|f2^jUFHV%h946eqoou-V5}qHQa8%E8F5hPg3CJ~tk+vrfOYE$YP^uMN{XIX{IM)T*S_vns zf;AX&3Ffp2&vVb^>9TN8O!D!8oYa*EbqQs+_{TmTq6h=%u20;M{qf+b64aJ7xIsU$ z=Om8ku5b&(Msqbd+c5Z$`z<<-X#r=b%#g!iuV?-|Rzsr_C}wE>d5?;UFls8qae*vg zf94J@=w%SI%f_$J!i^F@fMriJ=1%4{PMromb2i;YMJBN$Gqu5=e;-l(9dQpEpaPlG zBb9vs_Y0rd+!}P|HnZ8Zu;SY*BTn+HeG4SmbWRk#-u-bhBjQ%Z=n8?MarHHSzQA>X zd7vt_HQI5OxxC#fcM{_kr?>!W5o}~)7{)WL=uXRL88yE{F`0h>fzqyz8wjAaAAU^` zT0&u-M|yZ;@KJ0jZZ;fM%V_DlG>7}+w~PpImGLSjzaGOx{`UCW&+dT9nkAa@qEQ(P za4FvbjB;X!Kk8$Gx*m<-0lNPT_#XB=FsrjtsMxz_hD9(((;S-J+k;$w82%%L; zMMSi%CMnLUNFwj?+rNdG9v4_b7UV_;+J`@@tP+zsOeay&-fqW7(v(K$cSd>2D)|DY{RMQp)%n^x%&CwczLd7j#B&tY{f`%#a>(y_^ zJjG<2jU#s2xI)z1My__^c+5lppbq%s`{#`QEf+lP_=%zq9)6qKpHqIMryuw~GBHGlYFhN`u`b0)T zF==f(wv-)23$KRuVsG8Bx75CuBF8mQ7MvMaD6uqKtsqClZc_$KxOcXZdEnSC1LW9< zFt144^N zu>fyE1XCiK>B1zfSsfFVr$E^O?ACGSl)LAR>U5g!YWR1wKzTzXt(3^gM*hx5wJJ)+ z6>-9?UK5FPj{qWS;fi>WJe=0}K$*k2-VJh2r+3}G-xI@pWH`PMiP>0!)jxPZ2=w&9 z5M_%2hNRnFc>zQ#-C^dmhk1yHjcTKSv5r%yf{X^QAi3TN2SKef6IyodYc6B@^e==h z>$T8DLDrig3}z(d0=~))N1W6`Dyo<%MF?~51-M`L6^(A?&_eWh9n4lE)?jbVifT^$ z!ac+&p#mkJKQtvNPU)6MF!;B$FUxja!VowjR0jz7|GHR9^*{EF&#c)BlaN9QOhAN| z6MKdzJttSO2#~o8KFIA9uRty*H6{fa?S2NzXC;G#egc4fGUU-s=rLoX@yhFmmsYbQ zAzP%q%tK|D0{+%+DA@!T+j6m&c^KN)`Y~~S;6T{B{Li!u@4H;b88ehrgWcFr(Uqa) zh3sbW{d$<{TZMeV;63a!WpkJfnq}!Cr*JzgEEA6&nW$c`B?Hy=4tNLvIelVC?DE)T zUkX}yf(b*|9Nr_&60sEtDnVTad;Ja!DWxpXZ^!Co^M>g38j~UNS;!uf)fCpXAh~U%3ZsA?$pG zh|tp0<>Tn5v&S(|mWV3(uK-sn1N6=ZO3TF9Fb%?Xb3NKn}iq@zx4cO0E?J++l{PBNd@--ve{scw;ga;DWjz5mQ&y3M5<&SQ2gk3L(!{ z=Ag3U01D3yWp3N?aNo-gHDHf{Uc?4v8|5oBQS<(V8N#ik=fZPoSRM=2ulN!mlPG(B zU*e5MXMS$0x?z9?YGMY5Cw_y23HlLW#$d#3+eiPpV1k2M7{KIz$4FViZ5jlpP?fOV z-IL<@&y;XE8p4p8>s`3#4cpc3w)wYKM10IXK&Exc8P3R%In~i>g(f2Ye@F@wW&dSn z+5hk)bN-JQd9uk08^MwMM-P?oAJN2in$j*=D)5|Uf^Pe|rpTdzOGt>9fIiYahVSqP5vKm4?}|L@iF|4=3vH*xq9=Jo45SxljIq?TuJqGx1cgWS|m;-A>}s1E#nPF z56aON-$udH!v!{ws_vv$BrsOnfugu)80au~sNgQTAib*m~(iz;vD4aP{>SSopCni)2|S& zf#-g`f#~#TIT3w$ie+*N-&4W0)!N`LZ!9n5DOwqL4Oawj5uvX2?>hbUVU@sv!hw(# zPigMaqR<_6CY9SP`vPz?J-iNm+UM zX)PjH0}iDR7dgd}os_^kj$R2%#mq+d5*ggHDK64Ft0&5!@RUaQjT84Uj}j9RMPNtT zzI~>gq6hy8w4IaPtIfv7Rs3=MKx^uZ6H zGLo}F=Wz%ZX>a)exW`G&2_-**kuwG#&9H!wf-8E0hu8M)T$rbi&pd{m|I(@~ibmhM zNpetP(xx%=5-bH^aMuOSs@*kq=W%3AdEgD2+P2t+PQ1Y=ZrF?nmw~v}Wx?;8omQjI zIF@uF<{}jyG`lxXqdEc`cjn&^8j)Mn(((Q}%OhejmF#ulJtQN~4`PJG=zhe4vYEgK zG@+ef#18icO6M?s%aiorR34S5hXox*;!iLFEeIEgh)^XQfJQ4;0xNzaHv-OA>S+~+ zYIzv2IOZ~??NafMgRLksi-+3LarN$12@Z>j+Ui*FEErmZa{#2lSD0ID`(}Ud;kc)` zGnj*8Wh|*Gp#tVxQJ&m}^{e^i$-N370)c}cVcW!w@cZ;;2rl|)VgKgYidymcgWK!D z;{<=vVzgXl25>{|1iMaU4=)D;f-G-gUGJ zaPiWm2lKfSQb{FZ8qMJB#qC^GK3+rG<%-niH-RQ^PK;=(t8dMBB;kDpPU#S)zPx9+ z&sYlxGs1O0QrvVYNlcPi^)5chH$KQE`!U9^@kjMha!b!m_xIh~ z5NQG^{u3PbU^mglj8jNkHUx_)+R2MYL1q38Lw)60KX-|JJF;fQyN7JPwR`&|{$28{ z6b1s2Hga&;>K@6e!i75$0jB{oj)ch7}->aIQKCnD^poUrv^5~-# z$s-(5;#dx~#RpEex&DQ4XQZel;P`CT&lw>sLLxRYt(vq2rAj`Pz0PrD1?teiE;P3Z z+2a3QMYwyL?%ZIB%tdma8Y@6ir5)D(;~vj@@4!k_2-$2U%2^?Xr|u?BytC0o-FOV^{o#*rEu{0_pfkiITYNX_EEF>o*#H#bh=EwL%XOx69YWOP`@Kfj>q|@N zhR&)V?SGd58)b>cUraoS8V#;%G~%!%6xe#_Lm96rsC(woBeA$Z$DTwI-Cd>P$jk7mOsbP{0kb`ei(knImp@M zt+So`IGCPrvitNYokMBC!crg(2aFE<(V=Gu)6+^X+fm z(v&v^NN)c+uh|cVsuQ|}>YD<=7~x2ah}!@xzWt99cnwf@pMaKPD%u{YKb zeJB3Z-#J3;=7K}yKc_W8_o2jbS8M>%*}N*{)Z#CE*YvRd%#Ss}IJgvsA|p&__+vv` ziz-7mc~kAHgYG^%=?~jrDL#CE(U}}>fxT=vX5=ClI~6X~zF!&WhIerOHMr1}_L2g$ zh_@l-hcmm`@(u{AOyX~j`Ry@ehagFo{(zD85 zoSiCqOXwf}^m=ZorgTNN{5e}k+pkvKDmQJn<;{Iy-8{3te|q%uFjb&9B_7TMT~AB< zW(F;O@j=uQvP$~->Qs;INdc%-t2pHZ*Fp7V+PhmM4Mg%xAv4bgvhz5XnWKAjkWTg+uRD&ZS1NpiWZdTP9j`E$=J z9Pw2;!w1U7vsP1+wP&{$>1nkSQ0vUkJxNU1p-L!xD|=cb+8OKiy21U+eoOIy4R7W& zsV7|jo{Pt(X-bRjQ*YonKC)AN?Oxy1iS*T9LN>=sw$DRW%x@)vEpT|9;o3 z?9LU5o_(1eFl+aPRVOlIXxeoG#e*R*!!10pFj^BkMjyR;sUn{2EbSFGc9;t8H`8ia zl=!WQ*`~lDLcvb34}(EFmbd=R`m{ctM(SD6cDeOSmhH@tVeOI9eN(XcHW_4l`^t6d zrc_g|w6To~Lv;OjXKZM^utRM?t*(`Fv~ zXRy_WBO9mks0cXa*Uh00CU;TZj9tTxSy4@Oaz)YOvPZy62P636^?q5JH;@dnY*Ua& z+mdNeAqkiH-n)r8P`jJ=X$u~yB``KG!r}SFNZxzN=L;VD9f@2LF5=>OkLm6@K)EBy z^2jFdJIC*A5%%)@al4QRb;ifHM{r*ZdvPREpm^xMHYXM5c5A=er7C*?c9a7wEjl)D z5w`~3e=%St4|2lw$*Y}5Bu^&ST?fC=b6Hh^sUi<)9S%p-3p;kiC`VSr(5D0u=hWRkSlY<8WXNMP#Byg?WvpnVOeS`s6CVHF$l z{3N$Nkl&p!^L45D_mpMaOG|UCo|lb$M4swT4wg=`8qlvBx1?Tquzv9F6^ZwhGUZoP z!K+xIW!IGG;3GIFgi<2;Iq?j*plPu-&Heq`ujDK<7IaJ!cMfiOqyBuqz)j`{$sHd# zr>bV<_)p%&T~$FemmaF67FG`3sxOxV6d#3mh5SANvdnynFkd zWCHfw>aj88D0u@Hw$(ORJ;Ap4d#>NP4%uUBlnYQA1?!nKd$>N+(r4O_y!2VFXM5tP zAg%;GQ~3PZ&S}37CM4%+JC}i%(caxS(8bK4^>6m~9wm=G7d@Wy%_d@v+WdE`zZq_d z18kUs-~FQ7SA4(Pn*57r=$fa_;k0vDl?j0Q09-lFR!tmoN{Rd|BQ)mzw{@`pXoApG z<><|Z>UGhE?K~&OAqoH~!TZme{@6bLa|WvKU-uK_ zmW*Z!Bcwz{CQpazl^!W(dL=`WG%P-KidT1k3(twJI`AhYZaK5}`5ysDvGY%Kt!Jp}$%642Q!3aB6m7g;I6NU=h zR2L{e@h7Busd^0b}xi3qBYoI0cBk-nK}QF#XKG?4Z+RTIgk zZGyvfi{7qRnYNs9g;Nf4gPuy`cb%2m;1b5E!OCfGp6d@UQ!wJ!Py*ORvGaQD_Y|26|48+(AFIP$mLU6Rde>!xtqa^O(l-1VA9M}x4HQZ>i|BReD z6=z(y+0gE54fk6T6mJzbLhlZaI1hz>w|>T&l_4L;){wawtB^k|jM&jZ?k&<6Y(2C3 zZyn;)b|fscDV^f!eRFvWR4vU+g&t#i>NDjb@$;x1c3N(b+8<$U*gSJk@wsKQe3 zD0Y8$^$SpP357-`^hyK~S8X~Xy=MQNkgpSWJN-sVrplk1(K-VK zG_r#AL#qNAxlr-8arb9Fr|4J$BwT>lJ65@tj0<0`s$l>r>AXPMJ*fF=6zt*f8;XXi zU3(9wccXB|kAOjIhgl6OgbC|#4sYhW)-55&;+E$vETZYJW_N$^C32}bT&iPwSk;5tM{aU4^mM|VyWdXPAbu&83!Tq#oAA`uK~^3mYJz462L zT^jkFQ`evplFBtWc2cTNZ>6i}I62}&S5OMWD$7l>eL3Z!5-;S;@r<4O)z=0w(`*=w zp<9h`c?X8VG6>r>)E_RM`;8Z0I7Q;JT<1;JW-(=Le%K7T4oAF=4{A?by594*P-EYU zzRCokn9A~x?>ydipH*{EO>&q$mDk8;INrWAFL3bYoiC%-+*?G&?;r6mo_r){ESDR> z{cmI1)T!vlum>o6#_EmW`^+mixAflWIQj9#d_gDUu1fqo^O-<#U~Z4x{8~|wRl)S= zHMWj}ZHn|$-VaVP^pu4M(*}jSxQ^o3mGu#(b(%`lf9=I;g zdUPKfjwlNjaR$mlD-w!N)Sp4y3^A)aak(v+fO029$_noHq%P};?;W}Y?MmVHPnD8P zH4Z*iYP&UX{@Iz^9JA016}SsRmh8XfDrd@v$RT@I9r$Zy`T>va?6P%RADHG3YU?(< z*C#yHDQ+gis&DNaQ^+r1}@QCv5f((yu#cG6>si$)Z(@6yB zog*AuYd@gAvj6;q(ngM=$Zd1anI)-wWc9^{fwE=u8Cv?M`;NK#&?b>?pjg$WVVY!{ z4$txibgmK9_w>ISXc?_Lk6(Fn&m$x#jMW0*pxJe5ns1e#SDx|)(zS?=nwuGBo2hw| zw`-rhxSXy(6&1>1l?km`VQi6^28zFcYN)C5xs9eudB|f}fqb5XMmgVcTph3L^93dj z*7BEi8#_Vp?;r3OGcRrZyC5m9O61P5fuDX=R@_-g%CTjEHH_?36Ga#J=69bJzMXim}6Wxlu!~la%zXk10nuVMNIW z+4zMG&Mn`dhVaEK8!%=jw162g*)Ah)QIU@UYKF0iaZx}#cK33_E2B5O7!Ra&vSY}ml$ZVTCR7wh?d{u zk{g|CBK&7^2Y3`~wxE!mtgOLxPlyBrj0An7muv84UPFavuBX^q&yU~v|Mhx|Iw;Ah z=8Z8u$whU0cB27Wrg}2<<6~CJzM@sL+=y%_{5+B;UhD&S+um5ocA* z4`p}@5jp>TC3}Gv3svBdpdIX62KwIzE%-pXhYM)rBW%BcpFNgwu^@To8Bh>;oE7f( zv3<$hKhG&G7TCVE%IvJj4Oa!HWR`R27%)aIEw5O;8ap`a>{(smKi}>I49O|_B9rZl zVZu9HA{9dGdmYW)5&d+h?X#599Tpht2D4eE-4}VGB*-19#nzi*E*MwG&F=0oA}c0S zr8CU?R+ZJ}Z6}UJRZa~FfzgWzEv^69YEbd-_h~{;!>3CXtZCj2-0WN~blC%XM$bPH zi%g)YyW&~gGUhL}34vq>gq0oal79MHv_cb7sS4=9k?)6M1Lz?(Ilaldy9lb?1GFTP zG}@bOW_Q|ue>QCL1q;#Jo*p48=RvWwUxIay@KIvnZAyP7Yy=n%m9IdhaMZnk?_)F! z$^cBA<$I;l_T&Hdg4Gi6v0sJUe0y#cT!-&@z0&?OJ3sxK0G-%dPK)EH`o>u;@~=4Z z8&y=Tz2t8`u+D)l>!#}iixc-=7t-Eh^5ub_hk$+*5k6Wsw2XVnzl?bJ=ew`>HmLr_ ze!T$N|FQKy+1*z48WId7*OA~}n$l|`R41|5sOfwDTgvQ6i$1qJVuKC`tTDJGA(BY= zho*sPiW2lq+1~K^0_Ak`?!JE{{k-jr;YTB!7nJD)tlJTOIs$9Rbx@PrmKXzlPJg}^ zxBvdUTGaf+`K28uiT+L3xfY1v?us^WeM;b6A20hi9ZR~y1s_LEp(I2 z>KDME%~d2shHPN9o}oRU328l(lw6qRx4=u z@~2dd_&cOP-xfG?HbhTjb?;o~q~bjk52?)~apR~-Y_Lklw|4eM3`0`lJr zO&g}7FBQ^`C>h}*{r`N2wp)=qI97u+w2B&cwTe&fA1sDr16oW*@6vWh)n-iGeown+^*ZI75H)f9g zW;mWugO2hTa+2^L+4S8nKEh2aSi`b8^+noAC3a}IB{OZxED^{L8Y1~P*r>^=;xJ$x zoYfgvdeRXKvJ(8F1mhn(T=9dBdr3d#Nzu7x#13mQKCXKH z!0(yZqx^Y>?phbLf}5cdfWs*>j55bFJhr%jetCEWR%CbQ1Ay2(5SEOKi)RE z&ZwK9oZ~U|%Ss5vjZXSxWe*=duej)J@$t4I?~>G`0fZWx#N9YwSa4FM<@gcOOE2tY zR7)%1$s3+?AruXLV6c!JbU{brus?C=g$=UuVJngm{ZM*@sd7nB?pzhMane~<)Qo_d z`|D~iOv;|*%$5{F524Ew&?*`Pp9zFvpx{qAnq;Ug+m59ipBPui#gQ`L3pAsz)3i#f zd$(WpJR&>I`j>YqtVSs63?V=KV7~24gy|p8GCwz!;lJy49oAt3NEjZjSEuTvcHQkfb*ZwFpM_IMBB#sXARbNi zTxuGO;5TABbhh+_J#G#0R_hv|5f#%#oim<%QeULlKB#73vUu+%q z+vl_Jw23|~Y>B$Vr%ziiJ1&;IkmW!DR?aHJcB*5cwF-DNF1=oJ{8cgI!A40W{ha>v z-F#p@^oiTWrk!(1?@7cJ6~lj7I(9{Ci3zEGn#33{nJ?EqyHbmzCb*=p$-JugY6~KE&`Qk5 zUjR&xN5_Bwo-jHQne9>DvW_bIF;`UOufK|1F1y}uUtMJP*Gz59^U6%^f#*2t&`9|9 zzzAtBwr*o!RLAa7ne%f#u>ZAG5kSqCpnB3OiLJ`FpNu@hEJ*FE6p-Bc{Ir@~w31WK6&xxX&{Y%E}ovBk$dF2W})Is)Y84p0{V5)); zQG9g%Fhb&ke2@P;QuV>fzdJ(+uRa(({0;PAAq3uhDy0|1yr}-ip>&5cr|PzKM3Eg_ zo;h95_JaP{-0*m`*Yx2@4kVr2(f@9mXd-nEFh|Krp7QF;uC|7#=yJlklAh)piI&%) zjx0+>4~GK21pvq8IO5pga+39U5_=rIwC}3D%OrGk$5meh8U22UjXFONT}P|!4{a_; zLeBP-?N^y4J0rM}*_@lz(dlpf<$jVl2c@gAb*{QC=jVDswpEpj|D*?(GTrvg{e%9D znyJ|(eKT2>KvdN_@f}Ie6uIzK1AvCuhnPc zJ+^|jq^by+IoZwuZ+14R9ygXPt@SUcM2#QM2K^HGSX}^j-c9YIgo*z4QQ+i;`|CB3 zY4J-ig4B@LYuFw1Y8Ex%ch*vF?N|5M=X6b|D8A`fk3)wFoZ%7$cVynp(6J?;1wmM` zsr|1X{PfMh!d4Yv*cDW?1P-Aj<#)#8ec0e=H>>g9=qw7HFi&j9eV#eG#cDo zZLXjYos2Wq_UksC)ugb4TYr56UMZcL=K?8PQRG4*q6)(ch=}Se+}$fjEV(cW5?J`Z zCfvu#WMuiJ`~+}d@Imk$d7hMJ>sp{&%^z$DNLbkZ4|qrqBe2DB-~w>zX#)=f&tIS% zm||1_^dCFM)P>#IlvJpIooZ z&pcz9m!ZijuzZM>eCxN5J8F%lF&+qM`?oggPE_~wE;%-!U++p@s5J(Lm)*_}1`W4Y zOg;3l>dub*7r^1;2o0c@?Fu6V3Yd4F4qPo}zAEf@12EXb>St`}e=Edhmkdl9Yma{2 zv=AJ?efpEmWhPZKe3*FB>Ho8=lzx4n>9ehtKmO+VspbVc`=`9sGF!6(i-AeRfq~&> zdaS^cnOE(Aj-O*C@2kc#N1SD6fVOYgZ;RW&wZIdqfp%NU+ROeBZOW;N=$*Ct+&4x> zh7Su*x;;FXEzC4Q5Eu#TZae^Psd!KftYdy3<713S_^loIcwaa$Kp66pHaRaSesw}2 zLL&O;S2Oat)3Py_l=IPPDn-XWhG7(Pr;}sbxYS(9rifFZqPN zb52O-Umdtu>aDKzd7$SV^5*nA0cG|{ey{V?5m4gKTDswT=#?Gv?{(eJy$6L(Hn8le zom|2$#xc=R>?Z@zYx*30CmWC5UWRXU-6z|}eFF|gKIo2_ zdO-gqe|nvk=k&WzGv2RWUATWa@H8C;!v;s-SUkgwGM+E@qtuS@00XD)`~r~sGmUN< zU#Opb!{JPbkJ+bd?;|e*Q*gr->wO--4jXhbYPas#ckI8 z3+=Bk*VsH-KYekP<(2o9XMvg+Y#RhYmYj&=mx+&AD{i%KL%l*U&}U)0qONWZ<8u20 zlzia-<=mvzS`t?A854cZy;?ba{jpztuR&|^w);0d?q028v5(_?d)>zO_paqL|J`~r zyY6tU1F*4Sz5n}xpZ}feXUyquddsqT^KKbkQRlrfx_{r^?YN%|(qF#5eA=Gh@AW-7 z4k|6mo~84EQ}Io$Xsdu){+GSifuY90ooST(p;}rdUgh|I-pbR>_uGGD*YB@twU@kK zy%^;FqV!F(Ui{tPa{rlt+NC{5GQRKq{$=v_?}{xai{^g+&jfP48L$=j|J&pL*&lQ7(b-?i8^D}YR*#7zw$zw8B_6+KkHtBZro@^tlcS?83{1OTU3 BMjHSC diff --git a/assets/images/monerocom_android_icon/mipmap-anydpi-v26/ic_launcher.xml b/assets/images/monerocom_android_icon/mipmap-anydpi-v26/ic_launcher.xml index 90f958096..00d924171 100644 --- a/assets/images/monerocom_android_icon/mipmap-anydpi-v26/ic_launcher.xml +++ b/assets/images/monerocom_android_icon/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +1,5 @@ - - + + \ No newline at end of file diff --git a/assets/images/monerocom_android_icon/mipmap-hdpi/ic_launcher.png b/assets/images/monerocom_android_icon/mipmap-hdpi/ic_launcher.png index 583765d8f79ba95b8e54234bcfeb9cdbc9bea766..1785f4b05b3882b71f670dbb6848a5c64ff9c821 100644 GIT binary patch delta 2454 zcmV;H32FA}DW4ONBYz2INklC39V}cEu_(I%jqNPzN(W16e{s4=G?(DXd?Y8@$8E!2lW2oUyl;b=>`$huLwW2|7V2O@+qSLg1Y{C|wup$XA_VtIa`G&WnM~$3mmK{r zG&)2sYjSc@4Sx;}-rH99)F(p^mdfoi}OykTb5s}r``Ic}?MuiI+tNn7=d*=o<5wi?Z3m1P&t zs}dZ7lF8)b$QqTPM_H_z1dSV6wL=K_{jjC(>@(GewtpJxy&ZeGzK~Iu z%Io(e47K1zLw#n4p&s08suzyi>d2(+kgBg45iUWiku?%QBO@cLSgcZl5bBT!_s7>P zwYbYrmk0?h&xOMU8#C&ILfH3*Ox6E}tuj{e?}UUyP=9~_6UbT@f*@u@%%t^IOTBNi zQ6zL!ynjp#W9#EBcW7^-(H6iKxw2y&Lm z-JDrta=^vn_@6vt69FH2TEAbC#v30wV6A{2=tiK9LrpgAiKL?Q>&hM?4GTP@rgJd~d=+VaV5hI;C# zrGH*Gir3R|T1=M`w;&U*oh~$9y36c-hulHL;Bus_3iPrq$70W3%+%@nU zC*}Q+Xiq}&CbV(8M5AM;bAHV|4>Nvl#8%fy!in~+3h#4t#81#`l6z1`=|q$QcmLUx z_5WImBD7b`>i$7fUDr{Z7EqTh74!PrVSh`#=}83nO|-9q4BAEf1U(W^doGqc{_j*F z1XHC$%$$IZ7!%%nB2ZN7L33UaC%j1J%_wnhIpC20axhe$ z==cWWgyCki<(@L^9Ms~So15){NaBhWK>)57Q6FBLfC5P!DA zCY1OvOmcoAQr%Sw@exGyqNLD;(D6~x7CMH^p-ysr4w3A(ZZj}RS0!@hb#;60{kM0S zl}0cSA3-O?RA^r5g6Mc?pXr>BFgRuR^Cu2j>d<615J`|j)WSTk$rE&$Xdv@T2ptCT z5k#Zv-HGx9(E+4Q%K13-Ydz_}>VHEyv!l!SxiTbCazG9a-b)bpd$_{16yhVOOEO#X z6kQ-MxbuVQ96>{J^yWEekh|6q(S*HW^tpnr<+@0Z%DJKqU}B=Relockm#AdezNfFL)DfqSKRt#HpQK7#%$cb$g0PKp;~ zz7WItN5zD^KFdoGzQ;=vfPWlzEzTE5zj#}LAg=~Jy#E|_(g!6`yWVFT2f-i9mj*QP zR}5R~heM_VmkbDU&xIs%C0BDGhwog1Cgk&9O8)eN{2H!yR)F{jqDS+IZRH69?3|XX zy8n?U$i?;Ix9;gToerb>nM;s9w+e`lAn>hSg{U(X=8GB99dzfg|9}4UFfad)1OkpnN!&N?|iWl^; z`K>CF1L7qJkhAzDjDG-A`}B6hsmYx6vbokNer&283zwKrNghO2?V1&H@k8D=Y(&IQ z5TW<3zF?XFNkk;-GIu_u!ogEn_2gm8X<-oc?hxE7k&G@R4^nxFK!d(3j(v{YlrPCS zbQSb#3W4|u0+b73p7&v6kc~dJslDr<84yPKpoeun+a&eel7Fs3bD!fEh0LRqk@KP2 z5QI<$70wRB=l2a=#@EJKKmpYTqpkO_Fls&VD)uqlkjB6aI_9%Z3qIW zI-7yI0Di#iXnsM~?Y*Y@nq<)57&O)0J5A?FG_(yrq|ejWxJCRMWa`)DgW3@Ub_Hmn z#RW+Ec&Fhs@_+Q}Dudb*1lSoxBXj|3g%3+QL2pUFt|?G^f&jf7ze+z2(Bl2co2v&c+{m`9Yr?D}M#@9(vtB8Zw=Xyuzyf+#tvc z@+F)&H5d_xzaNy#bEx1+5O3IQI9c;wr6eIK4C!m8LRAQ=`hPWCj2XEG8inT{hAs7g zL?G(1Z%U#_Tb1_e+9Q_JDmh%;|7f^y30jS;kq8O5xy6|kN!;O}O3m49jD1vd&l(BMD@ zWVvj?f&~}JF`Q|Y8bZ=+(Wbd_oF|K3+Q>kLyez?;a)<%j(*e!V9L>=j4Ke-)k=Gga Ua1XYdBLDyZ07*qoM6N<$f}G69iU0rr literal 5353 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 Hu0mjfHULi7 diff --git a/assets/images/monerocom_android_icon/mipmap-hdpi/ic_launcher_adaptive_back.png b/assets/images/monerocom_android_icon/mipmap-hdpi/ic_launcher_adaptive_back.png index a025d330ce2dc31fcfd5e198135dcab8a444dca7..5b0fde82724524a2c88fcf95e1426e76ec35efbf 100644 GIT binary patch literal 509 zcmeAS@N?(olHy`uVBq!ia0vp^i$Iuz4M-mPBqq(kz<9*d#WAEJ?(L<8j0^@m4IBRb zFM0j_fIz2gTe~DWM4f!a|i9 literal 932 zcmeAS@N?(olHy`uVBq!ia0vp^i$Iuz4M-mPBqj}{7>k44ofy`glX(f`xTHpSruq6Z zXaU(A42G$TlC0TWzy(E?@!8>Em^;FcaxIiIJCV@L(# z+e-&|85DS!4HN#)W!%W}y+Ax;O2xbC!mvv4F FO#md*#O%y{> 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 literal 7009 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 diff --git a/assets/images/monerocom_android_icon/mipmap-mdpi/ic_launcher.png b/assets/images/monerocom_android_icon/mipmap-mdpi/ic_launcher.png index 50e1973f558ee3215e92570d0b7586cd90871552..12c31ef57ffd047be666d04d85af7b780edd957c 100644 GIT binary patch delta 1668 zcmV-~27CFn85FQ$1Vp3~j6zUUA zG}gq#CMp_@&uEMq^_Rvp8h&VE5Th}ssZ~iJ6{1xhUE0Ey(jq9eKuak?kpZ&vlAwqALDq4NPiBHn`PvvywVO_G>K5p zXKRd#k9#8io(Wt7%*hgX@0otwe1|gu$LYYT!NI}KL?Y3fO(Z$2A}2RT-{E{{n&xU; zD7bLkAQp>#1!@yh3Xo*7^!4@4f`BewgrkOI0>`W%d2fx230~bbH8oecxeggPnag8y zbMuXcVMLPx_M}j^*A+4uPX^fh( zt=E(t5mTD_OgS-Nis3VVIJgCrmzOVca~(1i0i)i5-grVbb(!+oU%K2L)?{8tlUbYN za?!@PT)HVPv#a8AQ>`YC|E|k7M+|9$K*RKYj|#Vd(tpy@#cr-c#@PzsYX5M|kUQ%% znf6;;CRV0L4sgR(P2SzFOZyqq^PO&FRKP*3;$ypXnewZbD^0p+VN6c zCMR=-$5-K6ai5jXh=A`pjFbsG6>~o{!-?ZIru6%ROy) zNoPbrH+=q%uz%=~{0A+%oWe?X4kV=HpdpKEG=I4abzu5NyB5r@(xeDApti@fR=o9; zY3+_mSVdq0DzTCzs*)$3-)oa^Mzvj5uSsr-T_TwLs}CE)hD}BUytvmt_8AK82oJ7& z;m+a76D(pgu`_E>{8X}j2t)wm`L^x;;q(3h-HL67&BbULp8i9(j_N#uPINCs-nvb* z+JB1U175-^0uitu@p^5QR{#mIVT(W@V}1sRSNGU%Lkm^s79zZk^qcZPgJzjQX-E29 z2t+^~+~g9URb`UWBI!2#n*z3@`(#D^8cyTRnY&@1$NKHQhXQzxuB8%I5r_b;YM!#9 z#Jo`4O5UH5;B*^D07b=NkKZ1(ZTBva?|+Kh7D{oBfaMKiB%l_g)Q})pWodP#16h|o&8>VFi# z&nSX5Vs5f`as+Tk=s@YJa9{$sip!JRuHycN|10oY`*e8 zErv?g4}l0EK5sXCJ4&uHixNeCfeP#AR&KESybrbDXup@N9|9Aw4{gF6pISih@o*>V z0iEYZh*?r&`@A}j&&V$zq)49O!+&s639AT90PT<6qe{xbB9IQjZn+cx446_13uUrC zh|r_keAsGOZzuTqQREbb@F6B$Ll>9;;s7c#`+b$X0~WJ)kOzn0N&{G7({(M0vnBZ+ zNl&-peD+Pnd+Z!iiDyIr32|i^$0~U@STop_z78Axs8zT6r6+dlXh*zHW`F$u;YQn? zRPuofAZU~C9Y`HYXA3$PtysNZ-~xy<2#+_gy6S443vNbO9X{i|S4IR7{SdLTO}E~< zsboe2h9i3-cB$$;GAe+eGi`2{p`Bopr+)Xj3K-SPUAjxfaYG)3 zUDBnTw+<>unonbVclt@2VShd7yPe7pZUG~Dxf>3L7mRcVR4~E$@WT%DV?3d~)MU37 z>_Yh-ln%zmj)K)|Q^75utgLK_o9mDv$sY~Yu3bA@*YzG=WR8;`IKWLJkw|YzNy$8N z4242o0UTogd^5GBrDY97@H(N8Yz^n$nx;u(W8*q-nq2Z_Q z?(Rr58a)a1F&@Vf&OLj2dLngob?fu<^BF$;-8!`Zj^u=Cz}&*Z!lf%#tazxnxHv1| zy_aE-3pu4F?+i{XDk_?SKl6YYSwSl^3%gs}kt O0000Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031 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 iCODO-jGj=ueEJW(KOR diff --git a/assets/images/monerocom_android_icon/mipmap-mdpi/ic_launcher_adaptive_back.png b/assets/images/monerocom_android_icon/mipmap-mdpi/ic_launcher_adaptive_back.png index 9f0bf490744c992644b388eab89dedf8bcc57bbd..5d25e42e7cf9bcf1d30e3da506f53494485d87c1 100644 GIT binary patch literal 327 zcmeAS@N?(olHy`uVBq!ia0vp^IUvlz1|<8_!p|}=F!Fi2IEGZjy}h`Rm%)JJfWg0d zsc&%?Jig5^-Mr+C^pDwzhHXbB#F8U=Mg&8KA!kZV!d4T0U;r_Ay85}Sb4q9e0M-L@ A5&!@I literal 539 zcmeAS@N?(olHy`uVBq!ia0vp^IUvlz1|<8_!p{OJ#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyz1gS-^~7gB1R}eM=6gtku)SF{Fa= z?d3*J1_hoY4yFI+uHNDLz{=6%SM@#J>4pVHOC0ty9!%<2n2}(}Y#75WtdpkDmYvvi zl;=o+uFr-UjS}lxImL_x4sSI$n8cQ}Lrg8=j04a0LoD5r9S@^MH4zSoqfM~~53*dD T_VaxrC}KQa{an^LB{Ts5BU!L= diff --git a/assets/images/monerocom_android_icon/mipmap-mdpi/ic_launcher_adaptive_fore.png b/assets/images/monerocom_android_icon/mipmap-mdpi/ic_launcher_adaptive_fore.png index 2230fe0eca71a92a7367866f24ce9e96f84d7b4b..28bbd57b881e1e64e619a399ff83952149765076 100644 GIT binary patch delta 2243 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 IrSI+k15r?6&Hw-a literal 3890 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≦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 M07*qoM6N<$f))61=l}o! diff --git a/assets/images/monerocom_android_icon/mipmap-xhdpi/ic_launcher_adaptive_back.png b/assets/images/monerocom_android_icon/mipmap-xhdpi/ic_launcher_adaptive_back.png index 65a3f3a1c9554fa5f8ba06e70ce0bd821dbd9355..c4b66dc58bf56a9d50d7315cd062d24c34e9b4ab 100644 GIT binary patch literal 677 zcmeAS@N?(olHy`uVBq!ia0vp^H$a$!4M=t>=)PrOV9N1yaSW-5dwY2yBZC1?!-jwV zOI|N;_g0w~sbHMX@Xt`9g@;YC+3`ezfYB&(G#n^N1PhsYr31S!YD$IylOKbptDnm{ Hr-UW|syexb literal 1397 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

LhR)(J6Sw>s>O%nW>lpVQ+ R3uXU0(9?!$m221q{~zC>5Rw1@ literal 8996 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 Y7p%wTseYEQ|Hn{KkWrDYkTePSA6}sNX8-^I diff --git a/assets/images/monerocom_android_icon/mipmap-xxhdpi/ic_launcher.png b/assets/images/monerocom_android_icon/mipmap-xxhdpi/ic_launcher.png index 1ad794a7b8641460e1a437e3c228ebdf4d760b45..2ceba55ad2a59ebd338ddd9ac5eeaa1ab73976e9 100644 GIT binary patch literal 5090 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 Hu0mjf>;tu) diff --git a/assets/images/monerocom_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_back.png b/assets/images/monerocom_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_back.png index 66e3bf6b943013dbed0038a974fdcbb721cff609..75dc0219d798e9a16c6b26138a20c88be3078fea 100644 GIT binary patch literal 1017 zcmeAS@N?(olHy`uVBq!ia0y~yU~~at4mO}j{44ik3=GT%JY5_^D&pQ=G2~@1;5o42 zllorI&~H9o%dp?br9nc;fk#lGjYGhhr9+YFhyY_!2ZQ0L@MxHfCWwK~ a4SF@p%dC1en zF{Fa=?UhDO1_c4;jo1H{haHqwmQ|b*{XDmafsu(N%~-*qfuT`fp<^D1W?{J~$|0aI zp+R966Hr!2z$F|g@4(dbf{TSiz{5cxwh^d{lVg##fP#Ypqhkpx6AOomLdUvM&7%P} wnn*@7#%N(MT6&Jw7^Ai1Xv=^qO{oK{zJJ(Set((U0&3NHy85}Sb4q9e09br9WdHyG diff --git a/assets/images/monerocom_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_fore.png b/assets/images/monerocom_android_icon/mipmap-xxhdpi/ic_launcher_adaptive_fore.png index cab647d0c3f358e6177b8fa2322a51b9e7a0af14..e078655c97ffe074de668e0b26eb7634c2ff2775 100644 GIT binary patch literal 8688 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 Hqrm?Fdcn@Y diff --git a/assets/images/monerocom_android_icon/mipmap-xxxhdpi/ic_launcher.png b/assets/images/monerocom_android_icon/mipmap-xxxhdpi/ic_launcher.png index 43ab3ac30bc4ecdb0bc5b063e9ca2881831c4462..beca2d29bf24e223731304270038242f6c596649 100644 GIT binary patch literal 7015 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

DX^)MkFzcz0G!i4E5Y=p5HILWhq&adhlr!F^Is? zoyzS^H3r_^M=|f&Rr4yF#m~2^Yd6Z6NWr_}!RH4c>`PWPG8w=996<<0pVH2=za3%o z$t*Gk`ua23rZ)FfT~t|oPzp_FlpJ$B+{!&76OuL_*B(#I%$6_#=05AiOT@%V9A6+N z9lnSxA*()RQ6r>jPvq$~YcfcneXA(sxQC3IOZ%$D?!{w#?kj<#H~580zFtq@UpxyL zMeN7UrWP(X^X2c3(=-{M6|l}>dck)}NJKTg&)?GUW{G4%qbGl_KH%aYvg294Zrt13 zQ%9Sik&Dt)Nn)a+P!(^2y;)iAf&DC5oyY$Mz{fqYa#sia>;bk@p6^@2b;;akxw6Nr zel$8%FM0G_6FRyK#8DC!HAik(+l9-X;^s5t3@3PUGN~$$qj%R%(iHwuFGLgnQDeg& zr0Ge9A8k$=r#wFVmgY#}RtRe{LYnhI6?Ex}xg0T8{V^e$x0h<;aSpHf;Oz!JzP{2a z!rF0Z)FMQjtZ?1U$?0U}s}wox)?FOgdx{PV3k-Jzip50fc)`b*Gz&S*(p6)r% zRv9|~>14 z&deipw|=nxA-zczbik!k@nHq+RzgVygcKJ(b_QAWcsA zS$uE&)W<=!Lw~Tg>9c$LC#s~5cy9if^LV-*iB1*IU$z8atK%)Wf_pr5jGjqQ{lAiI b$}M3XqhLiT=g>0l0}W7ns;yk3WEuHCxwvsn literal 18470 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 aVhm$-vpB008VIa_7(8A5T-G@yGywok5_;wU literal 4312 zcmeAS@N?(olHy`uVBq!ia0y~yVB7%09Be?56MhC-K#H+A$lZxy-8q?;K#oglglC$s zF9S$|gMqO0ZUq)atA zqxUs66QBr(gn>OsKa(dT^RzX-89)&MgM>Pe2+JfUHl4`X7eH1e9QXqg;ZR}aiP&Ve zkP~R|frg(T5djY_i47^aPQpNgfevFHb=YW#ji#~DTsc}?j25t?Rnll(Ioi4yZI6vM q6i1uZqn(k_Ueaj4k|sUz2TU)@*<%i~?^+ESRq%B6b6Mw<&;$SzoI(r$ diff --git a/assets/images/monerocom_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png b/assets/images/monerocom_android_icon/mipmap-xxxhdpi/ic_launcher_adaptive_fore.png index a790c3a744e0122930804054e0a3fde5de75c4df..255b1b71f857403ce0b7db522655bf655f710047 100644 GIT binary patch literal 12745 zcmd^m`9GBX7x#r5cT_6LEj3CadrZhyD$1^GV;yA~J7qGAv9-unvc}k3kbNi1pt2iF z_A!RC3^6len2E7Gm+$lZ7tg$2^UF1^&-pCpbI$wyK1cL@<9o+=&hh{Na7<5E+Y|uU zDh|K@a)D2}jju`pfI_^U_AT>3IF)oHIC%_runzzJPV4q$zzJ;vjBupb<_X*M$$%fG zr8Zk(Ta9%_woO*0bu~WT<)~_E-UK6v=+`ep5btxAcvkV>iIcJa(u6fy>C4+Uxqrbm zWUyGg7=9tSW@oM0V5NEOqj|Q-dDCBzh7Fs@bLeWbxMmVT zVl803=ibZ#jVU_Q+HfAZP<=e-o=C6jOlycoC?d3Lm-fCDJzMi=YDFkH%c;4}6pHoG8nQ77F?*Ad=1DEdrwYJXD9*wm5BRXdqHN&zII z+IN~fa6zwhi)Z|`qLO^EdCQH)`?zI+lA!X3A%VjRJa?)(H#=5GSoR@RPYiYUl%!?q zog*y9V_8odahd>7nmoSa03qbFjO8D=X2L0DzajBwee*XeHJ9tR0wZ=Vm9JSq^~ao` z-#vbOwDtF`_NGud0k>N-ZNbAvt6RBH>FGuOnCSuxXI@#X$vMn@-*Sbe;UF%Ty#+^R z543lh4)Y!6xPkzNo`+VLF|Eucp3Ed6loZZgz9k0QS$MT$YD#7@&0;k4`TiTlHD8 zXiPocpZZWR=L@6FU``nN@x0B?=BJO|H0_qz_~dehe@^@6f?zX{noha1kyj*ZzmYAY zK%6ErT>6TpW2*uxMg@Rty(Mx90`G|2OMR9+u)d}H7mIUX;wp;|x`Cf=GbP2}2?8{w zJ)}#9W>lhO!XVc|4;fiBEnr7s0~~gCA!YPplEEvofl=hSfhV<$z?_7$mKPpXcUNvx zD1-dKR7A0-3pwhxM1fh{xe9Lm;l}w81nb@zwXmi-W8?apFu<)EGF8O==2*jEdRO!$ z$0fb8z?@%A^S3v6tAkVbR5`RV)`^;ptIsPi{!OQ~Tma7ft8x1V6 z)l~ua&r+VfsVPrGI?=z;F3%V?SL1R3t>TT^AW~Rx0;`63EVxxOErEfRyRjX3JE5eZ z@SU^(Tg`29{I3`r?AT3M@0V}!lX^WTH7}U(;6j|G1Oov#B|Nl|3}03i&&pgw(x4O*u)$B^8i|q-iN1XIUtT+d zOxqrf|BG^q`7a#7_}LeP54W@SXnL7<#< z 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 literal 21803 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

2G#r9U6*x zTg8D4yihvSP-ZV5H#!MSV%p_28iHTR^utp+@9(PxM*Bjes6!|Gs;>j~3hK~_Svxy( z;jo-Sd2sMK`GhDXB`u5P_YWs7mXC=HCTFHQZg)Ub%)74AdF)0u2r3<6=d{-(sR01q zEq&~+pc@BPZJ98vm85rM=n%v*sQoh*aVcBxx{B`B(ja402)TPlW6APzDHL^wZ3Ge& zicm<57{4eEAjF>B{U#S+Y>UfAPW=i6UzJ1kGWGM$rJRA)l^M(EyQXeUS8G)tCM76T zR^=Er0Sc4s+)T)!0hW_ZI#9d=u7d%goutogvIRz+9}r)pA*oc#S^$x7V3OGI4zj}Q zqC53&x>Eb@8?78M82EOfp9mU^a~RtNm*L+Rah7Lja`%N!a(&HoUK#$R4f4!|sLbs; zyUCW9yculuzG*g;9u=)XGGb4}d_cmOl`6SEt#DiS-o|Fpiys87n{*+5RJNO7?}AeSJ`3|O z)>OB~g2?YXOj$TsnlZt$t6gu!qj27)&q%;~!@I4xP%RMVO#BmF5C$YMM|E8F5oN2K zEz_rh*MJ#RQ4@N3#@0m!^Ys2MN$)QpB1P#nfkIkPQS3QDV=I+~QN_S?Q}n*WL53jn zwpBymT6_gsQj#H&6TQ7UC6%b1SJfsd(&gLI$`S*0F-`e z9=M@shXJ-KqLs2XX4Y2N4Nc4@nko;3M~OuJ+QdL<{Uxf+R;3!>0aQ~ZAWV$h6O52KThi=BhoOjcW)tFG4vMk%9`Q((ih0 zKmaPf>@U@Zr2JFeZnAj%m(}F?ai;8n7d*;9a>0Keptf=%{9DWYmEn#3Uh=(ktk&nr z(J8OTCs7ED^<*Jdn5QKbdb;KQ4jCq+@bcPE;D{Ak*ZPmW&9j4(fa%2f*Qle|D-@3x zbBFicDXxAL_r>ZLbRd2HZA3R;hRjSFRU2kablWK@RzXGCpPKh_z<^wb$;zFXqdoa+ zoH`;k^H&ejwxFdY+~(IN)eS8Z$Cb-XZ~L0hLulQ+_-T}!&yVjRys{Ph^n)0JfLr?u zuOjh)D4-DWjs5*>D!@uycU8MRvm-}pS(?O-5^5!KybE?+gYp%Mpk-ZJ#k$E(e;6^D zg`9oxS~Kg(6aKZ{n;EDJZEc(>sWdsD5Lf;!#zfVaxe1LQUH#n;ZGzhT^on!|(uV`z zdm0|=gcWsJuDJLbYuyugP;QA_c*uj4;`;Q`NP|;?p?X1eGESd><&tXi^Uo?(hE_zP zto0ayenSzxnd(34>6Z0X5<3iy0I=_?2G)pn=7OXw0}YH-U!Wpa-#F8ZsE~U2Ffc@1 zo%q_Zc@SE0A7yvy$kULL*e>jOwP6D7R?h*Z#C8{@Px`RY8VnT{WY`yzRJ6k5@NBK9bO4bt*y)7xQA4 zPNyp;JaC`M7W_M@ka*1j?g{y}=mPyyE_mv};5Xigh-g3nR`o^aAM2kB&uP-LctHkz<$KiJa;L`Mfe0nZCh3E2_-J#p@AlFAm|Cl5RBZ|b@Ohkf` z_}}0M!Us~9&72l)#6s!w+(aFG7y}>l#}OBt84gi zI1c>H0S;Mw%<3R!^_+ZQO$o;|MAjOMnXD8m{@K1p82h2-+HGq5|W&=QXSC-Fp zqKc6o#7txCiT}$KkJB*b`oGWrD)9fM0(zG=j+j2p)(N;$CiEFbrTW^&@N!M3i2njl C^h&M( From e5d99313eb72405bc90903f47288983eb75bc120 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Thu, 2 Nov 2023 16:52:47 +0100 Subject: [PATCH 022/241] Cw 498 improve wallet accounts (#1152) * CW-498 Call updateTransactions on account change * CW-498 Code Cleanup * CW-498 Add Wallet Address to trade to match transactions to trades * CW-498 Fix containsAddress to include only addresses of account * Handle nullability for fromWalletAddress --------- Co-authored-by: OmarHatem --- cw_core/lib/wallet_addresses.dart | 4 +- cw_haven/lib/haven_wallet_addresses.dart | 10 +- cw_monero/lib/monero_wallet.dart | 14 +- cw_monero/lib/monero_wallet_addresses.dart | 8 +- lib/exchange/trade.dart | 11 +- lib/monero/cw_monero.dart | 140 ++++++--------- lib/src/widgets/blockchain_height_widget.dart | 13 +- lib/store/dashboard/trade_filter_store.dart | 46 ++--- .../dashboard/dashboard_view_model.dart | 169 +++++++++--------- lib/view_model/dashboard/trade_list_item.dart | 15 +- .../exchange/exchange_view_model.dart | 1 + lib/view_model/wallet_keys_view_model.dart | 3 +- tool/configure.dart | 2 +- 13 files changed, 206 insertions(+), 230 deletions(-) diff --git a/cw_core/lib/wallet_addresses.dart b/cw_core/lib/wallet_addresses.dart index 27b5468c5..632eb1332 100644 --- a/cw_core/lib/wallet_addresses.dart +++ b/cw_core/lib/wallet_addresses.dart @@ -36,4 +36,6 @@ abstract class WalletAddresses { print(e.toString()); } } -} \ No newline at end of file + + bool containsAddress(String address) => addressesMap.containsKey(address); +} diff --git a/cw_haven/lib/haven_wallet_addresses.dart b/cw_haven/lib/haven_wallet_addresses.dart index ff6b6aa3f..eeeb763cf 100644 --- a/cw_haven/lib/haven_wallet_addresses.dart +++ b/cw_haven/lib/haven_wallet_addresses.dart @@ -63,14 +63,14 @@ abstract class HavenWalletAddressesBase extends WalletAddressesWithAccount + addressInfos[account?.id ?? 0]?.any((it) => it.address == address) ?? false; +} diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 75c1df89e..83219af5b 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -57,9 +57,7 @@ abstract class MoneroWalletBase walletAddresses = MoneroWalletAddresses(walletInfo, transactionHistory); _onAccountChangeReaction = reaction((_) => walletAddresses.account, (Account? account) { - if (account == null) { - return; - } + if (account == null) return; balance = ObservableMap.of({ currency: MoneroBalance( @@ -67,6 +65,7 @@ abstract class MoneroWalletBase unlockedBalance: monero_wallet.getUnlockedBalance(accountIndex: account.id)) }); _updateSubAddress(isEnabledAutoGenerateSubaddress, account: account); + _askForUpdateTransactionHistory(); }); reaction((_) => isEnabledAutoGenerateSubaddress, (bool enabled) { @@ -362,9 +361,7 @@ abstract class MoneroWalletBase } @override - Future changePassword(String password) async { - monero_wallet.setPasswordSync(password); - } + Future changePassword(String password) async => monero_wallet.setPasswordSync(password); Future getNodeHeight() async => monero_wallet.getNodeHeight(); @@ -499,9 +496,8 @@ abstract class MoneroWalletBase } } - String getSubaddressLabel(int accountIndex, int addressIndex) { - return monero_wallet.getSubaddressLabel(accountIndex, addressIndex); - } + String getSubaddressLabel(int accountIndex, int addressIndex) => + monero_wallet.getSubaddressLabel(accountIndex, addressIndex); List _getAllTransactionsOfAccount(int? accountIndex) => transaction_history .getAllTransactions() diff --git a/cw_monero/lib/monero_wallet_addresses.dart b/cw_monero/lib/monero_wallet_addresses.dart index a9da3d5d4..f74e7dd5b 100644 --- a/cw_monero/lib/monero_wallet_addresses.dart +++ b/cw_monero/lib/monero_wallet_addresses.dart @@ -1,11 +1,11 @@ +import 'package:cw_core/account.dart'; import 'package:cw_core/address_info.dart'; +import 'package:cw_core/subaddress.dart'; import 'package:cw_core/wallet_addresses.dart'; import 'package:cw_core/wallet_info.dart'; -import 'package:cw_core/account.dart'; import 'package:cw_monero/api/wallet.dart'; import 'package:cw_monero/monero_account_list.dart'; import 'package:cw_monero/monero_subaddress_list.dart'; -import 'package:cw_core/subaddress.dart'; import 'package:cw_monero/monero_transaction_history.dart'; import 'package:mobx/mobx.dart'; @@ -112,4 +112,8 @@ abstract class MoneroWalletAddressesBase extends WalletAddresses with Store { subaddress = subaddressList.subaddresses.last; address = subaddress!.address; } + + @override + bool containsAddress(String address) => + addressInfos[account?.id ?? 0]?.any((it) => it.address == address) ?? false; } diff --git a/lib/exchange/trade.dart b/lib/exchange/trade.dart index 3e557d39e..4eb48c248 100644 --- a/lib/exchange/trade.dart +++ b/lib/exchange/trade.dart @@ -27,6 +27,7 @@ class Trade extends HiveObject { this.password, this.providerId, this.providerName, + this.fromWalletAddress }) { if (provider != null) providerRaw = provider.raw; @@ -101,6 +102,9 @@ class Trade extends HiveObject { @HiveField(16) String? providerName; + @HiveField(17) + String? fromWalletAddress; + static Trade fromMap(Map map) { return Trade( id: map['id'] as String, @@ -110,7 +114,9 @@ class Trade extends HiveObject { createdAt: map['date'] != null ? DateTime.fromMillisecondsSinceEpoch(map['date'] as int) : null, amount: map['amount'] as String, - walletId: map['wallet_id'] as String); + walletId: map['wallet_id'] as String, + fromWalletAddress: map['from_wallet_address'] as String? + ); } Map toMap() { @@ -121,7 +127,8 @@ class Trade extends HiveObject { 'output': to.serialize(), 'date': createdAt != null ? createdAt!.millisecondsSinceEpoch : null, 'amount': amount, - 'wallet_id': walletId + 'wallet_id': walletId, + 'from_wallet_address': fromWalletAddress }; } diff --git a/lib/monero/cw_monero.dart b/lib/monero/cw_monero.dart index 4f45bc974..1de7b8452 100644 --- a/lib/monero/cw_monero.dart +++ b/lib/monero/cw_monero.dart @@ -120,8 +120,6 @@ class CWMoneroWalletDetails extends MoneroWalletDetails { @computed @override MoneroBalance get balance { - final moneroWallet = _wallet as MoneroWallet; - final balance = moneroWallet.balance; throw Exception('Unimplemented'); // return MoneroBalance(); //return MoneroBalance( @@ -132,14 +130,10 @@ class CWMoneroWalletDetails extends MoneroWalletDetails { class CWMonero extends Monero { @override - MoneroAccountList getAccountList(Object wallet) { - return CWMoneroAccountList(wallet); - } + MoneroAccountList getAccountList(Object wallet) => CWMoneroAccountList(wallet); @override - MoneroSubaddressList getSubaddressList(Object wallet) { - return CWMoneroSubaddressList(wallet); - } + MoneroSubaddressList getSubaddressList(Object wallet) => CWMoneroSubaddressList(wallet); @override TransactionHistoryBase getTransactionHistory(Object wallet) { @@ -148,19 +142,13 @@ class CWMonero extends Monero { } @override - MoneroWalletDetails getMoneroWalletDetails(Object wallet) { - return CWMoneroWalletDetails(wallet); - } + MoneroWalletDetails getMoneroWalletDetails(Object wallet) => CWMoneroWalletDetails(wallet); @override - int getHeigthByDate({required DateTime date}) { - return getMoneroHeigthByDate(date: date); - } + int getHeightByDate({required DateTime date}) => getMoneroHeigthByDate(date: date); @override - TransactionPriority getDefaultTransactionPriority() { - return MoneroTransactionPriority.automatic; - } + TransactionPriority getDefaultTransactionPriority() => MoneroTransactionPriority.automatic; @override TransactionPriority getMoneroTransactionPrioritySlow() => MoneroTransactionPriority.slow; @@ -170,14 +158,11 @@ class CWMonero extends Monero { MoneroTransactionPriority.automatic; @override - TransactionPriority deserializeMoneroTransactionPriority({required int raw}) { - return MoneroTransactionPriority.deserialize(raw: raw); - } + TransactionPriority deserializeMoneroTransactionPriority({required int raw}) => + MoneroTransactionPriority.deserialize(raw: raw); @override - List getTransactionPriorities() { - return MoneroTransactionPriority.all; - } + List getTransactionPriorities() => MoneroTransactionPriority.all; @override List getMoneroWordList(String language) { @@ -209,41 +194,37 @@ class CWMonero extends Monero { @override WalletCredentials createMoneroRestoreWalletFromKeysCredentials( - {required String name, - required String spendKey, - required String viewKey, - required String address, - required String password, - required String language, - required int height}) { - return MoneroRestoreWalletFromKeysCredentials( - name: name, - spendKey: spendKey, - viewKey: viewKey, - address: address, - password: password, - language: language, - height: height); - } + {required String name, + required String spendKey, + required String viewKey, + required String address, + required String password, + required String language, + required int height}) => + MoneroRestoreWalletFromKeysCredentials( + name: name, + spendKey: spendKey, + viewKey: viewKey, + address: address, + password: password, + language: language, + height: height); @override WalletCredentials createMoneroRestoreWalletFromSeedCredentials( - {required String name, - required String password, - required int height, - required String mnemonic}) { - return MoneroRestoreWalletFromSeedCredentials( - name: name, password: password, height: height, mnemonic: mnemonic); - } + {required String name, + required String password, + required int height, + required String mnemonic}) => + MoneroRestoreWalletFromSeedCredentials( + name: name, password: password, height: height, mnemonic: mnemonic); @override WalletCredentials createMoneroNewWalletCredentials({ required String name, required String language, - String? password, - }) { - return MoneroNewWalletCredentials(name: name, password: password, language: language); - } + String? password}) => + MoneroNewWalletCredentials(name: name, password: password, language: language); @override Map getKeys(Object wallet) { @@ -259,43 +240,37 @@ class CWMonero extends Monero { @override Object createMoneroTransactionCreationCredentials( - {required List outputs, required TransactionPriority priority}) { - return MoneroTransactionCreationCredentials( - outputs: outputs - .map((out) => OutputInfo( - fiatAmount: out.fiatAmount, - cryptoAmount: out.cryptoAmount, - address: out.address, - note: out.note, - sendAll: out.sendAll, - extractedAddress: out.extractedAddress, - isParsedAddress: out.isParsedAddress, - formattedCryptoAmount: out.formattedCryptoAmount)) - .toList(), - priority: priority as MoneroTransactionPriority); - } + {required List outputs, required TransactionPriority priority}) => + MoneroTransactionCreationCredentials( + outputs: outputs + .map((out) => OutputInfo( + fiatAmount: out.fiatAmount, + cryptoAmount: out.cryptoAmount, + address: out.address, + note: out.note, + sendAll: out.sendAll, + extractedAddress: out.extractedAddress, + isParsedAddress: out.isParsedAddress, + formattedCryptoAmount: out.formattedCryptoAmount)) + .toList(), + priority: priority as MoneroTransactionPriority); @override Object createMoneroTransactionCreationCredentialsRaw( - {required List outputs, required TransactionPriority priority}) { - return MoneroTransactionCreationCredentials( - outputs: outputs, priority: priority as MoneroTransactionPriority); - } + {required List outputs, required TransactionPriority priority}) => + MoneroTransactionCreationCredentials( + outputs: outputs, priority: priority as MoneroTransactionPriority); @override - String formatterMoneroAmountToString({required int amount}) { - return moneroAmountToString(amount: amount); - } + String formatterMoneroAmountToString({required int amount}) => + moneroAmountToString(amount: amount); @override - double formatterMoneroAmountToDouble({required int amount}) { - return moneroAmountToDouble(amount: amount); - } + double formatterMoneroAmountToDouble({required int amount}) => + moneroAmountToDouble(amount: amount); @override - int formatterMoneroParseAmount({required String amount}) { - return moneroParseAmount(amount: amount); - } + int formatterMoneroParseAmount({required String amount}) => moneroParseAmount(amount: amount); @override Account getCurrentAccount(Object wallet) { @@ -312,9 +287,7 @@ class CWMonero extends Monero { } @override - void onStartup() { - monero_wallet_api.onStartup(); - } + void onStartup() => monero_wallet_api.onStartup(); @override int getTransactionInfoAccountId(TransactionInfo tx) { @@ -324,9 +297,8 @@ class CWMonero extends Monero { @override WalletService createMoneroWalletService( - Box walletInfoSource, Box unspentCoinSource) { - return MoneroWalletService(walletInfoSource, unspentCoinSource); - } + Box walletInfoSource, Box unspentCoinSource) => + MoneroWalletService(walletInfoSource, unspentCoinSource); @override String getTransactionAddress(Object wallet, int accountIndex, int addressIndex) { diff --git a/lib/src/widgets/blockchain_height_widget.dart b/lib/src/widgets/blockchain_height_widget.dart index 2ba0a3406..221f87446 100644 --- a/lib/src/widgets/blockchain_height_widget.dart +++ b/lib/src/widgets/blockchain_height_widget.dart @@ -36,16 +36,13 @@ class BlockchainHeightState extends State { restoreHeightController.addListener(() { if (restoreHeightController.text.isNotEmpty) { widget.onHeightOrDateEntered?.call(true); - } - else { + } else { widget.onHeightOrDateEntered?.call(false); dateController.text = ''; } try { - _changeHeight(restoreHeightController.text != null && - restoreHeightController.text.isNotEmpty - ? int.parse(restoreHeightController.text) - : 0); + _changeHeight( + restoreHeightController.text.isNotEmpty ? int.parse(restoreHeightController.text) : 0); } catch (_) { _changeHeight(0); } @@ -117,7 +114,7 @@ class BlockchainHeightState extends State { ); } - Future _selectDate(BuildContext context) async { + Future _selectDate(BuildContext context) async { final now = DateTime.now(); final date = await getDate( context: context, @@ -126,7 +123,7 @@ class BlockchainHeightState extends State { lastDate: now); if (date != null) { - final height = monero!.getHeigthByDate(date: date); + final height = monero!.getHeightByDate(date: date); setState(() { dateController.text = DateFormat('yyyy-MM-dd').format(date); restoreHeightController.text = '$height'; diff --git a/lib/store/dashboard/trade_filter_store.dart b/lib/store/dashboard/trade_filter_store.dart index 799e8b951..4e901aa5e 100644 --- a/lib/store/dashboard/trade_filter_store.dart +++ b/lib/store/dashboard/trade_filter_store.dart @@ -1,7 +1,7 @@ -import 'package:cw_core/wallet_base.dart'; -import 'package:mobx/mobx.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:mobx/mobx.dart'; part'trade_filter_store.g.dart'; @@ -87,29 +87,31 @@ abstract class TradeFilterStoreBase with Store { } List filtered({required List trades, required WalletBase wallet}) { - final _trades = - trades.where((item) => item.trade.walletId == wallet.id).toList(); + final _trades = trades + .where((item) => item.trade.walletId == wallet.id && isTradeInAccount(item, wallet)) + .toList(); final needToFilter = !displayAllTrades; return needToFilter ? _trades - .where((item) => - (displayXMRTO && - item.trade.provider == ExchangeProviderDescription.xmrto) || - (displaySideShift && - item.trade.provider == ExchangeProviderDescription.sideShift) || - (displayChangeNow && - item.trade.provider == - ExchangeProviderDescription.changeNow) || - (displayMorphToken && - item.trade.provider == - ExchangeProviderDescription.morphToken) - ||(displaySimpleSwap && - item.trade.provider == - ExchangeProviderDescription.simpleSwap) - ||(displayTrocador && item.trade.provider == ExchangeProviderDescription.trocador) - ||(displayExolix && item.trade.provider == ExchangeProviderDescription.exolix)) - .toList() + .where((item) => + (displayXMRTO && item.trade.provider == ExchangeProviderDescription.xmrto) || + (displaySideShift && + item.trade.provider == ExchangeProviderDescription.sideShift) || + (displayChangeNow && + item.trade.provider == ExchangeProviderDescription.changeNow) || + (displayMorphToken && + item.trade.provider == ExchangeProviderDescription.morphToken) || + (displaySimpleSwap && + item.trade.provider == ExchangeProviderDescription.simpleSwap) || + (displayTrocador && item.trade.provider == ExchangeProviderDescription.trocador) || + (displayExolix && item.trade.provider == ExchangeProviderDescription.exolix)) + .toList() : _trades; } -} \ No newline at end of file + + bool isTradeInAccount(TradeListItem item, WalletBase wallet) => + item.trade.fromWalletAddress == null + ? true + : wallet.walletAddresses.containsAddress(item.trade.fromWalletAddress!); +} diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 03f0aa9a8..fbb2fc76f 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -1,36 +1,36 @@ import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; +import 'package:cake_wallet/entities/balance_display_mode.dart'; import 'package:cake_wallet/entities/buy_provider_types.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; -import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart'; -import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.dart'; -import 'package:cake_wallet/view_model/settings/sync_mode.dart'; -import 'package:cake_wallet/wallet_type_utils.dart'; -import 'package:cw_core/transaction_history.dart'; -import 'package:cw_core/balance.dart'; -import 'package:cake_wallet/entities/balance_display_mode.dart'; -import 'package:cw_core/transaction_info.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; -import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/monero/monero.dart'; +import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart'; +import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/dashboard/orders_store.dart'; +import 'package:cake_wallet/store/dashboard/trade_filter_store.dart'; +import 'package:cake_wallet/store/dashboard/trades_store.dart'; +import 'package:cake_wallet/store/dashboard/transaction_filter_store.dart'; +import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:cake_wallet/utils/mobx.dart'; +import 'package:cake_wallet/view_model/dashboard/action_list_item.dart'; +import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.dart'; import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/filter_item.dart'; +import 'package:cake_wallet/view_model/dashboard/formatted_item_list.dart'; import 'package:cake_wallet/view_model/dashboard/order_list_item.dart'; import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart'; import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart'; -import 'package:cake_wallet/view_model/dashboard/action_list_item.dart'; -import 'package:mobx/mobx.dart'; -import 'package:cw_core/wallet_base.dart'; +import 'package:cake_wallet/view_model/settings/sync_mode.dart'; +import 'package:cake_wallet/wallet_type_utils.dart'; +import 'package:cw_core/balance.dart'; import 'package:cw_core/sync_status.dart'; +import 'package:cw_core/transaction_history.dart'; +import 'package:cw_core/transaction_info.dart'; +import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:cake_wallet/store/app_store.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/store/dashboard/trades_store.dart'; -import 'package:cake_wallet/store/dashboard/trade_filter_store.dart'; -import 'package:cake_wallet/store/dashboard/transaction_filter_store.dart'; -import 'package:cake_wallet/view_model/dashboard/formatted_item_list.dart'; -import 'package:cake_wallet/monero/monero.dart'; +import 'package:mobx/mobx.dart'; part 'dashboard_view_model.g.dart'; @@ -47,69 +47,69 @@ abstract class DashboardViewModelBase with Store { required this.yatStore, required this.ordersStore, required this.anonpayTransactionsStore}) - : hasSellAction = false, - hasBuyAction = false, - hasExchangeAction = false, - isShowFirstYatIntroduction = false, - isShowSecondYatIntroduction = false, - isShowThirdYatIntroduction = false, - filterItems = { - S.current.transactions: [ - FilterItem( - value: () => transactionFilterStore.displayAll, - caption: S.current.all_transactions, - onChanged: transactionFilterStore.toggleAll), - FilterItem( - value: () => transactionFilterStore.displayIncoming, - caption: S.current.incoming, - onChanged:transactionFilterStore.toggleIncoming), - FilterItem( - value: () => transactionFilterStore.displayOutgoing, - caption: S.current.outgoing, - onChanged: transactionFilterStore.toggleOutgoing), - // FilterItem( - // value: () => false, - // caption: S.current.transactions_by_date, - // onChanged: null), - ], - S.current.trades: [ - FilterItem( - value: () => tradeFilterStore.displayAllTrades, - caption: S.current.all_trades, - onChanged: () => tradeFilterStore - .toggleDisplayExchange(ExchangeProviderDescription.all)), - FilterItem( - value: () => tradeFilterStore.displayChangeNow, - caption: ExchangeProviderDescription.changeNow.title, - onChanged: () => tradeFilterStore - .toggleDisplayExchange(ExchangeProviderDescription.changeNow)), - FilterItem( - value: () => tradeFilterStore.displaySideShift, - caption: ExchangeProviderDescription.sideShift.title, - onChanged: () => tradeFilterStore - .toggleDisplayExchange(ExchangeProviderDescription.sideShift)), - FilterItem( - value: () => tradeFilterStore.displaySimpleSwap, - caption: ExchangeProviderDescription.simpleSwap.title, - onChanged: () => tradeFilterStore - .toggleDisplayExchange(ExchangeProviderDescription.simpleSwap)), - FilterItem( - value: () => tradeFilterStore.displayTrocador, - caption: ExchangeProviderDescription.trocador.title, - onChanged: () => tradeFilterStore - .toggleDisplayExchange(ExchangeProviderDescription.trocador)), - FilterItem( - value: () => tradeFilterStore.displayExolix, - caption: ExchangeProviderDescription.exolix.title, - onChanged: () => tradeFilterStore - .toggleDisplayExchange(ExchangeProviderDescription.exolix)), - ] - }, - subname = '', - name = appStore.wallet!.name, - type = appStore.wallet!.type, - transactions = ObservableList(), - wallet = appStore.wallet! { + : hasSellAction = false, + hasBuyAction = false, + hasExchangeAction = false, + isShowFirstYatIntroduction = false, + isShowSecondYatIntroduction = false, + isShowThirdYatIntroduction = false, + filterItems = { + S.current.transactions: [ + FilterItem( + value: () => transactionFilterStore.displayAll, + caption: S.current.all_transactions, + onChanged: transactionFilterStore.toggleAll), + FilterItem( + value: () => transactionFilterStore.displayIncoming, + caption: S.current.incoming, + onChanged: transactionFilterStore.toggleIncoming), + FilterItem( + value: () => transactionFilterStore.displayOutgoing, + caption: S.current.outgoing, + onChanged: transactionFilterStore.toggleOutgoing), + // FilterItem( + // value: () => false, + // caption: S.current.transactions_by_date, + // onChanged: null), + ], + S.current.trades: [ + FilterItem( + value: () => tradeFilterStore.displayAllTrades, + caption: S.current.all_trades, + onChanged: () => + tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.all)), + FilterItem( + value: () => tradeFilterStore.displayChangeNow, + caption: ExchangeProviderDescription.changeNow.title, + onChanged: () => + tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.changeNow)), + FilterItem( + value: () => tradeFilterStore.displaySideShift, + caption: ExchangeProviderDescription.sideShift.title, + onChanged: () => + tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.sideShift)), + FilterItem( + value: () => tradeFilterStore.displaySimpleSwap, + caption: ExchangeProviderDescription.simpleSwap.title, + onChanged: () => + tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.simpleSwap)), + FilterItem( + value: () => tradeFilterStore.displayTrocador, + caption: ExchangeProviderDescription.trocador.title, + onChanged: () => + tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.trocador)), + FilterItem( + value: () => tradeFilterStore.displayExolix, + caption: ExchangeProviderDescription.exolix.title, + onChanged: () => + tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.exolix)), + ] + }, + subname = '', + name = appStore.wallet!.name, + type = appStore.wallet!.type, + transactions = ObservableList(), + wallet = appStore.wallet! { name = wallet.name; type = wallet.type; isShowFirstYatIntroduction = false; @@ -222,9 +222,8 @@ abstract class DashboardViewModelBase with Store { BalanceDisplayMode get balanceDisplayMode => appStore.settingsStore.balanceDisplayMode; @computed - bool get shouldShowMarketPlaceInDashboard { - return appStore.settingsStore.shouldShowMarketPlaceInDashboard; - } + bool get shouldShowMarketPlaceInDashboard => + appStore.settingsStore.shouldShowMarketPlaceInDashboard; @computed List get trades => diff --git a/lib/view_model/dashboard/trade_list_item.dart b/lib/view_model/dashboard/trade_list_item.dart index d83445308..964ba4ffa 100644 --- a/lib/view_model/dashboard/trade_list_item.dart +++ b/lib/view_model/dashboard/trade_list_item.dart @@ -1,25 +1,18 @@ +import 'package:cake_wallet/entities/balance_display_mode.dart'; import 'package:cake_wallet/exchange/trade.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/view_model/dashboard/action_list_item.dart'; -import 'package:cake_wallet/entities/balance_display_mode.dart'; class TradeListItem extends ActionListItem { - TradeListItem({ - required this.trade, - required this.settingsStore}); + TradeListItem({required this.trade, required this.settingsStore}); final Trade trade; final SettingsStore settingsStore; BalanceDisplayMode get displayMode => settingsStore.balanceDisplayMode; - String get tradeFormattedAmount { - return trade.amount != null - ? displayMode == BalanceDisplayMode.hiddenBalance - ? '---' - : trade.amountFormatted() - : trade.amount; - } + String get tradeFormattedAmount => + displayMode == BalanceDisplayMode.hiddenBalance ? '---' : trade.amountFormatted(); @override DateTime get date => trade.createdAt!; diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 8692b193b..704e5c029 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -491,6 +491,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with final trade = await provider.createTrade(request: request, isFixedRateMode: isFixedRateMode); trade.walletId = wallet.id; + trade.fromWalletAddress = wallet.walletAddresses.address; tradesStore.setTrade(trade); await trades.add(trade); tradeState = TradeIsCreatedSuccessfully(trade: trade); diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart index 81f521d27..257bae1fd 100644 --- a/lib/view_model/wallet_keys_view_model.dart +++ b/lib/view_model/wallet_keys_view_model.dart @@ -1,4 +1,3 @@ -import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_info.dart'; @@ -194,7 +193,7 @@ abstract class WalletKeysViewModelBase with Store { int _getRestoreHeightByTransactions(WalletType type, DateTime date) { if (type == WalletType.monero) { - return monero!.getHeigthByDate(date: date); + return monero!.getHeightByDate(date: date); } else if (type == WalletType.haven) { return haven!.getHeightByDate(date: date); } diff --git a/tool/configure.dart b/tool/configure.dart index 90e275994..bc32581a6 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -235,7 +235,7 @@ abstract class Monero { String getSubaddressLabel(Object wallet, int accountIndex, int addressIndex); - int getHeigthByDate({required DateTime date}); + int getHeightByDate({required DateTime date}); TransactionPriority getDefaultTransactionPriority(); TransactionPriority getMoneroTransactionPrioritySlow(); TransactionPriority getMoneroTransactionPriorityAutomatic(); From d997ee81a1698c46f0cc2b16c5a1d4c98fec1c03 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 2 Nov 2023 19:19:39 +0200 Subject: [PATCH 023/241] CW-315-Add-a-toast-message-to-enable-denied-permissions-in-device-settings (#1157) * add permission handler * localization * minor fixes --------- Co-authored-by: OmarHatem --- .../nodes/node_create_or_edit_page.dart | 2 +- .../nodes/pow_node_create_or_edit_page.dart | 2 +- .../screens/restore/restore_options_page.dart | 5 +++ .../wc_connections_listing_view.dart | 5 +++ lib/src/widgets/address_text_field.dart | 5 +++ lib/utils/permission_handler.dart | 32 +++++++++++++++++++ .../node_create_or_edit_view_model.dart | 8 ++++- res/values/strings_ar.arb | 1 + res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 1 + res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 1 + res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 1 + res/values/strings_my.arb | 1 + res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_th.arb | 1 + res/values/strings_tl.arb | 1 + res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + 33 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 lib/utils/permission_handler.dart diff --git a/lib/src/screens/nodes/node_create_or_edit_page.dart b/lib/src/screens/nodes/node_create_or_edit_page.dart index 3525160e8..ff9d59719 100644 --- a/lib/src/screens/nodes/node_create_or_edit_page.dart +++ b/lib/src/screens/nodes/node_create_or_edit_page.dart @@ -69,7 +69,7 @@ class NodeCreateOrEditPage extends BasePage { @override Widget trailing(BuildContext context) => IconButton( onPressed: () async { - await nodeCreateOrEditViewModel.scanQRCodeForNewNode(); + await nodeCreateOrEditViewModel.scanQRCodeForNewNode(context); }, splashColor: Colors.transparent, highlightColor: Colors.transparent, diff --git a/lib/src/screens/nodes/pow_node_create_or_edit_page.dart b/lib/src/screens/nodes/pow_node_create_or_edit_page.dart index 8460579ef..e91791881 100644 --- a/lib/src/screens/nodes/pow_node_create_or_edit_page.dart +++ b/lib/src/screens/nodes/pow_node_create_or_edit_page.dart @@ -69,7 +69,7 @@ class PowNodeCreateOrEditPage extends BasePage { @override Widget trailing(BuildContext context) => IconButton( onPressed: () async { - await nodeCreateOrEditViewModel.scanQRCodeForNewNode(); + await nodeCreateOrEditViewModel.scanQRCodeForNewNode(context); }, splashColor: Colors.transparent, highlightColor: Colors.transparent, diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart index 2ca210c00..2252551cc 100644 --- a/lib/src/screens/restore/restore_options_page.dart +++ b/lib/src/screens/restore/restore_options_page.dart @@ -12,6 +12,8 @@ import 'package:cake_wallet/routes.dart'; import 'package:flutter/cupertino.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:cake_wallet/utils/permission_handler.dart'; class RestoreOptionsPage extends BasePage { RestoreOptionsPage({required this.isNewInstall}); @@ -55,6 +57,9 @@ class RestoreOptionsPage extends BasePage { padding: EdgeInsets.only(top: 24), child: OptionTile( onPressed: () async { + bool isCameraPermissionGranted = + await PermissionHandler.checkPermission(Permission.camera, context); + if (!isCameraPermissionGranted) return; bool isPinSet = false; if (isNewInstall) { await Navigator.pushNamed(context, Routes.setupPin, diff --git a/lib/src/screens/wallet_connect/wc_connections_listing_view.dart b/lib/src/screens/wallet_connect/wc_connections_listing_view.dart index bb60dc4ad..359d96b26 100644 --- a/lib/src/screens/wallet_connect/wc_connections_listing_view.dart +++ b/lib/src/screens/wallet_connect/wc_connections_listing_view.dart @@ -8,10 +8,12 @@ import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; import 'package:cake_wallet/entities/qr_scanner.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/utils/permission_handler.dart'; import 'widgets/pairing_item_widget.dart'; import 'wc_pairing_detail_page.dart'; @@ -58,6 +60,9 @@ class WCPairingsWidget extends BasePage { final String? uri; if (DeviceInfo.instance.isMobile) { + bool isCameraPermissionGranted = + await PermissionHandler.checkPermission(Permission.camera, context); + if (!isCameraPermissionGranted) return; uri = await presentQRScanner(); } else { uri = await _showEnterWalletConnectURIPopUp(context); diff --git a/lib/src/widgets/address_text_field.dart b/lib/src/widgets/address_text_field.dart index 000e6325e..fcdbad701 100644 --- a/lib/src/widgets/address_text_field.dart +++ b/lib/src/widgets/address_text_field.dart @@ -9,6 +9,8 @@ import 'package:cake_wallet/entities/qr_scanner.dart'; import 'package:cake_wallet/entities/contact_base.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; +import 'package:cake_wallet/utils/permission_handler.dart'; +import 'package:permission_handler/permission_handler.dart'; enum AddressTextFieldOption { paste, qrCode, addressBook } @@ -188,6 +190,9 @@ class AddressTextField extends StatelessWidget { } Future _presentQRScanner(BuildContext context) async { + bool isCameraPermissionGranted = + await PermissionHandler.checkPermission(Permission.camera, context); + if (!isCameraPermissionGranted) return; final code = await presentQRScanner(); if (code.isEmpty) { return; diff --git a/lib/utils/permission_handler.dart b/lib/utils/permission_handler.dart new file mode 100644 index 000000000..7e8a8f710 --- /dev/null +++ b/lib/utils/permission_handler.dart @@ -0,0 +1,32 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/utils/show_bar.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:permission_handler/permission_handler.dart'; + +class PermissionHandler { + static Future checkPermission(Permission permission, BuildContext context) async { + final Map _permissionMessages = { + Permission.camera: S.of(context).camera_permission_is_required, + }; + + var status = await permission.status; + + if (status.isDenied) { + status = await permission.request(); + } + + if (status.isPermanentlyDenied || status.isDenied) { + String? message = _permissionMessages[permission]; + if (message != null) { + showBar(context, message); + } + return false; + } + + if (status.isGranted) { + return true; + } + + return false; + } +} diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart index f749ed0d5..0fb9a83c6 100644 --- a/lib/view_model/node_list/node_create_or_edit_view_model.dart +++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart @@ -1,11 +1,14 @@ import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/entities/qr_scanner.dart'; import 'package:cake_wallet/store/settings_store.dart'; +import 'package:flutter/cupertino.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_core/node.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:collection/collection.dart'; +import 'package:cake_wallet/utils/permission_handler.dart'; +import 'package:permission_handler/permission_handler.dart'; part 'node_create_or_edit_view_model.g.dart'; @@ -175,8 +178,11 @@ abstract class NodeCreateOrEditViewModelBase with Store { void setAsCurrent(Node node) => _settingsStore.nodes[_walletType] = node; @action - Future scanQRCodeForNewNode() async { + Future scanQRCodeForNewNode(BuildContext context) async { try { + bool isCameraPermissionGranted = + await PermissionHandler.checkPermission(Permission.camera, context); + if (!isCameraPermissionGranted) return; String code = await presentQRScanner(); if (code.isEmpty) { diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 96b237783..fa5eb4960 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -723,5 +723,6 @@ "enter_seed_phrase": "أدخل عبارة البذور الخاصة بك", "add_contact": "ﻝﺎﺼﺗﺍ ﺔﻬﺟ ﺔﻓﺎﺿﺇ", "exchange_provider_unsupported": "${providerName} لم يعد مدعومًا!", + "camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ", "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 11eb30e8f..49ae4076f 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -719,5 +719,6 @@ "enter_seed_phrase": "Въведете вашата фраза за семена", "add_contact": "Добави контакт", "exchange_provider_unsupported": "${providerName} вече не се поддържа!", + "camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.", "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 6de65a921..38c49492e 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -719,5 +719,6 @@ "enter_seed_phrase": "Zadejte svou frázi semen", "add_contact": "Přidat kontakt", "exchange_provider_unsupported": "${providerName} již není podporováno!", + "camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.", "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 2cfbd8e21..306272aa4 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -727,5 +727,6 @@ "enter_seed_phrase": "Geben Sie Ihre Seed-Phrase ein", "add_contact": "Kontakt hinzufügen", "exchange_provider_unsupported": "${providerName} wird nicht mehr unterstützt!", + "camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.", "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index aad508e2e..4589f9d3e 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -728,5 +728,6 @@ "enter_seed_phrase": "Enter your seed phrase", "add_contact": "Add contact", "exchange_provider_unsupported": "${providerName} is no longer supported!", + "camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.", "switchToETHWallet": "Please switch to an Ethereum wallet and try again" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 4dc954599..221e1a293 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -727,5 +727,6 @@ "enter_seed_phrase": "Ingrese su frase de semillas", "add_contact": "Agregar contacto", "exchange_provider_unsupported": "¡${providerName} ya no es compatible!", + "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.", "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente." } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 13671d986..f2549c3e6 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -727,5 +727,6 @@ "enter_seed_phrase": "Entrez votre phrase de semence", "add_contact": "Ajouter le contact", "exchange_provider_unsupported": "${providerName} n'est plus pris en charge!", + "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", "switchToETHWallet": "Veuillez passer à un portefeuille Ethereum et réessayer" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 6430986be..d181c15b5 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -705,5 +705,6 @@ "enter_seed_phrase": "Shigar da Sert Sentarku", "add_contact": "Ƙara lamba", "exchange_provider_unsupported": "${providerName}", + "camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.", "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 047d3a0d6..c47622a19 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -727,5 +727,6 @@ "enter_seed_phrase": "अपना बीज वाक्यांश दर्ज करें", "add_contact": "संपर्क जोड़ें", "exchange_provider_unsupported": "${providerName} अब समर्थित नहीं है!", + "camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।", "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index e532703da..6c3a4df3d 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -725,5 +725,6 @@ "enter_seed_phrase": "Unesite svoju sjemensku frazu", "add_contact": "Dodaj kontakt", "exchange_provider_unsupported": "${providerName} više nije podržan!", + "camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.", "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 1ba4d7978..4c7f8c167 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -715,5 +715,6 @@ "enter_seed_phrase": "Masukkan frasa benih Anda", "add_contact": "Tambah kontak", "exchange_provider_unsupported": "${providerName} tidak lagi didukung!", + "camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.", "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 0f137971b..5b2d46ac1 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -727,5 +727,6 @@ "enter_seed_phrase": "Inserisci la tua frase di semi", "add_contact": "Aggiungi contatto", "exchange_provider_unsupported": "${providerName} non è più supportato!", + "camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.", "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index aa8fee600..36e8fe90f 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -727,5 +727,6 @@ "enter_seed_phrase": "シードフレーズを入力してください", "add_contact": "連絡先を追加", "exchange_provider_unsupported": "${providerName}はサポートされなくなりました!", + "camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。", "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 6b2a12929..d03de7731 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -725,5 +725,6 @@ "enter_seed_phrase": "시드 문구를 입력하십시오", "add_contact": "주소록에 추가", "exchange_provider_unsupported": "${providerName}은 더 이상 지원되지 않습니다!", + "camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.", "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요." } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 0268d0375..a844ba99f 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -725,5 +725,6 @@ "enter_seed_phrase": "သင့်ရဲ့မျိုးစေ့စကားစုကိုရိုက်ထည့်ပါ", "add_contact": "အဆက်အသွယ်ထည့်ပါ။", "exchange_provider_unsupported": "${providerName} မရှိတော့ပါ!", + "camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။", "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 8706fb8ab..6f3f24bb4 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -727,5 +727,6 @@ "enter_seed_phrase": "Voer uw zaadzin in", "add_contact": "Contactpersoon toevoegen", "exchange_provider_unsupported": "${providerName} wordt niet langer ondersteund!", + "camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.", "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 9c09cb520..2520d57a1 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -727,5 +727,6 @@ "enter_seed_phrase": "Wprowadź swoją frazę nasienną", "add_contact": "Dodaj kontakt", "exchange_provider_unsupported": "${providerName} nie jest już obsługiwany!", + "camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.", "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 0e3206549..49fda1bee 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -726,5 +726,6 @@ "enter_seed_phrase": "Digite sua frase de semente", "add_contact": "Adicionar contato", "exchange_provider_unsupported": "${providerName} não é mais suportado!", + "camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.", "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 2f9d4846f..b4c4681b9 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -727,5 +727,6 @@ "enter_seed_phrase": "Введите свою семенную фразу", "add_contact": "Добавить контакт", "exchange_provider_unsupported": "${providerName} больше не поддерживается!", + "camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.", "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку." } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index fc38e69df..91c05c968 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -725,5 +725,6 @@ "enter_seed_phrase": "ป้อนวลีเมล็ดพันธุ์ของคุณ", "add_contact": "เพิ่มผู้ติดต่อ", "exchange_provider_unsupported": "${providerName} ไม่ได้รับการสนับสนุนอีกต่อไป!", + "camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป", "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 4c847c84e..546b1515c 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -722,5 +722,6 @@ "enter_seed_phrase": "Ipasok ang iyong pariralang binhi", "add_contact": "Magdagdag ng contact", "exchange_provider_unsupported": "Ang ${providerName} ay hindi na suportado!", + "camera_permission_is_required": "Kinakailangan ang pahintulot sa camera.\nMangyaring paganahin ito mula sa mga setting ng app.", "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 7ac1546f5..60e276513 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -725,5 +725,6 @@ "enter_seed_phrase": "Tohum ifadenizi girin", "add_contact": "Kişi ekle", "exchange_provider_unsupported": "${providerName} artık desteklenmiyor!", + "camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.", "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index ad5fb22c7..034260c13 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -727,5 +727,6 @@ "enter_seed_phrase": "Введіть свою насіннєву фразу", "add_contact": "Додати контакт", "exchange_provider_unsupported": "${providerName} більше не підтримується!", + "camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.", "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 027f4e052..237fa24dd 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -719,5 +719,6 @@ "enter_seed_phrase": "اپنے بیج کا جملہ درج کریں", "add_contact": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮧﻄﺑﺍﺭ", "exchange_provider_unsupported": "${providerName} اب تعاون نہیں کیا جاتا ہے!", + "camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ", "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 98c80bc48..df06da974 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -721,5 +721,6 @@ "enter_seed_phrase": "Tẹ ọrọ-iru irugbin rẹ", "add_contact": "Fi olubasọrọ kun", "exchange_provider_unsupported": "${providerName} ko ni atilẹyin mọ!", + "camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.", "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index ac46a3fc6..4a464b50f 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -726,5 +726,6 @@ "enter_seed_phrase": "输入您的种子短语", "add_contact": "增加联系人", "exchange_provider_unsupported": "${providerName}不再支持!", + "camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。", "switchToETHWallet": "请切换到以太坊钱包并重试" } From 9aede1f3c18c1cdacc039b50fe41f1b5ac43c4e8 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Thu, 2 Nov 2023 19:17:52 +0100 Subject: [PATCH 024/241] fix: Implement totp on exchange to external ticket as well as update UI properly when a preset is selected (#1156) Co-authored-by: OmarHatem --- lib/entities/cake_2fa_preset_options.dart | 1 + lib/entities/preferences_key.dart | 2 ++ .../screens/setup_2fa/modify_2fa_page.dart | 11 +++++++++ lib/store/settings_store.dart | 20 ++++++++++++++++ .../exchange/exchange_view_model.dart | 23 +++++++++++-------- lib/view_model/set_up_2fa_viewmodel.dart | 14 +++++++++++ res/values/strings_ar.arb | 1 + res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 1 + res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 1 + res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 1 + res/values/strings_my.arb | 1 + res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_th.arb | 1 + res/values/strings_tl.arb | 1 + res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + 32 files changed, 88 insertions(+), 9 deletions(-) diff --git a/lib/entities/cake_2fa_preset_options.dart b/lib/entities/cake_2fa_preset_options.dart index 417af2b98..feb593fbe 100644 --- a/lib/entities/cake_2fa_preset_options.dart +++ b/lib/entities/cake_2fa_preset_options.dart @@ -33,6 +33,7 @@ enum VerboseControlSettings { sendsToNonContacts, sendsToInternalWallets, exchangesToInternalWallets, + exchangesToExternalWallets, securityAndBackupSettings, creatingNewWallets, } diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index cbd12d777..fe9182e97 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -71,6 +71,8 @@ class PreferencesKey { 'should_require_totp_2fa_for_sends_to_internal_wallets'; static const shouldRequireTOTP2FAForExchangesToInternalWallets = 'should_require_totp_2fa_for_exchanges_to_internal_wallets'; + static const shouldRequireTOTP2FAForExchangesToExternalWallets = + 'should_require_totp_2fa_for_exchanges_to_external_wallets'; static const shouldRequireTOTP2FAForAddingContacts = 'should_require_totp_2fa_for_adding_contacts'; static const shouldRequireTOTP2FAForCreatingNewWallets = diff --git a/lib/src/screens/setup_2fa/modify_2fa_page.dart b/lib/src/screens/setup_2fa/modify_2fa_page.dart index 148e3076e..601d084e7 100644 --- a/lib/src/screens/setup_2fa/modify_2fa_page.dart +++ b/lib/src/screens/setup_2fa/modify_2fa_page.dart @@ -133,6 +133,17 @@ class _2FAControlsWidget extends StatelessWidget { }, ), StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + Observer( + builder: (context) { + return SettingsSwitcherCell( + title: S.current.require_for_exchanges_to_external_wallets, + value: setup2FAViewModel.shouldRequireTOTP2FAForExchangesToExternalWallets, + onValueChange: (context, value) async => + setup2FAViewModel.switchShouldRequireTOTP2FAForExchangesToExternalWallets(value), + ); + }, + ), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), Observer( builder: (context) { return SettingsSwitcherCell( diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index a2e2570e0..ad4b8fd1e 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -76,6 +76,7 @@ abstract class SettingsStoreBase with Store { required bool initialShouldRequireTOTP2FAForSendsToNonContact, required bool initialShouldRequireTOTP2FAForSendsToInternalWallets, required bool initialShouldRequireTOTP2FAForExchangesToInternalWallets, + required bool initialShouldRequireTOTP2FAForExchangesToExternalWallets, required bool initialShouldRequireTOTP2FAForAddingContacts, required bool initialShouldRequireTOTP2FAForCreatingNewWallets, required bool initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings, @@ -118,6 +119,8 @@ abstract class SettingsStoreBase with Store { initialShouldRequireTOTP2FAForSendsToInternalWallets, shouldRequireTOTP2FAForExchangesToInternalWallets = initialShouldRequireTOTP2FAForExchangesToInternalWallets, + shouldRequireTOTP2FAForExchangesToExternalWallets = + initialShouldRequireTOTP2FAForExchangesToExternalWallets, shouldRequireTOTP2FAForAddingContacts = initialShouldRequireTOTP2FAForAddingContacts, shouldRequireTOTP2FAForCreatingNewWallets = initialShouldRequireTOTP2FAForCreatingNewWallets, @@ -271,6 +274,12 @@ abstract class SettingsStoreBase with Store { PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets, requireTOTP2FAForExchangesToInternalWallets)); + reaction( + (_) => shouldRequireTOTP2FAForExchangesToExternalWallets, + (bool requireTOTP2FAForExchangesToExternalWallets) => sharedPreferences.setBool( + PreferencesKey.shouldRequireTOTP2FAForExchangesToExternalWallets, + requireTOTP2FAForExchangesToExternalWallets)); + reaction( (_) => shouldRequireTOTP2FAForAddingContacts, (bool requireTOTP2FAForAddingContacts) => sharedPreferences.setBool( @@ -425,6 +434,9 @@ abstract class SettingsStoreBase with Store { @observable bool shouldRequireTOTP2FAForExchangesToInternalWallets; + @observable + bool shouldRequireTOTP2FAForExchangesToExternalWallets; + @observable Cake2FAPresetsOptions selectedCake2FAPreset; @@ -597,6 +609,9 @@ abstract class SettingsStoreBase with Store { final shouldRequireTOTP2FAForExchangesToInternalWallets = sharedPreferences .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ?? false; + final shouldRequireTOTP2FAForExchangesToExternalWallets = sharedPreferences + .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToExternalWallets) ?? + false; final shouldRequireTOTP2FAForAddingContacts = sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForAddingContacts) ?? false; final shouldRequireTOTP2FAForCreatingNewWallets = @@ -751,6 +766,8 @@ abstract class SettingsStoreBase with Store { shouldRequireTOTP2FAForSendsToInternalWallets, initialShouldRequireTOTP2FAForExchangesToInternalWallets: shouldRequireTOTP2FAForExchangesToInternalWallets, + initialShouldRequireTOTP2FAForExchangesToExternalWallets: + shouldRequireTOTP2FAForExchangesToExternalWallets, initialShouldRequireTOTP2FAForAddingContacts: shouldRequireTOTP2FAForAddingContacts, initialShouldRequireTOTP2FAForCreatingNewWallets: shouldRequireTOTP2FAForCreatingNewWallets, initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings: @@ -835,6 +852,9 @@ abstract class SettingsStoreBase with Store { shouldRequireTOTP2FAForExchangesToInternalWallets = sharedPreferences .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ?? false; + shouldRequireTOTP2FAForExchangesToExternalWallets = sharedPreferences + .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToExternalWallets) ?? + false; shouldRequireTOTP2FAForAddingContacts = sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForAddingContacts) ?? false; shouldRequireTOTP2FAForCreatingNewWallets = diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 704e5c029..1a6b118f8 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -237,15 +237,21 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with bool get shouldDisplayTOTP2FAForExchangesToInternalWallet => _settingsStore.shouldRequireTOTP2FAForExchangesToInternalWallets; + @computed + bool get shouldDisplayTOTP2FAForExchangesToExternalWallet => + _settingsStore.shouldRequireTOTP2FAForExchangesToExternalWallets; + //* Still open to further optimize these checks //* It works but can be made better @action bool shouldDisplayTOTP() { final isInternalWallet = checkIfWalletIsAnInternalWallet(receiveAddress); + if (isInternalWallet) { return shouldDisplayTOTP2FAForExchangesToInternalWallet; + } else { + return shouldDisplayTOTP2FAForExchangesToExternalWallet; } - return false; } @computed @@ -263,7 +269,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with (wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin || wallet.type == WalletType.bitcoinCash) && - depositCurrency == wallet.currency; + depositCurrency == wallet.currency; bool get isMoneroWallet => wallet.type == WalletType.monero; @@ -275,14 +281,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with case WalletType.bitcoin: return transactionPriority == bitcoin!.getBitcoinTransactionPrioritySlow(); case WalletType.litecoin: - return transactionPriority == - bitcoin!.getLitecoinTransactionPrioritySlow(); + return transactionPriority == bitcoin!.getLitecoinTransactionPrioritySlow(); case WalletType.ethereum: - return transactionPriority == - ethereum!.getEthereumTransactionPrioritySlow(); + return transactionPriority == ethereum!.getEthereumTransactionPrioritySlow(); case WalletType.bitcoinCash: - return transactionPriority == - bitcoinCash!.getBitcoinCashTransactionPrioritySlow(); + return transactionPriority == bitcoinCash!.getBitcoinCashTransactionPrioritySlow(); default: return false; } @@ -535,7 +538,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with @action void calculateDepositAllAmount() { - if (wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin || wallet.type == WalletType.bitcoinCash) { + if (wallet.type == WalletType.bitcoin || + wallet.type == WalletType.litecoin || + wallet.type == WalletType.bitcoinCash) { final availableBalance = wallet.balance[wallet.currency]!.available; final priority = _settingsStore.priority[wallet.type]!; final fee = wallet.calculateEstimatedFee(priority, null); diff --git a/lib/view_model/set_up_2fa_viewmodel.dart b/lib/view_model/set_up_2fa_viewmodel.dart index b8fc40f23..9587e3075 100644 --- a/lib/view_model/set_up_2fa_viewmodel.dart +++ b/lib/view_model/set_up_2fa_viewmodel.dart @@ -74,6 +74,10 @@ abstract class Setup2FAViewModelBase with Store { bool get shouldRequireTOTP2FAForExchangesToInternalWallets => _settingsStore.shouldRequireTOTP2FAForExchangesToInternalWallets; + @computed + bool get shouldRequireTOTP2FAForExchangesToExternalWallets => + _settingsStore.shouldRequireTOTP2FAForExchangesToExternalWallets; + @computed bool get shouldRequireTOTP2FAForAddingContacts => _settingsStore.shouldRequireTOTP2FAForAddingContacts; @@ -277,6 +281,7 @@ abstract class Setup2FAViewModelBase with Store { switchShouldRequireTOTP2FAForAddingContacts(false); switchShouldRequireTOTP2FAForCreatingNewWallet(false); switchShouldRequireTOTP2FAForExchangesToInternalWallets(false); + switchShouldRequireTOTP2FAForExchangesToExternalWallets(false); switchShouldRequireTOTP2FAForSendsToInternalWallets(false); switchShouldRequireTOTP2FAForAllSecurityAndBackupSettings(false); selected2FASettings.clear(); @@ -306,6 +311,7 @@ abstract class Setup2FAViewModelBase with Store { @action void selectCakePreset(Cake2FAPresetsOptions preset) { + setAllControlsToFalse(); presetsMap[preset]?.forEach(toggleControl); _settingsStore.selectedCake2FAPreset = preset; } @@ -324,6 +330,8 @@ abstract class Setup2FAViewModelBase with Store { switchShouldRequireTOTP2FAForAllSecurityAndBackupSettings, VerboseControlSettings.exchangesToInternalWallets: switchShouldRequireTOTP2FAForExchangesToInternalWallets, + VerboseControlSettings.exchangesToExternalWallets: + switchShouldRequireTOTP2FAForExchangesToExternalWallets, }; methodsMap[control]?.call(value); @@ -359,6 +367,12 @@ abstract class Setup2FAViewModelBase with Store { updateSelectedSettings(VerboseControlSettings.exchangesToInternalWallets, value); } + @action + void switchShouldRequireTOTP2FAForExchangesToExternalWallets(bool value) { + _settingsStore.shouldRequireTOTP2FAForExchangesToExternalWallets = value; + updateSelectedSettings(VerboseControlSettings.exchangesToExternalWallets, value); + } + @action void switchShouldRequireTOTP2FAForAddingContacts(bool value) { _settingsStore.shouldRequireTOTP2FAForAddingContacts = value; diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index fa5eb4960..a803ef687 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -723,6 +723,7 @@ "enter_seed_phrase": "أدخل عبارة البذور الخاصة بك", "add_contact": "ﻝﺎﺼﺗﺍ ﺔﻬﺟ ﺔﻓﺎﺿﺇ", "exchange_provider_unsupported": "${providerName} لم يعد مدعومًا!", + "require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ", "camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ", "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 49ae4076f..85d19d8c4 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -719,6 +719,7 @@ "enter_seed_phrase": "Въведете вашата фраза за семена", "add_contact": "Добави контакт", "exchange_provider_unsupported": "${providerName} вече не се поддържа!", + "require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли", "camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.", "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 38c49492e..b6a59979d 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -719,6 +719,7 @@ "enter_seed_phrase": "Zadejte svou frázi semen", "add_contact": "Přidat kontakt", "exchange_provider_unsupported": "${providerName} již není podporováno!", + "require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek", "camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.", "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 306272aa4..9b7e0f6ef 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "Geben Sie Ihre Seed-Phrase ein", "add_contact": "Kontakt hinzufügen", "exchange_provider_unsupported": "${providerName} wird nicht mehr unterstützt!", + "require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets", "camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.", "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 4589f9d3e..e7ca7a850 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -728,6 +728,7 @@ "enter_seed_phrase": "Enter your seed phrase", "add_contact": "Add contact", "exchange_provider_unsupported": "${providerName} is no longer supported!", + "require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets", "camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.", "switchToETHWallet": "Please switch to an Ethereum wallet and try again" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 221e1a293..a05ebd09b 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "Ingrese su frase de semillas", "add_contact": "Agregar contacto", "exchange_provider_unsupported": "¡${providerName} ya no es compatible!", + "require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas", "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.", "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente." } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index f2549c3e6..4997ca37d 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "Entrez votre phrase de semence", "add_contact": "Ajouter le contact", "exchange_provider_unsupported": "${providerName} n'est plus pris en charge!", + "require_for_exchanges_to_external_wallets": "Exiger des échanges vers des portefeuilles externes", "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", "switchToETHWallet": "Veuillez passer à un portefeuille Ethereum et réessayer" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index d181c15b5..c07f5c86b 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -705,6 +705,7 @@ "enter_seed_phrase": "Shigar da Sert Sentarku", "add_contact": "Ƙara lamba", "exchange_provider_unsupported": "${providerName}", + "require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje", "camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.", "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index c47622a19..c949c9938 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "अपना बीज वाक्यांश दर्ज करें", "add_contact": "संपर्क जोड़ें", "exchange_provider_unsupported": "${providerName} अब समर्थित नहीं है!", + "require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है", "camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।", "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 6c3a4df3d..923547f49 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -725,6 +725,7 @@ "enter_seed_phrase": "Unesite svoju sjemensku frazu", "add_contact": "Dodaj kontakt", "exchange_provider_unsupported": "${providerName} više nije podržan!", + "require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike", "camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.", "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 4c7f8c167..c6537f1b1 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -715,6 +715,7 @@ "enter_seed_phrase": "Masukkan frasa benih Anda", "add_contact": "Tambah kontak", "exchange_provider_unsupported": "${providerName} tidak lagi didukung!", + "require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal", "camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.", "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 5b2d46ac1..82955798f 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "Inserisci la tua frase di semi", "add_contact": "Aggiungi contatto", "exchange_provider_unsupported": "${providerName} non è più supportato!", + "require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni", "camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.", "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 36e8fe90f..e69b55cc6 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "シードフレーズを入力してください", "add_contact": "連絡先を追加", "exchange_provider_unsupported": "${providerName}はサポートされなくなりました!", + "require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要", "camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。", "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index d03de7731..ce65b820f 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -725,6 +725,7 @@ "enter_seed_phrase": "시드 문구를 입력하십시오", "add_contact": "주소록에 추가", "exchange_provider_unsupported": "${providerName}은 더 이상 지원되지 않습니다!", + "require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요", "camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.", "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요." } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index a844ba99f..5d015475f 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -725,6 +725,7 @@ "enter_seed_phrase": "သင့်ရဲ့မျိုးစေ့စကားစုကိုရိုက်ထည့်ပါ", "add_contact": "အဆက်အသွယ်ထည့်ပါ။", "exchange_provider_unsupported": "${providerName} မရှိတော့ပါ!", + "require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", "camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။", "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 6f3f24bb4..c05dab90a 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "Voer uw zaadzin in", "add_contact": "Contactpersoon toevoegen", "exchange_provider_unsupported": "${providerName} wordt niet langer ondersteund!", + "require_for_exchanges_to_external_wallets": "Vereist voor uitwisselingen naar externe portemonnees", "camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.", "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 2520d57a1..16bf88418 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "Wprowadź swoją frazę nasienną", "add_contact": "Dodaj kontakt", "exchange_provider_unsupported": "${providerName} nie jest już obsługiwany!", + "require_for_exchanges_to_external_wallets": "Wymagaj wymiany na portfele zewnętrzne", "camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.", "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 49fda1bee..18337cfdb 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -726,6 +726,7 @@ "enter_seed_phrase": "Digite sua frase de semente", "add_contact": "Adicionar contato", "exchange_provider_unsupported": "${providerName} não é mais suportado!", + "require_for_exchanges_to_external_wallets": "Exigir trocas para carteiras externas", "camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.", "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index b4c4681b9..40deb5fb9 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "Введите свою семенную фразу", "add_contact": "Добавить контакт", "exchange_provider_unsupported": "${providerName} больше не поддерживается!", + "require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки", "camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.", "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку." } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 91c05c968..2da16ffcd 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -725,6 +725,7 @@ "enter_seed_phrase": "ป้อนวลีเมล็ดพันธุ์ของคุณ", "add_contact": "เพิ่มผู้ติดต่อ", "exchange_provider_unsupported": "${providerName} ไม่ได้รับการสนับสนุนอีกต่อไป!", + "require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก", "camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป", "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 546b1515c..231dd2db3 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -722,6 +722,7 @@ "enter_seed_phrase": "Ipasok ang iyong pariralang binhi", "add_contact": "Magdagdag ng contact", "exchange_provider_unsupported": "Ang ${providerName} ay hindi na suportado!", + "require_for_exchanges_to_external_wallets": "Kinakailangan para sa mga palitan sa mga panlabas na wallet", "camera_permission_is_required": "Kinakailangan ang pahintulot sa camera.\nMangyaring paganahin ito mula sa mga setting ng app.", "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 60e276513..54062b723 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -725,6 +725,7 @@ "enter_seed_phrase": "Tohum ifadenizi girin", "add_contact": "Kişi ekle", "exchange_provider_unsupported": "${providerName} artık desteklenmiyor!", + "require_for_exchanges_to_external_wallets": "Harici cüzdanlara geçiş yapılmasını zorunlu kılın", "camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.", "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 034260c13..0c5aaee59 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "Введіть свою насіннєву фразу", "add_contact": "Додати контакт", "exchange_provider_unsupported": "${providerName} більше не підтримується!", + "require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці", "camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.", "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 237fa24dd..ec4ccb5b8 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -719,6 +719,7 @@ "enter_seed_phrase": "اپنے بیج کا جملہ درج کریں", "add_contact": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮧﻄﺑﺍﺭ", "exchange_provider_unsupported": "${providerName} اب تعاون نہیں کیا جاتا ہے!", + "require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ", "camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ", "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index df06da974..d30d36cb7 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -721,6 +721,7 @@ "enter_seed_phrase": "Tẹ ọrọ-iru irugbin rẹ", "add_contact": "Fi olubasọrọ kun", "exchange_provider_unsupported": "${providerName} ko ni atilẹyin mọ!", + "require_for_exchanges_to_external_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ ita", "camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.", "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 4a464b50f..b68ffcc0e 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -726,6 +726,7 @@ "enter_seed_phrase": "输入您的种子短语", "add_contact": "增加联系人", "exchange_provider_unsupported": "${providerName}不再支持!", + "require_for_exchanges_to_external_wallets": "需要兑换到外部钱包", "camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。", "switchToETHWallet": "请切换到以太坊钱包并重试" } From 7710a19e827483ccab4ac40e1c0cf5f1543a66dd Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 3 Nov 2023 07:41:17 +0200 Subject: [PATCH 025/241] CW-502-Add-Monero-Account-Management-to-Home-Screen (#1140) * Add the monero account widget on the Home screen * [skip ci] add hasAccounts variable --- .../dashboard/widgets/balance_page.dart | 101 ++++++++++-------- .../widgets/home_screen_account_widget.dart | 69 ++++++++++++ .../dashboard/balance_view_model.dart | 3 + 3 files changed, 129 insertions(+), 44 deletions(-) create mode 100644 lib/src/screens/dashboard/widgets/home_screen_account_widget.dart diff --git a/lib/src/screens/dashboard/widgets/balance_page.dart b/lib/src/screens/dashboard/widgets/balance_page.dart index c8d7faf11..b4c4f71dc 100644 --- a/lib/src/screens/dashboard/widgets/balance_page.dart +++ b/lib/src/screens/dashboard/widgets/balance_page.dart @@ -1,17 +1,18 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/dashboard/widgets/home_screen_account_widget.dart'; import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart'; +import 'package:cake_wallet/src/widgets/introducing_card.dart'; import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; import 'package:cake_wallet/utils/feature_flag.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; -import 'package:flutter/material.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:auto_size_text/auto_size_text.dart'; -import 'package:cake_wallet/src/widgets/introducing_card.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; -import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; class BalancePage extends StatelessWidget { BalancePage({required this.dashboardViewModel, required this.settingsStore}); @@ -28,47 +29,59 @@ class BalancePage extends StatelessWidget { !dashboardViewModel.balanceViewModel.isReversing, child: SingleChildScrollView( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - SizedBox(height: 56), - Container( - margin: const EdgeInsets.only(left: 24, bottom: 16), - child: Observer( - builder: (_) { - return Row( - children: [ - Text( - dashboardViewModel.balanceViewModel.asset, - style: TextStyle( - fontSize: 24, - fontFamily: 'Lato', - fontWeight: FontWeight.w600, - color: - Theme.of(context).extension()!.pageTitleTextColor, - height: 1, - ), - maxLines: 1, - textAlign: TextAlign.center, - ), - if (dashboardViewModel.balanceViewModel.isHomeScreenSettingsEnabled) - InkWell( - onTap: () => Navigator.pushNamed(context, Routes.homeSettings, - arguments: dashboardViewModel.balanceViewModel), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Image.asset( - 'assets/images/home_screen_settings_icon.png', - color: Theme.of(context) - .extension()! - .pageTitleTextColor, + Observer( + builder: (_) => dashboardViewModel.balanceViewModel.hasAccounts + ? HomeScreenAccountWidget( + walletName: dashboardViewModel.name, + accountName: dashboardViewModel.subname) + : Column( + children: [ + SizedBox(height: 56), + Container( + margin: const EdgeInsets.only(left: 24, bottom: 16), + child: Observer( + builder: (_) { + return Row( + children: [ + Text( + dashboardViewModel.balanceViewModel.asset, + style: TextStyle( + fontSize: 24, + fontFamily: 'Lato', + fontWeight: FontWeight.w600, + color: Theme.of(context) + .extension()! + .pageTitleTextColor, + height: 1, + ), + maxLines: 1, + textAlign: TextAlign.center, + ), + if (dashboardViewModel + .balanceViewModel.isHomeScreenSettingsEnabled) + InkWell( + onTap: () => Navigator.pushNamed( + context, Routes.homeSettings, + arguments: dashboardViewModel.balanceViewModel), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Image.asset( + 'assets/images/home_screen_settings_icon.png', + color: Theme.of(context) + .extension()! + .pageTitleTextColor, + ), + ), + ), + ], + ); + }, ), ), - ), - ], - ); - }, - ), - ), + ], + )), Observer( builder: (_) { if (dashboardViewModel.balanceViewModel.isShowCard && diff --git a/lib/src/screens/dashboard/widgets/home_screen_account_widget.dart b/lib/src/screens/dashboard/widgets/home_screen_account_widget.dart new file mode 100644 index 000000000..f548a8737 --- /dev/null +++ b/lib/src/screens/dashboard/widgets/home_screen_account_widget.dart @@ -0,0 +1,69 @@ +import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/src/screens/monero_accounts/monero_account_list_page.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:flutter/material.dart'; + +class HomeScreenAccountWidget extends StatelessWidget { + HomeScreenAccountWidget({this.walletName, this.accountName}); + + final String? walletName; + final String? accountName; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () async { + await showPopUp( + context: context, + builder: (_) => getIt.get()); + }, + child: Container( + height: 100.0, + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + child: Text( + walletName ?? '', + style: TextStyle( + fontSize: 22.0, + fontWeight: FontWeight.bold, + fontFamily: 'Lato', + color: Theme.of(context).extension()!.pageTitleTextColor, + ), + ), + ), + SizedBox( + height: 5.0, + ), + Container( + child: Text( + accountName ?? '', + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.bold, + fontFamily: 'Lato', + color: Theme.of(context).extension()!.pageTitleTextColor, + ), + ), + ), + ], + ), + Container( + child: Icon( + Icons.keyboard_arrow_down, + color: Theme.of(context).extension()!.pageTitleTextColor, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index b0e60963d..06d05b3a3 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -83,6 +83,9 @@ abstract class BalanceViewModelBase with Store { @computed bool get isHomeScreenSettingsEnabled => wallet.type == WalletType.ethereum; + @computed + bool get hasAccounts => wallet.type == WalletType.monero; + @computed SortBalanceBy get sortBalanceBy => settingsStore.sortBalanceBy; From 2d454e0e486bf0afa81d977d8ef33506636f6a2e Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 3 Nov 2023 07:42:18 +0200 Subject: [PATCH 026/241] CW-511-Tablet-iPad-keyboard-issue (#1143) * fix keyboard issue * Update responsive_layout_util.dart * fix close button color * minor fix * [skip ci] Update pin_code_widget.dart * Update main.dart * fix qr widget overflow issue * Fix minor UI issue --------- Co-authored-by: Omar Hatem --- lib/di.dart | 2 +- lib/main.dart | 23 +- lib/src/screens/dashboard/dashboard_page.dart | 29 +-- .../dashboard/widgets/address_page.dart | 12 +- .../dashboard/widgets/transactions_page.dart | 2 +- lib/src/screens/exchange/exchange_page.dart | 4 +- .../screens/new_wallet/new_wallet_page.dart | 2 +- .../new_wallet/new_wallet_type_page.dart | 2 +- lib/src/screens/pin_code/pin_code_widget.dart | 2 +- .../screens/receive/anonpay_invoice_page.dart | 2 +- .../receive/widgets/currency_input_field.dart | 2 +- .../screens/receive/widgets/qr_widget.dart | 223 +++++++++--------- .../restore/restore_from_backup_page.dart | 2 +- .../screens/restore/restore_options_page.dart | 2 +- .../screens/restore/wallet_restore_page.dart | 2 +- lib/src/screens/seed/pre_seed_page.dart | 2 +- lib/src/screens/seed/wallet_seed_page.dart | 2 +- lib/src/screens/send/send_page.dart | 4 +- lib/src/screens/send/widgets/send_card.dart | 6 +- .../settings/display_settings_page.dart | 2 +- .../screens/wallet_list/wallet_list_page.dart | 2 +- lib/src/screens/welcome/welcome_page.dart | 2 +- lib/src/widgets/add_template_button.dart | 2 +- lib/src/widgets/address_text_field.dart | 2 +- lib/src/widgets/alert_background.dart | 2 +- lib/src/widgets/check_box_picker.dart | 2 +- lib/src/widgets/picker.dart | 2 +- .../widgets/picker_inner_wrapper_widget.dart | 4 +- lib/src/widgets/picker_wrapper_widget.dart | 2 +- lib/src/widgets/primary_button.dart | 8 +- lib/utils/responsive_layout_util.dart | 73 +++--- 31 files changed, 222 insertions(+), 206 deletions(-) diff --git a/lib/di.dart b/lib/di.dart index b0caf5899..53620d3e8 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -280,7 +280,7 @@ Future setup({ powNodeSource: _powNodeSource, isBitcoinBuyEnabled: isBitcoinBuyEnabled, // Enforce darkTheme on platforms other than mobile till the design for other themes is completed - initialTheme: ResponsiveLayoutUtil.instance.isMobile && DeviceInfo.instance.isMobile + initialTheme: responsiveLayoutUtil.shouldRenderMobileUI && DeviceInfo.instance.isMobile ? null : ThemeList.darkTheme, ); diff --git a/lib/main.dart b/lib/main.dart index d5b0e2f81..6807e9185 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/entities/language_service.dart'; import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/locales/locale.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; +import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/exception_handler.dart'; import 'package:cw_core/address_info.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; @@ -322,22 +323,20 @@ class _Home extends StatefulWidget { class _HomeState extends State<_Home> { @override void didChangeDependencies() { - if (!ResponsiveLayoutUtil.instance.isMobile) { - _setOrientation(context); - } + _setOrientation(context); + super.didChangeDependencies(); } void _setOrientation(BuildContext context) { - final orientation = MediaQuery.of(context).orientation; - final width = MediaQuery.of(context).size.width; - final height = MediaQuery.of(context).size.height; - if (orientation == Orientation.portrait && width < height) { - SystemChrome.setPreferredOrientations( - [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); - } else if (orientation == Orientation.landscape && width > height) { - SystemChrome.setPreferredOrientations( - [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); + if (!DeviceInfo.instance.isDesktop) { + if (responsiveLayoutUtil.shouldRenderMobileUI) { + SystemChrome.setPreferredOrientations( + [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); + } else { + SystemChrome.setPreferredOrientations( + [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); + } } } diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index d7ba8410e..d4662c625 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -52,26 +52,23 @@ class DashboardPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - body: LayoutBuilder( - builder: (context, constraints) { + body: Observer( + builder: (_) { + final dashboardPageView = _DashboardPageView( + balancePage: balancePage, + bottomSheetService: bottomSheetService, + dashboardViewModel: dashboardViewModel, + addressListViewModel: addressListViewModel, + ); + if (DeviceInfo.instance.isDesktop) { - if (constraints.maxWidth > ResponsiveLayoutUtil.kDesktopMaxDashBoardWidthConstraint) { + if (responsiveLayoutUtil.screenWidth > ResponsiveLayoutUtilBase.kDesktopMaxDashBoardWidthConstraint) { return getIt.get(); } else { - return _DashboardPageView( - balancePage: balancePage, - bottomSheetService: bottomSheetService, - dashboardViewModel: dashboardViewModel, - addressListViewModel: addressListViewModel, - ); + return dashboardPageView; } - } else if (ResponsiveLayoutUtil.instance.shouldRenderMobileUI()) { - return _DashboardPageView( - bottomSheetService: bottomSheetService, - balancePage: balancePage, - dashboardViewModel: dashboardViewModel, - addressListViewModel: addressListViewModel, - ); + } else if (responsiveLayoutUtil.shouldRenderMobileUI) { + return dashboardPageView; } else { return getIt.get(); } diff --git a/lib/src/screens/dashboard/widgets/address_page.dart b/lib/src/screens/dashboard/widgets/address_page.dart index d584ce95b..c57613fa5 100644 --- a/lib/src/screens/dashboard/widgets/address_page.dart +++ b/lib/src/screens/dashboard/widgets/address_page.dart @@ -64,7 +64,15 @@ class AddressPage extends BasePage { @override Widget? leading(BuildContext context) { - bool isMobileView = ResponsiveLayoutUtil.instance.isMobile; + final _backButton = Icon( + Icons.arrow_back_ios, + color: titleColor(context), + size: 16, + ); + final _closeButton = + currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage; + + bool isMobileView = responsiveLayoutUtil.shouldRenderMobileUI; return MergeSemantics( child: SizedBox( @@ -79,7 +87,7 @@ class AddressPage extends BasePage { overlayColor: MaterialStateColor.resolveWith((states) => Colors.transparent), ), onPressed: () => onClose(context), - child: !isMobileView ? closeButton(context) : backButton(context), + child: !isMobileView ? _closeButton : _backButton, ), ), ), diff --git a/lib/src/screens/dashboard/widgets/transactions_page.dart b/lib/src/screens/dashboard/widgets/transactions_page.dart index 3f6b8a3c6..5c7b78f3a 100644 --- a/lib/src/screens/dashboard/widgets/transactions_page.dart +++ b/lib/src/screens/dashboard/widgets/transactions_page.dart @@ -34,7 +34,7 @@ class TransactionsPage extends StatelessWidget { onLongPressUp: () => dashboardViewModel.balanceViewModel.isReversing = !dashboardViewModel.balanceViewModel.isReversing, child: Container( - color: ResponsiveLayoutUtil.instance.isMobile + color: responsiveLayoutUtil.shouldRenderMobileUI ? null : Theme.of(context).colorScheme.background, padding: EdgeInsets.only(top: 24, bottom: 24), diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 7ff9e6c30..1f441ea99 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -127,7 +127,7 @@ class ExchangePage extends BasePage { final _closeButton = currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage; - bool isMobileView = ResponsiveLayoutUtil.instance.isMobile; + bool isMobileView = responsiveLayoutUtil.shouldRenderMobileUI; return MergeSemantics( child: SizedBox( @@ -705,7 +705,7 @@ class ExchangePage extends BasePage { }, )); - if (ResponsiveLayoutUtil.instance.isMobile) { + if (responsiveLayoutUtil.shouldRenderMobileUI) { return MobileExchangeCardsSection( firstExchangeCard: firstExchangeCard, secondExchangeCard: secondExchangeCard, diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index b9dcc5ae3..5577fcd88 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -96,7 +96,7 @@ class _WalletNameFormState extends State { content: Center( child: ConstrainedBox( constraints: - BoxConstraints(maxWidth: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint), + BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ diff --git a/lib/src/screens/new_wallet/new_wallet_type_page.dart b/lib/src/screens/new_wallet/new_wallet_type_page.dart index 6f3bb078b..225e5b82d 100644 --- a/lib/src/screens/new_wallet/new_wallet_type_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_type_page.dart @@ -70,7 +70,7 @@ class WalletTypeFormState extends State { Widget build(BuildContext context) { return Center( child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint), + constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: Column( children: [ Padding( diff --git a/lib/src/screens/pin_code/pin_code_widget.dart b/lib/src/screens/pin_code/pin_code_widget.dart index 9b22fa822..36328aee2 100644 --- a/lib/src/screens/pin_code/pin_code_widget.dart +++ b/lib/src/screens/pin_code/pin_code_widget.dart @@ -191,7 +191,7 @@ class PinCodeState extends State { child: Center( child: ConstrainedBox( constraints: BoxConstraints( - maxWidth: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint, + maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint, ), child: Container( key: _gridViewKey, diff --git a/lib/src/screens/receive/anonpay_invoice_page.dart b/lib/src/screens/receive/anonpay_invoice_page.dart index deda679c5..fc835c72d 100644 --- a/lib/src/screens/receive/anonpay_invoice_page.dart +++ b/lib/src/screens/receive/anonpay_invoice_page.dart @@ -99,7 +99,7 @@ class AnonPayInvoicePage extends BasePage { child: ScrollableWithBottomSection( contentPadding: EdgeInsets.only(bottom: 24), content: Container( - decoration: ResponsiveLayoutUtil.instance.isMobile ? BoxDecoration( + decoration: responsiveLayoutUtil.shouldRenderMobileUI ? BoxDecoration( borderRadius: BorderRadius.only( bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)), gradient: LinearGradient( diff --git a/lib/src/screens/receive/widgets/currency_input_field.dart b/lib/src/screens/receive/widgets/currency_input_field.dart index 20e7bd660..1241b2ba7 100644 --- a/lib/src/screens/receive/widgets/currency_input_field.dart +++ b/lib/src/screens/receive/widgets/currency_input_field.dart @@ -32,7 +32,7 @@ class CurrencyInputField extends StatelessWidget { ); // This magic number for wider screen sets the text input focus at center of the inputfield final _width = - ResponsiveLayoutUtil.instance.isMobile ? MediaQuery.of(context).size.width : 500; + responsiveLayoutUtil.shouldRenderMobileUI ? MediaQuery.of(context).size.width : 500; return Column( children: [ diff --git a/lib/src/screens/receive/widgets/qr_widget.dart b/lib/src/screens/receive/widgets/qr_widget.dart index a34893cd8..bbfd4d5c1 100644 --- a/lib/src/screens/receive/widgets/qr_widget.dart +++ b/lib/src/screens/receive/widgets/qr_widget.dart @@ -38,129 +38,134 @@ class QRWidget extends StatelessWidget { final copyImage = Image.asset('assets/images/copy_address.png', color: Theme.of(context).extension()!.qrWidgetCopyButtonColor); - return Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Column( - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 12), - child: Text( - S.of(context).qr_fullscreen, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Theme.of(context).extension()!.textColor), - ), - ), - Row( - children: [ - Spacer(flex: 3), - Observer( - builder: (_) => Flexible( - flex: 5, - child: GestureDetector( - onTap: () { - BrightnessUtil.changeBrightnessForFunction( - () async { - await Navigator.pushNamed(context, Routes.fullscreenQR, - arguments: QrViewData( - data: addressListViewModel.uri.toString(), - heroTag: heroTag, - )); + return Center( + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Column( + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 12), + child: Text( + S.of(context).qr_fullscreen, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Theme.of(context).extension()!.textColor), + ), + ), + Row( + children: [ + Spacer(flex: 3), + Observer( + builder: (_) => Flexible( + flex: 5, + child: GestureDetector( + onTap: () { + BrightnessUtil.changeBrightnessForFunction( + () async { + await Navigator.pushNamed(context, Routes.fullscreenQR, + arguments: QrViewData( + data: addressListViewModel.uri.toString(), + heroTag: heroTag, + )); + }, + ); }, - ); - }, - child: Hero( - tag: Key(heroTag ?? addressListViewModel.uri.toString()), - child: Center( - child: AspectRatio( - aspectRatio: 1.0, - child: Container( - padding: EdgeInsets.all(5), - decoration: BoxDecoration( - border: Border.all( - width: 3, - color: Theme.of(context).extension()!.textColor, - ), - ), - child: Container( + child: Hero( + tag: Key(heroTag ?? addressListViewModel.uri.toString()), + child: Center( + child: AspectRatio( + aspectRatio: 1.0, + child: Container( + padding: EdgeInsets.all(5), decoration: BoxDecoration( border: Border.all( width: 3, - color:Colors.white, + color: + Theme.of(context).extension()!.textColor, ), ), - child: QrImage(data: addressListViewModel.uri.toString())), + child: Container( + decoration: BoxDecoration( + border: Border.all( + width: 3, + color: Colors.white, + ), + ), + child: QrImage(data: addressListViewModel.uri.toString())), + ), + ), ), ), ), ), ), - ), - ), - Spacer(flex: 3) - ], - ), - ], - ), - Observer(builder: (_) { - return Padding( - padding: EdgeInsets.only(top: 10), - child: Row( - children: [ - Expanded( - child: Form( - key: formKey, - child: CurrencyInputField( - focusNode: amountTextFieldFocusNode, - controller: amountController, - onTapPicker: () => _presentPicker(context), - selectedCurrency: addressListViewModel.selectedCurrency, - isLight: isLight, - ), - ), - ), - ], - ), - ); - }), - Padding( - padding: EdgeInsets.only(top: 20, bottom: 8), - child: Builder( - builder: (context) => Observer( - builder: (context) => GestureDetector( - onTap: () { - Clipboard.setData(ClipboardData(text: addressListViewModel.address.address)); - showBar(context, S.of(context).copied_to_clipboard); - }, - child: Row( - mainAxisSize: MainAxisSize.max, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Text( - addressListViewModel.address.address, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.w500, - color: Theme.of(context).extension()!.textColor), - ), - ), - Padding( - padding: EdgeInsets.only(left: 12), - child: copyImage, - ) + Spacer(flex: 3) ], ), - ), + ], ), - ), - ) - ], + Observer(builder: (_) { + return Padding( + padding: EdgeInsets.only(top: 10), + child: Row( + children: [ + Expanded( + child: Form( + key: formKey, + child: CurrencyInputField( + focusNode: amountTextFieldFocusNode, + controller: amountController, + onTapPicker: () => _presentPicker(context), + selectedCurrency: addressListViewModel.selectedCurrency, + isLight: isLight, + ), + ), + ), + ], + ), + ); + }), + Padding( + padding: EdgeInsets.only(top: 20, bottom: 8), + child: Builder( + builder: (context) => Observer( + builder: (context) => GestureDetector( + onTap: () { + Clipboard.setData(ClipboardData(text: addressListViewModel.address.address)); + showBar(context, S.of(context).copied_to_clipboard); + }, + child: Row( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Text( + addressListViewModel.address.address, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w500, + color: Theme.of(context).extension()!.textColor), + ), + ), + Padding( + padding: EdgeInsets.only(left: 12), + child: copyImage, + ) + ], + ), + ), + ), + ), + ) + ], + ), + ), ); } diff --git a/lib/src/screens/restore/restore_from_backup_page.dart b/lib/src/screens/restore/restore_from_backup_page.dart index bf944a6e1..c3440fb06 100644 --- a/lib/src/screens/restore/restore_from_backup_page.dart +++ b/lib/src/screens/restore/restore_from_backup_page.dart @@ -42,7 +42,7 @@ class RestoreFromBackupPage extends BasePage { return Center( child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint), + constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: Padding( padding: EdgeInsets.only(bottom: 24, left: 24, right: 24), child: Column(children: [ diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart index 2252551cc..e54c0da29 100644 --- a/lib/src/screens/restore/restore_options_page.dart +++ b/lib/src/screens/restore/restore_options_page.dart @@ -31,7 +31,7 @@ class RestoreOptionsPage extends BasePage { Widget body(BuildContext context) { return Center( child: Container( - width: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint, + width: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint, height: double.infinity, padding: EdgeInsets.symmetric(vertical: 24, horizontal: 24), child: SingleChildScrollView( diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index 649dadd19..4fa9e340d 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -163,7 +163,7 @@ class WalletRestorePage extends BasePage { color: Theme.of(context).colorScheme.background, child: Center( child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint), + constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ diff --git a/lib/src/screens/seed/pre_seed_page.dart b/lib/src/screens/seed/pre_seed_page.dart index 7e6bfb1de..bb6902a7e 100644 --- a/lib/src/screens/seed/pre_seed_page.dart +++ b/lib/src/screens/seed/pre_seed_page.dart @@ -35,7 +35,7 @@ class PreSeedPage extends BasePage { alignment: Alignment.center, padding: EdgeInsets.all(24), child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint), + constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ diff --git a/lib/src/screens/seed/wallet_seed_page.dart b/lib/src/screens/seed/wallet_seed_page.dart index fa17d7ccf..200b87b7d 100644 --- a/lib/src/screens/seed/wallet_seed_page.dart +++ b/lib/src/screens/seed/wallet_seed_page.dart @@ -93,7 +93,7 @@ class WalletSeedPage extends BasePage { padding: EdgeInsets.all(24), alignment: Alignment.center, child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint), + constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 6b35158e3..fca3684ca 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -69,7 +69,7 @@ class SendPage extends BasePage { final _closeButton = currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage; - bool isMobileView = ResponsiveLayoutUtil.instance.isMobile; + bool isMobileView = responsiveLayoutUtil.shouldRenderMobileUI; return MergeSemantics( child: SizedBox( @@ -98,7 +98,7 @@ class SendPage extends BasePage { double _sendCardHeight(BuildContext context) { final double initialHeight = sendViewModel.hasCoinControl ? 500 : 465; - if (!ResponsiveLayoutUtil.instance.isMobile) { + if (!responsiveLayoutUtil.shouldRenderMobileUI) { return initialHeight - 66; } return initialHeight; diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index ec1ee5087..65069e903 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -122,7 +122,7 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin with AutomaticKeepAliveClientMixin { await hideProgressText(); // only pop the wallets route in mobile as it will go back to dashboard page // in desktop platforms the navigation tree is different - if (ResponsiveLayoutUtil.instance.shouldRenderMobileUI()) { + if (responsiveLayoutUtil.shouldRenderMobileUI) { WidgetsBinding.instance.addPostFrameCallback((_) { Navigator.of(context).pop(); }); diff --git a/lib/src/screens/welcome/welcome_page.dart b/lib/src/screens/welcome/welcome_page.dart index 52de38021..2142fdf9b 100644 --- a/lib/src/screens/welcome/welcome_page.dart +++ b/lib/src/screens/welcome/welcome_page.dart @@ -70,7 +70,7 @@ class WelcomePage extends BasePage { padding: EdgeInsets.only(top: 64, bottom: 24, left: 24, right: 24), child: ConstrainedBox( constraints: BoxConstraints( - maxWidth: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint), + maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ diff --git a/lib/src/widgets/add_template_button.dart b/lib/src/widgets/add_template_button.dart index 667a103ab..a5e9f2e2a 100644 --- a/lib/src/widgets/add_template_button.dart +++ b/lib/src/widgets/add_template_button.dart @@ -27,7 +27,7 @@ class AddTemplateButton extends StatelessWidget { child: Container( height: 34, padding: EdgeInsets.symmetric( - horizontal: ResponsiveLayoutUtil.instance.isMobile ? 10 : 30), + horizontal: responsiveLayoutUtil.shouldRenderMobileUI ? 10 : 30), alignment: Alignment.center, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(20)), diff --git a/lib/src/widgets/address_text_field.dart b/lib/src/widgets/address_text_field.dart index fcdbad701..092a70422 100644 --- a/lib/src/widgets/address_text_field.dart +++ b/lib/src/widgets/address_text_field.dart @@ -100,7 +100,7 @@ class AddressTextField extends StatelessWidget { child: SizedBox( width: prefixIconWidth * options.length + (spaceBetweenPrefixIcons * options.length), child: Row( - mainAxisAlignment: ResponsiveLayoutUtil.instance.isMobile + mainAxisAlignment: responsiveLayoutUtil.shouldRenderMobileUI ? MainAxisAlignment.spaceBetween : MainAxisAlignment.end, children: [ diff --git a/lib/src/widgets/alert_background.dart b/lib/src/widgets/alert_background.dart index 0ced8ee06..56f10d1f6 100644 --- a/lib/src/widgets/alert_background.dart +++ b/lib/src/widgets/alert_background.dart @@ -25,7 +25,7 @@ class AlertBackground extends StatelessWidget { Theme.of(context).extension()!.backdropColor), child: Center( child: Container( - width: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint, + width: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint, child: child, ), ), diff --git a/lib/src/widgets/check_box_picker.dart b/lib/src/widgets/check_box_picker.dart index 71bfa7ee9..b4db82628 100644 --- a/lib/src/widgets/check_box_picker.dart +++ b/lib/src/widgets/check_box_picker.dart @@ -61,7 +61,7 @@ class CheckBoxPickerState extends State { child: ConstrainedBox( constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.65, - maxWidth: ResponsiveLayoutUtil.kPopupWidth, + maxWidth: ResponsiveLayoutUtilBase.kPopupWidth, ), child: Column( mainAxisSize: MainAxisSize.min, diff --git a/lib/src/widgets/picker.dart b/lib/src/widgets/picker.dart index 6b6543d2f..01b869b1b 100644 --- a/lib/src/widgets/picker.dart +++ b/lib/src/widgets/picker.dart @@ -151,7 +151,7 @@ class _PickerState extends State> { child: ConstrainedBox( constraints: BoxConstraints( maxHeight: containerHeight, - maxWidth: ResponsiveLayoutUtil.kPopupWidth, + maxWidth: ResponsiveLayoutUtilBase.kPopupWidth, ), child: Column( mainAxisSize: MainAxisSize.min, diff --git a/lib/src/widgets/picker_inner_wrapper_widget.dart b/lib/src/widgets/picker_inner_wrapper_widget.dart index 3d9a289bc..2dd61e948 100644 --- a/lib/src/widgets/picker_inner_wrapper_widget.dart +++ b/lib/src/widgets/picker_inner_wrapper_widget.dart @@ -52,7 +52,7 @@ class PickerInnerWrapperWidget extends StatelessWidget { itemsHeight != null && itemsHeight! <= containerHeight ? itemsHeight! : containerHeight, - maxWidth: ResponsiveLayoutUtil.kPopupWidth, + maxWidth: ResponsiveLayoutUtilBase.kPopupWidth, ), child: Column( children: children, @@ -77,7 +77,7 @@ class PickerInnerWrapperWidget extends StatelessWidget { child: ConstrainedBox( constraints: BoxConstraints( maxHeight: containerHeight, - maxWidth: ResponsiveLayoutUtil.kPopupWidth, + maxWidth: ResponsiveLayoutUtilBase.kPopupWidth, ), child: Column( children: children, diff --git a/lib/src/widgets/picker_wrapper_widget.dart b/lib/src/widgets/picker_wrapper_widget.dart index 244199936..f69bcd514 100644 --- a/lib/src/widgets/picker_wrapper_widget.dart +++ b/lib/src/widgets/picker_wrapper_widget.dart @@ -44,7 +44,7 @@ class PickerWrapperWidget extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: children, ), - SizedBox(height: ResponsiveLayoutUtil.kPopupSpaceHeight), + SizedBox(height: ResponsiveLayoutUtilBase.kPopupSpaceHeight), AlertCloseButton(bottom: closeButtonBottom), ], ), diff --git a/lib/src/widgets/primary_button.dart b/lib/src/widgets/primary_button.dart index c27169894..5f6b50f8b 100644 --- a/lib/src/widgets/primary_button.dart +++ b/lib/src/widgets/primary_button.dart @@ -26,7 +26,7 @@ class PrimaryButton extends StatelessWidget { @override Widget build(BuildContext context) { final content = ConstrainedBox( - constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint), + constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: SizedBox( width: double.infinity, height: 52.0, @@ -82,7 +82,7 @@ class LoadingPrimaryButton extends StatelessWidget { @override Widget build(BuildContext context) { return ConstrainedBox( - constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint), + constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: SizedBox( width: double.infinity, height: 52.0, @@ -138,7 +138,7 @@ class PrimaryIconButton extends StatelessWidget { @override Widget build(BuildContext context) { return ConstrainedBox( - constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint), + constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: SizedBox( width: double.infinity, height: 52.0, @@ -201,7 +201,7 @@ class PrimaryImageButton extends StatelessWidget { @override Widget build(BuildContext context) { return ConstrainedBox( - constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtil.kDesktopMaxWidthConstraint), + constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: SizedBox( width: double.infinity, height: 52.0, diff --git a/lib/utils/responsive_layout_util.dart b/lib/utils/responsive_layout_util.dart index 4c06b7a3c..428ab61cc 100644 --- a/lib/utils/responsive_layout_util.dart +++ b/lib/utils/responsive_layout_util.dart @@ -1,46 +1,53 @@ import 'package:flutter/material.dart'; +import 'package:mobx/mobx.dart'; -class ResponsiveLayoutUtil { +part 'responsive_layout_util.g.dart'; + +class _ResponsiveLayoutUtil = ResponsiveLayoutUtilBase with _$_ResponsiveLayoutUtil; + +abstract class ResponsiveLayoutUtilBase with Store, WidgetsBindingObserver { static const double _kMobileThreshold = 550; static const double kDesktopMaxWidthConstraint = 400; static const double kDesktopMaxDashBoardWidthConstraint = 900; static const double kPopupWidth = 400; static const double kPopupSpaceHeight = 100; - const ResponsiveLayoutUtil._(); - - static final instance = ResponsiveLayoutUtil._(); - - bool get isMobile => - MediaQueryData.fromWindow(WidgetsBinding.instance.window).size.shortestSide <= - _kMobileThreshold; - - bool shouldRenderMobileUI() { - final mediaQuery = MediaQueryData.fromWindow(WidgetsBinding.instance.window); - final orientation = mediaQuery.orientation; - final width = mediaQuery.size.width; - final height = mediaQuery.size.height; - if (isMobile || - (orientation == Orientation.portrait && width < height) || - (orientation == Orientation.landscape && width < height)) { - return true; - } else { - return false; - } + ResponsiveLayoutUtilBase() { + WidgetsBinding.instance.addObserver(this); + final initialMediaQuery = MediaQueryData.fromView(WidgetsBinding.instance!.window); + updateDeviceInfo(initialMediaQuery); } - /// Returns dynamic size. - /// - /// If screen size is mobile, it returns 66% ([scale]) of the [originalValue]. - double getDynamicSize( - double originalValue, { - double? mobileSize, - double? scale, - }) { - scale ??= 2 / 3; - mobileSize ??= originalValue * scale; - final value = isMobile ? mobileSize : originalValue; + @override + void didChangeMetrics() { + final mediaQuery = MediaQueryData.fromView(WidgetsBinding.instance!.window); + updateDeviceInfo(mediaQuery); + } - return value.roundToDouble(); + @observable + double screenWidth = 0.0; + + @observable + double screenHeight = 0.0; + + @observable + Orientation orientation = Orientation.portrait; + + @action + void updateDeviceInfo(MediaQueryData mediaQuery) { + orientation = mediaQuery.orientation; + screenWidth = mediaQuery.size.width; + screenHeight = mediaQuery.size.height; + } + + @computed + bool get shouldRenderMobileUI { + return (screenWidth <= _kMobileThreshold) || + (orientation == Orientation.portrait && screenWidth < screenHeight) || + (orientation == Orientation.landscape && screenWidth < screenHeight); } } + +_ResponsiveLayoutUtil _singletonResponsiveLayoutUtil = _ResponsiveLayoutUtil(); + +_ResponsiveLayoutUtil get responsiveLayoutUtil => _singletonResponsiveLayoutUtil; From ca6ccf1cf9b66ae2e2f343cff89b77545c0b9482 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 3 Nov 2023 21:23:11 +0200 Subject: [PATCH 027/241] CW-506-Add-a-switch-to-enable-disable-domain-lookups (#1155) * looks up domain ui * update address resolv func * add localization * minor fixes * Revert "Merge branch 'main' into CW-506-Add-a-switch-to-enable-disable-domain-lookups" This reverts commit 92924a90e828cc9adf0ac8d517ae32ef316353fd, reversing changes made to 5a2a20305404ed8e83e0b5974c0a58d703264bcd. * Revert "Revert "Merge branch 'main' into CW-506-Add-a-switch-to-enable-disable-domain-lookups"" This reverts commit 00cf6a1cadb5bca4798d42c1a3566cd8772bb6bb. * fix merge commit --- lib/core/backup_service.dart | 36 ++++++ lib/di.dart | 8 +- lib/entities/parse_address_from_domain.dart | 111 ++++++++++-------- lib/entities/preferences_key.dart | 6 + lib/router.dart | 5 + lib/routes.dart | 1 + .../screens/settings/domain_lookups_page.dart | 56 +++++++++ lib/src/screens/settings/privacy_page.dart | 6 + lib/store/settings_store.dart | 72 ++++++++++++ .../settings/privacy_settings_view_model.dart | 39 +++++- res/values/strings_ar.arb | 1 + res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 1 + res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 1 + res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 1 + res/values/strings_my.arb | 1 + res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_th.arb | 1 + res/values/strings_tl.arb | 1 + res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + 36 files changed, 316 insertions(+), 50 deletions(-) create mode 100644 lib/src/screens/settings/domain_lookups_page.dart diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index d439969f5..520447dd4 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -246,6 +246,12 @@ class BackupService { final sortBalanceTokensBy = data[PreferencesKey.sortBalanceBy] as int?; final pinNativeTokenAtTop = data[PreferencesKey.pinNativeTokenAtTop] as bool?; final useEtherscan = data[PreferencesKey.useEtherscan] as bool?; + final lookupsTwitter = data[PreferencesKey.lookupsTwitter] as bool?; + final lookupsMastodon = data[PreferencesKey.lookupsMastodon] as bool?; + final lookupsYatService = data[PreferencesKey.lookupsYatService] as bool?; + final lookupsUnstoppableDomains = data[PreferencesKey.lookupsUnstoppableDomains] as bool?; + final lookupsOpenAlias = data[PreferencesKey.lookupsOpenAlias] as bool?; + final lookupsENS = data[PreferencesKey.lookupsENS] as bool?; final syncAll = data[PreferencesKey.syncAllKey] as bool?; final syncMode = data[PreferencesKey.syncModeKey] as int?; final autoGenerateSubaddressStatus = data[PreferencesKey.autoGenerateSubaddressStatusKey] as int?; @@ -373,6 +379,24 @@ class BackupService { if (useEtherscan != null) await _sharedPreferences.setBool(PreferencesKey.useEtherscan, useEtherscan); + if (lookupsTwitter != null) + await _sharedPreferences.setBool(PreferencesKey.lookupsTwitter, lookupsTwitter); + + if (lookupsMastodon != null) + await _sharedPreferences.setBool(PreferencesKey.lookupsMastodon, lookupsMastodon); + + if (lookupsYatService != null) + await _sharedPreferences.setBool(PreferencesKey.lookupsYatService, lookupsYatService); + + if (lookupsUnstoppableDomains != null) + await _sharedPreferences.setBool(PreferencesKey.lookupsUnstoppableDomains, lookupsUnstoppableDomains); + + if (lookupsOpenAlias != null) + await _sharedPreferences.setBool(PreferencesKey.lookupsOpenAlias, lookupsOpenAlias); + + if (lookupsENS != null) + await _sharedPreferences.setBool(PreferencesKey.lookupsENS, lookupsENS); + if (syncAll != null) await _sharedPreferences.setBool(PreferencesKey.syncAllKey, syncAll); @@ -529,6 +553,18 @@ class BackupService { _sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop), PreferencesKey.useEtherscan: _sharedPreferences.getBool(PreferencesKey.useEtherscan), + PreferencesKey.lookupsTwitter: + _sharedPreferences.getBool(PreferencesKey.lookupsTwitter), + PreferencesKey.lookupsMastodon: + _sharedPreferences.getBool(PreferencesKey.lookupsMastodon), + PreferencesKey.lookupsYatService: + _sharedPreferences.getBool(PreferencesKey.lookupsYatService), + PreferencesKey.lookupsUnstoppableDomains: + _sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains), + PreferencesKey.lookupsOpenAlias: + _sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias), + PreferencesKey.lookupsENS: + _sharedPreferences.getBool(PreferencesKey.lookupsENS), PreferencesKey.syncModeKey: _sharedPreferences.getInt(PreferencesKey.syncModeKey), PreferencesKey.syncAllKey: diff --git a/lib/di.dart b/lib/di.dart index 53620d3e8..10662d816 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -36,6 +36,7 @@ import 'package:cake_wallet/src/screens/receive/anonpay_invoice_page.dart'; import 'package:cake_wallet/src/screens/receive/anonpay_receive_page.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_choose_derivation.dart'; import 'package:cake_wallet/src/screens/settings/display_settings_page.dart'; +import 'package:cake_wallet/src/screens/settings/domain_lookups_page.dart'; import 'package:cake_wallet/src/screens/settings/manage_nodes_page.dart'; import 'package:cake_wallet/src/screens/settings/other_settings_page.dart'; import 'package:cake_wallet/src/screens/settings/privacy_page.dart'; @@ -751,6 +752,8 @@ Future setup({ getIt.registerFactory(() => PrivacyPage(getIt.get())); + getIt.registerFactory(() => DomainLookupsPage(getIt.get())); + getIt.registerFactory(() => DisplaySettingsPage(getIt.get())); getIt.registerFactory(() => OtherSettingsPage(getIt.get())); @@ -981,7 +984,10 @@ Future setup({ getIt.registerFactory(() => YatService()); getIt.registerFactory(() => - AddressResolver(yatService: getIt.get(), wallet: getIt.get().wallet!)); + AddressResolver( + yatService: getIt.get(), + wallet: getIt.get().wallet!, + settingsStore: getIt.get())); getIt.registerFactoryParam( (QrViewData viewData, _) => FullscreenQRPage(qrViewData: viewData)); diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart index 6e52a93c7..e184f5649 100644 --- a/lib/entities/parse_address_from_domain.dart +++ b/lib/entities/parse_address_from_domain.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/entities/parsed_address.dart'; import 'package:cake_wallet/entities/unstoppable_domain_address.dart'; import 'package:cake_wallet/entities/emoji_string_extension.dart'; import 'package:cake_wallet/mastodon/mastodon_api.dart'; +import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/twitter/twitter_api.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/wallet_base.dart'; @@ -13,11 +14,13 @@ import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/entities/fio_address_provider.dart'; class AddressResolver { - AddressResolver({required this.yatService, required this.wallet}) : walletType = wallet.type; + AddressResolver({required this.yatService, required this.wallet, required this.settingsStore}) + : walletType = wallet.type; final YatService yatService; final WalletType walletType; final WalletBase wallet; + final SettingsStore settingsStore; static const unstoppableDomains = [ 'crypto', @@ -58,51 +61,55 @@ class AddressResolver { Future resolve(String text, String ticker) async { try { if (text.startsWith('@') && !text.substring(1).contains('@')) { - final formattedName = text.substring(1); - final twitterUser = await TwitterApi.lookupUserByName(userName: formattedName); - final addressFromBio = extractAddressByType( - raw: twitterUser.description, type: CryptoCurrency.fromString(ticker)); - if (addressFromBio != null) { - return ParsedAddress.fetchTwitterAddress(address: addressFromBio, name: text); - } + if(settingsStore.lookupsTwitter) { + final formattedName = text.substring(1); + final twitterUser = await TwitterApi.lookupUserByName(userName: formattedName); + final addressFromBio = extractAddressByType( + raw: twitterUser.description, type: CryptoCurrency.fromString(ticker)); + if (addressFromBio != null) { + return ParsedAddress.fetchTwitterAddress(address: addressFromBio, name: text); + } - final pinnedTweet = twitterUser.pinnedTweet?.text; - if (pinnedTweet != null) { - final addressFromPinnedTweet = - extractAddressByType(raw: pinnedTweet, type: CryptoCurrency.fromString(ticker)); - if (addressFromPinnedTweet != null) { - return ParsedAddress.fetchTwitterAddress(address: addressFromPinnedTweet, name: text); + final pinnedTweet = twitterUser.pinnedTweet?.text; + if (pinnedTweet != null) { + final addressFromPinnedTweet = + extractAddressByType(raw: pinnedTweet, type: CryptoCurrency.fromString(ticker)); + if (addressFromPinnedTweet != null) { + return ParsedAddress.fetchTwitterAddress(address: addressFromPinnedTweet, name: text); + } } } } if (text.startsWith('@') && text.contains('@', 1) && text.contains('.', 1)) { - final subText = text.substring(1); - final hostNameIndex = subText.indexOf('@'); - final hostName = subText.substring(hostNameIndex + 1); - final userName = subText.substring(0, hostNameIndex); + if (settingsStore.lookupsMastodon) { + final subText = text.substring(1); + final hostNameIndex = subText.indexOf('@'); + final hostName = subText.substring(hostNameIndex + 1); + final userName = subText.substring(0, hostNameIndex); - final mastodonUser = - await MastodonAPI.lookupUserByUserName(userName: userName, apiHost: hostName); + final mastodonUser = + await MastodonAPI.lookupUserByUserName(userName: userName, apiHost: hostName); - if (mastodonUser != null) { - String? addressFromBio = - extractAddressByType(raw: mastodonUser.note, type: CryptoCurrency.fromString(ticker)); + if (mastodonUser != null) { + String? addressFromBio = + extractAddressByType(raw: mastodonUser.note, type: CryptoCurrency.fromString(ticker)); - if (addressFromBio != null) { - return ParsedAddress.fetchMastodonAddress(address: addressFromBio, name: text); - } else { - final pinnedPosts = - await MastodonAPI.getPinnedPosts(userId: mastodonUser.id, apiHost: hostName); + if (addressFromBio != null) { + return ParsedAddress.fetchMastodonAddress(address: addressFromBio, name: text); + } else { + final pinnedPosts = + await MastodonAPI.getPinnedPosts(userId: mastodonUser.id, apiHost: hostName); - if (pinnedPosts.isNotEmpty) { - final userPinnedPostsText = pinnedPosts.map((item) => item.content).join('\n'); - String? addressFromPinnedPost = extractAddressByType( - raw: userPinnedPostsText, type: CryptoCurrency.fromString(ticker)); + if (pinnedPosts.isNotEmpty) { + final userPinnedPostsText = pinnedPosts.map((item) => item.content).join('\n'); + String? addressFromPinnedPost = extractAddressByType( + raw: userPinnedPostsText, type: CryptoCurrency.fromString(ticker)); - if (addressFromPinnedPost != null) { - return ParsedAddress.fetchMastodonAddress( - address: addressFromPinnedPost, name: text); + if (addressFromPinnedPost != null) { + return ParsedAddress.fetchMastodonAddress( + address: addressFromPinnedPost, name: text); + } } } } @@ -117,9 +124,11 @@ class AddressResolver { } } if (text.hasOnlyEmojis) { - if (walletType != WalletType.haven) { - final addresses = await yatService.fetchYatAddress(text, ticker); - return ParsedAddress.fetchEmojiAddress(addresses: addresses, name: text); + if(settingsStore.lookupsYatService) { + if (walletType != WalletType.haven) { + final addresses = await yatService.fetchYatAddress(text, ticker); + return ParsedAddress.fetchEmojiAddress(addresses: addresses, name: text); + } } } final formattedName = OpenaliasRecord.formatDomainName(text); @@ -131,23 +140,29 @@ class AddressResolver { } if (unstoppableDomains.any((domain) => name.trim() == domain)) { - final address = await fetchUnstoppableDomainAddress(text, ticker); - return ParsedAddress.fetchUnstoppableDomainAddress(address: address, name: text); + if(settingsStore.lookupsUnstoppableDomains) { + final address = await fetchUnstoppableDomainAddress(text, ticker); + return ParsedAddress.fetchUnstoppableDomainAddress(address: address, name: text); + } } if (text.endsWith(".eth")) { - final address = await EnsRecord.fetchEnsAddress(text, wallet: wallet); - if (address.isNotEmpty && address != "0x0000000000000000000000000000000000000000") { - return ParsedAddress.fetchEnsAddress(name: text, address: address); + if (settingsStore.lookupsENS) { + final address = await EnsRecord.fetchEnsAddress(text, wallet: wallet); + if (address.isNotEmpty && address != "0x0000000000000000000000000000000000000000") { + return ParsedAddress.fetchEnsAddress(name: text, address: address); + } } } if (formattedName.contains(".")) { - final txtRecord = await OpenaliasRecord.lookupOpenAliasRecord(formattedName); - if (txtRecord != null) { - final record = await OpenaliasRecord.fetchAddressAndName( - formattedName: formattedName, ticker: ticker, txtRecord: txtRecord); - return ParsedAddress.fetchOpenAliasAddress(record: record, name: text); + if(settingsStore.lookupsOpenAlias) { + final txtRecord = await OpenaliasRecord.lookupOpenAliasRecord(formattedName); + if (txtRecord != null) { + final record = await OpenaliasRecord.fetchAddressAndName( + formattedName: formattedName, ticker: ticker, txtRecord: txtRecord); + return ParsedAddress.fetchOpenAliasAddress(record: record, name: text); + } } } } catch (e) { diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index fe9182e97..5ecd1bcc7 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -50,6 +50,12 @@ class PreferencesKey { static const sortBalanceBy = 'sort_balance_by'; static const pinNativeTokenAtTop = 'pin_native_token_at_top'; static const useEtherscan = 'use_etherscan'; + static const lookupsTwitter = 'looks_up_twitter'; + static const lookupsMastodon = 'looks_up_mastodon'; + static const lookupsYatService = 'looks_up_mastodon'; + static const lookupsUnstoppableDomains = 'looks_up_mastodon'; + static const lookupsOpenAlias = 'looks_up_mastodon'; + static const lookupsENS = 'looks_up_ens'; static String moneroWalletUpdateV1Key(String name) => '${PreferencesKey.moneroWalletPasswordUpdateV1Base}_${name}'; diff --git a/lib/router.dart b/lib/router.dart index 90f0355a6..1211bbcb6 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -24,6 +24,7 @@ import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart import 'package:cake_wallet/src/screens/restore/wallet_restore_choose_derivation.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'; +import 'package:cake_wallet/src/screens/settings/domain_lookups_page.dart'; import 'package:cake_wallet/src/screens/settings/manage_nodes_page.dart'; import 'package:cake_wallet/src/screens/settings/other_settings_page.dart'; import 'package:cake_wallet/src/screens/settings/privacy_page.dart'; @@ -322,6 +323,10 @@ Route createRoute(RouteSettings settings) { return CupertinoPageRoute( fullscreenDialog: true, builder: (_) => getIt.get()); + case Routes.domainLookupsPage: + return CupertinoPageRoute( + fullscreenDialog: true, builder: (_) => getIt.get()); + case Routes.displaySettingsPage: return CupertinoPageRoute( fullscreenDialog: true, builder: (_) => getIt.get()); diff --git a/lib/routes.dart b/lib/routes.dart index 832795a2b..0b4e8817d 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -81,6 +81,7 @@ class Routes { static const connectionSync = '/connection_sync_page'; static const securityBackupPage = '/security_and_backup_page'; static const privacyPage = '/privacy_page'; + static const domainLookupsPage = '/domain_lookups_page'; static const displaySettingsPage = '/display_settings_page'; static const otherSettingsPage = '/other_settings_page'; static const advancedPrivacySettings = '/advanced_privacy_settings'; diff --git a/lib/src/screens/settings/domain_lookups_page.dart b/lib/src/screens/settings/domain_lookups_page.dart new file mode 100644 index 000000000..80849b8ea --- /dev/null +++ b/lib/src/screens/settings/domain_lookups_page.dart @@ -0,0 +1,56 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; +import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class DomainLookupsPage extends BasePage { + DomainLookupsPage(this._privacySettingsViewModel); + + @override + String get title => S.current.domain_looks_up; + + final PrivacySettingsViewModel _privacySettingsViewModel; + + @override + Widget body(BuildContext context) { + return SingleChildScrollView( + child: Observer(builder: (_) { + return Container( + padding: EdgeInsets.only(top: 10), + child: Column( + children: [ + SettingsSwitcherCell( + title: 'Twitter', + value: _privacySettingsViewModel.lookupTwitter, + onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsTwitter(value)), + SettingsSwitcherCell( + title: 'Mastodon', + value: _privacySettingsViewModel.looksUpMastodon, + onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsMastodon(value)), + SettingsSwitcherCell( + title: 'Yat service', + value: _privacySettingsViewModel.looksUpYatService, + onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsYatService(value)), + SettingsSwitcherCell( + title: 'Unstoppable Domains', + value: _privacySettingsViewModel.looksUpUnstoppableDomains, + onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsUnstoppableDomains(value)), + SettingsSwitcherCell( + title: 'OpenAlias,', + value: _privacySettingsViewModel.looksUpOpenAlias, + onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsOpenAlias(value)), + SettingsSwitcherCell( + title: 'Ethereum Name Service', + value: _privacySettingsViewModel.looksUpENS, + onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsENS(value)), + + //if (!isHaven) it does not work correctly + ], + ), + ); + }), + ); + } +} diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index e953fd4ee..8e71b6020 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -1,7 +1,9 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/utils/device_info.dart'; @@ -84,6 +86,10 @@ class PrivacyPage extends BasePage { onValueChange: (BuildContext _, bool value) { _privacySettingsViewModel.setUseEtherscan(value); }), + SettingsCellWithArrow( + title: S.current.domain_looks_up, + handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage), + ), ], ); }), diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index ad4b8fd1e..cb9df3d1d 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -83,6 +83,12 @@ abstract class SettingsStoreBase with Store { required this.sortBalanceBy, required this.pinNativeTokenAtTop, required this.useEtherscan, + required this.lookupsTwitter, + required this.lookupsMastodon, + required this.lookupsYatService, + required this.lookupsUnstoppableDomains, + required this.lookupsOpenAlias, + required this.lookupsENS, TransactionPriority? initialBitcoinTransactionPriority, TransactionPriority? initialMoneroTransactionPriority, TransactionPriority? initialHavenTransactionPriority, @@ -362,6 +368,36 @@ abstract class SettingsStoreBase with Store { (bool useEtherscan) => _sharedPreferences.setBool(PreferencesKey.useEtherscan, useEtherscan)); + reaction( + (_) => lookupsTwitter, + (bool looksUpTwitter) => + _sharedPreferences.setBool(PreferencesKey.lookupsTwitter, looksUpTwitter)); + + reaction( + (_) => lookupsMastodon, + (bool looksUpMastodon) => + _sharedPreferences.setBool(PreferencesKey.lookupsMastodon, looksUpMastodon)); + + reaction( + (_) => lookupsYatService, + (bool looksUpYatService) => + _sharedPreferences.setBool(PreferencesKey.lookupsYatService, looksUpYatService)); + + reaction( + (_) => lookupsUnstoppableDomains, + (bool looksUpUnstoppableDomains) => + _sharedPreferences.setBool(PreferencesKey.lookupsUnstoppableDomains, looksUpUnstoppableDomains)); + + reaction( + (_) => lookupsOpenAlias, + (bool looksUpOpenAlias) => + _sharedPreferences.setBool(PreferencesKey.lookupsOpenAlias, looksUpOpenAlias)); + + reaction( + (_) => lookupsENS, + (bool looksUpENS) => + _sharedPreferences.setBool(PreferencesKey.lookupsENS, looksUpENS)); + this.nodes.observe((change) { if (change.newValue != null && change.key != null) { _saveCurrentNode(change.newValue!, change.key!); @@ -488,6 +524,24 @@ abstract class SettingsStoreBase with Store { @observable bool useEtherscan; + @observable + bool lookupsTwitter; + + @observable + bool lookupsMastodon; + + @observable + bool lookupsYatService; + + @observable + bool lookupsUnstoppableDomains; + + @observable + bool lookupsOpenAlias; + + @observable + bool lookupsENS; + @observable SyncMode currentSyncMode; @@ -647,6 +701,12 @@ abstract class SettingsStoreBase with Store { final pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true; final useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true; + final lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true; + final lookupsMastodon = sharedPreferences.getBool(PreferencesKey.lookupsMastodon) ?? true; + final lookupsYatService = sharedPreferences.getBool(PreferencesKey.lookupsYatService) ?? true; + final lookupsUnstoppableDomains = sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true; + final lookupsOpenAlias = sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias) ?? true; + final lookupsENS = sharedPreferences.getBool(PreferencesKey.lookupsENS) ?? true; // If no value if (pinLength == null || pinLength == 0) { @@ -754,6 +814,12 @@ abstract class SettingsStoreBase with Store { sortBalanceBy: sortBalanceBy, pinNativeTokenAtTop: pinNativeTokenAtTop, useEtherscan: useEtherscan, + lookupsTwitter: lookupsTwitter, + lookupsMastodon: lookupsMastodon, + lookupsYatService: lookupsYatService, + lookupsUnstoppableDomains: lookupsUnstoppableDomains, + lookupsOpenAlias: lookupsOpenAlias, + lookupsENS: lookupsENS, initialMoneroTransactionPriority: moneroTransactionPriority, initialBitcoinTransactionPriority: bitcoinTransactionPriority, initialHavenTransactionPriority: havenTransactionPriority, @@ -894,6 +960,12 @@ abstract class SettingsStoreBase with Store { .values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? sortBalanceBy.index]; pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true; useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true; + lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true; + lookupsMastodon = sharedPreferences.getBool(PreferencesKey.lookupsMastodon) ?? true; + lookupsYatService = sharedPreferences.getBool(PreferencesKey.lookupsYatService) ?? true; + lookupsUnstoppableDomains = sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true; + lookupsOpenAlias = sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias) ?? true; + lookupsENS = sharedPreferences.getBool(PreferencesKey.lookupsENS) ?? true; final nodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey); final bitcoinElectrumServerId = diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart index 27ce919df..b3ffeb353 100644 --- a/lib/view_model/settings/privacy_settings_view_model.dart +++ b/lib/view_model/settings/privacy_settings_view_model.dart @@ -12,7 +12,8 @@ import 'package:cake_wallet/entities/fiat_api_mode.dart'; part 'privacy_settings_view_model.g.dart'; -class PrivacySettingsViewModel = PrivacySettingsViewModelBase with _$PrivacySettingsViewModel; +class +PrivacySettingsViewModel = PrivacySettingsViewModelBase with _$PrivacySettingsViewModel; abstract class PrivacySettingsViewModelBase with Store { PrivacySettingsViewModelBase(this._settingsStore, this._wallet); @@ -57,6 +58,24 @@ abstract class PrivacySettingsViewModelBase with Store { @computed bool get useEtherscan => _settingsStore.useEtherscan; + @computed + bool get lookupTwitter => _settingsStore.lookupsTwitter; + + @computed + bool get looksUpMastodon => _settingsStore.lookupsMastodon; + + @computed + bool get looksUpYatService => _settingsStore.lookupsYatService; + + @computed + bool get looksUpUnstoppableDomains => _settingsStore.lookupsUnstoppableDomains; + + @computed + bool get looksUpOpenAlias => _settingsStore.lookupsOpenAlias; + + @computed + bool get looksUpENS => _settingsStore.lookupsENS; + bool get canUseEtherscan => _wallet.type == WalletType.ethereum; @action @@ -78,6 +97,24 @@ abstract class PrivacySettingsViewModelBase with Store { @action void setDisableSell(bool value) => _settingsStore.disableSell = value; + @action + void setLookupsTwitter(bool value) => _settingsStore.lookupsTwitter = value; + + @action + void setLookupsMastodon(bool value) => _settingsStore.lookupsMastodon = value; + + @action + void setLookupsENS(bool value) => _settingsStore.lookupsENS = value; + + @action + void setLookupsYatService(bool value) => _settingsStore.lookupsYatService = value; + + @action + void setLookupsUnstoppableDomains(bool value) => _settingsStore.lookupsUnstoppableDomains = value; + + @action + void setLookupsOpenAlias(bool value) => _settingsStore.lookupsOpenAlias = value; + @action void setUseEtherscan(bool value) { _settingsStore.useEtherscan = value; diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index a803ef687..4100bdeb8 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -723,6 +723,7 @@ "enter_seed_phrase": "أدخل عبارة البذور الخاصة بك", "add_contact": "ﻝﺎﺼﺗﺍ ﺔﻬﺟ ﺔﻓﺎﺿﺇ", "exchange_provider_unsupported": "${providerName} لم يعد مدعومًا!", + "domain_looks_up": "ﻝﺎﺠﻤﻟﺍ ﺚﺤﺑ ﺕﺎﻴﻠﻤﻋ", "require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ", "camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ", "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ" diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 85d19d8c4..e12a24119 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -719,6 +719,7 @@ "enter_seed_phrase": "Въведете вашата фраза за семена", "add_contact": "Добави контакт", "exchange_provider_unsupported": "${providerName} вече не се поддържа!", + "domain_looks_up": "Търсене на домейни", "require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли", "camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.", "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново" diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index b6a59979d..52087ef60 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -719,6 +719,7 @@ "enter_seed_phrase": "Zadejte svou frázi semen", "add_contact": "Přidat kontakt", "exchange_provider_unsupported": "${providerName} již není podporováno!", + "domain_looks_up": "Vyhledávání domén", "require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek", "camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.", "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu" diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 9b7e0f6ef..733b645c9 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "Geben Sie Ihre Seed-Phrase ein", "add_contact": "Kontakt hinzufügen", "exchange_provider_unsupported": "${providerName} wird nicht mehr unterstützt!", + "domain_looks_up": "Domain-Suchen", "require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets", "camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.", "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut" diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index e7ca7a850..4264d6b37 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -728,6 +728,7 @@ "enter_seed_phrase": "Enter your seed phrase", "add_contact": "Add contact", "exchange_provider_unsupported": "${providerName} is no longer supported!", + "domain_looks_up": "Domain lookups", "require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets", "camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.", "switchToETHWallet": "Please switch to an Ethereum wallet and try again" diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index a05ebd09b..728d15afb 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "Ingrese su frase de semillas", "add_contact": "Agregar contacto", "exchange_provider_unsupported": "¡${providerName} ya no es compatible!", + "domain_looks_up": "Búsquedas de dominio", "require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas", "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.", "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente." diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 4997ca37d..a65442850 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "Entrez votre phrase de semence", "add_contact": "Ajouter le contact", "exchange_provider_unsupported": "${providerName} n'est plus pris en charge!", + "domain_looks_up": "Recherches de domaine", "require_for_exchanges_to_external_wallets": "Exiger des échanges vers des portefeuilles externes", "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", "switchToETHWallet": "Veuillez passer à un portefeuille Ethereum et réessayer" diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index c07f5c86b..57199fa47 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -705,6 +705,7 @@ "enter_seed_phrase": "Shigar da Sert Sentarku", "add_contact": "Ƙara lamba", "exchange_provider_unsupported": "${providerName}", + "domain_looks_up": "Binciken yanki", "require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje", "camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.", "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa" diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index c949c9938..536731c94 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "अपना बीज वाक्यांश दर्ज करें", "add_contact": "संपर्क जोड़ें", "exchange_provider_unsupported": "${providerName} अब समर्थित नहीं है!", + "domain_looks_up": "डोमेन लुकअप", "require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है", "camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।", "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें" diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 923547f49..936e41338 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -725,6 +725,7 @@ "enter_seed_phrase": "Unesite svoju sjemensku frazu", "add_contact": "Dodaj kontakt", "exchange_provider_unsupported": "${providerName} više nije podržan!", + "domain_looks_up": "Pretraga domena", "require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike", "camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.", "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno" diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index c6537f1b1..036e3e96d 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -715,6 +715,7 @@ "enter_seed_phrase": "Masukkan frasa benih Anda", "add_contact": "Tambah kontak", "exchange_provider_unsupported": "${providerName} tidak lagi didukung!", + "domain_looks_up": "Pencarian domain", "require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal", "camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.", "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi" diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 82955798f..5138b1a59 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "Inserisci la tua frase di semi", "add_contact": "Aggiungi contatto", "exchange_provider_unsupported": "${providerName} non è più supportato!", + "domain_looks_up": "Ricerche di domini", "require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni", "camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.", "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova" diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index e69b55cc6..cc6dad9a8 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "シードフレーズを入力してください", "add_contact": "連絡先を追加", "exchange_provider_unsupported": "${providerName}はサポートされなくなりました!", + "domain_looks_up": "ドメイン検索", "require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要", "camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。", "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください" diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index ce65b820f..9ce833b08 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -725,6 +725,7 @@ "enter_seed_phrase": "시드 문구를 입력하십시오", "add_contact": "주소록에 추가", "exchange_provider_unsupported": "${providerName}은 더 이상 지원되지 않습니다!", + "domain_looks_up": "도메인 조회", "require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요", "camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.", "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요." diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 5d015475f..c92871c5f 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -725,6 +725,7 @@ "enter_seed_phrase": "သင့်ရဲ့မျိုးစေ့စကားစုကိုရိုက်ထည့်ပါ", "add_contact": "အဆက်အသွယ်ထည့်ပါ။", "exchange_provider_unsupported": "${providerName} မရှိတော့ပါ!", + "domain_looks_up": "ဒိုမိန်းရှာဖွေမှုများ", "require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", "camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။", "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။" diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index c05dab90a..c93861b2b 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "Voer uw zaadzin in", "add_contact": "Contactpersoon toevoegen", "exchange_provider_unsupported": "${providerName} wordt niet langer ondersteund!", + "domain_looks_up": "Domein opzoeken", "require_for_exchanges_to_external_wallets": "Vereist voor uitwisselingen naar externe portemonnees", "camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.", "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw" diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 16bf88418..5d32aaa74 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "Wprowadź swoją frazę nasienną", "add_contact": "Dodaj kontakt", "exchange_provider_unsupported": "${providerName} nie jest już obsługiwany!", + "domain_looks_up": "Wyszukiwanie domen", "require_for_exchanges_to_external_wallets": "Wymagaj wymiany na portfele zewnętrzne", "camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.", "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie" diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 18337cfdb..aa1f7459f 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -726,6 +726,7 @@ "enter_seed_phrase": "Digite sua frase de semente", "add_contact": "Adicionar contato", "exchange_provider_unsupported": "${providerName} não é mais suportado!", + "domain_looks_up": "Pesquisas de domínio", "require_for_exchanges_to_external_wallets": "Exigir trocas para carteiras externas", "camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.", "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente" diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 40deb5fb9..31fc00bca 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "Введите свою семенную фразу", "add_contact": "Добавить контакт", "exchange_provider_unsupported": "${providerName} больше не поддерживается!", + "domain_looks_up": "Поиск доменов", "require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки", "camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.", "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку." diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 2da16ffcd..b9757a08d 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -725,6 +725,7 @@ "enter_seed_phrase": "ป้อนวลีเมล็ดพันธุ์ของคุณ", "add_contact": "เพิ่มผู้ติดต่อ", "exchange_provider_unsupported": "${providerName} ไม่ได้รับการสนับสนุนอีกต่อไป!", + "domain_looks_up": "การค้นหาโดเมน", "require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก", "camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป", "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง" diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 231dd2db3..6157d9eb3 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -722,6 +722,7 @@ "enter_seed_phrase": "Ipasok ang iyong pariralang binhi", "add_contact": "Magdagdag ng contact", "exchange_provider_unsupported": "Ang ${providerName} ay hindi na suportado!", + "domain_looks_up": "Mga paghahanap ng domain", "require_for_exchanges_to_external_wallets": "Kinakailangan para sa mga palitan sa mga panlabas na wallet", "camera_permission_is_required": "Kinakailangan ang pahintulot sa camera.\nMangyaring paganahin ito mula sa mga setting ng app.", "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli" diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 54062b723..ddc669221 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -725,6 +725,7 @@ "enter_seed_phrase": "Tohum ifadenizi girin", "add_contact": "Kişi ekle", "exchange_provider_unsupported": "${providerName} artık desteklenmiyor!", + "domain_looks_up": "Etki alanı aramaları", "require_for_exchanges_to_external_wallets": "Harici cüzdanlara geçiş yapılmasını zorunlu kılın", "camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.", "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin" diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 0c5aaee59..9fb39b6cf 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -727,6 +727,7 @@ "enter_seed_phrase": "Введіть свою насіннєву фразу", "add_contact": "Додати контакт", "exchange_provider_unsupported": "${providerName} більше не підтримується!", + "domain_looks_up": "Пошук доменів", "require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці", "camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.", "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу" diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index ec4ccb5b8..e3f934891 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -719,6 +719,7 @@ "enter_seed_phrase": "اپنے بیج کا جملہ درج کریں", "add_contact": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮧﻄﺑﺍﺭ", "exchange_provider_unsupported": "${providerName} اب تعاون نہیں کیا جاتا ہے!", + "domain_looks_up": "ڈومین تلاش کرنا", "require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ", "camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ", "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ" diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index d30d36cb7..aafb70803 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -721,6 +721,7 @@ "enter_seed_phrase": "Tẹ ọrọ-iru irugbin rẹ", "add_contact": "Fi olubasọrọ kun", "exchange_provider_unsupported": "${providerName} ko ni atilẹyin mọ!", + "domain_looks_up": "Awọn wiwa agbegbe", "require_for_exchanges_to_external_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ ita", "camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.", "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi" diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index b68ffcc0e..67a852bcb 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -726,6 +726,7 @@ "enter_seed_phrase": "输入您的种子短语", "add_contact": "增加联系人", "exchange_provider_unsupported": "${providerName}不再支持!", + "domain_looks_up": "域名查找", "require_for_exchanges_to_external_wallets": "需要兑换到外部钱包", "camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。", "switchToETHWallet": "请切换到以太坊钱包并重试" From 37c2ee9e9ec9c8db5d913846c9610b7588b42b3e Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Fri, 3 Nov 2023 21:24:45 +0200 Subject: [PATCH 028/241] Generic fixes (#1154) * Fix White screen issue Bypass node certificate issue * check on Fiat currency only with fiat templates * Add possible missing cache file android error * Dispose exchange state reaction when page is closed * Fix minor chinese translation * Temp remove BCH from robinhood * Minor fixes --- cw_core/lib/node.dart | 3 + cw_monero/lib/monero_wallet_service.dart | 15 ++- ios/Podfile.lock | 4 +- lib/buy/robinhood/robinhood_buy_provider.dart | 2 +- lib/entities/default_settings_migration.dart | 103 ++++++++++-------- lib/entities/main_actions.dart | 2 +- .../exchange_trade/exchange_trade_page.dart | 7 +- lib/src/screens/root/root.dart | 3 +- lib/src/screens/send/send_page.dart | 32 +++--- res/values/strings_zh.arb | 4 +- 10 files changed, 98 insertions(+), 77 deletions(-) diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index dc3620ec2..5f0951447 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -162,6 +162,9 @@ class Node extends HiveObject with Keyable { try { final authenticatingClient = HttpClient(); + authenticatingClient.badCertificateCallback = + ((X509Certificate cert, String host, int port) => true); + authenticatingClient.addCredentials( rpcUri, realm, diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 9ee4cf374..8cb3aa948 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -57,7 +57,7 @@ class MoneroWalletService extends WalletService< final Box walletInfoSource; final Box unspentCoinsInfoSource; - + static bool walletFilesExist(String path) => !File(path).existsSync() && !File('$path.keys').existsSync(); @@ -135,9 +135,18 @@ class MoneroWalletService extends WalletService< (e is WalletOpeningException && e.message.contains('basic_string')); final bool isMissingCacheFilesAndroid = e.toString().contains('input_stream') || - (e is WalletOpeningException && e.message.contains('input_stream')); + e.toString().contains('input stream error') || + (e is WalletOpeningException && + (e.message.contains('input_stream') || e.message.contains('input stream error'))); - if (isBadAlloc || doesNotCorrespond || isMissingCacheFilesIOS || isMissingCacheFilesAndroid) { + final bool invalidSignature = e.toString().contains('invalid signature') || + (e is WalletOpeningException && e.message.contains('invalid signature')); + + if (isBadAlloc || + doesNotCorrespond || + isMissingCacheFilesIOS || + isMissingCacheFilesAndroid || + invalidSignature) { await restoreOrResetWalletFiles(name); return openWallet(name, password); } diff --git a/ios/Podfile.lock b/ios/Podfile.lock index f09ad4561..970ee3f80 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -283,7 +283,7 @@ SPEC CHECKSUMS: flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83 flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be - fluttertoast: fafc4fa4d01a6a9e4f772ecd190ffa525e9e2d9c + fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0 in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605 MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb @@ -302,7 +302,7 @@ SPEC CHECKSUMS: Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 uni_links: d97da20c7701486ba192624d99bffaaffcfc298a UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841 - url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4 + url_launcher_ios: 68d46cc9766d0c41dbdc884310529557e3cd7a86 wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6 diff --git a/lib/buy/robinhood/robinhood_buy_provider.dart b/lib/buy/robinhood/robinhood_buy_provider.dart index 0cb367298..e7a9e0579 100644 --- a/lib/buy/robinhood/robinhood_buy_provider.dart +++ b/lib/buy/robinhood/robinhood_buy_provider.dart @@ -34,7 +34,7 @@ class RobinhoodBuyProvider { case WalletType.bitcoin: return _wallet.signMessage(message, address: _wallet.walletAddresses.address); default: - throw Exception("WalletType is not available for Robinhood"); + throw Exception("WalletType is not available for Robinhood ${_wallet.type}"); } } diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 94283302d..47092c22f 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -191,63 +191,70 @@ Future defaultSettingsMigration( } Future _validateWalletInfoBoxData(Box walletInfoSource) async { - final root = await getApplicationDocumentsDirectory(); + try { + final root = await getApplicationDocumentsDirectory(); - for (var type in WalletType.values) { - if (type == WalletType.none) { - continue; - } - - String prefix = walletTypeToString(type).toLowerCase(); - Directory walletsDir = Directory('${root.path}/wallets/$prefix/'); - - if (!walletsDir.existsSync()) { - continue; - } - - List walletNames = walletsDir.listSync().map((e) => e.path.split("/").last).toList(); - - for (var name in walletNames) { - final dir = Directory(await pathForWalletDir(name: name, type: type)); - - final walletFiles = dir.listSync(); - final hasCacheFile = walletFiles.any((element) => element.path.contains("$name/$name")); - - if (!hasCacheFile) { + for (var type in WalletType.values) { + if (type == WalletType.none) { continue; } - if (type == WalletType.monero || type == WalletType.haven) { - final hasKeysFile = walletFiles.any((element) => element.path.contains(".keys")); + String prefix = walletTypeToString(type).toLowerCase(); + Directory walletsDir = Directory('${root.path}/wallets/$prefix/'); - if (!hasKeysFile) { + if (!walletsDir.existsSync()) { + continue; + } + + List walletNames = walletsDir.listSync().map((e) => e.path.split("/").last).toList(); + + for (var name in walletNames) { + final Directory dir; + try { + dir = Directory(await pathForWalletDir(name: name, type: type)); + } catch (_) { continue; } + + final walletFiles = dir.listSync(); + final hasCacheFile = walletFiles.any((element) => element.path.contains("$name/$name")); + + if (!hasCacheFile) { + continue; + } + + if (type == WalletType.monero || type == WalletType.haven) { + final hasKeysFile = walletFiles.any((element) => element.path.contains(".keys")); + + if (!hasKeysFile) { + continue; + } + } + + final id = prefix + '_' + name; + final exist = walletInfoSource.values.any((el) => el.id == id); + + if (exist) { + continue; + } + + final walletInfo = WalletInfo.external( + id: id, + type: type, + name: name, + isRecovery: true, + restoreHeight: 0, + date: DateTime.now(), + dirPath: dir.path, + path: '${dir.path}/$name', + address: '', + showIntroCakePayCard: false, + ); + + walletInfoSource.add(walletInfo); } - - final id = prefix + '_' + name; - final exist = walletInfoSource.values.any((el) => el.id == id); - - if (exist) { - continue; - } - - final walletInfo = WalletInfo.external( - id: id, - type: type, - name: name, - isRecovery: true, - restoreHeight: 0, - date: DateTime.now(), - dirPath: dir.path, - path: '${dir.path}/$name', - address: '', - showIntroCakePayCard: false, - ); - - walletInfoSource.add(walletInfo); } - } + } catch (_) {} } Future validateBitcoinSavedTransactionPriority(SharedPreferences sharedPreferences) async { diff --git a/lib/entities/main_actions.dart b/lib/entities/main_actions.dart index 46865cbcc..5f270deaf 100644 --- a/lib/entities/main_actions.dart +++ b/lib/entities/main_actions.dart @@ -52,7 +52,7 @@ class MainActions { case WalletType.bitcoin: case WalletType.litecoin: case WalletType.ethereum: - case WalletType.bitcoinCash: + // case WalletType.bitcoinCash: // TODO: add sign message function to BCH first switch (defaultBuyProvider) { case BuyProviderType.AskEachTime: Navigator.pushNamed(context, Routes.buy); diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index 22606c21e..23595efdf 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -91,6 +91,8 @@ class ExchangeTradeState extends State { bool _effectsInstalled = false; + ReactionDisposer? _exchangeStateReaction; + @override void initState() { super.initState(); @@ -103,8 +105,9 @@ class ExchangeTradeState extends State { @override void dispose() { - super.dispose(); widget.exchangeTradeViewModel.timer?.cancel(); + _exchangeStateReaction?.reaction.dispose(); + super.dispose(); } @override @@ -229,7 +232,7 @@ class ExchangeTradeState extends State { return; } - reaction((_) => this.widget.exchangeTradeViewModel.sendViewModel.state, + _exchangeStateReaction = reaction((_) => this.widget.exchangeTradeViewModel.sendViewModel.state, (ExecutionState state) { if (state is FailureState) { WidgetsBinding.instance.addPostFrameCallback((_) { diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index 72aed6a97..ca86cdccc 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -13,8 +13,7 @@ import 'package:cake_wallet/store/authentication_store.dart'; import 'package:cake_wallet/entities/qr_scanner.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:uni_links/uni_links.dart'; - -import '../setup_2fa/setup_2fa_enter_code_page.dart'; +import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart'; class Root extends StatefulWidget { Root({ diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index fca3684ca..b20b94cba 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -413,39 +413,39 @@ class SendPage extends BasePage { if (context.mounted) { showPopUp( context: context, - builder: (BuildContext context) { + builder: (BuildContext _dialogContext) { return ConfirmSendingAlert( - alertTitle: S.of(context).confirm_sending, - amount: S.of(context).send_amount, + alertTitle: S.of(_dialogContext).confirm_sending, + amount: S.of(_dialogContext).send_amount, amountValue: sendViewModel.pendingTransaction!.amountFormatted, fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted, - fee: S.of(context).send_fee, + fee: S.of(_dialogContext).send_fee, feeValue: sendViewModel.pendingTransaction!.feeFormatted, feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted, outputs: sendViewModel.outputs, - rightButtonText: S.of(context).ok, - leftButtonText: S.of(context).cancel, + rightButtonText: S.of(_dialogContext).ok, + leftButtonText: S.of(_dialogContext).cancel, actionRightButton: () { - Navigator.of(context).pop(); + Navigator.of(_dialogContext).pop(); sendViewModel.commitTransaction(); showPopUp( context: context, - builder: (BuildContext context) { + builder: (BuildContext _dialogContext) { return Observer(builder: (_) { final state = sendViewModel.state; if (state is FailureState) { - Navigator.of(context).pop(); + Navigator.of(_dialogContext).pop(); } if (state is TransactionCommitted) { return AlertWithOneAction( alertTitle: '', - alertContent: S.of(context).send_success( + alertContent: S.of(_dialogContext).send_success( sendViewModel.selectedCryptoCurrency.toString()), - buttonText: S.of(context).ok, + buttonText: S.of(_dialogContext).ok, buttonAction: () { - Navigator.of(context).pop(); + Navigator.of(_dialogContext).pop(); RequestReviewHandler.requestReview(); }); } @@ -454,7 +454,7 @@ class SendPage extends BasePage { }); }); }, - actionLeftButton: () => Navigator.of(context).pop()); + actionLeftButton: () => Navigator.of(_dialogContext).pop()); }); } }); @@ -472,15 +472,15 @@ class SendPage extends BasePage { Future _setInputsFromTemplate(BuildContext context, {required Output output, required Template template}) async { - final fiatFromTemplate = - FiatCurrency.all.singleWhere((element) => element.title == template.fiatCurrency); - output.address = template.address; if (template.isCurrencySelected) { sendViewModel.setSelectedCryptoCurrency(template.cryptoCurrency); output.setCryptoAmount(template.amount); } else { + final fiatFromTemplate = + FiatCurrency.all.singleWhere((element) => element.title == template.fiatCurrency); + sendViewModel.setFiatCurrency(fiatFromTemplate); output.setFiatAmount(template.amountFiat); } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 67a852bcb..336083a72 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -64,8 +64,8 @@ "powered_by": "Powered by ${title}", "error": "错误", "estimated": "估计值", - "min_value": "最低: ${value} ${currency}", - "max_value": "最高: ${value} ${currency}", + "min_value": "最小: ${value} ${currency}", + "max_value": "最大: ${value} ${currency}", "change_currency": "更改币种", "overwrite_amount": "Overwrite amount", "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", From a65c395337782acbbead938f156d4b015f7929a1 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Sun, 5 Nov 2023 00:40:11 +0200 Subject: [PATCH 029/241] v4.10.3 and v1.7.3 (#1159) * Update app versions * Ignore camera permission check for iOS --- assets/text/Monerocom_Release_Notes.txt | 8 ++++---- assets/text/Release_Notes.txt | 9 +++++---- lib/utils/permission_handler.dart | 5 +++++ macos/Podfile.lock | 2 +- scripts/android/app_env.sh | 8 ++++---- scripts/ios/app_env.sh | 8 ++++---- scripts/macos/app_env.sh | 4 ++-- 7 files changed, 25 insertions(+), 19 deletions(-) diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index fb2cd98fe..9c09278a5 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,4 +1,4 @@ -BirdPay enhancements -Nano fixes and improvements -Minor bug fixes -Accessibility enhancements \ No newline at end of file +UI enhancements +Privacy settings enhancements +Tablet/iPad fixes +Bug fixes \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index fb2cd98fe..8b8ab36a1 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,4 +1,5 @@ -BirdPay enhancements -Nano fixes and improvements -Minor bug fixes -Accessibility enhancements \ No newline at end of file +WalletConnect enhancements +UI enhancements +Privacy settings enhancements +Tablet/iPad fixes +Bug fixes \ No newline at end of file diff --git a/lib/utils/permission_handler.dart b/lib/utils/permission_handler.dart index 7e8a8f710..6b76f767a 100644 --- a/lib/utils/permission_handler.dart +++ b/lib/utils/permission_handler.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:flutter/cupertino.dart'; @@ -5,6 +7,9 @@ import 'package:permission_handler/permission_handler.dart'; class PermissionHandler { static Future checkPermission(Permission permission, BuildContext context) async { + if (Platform.isIOS) { + return true; + } final Map _permissionMessages = { Permission.camera: S.of(context).camera_permission_is_required, }; diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 421dc204c..664a5231b 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -103,7 +103,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308 - cw_monero: f8b7f104508efba2591548e76b5c058d05cba3f0 + cw_monero: ec03de55a19c4a2b174ea687e0f4202edc716fa4 device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225 flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 5705fbe51..ba7575d3a 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.7.2" -MONERO_COM_BUILD_NUMBER=63 +MONERO_COM_VERSION="1.7.3" +MONERO_COM_BUILD_NUMBER=64 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.10.2" -CAKEWALLET_BUILD_NUMBER=177 +CAKEWALLET_VERSION="4.10.3" +CAKEWALLET_BUILD_NUMBER=178 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 7c9852243..328b3825b 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.7.2" -MONERO_COM_BUILD_NUMBER=61 +MONERO_COM_VERSION="1.7.4" +MONERO_COM_BUILD_NUMBER=63 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.10.2" -CAKEWALLET_BUILD_NUMBER=191 +CAKEWALLET_VERSION="4.10.4" +CAKEWALLET_BUILD_NUMBER=196 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 88f1c9774..57434db8e 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -15,8 +15,8 @@ if [ -n "$1" ]; then fi CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.3.2" -CAKEWALLET_BUILD_NUMBER=39 +CAKEWALLET_VERSION="1.3.3" +CAKEWALLET_BUILD_NUMBER=40 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From a164e5defcd311ed0d13b989b24ffacfea75d60a Mon Sep 17 00:00:00 2001 From: Mathias Herberts Date: Sat, 4 Nov 2023 23:36:56 +0000 Subject: [PATCH 030/241] Updated FR translations (#1162) --- res/values/strings_fr.arb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index a65442850..d4d27ae0b 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -720,15 +720,15 @@ "message": "Message", "do_not_have_enough_gas_asset": "Vous n'avez pas assez de ${currency} pour effectuer une transaction avec les conditions actuelles du réseau blockchain. Vous avez besoin de plus de ${currency} pour payer les frais du réseau blockchain, même si vous envoyez un actif différent.", "totp_auth_url": "URL D'AUTORISATION TOTP", - "awaitDAppProcessing": "Veuillez attendre que le dApp termine le traitement.", - "copyWalletConnectLink": "Copiez le lien WalletConnect depuis dApp et collez-le ici", + "awaitDAppProcessing": "Veuillez attendre que l'application décentralisée (dApp) termine le traitement.", + "copyWalletConnectLink": "Copiez le lien WalletConnect depuis l'application décentralisée (dApp) et collez-le ici", "enterWalletConnectURI": "Saisissez l'URI de WalletConnect.", - "seed_key": "Clé de graines", - "enter_seed_phrase": "Entrez votre phrase de semence", + "seed_key": "Clé secrète (seed key)", + "enter_seed_phrase": "Entrez votre phrase secrète (seed)", "add_contact": "Ajouter le contact", - "exchange_provider_unsupported": "${providerName} n'est plus pris en charge!", + "exchange_provider_unsupported": "${providerName} n'est plus pris en charge !", "domain_looks_up": "Recherches de domaine", - "require_for_exchanges_to_external_wallets": "Exiger des échanges vers des portefeuilles externes", + "require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes", "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", - "switchToETHWallet": "Veuillez passer à un portefeuille Ethereum et réessayer" + "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer" } From fdeee8874a8d0bdd1fbaebb27d235c191ea019c0 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Tue, 14 Nov 2023 15:56:36 -0600 Subject: [PATCH 031/241] disable bio auth (#1172) * disable bio auth * enforce dark theme on desktop platforms --------- Co-authored-by: fossephate --- lib/core/backup_service.dart | 63 ++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 520447dd4..85fd8f588 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; +import 'package:cake_wallet/themes/theme_list.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/foundation.dart'; @@ -254,7 +255,8 @@ class BackupService { final lookupsENS = data[PreferencesKey.lookupsENS] as bool?; final syncAll = data[PreferencesKey.syncAllKey] as bool?; final syncMode = data[PreferencesKey.syncModeKey] as int?; - final autoGenerateSubaddressStatus = data[PreferencesKey.autoGenerateSubaddressStatusKey] as int?; + final autoGenerateSubaddressStatus = + data[PreferencesKey.autoGenerateSubaddressStatusKey] as int?; await _sharedPreferences.setString(PreferencesKey.currentWalletName, currentWalletName); @@ -291,9 +293,12 @@ class BackupService { await _sharedPreferences.setInt( PreferencesKey.currentTransactionPriorityKeyLegacy, currentTransactionPriorityKeyLegacy); - if (allowBiometricalAuthentication != null && !Platform.isMacOS && !Platform.isLinux) + if (Platform.isMacOS || Platform.isLinux) { + await _sharedPreferences.setBool(PreferencesKey.allowBiometricalAuthenticationKey, false); + } else if (allowBiometricalAuthentication != null) { await _sharedPreferences.setBool( PreferencesKey.allowBiometricalAuthenticationKey, allowBiometricalAuthentication); + } if (currentBitcoinElectrumSererId != null) await _sharedPreferences.setInt( @@ -309,14 +314,19 @@ class BackupService { if (fiatApiMode != null) await _sharedPreferences.setInt(PreferencesKey.currentFiatApiModeKey, fiatApiMode); if (autoGenerateSubaddressStatus != null) - await _sharedPreferences.setInt(PreferencesKey.autoGenerateSubaddressStatusKey, - autoGenerateSubaddressStatus); + await _sharedPreferences.setInt( + PreferencesKey.autoGenerateSubaddressStatusKey, autoGenerateSubaddressStatus); if (currentPinLength != null) await _sharedPreferences.setInt(PreferencesKey.currentPinLength, currentPinLength); - if (currentTheme != null && DeviceInfo.instance.isMobile) + if (currentTheme != null && DeviceInfo.instance.isMobile) { await _sharedPreferences.setInt(PreferencesKey.currentTheme, currentTheme); + // enforce dark theme on desktop platforms until the design is ready: + } else if (DeviceInfo.instance.isDesktop) { + await _sharedPreferences.setInt(PreferencesKey.currentTheme, ThemeList.darkTheme.raw); + } + if (exchangeStatus != null) await _sharedPreferences.setInt(PreferencesKey.exchangeStatusKey, exchangeStatus); @@ -389,19 +399,17 @@ class BackupService { await _sharedPreferences.setBool(PreferencesKey.lookupsYatService, lookupsYatService); if (lookupsUnstoppableDomains != null) - await _sharedPreferences.setBool(PreferencesKey.lookupsUnstoppableDomains, lookupsUnstoppableDomains); + await _sharedPreferences.setBool( + PreferencesKey.lookupsUnstoppableDomains, lookupsUnstoppableDomains); if (lookupsOpenAlias != null) await _sharedPreferences.setBool(PreferencesKey.lookupsOpenAlias, lookupsOpenAlias); - if (lookupsENS != null) - await _sharedPreferences.setBool(PreferencesKey.lookupsENS, lookupsENS); + if (lookupsENS != null) await _sharedPreferences.setBool(PreferencesKey.lookupsENS, lookupsENS); - if (syncAll != null) - await _sharedPreferences.setBool(PreferencesKey.syncAllKey, syncAll); + if (syncAll != null) await _sharedPreferences.setBool(PreferencesKey.syncAllKey, syncAll); - if (syncMode != null) - await _sharedPreferences.setInt(PreferencesKey.syncModeKey, syncMode); + if (syncMode != null) await _sharedPreferences.setInt(PreferencesKey.syncModeKey, syncMode); await preferencesFile.delete(); } @@ -505,7 +513,8 @@ class BackupService { _sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey), PreferencesKey.disableBuyKey: _sharedPreferences.getBool(PreferencesKey.disableBuyKey), PreferencesKey.disableSellKey: _sharedPreferences.getBool(PreferencesKey.disableSellKey), - PreferencesKey.defaultBuyProvider: _sharedPreferences.getInt(PreferencesKey.defaultBuyProvider), + PreferencesKey.defaultBuyProvider: + _sharedPreferences.getInt(PreferencesKey.defaultBuyProvider), PreferencesKey.isDarkThemeLegacy: _sharedPreferences.getBool(PreferencesKey.isDarkThemeLegacy), PreferencesKey.currentPinLength: _sharedPreferences.getInt(PreferencesKey.currentPinLength), @@ -547,28 +556,20 @@ class BackupService { _sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets), PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings: _sharedPreferences .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings), - PreferencesKey.sortBalanceBy: - _sharedPreferences.getInt(PreferencesKey.sortBalanceBy), + PreferencesKey.sortBalanceBy: _sharedPreferences.getInt(PreferencesKey.sortBalanceBy), PreferencesKey.pinNativeTokenAtTop: _sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop), - PreferencesKey.useEtherscan: - _sharedPreferences.getBool(PreferencesKey.useEtherscan), - PreferencesKey.lookupsTwitter: - _sharedPreferences.getBool(PreferencesKey.lookupsTwitter), - PreferencesKey.lookupsMastodon: - _sharedPreferences.getBool(PreferencesKey.lookupsMastodon), + PreferencesKey.useEtherscan: _sharedPreferences.getBool(PreferencesKey.useEtherscan), + PreferencesKey.lookupsTwitter: _sharedPreferences.getBool(PreferencesKey.lookupsTwitter), + PreferencesKey.lookupsMastodon: _sharedPreferences.getBool(PreferencesKey.lookupsMastodon), PreferencesKey.lookupsYatService: - _sharedPreferences.getBool(PreferencesKey.lookupsYatService), + _sharedPreferences.getBool(PreferencesKey.lookupsYatService), PreferencesKey.lookupsUnstoppableDomains: - _sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains), - PreferencesKey.lookupsOpenAlias: - _sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias), - PreferencesKey.lookupsENS: - _sharedPreferences.getBool(PreferencesKey.lookupsENS), - PreferencesKey.syncModeKey: - _sharedPreferences.getInt(PreferencesKey.syncModeKey), - PreferencesKey.syncAllKey: - _sharedPreferences.getBool(PreferencesKey.syncAllKey), + _sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains), + PreferencesKey.lookupsOpenAlias: _sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias), + PreferencesKey.lookupsENS: _sharedPreferences.getBool(PreferencesKey.lookupsENS), + PreferencesKey.syncModeKey: _sharedPreferences.getInt(PreferencesKey.syncModeKey), + PreferencesKey.syncAllKey: _sharedPreferences.getBool(PreferencesKey.syncAllKey), PreferencesKey.autoGenerateSubaddressStatusKey: _sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey), }; From 062315f01b292b96edddffa30b5fa3b0e28cd128 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Wed, 15 Nov 2023 11:31:25 -0600 Subject: [PATCH 032/241] Secure storage overwrite fix (#1161) * secure storage overwrite fix * add comment * bump encrypt package, use more explicit iv source --------- Co-authored-by: fossephate --- lib/core/auth_service.dart | 10 +++++----- lib/entities/encrypt.dart | 8 ++++---- pubspec_base.yaml | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/core/auth_service.dart b/lib/core/auth_service.dart index 854640015..321b5b94a 100644 --- a/lib/core/auth_service.dart +++ b/lib/core/auth_service.dart @@ -38,6 +38,9 @@ class AuthService with Store { Future setPassword(String password) async { final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final encodedPassword = encodedPinCode(pin: password); + // secure storage has a weird bug on macOS, where overwriting a key doesn't work, unless + // we delete what's there first: + await secureStorage.delete(key: key); await secureStorage.write(key: key, value: encodedPassword); } @@ -104,9 +107,8 @@ class AuthService with Store { } return; } -} + } - Navigator.of(context).pushNamed(Routes.auth, arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async { if (!isAuthenticatedSuccessfully) { @@ -140,8 +142,6 @@ class AuthService with Store { } } } - - }); - + }); } } diff --git a/lib/entities/encrypt.dart b/lib/entities/encrypt.dart index 3e644a2b7..891f7a92d 100644 --- a/lib/entities/encrypt.dart +++ b/lib/entities/encrypt.dart @@ -2,18 +2,18 @@ import 'package:encrypt/encrypt.dart'; // import 'package:password/password.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; -String encrypt({required String source, required String key, int keyLength = 16}) { +String encrypt({required String source, required String key}) { final _key = Key.fromUtf8(key); - final iv = IV.fromLength(keyLength); + final iv = IV.allZerosOfLength(16); final encrypter = Encrypter(AES(_key)); final encrypted = encrypter.encrypt(source, iv: iv); return encrypted.base64; } -String decrypt({required String source, required String key, int keyLength = 16}) { +String decrypt({required String source, required String key}) { final _key = Key.fromUtf8(key); - final iv = IV.fromLength(keyLength); + final iv = IV.allZerosOfLength(16); final encrypter = Encrypter(AES(_key)); final decrypted = encrypter.decrypt64(source, iv: iv); diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 82cb697f5..573f8c671 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -49,7 +49,7 @@ dependencies: lottie: ^1.3.0 animate_do: ^2.1.0 cupertino_icons: ^1.0.5 - encrypt: 5.0.1 + encrypt: 5.0.2 crypto: ^3.0.2 # password: ^1.0.0 basic_utils: ^5.6.1 From 4cffc8d4c503ab1bbb6d92f8162222bd5f2ef27d Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 15 Nov 2023 21:04:30 +0200 Subject: [PATCH 033/241] Update wallet_restore_page.dart (#1178) --- .../screens/restore/wallet_restore_page.dart | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index 4fa9e340d..d77c8aa2a 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -196,23 +196,35 @@ class WalletRestorePage extends BasePage { ), Padding( padding: EdgeInsets.only(top: 20, bottom: 24, left: 24, right: 24), - child: Observer( - builder: (context) { - return LoadingPrimaryButton( - onPressed: () async { - await _confirmForm(context); + child: Column( + children: [ + Observer( + builder: (context) { + return LoadingPrimaryButton( + onPressed: () async { + await _confirmForm(context); + }, + text: S.of(context).restore_recover, + color: Theme.of(context) + .extension()! + .createNewWalletButtonBackgroundColor, + textColor: Theme.of(context) + .extension()! + .restoreWalletButtonTextColor, + isLoading: walletRestoreViewModel.state is IsExecutingState, + isDisabled: !walletRestoreViewModel.isButtonEnabled, + ); }, - text: S.of(context).restore_recover, - color: Theme.of(context) - .extension()! - .createNewWalletButtonBackgroundColor, - textColor: Theme.of(context) - .extension()! - .restoreWalletButtonTextColor, - isLoading: walletRestoreViewModel.state is IsExecutingState, - isDisabled: !walletRestoreViewModel.isButtonEnabled, - ); - }, + ), + const SizedBox(height: 25), + GestureDetector( + onTap: () { + Navigator.of(context) + .pushNamed(Routes.advancedPrivacySettings, arguments: walletRestoreViewModel.type); + }, + child: Text(S.of(context).advanced_privacy_settings), + ), + ], ), ) ], From 8084f490b593b4dd74956ab00cf516213a69762b Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Thu, 16 Nov 2023 00:12:23 +0100 Subject: [PATCH 034/241] Cw 467 mark change outputs in unspent outputs list (#1137) * CW-490 Use native Coin Freeze * CW-467 Code cleanup * CW-467 Fix native Code * CW-467 Extend Unspend * CW-467 Add isChange * CW-467 Minor Fixes * CW-467 Add isChange to Electrum Unspents * CW-467 Localize Change Tag * CW-467 Fix frozen balance showing on other monero wallets * CW-467 Fix frozen balance showing on other monero wallets --- cw_bitcoin/lib/electrum_wallet.dart | 124 +++++++++--------- cw_core/lib/unspent_coins_info.dart | 10 +- cw_core/lib/unspent_transaction_output.dart | 2 + cw_monero/ios/Classes/monero_api.cpp | 15 +++ cw_monero/lib/api/coins_info.dart | 12 ++ cw_monero/lib/api/signatures.dart | 7 + cw_monero/lib/api/transaction_history.dart | 22 +++- cw_monero/lib/api/types.dart | 7 + cw_monero/lib/monero_unspent.dart | 36 ++--- cw_monero/lib/monero_wallet.dart | 31 +++-- lib/monero/cw_monero.dart | 5 +- .../unspent_coins_list_page.dart | 81 +++--------- .../widgets/unspent_coins_list_item.dart | 46 +++++-- .../dashboard/balance_view_model.dart | 18 +-- .../unspent_coins/unspent_coins_item.dart | 4 + .../unspent_coins_list_view_model.dart | 59 +++------ res/values/strings_ar.arb | 3 +- res/values/strings_bg.arb | 3 +- res/values/strings_cs.arb | 3 +- res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 3 +- res/values/strings_es.arb | 3 +- res/values/strings_fr.arb | 3 +- res/values/strings_ha.arb | 3 +- res/values/strings_hi.arb | 3 +- res/values/strings_hr.arb | 3 +- res/values/strings_id.arb | 3 +- res/values/strings_it.arb | 3 +- res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 3 +- res/values/strings_nl.arb | 3 +- res/values/strings_pl.arb | 3 +- res/values/strings_pt.arb | 3 +- res/values/strings_ru.arb | 3 +- res/values/strings_th.arb | 3 +- res/values/strings_tl.arb | 3 +- res/values/strings_tr.arb | 3 +- res/values/strings_uk.arb | 3 +- res/values/strings_ur.arb | 3 +- res/values/strings_yo.arb | 3 +- res/values/strings_zh.arb | 3 +- 42 files changed, 296 insertions(+), 261 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 804b53379..05486aa20 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -2,41 +2,41 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:math'; -import 'package:cw_core/pending_transaction.dart'; -import 'package:cw_core/unspent_coins_info.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:hive/hive.dart'; -import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; -import 'package:mobx/mobx.dart'; -import 'package:rxdart/subjects.dart'; -import 'package:flutter/foundation.dart'; + import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:cw_bitcoin/electrum_transaction_info.dart'; -import 'package:cw_core/pathForWallet.dart'; +import 'package:collection/collection.dart'; import 'package:cw_bitcoin/address_to_output_script.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; -import 'package:cw_bitcoin/electrum_balance.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; -import 'package:cw_bitcoin/electrum_transaction_history.dart'; import 'package:cw_bitcoin/bitcoin_transaction_no_inputs_exception.dart'; import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; import 'package:cw_bitcoin/bitcoin_transaction_wrong_balance_exception.dart'; import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_bitcoin/bitcoin_wallet_keys.dart'; +import 'package:cw_bitcoin/electrum.dart'; +import 'package:cw_bitcoin/electrum_balance.dart'; +import 'package:cw_bitcoin/electrum_transaction_history.dart'; +import 'package:cw_bitcoin/electrum_transaction_info.dart'; +import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:cw_bitcoin/file.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/script_hash.dart'; import 'package:cw_bitcoin/utils.dart'; -import 'package:cw_core/wallet_base.dart'; -import 'package:cw_core/node.dart'; -import 'package:cw_core/sync_status.dart'; -import 'package:cw_core/transaction_priority.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cw_bitcoin/electrum.dart'; -import 'package:hex/hex.dart'; import 'package:cw_core/crypto_currency.dart'; -import 'package:collection/collection.dart'; -import 'package:bip32/bip32.dart'; +import 'package:cw_core/node.dart'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/pending_transaction.dart'; +import 'package:cw_core/sync_status.dart'; +import 'package:cw_core/transaction_direction.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:flutter/foundation.dart'; +import 'package:hex/hex.dart'; +import 'package:hive/hive.dart'; +import 'package:mobx/mobx.dart'; +import 'package:rxdart/subjects.dart'; part 'electrum_wallet.g.dart'; @@ -47,18 +47,18 @@ abstract class ElectrumWalletBase with Store { ElectrumWalletBase( {required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - required this.networkType, - required this.mnemonic, - required Uint8List seedBytes, - List? initialAddresses, - ElectrumClient? electrumClient, - ElectrumBalance? initialBalance, - CryptoCurrency? currency}) + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required this.networkType, + required this.mnemonic, + required Uint8List seedBytes, + List? initialAddresses, + ElectrumClient? electrumClient, + ElectrumBalance? initialBalance, + CryptoCurrency? currency}) : hd = currency == CryptoCurrency.bch - ? bitcoinCashHDWallet(seedBytes) - : bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/0"), + ? bitcoinCashHDWallet(seedBytes) + : bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/0"), syncStatus = NotConnectedSyncStatus(), _password = password, _feeRates = [], @@ -67,9 +67,9 @@ abstract class ElectrumWalletBase _scripthashesUpdateSubject = {}, balance = ObservableMap.of(currency != null ? { - currency: - initialBalance ?? const ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0) - } + currency: + initialBalance ?? const ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0) + } : {}), this.unspentCoinsInfo = unspentCoinsInfo, super(walletInfo) { @@ -79,8 +79,7 @@ abstract class ElectrumWalletBase } static bitcoin.HDWallet bitcoinCashHDWallet(Uint8List seedBytes) => - bitcoin.HDWallet.fromSeed(seedBytes) - .derivePath("m/44'/145'/0'/0"); + bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/0"); static int estimatedTransactionSize(int inputsCount, int outputsCounts) => inputsCount * 146 + outputsCounts * 33 + 8; @@ -294,10 +293,12 @@ abstract class ElectrumWalletBase if (input.isP2wpkh) { final p2wpkh = bitcoin .P2WPKH( - data: generatePaymentData( - hd: input.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, - index: input.bitcoinAddressRecord.index), - network: networkType) + data: generatePaymentData( + hd: input.bitcoinAddressRecord.isHidden + ? walletAddresses.sideHd + : walletAddresses.mainHd, + index: input.bitcoinAddressRecord.index), + network: networkType) .data; txb.addInput(input.hash, input.vout, null, p2wpkh.output); @@ -347,12 +348,12 @@ abstract class ElectrumWalletBase } String toJSON() => json.encode({ - 'mnemonic': mnemonic, - 'account_index': walletAddresses.currentReceiveAddressIndex.toString(), - 'change_address_index': walletAddresses.currentChangeAddressIndex.toString(), - 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), - 'balance': balance[currency]?.toJSON() - }); + 'mnemonic': mnemonic, + 'account_index': walletAddresses.currentReceiveAddressIndex.toString(), + 'change_address_index': walletAddresses.currentChangeAddressIndex.toString(), + 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), + 'balance': balance[currency]?.toJSON() + }); int feeRate(TransactionPriority priority) { try { @@ -367,7 +368,7 @@ abstract class ElectrumWalletBase } int feeAmountForPriority( - BitcoinTransactionPriority priority, int inputsCount, int outputsCount) => + BitcoinTransactionPriority priority, int inputsCount, int outputsCount) => feeRate(priority) * estimatedTransactionSize(inputsCount, outputsCount); int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount) => @@ -467,18 +468,20 @@ abstract class ElectrumWalletBase Future makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); Future updateUnspent() async { - final unspent = await Future.wait(walletAddresses - .addresses.map((address) => electrumClient + final unspent = await Future.wait(walletAddresses.addresses.map((address) => electrumClient .getListUnspentWithAddress(address.address, networkType) - .then((unspent) => unspent - .map((unspent) { - try { - return BitcoinUnspent.fromJSON(address, unspent); - } catch(_) { - return null; - } - }).whereNotNull()))); + .then((unspent) => unspent.map((unspent) { + try { + return BitcoinUnspent.fromJSON(address, unspent); + } catch (_) { + return null; + } + }).whereNotNull()))); unspentCoins = unspent.expand((e) => e).toList(); + unspentCoins.forEach((coin) async { + final tx = await fetchTransactionInfo(hash: coin.hash, height: 0); + coin.isChange = tx!.direction == TransactionDirection.outgoing; + }); if (unspentCoinsInfo.isEmpty) { unspentCoins.forEach((coin) => _addCoinInfo(coin)); @@ -515,6 +518,7 @@ abstract class ElectrumWalletBase address: coin.bitcoinAddressRecord.address, value: coin.value, vout: coin.vout, + isChange: coin.isChange, ); await unspentCoinsInfo.add(newInfo); @@ -524,7 +528,7 @@ abstract class ElectrumWalletBase try { final List keys = []; final currentWalletUnspentCoins = - unspentCoinsInfo.values.where((element) => element.walletId.contains(id)); + unspentCoinsInfo.values.where((element) => element.walletId.contains(id)); if (currentWalletUnspentCoins.isNotEmpty) { currentWalletUnspentCoins.forEach((element) { @@ -657,7 +661,7 @@ abstract class ElectrumWalletBase final addresses = walletAddresses.addresses.toList(); final balanceFutures = >>[]; for (var i = 0; i < addresses.length; i++) { - final addressRecord = addresses[i] ; + final addressRecord = addresses[i]; final sh = scriptHash(addressRecord.address, networkType: networkType); final balanceFuture = electrumClient.getBalance(sh); balanceFutures.add(balanceFuture); diff --git a/cw_core/lib/unspent_coins_info.dart b/cw_core/lib/unspent_coins_info.dart index 68bbcbfd2..25abd3e48 100644 --- a/cw_core/lib/unspent_coins_info.dart +++ b/cw_core/lib/unspent_coins_info.dart @@ -14,7 +14,9 @@ class UnspentCoinsInfo extends HiveObject { required this.address, required this.vout, required this.value, - this.keyImage = null + this.keyImage = null, + this.isChange = false, + this.accountIndex = 0 }); static const typeId = UNSPENT_COINS_INFO_TYPE_ID; @@ -47,6 +49,12 @@ class UnspentCoinsInfo extends HiveObject { @HiveField(8, defaultValue: null) String? keyImage; + + @HiveField(9, defaultValue: false) + bool isChange; + + @HiveField(10, defaultValue: 0) + int accountIndex; String get note => noteRaw ?? ''; diff --git a/cw_core/lib/unspent_transaction_output.dart b/cw_core/lib/unspent_transaction_output.dart index 6827f4c01..b52daf43c 100644 --- a/cw_core/lib/unspent_transaction_output.dart +++ b/cw_core/lib/unspent_transaction_output.dart @@ -2,6 +2,7 @@ class Unspent { Unspent(this.address, this.hash, this.value, this.vout, this.keyImage) : isSending = true, isFrozen = false, + isChange = false, note = ''; final String address; @@ -10,6 +11,7 @@ class Unspent { final int vout; final String? keyImage; + bool isChange; bool isSending; bool isFrozen; String note; diff --git a/cw_monero/ios/Classes/monero_api.cpp b/cw_monero/ios/Classes/monero_api.cpp index e04282fe8..a0712255a 100644 --- a/cw_monero/ios/Classes/monero_api.cpp +++ b/cw_monero/ios/Classes/monero_api.cpp @@ -841,6 +841,12 @@ extern "C" return m_transaction_history->count(); } + TransactionInfoRow* get_transaction(char * txId) + { + Monero::TransactionInfo *row = m_transaction_history->transaction(std::string(txId)); + return new TransactionInfoRow(row); + } + int LedgerExchange( unsigned char *command, unsigned int cmd_len, @@ -970,6 +976,15 @@ extern "C" return result; } + void freeze_coin(int index) + { + m_coins->setFrozen(index); + } + + void thaw_coin(int index) + { + m_coins->thaw(index); + } #ifdef __cplusplus } diff --git a/cw_monero/lib/api/coins_info.dart b/cw_monero/lib/api/coins_info.dart index 9a5303f9d..d7350a6e2 100644 --- a/cw_monero/lib/api/coins_info.dart +++ b/cw_monero/lib/api/coins_info.dart @@ -16,8 +16,20 @@ final coinNative = moneroApi .lookup>('coin') .asFunction(); +final freezeCoinNative = moneroApi + .lookup>('freeze_coin') + .asFunction(); + +final thawCoinNative = moneroApi + .lookup>('thaw_coin') + .asFunction(); + void refreshCoins(int accountIndex) => refreshCoinsNative(accountIndex); int countOfCoins() => coinsCountNative(); CoinsInfoRow getCoin(int index) => coinNative(index).ref; + +void freezeCoin(int index) => freezeCoinNative(index); + +void thawCoin(int index) => thawCoinNative(index); diff --git a/cw_monero/lib/api/signatures.dart b/cw_monero/lib/api/signatures.dart index e208414c8..9be828df0 100644 --- a/cw_monero/lib/api/signatures.dart +++ b/cw_monero/lib/api/signatures.dart @@ -1,6 +1,7 @@ import 'dart:ffi'; import 'package:cw_monero/api/structs/coins_info_row.dart'; import 'package:cw_monero/api/structs/pending_transaction.dart'; +import 'package:cw_monero/api/structs/transaction_info_row.dart'; import 'package:cw_monero/api/structs/ut8_box.dart'; import 'package:ffi/ffi.dart'; @@ -81,6 +82,8 @@ typedef account_set_label = Void Function(Int32 accountIndex, Pointer labe typedef transactions_refresh = Void Function(); +typedef get_transaction = Pointer Function(Pointer txId); + typedef get_tx_key = Pointer? Function(Pointer txId); typedef transactions_count = Int64 Function(); @@ -139,3 +142,7 @@ typedef coins_count = Int64 Function(); // typedef coins_from_txid = Pointer Function(Pointer txid); typedef coin = Pointer Function(Int32 index); + +typedef freeze_coin = Void Function(Int32 index); + +typedef thaw_coin = Void Function(Int32 index); diff --git a/cw_monero/lib/api/transaction_history.dart b/cw_monero/lib/api/transaction_history.dart index 1964c4067..73c8de801 100644 --- a/cw_monero/lib/api/transaction_history.dart +++ b/cw_monero/lib/api/transaction_history.dart @@ -1,15 +1,16 @@ import 'dart:ffi'; + import 'package:cw_monero/api/convert_utf8_to_string.dart'; +import 'package:cw_monero/api/exceptions/creation_transaction_exception.dart'; +import 'package:cw_monero/api/monero_api.dart'; import 'package:cw_monero/api/monero_output.dart'; +import 'package:cw_monero/api/signatures.dart'; +import 'package:cw_monero/api/structs/pending_transaction.dart'; +import 'package:cw_monero/api/structs/transaction_info_row.dart'; import 'package:cw_monero/api/structs/ut8_box.dart'; +import 'package:cw_monero/api/types.dart'; import 'package:ffi/ffi.dart'; import 'package:flutter/foundation.dart'; -import 'package:cw_monero/api/signatures.dart'; -import 'package:cw_monero/api/types.dart'; -import 'package:cw_monero/api/monero_api.dart'; -import 'package:cw_monero/api/structs/transaction_info_row.dart'; -import 'package:cw_monero/api/structs/pending_transaction.dart'; -import 'package:cw_monero/api/exceptions/creation_transaction_exception.dart'; final transactionsRefreshNative = moneroApi .lookup>('transactions_refresh') @@ -38,6 +39,10 @@ final transactionCommitNative = moneroApi final getTxKeyNative = moneroApi.lookup>('get_tx_key').asFunction(); +final getTransactionNative = moneroApi + .lookup>('get_transaction') + .asFunction(); + String getTxKey(String txId) { final txIdPointer = txId.toNativeUtf8(); final keyPointer = getTxKeyNative(txIdPointer); @@ -65,6 +70,11 @@ List getAllTransactions() { .toList(); } +TransactionInfoRow getTransaction(String txId) { + final txIdPointer = txId.toNativeUtf8(); + return getTransactionNative(txIdPointer).ref; +} + PendingTransactionDescription createTransactionSync( {required String address, required String paymentId, diff --git a/cw_monero/lib/api/types.dart b/cw_monero/lib/api/types.dart index 2c92f2d80..4c0c980dc 100644 --- a/cw_monero/lib/api/types.dart +++ b/cw_monero/lib/api/types.dart @@ -1,6 +1,7 @@ import 'dart:ffi'; import 'package:cw_monero/api/structs/coins_info_row.dart'; import 'package:cw_monero/api/structs/pending_transaction.dart'; +import 'package:cw_monero/api/structs/transaction_info_row.dart'; import 'package:cw_monero/api/structs/ut8_box.dart'; import 'package:ffi/ffi.dart'; @@ -81,6 +82,8 @@ typedef AccountSetLabel = void Function(int accountIndex, Pointer label); typedef TransactionsRefresh = void Function(); +typedef GetTransaction = Pointer Function(Pointer txId); + typedef GetTxKey = Pointer? Function(Pointer txId); typedef TransactionsCount = int Function(); @@ -139,3 +142,7 @@ typedef RefreshCoins = void Function(int); typedef CoinsCount = int Function(); typedef GetCoin = Pointer Function(int); + +typedef FreezeCoin = void Function(int); + +typedef ThawCoin = void Function(int); diff --git a/cw_monero/lib/monero_unspent.dart b/cw_monero/lib/monero_unspent.dart index c2ff9f9db..65b5c595d 100644 --- a/cw_monero/lib/monero_unspent.dart +++ b/cw_monero/lib/monero_unspent.dart @@ -1,28 +1,20 @@ +import 'package:cw_core/unspent_transaction_output.dart'; import 'package:cw_monero/api/structs/coins_info_row.dart'; -class MoneroUnspent { - MoneroUnspent(this.address, this.hash, this.keyImage, this.value, this.isFrozen, this.isUnlocked) - : isSending = true, - note = ''; +class MoneroUnspent extends Unspent { + MoneroUnspent( + String address, String hash, String keyImage, int value, bool isFrozen, this.isUnlocked) + : super(address, hash, value, 0, keyImage) { + this.isFrozen = isFrozen; + } - MoneroUnspent.fromCoinsInfoRow(CoinsInfoRow coinsInfoRow) - : address = coinsInfoRow.getAddress(), - hash = coinsInfoRow.getHash(), - keyImage = coinsInfoRow.getKeyImage(), - value = coinsInfoRow.amount, - isFrozen = coinsInfoRow.frozen == 1, - isUnlocked = coinsInfoRow.unlocked == 1, - isSending = true, - note = ''; - - final String address; - final String hash; - final String keyImage; - final int value; + factory MoneroUnspent.fromCoinsInfoRow(CoinsInfoRow coinsInfoRow) => MoneroUnspent( + coinsInfoRow.getAddress(), + coinsInfoRow.getHash(), + coinsInfoRow.getKeyImage(), + coinsInfoRow.amount, + coinsInfoRow.frozen == 1, + coinsInfoRow.unlocked == 1); final bool isUnlocked; - - bool isFrozen; - bool isSending; - String note; } diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 83219af5b..d7e66ecec 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:io'; + import 'package:cw_core/account.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/monero_amount_format.dart'; @@ -22,14 +23,14 @@ import 'package:cw_monero/api/transaction_history.dart' as transaction_history; import 'package:cw_monero/api/wallet.dart' as monero_wallet; import 'package:cw_monero/exceptions/monero_transaction_creation_exception.dart'; import 'package:cw_monero/exceptions/monero_transaction_no_inputs_exception.dart'; -import 'package:cw_monero/pending_monero_transaction.dart'; import 'package:cw_monero/monero_transaction_creation_credentials.dart'; import 'package:cw_monero/monero_transaction_history.dart'; import 'package:cw_monero/monero_transaction_info.dart'; import 'package:cw_monero/monero_unspent.dart'; import 'package:cw_monero/monero_wallet_addresses.dart'; -import 'package:mobx/mobx.dart'; +import 'package:cw_monero/pending_monero_transaction.dart'; import 'package:hive/hive.dart'; +import 'package:mobx/mobx.dart'; part 'monero_wallet.g.dart'; @@ -204,7 +205,7 @@ abstract class MoneroWalletBase for (final utx in unspentCoins) { if (utx.isSending) { allInputsAmount += utx.value; - inputs.add(utx.keyImage); + inputs.add(utx.keyImage!); } } final spendAllCoins = inputs.length == unspentCoins.length; @@ -395,7 +396,9 @@ abstract class MoneroWalletBase for (var i = 0; i < coinCount; i++) { final coin = getCoin(i); if (coin.spent == 0) { - unspentCoins.add(MoneroUnspent.fromCoinsInfoRow(coin)); + final unspent = MoneroUnspent.fromCoinsInfoRow(coin); + unspent.isChange = transaction_history.getTransaction(unspent.hash).direction == 1; + unspentCoins.add(unspent); } } @@ -406,8 +409,10 @@ abstract class MoneroWalletBase if (unspentCoins.isNotEmpty) { unspentCoins.forEach((coin) { - final coinInfoList = unspentCoinsInfo.values - .where((element) => element.walletId.contains(id) && element.hash.contains(coin.hash)); + final coinInfoList = unspentCoinsInfo.values.where((element) => + element.walletId.contains(id) && + element.accountIndex == walletAddresses.account!.id && + element.keyImage!.contains(coin.keyImage!)); if (coinInfoList.isNotEmpty) { final coinInfo = coinInfoList.first; @@ -435,7 +440,9 @@ abstract class MoneroWalletBase address: coin.address, value: coin.value, vout: 0, - keyImage: coin.keyImage); + keyImage: coin.keyImage, + isChange: coin.isChange, + accountIndex: walletAddresses.account!.id); await unspentCoinsInfo.add(newInfo); } @@ -443,12 +450,13 @@ abstract class MoneroWalletBase Future _refreshUnspentCoinsInfo() async { try { final List keys = []; - final currentWalletUnspentCoins = - unspentCoinsInfo.values.where((element) => element.walletId.contains(id)); + final currentWalletUnspentCoins = unspentCoinsInfo.values.where((element) => + element.walletId.contains(id) && element.accountIndex == walletAddresses.account!.id); if (currentWalletUnspentCoins.isNotEmpty) { currentWalletUnspentCoins.forEach((element) { - final existUnspentCoins = unspentCoins.where((coin) => element.hash.contains(coin.hash)); + final existUnspentCoins = + unspentCoins.where((coin) => element.keyImage!.contains(coin.keyImage!)); if (existUnspentCoins.isEmpty) { keys.add(element.key); @@ -566,7 +574,8 @@ abstract class MoneroWalletBase int _getFrozenBalance() { var frozenBalance = 0; - for (var coin in unspentCoinsInfo.values) { + for (var coin in unspentCoinsInfo.values.where((element) => + element.walletId == id && element.accountIndex == walletAddresses.account!.id)) { if (coin.isFrozen) frozenBalance += coin.value; } diff --git a/lib/monero/cw_monero.dart b/lib/monero/cw_monero.dart index 1de7b8452..9ae248ca0 100644 --- a/lib/monero/cw_monero.dart +++ b/lib/monero/cw_monero.dart @@ -321,10 +321,7 @@ class CWMonero extends Monero { @override List getUnspents(Object wallet) { final moneroWallet = wallet as MoneroWallet; - return moneroWallet.unspentCoins - .map((MoneroUnspent moneroUnspent) => Unspent(moneroUnspent.address, moneroUnspent.hash, - moneroUnspent.value, 0, moneroUnspent.keyImage)) - .toList(); + return moneroWallet.unspentCoins; } @override diff --git a/lib/src/screens/unspent_coins/unspent_coins_list_page.dart b/lib/src/screens/unspent_coins/unspent_coins_list_page.dart index 1a173f62a..36cbda641 100644 --- a/lib/src/screens/unspent_coins/unspent_coins_list_page.dart +++ b/lib/src/screens/unspent_coins/unspent_coins_list_page.dart @@ -1,15 +1,13 @@ import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart'; -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_list_view_model.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:cake_wallet/generated/i18n.dart'; class UnspentCoinsListPage extends BasePage { UnspentCoinsListPage({required this.unspentCoinsListViewModel}); @@ -17,31 +15,10 @@ class UnspentCoinsListPage extends BasePage { @override String get title => S.current.unspent_coins_title; - //@override - //Widget trailing(BuildContext context) { - // final questionImage = Image.asset('assets/images/question_mark.png', - // color: Theme.of(context).extension()!.titleColor); - - // return SizedBox( - // height: 20.0, - // width: 20.0, - // child: ButtonTheme( - // minWidth: double.minPositive, - // child: FlatButton( - // highlightColor: Colors.transparent, - // splashColor: Colors.transparent, - // padding: EdgeInsets.all(0), - // onPressed: () => showUnspentCoinsAlert(context), - // child: questionImage), - // ), - // ); - //} - final UnspentCoinsListViewModel unspentCoinsListViewModel; @override - Widget body(BuildContext context) => - UnspentCoinsListForm(unspentCoinsListViewModel); + Widget body(BuildContext context) => UnspentCoinsListForm(unspentCoinsListViewModel); } class UnspentCoinsListForm extends StatefulWidget { @@ -50,8 +27,7 @@ class UnspentCoinsListForm extends StatefulWidget { final UnspentCoinsListViewModel unspentCoinsListViewModel; @override - UnspentCoinsListFormState createState() => - UnspentCoinsListFormState(unspentCoinsListViewModel); + UnspentCoinsListFormState createState() => UnspentCoinsListFormState(unspentCoinsListViewModel); } class UnspentCoinsListFormState extends State { @@ -59,16 +35,6 @@ class UnspentCoinsListFormState extends State { final UnspentCoinsListViewModel unspentCoinsListViewModel; - @override - void initState() { - super.initState(); - WidgetsBinding.instance.addPostFrameCallback(afterLayout); - } - - void afterLayout(dynamic _) { - //showUnspentCoinsAlert(context); - } - @override Widget build(BuildContext context) { return Container( @@ -76,8 +42,7 @@ class UnspentCoinsListFormState extends State { child: Observer( builder: (_) => ListView.separated( itemCount: unspentCoinsListViewModel.items.length, - separatorBuilder: (_, __) => - SizedBox(height: 15), + separatorBuilder: (_, __) => SizedBox(height: 15), itemBuilder: (_, int index) { return Observer(builder: (_) { final item = unspentCoinsListViewModel.items[index]; @@ -86,38 +51,22 @@ class UnspentCoinsListFormState extends State { : item.address; return GestureDetector( - onTap: () => - Navigator.of(context) - .pushNamed(Routes.unspentCoinsDetails, - arguments: [item, unspentCoinsListViewModel]), + onTap: () => Navigator.of(context).pushNamed(Routes.unspentCoinsDetails, + arguments: [item, unspentCoinsListViewModel]), child: UnspentCoinsListItem( note: item.note, amount: item.amount, address: address, isSending: item.isSending, isFrozen: item.isFrozen, + isChange: item.isChange, onCheckBoxTap: item.isFrozen - ? null - : () async { - item.isSending = !item.isSending; - await unspentCoinsListViewModel - .saveUnspentCoinInfo(item);})); + ? null + : () async { + item.isSending = !item.isSending; + await unspentCoinsListViewModel.saveUnspentCoinInfo(item); + })); }); - } - ) - ) - ); + }))); } } - -void showUnspentCoinsAlert(BuildContext context) { - showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: '', - alertContent: 'Information about unspent coins', - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop()); - }); -} \ No newline at end of file diff --git a/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart b/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart index 93cf27af1..d629e9454 100644 --- a/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart +++ b/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart @@ -1,8 +1,8 @@ import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:flutter/material.dart'; -import 'package:cake_wallet/generated/i18n.dart'; class UnspentCoinsListItem extends StatelessWidget { UnspentCoinsListItem({ @@ -11,6 +11,7 @@ class UnspentCoinsListItem extends StatelessWidget { required this.address, required this.isSending, required this.isFrozen, + required this.isChange, this.onCheckBoxTap, }); @@ -19,6 +20,7 @@ class UnspentCoinsListItem extends StatelessWidget { final String address; final bool isSending; final bool isFrozen; + final bool isChange; final Function()? onCheckBoxTap; @override @@ -27,9 +29,8 @@ class UnspentCoinsListItem extends StatelessWidget { final selectedItemColor = Theme.of(context).primaryColor; final itemColor = isSending ? selectedItemColor : unselectedItemColor; - final amountColor = isSending - ? Colors.white - : Theme.of(context).extension()!.buttonTextColor; + final amountColor = + isSending ? Colors.white : Theme.of(context).extension()!.buttonTextColor; final addressColor = isSending ? Colors.white.withOpacity(0.5) : Theme.of(context).extension()!.buttonSecondaryTextColor; @@ -47,7 +48,8 @@ class UnspentCoinsListItem extends StatelessWidget { child: StandardCheckbox( iconColor: amountColor, borderColor: addressColor, - value: isSending, onChanged: (value) => onCheckBoxTap?.call())), + value: isSending, + onChanged: (value) => onCheckBoxTap?.call())), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -57,9 +59,7 @@ class UnspentCoinsListItem extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ + Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ if (note.isNotEmpty) AutoSizeText( note, @@ -69,8 +69,8 @@ class UnspentCoinsListItem extends StatelessWidget { ), AutoSizeText( amount, - style: - TextStyle(color: amountColor, fontSize: 15, fontWeight: FontWeight.w600), + style: TextStyle( + color: amountColor, fontSize: 15, fontWeight: FontWeight.w600), maxLines: 1, ) ]), @@ -84,23 +84,41 @@ class UnspentCoinsListItem extends StatelessWidget { alignment: Alignment.center, child: Text( S.of(context).frozen, - style: - TextStyle(color: amountColor, fontSize: 7, fontWeight: FontWeight.w600), - )) + style: TextStyle( + color: amountColor, fontSize: 7, fontWeight: FontWeight.w600), + )), ], ), Expanded( child: Row( crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ AutoSizeText( - '${address.substring(0, 5)}...${address.substring(address.length-5)}', // ToDo: Maybe use address label + '${address.substring(0, 5)}...${address.substring(address.length - 5)}', // ToDo: Maybe use address label style: TextStyle( color: addressColor, fontSize: 12, ), maxLines: 1, ), + if (isChange) + Container( + height: 17, + padding: EdgeInsets.only(left: 6, right: 6), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(8.5)), + color: Colors.white), + alignment: Alignment.center, + child: Text( + S.of(context).unspent_change, + style: TextStyle( + color: itemColor, + fontSize: 7, + fontWeight: FontWeight.w600, + ), + ), + ), ], ), ), diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index 06d05b3a3..f32b43cd6 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -175,10 +175,8 @@ abstract class BalanceViewModelBase with Store { return '---'; } - return _getFiatBalance( - price: price, - cryptoAmount: getFormattedFrozenBalance(walletBalance)) + ' ' + fiatCurrency.toString(); - + return _getFiatBalance(price: price, cryptoAmount: getFormattedFrozenBalance(walletBalance)) + + ' ${fiatCurrency.toString()}'; } @computed @@ -201,10 +199,8 @@ abstract class BalanceViewModelBase with Store { return '---'; } - return _getFiatBalance( - price: price, - cryptoAmount: walletBalance.formattedAvailableBalance) + ' ' + fiatCurrency.toString(); - + return _getFiatBalance(price: price, cryptoAmount: walletBalance.formattedAvailableBalance) + + ' ${fiatCurrency.toString()}'; } @computed @@ -216,10 +212,8 @@ abstract class BalanceViewModelBase with Store { return '---'; } - return _getFiatBalance( - price: price, - cryptoAmount: walletBalance.formattedAdditionalBalance) + ' ' + fiatCurrency.toString(); - + return _getFiatBalance(price: price, cryptoAmount: walletBalance.formattedAdditionalBalance) + + ' ${fiatCurrency.toString()}'; } @computed diff --git a/lib/view_model/unspent_coins/unspent_coins_item.dart b/lib/view_model/unspent_coins/unspent_coins_item.dart index 9d1f6c71c..bb5c4dd7b 100644 --- a/lib/view_model/unspent_coins/unspent_coins_item.dart +++ b/lib/view_model/unspent_coins/unspent_coins_item.dart @@ -12,6 +12,7 @@ abstract class UnspentCoinsItemBase with Store { required this.isFrozen, required this.note, required this.isSending, + required this.isChange, required this.amountRaw, required this.vout, required this.keyImage @@ -35,6 +36,9 @@ abstract class UnspentCoinsItemBase with Store { @observable bool isSending; + @observable + bool isChange; + @observable int amountRaw; diff --git a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart index 709c50562..1815b1689 100644 --- a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart +++ b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart @@ -1,10 +1,8 @@ -import 'package:collection/collection.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; -import 'package:cw_core/unspent_transaction_output.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_item.dart'; import 'package:cw_core/unspent_coins_info.dart'; -import 'package:cw_core/wallet_addresses.dart'; +import 'package:cw_core/unspent_transaction_output.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; @@ -26,66 +24,49 @@ abstract class UnspentCoinsListViewModelBase with Store { @computed ObservableList get items => ObservableList.of(_getUnspents().map((elem) { - final amount = formatAmountToString(elem.value) + ' ${wallet.currency.title}'; - final info = getUnspentCoinInfo(elem.hash, elem.address, elem.value, elem.vout, elem.keyImage); return UnspentCoinsItem( address: elem.address, - amount: amount, + amount: '${formatAmountToString(elem.value)} ${wallet.currency.title}', hash: elem.hash, - isFrozen: info?.isFrozen ?? false, - note: info?.note ?? '', - isSending: info?.isSending ?? true, + isFrozen: info.isFrozen, + note: info.note, + isSending: info.isSending, amountRaw: elem.value, vout: elem.vout, - keyImage: elem.keyImage); + keyImage: elem.keyImage, + isChange: elem.isChange, + ); })); Future saveUnspentCoinInfo(UnspentCoinsItem item) async { try { final info = getUnspentCoinInfo(item.hash, item.address, item.amountRaw, item.vout, item.keyImage); - if (info == null) { - final newInfo = UnspentCoinsInfo( - walletId: wallet.id, - hash: item.hash, - address: item.address, - value: item.amountRaw, - vout: item.vout, - isFrozen: item.isFrozen, - isSending: item.isSending, - noteRaw: item.note, - keyImage: item.keyImage); - await _unspentCoinsInfo.add(newInfo); - _updateUnspents(); - wallet.updateBalance(); - return; - } info.isFrozen = item.isFrozen; info.isSending = item.isSending; info.note = item.note; await info.save(); - _updateUnspents(); - wallet.updateBalance(); + await _updateUnspents(); + await wallet.updateBalance(); } catch (e) { print(e.toString()); } } - UnspentCoinsInfo? getUnspentCoinInfo( - String hash, String address, int value, int vout, String? keyImage) { - return _unspentCoinsInfo.values.firstWhereOrNull((element) => - element.walletId == wallet.id && - element.hash == hash && - element.address == address && - element.value == value && - element.vout == vout && - element.keyImage == keyImage); - } + UnspentCoinsInfo getUnspentCoinInfo( + String hash, String address, int value, int vout, String? keyImage) => + _unspentCoinsInfo.values.firstWhere((element) => + element.walletId == wallet.id && + element.hash == hash && + element.address == address && + element.value == value && + element.vout == vout && + element.keyImage == keyImage); String formatAmountToString(int fullBalance) { if (wallet.type == WalletType.monero) @@ -95,7 +76,7 @@ abstract class UnspentCoinsListViewModelBase with Store { return ''; } - void _updateUnspents() { + Future _updateUnspents() async { if (wallet.type == WalletType.monero) return monero!.updateUnspents(wallet); if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(wallet.type)) return bitcoin!.updateUnspents(wallet); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 4100bdeb8..54a9a1d75 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -726,5 +726,6 @@ "domain_looks_up": "ﻝﺎﺠﻤﻟﺍ ﺚﺤﺑ ﺕﺎﻴﻠﻤﻋ", "require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ", "camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ", - "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ" + "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", + "unspent_change": "يتغير" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index e12a24119..89be7d8a9 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -722,5 +722,6 @@ "domain_looks_up": "Търсене на домейни", "require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли", "camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.", - "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново" + "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново", + "unspent_change": "Промяна" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 52087ef60..4b3d2c44e 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -722,5 +722,6 @@ "domain_looks_up": "Vyhledávání domén", "require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek", "camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.", - "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu" + "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu", + "unspent_change": "Změna" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 733b645c9..8fa81fdb0 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -730,5 +730,6 @@ "domain_looks_up": "Domain-Suchen", "require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets", "camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.", - "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut" + "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut", + "unspent_change": "Wechselgeld" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 4264d6b37..327bfbdc9 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -731,5 +731,6 @@ "domain_looks_up": "Domain lookups", "require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets", "camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.", - "switchToETHWallet": "Please switch to an Ethereum wallet and try again" + "switchToETHWallet": "Please switch to an Ethereum wallet and try again", + "unspent_change": "Change" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 728d15afb..89143e97c 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -730,5 +730,6 @@ "domain_looks_up": "Búsquedas de dominio", "require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas", "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.", - "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente." + "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente.", + "unspent_change": "Cambiar" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index d4d27ae0b..8e43afee5 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -730,5 +730,6 @@ "domain_looks_up": "Recherches de domaine", "require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes", "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", - "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer" + "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", + "unspent_change": "Changement" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 57199fa47..506c68503 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -708,5 +708,6 @@ "domain_looks_up": "Binciken yanki", "require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje", "camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.", - "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa" + "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa", + "unspent_change": "Canza" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 536731c94..5c77d0f01 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -730,5 +730,6 @@ "domain_looks_up": "डोमेन लुकअप", "require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है", "camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।", - "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें" + "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें", + "unspent_change": "परिवर्तन" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 936e41338..e09df5a99 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -728,5 +728,6 @@ "domain_looks_up": "Pretraga domena", "require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike", "camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.", - "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno" + "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno", + "unspent_change": "Promijeniti" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 036e3e96d..1f1640744 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -718,5 +718,6 @@ "domain_looks_up": "Pencarian domain", "require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal", "camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.", - "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi" + "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi", + "unspent_change": "Mengubah" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 5138b1a59..0a626932c 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -730,5 +730,6 @@ "domain_looks_up": "Ricerche di domini", "require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni", "camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.", - "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova" + "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova", + "unspent_change": "Modifica" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index cc6dad9a8..40ab152a9 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -730,5 +730,6 @@ "domain_looks_up": "ドメイン検索", "require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要", "camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。", - "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください" + "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください", + "unspent_change": "変化" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 9ce833b08..ea95072cf 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -728,5 +728,6 @@ "domain_looks_up": "도메인 조회", "require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요", "camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.", - "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요." + "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요.", + "unspent_change": "변화" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index c92871c5f..f2a4a8fac 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -728,5 +728,6 @@ "domain_looks_up": "ဒိုမိန်းရှာဖွေမှုများ", "require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", "camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။", - "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။" + "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။", + "unspent_change": "ပေြာင်းလဲခြင်း" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index c93861b2b..a582a9439 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -730,5 +730,6 @@ "domain_looks_up": "Domein opzoeken", "require_for_exchanges_to_external_wallets": "Vereist voor uitwisselingen naar externe portemonnees", "camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.", - "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw" + "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw", + "unspent_change": "Wijziging" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 5d32aaa74..85b8668b9 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -730,5 +730,6 @@ "domain_looks_up": "Wyszukiwanie domen", "require_for_exchanges_to_external_wallets": "Wymagaj wymiany na portfele zewnętrzne", "camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.", - "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie" + "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie", + "unspent_change": "Zmiana" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index aa1f7459f..3c7253197 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -729,5 +729,6 @@ "domain_looks_up": "Pesquisas de domínio", "require_for_exchanges_to_external_wallets": "Exigir trocas para carteiras externas", "camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.", - "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente" + "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente", + "unspent_change": "Mudar" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 31fc00bca..a833e2c4c 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -730,5 +730,6 @@ "domain_looks_up": "Поиск доменов", "require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки", "camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.", - "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку." + "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку.", + "unspent_change": "Изменять" } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index b9757a08d..f20d7e3ae 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -728,5 +728,6 @@ "domain_looks_up": "การค้นหาโดเมน", "require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก", "camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป", - "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง" + "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง", + "unspent_change": "เปลี่ยน" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 6157d9eb3..e323a3523 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -725,5 +725,6 @@ "domain_looks_up": "Mga paghahanap ng domain", "require_for_exchanges_to_external_wallets": "Kinakailangan para sa mga palitan sa mga panlabas na wallet", "camera_permission_is_required": "Kinakailangan ang pahintulot sa camera.\nMangyaring paganahin ito mula sa mga setting ng app.", - "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli" + "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli", + "unspent_change": "Baguhin" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index ddc669221..b13b85bb4 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -728,5 +728,6 @@ "domain_looks_up": "Etki alanı aramaları", "require_for_exchanges_to_external_wallets": "Harici cüzdanlara geçiş yapılmasını zorunlu kılın", "camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.", - "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin" + "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin", + "unspent_change": "Değiştirmek" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 9fb39b6cf..6ee8a491e 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -730,5 +730,6 @@ "domain_looks_up": "Пошук доменів", "require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці", "camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.", - "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу" + "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу", + "unspent_change": "Зміна" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index e3f934891..2f44cb510 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -722,5 +722,6 @@ "domain_looks_up": "ڈومین تلاش کرنا", "require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ", "camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ", - "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ" + "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ", + "unspent_change": "تبدیل کریں" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index aafb70803..09f9d1b87 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -724,5 +724,6 @@ "domain_looks_up": "Awọn wiwa agbegbe", "require_for_exchanges_to_external_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ ita", "camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.", - "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi" + "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi", + "unspent_change": "Yipada" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 336083a72..1eec3f477 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -729,5 +729,6 @@ "domain_looks_up": "域名查找", "require_for_exchanges_to_external_wallets": "需要兑换到外部钱包", "camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。", - "switchToETHWallet": "请切换到以太坊钱包并重试" + "switchToETHWallet": "请切换到以太坊钱包并重试", + "unspent_change": "改变" } From 28ad0dbd692880bdb4e24bdd5c93e72d947d3a2a Mon Sep 17 00:00:00 2001 From: Mathias Herberts Date: Wed, 15 Nov 2023 23:18:50 +0000 Subject: [PATCH 035/241] Minor fixes to FR localization (#1164) Co-authored-by: Omar Hatem --- res/values/strings_fr.arb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 8e43afee5..f83493f7a 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -727,9 +727,9 @@ "enter_seed_phrase": "Entrez votre phrase secrète (seed)", "add_contact": "Ajouter le contact", "exchange_provider_unsupported": "${providerName} n'est plus pris en charge !", - "domain_looks_up": "Recherches de domaine", + "domain_looks_up": "Résolution de nom", "require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes", - "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", + "camera_permission_is_required": "L'autorisation d'accès à la caméra est requise.\nVeuillez l'activer depuis les paramètres de l'application.", "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", "unspent_change": "Changement" } From bb5336ff604e9983f5ddcf546abf206431adb37c Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 17 Nov 2023 01:22:10 +0200 Subject: [PATCH 036/241] CW-516-Improve-balance-layout-in-home-screen (#1171) * unavailable balance * localization * unavailable balance description * add unavailable balance popup --- cw_core/lib/balance.dart | 2 +- cw_core/lib/monero_balance.dart | 14 +-- .../dashboard/widgets/balance_page.dart | 102 +++++++++++------- .../dashboard/balance_view_model.dart | 2 +- res/values/strings_ar.arb | 5 +- res/values/strings_bg.arb | 3 +- res/values/strings_cs.arb | 3 +- res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 3 +- res/values/strings_es.arb | 3 +- res/values/strings_fr.arb | 3 +- res/values/strings_ha.arb | 3 +- res/values/strings_hi.arb | 3 +- res/values/strings_hr.arb | 3 +- res/values/strings_id.arb | 3 +- res/values/strings_it.arb | 3 +- res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 3 +- res/values/strings_nl.arb | 3 +- res/values/strings_pl.arb | 3 +- res/values/strings_pt.arb | 3 +- res/values/strings_ru.arb | 3 +- res/values/strings_th.arb | 3 +- res/values/strings_tl.arb | 3 +- res/values/strings_tr.arb | 3 +- res/values/strings_uk.arb | 3 +- res/values/strings_ur.arb | 3 +- res/values/strings_yo.arb | 3 +- res/values/strings_zh.arb | 3 +- 30 files changed, 124 insertions(+), 76 deletions(-) diff --git a/cw_core/lib/balance.dart b/cw_core/lib/balance.dart index 6145411c4..431aff515 100644 --- a/cw_core/lib/balance.dart +++ b/cw_core/lib/balance.dart @@ -9,5 +9,5 @@ abstract class Balance { String get formattedAdditionalBalance; - String get formattedFrozenBalance => ''; + String get formattedUnAvailableBalance => ''; } diff --git a/cw_core/lib/monero_balance.dart b/cw_core/lib/monero_balance.dart index bf30110a3..98a7f134a 100644 --- a/cw_core/lib/monero_balance.dart +++ b/cw_core/lib/monero_balance.dart @@ -4,17 +4,18 @@ import 'package:cw_core/monero_amount_format.dart'; class MoneroBalance extends Balance { MoneroBalance({required this.fullBalance, required this.unlockedBalance, this.frozenBalance = 0}) : formattedFullBalance = moneroAmountToString(amount: fullBalance), - formattedUnlockedBalance = moneroAmountToString(amount: unlockedBalance), - frozenFormatted = moneroAmountToString(amount: frozenBalance), + formattedUnlockedBalance = moneroAmountToString(amount: unlockedBalance - frozenBalance), + formattedLockedBalance = + moneroAmountToString(amount: frozenBalance + fullBalance - unlockedBalance), super(unlockedBalance, fullBalance); MoneroBalance.fromString( {required this.formattedFullBalance, required this.formattedUnlockedBalance, - this.frozenFormatted = '0.0'}) + this.formattedLockedBalance = '0.0'}) : fullBalance = moneroParseAmount(amount: formattedFullBalance), unlockedBalance = moneroParseAmount(amount: formattedUnlockedBalance), - frozenBalance = moneroParseAmount(amount: frozenFormatted), + frozenBalance = moneroParseAmount(amount: formattedLockedBalance), super(moneroParseAmount(amount: formattedUnlockedBalance), moneroParseAmount(amount: formattedFullBalance)); @@ -23,10 +24,11 @@ class MoneroBalance extends Balance { final int frozenBalance; final String formattedFullBalance; final String formattedUnlockedBalance; - final String frozenFormatted; + final String formattedLockedBalance; @override - String get formattedFrozenBalance => frozenFormatted == '0.0' ? '' : frozenFormatted; + String get formattedUnAvailableBalance => + formattedLockedBalance == '0.0' ? '' : formattedLockedBalance; @override String get formattedAvailableBalance => formattedUnlockedBalance; diff --git a/lib/src/screens/dashboard/widgets/balance_page.dart b/lib/src/screens/dashboard/widgets/balance_page.dart index b4c4f71dc..41d4e7bb0 100644 --- a/lib/src/screens/dashboard/widgets/balance_page.dart +++ b/lib/src/screens/dashboard/widgets/balance_page.dart @@ -165,7 +165,9 @@ class BalancePage extends StatelessWidget { children: [ GestureDetector( behavior: HitTestBehavior.opaque, - onTap: hasAdditionalBalance ? () => _showBalanceDescription(context) : null, + onTap: hasAdditionalBalance ? () => + _showBalanceDescription(context, S.current.available_balance_description) + : null, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -225,47 +227,65 @@ class BalancePage extends StatelessWidget { ], ), if (frozenBalance.isNotEmpty) - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: 26), - Text( - S.current.frozen_balance, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context).extension()!.labelTextColor, - height: 1, + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: hasAdditionalBalance ? + () => _showBalanceDescription(context, S.current.unavailable_balance_description) + : null, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 26), + Row( + children: [ + Text( + S.current.unavailable_balance, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.labelTextColor, + height: 1, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Icon(Icons.help_outline, + size: 16, + color: Theme.of(context) + .extension()! + .labelTextColor), + ), + ], ), - ), - SizedBox(height: 8), - AutoSizeText( - frozenBalance, - style: TextStyle( - fontSize: 20, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context).extension()!.textColor, - height: 1, + SizedBox(height: 8), + AutoSizeText( + frozenBalance, + style: TextStyle( + fontSize: 20, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.textColor, + height: 1, + ), + maxLines: 1, + textAlign: TextAlign.center, ), - maxLines: 1, - textAlign: TextAlign.center, - ), - SizedBox(height: 4), - Text( - frozenFiatBalance, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context).extension()!.textColor, - height: 1, + SizedBox(height: 4), + Text( + frozenFiatBalance, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.textColor, + height: 1, + ), ), - ), - ], + ], + ), ), if (hasAdditionalBalance) Column( @@ -316,9 +336,9 @@ class BalancePage extends StatelessWidget { ); } - void _showBalanceDescription(BuildContext context) { + void _showBalanceDescription(BuildContext context, String content) { showPopUp( context: context, - builder: (_) => InformationPage(information: S.current.available_balance_description)); + builder: (_) => InformationPage(information: content)); } } diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index f32b43cd6..9366985b5 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -392,6 +392,6 @@ abstract class BalanceViewModelBase with Store { } } - String getFormattedFrozenBalance(Balance walletBalance) => walletBalance.formattedFrozenBalance; + String getFormattedFrozenBalance(Balance walletBalance) => walletBalance.formattedUnAvailableBalance; } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 54a9a1d75..4727a0262 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -591,7 +591,6 @@ "sweeping_wallet_alert": "لن يستغرق هذا وقتًا طويلاً. لا تترك هذه الشاشة وإلا فقد يتم فقد أموال سويبت", "decimal_places_error": "عدد كبير جدًا من المنازل العشرية", "edit_node": "تحرير العقدة", - "frozen_balance": "الرصيد المجمد", "invoice_details": "تفاصيل الفاتورة", "donation_link_details": "تفاصيل رابط التبرع", "anonpay_description": "توليد ${type}. يمكن للمستلم ${method} بأي عملة مشفرة مدعومة ، وستتلقى أموالاً في هذه", @@ -727,5 +726,7 @@ "require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ", "camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ", "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", + "unavailable_balance": " ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ", + "unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ", "unspent_change": "يتغير" -} +} \ No newline at end of file diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 89be7d8a9..d52529e38 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -588,7 +588,6 @@ "error_dialog_content": "Получихме грешка.\n\nМоля, изпратете доклада до нашия отдел поддръжка, за да подобрим приложението.", "decimal_places_error": "Твърде много знаци след десетичната запетая", "edit_node": "Редактиране на възел", - "frozen_balance": "Замразен баланс", "invoice_details": "IДанни за фактура", "donation_link_details": "Подробности за връзката за дарение", "anonpay_description": "Генерирайте ${type}. Получателят може да ${method} с всяка поддържана криптовалута и вие ще получите средства в този портфейл.", @@ -723,5 +722,7 @@ "require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли", "camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.", "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново", + "unavailable_balance": "Неналично салдо", + "unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.", "unspent_change": "Промяна" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 4b3d2c44e..8b86c517f 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -588,7 +588,6 @@ "error_dialog_content": "Nastala chyba.\n\nProsím odešlete zprávu o chybě naší podpoře, aby mohli zajistit opravu.", "decimal_places_error": "Příliš mnoho desetinných míst", "edit_node": "Upravit uzel", - "frozen_balance": "Zmrazená bilance", "invoice_details": "detaily faktury", "donation_link_details": "Podrobnosti odkazu na darování", "anonpay_description": "Vygenerujte ${type}. Příjemce může ${method} s jakoukoli podporovanou kryptoměnou a vy obdržíte prostředky v této peněžence.", @@ -723,5 +722,7 @@ "require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek", "camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.", "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu", + "unavailable_balance": "Nedostupný zůstatek", + "unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.", "unspent_change": "Změna" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 8fa81fdb0..0928e1462 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "Das sollte nicht lange dauern. VERLASSEN SIE DIESEN BILDSCHIRM NICHT, ANDERNFALLS KÖNNEN DIE GELDER VERLOREN GEHEN", "decimal_places_error": "Zu viele Nachkommastellen", "edit_node": "Knoten bearbeiten", - "frozen_balance": "Gefrorenes Guthaben", "invoice_details": "Rechnungs-Details", "donation_link_details": "Details zum Spendenlink", "anonpay_description": "Generieren Sie ${type}. Der Empfänger kann ${method} mit jeder unterstützten Kryptowährung verwenden, und Sie erhalten Geld in dieser Wallet.", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets", "camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.", "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut", + "unavailable_balance": "Nicht verfügbares Guthaben", + "unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.", "unspent_change": "Wechselgeld" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 327bfbdc9..55b6f8339 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -606,7 +606,6 @@ "onion_link": "Onion link", "decimal_places_error": "Too many decimal places", "edit_node": "Edit Node", - "frozen_balance": "Frozen Balance", "settings": "Settings", "sell_monero_com_alert_content": "Selling Monero is not supported yet", "error_text_input_below_minimum_limit": "Amount is less than the minimum", @@ -732,5 +731,7 @@ "require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets", "camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.", "switchToETHWallet": "Please switch to an Ethereum wallet and try again", + "unavailable_balance": "Unavailable balance", + "unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.", "unspent_change": "Change" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 89143e97c..048bf05ea 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "Esto no debería llevar mucho tiempo. NO DEJES ESTA PANTALLA O SE PUEDEN PERDER LOS FONDOS BARRIDOS", "decimal_places_error": "Demasiados lugares decimales", "edit_node": "Editar nodo", - "frozen_balance": "Balance congelado", "invoice_details": "Detalles de la factura", "donation_link_details": "Detalles del enlace de donación", "anonpay_description": "Genera ${type}. El destinatario puede ${method} con cualquier criptomoneda admitida, y recibirá fondos en esta billetera.", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas", "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.", "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente.", + "unavailable_balance": "Saldo no disponible", + "unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.", "unspent_change": "Cambiar" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index f83493f7a..d82f8a677 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "Cette opération ne devrait pas prendre longtemps. NE QUITTEZ PAS CET ÉCRAN OU LES FONDS CONSOLIDÉS POURRAIENT ÊTRE PERDUS", "decimal_places_error": "Trop de décimales", "edit_node": "Modifier le nœud", - "frozen_balance": "Solde gelé", "invoice_details": "Détails de la facture", "donation_link_details": "Détails du lien de don", "anonpay_description": "Générez ${type}. Le destinataire peut ${method} avec n'importe quelle crypto-monnaie prise en charge, et vous recevrez des fonds dans ce portefeuille (wallet).", @@ -729,6 +728,8 @@ "exchange_provider_unsupported": "${providerName} n'est plus pris en charge !", "domain_looks_up": "Résolution de nom", "require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes", + "unavailable_balance": "Solde indisponible", + "unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.", "camera_permission_is_required": "L'autorisation d'accès à la caméra est requise.\nVeuillez l'activer depuis les paramètres de l'application.", "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", "unspent_change": "Changement" diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 506c68503..6c0644316 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -602,7 +602,6 @@ "onion_link": "Lambar onion", "decimal_places_error": "Wadannan suna da tsawon harsuna", "edit_node": "Shirya Node", - "frozen_balance": "Falin kuma maɓallin", "settings": "Saiti", "sell_monero_com_alert_content": "Selling Monero bai sami ƙarshen mai bukatar samun ba", "error_text_input_below_minimum_limit": "Kudin ba a kamai", @@ -709,5 +708,7 @@ "require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje", "camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.", "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa", + "unavailable_balance": "Ma'aunin da ba ya samuwa", + "unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.", "unspent_change": "Canza" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 5c77d0f01..ae0b1a94d 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "इसमें अधिक समय नहीं लगना चाहिए। इस स्क्रीन को न छोड़ें या स्वैप्ट फंड खो सकते हैं", "decimal_places_error": "बहुत अधिक दशमलव स्थान", "edit_node": "नोड संपादित करें", - "frozen_balance": "जमे हुए संतुलन", "invoice_details": "चालान विवरण", "donation_link_details": "दान लिंक विवरण", "anonpay_description": "${type} उत्पन्न करें। प्राप्तकर्ता किसी भी समर्थित क्रिप्टोकरेंसी के साथ ${method} कर सकता है, और आपको इस वॉलेट में धन प्राप्त होगा।", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है", "camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।", "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें", + "unavailable_balance": "अनुपलब्ध शेष", + "unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।", "unspent_change": "परिवर्तन" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index e09df5a99..d9dcba723 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "Ovo ne bi trebalo dugo trajati. NE NAPUŠTAJTE OVAJ ZASLON INAČE SE POBREŠENA SREDSTVA MOGU IZGUBITI", "decimal_places_error": "Previše decimalnih mjesta", "edit_node": "Uredi čvor", - "frozen_balance": "Zamrznuti saldo", "invoice_details": "Podaci o fakturi", "donation_link_details": "Detalji veza za donacije", "anonpay_description": "Generiraj ${type}. Primatelj može ${method} s bilo kojom podržanom kriptovalutom, a vi ćete primiti sredstva u ovaj novčanik.", @@ -729,5 +728,7 @@ "require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike", "camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.", "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno", + "unavailable_balance": "Nedostupno stanje", + "unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.", "unspent_change": "Promijeniti" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 1f1640744..e6498d169 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -584,7 +584,6 @@ "contact_list_wallets": "Dompet Saya", "decimal_places_error": "Terlalu banyak tempat desimal", "edit_node": "Sunting Node", - "frozen_balance": "Saldo Beku", "invoice_details": "Detail faktur", "donation_link_details": "Detail tautan donasi", "anonpay_description": "Hasilkan ${type}. Penerima dapat ${method} dengan cryptocurrency apa pun yang didukung, dan Anda akan menerima dana di dompet ini.", @@ -719,5 +718,7 @@ "require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal", "camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.", "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi", + "unavailable_balance": "Saldo tidak tersedia", + "unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.", "unspent_change": "Mengubah" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 0a626932c..b78644766 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "Questo non dovrebbe richiedere molto tempo. NON LASCIARE QUESTA SCHERMATA O I FONDI SPAZZATI POTREBBERO ANDARE PERSI", "decimal_places_error": "Troppe cifre decimali", "edit_node": "Modifica nodo", - "frozen_balance": "Equilibrio congelato", "invoice_details": "Dettagli della fattura", "donation_link_details": "Dettagli del collegamento alla donazione", "anonpay_description": "Genera ${type}. Il destinatario può ${method} con qualsiasi criptovaluta supportata e riceverai fondi in questo portafoglio.", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni", "camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.", "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova", + "unavailable_balance": "Saldo non disponibile", + "unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.", "unspent_change": "Modifica" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 40ab152a9..1c7ad6497 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "これには時間がかかりません。この画面から離れないでください。そうしないと、スイープ ファンドが失われる可能性があります", "decimal_places_error": "小数点以下の桁数が多すぎる", "edit_node": "ノードを編集", - "frozen_balance": "冷凍残高", "invoice_details": "請求の詳細", "donation_link_details": "寄付リンクの詳細", "anonpay_description": "${type} を生成します。受取人はサポートされている任意の暗号通貨で ${method} でき、あなたはこのウォレットで資金を受け取ります。", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要", "camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。", "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください", + "unavailable_balance": "利用できない残高", + "unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。", "unspent_change": "変化" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index ea95072cf..cbf1744e1 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "오래 걸리지 않습니다. 이 화면을 떠나지 마십시오. 그렇지 않으면 스웹트 자금이 손실될 수 있습니다.", "decimal_places_error": "소수점 이하 자릿수가 너무 많습니다.", "edit_node": "노드 편집", - "frozen_balance": "얼어붙은 균형", "invoice_details": "인보이스 세부정보", "donation_link_details": "기부 링크 세부정보", "anonpay_description": "${type} 생성. 수신자는 지원되는 모든 암호화폐로 ${method}할 수 있으며 이 지갑에서 자금을 받게 됩니다.", @@ -729,5 +728,7 @@ "require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요", "camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.", "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요.", + "unavailable_balance": "사용할 수 없는 잔액", + "unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.", "unspent_change": "변화" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index f2a4a8fac..bb2f8a86d 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -593,7 +593,6 @@ "sweeping_wallet_alert": "ဒါက ကြာကြာမခံသင့်ပါဘူး။ ဤစခရင်ကို ချန်မထားပါနှင့် သို့မဟုတ် ထုတ်ယူထားသော ရန်ပုံငွေများ ဆုံးရှုံးနိုင်သည်", "decimal_places_error": "ဒဿမနေရာများ များလွန်းသည်။", "edit_node": "Node ကို တည်းဖြတ်ပါ။", - "frozen_balance": "ေးခဲမှူ", "invoice_details": "ပြေစာအသေးစိတ်", "donation_link_details": "လှူဒါန်းရန်လင့်ခ်အသေးစိတ်", "anonpay_description": "${type} ကို ဖန်တီးပါ။ လက်ခံသူက ${method} ကို ပံ့ပိုးပေးထားသည့် cryptocurrency တစ်ခုခုဖြင့် လုပ်ဆောင်နိုင်ပြီး၊ သင်သည် ဤပိုက်ဆံအိတ်တွင် ရံပုံငွေများ ရရှိမည်ဖြစ်သည်။", @@ -729,5 +728,7 @@ "require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", "camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။", "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။", + "unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။", + "unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။", "unspent_change": "ပေြာင်းလဲခြင်း" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index a582a9439..e833dde50 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "Dit duurt niet lang. VERLAAT DIT SCHERM NIET, ANDERS KAN HET SWEPT-GELD VERLOREN WORDEN", "decimal_places_error": "Te veel decimalen", "edit_node": "Knooppunt bewerken", - "frozen_balance": "Bevroren saldo", "invoice_details": "Factuurgegevens", "donation_link_details": "Details van de donatielink", "anonpay_description": "Genereer ${type}. De ontvanger kan ${method} gebruiken met elke ondersteunde cryptocurrency en u ontvangt geld in deze portemonnee", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "Vereist voor uitwisselingen naar externe portemonnees", "camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.", "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw", + "unavailable_balance": "Onbeschikbaar saldo", + "unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.", "unspent_change": "Wijziging" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 85b8668b9..8429cec8a 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "To nie powinno zająć dużo czasu. NIE WYCHODŹ Z TEGO EKRANU, W PRZECIWNYM WYPADKU MOŻE ZOSTAĆ UTRACONA ŚRODKI", "decimal_places_error": "Za dużo miejsc dziesiętnych", "edit_node": "Edytuj węzeł", - "frozen_balance": "Zamrożona równowaga", "invoice_details": "Dane do faktury", "donation_link_details": "Szczegóły linku darowizny", "anonpay_description": "Wygeneruj ${type}. Odbiorca może ${method} z dowolną obsługiwaną kryptowalutą, a Ty otrzymasz środki w tym portfelu.", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "Wymagaj wymiany na portfele zewnętrzne", "camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.", "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie", + "unavailable_balance": "Niedostępne saldo", + "unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.", "unspent_change": "Zmiana" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 3c7253197..9bb27a582 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -594,7 +594,6 @@ "sweeping_wallet_alert": "To nie powinno zająć dużo czasu. NIE WYCHODŹ Z TEGO EKRANU, W PRZECIWNYM WYPADKU MOŻE ZOSTAĆ UTRACONA ŚRODKI", "decimal_places_error": "Muitas casas decimais", "edit_node": "Editar nó", - "frozen_balance": "Saldo Congelado", "invoice_details": "Detalhes da fatura", "donation_link_details": "Detalhes do link de doação", "anonpay_description": "Gere ${type}. O destinatário pode ${method} com qualquer criptomoeda suportada e você receberá fundos nesta carteira.", @@ -730,5 +729,7 @@ "require_for_exchanges_to_external_wallets": "Exigir trocas para carteiras externas", "camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.", "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente", + "unavailable_balance": "Saldo indisponível", + "unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.", "unspent_change": "Mudar" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index a833e2c4c..d0f64c8b2 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "Это не должно занять много времени. НЕ ПОКИДАЙТЕ ЭТОТ ЭКРАН, ИНАЧЕ ВЫЧИСЛЕННЫЕ СРЕДСТВА МОГУТ БЫТЬ ПОТЕРЯНЫ", "decimal_places_error": "Слишком много десятичных знаков", "edit_node": "Редактировать узел", - "frozen_balance": "Замороженный баланс", "invoice_details": "Детали счета", "donation_link_details": "Информация о ссылке для пожертвований", "anonpay_description": "Создайте ${type}. Получатель может использовать ${method} с любой поддерживаемой криптовалютой, и вы получите средства на этот кошелек.", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки", "camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.", "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку.", + "unavailable_balance": "Недоступный баланс", + "unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.", "unspent_change": "Изменять" } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index f20d7e3ae..3159bd649 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -593,7 +593,6 @@ "sweeping_wallet_alert": "การดำเนินการนี้ใช้เวลาไม่นาน อย่าออกจากหน้าจอนี้ มิฉะนั้นเงินที่กวาดไปอาจสูญหาย", "decimal_places_error": "ทศนิยมมากเกินไป", "edit_node": "แก้ไขโหนด", - "frozen_balance": "ยอดคงเหลือแช่แข็ง", "invoice_details": "รายละเอียดใบแจ้งหนี้", "donation_link_details": "รายละเอียดลิงค์บริจาค", "anonpay_description": "สร้าง ${type} ผู้รับสามารถ ${method} ด้วยสกุลเงินดิจิทัลที่รองรับ และคุณจะได้รับเงินในกระเป๋าสตางค์นี้", @@ -729,5 +728,7 @@ "require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก", "camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป", "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง", + "unavailable_balance": "ยอดคงเหลือไม่พร้อมใช้งาน", + "unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง", "unspent_change": "เปลี่ยน" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index e323a3523..b38dc35ad 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -606,7 +606,6 @@ "onion_link": "Link ng Onion", "decimal_places_error": "Masyadong maraming mga lugar na desimal", "edit_node": "I -edit ang node", - "frozen_balance": "Frozen na balanse", "settings": "Mga setting", "sell_monero_com_alert_content": "Ang pagbebenta ng Monero ay hindi pa suportado", "error_text_input_below_minimum_limit": "Ang halaga ay mas mababa sa minimum", @@ -726,5 +725,7 @@ "require_for_exchanges_to_external_wallets": "Kinakailangan para sa mga palitan sa mga panlabas na wallet", "camera_permission_is_required": "Kinakailangan ang pahintulot sa camera.\nMangyaring paganahin ito mula sa mga setting ng app.", "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli", + "unavailable_balance": "Hindi available na balanse", + "unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.", "unspent_change": "Baguhin" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index b13b85bb4..77d29f8d2 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -593,7 +593,6 @@ "sweeping_wallet_alert": "Bu uzun sürmemeli. BU EKRANDAN BIRAKMAYIN YOKSA SÜPÜRÜLEN FONLAR KAYBOLABİLİR", "decimal_places_error": "Çok fazla ondalık basamak", "edit_node": "Düğümü Düzenle", - "frozen_balance": "Dondurulmuş Bakiye", "invoice_details": "fatura detayları", "donation_link_details": "Bağış bağlantısı ayrıntıları", "anonpay_description": "${type} oluşturun. Alıcı, desteklenen herhangi bir kripto para birimi ile ${method} yapabilir ve bu cüzdanda para alırsınız.", @@ -729,5 +728,7 @@ "require_for_exchanges_to_external_wallets": "Harici cüzdanlara geçiş yapılmasını zorunlu kılın", "camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.", "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin", + "unavailable_balance": "Kullanılamayan bakiye", + "unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.", "unspent_change": "Değiştirmek" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 6ee8a491e..aa9e29687 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -595,7 +595,6 @@ "sweeping_wallet_alert": "Це не повинно зайняти багато часу. НЕ ЗАЛИШАЙТЕ ЦЬОГО ЕКРАНУ, АБО КОШТИ МОЖУТЬ БУТИ ВТРАЧЕНІ", "decimal_places_error": "Забагато знаків після коми", "edit_node": "Редагувати вузол", - "frozen_balance": "Заморожений баланс", "invoice_details": "Реквізити рахунку-фактури", "donation_link_details": "Деталі посилання для пожертв", "anonpay_description": "Згенерувати ${type}. Одержувач може ${method} будь-якою підтримуваною криптовалютою, і ви отримаєте кошти на цей гаманець.", @@ -731,5 +730,7 @@ "require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці", "camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.", "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу", + "unavailable_balance": "Недоступний баланс", + "unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.", "unspent_change": "Зміна" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 2f44cb510..e8cf03835 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -588,7 +588,6 @@ "error_dialog_content": "افوہ، ہمیں کچھ خرابی ملی۔\n\nایپلی کیشن کو بہتر بنانے کے لیے براہ کرم کریش رپورٹ ہماری سپورٹ ٹیم کو بھیجیں۔", "decimal_places_error": "بہت زیادہ اعشاریہ جگہیں۔", "edit_node": "نوڈ میں ترمیم کریں۔", - "frozen_balance": "منجمد بیلنس", "invoice_details": "رسید کی تفصیلات", "donation_link_details": "عطیہ کے لنک کی تفصیلات", "anonpay_description": "${type} بنائیں۔ وصول کنندہ کسی بھی تعاون یافتہ کرپٹو کرنسی کے ساتھ ${method} کرسکتا ہے، اور آپ کو اس بٹوے میں فنڈز موصول ہوں گے۔", @@ -723,5 +722,7 @@ "require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ", "camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ", "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ", + "unavailable_balance": " ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ", + "unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ", "unspent_change": "تبدیل کریں" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 09f9d1b87..7784e785a 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -599,7 +599,6 @@ "onion_link": "Kọja ilọ alubosa", "decimal_places_error": "Oọ̀rọ̀ ayipada ti o wa ni o dara julọ", "edit_node": "Tun awọn ọwọnrin ṣiṣe", - "frozen_balance": "Aferugbo Iye", "settings": "Awọn aseṣe", "sell_monero_com_alert_content": "Kọ ju lọwọ Monero ko ṣe ni ibamu", "error_text_input_below_minimum_limit": "Iye jọwọ ni o kere ti o wọle diẹ", @@ -725,5 +724,7 @@ "require_for_exchanges_to_external_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ ita", "camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.", "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi", + "unavailable_balance": "Iwontunwonsi ti ko si", + "unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.", "unspent_change": "Yipada" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 1eec3f477..454c79194 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -594,7 +594,6 @@ "sweeping_wallet_alert": "\n这应该不会花很长时间。请勿离开此屏幕,否则可能会丢失所掠取的资金", "decimal_places_error": "小数位太多", "edit_node": "编辑节点", - "frozen_balance": "冻结余额", "invoice_details": "发票明细", "donation_link_details": "捐赠链接详情", "anonpay_description": "生成 ${type}。收款人可以使用任何受支持的加密货币 ${method},您将在此钱包中收到资金。", @@ -730,5 +729,7 @@ "require_for_exchanges_to_external_wallets": "需要兑换到外部钱包", "camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。", "switchToETHWallet": "请切换到以太坊钱包并重试", + "unavailable_balance": "不可用余额", + "unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。", "unspent_change": "改变" } From 36361ef329fb7ae988d3e4e48b4109b7b98cc836 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 17 Nov 2023 01:23:34 +0200 Subject: [PATCH 037/241] CW-526-Add-Trocador-providers-option-in-privacy-settings (#1177) * Trocador settings page UI * add trocador providers states * add settings icon * minor fix * Revert "minor fix" This reverts commit e59d9dfdaf9bd1c13a17ae5012db80a8f973a4d4. * fixes * PR fixes * remove trocador menu icon --- lib/di.dart | 6 +++ .../provider/trocador_exchange_provider.dart | 43 +++++++++++++++++-- lib/router.dart | 5 +++ lib/routes.dart | 1 + lib/src/screens/settings/privacy_page.dart | 4 ++ .../settings/trocador_providers_page.dart | 37 ++++++++++++++++ lib/store/settings_store.dart | 19 ++++++++ .../exchange/exchange_view_model.dart | 3 +- .../trocador_providers_view_model.dart | 21 +++++++++ 9 files changed, 134 insertions(+), 5 deletions(-) create mode 100644 lib/src/screens/settings/trocador_providers_page.dart create mode 100644 lib/view_model/settings/trocador_providers_view_model.dart diff --git a/lib/di.dart b/lib/di.dart index 10662d816..8cc393510 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -45,6 +45,7 @@ import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dar import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart'; import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; +import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; @@ -92,6 +93,7 @@ import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart'; import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart'; import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart'; import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; +import 'package:cake_wallet/view_model/settings/trocador_providers_view_model.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_edit_view_model.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart'; @@ -699,6 +701,8 @@ Future setup({ return PrivacySettingsViewModel(getIt.get(), getIt.get().wallet!); }); + getIt.registerFactory(() => TrocadorProvidersViewModel(getIt.get())); + getIt.registerFactory(() { return OtherSettingsViewModel(getIt.get(), getIt.get().wallet!); }); @@ -752,6 +756,8 @@ Future setup({ getIt.registerFactory(() => PrivacyPage(getIt.get())); + getIt.registerFactory(() => TrocadorProvidersPage(getIt.get())); + getIt.registerFactory(() => DomainLookupsPage(getIt.get())); getIt.registerFactory(() => DisplaySettingsPage(getIt.get())); diff --git a/lib/exchange/provider/trocador_exchange_provider.dart b/lib/exchange/provider/trocador_exchange_provider.dart index 3d08bbd37..52e38ecc8 100644 --- a/lib/exchange/provider/trocador_exchange_provider.dart +++ b/lib/exchange/provider/trocador_exchange_provider.dart @@ -12,11 +12,27 @@ import 'package:cw_core/crypto_currency.dart'; import 'package:http/http.dart'; class TrocadorExchangeProvider extends ExchangeProvider { - TrocadorExchangeProvider({this.useTorOnly = false}) - : _lastUsedRateId = '', + TrocadorExchangeProvider({this.useTorOnly = false, this.providerStates = const {}}) + : _lastUsedRateId = '', _provider = [], super(pairList: supportedPairs(_notSupported)); bool useTorOnly; + final Map providerStates; + + static const List availableProviders = [ + 'Swapter', + 'StealthEx', + 'Simpleswap', + 'Swapuz' + 'ChangeNow', + 'Changehero', + 'FixedFloat', + 'LetsExchange', + 'Exolix', + 'Godex', + 'Exch', + 'CoinCraddle' + ]; static const List _notSupported = [ CryptoCurrency.stx, @@ -33,6 +49,7 @@ class TrocadorExchangeProvider extends ExchangeProvider { static const coinPath = 'api/coin'; String _lastUsedRateId; + List _provider; @override String get title => 'Trocador'; @@ -105,7 +122,6 @@ class TrocadorExchangeProvider extends ExchangeProvider { 'payment': isFixedRateMode ? 'True' : 'False', 'min_kycrating': 'C', 'markup': markup, - 'best_only': 'True', }; final uri = await _getUri(newRatePath, params); @@ -115,6 +131,9 @@ class TrocadorExchangeProvider extends ExchangeProvider { final toAmount = double.parse(responseJSON['amount_to'].toString()); final rateId = responseJSON['trade_id'] as String? ?? ''; + var quotes = responseJSON['quotes']['quotes'] as List; + _provider = quotes.map((quote) => quote['provider']).toList(); + if (rateId.isNotEmpty) _lastUsedRateId = rateId; return isReceiveAmount ? (amount / fromAmount) : (toAmount / amount); @@ -126,6 +145,7 @@ class TrocadorExchangeProvider extends ExchangeProvider { @override Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { + final params = { 'api_key': apiKey, 'ticker_from': _normalizeCurrency(request.fromCurrency), @@ -135,7 +155,6 @@ class TrocadorExchangeProvider extends ExchangeProvider { 'payment': isFixedRateMode ? 'True' : 'False', 'min_kycrating': 'C', 'markup': markup, - 'best_only': 'True', if (!isFixedRateMode) 'amount_from': request.fromAmount, if (isFixedRateMode) 'amount_to': request.toAmount, 'address': request.toAddress, @@ -153,6 +172,22 @@ class TrocadorExchangeProvider extends ExchangeProvider { params['id'] = _lastUsedRateId; } + + String firstAvailableProvider = ''; + + for (var provider in _provider) { + if (providerStates.containsKey(provider) && providerStates[provider] == true) { + firstAvailableProvider = provider as String; + break; + } + } + + if (firstAvailableProvider.isEmpty) { + throw Exception('No available provider is enabled'); + } + + params['provider'] = firstAvailableProvider; + final uri = await _getUri(createTradePath, params); final response = await get(uri); diff --git a/lib/router.dart b/lib/router.dart index 1211bbcb6..dc2d8f8ab 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -42,6 +42,7 @@ import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart'; import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; +import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; @@ -323,6 +324,10 @@ Route createRoute(RouteSettings settings) { return CupertinoPageRoute( fullscreenDialog: true, builder: (_) => getIt.get()); + case Routes.trocadorProvidersPage: + return CupertinoPageRoute( + fullscreenDialog: true, builder: (_) => getIt.get()); + case Routes.domainLookupsPage: return CupertinoPageRoute( fullscreenDialog: true, builder: (_) => getIt.get()); diff --git a/lib/routes.dart b/lib/routes.dart index 0b4e8817d..8b521247a 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -81,6 +81,7 @@ class Routes { static const connectionSync = '/connection_sync_page'; static const securityBackupPage = '/security_and_backup_page'; static const privacyPage = '/privacy_page'; + static const trocadorProvidersPage = '/trocador_providers_page'; static const domainLookupsPage = '/domain_lookups_page'; static const displaySettingsPage = '/display_settings_page'; static const otherSettingsPage = '/other_settings_page'; diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index 8e71b6020..7a8671224 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -90,6 +90,10 @@ class PrivacyPage extends BasePage { title: S.current.domain_looks_up, handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage), ), + SettingsCellWithArrow( + title: 'Trocador providers', + handler: (context) => Navigator.of(context).pushNamed(Routes.trocadorProvidersPage), + ), ], ); }), diff --git a/lib/src/screens/settings/trocador_providers_page.dart b/lib/src/screens/settings/trocador_providers_page.dart new file mode 100644 index 000000000..b972c22d5 --- /dev/null +++ b/lib/src/screens/settings/trocador_providers_page.dart @@ -0,0 +1,37 @@ +import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; +import 'package:cake_wallet/view_model/settings/trocador_providers_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class TrocadorProvidersPage extends BasePage { + TrocadorProvidersPage(this.trocadorProvidersViewModel); + + @override + String get title => 'Trocador Providers'; + + final TrocadorProvidersViewModel trocadorProvidersViewModel; + + @override + Widget body(BuildContext context) { + final availableProviders = TrocadorExchangeProvider.availableProviders; + final providerStates = trocadorProvidersViewModel.providerStates; + return Container( + padding: EdgeInsets.only(top: 10), + child: ListView.builder( + itemCount: availableProviders.length, + itemBuilder: (_, index) { + String provider = availableProviders[index]; + return Observer( + builder: (_) => SettingsSwitcherCell( + title: provider, + value: providerStates[provider] ?? false, + onValueChange: (BuildContext _, bool value) { + trocadorProvidersViewModel.toggleProviderState(provider); + })); + }, + ), + ); + } +} diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index cb9df3d1d..3c9ba36d5 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -10,6 +10,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/sort_balance_types.dart'; +import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; import 'package:cake_wallet/view_model/settings/sync_mode.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; @@ -161,6 +162,8 @@ abstract class SettingsStoreBase with Store { priority[WalletType.bitcoinCash] = initialBitcoinCashTransactionPriority; } + initializeTrocadorProviderStates(); + reaction( (_) => fiatCurrency, (FiatCurrency fiatCurrency) => sharedPreferences.setString( @@ -515,6 +518,9 @@ abstract class SettingsStoreBase with Store { @observable ObservableMap priority; + @observable + ObservableMap trocadorProviderStates = ObservableMap(); + @observable SortBalanceBy sortBalanceBy; @@ -1059,6 +1065,19 @@ abstract class SettingsStoreBase with Store { powNodes[walletType] = node; } + void initializeTrocadorProviderStates() { + for (var provider in TrocadorExchangeProvider.availableProviders) { + final savedState = _sharedPreferences.getBool(provider) ?? true; + trocadorProviderStates[provider] = savedState; + } + } + + void saveTrocadorProviderState(String providerName, bool state) { + _sharedPreferences.setBool(providerName, state); + trocadorProviderStates[providerName] = state; + } + + static Future _getDeviceName() async { String? deviceName = ''; final deviceInfoPlugin = DeviceInfoPlugin(); diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 1a6b118f8..80c331ab2 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -146,7 +146,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with ChangeNowExchangeProvider(settingsStore: _settingsStore), SideShiftExchangeProvider(), SimpleSwapExchangeProvider(), - TrocadorExchangeProvider(useTorOnly: _useTorOnly), + TrocadorExchangeProvider(useTorOnly: _useTorOnly, + providerStates: _settingsStore.trocadorProviderStates), if (FeatureFlag.isExolixEnabled) ExolixExchangeProvider(), ]; diff --git a/lib/view_model/settings/trocador_providers_view_model.dart b/lib/view_model/settings/trocador_providers_view_model.dart new file mode 100644 index 000000000..19204d1f9 --- /dev/null +++ b/lib/view_model/settings/trocador_providers_view_model.dart @@ -0,0 +1,21 @@ +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:mobx/mobx.dart'; + +part 'trocador_providers_view_model.g.dart'; + +class TrocadorProvidersViewModel = TrocadorProvidersViewModelBase with _$TrocadorProvidersViewModel; + +abstract class TrocadorProvidersViewModelBase with Store { + TrocadorProvidersViewModelBase(this._settingsStore); + + final SettingsStore _settingsStore; + + @computed + Map get providerStates => _settingsStore.trocadorProviderStates; + + @action + void toggleProviderState(String providerName) { + final currentState = providerStates[providerName] ?? false; + _settingsStore.saveTrocadorProviderState(providerName, !currentState); + } +} \ No newline at end of file From 8237b89d56a7c3a8f035abb4976589e6c5deb470 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 17 Nov 2023 15:45:42 +0200 Subject: [PATCH 038/241] CW-520-Enable-user-to-choose-12-or-24-seed-words-for-BCH-and-ETH (#1181) * seed phrase option UI * bch seed length option * eth seed lengh option * update preseed info * update localization files --- .../lib/src/bitcoin_cash_wallet_service.dart | 7 ++++- cw_core/lib/wallet_credentials.dart | 2 ++ cw_ethereum/lib/ethereum_wallet_service.dart | 9 ++++++- lib/core/wallet_creation_service.dart | 6 +++++ lib/di.dart | 13 ++++++---- lib/entities/preferences_key.dart | 1 + lib/entities/seed_phrase_length.dart | 26 +++++++++++++++++++ lib/router.dart | 5 +++- .../advanced_privacy_settings_page.dart | 13 ++++++++++ lib/src/screens/seed/pre_seed_page.dart | 15 +++++++---- lib/store/settings_store.dart | 16 ++++++++++++ .../advanced_privacy_settings_view_model.dart | 10 +++++++ res/values/strings_ar.arb | 3 ++- res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 1 + res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 1 + res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 1 + res/values/strings_my.arb | 1 + res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_th.arb | 1 + res/values/strings_tl.arb | 1 + res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + 38 files changed, 137 insertions(+), 14 deletions(-) create mode 100644 lib/entities/seed_phrase_length.dart diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart index fa572b38b..8cc469a3a 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart @@ -32,8 +32,13 @@ class BitcoinCashWalletService extends WalletService create( credentials) async { + final strength = (credentials.seedPhraseLength == 12) + ? 128 + : (credentials.seedPhraseLength == 24) + ? 256 + : 128; final wallet = await BitcoinCashWalletBase.create( - mnemonic: await Mnemonic.generate(), + mnemonic: await Mnemonic.generate(strength: strength), password: credentials.password!, walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource); diff --git a/cw_core/lib/wallet_credentials.dart b/cw_core/lib/wallet_credentials.dart index 0cdf892bd..4d5f331c9 100644 --- a/cw_core/lib/wallet_credentials.dart +++ b/cw_core/lib/wallet_credentials.dart @@ -4,6 +4,7 @@ abstract class WalletCredentials { WalletCredentials({ required this.name, this.height, + this.seedPhraseLength, this.walletInfo, this.password, this.derivationType, @@ -12,6 +13,7 @@ abstract class WalletCredentials { final String name; final int? height; + int? seedPhraseLength; String? password; DerivationType? derivationType; String? derivationPath; diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index 16dbc0b04..8810d6014 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -20,7 +20,14 @@ class EthereumWalletService extends WalletService create(EthereumNewWalletCredentials credentials) async { - final mnemonic = bip39.generateMnemonic(); + + final strength = (credentials.seedPhraseLength == 12) + ? 128 + : (credentials.seedPhraseLength == 24) + ? 256 + : 128; + + final mnemonic = bip39.generateMnemonic(strength: strength); final wallet = EthereumWallet( walletInfo: credentials.walletInfo!, mnemonic: mnemonic, diff --git a/lib/core/wallet_creation_service.dart b/lib/core/wallet_creation_service.dart index dda591115..8548f079f 100644 --- a/lib/core/wallet_creation_service.dart +++ b/lib/core/wallet_creation_service.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:flutter/foundation.dart'; @@ -18,6 +19,7 @@ class WalletCreationService { required this.secureStorage, required this.keyService, required this.sharedPreferences, + required this.settingsStore, required this.walletInfoSource}) : type = initialType { changeWalletType(type: type); @@ -26,6 +28,7 @@ class WalletCreationService { WalletType type; final FlutterSecureStorage secureStorage; final SharedPreferences sharedPreferences; + final SettingsStore settingsStore; final KeyService keyService; final Box walletInfoSource; WalletService? _service; @@ -56,6 +59,9 @@ class WalletCreationService { checkIfExists(credentials.name); final password = generateWalletPassword(); credentials.password = password; + if (type == WalletType.bitcoinCash || type == WalletType.ethereum) { + credentials.seedPhraseLength = settingsStore.seedPhraseLength.value; + } await keyService.saveWalletPassword(password: password, walletName: credentials.name); final wallet = await _service!.create(credentials); diff --git a/lib/di.dart b/lib/di.dart index 8cc393510..a59483a4f 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -333,6 +333,7 @@ Future setup({ keyService: getIt.get(), secureStorage: getIt.get(), sharedPreferences: getIt.get(), + settingsStore: getIt.get(), walletInfoSource: _walletInfoSource)); getIt.registerFactory(() => WalletLoadingService( @@ -340,9 +341,10 @@ Future setup({ getIt.get(), (WalletType type) => getIt.get(param1: type))); - getIt.registerFactoryParam((type, _) => WalletNewVM( - getIt.get(), getIt.get(param1: type), _walletInfoSource, - type: type)); + getIt.registerFactoryParam((type, _) => + WalletNewVM(getIt.get(), + getIt.get(param1: type), _walletInfoSource, + type: type)); getIt.registerFactoryParam((WalletType type, _) { return WalletRestorationFromQRVM(getIt.get(), @@ -894,8 +896,9 @@ Future setup({ getIt.registerFactoryParam( (param1, isCreate) => NewWalletTypePage(onTypeSelected: param1, isCreate: isCreate ?? true)); - getIt.registerFactoryParam( - (WalletType type, _) => PreSeedPage(type)); + getIt.registerFactoryParam( + (WalletType type, AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel) + => PreSeedPage(type, advancedPrivacySettingsViewModel)); getIt.registerFactoryParam((trade, _) => TradeDetailsViewModel( diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 5ecd1bcc7..b8730d802 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -87,4 +87,5 @@ class PreferencesKey { 'should_require_totp_2fa_for_all_security_and_backup_settings'; static const selectedCake2FAPreset = 'selected_cake_2fa_preset'; static const totpSecretKey = 'totp_secret_key'; + static const currentSeedPhraseLength = 'current_seed_phrase_length'; } diff --git a/lib/entities/seed_phrase_length.dart b/lib/entities/seed_phrase_length.dart new file mode 100644 index 000000000..65e9fac40 --- /dev/null +++ b/lib/entities/seed_phrase_length.dart @@ -0,0 +1,26 @@ +import 'package:cake_wallet/generated/i18n.dart'; + +enum SeedPhraseLength { + twelveWords(12), + twentyFourWords(24); + + const SeedPhraseLength(this.value); + final int value; + + static SeedPhraseLength deserialize({required int raw}) => + SeedPhraseLength.values.firstWhere((e) => e.value == raw); + + @override + String toString() { + String label = ''; + switch (this) { + case SeedPhraseLength.twelveWords: + label = '12 Words'; + break; + case SeedPhraseLength.twentyFourWords: + label = '24 Words'; + break; + } + return label; + } +} \ No newline at end of file diff --git a/lib/router.dart b/lib/router.dart index dc2d8f8ab..8174e0be8 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -418,7 +418,10 @@ Route createRoute(RouteSettings settings) { case Routes.preSeed: return MaterialPageRoute( - builder: (_) => getIt.get(param1: settings.arguments as WalletType)); + builder: (_) => getIt.get( + param1: settings.arguments as WalletType, + param2: getIt.get( + param1: settings.arguments as WalletType))); case Routes.backup: return CupertinoPageRoute( diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index 386f3012b..66a28042d 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -1,7 +1,9 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; +import 'package:cake_wallet/entities/seed_phrase_length.dart'; import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; @@ -94,6 +96,17 @@ class _AdvancedPrivacySettingsBodyState extends State( + title: S.current.seed_phrase_length, + items: SeedPhraseLength.values, + selectedItem: widget.privacySettingsViewModel.seedPhraseLength, + onItemSelected: (SeedPhraseLength length) { + widget.privacySettingsViewModel.setSeedPhraseLength(length); + }, + ); + }), ], ), bottomSectionPadding: EdgeInsets.all(24), diff --git a/lib/src/screens/seed/pre_seed_page.dart b/lib/src/screens/seed/pre_seed_page.dart index bb6902a7e..947099983 100644 --- a/lib/src/screens/seed/pre_seed_page.dart +++ b/lib/src/screens/seed/pre_seed_page.dart @@ -1,5 +1,6 @@ import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; @@ -9,15 +10,19 @@ import 'package:cake_wallet/themes/theme_base.dart'; import 'package:flutter/material.dart'; class PreSeedPage extends BasePage { - PreSeedPage(this.type) + PreSeedPage(this.type, this.advancedPrivacySettingsViewModel) : imageLight = Image.asset('assets/images/pre_seed_light.png'), imageDark = Image.asset('assets/images/pre_seed_dark.png'), - wordsCount = _wordsCount(type); + seedPhraseLength = advancedPrivacySettingsViewModel.seedPhraseLength.value { + wordsCount = _wordsCount(type, seedPhraseLength); + } final Image imageDark; final Image imageLight; final WalletType type; - final int wordsCount; + final AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel; + final int seedPhraseLength; + late final int wordsCount; @override Widget? leading(BuildContext context) => null; @@ -68,13 +73,13 @@ class PreSeedPage extends BasePage { )); } - static int _wordsCount(WalletType type) { + static int _wordsCount(WalletType type, int seedPhraseLength) { switch (type) { case WalletType.monero: return 25; case WalletType.ethereum: case WalletType.bitcoinCash: - return 12; + return seedPhraseLength; default: return 24; } diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 3c9ba36d5..61e9ba029 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -9,6 +9,7 @@ import 'package:cake_wallet/entities/background_tasks.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; +import 'package:cake_wallet/entities/seed_phrase_length.dart'; import 'package:cake_wallet/entities/sort_balance_types.dart'; import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; import 'package:cake_wallet/view_model/settings/sync_mode.dart'; @@ -71,6 +72,7 @@ abstract class SettingsStoreBase with Store { required this.isBitcoinBuyEnabled, required this.actionlistDisplayMode, required this.pinTimeOutDuration, + required this.seedPhraseLength, required Cake2FAPresetsOptions initialCake2FAPresetOptions, required bool initialShouldRequireTOTP2FAForAccessingWallet, required bool initialShouldRequireTOTP2FAForSendsToContact, @@ -329,6 +331,11 @@ abstract class SettingsStoreBase with Store { (String languageCode) => sharedPreferences.setString(PreferencesKey.currentLanguageCode, languageCode)); + reaction( + (_) => seedPhraseLength, + (SeedPhraseLength seedPhraseWordCount) => + sharedPreferences.setInt(PreferencesKey.currentSeedPhraseLength, seedPhraseWordCount.value)); + reaction( (_) => pinTimeOutDuration, (PinCodeRequiredDuration pinCodeInterval) => @@ -418,6 +425,7 @@ abstract class SettingsStoreBase with Store { static const defaultActionsMode = 11; static const defaultPinCodeTimeOutDuration = PinCodeRequiredDuration.tenminutes; static const defaultAutoGenerateSubaddressStatus = AutoGenerateSubaddressStatus.initialized; + static const defaultSeedPhraseLength = SeedPhraseLength.twelveWords; @observable FiatCurrency fiatCurrency; @@ -509,6 +517,9 @@ abstract class SettingsStoreBase with Store { @observable PinCodeRequiredDuration pinTimeOutDuration; + @observable + SeedPhraseLength seedPhraseLength; + @computed ThemeData get theme => currentTheme.themeData; @@ -699,9 +710,13 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getInt(PreferencesKey.displayActionListModeKey) ?? defaultActionsMode)); var pinLength = sharedPreferences.getInt(PreferencesKey.currentPinLength); final timeOutDuration = sharedPreferences.getInt(PreferencesKey.pinTimeOutDuration); + final seedPhraseCount = sharedPreferences.getInt(PreferencesKey.currentSeedPhraseLength); final pinCodeTimeOutDuration = timeOutDuration != null ? PinCodeRequiredDuration.deserialize(raw: timeOutDuration) : defaultPinCodeTimeOutDuration; + final seedPhraseWordCount = seedPhraseCount != null + ? SeedPhraseLength.deserialize(raw: seedPhraseCount) + : defaultSeedPhraseLength; final sortBalanceBy = SortBalanceBy.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? 0]; final pinNativeTokenAtTop = @@ -816,6 +831,7 @@ abstract class SettingsStoreBase with Store { actionlistDisplayMode: actionListDisplayMode, initialPinLength: pinLength, pinTimeOutDuration: pinCodeTimeOutDuration, + seedPhraseLength: seedPhraseWordCount, initialLanguageCode: savedLanguageCode, sortBalanceBy: sortBalanceBy, pinNativeTokenAtTop: pinNativeTokenAtTop, diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart index 380937212..b67a4378a 100644 --- a/lib/view_model/advanced_privacy_settings_view_model.dart +++ b/lib/view_model/advanced_privacy_settings_view_model.dart @@ -1,5 +1,6 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; +import 'package:cake_wallet/entities/seed_phrase_length.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; @@ -25,9 +26,15 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { final SettingsStore _settingsStore; + bool get hasSeedPhraseLengthOption => + type == WalletType.bitcoinCash || type == WalletType.ethereum; + @computed bool get addCustomNode => _addCustomNode; + @computed + SeedPhraseLength get seedPhraseLength => _settingsStore.seedPhraseLength; + @action void setFiatApiMode(FiatApiMode fiatApiMode) => _settingsStore.fiatApiMode = fiatApiMode; @@ -36,4 +43,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { @action void toggleAddCustomNode() => _addCustomNode = !_addCustomNode; + + @action + void setSeedPhraseLength(SeedPhraseLength length) => _settingsStore.seedPhraseLength = length; } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 4727a0262..21ebc7def 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -726,7 +726,8 @@ "require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ", "camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ", "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", + "seed_phrase_length": " ﺭﻭﺬﺒﻟﺍ ﺓﺭﺎﺒﻌﻟﺍ ﻝﻮﻃ", "unavailable_balance": " ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ", "unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ", "unspent_change": "يتغير" -} \ No newline at end of file +} diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index d52529e38..b091e072f 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -722,6 +722,7 @@ "require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли", "camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.", "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново", + "seed_phrase_length": "Дължина на началната фраза", "unavailable_balance": "Неналично салдо", "unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.", "unspent_change": "Промяна" diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 8b86c517f..2c73fdc3e 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -722,6 +722,7 @@ "require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek", "camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.", "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu", + "seed_phrase_length": "Délka fráze semene", "unavailable_balance": "Nedostupný zůstatek", "unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.", "unspent_change": "Změna" diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 0928e1462..567f9d9c0 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets", "camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.", "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut", + "seed_phrase_length": "Länge der Seed-Phrase", "unavailable_balance": "Nicht verfügbares Guthaben", "unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.", "unspent_change": "Wechselgeld" diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 55b6f8339..1d50540a7 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -731,6 +731,7 @@ "require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets", "camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.", "switchToETHWallet": "Please switch to an Ethereum wallet and try again", + "seed_phrase_length": "Seed phrase length", "unavailable_balance": "Unavailable balance", "unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.", "unspent_change": "Change" diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 048bf05ea..d021902d3 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas", "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.", "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente.", + "seed_phrase_length": "Longitud de la frase inicial", "unavailable_balance": "Saldo no disponible", "unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.", "unspent_change": "Cambiar" diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index d82f8a677..9e6a6c07e 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -728,6 +728,7 @@ "exchange_provider_unsupported": "${providerName} n'est plus pris en charge !", "domain_looks_up": "Résolution de nom", "require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes", + "seed_phrase_length": "Longueur de la phrase de départ", "unavailable_balance": "Solde indisponible", "unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.", "camera_permission_is_required": "L'autorisation d'accès à la caméra est requise.\nVeuillez l'activer depuis les paramètres de l'application.", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 6c0644316..b865c4790 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -708,6 +708,7 @@ "require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje", "camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.", "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa", + "seed_phrase_length": "Tsawon jimlar iri", "unavailable_balance": "Ma'aunin da ba ya samuwa", "unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.", "unspent_change": "Canza" diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index ae0b1a94d..5f53141e5 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है", "camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।", "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें", + "seed_phrase_length": "बीज वाक्यांश की लंबाई", "unavailable_balance": "अनुपलब्ध शेष", "unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।", "unspent_change": "परिवर्तन" diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index d9dcba723..58bd0f497 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -728,6 +728,7 @@ "require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike", "camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.", "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno", + "seed_phrase_length": "Duljina početne fraze", "unavailable_balance": "Nedostupno stanje", "unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.", "unspent_change": "Promijeniti" diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index e6498d169..c03523f5d 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -718,6 +718,7 @@ "require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal", "camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.", "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi", + "seed_phrase_length": "Panjang frase benih", "unavailable_balance": "Saldo tidak tersedia", "unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.", "unspent_change": "Mengubah" diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index b78644766..1c9387180 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni", "camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.", "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova", + "seed_phrase_length": "Lunghezza della frase seed", "unavailable_balance": "Saldo non disponibile", "unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.", "unspent_change": "Modifica" diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 1c7ad6497..42aeb34f8 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要", "camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。", "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください", + "seed_phrase_length": "シードフレーズの長さ", "unavailable_balance": "利用できない残高", "unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。", "unspent_change": "変化" diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index cbf1744e1..8e09c7034 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -728,6 +728,7 @@ "require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요", "camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.", "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요.", + "seed_phrase_length": "시드 문구 길이", "unavailable_balance": "사용할 수 없는 잔액", "unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.", "unspent_change": "변화" diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index bb2f8a86d..71255d98e 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -728,6 +728,7 @@ "require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", "camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။", "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။", + "seed_phrase_length": "မျိုးစေ့စာပိုဒ်တိုအရှည်", "unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။", "unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။", "unspent_change": "ပေြာင်းလဲခြင်း" diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index e833dde50..4de0fac30 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "Vereist voor uitwisselingen naar externe portemonnees", "camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.", "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw", + "seed_phrase_length": "Lengte van de zaadzin", "unavailable_balance": "Onbeschikbaar saldo", "unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.", "unspent_change": "Wijziging" diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 8429cec8a..160bf2f88 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "Wymagaj wymiany na portfele zewnętrzne", "camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.", "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie", + "seed_phrase_length": "Długość frazy początkowej", "unavailable_balance": "Niedostępne saldo", "unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.", "unspent_change": "Zmiana" diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 9bb27a582..ab221dd49 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -729,6 +729,7 @@ "require_for_exchanges_to_external_wallets": "Exigir trocas para carteiras externas", "camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.", "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente", + "seed_phrase_length": "Comprimento da frase-semente", "unavailable_balance": "Saldo indisponível", "unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.", "unspent_change": "Mudar" diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index d0f64c8b2..4474c26e3 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки", "camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.", "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку.", + "seed_phrase_length": "Длина исходной фразы", "unavailable_balance": "Недоступный баланс", "unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.", "unspent_change": "Изменять" diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 3159bd649..90f71cf75 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -728,6 +728,7 @@ "require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก", "camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป", "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง", + "seed_phrase_length": "ความยาววลีของเมล็ด", "unavailable_balance": "ยอดคงเหลือไม่พร้อมใช้งาน", "unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง", "unspent_change": "เปลี่ยน" diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index b38dc35ad..ffd89c30e 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -725,6 +725,7 @@ "require_for_exchanges_to_external_wallets": "Kinakailangan para sa mga palitan sa mga panlabas na wallet", "camera_permission_is_required": "Kinakailangan ang pahintulot sa camera.\nMangyaring paganahin ito mula sa mga setting ng app.", "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli", + "seed_phrase_length": "Haba ng parirala ng binhi", "unavailable_balance": "Hindi available na balanse", "unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.", "unspent_change": "Baguhin" diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 77d29f8d2..0e2690ad6 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -728,6 +728,7 @@ "require_for_exchanges_to_external_wallets": "Harici cüzdanlara geçiş yapılmasını zorunlu kılın", "camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.", "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin", + "seed_phrase_length": "Çekirdek cümle uzunluğu", "unavailable_balance": "Kullanılamayan bakiye", "unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.", "unspent_change": "Değiştirmek" diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index aa9e29687..044bde32a 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -730,6 +730,7 @@ "require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці", "camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.", "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу", + "seed_phrase_length": "Довжина початкової фрази", "unavailable_balance": "Недоступний баланс", "unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.", "unspent_change": "Зміна" diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index e8cf03835..a8b3813a3 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -722,6 +722,7 @@ "require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ", "camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ", "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ", + "seed_phrase_length": " ﯽﺋﺎﺒﻤﻟ ﯽﮐ ﮯﻠﻤﺟ ﮯﮐ ﺞﯿﺑ", "unavailable_balance": " ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ", "unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ", "unspent_change": "تبدیل کریں" diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 7784e785a..6b46201b8 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -724,6 +724,7 @@ "require_for_exchanges_to_external_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ ita", "camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.", "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi", + "seed_phrase_length": "Gigun gbolohun irugbin", "unavailable_balance": "Iwontunwonsi ti ko si", "unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.", "unspent_change": "Yipada" diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 454c79194..c54ba2696 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -729,6 +729,7 @@ "require_for_exchanges_to_external_wallets": "需要兑换到外部钱包", "camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。", "switchToETHWallet": "请切换到以太坊钱包并重试", + "seed_phrase_length": "种子短语长度", "unavailable_balance": "不可用余额", "unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。", "unspent_change": "改变" From f4e71c72ef9c509dffa95bb46cb3ba3d5f0aa52e Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Fri, 17 Nov 2023 13:35:46 -0500 Subject: [PATCH 039/241] Nano rep fixes (#1145) * add preference keys for default nano/banano rep * updates to change rep page, add success message * forgot to save this file * nano_client cleanup * first pass * refactor to use sharedprefs in nano_client * review fixes --- cw_nano/lib/nano_client.dart | 204 +++++++++--------- cw_nano/lib/nano_wallet.dart | 2 +- cw_nano/pubspec.lock | 63 +++++- cw_nano/pubspec.yaml | 1 + lib/core/backup_service.dart | 15 +- lib/di.dart | 11 +- lib/entities/preferences_key.dart | 2 + lib/nano/cw_nano.dart | 5 +- lib/reactions/on_current_wallet_change.dart | 1 + .../screens/nano/nano_change_rep_page.dart | 52 ++++- lib/store/settings_store.dart | 80 ++++--- res/values/strings_ar.arb | 1 + res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 5 +- res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 5 +- res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 1 + res/values/strings_my.arb | 1 + res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_th.arb | 1 + res/values/strings_tl.arb | 1 + res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + 37 files changed, 321 insertions(+), 149 deletions(-) diff --git a/cw_nano/lib/nano_client.dart b/cw_nano/lib/nano_client.dart index 2866c4653..f1d08204a 100644 --- a/cw_nano/lib/nano_client.dart +++ b/cw_nano/lib/nano_client.dart @@ -8,18 +8,28 @@ import 'package:cw_nano/nano_util.dart'; import 'package:http/http.dart' as http; import 'package:nanodart/nanodart.dart'; import 'package:cw_core/node.dart'; +import 'package:shared_preferences/shared_preferences.dart'; class NanoClient { - static const String DEFAULT_REPRESENTATIVE = - "nano_38713x95zyjsqzx6nm1dsom1jmm668owkeb9913ax6nfgj15az3nu8xkx579"; - static const Map CAKE_HEADERS = { "Content-Type": "application/json", "nano-app": "cake-wallet" }; + NanoClient() { + SharedPreferences.getInstance().then((value) => prefs = value); + } + + late SharedPreferences prefs; Node? _node; Node? _powNode; + static const String _defaultDefaultRepresentative = + "nano_38713x95zyjsqzx6nm1dsom1jmm668owkeb9913ax6nfgj15az3nu8xkx579"; + + String getRepFromPrefs() { + // from preferences_key.dart "defaultNanoRep" key: + return prefs.getString("default_nano_representative") ?? _defaultDefaultRepresentative; + } bool connect(Node node) { try { @@ -84,44 +94,45 @@ class NanoClient { required String repAddress, required String ourAddress, }) async { + AccountInfoResponse? accountInfo = await getAccountInfo(ourAddress); + + if (accountInfo == null) { + throw Exception( + "error while getting account info, you can't change the rep of an unopened account"); + } + + // construct the change block: + Map changeBlock = { + "type": "state", + "account": ourAddress, + "previous": accountInfo.frontier, + "representative": repAddress, + "balance": accountInfo.balance, + "link": "0000000000000000000000000000000000000000000000000000000000000000", + "link_as_account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp", + }; + + // sign the change block: + final String hash = NanoBlocks.computeStateHash( + NanoAccountType.NANO, + changeBlock["account"]!, + changeBlock["previous"]!, + changeBlock["representative"]!, + BigInt.parse(changeBlock["balance"]!), + changeBlock["link"]!, + ); + final String signature = NanoSignatures.signBlock(hash, privateKey); + + // get PoW for the send block: + final String work = await requestWork(accountInfo.frontier); + + changeBlock["signature"] = signature; + changeBlock["work"] = work; + try { - AccountInfoResponse? accountInfo = await getAccountInfo(ourAddress); - - if (accountInfo == null) { - throw Exception("error while getting account info"); - } - - // construct the change block: - Map changeBlock = { - "type": "state", - "account": ourAddress, - "previous": accountInfo.frontier, - "representative": repAddress, - "balance": accountInfo.balance, - "link": "0000000000000000000000000000000000000000000000000000000000000000", - "link_as_account": "nano_1111111111111111111111111111111111111111111111111111hifc8npp", - }; - - // sign the change block: - final String hash = NanoBlocks.computeStateHash( - NanoAccountType.NANO, - changeBlock["account"]!, - changeBlock["previous"]!, - changeBlock["representative"]!, - BigInt.parse(changeBlock["balance"]!), - changeBlock["link"]!, - ); - final String signature = NanoSignatures.signBlock(hash, privateKey); - - // get PoW for the send block: - final String work = await requestWork(accountInfo.frontier); - - changeBlock["signature"] = signature; - changeBlock["work"] = work; - return await processBlock(changeBlock, "change"); } catch (e) { - throw Exception("error while changing representative"); + throw Exception("error while changing representative: $e"); } } @@ -191,68 +202,63 @@ class NanoClient { BigInt? balanceAfterTx, String? previousHash, }) async { - try { - // our address: - final String publicAddress = NanoUtil.privateKeyToAddress(privateKey); + // our address: + final String publicAddress = NanoUtil.privateKeyToAddress(privateKey); - // first get the current account balance: - if (balanceAfterTx == null) { - final BigInt currentBalance = (await getBalance(publicAddress)).currentBalance; - final BigInt txAmount = BigInt.parse(amountRaw); - balanceAfterTx = currentBalance - txAmount; - } - - // get the account info (we need the frontier and representative): - AccountInfoResponse? infoResponse = await getAccountInfo(publicAddress); - if (infoResponse == null) { - throw Exception( - "error while getting account info! (we probably don't have an open account yet)"); - } - - String frontier = infoResponse.frontier; - // override if provided: - if (previousHash != null) { - frontier = previousHash; - } - final String representative = infoResponse.representative; - // link = destination address: - final String link = NanoAccounts.extractPublicKey(destinationAddress); - final String linkAsAccount = destinationAddress; - - // construct the send block: - Map sendBlock = { - "type": "state", - "account": publicAddress, - "previous": frontier, - "representative": representative, - "balance": balanceAfterTx.toString(), - "link": link, - }; - - // sign the send block: - final String hash = NanoBlocks.computeStateHash( - NanoAccountType.NANO, - sendBlock["account"]!, - sendBlock["previous"]!, - sendBlock["representative"]!, - BigInt.parse(sendBlock["balance"]!), - sendBlock["link"]!, - ); - final String signature = NanoSignatures.signBlock(hash, privateKey); - - // get PoW for the send block: - final String work = await requestWork(frontier); - - sendBlock["link_as_account"] = linkAsAccount; - sendBlock["signature"] = signature; - sendBlock["work"] = work; - - // ready to post send block: - return sendBlock; - } catch (e) { - print(e); - rethrow; + // first get the current account balance: + if (balanceAfterTx == null) { + final BigInt currentBalance = (await getBalance(publicAddress)).currentBalance; + final BigInt txAmount = BigInt.parse(amountRaw); + balanceAfterTx = currentBalance - txAmount; } + + // get the account info (we need the frontier and representative): + AccountInfoResponse? infoResponse = await getAccountInfo(publicAddress); + if (infoResponse == null) { + throw Exception( + "error while getting account info! (we probably don't have an open account yet)"); + } + + String frontier = infoResponse.frontier; + // override if provided: + if (previousHash != null) { + frontier = previousHash; + } + final String representative = infoResponse.representative; + // link = destination address: + final String link = NanoAccounts.extractPublicKey(destinationAddress); + final String linkAsAccount = destinationAddress; + + // construct the send block: + Map sendBlock = { + "type": "state", + "account": publicAddress, + "previous": frontier, + "representative": representative, + "balance": balanceAfterTx.toString(), + "link": link, + }; + + // sign the send block: + final String hash = NanoBlocks.computeStateHash( + NanoAccountType.NANO, + sendBlock["account"]!, + sendBlock["previous"]!, + sendBlock["representative"]!, + BigInt.parse(sendBlock["balance"]!), + sendBlock["link"]!, + ); + final String signature = NanoSignatures.signBlock(hash, privateKey); + + // get PoW for the send block: + final String work = await requestWork(frontier); + + sendBlock["link_as_account"] = linkAsAccount; + sendBlock["signature"] = signature; + sendBlock["work"] = work; + + // ready to post send block: + return sendBlock; } Future receiveBlock({ @@ -274,7 +280,7 @@ class NanoClient { // account is not open yet, we need to create an open block: openBlock = true; // we don't have a representative set yet: - representative = DEFAULT_REPRESENTATIVE; + representative = await getRepFromPrefs(); // we don't have a frontier yet: frontier = "0000000000000000000000000000000000000000000000000000000000000000"; } else { diff --git a/cw_nano/lib/nano_wallet.dart b/cw_nano/lib/nano_wallet.dart index bf7cc6bca..44d564fc6 100644 --- a/cw_nano/lib/nano_wallet.dart +++ b/cw_nano/lib/nano_wallet.dart @@ -382,7 +382,7 @@ abstract class NanoWalletBase _representativeAddress = accountInfo.representative; } catch (e) { // account not found: - _representativeAddress = NanoClient.DEFAULT_REPRESENTATIVE; + _representativeAddress = await _client.getRepFromPrefs(); throw Exception("Failed to get representative address $e"); } } diff --git a/cw_nano/pubspec.lock b/cw_nano/pubspec.lock index ea932baee..d28558422 100644 --- a/cw_nano/pubspec.lock +++ b/cw_nano/pubspec.lock @@ -290,6 +290,11 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" frontend_server_client: dependency: transitive description: @@ -594,6 +599,62 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.2" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7" + url: "https://pub.dev" + source: hosted + version: "2.3.4" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a + url: "https://pub.dev" + source: hosted + version: "2.3.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf + url: "https://pub.dev" + source: hosted + version: "2.2.1" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" + url: "https://pub.dev" + source: hosted + version: "2.3.2" shelf: dependency: transitive description: @@ -753,4 +814,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.3.0" + flutter: ">=3.7.0" diff --git a/cw_nano/pubspec.yaml b/cw_nano/pubspec.yaml index 054dd5df4..f06177d3c 100644 --- a/cw_nano/pubspec.yaml +++ b/cw_nano/pubspec.yaml @@ -21,6 +21,7 @@ dependencies: ed25519_hd_key: ^2.2.0 hex: ^0.2.0 http: ^1.1.0 + shared_preferences: ^2.0.15 cw_core: path: ../cw_core diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 85fd8f588..2913505c0 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -247,6 +247,8 @@ class BackupService { final sortBalanceTokensBy = data[PreferencesKey.sortBalanceBy] as int?; final pinNativeTokenAtTop = data[PreferencesKey.pinNativeTokenAtTop] as bool?; final useEtherscan = data[PreferencesKey.useEtherscan] as bool?; + final defaultNanoRep = data[PreferencesKey.defaultNanoRep] as String?; + final defaultBananoRep = data[PreferencesKey.defaultBananoRep] as String?; final lookupsTwitter = data[PreferencesKey.lookupsTwitter] as bool?; final lookupsMastodon = data[PreferencesKey.lookupsMastodon] as bool?; final lookupsYatService = data[PreferencesKey.lookupsYatService] as bool?; @@ -322,11 +324,10 @@ class BackupService { if (currentTheme != null && DeviceInfo.instance.isMobile) { await _sharedPreferences.setInt(PreferencesKey.currentTheme, currentTheme); - // enforce dark theme on desktop platforms until the design is ready: + // enforce dark theme on desktop platforms until the design is ready: } else if (DeviceInfo.instance.isDesktop) { await _sharedPreferences.setInt(PreferencesKey.currentTheme, ThemeList.darkTheme.raw); } - if (exchangeStatus != null) await _sharedPreferences.setInt(PreferencesKey.exchangeStatusKey, exchangeStatus); @@ -389,6 +390,13 @@ class BackupService { if (useEtherscan != null) await _sharedPreferences.setBool(PreferencesKey.useEtherscan, useEtherscan); + if (defaultNanoRep != null) + await _sharedPreferences.setString(PreferencesKey.defaultNanoRep, defaultNanoRep); + + if (defaultBananoRep != null) + await _sharedPreferences.setString(PreferencesKey.defaultBananoRep, defaultBananoRep); + + if (syncAll != null) await _sharedPreferences.setBool(PreferencesKey.syncAllKey, syncAll); if (lookupsTwitter != null) await _sharedPreferences.setBool(PreferencesKey.lookupsTwitter, lookupsTwitter); @@ -560,6 +568,9 @@ class BackupService { PreferencesKey.pinNativeTokenAtTop: _sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop), PreferencesKey.useEtherscan: _sharedPreferences.getBool(PreferencesKey.useEtherscan), + PreferencesKey.defaultNanoRep: _sharedPreferences.getString(PreferencesKey.defaultNanoRep), + PreferencesKey.defaultBananoRep: + _sharedPreferences.getString(PreferencesKey.defaultBananoRep), PreferencesKey.lookupsTwitter: _sharedPreferences.getBool(PreferencesKey.lookupsTwitter), PreferencesKey.lookupsMastodon: _sharedPreferences.getBool(PreferencesKey.lookupsMastodon), PreferencesKey.lookupsYatService: diff --git a/lib/di.dart b/lib/di.dart index a59483a4f..94f5dbb63 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -522,8 +522,7 @@ Future setup({ getIt.registerFactory( () => Modify2FAPage(setup2FAViewModel: getIt.get())); - getIt.registerFactory( - () => DesktopSettingsPage()); + getIt.registerFactory(() => DesktopSettingsPage()); getIt.registerFactoryParam( (pageOption, _) => ReceiveOptionViewModel(getIt.get().wallet!, pageOption)); @@ -766,7 +765,10 @@ Future setup({ getIt.registerFactory(() => OtherSettingsPage(getIt.get())); - getIt.registerFactory(() => NanoChangeRepPage(getIt.get().wallet!)); + getIt.registerFactory(() => NanoChangeRepPage( + settingsStore: getIt.get().settingsStore, + wallet: getIt.get().wallet!, + )); getIt.registerFactoryParam( (WalletType? type, bool? isPow) => NodeCreateOrEditViewModel( @@ -839,7 +841,8 @@ Future setup({ case WalletType.ethereum: return ethereum!.createEthereumWalletService(_walletInfoSource); case WalletType.bitcoinCash: - return bitcoinCash!.createBitcoinCashWalletService(_walletInfoSource, _unspentCoinsInfoSource!); + return bitcoinCash! + .createBitcoinCashWalletService(_walletInfoSource, _unspentCoinsInfoSource!); case WalletType.nano: return nano!.createNanoWalletService(_walletInfoSource); default: diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index b8730d802..85df63b69 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -50,6 +50,8 @@ class PreferencesKey { static const sortBalanceBy = 'sort_balance_by'; static const pinNativeTokenAtTop = 'pin_native_token_at_top'; static const useEtherscan = 'use_etherscan'; + static const defaultNanoRep = 'default_nano_representative'; + static const defaultBananoRep = 'default_banano_representative'; static const lookupsTwitter = 'looks_up_twitter'; static const lookupsMastodon = 'looks_up_mastodon'; static const lookupsYatService = 'looks_up_mastodon'; diff --git a/lib/nano/cw_nano.dart b/lib/nano/cw_nano.dart index 778b2584a..0c072c95c 100644 --- a/lib/nano/cw_nano.dart +++ b/lib/nano/cw_nano.dart @@ -166,7 +166,10 @@ class CWNano extends Nano { @override Future changeRep(Object wallet, String address) async { - return (wallet as NanoWallet).changeRep(address); + if ((wallet as NanoWallet).transactionHistory.transactions.isEmpty) { + throw Exception("Can't change representative without an existing transaction history"); + } + return wallet.changeRep(address); } @override diff --git a/lib/reactions/on_current_wallet_change.dart b/lib/reactions/on_current_wallet_change.dart index cf1cf7b81..5f956dc1a 100644 --- a/lib/reactions/on_current_wallet_change.dart +++ b/lib/reactions/on_current_wallet_change.dart @@ -2,6 +2,7 @@ import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/update_haven_rate.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; +import 'package:cake_wallet/nano/nano.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/transaction_info.dart'; diff --git a/lib/src/screens/nano/nano_change_rep_page.dart b/lib/src/screens/nano/nano_change_rep_page.dart index bf541c39a..a625f7e29 100644 --- a/lib/src/screens/nano/nano_change_rep_page.dart +++ b/lib/src/screens/nano/nano_change_rep_page.dart @@ -1,8 +1,11 @@ import 'package:cake_wallet/core/address_validator.dart'; import 'package:cake_wallet/nano/nano.dart'; +import 'package:cake_wallet/src/widgets/address_text_field.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; -import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/themes/extensions/address_theme.dart'; +import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/wallet_base.dart'; @@ -14,21 +17,28 @@ import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; class NanoChangeRepPage extends BasePage { - NanoChangeRepPage(WalletBase wallet) + NanoChangeRepPage({required SettingsStore settingsStore, required WalletBase wallet}) : _wallet = wallet, - _addressController = TextEditingController() { + _settingsStore = settingsStore, + _addressController = TextEditingController(), + _formKey = GlobalKey() { _addressController.text = nano!.getRepresentative(wallet); } final TextEditingController _addressController; final WalletBase _wallet; + final SettingsStore _settingsStore; + + final GlobalKey _formKey; @override String get title => S.current.change_rep; @override Widget body(BuildContext context) { - return Container( + return Form( + key: _formKey, + child: Container( padding: EdgeInsets.only(left: 24, right: 24), child: ScrollableWithBottomSection( contentPadding: EdgeInsets.only(bottom: 24.0), @@ -38,9 +48,17 @@ class NanoChangeRepPage extends BasePage { Row( children: [ Expanded( - child: BaseTextFormField( + child: AddressTextField( controller: _addressController, - hintText: S.of(context).node_address, + onURIScanned: (uri) { + final paymentRequest = PaymentRequest.fromUri(uri); + _addressController.text = paymentRequest.address; + }, + options: [ + AddressTextFieldOption.paste, + AddressTextFieldOption.qrCode, + ], + buttonColor: Theme.of(context).extension()!.actionButtonColor, validator: AddressValidator(type: CryptoCurrency.nano), ), ) @@ -59,6 +77,11 @@ class NanoChangeRepPage extends BasePage { padding: EdgeInsets.only(right: 8.0), child: LoadingPrimaryButton( onPressed: () async { + if (_formKey.currentState != null && + !_formKey.currentState!.validate()) { + return; + } + final confirmed = await showPopUp( context: context, builder: (BuildContext context) { @@ -74,8 +97,19 @@ class NanoChangeRepPage extends BasePage { if (confirmed) { try { + _settingsStore.defaultNanoRep = _addressController.text; + await nano!.changeRep(_wallet, _addressController.text); - Navigator.of(context).pop(); + + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: S.of(context).successful, + alertContent: S.of(context).change_rep_successful, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.pop(context)); + }); } catch (e) { await showPopUp( context: context, @@ -97,6 +131,8 @@ class NanoChangeRepPage extends BasePage { )), ], )), - )); + ), + ), + ); } } diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 61e9ba029..1522ea354 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -86,6 +86,8 @@ abstract class SettingsStoreBase with Store { required this.sortBalanceBy, required this.pinNativeTokenAtTop, required this.useEtherscan, + required this.defaultNanoRep, + required this.defaultBananoRep, required this.lookupsTwitter, required this.lookupsMastodon, required this.lookupsYatService, @@ -378,6 +380,13 @@ abstract class SettingsStoreBase with Store { (bool useEtherscan) => _sharedPreferences.setBool(PreferencesKey.useEtherscan, useEtherscan)); + reaction((_) => defaultNanoRep, + (String nanoRep) => _sharedPreferences.setString(PreferencesKey.defaultNanoRep, nanoRep)); + + reaction( + (_) => defaultBananoRep, + (String bananoRep) => + _sharedPreferences.setString(PreferencesKey.defaultBananoRep, bananoRep)); reaction( (_) => lookupsTwitter, (bool looksUpTwitter) => @@ -541,6 +550,12 @@ abstract class SettingsStoreBase with Store { @observable bool useEtherscan; + @observable + String defaultNanoRep; + + @observable + String defaultBananoRep; + @observable bool lookupsTwitter; @@ -618,8 +633,8 @@ abstract class SettingsStoreBase with Store { TransactionPriority? moneroTransactionPriority = monero?.deserializeMoneroTransactionPriority( raw: sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!); TransactionPriority? bitcoinTransactionPriority = - bitcoin?.deserializeBitcoinTransactionPriority( - sharedPreferences.getInt(PreferencesKey.bitcoinTransactionPriority)!); + bitcoin?.deserializeBitcoinTransactionPriority( + sharedPreferences.getInt(PreferencesKey.bitcoinTransactionPriority)!); TransactionPriority? havenTransactionPriority; TransactionPriority? litecoinTransactionPriority; @@ -658,8 +673,8 @@ abstract class SettingsStoreBase with Store { final isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? false; final disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? false; final disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? false; - final defaultBuyProvider = BuyProviderType.values[sharedPreferences.getInt( - PreferencesKey.defaultBuyProvider) ?? 0]; + final defaultBuyProvider = + BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0]; final currentFiatApiMode = FiatApiMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey) ?? FiatApiMode.enabled.raw); @@ -678,7 +693,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToInternalWallets) ?? false; final shouldRequireTOTP2FAForExchangesToInternalWallets = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ?? + .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ?? false; final shouldRequireTOTP2FAForExchangesToExternalWallets = sharedPreferences .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToExternalWallets) ?? @@ -689,7 +704,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets) ?? false; final shouldRequireTOTP2FAForAllSecurityAndBackupSettings = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ?? + .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ?? false; final useTOTP2FA = sharedPreferences.getBool(PreferencesKey.useTOTP2FA) ?? false; final totpSecretKey = sharedPreferences.getString(PreferencesKey.totpSecretKey) ?? ''; @@ -718,10 +733,12 @@ abstract class SettingsStoreBase with Store { ? SeedPhraseLength.deserialize(raw: seedPhraseCount) : defaultSeedPhraseLength; final sortBalanceBy = - SortBalanceBy.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? 0]; + SortBalanceBy.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? 0]; final pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true; final useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true; + final defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? ""; + final defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? ""; final lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true; final lookupsMastodon = sharedPreferences.getBool(PreferencesKey.lookupsMastodon) ?? true; final lookupsYatService = sharedPreferences.getBool(PreferencesKey.lookupsYatService) ?? true; @@ -738,11 +755,11 @@ abstract class SettingsStoreBase with Store { await LanguageService.localeDetection(); final nodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey); final bitcoinElectrumServerId = - sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); + sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); final litecoinElectrumServerId = - sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); + sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); final bitcoinCashElectrumServerId = - sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); + sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); final havenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey); final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey); final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); @@ -759,7 +776,7 @@ abstract class SettingsStoreBase with Store { final deviceName = await _getDeviceName() ?? ''; final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true; final generateSubaddresses = - sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); + sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); final autoGenerateSubaddressStatus = generateSubaddresses != null ? AutoGenerateSubaddressStatus.deserialize(raw: generateSubaddresses) @@ -799,10 +816,10 @@ abstract class SettingsStoreBase with Store { powNodes[WalletType.nano] = nanoPowNode; } - final savedSyncMode = SyncMode.all.firstWhere((element) { - return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 1); - }); - final savedSyncAll = sharedPreferences.getBool(PreferencesKey.syncAllKey) ?? true; + final savedSyncMode = SyncMode.all.firstWhere((element) { + return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 1); + }); + final savedSyncAll = sharedPreferences.getBool(PreferencesKey.syncAllKey) ?? true; return SettingsStore( sharedPreferences: sharedPreferences, @@ -836,6 +853,8 @@ abstract class SettingsStoreBase with Store { sortBalanceBy: sortBalanceBy, pinNativeTokenAtTop: pinNativeTokenAtTop, useEtherscan: useEtherscan, + defaultNanoRep: defaultNanoRep, + defaultBananoRep: defaultBananoRep, lookupsTwitter: lookupsTwitter, lookupsMastodon: lookupsMastodon, lookupsYatService: lookupsYatService, @@ -874,35 +893,35 @@ abstract class SettingsStoreBase with Store { raw: sharedPreferences.getString(PreferencesKey.currentFiatCurrencyKey)!); priority[WalletType.monero] = monero?.deserializeMoneroTransactionPriority( - raw: sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ?? + raw: sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ?? priority[WalletType.monero]!; priority[WalletType.bitcoin] = bitcoin?.deserializeBitcoinTransactionPriority( - sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ?? + sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority)!) ?? priority[WalletType.bitcoin]!; if (sharedPreferences.getInt(PreferencesKey.havenTransactionPriority) != null) { priority[WalletType.haven] = monero?.deserializeMoneroTransactionPriority( - raw: sharedPreferences.getInt(PreferencesKey.havenTransactionPriority)!) ?? + raw: sharedPreferences.getInt(PreferencesKey.havenTransactionPriority)!) ?? priority[WalletType.haven]!; } if (sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority) != null) { priority[WalletType.litecoin] = bitcoin?.deserializeLitecoinTransactionPriority( - sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority)!) ?? + sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority)!) ?? priority[WalletType.litecoin]!; } if (sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority) != null) { priority[WalletType.ethereum] = ethereum?.deserializeEthereumTransactionPriority( - sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority)!) ?? + sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority)!) ?? priority[WalletType.ethereum]!; } if (sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority) != null) { priority[WalletType.bitcoinCash] = bitcoinCash?.deserializeBitcoinCashTransactionPriority( - sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority)!) ?? + sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority)!) ?? priority[WalletType.bitcoinCash]!; } final generateSubaddresses = - sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); + sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); autoGenerateSubaddressStatus = generateSubaddresses != null ? AutoGenerateSubaddressStatus.deserialize(raw: generateSubaddresses) @@ -921,7 +940,7 @@ abstract class SettingsStoreBase with Store { disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? disableBuy; disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? disableSell; defaultBuyProvider = - BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0]; + BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0]; allowBiometricalAuthentication = sharedPreferences.getBool(PreferencesKey.allowBiometricalAuthenticationKey) ?? allowBiometricalAuthentication; @@ -938,7 +957,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToInternalWallets) ?? false; shouldRequireTOTP2FAForExchangesToInternalWallets = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ?? + .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ?? false; shouldRequireTOTP2FAForExchangesToExternalWallets = sharedPreferences .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToExternalWallets) ?? @@ -949,7 +968,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets) ?? false; shouldRequireTOTP2FAForAllSecurityAndBackupSettings = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ?? + .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ?? false; shouldShowMarketPlaceInDashboard = sharedPreferences.getBool(PreferencesKey.shouldShowMarketPlaceInDashboard) ?? @@ -982,6 +1001,8 @@ abstract class SettingsStoreBase with Store { .values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? sortBalanceBy.index]; pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true; useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true; + defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? ""; + defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? ""; lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true; lookupsMastodon = sharedPreferences.getBool(PreferencesKey.lookupsMastodon) ?? true; lookupsYatService = sharedPreferences.getBool(PreferencesKey.lookupsYatService) ?? true; @@ -991,11 +1012,11 @@ abstract class SettingsStoreBase with Store { final nodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey); final bitcoinElectrumServerId = - sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); + sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); final litecoinElectrumServerId = - sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); + sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); final bitcoinCashElectrumServerId = - sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); + sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); final havenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey); final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey); final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); @@ -1057,7 +1078,8 @@ abstract class SettingsStoreBase with Store { await _sharedPreferences.setInt(PreferencesKey.currentEthereumNodeIdKey, node.key as int); break; case WalletType.bitcoinCash: - await _sharedPreferences.setInt(PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int); + await _sharedPreferences.setInt( + PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int); break; case WalletType.nano: await _sharedPreferences.setInt(PreferencesKey.currentNanoNodeIdKey, node.key as int); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 21ebc7def..a5298c343 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -720,6 +720,7 @@ "enterWalletConnectURI": "WalletConnect ـﻟ URI ﻞﺧﺩﺃ", "seed_key": "مفتاح البذور", "enter_seed_phrase": "أدخل عبارة البذور الخاصة بك", + "change_rep_successful": "تم تغيير ممثل بنجاح", "add_contact": "ﻝﺎﺼﺗﺍ ﺔﻬﺟ ﺔﻓﺎﺿﺇ", "exchange_provider_unsupported": "${providerName} لم يعد مدعومًا!", "domain_looks_up": "ﻝﺎﺠﻤﻟﺍ ﺚﺤﺑ ﺕﺎﻴﻠﻤﻋ", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index b091e072f..3b085cd59 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -716,6 +716,7 @@ "enterWalletConnectURI": "Въведете URI на WalletConnect", "seed_key": "Ключ за семена", "enter_seed_phrase": "Въведете вашата фраза за семена", + "change_rep_successful": "Успешно промени представител", "add_contact": "Добави контакт", "exchange_provider_unsupported": "${providerName} вече не се поддържа!", "domain_looks_up": "Търсене на домейни", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 2c73fdc3e..f6d024957 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -716,6 +716,7 @@ "enterWalletConnectURI": "Zadejte identifikátor URI WalletConnect", "seed_key": "Klíč semen", "enter_seed_phrase": "Zadejte svou frázi semen", + "change_rep_successful": "Úspěšně změnil zástupce", "add_contact": "Přidat kontakt", "exchange_provider_unsupported": "${providerName} již není podporováno!", "domain_looks_up": "Vyhledávání domén", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 567f9d9c0..6519f0ef6 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -722,8 +722,9 @@ "awaitDAppProcessing": "Bitte warten Sie, bis die dApp die Verarbeitung abgeschlossen hat.", "copyWalletConnectLink": "Kopieren Sie den WalletConnect-Link von dApp und fügen Sie ihn hier ein", "enterWalletConnectURI": "Geben Sie den WalletConnect-URI ein", - "seed_key": "Seed-Schlüssel", - "enter_seed_phrase": "Geben Sie Ihre Seed-Phrase ein", + "seed_key": "Samenschlüssel", + "enter_seed_phrase": "Geben Sie Ihre Samenphrase ein", + "change_rep_successful": "Erfolgreich veränderte Vertreter", "add_contact": "Kontakt hinzufügen", "exchange_provider_unsupported": "${providerName} wird nicht mehr unterstützt!", "domain_looks_up": "Domain-Suchen", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 1d50540a7..2c1d00eb6 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -725,6 +725,7 @@ "enterWalletConnectURI": "Enter WalletConnect URI", "seed_key": "Seed key", "enter_seed_phrase": "Enter your seed phrase", + "change_rep_successful": "Successfully changed representative", "add_contact": "Add contact", "exchange_provider_unsupported": "${providerName} is no longer supported!", "domain_looks_up": "Domain lookups", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index d021902d3..3629a6d37 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -724,6 +724,7 @@ "enterWalletConnectURI": "Ingrese el URI de WalletConnect", "seed_key": "Llave de semilla", "enter_seed_phrase": "Ingrese su frase de semillas", + "change_rep_successful": "Representante cambiado con éxito", "add_contact": "Agregar contacto", "exchange_provider_unsupported": "¡${providerName} ya no es compatible!", "domain_looks_up": "Búsquedas de dominio", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 9e6a6c07e..cae478d7d 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -722,8 +722,9 @@ "awaitDAppProcessing": "Veuillez attendre que l'application décentralisée (dApp) termine le traitement.", "copyWalletConnectLink": "Copiez le lien WalletConnect depuis l'application décentralisée (dApp) et collez-le ici", "enterWalletConnectURI": "Saisissez l'URI de WalletConnect.", - "seed_key": "Clé secrète (seed key)", - "enter_seed_phrase": "Entrez votre phrase secrète (seed)", + "seed_key": "Clé de graines", + "enter_seed_phrase": "Entrez votre phrase de semence", + "change_rep_successful": "Représentant changé avec succès", "add_contact": "Ajouter le contact", "exchange_provider_unsupported": "${providerName} n'est plus pris en charge !", "domain_looks_up": "Résolution de nom", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index b865c4790..84c3b4b74 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -702,6 +702,7 @@ "enterWalletConnectURI": "Shigar da WalletConnect URI", "seed_key": "Maɓallin iri", "enter_seed_phrase": "Shigar da Sert Sentarku", + "change_rep_successful": "An samu nasarar canzawa wakilin", "add_contact": "Ƙara lamba", "exchange_provider_unsupported": "${providerName}", "domain_looks_up": "Binciken yanki", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 5f53141e5..af3b888cb 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -724,6 +724,7 @@ "enterWalletConnectURI": "वॉलेटकनेक्ट यूआरआई दर्ज करें", "seed_key": "बीज कुंजी", "enter_seed_phrase": "अपना बीज वाक्यांश दर्ज करें", + "change_rep_successful": "सफलतापूर्वक बदलकर प्रतिनिधि", "add_contact": "संपर्क जोड़ें", "exchange_provider_unsupported": "${providerName} अब समर्थित नहीं है!", "domain_looks_up": "डोमेन लुकअप", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 58bd0f497..3c56b8552 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -722,6 +722,7 @@ "enterWalletConnectURI": "Unesite WalletConnect URI", "seed_key": "Sjemenski ključ", "enter_seed_phrase": "Unesite svoju sjemensku frazu", + "change_rep_successful": "Uspješno promijenjena reprezentativna", "add_contact": "Dodaj kontakt", "exchange_provider_unsupported": "${providerName} više nije podržan!", "domain_looks_up": "Pretraga domena", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index c03523f5d..b3d22780a 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -712,6 +712,7 @@ "enterWalletConnectURI": "Masukkan URI WalletConnect", "seed_key": "Kunci benih", "enter_seed_phrase": "Masukkan frasa benih Anda", + "change_rep_successful": "Berhasil mengubah perwakilan", "add_contact": "Tambah kontak", "exchange_provider_unsupported": "${providerName} tidak lagi didukung!", "domain_looks_up": "Pencarian domain", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 1c9387180..8fc157f27 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -724,6 +724,7 @@ "enterWalletConnectURI": "Inserisci l'URI di WalletConnect", "seed_key": "Chiave di semi", "enter_seed_phrase": "Inserisci la tua frase di semi", + "change_rep_successful": "Rappresentante modificato con successo", "add_contact": "Aggiungi contatto", "exchange_provider_unsupported": "${providerName} non è più supportato!", "domain_looks_up": "Ricerche di domini", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 42aeb34f8..06d8efd37 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -724,6 +724,7 @@ "enterWalletConnectURI": "WalletConnect URI を入力してください", "seed_key": "シードキー", "enter_seed_phrase": "シードフレーズを入力してください", + "change_rep_successful": "代表者の変更に成功しました", "add_contact": "連絡先を追加", "exchange_provider_unsupported": "${providerName}はサポートされなくなりました!", "domain_looks_up": "ドメイン検索", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 8e09c7034..6830b1183 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -722,6 +722,7 @@ "enterWalletConnectURI": "WalletConnect URI를 입력하세요.", "seed_key": "시드 키", "enter_seed_phrase": "시드 문구를 입력하십시오", + "change_rep_successful": "대리인이 성공적으로 변경되었습니다", "add_contact": "주소록에 추가", "exchange_provider_unsupported": "${providerName}은 더 이상 지원되지 않습니다!", "domain_looks_up": "도메인 조회", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 71255d98e..ff8f6683b 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -722,6 +722,7 @@ "enterWalletConnectURI": "WalletConnect URI ကိုရိုက်ထည့်ပါ။", "seed_key": "မျိုးစေ့သော့", "enter_seed_phrase": "သင့်ရဲ့မျိုးစေ့စကားစုကိုရိုက်ထည့်ပါ", + "change_rep_successful": "အောင်မြင်စွာကိုယ်စားလှယ်ပြောင်းလဲသွားတယ်", "add_contact": "အဆက်အသွယ်ထည့်ပါ။", "exchange_provider_unsupported": "${providerName} မရှိတော့ပါ!", "domain_looks_up": "ဒိုမိန်းရှာဖွေမှုများ", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 4de0fac30..753e28cd5 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -724,6 +724,7 @@ "enterWalletConnectURI": "Voer WalletConnect-URI in", "seed_key": "Zaadsleutel", "enter_seed_phrase": "Voer uw zaadzin in", + "change_rep_successful": "Met succes veranderde vertegenwoordiger", "add_contact": "Contactpersoon toevoegen", "exchange_provider_unsupported": "${providerName} wordt niet langer ondersteund!", "domain_looks_up": "Domein opzoeken", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 160bf2f88..1900ca590 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -724,6 +724,7 @@ "enterWalletConnectURI": "Wprowadź identyfikator URI WalletConnect", "seed_key": "Klucz nasion", "enter_seed_phrase": "Wprowadź swoją frazę nasienną", + "change_rep_successful": "Pomyślnie zmienił przedstawiciela", "add_contact": "Dodaj kontakt", "exchange_provider_unsupported": "${providerName} nie jest już obsługiwany!", "domain_looks_up": "Wyszukiwanie domen", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index ab221dd49..86c7a6b0d 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -723,6 +723,7 @@ "enterWalletConnectURI": "Insira o URI do WalletConnect", "seed_key": "Chave de semente", "enter_seed_phrase": "Digite sua frase de semente", + "change_rep_successful": "Mudou com sucesso o representante", "add_contact": "Adicionar contato", "exchange_provider_unsupported": "${providerName} não é mais suportado!", "domain_looks_up": "Pesquisas de domínio", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 4474c26e3..a37b0908b 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -724,6 +724,7 @@ "enterWalletConnectURI": "Введите URI WalletConnect", "seed_key": "Ключ семян", "enter_seed_phrase": "Введите свою семенную фразу", + "change_rep_successful": "Успешно изменил представитель", "add_contact": "Добавить контакт", "exchange_provider_unsupported": "${providerName} больше не поддерживается!", "domain_looks_up": "Поиск доменов", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 90f71cf75..fa36c04bb 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -722,6 +722,7 @@ "enterWalletConnectURI": "เข้าสู่ WalletConnect URI", "seed_key": "คีย์เมล็ดพันธุ์", "enter_seed_phrase": "ป้อนวลีเมล็ดพันธุ์ของคุณ", + "change_rep_successful": "เปลี่ยนตัวแทนสำเร็จ", "add_contact": "เพิ่มผู้ติดต่อ", "exchange_provider_unsupported": "${providerName} ไม่ได้รับการสนับสนุนอีกต่อไป!", "domain_looks_up": "การค้นหาโดเมน", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index ffd89c30e..b8bf168ce 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -719,6 +719,7 @@ "enterWalletConnectURI": "Ilagay ang WalletConnect URI", "seed_key": "Seed Key", "enter_seed_phrase": "Ipasok ang iyong pariralang binhi", + "change_rep_successful": "Matagumpay na nagbago ng kinatawan", "add_contact": "Magdagdag ng contact", "exchange_provider_unsupported": "Ang ${providerName} ay hindi na suportado!", "domain_looks_up": "Mga paghahanap ng domain", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 0e2690ad6..f7962b526 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -722,6 +722,7 @@ "enterWalletConnectURI": "WalletConnect URI'sini girin", "seed_key": "Tohum", "enter_seed_phrase": "Tohum ifadenizi girin", + "change_rep_successful": "Temsilciyi başarıyla değiştirdi", "add_contact": "Kişi ekle", "exchange_provider_unsupported": "${providerName} artık desteklenmiyor!", "domain_looks_up": "Etki alanı aramaları", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 044bde32a..0e4cc3ecb 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -724,6 +724,7 @@ "enterWalletConnectURI": "Введіть URI WalletConnect", "seed_key": "Насіннєвий ключ", "enter_seed_phrase": "Введіть свою насіннєву фразу", + "change_rep_successful": "Успішно змінив представник", "add_contact": "Додати контакт", "exchange_provider_unsupported": "${providerName} більше не підтримується!", "domain_looks_up": "Пошук доменів", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index a8b3813a3..cd05010d7 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -716,6 +716,7 @@ "enterWalletConnectURI": "WalletConnect URI ۔ﮟﯾﺮﮐ ﺝﺭﺩ", "seed_key": "بیج کی کلید", "enter_seed_phrase": "اپنے بیج کا جملہ درج کریں", + "change_rep_successful": "نمائندہ کو کامیابی کے ساتھ تبدیل کیا", "add_contact": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮧﻄﺑﺍﺭ", "exchange_provider_unsupported": "${providerName} اب تعاون نہیں کیا جاتا ہے!", "domain_looks_up": "ڈومین تلاش کرنا", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 6b46201b8..fc632f8a8 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -718,6 +718,7 @@ "enterWalletConnectURI": "Tẹ WalletConnect URI sii", "seed_key": "Bọtini Ose", "enter_seed_phrase": "Tẹ ọrọ-iru irugbin rẹ", + "change_rep_successful": "Ni ifijišẹ yipada aṣoju", "add_contact": "Fi olubasọrọ kun", "exchange_provider_unsupported": "${providerName} ko ni atilẹyin mọ!", "domain_looks_up": "Awọn wiwa agbegbe", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index c54ba2696..e57df96d9 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -723,6 +723,7 @@ "enterWalletConnectURI": "输入 WalletConnect URI", "seed_key": "种子钥匙", "enter_seed_phrase": "输入您的种子短语", + "change_rep_successful": "成功改变了代表", "add_contact": "增加联系人", "exchange_provider_unsupported": "${providerName}不再支持!", "domain_looks_up": "域名查找", From 539eb9b3eb27306c5b3b578f17408ecf0dd4e242 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Fri, 17 Nov 2023 19:37:32 +0100 Subject: [PATCH 040/241] Cw 523 robinhood enhancements (#1176) * CW-523 Add BCH support to Robinhood * CW-523 Only show popup on Robinhood error * CW-523 Add BitcoinCash to Robinhood Provider --- .../lib/src/bitcoin_cash_address_utils.dart | 1 + .../lib/src/bitcoin_cash_wallet.dart | 14 +++++++++++++ lib/buy/robinhood/robinhood_buy_provider.dart | 20 +++++++++++-------- lib/entities/main_actions.dart | 2 +- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_address_utils.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_address_utils.dart index ca47ea9f6..5832835eb 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_address_utils.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_address_utils.dart @@ -2,4 +2,5 @@ import 'package:bitbox/bitbox.dart' as bitbox; class AddressUtils { static String getCashAddrFormat(String address) => bitbox.Address.toCashAddress(address); + static String toLegacyAddress(String address) => bitbox.Address.toLegacyAddress(address); } diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index b4924e2db..5f2a33ab6 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:bitbox/bitbox.dart' as bitbox; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:cw_bitcoin/bitcoin_address_record.dart'; @@ -294,4 +296,16 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { return 0; } + + @override + String signMessage(String message, {String? address = null}) { + final index = address != null + ? walletAddresses.addresses + .firstWhere((element) => element.address == AddressUtils.toLegacyAddress(address)) + .index + : null; + return index == null + ? base64Encode(hd.sign(message)) + : base64Encode(hd.derive(index).sign(message)); + } } diff --git a/lib/buy/robinhood/robinhood_buy_provider.dart b/lib/buy/robinhood/robinhood_buy_provider.dart index e7a9e0579..ade0bf99f 100644 --- a/lib/buy/robinhood/robinhood_buy_provider.dart +++ b/lib/buy/robinhood/robinhood_buy_provider.dart @@ -3,7 +3,6 @@ import 'dart:convert'; import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/utils/exception_handler.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; @@ -12,8 +11,7 @@ import 'package:http/http.dart' as http; import 'package:url_launcher/url_launcher.dart'; class RobinhoodBuyProvider { - RobinhoodBuyProvider({required WalletBase wallet}) - : this._wallet = wallet; + RobinhoodBuyProvider({required WalletBase wallet}) : this._wallet = wallet; final WalletBase _wallet; @@ -21,10 +19,15 @@ class RobinhoodBuyProvider { static const _cIdBaseUrl = 'exchange-helper.cakewallet.com'; String get _applicationId => secrets.robinhoodApplicationId; + String get _apiSecret => secrets.robinhoodCIdApiSecret; - bool get isAvailable => - [WalletType.bitcoin, WalletType.litecoin, WalletType.ethereum].contains(_wallet.type); + bool get isAvailable => [ + WalletType.bitcoin, + WalletType.bitcoinCash, + WalletType.litecoin, + WalletType.ethereum + ].contains(_wallet.type); String getSignature(String message) { switch (_wallet.type) { @@ -32,6 +35,7 @@ class RobinhoodBuyProvider { return _wallet.signMessage(message); case WalletType.litecoin: case WalletType.bitcoin: + case WalletType.bitcoinCash: return _wallet.signMessage(message, address: _wallet.walletAddresses.address); default: throw Exception("WalletType is not available for Robinhood ${_wallet.type}"); @@ -55,7 +59,8 @@ class RobinhoodBuyProvider { if (response.statusCode == 200) { return (jsonDecode(response.body) as Map)['connectId'] as String; } else { - throw Exception('Provider currently unavailable. Status: ${response.statusCode} ${response.body}'); + throw Exception( + 'Provider currently unavailable. Status: ${response.statusCode} ${response.body}'); } } @@ -76,8 +81,7 @@ class RobinhoodBuyProvider { try { final uri = await requestUrl(); await launchUrl(uri, mode: LaunchMode.externalApplication); - } catch (e, s) { - ExceptionHandler.onError(FlutterErrorDetails(exception: e, stack: s)); + } catch (_) { await showPopUp( context: context, builder: (BuildContext context) { diff --git a/lib/entities/main_actions.dart b/lib/entities/main_actions.dart index 5f270deaf..46865cbcc 100644 --- a/lib/entities/main_actions.dart +++ b/lib/entities/main_actions.dart @@ -52,7 +52,7 @@ class MainActions { case WalletType.bitcoin: case WalletType.litecoin: case WalletType.ethereum: - // case WalletType.bitcoinCash: // TODO: add sign message function to BCH first + case WalletType.bitcoinCash: switch (defaultBuyProvider) { case BuyProviderType.AskEachTime: Navigator.pushNamed(context, Routes.buy); From e0925092641449c151f8213ca808d617f8eef29c Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Sat, 18 Nov 2023 00:15:15 +0200 Subject: [PATCH 041/241] Generic fixes (#1173) * - Catch get balance network issues - Disable remove button when adding node * Update packages and android gradle version minor enhancements * Backup issue fix * update workflow java version * Remove useless permission check for saving file * minor enhancements * only delete secure storage key before overriding it on MacOS * Minor UI changes * Remove debug prints [skip ci] * Revert FR localization changes --- .github/workflows/cache_dependencies.yml | 2 +- .github/workflows/pr_test_build.yml | 2 +- android/app/build.gradle | 1 - android/app/src/main/AndroidManifestBase.xml | 1 + android/build.gradle | 4 +- cw_ethereum/lib/ethereum_client.dart | 9 +- cw_haven/android/build.gradle | 4 +- cw_monero/android/build.gradle | 4 +- cw_shared_external/android/build.gradle | 4 +- lib/core/auth_service.dart | 6 +- lib/core/backup_service.dart | 2 +- lib/ionia/ionia_service.dart | 5 +- .../on_wallet_sync_status_change.dart | 6 +- lib/src/screens/backup/backup_page.dart | 10 +- lib/src/screens/buy/buy_options_page.dart | 20 +-- .../monero_account_list_page.dart | 4 +- .../monero_accounts/widgets/account_tile.dart | 3 +- .../nodes/node_create_or_edit_page.dart | 36 +++--- .../restore/restore_from_backup_page.dart | 114 +++++++++++++----- .../screens/restore/restore_options_page.dart | 9 +- lib/src/widgets/base_alert_dialog.dart | 3 +- lib/src/widgets/option_tile.dart | 2 +- lib/utils/permission_handler.dart | 4 +- macos/Flutter/GeneratedPluginRegistrant.swift | 10 +- pubspec_base.yaml | 15 ++- res/values/strings_fr.arb | 4 +- 26 files changed, 168 insertions(+), 116 deletions(-) diff --git a/.github/workflows/cache_dependencies.yml b/.github/workflows/cache_dependencies.yml index 5373bbc87..bf0d0f7bc 100644 --- a/.github/workflows/cache_dependencies.yml +++ b/.github/workflows/cache_dependencies.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-java@v1 with: - java-version: '8.x' + java-version: '11.x' - name: Flutter action uses: subosito/flutter-action@v1 diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 5434429b2..3c6b132bd 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-java@v1 with: - java-version: "8.x" + java-version: "11.x" - name: Flutter action uses: subosito/flutter-action@v1 diff --git a/android/app/build.gradle b/android/app/build.gradle index 946c53697..e6b9eb2f8 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -75,7 +75,6 @@ android { shrinkResources false minifyEnabled false - useProguard false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index 77a555db8..910149f60 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -3,6 +3,7 @@ + diff --git a/android/build.gradle b/android/build.gradle index bd4ebd770..8286d9cb9 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.6.21' + ext.kotlin_version = '1.7.10' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.1.3' + classpath 'com.android.tools.build:gradle:7.3.0' classpath 'com.google.gms:google-services:4.3.8' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } diff --git a/cw_ethereum/lib/ethereum_client.dart b/cw_ethereum/lib/ethereum_client.dart index 42221c4f5..f0c7381e8 100644 --- a/cw_ethereum/lib/ethereum_client.dart +++ b/cw_ethereum/lib/ethereum_client.dart @@ -38,8 +38,13 @@ class EthereumClient { // }); } - Future getBalance(EthereumAddress address) async => - await _client!.getBalance(address); + Future getBalance(EthereumAddress address) async { + try { + return await _client!.getBalance(address); + } catch (_) { + return EtherAmount.zero(); + } + } Future getGasUnitPrice() async { try { diff --git a/cw_haven/android/build.gradle b/cw_haven/android/build.gradle index 91da1b857..fb941f657 100644 --- a/cw_haven/android/build.gradle +++ b/cw_haven/android/build.gradle @@ -2,14 +2,14 @@ group 'com.cakewallet.cw_haven' version '1.0-SNAPSHOT' buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.7.10' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:7.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/cw_monero/android/build.gradle b/cw_monero/android/build.gradle index 1d7ae93d8..fc4835e81 100644 --- a/cw_monero/android/build.gradle +++ b/cw_monero/android/build.gradle @@ -2,14 +2,14 @@ group 'com.cakewallet.monero' version '1.0-SNAPSHOT' buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.7.10' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.4' + classpath 'com.android.tools.build:gradle:7.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/cw_shared_external/android/build.gradle b/cw_shared_external/android/build.gradle index d6cdaf658..8db51f0e6 100644 --- a/cw_shared_external/android/build.gradle +++ b/cw_shared_external/android/build.gradle @@ -2,14 +2,14 @@ group 'com.cakewallet.cw_shared_external' version '1.0-SNAPSHOT' buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.7.10' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:7.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/lib/core/auth_service.dart b/lib/core/auth_service.dart index 321b5b94a..c072bf65e 100644 --- a/lib/core/auth_service.dart +++ b/lib/core/auth_service.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:cake_wallet/core/totp_request_details.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; @@ -40,7 +42,9 @@ class AuthService with Store { final encodedPassword = encodedPinCode(pin: password); // secure storage has a weird bug on macOS, where overwriting a key doesn't work, unless // we delete what's there first: - await secureStorage.delete(key: key); + if (Platform.isMacOS) { + await secureStorage.delete(key: key); + } await secureStorage.write(key: key, value: encodedPassword); } diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 2913505c0..b13a01889 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -295,7 +295,7 @@ class BackupService { await _sharedPreferences.setInt( PreferencesKey.currentTransactionPriorityKeyLegacy, currentTransactionPriorityKeyLegacy); - if (Platform.isMacOS || Platform.isLinux) { + if (DeviceInfo.instance.isDesktop) { await _sharedPreferences.setBool(PreferencesKey.allowBiometricalAuthenticationKey, false); } else if (allowBiometricalAuthentication != null) { await _sharedPreferences.setBool( diff --git a/lib/ionia/ionia_service.dart b/lib/ionia/ionia_service.dart index 51e23ad28..0396ed7c1 100644 --- a/lib/ionia/ionia_service.dart +++ b/lib/ionia/ionia_service.dart @@ -6,7 +6,6 @@ import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/ionia/ionia_api.dart'; import 'package:cake_wallet/ionia/ionia_gift_card.dart'; import 'package:cake_wallet/ionia/ionia_category.dart'; -import 'package:platform_device_id/platform_device_id.dart'; class IoniaService { IoniaService(this.secureStorage, this.ioniaApi); @@ -112,9 +111,9 @@ class IoniaService { required String currency}) async { final username = (await secureStorage.read(key: ioniaUsernameStorageKey))!; final password = (await secureStorage.read(key: ioniaPasswordStorageKey))!; - final deviceId = await PlatformDeviceId.getDeviceId; + final deviceId = ''; return ioniaApi.purchaseGiftCard( - requestedUUID: deviceId!, + requestedUUID: deviceId, merchId: merchId, amount: amount, currency: currency, diff --git a/lib/reactions/on_wallet_sync_status_change.dart b/lib/reactions/on_wallet_sync_status_change.dart index 767bfd7e8..9a13db597 100644 --- a/lib/reactions/on_wallet_sync_status_change.dart +++ b/lib/reactions/on_wallet_sync_status_change.dart @@ -7,7 +7,7 @@ import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/sync_status.dart'; -import 'package:wakelock/wakelock.dart'; +import 'package:wakelock_plus/wakelock_plus.dart'; ReactionDisposer? _onWalletSyncStatusChangeReaction; @@ -27,10 +27,10 @@ void startWalletSyncStatusChangeReaction( } } if (status is SyncingSyncStatus) { - await Wakelock.enable(); + await WakelockPlus.enable(); } if (status is SyncedSyncStatus || status is FailedSyncStatus) { - await Wakelock.disable(); + await WakelockPlus.disable(); } } catch(e) { print(e.toString()); diff --git a/lib/src/screens/backup/backup_page.dart b/lib/src/screens/backup/backup_page.dart index 5995e71c4..d17702724 100644 --- a/lib/src/screens/backup/backup_page.dart +++ b/lib/src/screens/backup/backup_page.dart @@ -17,7 +17,6 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:permission_handler/permission_handler.dart'; class BackupPage extends BasePage { BackupPage(this.backupViewModelBase); @@ -129,15 +128,8 @@ class BackupPage extends BasePage { alertTitle: S.of(context).export_backup, alertContent: S.of(context).select_destination, rightButtonText: S.of(context).save_to_downloads, - leftButtonText:S.of(context).share, + leftButtonText: S.of(context).share, actionRightButton: () async { - final permission = await Permission.storage.request(); - - if (permission.isDenied) { - Navigator.of(dialogContext).pop(); - return; - } - await backupViewModelBase.saveToDownload(backup.name, backup.content); Navigator.of(dialogContext).pop(); }, diff --git a/lib/src/screens/buy/buy_options_page.dart b/lib/src/screens/buy/buy_options_page.dart index 45edfc921..930878544 100644 --- a/lib/src/screens/buy/buy_options_page.dart +++ b/lib/src/screens/buy/buy_options_page.dart @@ -34,16 +34,6 @@ class BuyOptionsPage extends BasePage { constraints: BoxConstraints(maxWidth: 330), child: Column( children: [ - Padding( - padding: EdgeInsets.only(top: 24), - child: OptionTile( - image: iconRobinhood, - title: "Robinhood Connect", - description: S.of(context).robinhood_option_description, - onPressed: () async => - await getIt.get().launchProvider(context), - ), - ), Padding( padding: EdgeInsets.only(top: 24), child: OptionTile( @@ -54,6 +44,16 @@ class BuyOptionsPage extends BasePage { await getIt.get().launchProvider(context), ), ), + Padding( + padding: EdgeInsets.only(top: 24), + child: OptionTile( + image: iconRobinhood, + title: "Robinhood Connect", + description: S.of(context).robinhood_option_description, + onPressed: () async => + await getIt.get().launchProvider(context), + ), + ), Spacer(), Padding( padding: EdgeInsets.fromLTRB(24, 24, 24, 32), diff --git a/lib/src/screens/monero_accounts/monero_account_list_page.dart b/lib/src/screens/monero_accounts/monero_account_list_page.dart index 6b3d3e08b..38055854b 100644 --- a/lib/src/screens/monero_accounts/monero_account_list_page.dart +++ b/lib/src/screens/monero_accounts/monero_account_list_page.dart @@ -15,7 +15,7 @@ class MoneroAccountListPage extends StatelessWidget { @override Widget build(BuildContext context) { - double itemHeight = 80; + double itemHeight = 65; double buttonHeight = 62; return Observer(builder: (_) { @@ -31,7 +31,7 @@ class MoneroAccountListPage extends StatelessWidget { child: ListView.separated( padding: EdgeInsets.zero, controller: controller, - separatorBuilder: (context, index) => const VerticalSectionDivider(), + separatorBuilder: (context, index) => const HorizontalSectionDivider(), itemCount: accounts.length, itemBuilder: (context, index) { final account = accounts[index]; diff --git a/lib/src/screens/monero_accounts/widgets/account_tile.dart b/lib/src/screens/monero_accounts/widgets/account_tile.dart index 3e428f355..97d328214 100644 --- a/lib/src/screens/monero_accounts/widgets/account_tile.dart +++ b/lib/src/screens/monero_accounts/widgets/account_tile.dart @@ -1,5 +1,4 @@ import 'package:cake_wallet/themes/extensions/account_list_theme.dart'; -import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -33,7 +32,7 @@ class AccountTile extends StatelessWidget { final Widget cell = GestureDetector( onTap: onTap, child: Container( - height: 77, + height: 60, width: double.infinity, padding: EdgeInsets.only(left: 24, right: 24), color: color, diff --git a/lib/src/screens/nodes/node_create_or_edit_page.dart b/lib/src/screens/nodes/node_create_or_edit_page.dart index ff9d59719..50c1c3be5 100644 --- a/lib/src/screens/nodes/node_create_or_edit_page.dart +++ b/lib/src/screens/nodes/node_create_or_edit_page.dart @@ -78,7 +78,7 @@ class NodeCreateOrEditPage extends BasePage { 'assets/images/qr_code_icon.png', ), ); - + final NodeCreateOrEditViewModel nodeCreateOrEditViewModel; final Node? editingNode; final bool? isSelected; @@ -133,27 +133,20 @@ class NodeCreateOrEditPage extends BasePage { mainAxisAlignment: MainAxisAlignment.center, children: [ Flexible( - child: Container( - padding: EdgeInsets.only(right: 8.0), - child: LoadingPrimaryButton( + child: Container( + padding: EdgeInsets.only(right: 8.0), + child: LoadingPrimaryButton( onPressed: () async { final confirmed = await showPopUp( context: context, builder: (BuildContext context) { return AlertWithTwoActions( - alertTitle: - S.of(context).remove_node, - alertContent: S - .of(context) - .remove_node_message, - rightButtonText: - S.of(context).remove, - leftButtonText: - S.of(context).cancel, - actionRightButton: () => - Navigator.pop(context, true), - actionLeftButton: () => - Navigator.pop(context, false)); + alertTitle: S.of(context).remove_node, + alertContent: S.of(context).remove_node_message, + rightButtonText: S.of(context).remove, + leftButtonText: S.of(context).cancel, + actionRightButton: () => Navigator.pop(context, true), + actionLeftButton: () => Navigator.pop(context, false)); }) ?? false; @@ -163,11 +156,14 @@ class NodeCreateOrEditPage extends BasePage { } }, text: S.of(context).delete, - isDisabled: !nodeCreateOrEditViewModel.isReady || + isDisabled: editingNode == null || + !nodeCreateOrEditViewModel.isReady || (isSelected ?? false), color: Palette.red, - textColor: Colors.white), - )), + textColor: Colors.white, + ), + ), + ), Flexible( child: Container( padding: EdgeInsets.only(left: 8.0), diff --git a/lib/src/screens/restore/restore_from_backup_page.dart b/lib/src/screens/restore/restore_from_backup_page.dart index c3440fb06..f7fddac3f 100644 --- a/lib/src/screens/restore/restore_from_backup_page.dart +++ b/lib/src/screens/restore/restore_from_backup_page.dart @@ -4,7 +4,6 @@ import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/src/widgets/framework.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/view_model/restore_from_backup_view_model.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; @@ -31,10 +30,11 @@ class RestoreFromBackupPage extends BasePage { context: context, builder: (BuildContext context) { return AlertWithOneAction( - alertTitle: S.of(context).error, - alertContent: state.error, - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop()); + alertTitle: S.of(context).error, + alertContent: state.error, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop(), + ); }); }); } @@ -44,42 +44,97 @@ class RestoreFromBackupPage extends BasePage { child: ConstrainedBox( constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: Padding( - padding: EdgeInsets.only(bottom: 24, left: 24, right: 24), - child: Column(children: [ + padding: EdgeInsets.only(bottom: 24, left: 24, right: 24), + child: Column( + children: [ Expanded( child: Container( child: Center( - child: TextFormField( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextFormField( obscureText: true, enableSuggestions: false, autocorrect: false, - decoration: InputDecoration( - hintText: S.of(context).enter_backup_password), + decoration: + InputDecoration(hintText: S.of(context).enter_backup_password), keyboardType: TextInputType.visiblePassword, controller: textEditingController, - style: TextStyle(fontSize: 26, color: Colors.black))), + style: TextStyle(fontSize: 26, color: Colors.black), + ), + Observer( + builder: (_) { + if (restoreFromBackupViewModel.filePath.isNotEmpty) { + return Column( + children: [ + const SizedBox(height: 100), + Row( + children: [ + Text( + "File Name: ", + style: TextStyle( + fontSize: 18.0, + fontWeight: FontWeight.bold, + fontFamily: 'Lato', + color: titleColor(context), + ), + ), + Expanded( + child: Text( + restoreFromBackupViewModel.filePath.split("/").last, + style: TextStyle( + fontSize: 18.0, + fontWeight: FontWeight.bold, + fontFamily: 'Lato', + color: titleColor(context), + ), + ), + ), + ], + ), + ], + ); + } + + return const SizedBox(); + }, + ), + ], + ), + ), ), ), Container( - child: Row(children: [ - Expanded( - child: PrimaryButton( + child: Row( + children: [ + Expanded( + child: PrimaryButton( onPressed: () => presentFilePicker(), text: S.of(context).select_backup_file, color: Colors.grey, - textColor: Colors.white)), - SizedBox(width: 20), - Expanded(child: Observer(builder: (_) { - return LoadingPrimaryButton( - isLoading: - restoreFromBackupViewModel.state is IsExecutingState, - onPressed: () => onImportHandler(context), - text: S.of(context).import, - color: Theme.of(context).primaryColor, - textColor: Colors.white); - })) - ])), - ])), + textColor: Colors.white, + ), + ), + SizedBox(width: 20), + Expanded( + child: Observer( + builder: (_) { + return LoadingPrimaryButton( + isLoading: restoreFromBackupViewModel.state is IsExecutingState, + onPressed: () => onImportHandler(context), + text: S.of(context).import, + color: Theme.of(context).primaryColor, + textColor: Colors.white); + }, + ), + ), + ], + ), + ), + ], + ), + ), ), ); } @@ -87,7 +142,7 @@ class RestoreFromBackupPage extends BasePage { Future presentFilePicker() async { final result = await FilePicker.platform.pickFiles(); - if (result?.files?.isEmpty ?? true) { + if (result?.files.isEmpty ?? true) { return; } @@ -95,8 +150,7 @@ class RestoreFromBackupPage extends BasePage { } Future onImportHandler(BuildContext context) async { - if (textEditingController.text.isEmpty || - (restoreFromBackupViewModel.filePath.isEmpty ?? true)) { + if (textEditingController.text.isEmpty || (restoreFromBackupViewModel.filePath.isEmpty)) { await showPopUp( context: context, builder: (_) { diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart index e54c0da29..91ee9bd0b 100644 --- a/lib/src/screens/restore/restore_options_page.dart +++ b/lib/src/screens/restore/restore_options_page.dart @@ -21,7 +21,6 @@ class RestoreOptionsPage extends BasePage { @override String get title => S.current.restore_restore_wallet; - final bool isNewInstall; final imageSeedKeys = Image.asset('assets/images/restore_wallet_image.png'); final imageBackup = Image.asset('assets/images/backup.png'); @@ -38,8 +37,7 @@ class RestoreOptionsPage extends BasePage { child: Column( children: [ OptionTile( - onPressed: () => Navigator.pushNamed( - context, Routes.restoreWalletFromSeedKeys, + onPressed: () => Navigator.pushNamed(context, Routes.restoreWalletFromSeedKeys, arguments: isNewInstall), image: imageSeedKeys, title: S.of(context).restore_title_from_seed_keys, @@ -58,7 +56,7 @@ class RestoreOptionsPage extends BasePage { child: OptionTile( onPressed: () async { bool isCameraPermissionGranted = - await PermissionHandler.checkPermission(Permission.camera, context); + await PermissionHandler.checkPermission(Permission.camera, context); if (!isCameraPermissionGranted) return; bool isPinSet = false; if (isNewInstall) { @@ -73,7 +71,8 @@ class RestoreOptionsPage extends BasePage { final restoreWallet = await WalletRestoreFromQRCode.scanQRCodeForRestoring(context); - final restoreFromQRViewModel = getIt.get(param1: restoreWallet.type); + final restoreFromQRViewModel = + getIt.get(param1: restoreWallet.type); await restoreFromQRViewModel.create(restoreWallet: restoreWallet); if (restoreFromQRViewModel.state is FailureState) { diff --git a/lib/src/widgets/base_alert_dialog.dart b/lib/src/widgets/base_alert_dialog.dart index 757ee1862..02a1f6ad0 100644 --- a/lib/src/widgets/base_alert_dialog.dart +++ b/lib/src/widgets/base_alert_dialog.dart @@ -3,7 +3,6 @@ import 'dart:ui'; import 'package:cake_wallet/src/widgets/section_divider.dart'; import 'package:cake_wallet/themes/extensions/alert_theme.dart'; import 'package:flutter/material.dart'; -import 'package:cake_wallet/palette.dart'; class BaseAlertDialog extends StatelessWidget { String get titleText => ''; @@ -49,7 +48,7 @@ class BaseAlertDialog extends StatelessWidget { Widget actionButtons(BuildContext context) { return Container( - height: 52, + height: 60, child: Row( mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.stretch, diff --git a/lib/src/widgets/option_tile.dart b/lib/src/widgets/option_tile.dart index 6a2825003..8b46641fb 100644 --- a/lib/src/widgets/option_tile.dart +++ b/lib/src/widgets/option_tile.dart @@ -52,7 +52,7 @@ class OptionTile extends StatelessWidget { child: Text( description, style: TextStyle( - fontSize: 16, + fontSize: 14, fontWeight: FontWeight.normal, color: Theme.of(context).extension()!.descriptionColor, ), diff --git a/lib/utils/permission_handler.dart b/lib/utils/permission_handler.dart index 6b76f767a..6a6126df2 100644 --- a/lib/utils/permission_handler.dart +++ b/lib/utils/permission_handler.dart @@ -17,7 +17,9 @@ class PermissionHandler { var status = await permission.status; if (status.isDenied) { - status = await permission.request(); + try { + status = await permission.request(); + } catch (_) {} } if (status.isPermanentlyDenied || status.isDenied) { diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index c55241797..68d03b5f8 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -12,13 +12,12 @@ import devicelocale import flutter_secure_storage_macos import in_app_review import package_info +import package_info_plus import path_provider_foundation -import platform_device_id -import platform_device_id_macos import share_plus_macos import shared_preferences_foundation import url_launcher_macos -import wakelock_macos +import wakelock_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) @@ -28,11 +27,10 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin")) FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin")) + FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) - PlatformDeviceIdMacosPlugin.register(with: registry.registrar(forPlugin: "PlatformDeviceIdMacosPlugin")) - PlatformDeviceIdMacosPlugin.register(with: registry.registrar(forPlugin: "PlatformDeviceIdMacosPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) - WakelockMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockMacosPlugin")) + WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) } diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 573f8c671..f43d65400 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -60,16 +60,21 @@ dependencies: another_flushbar: ^1.12.29 archive: ^3.3.0 cryptography: ^2.0.5 - file_picker: ^5.2.5 + file_picker: + git: + url: https://github.com/cake-tech/flutter_file_picker.git + ref: master unorm_dart: ^0.2.0 # check unorm_dart for usage and for replace permission_handler: ^10.0.0 - device_display_brightness: ^0.0.6 + device_display_brightness: + git: + url: https://github.com/cake-tech/device_display_brightness.git + ref: master workmanager: ^0.5.1 - platform_device_id: ^1.0.1 - wakelock: ^0.6.2 + wakelock_plus: ^1.1.3 flutter_mailer: ^2.0.2 - device_info_plus: 8.1.0 + device_info_plus: ^9.1.0 base32: 2.1.3 in_app_review: ^2.0.6 cake_backup: diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index cae478d7d..9f8a269d4 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -722,8 +722,8 @@ "awaitDAppProcessing": "Veuillez attendre que l'application décentralisée (dApp) termine le traitement.", "copyWalletConnectLink": "Copiez le lien WalletConnect depuis l'application décentralisée (dApp) et collez-le ici", "enterWalletConnectURI": "Saisissez l'URI de WalletConnect.", - "seed_key": "Clé de graines", - "enter_seed_phrase": "Entrez votre phrase de semence", + "seed_key": "Clé secrète (seed key)", + "enter_seed_phrase": "Entrez votre phrase secrète (seed)", "change_rep_successful": "Représentant changé avec succès", "add_contact": "Ajouter le contact", "exchange_provider_unsupported": "${providerName} n'est plus pris en charge !", From ab83f5b67fe085c993abb7738e7d692364ebb5e7 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Sat, 18 Nov 2023 15:43:15 +0200 Subject: [PATCH 042/241] Cw 519 tor connection (#1158) * initial draft for tor feature * Configure nodes to use Tor proxy if enabled * Add socks proxy upon connecting to tor fix disconnect button * Try tor with github actions * accept defaults for rust installation * Merge main Change Tor tile name --- .github/workflows/pr_test_build.yml | 2 + cw_bitcoin/pubspec.lock | 43 ++- .../.plugin_symlinks/path_provider_linux | 2 +- .../linux/flutter/generated_plugins.cmake | 1 + cw_core/lib/node.dart | 23 +- cw_core/pubspec.lock | 43 ++- cw_core/pubspec.yaml | 5 + cw_haven/pubspec.lock | 43 ++- cw_monero/example/pubspec.lock | 43 ++- cw_monero/pubspec.lock | 43 ++- cw_nano/pubspec.lock | 41 ++- ios/Podfile.lock | 6 + lib/di.dart | 2 + lib/router.dart | 4 + lib/routes.dart | 1 + .../settings/connection_sync_page.dart | 7 +- lib/src/screens/settings/tor_page.dart | 267 ++++++++++++++++++ pubspec_base.yaml | 7 +- res/values/strings_ar.arb | 3 +- res/values/strings_bg.arb | 3 +- res/values/strings_cs.arb | 3 +- res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 3 +- res/values/strings_es.arb | 3 +- res/values/strings_fr.arb | 3 +- res/values/strings_ha.arb | 3 +- res/values/strings_hi.arb | 3 +- res/values/strings_hr.arb | 3 +- res/values/strings_id.arb | 3 +- res/values/strings_it.arb | 3 +- res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 3 +- res/values/strings_nl.arb | 3 +- res/values/strings_pl.arb | 3 +- res/values/strings_pt.arb | 3 +- res/values/strings_ru.arb | 3 +- res/values/strings_th.arb | 3 +- res/values/strings_tl.arb | 3 +- res/values/strings_tr.arb | 3 +- res/values/strings_uk.arb | 3 +- res/values/strings_ur.arb | 3 +- res/values/strings_yo.arb | 3 +- res/values/strings_zh.arb | 3 +- 44 files changed, 548 insertions(+), 113 deletions(-) create mode 100644 lib/src/screens/settings/tor_page.dart diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 3c6b132bd..d74b85ce4 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -38,6 +38,8 @@ jobs: sudo mkdir -p /opt/android sudo chown $USER /opt/android cd /opt/android + -y curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + cargo install cargo-ndk git clone https://github.com/cake-tech/cake_wallet.git --branch $GITHUB_HEAD_REF cd cake_wallet/scripts/android/ ./install_ndk.sh diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index eb75227b6..43391881f 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -481,50 +481,50 @@ packages: dependency: "direct main" description: name: path_provider - sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.0.12" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.2.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.2.1" platform: dependency: transitive description: @@ -610,6 +610,14 @@ packages: description: flutter source: sdk version: "0.0.99" + socks5_proxy: + dependency: transitive + description: + name: socks5_proxy + sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a" + url: "https://pub.dev" + source: hosted + version: "1.0.4" source_gen: dependency: transitive description: @@ -690,6 +698,15 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + tor: + dependency: transitive + description: + path: "." + ref: main + resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" + url: "https://github.com/cake-tech/tor.git" + source: git + version: "0.0.1" typed_data: dependency: transitive description: @@ -756,4 +773,4 @@ packages: version: "3.1.1" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.0.0" + flutter: ">=3.7.0" diff --git a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux index 0ed52b295..17553f81e 120000 --- a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux +++ b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux @@ -1 +1 @@ -/Users/blazebrain/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ \ No newline at end of file +/Users/omarhatem/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ \ No newline at end of file diff --git a/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake b/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake index 2e1de87a7..3d57782b2 100644 --- a/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake +++ b/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + tor ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 5f0951447..3f6056ae1 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -6,6 +6,7 @@ import 'package:hive/hive.dart'; import 'package:cw_core/hive_type_ids.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:http/io_client.dart' as ioc; +import 'package:tor/tor.dart'; part 'node.g.dart'; @@ -129,9 +130,7 @@ class Node extends HiveObject with Keyable { try { switch (type) { case WalletType.monero: - return useSocksProxy - ? requestNodeWithProxy(socksProxyAddress ?? '') - : requestMoneroNode(); + return requestMoneroNode(); case WalletType.bitcoin: return requestElectrumServer(); case WalletType.litecoin: @@ -154,6 +153,9 @@ class Node extends HiveObject with Keyable { } Future requestMoneroNode() async { + if (uri.toString().contains(".onion") || useSocksProxy) { + return await requestNodeWithProxy(); + } final path = '/json_rpc'; final rpcUri = isSSL ? Uri.https(uri.authority, path) : Uri.http(uri.authority, path); final realm = 'monero-rpc'; @@ -205,11 +207,20 @@ class Node extends HiveObject with Keyable { } } - Future requestNodeWithProxy(String proxy) async { - if (proxy.isEmpty || !proxy.contains(':')) { + Future requestNodeWithProxy() async { + if ((socksProxyAddress == null || + socksProxyAddress!.isEmpty || + !socksProxyAddress!.contains(':')) && + !Tor.instance.enabled) { return false; } - final proxyAddress = proxy.split(':')[0]; + + String? proxy = socksProxyAddress; + + if ((proxy?.isEmpty ?? true) && Tor.instance.enabled) { + proxy = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}"; + } + final proxyAddress = proxy!.split(':')[0]; final proxyPort = int.parse(proxy.split(':')[1]); try { final socket = await Socket.connect(proxyAddress, proxyPort, timeout: Duration(seconds: 5)); diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock index e399526fd..058f33ba4 100644 --- a/cw_core/pubspec.lock +++ b/cw_core/pubspec.lock @@ -407,50 +407,50 @@ packages: dependency: "direct main" description: name: path_provider - sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.0.12" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.2.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.2.1" platform: dependency: transitive description: @@ -528,6 +528,14 @@ packages: description: flutter source: sdk version: "0.0.99" + socks5_proxy: + dependency: "direct main" + description: + name: socks5_proxy + sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a" + url: "https://pub.dev" + source: hosted + version: "1.0.4" source_gen: dependency: transitive description: @@ -608,6 +616,15 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + tor: + dependency: "direct main" + description: + path: "." + ref: main + resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" + url: "https://github.com/cake-tech/tor.git" + source: git + version: "0.0.1" typed_data: dependency: transitive description: @@ -666,4 +683,4 @@ packages: version: "3.1.1" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.0.0" + flutter: ">=3.7.0" diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml index 9dcb7eaba..3763a7318 100644 --- a/cw_core/pubspec.yaml +++ b/cw_core/pubspec.yaml @@ -19,6 +19,11 @@ dependencies: flutter_mobx: ^2.0.6+1 intl: ^0.18.0 encrypt: ^5.0.1 + socks5_proxy: ^1.0.4 + tor: + git: + url: https://github.com/cake-tech/tor.git + ref: main dev_dependencies: flutter_test: diff --git a/cw_haven/pubspec.lock b/cw_haven/pubspec.lock index a63aa3237..525e8e5fa 100644 --- a/cw_haven/pubspec.lock +++ b/cw_haven/pubspec.lock @@ -414,50 +414,50 @@ packages: dependency: "direct main" description: name: path_provider - sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.0.12" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.2.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.1" platform: dependency: transitive description: @@ -535,6 +535,14 @@ packages: description: flutter source: sdk version: "0.0.99" + socks5_proxy: + dependency: transitive + description: + name: socks5_proxy + sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a" + url: "https://pub.dev" + source: hosted + version: "1.0.4" source_gen: dependency: transitive description: @@ -615,6 +623,15 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + tor: + dependency: transitive + description: + path: "." + ref: main + resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" + url: "https://github.com/cake-tech/tor.git" + source: git + version: "0.0.1" typed_data: dependency: transitive description: @@ -673,4 +690,4 @@ packages: version: "3.1.1" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.0.0" + flutter: ">=3.7.0" diff --git a/cw_monero/example/pubspec.lock b/cw_monero/example/pubspec.lock index 1aae6b0c9..661341e96 100644 --- a/cw_monero/example/pubspec.lock +++ b/cw_monero/example/pubspec.lock @@ -237,50 +237,50 @@ packages: dependency: transitive description: name: path_provider - sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.0.12" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.2.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.1" platform: dependency: transitive description: @@ -318,6 +318,14 @@ packages: description: flutter source: sdk version: "0.0.99" + socks5_proxy: + dependency: transitive + description: + name: socks5_proxy + sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a" + url: "https://pub.dev" + source: hosted + version: "1.0.4" source_span: dependency: transitive description: @@ -366,6 +374,15 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.1" + tor: + dependency: transitive + description: + path: "." + ref: main + resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" + url: "https://github.com/cake-tech/tor.git" + source: git + version: "0.0.1" typed_data: dependency: transitive description: @@ -400,4 +417,4 @@ packages: version: "0.2.0+3" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.0.0" + flutter: ">=3.7.0" diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index 37e08e7ca..dc0f9aeed 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -414,50 +414,50 @@ packages: dependency: "direct main" description: name: path_provider - sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.0.12" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.2.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.1" platform: dependency: transitive description: @@ -535,6 +535,14 @@ packages: description: flutter source: sdk version: "0.0.99" + socks5_proxy: + dependency: transitive + description: + name: socks5_proxy + sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a" + url: "https://pub.dev" + source: hosted + version: "1.0.4" source_gen: dependency: transitive description: @@ -615,6 +623,15 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + tor: + dependency: transitive + description: + path: "." + ref: main + resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" + url: "https://github.com/cake-tech/tor.git" + source: git + version: "0.0.1" typed_data: dependency: transitive description: @@ -673,4 +690,4 @@ packages: version: "3.1.1" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.0.0" + flutter: ">=3.7.0" diff --git a/cw_nano/pubspec.lock b/cw_nano/pubspec.lock index d28558422..4a5496fa6 100644 --- a/cw_nano/pubspec.lock +++ b/cw_nano/pubspec.lock @@ -491,50 +491,50 @@ packages: dependency: transitive description: name: path_provider - sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2" + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86" + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.0.27" + version: "2.2.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "916731ccbdce44d545414dd9961f26ba5fbaa74bcbb55237d8e65a623a8c7297" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.2.4" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.11" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.0.6" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96" + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.2.1" pinenacl: dependency: transitive description: @@ -676,6 +676,14 @@ packages: description: flutter source: sdk version: "0.0.99" + socks5_proxy: + dependency: transitive + description: + name: socks5_proxy + sha256: "1d21b5606169654bbf4cfb904e8e6ed897e9f763358709f87310c757096d909a" + url: "https://pub.dev" + source: hosted + version: "1.0.4" source_gen: dependency: transitive description: @@ -756,6 +764,15 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + tor: + dependency: transitive + description: + path: "." + ref: main + resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" + url: "https://github.com/cake-tech/tor.git" + source: git + version: "0.0.1" typed_data: dependency: transitive description: diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 970ee3f80..cc60cad08 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -147,6 +147,8 @@ PODS: - SwiftProtobuf (1.22.0) - SwiftyGif (5.4.4) - Toast (4.0.0) + - tor (0.0.1): + - Flutter - uni_links (0.0.1): - Flutter - UnstoppableDomainsResolution (4.0.0): @@ -185,6 +187,7 @@ DEPENDENCIES: - sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + - tor (from `.symlinks/plugins/tor/ios`) - uni_links (from `.symlinks/plugins/uni_links/ios`) - UnstoppableDomainsResolution (~> 4.0.0) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) @@ -255,6 +258,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/share_plus/ios" shared_preferences_foundation: :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + tor: + :path: ".symlinks/plugins/tor/ios" uni_links: :path: ".symlinks/plugins/uni_links/ios" url_launcher_ios: @@ -300,6 +305,7 @@ SPEC CHECKSUMS: SwiftProtobuf: 40bd808372cb8706108f22d28f8ab4a6b9bc6989 SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 + tor: 662a9f5b980b5c86decb8ba611de9bcd4c8286eb uni_links: d97da20c7701486ba192624d99bffaaffcfc298a UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841 url_launcher_ios: 68d46cc9766d0c41dbdc884310529557e3cd7a86 diff --git a/lib/di.dart b/lib/di.dart index 94f5dbb63..d6a43030a 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -46,6 +46,7 @@ import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page. import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart'; import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart'; +import 'package:cake_wallet/src/screens/settings/tor_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; @@ -1175,6 +1176,7 @@ Future setup({ getIt.registerFactory( () => WalletConnectConnectionsView(web3walletService: getIt.get())); + getIt.registerFactory(() => TorPage(getIt.get())); _isSetupFinished = true; } diff --git a/lib/router.dart b/lib/router.dart index 8174e0be8..75f491dfc 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -43,6 +43,7 @@ import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart'; import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart'; +import 'package:cake_wallet/src/screens/settings/tor_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; @@ -615,6 +616,9 @@ Route createRoute(RouteSettings settings) { web3walletService: getIt.get(), launchUri: settings.arguments as Uri?, )); + case Routes.torPage: + return MaterialPageRoute(builder: (_) => getIt.get()); + default: return MaterialPageRoute( builder: (_) => Scaffold( diff --git a/lib/routes.dart b/lib/routes.dart index 8b521247a..4c1a917ab 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -101,4 +101,5 @@ class Routes { static const manageNodes = '/manage_nodes'; static const managePowNodes = '/manage_pow_nodes'; static const walletConnectConnectionsListing = '/wallet-connect-connections-listing'; + static const torPage = '/tor_page'; } diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart index e4763653b..7d1289e78 100644 --- a/lib/src/screens/settings/connection_sync_page.dart +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -3,7 +3,6 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arro import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/wallet_connect_button.dart'; -import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; @@ -90,7 +89,11 @@ class ConnectionSyncPage extends BasePage { onTap: () => Navigator.of(context).pushNamed(Routes.walletConnectConnectionsListing), ), const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), - ] + ], + SettingsCellWithArrow( + title: S.current.tor_connection, + handler: (context) => Navigator.of(context).pushNamed(Routes.torPage), + ), ], ), ); diff --git a/lib/src/screens/settings/tor_page.dart b/lib/src/screens/settings/tor_page.dart new file mode 100644 index 000000000..d1d5c7e83 --- /dev/null +++ b/lib/src/screens/settings/tor_page.dart @@ -0,0 +1,267 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/store/app_store.dart'; +import 'package:flutter/material.dart'; +import 'package:tor/tor.dart'; + +class TorPage extends BasePage { + final AppStore appStore; + + TorPage(this.appStore); + + @override + Widget body(BuildContext context) { + return TorPageBody(appStore); + } +} + +class TorPageBody extends StatefulWidget { + final AppStore appStore; + + const TorPageBody(this.appStore, {Key? key}) : super(key: key); + + @override + State createState() => _TorPageBodyState(); +} + +class _TorPageBodyState extends State { + bool torEnabled = false; + bool connecting = false; + + // Set the default text for the host input field. + final hostController = TextEditingController(text: 'https://icanhazip.com/'); + + // https://check.torproject.org is another good option. + + Future startTor() async { + setState(() { + connecting = true; // Update flag + }); + + await Tor.init(); + + // Start the proxy + await Tor.instance.start(); + + // Toggle started flag. + setState(() { + torEnabled = Tor.instance.enabled; // Update flag + connecting = false; + }); + + final node = widget.appStore.settingsStore.getCurrentNode(widget.appStore.wallet!.type); + if (node.socksProxyAddress?.isEmpty ?? true) { + node.socksProxyAddress = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}"; + } + widget.appStore.wallet!.connectToNode(node: node); + + print('Done awaiting; tor should be running'); + } + + Future endTor() async { + // Start the proxy + Tor.instance.disable(); + + // Toggle started flag. + setState(() { + torEnabled = Tor.instance.enabled; // Update flag + }); + + print('Done awaiting; tor should be stopped'); + } + + @override + void initState() { + super.initState(); + + torEnabled = Tor.instance.enabled; + } + + @override + void dispose() { + // Clean up the controller when the widget is disposed. + hostController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Container( + padding: const EdgeInsets.all(10), + child: connecting + ? ConnectingScreen() + : torEnabled + ? DisconnectScreen(disconnect: endTor) + : ConnectScreen(connect: startTor), + ), + ); + } +} + +class ConnectScreen extends StatelessWidget { + final Function() connect; + + const ConnectScreen({super.key, required this.connect}); + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 200, + height: 200, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.blue, + ), + child: Icon( + Icons.lock, + color: Colors.white, + size: 100, + ), + ), + SizedBox(height: 20), + Text( + 'Connect to Tor', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 10), + Text( + 'Your connection to the Tor network ensures privacy and security.', + style: TextStyle( + fontSize: 16, + color: Colors.grey, + ), + textAlign: TextAlign.center, + ), + SizedBox(height: 30), + ElevatedButton( + onPressed: connect, + style: ElevatedButton.styleFrom( + primary: Colors.blue, + padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(30), + ), + ), + child: Text( + 'Connect', + style: TextStyle( + fontSize: 18, + color: Colors.white, + ), + ), + ), + ], + ), + ); + } +} + +class DisconnectScreen extends StatelessWidget { + final Function() disconnect; + + const DisconnectScreen({super.key, required this.disconnect}); + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 200, + height: 200, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.green, + ), + child: Icon( + Icons.check, + color: Colors.white, + size: 100, + ), + ), + SizedBox(height: 20), + Text( + 'Connected to Tor', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 10), + Text( + 'You are currently connected to the Tor network.', + style: TextStyle( + fontSize: 16, + color: Colors.grey, + ), + textAlign: TextAlign.center, + ), + SizedBox(height: 30), + ElevatedButton( + onPressed: disconnect, + style: ElevatedButton.styleFrom( + primary: Colors.red, + padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(30), + ), + ), + child: Text( + 'Disconnect', + style: TextStyle( + fontSize: 18, + color: Colors.white, + ), + ), + ), + ], + ), + ); + } +} + +class ConnectingScreen extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 200, + height: 200, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.yellow, + ), + child: Icon( + Icons.hourglass_bottom, + color: Colors.white, + size: 100, + ), + ), + SizedBox(height: 20), + Text( + 'Connecting...', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 10), + ], + ), + ); + } +} diff --git a/pubspec_base.yaml b/pubspec_base.yaml index f43d65400..c6101d28c 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -83,7 +83,7 @@ dependencies: ref: main version: 1.0.0 flutter_plugin_android_lifecycle: 2.0.9 - path_provider_android: 2.0.24 + path_provider_android: ^2.2.1 shared_preferences_android: 2.0.17 url_launcher_android: 6.0.24 sensitive_clipboard: ^1.0.0 @@ -98,6 +98,11 @@ dependencies: url: https://github.com/cake-tech/bitcoin_flutter.git ref: cake-update-v3 fluttertoast: 8.1.4 + tor: + git: + url: https://github.com/cake-tech/tor.git + ref: main + socks5_proxy: ^1.0.4 dev_dependencies: flutter_test: diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index a5298c343..84a0a72f5 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -730,5 +730,6 @@ "seed_phrase_length": " ﺭﻭﺬﺒﻟﺍ ﺓﺭﺎﺒﻌﻟﺍ ﻝﻮﻃ", "unavailable_balance": " ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ", "unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ", - "unspent_change": "يتغير" + "unspent_change": "يتغير", + "tor_connection": " ﺭﻮﺗ ﻝﺎﺼﺗﺍ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 3b085cd59..b1851156c 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -726,5 +726,6 @@ "seed_phrase_length": "Дължина на началната фраза", "unavailable_balance": "Неналично салдо", "unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.", - "unspent_change": "Промяна" + "unspent_change": "Промяна", + "tor_connection": "Tor връзка" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index f6d024957..2e59f5fc5 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -726,5 +726,6 @@ "seed_phrase_length": "Délka fráze semene", "unavailable_balance": "Nedostupný zůstatek", "unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.", - "unspent_change": "Změna" + "unspent_change": "Změna", + "tor_connection": "Připojení Tor" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 6519f0ef6..7868553be 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "Länge der Seed-Phrase", "unavailable_balance": "Nicht verfügbares Guthaben", "unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.", - "unspent_change": "Wechselgeld" + "unspent_change": "Wechselgeld", + "tor_connection": "Tor-Verbindung" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 2c1d00eb6..c3cd256d9 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -735,5 +735,6 @@ "seed_phrase_length": "Seed phrase length", "unavailable_balance": "Unavailable balance", "unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.", - "unspent_change": "Change" + "unspent_change": "Change", + "tor_connection": "Tor connection" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 3629a6d37..4e624a9b4 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "Longitud de la frase inicial", "unavailable_balance": "Saldo no disponible", "unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.", - "unspent_change": "Cambiar" + "unspent_change": "Cambiar", + "tor_connection": "conexión tor" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 9f8a269d4..d4d414029 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -734,5 +734,6 @@ "unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.", "camera_permission_is_required": "L'autorisation d'accès à la caméra est requise.\nVeuillez l'activer depuis les paramètres de l'application.", "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", - "unspent_change": "Changement" + "unspent_change": "Changement", + "tor_connection": "Connexion Tor" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 84c3b4b74..0e2589b6a 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -712,5 +712,6 @@ "seed_phrase_length": "Tsawon jimlar iri", "unavailable_balance": "Ma'aunin da ba ya samuwa", "unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.", - "unspent_change": "Canza" + "unspent_change": "Canza", + "tor_connection": "Tor haɗin gwiwa" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index af3b888cb..19467af09 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "बीज वाक्यांश की लंबाई", "unavailable_balance": "अनुपलब्ध शेष", "unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।", - "unspent_change": "परिवर्तन" + "unspent_change": "परिवर्तन", + "tor_connection": "टोर कनेक्शन" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 3c56b8552..30eea10dc 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -732,5 +732,6 @@ "seed_phrase_length": "Duljina početne fraze", "unavailable_balance": "Nedostupno stanje", "unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.", - "unspent_change": "Promijeniti" + "unspent_change": "Promijeniti", + "tor_connection": "Tor veza" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index b3d22780a..c10feffbc 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -722,5 +722,6 @@ "seed_phrase_length": "Panjang frase benih", "unavailable_balance": "Saldo tidak tersedia", "unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.", - "unspent_change": "Mengubah" + "unspent_change": "Mengubah", + "tor_connection": "koneksi Tor" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 8fc157f27..a13930666 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "Lunghezza della frase seed", "unavailable_balance": "Saldo non disponibile", "unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.", - "unspent_change": "Modifica" + "unspent_change": "Modifica", + "tor_connection": "Connessione Tor" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 06d8efd37..3e61dbd9d 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "シードフレーズの長さ", "unavailable_balance": "利用できない残高", "unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。", - "unspent_change": "変化" + "unspent_change": "変化", + "tor_connection": "Tor接続" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 6830b1183..de09c65d1 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -732,5 +732,6 @@ "seed_phrase_length": "시드 문구 길이", "unavailable_balance": "사용할 수 없는 잔액", "unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.", - "unspent_change": "변화" + "unspent_change": "변화", + "tor_connection": "토르 연결" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index ff8f6683b..1853c0eff 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -732,5 +732,6 @@ "seed_phrase_length": "မျိုးစေ့စာပိုဒ်တိုအရှည်", "unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။", "unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။", - "unspent_change": "ပေြာင်းလဲခြင်း" + "unspent_change": "ပေြာင်းလဲခြင်း", + "tor_connection": "Tor ချိတ်ဆက်မှု" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 753e28cd5..a497c20ab 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "Lengte van de zaadzin", "unavailable_balance": "Onbeschikbaar saldo", "unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.", - "unspent_change": "Wijziging" + "unspent_change": "Wijziging", + "tor_connection": "Tor-verbinding" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 1900ca590..dc69468bd 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "Długość frazy początkowej", "unavailable_balance": "Niedostępne saldo", "unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.", - "unspent_change": "Zmiana" + "unspent_change": "Zmiana", + "tor_connection": "Połączenie Torem" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 86c7a6b0d..c6d22ae23 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -733,5 +733,6 @@ "seed_phrase_length": "Comprimento da frase-semente", "unavailable_balance": "Saldo indisponível", "unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.", - "unspent_change": "Mudar" + "unspent_change": "Mudar", + "tor_connection": "Conexão Tor" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index a37b0908b..50bef718d 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "Длина исходной фразы", "unavailable_balance": "Недоступный баланс", "unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.", - "unspent_change": "Изменять" + "unspent_change": "Изменять", + "tor_connection": "Тор соединение" } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index fa36c04bb..95a1cd406 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -732,5 +732,6 @@ "seed_phrase_length": "ความยาววลีของเมล็ด", "unavailable_balance": "ยอดคงเหลือไม่พร้อมใช้งาน", "unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง", - "unspent_change": "เปลี่ยน" + "unspent_change": "เปลี่ยน", + "tor_connection": "การเชื่อมต่อทอร์" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index b8bf168ce..960432a1b 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -729,5 +729,6 @@ "seed_phrase_length": "Haba ng parirala ng binhi", "unavailable_balance": "Hindi available na balanse", "unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.", - "unspent_change": "Baguhin" + "unspent_change": "Baguhin", + "tor_connection": "Koneksyon ng Tor" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index f7962b526..1b7982504 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -732,5 +732,6 @@ "seed_phrase_length": "Çekirdek cümle uzunluğu", "unavailable_balance": "Kullanılamayan bakiye", "unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.", - "unspent_change": "Değiştirmek" + "unspent_change": "Değiştirmek", + "tor_connection": "Tor bağlantısı" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 0e4cc3ecb..849542e6f 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -734,5 +734,6 @@ "seed_phrase_length": "Довжина початкової фрази", "unavailable_balance": "Недоступний баланс", "unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.", - "unspent_change": "Зміна" + "unspent_change": "Зміна", + "tor_connection": "Підключення Tor" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index cd05010d7..0b7e4c0a7 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -726,5 +726,6 @@ "seed_phrase_length": " ﯽﺋﺎﺒﻤﻟ ﯽﮐ ﮯﻠﻤﺟ ﮯﮐ ﺞﯿﺑ", "unavailable_balance": " ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ", "unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ", - "unspent_change": "تبدیل کریں" + "unspent_change": "تبدیل کریں", + "tor_connection": " ﻦﺸﮑﻨﮐ ﺭﻮﭨ" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index fc632f8a8..57962b38e 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -728,5 +728,6 @@ "seed_phrase_length": "Gigun gbolohun irugbin", "unavailable_balance": "Iwontunwonsi ti ko si", "unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.", - "unspent_change": "Yipada" + "unspent_change": "Yipada", + "tor_connection": "Tor asopọ" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index e57df96d9..0862f20e2 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -733,5 +733,6 @@ "seed_phrase_length": "种子短语长度", "unavailable_balance": "不可用余额", "unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。", - "unspent_change": "改变" + "unspent_change": "改变", + "tor_connection": "Tor连接" } From 56619b854686de1f5e63437554fba866d81060eb Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Mon, 20 Nov 2023 19:40:47 +0200 Subject: [PATCH 043/241] v4.10.5 and v1.7.5 (#1183) * Update app version and release notes * Add Tor to this release * Minor readability enhancement [skip ci] * Temporarily disable Tor feature --- assets/text/Monerocom_Release_Notes.txt | 7 +- assets/text/Release_Notes.txt | 8 +- cw_core/lib/node.dart | 7 +- ios/Podfile.lock | 32 ++-- .../settings/connection_sync_page.dart | 10 +- lib/src/screens/settings/privacy_page.dart | 138 +++++++++--------- lib/utils/feature_flag.dart | 1 + macos/Podfile.lock | 28 ++-- scripts/android/app_env.sh | 8 +- scripts/ios/app_env.sh | 8 +- scripts/macos/app_env.sh | 4 +- 11 files changed, 124 insertions(+), 127 deletions(-) diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 9c09278a5..caac086d1 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,4 +1,7 @@ -UI enhancements +Coin control fixes and enhancements +In-app Tor connection +Accessibility enhancements Privacy settings enhancements -Tablet/iPad fixes +UI enhancements +Backup flow fixes Bug fixes \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 8b8ab36a1..caac086d1 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,5 +1,7 @@ -WalletConnect enhancements -UI enhancements +Coin control fixes and enhancements +In-app Tor connection +Accessibility enhancements Privacy settings enhancements -Tablet/iPad fixes +UI enhancements +Backup flow fixes Bug fixes \ No newline at end of file diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 3f6056ae1..484325f91 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -93,6 +93,8 @@ class Node extends HiveObject with Keyable { } } + bool get isValidProxyAddress => socksProxyAddress?.contains(':') ?? false; + @override bool operator ==(other) => other is Node && @@ -208,10 +210,7 @@ class Node extends HiveObject with Keyable { } Future requestNodeWithProxy() async { - if ((socksProxyAddress == null || - socksProxyAddress!.isEmpty || - !socksProxyAddress!.contains(':')) && - !Tor.instance.enabled) { + if (!isValidProxyAddress && !Tor.instance.enabled) { return false; } diff --git a/ios/Podfile.lock b/ios/Podfile.lock index cc60cad08..775419d18 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -63,8 +63,6 @@ PODS: - Flutter - device_display_brightness (0.0.1): - Flutter - - device_info (0.0.1): - - Flutter - device_info_plus (0.0.1): - Flutter - devicelocale (0.0.1): @@ -126,13 +124,13 @@ PODS: - OrderedSet (5.0.0) - package_info (0.0.1): - Flutter + - package_info_plus (0.4.5): + - Flutter - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS - permission_handler_apple (9.1.1): - Flutter - - platform_device_id (0.0.1): - - Flutter - ReachabilitySwift (5.0.0) - SDWebImage (5.16.0): - SDWebImage/Core (= 5.16.0) @@ -156,7 +154,7 @@ PODS: - CryptoSwift - url_launcher_ios (0.0.1): - Flutter - - wakelock (0.0.1): + - wakelock_plus (0.0.1): - Flutter - workmanager (0.0.1): - Flutter @@ -169,7 +167,6 @@ DEPENDENCIES: - cw_monero (from `.symlinks/plugins/cw_monero/ios`) - cw_shared_external (from `.symlinks/plugins/cw_shared_external/ios`) - device_display_brightness (from `.symlinks/plugins/device_display_brightness/ios`) - - device_info (from `.symlinks/plugins/device_info/ios`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - devicelocale (from `.symlinks/plugins/devicelocale/ios`) - file_picker (from `.symlinks/plugins/file_picker/ios`) @@ -181,9 +178,9 @@ DEPENDENCIES: - in_app_review (from `.symlinks/plugins/in_app_review/ios`) - local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`) - package_info (from `.symlinks/plugins/package_info/ios`) + - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - - platform_device_id (from `.symlinks/plugins/platform_device_id/ios`) - sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) @@ -191,7 +188,7 @@ DEPENDENCIES: - uni_links (from `.symlinks/plugins/uni_links/ios`) - UnstoppableDomainsResolution (~> 4.0.0) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - - wakelock (from `.symlinks/plugins/wakelock/ios`) + - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`) - workmanager (from `.symlinks/plugins/workmanager/ios`) SPEC REPOS: @@ -222,8 +219,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/cw_shared_external/ios" device_display_brightness: :path: ".symlinks/plugins/device_display_brightness/ios" - device_info: - :path: ".symlinks/plugins/device_info/ios" device_info_plus: :path: ".symlinks/plugins/device_info_plus/ios" devicelocale: @@ -246,12 +241,12 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/local_auth_ios/ios" package_info: :path: ".symlinks/plugins/package_info/ios" + package_info_plus: + :path: ".symlinks/plugins/package_info_plus/ios" path_provider_foundation: :path: ".symlinks/plugins/path_provider_foundation/darwin" permission_handler_apple: :path: ".symlinks/plugins/permission_handler_apple/ios" - platform_device_id: - :path: ".symlinks/plugins/platform_device_id/ios" sensitive_clipboard: :path: ".symlinks/plugins/sensitive_clipboard/ios" share_plus: @@ -264,8 +259,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/uni_links/ios" url_launcher_ios: :path: ".symlinks/plugins/url_launcher_ios/ios" - wakelock: - :path: ".symlinks/plugins/wakelock/ios" + wakelock_plus: + :path: ".symlinks/plugins/wakelock_plus/ios" workmanager: :path: ".symlinks/plugins/workmanager/ios" @@ -278,12 +273,11 @@ SPEC CHECKSUMS: cw_monero: 4cf3b96f2da8e95e2ef7d6703dd4d2c509127b7d cw_shared_external: 2972d872b8917603478117c9957dfca611845a92 device_display_brightness: 1510e72c567a1f6ce6ffe393dcd9afd1426034f7 - device_info: d7d233b645a32c40dfdc212de5cf646ca482f175 - device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed + device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 devicelocale: b22617f40038496deffba44747101255cee005b0 DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 - file_picker: ce3938a0df3cc1ef404671531facef740d03f920 + file_picker: 15fd9539e4eb735dc54bae8c0534a7a9511a03de Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83 @@ -294,9 +288,9 @@ SPEC CHECKSUMS: MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 + package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 - platform_device_id: 81b3e2993881f87d0c82ef151dc274df4869aef5 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 SDWebImage: 2aea163b50bfcb569a2726b6a754c54a4506fcf6 sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986 @@ -309,7 +303,7 @@ SPEC CHECKSUMS: uni_links: d97da20c7701486ba192624d99bffaaffcfc298a UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841 url_launcher_ios: 68d46cc9766d0c41dbdc884310529557e3cd7a86 - wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f + wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47 workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6 PODFILE CHECKSUM: 09df1114e7c360f55770d35a79356bf5446e0100 diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart index 7d1289e78..50881dd57 100644 --- a/lib/src/screens/settings/connection_sync_page.dart +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -4,6 +4,7 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.da import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/wallet_connect_button.dart'; import 'package:cake_wallet/utils/device_info.dart'; +import 'package:cake_wallet/utils/feature_flag.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/settings/sync_mode.dart'; @@ -90,10 +91,11 @@ class ConnectionSyncPage extends BasePage { ), const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), ], - SettingsCellWithArrow( - title: S.current.tor_connection, - handler: (context) => Navigator.of(context).pushNamed(Routes.torPage), - ), + if (FeatureFlag.isInAppTorEnabled) + SettingsCellWithArrow( + title: S.current.tor_connection, + handler: (context) => Navigator.of(context).pushNamed(Routes.torPage), + ), ], ), ); diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index 7a8671224..b1927648a 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -22,81 +22,83 @@ class PrivacyPage extends BasePage { @override Widget body(BuildContext context) { - return Container( - padding: EdgeInsets.only(top: 10), - child: Observer(builder: (_) { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - SettingsChoicesCell( - ChoicesListItem( - title: S.current.fiat_api, - items: FiatApiMode.all, - selectedItem: _privacySettingsViewModel.fiatApiMode, - onItemSelected: (FiatApiMode fiatApiMode) => - _privacySettingsViewModel.setFiatMode(fiatApiMode), + return SingleChildScrollView( + child: Container( + padding: EdgeInsets.only(top: 10), + child: Observer(builder: (_) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SettingsChoicesCell( + ChoicesListItem( + title: S.current.fiat_api, + items: FiatApiMode.all, + selectedItem: _privacySettingsViewModel.fiatApiMode, + onItemSelected: (FiatApiMode fiatApiMode) => + _privacySettingsViewModel.setFiatMode(fiatApiMode), + ), ), - ), - SettingsChoicesCell( - ChoicesListItem( - title: S.current.exchange, - items: ExchangeApiMode.all, - selectedItem: _privacySettingsViewModel.exchangeStatus, - onItemSelected: (ExchangeApiMode mode) => - _privacySettingsViewModel.setExchangeApiMode(mode), + SettingsChoicesCell( + ChoicesListItem( + title: S.current.exchange, + items: ExchangeApiMode.all, + selectedItem: _privacySettingsViewModel.exchangeStatus, + onItemSelected: (ExchangeApiMode mode) => + _privacySettingsViewModel.setExchangeApiMode(mode), + ), ), - ), - SettingsSwitcherCell( - title: S.current.settings_save_recipient_address, - value: _privacySettingsViewModel.shouldSaveRecipientAddress, - onValueChange: (BuildContext _, bool value) { - _privacySettingsViewModel.setShouldSaveRecipientAddress(value); - }), - if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible) SettingsSwitcherCell( - title: S.current.auto_generate_subaddresses, - value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled, - onValueChange: (BuildContext _, bool value) { - _privacySettingsViewModel.setAutoGenerateSubaddresses(value); - }, - ), - if (DeviceInfo.instance.isMobile) - SettingsSwitcherCell( - title: S.current.prevent_screenshots, - value: _privacySettingsViewModel.isAppSecure, + title: S.current.settings_save_recipient_address, + value: _privacySettingsViewModel.shouldSaveRecipientAddress, onValueChange: (BuildContext _, bool value) { - _privacySettingsViewModel.setIsAppSecure(value); + _privacySettingsViewModel.setShouldSaveRecipientAddress(value); }), - SettingsSwitcherCell( - title: S.current.disable_buy, - value: _privacySettingsViewModel.disableBuy, - onValueChange: (BuildContext _, bool value) { - _privacySettingsViewModel.setDisableBuy(value); - }), - SettingsSwitcherCell( - title: S.current.disable_sell, - value: _privacySettingsViewModel.disableSell, - onValueChange: (BuildContext _, bool value) { - _privacySettingsViewModel.setDisableSell(value); - }), - if (_privacySettingsViewModel.canUseEtherscan) - SettingsSwitcherCell( - title: S.current.etherscan_history, - value: _privacySettingsViewModel.useEtherscan, + if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible) + SettingsSwitcherCell( + title: S.current.auto_generate_subaddresses, + value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled, onValueChange: (BuildContext _, bool value) { - _privacySettingsViewModel.setUseEtherscan(value); + _privacySettingsViewModel.setAutoGenerateSubaddresses(value); + }, + ), + if (DeviceInfo.instance.isMobile) + SettingsSwitcherCell( + title: S.current.prevent_screenshots, + value: _privacySettingsViewModel.isAppSecure, + onValueChange: (BuildContext _, bool value) { + _privacySettingsViewModel.setIsAppSecure(value); + }), + SettingsSwitcherCell( + title: S.current.disable_buy, + value: _privacySettingsViewModel.disableBuy, + onValueChange: (BuildContext _, bool value) { + _privacySettingsViewModel.setDisableBuy(value); }), - SettingsCellWithArrow( - title: S.current.domain_looks_up, - handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage), - ), - SettingsCellWithArrow( - title: 'Trocador providers', - handler: (context) => Navigator.of(context).pushNamed(Routes.trocadorProvidersPage), - ), - ], - ); - }), + SettingsSwitcherCell( + title: S.current.disable_sell, + value: _privacySettingsViewModel.disableSell, + onValueChange: (BuildContext _, bool value) { + _privacySettingsViewModel.setDisableSell(value); + }), + if (_privacySettingsViewModel.canUseEtherscan) + SettingsSwitcherCell( + title: S.current.etherscan_history, + value: _privacySettingsViewModel.useEtherscan, + onValueChange: (BuildContext _, bool value) { + _privacySettingsViewModel.setUseEtherscan(value); + }), + SettingsCellWithArrow( + title: S.current.domain_looks_up, + handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage), + ), + SettingsCellWithArrow( + title: 'Trocador providers', + handler: (context) => Navigator.of(context).pushNamed(Routes.trocadorProvidersPage), + ), + ], + ); + }), + ), ); } } diff --git a/lib/utils/feature_flag.dart b/lib/utils/feature_flag.dart index 628023f85..91a4c67ca 100644 --- a/lib/utils/feature_flag.dart +++ b/lib/utils/feature_flag.dart @@ -1,4 +1,5 @@ class FeatureFlag { static const bool isCakePayEnabled = false; static const bool isExolixEnabled = false; + static const bool isInAppTorEnabled = false; } \ No newline at end of file diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 664a5231b..329732075 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -30,13 +30,11 @@ PODS: - FlutterMacOS - package_info (0.0.1): - FlutterMacOS + - package_info_plus (0.0.1): + - FlutterMacOS - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS - - platform_device_id (0.0.1): - - FlutterMacOS - - platform_device_id_macos (0.0.1): - - FlutterMacOS - ReachabilitySwift (5.0.0) - share_plus_macos (0.0.1): - FlutterMacOS @@ -45,7 +43,7 @@ PODS: - FlutterMacOS - url_launcher_macos (0.0.1): - FlutterMacOS - - wakelock_macos (0.0.1): + - wakelock_plus (0.0.1): - FlutterMacOS DEPENDENCIES: @@ -57,13 +55,12 @@ DEPENDENCIES: - FlutterMacOS (from `Flutter/ephemeral`) - in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`) - package_info (from `Flutter/ephemeral/.symlinks/plugins/package_info/macos`) + - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - - platform_device_id (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos`) - - platform_device_id_macos (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id_macos/macos`) - share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`) - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - - wakelock_macos (from `Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos`) + - wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`) SPEC REPOS: trunk: @@ -86,20 +83,18 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/in_app_review/macos package_info: :path: Flutter/ephemeral/.symlinks/plugins/package_info/macos + package_info_plus: + :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos path_provider_foundation: :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin - platform_device_id: - :path: Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos - platform_device_id_macos: - :path: Flutter/ephemeral/.symlinks/plugins/platform_device_id_macos/macos share_plus_macos: :path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos shared_preferences_foundation: :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin url_launcher_macos: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos - wakelock_macos: - :path: Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos + wakelock_plus: + :path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos SPEC CHECKSUMS: connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308 @@ -110,14 +105,13 @@ SPEC CHECKSUMS: FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0 package_info: 6eba2fd8d3371dda2d85c8db6fe97488f24b74b2 + package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 - platform_device_id: 3e414428f45df149bbbfb623e2c0ca27c545b763 - platform_device_id_macos: f763bb55f088be804d61b96eb4710b8ab6598e94 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4 shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 - wakelock_macos: bc3f2a9bd8d2e6c89fee1e1822e7ddac3bd004a9 + wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269 PODFILE CHECKSUM: 5107934592df7813b33d744aebc8ddc6b5a5445f diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index ba7575d3a..5dd9f2edf 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.7.3" -MONERO_COM_BUILD_NUMBER=64 +MONERO_COM_VERSION="1.7.5" +MONERO_COM_BUILD_NUMBER=67 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.10.3" -CAKEWALLET_BUILD_NUMBER=178 +CAKEWALLET_VERSION="4.10.5" +CAKEWALLET_BUILD_NUMBER=181 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 328b3825b..810b2b78c 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.7.4" -MONERO_COM_BUILD_NUMBER=63 +MONERO_COM_VERSION="1.7.5" +MONERO_COM_BUILD_NUMBER=65 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.10.4" -CAKEWALLET_BUILD_NUMBER=196 +CAKEWALLET_VERSION="4.10.5" +CAKEWALLET_BUILD_NUMBER=199 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 57434db8e..665da3425 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -15,8 +15,8 @@ if [ -n "$1" ]; then fi CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.3.3" -CAKEWALLET_BUILD_NUMBER=40 +CAKEWALLET_VERSION="1.3.5" +CAKEWALLET_BUILD_NUMBER=42 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From 306e4671b4aedf3699c7daaa24cae7f9c2482726 Mon Sep 17 00:00:00 2001 From: Serhii Date: Tue, 21 Nov 2023 14:46:11 +0200 Subject: [PATCH 044/241] add 2fa guid and how to use sections --- lib/src/screens/setup_2fa/setup_2fa.dart | 10 +++++++++- .../screens/setup_2fa/setup_2fa_qr_page.dart | 20 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/src/screens/setup_2fa/setup_2fa.dart b/lib/src/screens/setup_2fa/setup_2fa.dart index 895fbb9c0..3bdd49f5b 100644 --- a/lib/src/screens/setup_2fa/setup_2fa.dart +++ b/lib/src/screens/setup_2fa/setup_2fa.dart @@ -19,6 +19,9 @@ class Setup2FAPage extends BasePage { @override Widget body(BuildContext context) { + final cake2FAGuideTitle = 'Cake 2FA Guide'; + final cake2FAGuideUri = + Uri.parse('https://guides.cakewallet.com/docs/advanced-features/authentication'); return SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -50,7 +53,7 @@ class Setup2FAPage extends BasePage { ], ), ), - SizedBox(height: 86), + SizedBox(height: 56), SettingsCellWithArrow( title: S.current.setup_totp_recommended, handler: (_) { @@ -59,6 +62,11 @@ class Setup2FAPage extends BasePage { }, ), StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + SettingsCellWithArrow( + title: cake2FAGuideTitle, + handler: (_) => Navigator.of(context) + .pushNamed(Routes.webViewPage, arguments: [cake2FAGuideTitle, cake2FAGuideUri])), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), ], ), ); 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 43dbab05f..a50c64aa0 100644 --- a/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart +++ b/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart @@ -30,6 +30,9 @@ class Setup2FAQRPage extends BasePage { width: 12, color: Color(0xFF355688), ); + final cake2FAHowToUseTitle = 'How to use'; + final cake2FAHowToUseUrl = Uri.parse( + 'https://guides.cakewallet.com/docs/advanced-features/authentication/#enabling-cake-2fa'); return Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: Column( @@ -180,6 +183,23 @@ class Setup2FAQRPage extends BasePage { ), SizedBox(height: 8), StandardListSeparator(), + SizedBox(height: 16), + GestureDetector( + onTap: () => Navigator.of(context).pushNamed(Routes.webViewPage, + arguments: [cake2FAHowToUseTitle, cake2FAHowToUseUrl]), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(cake2FAHowToUseTitle, + style: TextStyle( + decoration: TextDecoration.underline, + fontSize: 16, + fontWeight: FontWeight.w700, + )), + Icon(Icons.info_outline,size: 20) + ], + )), Spacer(), PrimaryButton( onPressed: () { From 0c77b23ecb0c08e7931d341d2cdf643edc51e7f5 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Wed, 22 Nov 2023 18:43:26 +0100 Subject: [PATCH 045/241] feat: Implement NFT Tab for Eth (#1166) * feat: Implement NFT Listing and Importing of new NFTs, also display NFTs linked to the wallet address * Adjust UI based on wallet type, display nfts only when an ethereum wallet * fix: Prevent tab bar from scrolling * feat:Add NFT tab: adjust models and add localization * feat:Add NFT tab: adjust models and add localization * chore: Remove unused widget * fix: Adjust UI to reflect more data, display image based on type, either png or svg, adjust theme-a * fix: Update viewmodel * fix: Add missing dependency to fix failing CI * fix: Revert change in inject app script * Delete cw_polygon/pubspec.lock * - Code enhancements - UI fixes - Removing unrelated files --------- Co-authored-by: Omar Hatem --- .github/workflows/pr_test_build.yml | 1 + .../.plugin_symlinks/path_provider_linux | 2 +- .../flutter/ephemeral/.plugin_symlinks/tor | 1 + ios/Podfile.lock | 2 +- lib/di.dart | 29 +-- lib/entities/wallet_nft_response.dart | 95 ++++++++++ lib/router.dart | 25 ++- lib/routes.dart | 8 +- lib/src/screens/dashboard/dashboard_page.dart | 8 +- .../dashboard/desktop_dashboard_page.dart | 5 +- .../desktop_dashboard_actions.dart | 2 +- .../{widgets => pages}/address_page.dart | 48 +++-- .../{widgets => pages}/balance_page.dart | 142 +++++++++++--- .../{widgets => pages}/market_place_page.dart | 0 .../dashboard/pages/nft_details_page.dart | 178 ++++++++++++++++++ .../dashboard/pages/nft_import_page.dart | 168 +++++++++++++++++ .../dashboard/pages/nft_listing_page.dart | 84 +++++++++ .../{widgets => pages}/transactions_page.dart | 58 +++--- .../widgets/nft_image_tile_widget.dart | 37 ++++ .../dashboard/widgets/nft_tile_widget.dart | 95 ++++++++++ lib/src/widgets/address_text_field.dart | 3 + lib/utils/exception_handler.dart | 1 + lib/view_model/dashboard/nft_view_model.dart | 139 ++++++++++++++ pubspec_base.yaml | 1 + res/values/strings_ar.arb | 15 +- res/values/strings_bg.arb | 7 + res/values/strings_cs.arb | 9 +- res/values/strings_de.arb | 7 + res/values/strings_en.arb | 7 + res/values/strings_es.arb | 7 + res/values/strings_fr.arb | 9 + res/values/strings_ha.arb | 7 + res/values/strings_hi.arb | 7 + res/values/strings_hr.arb | 9 +- res/values/strings_id.arb | 7 + res/values/strings_it.arb | 9 +- res/values/strings_ja.arb | 9 +- res/values/strings_ko.arb | 7 + res/values/strings_my.arb | 7 + res/values/strings_nl.arb | 7 + res/values/strings_pl.arb | 9 +- res/values/strings_pt.arb | 7 + res/values/strings_ru.arb | 7 + res/values/strings_th.arb | 7 + res/values/strings_tl.arb | 7 + res/values/strings_tr.arb | 9 +- res/values/strings_uk.arb | 9 +- res/values/strings_ur.arb | 15 +- res/values/strings_yo.arb | 9 +- res/values/strings_zh.arb | 9 +- tool/utils/secret_key.dart | 1 + 51 files changed, 1219 insertions(+), 132 deletions(-) create mode 120000 cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/tor create mode 100644 lib/entities/wallet_nft_response.dart rename lib/src/screens/dashboard/{widgets => pages}/address_page.dart (86%) rename lib/src/screens/dashboard/{widgets => pages}/balance_page.dart (77%) rename lib/src/screens/dashboard/{widgets => pages}/market_place_page.dart (100%) create mode 100644 lib/src/screens/dashboard/pages/nft_details_page.dart create mode 100644 lib/src/screens/dashboard/pages/nft_import_page.dart create mode 100644 lib/src/screens/dashboard/pages/nft_listing_page.dart rename lib/src/screens/dashboard/{widgets => pages}/transactions_page.dart (77%) create mode 100644 lib/src/screens/dashboard/widgets/nft_image_tile_widget.dart create mode 100644 lib/src/screens/dashboard/widgets/nft_tile_widget.dart create mode 100644 lib/view_model/dashboard/nft_view_model.dart diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index d74b85ce4..7b2b611d3 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -136,6 +136,7 @@ jobs: echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart echo "const robinhoodCIdApiSecret = '${{ 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 - name: Rename app run: echo -e "id=com.cakewallet.test\nname=$GITHUB_HEAD_REF" > /opt/android/cake_wallet/android/app.properties diff --git a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux index 17553f81e..0ed52b295 120000 --- a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux +++ b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux @@ -1 +1 @@ -/Users/omarhatem/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ \ No newline at end of file +/Users/blazebrain/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ \ No newline at end of file diff --git a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/tor b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/tor new file mode 120000 index 000000000..7ee2b206d --- /dev/null +++ b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/tor @@ -0,0 +1 @@ +/Users/blazebrain/.pub-cache/git/tor-09ba92cb11d4e3cacf97256e57863b805f79f2e5/ \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 775419d18..bbb088325 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -302,7 +302,7 @@ SPEC CHECKSUMS: tor: 662a9f5b980b5c86decb8ba611de9bcd4c8286eb uni_links: d97da20c7701486ba192624d99bffaaffcfc298a UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841 - url_launcher_ios: 68d46cc9766d0c41dbdc884310529557e3cd7a86 + url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47 workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6 diff --git a/lib/di.dart b/lib/di.dart index d6a43030a..0a7097b7b 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -27,7 +27,7 @@ import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sideba import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart'; import 'package:cake_wallet/src/screens/dashboard/edit_token_page.dart'; import 'package:cake_wallet/src/screens/dashboard/home_settings_page.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/transactions_page.dart'; import 'package:cake_wallet/src/screens/nano/nano_change_rep_page.dart'; import 'package:cake_wallet/src/screens/nano_accounts/nano_account_edit_or_create_page.dart'; import 'package:cake_wallet/src/screens/nano_accounts/nano_account_list_page.dart'; @@ -65,6 +65,7 @@ import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart'; import 'package:cake_wallet/view_model/anonpay_details_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/home_settings_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart'; +import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_auth_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_buy_card_view_model.dart'; @@ -80,7 +81,7 @@ import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_cards_page.dar import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_page.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_tip_page.dart'; import 'package:cake_wallet/src/screens/ionia/ionia.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/balance_page.dart'; import 'package:cake_wallet/view_model/ionia/ionia_account_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_gift_cards_list_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_purchase_merch_view_model.dart'; @@ -212,7 +213,7 @@ import 'package:cake_wallet/store/templates/exchange_template_store.dart'; import 'package:cake_wallet/entities/template.dart'; import 'package:cake_wallet/exchange/exchange_template.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; -import 'package:cake_wallet/src/screens/dashboard/widgets/address_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/address_page.dart'; import 'package:cake_wallet/anypay/anypay_api.dart'; import 'package:cake_wallet/view_model/ionia/ionia_gift_card_details_view_model.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_payment_status_page.dart'; @@ -342,10 +343,9 @@ Future setup({ getIt.get(), (WalletType type) => getIt.get(param1: type))); - getIt.registerFactoryParam((type, _) => - WalletNewVM(getIt.get(), - getIt.get(param1: type), _walletInfoSource, - type: type)); + getIt.registerFactoryParam((type, _) => WalletNewVM( + getIt.get(), getIt.get(param1: type), _walletInfoSource, + type: type)); getIt.registerFactoryParam((WalletType type, _) { return WalletRestorationFromQRVM(getIt.get(), @@ -483,6 +483,7 @@ Future setup({ }); getIt.registerFactory(() => BalancePage( + nftViewModel: getIt.get(), dashboardViewModel: getIt.get(), settingsStore: getIt.get())); @@ -901,8 +902,8 @@ Future setup({ (param1, isCreate) => NewWalletTypePage(onTypeSelected: param1, isCreate: isCreate ?? true)); getIt.registerFactoryParam( - (WalletType type, AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel) - => PreSeedPage(type, advancedPrivacySettingsViewModel)); + (WalletType type, AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel) => + PreSeedPage(type, advancedPrivacySettingsViewModel)); getIt.registerFactoryParam((trade, _) => TradeDetailsViewModel( @@ -996,11 +997,10 @@ Future setup({ getIt.registerFactory(() => YatService()); - getIt.registerFactory(() => - AddressResolver( - yatService: getIt.get(), - wallet: getIt.get().wallet!, - settingsStore: getIt.get())); + getIt.registerFactory(() => AddressResolver( + yatService: getIt.get(), + wallet: getIt.get().wallet!, + settingsStore: getIt.get())); getIt.registerFactoryParam( (QrViewData viewData, _) => FullscreenQRPage(qrViewData: viewData)); @@ -1176,6 +1176,7 @@ Future setup({ getIt.registerFactory( () => WalletConnectConnectionsView(web3walletService: getIt.get())); + getIt.registerFactory(() => NFTViewModel(appStore, getIt.get())); getIt.registerFactory(() => TorPage(getIt.get())); _isSetupFinished = true; diff --git a/lib/entities/wallet_nft_response.dart b/lib/entities/wallet_nft_response.dart new file mode 100644 index 000000000..74a7508ab --- /dev/null +++ b/lib/entities/wallet_nft_response.dart @@ -0,0 +1,95 @@ +class WalletNFTsResponseModel { + final int? page; + final int? pageSize; + + final List? result; + final String? status; + + WalletNFTsResponseModel({this.page, this.pageSize, this.result, this.status}); + + factory WalletNFTsResponseModel.fromJson(Map json) { + return WalletNFTsResponseModel( + page: json['page'] as int?, + pageSize: json['page_size'] as int?, + result: (json['result'] as List?) + ?.map((x) => NFTAssetModel.fromJson(x as Map)) + .toList(), + status: json['status'] as String?, + ); + } +} + +class NFTAssetModel { + final String? tokenAddress; + final String? tokenId; + final String? contractType; + final String? name; + final String? symbol; + NormalizedMetadata? normalizedMetadata; + + NFTAssetModel( + {this.tokenAddress, + this.tokenId, + this.contractType, + this.name, + this.symbol, + this.normalizedMetadata}); + + factory NFTAssetModel.fromJson(Map json) { + return NFTAssetModel( + tokenAddress: json['token_address'] as String?, + tokenId: json['token_id'] as String?, + contractType: json['contract_type'] as String?, + name: json['name'] as String?, + symbol: json['symbol'] as String?, + normalizedMetadata: json['normalized_metadata'] != null + ? new NormalizedMetadata.fromJson( + json['normalized_metadata'] as Map) + : null, + ); + } +} + +class NormalizedMetadata { + final String? name; + final String? description; + final String? image; + NormalizedMetadata({ + this.name, + this.description, + this.image, + }); + + factory NormalizedMetadata.fromJson(Map json) { + return NormalizedMetadata( + name: json['name'] as String?, + description: json['description'] as String?, + image: json['image'] as String?, + ); + + } + + String? get imageUrl { + if (image == null) return image; + + if (image!.contains('ipfs.io')) return image; + + if (!image!.contains('ipfs')) return image; + + // IPFS public gateway provided by Cloudflare is https://cloudflare-ipfs.com/ipfs/ + // + // Here is an example of an ipfs image link: + // + // [ipfs://bafkreia2i2ctfexpovgzfff66wqhbmwwpvqjvozan7ioifzcnq76jharwu] + + //https://ipfs.io/ipfs/QmTRcRXo6cXByjHYHTVxGpag6vpocrG3rxjPC9PxKAArR9/1620.png + + const String ipfsPublicGateway = 'https://cloudflare-ipfs.com/ipfs/'; + + final ipfsPath = image?.split('//')[1]; + + final imageLink = '$ipfsPublicGateway$ipfsPath'; + + return imageLink; + } +} diff --git a/lib/router.dart b/lib/router.dart index 75f491dfc..fb21ba32c 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart'; import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/entities/qr_view_data.dart'; +import 'package:cake_wallet/entities/wallet_nft_response.dart'; import 'package:cake_wallet/src/screens/anonpay_details/anonpay_details_page.dart'; import 'package:cake_wallet/src/screens/backup/backup_page.dart'; import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart'; @@ -13,6 +14,7 @@ import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart'; import 'package:cake_wallet/src/screens/buy/webview_page.dart'; import 'package:cake_wallet/src/screens/dashboard/edit_token_page.dart'; import 'package:cake_wallet/src/screens/dashboard/home_settings_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/nft_details_page.dart'; import 'package:cake_wallet/src/screens/nano/nano_change_rep_page.dart'; import 'package:cake_wallet/src/screens/nano_accounts/nano_account_edit_or_create_page.dart'; import 'package:cake_wallet/src/screens/nodes/pow_node_create_or_edit_page.dart'; @@ -20,7 +22,7 @@ import 'package:cake_wallet/src/screens/restore/sweeping_wallet_page.dart'; import 'package:cake_wallet/src/screens/receive/anonpay_invoice_page.dart'; import 'package:cake_wallet/src/screens/receive/anonpay_receive_page.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/transactions_page.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_choose_derivation.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'; @@ -56,6 +58,7 @@ import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.da import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart'; import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart'; import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; @@ -102,7 +105,7 @@ import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dar import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_page.dart'; import 'package:flutter/services.dart'; import 'package:cake_wallet/wallet_types.g.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/address_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/address_page.dart'; import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart'; import 'package:cake_wallet/src/screens/ionia/ionia.dart'; import 'package:cake_wallet/src/screens/ionia/cards/ionia_payment_status_page.dart'; @@ -111,6 +114,8 @@ import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/node.dart'; +import 'src/screens/dashboard/pages/nft_import_page.dart'; + late RouteSettings currentRouteSettings; Route createRoute(RouteSettings settings) { @@ -616,6 +621,22 @@ Route createRoute(RouteSettings settings) { web3walletService: getIt.get(), launchUri: settings.arguments as Uri?, )); + + case Routes.nftDetailsPage: + return MaterialPageRoute( + builder: (_) => NFTDetailsPage( + nftAsset: settings.arguments as NFTAssetModel, + dashboardViewModel: getIt.get(), + ), + ); + + case Routes.importNFTPage: + return MaterialPageRoute( + builder: (_) => ImportNFTPage( + nftViewModel: settings.arguments as NFTViewModel, + ), + ); + case Routes.torPage: return MaterialPageRoute(builder: (_) => getIt.get()); diff --git a/lib/routes.dart b/lib/routes.dart index 4c1a917ab..4511d48e1 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -7,7 +7,8 @@ class Routes { static const restoreOptions = '/restore_options'; static const restoreWalletFromSeedKeys = '/restore_wallet_from_seeds_keys'; static const restoreWalletTypeFromQR = '/restore_wallet_from_qr_code'; - static const restoreWalletChooseDerivation = '/restore_wallet_choose_derivation'; + static const restoreWalletChooseDerivation = + '/restore_wallet_choose_derivation'; static const dashboard = '/dashboard'; static const send = '/send'; static const transactionDetails = '/transaction_info'; @@ -100,6 +101,9 @@ class Routes { static const editToken = '/edit_token'; static const manageNodes = '/manage_nodes'; static const managePowNodes = '/manage_pow_nodes'; - static const walletConnectConnectionsListing = '/wallet-connect-connections-listing'; + static const walletConnectConnectionsListing = + '/wallet-connect-connections-listing'; + static const nftDetailsPage = '/nft_details_page'; + static const importNFTPage = '/import_nft_page'; static const torPage = '/tor_page'; } diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index d4662c625..2552f4a4a 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -1,11 +1,10 @@ import 'dart:async'; import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart'; -import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/main_actions.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/market_place_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/market_place_page.dart'; import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/bottom_sheet_listener.dart'; import 'package:cake_wallet/src/widgets/gradient_background.dart'; import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; @@ -15,7 +14,6 @@ import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/yat_emoji_id.dart'; -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; @@ -23,8 +21,8 @@ import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/menu_widget.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/action_button.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/balance_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/transactions_page.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; diff --git a/lib/src/screens/dashboard/desktop_dashboard_page.dart b/lib/src/screens/dashboard/desktop_dashboard_page.dart index ed9fa6912..216ea152d 100644 --- a/lib/src/screens/dashboard/desktop_dashboard_page.dart +++ b/lib/src/screens/dashboard/desktop_dashboard_page.dart @@ -1,17 +1,14 @@ import 'dart:async'; import 'package:cake_wallet/entities/preferences_key.dart'; -import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/release_notes/release_notes_screen.dart'; import 'package:cake_wallet/src/screens/yat_emoji_id.dart'; -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/utils/version_comparator.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/balance_page.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart'; -import 'package:mobx/mobx.dart'; import 'package:cake_wallet/main.dart'; import 'package:cake_wallet/router.dart' as Router; import 'package:shared_preferences/shared_preferences.dart'; diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart index 5e1f8d16a..20ddea361 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart @@ -1,7 +1,7 @@ import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/main_actions.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_action_button.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/market_place_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/market_place_page.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart'; import 'package:flutter/material.dart'; diff --git a/lib/src/screens/dashboard/widgets/address_page.dart b/lib/src/screens/dashboard/pages/address_page.dart similarity index 86% rename from lib/src/screens/dashboard/widgets/address_page.dart rename to lib/src/screens/dashboard/pages/address_page.dart index c57613fa5..ff21d4aad 100644 --- a/lib/src/screens/dashboard/widgets/address_page.dart +++ b/lib/src/screens/dashboard/pages/address_page.dart @@ -6,10 +6,8 @@ import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/receive_page_option.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/present_receive_option_picker.dart'; -import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/gradient_background.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; -import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; @@ -26,7 +24,6 @@ import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; class AddressPage extends BasePage { @@ -163,8 +160,7 @@ class AddressPage extends BasePage { return GestureDetector( onTap: () async => dashboardViewModel.isAutoGenerateSubaddressesEnabled ? await showPopUp( - context: context, - builder: (_) => getIt.get()) + context: context, builder: (_) => getIt.get()) : Navigator.of(context).pushNamed(Routes.receive), child: Container( height: 50, @@ -184,26 +180,27 @@ class AddressPage extends BasePage { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Observer( - builder: (_) { - String label = addressListViewModel.hasAccounts - ? S.of(context).accounts_subaddresses - : S.of(context).addresses; + builder: (_) { + String label = addressListViewModel.hasAccounts + ? S.of(context).accounts_subaddresses + : S.of(context).addresses; - if (dashboardViewModel.isAutoGenerateSubaddressesEnabled) { - label = addressListViewModel.hasAccounts - ? S.of(context).accounts - : S.of(context).account; - } - return Text( - label, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Theme.of(context) - .extension()! - .textColor), - ); - },), + if (dashboardViewModel.isAutoGenerateSubaddressesEnabled) { + label = addressListViewModel.hasAccounts + ? S.of(context).accounts + : S.of(context).account; + } + return Text( + label, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Theme.of(context) + .extension()! + .textColor), + ); + }, + ), Icon( Icons.arrow_forward_ios, size: 14, @@ -213,7 +210,8 @@ class AddressPage extends BasePage { ), ), ); - } else if (dashboardViewModel.isAutoGenerateSubaddressesEnabled || addressListViewModel.showElectrumAddressDisclaimer) { + } else if (dashboardViewModel.isAutoGenerateSubaddressesEnabled || + addressListViewModel.showElectrumAddressDisclaimer) { return Text(S.of(context).electrum_address_disclaimer, textAlign: TextAlign.center, style: TextStyle( diff --git a/lib/src/screens/dashboard/widgets/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart similarity index 77% rename from lib/src/screens/dashboard/widgets/balance_page.dart rename to lib/src/screens/dashboard/pages/balance_page.dart index 41d4e7bb0..057352456 100644 --- a/lib/src/screens/dashboard/widgets/balance_page.dart +++ b/lib/src/screens/dashboard/pages/balance_page.dart @@ -1,6 +1,7 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/nft_listing_page.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/home_screen_account_widget.dart'; import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart'; import 'package:cake_wallet/src/widgets/introducing_card.dart'; @@ -11,15 +12,80 @@ import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; import 'package:cake_wallet/utils/feature_flag.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; class BalancePage extends StatelessWidget { - BalancePage({required this.dashboardViewModel, required this.settingsStore}); + BalancePage({ + required this.dashboardViewModel, + required this.settingsStore, + required this.nftViewModel, + }); final DashboardViewModel dashboardViewModel; + final NFTViewModel nftViewModel; final SettingsStore settingsStore; + @override + Widget build(BuildContext context) { + return Observer( + builder: (context) { + final isEthereumWallet = dashboardViewModel.type == WalletType.ethereum; + return DefaultTabController( + length: isEthereumWallet ? 2 : 1, + child: Column( + children: [ + if (isEthereumWallet) + Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: const EdgeInsets.only(left: 8), + child: TabBar( + indicatorSize: TabBarIndicatorSize.label, + isScrollable: true, + physics: NeverScrollableScrollPhysics(), + labelStyle: TextStyle( + fontSize: 18, + fontFamily: 'Lato', + fontWeight: FontWeight.w600, + color: + Theme.of(context).extension()!.pageTitleTextColor, + height: 1, + ), + tabs: [ + Tab(text: 'My Crypto'), + Tab(text: 'My NFTs'), + ], + ), + ), + ), + Expanded( + child: TabBarView( + physics: NeverScrollableScrollPhysics(), + children: [ + CryptoBalanceWidget(dashboardViewModel: dashboardViewModel), + if (isEthereumWallet) NFTListingPage(nftViewModel: nftViewModel) + ], + ), + ), + ], + ), + ); + }, + ); + } +} + +class CryptoBalanceWidget extends StatelessWidget { + const CryptoBalanceWidget({ + super.key, + required this.dashboardViewModel, + }); + + final DashboardViewModel dashboardViewModel; + @override Widget build(BuildContext context) { return GestureDetector( @@ -38,7 +104,7 @@ class BalancePage extends StatelessWidget { accountName: dashboardViewModel.subname) : Column( children: [ - SizedBox(height: 56), + SizedBox(height: 16), Container( margin: const EdgeInsets.only(left: 24, bottom: 16), child: Observer( @@ -105,8 +171,7 @@ class BalancePage extends StatelessWidget { itemBuilder: (__, index) { final balance = dashboardViewModel.balanceViewModel.formattedBalances.elementAt(index); - return buildBalanceRow( - context, + return BalanceRowWidget( availableBalanceLabel: '${dashboardViewModel.balanceViewModel.availableBalanceLabel}', availableBalance: balance.availableBalance, @@ -130,20 +195,44 @@ class BalancePage extends StatelessWidget { ), ); } +} - Widget buildBalanceRow( - BuildContext context, { - required String availableBalanceLabel, - required String availableBalance, - required String availableFiatBalance, - required String additionalBalanceLabel, - required String additionalBalance, - required String additionalFiatBalance, - required String frozenBalance, - required String frozenFiatBalance, - required String currency, - required bool hasAdditionalBalance, - }) { +class BalanceRowWidget extends StatelessWidget { + const BalanceRowWidget({ + required this.availableBalanceLabel, + required this.availableBalance, + required this.availableFiatBalance, + required this.additionalBalanceLabel, + required this.additionalBalance, + required this.additionalFiatBalance, + required this.frozenBalance, + required this.frozenFiatBalance, + required this.currency, + required this.hasAdditionalBalance, + super.key, + }); + + final String availableBalanceLabel; + final String availableBalance; + final String availableFiatBalance; + final String additionalBalanceLabel; + final String additionalBalance; + final String additionalFiatBalance; + final String frozenBalance; + final String frozenFiatBalance; + final String currency; + final bool hasAdditionalBalance; + + // void _showBalanceDescription(BuildContext context) { + // showPopUp( + // context: context, + // builder: (_) => + // InformationPage(information: S.current.available_balance_description), + // ); + // } + + @override + Widget build(BuildContext context) { return Container( margin: const EdgeInsets.only(left: 16, right: 16), decoration: BoxDecoration( @@ -165,8 +254,9 @@ class BalancePage extends StatelessWidget { children: [ GestureDetector( behavior: HitTestBehavior.opaque, - onTap: hasAdditionalBalance ? () => - _showBalanceDescription(context, S.current.available_balance_description) + onTap: hasAdditionalBalance + ? () => + _showBalanceDescription(context, S.current.available_balance_description) : null, child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -229,8 +319,9 @@ class BalancePage extends StatelessWidget { if (frozenBalance.isNotEmpty) GestureDetector( behavior: HitTestBehavior.opaque, - onTap: hasAdditionalBalance ? - () => _showBalanceDescription(context, S.current.unavailable_balance_description) + onTap: hasAdditionalBalance + ? () => + _showBalanceDescription(context, S.current.unavailable_balance_description) : null, child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -253,9 +344,8 @@ class BalancePage extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 4), child: Icon(Icons.help_outline, size: 16, - color: Theme.of(context) - .extension()! - .labelTextColor), + color: + Theme.of(context).extension()!.labelTextColor), ), ], ), @@ -337,8 +427,6 @@ class BalancePage extends StatelessWidget { } void _showBalanceDescription(BuildContext context, String content) { - showPopUp( - context: context, - builder: (_) => InformationPage(information: content)); + showPopUp(context: context, builder: (_) => InformationPage(information: content)); } } diff --git a/lib/src/screens/dashboard/widgets/market_place_page.dart b/lib/src/screens/dashboard/pages/market_place_page.dart similarity index 100% rename from lib/src/screens/dashboard/widgets/market_place_page.dart rename to lib/src/screens/dashboard/pages/market_place_page.dart diff --git a/lib/src/screens/dashboard/pages/nft_details_page.dart b/lib/src/screens/dashboard/pages/nft_details_page.dart new file mode 100644 index 000000000..4bddb550b --- /dev/null +++ b/lib/src/screens/dashboard/pages/nft_details_page.dart @@ -0,0 +1,178 @@ +import 'package:cake_wallet/entities/wallet_nft_response.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/widgets/menu_widget.dart'; +import 'package:cake_wallet/src/screens/dashboard/widgets/nft_image_tile_widget.dart'; +import 'package:cake_wallet/src/widgets/gradient_background.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; +import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:flutter/material.dart'; + +class NFTDetailsPage extends BasePage { + NFTDetailsPage({required this.dashboardViewModel, required this.nftAsset}); + + final DashboardViewModel dashboardViewModel; + final NFTAssetModel nftAsset; + + @override + bool get gradientBackground => true; + + @override + Widget Function(BuildContext, Widget) get rootWrapper => + (BuildContext context, Widget scaffold) => + GradientBackground(scaffold: scaffold); + + @override + bool get resizeToAvoidBottomInset => false; + + @override + Widget get endDrawer => MenuWidget(dashboardViewModel); + + @override + Widget trailing(BuildContext context) { + final menuButton = Image.asset( + 'assets/images/menu.png', + color: + Theme.of(context).extension()!.pageTitleTextColor, + ); + + return Container( + alignment: Alignment.centerRight, + width: 40, + child: TextButton( + // FIX-ME: Style + //highlightColor: Colors.transparent, + //splashColor: Colors.transparent, + //padding: EdgeInsets.all(0), + onPressed: () => onOpenEndDrawer(), + child: Semantics(label: S.of(context).wallet_menu, child: menuButton), + ), + ); + } + + @override + Widget body(BuildContext context) { + return SingleChildScrollView( + child: Column( + children: [ + Container( + width: double.infinity, + margin: const EdgeInsets.all(16), + padding: const EdgeInsets.symmetric(vertical: 16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30.0), + border: Border.all( + color: Theme.of(context) + .extension()! + .cardBorderColor, + width: 1, + ), + color: Theme.of(context) + .extension()! + .syncedBackgroundColor, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + height: MediaQuery.sizeOf(context).height / 2.5, + width: double.infinity, + clipBehavior: Clip.hardEdge, + margin: const EdgeInsets.all(8), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.0), + border: Border.all( + color: Theme.of(context) + .extension()! + .cardBorderColor, + width: 1, + ), + color: Theme.of(context) + .extension()! + .syncedBackgroundColor, + + ), + child: NFTImageWidget( + imageUrl: nftAsset.normalizedMetadata?.imageUrl, + ), + ), + SizedBox(height: 16), + _NFTSingleInfoTile( + infoType: S.current.name, + infoValue: nftAsset.normalizedMetadata?.name ?? '', + ), + + if (nftAsset.normalizedMetadata?.description != null) ...[ + SizedBox(height: 16), + _NFTSingleInfoTile( + infoType: 'Description', + infoValue: nftAsset.normalizedMetadata?.description ?? '', + ), + ], + + SizedBox(height: 16), + _NFTSingleInfoTile( + infoType: 'Contract Name', + infoValue: nftAsset.name ?? '', + ), + SizedBox(height: 8), + _NFTSingleInfoTile( + infoType: 'Contract Symbol', + infoValue: nftAsset.symbol ?? '', + ), + ], + ), + ), + ], + ), + ); + } +} + +class _NFTSingleInfoTile extends StatelessWidget { + const _NFTSingleInfoTile({ + required this.infoType, + required this.infoValue, + }); + + final String infoType; + final String infoValue; + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( +infoType, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context) + .extension()! + .labelTextColor, + height: 1, + ), + ), + SizedBox(height: 8), + Text( + infoValue, + style: TextStyle( + fontSize: 16, + fontFamily: 'Lato', + fontWeight: FontWeight.w600, + color: Theme.of(context) + .extension()! + .assetTitleColor, + height: 1, + ), + ), + ], + ), + ); + } +} diff --git a/lib/src/screens/dashboard/pages/nft_import_page.dart b/lib/src/screens/dashboard/pages/nft_import_page.dart new file mode 100644 index 000000000..6b40b46cc --- /dev/null +++ b/lib/src/screens/dashboard/pages/nft_import_page.dart @@ -0,0 +1,168 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/widgets/address_text_field.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart'; +import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class ImportNFTPage extends StatefulWidget { + const ImportNFTPage({required this.nftViewModel, super.key}); + + final NFTViewModel nftViewModel; + + @override + State createState() => _ImportNFTPageState(); +} + +class _ImportNFTPageState extends State { + late TextEditingController tokenAddressController; + late TextEditingController tokenIDController; + + @override + void initState() { + super.initState(); + tokenAddressController = TextEditingController(); + tokenIDController = TextEditingController(); + } + + @override + void dispose() { + tokenAddressController.dispose(); + tokenIDController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return _ImportNFTPage( + nftViewModel: widget.nftViewModel, + tokenAddressController: tokenAddressController, + tokenIDController: tokenIDController, + ); + } +} + +class _ImportNFTPage extends BasePage { + _ImportNFTPage({ + required this.tokenIDController, + required this.tokenAddressController, + required this.nftViewModel, + }); + + final NFTViewModel nftViewModel; + final TextEditingController tokenIDController; + final TextEditingController tokenAddressController; + + @override + String? get title => S.current.import; + + @override + Widget body(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + + Text( + S.current.address, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontFamily: 'Lato', + fontWeight: FontWeight.w800, + color: + Theme.of(context).extension()!.hintTextColor, + height: 1, + ), + ), + AddressTextField( + controller: tokenAddressController, + options: [AddressTextFieldOption.paste], + onPushPasteButton: (context) async { + final clipboard = await Clipboard.getData('text/plain'); + final tokenAddress = clipboard?.text ?? ''; + + if (tokenAddress.isNotEmpty) { + tokenAddressController.text = tokenAddress; + } + }, + borderColor: Theme.of(context) + .extension()! + .textfieldUnderlineColor, + iconColor: Theme.of(context).primaryColor, + placeholder: '0x...', + textStyle: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: PaletteDark.darkCyanBlue, + ), + hintStyle: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: PaletteDark.darkCyanBlue, + ), + ), + + SizedBox(height: 48), + Text( + S.current.tokenID, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontFamily: 'Lato', + fontWeight: FontWeight.w800, + color: Theme.of(context).extension()!.hintTextColor, + height: 1, + ), + ), + AddressTextField( + controller: tokenIDController, + options: [AddressTextFieldOption.paste], + onPushPasteButton: (context) async { + final clipboard = await Clipboard.getData('text/plain'); + final tokenID = clipboard?.text ?? ''; + + if (tokenID.isNotEmpty) { + tokenIDController.text = tokenID; + } + }, + borderColor: Theme.of(context) + .extension()! + .textfieldUnderlineColor, + iconColor: Theme.of(context).primaryColor, + placeholder: S.current.enterTokenID, + textStyle: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: PaletteDark.darkCyanBlue, + ), + hintStyle: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + color: PaletteDark.darkCyanBlue, + ), + ), + Spacer(), + Observer(builder: (context) { + return LoadingPrimaryButton( + isLoading: nftViewModel.isImportNFTLoading, + text: S.current.import, + color: Theme.of(context).primaryColor, + textColor: Colors.white, + onPressed: () async { + await nftViewModel.importNFT(tokenAddressController.text, tokenIDController.text); + Navigator.pop(context); + }, + ); + }), + ], + ), + ); + } +} diff --git a/lib/src/screens/dashboard/pages/nft_listing_page.dart b/lib/src/screens/dashboard/pages/nft_listing_page.dart new file mode 100644 index 000000000..46690a969 --- /dev/null +++ b/lib/src/screens/dashboard/pages/nft_listing_page.dart @@ -0,0 +1,84 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/dashboard/widgets/nft_tile_widget.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; +import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class NFTListingPage extends StatelessWidget { + final NFTViewModel nftViewModel; + + const NFTListingPage({super.key, required this.nftViewModel}); + @override + Widget build(BuildContext context) { + return Observer( + builder: (context) { + return Column( + children: [ + SizedBox(height: 16), + Padding( + padding: EdgeInsets.only(left: 16, right: 16, bottom: 16), + child: PrimaryButton( + text: S.current.import, + color: Theme.of(context) + .extension()! + .syncedBackgroundColor, + textColor: Colors.white, + onPressed: () => Navigator.pushNamed( + context, + Routes.importNFTPage, + arguments: nftViewModel, + ), + ), + ), + if (nftViewModel.isLoading) + Expanded( + child: Center( + child: CircularProgressIndicator( + backgroundColor: Theme.of(context).extension()!.textColor, + valueColor: AlwaysStoppedAnimation( + Theme.of(context) + .extension()! + .firstGradientBottomPanelColor, + ), + ), + ), + ), + if (!nftViewModel.isLoading) + Expanded( + child: nftViewModel.nftAssetByWalletModels.isEmpty + ? Center( + child: Text( + S.current.noNFTYet, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 20, + fontFamily: 'Lato', + fontWeight: FontWeight.w600, + color: Theme.of(context) + .extension()! + .pageTitleTextColor, + height: 1, + ), + ), + ) + : ListView.separated( + padding: EdgeInsets.symmetric(horizontal: 4, vertical: 16), + separatorBuilder: (context, index) => SizedBox(height: 8), + itemCount: nftViewModel.nftAssetByWalletModels.length, + itemBuilder: (context, index) { + final nftAsset = nftViewModel.nftAssetByWalletModels[index]; + return NFTTileWidget(nftAsset: nftAsset); + }, + ), + ) + ], + ); + }, + ); + } +} diff --git a/lib/src/screens/dashboard/widgets/transactions_page.dart b/lib/src/screens/dashboard/pages/transactions_page.dart similarity index 77% rename from lib/src/screens/dashboard/widgets/transactions_page.dart rename to lib/src/screens/dashboard/pages/transactions_page.dart index 5c7b78f3a..1be8a2a65 100644 --- a/lib/src/screens/dashboard/widgets/transactions_page.dart +++ b/lib/src/screens/dashboard/pages/transactions_page.dart @@ -46,9 +46,11 @@ class TransactionsPage extends StatelessWidget { return Padding( padding: const EdgeInsets.fromLTRB(24, 0, 24, 8), child: DashBoardRoundedCardWidget( - onTap: () => Navigator.of(context).pushNamed( - Routes.webViewPage, - arguments: ['', Uri.parse('https://guides.cakewallet.com/docs/bugs-service-status/why_are_my_funds_not_appearing/')]), + onTap: () => Navigator.of(context).pushNamed(Routes.webViewPage, arguments: [ + '', + Uri.parse( + 'https://guides.cakewallet.com/docs/bugs-service-status/why_are_my_funds_not_appearing/') + ]), title: S.of(context).syncing_wallet_alert_title, subTitle: S.of(context).syncing_wallet_alert_content, ), @@ -76,40 +78,34 @@ class TransactionsPage extends StatelessWidget { return Observer( builder: (_) => TransactionRow( - onTap: () => Navigator.of(context).pushNamed( - Routes.transactionDetails, - arguments: transaction), + onTap: () => Navigator.of(context) + .pushNamed(Routes.transactionDetails, arguments: transaction), direction: transaction.direction, - formattedDate: DateFormat('HH:mm') - .format(transaction.date), + formattedDate: DateFormat('HH:mm').format(transaction.date), formattedAmount: item.formattedCryptoAmount, - formattedFiatAmount: dashboardViewModel - .balanceViewModel.isFiatDisabled - ? '' - : item.formattedFiatAmount, + formattedFiatAmount: + dashboardViewModel.balanceViewModel.isFiatDisabled + ? '' + : item.formattedFiatAmount, isPending: transaction.isPending, - title: item.formattedTitle + - item.formattedStatus)); + title: item.formattedTitle + item.formattedStatus)); } if (item is AnonpayTransactionListItem) { final transactionInfo = item.transaction; return AnonpayTransactionRow( - onTap: () => Navigator.of(context).pushNamed( - Routes.anonPayDetailsPage, - arguments: transactionInfo), + onTap: () => Navigator.of(context) + .pushNamed(Routes.anonPayDetailsPage, arguments: transactionInfo), currency: transactionInfo.fiatAmount != null ? transactionInfo.fiatEquiv ?? '' - : CryptoCurrency.fromFullName( - transactionInfo.coinTo) + : CryptoCurrency.fromFullName(transactionInfo.coinTo) .name .toUpperCase(), provider: transactionInfo.provider, amount: transactionInfo.fiatAmount?.toString() ?? (transactionInfo.amountTo?.toString() ?? ''), - createdAt: DateFormat('HH:mm') - .format(transactionInfo.createdAt), + createdAt: DateFormat('HH:mm').format(transactionInfo.createdAt), ); } @@ -118,17 +114,14 @@ class TransactionsPage extends StatelessWidget { return Observer( builder: (_) => TradeRow( - onTap: () => Navigator.of(context).pushNamed( - Routes.tradeDetails, - arguments: trade), + onTap: () => Navigator.of(context) + .pushNamed(Routes.tradeDetails, arguments: trade), provider: trade.provider, from: trade.from, to: trade.to, - createdAtFormattedDate: - trade.createdAt != null - ? DateFormat('HH:mm') - .format(trade.createdAt!) - : null, + createdAtFormattedDate: trade.createdAt != null + ? DateFormat('HH:mm').format(trade.createdAt!) + : null, formattedAmount: item.tradeFormattedAmount)); } @@ -138,13 +131,12 @@ class TransactionsPage extends StatelessWidget { return Observer( builder: (_) => OrderRow( onTap: () => Navigator.of(context) - .pushNamed(Routes.orderDetails, - arguments: order), + .pushNamed(Routes.orderDetails, arguments: order), provider: order.provider, from: order.from!, to: order.to!, - createdAtFormattedDate: DateFormat('HH:mm') - .format(order.createdAt), + createdAtFormattedDate: + DateFormat('HH:mm').format(order.createdAt), formattedAmount: item.orderFormattedAmount, )); } diff --git a/lib/src/screens/dashboard/widgets/nft_image_tile_widget.dart b/lib/src/screens/dashboard/widgets/nft_image_tile_widget.dart new file mode 100644 index 000000000..d34ff02cb --- /dev/null +++ b/lib/src/screens/dashboard/widgets/nft_image_tile_widget.dart @@ -0,0 +1,37 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class NFTImageWidget extends StatelessWidget { + const NFTImageWidget({ + required this.imageUrl, + }); + + final String? imageUrl; + + @override + Widget build(BuildContext context) { + try { + if (imageUrl == null) return Icon(Icons.error); + + if (imageUrl!.contains('.svg')) { + return SvgPicture.network(imageUrl!); + } + + return Image.network( + imageUrl!, + fit: BoxFit.cover, + loadingBuilder: (BuildContext _, Widget child, ImageChunkEvent? loadingProgress) { + if (loadingProgress == null) { + return child; + } else { + return CupertinoActivityIndicator(animating: true); + } + }, + errorBuilder: (_, __, ___) => Icon(Icons.error), + ); + } catch (_) { + return Icon(Icons.error); + } + } +} diff --git a/lib/src/screens/dashboard/widgets/nft_tile_widget.dart b/lib/src/screens/dashboard/widgets/nft_tile_widget.dart new file mode 100644 index 000000000..0be027f44 --- /dev/null +++ b/lib/src/screens/dashboard/widgets/nft_tile_widget.dart @@ -0,0 +1,95 @@ +import 'package:cake_wallet/entities/wallet_nft_response.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/dashboard/widgets/nft_image_tile_widget.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class NFTTileWidget extends StatelessWidget { + const NFTTileWidget({super.key, required this.nftAsset}); + + final NFTAssetModel nftAsset; + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () => Navigator.pushNamed(context, Routes.nftDetailsPage, + arguments: nftAsset), + child: Container( + width: double.infinity, + margin: const EdgeInsets.only(left: 16, right: 16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30.0), + border: Border.all( + color: Theme.of(context) + .extension()! + .cardBorderColor, + width: 1, + ), + color: Theme.of(context) + .extension()! + .syncedBackgroundColor, + ), + child: Row( + children: [ + Container( + height: 100, + width: 100, + clipBehavior: Clip.hardEdge, + margin: const EdgeInsets.all(8), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.0), + border: Border.all( + color: Theme.of(context) + .extension()! + .cardBorderColor, + width: 1, + ), + color: Theme.of(context) + .extension()! + .syncedBackgroundColor, + ), + child: NFTImageWidget( + imageUrl: nftAsset.normalizedMetadata?.imageUrl, + ), + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${nftAsset.name ?? ''} - ${nftAsset.symbol ?? ''}', + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context) + .extension()! + .labelTextColor, + height: 1, + ), + ), + SizedBox(height: 8), + Text( + nftAsset.normalizedMetadata?.name ?? nftAsset.name ?? "", + style: TextStyle( + fontSize: 20, + fontFamily: 'Lato', + fontWeight: FontWeight.w900, + color: Theme.of(context) + .extension()! + .assetTitleColor, + height: 1, + ), + ), + ], + ), + ) + ], + ), + ), + ); + } +} + diff --git a/lib/src/widgets/address_text_field.dart b/lib/src/widgets/address_text_field.dart index 092a70422..0467b18a2 100644 --- a/lib/src/widgets/address_text_field.dart +++ b/lib/src/widgets/address_text_field.dart @@ -67,13 +67,16 @@ class AddressTextField extends StatelessWidget { enabled: isActive, controller: controller, focusNode: focusNode, + style: textStyle ?? TextStyle( fontSize: 16, color: Theme.of(context).extension()!.titleColor), decoration: InputDecoration( + suffixIcon: SizedBox( width: prefixIconWidth * options.length + (spaceBetweenPrefixIcons * options.length), ), + hintStyle: hintStyle ?? TextStyle(fontSize: 16, color: Theme.of(context).hintColor), hintText: placeholder ?? S.current.widgets_address, focusedBorder: isBorderExist diff --git a/lib/utils/exception_handler.dart b/lib/utils/exception_handler.dart index bea43a6c6..36eac4941 100644 --- a/lib/utils/exception_handler.dart +++ b/lib/utils/exception_handler.dart @@ -162,6 +162,7 @@ class ExceptionHandler { "Error while launching http", "OS Error: Network is unreachable", "ClientException: Write failed, uri=http", + "Connection terminated during handshake", ]; static Future _addDeviceInfo(File file) async { diff --git a/lib/view_model/dashboard/nft_view_model.dart b/lib/view_model/dashboard/nft_view_model.dart new file mode 100644 index 000000000..ec5919b7d --- /dev/null +++ b/lib/view_model/dashboard/nft_view_model.dart @@ -0,0 +1,139 @@ +// ignore_for_file: public_member_api_docs, sort_constructors_first +import 'dart:convert'; +import 'dart:developer'; + +import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart'; +import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_widget.dart'; +import 'package:http/http.dart' as http; +import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/.secrets.g.dart' as secrets; + +import 'package:cake_wallet/entities/wallet_nft_response.dart'; +import 'package:cake_wallet/store/app_store.dart'; + +part 'nft_view_model.g.dart'; + +class NFTViewModel = NFTViewModelBase with _$NFTViewModel; + +abstract class NFTViewModelBase with Store { + NFTViewModelBase(this.appStore, this.bottomSheetService) + : isLoading = false, + isImportNFTLoading = false, + nftAssetByWalletModels = ObservableList() { + getNFTAssetByWallet(); + + reaction((_) => appStore.wallet, (_) => getNFTAssetByWallet()); + } + + final AppStore appStore; + final BottomSheetService bottomSheetService; + + @observable + bool isLoading; + + @observable + bool isImportNFTLoading; + + ObservableList nftAssetByWalletModels; + + @action + Future getNFTAssetByWallet() async { + final walletAddress = appStore.wallet!.walletInfo.address; + log('Fetching wallet NFTs for $walletAddress'); + + // the [chain] refers to the chain network that the nft is on + // the [format] refers to the number format type of the responses + // the [normalizedMetadata] field is a boolean that determines if + // the response would include a json string of the NFT Metadata that can be decoded + // and used within the wallet + final uri = Uri.https( + 'deep-index.moralis.io', + '/api/v2.2/$walletAddress/nft', + { + "chain": "eth", + "format": "decimal", + "media_items": "false", + "normalizeMetadata": "true", + }, + ); + + try { + isLoading = true; + + final response = await http.get( + uri, + headers: { + "Accept": "application/json", + "X-API-Key": secrets.moralisApiKey, + }, + ); + + final decodedResponse = jsonDecode(response.body) as Map; + + final result = WalletNFTsResponseModel.fromJson(decodedResponse).result ?? []; + + nftAssetByWalletModels.clear(); + + nftAssetByWalletModels.addAll(result); + + isLoading = false; + } catch (e) { + isLoading = false; + log(e.toString()); + bottomSheetService.queueBottomSheet( + isModalDismissible: true, + widget: BottomSheetMessageDisplayWidget( + message: e.toString(), + ), + ); + } + } + + @action + Future importNFT(String tokenAddress, String tokenId) async { + + // the [chain] refers to the chain network that the nft is on + // the [format] refers to the number format type of the responses + // the [normalizedMetadata] field is a boolean that determines if + // the response would include a json string of the NFT Metadata that can be decoded + // and used within the wallet + final uri = Uri.https( + 'deep-index.moralis.io', + '/api/v2.2/nft/$tokenAddress/$tokenId', + { + "chain": "eth", + "format": "decimal", + "media_items": "false", + "normalizeMetadata": "true", + }, + ); + + try { + isImportNFTLoading = true; + + final response = await http.get( + uri, + headers: { + "Accept": "application/json", + "X-API-Key": secrets.moralisApiKey, + }, + ); + + final decodedResponse = jsonDecode(response.body) as Map; + + final nftAsset = NFTAssetModel.fromJson(decodedResponse); + + nftAssetByWalletModels.add(nftAsset); + + isImportNFTLoading = false; + } catch (e) { + isImportNFTLoading = false; + bottomSheetService.queueBottomSheet( + isModalDismissible: true, + widget: BottomSheetMessageDisplayWidget( + message: e.toString(), + ), + ); + } + } +} diff --git a/pubspec_base.yaml b/pubspec_base.yaml index c6101d28c..edfc64890 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -103,6 +103,7 @@ dependencies: url: https://github.com/cake-tech/tor.git ref: main socks5_proxy: ^1.0.4 + flutter_svg: ^2.0.9 dev_dependencies: flutter_test: diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 84a0a72f5..fb883eb13 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -383,7 +383,7 @@ "change_backup_password_alert": "لن تكون ملفات النسخ الاحتياطي السابقة متاحة للاستيراد بكلمة مرور نسخ احتياطي جديدة. سيتم استخدام كلمة مرور النسخ الاحتياطي الجديدة لملفات النسخ الاحتياطي الجديدة فقط. هل أنت متأكد أنك تريد تغيير كلمة المرور الاحتياطية؟", "enter_backup_password": "أدخل كلمة المرور الاحتياطية هنا", "select_backup_file": "حدد ملف النسخ الاحتياطي", - "import": "اختيار ملف", + "import": "ﺩﺭﻮﺘﺴﻳ", "please_select_backup_file": "الرجاء تحديد ملف النسخ الاحتياطي وإدخال كلمة مرور النسخ الاحتياطي.", "fixed_rate": "السعر الثابت", "fixed_rate_alert": "ستتمكن من إدخال مبلغ الاستلام عند تشغيل وضع السعر الثابت. هل تريد التبديل إلى وضع السعر الثابت؟", @@ -727,9 +727,16 @@ "require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ", "camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ", "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", - "seed_phrase_length": " ﺭﻭﺬﺒﻟﺍ ﺓﺭﺎﺒﻌﻟﺍ ﻝﻮﻃ", - "unavailable_balance": " ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ", + "importNFTs": "NFTs ﺩﺍﺮﻴﺘﺳﺍ", + "noNFTYet": "ﻥﻵﺍ ﻰﺘﺣ NFTs ﺪﺟﻮﻳ ﻻ", + "address": " ﻥﺍﻮﻨﻋ", + "enterTokenID": "ﺰﻴﻤﻤﻟﺍ ﺰﻣﺮﻟﺍ ﻑﺮﻌﻣ ﻞﺧﺩﺃ", + "tokenID": "ﻒﻳﺮﻌﺗ ﺔﻗﺎﻄﺑ", + "name": "ﻢﺳﺍ", + "symbol": "ﺰﻣﺭ", + "seed_phrase_length": "ﺭﻭﺬﺒﻟﺍ ﺓﺭﺎﺒﻌﻟﺍ ﻝﻮﻃ", + "unavailable_balance": "ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ", "unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ", "unspent_change": "يتغير", - "tor_connection": " ﺭﻮﺗ ﻝﺎﺼﺗﺍ" + "tor_connection": "ﺭﻮﺗ ﻝﺎﺼﺗﺍ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index b1851156c..1b3ded5d6 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -723,6 +723,13 @@ "require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли", "camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.", "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново", + "importNFTs": "Импортирайте NFT", + "noNFTYet": "Все още няма NFT", + "address": "Адрес", + "enterTokenID": "Въведете идентификатора на токена", + "tokenID": "документ за самоличност", + "name": "Име", + "symbol": "Символ", "seed_phrase_length": "Дължина на началната фраза", "unavailable_balance": "Неналично салдо", "unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 2e59f5fc5..4f0e89bd3 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -383,7 +383,7 @@ "change_backup_password_alert": "Vaše předchozí soubory se zálohami nebude možné naimportovat s novým heslem. Nové heslo bude použito pouze pro nové zálohy. Opravdu chcete změnit heslo pro zálohy?", "enter_backup_password": "Zde zadejte své heslo pro zálohy", "select_backup_file": "Vybrat soubor se zálohou", - "import": "Importovat", + "import": "Import", "please_select_backup_file": "Prosím vyberte soubor se zálohou a zadejte heslo pro zálohy.", "fixed_rate": "Pevný kurz", "fixed_rate_alert": "Když je zvolený pevný kurz, můžete zadat konkrétní částku, kterou chcete dostat. Chcete se přepnout do režimu s pevným kurzem?", @@ -723,6 +723,13 @@ "require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek", "camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.", "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu", + "importNFTs": "Importujte NFT", + "noNFTYet": "Zatím žádné NFT", + "address": "Adresa", + "enterTokenID": "Zadejte ID tokenu", + "tokenID": "ID", + "name": "název", + "symbol": "Symbol", "seed_phrase_length": "Délka fráze semene", "unavailable_balance": "Nedostupný zůstatek", "unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 7868553be..360e621db 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -731,6 +731,13 @@ "require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets", "camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.", "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut", + "importNFTs": "NFTs importieren", + "noNFTYet": "Noch keine NFTs", + "address": "Adresse", + "enterTokenID": "Geben Sie die Token-ID ein", + "tokenID": "AUSWEIS", + "name": "Name", + "symbol": "Symbol", "seed_phrase_length": "Länge der Seed-Phrase", "unavailable_balance": "Nicht verfügbares Guthaben", "unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index c3cd256d9..0f059759d 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -732,6 +732,13 @@ "require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets", "camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.", "switchToETHWallet": "Please switch to an Ethereum wallet and try again", + "importNFTs": "Import NFTs", + "noNFTYet": "No NFTs yet", + "address": "Address", + "enterTokenID": "Enter the token ID", + "tokenID": "ID", + "name": "Name", + "symbol": "Symbol", "seed_phrase_length": "Seed phrase length", "unavailable_balance": "Unavailable balance", "unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 4e624a9b4..8a4f180f6 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -731,6 +731,13 @@ "require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas", "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.", "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente.", + "importNFTs": "Importar NFT", + "noNFTYet": "Aún no hay NFT", + "address": "DIRECCIÓN", + "enterTokenID": "Ingrese el ID del token", + "tokenID": "IDENTIFICACIÓN", + "name": "Nombre", + "symbol": "Símbolo", "seed_phrase_length": "Longitud de la frase inicial", "unavailable_balance": "Saldo no disponible", "unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index d4d414029..158aaadb4 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -729,6 +729,15 @@ "exchange_provider_unsupported": "${providerName} n'est plus pris en charge !", "domain_looks_up": "Résolution de nom", "require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes", + "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", + "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", + "importNFTs": "Importer des NFT", + "noNFTYet": "Pas encore de NFT", + "address": "Adresse", + "enterTokenID": "Entrez l'ID du jeton", + "tokenID": "IDENTIFIANT", + "name": "Nom", + "symbol": "Symbole", "seed_phrase_length": "Longueur de la phrase de départ", "unavailable_balance": "Solde indisponible", "unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 0e2589b6a..8b6f38d05 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -709,6 +709,13 @@ "require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje", "camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.", "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa", + "importNFTs": "Shigo da NFTs", + "noNFTYet": "Babu NFTs tukuna", + "address": "Adireshi", + "enterTokenID": "Shigar da alamar alama", + "tokenID": "ID", + "name": "Suna", + "symbol": "Alama", "seed_phrase_length": "Tsawon jimlar iri", "unavailable_balance": "Ma'aunin da ba ya samuwa", "unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 19467af09..9afc420a2 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -731,6 +731,13 @@ "require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है", "camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।", "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें", + "importNFTs": "एनएफटी आयात करें", + "noNFTYet": "अभी तक कोई एनएफटी नहीं", + "address": "पता", + "enterTokenID": "टोकन आईडी दर्ज करें", + "tokenID": "पहचान", + "name": "नाम", + "symbol": "प्रतीक", "seed_phrase_length": "बीज वाक्यांश की लंबाई", "unavailable_balance": "अनुपलब्ध शेष", "unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 30eea10dc..fd4efa97e 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -383,7 +383,7 @@ "change_backup_password_alert": "Nećemo moći uvesti Vaše prethodne datoteke sigurnosne kopije s novom lozinkom za sigurnosnu kopiju. Novu lozinku za sigurnosnu kopiju moći ćete koristiti samo za nove datoteke sigurnosne kopije. Jeste li sigurni da želite promijeniti lozinku za sigurnosnu kopiju?", "enter_backup_password": "Unesite svoju lozinku za sigurnosnu kopiju ovdje", "select_backup_file": "Odaberite datoteku sigurnosne kopije", - "import": "Uvezi", + "import": "Uvoz", "please_select_backup_file": "Molimo odaberite datoteku sigurnosne kopije i unesite lozinku za sigurnosnu kopiju.", "fixed_rate": "Fiksna stopa", "fixed_rate_alert": "Moći ćete unijeti iznos koji želite primiti nakon što označite način rada fiksne stope. Želite li se prebaciti na način rada fiksne stope?", @@ -729,6 +729,13 @@ "require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike", "camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.", "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno", + "importNFTs": "Uvoz NFT-ova", + "noNFTYet": "Još nema NFT-ova", + "address": "Adresa", + "enterTokenID": "Unesite ID tokena", + "tokenID": "iskaznica", + "name": "Ime", + "symbol": "Simbol", "seed_phrase_length": "Duljina početne fraze", "unavailable_balance": "Nedostupno stanje", "unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index c10feffbc..4de382641 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -719,6 +719,13 @@ "require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal", "camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.", "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi", + "importNFTs": "Impor NFT", + "noNFTYet": "Belum ada NFT", + "address": "Alamat", + "enterTokenID": "Masukkan ID tokennya", + "tokenID": "PENGENAL", + "name": "Nama", + "symbol": "Simbol", "seed_phrase_length": "Panjang frase benih", "unavailable_balance": "Saldo tidak tersedia", "unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index a13930666..4fc35b3e3 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -383,7 +383,7 @@ "change_backup_password_alert": "I precedenti file di backup non potranno essere importati con la nuova password di backup. La nuova password di backup verrà usata soltanto per i nuovi file di backup. Sei sicuro di voler cambiare la tua password di backup?", "enter_backup_password": "Inserisci la password di backup qui", "select_backup_file": "Seleziona file di backup", - "import": "Importa", + "import": "Importare", "please_select_backup_file": "Gentilmente seleziona il file di backup e inserisci la password di backup.", "fixed_rate": "Tasso fisso", "fixed_rate_alert": "Potrai inserire l'ammontare da ricevere quando il tasso è fisso. Vuoi cambiare alla modalità tasso fisso?", @@ -731,6 +731,13 @@ "require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni", "camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.", "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova", + "importNFTs": "Importa NFT", + "noNFTYet": "Nessun NFT ancora", + "address": "Indirizzo", + "enterTokenID": "Inserisci l'ID del token", + "tokenID": "ID", + "name": "Nome", + "symbol": "Simbolo", "seed_phrase_length": "Lunghezza della frase seed", "unavailable_balance": "Saldo non disponibile", "unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 3e61dbd9d..a4fe8b46f 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -383,7 +383,7 @@ "change_backup_password_alert": "以前のバックアップファイルは、新しいバックアップパスワードでインポートできなくなります。 新しいバックアップパスワードは、新しいバックアップファイルにのみ使用されます。 バックアップパスワードを変更してもよろしいですか?", "enter_backup_password": "ここにバックアップパスワードを入力してください", "select_backup_file": "バックアップファイルを選択", - "import": "インポート", + "import": "輸入", "please_select_backup_file": "バックアップファイルを選択し、バックアップパスワードを入力してください。", "fixed_rate": "固定金利", "fixed_rate_alert": "固定金利モードにチェックを入れると、受取額を入力できるようになります。 固定金利モードに切り替えますか?", @@ -731,6 +731,13 @@ "require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要", "camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。", "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください", + "importNFTs": "NFTのインポート", + "noNFTYet": "NFTはまだありません", + "address": "住所", + "enterTokenID": "トークンIDを入力してください", + "tokenID": "ID", + "name": "名前", + "symbol": "シンボル", "seed_phrase_length": "シードフレーズの長さ", "unavailable_balance": "利用できない残高", "unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index de09c65d1..2b638e9d5 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -729,6 +729,13 @@ "require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요", "camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.", "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요.", + "importNFTs": "NFT 가져오기", + "noNFTYet": "아직 NFT가 없습니다", + "address": "주소", + "enterTokenID": "토큰 ID를 입력하세요", + "tokenID": "ID", + "name": "이름", + "symbol": "상징", "seed_phrase_length": "시드 문구 길이", "unavailable_balance": "사용할 수 없는 잔액", "unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 1853c0eff..19ee9c051 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -729,6 +729,13 @@ "require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", "camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။", "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။", + "importNFTs": "NFTs များကို တင်သွင်းပါ။", + "noNFTYet": "NFTs မရှိသေးပါ။", + "address": "လိပ်စာ", + "enterTokenID": "တိုကင် ID ကိုထည့်ပါ။", + "tokenID": "အမှတ်သညာ", + "name": "နာမည်", + "symbol": "သင်္ကေတ", "seed_phrase_length": "မျိုးစေ့စာပိုဒ်တိုအရှည်", "unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။", "unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index a497c20ab..838fec0c1 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -731,6 +731,13 @@ "require_for_exchanges_to_external_wallets": "Vereist voor uitwisselingen naar externe portemonnees", "camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.", "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw", + "importNFTs": "NFT's importeren", + "noNFTYet": "Nog geen NFT's", + "address": "Adres", + "enterTokenID": "Voer de token-ID in", + "tokenID": "ID kaart", + "name": "Naam", + "symbol": "Symbool", "seed_phrase_length": "Lengte van de zaadzin", "unavailable_balance": "Onbeschikbaar saldo", "unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index dc69468bd..309f20613 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -383,7 +383,7 @@ "change_backup_password_alert": "Twoje poprzednie pliki kopii zapasowej nie będą dostępne do zaimportowania z nowym hasłem kopii zapasowej. Nowe hasło kopii zapasowej będzie używane tylko dla nowych plików kopii zapasowych. Czy na pewno chcesz zmienić hasło zapasowe?", "enter_backup_password": "Wprowadź tutaj hasło kopii zapasowej", "select_backup_file": "Wybierz plik kopii zapasowej", - "import": "Zaimportuj", + "import": "Import", "please_select_backup_file": "Wybierz plik kopii zapasowej i wprowadź hasło.", "fixed_rate": "Stała stawka", "fixed_rate_alert": "Będziesz mógł wprowadzić kwotę do otrzymania, gdy wybrany bedzie tryb stałego przeliczenia. Czy chcesz przejść do trybu stałej stawki?", @@ -731,6 +731,13 @@ "require_for_exchanges_to_external_wallets": "Wymagaj wymiany na portfele zewnętrzne", "camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.", "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie", + "importNFTs": "Importuj NFT", + "noNFTYet": "Nie ma jeszcze NFT", + "address": "Adres", + "enterTokenID": "Wprowadź identyfikator tokena", + "tokenID": "ID", + "name": "Nazwa", + "symbol": "Symbol", "seed_phrase_length": "Długość frazy początkowej", "unavailable_balance": "Niedostępne saldo", "unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index c6d22ae23..8feeb732c 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -730,6 +730,13 @@ "require_for_exchanges_to_external_wallets": "Exigir trocas para carteiras externas", "camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.", "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente", + "importNFTs": "Importar NFTs", + "noNFTYet": "Ainda não há NFT", + "address": "Endereço", + "enterTokenID": "Insira o ID do token", + "tokenID": "EU IA", + "name": "Nome", + "symbol": "Símbolo", "seed_phrase_length": "Comprimento da frase-semente", "unavailable_balance": "Saldo indisponível", "unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 50bef718d..98eddcae7 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -731,6 +731,13 @@ "require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки", "camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.", "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку.", + "importNFTs": "Импортировать NFT", + "noNFTYet": "NFT пока нет", + "address": "Адрес", + "enterTokenID": "Введите идентификатор токена", + "tokenID": "ИДЕНТИФИКАТОР", + "name": "Имя", + "symbol": "Символ", "seed_phrase_length": "Длина исходной фразы", "unavailable_balance": "Недоступный баланс", "unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 95a1cd406..c9cfca47c 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -729,6 +729,13 @@ "require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก", "camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป", "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง", + "importNFTs": "นำเข้า NFT", + "noNFTYet": "ยังไม่มี NFT", + "address": "ที่อยู่", + "enterTokenID": "ป้อนรหัสโทเค็น", + "tokenID": "บัตรประจำตัวประชาชน", + "name": "ชื่อ", + "symbol": "เครื่องหมาย", "seed_phrase_length": "ความยาววลีของเมล็ด", "unavailable_balance": "ยอดคงเหลือไม่พร้อมใช้งาน", "unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 960432a1b..d68dbc656 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -726,6 +726,13 @@ "require_for_exchanges_to_external_wallets": "Kinakailangan para sa mga palitan sa mga panlabas na wallet", "camera_permission_is_required": "Kinakailangan ang pahintulot sa camera.\nMangyaring paganahin ito mula sa mga setting ng app.", "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli", + "importNFTs": "Mag-import ng mga NFT", + "noNFTYet": "Wala pang NFT", + "address": "Address", + "enterTokenID": "Ilagay ang token ID", + "tokenID": "ID", + "name": "Pangalan", + "symbol": "Simbolo", "seed_phrase_length": "Haba ng parirala ng binhi", "unavailable_balance": "Hindi available na balanse", "unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 1b7982504..c0fc58feb 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -383,7 +383,7 @@ "change_backup_password_alert": "Önceki yedekleme dosyaların yeni yedek parolası ile içe aktarılamayacaktır. Yeni yedekleme parolası yalnızca yeni yedekleme dosyaları için kullanılabilir olacak. Yedekleme parolasını değiştirmek istediğinden emin misin?", "enter_backup_password": "Yedekleme parolasını buraya gir", "select_backup_file": "Yedek dosyası seç", - "import": "İçe aktar", + "import": "İçe aktarmak", "please_select_backup_file": "Lütfen yedekleme dosyasını seç ve yedekleme parolasını gir.", "fixed_rate": "Sabit oran", "fixed_rate_alert": "Sabit oran modunu işaretlersen alım tutarını girebilirsin. Sabit oran moduna geçmek ister misin?", @@ -729,6 +729,13 @@ "require_for_exchanges_to_external_wallets": "Harici cüzdanlara geçiş yapılmasını zorunlu kılın", "camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.", "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin", + "importNFTs": "NFT'leri içe aktar", + "noNFTYet": "Henüz NFT yok", + "address": "Adres", + "enterTokenID": "Belirteç kimliğini girin", + "tokenID": "İD", + "name": "İsim", + "symbol": "Sembol", "seed_phrase_length": "Çekirdek cümle uzunluğu", "unavailable_balance": "Kullanılamayan bakiye", "unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 849542e6f..0ad5fa97a 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -383,7 +383,7 @@ "change_backup_password_alert": "Ваші попередні файли резервних копій будуть недоступні для імпорту з новим паролем резервної копії. Новий пароль резервної копії буде використовуватися тільки для нових файлів резервних копій. Ви впевнені, що хочете змінити пароль резервної копії?", "enter_backup_password": "Введіть пароль резервної копії", "select_backup_file": "Виберіть файл резервної копії", - "import": "Імпортувати", + "import": "Імпорт", "please_select_backup_file": "Виберіть файл резервної копії та введіть пароль резервної копії.", "fixed_rate": "Фіксована ставка", "fixed_rate_alert": "Ви зможете ввести суму отримання тоді, коли буде встановлений режим фіксованої ставки. Ви хочете перейти в режим фіксованої ставки?", @@ -731,6 +731,13 @@ "require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці", "camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.", "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу", + "importNFTs": "Імпорт NFT", + "noNFTYet": "NFT ще немає", + "address": "Адреса", + "enterTokenID": "Введіть ідентифікатор токена", + "tokenID": "ID", + "name": "Ім'я", + "symbol": "символ", "seed_phrase_length": "Довжина початкової фрази", "unavailable_balance": "Недоступний баланс", "unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 0b7e4c0a7..e26c3b4d4 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -384,7 +384,7 @@ "change_backup_password_alert": "آپ کی پچھلی بیک اپ فائلیں نئے بیک اپ پاس ورڈ کے ساتھ درآمد کرنے کے لیے دستیاب نہیں ہوں گی۔ نیا بیک اپ پاس ورڈ صرف نئی بیک اپ فائلوں کے لیے استعمال کیا جائے گا۔ کیا آپ واقعی بیک اپ پاس ورڈ تبدیل کرنا چاہتے ہیں؟", "enter_backup_password": "یہاں بیک اپ پاس ورڈ درج کریں۔", "select_backup_file": "بیک اپ فائل کو منتخب کریں۔", - "import": "درآمد کریں۔", + "import": " ۔ﮟﯾﺮﮐ ﺪﻣﺁﺭﺩ", "please_select_backup_file": "براہ کرم بیک اپ فائل منتخب کریں اور بیک اپ پاس ورڈ درج کریں۔", "fixed_rate": "مقررہ شرح", "fixed_rate_alert": "فکسڈ ریٹ موڈ چیک ہونے پر آپ وصولی رقم درج کر سکیں گے۔ کیا آپ فکسڈ ریٹ موڈ پر سوئچ کرنا چاہتے ہیں؟", @@ -723,9 +723,16 @@ "require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ", "camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ", "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ", - "seed_phrase_length": " ﯽﺋﺎﺒﻤﻟ ﯽﮐ ﮯﻠﻤﺟ ﮯﮐ ﺞﯿﺑ", - "unavailable_balance": " ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ", + "importNFTs": "NFTs ۔ﮟﯾﺮﮐ ﺪﻣﺁﺭﺩ", + "noNFTYet": "۔ﮟﯿﮨ ﮟﯿﮩﻧ NFTs ﯽﺋﻮﮐ ﮏﺗ ﯽﮭﺑﺍ", + "address": "ﮧﺘﭘ", + "enterTokenID": " ۔ﮟﯾﺮﮐ ﺝﺭﺩ ID ﻦﮐﻮﭨ", + "tokenID": "ID", + "name": "ﻡﺎﻧ", + "symbol": "ﺖﻣﻼﻋ", + "seed_phrase_length": "ﯽﺋﺎﺒﻤﻟ ﯽﮐ ﮯﻠﻤﺟ ﮯﮐ ﺞﯿﺑ", + "unavailable_balance": "ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ", "unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ", "unspent_change": "تبدیل کریں", - "tor_connection": " ﻦﺸﮑﻨﮐ ﺭﻮﭨ" + "tor_connection": "ﻦﺸﮑﻨﮐ ﺭﻮﭨ" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 57962b38e..d512f5e8f 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -381,7 +381,7 @@ "change_backup_password_alert": "Ẹ kò lè fi ọ̀rọ̀ aṣínà títun ti ẹ̀dà nípamọ́ ṣí àwọn àkọsílẹ̀ nípamọ́ tẹ́lẹ̀tẹ́lẹ̀ yín. Ẹ máa fi ọ̀rọ̀ aṣínà ti ẹ̀dà nípamọ́ títun ṣí àwọn àkọsílẹ̀ nípamọ́ títun nìkan. Ṣé ó dá ẹ lójú pé ẹ fẹ́ pààrọ̀ aṣínà ti ẹ̀dà nípamọ́?", "enter_backup_password": "Tẹ̀ ọ̀rọ̀ aṣínà ti ẹ̀dà ḿbí", "select_backup_file": "Select backup file", - "import": "Gba wọlé", + "import": "gbe wọle", "please_select_backup_file": "Ẹ jọ̀wọ́ yan àkọsílẹ̀ nípamọ́ àti tẹ̀ ọ̀rọ̀ aṣínà ti ẹ̀dà.", "fixed_rate": "Iye t'á ṣẹ́ owó sí ò ní pààrọ̀", "fixed_rate_alert": "Ẹ lè tẹ̀ iye owó tó ń bọ̀ tí iye t'a ṣẹ́ owó sí bá is checked. Ṣé ẹ fẹ́ sún ipò ti iye t'á ṣẹ́ owó sí ò ní pààrọ̀ mọ́?", @@ -725,6 +725,13 @@ "require_for_exchanges_to_external_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ ita", "camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.", "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi", + "importNFTs": "Gbe awọn NFT wọle", + "noNFTYet": "Ko si awọn NFT sibẹsibẹ", + "address": "Adirẹsi", + "enterTokenID": "Tẹ ID ami sii", + "tokenID": "ID", + "name": "Oruko", + "symbol": "Aami", "seed_phrase_length": "Gigun gbolohun irugbin", "unavailable_balance": "Iwontunwonsi ti ko si", "unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 0862f20e2..974008594 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -382,7 +382,7 @@ "change_backup_password_alert": "您以前的备份文件将无法使用新的备份密码導入。 新的备份密码将仅用于新的备份文件。 您确定要更改备份密码吗?", "enter_backup_password": "在此处输入備用密码", "select_backup_file": "选择备份文件", - "import": "导入", + "import": "进口", "please_select_backup_file": "请选择备份文件,然后输入备份密码。", "fixed_rate": "固定汇率", "fixed_rate_alert": "选中固定汇率模式后,您将可以输入接收金额。 您要切换到固定汇率模式吗?", @@ -730,6 +730,13 @@ "require_for_exchanges_to_external_wallets": "需要兑换到外部钱包", "camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。", "switchToETHWallet": "请切换到以太坊钱包并重试", + "importNFTs": "导入 NFT", + "noNFTYet": "还没有 NFT", + "address": "地址", + "enterTokenID": "输入令牌 ID", + "tokenID": "ID", + "name": "姓名", + "symbol": "象征", "seed_phrase_length": "种子短语长度", "unavailable_balance": "不可用余额", "unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。", diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index a8c6a6166..163b80135 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -36,6 +36,7 @@ class SecretKey { SecretKey('robinhoodApplicationId', () => ''), SecretKey('robinhoodCIdApiSecret', () => ''), SecretKey('walletConnectProjectId', () => ''), + SecretKey('moralisApiKey', () => '') ]; static final ethereumSecrets = [ From 217c19272fb2f8262b0c213ec1370d8b72c3863f Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 22 Nov 2023 23:37:05 +0200 Subject: [PATCH 046/241] pre seed page refactoring --- lib/di.dart | 16 +++++------ lib/router.dart | 10 +++---- lib/routes.dart | 2 +- .../screens/new_wallet/new_wallet_page.dart | 2 +- .../{pre_seed_page.dart => warning_page.dart} | 28 ++++--------------- lib/view_model/wallet_new_vm.dart | 17 ++++++++++- 6 files changed, 35 insertions(+), 40 deletions(-) rename lib/src/screens/seed/{pre_seed_page.dart => warning_page.dart} (76%) diff --git a/lib/di.dart b/lib/di.dart index d6a43030a..3c2c87783 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -129,7 +129,7 @@ import 'package:cake_wallet/src/screens/rescan/rescan_page.dart'; import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart'; import 'package:cake_wallet/src/screens/restore/restore_options_page.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; -import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart'; +import 'package:cake_wallet/src/screens/seed/warning_page.dart'; import 'package:cake_wallet/src/screens/seed/wallet_seed_page.dart'; import 'package:cake_wallet/src/screens/send/send_template_page.dart'; import 'package:cake_wallet/src/screens/setup_pin_code/setup_pin_code.dart'; @@ -337,6 +337,9 @@ Future setup({ settingsStore: getIt.get(), walletInfoSource: _walletInfoSource)); + getIt.registerFactoryParam( + (type, _) => AdvancedPrivacySettingsViewModel(type, getIt.get())); + getIt.registerFactory(() => WalletLoadingService( getIt.get(), getIt.get(), @@ -345,7 +348,7 @@ Future setup({ getIt.registerFactoryParam((type, _) => WalletNewVM(getIt.get(), getIt.get(param1: type), _walletInfoSource, - type: type)); + getIt.get(param1: type),type: type)); getIt.registerFactoryParam((WalletType type, _) { return WalletRestorationFromQRVM(getIt.get(), @@ -900,9 +903,9 @@ Future setup({ getIt.registerFactoryParam( (param1, isCreate) => NewWalletTypePage(onTypeSelected: param1, isCreate: isCreate ?? true)); - getIt.registerFactoryParam( - (WalletType type, AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel) - => PreSeedPage(type, advancedPrivacySettingsViewModel)); + getIt.registerFactoryParam( + (seedPhraseLength, _) + => WarningPage(seedPhraseLength)); getIt.registerFactoryParam((trade, _) => TradeDetailsViewModel( @@ -1149,9 +1152,6 @@ Future setup({ IoniaPaymentStatusPage( getIt.get(param1: paymentInfo, param2: committedInfo))); - getIt.registerFactoryParam( - (type, _) => AdvancedPrivacySettingsViewModel(type, getIt.get())); - getIt.registerFactoryParam((balanceViewModel, _) => HomeSettingsPage(getIt.get(param1: balanceViewModel))); diff --git a/lib/router.dart b/lib/router.dart index 75f491dfc..f51a0a6db 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -40,7 +40,7 @@ import 'package:cake_wallet/src/screens/order_details/order_details_page.dart'; import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; -import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart'; +import 'package:cake_wallet/src/screens/seed/warning_page.dart'; import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart'; import 'package:cake_wallet/src/screens/settings/tor_page.dart'; @@ -417,12 +417,10 @@ Route createRoute(RouteSettings settings) { case Routes.faq: return MaterialPageRoute(builder: (_) => getIt.get()); - case Routes.preSeed: + case Routes.warningPage: return MaterialPageRoute( - builder: (_) => getIt.get( - param1: settings.arguments as WalletType, - param2: getIt.get( - param1: settings.arguments as WalletType))); + builder: (_) => getIt.get( + param1: settings.arguments as int)); case Routes.backup: return CupertinoPageRoute( diff --git a/lib/routes.dart b/lib/routes.dart index 4c1a917ab..9b3e8fbba 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -47,7 +47,7 @@ class Routes { static const exchangeTemplate = '/exchange_template'; static const restoreWalletType = '/restore_wallet_type'; static const restoreWallet = '/restore_wallet'; - static const preSeed = '/pre_seed'; + static const warningPage = '/warning_page'; static const backup = '/backup'; static const editBackupPassword = '/edit_backup_passowrd'; static const restoreFromBackup = '/restore_from_backup'; diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index 5577fcd88..040aa85ea 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -67,7 +67,7 @@ class _WalletNameFormState extends State { _stateReaction ??= reaction((_) => _walletNewVM.state, (ExecutionState state) async { if (state is ExecutedSuccessfullyState) { Navigator.of(navigatorKey.currentContext!) - .pushNamed(Routes.preSeed, arguments: _walletNewVM.type); + .pushNamed(Routes.warningPage, arguments: _walletNewVM.seedPhraseWordsLength); } if (state is FailureState) { diff --git a/lib/src/screens/seed/pre_seed_page.dart b/lib/src/screens/seed/warning_page.dart similarity index 76% rename from lib/src/screens/seed/pre_seed_page.dart rename to lib/src/screens/seed/warning_page.dart index 947099983..24e476373 100644 --- a/lib/src/screens/seed/pre_seed_page.dart +++ b/lib/src/screens/seed/warning_page.dart @@ -9,20 +9,14 @@ import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:flutter/material.dart'; -class PreSeedPage extends BasePage { - PreSeedPage(this.type, this.advancedPrivacySettingsViewModel) +class WarningPage extends BasePage { + WarningPage(this.seedPhraseLength) : imageLight = Image.asset('assets/images/pre_seed_light.png'), - imageDark = Image.asset('assets/images/pre_seed_dark.png'), - seedPhraseLength = advancedPrivacySettingsViewModel.seedPhraseLength.value { - wordsCount = _wordsCount(type, seedPhraseLength); - } + imageDark = Image.asset('assets/images/pre_seed_dark.png'); final Image imageDark; final Image imageLight; - final WalletType type; - final AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel; - final int seedPhraseLength; - late final int wordsCount; + final int? seedPhraseLength; @override Widget? leading(BuildContext context) => null; @@ -53,7 +47,7 @@ class PreSeedPage extends BasePage { Padding( padding: EdgeInsets.all(10), child: Text( - S.of(context).pre_seed_description(wordsCount.toString()), + S.of(context).pre_seed_description(seedPhraseLength.toString()), textAlign: TextAlign.center, style: TextStyle( fontSize: 14, @@ -72,16 +66,4 @@ class PreSeedPage extends BasePage { ), )); } - - static int _wordsCount(WalletType type, int seedPhraseLength) { - switch (type) { - case WalletType.monero: - return 25; - case WalletType.ethereum: - case WalletType.bitcoinCash: - return seedPhraseLength; - default: - return 24; - } - } } diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart index 9b1f0834d..d210f1aab 100644 --- a/lib/view_model/wallet_new_vm.dart +++ b/lib/view_model/wallet_new_vm.dart @@ -15,6 +15,7 @@ import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/view_model/wallet_creation_vm.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/haven/haven.dart'; +import 'advanced_privacy_settings_view_model.dart'; part 'wallet_new_vm.g.dart'; @@ -22,16 +23,30 @@ class WalletNewVM = WalletNewVMBase with _$WalletNewVM; abstract class WalletNewVMBase extends WalletCreationVM with Store { WalletNewVMBase(AppStore appStore, WalletCreationService walletCreationService, - Box walletInfoSource, + Box walletInfoSource, this.advancedPrivacySettingsViewModel, {required WalletType type}) : selectedMnemonicLanguage = '', super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: false); + final AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel; + @observable String selectedMnemonicLanguage; bool get hasLanguageSelector => type == WalletType.monero || type == WalletType.haven; + int get seedPhraseWordsLength { + switch (type) { + case WalletType.monero: + return 25; + case WalletType.ethereum: + case WalletType.bitcoinCash: + return advancedPrivacySettingsViewModel.seedPhraseLength.value; + default: + return 24; + } + } + @override WalletCredentials getCredentials(dynamic options) { switch (type) { From b87c11bbe47b84fa762f776c6c3ac1cb7c929c84 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 23 Nov 2023 16:51:22 +0200 Subject: [PATCH 047/241] fix 2fa UI --- assets/images/setup_2fa_img.png | Bin 0 -> 20129 bytes lib/di.dart | 2 +- lib/router.dart | 2 +- lib/src/screens/receive/widgets/qr_image.dart | 8 +- lib/src/screens/seed/warning_page.dart | 40 ++++--- .../settings/security_backup_page.dart | 2 +- lib/src/screens/setup_2fa/setup_2fa.dart | 60 +++++----- .../screens/setup_2fa/setup_2fa_qr_page.dart | 109 +++++++++--------- 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_hi.arb | 1 - res/values/strings_hr.arb | 1 - res/values/strings_id.arb | 1 - res/values/strings_it.arb | 1 - res/values/strings_ja.arb | 1 - res/values/strings_ko.arb | 1 - res/values/strings_my.arb | 1 - res/values/strings_nl.arb | 1 - res/values/strings_pl.arb | 1 - res/values/strings_pt.arb | 1 - res/values/strings_ru.arb | 1 - res/values/strings_th.arb | 1 - res/values/strings_tl.arb | 1 - res/values/strings_tr.arb | 1 - res/values/strings_uk.arb | 1 - res/values/strings_ur.arb | 1 - res/values/strings_yo.arb | 1 - res/values/strings_zh.arb | 1 - 33 files changed, 114 insertions(+), 134 deletions(-) create mode 100644 assets/images/setup_2fa_img.png diff --git a/assets/images/setup_2fa_img.png b/assets/images/setup_2fa_img.png new file mode 100644 index 0000000000000000000000000000000000000000..3df3bdaddaa907f7d908892dd15d3978db38519c GIT binary patch literal 20129 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 setup({ getIt.registerFactoryParam( (param1, isCreate) => NewWalletTypePage(onTypeSelected: param1, isCreate: isCreate ?? true)); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (seedPhraseLength, _) => WarningPage(seedPhraseLength)); diff --git a/lib/router.dart b/lib/router.dart index f51a0a6db..f622006e2 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -420,7 +420,7 @@ Route createRoute(RouteSettings settings) { case Routes.warningPage: return MaterialPageRoute( builder: (_) => getIt.get( - param1: settings.arguments as int)); + param1: settings.arguments as int?)); case Routes.backup: return CupertinoPageRoute( diff --git a/lib/src/screens/receive/widgets/qr_image.dart b/lib/src/screens/receive/widgets/qr_image.dart index f4c1eb177..f388fdd0b 100644 --- a/lib/src/screens/receive/widgets/qr_image.dart +++ b/lib/src/screens/receive/widgets/qr_image.dart @@ -4,12 +4,16 @@ import 'package:qr_flutter/qr_flutter.dart' as qr; class QrImage extends StatelessWidget { QrImage({ required this.data, + this.foregroundColor = Colors.black, + this.backgroundColor = Colors.white, this.size = 100.0, this.version, this.errorCorrectionLevel = qr.QrErrorCorrectLevel.L, }); final double size; + final Color foregroundColor; + final Color backgroundColor; final String data; final int? version; final int errorCorrectionLevel; @@ -21,8 +25,8 @@ class QrImage extends StatelessWidget { errorCorrectionLevel: errorCorrectionLevel, version: version ?? 9, // Previous value: 7 something happened after flutter upgrade monero wallets addresses are longer than ver. 7 ??? size: size, - foregroundColor: Colors.black, - backgroundColor: Colors.white, + foregroundColor: foregroundColor, + backgroundColor: backgroundColor, padding: const EdgeInsets.all(8.0), ); } diff --git a/lib/src/screens/seed/warning_page.dart b/lib/src/screens/seed/warning_page.dart index 24e476373..cd7c3b1f6 100644 --- a/lib/src/screens/seed/warning_page.dart +++ b/lib/src/screens/seed/warning_page.dart @@ -11,15 +11,17 @@ import 'package:flutter/material.dart'; class WarningPage extends BasePage { WarningPage(this.seedPhraseLength) - : imageLight = Image.asset('assets/images/pre_seed_light.png'), + : isPreSeedPage = seedPhraseLength != null, + imageLight = Image.asset('assets/images/pre_seed_light.png'), imageDark = Image.asset('assets/images/pre_seed_dark.png'); final Image imageDark; final Image imageLight; final int? seedPhraseLength; + final bool isPreSeedPage; @override - Widget? leading(BuildContext context) => null; + Widget? leading(BuildContext context) => isPreSeedPage ? null : super.leading(context); @override String? get title => S.current.pre_seed_title; @@ -28,37 +30,43 @@ class WarningPage extends BasePage { Widget body(BuildContext context) { final image = currentTheme.type == ThemeType.dark ? imageDark : imageLight; + final text = + "Cake 2FA is a second authentication for certain actions in the wallet. It is NOT as secure as cold storage. If you lose access to your 2FA app or passkeys, you WILL lose access to this wallet. You will need to restore your wallet from the mnemonic seed. Cake support will be unable to assist you if you lose access to your 2FA or mnemonic seeds. Before using Cake 2FA, we recommend reading through the guide here."; + return WillPopScope( onWillPop: () async => false, child: Container( alignment: Alignment.center, padding: EdgeInsets.all(24), child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), + constraints: + BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ConstrainedBox( - constraints: BoxConstraints( - maxHeight: MediaQuery.of(context).size.height * 0.3 - ), + constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.3), child: AspectRatio(aspectRatio: 1, child: image), ), Padding( padding: EdgeInsets.all(10), child: Text( - S.of(context).pre_seed_description(seedPhraseLength.toString()), - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.normal, - color: Theme.of(context).extension()!.secondaryTextColor), - ), + isPreSeedPage + ? S.of(context).pre_seed_description(seedPhraseLength.toString()) + : text, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + color: isPreSeedPage + ? Theme.of(context).extension()!.secondaryTextColor + : Theme.of(context).extension()!.titleColor)), ), PrimaryButton( - onPressed: () => - Navigator.of(context).popAndPushNamed(Routes.seed, arguments: true), - text: S.of(context).pre_seed_button_text, + onPressed: () => isPreSeedPage + ? Navigator.of(context).popAndPushNamed(Routes.seed, arguments: true) + : Navigator.of(context).popAndPushNamed(Routes.setup_2faPage), + text: isPreSeedPage ? S.of(context).pre_seed_button_text : 'Neeeeeeee', color: Theme.of(context).primaryColor, textColor: Colors.white) ], diff --git a/lib/src/screens/settings/security_backup_page.dart b/lib/src/screens/settings/security_backup_page.dart index a0fb16cb6..c6fa939de 100644 --- a/lib/src/screens/settings/security_backup_page.dart +++ b/lib/src/screens/settings/security_backup_page.dart @@ -108,7 +108,7 @@ class SecurityBackupPage extends BasePage { context, route: _securitySettingsViewModel.useTotp2FA ? Routes.modify2FAPage - : Routes.setup_2faPage, + : Routes.warningPage, conditionToDetermineIfToUse2FA: _securitySettingsViewModel .shouldRequireTOTP2FAForAllSecurityAndBackupSettings, ), diff --git a/lib/src/screens/setup_2fa/setup_2fa.dart b/lib/src/screens/setup_2fa/setup_2fa.dart index 3bdd49f5b..9d8ffe839 100644 --- a/lib/src/screens/setup_2fa/setup_2fa.dart +++ b/lib/src/screens/setup_2fa/setup_2fa.dart @@ -1,13 +1,12 @@ import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; -import 'package:flutter/material.dart'; - import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart'; +import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/view_model/set_up_2fa_viewmodel.dart'; - -import '../../widgets/standard_list.dart'; +import 'package:flutter/material.dart'; +import 'package:url_launcher/url_launcher.dart'; class Setup2FAPage extends BasePage { Setup2FAPage({required this.setup2FAViewModel}); @@ -21,36 +20,27 @@ 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://guides.cakewallet.com/docs/advanced-features/authentication'); return SingleChildScrollView( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ + ConstrainedBox( + constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.3), + child: + AspectRatio(aspectRatio: 1, child: Image.asset('assets/images/setup_2fa_img.png')), + ), Padding( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - S.current.important_note, - style: TextStyle( - fontWeight: FontWeight.w700, - fontSize: 14, - height: 1.571, - color: Theme.of(context).extension()!.titleColor, - ), - ), - SizedBox(height: 16), - Text( - S.current.setup_2fa_text, - style: TextStyle( - fontWeight: FontWeight.w400, - fontSize: 14, - height: 1.571, - color: Theme.of(context).extension()!.titleColor, - ), - ), - ], + child: Text( + S.current.setup_2fa_text, + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.w400, + fontSize: 14, + height: 1.571, + color: Theme.of(context).extension()!.titleColor, + ), ), ), SizedBox(height: 56), @@ -63,12 +53,16 @@ class Setup2FAPage extends BasePage { ), StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), SettingsCellWithArrow( - title: cake2FAGuideTitle, - handler: (_) => Navigator.of(context) - .pushNamed(Routes.webViewPage, arguments: [cake2FAGuideTitle, cake2FAGuideUri])), + title: cake2FAGuideTitle, handler: (_) => _launchUrl(cake2FAGuideUri)), StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), ], ), ); } + + static void _launchUrl(Uri url) async { + try { + await launchUrl(url); + } catch (e) {} + } } 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 a50c64aa0..620f13670 100644 --- a/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart +++ b/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart @@ -4,8 +4,8 @@ import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/standard_list.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/palette.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'; @@ -13,6 +13,7 @@ import 'package:cake_wallet/view_model/set_up_2fa_viewmodel.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:qr_flutter/qr_flutter.dart' as qr; +import 'package:url_launcher/url_launcher.dart'; class Setup2FAQRPage extends BasePage { Setup2FAQRPage({required this.setup2FAViewModel}); @@ -24,12 +25,8 @@ class Setup2FAQRPage extends BasePage { @override Widget body(BuildContext context) { - final copyImage = Image.asset( - 'assets/images/copy_content.png', - height: 12, - width: 12, - color: Color(0xFF355688), - ); + final copyImage = Image.asset('assets/images/copy_content.png', + height: 16, width: 16, color: Theme.of(context).extension()!.titleColor); final cake2FAHowToUseTitle = 'How to use'; final cake2FAHowToUseUrl = Uri.parse( 'https://guides.cakewallet.com/docs/advanced-features/authentication/#enabling-cake-2fa'); @@ -37,41 +34,49 @@ class Setup2FAQRPage extends BasePage { padding: const EdgeInsets.symmetric(horizontal: 24), child: Column( children: [ - SizedBox(height: 58), + Spacer(), Text( S.current.add_secret_code, style: TextStyle( fontSize: 14, fontWeight: FontWeight.w700, height: 1.5714, - color: Palette.darkBlueCraiola, + color: Theme.of(context).extension()!.titleColor, ), ), SizedBox(height: 10), - AspectRatio( - aspectRatio: 1.0, - child: Container( - padding: EdgeInsets.all(5), - decoration: BoxDecoration( - border: Border.all( - width: 3, - color: Theme.of(context).extension()!.textColor, - ), - ), + ConstrainedBox( + constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.4), + child: AspectRatio( + aspectRatio: 1.0, child: Container( - decoration: BoxDecoration( - border: Border.all( - width: 3, - color: Colors.white, - ), + padding: EdgeInsets.all(5), + decoration: BoxDecoration( + border: Border.all( + width: 3, + color: Theme.of(context).extension()!.textColor, ), - child: QrImage( - data: setup2FAViewModel.totpVersionOneLink, - version: qr.QrVersions.auto, - )), + ), + child: Container( + child: QrImage( + data: setup2FAViewModel.totpVersionOneLink, + version: qr.QrVersions.auto, + foregroundColor: Theme.of(context).extension()!.titleColor, + backgroundColor: Colors.transparent, + )), + ), + ), + ), + SizedBox(height: 26), + Text( + S.current.add_secret_code, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w700, + height: 1.5714, + color: Theme.of(context).extension()!.titleColor, ), ), - SizedBox(height: 13), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, @@ -86,7 +91,7 @@ class Setup2FAQRPage extends BasePage { style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, - color: Palette.darkGray, + color: Theme.of(context).extension()!.secondaryTextColor, height: 1.8333, ), ), @@ -94,10 +99,8 @@ class Setup2FAQRPage extends BasePage { Text( '${setup2FAViewModel.totpSecretKey}', style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w700, - height: 1.375, - ), + fontSize: 18, + color: Theme.of(context).extension()!.titleColor), maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -115,10 +118,6 @@ class Setup2FAQRPage extends BasePage { showBar(context, S.of(context).copied_to_clipboard); }, child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(6), - color: Color(0xFFF2F0FA), - ), child: copyImage, ), ), @@ -142,7 +141,7 @@ class Setup2FAQRPage extends BasePage { style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, - color: Palette.darkGray, + color: Theme.of(context).extension()!.secondaryTextColor, height: 1.8333, ), ), @@ -150,10 +149,8 @@ class Setup2FAQRPage extends BasePage { Text( '${setup2FAViewModel.totpVersionOneLink}', style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w700, - height: 1.375, - ), + fontSize: 18, + color: Theme.of(context).extension()!.titleColor), maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -171,10 +168,6 @@ class Setup2FAQRPage extends BasePage { showBar(context, S.of(context).copied_to_clipboard); }, child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(6), - color: Color(0xFFF2F0FA), - ), child: copyImage, ), ), @@ -185,22 +178,22 @@ class Setup2FAQRPage extends BasePage { StandardListSeparator(), SizedBox(height: 16), GestureDetector( - onTap: () => Navigator.of(context).pushNamed(Routes.webViewPage, - arguments: [cake2FAHowToUseTitle, cake2FAHowToUseUrl]), + onTap: () => _launchUrl(cake2FAHowToUseUrl), child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ Text(cake2FAHowToUseTitle, style: TextStyle( - decoration: TextDecoration.underline, - fontSize: 16, - fontWeight: FontWeight.w700, - )), - Icon(Icons.info_outline,size: 20) + decoration: TextDecoration.underline, + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).extension()!.titleColor)), + Icon(Icons.info_outline, + size: 20, color: Theme.of(context).extension()!.titleColor) ], )), - Spacer(), + Spacer(flex: 5), PrimaryButton( onPressed: () { Navigator.of(context).pushReplacementNamed(Routes.totpAuthCodePage, @@ -217,4 +210,10 @@ class Setup2FAQRPage extends BasePage { ), ); } + + static void _launchUrl(Uri url) async { + try { + await launchUrl(url); + } catch (e) {} + } } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 84a0a72f5..257ad2d6d 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -623,7 +623,6 @@ "enter_totp_code": "الرجاء إدخال رمز TOTP.", "add_secret_code": "أضف هذا الرمز السري إلى جهاز آخر", "totp_secret_code": "كود TOTP السري", - "important_note": "ملاحظة مهمة", "setup_2fa_text": "كعكة 2FA ليست آمنة مثل التخزين البارد. تحمي 2FA من الأنواع الأساسية للهجمات ، مثل قيام صديقك بتقديم بصمة إصبعك أثناء نومك. لا تحمي Cake 2FA من جهاز مخترق من قِبل مهاجم متطور. إذا فقدت الوصول إلى رموز 2FA الخاصة بك ، ستفقد إمكانية الوصول إلى هذه المحفظة. سوف تحتاج إلى استعادة محفظتك من بذرة ذاكري. يجب عليك بالتالي الاحتفاظ بنسخة احتياطية من بذور الذاكرة الخاصة بك! علاوة على ذلك ، سيتمكن أي شخص لديه حق الوصول إلى بذرة (بذور) ذاكري من سرقة أموالك ، متجاوزًا Cake 2FA. لن يتمكن فريق دعم الكيك من مساعدتك إذا فقدت الوصول إلى بذرتك ، نظرًا لأن Cake هي المحفظة غير الحافظة.", "setup_totp_recommended": "إعداد TOTP (موصى به)", "disable_buy": "تعطيل إجراء الشراء", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index b1851156c..3dcd335e5 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -619,7 +619,6 @@ "enter_totp_code": "Моля, въведете TOTP кода.", "add_secret_code": "Добавете този таен код към друго устройство", "totp_secret_code": "TOTP таен код", - "important_note": "Важна забележка", "setup_2fa_text": "Тортата 2FA НЕ е толкова сигурна, колкото хладилното съхранение. 2FA защитава срещу основни видове атаки, като например вашият приятел да предостави вашия пръстов отпечатък, докато спите.\n\n Cake 2FA НЕ защитава срещу компрометирано устройство от сложен хакер.\n\n Ако загубите достъп до своите 2FA кодове , ЩЕ ЗАГУБИТЕ ДОСТЪП ДО ТОЗИ ПОРТФЕЙЛ. Ще трябва да възстановите портфейла си от мнемонично семе. ЗАТОВА ТРЯБВА ДА НАПРАВИТЕ РЕЗЕРВНО КОПИЕ НА ВАШИТЕ МНЕМОНИЧНИ СЕМЕНА! Освен това, някой с достъп до вашите мнемонични начални точки ще може да открадне вашите средства, заобикаляйки Cake 2FA.\n\n Персоналът по поддръжката на Cake няма да може да ви помогне, ако загубите достъп до вашите мнемонични начални стойности, тъй като Cake е портфейл без попечителство.", "setup_totp_recommended": "Настройка на TOTP (препоръчително)", "disable_buy": "Деактивирайте действието за покупка", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 2e59f5fc5..bc360ebb7 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -619,7 +619,6 @@ "enter_totp_code": "Zadejte kód TOTP.", "add_secret_code": "Přidejte tento tajný kód do jiného zařízení", "totp_secret_code": "Tajný kód TOTP", - "important_note": "Důležitá poznámka", "setup_2fa_text": "Cake 2FA NENÍ tak bezpečný jako skladování v chladu. 2FA chrání před základními typy útoků, jako je váš přítel, který vám poskytne otisk prstu, když spíte.\n\n Cake 2FA nechrání před napadením zařízení sofistikovaným útočníkem.\n\n Pokud ztratíte přístup ke svým kódům 2FA , ZTRÁTÍTE PŘÍSTUP K TÉTO PENĚŽENCE. Budete muset obnovit svou peněženku z mnemotechnického semínka. MUSÍTE TEDY ZÁLOHOVAT SVÉ MNEMONICKÉ SEMÉNKY! Kromě toho někdo s přístupem k vašemu mnemotechnickému semenu bude moci ukrást vaše finanční prostředky a obejít Cake 2FA.\n\n Pracovníci podpory Cake vám nebudou schopni pomoci, pokud ztratíte přístup k vašemu mnemotechnickému semenu, protože Cake je nevazební peněženka.", "setup_totp_recommended": "Nastavit TOTP (doporučeno)", "disable_buy": "Zakázat akci nákupu", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 7868553be..c7e104713 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -627,7 +627,6 @@ "enter_totp_code": "Bitte geben Sie den TOTP-Code ein.", "add_secret_code": "Fügen Sie diesen Geheimcode einem anderen Gerät hinzu", "totp_secret_code": "TOTP-Geheimcode", - "important_note": "Wichtiger Hinweis", "setup_2fa_text": "Cake 2FA ist NICHT so sicher wie eine Cold Wallet. 2FA schützt vor grundlegenden Arten von Angriffen, z.B. wenn Ihr Freund Ihren Fingerabdruck verwendet, während Sie schlafen.\n\n Cake 2FA schützt NICHT vor einem kompromittierten Gerät durch einen raffinierten Angreifer.\n\n Wenn Sie den Zugriff auf Ihre 2FA-Codes verlieren , VERLIEREN SIE DEN ZUGANG ZU DIESEM WALLET. Sie müssen Ihre Wallet aus mnemonic Seed wiederherstellen. SIE MÜSSEN DESHALB IHRE MNEMONISCHEN SEEDS SICHERN! Außerdem kann jemand mit Zugriff auf Ihre mnemonischen Seed(s) Ihr Geld stehlen und Cake 2FA umgehen.\n\n Cake-Supportmitarbeiter können Ihnen nicht helfen, wenn Sie den Zugriff auf Ihre mnemonischen Seed(s) verlieren, da Cake Wallet eine Wallet ohne treuhänderische Verwahrung ist.", "setup_totp_recommended": "TOTP einrichten (empfohlen)", "disable_buy": "Kaufaktion deaktivieren", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index c3cd256d9..d5de6688f 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -628,7 +628,6 @@ "enter_totp_code": "Please enter the TOTP Code.", "add_secret_code": "Add this secret code to another device", "totp_secret_code": "TOTP Secret Code", - "important_note": "Important note", "setup_2fa_text": "Cake 2FA is NOT as secure as cold storage. 2FA protects against basic types of attacks, such as your friend providing your fingerprint while you are sleeping.\n\n Cake 2FA does NOT protect against a compromised device by a sophisticated attacker.\n\n If you lose access to your 2FA codes, YOU WILL LOSE ACCESS TO THIS WALLET. You will need to restore your wallet from mnemonic seed. YOU MUST THEREFORE BACK UP YOUR MNEMONIC SEEDS! Further, someone with access to your mnemonic seed(s) will be able to steal your funds, bypassing Cake 2FA.\n\n Cake support staff will be unable to assist you if you lose access to your mnemonic seed, since Cake is a noncustodial wallet.", "setup_totp_recommended": "Set up TOTP (Recommended)", "disable_buy": "Disable buy action", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 4e624a9b4..765ca7074 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -627,7 +627,6 @@ "enter_totp_code": "Ingrese el código TOTP.", "add_secret_code": "Agregue este código secreto a otro dispositivo", "totp_secret_code": "Código secreto TOTP", - "important_note": "Nota IMPORTANTE", "setup_2fa_text": "Cake 2FA NO es tan seguro como el almacenamiento en frío. 2FA protege contra tipos básicos de ataques, como cuando un amigo proporciona su huella digital mientras usted duerme.\n\n Cake 2FA NO protege contra un dispositivo comprometido por un atacante sofisticado.\n\n Si pierde el acceso a sus códigos 2FA , PERDERÁS EL ACCESO A ESTA BILLETERA. Deberá restaurar su billetera desde la semilla mnemotécnica. ¡POR LO TANTO, DEBE HACER UNA COPIA DE SEGURIDAD DE SUS SEMILLAS MNEMÓNICAS! Además, alguien con acceso a sus semillas mnemotécnicas podrá robar sus fondos, sin pasar por Cake 2FA.\n\n El personal de soporte de Cake no podrá ayudarlo si pierde el acceso a su semilla mnemotécnica, ya que Cake es un billetera sin custodia.", "setup_totp_recommended": "Configurar TOTP (Recomendado)", "disable_buy": "Desactivar acción de compra", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index d4d414029..1898071df 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -627,7 +627,6 @@ "enter_totp_code": "Veuillez entrer le code TOTP.", "add_secret_code": "Configurer un autre appareil à l'aide de ce secret TOTP", "totp_secret_code": "Secret TOTP", - "important_note": "Note importante", "setup_2fa_text": "Cake 2FA (Authentification à 2 Facteurs) n'est PAS aussi sûr que le stockage à froid. Cake 2FA protège contre les attaques basiques, comme un ami fournissant votre empreinte digitale pendant que vous dormez.\n\n Cake 2FA ne protège PAS contre un appareil compromis par un attaquant sophistiqué.\n\n Si vous perdez l'accès à vos codes 2FA , VOUS PERDREZ L'ACCÈS À CE PORTEFEUILLE (WALLET). Vous devrez restaurer votre portefeuille à partir de sa phrase secrète (seed). VOUS DEVEZ DONC SAUVEGARDER VOTRE PHRASE SECRÈTE ! De plus, quelqu'un ayant accès à votre phrase secrète pourra voler vos fonds, en contournant Cake 2FA.\n\n Le personnel d'assistance de Cake ne pourra pas vous aider si vous perdez l'accès à votre phrase secrète, puisque Cake est un portefeuille non dépositaire (non custodial).", "setup_totp_recommended": "Configurer TOTP (recommandé)", "disable_buy": "Désactiver l'action d'achat", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 19467af09..156e4ed92 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -627,7 +627,6 @@ "enter_totp_code": "कृपया TOTP कोड दर्ज करें।", "add_secret_code": "इस गुप्त कोड को किसी अन्य डिवाइस में जोड़ें", "totp_secret_code": "टीओटीपी गुप्त कोड", - "important_note": "महत्वपूर्ण लेख", "setup_2fa_text": "केक 2FA कोल्ड स्टोरेज जितना सुरक्षित नहीं है। 2FA बुनियादी प्रकार के हमलों से बचाता है, जैसे कि आपका मित्र सोते समय आपको अपना फ़िंगरप्रिंट प्रदान करता है।\n\n Cake 2FA परिष्कृत हमलावर द्वारा किसी डिवाइस से छेड़छाड़ से रक्षा नहीं करता है।\n\n यदि आप अपने 2FA कोड तक पहुंच खो देते हैं , आप इस वॉलेट तक पहुंच खो देंगे। आपको अपने बटुए को स्मरणीय बीज से पुनर्स्थापित करने की आवश्यकता होगी। इसलिए आपको अपने स्मरणीय बीजों का बैकअप लेना चाहिए! इसके अलावा, आपके स्मरक बीज (बीजों) तक पहुंच रखने वाला कोई व्यक्ति केक 2FA को दरकिनार कर आपके धन की चोरी करने में सक्षम होगा। अप्रबंधित बटुआ।", "setup_totp_recommended": "टीओटीपी सेट अप करें (अनुशंसित)", "disable_buy": "खरीद कार्रवाई अक्षम करें", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 30eea10dc..9a14cd2d9 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -627,7 +627,6 @@ "enter_totp_code": "Unesite TOTP kod.", "add_secret_code": "Dodajte ovaj tajni kod na drugi uređaj", "totp_secret_code": "TOTP tajni kod", - "important_note": "Važna nota", "setup_2fa_text": "Torta 2FA NIJE sigurna kao hladno skladište. 2FA štiti od osnovnih vrsta napada, kao što je vaš prijatelj koji vam daje otisak prsta dok spavate.\n\n Cake 2FA NE štiti od kompromitiranog uređaja od strane sofisticiranog napadača.\n\n Ako izgubite pristup svojim 2FA kodovima , IZGUBIT ĆETE PRISTUP OVOM NOVČANIKU. Morat ćete obnoviti svoj novčanik iz mnemoničkog sjemena. STOGA MORATE NAPRAVITI SIGURNOSNE KOPIJE SVOJIH MNEMONIČKIH SJEMENA! Nadalje, netko tko ima pristup vašem mnemoničkom seedu(ima) moći će ukrasti vaša sredstva, zaobilazeći Cake 2FA.\n\n Cake osoblje za podršku neće vam moći pomoći ako izgubite pristup svom mnemoničkom seedu, budući da je Cake neskrbnički novčanik.", "setup_totp_recommended": "Postavite TOTP (preporučeno)", "disable_buy": "Onemogući kupnju", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index c10feffbc..e6f8eb5bd 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -615,7 +615,6 @@ "enter_totp_code": "Masukkan Kode TOTP.", "add_secret_code": "Tambahkan kode rahasia ini ke perangkat lain", "totp_secret_code": "Kode Rahasia TOTP", - "important_note": "Catatan penting", "setup_2fa_text": "Cake 2FA TIDAK seaman cold storage. 2FA melindungi dari jenis serangan dasar, seperti teman Anda memberikan sidik jari saat Anda sedang tidur.\n\n Cake 2FA TIDAK melindungi dari perangkat yang disusupi oleh penyerang canggih.\n\n Jika Anda kehilangan akses ke kode 2FA , ANDA AKAN KEHILANGAN AKSES KE DOMPET INI. Anda perlu memulihkan dompet Anda dari benih mnemonik. OLEH KARENA ITU, ANDA HARUS MENYIMPAN BIJI MNEMONIK ANDA! Selanjutnya, seseorang yang memiliki akses ke benih mnemonik Anda akan dapat mencuri dana Anda, melewati Cake 2FA.\n\n Staf pendukung Cake tidak akan dapat membantu Anda jika Anda kehilangan akses ke benih mnemonik Anda, karena Cake adalah dompet tanpa hak asuh.", "setup_totp_recommended": "Siapkan TOTP (Disarankan)", "disable_buy": "Nonaktifkan tindakan beli", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index a13930666..fc4254599 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -627,7 +627,6 @@ "enter_totp_code": "Inserisci il codice TOTP.", "add_secret_code": "Aggiungi questo codice segreto a un altro dispositivo", "totp_secret_code": "TOTP codice segreto", - "important_note": "Nota importante", "setup_2fa_text": "Cake 2FA NON è sicuro come la cella frigorifera. 2FA protegge da tipi di attacchi di base, come il tuo amico che fornisce la tua impronta digitale mentre dormi.\n\n Cake 2FA NON protegge da un dispositivo compromesso da un aggressore sofisticato.\n\n Se perdi l'accesso ai tuoi codici 2FA , PERDERAI L'ACCESSO A QUESTO PORTAFOGLIO. Dovrai ripristinare il tuo portafoglio dal seme mnemonico. DOVETE QUINDI SOSTITUIRE I VOSTRI SEMI MNEMONICI! Inoltre, qualcuno con accesso ai tuoi seed mnemonici sarà in grado di rubare i tuoi fondi, aggirando Cake 2FA.\n\n Il personale di supporto di Cake non sarà in grado di aiutarti se perdi l'accesso al tuo seed mnemonico, poiché Cake è un portafoglio non detentivo.", "setup_totp_recommended": "Imposta TOTP (consigliato)", "disable_buy": "Disabilita l'azione di acquisto", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 3e61dbd9d..b4aece35f 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -627,7 +627,6 @@ "enter_totp_code": "TOTPコードを入力してください。", "add_secret_code": "このシークレット コードを別のデバイスに追加する", "totp_secret_code": "TOTPシークレットコード", - "important_note": "重要な注意点", "setup_2fa_text": "Cake 2FA は、コールド ストレージほど安全ではありません。 2FA は、あなたが寝ているときに友人が指紋を提供するなどの基本的なタイプの攻撃から保護します。\n\n Cake 2FA は、巧妙な攻撃者による侵害されたデバイスから保護しません。\n\n 2FA コードにアクセスできなくなった場合、このウォレットにアクセスできなくなります。ニーモニック シードからウォレットを復元する必要があります。したがって、ニーモニック シードをバックアップする必要があります。さらに、あなたのニーモニック シードにアクセスできる誰かが、Cake 2FA をバイパスして、あなたの資金を盗むことができます。\n\n Cake は無印の財布。", "setup_totp_recommended": "TOTP を設定する (推奨)", "disable_buy": "購入アクションを無効にする", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index de09c65d1..e048ca2c5 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -627,7 +627,6 @@ "enter_totp_code": "TOTP 코드를 입력하세요.", "add_secret_code": "이 비밀 코드를 다른 장치에 추가", "totp_secret_code": "TOTP 비밀 코드", - "important_note": "중요 사항", "setup_2fa_text": "케이크 2FA는 냉장 보관만큼 안전하지 않습니다. 2FA는 당신이 잠자는 동안 친구가 지문을 제공하는 것과 같은 기본적인 유형의 공격으로부터 보호합니다.\n\n Cake 2FA는 정교한 공격자에 의해 손상된 장치로부터 보호하지 않습니다.\n\n 2FA 코드에 대한 액세스 권한을 잃으면 , 이 지갑에 대한 액세스 권한을 잃게 됩니다. 니모닉 시드에서 지갑을 복원해야 합니다. 따라서 니모닉 시드를 백업해야 합니다! 또한 니모닉 시드에 액세스할 수 있는 사람이 Cake 2FA를 우회하여 자금을 훔칠 수 있습니다.\n\n 니모닉 시드에 대한 액세스 권한을 잃으면 Cake 지원 직원이 도와줄 수 없습니다. 비수탁 지갑.", "setup_totp_recommended": "TOTP 설정(권장)", "disable_buy": "구매 행동 비활성화", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 1853c0eff..f6593fa04 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -625,7 +625,6 @@ "enter_totp_code": "ကျေးဇူးပြု၍ TOTP ကုဒ်ကို ထည့်ပါ။", "add_secret_code": "ဤလျှို့ဝှက်ကုဒ်ကို အခြားစက်ပစ္စည်းသို့ ထည့်ပါ။", "totp_secret_code": "TOTP လျှို့ဝှက်ကုဒ်", - "important_note": "အရေးကြီးသောမှတ်ချက်", "setup_2fa_text": "ကိတ်မုန့် 2FA သည် အအေးခန်းကဲ့သို့ မလုံခြုံပါ။ 2FA သည် သင်အိပ်နေစဉ်တွင် သင့်သူငယ်ချင်းသည် သင့်လက်ဗွေရာကို ပေးဆောင်ခြင်းကဲ့သို့သော အခြေခံတိုက်ခိုက်မှုအမျိုးအစားများကို ကာကွယ်ပေးပါသည်။\n\n Cake 2FA သည် ခေတ်မီဆန်းပြားသော တိုက်ခိုက်သူ၏ အန္တရာယ်ပြုသည့်စက်ပစ္စည်းကို မကာကွယ်ပါ။\n\n သင်၏ 2FA ကုဒ်များကို အသုံးပြုခွင့်ဆုံးရှုံးသွားပါက၊ ဤပိုက်ဆံအိတ်ကို သင်ဝင်ရောက်ခွင့်ဆုံးရှုံးလိမ့်မည်။ သင့်ပိုက်ဆံအိတ်ကို mnemonic မျိုးစေ့မှ ပြန်လည်ရယူရန် လိုအပ်မည်ဖြစ်သည်။ ထို့ကြောင့် သင်၏ MNEMONIC မျိုးစေ့များကို အရန်သိမ်းထားရပါမည်။ ထို့အပြင်၊ သင်၏ mnemonic မျိုးစေ့(များ) ကို အသုံးပြုခွင့်ရှိသူတစ်ဦးက Cake 2FA ကိုကျော်ဖြတ်ကာ သင့်ရန်ပုံငွေများကို ခိုးယူနိုင်ပါမည်။\n\n ကိတ်မုန့်သည် သင့် mnemonic မျိုးစေ့သို့ ဝင်ရောက်ခွင့်ဆုံးရှုံးသွားပါက သင့်အား ကူညီပေးနိုင်မည်မဟုတ်ပါ၊ အထိန်းအချုပ်မရှိသော ပိုက်ဆံအိတ်။", "setup_totp_recommended": "TOTP ကို ​​စနစ်ထည့်သွင်းပါ (အကြံပြုထားသည်)", "disable_buy": "ဝယ်ယူမှု လုပ်ဆောင်ချက်ကို ပိတ်ပါ။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index a497c20ab..e5b4856d0 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -627,7 +627,6 @@ "enter_totp_code": "Voer de TOTP-code in.", "add_secret_code": "Voeg deze geheime code toe aan een ander apparaat", "totp_secret_code": "TOTP-geheime code", - "important_note": "Belangrijke notitie", "setup_2fa_text": "Cake 2FA is NIET zo veilig als koude opslag. 2FA beschermt tegen basistypen aanvallen, zoals uw vriend die uw vingerafdruk geeft terwijl u slaapt.\n\n Cake 2FA biedt GEEN bescherming tegen een gecompromitteerd apparaat door een geavanceerde aanvaller.\n\n Als u de toegang tot uw 2FA-codes kwijtraakt , VERLIEST U DE TOEGANG TOT DEZE PORTEFEUILLE. U moet uw portemonnee herstellen van mnemonic seed. JE MOET DAAROM EEN BACK-UP MAKEN VAN JE MNEMONISCHE ZADEN! Verder kan iemand met toegang tot je geheugensteuntje(s) je geld stelen, waarbij Cake 2FA wordt omzeild.\n\n Het ondersteunend personeel van Cake kan je niet helpen als je de toegang tot je geheugensteuntje kwijtraakt, aangezien Cake een niet-bewaarbare portemonnee.", "setup_totp_recommended": "TOTP instellen (aanbevolen)", "disable_buy": "Koopactie uitschakelen", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index dc69468bd..8f337210f 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -627,7 +627,6 @@ "enter_totp_code": "Wprowadź kod TOTP.", "add_secret_code": "Dodaj ten tajny kod do innego urządzenia", "totp_secret_code": "Tajny kod TOTP", - "important_note": "Ważna uwaga", "setup_2fa_text": "Cake 2FA NIE jest tak bezpieczny jak przechowywanie w chłodni. 2FA chroni przed podstawowymi typami ataków, takimi jak udostępnienie odcisku palca przez znajomego podczas snu.\n\n Cake 2FA NIE chroni przed zhakowanym urządzeniem przez wyrafinowanego atakującego.\n\n Jeśli utracisz dostęp do swoich kodów 2FA , UTRACISZ DOSTĘP DO TEGO PORTFELA. Będziesz musiał przywrócić swój portfel z mnemonicznego materiału siewnego. DLATEGO MUSISZ ZROBIĆ KOPIĘ SWOICH NASION MNEMONICZNYCH! Co więcej, ktoś z dostępem do twoich mnemonicznych nasion będzie mógł ukraść twoje fundusze, omijając Cake 2FA.\n\n Personel pomocniczy Cake nie będzie mógł ci pomóc, jeśli stracisz dostęp do swojego mnemonicznego seeda, ponieważ Cake jest portfel niezabezpieczony.", "setup_totp_recommended": "Skonfiguruj TOTP (zalecane)", "disable_buy": "Wyłącz akcję kupna", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index c6d22ae23..8cc574362 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -626,7 +626,6 @@ "enter_totp_code": "Digite o código TOTP.", "add_secret_code": "Adicione este código secreto a outro dispositivo", "totp_secret_code": "Código Secreto TOTP", - "important_note": "Nota importante", "setup_2fa_text": "O Cake 2FA NÃO é tão seguro quanto o armazenamento a frio. O 2FA protege contra tipos básicos de ataques, como seu amigo fornecer sua impressão digital enquanto você está dormindo.\n\n O Cake 2FA NÃO protege contra um dispositivo comprometido por um invasor sofisticado.\n\n Se você perder o acesso aos seus códigos 2FA , VOCÊ PERDERÁ O ACESSO A ESTA CARTEIRA. Você precisará restaurar sua carteira da semente mnemônica. VOCÊ DEVE, PORTANTO, FAZER BACKUP DE SUAS SEMENTES MNEMÔNICAS! Além disso, alguém com acesso às suas sementes mnemônicas poderá roubar seus fundos, ignorando o Cake 2FA.\n\n A equipe de suporte do Cake não poderá ajudá-lo se você perder o acesso à sua semente mnemônica, pois o Cake é um carteira não custodial.", "setup_totp_recommended": "Configurar TOTP (recomendado)", "disable_buy": "Desativar ação de compra", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 50bef718d..e7178dc2e 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -627,7 +627,6 @@ "enter_totp_code": "Пожалуйста, введите TOTP-код.", "add_secret_code": "Добавьте этот секретный код на другое устройство", "totp_secret_code": "Секретный код ТОТП", - "important_note": "Важная заметка", "setup_2fa_text": "Cake 2FA НЕ так безопасен, как холодное хранилище. Двухфакторная аутентификация защищает от основных типов атак, таких как отпечаток вашего друга, когда вы спите.\n\n Двухфакторная аутентификация Cake НЕ защищает от взлома устройства опытным злоумышленником.\n\n Если вы потеряете доступ к своим кодам двухфакторной аутентификации. , ВЫ ПОТЕРЯЕТЕ ДОСТУП К ЭТОМУ КОШЕЛЬКУ. Вам нужно будет восстановить свой кошелек из мнемонической семени. ПОЭТОМУ ВЫ ДОЛЖНЫ СОЗДАТЬ РЕЗЕРВНУЮ ВЕРСИЮ СВОИХ МНЕМОНИКОВ! Кроме того, кто-то, имеющий доступ к вашему мнемоническому семени, сможет украсть ваши средства, минуя Cake 2FA.\n\n Персонал службы поддержки Cake не сможет помочь вам, если вы потеряете доступ к своему мнемоническому семени, поскольку Cake — это некастодиальный кошелек.", "setup_totp_recommended": "Настроить TOTP (рекомендуется)", "disable_buy": "Отключить действие покупки", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 95a1cd406..2c7255e33 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -625,7 +625,6 @@ "enter_totp_code": "กรุณาใส่รหัสทีโอที", "add_secret_code": "เพิ่มรหัสลับนี้ไปยังอุปกรณ์อื่น", "totp_secret_code": "รหัสลับ TOTP", - "important_note": "โน๊ตสำคัญ", "setup_2fa_text": "Cake 2FA ไม่ปลอดภัยเท่าห้องเย็น 2FA ป้องกันการโจมตีประเภทพื้นฐาน เช่น เพื่อนของคุณให้ลายนิ้วมือขณะที่คุณนอนหลับ\n\n Cake 2FA ไม่ป้องกันอุปกรณ์ที่ถูกบุกรุกโดยผู้โจมตีที่เชี่ยวชาญ\n\n หากคุณสูญเสียการเข้าถึงรหัส 2FA ของคุณ คุณจะสูญเสียการเข้าถึงกระเป๋าเงินนี้ คุณจะต้องกู้คืนกระเป๋าเงินของคุณจากเมล็ดช่วยจำ คุณต้องสำรองเมล็ดความจำของคุณ! นอกจากนี้ ผู้ที่สามารถเข้าถึงเมล็ดช่วยจำของคุณจะสามารถขโมยเงินของคุณ โดยผ่าน Cake 2FA\n\n เจ้าหน้าที่ช่วยเหลือของ Cake จะไม่สามารถช่วยเหลือคุณได้ หากคุณสูญเสียการเข้าถึงเมล็ดช่วยจำ เนื่องจาก Cake เป็น กระเป๋าสตางค์ที่ไม่เป็นผู้ดูแล", "setup_totp_recommended": "ตั้งค่า TOTP (แนะนำ)", "disable_buy": "ปิดการใช้งานการซื้อ", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 960432a1b..03ca14497 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -628,7 +628,6 @@ "enter_totp_code": "Mangyaring ipasok ang TOTP code.", "add_secret_code": "Idagdag ang lihim na code na ito sa isa pang aparato", "totp_secret_code": "TOTP Secret Code", - "important_note": "Mahalagang paalaala", "setup_2fa_text": "Ang cake 2FA ay hindi ligtas tulad ng malamig na imbakan. Pinoprotektahan ng 2FA laban sa mga pangunahing uri ng pag -atake, tulad ng iyong kaibigan na nagbibigay ng iyong fingerprint habang natutulog ka.\n\n Hindi pinoprotektahan ng cake 2FA laban sa isang nakompromiso na aparato ng isang sopistikadong umaatake.\n\n Kung nawalan ka ng pag -access sa iyong 2FA code, mawawalan ka ng access sa pitaka na ito. Kakailanganin mong ibalik ang iyong pitaka mula sa binhi ng mnemonic. Dapat mong i -back up ang iyong mga buto ng mnemonic! Dagdag pa, ang isang tao na may access sa iyong (mga) binhi ng mnemonic ay maaaring magnakaw ng iyong mga pondo, na lumampas sa cake 2FA.\n\n Ang mga kawani ng suporta sa cake ay hindi makakatulong sa iyo kung nawalan ka ng pag -access sa iyong mnemonic seed, dahil ang cake ay isang noncustodial wallet.", "setup_totp_recommended": "I -set up ang TOTP (inirerekomenda)", "disable_buy": "Huwag paganahin ang pagkilos ng pagbili", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 1b7982504..2cd0691a1 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -625,7 +625,6 @@ "enter_totp_code": "Lütfen TOTP Kodunu giriniz.", "add_secret_code": "Bu gizli kodu başka bir cihaza ekleyin", "totp_secret_code": "TOTP Gizli Kodu", - "important_note": "Önemli Not", "setup_2fa_text": "Cake 2FA, soğuk hava deposu kadar güvenli DEĞİLDİR. 2FA, siz uyurken arkadaşınızın parmak izinizi sağlaması gibi temel saldırı türlerine karşı koruma sağlar.\n\n Cake 2FA, gelişmiş bir saldırgan tarafından güvenliği ihlal edilmiş bir cihaza karşı koruma SAĞLAMAZ.\n\n 2FA kodlarınıza erişimi kaybederseniz , BU CÜZDANA ERİŞİMİNİZİ KAYBEDECEKSİNİZ. Mnemonic seed'den cüzdanınızı geri yüklemeniz gerekecek. BU NEDENLE HATIRLAYICI TOHUMLARINIZI YEDEKLEMELİSİNİZ! Ayrıca anımsatıcı tohumlarınıza erişimi olan biri, Cake 2FA'yı atlayarak paranızı çalabilir.\n\n Cake, anımsatıcı tohumlarınıza erişimi kaybederseniz size yardımcı olamaz, çünkü Cake bir saklama dışı cüzdan.", "setup_totp_recommended": "TOTP'yi kurun (Önerilir)", "disable_buy": "Satın alma işlemini devre dışı bırak", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 849542e6f..5d5a2bfbe 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -627,7 +627,6 @@ "enter_totp_code": "Будь ласка, введіть код TOTP.", "add_secret_code": "Додайте цей секретний код на інший пристрій", "totp_secret_code": "Секретний код TOTP", - "important_note": "Важливе зауваження", "setup_2fa_text": "Торт 2FA НЕ такий безпечний, як холодне зберігання. 2FA захищає від основних типів атак, наприклад ваш друг надає ваш відбиток пальця, поки ви спите.\n\n Cake 2FA НЕ захищає від скомпрометованого пристрою досвідченим зловмисником.\n\n Якщо ви втратите доступ до своїх кодів 2FA , ВИ ВТРАТИТЕ ДОСТУП ДО ЦЬОГО ГАМАНЦЯ. Вам потрібно буде відновити свій гаманець з мнемонічного коду. ТОМУ ВИ ПОВИННІ СТВОРИТИ РЕЗЕРВНУ КОПІЮ СВОЇХ МНЕМОНІЧНИХ НАСІН! Крім того, хтось із доступом до ваших мнемонічних початкових значень зможе викрасти ваші кошти, оминаючи Cake 2FA.\n\n Співробітники служби підтримки Cake не зможуть вам допомогти, якщо ви втратите доступ до своїх мнемонічних вихідних даних, оскільки Cake є гаманець без опіки.", "setup_totp_recommended": "Налаштувати TOTP (рекомендовано)", "disable_buy": "Вимкнути дію покупки", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 0b7e4c0a7..62ce60061 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -619,7 +619,6 @@ "enter_totp_code": "براہ کرم TOTP کوڈ درج کریں۔", "add_secret_code": "اس خفیہ کوڈ کو کسی اور ڈیوائس میں شامل کریں۔", "totp_secret_code": "TOTP خفیہ کوڈ", - "important_note": "اہم نوٹ", "setup_2fa_text": "کیک 2FA کولڈ اسٹوریج کی طرح محفوظ نہیں ہے۔ 2FA بنیادی قسم کے حملوں سے حفاظت کرتا ہے، جیسے کہ آپ کا دوست آپ کے سوتے وقت آپ کے فنگر پرنٹ فراہم کرتا ہے۔\n\n کیک 2FA کسی جدید حملہ آور کے ذریعے سمجھوتہ کرنے والے آلہ سے حفاظت نہیں کرتا ہے۔\n\n اگر آپ اپنے 2FA کوڈز تک رسائی کھو دیتے ہیں ، آپ اس بٹوے تک رسائی سے محروم ہو جائیں گے۔ آپ کو یادداشت کے بیج سے اپنے بٹوے کو بحال کرنے کی ضرورت ہوگی۔ اس لیے آپ کو اپنے یادداشت کے بیجوں کا بیک اپ لینا چاہیے! اس کے علاوہ، آپ کے یادداشت کے بیج تک رسائی رکھنے والا کوئی شخص کیک 2FA کو نظرانداز کرتے ہوئے آپ کے فنڈز چرا سکے گا۔\n\n اگر آپ اپنے یادداشت کے بیج تک رسائی کھو دیتے ہیں تو کیک کا معاون عملہ آپ کی مدد نہیں کر سکے گا، کیونکہ کیک ایک ہے غیر نگہداشت پرس.", "setup_totp_recommended": "TOTP ترتیب دیں (تجویز کردہ)", "disable_buy": "خرید ایکشن کو غیر فعال کریں۔", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 57962b38e..e0bc8a0ef 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -621,7 +621,6 @@ "enter_totp_code": "Jọwọ pọ koodu TOTP.", "add_secret_code": "Fọya koodu iye yii si eto miiran", "totp_secret_code": "Koodu iye TOTP", - "important_note": "Iwọ nikan nipasẹ iwe iṣẹ kan", "setup_2fa_text": "Cake 2FA kii ṣe nipasẹ aisan tabi ni akoso aisan. 2FA ti ṣe pada ninu awọn iṣẹ pataki, bi atilẹyin ti o fun iṣẹ rẹ ti o ti jẹ saanu.\n\n Cake 2FA kii ṣe pada ninu atilẹyin ti o ti ba alabara kan ti o sise gidi gan.\n\n Ti o ba pọ akosile rẹ 2FA, O YOO RI ATOJU SI IWE IWE NA. O yoo nilo lati yan pẹlu iwe iwe ni o ba ṣe iṣẹ rẹ. O ni aṣẹ iru ki o gba asise akojọ iwe iwe rẹ! Nitori a ko ni aṣẹ pẹlu ohun ti o ba ṣe iṣẹ rẹ lati yan pẹlu akojọ iwe iwe rẹ, nitori Cake ni iwe iwe ti ko se iṣẹ itumọ.", "setup_totp_recommended": "Sọ TOTP (Kẹṣọdọ)", "disable_buy": "Ko iṣọrọ ọja", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 0862f20e2..2ad656317 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -626,7 +626,6 @@ "enter_totp_code": "请输入 TOTP 代码。", "add_secret_code": "将此密码添加到另一台设备", "totp_secret_code": "TOTP密码", - "important_note": "重要的提示", "setup_2fa_text": "Cake 2FA 不如冷藏安全。 2FA 可防止基本类型的攻击,例如您的朋友在您睡觉时提供您的指纹。\n\n Cake 2FA 无法防止老练的攻击者破坏设备。\n\n 如果您无法访问您的 2FA 代码, 您将无法访问此钱包。您将需要从助记词种子恢复您的钱包。因此,您必须备份您的助记词种子!此外,有权访问您的助记种子的人将能够绕过 Cake 2FA 窃取您的资金。\n\n 如果您无法访问您的助记种子,Cake 支持人员将无法帮助您,因为 Cake 是一个非托管钱包。", "setup_totp_recommended": "设置 TOTP(推荐)", "disable_buy": "禁用购买操作", From 7fe1091b4c16f01bd47a160f3c6c6e5dc1555778 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 23 Nov 2023 19:33:21 +0200 Subject: [PATCH 048/241] fix text --- lib/src/screens/seed/warning_page.dart | 43 ++++++++-------- lib/src/screens/setup_2fa/setup_2fa.dart | 49 +++++++++++-------- .../screens/setup_2fa/setup_2fa_qr_page.dart | 2 +- res/values/strings_en.arb | 6 ++- 4 files changed, 57 insertions(+), 43 deletions(-) diff --git a/lib/src/screens/seed/warning_page.dart b/lib/src/screens/seed/warning_page.dart index cd7c3b1f6..7bd87113b 100644 --- a/lib/src/screens/seed/warning_page.dart +++ b/lib/src/screens/seed/warning_page.dart @@ -30,9 +30,6 @@ class WarningPage extends BasePage { Widget body(BuildContext context) { final image = currentTheme.type == ThemeType.dark ? imageDark : imageLight; - final text = - "Cake 2FA is a second authentication for certain actions in the wallet. It is NOT as secure as cold storage. If you lose access to your 2FA app or passkeys, you WILL lose access to this wallet. You will need to restore your wallet from the mnemonic seed. Cake support will be unable to assist you if you lose access to your 2FA or mnemonic seeds. Before using Cake 2FA, we recommend reading through the guide here."; - return WillPopScope( onWillPop: () async => false, child: Container( @@ -44,29 +41,35 @@ class WarningPage extends BasePage { child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - ConstrainedBox( - constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.3), - child: AspectRatio(aspectRatio: 1, child: image), + Expanded( + child: ConstrainedBox( + constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.3), + child: AspectRatio(aspectRatio: 1, child: image), + ), ), - Padding( - padding: EdgeInsets.all(10), - child: Text( - isPreSeedPage - ? S.of(context).pre_seed_description(seedPhraseLength.toString()) - : text, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.normal, - color: isPreSeedPage - ? Theme.of(context).extension()!.secondaryTextColor - : Theme.of(context).extension()!.titleColor)), + Expanded( + child: Padding( + padding: EdgeInsets.all(10), + child: Text( + isPreSeedPage + ? S.of(context).pre_seed_description(seedPhraseLength.toString()) + : S.of(context).setup_warning_2fa_text, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + color: isPreSeedPage + ? Theme.of(context).extension()!.secondaryTextColor + : Theme.of(context).extension()!.titleColor)), + ), ), PrimaryButton( onPressed: () => isPreSeedPage ? Navigator.of(context).popAndPushNamed(Routes.seed, arguments: true) : Navigator.of(context).popAndPushNamed(Routes.setup_2faPage), - text: isPreSeedPage ? S.of(context).pre_seed_button_text : 'Neeeeeeee', + text: isPreSeedPage + ? S.of(context).pre_seed_button_text + : S.of(context).understand, color: Theme.of(context).primaryColor, textColor: Colors.white) ], diff --git a/lib/src/screens/setup_2fa/setup_2fa.dart b/lib/src/screens/setup_2fa/setup_2fa.dart index 9d8ffe839..d38de1f8c 100644 --- a/lib/src/screens/setup_2fa/setup_2fa.dart +++ b/lib/src/screens/setup_2fa/setup_2fa.dart @@ -14,23 +14,27 @@ class Setup2FAPage extends BasePage { final Setup2FAViewModel setup2FAViewModel; @override - String get title => S.current.setup_2fa; + String get title => 'CAKE 2FA'; @override Widget body(BuildContext context) { final cake2FAGuideTitle = 'Cake 2FA Guide'; final cake2FAGuideUri = Uri.parse('https://guides.cakewallet.com/docs/advanced-features/authentication'); - return SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - ConstrainedBox( + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + flex: 2, + child: ConstrainedBox( constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.3), child: AspectRatio(aspectRatio: 1, child: Image.asset('assets/images/setup_2fa_img.png')), ), - Padding( + ), + Expanded( + flex: 2, + child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), child: Text( S.current.setup_2fa_text, @@ -43,20 +47,25 @@ class Setup2FAPage extends BasePage { ), ), ), - SizedBox(height: 56), - SettingsCellWithArrow( - title: S.current.setup_totp_recommended, - handler: (_) { - setup2FAViewModel.generateSecretKey(); - return Navigator.of(context).pushReplacementNamed(Routes.setup_2faQRPage); - }, + ), + Expanded( + child: Column( + children: [ + SettingsCellWithArrow( + title: S.current.setup_totp_recommended, + handler: (_) { + setup2FAViewModel.generateSecretKey(); + return Navigator.of(context).pushReplacementNamed(Routes.setup_2faQRPage); + }, + ), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + SettingsCellWithArrow( + title: cake2FAGuideTitle, handler: (_) => _launchUrl(cake2FAGuideUri)), + StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), + ], ), - StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), - SettingsCellWithArrow( - title: cake2FAGuideTitle, handler: (_) => _launchUrl(cake2FAGuideUri)), - StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), - ], - ), + ), + ], ); } 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 620f13670..237107783 100644 --- a/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart +++ b/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart @@ -36,7 +36,7 @@ class Setup2FAQRPage extends BasePage { children: [ Spacer(), Text( - S.current.add_secret_code, + S.current.scan_qr_on_device, style: TextStyle( fontSize: 14, fontWeight: FontWeight.w700, diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index d5de6688f..24fa9f9e6 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -626,9 +626,11 @@ "totp_verification_success": "Verification Successful!", "totp_2fa_failure": "Incorrect code. Please try a different code or generate a new secret key. Use a compatible 2FA app that supports 8-digit codes and SHA512.", "enter_totp_code": "Please enter the TOTP Code.", - "add_secret_code": "Add this secret code to another device", + "scan_qr_on_device": "Scan this QR code on another device", + "add_secret_code": "Or, add this secret code to an authenticator app", "totp_secret_code": "TOTP Secret Code", - "setup_2fa_text": "Cake 2FA is NOT as secure as cold storage. 2FA protects against basic types of attacks, such as your friend providing your fingerprint while you are sleeping.\n\n Cake 2FA does NOT protect against a compromised device by a sophisticated attacker.\n\n If you lose access to your 2FA codes, YOU WILL LOSE ACCESS TO THIS WALLET. You will need to restore your wallet from mnemonic seed. YOU MUST THEREFORE BACK UP YOUR MNEMONIC SEEDS! Further, someone with access to your mnemonic seed(s) will be able to steal your funds, bypassing Cake 2FA.\n\n Cake support staff will be unable to assist you if you lose access to your mnemonic seed, since Cake is a noncustodial wallet.", + "setup_2fa_text": "Cake 2FA works through TOTP as the second authentication factor.\n\nCake 2FA's TOTP requires SHA-512 and 8 digit support; this provides increased security. More information and supported apps can be found in the guide here.", + "setup_warning_2fa_text": "Cake 2FA is a second authentication for certain actions in the wallet. It is NOT as secure as cold storage.\n If you lose access to your 2FA app or passkeys, you WILL lose access to this wallet.\n You will need to restore your wallet from the mnemonic seed.\n Cake support will be unable to assist you if you lose access to your 2FA or mnemonic seeds. Before using Cake 2FA, we recommend reading through the guide.", "setup_totp_recommended": "Set up TOTP (Recommended)", "disable_buy": "Disable buy action", "disable_sell": "Disable sell action", From fa25a4b2240bdd32170dee3944da88d0ce37d81b Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Sat, 25 Nov 2023 01:31:49 +0200 Subject: [PATCH 049/241] Generic fixes (#1191) * check on the url validity before using it * handle tx nullability * add localization script to configure --- configure_cake_wallet_android.sh | 1 + cw_bitcoin/lib/electrum_wallet.dart | 2 +- lib/src/screens/wallet_connect/wc_connections_listing_view.dart | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/configure_cake_wallet_android.sh b/configure_cake_wallet_android.sh index b8aa433de..6998555d5 100755 --- a/configure_cake_wallet_android.sh +++ b/configure_cake_wallet_android.sh @@ -2,6 +2,7 @@ cd scripts/android source ./app_env.sh cakewallet ./app_config.sh cd ../.. && flutter pub get +flutter packages pub run tool/generate_localization.dart cd cw_core && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_monero && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 05486aa20..903fa14cc 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -480,7 +480,7 @@ abstract class ElectrumWalletBase unspentCoins = unspent.expand((e) => e).toList(); unspentCoins.forEach((coin) async { final tx = await fetchTransactionInfo(hash: coin.hash, height: 0); - coin.isChange = tx!.direction == TransactionDirection.outgoing; + coin.isChange = tx?.direction == TransactionDirection.outgoing; }); if (unspentCoinsInfo.isEmpty) { diff --git a/lib/src/screens/wallet_connect/wc_connections_listing_view.dart b/lib/src/screens/wallet_connect/wc_connections_listing_view.dart index 359d96b26..eda2a748f 100644 --- a/lib/src/screens/wallet_connect/wc_connections_listing_view.dart +++ b/lib/src/screens/wallet_connect/wc_connections_listing_view.dart @@ -31,6 +31,8 @@ class WalletConnectConnectionsView extends StatelessWidget { final actualLinkList = launchUri.query.split("uri="); + if (actualLinkList.length <= 1) return; + final query = actualLinkList[1]; final uri = Uri.decodeComponent(query); From eeb9976d090d70691e0f7ef4d92e94c5e99d99cd Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Fri, 24 Nov 2023 18:35:00 -0500 Subject: [PATCH 050/241] update wallet restore page to be less confusing for nano users (#1186) * update wallet restore page to be less confusing for nano users * update translations * only include private key if seed phrase is null * restore fixes * fix default derivation being wrong on restore * fix default nano derivationType & qr code parameters * update language on nano restore (hex form) * support hex seed from qr restore --- cw_core/lib/wallet_base.dart | 2 + cw_nano/lib/nano_wallet.dart | 44 +++++++++++-------- .../wallet_restore_from_keys_form.dart | 2 +- lib/view_model/restore/restore_wallet.dart | 2 +- .../restore/wallet_restore_from_qr_code.dart | 8 ++++ lib/view_model/wallet_keys_view_model.dart | 24 +++++----- res/values/strings_ar.arb | 1 + res/values/strings_bg.arb | 5 ++- res/values/strings_cs.arb | 5 ++- res/values/strings_de.arb | 5 ++- res/values/strings_en.arb | 5 ++- res/values/strings_es.arb | 5 ++- res/values/strings_fr.arb | 5 ++- res/values/strings_ha.arb | 5 ++- res/values/strings_hi.arb | 5 ++- res/values/strings_hr.arb | 5 ++- res/values/strings_id.arb | 5 ++- res/values/strings_it.arb | 5 ++- res/values/strings_ja.arb | 5 ++- res/values/strings_ko.arb | 5 ++- res/values/strings_my.arb | 5 ++- res/values/strings_nl.arb | 5 ++- res/values/strings_pl.arb | 5 ++- res/values/strings_pt.arb | 5 ++- res/values/strings_ru.arb | 5 ++- res/values/strings_th.arb | 5 ++- res/values/strings_tl.arb | 5 ++- res/values/strings_tr.arb | 5 ++- res/values/strings_uk.arb | 5 ++- res/values/strings_ur.arb | 3 +- res/values/strings_yo.arb | 5 ++- res/values/strings_zh.arb | 5 ++- 32 files changed, 125 insertions(+), 81 deletions(-) diff --git a/cw_core/lib/wallet_base.dart b/cw_core/lib/wallet_base.dart index d15ea42cd..09b423c14 100644 --- a/cw_core/lib/wallet_base.dart +++ b/cw_core/lib/wallet_base.dart @@ -44,6 +44,8 @@ abstract class WalletBase null; + String? get hexSeed => null; + Object get keys; WalletAddresses get walletAddresses; diff --git a/cw_nano/lib/nano_wallet.dart b/cw_nano/lib/nano_wallet.dart index 44d564fc6..795634849 100644 --- a/cw_nano/lib/nano_wallet.dart +++ b/cw_nano/lib/nano_wallet.dart @@ -58,13 +58,13 @@ abstract class NanoWalletBase } } - final String _mnemonic; + String _mnemonic; final String _password; - final DerivationType _derivationType; + DerivationType _derivationType; String? _privateKey; String? _publicAddress; - String? _seedKey; + String? _hexSeed; String? _representativeAddress; Timer? _receiveTimer; @@ -85,22 +85,26 @@ abstract class NanoWalletBase // initialize the different forms of private / public key we'll need: Future init() async { + if (_derivationType == DerivationType.unknown) { + _derivationType = DerivationType.nano; + } final String type = (_derivationType == DerivationType.nano) ? "standard" : "hd"; - // our "mnemonic" is actually a seedkey: + // our "mnemonic" is actually a hex form seed: if (!_mnemonic.contains(' ')) { - _seedKey = _mnemonic; + _hexSeed = _mnemonic; + _mnemonic = ""; } - if (_seedKey == null) { + if (_hexSeed == null) { if (_derivationType == DerivationType.nano) { - _seedKey = bip39.mnemonicToEntropy(_mnemonic).toUpperCase(); + _hexSeed = bip39.mnemonicToEntropy(_mnemonic).toUpperCase(); } else { - _seedKey = await NanoUtil.hdMnemonicListToSeed(_mnemonic.split(' ')); + _hexSeed = await NanoUtil.hdMnemonicListToSeed(_mnemonic.split(' ')); } } - _privateKey = await NanoUtil.uniSeedToPrivate(_seedKey!, 0, type); - _publicAddress = await NanoUtil.uniSeedToAddress(_seedKey!, 0, type); + _privateKey = await NanoUtil.uniSeedToPrivate(_hexSeed!, 0, type); + _publicAddress = await NanoUtil.uniSeedToAddress(_hexSeed!, 0, type); this.walletInfo.address = _publicAddress!; await walletAddresses.init(); @@ -275,11 +279,11 @@ abstract class NanoWalletBase @override NanoWalletKeys get keys { - return NanoWalletKeys(seedKey: _seedKey!); + return NanoWalletKeys(seedKey: _hexSeed!); } @override - String? get privateKey => _seedKey!; + String? get privateKey => _privateKey!; @override Future rescan({required int height}) async { @@ -297,7 +301,9 @@ abstract class NanoWalletBase } @override - String get seed => _mnemonic; + String? get seed => _mnemonic.isNotEmpty ? _mnemonic : null; + + String get hexSeed => _hexSeed!; String get representative => _representativeAddress ?? ""; @@ -330,7 +336,7 @@ abstract class NanoWalletBase Future makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); String toJSON() => json.encode({ - 'seedKey': _seedKey, + 'seedKey': _hexSeed, 'mnemonic': _mnemonic, 'currentBalance': balance[currency]?.currentBalance.toString() ?? "0", 'receivableBalance': balance[currency]?.receivableBalance.toString() ?? "0", @@ -351,9 +357,9 @@ abstract class NanoWalletBase formattedCurrentBalance: data['currentBalance'] as String? ?? "0", formattedReceivableBalance: data['receivableBalance'] as String? ?? "0"); - DerivationType derivationType = DerivationType.bip39; - if (data['derivationType'] == "DerivationType.nano") { - derivationType = DerivationType.nano; + DerivationType derivationType = DerivationType.nano; + if (data['derivationType'] == "DerivationType.bip39") { + derivationType = DerivationType.bip39; } walletInfo.derivationType = derivationType; @@ -390,9 +396,9 @@ abstract class NanoWalletBase Future regenerateAddress() async { final String type = (_derivationType == DerivationType.nano) ? "standard" : "hd"; _privateKey = - await NanoUtil.uniSeedToPrivate(_seedKey!, this.walletAddresses.account!.id, type); + await NanoUtil.uniSeedToPrivate(_hexSeed!, this.walletAddresses.account!.id, type); _publicAddress = - await NanoUtil.uniSeedToAddress(_seedKey!, this.walletAddresses.account!.id, type); + await NanoUtil.uniSeedToAddress(_hexSeed!, this.walletAddresses.account!.id, type); this.walletInfo.address = _publicAddress!; this.walletAddresses.address = _publicAddress!; diff --git a/lib/src/screens/restore/wallet_restore_from_keys_form.dart b/lib/src/screens/restore/wallet_restore_from_keys_form.dart index 2c0dfa53f..588fd7187 100644 --- a/lib/src/screens/restore/wallet_restore_from_keys_form.dart +++ b/lib/src/screens/restore/wallet_restore_from_keys_form.dart @@ -133,7 +133,7 @@ class WalletRestoreFromKeysFromState extends State { widget.walletRestoreViewModel.type == WalletType.banano; return AddressTextField( controller: privateKeyController, - placeholder: nanoBased ? S.of(context).seed_key : S.of(context).private_key, + placeholder: nanoBased ? S.of(context).seed_hex_form : S.of(context).private_key, options: [AddressTextFieldOption.paste], buttonColor: Theme.of(context).hintColor, onPushPasteButton: (_) { diff --git a/lib/view_model/restore/restore_wallet.dart b/lib/view_model/restore/restore_wallet.dart index 264b3d421..d46c48092 100644 --- a/lib/view_model/restore/restore_wallet.dart +++ b/lib/view_model/restore/restore_wallet.dart @@ -45,7 +45,7 @@ class RestoredWallet { factory RestoredWallet.fromSeed(Map json) { final height = json['height'] as String?; final mnemonic_seed = json['mnemonic_seed'] as String?; - final seed = json['seed'] as String?; + final seed = json['seed'] as String? ?? json['hexSeed'] as String?; return RestoredWallet( restoreMode: json['mode'] as WalletRestoreMode, type: json['type'] as WalletType, diff --git a/lib/view_model/restore/wallet_restore_from_qr_code.dart b/lib/view_model/restore/wallet_restore_from_qr_code.dart index 077675d1f..145db74d7 100644 --- a/lib/view_model/restore/wallet_restore_from_qr_code.dart +++ b/lib/view_model/restore/wallet_restore_from_qr_code.dart @@ -151,6 +151,14 @@ class WalletRestoreFromQRCode { return WalletRestoreMode.keys; } + if ((type == WalletType.nano || type == WalletType.banano) && credentials.containsKey('hexSeed')) { + final hexSeed = credentials['hexSeed'] as String; + if (hexSeed.isEmpty) { + throw Exception('Unexpected restore mode: hexSeed'); + } + return WalletRestoreMode.seed; + } + throw Exception('Unexpected restore mode: restore params are invalid'); } } diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart index 257bae1fd..d9de9473d 100644 --- a/lib/view_model/wallet_keys_view_model.dart +++ b/lib/view_model/wallet_keys_view_model.dart @@ -107,19 +107,18 @@ abstract class WalletKeysViewModelBase with Store { ]); } - if (_appStore.wallet!.type == WalletType.nano || _appStore.wallet!.type == WalletType.banano) { + bool nanoBased = + _appStore.wallet!.type == WalletType.nano || _appStore.wallet!.type == WalletType.banano; - // we don't necessarily have the seed phrase for nano / banano: - if (_appStore.wallet!.seed != null) { - items.addAll([ - StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!), - ]); - } - - // we always have the hex version of the seed: + if (nanoBased) { + // we always have the hex version of the seed and private key: items.addAll([ + if (_appStore.wallet!.seed != null) + StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!), + if (_appStore.wallet!.hexSeed != null) + StandartListItem(title: S.current.seed_hex_form, value: _appStore.wallet!.hexSeed!), if (_appStore.wallet!.privateKey != null) - StandartListItem(title: S.current.spend_key_private, value: _appStore.wallet!.privateKey!), + StandartListItem(title: S.current.private_key, value: _appStore.wallet!.privateKey!), ]); } } @@ -172,7 +171,10 @@ abstract class WalletKeysViewModelBase with Store { final restoreHeightResult = await restoreHeight; return { if (_appStore.wallet!.seed != null) 'seed': _appStore.wallet!.seed!, - if (_appStore.wallet!.privateKey != null) 'private_key': _appStore.wallet!.privateKey!, + if (_appStore.wallet!.seed == null && _appStore.wallet!.hexSeed != null) + 'hexSeed': _appStore.wallet!.hexSeed!, + if (_appStore.wallet!.seed == null && _appStore.wallet!.privateKey != null) + 'private_key': _appStore.wallet!.privateKey!, if (restoreHeightResult != null) ...{'height': restoreHeightResult} }; } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index fb883eb13..8065a5bd1 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -738,5 +738,6 @@ "unavailable_balance": "ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ", "unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ", "unspent_change": "يتغير", + "seed_hex_form": "بذور المحفظة (شكل عرافة)", "tor_connection": "ﺭﻮﺗ ﻝﺎﺼﺗﺍ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 1b3ded5d6..ab45efba3 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -734,5 +734,6 @@ "unavailable_balance": "Неналично салдо", "unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.", "unspent_change": "Промяна", - "tor_connection": "Tor връзка" -} + "tor_connection": "Tor връзка", + "seed_hex_form": "Семена от портфейл (шестнадесетична форма)" +} \ No newline at end of file diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 4f0e89bd3..88792ec15 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -734,5 +734,6 @@ "unavailable_balance": "Nedostupný zůstatek", "unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.", "unspent_change": "Změna", - "tor_connection": "Připojení Tor" -} + "tor_connection": "Připojení Tor", + "seed_hex_form": "Semeno peněženky (hex formulář)" +} \ No newline at end of file diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 360e621db..7b204f20c 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -742,5 +742,6 @@ "unavailable_balance": "Nicht verfügbares Guthaben", "unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.", "unspent_change": "Wechselgeld", - "tor_connection": "Tor-Verbindung" -} + "tor_connection": "Tor-Verbindung", + "seed_hex_form": "Brieftaschensamen (Sechskantform)" +} \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 0f059759d..bbcbdb6c0 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -743,5 +743,6 @@ "unavailable_balance": "Unavailable balance", "unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.", "unspent_change": "Change", - "tor_connection": "Tor connection" -} + "tor_connection": "Tor connection", + "seed_hex_form": "Wallet seed (hex form)" +} \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 8a4f180f6..e47f3e744 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -742,5 +742,6 @@ "unavailable_balance": "Saldo no disponible", "unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.", "unspent_change": "Cambiar", - "tor_connection": "conexión tor" -} + "tor_connection": "conexión tor", + "seed_hex_form": "Semilla de billetera (forma hexadecimal)" +} \ No newline at end of file diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 158aaadb4..f87ed9809 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -744,5 +744,6 @@ "camera_permission_is_required": "L'autorisation d'accès à la caméra est requise.\nVeuillez l'activer depuis les paramètres de l'application.", "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", "unspent_change": "Changement", - "tor_connection": "Connexion Tor" -} + "tor_connection": "Connexion Tor", + "seed_hex_form": "Graine du portefeuille (forme hexagonale)" +} \ No newline at end of file diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 8b6f38d05..2dce6f80d 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -720,5 +720,6 @@ "unavailable_balance": "Ma'aunin da ba ya samuwa", "unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.", "unspent_change": "Canza", - "tor_connection": "Tor haɗin gwiwa" -} + "tor_connection": "Tor haɗin gwiwa", + "seed_hex_form": "Gany Sero (form form)" +} \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 9afc420a2..66a4c8e47 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -742,5 +742,6 @@ "unavailable_balance": "अनुपलब्ध शेष", "unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।", "unspent_change": "परिवर्तन", - "tor_connection": "टोर कनेक्शन" -} + "tor_connection": "टोर कनेक्शन", + "seed_hex_form": "वॉलेट सीड (हेक्स फॉर्म)" +} \ No newline at end of file diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index fd4efa97e..4e84d3ed4 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -740,5 +740,6 @@ "unavailable_balance": "Nedostupno stanje", "unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.", "unspent_change": "Promijeniti", - "tor_connection": "Tor veza" -} + "tor_connection": "Tor veza", + "seed_hex_form": "Sjeme novčanika (šesterokutni oblik)" +} \ No newline at end of file diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 4de382641..82e9bca56 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -730,5 +730,6 @@ "unavailable_balance": "Saldo tidak tersedia", "unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.", "unspent_change": "Mengubah", - "tor_connection": "koneksi Tor" -} + "tor_connection": "koneksi Tor", + "seed_hex_form": "Biji dompet (bentuk hex)" +} \ No newline at end of file diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 4fc35b3e3..0005fb5e7 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -742,5 +742,6 @@ "unavailable_balance": "Saldo non disponibile", "unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.", "unspent_change": "Modifica", - "tor_connection": "Connessione Tor" -} + "tor_connection": "Connessione Tor", + "seed_hex_form": "Seme di portafoglio (forma esadecimale)" +} \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index a4fe8b46f..d57eaef5d 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -742,5 +742,6 @@ "unavailable_balance": "利用できない残高", "unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。", "unspent_change": "変化", - "tor_connection": "Tor接続" -} + "tor_connection": "Tor接続", + "seed_hex_form": "ウォレットシード(ヘックスフォーム)" +} \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 2b638e9d5..775918659 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -740,5 +740,6 @@ "unavailable_balance": "사용할 수 없는 잔액", "unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.", "unspent_change": "변화", - "tor_connection": "토르 연결" -} + "tor_connection": "토르 연결", + "seed_hex_form": "지갑 씨앗 (16 진 양식)" +} \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 19ee9c051..4aacb0bd3 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -740,5 +740,6 @@ "unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။", "unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။", "unspent_change": "ပေြာင်းလဲခြင်း", - "tor_connection": "Tor ချိတ်ဆက်မှု" -} + "tor_connection": "Tor ချိတ်ဆက်မှု", + "seed_hex_form": "ပိုက်ဆံအိတ်မျိုးစေ့ (Hex Form)" +} \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 838fec0c1..cf779afab 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -742,5 +742,6 @@ "unavailable_balance": "Onbeschikbaar saldo", "unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.", "unspent_change": "Wijziging", - "tor_connection": "Tor-verbinding" -} + "tor_connection": "Tor-verbinding", + "seed_hex_form": "Portemonnee zaad (hexvorm)" +} \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 309f20613..04c420db4 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -742,5 +742,6 @@ "unavailable_balance": "Niedostępne saldo", "unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.", "unspent_change": "Zmiana", - "tor_connection": "Połączenie Torem" -} + "tor_connection": "Połączenie Torem", + "seed_hex_form": "Nasiona portfela (forma sześciokątna)" +} \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 8feeb732c..a461141f3 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -741,5 +741,6 @@ "unavailable_balance": "Saldo indisponível", "unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.", "unspent_change": "Mudar", - "tor_connection": "Conexão Tor" -} + "tor_connection": "Conexão Tor", + "seed_hex_form": "Semente de carteira (forma hexadecimal)" +} \ No newline at end of file diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 98eddcae7..8d0cc647a 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -742,5 +742,6 @@ "unavailable_balance": "Недоступный баланс", "unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.", "unspent_change": "Изменять", - "tor_connection": "Тор соединение" -} + "tor_connection": "Тор соединение", + "seed_hex_form": "Семя кошелька (шестнадцатеричная форма)" +} \ No newline at end of file diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index c9cfca47c..151c65cd3 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -740,5 +740,6 @@ "unavailable_balance": "ยอดคงเหลือไม่พร้อมใช้งาน", "unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง", "unspent_change": "เปลี่ยน", - "tor_connection": "การเชื่อมต่อทอร์" -} + "tor_connection": "การเชื่อมต่อทอร์", + "seed_hex_form": "เมล็ดกระเป๋าเงิน (รูปแบบฐานสิบหก)" +} \ No newline at end of file diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index d68dbc656..258eb6f12 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -737,5 +737,6 @@ "unavailable_balance": "Hindi available na balanse", "unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.", "unspent_change": "Baguhin", - "tor_connection": "Koneksyon ng Tor" -} + "tor_connection": "Koneksyon ng Tor", + "seed_hex_form": "Wallet seed (hex form)" +} \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index c0fc58feb..33362b83c 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -740,5 +740,6 @@ "unavailable_balance": "Kullanılamayan bakiye", "unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.", "unspent_change": "Değiştirmek", - "tor_connection": "Tor bağlantısı" -} + "tor_connection": "Tor bağlantısı", + "seed_hex_form": "Cüzdan tohumu (onaltılık form)" +} \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 0ad5fa97a..7b79ac6e4 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -742,5 +742,6 @@ "unavailable_balance": "Недоступний баланс", "unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.", "unspent_change": "Зміна", - "tor_connection": "Підключення Tor" -} + "tor_connection": "Підключення Tor", + "seed_hex_form": "Насіння гаманця (шістнадцяткова форма)" +} \ No newline at end of file diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index e26c3b4d4..c8362ab33 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -734,5 +734,6 @@ "unavailable_balance": "ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ", "unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ", "unspent_change": "تبدیل کریں", + "seed_hex_form": "پرس بیج (ہیکس فارم)", "tor_connection": "ﻦﺸﮑﻨﮐ ﺭﻮﭨ" -} +} \ No newline at end of file diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index d512f5e8f..7b9b075d7 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -736,5 +736,6 @@ "unavailable_balance": "Iwontunwonsi ti ko si", "unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.", "unspent_change": "Yipada", - "tor_connection": "Tor asopọ" -} + "tor_connection": "Tor asopọ", + "seed_hex_form": "Irú Opamọwọ apamọwọ (HOX)" +} \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 974008594..e95bc077b 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -741,5 +741,6 @@ "unavailable_balance": "不可用余额", "unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。", "unspent_change": "改变", - "tor_connection": "Tor连接" -} + "tor_connection": "Tor连接", + "seed_hex_form": "钱包种子(十六进制形式)" +} \ No newline at end of file From 00c97c74b81d3d0af272379b9971aa8402773a69 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Sat, 25 Nov 2023 01:37:12 +0100 Subject: [PATCH 051/241] Cw 462 monero polyseed restore support (#1109) * CW-462 Mark Places to integrate Polyseed * CW-462 Add Restore from Polyseed * CW-462 Add Restore from Polyseed * CW-462 Add new Monero date-height pairs * CW-462 Little Cleanup * CW-462 Ups I missed that Debug line :/ * CW-462 Fix Polyseed not showing in Wallet-Seed/Keys Page * CW-462 Prepare for Wallet creation * CW-462 Fix merge conflict * CW-462 Fix generating monero.dart * CW-462 Add Polyseed generation * CW-462 Add Polyseed Languages to SeedLanguagePicker * CW-462 Apply requested changes * CW-462 Minor bug fixes in restore screen * Update wallet_restore_from_seed_form.dart * CW-462 Minor Bugfix * CW-462 Fix Restore from QR for Polyseeds * CW-462 Fix null-check-operator exception for Polyseeds and minor inconveniences * CW-462 Fix minor inconveniences * Fix conflicts and review comments and wrap unspent issue with try and catch with reporting failure --------- Co-authored-by: OmarHatem --- cw_core/lib/get_height_by_date.dart | 36 +++- cw_core/pubspec.lock | 4 +- cw_core/pubspec.yaml | 2 +- cw_monero/example/pubspec.lock | 15 +- cw_monero/ios/Classes/monero_api.cpp | 34 ++++ cw_monero/lib/api/signatures.dart | 3 + cw_monero/lib/api/types.dart | 3 + cw_monero/lib/api/wallet_manager.dart | 77 ++++++++- cw_monero/lib/monero_wallet.dart | 91 ++++++---- cw_monero/lib/monero_wallet_service.dart | 61 ++++++- cw_monero/pubspec.lock | 15 +- cw_monero/pubspec.yaml | 3 + lib/entities/preferences_key.dart | 1 + lib/entities/seed_type.dart | 36 ++++ lib/monero/cw_monero.dart | 8 +- lib/router.dart | 16 +- lib/routes.dart | 1 - .../advanced_privacy_settings_page.dart | 32 ++-- .../screens/new_wallet/new_wallet_page.dart | 43 +++-- .../wallet_restore_from_seed_form.dart | 161 ++++++++++++------ .../screens/restore/wallet_restore_page.dart | 84 ++++----- .../seed_language/seed_language_page.dart | 95 ----------- .../widgets/seed_language_picker.dart | 82 --------- lib/src/widgets/seed_language_picker.dart | 93 ++++++++++ lib/src/widgets/seed_language_selector.dart | 24 +-- lib/store/settings_store.dart | 76 ++++++--- .../advanced_privacy_settings_view_model.dart | 9 + .../restore/wallet_restore_from_qr_code.dart | 12 +- lib/view_model/wallet_new_vm.dart | 9 +- pubspec_base.yaml | 3 + res/values/strings_ar.arb | 8 +- res/values/strings_bg.arb | 8 +- res/values/strings_cs.arb | 8 +- res/values/strings_de.arb | 14 +- res/values/strings_en.arb | 8 +- res/values/strings_es.arb | 8 +- res/values/strings_fr.arb | 9 +- res/values/strings_ha.arb | 8 +- res/values/strings_hi.arb | 8 +- res/values/strings_hr.arb | 8 +- res/values/strings_id.arb | 8 +- res/values/strings_it.arb | 8 +- res/values/strings_ja.arb | 8 +- res/values/strings_ko.arb | 8 +- res/values/strings_my.arb | 8 +- res/values/strings_nl.arb | 8 +- res/values/strings_pl.arb | 8 +- res/values/strings_pt.arb | 8 +- res/values/strings_ru.arb | 8 +- res/values/strings_th.arb | 8 +- res/values/strings_tl.arb | 7 +- res/values/strings_tr.arb | 8 +- res/values/strings_uk.arb | 8 +- res/values/strings_ur.arb | 8 +- res/values/strings_yo.arb | 8 +- res/values/strings_zh.arb | 8 +- tool/configure.dart | 7 +- 57 files changed, 906 insertions(+), 444 deletions(-) create mode 100644 lib/entities/seed_type.dart delete mode 100644 lib/src/screens/seed_language/seed_language_page.dart delete mode 100644 lib/src/screens/seed_language/widgets/seed_language_picker.dart create mode 100644 lib/src/widgets/seed_language_picker.dart diff --git a/cw_core/lib/get_height_by_date.dart b/cw_core/lib/get_height_by_date.dart index 819990e0a..a680e6c25 100644 --- a/cw_core/lib/get_height_by_date.dart +++ b/cw_core/lib/get_height_by_date.dart @@ -84,7 +84,41 @@ final dates = { "2020-8": 2153983, "2020-9": 2176466, "2020-10": 2198453, - "2020-11": 2220000 + "2020-11": 2220000, + "2020-12": 2242240, + "2021-1": 2264584, + "2021-2": 2286892, + "2021-3": 2307079, + "2021-4": 2329385, + "2021-5": 2351004, + "2021-6": 2373306, + "2021-7": 2394882, + "2021-8": 2417162, + "2021-9": 2439490, + "2021-10": 2461020, + "2021-11": 2483377, + "2021-12": 2504932, + "2022-1": 2527316, + "2022-2": 2549605, + "2022-3": 2569711, + "2022-4": 2591995, + "2022-5": 2613603, + "2022-6": 2635840, + "2022-7": 2657395, + "2022-8": 2679705, + "2022-9": 2701991, + "2022-10": 2723607, + "2022-11": 2745899, + "2022-12": 2767427, + "2023-1": 2789763, + "2023-2": 2811996, + "2023-3": 2832118, + "2023-4": 2854365, + "2023-5": 2875972, + "2023-6": 2898234, + "2023-7": 2919771, + "2023-8": 2942045, + "2023-9": 2964280 }; int getMoneroHeigthByDate({required DateTime date}) { diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock index 058f33ba4..f351759ed 100644 --- a/cw_core/pubspec.lock +++ b/cw_core/pubspec.lock @@ -271,10 +271,10 @@ packages: dependency: "direct dev" description: name: hive_generator - sha256: "81fd20125cb2ce8fd23623d7744ffbaf653aae93706c9bd3bf7019ea0ace3938" + sha256: "06cb8f58ace74de61f63500564931f9505368f45f98958bd7a6c35ba24159db4" url: "https://pub.dev" source: hosted - version: "1.1.3" + version: "2.0.1" http: dependency: "direct main" description: diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml index 3763a7318..533b578ad 100644 --- a/cw_core/pubspec.yaml +++ b/cw_core/pubspec.yaml @@ -31,7 +31,7 @@ dev_dependencies: build_runner: ^2.1.11 build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 - hive_generator: ^1.1.3 + hive_generator: ^2.0.1 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_monero/example/pubspec.lock b/cw_monero/example/pubspec.lock index 661341e96..3dd2b5b61 100644 --- a/cw_monero/example/pubspec.lock +++ b/cw_monero/example/pubspec.lock @@ -301,10 +301,19 @@ packages: dependency: transitive description: name: pointycastle - sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" url: "https://pub.dev" source: hosted - version: "3.6.2" + version: "3.7.3" + polyseed: + dependency: transitive + description: + path: "." + ref: HEAD + resolved-ref: "504d58a5b147fccd3bc85a25f2e72fb32771ddd7" + url: "https://github.com/cake-tech/polyseed_dart.git" + source: git + version: "0.0.1" process: dependency: transitive description: @@ -416,5 +425,5 @@ packages: source: hosted version: "0.2.0+3" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.0.6 <4.0.0" flutter: ">=3.7.0" diff --git a/cw_monero/ios/Classes/monero_api.cpp b/cw_monero/ios/Classes/monero_api.cpp index a0712255a..7ad873647 100644 --- a/cw_monero/ios/Classes/monero_api.cpp +++ b/cw_monero/ios/Classes/monero_api.cpp @@ -374,6 +374,35 @@ extern "C" return true; } + bool restore_wallet_from_spend_key(char *path, char *password, char *seed, char *language, char *spendKey, int32_t networkType, uint64_t restoreHeight, char *error) + { + Monero::NetworkType _networkType = static_cast(networkType); + Monero::Wallet *wallet = Monero::WalletManagerFactory::getWalletManager()->createDeterministicWalletFromSpendKey( + std::string(path), + std::string(password), + std::string(language), + _networkType, + (uint64_t)restoreHeight, + std::string(spendKey)); + + int status; + std::string errorString; + + wallet->statusWithErrorString(status, errorString); + + if (status != Monero::Wallet::Status_Ok || !errorString.empty()) + { + error = strdup(errorString.c_str()); + return false; + } + + // Cache Raw to support Polyseed + wallet->setCacheAttribute("cakewallet.seed", std::string(seed)); + + change_current_wallet(wallet); + return true; + } + bool load_wallet(char *path, char *password, int32_t nettype) { nice(19); @@ -438,6 +467,11 @@ extern "C" const char *seed() { + std::string _rawSeed = get_current_wallet()->getCacheAttribute("cakewallet.seed"); + if (!_rawSeed.empty()) + { + return strdup(_rawSeed.c_str()); + } return strdup(get_current_wallet()->seed().c_str()); } diff --git a/cw_monero/lib/api/signatures.dart b/cw_monero/lib/api/signatures.dart index 9be828df0..17099db91 100644 --- a/cw_monero/lib/api/signatures.dart +++ b/cw_monero/lib/api/signatures.dart @@ -14,6 +14,9 @@ typedef restore_wallet_from_seed = Int8 Function( typedef restore_wallet_from_keys = Int8 Function(Pointer, Pointer, Pointer, Pointer, Pointer, Pointer, Int32, Int64, Pointer); +typedef restore_wallet_from_spend_key = Int8 Function(Pointer, Pointer, Pointer, + Pointer, Pointer, Int32, Int64, Pointer); + typedef is_wallet_exist = Int8 Function(Pointer); typedef load_wallet = Int8 Function(Pointer, Pointer, Int8); diff --git a/cw_monero/lib/api/types.dart b/cw_monero/lib/api/types.dart index 4c0c980dc..1d3904870 100644 --- a/cw_monero/lib/api/types.dart +++ b/cw_monero/lib/api/types.dart @@ -14,6 +14,9 @@ typedef RestoreWalletFromSeed = int Function( typedef RestoreWalletFromKeys = int Function(Pointer, Pointer, Pointer, Pointer, Pointer, Pointer, int, int, Pointer); +typedef RestoreWalletFromSpendKey = int Function(Pointer, Pointer, Pointer, + Pointer, Pointer, int, int, Pointer); + typedef IsWalletExist = int Function(Pointer); typedef LoadWallet = int Function(Pointer, Pointer, int); diff --git a/cw_monero/lib/api/wallet_manager.dart b/cw_monero/lib/api/wallet_manager.dart index 093d7e63b..260b420c5 100644 --- a/cw_monero/lib/api/wallet_manager.dart +++ b/cw_monero/lib/api/wallet_manager.dart @@ -5,7 +5,6 @@ import 'package:cw_monero/api/convert_utf8_to_string.dart'; import 'package:cw_monero/api/signatures.dart'; import 'package:cw_monero/api/types.dart'; import 'package:cw_monero/api/monero_api.dart'; -import 'package:cw_monero/api/wallet.dart'; import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart'; import 'package:cw_monero/api/exceptions/wallet_creation_exception.dart'; import 'package:cw_monero/api/exceptions/wallet_restore_from_keys_exception.dart'; @@ -25,6 +24,11 @@ final restoreWalletFromKeysNative = moneroApi 'restore_wallet_from_keys') .asFunction(); +final restoreWalletFromSpendKeyNative = moneroApi + .lookup>( + 'restore_wallet_from_spend_key') + .asFunction(); + final isWalletExistNative = moneroApi .lookup>('is_wallet_exist') .asFunction(); @@ -141,6 +145,42 @@ void restoreWalletFromKeysSync( } } +void restoreWalletFromSpendKeySync( + {required String path, + required String password, + required String seed, + required String language, + required String spendKey, + int nettype = 0, + int restoreHeight = 0}) { + final pathPointer = path.toNativeUtf8(); + final passwordPointer = password.toNativeUtf8(); + final seedPointer = seed.toNativeUtf8(); + final languagePointer = language.toNativeUtf8(); + final spendKeyPointer = spendKey.toNativeUtf8(); + final errorMessagePointer = ''.toNativeUtf8(); + final isWalletRestored = restoreWalletFromSpendKeyNative( + pathPointer, + passwordPointer, + seedPointer, + languagePointer, + spendKeyPointer, + nettype, + restoreHeight, + errorMessagePointer) != + 0; + + calloc.free(pathPointer); + calloc.free(passwordPointer); + calloc.free(languagePointer); + calloc.free(spendKeyPointer); + + if (!isWalletRestored) { + throw WalletRestoreFromKeysException( + message: convertUTF8ToString(pointer: errorMessagePointer)); + } +} + void loadWallet({ required String path, required String password, @@ -194,6 +234,23 @@ void _restoreFromKeys(Map args) { spendKey: spendKey); } +void _restoreFromSpendKey(Map args) { + final path = args['path'] as String; + final password = args['password'] as String; + final seed = args['seed'] as String; + final language = args['language'] as String; + final spendKey = args['spendKey'] as String; + final restoreHeight = args['restoreHeight'] as int; + + restoreWalletFromSpendKeySync( + path: path, + password: password, + seed: seed, + language: language, + restoreHeight: restoreHeight, + spendKey: spendKey); +} + Future _openWallet(Map args) async => loadWallet(path: args['path'] as String, password: args['password'] as String); @@ -251,4 +308,22 @@ Future restoreFromKeys( 'restoreHeight': restoreHeight }); +Future restoreFromSpendKey( + {required String path, + required String password, + required String seed, + required String language, + required String spendKey, + int nettype = 0, + int restoreHeight = 0}) async => + compute, void>(_restoreFromSpendKey, { + 'path': path, + 'password': password, + 'seed': seed, + 'language': language, + 'spendKey': spendKey, + 'nettype': nettype, + 'restoreHeight': restoreHeight + }); + Future isWalletExist({required String path}) => compute(_isWalletExist, path); diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index d7e66ecec..71c7e3967 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -29,6 +29,7 @@ import 'package:cw_monero/monero_transaction_info.dart'; import 'package:cw_monero/monero_unspent.dart'; import 'package:cw_monero/monero_wallet_addresses.dart'; import 'package:cw_monero/pending_monero_transaction.dart'; +import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; @@ -78,6 +79,8 @@ abstract class MoneroWalletBase Box unspentCoinsInfo; + void Function(FlutterErrorDetails)? _onError; + @override late MoneroWalletAddresses walletAddresses; @@ -388,46 +391,59 @@ abstract class MoneroWalletBase } Future updateUnspent() async { - refreshCoins(walletAddresses.account!.id); + try { + refreshCoins(walletAddresses.account!.id); - unspentCoins.clear(); + unspentCoins.clear(); - final coinCount = countOfCoins(); - for (var i = 0; i < coinCount; i++) { - final coin = getCoin(i); - if (coin.spent == 0) { - final unspent = MoneroUnspent.fromCoinsInfoRow(coin); - unspent.isChange = transaction_history.getTransaction(unspent.hash).direction == 1; - unspentCoins.add(unspent); - } - } - - if (unspentCoinsInfo.isEmpty) { - unspentCoins.forEach((coin) => _addCoinInfo(coin)); - return; - } - - if (unspentCoins.isNotEmpty) { - unspentCoins.forEach((coin) { - final coinInfoList = unspentCoinsInfo.values.where((element) => - element.walletId.contains(id) && - element.accountIndex == walletAddresses.account!.id && - element.keyImage!.contains(coin.keyImage!)); - - if (coinInfoList.isNotEmpty) { - final coinInfo = coinInfoList.first; - - coin.isFrozen = coinInfo.isFrozen; - coin.isSending = coinInfo.isSending; - coin.note = coinInfo.note; - } else { - _addCoinInfo(coin); + final coinCount = countOfCoins(); + for (var i = 0; i < coinCount; i++) { + final coin = getCoin(i); + if (coin.spent == 0) { + final unspent = MoneroUnspent.fromCoinsInfoRow(coin); + if (unspent.hash.isNotEmpty) { + unspent.isChange = transaction_history + .getTransaction(unspent.hash) + .direction == 1; + } + unspentCoins.add(unspent); } - }); - } + } - await _refreshUnspentCoinsInfo(); - _askForUpdateBalance(); + if (unspentCoinsInfo.isEmpty) { + unspentCoins.forEach((coin) => _addCoinInfo(coin)); + return; + } + + if (unspentCoins.isNotEmpty) { + unspentCoins.forEach((coin) { + final coinInfoList = unspentCoinsInfo.values.where((element) => + element.walletId.contains(id) && + element.accountIndex == walletAddresses.account!.id && + element.keyImage!.contains(coin.keyImage!)); + + if (coinInfoList.isNotEmpty) { + final coinInfo = coinInfoList.first; + + coin.isFrozen = coinInfo.isFrozen; + coin.isSending = coinInfo.isSending; + coin.note = coinInfo.note; + } else { + _addCoinInfo(coin); + } + }); + } + + await _refreshUnspentCoinsInfo(); + _askForUpdateBalance(); + } catch (e, s) { + print(e.toString()); + _onError?.call(FlutterErrorDetails( + exception: e, + stack: s, + library: this.runtimeType.toString(), + )); + } } Future _addCoinInfo(MoneroUnspent coin) async { @@ -632,4 +648,7 @@ abstract class MoneroWalletBase walletAddresses.updateSubaddressList(accountIndex: account?.id ?? 0); } } + + @override + void setExceptionHandler(void Function(FlutterErrorDetails) onError) => _onError = onError; } diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 8cb3aa948..8e9eb6eac 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -7,16 +7,20 @@ 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/exceptions/wallet_opening_exception.dart'; import 'package:cw_monero/api/wallet_manager.dart' as monero_wallet_manager; import 'package:cw_monero/monero_wallet.dart'; import 'package:hive/hive.dart'; +import 'package:polyseed/polyseed.dart'; +import 'package:polyseed/src/utils/key_utils.dart'; class MoneroNewWalletCredentials extends WalletCredentials { - MoneroNewWalletCredentials({required String name, required this.language, String? password}) + MoneroNewWalletCredentials({required String name, required this.language, required this.isPolyseed, String? password}) : super(name: name, password: password); final String language; + final bool isPolyseed; } class MoneroRestoreWalletFromSeedCredentials extends WalletCredentials { @@ -68,10 +72,17 @@ class MoneroWalletService extends WalletService< Future create(MoneroNewWalletCredentials credentials) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); + + if (credentials.isPolyseed) { + final polyseed = Polyseed.create(); + final lang = PolyseedLang.getByEnglishName(credentials.language); + + return _restoreFromPolyseed( + path, credentials.password!, polyseed, credentials.walletInfo!, lang); + } + await monero_wallet_manager.createWallet( - path: path, - password: credentials.password!, - language: credentials.language); + path: path, password: credentials.password!, language: credentials.language); final wallet = MoneroWallet( walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); @@ -215,6 +226,12 @@ class MoneroWalletService extends WalletService< @override Future restoreFromSeed( MoneroRestoreWalletFromSeedCredentials credentials) async { + + // Restore from Polyseed + if (Polyseed.isValidSeed(credentials.mnemonic)) { + return restoreFromPolyseed(credentials); + } + try { final path = await pathForWallet(name: credentials.name, type: getType()); await monero_wallet_manager.restoreFromSeed( @@ -234,6 +251,42 @@ class MoneroWalletService extends WalletService< } } + Future restoreFromPolyseed(MoneroRestoreWalletFromSeedCredentials credentials) async { + try { + 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); + + return _restoreFromPolyseed(path, credentials.password!, polyseed, credentials.walletInfo!, lang); + } catch (e) { + // TODO: Implement Exception for wallet list service. + print('MoneroWalletsManager Error: $e'); + rethrow; + } + } + + Future _restoreFromPolyseed(String path, String password, Polyseed polyseed, + WalletInfo walletInfo, PolyseedLang lang, + {PolyseedCoin coin = PolyseedCoin.POLYSEED_MONERO}) async { + final height = getMoneroHeigthByDate( + date: DateTime.fromMillisecondsSinceEpoch(polyseed.birthday * 1000)); + final spendKey = keyToHexString(polyseed.generateKey(coin, 32)); + + await monero_wallet_manager.restoreFromSpendKey( + path: path, + password: password, + seed: polyseed.encode(lang, coin), + language: lang.nameEnglish, + restoreHeight: height, + spendKey: spendKey); + final wallet = MoneroWallet( + walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.init(); + + return wallet; + } + Future repairOldAndroidWallet(String name) async { try { if (!Platform.isAndroid) { diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index dc0f9aeed..46ebe8028 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -478,10 +478,19 @@ packages: dependency: transitive description: name: pointycastle - sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" url: "https://pub.dev" source: hosted - version: "3.6.2" + version: "3.7.3" + polyseed: + dependency: "direct main" + description: + path: "." + ref: HEAD + resolved-ref: "504d58a5b147fccd3bc85a25f2e72fb32771ddd7" + url: "https://github.com/cake-tech/polyseed_dart.git" + source: git + version: "0.0.1" pool: dependency: transitive description: @@ -689,5 +698,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.0.6 <4.0.0" flutter: ">=3.7.0" diff --git a/cw_monero/pubspec.yaml b/cw_monero/pubspec.yaml index cf2993ef3..55e9b354c 100644 --- a/cw_monero/pubspec.yaml +++ b/cw_monero/pubspec.yaml @@ -19,6 +19,9 @@ dependencies: flutter_mobx: ^2.0.6+1 intl: ^0.18.0 encrypt: ^5.0.1 + polyseed: + git: + url: https://github.com/cake-tech/polyseed_dart.git cw_core: path: ../cw_core diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 85df63b69..bdd6c24a7 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -64,6 +64,7 @@ class PreferencesKey { static const exchangeProvidersSelection = 'exchange-providers-selection'; static const autoGenerateSubaddressStatusKey = 'auto_generate_subaddress_status'; + static const moneroSeedType = 'monero_seed_type'; static const clearnetDonationLink = 'clearnet_donation_link'; static const onionDonationLink = 'onion_donation_link'; static const lastSeenAppVersion = 'last_seen_app_version'; diff --git a/lib/entities/seed_type.dart b/lib/entities/seed_type.dart new file mode 100644 index 000000000..0a1a191c6 --- /dev/null +++ b/lib/entities/seed_type.dart @@ -0,0 +1,36 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cw_core/enumerable_item.dart'; + +class SeedType extends EnumerableItem with Serializable { + const SeedType({required String title, required int raw}) : super(title: title, raw: raw); + + static const all = [SeedType.legacy, SeedType.polyseed]; + + static const defaultSeedType = legacy; + + static const legacy = SeedType(raw: 0, title: 'Legacy (25 words)'); + static const polyseed = SeedType(raw: 1, title: 'Polyseed (16 words)'); + + static SeedType deserialize({required int raw}) { + switch (raw) { + case 0: + return legacy; + case 1: + return polyseed; + default: + throw Exception('Unexpected token: $raw for SeedType deserialize'); + } + } + + @override + String toString() { + switch (this) { + case SeedType.legacy: + return S.current.seedtype_legacy; + case SeedType.polyseed: + return S.current.seedtype_polyseed; + default: + return ''; + } + } +} diff --git a/lib/monero/cw_monero.dart b/lib/monero/cw_monero.dart index 9ae248ca0..947d274a8 100644 --- a/lib/monero/cw_monero.dart +++ b/lib/monero/cw_monero.dart @@ -166,6 +166,10 @@ class CWMonero extends Monero { @override List getMoneroWordList(String language) { + if (language.startsWith("POLYSEED_")) { + final lang = language.replaceAll("POLYSEED_", ""); + return PolyseedLang.getByEnglishName(lang).words; + } switch (language.toLowerCase()) { case 'english': return EnglishMnemonics.words; @@ -223,8 +227,10 @@ class CWMonero extends Monero { WalletCredentials createMoneroNewWalletCredentials({ required String name, required String language, + required bool isPolyseed, String? password}) => - MoneroNewWalletCredentials(name: name, password: password, language: language); + MoneroNewWalletCredentials( + name: name, password: password, language: language, isPolyseed: isPolyseed); @override Map getKeys(Object wallet) { diff --git a/lib/router.dart b/lib/router.dart index fb21ba32c..313751ab3 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -56,6 +56,7 @@ import 'package:cake_wallet/src/screens/support_other_links/support_other_links_ import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart'; import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart'; +import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart'; @@ -87,7 +88,6 @@ import 'package:cake_wallet/src/screens/setup_pin_code/setup_pin_code.dart'; import 'package:cake_wallet/src/screens/restore/restore_options_page.dart'; import 'package:cake_wallet/src/screens/send/send_page.dart'; import 'package:cake_wallet/src/screens/disclaimer/disclaimer_page.dart'; -import 'package:cake_wallet/src/screens/seed_language/seed_language_page.dart'; import 'package:cake_wallet/src/screens/transaction_details/transaction_details_page.dart'; import 'package:cake_wallet/src/screens/monero_accounts/monero_account_edit_or_create_page.dart'; import 'package:cake_wallet/src/screens/contact/contact_list_page.dart'; @@ -147,8 +147,9 @@ Route createRoute(RouteSettings settings) { case Routes.newWallet: final type = settings.arguments as WalletType; final walletNewVM = getIt.get(param1: type); + final settingsStore = getIt.get(); - return CupertinoPageRoute(builder: (_) => NewWalletPage(walletNewVM)); + return CupertinoPageRoute(builder: (_) => NewWalletPage(walletNewVM, settingsStore)); case Routes.setupPin: Function(PinCodeState, String)? callback; @@ -264,17 +265,6 @@ Route createRoute(RouteSettings settings) { case Routes.changeRep: return CupertinoPageRoute(builder: (_) => getIt.get()); - case Routes.seedLanguage: - final args = settings.arguments as List; - final type = args.first as WalletType; - final redirectRoute = args[1] as String; - - return CupertinoPageRoute(builder: (_) { - return SeedLanguage( - onConfirm: (context, lang) => - Navigator.of(context).popAndPushNamed(redirectRoute, arguments: [type, lang])); - }); - case Routes.walletList: return MaterialPageRoute( fullscreenDialog: true, builder: (_) => getIt.get()); diff --git a/lib/routes.dart b/lib/routes.dart index 4511d48e1..60801297a 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -18,7 +18,6 @@ class Routes { static const disclaimer = '/disclaimer'; static const readDisclaimer = '/read_disclaimer'; static const changeRep = '/change_representative'; - static const seedLanguage = '/seed_language'; static const walletList = '/view_model.wallet_list'; static const auth = '/auth'; static const newNode = '/new_node_list'; diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index 66a28042d..4b61e7889 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/seed_phrase_length.dart'; +import 'package:cake_wallet/entities/seed_type.dart'; import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart'; @@ -97,16 +98,27 @@ class _AdvancedPrivacySettingsBodyState extends State( - title: S.current.seed_phrase_length, - items: SeedPhraseLength.values, - selectedItem: widget.privacySettingsViewModel.seedPhraseLength, - onItemSelected: (SeedPhraseLength length) { - widget.privacySettingsViewModel.setSeedPhraseLength(length); - }, - ); - }), + Observer(builder: (_) { + return SettingsPickerCell( + title: S.current.seed_phrase_length, + items: SeedPhraseLength.values, + selectedItem: widget.privacySettingsViewModel.seedPhraseLength, + onItemSelected: (SeedPhraseLength length) { + widget.privacySettingsViewModel.setSeedPhraseLength(length); + }, + ); + }), + if (widget.privacySettingsViewModel.hasSeedTypeOption) + Observer(builder: (_) { + return SettingsChoicesCell( + ChoicesListItem( + title: S.current.seedtype, + items: SeedType.all, + selectedItem: widget.privacySettingsViewModel.seedType, + onItemSelected: widget.privacySettingsViewModel.setSeedType, + ), + ); + }), ], ), bottomSectionPadding: EdgeInsets.all(24), diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index 5577fcd88..d86d51e93 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -14,17 +14,20 @@ import 'package:cake_wallet/src/widgets/seed_language_selector.dart'; import 'package:cake_wallet/src/screens/base_page.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/screens/seed_language/widgets/seed_language_picker.dart'; +import 'package:cake_wallet/src/widgets/seed_language_picker.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/view_model/wallet_new_vm.dart'; import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; +import 'package:cake_wallet/entities/seed_type.dart'; +import 'package:cake_wallet/store/settings_store.dart'; class NewWalletPage extends BasePage { - NewWalletPage(this._walletNewVM); + NewWalletPage(this._walletNewVM, this._settingsStore); final WalletNewVM _walletNewVM; + final SettingsStore _settingsStore; final walletNameImage = Image.asset('assets/images/wallet_name.png'); @@ -35,14 +38,15 @@ class NewWalletPage extends BasePage { @override Widget body(BuildContext context) => WalletNameForm( - _walletNewVM, currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage); + _walletNewVM, currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage, _settingsStore); } class WalletNameForm extends StatefulWidget { - WalletNameForm(this._walletNewVM, this.walletImage); + WalletNameForm(this._walletNewVM, this.walletImage, this._settingsStore); final WalletNewVM _walletNewVM; final Image walletImage; + final SettingsStore _settingsStore; @override _WalletNameFormState createState() => _WalletNameFormState(_walletNewVM); @@ -125,15 +129,20 @@ class _WalletNameFormState extends State { hintStyle: TextStyle( fontSize: 18.0, fontWeight: FontWeight.w500, - color: Theme.of(context).extension()!.hintTextColor), + color: + Theme.of(context).extension()!.hintTextColor), hintText: S.of(context).wallet_name, focusedBorder: UnderlineInputBorder( borderSide: BorderSide( - color: Theme.of(context).extension()!.underlineColor, + color: Theme.of(context) + .extension()! + .underlineColor, width: 1.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( - color: Theme.of(context).extension()!.underlineColor, + color: Theme.of(context) + .extension()! + .underlineColor, width: 1.0), ), suffixIcon: Semantics( @@ -160,7 +169,9 @@ class _WalletNameFormState extends State { height: 34, child: Image.asset( 'assets/images/refresh_icon.png', - color: Theme.of(context).extension()!.textFieldButtonIconColor, + color: Theme.of(context) + .extension()! + .textFieldButtonIconColor, ), ), ), @@ -184,10 +195,15 @@ class _WalletNameFormState extends State { color: Theme.of(context).extension()!.titleColor), ), ), - Padding( - padding: EdgeInsets.only(top: 24), - child: SeedLanguageSelector( - key: _languageSelectorKey, initialSelected: defaultSeedLanguage), + Observer( + builder: (BuildContext build) => Padding( + padding: EdgeInsets.only(top: 24), + child: SeedLanguageSelector( + key: _languageSelectorKey, + initialSelected: defaultSeedLanguage, + seedType: widget._settingsStore.moneroSeedType, + ), + ), ) ] ], @@ -237,9 +253,10 @@ class _WalletNameFormState extends State { buttonAction: () => Navigator.of(context).pop()); }); } else { + final isPolyseed = widget._settingsStore.moneroSeedType == SeedType.polyseed; _walletNewVM.create( options: _walletNewVM.hasLanguageSelector - ? _languageSelectorKey.currentState!.selected + ? [_languageSelectorKey.currentState!.selected, isPolyseed] : null); } } diff --git a/lib/src/screens/restore/wallet_restore_from_seed_form.dart b/lib/src/screens/restore/wallet_restore_from_seed_form.dart index d10277ced..ac8413212 100644 --- a/lib/src/screens/restore/wallet_restore_from_seed_form.dart +++ b/lib/src/screens/restore/wallet_restore_from_seed_form.dart @@ -1,17 +1,17 @@ +import 'package:cake_wallet/core/wallet_name_validator.dart'; import 'package:cake_wallet/entities/generate_name.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:cake_wallet/view_model/wallet_restore_view_model.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:cake_wallet/utils/show_pop_up.dart'; -import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart'; -import 'package:cake_wallet/src/widgets/seed_widget.dart'; +import 'package:cake_wallet/entities/seed_type.dart'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart'; -import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/core/wallet_name_validator.dart'; +import 'package:cake_wallet/src/widgets/picker.dart'; +import 'package:cake_wallet/src/widgets/seed_language_picker.dart'; +import 'package:cake_wallet/src/widgets/seed_widget.dart'; import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:flutter/material.dart'; +import 'package:polyseed/polyseed.dart'; class WalletRestoreFromSeedForm extends StatefulWidget { WalletRestoreFromSeedForm( @@ -34,8 +34,7 @@ class WalletRestoreFromSeedForm extends StatefulWidget { final void Function(String)? onLanguageChange; @override - WalletRestoreFromSeedFormState createState() => - WalletRestoreFromSeedFormState('English'); + WalletRestoreFromSeedFormState createState() => WalletRestoreFromSeedFormState('English'); } class WalletRestoreFromSeedFormState extends State { @@ -44,77 +43,116 @@ class WalletRestoreFromSeedFormState extends State { blockchainHeightKey = GlobalKey(), formKey = GlobalKey(), languageController = TextEditingController(), - nameTextEditingController = TextEditingController(); + nameTextEditingController = TextEditingController(), + seedTypeController = TextEditingController(); final GlobalKey seedWidgetStateKey; final GlobalKey blockchainHeightKey; final TextEditingController languageController; final TextEditingController nameTextEditingController; + final TextEditingController seedTypeController; final GlobalKey formKey; String language; + bool isPolyseed = false; @override void initState() { _setLanguageLabel(language); + _setSeedType(SeedType.defaultSeedType); super.initState(); } + void onSeedChange(String seed) { + if (widget.type == WalletType.monero && Polyseed.isValidSeed(seed)) { + final lang = PolyseedLang.getByPhrase(seed); + + _changeSeedType(SeedType.polyseed); + _changeLanguage(lang.nameEnglish); + } + widget.onSeedChange?.call(seed); + } + @override Widget build(BuildContext context) { return Container( padding: EdgeInsets.only(left: 24, right: 24), child: Column(children: [ Form( - key: formKey, - child: Stack( - alignment: Alignment.centerRight, - children: [ - BaseTextFormField( - controller: nameTextEditingController, - hintText: S.of(context).wallet_name, - suffixIcon: IconButton( - onPressed: () async { - final rName = await generateName(); - FocusManager.instance.primaryFocus?.unfocus(); + key: formKey, + child: Stack( + alignment: Alignment.centerRight, + children: [ + BaseTextFormField( + controller: nameTextEditingController, + hintText: S.of(context).wallet_name, + suffixIcon: IconButton( + onPressed: () async { + final rName = await generateName(); + FocusManager.instance.primaryFocus?.unfocus(); - setState(() { - nameTextEditingController.text = rName; - nameTextEditingController.selection = - TextSelection.fromPosition(TextPosition( - offset: nameTextEditingController.text.length)); - }); - }, - icon: Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(6.0), - color: Theme.of(context).hintColor, - ), - width: 34, - height: 34, - child: Image.asset( - 'assets/images/refresh_icon.png', - color: Theme.of(context).extension()!.textFieldButtonIconColor, + setState(() { + nameTextEditingController.text = rName; + nameTextEditingController.selection = TextSelection.fromPosition( + TextPosition(offset: nameTextEditingController.text.length)); + }); + }, + icon: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6.0), + color: Theme.of(context).hintColor, + ), + width: 34, + height: 34, + child: Image.asset( + 'assets/images/refresh_icon.png', + color: Theme.of(context) + .extension()! + .textFieldButtonIconColor, + ), + ), ), + validator: WalletNameValidator(), ), - ), - validator: WalletNameValidator(), - ), - ], - )), + ], + )), Container(height: 20), SeedWidget( key: seedWidgetStateKey, language: language, type: widget.type, - onSeedChange: widget.onSeedChange), + onSeedChange: onSeedChange), + if (widget.type == WalletType.monero) + GestureDetector( + onTap: () async { + await showPopUp( + context: context, + builder: (_) => Picker( + items: SeedType.all, + selectedAtIndex: isPolyseed ? 1 : 0, + mainAxisAlignment: MainAxisAlignment.start, + onItemSelected: _changeSeedType, + isSeparated: false, + )); + }, + child: Container( + color: Colors.transparent, + padding: EdgeInsets.only(top: 20.0), + child: IgnorePointer( + child: BaseTextFormField( + controller: seedTypeController, + enableInteractiveSelection: false, + readOnly: true)))), if (widget.displayLanguageSelector) GestureDetector( onTap: () async { await showPopUp( context: context, builder: (_) => SeedLanguagePicker( - selected: language, onItemSelected: _changeLanguage)); + selected: language, + onItemSelected: _changeLanguage, + seedType: isPolyseed ? SeedType.polyseed : SeedType.legacy, + )); }, child: Container( color: Colors.transparent, @@ -124,24 +162,35 @@ class WalletRestoreFromSeedFormState extends State { controller: languageController, enableInteractiveSelection: false, readOnly: true)))), - if (widget.displayBlockHeightSelector) + if (!isPolyseed && widget.displayBlockHeightSelector) BlockchainHeightWidget( focusNode: widget.blockHeightFocusNode, key: blockchainHeightKey, onHeightOrDateEntered: widget.onHeightOrDateEntered, - hasDatePicker: widget.type == WalletType.monero) + hasDatePicker: widget.type == WalletType.monero), ])); } void _changeLanguage(String language) { + final setLang = isPolyseed ? "POLYSEED_$language" : language; setState(() { - this.language = language; - seedWidgetStateKey.currentState!.changeSeedLanguage(language); - _setLanguageLabel(language); - widget.onLanguageChange?.call(language); + this.language = setLang; + seedWidgetStateKey.currentState!.changeSeedLanguage(setLang); + _setLanguageLabel(setLang); + widget.onLanguageChange?.call(setLang); }); } void _setLanguageLabel(String language) => - languageController.text = '$language (Seed language)'; + languageController.text = '${language.replaceAll("POLYSEED_", "")} (Seed language)'; + + void _changeSeedType(SeedType item) { + _setSeedType(item); + _changeLanguage('English'); + } + + void _setSeedType(SeedType item) { + setState(() => isPolyseed = item == SeedType.polyseed); + seedTypeController.text = item.toString(); + } } diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index d77c8aa2a..ccac6f34c 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -1,29 +1,30 @@ +import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/restore/wallet_restore_from_keys_form.dart'; +import 'package:cake_wallet/src/screens/restore/wallet_restore_from_seed_form.dart'; +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; -import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; +import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/view_model/restore/restore_mode.dart'; +import 'package:cake_wallet/view_model/wallet_restore_view_model.dart'; import 'package:cw_core/nano_account_info_response.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:mobx/mobx.dart'; -import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:polyseed/polyseed.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/core/execution_state.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/view_model/wallet_restore_view_model.dart'; -import 'package:cake_wallet/src/screens/restore/wallet_restore_from_keys_form.dart'; -import 'package:cake_wallet/src/screens/restore/wallet_restore_from_seed_form.dart'; -import 'package:cake_wallet/src/widgets/primary_button.dart'; -import 'package:cake_wallet/utils/show_pop_up.dart'; -import 'package:cake_wallet/view_model/restore/restore_mode.dart'; -import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; class WalletRestorePage extends BasePage { WalletRestorePage(this.walletRestoreViewModel) @@ -48,27 +49,13 @@ class WalletRestorePage extends BasePage { } }, onSeedChange: (String seed) { - if (walletRestoreViewModel.hasBlockchainHeightLanguageSelector) { - final hasHeight = walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey - .currentState!.restoreHeightController.text.isNotEmpty; - if (hasHeight) { - walletRestoreViewModel.isButtonEnabled = _isValidSeed(); - } - } else { - walletRestoreViewModel.isButtonEnabled = _isValidSeed(); - } + final isPolyseed = + walletRestoreViewModel.type == WalletType.monero && Polyseed.isValidSeed(seed); + _validateOnChange(isPolyseed: isPolyseed); }, - onLanguageChange: (_) { - if (walletRestoreViewModel.hasBlockchainHeightLanguageSelector) { - final hasHeight = walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey - .currentState!.restoreHeightController.text.isNotEmpty; - - if (hasHeight) { - walletRestoreViewModel.isButtonEnabled = _isValidSeed(); - } - } else { - walletRestoreViewModel.isButtonEnabled = _isValidSeed(); - } + onLanguageChange: (String language) { + final isPolyseed = language.startsWith("POLYSEED_"); + _validateOnChange(isPolyseed: isPolyseed); })); break; case WalletRestoreMode.keys: @@ -163,7 +150,8 @@ class WalletRestorePage extends BasePage { color: Theme.of(context).colorScheme.background, child: Center( child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), + constraints: + BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -219,8 +207,8 @@ class WalletRestorePage extends BasePage { const SizedBox(height: 25), GestureDetector( onTap: () { - Navigator.of(context) - .pushNamed(Routes.advancedPrivacySettings, arguments: walletRestoreViewModel.type); + Navigator.of(context).pushNamed(Routes.advancedPrivacySettings, + arguments: walletRestoreViewModel.type); }, child: Text(S.of(context).advanced_privacy_settings), ), @@ -235,9 +223,26 @@ class WalletRestorePage extends BasePage { ); } + void _validateOnChange({bool isPolyseed = false}) { + if (!isPolyseed && walletRestoreViewModel.hasBlockchainHeightLanguageSelector) { + final hasHeight = walletRestoreFromSeedFormKey + .currentState?.blockchainHeightKey.currentState?.restoreHeightController.text.isNotEmpty; + + if (hasHeight == true) { + walletRestoreViewModel.isButtonEnabled = _isValidSeed(); + } + } else { + walletRestoreViewModel.isButtonEnabled = _isValidSeed(); + } + } + bool _isValidSeed() { - final seedWords = - walletRestoreFromSeedFormKey.currentState!.seedWidgetStateKey.currentState!.text.split(' '); + final seedPhrase = + walletRestoreFromSeedFormKey.currentState!.seedWidgetStateKey.currentState!.text; + if (walletRestoreViewModel.type == WalletType.monero && Polyseed.isValidSeed(seedPhrase)) + return true; + + final seedWords = seedPhrase.split(' '); if ((walletRestoreViewModel.type == WalletType.monero || walletRestoreViewModel.type == WalletType.haven) && @@ -282,7 +287,8 @@ class WalletRestorePage extends BasePage { if (walletRestoreViewModel.hasBlockchainHeightLanguageSelector) { credentials['height'] = - walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey.currentState!.height; + walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey.currentState?.height ?? + -1; } credentials['name'] = diff --git a/lib/src/screens/seed_language/seed_language_page.dart b/lib/src/screens/seed_language/seed_language_page.dart deleted file mode 100644 index b15da0375..000000000 --- a/lib/src/screens/seed_language/seed_language_page.dart +++ /dev/null @@ -1,95 +0,0 @@ -import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; -import 'package:cake_wallet/themes/theme_base.dart'; -import 'package:cake_wallet/src/widgets/seed_language_selector.dart'; -import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/screens/base_page.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/screens/seed_language/widgets/seed_language_picker.dart'; - -class SeedLanguage extends BasePage { - SeedLanguage({required this.onConfirm}); - - final Function(BuildContext, String) onConfirm; - - final walletNameImage = Image.asset('assets/images/wallet_name.png'); - final walletNameLightImage = - Image.asset('assets/images/wallet_name_light.png'); - - @override - String get title => S.current.wallet_list_restore_wallet; - - @override - Widget body(BuildContext context) => - SeedLanguageForm( - onConfirm: onConfirm, - walletImage: currentTheme.type == ThemeType.dark - ? walletNameImage : walletNameLightImage); -} - -class SeedLanguageForm extends StatefulWidget { - SeedLanguageForm({required this.onConfirm, required this.walletImage}); - - final Function(BuildContext, String) onConfirm; - final Image walletImage; - - @override - SeedLanguageFormState createState() => SeedLanguageFormState(); -} - -class SeedLanguageFormState extends State { - static const aspectRatioImage = 1.22; - final _languageSelectorKey = GlobalKey(); - - @override - Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.only(top: 24), - child: ScrollableWithBottomSection( - contentPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), - content: - Column(crossAxisAlignment: CrossAxisAlignment.center, children: [ - Padding( - padding: EdgeInsets.only(left: 12, right: 12), - child: AspectRatio( - aspectRatio: aspectRatioImage, - child: FittedBox(child: widget.walletImage, - fit: BoxFit.fill)), - ), - Padding( - padding: EdgeInsets.only(top: 40), - child: Text( - S.of(context).seed_language_choose, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16.0, - fontWeight: FontWeight.w500, - color: - Theme.of(context).extension()!.titleColor), - ), - ), - Padding( - padding: EdgeInsets.only(top: 24), - child: SeedLanguageSelector( - key: _languageSelectorKey, - initialSelected: defaultSeedLanguage), - ) - ]), - bottomSectionPadding: - EdgeInsets.only(left: 24, right: 24, bottom: 24), - bottomSection: Observer( - builder: (context) { - return PrimaryButton( - onPressed: () => widget.onConfirm( - context, _languageSelectorKey.currentState!.selected), - text: S.of(context).seed_language_next, - color: Colors.green, - textColor: Colors.white); - }, - )), - ); - } -} diff --git a/lib/src/screens/seed_language/widgets/seed_language_picker.dart b/lib/src/screens/seed_language/widgets/seed_language_picker.dart deleted file mode 100644 index 742a31e61..000000000 --- a/lib/src/screens/seed_language/widgets/seed_language_picker.dart +++ /dev/null @@ -1,82 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:cake_wallet/src/widgets/picker.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:cake_wallet/generated/i18n.dart'; - -List flagImages = [ - Image.asset('assets/images/flags/usa.png'), - Image.asset('assets/images/flags/chn.png'), - Image.asset('assets/images/flags/nld.png'), - Image.asset('assets/images/flags/deu.png'), - Image.asset('assets/images/flags/jpn.png'), - Image.asset('assets/images/flags/prt.png'), - Image.asset('assets/images/flags/rus.png'), - Image.asset('assets/images/flags/esp.png'), - Image.asset('assets/images/flags/fra.png'), - Image.asset('assets/images/flags/ita.png'), -]; - -const List languageCodes = [ - 'Eng', - 'Chi', - 'Ned', - 'Ger', - 'Jap', - 'Por', - 'Rus', - 'Esp', - 'Fre', - 'Ita', -]; - -const defaultSeedLanguage = 'English'; - -const List seedLanguages = [ - defaultSeedLanguage, - 'Chinese (simplified)', - 'Dutch', - 'German', - 'Japanese', - 'Portuguese', - 'Russian', - 'Spanish', - 'French', - 'Italian', -]; - -enum Places { topLeft, topRight, bottomLeft, bottomRight, inside } - -class SeedLanguagePicker extends StatefulWidget { - SeedLanguagePicker({Key? key, this.selected = defaultSeedLanguage, required this.onItemSelected}) - : super(key: key); - - final String selected; - final Function(String) onItemSelected; - - @override - SeedLanguagePickerState createState() => - SeedLanguagePickerState(selected: selected, onItemSelected: onItemSelected); -} - -class SeedLanguagePickerState extends State { - SeedLanguagePickerState({required this.selected, required this.onItemSelected}); - - final String selected; - final Function(String) onItemSelected; - - @override - Widget build(BuildContext context) { - return Picker( - selectedAtIndex: seedLanguages.indexOf(selected), - items: seedLanguages, - images: flagImages, - isGridView: true, - title: S.of(context).seed_choose, - hintText: S.of(context).seed_choose, - matchingCriteria: (String language, String searchText) { - return language.toLowerCase().contains(searchText); - }, - onItemSelected: onItemSelected, - ); - } -} diff --git a/lib/src/widgets/seed_language_picker.dart b/lib/src/widgets/seed_language_picker.dart new file mode 100644 index 000000000..3bb0376b1 --- /dev/null +++ b/lib/src/widgets/seed_language_picker.dart @@ -0,0 +1,93 @@ +import 'package:flutter/material.dart'; +import 'package:cake_wallet/src/widgets/picker.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:cake_wallet/generated/i18n.dart'; + +import 'package:cake_wallet/entities/seed_type.dart'; + +class SeedLanguagePickerOption { + SeedLanguagePickerOption(this.name, this.nameLocalized, this.image, this.supportedSeedTypes); + + final String name; + final String nameLocalized; + final Image image; + final List supportedSeedTypes; +} + +final List seedLanguages = [ + SeedLanguagePickerOption('English', S.current.seed_language_english, + Image.asset('assets/images/flags/usa.png'), [SeedType.legacy, SeedType.polyseed]), + SeedLanguagePickerOption('Chinese (simplified)', S.current.seed_language_chinese, + Image.asset('assets/images/flags/chn.png'), [SeedType.legacy, SeedType.polyseed]), + SeedLanguagePickerOption('Chinese (Traditional)', S.current.seed_language_chinese_traditional, + Image.asset('assets/images/flags/chn.png'), [SeedType.polyseed]), + SeedLanguagePickerOption('Dutch', S.current.seed_language_dutch, + Image.asset('assets/images/flags/nld.png'), [SeedType.legacy]), + SeedLanguagePickerOption('German', S.current.seed_language_german, + Image.asset('assets/images/flags/deu.png'), [SeedType.legacy]), + SeedLanguagePickerOption('Japanese', S.current.seed_language_japanese, + Image.asset('assets/images/flags/jpn.png'), [SeedType.legacy, SeedType.polyseed]), + SeedLanguagePickerOption('Korean', S.current.seed_language_korean, + Image.asset('assets/images/flags/kor.png'), [SeedType.polyseed]), + SeedLanguagePickerOption('Portuguese', S.current.seed_language_portuguese, + Image.asset('assets/images/flags/prt.png'), [SeedType.legacy, SeedType.polyseed]), + SeedLanguagePickerOption('Russian', S.current.seed_language_russian, + Image.asset('assets/images/flags/rus.png'), [SeedType.legacy]), + SeedLanguagePickerOption('Czech', S.current.seed_language_czech, + Image.asset('assets/images/flags/czk.png'), [SeedType.polyseed]), + SeedLanguagePickerOption('Spanish', S.current.seed_language_spanish, + Image.asset('assets/images/flags/esp.png'), [SeedType.legacy, SeedType.polyseed]), + SeedLanguagePickerOption('French', S.current.seed_language_french, + Image.asset('assets/images/flags/fra.png'), [SeedType.legacy, SeedType.polyseed]), + SeedLanguagePickerOption('Italian', S.current.seed_language_italian, + Image.asset('assets/images/flags/ita.png'), [SeedType.legacy, SeedType.polyseed]), +]; + +const defaultSeedLanguage = 'English'; + +enum Places { topLeft, topRight, bottomLeft, bottomRight, inside } + +class SeedLanguagePicker extends StatefulWidget { + SeedLanguagePicker( + {Key? key, + this.selected = defaultSeedLanguage, + this.seedType = SeedType.defaultSeedType, + required this.onItemSelected}) + : super(key: key); + + final SeedType seedType; + final String selected; + final Function(String) onItemSelected; + + @override + SeedLanguagePickerState createState() => SeedLanguagePickerState( + selected: selected, onItemSelected: onItemSelected, seedType: seedType); +} + +class SeedLanguagePickerState extends State { + SeedLanguagePickerState( + {required this.selected, required this.onItemSelected, required this.seedType}); + + final SeedType seedType; + final String selected; + final Function(String) onItemSelected; + + @override + Widget build(BuildContext context) { + final availableSeedLanguages = seedLanguages + .where((SeedLanguagePickerOption e) => e.supportedSeedTypes.contains(seedType)); + + return Picker( + selectedAtIndex: availableSeedLanguages.map((e) => e.name).toList().indexOf(selected), + items: availableSeedLanguages.map((e) => e.name).toList(), + images: availableSeedLanguages.map((e) => e.image).toList(), + isGridView: true, + title: S.of(context).seed_choose, + hintText: S.of(context).seed_choose, + matchingCriteria: (String language, String searchText) { + return language.toLowerCase().contains(searchText); + }, + onItemSelected: onItemSelected, + ); + } +} diff --git a/lib/src/widgets/seed_language_selector.dart b/lib/src/widgets/seed_language_selector.dart index 4db3684a8..07638bb2f 100644 --- a/lib/src/widgets/seed_language_selector.dart +++ b/lib/src/widgets/seed_language_selector.dart @@ -1,14 +1,15 @@ +import 'package:cake_wallet/entities/seed_type.dart'; +import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart'; +import 'package:cake_wallet/src/widgets/seed_language_picker.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart'; -import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart'; class SeedLanguageSelector extends StatefulWidget { - SeedLanguageSelector({Key? key, required this.initialSelected}) + SeedLanguageSelector({Key? key, required this.initialSelected, this.seedType = SeedType.defaultSeedType}) : super(key: key); final String initialSelected; + final SeedType seedType; @override SeedLanguageSelectorState createState() => @@ -18,30 +19,19 @@ class SeedLanguageSelector extends StatefulWidget { class SeedLanguageSelectorState extends State { SeedLanguageSelectorState({required this.selected}); - final seedLocales = [ - S.current.seed_language_english, - S.current.seed_language_chinese, - S.current.seed_language_dutch, - S.current.seed_language_german, - S.current.seed_language_japanese, - S.current.seed_language_portuguese, - S.current.seed_language_russian, - S.current.seed_language_spanish, - S.current.seed_language_french, - S.current.seed_language_italian, - ]; String selected; @override Widget build(BuildContext context) { return SelectButton( image: null, - text: seedLocales[seedLanguages.indexOf(selected)], + text: seedLanguages.firstWhere((e) => e.name == selected).nameLocalized, onTap: () async { await showPopUp( context: context, builder: (_) => SeedLanguagePicker( selected: this.selected, + seedType: widget.seedType, onItemSelected: (String selected) => setState(() => this.selected = selected))); }, diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 1522ea354..4aaa44e13 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -10,6 +10,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/seed_phrase_length.dart'; +import 'package:cake_wallet/entities/seed_type.dart'; import 'package:cake_wallet/entities/sort_balance_types.dart'; import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; import 'package:cake_wallet/view_model/settings/sync_mode.dart'; @@ -48,6 +49,7 @@ abstract class SettingsStoreBase with Store { required BalanceDisplayMode initialBalanceDisplayMode, required bool initialSaveRecipientAddress, required AutoGenerateSubaddressStatus initialAutoGenerateSubaddressStatus, + required SeedType initialMoneroSeedType, required bool initialAppSecure, required bool initialDisableBuy, required bool initialDisableSell, @@ -108,6 +110,7 @@ abstract class SettingsStoreBase with Store { balanceDisplayMode = initialBalanceDisplayMode, shouldSaveRecipientAddress = initialSaveRecipientAddress, autoGenerateSubaddressStatus = initialAutoGenerateSubaddressStatus, + moneroSeedType = initialMoneroSeedType, fiatApiMode = initialFiatMode, allowBiometricalAuthentication = initialAllowBiometricalAuthentication, selectedCake2FAPreset = initialCake2FAPresetOptions, @@ -240,6 +243,11 @@ abstract class SettingsStoreBase with Store { (AutoGenerateSubaddressStatus autoGenerateSubaddressStatus) => sharedPreferences.setInt( PreferencesKey.autoGenerateSubaddressStatusKey, autoGenerateSubaddressStatus.value)); + reaction( + (_) => moneroSeedType, + (SeedType moneroSeedType) => sharedPreferences.setInt( + PreferencesKey.moneroSeedType, moneroSeedType.raw)); + reaction( (_) => fiatApiMode, (FiatApiMode mode) => @@ -435,6 +443,7 @@ abstract class SettingsStoreBase with Store { static const defaultPinCodeTimeOutDuration = PinCodeRequiredDuration.tenminutes; static const defaultAutoGenerateSubaddressStatus = AutoGenerateSubaddressStatus.initialized; static const defaultSeedPhraseLength = SeedPhraseLength.twelveWords; + static const defaultMoneroSeedType = SeedType.defaultSeedType; @observable FiatCurrency fiatCurrency; @@ -460,6 +469,9 @@ abstract class SettingsStoreBase with Store { @observable AutoGenerateSubaddressStatus autoGenerateSubaddressStatus; + @observable + SeedType moneroSeedType; + @observable bool isAppSecure; @@ -775,12 +787,20 @@ abstract class SettingsStoreBase with Store { final packageInfo = await PackageInfo.fromPlatform(); final deviceName = await _getDeviceName() ?? ''; final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true; + final generateSubaddresses = sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); final autoGenerateSubaddressStatus = generateSubaddresses != null ? AutoGenerateSubaddressStatus.deserialize(raw: generateSubaddresses) : defaultAutoGenerateSubaddressStatus; + + final _moneroSeedType = sharedPreferences.getInt(PreferencesKey.moneroSeedType); + + final moneroSeedType = _moneroSeedType != null + ? SeedType.deserialize(raw: _moneroSeedType) + : defaultMoneroSeedType; + final nodes = {}; final powNodes = {}; @@ -833,27 +853,27 @@ abstract class SettingsStoreBase with Store { initialBalanceDisplayMode: currentBalanceDisplayMode, initialSaveRecipientAddress: shouldSaveRecipientAddress, initialAutoGenerateSubaddressStatus: autoGenerateSubaddressStatus, - initialAppSecure: isAppSecure, - initialDisableBuy: disableBuy, - initialDisableSell: disableSell, - initialDefaultBuyProvider: defaultBuyProvider, - initialFiatMode: currentFiatApiMode, - initialAllowBiometricalAuthentication: allowBiometricalAuthentication, - initialCake2FAPresetOptions: selectedCake2FAPreset, - initialUseTOTP2FA: useTOTP2FA, - initialTotpSecretKey: totpSecretKey, - initialFailedTokenTrial: tokenTrialNumber, - initialExchangeStatus: exchangeStatus, - initialTheme: savedTheme, - actionlistDisplayMode: actionListDisplayMode, - initialPinLength: pinLength, - pinTimeOutDuration: pinCodeTimeOutDuration, - seedPhraseLength: seedPhraseWordCount, - initialLanguageCode: savedLanguageCode, - sortBalanceBy: sortBalanceBy, - pinNativeTokenAtTop: pinNativeTokenAtTop, - useEtherscan: useEtherscan, - defaultNanoRep: defaultNanoRep, + initialMoneroSeedType: moneroSeedType, + initialAppSecure: isAppSecure, + initialDisableBuy: disableBuy, + initialDisableSell: disableSell, + initialDefaultBuyProvider: defaultBuyProvider, + initialFiatMode: currentFiatApiMode, + initialAllowBiometricalAuthentication: allowBiometricalAuthentication, + initialCake2FAPresetOptions: selectedCake2FAPreset, + initialUseTOTP2FA: useTOTP2FA, + initialTotpSecretKey: totpSecretKey, + initialFailedTokenTrial: tokenTrialNumber, + initialExchangeStatus: exchangeStatus, + initialTheme: savedTheme, + actionlistDisplayMode: actionListDisplayMode, + initialPinLength: pinLength, + pinTimeOutDuration: pinCodeTimeOutDuration, + seedPhraseLength: seedPhraseWordCount,initialLanguageCode: savedLanguageCode, + sortBalanceBy: sortBalanceBy, + pinNativeTokenAtTop: pinNativeTokenAtTop, + useEtherscan: useEtherscan, + defaultNanoRep: defaultNanoRep, defaultBananoRep: defaultBananoRep, lookupsTwitter: lookupsTwitter, lookupsMastodon: lookupsMastodon, @@ -862,10 +882,10 @@ abstract class SettingsStoreBase with Store { lookupsOpenAlias: lookupsOpenAlias, lookupsENS: lookupsENS, initialMoneroTransactionPriority: moneroTransactionPriority, - initialBitcoinTransactionPriority: bitcoinTransactionPriority, - initialHavenTransactionPriority: havenTransactionPriority, - initialLitecoinTransactionPriority: litecoinTransactionPriority, - initialBitcoinCashTransactionPriority: bitcoinCashTransactionPriority, + initialBitcoinTransactionPriority: bitcoinTransactionPriority, + initialHavenTransactionPriority: havenTransactionPriority, + initialLitecoinTransactionPriority: litecoinTransactionPriority, + initialBitcoinCashTransactionPriority: bitcoinCashTransactionPriority, initialShouldRequireTOTP2FAForAccessingWallet: shouldRequireTOTP2FAForAccessingWallet, initialShouldRequireTOTP2FAForSendsToContact: shouldRequireTOTP2FAForSendsToContact, initialShouldRequireTOTP2FAForSendsToNonContact: shouldRequireTOTP2FAForSendsToNonContact, @@ -927,6 +947,12 @@ abstract class SettingsStoreBase with Store { ? AutoGenerateSubaddressStatus.deserialize(raw: generateSubaddresses) : defaultAutoGenerateSubaddressStatus; + final _moneroSeedType = sharedPreferences.getInt(PreferencesKey.moneroSeedType); + + moneroSeedType = _moneroSeedType != null + ? SeedType.deserialize(raw: _moneroSeedType) + : defaultMoneroSeedType; + balanceDisplayMode = BalanceDisplayMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey)!); shouldSaveRecipientAddress = diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart index b67a4378a..f62815346 100644 --- a/lib/view_model/advanced_privacy_settings_view_model.dart +++ b/lib/view_model/advanced_privacy_settings_view_model.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/seed_phrase_length.dart'; +import 'package:cake_wallet/entities/seed_type.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; @@ -19,6 +20,9 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { @computed FiatApiMode get fiatApiMode => _settingsStore.fiatApiMode; + @computed + SeedType get seedType => _settingsStore.moneroSeedType; + @observable bool _addCustomNode = false; @@ -29,6 +33,8 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { bool get hasSeedPhraseLengthOption => type == WalletType.bitcoinCash || type == WalletType.ethereum; + bool get hasSeedTypeOption => type == WalletType.monero; + @computed bool get addCustomNode => _addCustomNode; @@ -38,6 +44,9 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { @action void setFiatApiMode(FiatApiMode fiatApiMode) => _settingsStore.fiatApiMode = fiatApiMode; + @action + void setSeedType(SeedType seedType) => _settingsStore.moneroSeedType = seedType; + @action void setExchangeApiMode(ExchangeApiMode value) => _settingsStore.exchangeStatus = value; diff --git a/lib/view_model/restore/wallet_restore_from_qr_code.dart b/lib/view_model/restore/wallet_restore_from_qr_code.dart index 145db74d7..6085f4354 100644 --- a/lib/view_model/restore/wallet_restore_from_qr_code.dart +++ b/lib/view_model/restore/wallet_restore_from_qr_code.dart @@ -10,6 +10,7 @@ import 'package:cw_core/wallet_type.dart'; import 'package:flutter/cupertino.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:collection/collection.dart'; +import 'package:polyseed/polyseed.dart'; class WalletRestoreFromQRCode { WalletRestoreFromQRCode(); @@ -51,7 +52,7 @@ class WalletRestoreFromQRCode { RegExp _getPattern(int wordCount) => RegExp(r'(?<=\W|^)((?:\w+\s+){' + (wordCount - 1).toString() + r'}\w+)(?=\W|$)'); - List patternCounts = walletType == WalletType.monero ? [25, 14, 13] : [24, 18, 12]; + List patternCounts = walletType == WalletType.monero ? [25, 16, 14, 13] : [24, 18, 12]; for (final count in patternCounts) { final pattern = _getPattern(count); @@ -123,12 +124,17 @@ class WalletRestoreFromQRCode { } if (credentials['seed'] != null) { - final seedValue = credentials['seed']; + final seedValue = credentials['seed'] as String; final words = SeedValidator.getWordList(type: type, language: 'english'); + + if (type == WalletType.monero && Polyseed.isValidSeed(seedValue)) { + return WalletRestoreMode.seed; + } + seedValue.split(' ').forEach((element) { if (!words.contains(element)) { throw Exception( - 'Unexpected restore mode: mnemonic_seed is invalid or does\'t match wallet type'); + "Unexpected restore mode: mnemonic_seed is invalid or doesn't match wallet type"); } }); return WalletRestoreMode.seed; diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart index 9b1f0834d..696559198 100644 --- a/lib/view_model/wallet_new_vm.dart +++ b/lib/view_model/wallet_new_vm.dart @@ -1,6 +1,4 @@ -import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; -import 'package:flutter/foundation.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; @@ -33,18 +31,19 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { bool get hasLanguageSelector => type == WalletType.monero || type == WalletType.haven; @override - WalletCredentials getCredentials(dynamic options) { + WalletCredentials getCredentials(dynamic _options) { + final options = _options as List; switch (type) { case WalletType.monero: return monero!.createMoneroNewWalletCredentials( - name: name, language: options as String); + name: name, language: options.first as String, isPolyseed: options.last as bool); case WalletType.bitcoin: return bitcoin!.createBitcoinNewWalletCredentials(name: name); case WalletType.litecoin: return bitcoin!.createBitcoinNewWalletCredentials(name: name); case WalletType.haven: return haven!.createHavenNewWalletCredentials( - name: name, language: options as String); + name: name, language: options.first as String); case WalletType.ethereum: return ethereum!.createEthereumNewWalletCredentials(name: name); case WalletType.bitcoinCash: diff --git a/pubspec_base.yaml b/pubspec_base.yaml index edfc64890..f71d38578 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -104,6 +104,9 @@ dependencies: ref: main socks5_proxy: ^1.0.4 flutter_svg: ^2.0.9 + polyseed: + git: + url: https://github.com/cake-tech/polyseed_dart.git dev_dependencies: flutter_test: diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 8065a5bd1..47b11c78e 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -739,5 +739,11 @@ "unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ", "unspent_change": "يتغير", "seed_hex_form": "بذور المحفظة (شكل عرافة)", - "tor_connection": "ﺭﻮﺗ ﻝﺎﺼﺗﺍ" + "tor_connection": "ﺭﻮﺗ ﻝﺎﺼﺗﺍ", + "seedtype": "البذور", + "seedtype_legacy": "إرث (25 كلمة)", + "seedtype_polyseed": "بوليسيد (16 كلمة)", + "seed_language_czech": "التشيكية", + "seed_language_korean": "الكورية", + "seed_language_chinese_traditional": "تقاليد صينية)" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index ab45efba3..162e85cad 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -735,5 +735,11 @@ "unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.", "unspent_change": "Промяна", "tor_connection": "Tor връзка", - "seed_hex_form": "Семена от портфейл (шестнадесетична форма)" + "seed_hex_form": "Семена от портфейл (шестнадесетична форма)", + "seedtype": "Семенна тип", + "seedtype_legacy": "Наследство (25 думи)", + "seedtype_polyseed": "Поли семе (16 думи)", + "seed_language_czech": "Чех", + "seed_language_korean": "Корейски", + "seed_language_chinese_traditional": "Традиционен китайски)" } \ No newline at end of file diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 88792ec15..8efdb59b5 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -735,5 +735,11 @@ "unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.", "unspent_change": "Změna", "tor_connection": "Připojení Tor", - "seed_hex_form": "Semeno peněženky (hex formulář)" + "seed_hex_form": "Semeno peněženky (hex formulář)", + "seedtype": "SeedType", + "seedtype_legacy": "Legacy (25 slov)", + "seedtype_polyseed": "Polyseed (16 slov)", + "seed_language_czech": "čeština", + "seed_language_korean": "korejština", + "seed_language_chinese_traditional": "Číňan (tradiční)" } \ No newline at end of file diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 7b204f20c..754a0f22e 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -722,9 +722,9 @@ "awaitDAppProcessing": "Bitte warten Sie, bis die dApp die Verarbeitung abgeschlossen hat.", "copyWalletConnectLink": "Kopieren Sie den WalletConnect-Link von dApp und fügen Sie ihn hier ein", "enterWalletConnectURI": "Geben Sie den WalletConnect-URI ein", - "seed_key": "Samenschlüssel", - "enter_seed_phrase": "Geben Sie Ihre Samenphrase ein", - "change_rep_successful": "Erfolgreich veränderte Vertreter", + "seed_key": "Seed-Schlüssel", + "enter_seed_phrase": "Geben Sie Ihre Seed-Phrase ein", + "change_rep_successful": "Vertreter erfolgreich gerändert", "add_contact": "Kontakt hinzufügen", "exchange_provider_unsupported": "${providerName} wird nicht mehr unterstützt!", "domain_looks_up": "Domain-Suchen", @@ -743,5 +743,11 @@ "unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.", "unspent_change": "Wechselgeld", "tor_connection": "Tor-Verbindung", - "seed_hex_form": "Brieftaschensamen (Sechskantform)" + "seed_hex_form": "Brieftaschensamen (Sechskantform)", + "seedtype": "Seedtyp", + "seedtype_legacy": "Veraltet (25 Wörter)", + "seedtype_polyseed": "Polyseed (16 Wörter)", + "seed_language_czech": "Tschechisch", + "seed_language_korean": "Koreanisch", + "seed_language_chinese_traditional": "Chinesisch (Traditionell)" } \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index bbcbdb6c0..d65aebe15 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -744,5 +744,11 @@ "unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.", "unspent_change": "Change", "tor_connection": "Tor connection", - "seed_hex_form": "Wallet seed (hex form)" + "seed_hex_form": "Wallet seed (hex form)", + "seedtype": "Seedtype", + "seedtype_legacy": "Legacy (25 words)", + "seedtype_polyseed": "Polyseed (16 words)", + "seed_language_czech": "Czech", + "seed_language_korean": "Korean", + "seed_language_chinese_traditional": "Chinese (Traditional)" } \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index e47f3e744..f785a15d5 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -743,5 +743,11 @@ "unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.", "unspent_change": "Cambiar", "tor_connection": "conexión tor", - "seed_hex_form": "Semilla de billetera (forma hexadecimal)" + "seed_hex_form": "Semilla de billetera (forma hexadecimal)", + "seedtype": "Type de semillas", + "seedtype_legacy": "Legado (25 palabras)", + "seedtype_polyseed": "Polieta (16 palabras)", + "seed_language_czech": "checo", + "seed_language_korean": "coreano", + "seed_language_chinese_traditional": "Chino tradicional)" } \ No newline at end of file diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index f87ed9809..88263ec05 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -745,5 +745,12 @@ "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", "unspent_change": "Changement", "tor_connection": "Connexion Tor", - "seed_hex_form": "Graine du portefeuille (forme hexagonale)" + "seed_hex_form": "Graine du portefeuille (forme hexagonale)", + "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", + "seedtype": "Type de type graine", + "seedtype_legacy": "Héritage (25 mots)", + "seedtype_polyseed": "Polyseed (16 mots)", + "seed_language_czech": "tchèque", + "seed_language_korean": "coréen", + "seed_language_chinese_traditional": "Chinois (Traditionnel)" } \ No newline at end of file diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 2dce6f80d..39b98b51a 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -721,5 +721,11 @@ "unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.", "unspent_change": "Canza", "tor_connection": "Tor haɗin gwiwa", - "seed_hex_form": "Gany Sero (form form)" + "seed_hex_form": "Gany Sero (form form)", + "seedtype": "Seedtype", + "seedtype_legacy": "Legacy (25 kalmomi)", + "seedtype_polyseed": "Polyseed (16 kalmomi)", + "seed_language_czech": "Czech", + "seed_language_korean": "Yaren Koriya", + "seed_language_chinese_traditional": "Sinanci (na gargajiya)" } \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 66a4c8e47..b050ef43b 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -743,5 +743,11 @@ "unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।", "unspent_change": "परिवर्तन", "tor_connection": "टोर कनेक्शन", - "seed_hex_form": "वॉलेट सीड (हेक्स फॉर्म)" + "seed_hex_form": "वॉलेट सीड (हेक्स फॉर्म)", + "seedtype": "बीज", + "seedtype_legacy": "विरासत (25 शब्द)", + "seedtype_polyseed": "पॉलीसीड (16 शब्द)", + "seed_language_czech": "चेक", + "seed_language_korean": "कोरियाई", + "seed_language_chinese_traditional": "चीनी पारंपरिक)" } \ No newline at end of file diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 4e84d3ed4..3c0f895e7 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -741,5 +741,11 @@ "unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.", "unspent_change": "Promijeniti", "tor_connection": "Tor veza", - "seed_hex_form": "Sjeme novčanika (šesterokutni oblik)" + "seed_hex_form": "Sjeme novčanika (šesterokutni oblik)", + "seedtype": "Sjemenska vrsta", + "seedtype_legacy": "Nasljeđe (25 riječi)", + "seedtype_polyseed": "Poliseed (16 riječi)", + "seed_language_czech": "češki", + "seed_language_korean": "korejski", + "seed_language_chinese_traditional": "Kinesko tradicionalno)" } \ No newline at end of file diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 82e9bca56..b29572746 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -731,5 +731,11 @@ "unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.", "unspent_change": "Mengubah", "tor_connection": "koneksi Tor", - "seed_hex_form": "Biji dompet (bentuk hex)" + "seed_hex_form": "Biji dompet (bentuk hex)", + "seedtype": "Seedtype", + "seedtype_legacy": "Legacy (25 kata)", + "seedtype_polyseed": "Polyseed (16 kata)", + "seed_language_czech": "Ceko", + "seed_language_korean": "Korea", + "seed_language_chinese_traditional": "Cina tradisional)" } \ No newline at end of file diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 0005fb5e7..19912d277 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -743,5 +743,11 @@ "unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.", "unspent_change": "Modifica", "tor_connection": "Connessione Tor", - "seed_hex_form": "Seme di portafoglio (forma esadecimale)" + "seed_hex_form": "Seme di portafoglio (forma esadecimale)", + "seedtype": "Seedtype", + "seedtype_legacy": "Legacy (25 parole)", + "seedtype_polyseed": "Polyseed (16 parole)", + "seed_language_czech": "ceco", + "seed_language_korean": "coreano", + "seed_language_chinese_traditional": "Cinese tradizionale)" } \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index d57eaef5d..ea138b317 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -743,5 +743,11 @@ "unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。", "unspent_change": "変化", "tor_connection": "Tor接続", - "seed_hex_form": "ウォレットシード(ヘックスフォーム)" + "seed_hex_form": "ウォレットシード(ヘックスフォーム)", + "seedtype": "SeedType", + "seedtype_legacy": "レガシー(25語)", + "seedtype_polyseed": "ポリシード(16語)", + "seed_language_czech": "チェコ", + "seed_language_korean": "韓国語", + "seed_language_chinese_traditional": "中国の伝統的な)" } \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 775918659..4df43018d 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -741,5 +741,11 @@ "unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.", "unspent_change": "변화", "tor_connection": "토르 연결", - "seed_hex_form": "지갑 씨앗 (16 진 양식)" + "seed_hex_form": "지갑 씨앗 (16 진 양식)", + "seedtype": "시드 타입", + "seedtype_legacy": "레거시 (25 단어)", + "seedtype_polyseed": "다문 (16 단어)", + "seed_language_czech": "체코 사람", + "seed_language_korean": "한국인", + "seed_language_chinese_traditional": "중국 전통)" } \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 4aacb0bd3..d82e30116 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -741,5 +741,11 @@ "unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။", "unspent_change": "ပေြာင်းလဲခြင်း", "tor_connection": "Tor ချိတ်ဆက်မှု", - "seed_hex_form": "ပိုက်ဆံအိတ်မျိုးစေ့ (Hex Form)" + "seed_hex_form": "ပိုက်ဆံအိတ်မျိုးစေ့ (Hex Form)", + "seedtype": "မျိုးပွားခြင်း", + "seedtype_legacy": "အမွေအနှစ် (စကားလုံး 25 လုံး)", + "seedtype_polyseed": "polyseed (စကားလုံး 16 လုံး)", + "seed_language_czech": "ချက်", + "seed_language_korean": "ကိုးရီးယား", + "seed_language_chinese_traditional": "တရုတ်ရိုးရာ)" } \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index cf779afab..8a290618d 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -743,5 +743,11 @@ "unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.", "unspent_change": "Wijziging", "tor_connection": "Tor-verbinding", - "seed_hex_form": "Portemonnee zaad (hexvorm)" + "seed_hex_form": "Portemonnee zaad (hexvorm)", + "seedtype": "Zaadtype", + "seedtype_legacy": "Legacy (25 woorden)", + "seedtype_polyseed": "Polyseed (16 woorden)", + "seed_language_czech": "Tsjechisch", + "seed_language_korean": "Koreaans", + "seed_language_chinese_traditional": "Chinese traditionele)" } \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 04c420db4..b84ddc98c 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -743,5 +743,11 @@ "unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.", "unspent_change": "Zmiana", "tor_connection": "Połączenie Torem", - "seed_hex_form": "Nasiona portfela (forma sześciokątna)" + "seed_hex_form": "Nasiona portfela (forma sześciokątna)", + "seedtype": "Sedtype", + "seedtype_legacy": "Dziedzictwo (25 słów)", + "seedtype_polyseed": "Poliqueed (16 słów)", + "seed_language_czech": "Czech", + "seed_language_korean": "koreański", + "seed_language_chinese_traditional": "Chiński tradycyjny)" } \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index a461141f3..ed7b8a801 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -742,5 +742,11 @@ "unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.", "unspent_change": "Mudar", "tor_connection": "Conexão Tor", - "seed_hex_form": "Semente de carteira (forma hexadecimal)" + "seed_hex_form": "Semente de carteira (forma hexadecimal)", + "seedtype": "SeedType", + "seedtype_legacy": "Legado (25 palavras)", + "seedtype_polyseed": "Polyseed (16 palavras)", + "seed_language_czech": "Tcheco", + "seed_language_korean": "coreano", + "seed_language_chinese_traditional": "Chinês tradicional)" } \ No newline at end of file diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 8d0cc647a..c7749d0ea 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -743,5 +743,11 @@ "unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.", "unspent_change": "Изменять", "tor_connection": "Тор соединение", - "seed_hex_form": "Семя кошелька (шестнадцатеричная форма)" + "seed_hex_form": "Семя кошелька (шестнадцатеричная форма)", + "seedtype": "SEEDTYPE", + "seedtype_legacy": "Наследие (25 слов)", + "seedtype_polyseed": "Полиса (16 слов)", + "seed_language_czech": "Чешский", + "seed_language_korean": "Корейский", + "seed_language_chinese_traditional": "Китайский традиционный)" } \ No newline at end of file diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 151c65cd3..791b0f005 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -741,5 +741,11 @@ "unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง", "unspent_change": "เปลี่ยน", "tor_connection": "การเชื่อมต่อทอร์", - "seed_hex_form": "เมล็ดกระเป๋าเงิน (รูปแบบฐานสิบหก)" + "seed_hex_form": "เมล็ดกระเป๋าเงิน (รูปแบบฐานสิบหก)", + "seedtype": "เมล็ดพันธุ์", + "seedtype_legacy": "มรดก (25 คำ)", + "seedtype_polyseed": "โพลีส (16 คำ)", + "seed_language_czech": "ภาษาเช็ก", + "seed_language_korean": "เกาหลี", + "seed_language_chinese_traditional": "จีน (ดั้งเดิม)" } \ No newline at end of file diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 258eb6f12..8891563b0 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -738,5 +738,10 @@ "unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.", "unspent_change": "Baguhin", "tor_connection": "Koneksyon ng Tor", - "seed_hex_form": "Wallet seed (hex form)" + "seed_hex_form": "Wallet seed (hex form)", + "seedtype_legacy": "Pamana (25 salita)", + "seedtype_polyseed": "Polyseed (16 na salita)", + "seed_language_czech": "Czech", + "seed_language_korean": "Korean", + "seed_language_chinese_traditional": "Intsik (tradisyonal)" } \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 33362b83c..a5d6a330a 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -741,5 +741,11 @@ "unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.", "unspent_change": "Değiştirmek", "tor_connection": "Tor bağlantısı", - "seed_hex_form": "Cüzdan tohumu (onaltılık form)" + "seed_hex_form": "Cüzdan tohumu (onaltılık form)", + "seedtype": "Tohum", + "seedtype_legacy": "Miras (25 kelime)", + "seedtype_polyseed": "Polyseed (16 kelime)", + "seed_language_czech": "Çek", + "seed_language_korean": "Koreli", + "seed_language_chinese_traditional": "Çin geleneği)" } \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 7b79ac6e4..81bc3c8aa 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -743,5 +743,11 @@ "unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.", "unspent_change": "Зміна", "tor_connection": "Підключення Tor", - "seed_hex_form": "Насіння гаманця (шістнадцяткова форма)" + "seed_hex_form": "Насіння гаманця (шістнадцяткова форма)", + "seedtype": "Насіннєвий тип", + "seedtype_legacy": "Спадщина (25 слів)", + "seedtype_polyseed": "Полісей (16 слів)", + "seed_language_czech": "Чеський", + "seed_language_korean": "Корейський", + "seed_language_chinese_traditional": "Китайський традиційний)" } \ No newline at end of file diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index c8362ab33..5b7f18ae7 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -735,5 +735,11 @@ "unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ", "unspent_change": "تبدیل کریں", "seed_hex_form": "پرس بیج (ہیکس فارم)", - "tor_connection": "ﻦﺸﮑﻨﮐ ﺭﻮﭨ" + "tor_connection": "ﻦﺸﮑﻨﮐ ﺭﻮﭨ", + "seedtype": "سیڈ ٹائپ", + "seedtype_legacy": "میراث (25 الفاظ)", + "seedtype_polyseed": "پالیسیڈ (16 الفاظ)", + "seed_language_czech": "چیک", + "seed_language_korean": "کورین", + "seed_language_chinese_traditional": "چینی (روایتی)" } \ No newline at end of file diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 7b9b075d7..6821aa7f9 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -737,5 +737,11 @@ "unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.", "unspent_change": "Yipada", "tor_connection": "Tor asopọ", - "seed_hex_form": "Irú Opamọwọ apamọwọ (HOX)" + "seed_hex_form": "Irú Opamọwọ apamọwọ (HOX)", + "seedtype": "Irugbin-seetypu", + "seedtype_legacy": "Legacy (awọn ọrọ 25)", + "seedtype_polyseed": "Polyseed (awọn ọrọ 16)", + "seed_language_czech": "Czech", + "seed_language_korean": "Ara ẹni", + "seed_language_chinese_traditional": "Kannada (ibile)" } \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index e95bc077b..b66d0e65e 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -742,5 +742,11 @@ "unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。", "unspent_change": "改变", "tor_connection": "Tor连接", - "seed_hex_form": "钱包种子(十六进制形式)" + "seed_hex_form": "钱包种子(十六进制形式)", + "seedtype": "籽粒", + "seedtype_legacy": "遗产(25个单词)", + "seedtype_polyseed": "多种物品(16个单词)", + "seed_language_czech": "捷克", + "seed_language_korean": "韩国人", + "seed_language_chinese_traditional": "中国传统的)" } \ No newline at end of file diff --git a/tool/configure.dart b/tool/configure.dart index bc32581a6..7d50ddf53 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -134,7 +134,6 @@ import 'package:cw_core/unspent_transaction_output.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_monero/monero_unspent.dart'; import 'package:mobx/mobx.dart'; -import 'package:flutter/foundation.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/transaction_priority.dart'; @@ -144,7 +143,8 @@ import 'package:cw_core/balance.dart'; 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:hive/hive.dart'; +import 'package:polyseed/polyseed.dart';"""; const moneroCWHeaders = """ import 'package:cw_core/get_height_by_date.dart'; import 'package:cw_core/monero_amount_format.dart'; @@ -152,7 +152,6 @@ import 'package:cw_core/monero_transaction_priority.dart'; import 'package:cw_monero/monero_wallet_service.dart'; import 'package:cw_monero/monero_wallet.dart'; import 'package:cw_monero/monero_transaction_info.dart'; -import 'package:cw_monero/monero_transaction_history.dart'; import 'package:cw_monero/monero_transaction_creation_credentials.dart'; import 'package:cw_core/account.dart' as monero_account; import 'package:cw_monero/api/wallet.dart' as monero_wallet_api; @@ -255,7 +254,7 @@ abstract class Monero { required String language, required int height}); WalletCredentials createMoneroRestoreWalletFromSeedCredentials({required String name, required String password, required int height, required String mnemonic}); - WalletCredentials createMoneroNewWalletCredentials({required String name, required String language, String password,}); + WalletCredentials createMoneroNewWalletCredentials({required String name, required String language, required bool isPolyseed, String password}); Map getKeys(Object wallet); Object createMoneroTransactionCreationCredentials({required List outputs, required TransactionPriority priority}); Object createMoneroTransactionCreationCredentialsRaw({required List outputs, required TransactionPriority priority}); From 615d016dd5b00afb6fd2792640cf3c83947a6c41 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Mon, 27 Nov 2023 08:28:34 -0500 Subject: [PATCH 052/241] be absolutely sure we delete secure storage keys before writing them (#1182) * be absolutely sure we delete secure storage keys before writing them * sync with other PR --------- Co-authored-by: fossephate Co-authored-by: Omar Hatem --- lib/core/backup_service.dart | 4 ++++ lib/core/key_service.dart | 1 + lib/entities/default_settings_migration.dart | 1 + lib/entities/fs_migration.dart | 1 + lib/entities/get_encryption_key.dart | 4 +++- lib/src/screens/support_chat/widgets/chatwoot_widget.dart | 6 ++++-- lib/view_model/edit_backup_password_view_model.dart | 1 + 7 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index b13a01889..7dd0b50f3 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -436,6 +436,7 @@ class BackupService { final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPassword = keychainJSON[backupPasswordKey] as String; + await _flutterSecureStorage.delete(key: backupPasswordKey); await _flutterSecureStorage.write(key: backupPasswordKey, value: backupPassword); keychainWalletsInfo.forEach((dynamic rawInfo) async { @@ -443,6 +444,7 @@ class BackupService { await importWalletKeychainInfo(info); }); + await _flutterSecureStorage.delete(key: pinCodeKey); await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin)); keychainDumpFile.deleteSync(); @@ -462,6 +464,7 @@ class BackupService { final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPassword = keychainJSON[backupPasswordKey] as String; + await _flutterSecureStorage.delete(key: backupPasswordKey); await _flutterSecureStorage.write(key: backupPasswordKey, value: backupPassword); keychainWalletsInfo.forEach((dynamic rawInfo) async { @@ -469,6 +472,7 @@ class BackupService { await importWalletKeychainInfo(info); }); + await _flutterSecureStorage.delete(key: pinCodeKey); await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin)); keychainDumpFile.deleteSync(); diff --git a/lib/core/key_service.dart b/lib/core/key_service.dart index 337f1ef21..fce254ea2 100644 --- a/lib/core/key_service.dart +++ b/lib/core/key_service.dart @@ -19,6 +19,7 @@ class KeyService { key: SecretStoreKey.moneroWalletPassword, walletName: walletName); final encodedPassword = encodeWalletPassword(password: password); + await _secureStorage.delete(key: key); await _secureStorage.write(key: key, value: encodedPassword); } diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 47092c22f..a65742e99 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -496,6 +496,7 @@ Future generateBackupPassword(FlutterSecureStorage secureStorage) async { } final password = encrypt.Key.fromSecureRandom(32).base16; + await secureStorage.delete(key: key); await secureStorage.write(key: key, value: password); } diff --git a/lib/entities/fs_migration.dart b/lib/entities/fs_migration.dart index e3088ff54..4280949cd 100644 --- a/lib/entities/fs_migration.dart +++ b/lib/entities/fs_migration.dart @@ -147,6 +147,7 @@ Future ios_migrate_pin() async { final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final encodedPassword = encodedPinCode(pin: pinPassword); + await flutterSecureStorage.delete(key: key); await flutterSecureStorage.write(key: key, value: encodedPassword); await prefs.setBool('ios_migration_pin_completed', true); } diff --git a/lib/entities/get_encryption_key.dart b/lib/entities/get_encryption_key.dart index e67380bb8..a32d4e311 100644 --- a/lib/entities/get_encryption_key.dart +++ b/lib/entities/get_encryption_key.dart @@ -9,7 +9,9 @@ Future> getEncryptionKey( if (stringifiedKey == null) { key = CakeHive.generateSecureKey(); final keyStringified = key.join(','); - await secureStorage.write(key: 'transactionDescriptionsBoxKey', value: keyStringified); + String storageKey = 'transactionDescriptionsBoxKey'; + await secureStorage.delete(key: storageKey); + await secureStorage.write(key: storageKey, value: keyStringified); } else { key = stringifiedKey.split(',').map((i) => int.parse(i)).toList(); } diff --git a/lib/src/screens/support_chat/widgets/chatwoot_widget.dart b/lib/src/screens/support_chat/widgets/chatwoot_widget.dart index d9a5f9bb8..73403d667 100644 --- a/lib/src/screens/support_chat/widgets/chatwoot_widget.dart +++ b/lib/src/screens/support_chat/widgets/chatwoot_widget.dart @@ -57,6 +57,8 @@ class ChatwootWidgetState extends State { return true; } - Future storeCookie(String value) async => - await widget.secureStorage.write(key: COOKIE_KEY, value: value); + Future storeCookie(String value) async { + await widget.secureStorage.delete(key: COOKIE_KEY); + await widget.secureStorage.write(key: COOKIE_KEY, value: value); + } } diff --git a/lib/view_model/edit_backup_password_view_model.dart b/lib/view_model/edit_backup_password_view_model.dart index e7b8ee017..aca76502a 100644 --- a/lib/view_model/edit_backup_password_view_model.dart +++ b/lib/view_model/edit_backup_password_view_model.dart @@ -37,6 +37,7 @@ abstract class EditBackupPasswordViewModelBase with Store { @action Future save() async { final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword); + await secureStorage.delete(key: key); await secureStorage.write(key: key, value: backupPassword); secretStore.write(key: key, value: backupPassword); } From 177d89b904fd1ec509c4be5449cb1112f1fcb273 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Mon, 27 Nov 2023 13:44:48 -0500 Subject: [PATCH 053/241] fix nano being sent to only the first output address in list (#1198) --- cw_nano/lib/nano_wallet.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cw_nano/lib/nano_wallet.dart b/cw_nano/lib/nano_wallet.dart index 795634849..b0d98efec 100644 --- a/cw_nano/lib/nano_wallet.dart +++ b/cw_nano/lib/nano_wallet.dart @@ -186,9 +186,9 @@ abstract class NanoWalletBase final block = await _client.constructSendBlock( amountRaw: amt.toString(), - destinationAddress: credentials.outputs.first.isParsedAddress - ? credentials.outputs.first.extractedAddress! - : credentials.outputs.first.address, + destinationAddress: txOut.isParsedAddress + ? txOut.extractedAddress! + : txOut.address, privateKey: _privateKey!, balanceAfterTx: runningBalance, previousHash: previousHash, From d07efc81ca257b0dadbcd11ba11d871df10bcd23 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Mon, 27 Nov 2023 22:50:12 +0100 Subject: [PATCH 054/241] Lookup NFTs only if the current wallet is an Ethereum Wallet (#1197) --- lib/view_model/dashboard/nft_view_model.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/view_model/dashboard/nft_view_model.dart b/lib/view_model/dashboard/nft_view_model.dart index ec5919b7d..c5acf5523 100644 --- a/lib/view_model/dashboard/nft_view_model.dart +++ b/lib/view_model/dashboard/nft_view_model.dart @@ -4,6 +4,7 @@ import 'dart:developer'; import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart'; import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_widget.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:http/http.dart' as http; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; @@ -38,6 +39,8 @@ abstract class NFTViewModelBase with Store { @action Future getNFTAssetByWallet() async { + if (appStore.wallet!.type != WalletType.ethereum) return; + final walletAddress = appStore.wallet!.walletInfo.address; log('Fetching wallet NFTs for $walletAddress'); From 89cb216bbf15a178acbfb5f4d72788e768a4be6e Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Wed, 29 Nov 2023 15:18:46 +0100 Subject: [PATCH 055/241] Fix refresh from 0 on creating polyseeds (#1202) * Fix refresh from 0 on creating polyseeds * Try to fix refresh from 0 on creating polyseeds --- cw_monero/lib/monero_wallet_service.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 8e9eb6eac..077ab4e54 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -273,6 +273,9 @@ class MoneroWalletService extends WalletService< date: DateTime.fromMillisecondsSinceEpoch(polyseed.birthday * 1000)); final spendKey = keyToHexString(polyseed.generateKey(coin, 32)); + walletInfo.isRecovery = true; + walletInfo.restoreHeight = height; + await monero_wallet_manager.restoreFromSpendKey( path: path, password: password, From 4d245b7ff159a09484f29f0a3466e5eaea7376f6 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Thu, 30 Nov 2023 16:51:19 +0200 Subject: [PATCH 056/241] v4.11.0 and v1.8.0 (#1192) * v4.11.0 and v1.8.0 * Add missing functionalities to mac os monero api.cpp * Fix creating a new wallet issue * Remove un-necessary linux, macos, and windows files from bitcoincash package --- assets/text/Monerocom_Release_Notes.txt | 9 +--- assets/text/Release_Notes.txt | 10 ++-- .../.plugin_symlinks/path_provider_linux | 1 - .../flutter/ephemeral/.plugin_symlinks/tor | 1 - .../flutter/generated_plugin_registrant.cc | 11 ---- .../flutter/generated_plugin_registrant.h | 15 ------ .../linux/flutter/generated_plugins.cmake | 24 --------- .../Flutter/GeneratedPluginRegistrant.swift | 12 ----- .../ephemeral/Flutter-Generated.xcconfig | 11 ---- .../ephemeral/flutter_export_environment.sh | 12 ----- .../flutter/generated_plugin_registrant.cc | 11 ---- .../flutter/generated_plugin_registrant.h | 15 ------ .../windows/flutter/generated_plugins.cmake | 23 --------- cw_ethereum/pubspec.yaml | 1 - cw_monero/macos/Classes/monero_api.cpp | 50 ++++++++++++++++++- ios/Podfile.lock | 6 --- lib/view_model/wallet_new_vm.dart | 6 +-- scripts/android/app_env.sh | 8 +-- scripts/ios/app_env.sh | 8 +-- scripts/macos/app_env.sh | 4 +- 20 files changed, 67 insertions(+), 171 deletions(-) delete mode 120000 cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux delete mode 120000 cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/tor delete mode 100644 cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.cc delete mode 100644 cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.h delete mode 100644 cw_bitcoin_cash/linux/flutter/generated_plugins.cmake delete mode 100644 cw_bitcoin_cash/macos/Flutter/GeneratedPluginRegistrant.swift delete mode 100644 cw_bitcoin_cash/macos/Flutter/ephemeral/Flutter-Generated.xcconfig delete mode 100644 cw_bitcoin_cash/macos/Flutter/ephemeral/flutter_export_environment.sh delete mode 100644 cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.cc delete mode 100644 cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.h delete mode 100644 cw_bitcoin_cash/windows/flutter/generated_plugins.cmake diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index caac086d1..2830ecdd8 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,7 +1,2 @@ -Coin control fixes and enhancements -In-app Tor connection -Accessibility enhancements -Privacy settings enhancements -UI enhancements -Backup flow fixes -Bug fixes \ No newline at end of file +Monero Polyseed support, under Advanced privacy settings, create and restore from a 16 words phrase and without the need to remember the wallet creation date +Minor bug fixes and enhancements \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index caac086d1..accdbb080 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,7 +1,3 @@ -Coin control fixes and enhancements -In-app Tor connection -Accessibility enhancements -Privacy settings enhancements -UI enhancements -Backup flow fixes -Bug fixes \ No newline at end of file +Monero Polyseed support, under Advanced privacy settings, create and restore from a 16 words phrase and without the need to remember the wallet creation date +Add Ethereum NFTs tab to see all of your purchased NFTs +Minor bug fixes and enhancements \ No newline at end of file diff --git a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux deleted file mode 120000 index 0ed52b295..000000000 --- a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux +++ /dev/null @@ -1 +0,0 @@ -/Users/blazebrain/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ \ No newline at end of file diff --git a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/tor b/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/tor deleted file mode 120000 index 7ee2b206d..000000000 --- a/cw_bitcoin_cash/linux/flutter/ephemeral/.plugin_symlinks/tor +++ /dev/null @@ -1 +0,0 @@ -/Users/blazebrain/.pub-cache/git/tor-09ba92cb11d4e3cacf97256e57863b805f79f2e5/ \ No newline at end of file diff --git a/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.cc b/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.cc deleted file mode 100644 index e71a16d23..000000000 --- a/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,11 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - - -void fl_register_plugins(FlPluginRegistry* registry) { -} diff --git a/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.h b/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.h deleted file mode 100644 index e0f0a47bc..000000000 --- a/cw_bitcoin_cash/linux/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void fl_register_plugins(FlPluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake b/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake deleted file mode 100644 index 3d57782b2..000000000 --- a/cw_bitcoin_cash/linux/flutter/generated_plugins.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST - tor -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/cw_bitcoin_cash/macos/Flutter/GeneratedPluginRegistrant.swift b/cw_bitcoin_cash/macos/Flutter/GeneratedPluginRegistrant.swift deleted file mode 100644 index e777c67df..000000000 --- a/cw_bitcoin_cash/macos/Flutter/GeneratedPluginRegistrant.swift +++ /dev/null @@ -1,12 +0,0 @@ -// -// Generated file. Do not edit. -// - -import FlutterMacOS -import Foundation - -import path_provider_foundation - -func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) -} diff --git a/cw_bitcoin_cash/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/cw_bitcoin_cash/macos/Flutter/ephemeral/Flutter-Generated.xcconfig deleted file mode 100644 index 2f46994d3..000000000 --- a/cw_bitcoin_cash/macos/Flutter/ephemeral/Flutter-Generated.xcconfig +++ /dev/null @@ -1,11 +0,0 @@ -// This is a generated file; do not edit or check into version control. -FLUTTER_ROOT=C:\Users\borod\flutter -FLUTTER_APPLICATION_PATH=C:\cake_wallet\cw_bitcoin_cash -COCOAPODS_PARALLEL_CODE_SIGN=true -FLUTTER_BUILD_DIR=build -FLUTTER_BUILD_NAME=0.0.1 -FLUTTER_BUILD_NUMBER=0.0.1 -DART_OBFUSCATION=false -TRACK_WIDGET_CREATION=true -TREE_SHAKE_ICONS=false -PACKAGE_CONFIG=.dart_tool/package_config.json diff --git a/cw_bitcoin_cash/macos/Flutter/ephemeral/flutter_export_environment.sh b/cw_bitcoin_cash/macos/Flutter/ephemeral/flutter_export_environment.sh deleted file mode 100644 index 2a3bcca5a..000000000 --- a/cw_bitcoin_cash/macos/Flutter/ephemeral/flutter_export_environment.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -# This is a generated file; do not edit or check into version control. -export "FLUTTER_ROOT=C:\Users\borod\flutter" -export "FLUTTER_APPLICATION_PATH=C:\cake_wallet\cw_bitcoin_cash" -export "COCOAPODS_PARALLEL_CODE_SIGN=true" -export "FLUTTER_BUILD_DIR=build" -export "FLUTTER_BUILD_NAME=0.0.1" -export "FLUTTER_BUILD_NUMBER=0.0.1" -export "DART_OBFUSCATION=false" -export "TRACK_WIDGET_CREATION=true" -export "TREE_SHAKE_ICONS=false" -export "PACKAGE_CONFIG=.dart_tool/package_config.json" diff --git a/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.cc b/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.cc deleted file mode 100644 index 8b6d4680a..000000000 --- a/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,11 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - - -void RegisterPlugins(flutter::PluginRegistry* registry) { -} diff --git a/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.h b/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.h deleted file mode 100644 index dc139d85a..000000000 --- a/cw_bitcoin_cash/windows/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void RegisterPlugins(flutter::PluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/cw_bitcoin_cash/windows/flutter/generated_plugins.cmake b/cw_bitcoin_cash/windows/flutter/generated_plugins.cmake deleted file mode 100644 index b93c4c30c..000000000 --- a/cw_bitcoin_cash/windows/flutter/generated_plugins.cmake +++ /dev/null @@ -1,23 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/cw_ethereum/pubspec.yaml b/cw_ethereum/pubspec.yaml index 5d19589f3..6946a43a1 100644 --- a/cw_ethereum/pubspec.yaml +++ b/cw_ethereum/pubspec.yaml @@ -17,7 +17,6 @@ dependencies: mobx: ^2.0.7+4 bip39: ^1.0.6 bip32: ^2.0.0 - ed25519_hd_key: ^2.2.0 hex: ^0.2.0 http: ^1.1.0 shared_preferences: ^2.0.15 diff --git a/cw_monero/macos/Classes/monero_api.cpp b/cw_monero/macos/Classes/monero_api.cpp index ac8a64861..a5ca13822 100644 --- a/cw_monero/macos/Classes/monero_api.cpp +++ b/cw_monero/macos/Classes/monero_api.cpp @@ -234,7 +234,6 @@ extern "C" } void setUnlocked(bool unlocked); - }; Monero::Coins *m_coins; @@ -375,6 +374,35 @@ extern "C" return true; } + bool restore_wallet_from_spend_key(char *path, char *password, char *seed, char *language, char *spendKey, int32_t networkType, uint64_t restoreHeight, char *error) + { + Monero::NetworkType _networkType = static_cast(networkType); + Monero::Wallet *wallet = Monero::WalletManagerFactory::getWalletManager()->createDeterministicWalletFromSpendKey( + std::string(path), + std::string(password), + std::string(language), + _networkType, + (uint64_t)restoreHeight, + std::string(spendKey)); + + int status; + std::string errorString; + + wallet->statusWithErrorString(status, errorString); + + if (status != Monero::Wallet::Status_Ok || !errorString.empty()) + { + error = strdup(errorString.c_str()); + return false; + } + + // Cache Raw to support Polyseed + wallet->setCacheAttribute("cakewallet.seed", std::string(seed)); + + change_current_wallet(wallet); + return true; + } + bool load_wallet(char *path, char *password, int32_t nettype) { nice(19); @@ -439,6 +467,11 @@ extern "C" const char *seed() { + std::string _rawSeed = get_current_wallet()->getCacheAttribute("cakewallet.seed"); + if (!_rawSeed.empty()) + { + return strdup(_rawSeed.c_str()); + } return strdup(get_current_wallet()->seed().c_str()); } @@ -842,6 +875,12 @@ extern "C" return m_transaction_history->count(); } + TransactionInfoRow* get_transaction(char * txId) + { + Monero::TransactionInfo *row = m_transaction_history->transaction(std::string(txId)); + return new TransactionInfoRow(row); + } + int LedgerExchange( unsigned char *command, unsigned int cmd_len, @@ -971,6 +1010,15 @@ extern "C" return result; } + void freeze_coin(int index) + { + m_coins->setFrozen(index); + } + + void thaw_coin(int index) + { + m_coins->thaw(index); + } #ifdef __cplusplus } diff --git a/ios/Podfile.lock b/ios/Podfile.lock index bbb088325..0ecb48591 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -122,8 +122,6 @@ PODS: - Flutter - MTBBarcodeScanner (5.0.11) - OrderedSet (5.0.0) - - package_info (0.0.1): - - Flutter - package_info_plus (0.4.5): - Flutter - path_provider_foundation (0.0.1): @@ -177,7 +175,6 @@ DEPENDENCIES: - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - in_app_review (from `.symlinks/plugins/in_app_review/ios`) - local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`) - - package_info (from `.symlinks/plugins/package_info/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) @@ -239,8 +236,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/in_app_review/ios" local_auth_ios: :path: ".symlinks/plugins/local_auth_ios/ios" - package_info: - :path: ".symlinks/plugins/package_info/ios" package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" path_provider_foundation: @@ -287,7 +282,6 @@ SPEC CHECKSUMS: local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605 MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c - package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart index 696559198..acf829168 100644 --- a/lib/view_model/wallet_new_vm.dart +++ b/lib/view_model/wallet_new_vm.dart @@ -32,18 +32,18 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { @override WalletCredentials getCredentials(dynamic _options) { - final options = _options as List; + final options = _options as List?; switch (type) { case WalletType.monero: return monero!.createMoneroNewWalletCredentials( - name: name, language: options.first as String, isPolyseed: options.last as bool); + name: name, language: options!.first as String, isPolyseed: options.last as bool); case WalletType.bitcoin: return bitcoin!.createBitcoinNewWalletCredentials(name: name); case WalletType.litecoin: return bitcoin!.createBitcoinNewWalletCredentials(name: name); case WalletType.haven: return haven!.createHavenNewWalletCredentials( - name: name, language: options.first as String); + name: name, language: options!.first as String); case WalletType.ethereum: return ethereum!.createEthereumNewWalletCredentials(name: name); case WalletType.bitcoinCash: diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 5dd9f2edf..d241c4421 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.7.5" -MONERO_COM_BUILD_NUMBER=67 +MONERO_COM_VERSION="1.8.0" +MONERO_COM_BUILD_NUMBER=68 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.10.5" -CAKEWALLET_BUILD_NUMBER=181 +CAKEWALLET_VERSION="4.11.0" +CAKEWALLET_BUILD_NUMBER=182 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 810b2b78c..874501cb5 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.7.5" -MONERO_COM_BUILD_NUMBER=65 +MONERO_COM_VERSION="1.8.0" +MONERO_COM_BUILD_NUMBER=66 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.10.5" -CAKEWALLET_BUILD_NUMBER=199 +CAKEWALLET_VERSION="4.11.0" +CAKEWALLET_BUILD_NUMBER=200 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 665da3425..f69670c9a 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -15,8 +15,8 @@ if [ -n "$1" ]; then fi CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.3.5" -CAKEWALLET_BUILD_NUMBER=42 +CAKEWALLET_VERSION="1.4.0" +CAKEWALLET_BUILD_NUMBER=43 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From 2bddeb6ac2e3e89c4cbabb8c3ba03de8905302f5 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Thu, 30 Nov 2023 16:38:28 +0100 Subject: [PATCH 057/241] Polyseed design changes (#1211) * Add icons to Language- and Seedtype-picker to indicate it's clickability * Add Seed Type Selector to New Wallet Page * Rename "Advanced Privacy Settings" to "Advanced Settings" --- .../screens/new_wallet/new_wallet_page.dart | 51 +++++++++---- .../wallet_restore_from_seed_form.dart | 75 ++++++++++++------- .../screens/restore/wallet_restore_page.dart | 2 +- lib/src/widgets/seed_language_selector.dart | 23 +++--- lib/view_model/wallet_new_vm.dart | 2 + res/values/strings_ar.arb | 4 +- res/values/strings_bg.arb | 6 +- res/values/strings_cs.arb | 6 +- res/values/strings_de.arb | 6 +- res/values/strings_en.arb | 6 +- res/values/strings_es.arb | 8 +- res/values/strings_fr.arb | 9 +-- res/values/strings_ha.arb | 6 +- res/values/strings_hi.arb | 6 +- res/values/strings_hr.arb | 8 +- res/values/strings_id.arb | 8 +- res/values/strings_it.arb | 6 +- res/values/strings_ja.arb | 6 +- res/values/strings_ko.arb | 6 +- res/values/strings_my.arb | 6 +- res/values/strings_nl.arb | 8 +- res/values/strings_pl.arb | 6 +- res/values/strings_pt.arb | 6 +- res/values/strings_ru.arb | 6 +- res/values/strings_th.arb | 6 +- res/values/strings_tl.arb | 6 +- res/values/strings_tr.arb | 6 +- res/values/strings_uk.arb | 8 +- res/values/strings_ur.arb | 6 +- res/values/strings_yo.arb | 6 +- res/values/strings_zh.arb | 6 +- 31 files changed, 183 insertions(+), 137 deletions(-) diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index d86d51e93..5c9533ace 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -1,4 +1,6 @@ import 'package:cake_wallet/entities/generate_name.dart'; +import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart'; +import 'package:cake_wallet/src/widgets/picker.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/main.dart'; import 'package:cake_wallet/routes.dart'; @@ -88,6 +90,8 @@ class _WalletNameFormState extends State { }); } }); + + _setSeedType(SeedType.defaultSeedType); super.initState(); } @@ -183,25 +187,38 @@ class _WalletNameFormState extends State { ), ), ), + if (_walletNewVM.hasLanguageSelector) ...[ - Padding( - padding: EdgeInsets.only(top: 40), - child: Text( - S.of(context).seed_language_choose, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16.0, - fontWeight: FontWeight.w500, - color: Theme.of(context).extension()!.titleColor), + if (_walletNewVM.hasSeedType) ...[ + Observer( + builder: (BuildContext build) => Padding( + padding: EdgeInsets.only(top: 24), + child: SelectButton( + text: widget._settingsStore.moneroSeedType.title, + onTap: () async { + await showPopUp( + context: context, + builder: (_) => Picker( + items: SeedType.all, + selectedAtIndex: isPolyseed ? 1 : 0, + onItemSelected: _setSeedType, + isSeparated: false, + ), + ); + }, + ), + ), ), - ), + ], Observer( builder: (BuildContext build) => Padding( - padding: EdgeInsets.only(top: 24), + padding: EdgeInsets.only(top: 10), child: SeedLanguageSelector( key: _languageSelectorKey, initialSelected: defaultSeedLanguage, - seedType: widget._settingsStore.moneroSeedType, + seedType: _walletNewVM.hasSeedType + ? widget._settingsStore.moneroSeedType + : SeedType.legacy, ), ), ) @@ -231,7 +248,7 @@ class _WalletNameFormState extends State { Navigator.of(context) .pushNamed(Routes.advancedPrivacySettings, arguments: _walletNewVM.type); }, - child: Text(S.of(context).advanced_privacy_settings), + child: Text(S.of(context).advanced_settings), ), ], )), @@ -253,11 +270,17 @@ class _WalletNameFormState extends State { buttonAction: () => Navigator.of(context).pop()); }); } else { - final isPolyseed = widget._settingsStore.moneroSeedType == SeedType.polyseed; _walletNewVM.create( options: _walletNewVM.hasLanguageSelector ? [_languageSelectorKey.currentState!.selected, isPolyseed] : null); } } + + bool get isPolyseed => widget._settingsStore.moneroSeedType == SeedType.polyseed; + + void _setSeedType(SeedType item) { + widget._settingsStore.moneroSeedType = item; + _languageSelectorKey.currentState?.selected = defaultSeedLanguage; // Reset Seed language + } } diff --git a/lib/src/screens/restore/wallet_restore_from_seed_form.dart b/lib/src/screens/restore/wallet_restore_from_seed_form.dart index ac8413212..f31657743 100644 --- a/lib/src/screens/restore/wallet_restore_from_seed_form.dart +++ b/lib/src/screens/restore/wallet_restore_from_seed_form.dart @@ -124,25 +124,30 @@ class WalletRestoreFromSeedFormState extends State { onSeedChange: onSeedChange), if (widget.type == WalletType.monero) GestureDetector( - onTap: () async { - await showPopUp( - context: context, - builder: (_) => Picker( - items: SeedType.all, - selectedAtIndex: isPolyseed ? 1 : 0, - mainAxisAlignment: MainAxisAlignment.start, - onItemSelected: _changeSeedType, - isSeparated: false, - )); - }, - child: Container( - color: Colors.transparent, - padding: EdgeInsets.only(top: 20.0), - child: IgnorePointer( - child: BaseTextFormField( - controller: seedTypeController, - enableInteractiveSelection: false, - readOnly: true)))), + onTap: () async { + await showPopUp( + context: context, + builder: (_) => Picker( + items: SeedType.all, + selectedAtIndex: isPolyseed ? 1 : 0, + mainAxisAlignment: MainAxisAlignment.start, + onItemSelected: _changeSeedType, + isSeparated: false, + )); + }, + child: Container( + color: Colors.transparent, + padding: EdgeInsets.only(top: 20.0), + child: IgnorePointer( + child: BaseTextFormField( + controller: seedTypeController, + enableInteractiveSelection: false, + readOnly: true, + suffixIcon: expandIcon, + ), + ), + ), + ), if (widget.displayLanguageSelector) GestureDetector( onTap: () async { @@ -154,14 +159,19 @@ class WalletRestoreFromSeedFormState extends State { seedType: isPolyseed ? SeedType.polyseed : SeedType.legacy, )); }, - child: Container( - color: Colors.transparent, - padding: EdgeInsets.only(top: 20.0), - child: IgnorePointer( - child: BaseTextFormField( - controller: languageController, - enableInteractiveSelection: false, - readOnly: true)))), + child: Container( + color: Colors.transparent, + padding: EdgeInsets.only(top: 20.0), + child: IgnorePointer( + child: BaseTextFormField( + controller: languageController, + enableInteractiveSelection: false, + readOnly: true, + suffixIcon: expandIcon, + ), + ), + ), + ), if (!isPolyseed && widget.displayBlockHeightSelector) BlockchainHeightWidget( focusNode: widget.blockHeightFocusNode, @@ -171,6 +181,17 @@ class WalletRestoreFromSeedFormState extends State { ])); } + Widget get expandIcon => Container( + padding: EdgeInsets.all(18), + width: 24, + height: 24, + child: Image.asset( + 'assets/images/arrow_bottom_purple_icon.png', + height: 8, + color: Theme.of(context).hintColor, + ), + ); + void _changeLanguage(String language) { final setLang = isPolyseed ? "POLYSEED_$language" : language; setState(() { diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index ccac6f34c..445858f30 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -210,7 +210,7 @@ class WalletRestorePage extends BasePage { Navigator.of(context).pushNamed(Routes.advancedPrivacySettings, arguments: walletRestoreViewModel.type); }, - child: Text(S.of(context).advanced_privacy_settings), + child: Text(S.of(context).advanced_settings), ), ], ), diff --git a/lib/src/widgets/seed_language_selector.dart b/lib/src/widgets/seed_language_selector.dart index 07638bb2f..dde78c58c 100644 --- a/lib/src/widgets/seed_language_selector.dart +++ b/lib/src/widgets/seed_language_selector.dart @@ -1,19 +1,20 @@ import 'package:cake_wallet/entities/seed_type.dart'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart'; import 'package:cake_wallet/src/widgets/seed_language_picker.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; class SeedLanguageSelector extends StatefulWidget { - SeedLanguageSelector({Key? key, required this.initialSelected, this.seedType = SeedType.defaultSeedType}) + SeedLanguageSelector( + {Key? key, required this.initialSelected, this.seedType = SeedType.defaultSeedType}) : super(key: key); final String initialSelected; final SeedType seedType; @override - SeedLanguageSelectorState createState() => - SeedLanguageSelectorState(selected: initialSelected); + SeedLanguageSelectorState createState() => SeedLanguageSelectorState(selected: initialSelected); } class SeedLanguageSelectorState extends State { @@ -25,15 +26,17 @@ class SeedLanguageSelectorState extends State { Widget build(BuildContext context) { return SelectButton( image: null, - text: seedLanguages.firstWhere((e) => e.name == selected).nameLocalized, + text: + "${seedLanguages.firstWhere((e) => e.name == selected).nameLocalized} (${S.of(context).seed_language})", onTap: () async { await showPopUp( - context: context, - builder: (_) => SeedLanguagePicker( - selected: this.selected, - seedType: widget.seedType, - onItemSelected: (String selected) => - setState(() => this.selected = selected))); + context: context, + builder: (_) => SeedLanguagePicker( + selected: this.selected, + seedType: widget.seedType, + onItemSelected: (String selected) => setState(() => this.selected = selected), + ), + ); }, ); } diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart index acf829168..a36d68482 100644 --- a/lib/view_model/wallet_new_vm.dart +++ b/lib/view_model/wallet_new_vm.dart @@ -30,6 +30,8 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { bool get hasLanguageSelector => type == WalletType.monero || type == WalletType.haven; + bool get hasSeedType => type == WalletType.monero; + @override WalletCredentials getCredentials(dynamic _options) { final options = _options as List?; diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 47b11c78e..6158342f3 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -160,7 +160,7 @@ "seed_title": "سييد", "seed_share": "شارك السييد", "copy": "نسخ", - "seed_language_choose": "الرجاء اختيار لغة السييد:", + "seed_language": "لغة البذور", "seed_choose": "اختر لغة السييد", "seed_language_next": "التالي", "seed_language_english": "إنجليزي", @@ -569,7 +569,7 @@ "always": "دائماً", "minutes_to_pin_code": "${minutes} دقيقة", "disable_exchange": "تعطيل التبادل", - "advanced_privacy_settings": "إعدادات الخصوصية المتقدمة", + "advanced_settings": "إعدادات متقدمة", "settings_can_be_changed_later": "يمكن تغيير هذه الإعدادات لاحقًا في إعدادات التطبيق", "add_custom_node": "إضافة عقدة مخصصة جديدة", "disable_fiat": "تعطيل fiat", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 162e85cad..8c3a528bb 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -160,7 +160,7 @@ "seed_title": "Seed", "seed_share": "Споделяне на seed", "copy": "Копиране", - "seed_language_choose": "Моля, изберете език на seed-а:", + "seed_language": "Език на семената", "seed_choose": "Изберете език на seed-а", "seed_language_next": "Следващ", "seed_language_english": "Английски", @@ -569,7 +569,7 @@ "always": "Винаги", "minutes_to_pin_code": "${minute} минути", "disable_exchange": "Деактивиране на борса", - "advanced_privacy_settings": "Допълнителни настройки за поверителност", + "advanced_settings": "Разширени настройки", "settings_can_be_changed_later": "Тези настройки могат да бъдат променени по-късно от приложението", "add_custom_node": "Добавяне на нов персонализиран Node", "disable_fiat": "Деактивиране на fiat", @@ -742,4 +742,4 @@ "seed_language_czech": "Чех", "seed_language_korean": "Корейски", "seed_language_chinese_traditional": "Традиционен китайски)" -} \ No newline at end of file +} diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 8efdb59b5..64f2b45e5 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -160,7 +160,7 @@ "seed_title": "Seed", "seed_share": "Sdílet seed", "copy": "Kopírovat", - "seed_language_choose": "Prosím zvolte si jazyk seedu:", + "seed_language": "Jazyk semen", "seed_choose": "Zvolte si jazyk seedu", "seed_language_next": "Další", "seed_language_english": "Angličtina", @@ -569,7 +569,7 @@ "always": "Vždy", "minutes_to_pin_code": "${minute} minutách", "disable_exchange": "Zakázat směnárny", - "advanced_privacy_settings": "Pokročilá nastavení soukromí", + "advanced_settings": "Pokročilé nastavení", "settings_can_be_changed_later": "Tato nastavení mohou být změněna později v nastavení v této aplikaci", "add_custom_node": "Přidat vlastní uzel", "disable_fiat": "Zakázat fiat", @@ -742,4 +742,4 @@ "seed_language_czech": "čeština", "seed_language_korean": "korejština", "seed_language_chinese_traditional": "Číňan (tradiční)" -} \ No newline at end of file +} diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 754a0f22e..2bb9e1404 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -160,7 +160,7 @@ "seed_title": "Seed", "seed_share": "Seed teilen", "copy": "Kopieren", - "seed_language_choose": "Bitte wählen Sie die Sprache des Seeds:", + "seed_language": "Seed-Sprache", "seed_choose": "Seed-Sprache auswählen", "seed_language_next": "Weiter", "seed_language_english": "Englisch", @@ -571,7 +571,7 @@ "always": "immer", "minutes_to_pin_code": "${minute} Minuten", "disable_exchange": "Exchange deaktivieren", - "advanced_privacy_settings": "Erweiterte Datenschutzeinstellungen", + "advanced_settings": "Erweiterte Einstellungen", "settings_can_be_changed_later": "Diese Einstellungen können später in den App-Einstellungen geändert werden", "add_custom_node": "Neuen benutzerdefinierten Knoten hinzufügen", "disable_fiat": "Fiat deaktivieren", @@ -750,4 +750,4 @@ "seed_language_czech": "Tschechisch", "seed_language_korean": "Koreanisch", "seed_language_chinese_traditional": "Chinesisch (Traditionell)" -} \ No newline at end of file +} diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index d65aebe15..88949525c 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -160,7 +160,7 @@ "seed_title": "Seed", "seed_share": "Share seed", "copy": "Copy", - "seed_language_choose": "Please choose seed language:", + "seed_language": "Seed language", "seed_choose": "Choose seed language", "seed_language_next": "Next", "seed_language_english": "English", @@ -572,7 +572,7 @@ "always": "Always", "minutes_to_pin_code": "${minute} minutes", "disable_exchange": "Disable exchange", - "advanced_privacy_settings": "Advanced Privacy Settings", + "advanced_settings": "Advanced Settings", "settings_can_be_changed_later": "These settings can be changed later in the app settings", "add_custom_node": "Add New Custom Node", "disable_fiat": "Disable fiat", @@ -751,4 +751,4 @@ "seed_language_czech": "Czech", "seed_language_korean": "Korean", "seed_language_chinese_traditional": "Chinese (Traditional)" -} \ No newline at end of file +} diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index f785a15d5..7a3907fb2 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -160,7 +160,7 @@ "seed_title": "Semilla", "seed_share": "Compartir semillas", "copy": "Dupdo", - "seed_language_choose": "Por favor elija el idioma semilla:", + "seed_language": "Lenguaje de semillas", "seed_choose": "Elige el idioma semilla", "seed_language_next": "Próximo", "seed_language_english": "Inglés", @@ -571,7 +571,7 @@ "always": "siempre", "minutes_to_pin_code": "${minute} minutos", "disable_exchange": "Deshabilitar intercambio", - "advanced_privacy_settings": "Configuración avanzada de privacidad", + "advanced_settings": "Ajustes avanzados", "settings_can_be_changed_later": "Estas configuraciones se pueden cambiar más tarde en la configuración de la aplicación", "add_custom_node": "Agregar nuevo nodo personalizado", "disable_fiat": "Deshabilitar fiat", @@ -749,5 +749,5 @@ "seedtype_polyseed": "Polieta (16 palabras)", "seed_language_czech": "checo", "seed_language_korean": "coreano", - "seed_language_chinese_traditional": "Chino tradicional)" -} \ No newline at end of file + "seed_language_chinese_traditional": "Chino (tradicional)" +} diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 88263ec05..0b2f54c6c 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -160,7 +160,7 @@ "seed_title": "Phrase secrète (seed)", "seed_share": "Partager la phrase secrète (seed)", "copy": "Copier", - "seed_language_choose": "Merci de choisir la langue de la phrase secrète (seed) :", + "seed_language": "Langage de la phrase secrète", "seed_choose": "Choisissez la langue de la phrase secrète (seed)", "seed_language_next": "Suivant", "seed_language_english": "Anglais", @@ -571,7 +571,7 @@ "always": "toujours", "minutes_to_pin_code": "${minute} minutes", "disable_exchange": "Désactiver l'échange", - "advanced_privacy_settings": "Paramètres de confidentialité avancés", + "advanced_settings": "Réglages avancés", "settings_can_be_changed_later": "Ces paramètres peuvent être modifiés ultérieurement dans les paramètres de l'application", "add_custom_node": "Ajouter un nouveau nœud personnalisé", "disable_fiat": "Désactiver les montants en fiat", @@ -741,16 +741,13 @@ "seed_phrase_length": "Longueur de la phrase de départ", "unavailable_balance": "Solde indisponible", "unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.", - "camera_permission_is_required": "L'autorisation d'accès à la caméra est requise.\nVeuillez l'activer depuis les paramètres de l'application.", - "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", "unspent_change": "Changement", "tor_connection": "Connexion Tor", "seed_hex_form": "Graine du portefeuille (forme hexagonale)", - "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", "seedtype": "Type de type graine", "seedtype_legacy": "Héritage (25 mots)", "seedtype_polyseed": "Polyseed (16 mots)", "seed_language_czech": "tchèque", "seed_language_korean": "coréen", "seed_language_chinese_traditional": "Chinois (Traditionnel)" -} \ No newline at end of file +} diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 39b98b51a..107599684 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -160,7 +160,7 @@ "seed_title": "iri", "seed_share": "Raba iri", "copy": "Kwafi", - "seed_language_choose": "Don Allah zaɓi harshen seed:", + "seed_language": "Harshen Magani", "seed_choose": "Zaɓi harshen seed", "seed_language_next": "Na gaba", "seed_language_english": "Ingilishi", @@ -570,7 +570,7 @@ "always": "Koyaushe", "minutes_to_pin_code": "${minute} minti", "disable_exchange": "Kashe musanya", - "advanced_privacy_settings": "Babban Saitunan Sirri", + "advanced_settings": "Saitunan ci gaba", "settings_can_be_changed_later": "Ana iya canza waɗannan saitunan daga baya a cikin saitunan app", "add_custom_node": "Ƙara Sabon Kulli na Custom", "disable_fiat": "Dakatar da fiat", @@ -728,4 +728,4 @@ "seed_language_czech": "Czech", "seed_language_korean": "Yaren Koriya", "seed_language_chinese_traditional": "Sinanci (na gargajiya)" -} \ No newline at end of file +} diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index b050ef43b..20cf5dd40 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -160,7 +160,7 @@ "seed_title": "बीज", "seed_share": "बीज साझा करें", "copy": "प्रतिलिपि", - "seed_language_choose": "कृपया बीज भाषा चुनें:", + "seed_language": "बीज", "seed_choose": "बीज भाषा चुनें", "seed_language_next": "आगामी", "seed_language_english": "अंग्रेज़ी", @@ -571,7 +571,7 @@ "always": "हमेशा", "minutes_to_pin_code": "${minute} मिनट", "disable_exchange": "एक्सचेंज अक्षम करें", - "advanced_privacy_settings": "उन्नत गोपनीयता सेटिंग्स", + "advanced_settings": "एडवांस सेटिंग", "settings_can_be_changed_later": "इन सेटिंग्स को बाद में ऐप सेटिंग में बदला जा सकता है", "add_custom_node": "नया कस्टम नोड जोड़ें", "disable_fiat": "िएट को अक्षम करें", @@ -750,4 +750,4 @@ "seed_language_czech": "चेक", "seed_language_korean": "कोरियाई", "seed_language_chinese_traditional": "चीनी पारंपरिक)" -} \ No newline at end of file +} diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 3c0f895e7..156d885ea 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -160,7 +160,7 @@ "seed_title": "Prisupni izraz", "seed_share": "Podijeli pristupni izraz", "copy": "Kopiraj", - "seed_language_choose": "Molimo odaberite jezik pristupnog izraza:", + "seed_language": "Sjemeni jezik", "seed_choose": "Odaberi jezik pristupnog izraza", "seed_language_next": "Dalje", "seed_language_english": "Engleski", @@ -571,7 +571,7 @@ "always": "Uvijek", "minutes_to_pin_code": "${minute} minuta", "disable_exchange": "Onemogući exchange", - "advanced_privacy_settings": "Napredne postavke privatnosti", + "advanced_settings": "Napredne postavke", "settings_can_be_changed_later": "Te se postavke mogu promijeniti kasnije u postavkama aplikacije", "add_custom_node": "Dodaj novi prilagođeni čvor", "disable_fiat": "Isključi, fiat", @@ -747,5 +747,5 @@ "seedtype_polyseed": "Poliseed (16 riječi)", "seed_language_czech": "češki", "seed_language_korean": "korejski", - "seed_language_chinese_traditional": "Kinesko tradicionalno)" -} \ No newline at end of file + "seed_language_chinese_traditional": "Kinesko (tradicionalno)" +} diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index b29572746..c6836b65b 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -160,7 +160,7 @@ "seed_title": "Bibit", "seed_share": "Bagikan bibit", "copy": "Salin", - "seed_language_choose": "Silakan pilih bahasa bibit:", + "seed_language": "Bahasa benih", "seed_choose": "Pilih bahasa bibit", "seed_language_next": "Selanjutnya", "seed_language_english": "Inggris", @@ -570,7 +570,7 @@ "always": "Selalu", "minutes_to_pin_code": "${minute} menit", "disable_exchange": "Nonaktifkan pertukaran", - "advanced_privacy_settings": "Pengaturan Privasi Lanjutan", + "advanced_settings": "Pengaturan lanjutan", "settings_can_be_changed_later": "Pengaturan ini dapat diubah nanti di pengaturan aplikasi", "add_custom_node": "Tambahkan Node Kustom Baru", "disable_fiat": "Nonaktifkan fiat", @@ -737,5 +737,5 @@ "seedtype_polyseed": "Polyseed (16 kata)", "seed_language_czech": "Ceko", "seed_language_korean": "Korea", - "seed_language_chinese_traditional": "Cina tradisional)" -} \ No newline at end of file + "seed_language_chinese_traditional": "Cina (tradisional)" +} diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 19912d277..1d6d355b6 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -160,7 +160,7 @@ "seed_title": "Seme", "seed_share": "Condividi seme", "copy": "Copia", - "seed_language_choose": "Gentilmente scegli la lingua del seme:", + "seed_language": "Linguaggio di semi", "seed_choose": "Scegli la lingua del seme", "seed_language_next": "Prossimo", "seed_language_english": "Inglese", @@ -571,7 +571,7 @@ "always": "sempre", "minutes_to_pin_code": "${minute} minuti", "disable_exchange": "Disabilita scambio", - "advanced_privacy_settings": "Impostazioni avanzate sulla privacy", + "advanced_settings": "Impostazioni avanzate", "settings_can_be_changed_later": "Queste impostazioni possono essere modificate in seguito nelle impostazioni dell'app", "add_custom_node": "Aggiungi nuovo nodo personalizzato", "disable_fiat": "Disabilita fiat", @@ -750,4 +750,4 @@ "seed_language_czech": "ceco", "seed_language_korean": "coreano", "seed_language_chinese_traditional": "Cinese tradizionale)" -} \ No newline at end of file +} diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index ea138b317..595a348d3 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -160,7 +160,7 @@ "seed_title": "シード", "seed_share": "シードを共有する", "copy": "コピー", - "seed_language_choose": "シード言語を選択してください:", + "seed_language": "シード言語", "seed_choose": "シード言語を選択してください", "seed_language_next": "次", "seed_language_english": "英語", @@ -571,7 +571,7 @@ "always": "いつも", "minutes_to_pin_code": "${minute} 分", "disable_exchange": "交換を無効にする", - "advanced_privacy_settings": "高度なプライバシー設定", + "advanced_settings": "高度な設定", "settings_can_be_changed_later": "これらの設定は、後でアプリの設定で変更できます", "add_custom_node": "新しいカスタム ノードを追加", "disable_fiat": "フィアットを無効にする", @@ -750,4 +750,4 @@ "seed_language_czech": "チェコ", "seed_language_korean": "韓国語", "seed_language_chinese_traditional": "中国の伝統的な)" -} \ No newline at end of file +} diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 4df43018d..0b0fff282 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -160,7 +160,7 @@ "seed_title": "씨", "seed_share": "시드 공유", "copy": "부", - "seed_language_choose": "종자 언어를 선택하십시오:", + "seed_language": "종자 언어", "seed_choose": "시드 언어를 선택하십시오", "seed_language_next": "다음 것", "seed_language_english": "영어", @@ -571,7 +571,7 @@ "always": "언제나", "minutes_to_pin_code": "${minute}분", "disable_exchange": "교환 비활성화", - "advanced_privacy_settings": "고급 개인 정보 설정", + "advanced_settings": "고급 설정", "settings_can_be_changed_later": "이 설정은 나중에 앱 설정에서 변경할 수 있습니다.", "add_custom_node": "새 사용자 정의 노드 추가", "disable_fiat": "법정화폐 비활성화", @@ -748,4 +748,4 @@ "seed_language_czech": "체코 사람", "seed_language_korean": "한국인", "seed_language_chinese_traditional": "중국 전통)" -} \ No newline at end of file +} diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index d82e30116..fea305f2d 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -160,7 +160,7 @@ "seed_title": "မျိုးစေ့", "seed_share": "မျိုးစေ့မျှဝေပါ။", "copy": "ကော်ပီ", - "seed_language_choose": "ကျေးဇူးပြု၍ မျိုးစေ့ဘာသာစကားကို ရွေးပါ-", + "seed_language": "မျိုးစေ့ဘာသာ", "seed_choose": "မျိုးစေ့ဘာသာစကားကို ရွေးချယ်ပါ။", "seed_language_next": "နောက်တစ်ခု", "seed_language_english": "အင်္ဂလိပ်စာ", @@ -569,7 +569,7 @@ "always": "အမြဲတမ်း", "minutes_to_pin_code": "${minute} မိနစ်", "disable_exchange": "လဲလှယ်မှုကို ပိတ်ပါ။", - "advanced_privacy_settings": "အဆင့်မြင့် ကိုယ်ရေးကိုယ်တာ ဆက်တင်များ", + "advanced_settings": "အဆင့်မြင့်ချိန်ညှိချက်များ", "settings_can_be_changed_later": "အက်ပ်ဆက်တင်များတွင် ဤဆက်တင်များကို နောက်ပိုင်းတွင် ပြောင်းလဲနိုင်သည်။", "add_custom_node": "စိတ်ကြိုက် Node အသစ်ကို ထည့်ပါ။", "disable_fiat": "Fiat ကိုပိတ်ပါ။", @@ -748,4 +748,4 @@ "seed_language_czech": "ချက်", "seed_language_korean": "ကိုးရီးယား", "seed_language_chinese_traditional": "တရုတ်ရိုးရာ)" -} \ No newline at end of file +} diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 8a290618d..e400de4c6 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -160,7 +160,7 @@ "seed_title": "Zaad", "seed_share": "Deel zaad", "copy": "Kopiëren", - "seed_language_choose": "Kies een starttaal:", + "seed_language": "Zaadtaal", "seed_choose": "Kies een starttaal", "seed_language_next": "Volgende", "seed_language_english": "Engels", @@ -571,7 +571,7 @@ "always": "altijd", "minutes_to_pin_code": "${minute} minuten", "disable_exchange": "Uitwisseling uitschakelen", - "advanced_privacy_settings": "Geavanceerde privacy-instellingen", + "advanced_settings": "Geavanceerde instellingen", "settings_can_be_changed_later": "Deze instellingen kunnen later worden gewijzigd in de app-instellingen", "add_custom_node": "Voeg een nieuw aangepast knooppunt toe", "disable_fiat": "Schakel Fiat uit", @@ -749,5 +749,5 @@ "seedtype_polyseed": "Polyseed (16 woorden)", "seed_language_czech": "Tsjechisch", "seed_language_korean": "Koreaans", - "seed_language_chinese_traditional": "Chinese traditionele)" -} \ No newline at end of file + "seed_language_chinese_traditional": "Chinese (traditionele)" +} diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index b84ddc98c..698115f8b 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -160,7 +160,7 @@ "seed_title": "Seed", "seed_share": "Udostępnij seed", "copy": "Kopiuj", - "seed_language_choose": "Proszę wybrać język słów we frazie seed:", + "seed_language": "Język nasion", "seed_choose": "Wybierz język", "seed_language_next": "Następny", "seed_language_english": "Angielski", @@ -571,7 +571,7 @@ "always": "zawsze", "minutes_to_pin_code": "${minute} minut", "disable_exchange": "Wyłącz wymianę", - "advanced_privacy_settings": "Zaawansowane ustawienia prywatności", + "advanced_settings": "Zaawansowane ustawienia", "settings_can_be_changed_later": "Te ustawienia można później zmienić w ustawieniach aplikacji", "add_custom_node": "Dodaj nowy węzeł niestandardowy", "disable_fiat": "Wyłącz waluty FIAT", @@ -750,4 +750,4 @@ "seed_language_czech": "Czech", "seed_language_korean": "koreański", "seed_language_chinese_traditional": "Chiński tradycyjny)" -} \ No newline at end of file +} diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index ed7b8a801..9a926834a 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -160,7 +160,7 @@ "seed_title": "Semente", "seed_share": "Compartilhar semente", "copy": "Copiar", - "seed_language_choose": "Por favor, escolha o idioma da semente:", + "seed_language": "Linguagem de semente", "seed_choose": "Escolha o idioma da semente", "seed_language_next": "Próximo", "seed_language_english": "Inglesa", @@ -570,7 +570,7 @@ "always": "sempre", "minutes_to_pin_code": "${minute} minutos", "disable_exchange": "Desativar troca", - "advanced_privacy_settings": "Configurações de privacidade avançadas", + "advanced_settings": "Configurações avançadas", "settings_can_be_changed_later": "Essas configurações podem ser alteradas posteriormente nas configurações do aplicativo", "add_custom_node": "Adicionar novo nó personalizado", "disable_fiat": "Desativar fiat", @@ -749,4 +749,4 @@ "seed_language_czech": "Tcheco", "seed_language_korean": "coreano", "seed_language_chinese_traditional": "Chinês tradicional)" -} \ No newline at end of file +} diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index c7749d0ea..e2a09009d 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -160,7 +160,7 @@ "seed_title": "Мнемоническая фраза", "seed_share": "Поделиться мнемонической фразой", "copy": "Скопировать", - "seed_language_choose": "Пожалуйста, выберите язык мнемонической фразы:", + "seed_language": "Язык семян", "seed_choose": "Выберите язык мнемонической фразы", "seed_language_next": "Продолжить", "seed_language_english": "Английский", @@ -571,7 +571,7 @@ "always": "всегда", "minutes_to_pin_code": "${minute} минут", "disable_exchange": "Отключить обмен", - "advanced_privacy_settings": "Расширенные настройки конфиденциальности", + "advanced_settings": "Расширенные настройки", "settings_can_be_changed_later": "Эти настройки можно изменить позже в настройках приложения.", "add_custom_node": "Добавить новый пользовательский узел", "disable_fiat": "Отключить фиат", @@ -750,4 +750,4 @@ "seed_language_czech": "Чешский", "seed_language_korean": "Корейский", "seed_language_chinese_traditional": "Китайский традиционный)" -} \ No newline at end of file +} diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 791b0f005..a4d7f405e 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -160,7 +160,7 @@ "seed_title": "Seed", "seed_share": "แบ่งปัน seed", "copy": "คัดลอก", - "seed_language_choose": "โปรดเลือกภาษาของ seed:", + "seed_language": "ภาษาเมล็ด", "seed_choose": "เลือกภาษาของ seed", "seed_language_next": "ถัดไป", "seed_language_english": "อังกฤษ", @@ -569,7 +569,7 @@ "always": "เสมอ", "minutes_to_pin_code": "${minute} นาที", "disable_exchange": "ปิดใช้งานการแลกเปลี่ยน", - "advanced_privacy_settings": "การตั้งค่าความเป็นส่วนตัวขั้นสูง", + "advanced_settings": "ตั้งค่าขั้นสูง", "settings_can_be_changed_later": "การตั้งค่านี้สามารถเปลี่ยนแปลงได้ภายหลังในการตั้งค่าแอพฯ", "add_custom_node": "เพิ่มจุดโหนดแบบกำหนดเอง", "disable_fiat": "ปิดใช้งานสกุลเงินตรา", @@ -748,4 +748,4 @@ "seed_language_czech": "ภาษาเช็ก", "seed_language_korean": "เกาหลี", "seed_language_chinese_traditional": "จีน (ดั้งเดิม)" -} \ No newline at end of file +} diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 8891563b0..04ba2af6d 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -160,7 +160,7 @@ "seed_title": "Binhi", "seed_share": "Magbahagi ng binhi", "copy": "Kopya", - "seed_language_choose": "Mangyaring pumili ng wika ng binhi:", + "seed_language": "Wika ng binhi", "seed_choose": "Pumili ng wika ng binhi", "seed_language_next": "Susunod", "seed_language_english": "Ingles", @@ -572,7 +572,7 @@ "always": "Palagi", "minutes_to_pin_code": "${minute} minuto", "disable_exchange": "Huwag paganahin ang palitan", - "advanced_privacy_settings": "Mga setting ng advanced na privacy", + "advanced_settings": "Mga Advanced na Setting", "settings_can_be_changed_later": "Ang mga setting na ito ay maaaring mabago mamaya sa mga setting ng app", "add_custom_node": "Magdagdag ng bagong pasadyang node", "disable_fiat": "Huwag paganahin ang Fiat", @@ -744,4 +744,4 @@ "seed_language_czech": "Czech", "seed_language_korean": "Korean", "seed_language_chinese_traditional": "Intsik (tradisyonal)" -} \ No newline at end of file +} diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index a5d6a330a..b7b5d33f8 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -160,7 +160,7 @@ "seed_title": "Tohum", "seed_share": "Tohumu paylaş", "copy": "Kopyala", - "seed_language_choose": "Lütfen tohum dilini seç:", + "seed_language": "Tohum dili", "seed_choose": "Tohum dilini seçin", "seed_language_next": "İleri", "seed_language_english": "İngilizce", @@ -569,7 +569,7 @@ "always": "Her Zaman", "minutes_to_pin_code": "${minute} dakika", "disable_exchange": "Borsayı devre dışı bırak", - "advanced_privacy_settings": "Gelişmiş Gizlilik Ayarları", + "advanced_settings": "Gelişmiş Ayarlar", "settings_can_be_changed_later": "Bu ayarlar daha sonra uygulama ayarlarından da değiştirilebilir", "add_custom_node": "Yeni Özel Düğüm Ekleme", "disable_fiat": "İtibari paraları devre dışı bırak", @@ -748,4 +748,4 @@ "seed_language_czech": "Çek", "seed_language_korean": "Koreli", "seed_language_chinese_traditional": "Çin geleneği)" -} \ No newline at end of file +} diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 81bc3c8aa..900e95acc 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -160,7 +160,7 @@ "seed_title": "Мнемонічна фраза", "seed_share": "Поділитися мнемонічною фразою", "copy": "Скопіювати", - "seed_language_choose": "Будь ласка, виберіть мову мнемонічної фрази:", + "seed_language": "Насіннєва мова", "seed_choose": "Виберіть мову мнемонічної фрази", "seed_language_next": "Продовжити", "seed_language_english": "Англійська", @@ -571,7 +571,7 @@ "always": "Завжди", "minutes_to_pin_code": "${minute} хвилин", "disable_exchange": "Вимкнути exchange", - "advanced_privacy_settings": "Розширені налаштування конфіденційності", + "advanced_settings": "Розширені налаштування", "settings_can_be_changed_later": "Ці параметри можна змінити пізніше в налаштуваннях програми", "add_custom_node": "Додати новий спеціальний вузол", "disable_fiat": "Вимкнути фиат", @@ -749,5 +749,5 @@ "seedtype_polyseed": "Полісей (16 слів)", "seed_language_czech": "Чеський", "seed_language_korean": "Корейський", - "seed_language_chinese_traditional": "Китайський традиційний)" -} \ No newline at end of file + "seed_language_chinese_traditional": "Китайський (традиційний)" +} diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 5b7f18ae7..5535bdf73 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -160,7 +160,7 @@ "seed_title": "بیج", "seed_share": "بیج بانٹیں۔", "copy": "کاپی", - "seed_language_choose": "براہ کرم بیج کی زبان کا انتخاب کریں:", + "seed_language": "بیج کی زبان", "seed_choose": "بیج کی زبان کا انتخاب کریں۔", "seed_language_next": "اگلے", "seed_language_english": "انگریزی", @@ -570,7 +570,7 @@ "always": "ہمیشہ", "minutes_to_pin_code": "${minute} منٹ", "disable_exchange": "تبادلے کو غیر فعال کریں۔", - "advanced_privacy_settings": "اعلی درجے کی رازداری کی ترتیبات", + "advanced_settings": "اعلی درجے کی ترتیبات", "settings_can_be_changed_later": "ان ترتیبات کو بعد میں ایپ کی ترتیبات میں تبدیل کیا جا سکتا ہے۔", "add_custom_node": "نیا کسٹم نوڈ شامل کریں۔", "disable_fiat": "فیاٹ کو غیر فعال کریں۔", @@ -742,4 +742,4 @@ "seed_language_czech": "چیک", "seed_language_korean": "کورین", "seed_language_chinese_traditional": "چینی (روایتی)" -} \ No newline at end of file +} diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 6821aa7f9..a867778f4 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -160,7 +160,7 @@ "seed_title": "Hóró", "seed_share": "Pín hóró", "copy": "Ṣẹ̀dà", - "seed_language_choose": "Ẹ jọ̀wọ́ yan èdè hóró:", + "seed_language": "Ewu ọmọ", "seed_choose": "Yan èdè hóró", "seed_language_next": "Tẹ̀síwájú", "seed_language_english": "Èdè Gẹ̀ẹ́sì", @@ -567,7 +567,7 @@ "always": "Ní gbogbo àwọn ìgbà", "minutes_to_pin_code": "${minute} ìṣẹ́jú", "disable_exchange": "Pa ilé pàṣípààrọ̀", - "advanced_privacy_settings": "Àwọn ààtò àdáni títóbi", + "advanced_settings": "Awọn eto ilọsiwaju", "settings_can_be_changed_later": "Ẹ lè pààrọ̀ àwọn ààtò yìí nínú ààtò áàpù t’ó bá yá", "add_custom_node": "Fikún apẹka títun t'ẹ́ pààrọ̀", "disable_fiat": "Pa owó tí ìjọba pàṣẹ wa lò", @@ -744,4 +744,4 @@ "seed_language_czech": "Czech", "seed_language_korean": "Ara ẹni", "seed_language_chinese_traditional": "Kannada (ibile)" -} \ No newline at end of file +} diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index b66d0e65e..7762af3a0 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -160,7 +160,7 @@ "seed_title": "种子", "seed_share": "分享种子", "copy": "复制", - "seed_language_choose": "请选择种子语言:", + "seed_language": "种子语言", "seed_choose": "选择种子语言", "seed_language_next": "下一个", "seed_language_english": "英文", @@ -570,7 +570,7 @@ "always": "总是", "minutes_to_pin_code": "${minute} 分钟", "disable_exchange": "禁用交换", - "advanced_privacy_settings": "高级隐私设置", + "advanced_settings": "高级设置", "settings_can_be_changed_later": "稍后可以在应用设置中更改这些设置", "add_custom_node": "添加新的自定义节点", "disable_fiat": "禁用法令", @@ -749,4 +749,4 @@ "seed_language_czech": "捷克", "seed_language_korean": "韩国人", "seed_language_chinese_traditional": "中国传统的)" -} \ No newline at end of file +} From 3760285a64405935fafe7aeeb051fd25d850585b Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Thu, 30 Nov 2023 16:39:09 -0500 Subject: [PATCH 058/241] ios/mac secure storage pin migration (potential fix) (#1205) * ios/mac secure storage pin migration * function call was incorrect * Update default_settings_migration.dart --------- Co-authored-by: Omar Hatem --- lib/entities/default_settings_migration.dart | 98 +++++++++++++------- lib/main.dart | 2 +- 2 files changed, 64 insertions(+), 36 deletions(-) diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index a65742e99..ec31b0539 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -1,5 +1,6 @@ import 'dart:io' show Directory, File, Platform; import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/entities/encrypt.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; @@ -82,8 +83,7 @@ Future defaultSettingsMigration( sharedPreferences: sharedPreferences, nodes: nodes); await changeLitecoinCurrentElectrumServerToDefault( sharedPreferences: sharedPreferences, nodes: nodes); - await changeHavenCurrentNodeToDefault( - sharedPreferences: sharedPreferences, nodes: nodes); + await changeHavenCurrentNodeToDefault(sharedPreferences: sharedPreferences, nodes: nodes); await changeBitcoinCashCurrentNodeToDefault( sharedPreferences: sharedPreferences, nodes: nodes); @@ -175,6 +175,9 @@ Future defaultSettingsMigration( await changeBitcoinCurrentElectrumServerToDefault( sharedPreferences: sharedPreferences, nodes: nodes); break; + case 25: + await rewriteSecureStoragePin(secureStorage: secureStorage); + break; default: break; @@ -340,9 +343,9 @@ Node? getNanoDefaultPowNode({required Box nodes}) { } Node? getBitcoinCashDefaultElectrumServer({required Box nodes}) { - return nodes.values.firstWhereOrNull( - (Node node) => node.uriRaw == cakeWalletBitcoinCashDefaultNodeUri) - ?? nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoinCash); + return nodes.values + .firstWhereOrNull((Node node) => node.uriRaw == cakeWalletBitcoinCashDefaultNodeUri) ?? + nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoinCash); } Node getMoneroDefaultNode({required Box nodes}) { @@ -364,6 +367,37 @@ Node getMoneroDefaultNode({required Box nodes}) { } } +Future rewriteSecureStoragePin({required FlutterSecureStorage secureStorage}) async { + // the bug only affects ios/mac: + if (!Platform.isIOS && !Platform.isMacOS) { + return; + } + + // first, get the encoded pin: + final keyForPinCode = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); + String? encodedPin; + try { + encodedPin = await secureStorage.read(key: keyForPinCode); + } catch (e) { + // either we don't have a pin, or we can't read it (maybe even because of the bug!) + // the only option here is to abort the migration or we risk losing the pin and locking the user out + return; + } + + if (encodedPin == null) { + return; + } + + // ensure we overwrite by deleting the old key first: + await secureStorage.delete(key: keyForPinCode); + await secureStorage.write( + key: keyForPinCode, + value: encodedPin, + iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock), + mOptions: MacOsOptions(accessibility: KeychainAccessibility.first_unlock), + ); +} + Future changeBitcoinCurrentElectrumServerToDefault( {required SharedPreferences sharedPreferences, required Box nodes}) async { final server = getBitcoinDefaultElectrumServer(nodes: nodes); @@ -381,8 +415,7 @@ Future changeLitecoinCurrentElectrumServerToDefault( } Future changeBitcoinCashCurrentNodeToDefault( - {required SharedPreferences sharedPreferences, - required Box nodes}) async { + {required SharedPreferences sharedPreferences, required Box nodes}) async { final server = getBitcoinCashDefaultElectrumServer(nodes: nodes); final serverId = server?.key as int ?? 0; @@ -538,34 +571,30 @@ Future checkCurrentNodes( final currentMoneroNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey); final currentBitcoinElectrumSeverId = sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); - final currentLitecoinElectrumSeverId = sharedPreferences - .getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); - final currentHavenNodeId = sharedPreferences - .getInt(PreferencesKey.currentHavenNodeIdKey); - final currentEthereumNodeId = sharedPreferences - .getInt(PreferencesKey.currentEthereumNodeIdKey); - final currentNanoNodeId = sharedPreferences - .getInt(PreferencesKey.currentNanoNodeIdKey); - final currentNanoPowNodeId = sharedPreferences - .getInt(PreferencesKey.currentNanoPowNodeIdKey); - final currentBitcoinCashNodeId = sharedPreferences - .getInt(PreferencesKey.currentBitcoinCashNodeIdKey); - final currentMoneroNode = nodeSource.values.firstWhereOrNull( - (node) => node.key == currentMoneroNodeId); - final currentBitcoinElectrumServer = nodeSource.values.firstWhereOrNull( - (node) => node.key == currentBitcoinElectrumSeverId); - final currentLitecoinElectrumServer = nodeSource.values.firstWhereOrNull( - (node) => node.key == currentLitecoinElectrumSeverId); - final currentHavenNodeServer = nodeSource.values.firstWhereOrNull( - (node) => node.key == currentHavenNodeId); - final currentEthereumNodeServer = nodeSource.values.firstWhereOrNull( - (node) => node.key == currentEthereumNodeId); + final currentLitecoinElectrumSeverId = + sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); + final currentHavenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey); + final currentEthereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey); + final currentNanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); + final currentNanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey); + final currentBitcoinCashNodeId = + sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); + final currentMoneroNode = + nodeSource.values.firstWhereOrNull((node) => node.key == currentMoneroNodeId); + final currentBitcoinElectrumServer = + nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinElectrumSeverId); + final currentLitecoinElectrumServer = + nodeSource.values.firstWhereOrNull((node) => node.key == currentLitecoinElectrumSeverId); + final currentHavenNodeServer = + nodeSource.values.firstWhereOrNull((node) => node.key == currentHavenNodeId); + final currentEthereumNodeServer = + nodeSource.values.firstWhereOrNull((node) => node.key == currentEthereumNodeId); final currentNanoNodeServer = - nodeSource.values.firstWhereOrNull((node) => node.key == currentNanoNodeId); + nodeSource.values.firstWhereOrNull((node) => node.key == currentNanoNodeId); final currentNanoPowNodeServer = - powNodeSource.values.firstWhereOrNull((node) => node.key == currentNanoPowNodeId); - final currentBitcoinCashNodeServer = nodeSource.values.firstWhereOrNull( - (node) => node.key == currentBitcoinCashNodeId); + powNodeSource.values.firstWhereOrNull((node) => node.key == currentNanoPowNodeId); + final currentBitcoinCashNodeServer = + nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinCashNodeId); if (currentMoneroNode == null) { final newCakeWalletNode = Node(uri: newCakeWalletMoneroUri, type: WalletType.monero); await nodeSource.add(newCakeWalletNode); @@ -617,8 +646,7 @@ Future checkCurrentNodes( if (currentBitcoinCashNodeServer == null) { final node = Node(uri: cakeWalletBitcoinCashDefaultNodeUri, type: WalletType.bitcoinCash); await nodeSource.add(node); - await sharedPreferences.setInt( - PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int); + await sharedPreferences.setInt(PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int); } } diff --git a/lib/main.dart b/lib/main.dart index 6807e9185..165db1ddd 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -163,7 +163,7 @@ Future initializeAppConfigs() async { transactionDescriptions: transactionDescriptions, secureStorage: secureStorage, anonpayInvoiceInfo: anonpayInvoiceInfo, - initialMigrationVersion: 23); + initialMigrationVersion: 25); } Future initialSetup( From 3b7f9a297cbe5aa4eb7ce9656af7685626e12618 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Sat, 2 Dec 2023 02:02:55 +0100 Subject: [PATCH 059/241] Bug missing polyseed (#1214) * Move file.dart * Add seedFallback for missing polyseeds * Remove unused dependency of cw_bitcoin * Minor fix MacOS * Add more blockheight-date matching * Scan only last 2 days for new Polyseed wallets --- .../lib/electrum_transaction_history.dart | 7 +++-- cw_bitcoin/lib/electrum_wallet.dart | 2 +- cw_bitcoin/lib/electrum_wallet_snapshot.dart | 4 +-- cw_bitcoin/pubspec.yaml | 1 - cw_core/lib/get_height_by_date.dart | 5 ++- .../lib => cw_core/lib/utils}/file.dart | 13 ++------ cw_monero/ios/Classes/monero_api.cpp | 6 ++-- cw_monero/lib/monero_wallet.dart | 9 ++++-- cw_monero/lib/monero_wallet_service.dart | 31 ++++++++++++++++--- cw_monero/macos/Classes/monero_api.cpp | 6 ++-- 10 files changed, 52 insertions(+), 32 deletions(-) rename {cw_bitcoin/lib => cw_core/lib/utils}/file.dart (66%) diff --git a/cw_bitcoin/lib/electrum_transaction_history.dart b/cw_bitcoin/lib/electrum_transaction_history.dart index be039fa36..d478c3b12 100644 --- a/cw_bitcoin/lib/electrum_transaction_history.dart +++ b/cw_bitcoin/lib/electrum_transaction_history.dart @@ -1,10 +1,11 @@ import 'dart:convert'; + +import 'package:cw_bitcoin/electrum_transaction_info.dart'; import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/transaction_history.dart'; +import 'package:cw_core/utils/file.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:mobx/mobx.dart'; -import 'package:cw_core/transaction_history.dart'; -import 'package:cw_bitcoin/file.dart'; -import 'package:cw_bitcoin/electrum_transaction_info.dart'; part 'electrum_transaction_history.g.dart'; diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 903fa14cc..85053133f 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -18,7 +18,6 @@ import 'package:cw_bitcoin/electrum_balance.dart'; import 'package:cw_bitcoin/electrum_transaction_history.dart'; import 'package:cw_bitcoin/electrum_transaction_info.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; -import 'package:cw_bitcoin/file.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/script_hash.dart'; import 'package:cw_bitcoin/utils.dart'; @@ -30,6 +29,7 @@ import 'package:cw_core/sync_status.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/utils/file.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:flutter/foundation.dart'; diff --git a/cw_bitcoin/lib/electrum_wallet_snapshot.dart b/cw_bitcoin/lib/electrum_wallet_snapshot.dart index def991ebe..86d3e2fed 100644 --- a/cw_bitcoin/lib/electrum_wallet_snapshot.dart +++ b/cw_bitcoin/lib/electrum_wallet_snapshot.dart @@ -1,8 +1,8 @@ import 'dart:convert'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum_balance.dart'; -import 'package:cw_bitcoin/file.dart'; import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/utils/file.dart'; import 'package:cw_core/wallet_type.dart'; class ElectrumWallletSnapshot { @@ -56,4 +56,4 @@ class ElectrumWallletSnapshot { regularAddressIndex: regularAddressIndex, changeAddressIndex: changeAddressIndex); } -} \ No newline at end of file +} diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index 693d5af7a..e90f9cda4 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -30,7 +30,6 @@ dependencies: rxdart: ^0.27.5 unorm_dart: ^0.2.0 cryptography: ^2.0.5 - encrypt: ^5.0.1 dev_dependencies: flutter_test: diff --git a/cw_core/lib/get_height_by_date.dart b/cw_core/lib/get_height_by_date.dart index a680e6c25..6f3ccaf68 100644 --- a/cw_core/lib/get_height_by_date.dart +++ b/cw_core/lib/get_height_by_date.dart @@ -118,7 +118,10 @@ final dates = { "2023-6": 2898234, "2023-7": 2919771, "2023-8": 2942045, - "2023-9": 2964280 + "2023-9": 2964280, + "2023-10": 2985937, + "2023-11": 3008178, + "2023-12": 3029759 }; int getMoneroHeigthByDate({required DateTime date}) { diff --git a/cw_bitcoin/lib/file.dart b/cw_core/lib/utils/file.dart similarity index 66% rename from cw_bitcoin/lib/file.dart rename to cw_core/lib/utils/file.dart index 8fd236ec3..0b1c5cffd 100644 --- a/cw_bitcoin/lib/file.dart +++ b/cw_core/lib/utils/file.dart @@ -2,17 +2,8 @@ import 'dart:io'; import 'package:cw_core/key.dart'; import 'package:encrypt/encrypt.dart' as encrypt; -Future write( - {required String path, - required String password, - required String data}) async { - final keys = extractKeys(password); - final key = encrypt.Key.fromBase64(keys.first); - final iv = encrypt.IV.fromBase64(keys.last); - final encrypted = await encode(key: key, iv: iv, data: data); - final f = File(path); - f.writeAsStringSync(encrypted); -} +Future write({required String path, required String password, required String data}) async => + writeData(path: path, password: password, data: data); Future writeData( {required String path, diff --git a/cw_monero/ios/Classes/monero_api.cpp b/cw_monero/ios/Classes/monero_api.cpp index 7ad873647..6162375b2 100644 --- a/cw_monero/ios/Classes/monero_api.cpp +++ b/cw_monero/ios/Classes/monero_api.cpp @@ -385,6 +385,9 @@ extern "C" (uint64_t)restoreHeight, std::string(spendKey)); + // Cache Raw to support Polyseed + wallet->setCacheAttribute("cakewallet.seed", std::string(seed)); + int status; std::string errorString; @@ -396,9 +399,6 @@ extern "C" return false; } - // Cache Raw to support Polyseed - wallet->setCacheAttribute("cakewallet.seed", std::string(seed)); - change_current_wallet(wallet); return true; } diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 71c7e3967..924a987cd 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -97,7 +97,8 @@ abstract class MoneroWalletBase ObservableMap balance; @override - String get seed => monero_wallet.getSeed(); + String get seed => _seed; + String _seed = monero_wallet.getSeed(); @override MoneroWalletKeys get keys => MoneroWalletKeys( @@ -113,7 +114,11 @@ abstract class MoneroWalletBase Timer? _autoSaveTimer; List unspentCoins; - Future init() async { + Future init({String seedFallback = ""}) async { + if (_seed.isEmpty) { + _seed = seedFallback; + } + await walletAddresses.init(); balance = ObservableMap.of({ currency: MoneroBalance( diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 077ab4e54..c71d43e83 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:cw_core/monero_wallet_utils.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/utils/file.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; @@ -77,8 +78,12 @@ class MoneroWalletService extends WalletService< final polyseed = Polyseed.create(); final lang = PolyseedLang.getByEnglishName(credentials.language); + final heightOverride = + getMoneroHeigthByDate(date: DateTime.now().subtract(Duration(days: 2))); + return _restoreFromPolyseed( - path, credentials.password!, polyseed, credentials.walletInfo!, lang); + path, credentials.password!, polyseed, credentials.walletInfo!, lang, + overrideHeight: heightOverride); } await monero_wallet_manager.createWallet( @@ -129,7 +134,12 @@ class MoneroWalletService extends WalletService< return openWallet(name, password); } - await wallet.init(); + if (wallet.seed.isEmpty) { + final seedFallback = await _getSeedBackup(path, password); + await wallet.init(seedFallback: seedFallback); + } else { + await wallet.init(); + } return wallet; } catch (e) { @@ -268,10 +278,11 @@ class MoneroWalletService extends WalletService< Future _restoreFromPolyseed(String path, String password, Polyseed polyseed, WalletInfo walletInfo, PolyseedLang lang, - {PolyseedCoin coin = PolyseedCoin.POLYSEED_MONERO}) async { - final height = getMoneroHeigthByDate( + {PolyseedCoin coin = PolyseedCoin.POLYSEED_MONERO, int? overrideHeight}) async { + final height = overrideHeight ?? getMoneroHeigthByDate( date: DateTime.fromMillisecondsSinceEpoch(polyseed.birthday * 1000)); final spendKey = keyToHexString(polyseed.generateKey(coin, 32)); + final seed = polyseed.encode(lang, coin); walletInfo.isRecovery = true; walletInfo.restoreHeight = height; @@ -279,10 +290,13 @@ class MoneroWalletService extends WalletService< await monero_wallet_manager.restoreFromSpendKey( path: path, password: password, - seed: polyseed.encode(lang, coin), + seed: seed, language: lang.nameEnglish, restoreHeight: height, spendKey: spendKey); + + await writeData(path: "$path.seed", password: password, data: seed); + final wallet = MoneroWallet( walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); @@ -290,6 +304,13 @@ class MoneroWalletService extends WalletService< return wallet; } + Future _getSeedBackup(String path, String password) async { + final seedFilePath = "$path.seed"; + final seedFile = File(seedFilePath); + if (!seedFile.existsSync()) return ""; + return read(path: seedFilePath, password: password); + } + Future repairOldAndroidWallet(String name) async { try { if (!Platform.isAndroid) { diff --git a/cw_monero/macos/Classes/monero_api.cpp b/cw_monero/macos/Classes/monero_api.cpp index a5ca13822..6fabc29fd 100644 --- a/cw_monero/macos/Classes/monero_api.cpp +++ b/cw_monero/macos/Classes/monero_api.cpp @@ -385,6 +385,9 @@ extern "C" (uint64_t)restoreHeight, std::string(spendKey)); + // Cache Raw to support Polyseed + wallet->setCacheAttribute("cakewallet.seed", std::string(seed)); + int status; std::string errorString; @@ -396,9 +399,6 @@ extern "C" return false; } - // Cache Raw to support Polyseed - wallet->setCacheAttribute("cakewallet.seed", std::string(seed)); - change_current_wallet(wallet); return true; } From b3d579c24aa81b9e34a3a2710edec6618114c7be Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Sat, 2 Dec 2023 03:26:43 +0100 Subject: [PATCH 060/241] CW-527-Add-Polygon-MATIC-Wallet (#1179) * chore: Initial setup for polygon package * feat: Add polygon node urls * feat: Add Polygon(MATIC) wallet WIP * feat: Add Polygon(MATIC) wallet WIP * feat: Add Polygon MATIC wallet [skip ci] * fix: Issue with create/restore wallet for polygon * feat: Add erc20 tokens for polygon * feat: Adding Polygon MATIC Wallet * fix: Add build command for polygon to workflow file to fix failing action * fix: Switch evm to not display additional balance * chore: Sync with remote * fix: Revert change to inject app script * feat: Add polygon erc20 tokens * feat: Increase migration version * fix: Restore from QR address validator fix * fix: Adjust wallet connect connection flow to adapt to wallet type * fix: Make wallet fetch nfts based on the current wallet type * fix: Make wallet fetch nfts based on the current wallet type * fix: Try fetching transactions with moralis * fix: Requested review changes * fix: Error creating new wallet * fix: Revert script * fix: Exclude spam NFTs from nft listing API response * Update default_erc20_tokens.dart * replace matic with matic poly * Add polygon wallet scheme to app links * style: reformat default_settings_migration.dart * minor enhancement * fix using different wallet function for setting the transaction priorities * fix: Add chain to calls * Add USDC.e to initial coins * Add other default polygon node * Use Polygon scan some UI fixes * Add polygon scan api key to secrets generation code --------- Co-authored-by: Omar Hatem --- .github/workflows/pr_test_build.yml | 2 + .gitignore | 1 + android/app/src/main/AndroidManifestBase.xml | 3 + assets/polygon_node_list.yml | 6 + cw_core/lib/currency_for_wallet_type.dart | 2 + cw_core/lib/erc20_token.dart | 1 + cw_core/lib/node.dart | 4 + cw_core/lib/wallet_type.dart | 16 +- cw_ethereum/lib/ethereum_client.dart | 32 +- .../lib/ethereum_transaction_info.dart | 13 +- .../lib/ethereum_transaction_model.dart | 1 + .../lib/pending_ethereum_transaction.dart | 8 +- cw_polygon/.gitignore | 30 + cw_polygon/.metadata | 10 + cw_polygon/CHANGELOG.md | 3 + cw_polygon/LICENSE | 1 + cw_polygon/README.md | 39 ++ cw_polygon/analysis_options.yaml | 4 + cw_polygon/lib/cw_polygon.dart | 7 + cw_polygon/lib/default_erc20_tokens.dart | 86 +++ .../lib/pending_polygon_transaction.dart | 19 + cw_polygon/lib/polygon_client.dart | 34 ++ cw_polygon/lib/polygon_exceptions.dart | 6 + cw_polygon/lib/polygon_formatter.dart | 25 + .../lib/polygon_mnemonics_exception.dart | 5 + .../lib/polygon_transaction_credentials.dart | 18 + .../lib/polygon_transaction_history.dart | 77 +++ cw_polygon/lib/polygon_transaction_info.dart | 49 ++ cw_polygon/lib/polygon_transaction_model.dart | 49 ++ .../lib/polygon_transaction_priority.dart | 51 ++ cw_polygon/lib/polygon_wallet.dart | 540 ++++++++++++++++++ cw_polygon/lib/polygon_wallet_addresses.dart | 5 + .../polygon_wallet_creation_credentials.dart | 28 + cw_polygon/lib/polygon_wallet_service.dart | 123 ++++ cw_polygon/pubspec.yaml | 73 +++ cw_polygon/test/cw_polygon_test.dart | 12 + ios/Runner/InfoBase.plist | 20 + lib/core/address_validator.dart | 2 + lib/core/fiat_conversion_service.dart | 2 +- lib/core/seed_validator.dart | 3 + .../wallet_connect/evm_chain_service.dart | 28 +- .../wallet_connect_key_service.dart | 28 +- .../wallet_connect/web3wallet_service.dart | 10 +- lib/di.dart | 6 +- lib/entities/default_settings_migration.dart | 39 ++ lib/entities/ens_record.dart | 6 + lib/entities/main_actions.dart | 5 +- lib/entities/node_list.dart | 21 +- lib/entities/preferences_key.dart | 3 + lib/entities/priority_for_wallet_type.dart | 3 + lib/polygon/cw_polygon.dart | 156 +++++ lib/reactions/fiat_rate_update.dart | 14 +- lib/reactions/on_current_wallet_change.dart | 12 +- lib/reactions/wallet_connect.dart | 46 ++ .../desktop_wallet_selection_dropdown.dart | 3 + .../screens/dashboard/pages/balance_page.dart | 10 +- .../dashboard/widgets/menu_widget.dart | 7 +- .../receive/widgets/currency_input_field.dart | 12 +- lib/src/screens/root/root.dart | 8 +- lib/src/screens/seed/pre_seed_page.dart | 18 +- .../settings/connection_sync_page.dart | 5 +- lib/src/screens/settings/privacy_page.dart | 8 + .../widgets/connection_request_widget.dart | 26 +- .../screens/wallet_list/wallet_list_page.dart | 3 + lib/store/app_store.dart | 4 +- lib/store/settings_store.dart | 174 ++++-- .../dashboard/balance_view_model.dart | 8 +- .../dashboard/home_settings_view_model.dart | 63 +- lib/view_model/dashboard/nft_view_model.dart | 14 +- .../dashboard/transaction_list_item.dart | 8 + .../exchange/exchange_trade_view_model.dart | 20 +- .../exchange/exchange_view_model.dart | 10 + .../node_list/node_list_view_model.dart | 3 + .../restore/restore_from_qr_vm.dart | 7 + .../restore/wallet_restore_from_qr_code.dart | 12 +- lib/view_model/send/output.dart | 26 +- .../send/send_template_view_model.dart | 4 +- lib/view_model/send/send_view_model.dart | 17 +- .../settings/privacy_settings_view_model.dart | 15 +- .../transaction_details_view_model.dart | 27 +- .../wallet_address_list_view_model.dart | 27 + lib/view_model/wallet_keys_view_model.dart | 8 +- lib/view_model/wallet_new_vm.dart | 4 + lib/view_model/wallet_restore_view_model.dart | 19 +- macos/Podfile.lock | 7 +- model_generator.sh | 1 + pubspec_base.yaml | 1 + res/values/strings_ar.arb | 3 +- res/values/strings_bg.arb | 3 +- res/values/strings_cs.arb | 3 +- res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 3 +- res/values/strings_es.arb | 3 +- res/values/strings_fr.arb | 3 +- res/values/strings_ha.arb | 3 +- res/values/strings_hi.arb | 3 +- res/values/strings_hr.arb | 3 +- res/values/strings_id.arb | 3 +- res/values/strings_it.arb | 3 +- res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 3 +- res/values/strings_nl.arb | 3 +- res/values/strings_pl.arb | 3 +- res/values/strings_pt.arb | 3 +- res/values/strings_ru.arb | 3 +- res/values/strings_th.arb | 3 +- res/values/strings_tl.arb | 3 +- res/values/strings_tr.arb | 3 +- res/values/strings_uk.arb | 3 +- res/values/strings_ur.arb | 3 +- res/values/strings_yo.arb | 3 +- res/values/strings_zh.arb | 3 +- scripts/android/pubspec_gen.sh | 2 +- tool/configure.dart | 110 +++- tool/utils/secret_key.dart | 1 + 116 files changed, 2351 insertions(+), 206 deletions(-) create mode 100644 assets/polygon_node_list.yml create mode 100644 cw_polygon/.gitignore create mode 100644 cw_polygon/.metadata create mode 100644 cw_polygon/CHANGELOG.md create mode 100644 cw_polygon/LICENSE create mode 100644 cw_polygon/README.md create mode 100644 cw_polygon/analysis_options.yaml create mode 100644 cw_polygon/lib/cw_polygon.dart create mode 100644 cw_polygon/lib/default_erc20_tokens.dart create mode 100644 cw_polygon/lib/pending_polygon_transaction.dart create mode 100644 cw_polygon/lib/polygon_client.dart create mode 100644 cw_polygon/lib/polygon_exceptions.dart create mode 100644 cw_polygon/lib/polygon_formatter.dart create mode 100644 cw_polygon/lib/polygon_mnemonics_exception.dart create mode 100644 cw_polygon/lib/polygon_transaction_credentials.dart create mode 100644 cw_polygon/lib/polygon_transaction_history.dart create mode 100644 cw_polygon/lib/polygon_transaction_info.dart create mode 100644 cw_polygon/lib/polygon_transaction_model.dart create mode 100644 cw_polygon/lib/polygon_transaction_priority.dart create mode 100644 cw_polygon/lib/polygon_wallet.dart create mode 100644 cw_polygon/lib/polygon_wallet_addresses.dart create mode 100644 cw_polygon/lib/polygon_wallet_creation_credentials.dart create mode 100644 cw_polygon/lib/polygon_wallet_service.dart create mode 100644 cw_polygon/pubspec.yaml create mode 100644 cw_polygon/test/cw_polygon_test.dart create mode 100644 lib/polygon/cw_polygon.dart create mode 100644 lib/reactions/wallet_connect.dart diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 7b2b611d3..8fef4fdb6 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -97,6 +97,7 @@ jobs: cd cw_ethereum && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. + cd cw_polygon && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs - name: Add secrets @@ -131,6 +132,7 @@ jobs: echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_ethereum/lib/.secrets.g.dart + echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> cw_ethereum/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/.gitignore b/.gitignore index c735d4058..0a883dd18 100644 --- a/.gitignore +++ b/.gitignore @@ -126,6 +126,7 @@ lib/haven/haven.dart lib/ethereum/ethereum.dart lib/bitcoin_cash/bitcoin_cash.dart lib/nano/nano.dart +lib/polygon/polygon.dart ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_180.png ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_120.png diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index 910149f60..f32482e22 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -62,6 +62,9 @@ + + + (other is Erc20Token && other.contractAddress == contractAddress) || diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 484325f91..cc749f23a 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -88,6 +88,8 @@ class Node extends HiveObject with Keyable { } else { return Uri.http(uriRaw, ''); } + case WalletType.polygon: + return Uri.https(uriRaw, ''); default: throw Exception('Unexpected type ${type.toString()} for Node uri'); } @@ -146,6 +148,8 @@ class Node extends HiveObject with Keyable { case WalletType.nano: case WalletType.banano: return requestNanoNode(); + case WalletType.polygon: + return requestElectrumServer(); default: return false; } diff --git a/cw_core/lib/wallet_type.dart b/cw_core/lib/wallet_type.dart index debf92e11..20f0bdb19 100644 --- a/cw_core/lib/wallet_type.dart +++ b/cw_core/lib/wallet_type.dart @@ -13,6 +13,7 @@ const walletTypes = [ WalletType.bitcoinCash, WalletType.nano, WalletType.banano, + WalletType.polygon, ]; @HiveType(typeId: WALLET_TYPE_TYPE_ID) @@ -44,6 +45,8 @@ enum WalletType { @HiveField(8) bitcoinCash, + @HiveField(9) + polygon } int serializeToInt(WalletType type) { @@ -64,6 +67,8 @@ int serializeToInt(WalletType type) { return 6; case WalletType.bitcoinCash: return 7; + case WalletType.polygon: + return 8; default: return -1; } @@ -87,6 +92,8 @@ WalletType deserializeFromInt(int raw) { return WalletType.banano; case 7: return WalletType.bitcoinCash; + case 8: + return WalletType.polygon; default: throw Exception('Unexpected token: $raw for WalletType deserializeFromInt'); } @@ -110,6 +117,8 @@ String walletTypeToString(WalletType type) { return 'Nano'; case WalletType.banano: return 'Banano'; + case WalletType.polygon: + return 'Polygon'; default: return ''; } @@ -133,6 +142,8 @@ String walletTypeToDisplayName(WalletType type) { return 'Nano (XNO)'; case WalletType.banano: return 'Banano (BAN)'; + case WalletType.polygon: + return 'Polygon (MATIC)'; default: return ''; } @@ -156,7 +167,10 @@ CryptoCurrency walletTypeToCryptoCurrency(WalletType type) { return CryptoCurrency.nano; case WalletType.banano: return CryptoCurrency.banano; + case WalletType.polygon: + return CryptoCurrency.maticpoly; default: - throw Exception('Unexpected wallet type: ${type.toString()} for CryptoCurrency walletTypeToCryptoCurrency'); + throw Exception( + 'Unexpected wallet type: ${type.toString()} for CryptoCurrency walletTypeToCryptoCurrency'); } } diff --git a/cw_ethereum/lib/ethereum_client.dart b/cw_ethereum/lib/ethereum_client.dart index f0c7381e8..5e408bb9e 100644 --- a/cw_ethereum/lib/ethereum_client.dart +++ b/cw_ethereum/lib/ethereum_client.dart @@ -15,12 +15,12 @@ import 'package:cw_ethereum/ethereum_transaction_priority.dart'; import 'package:cw_ethereum/.secrets.g.dart' as secrets; class EthereumClient { - final _httpClient = Client(); + final httpClient = Client(); Web3Client? _client; bool connect(Node node) { try { - _client = Web3Client(node.uri.toString(), _httpClient); + _client = Web3Client(node.uri.toString(), httpClient); return true; } catch (e) { @@ -74,9 +74,11 @@ class EthereumClient { required int exponent, String? contractAddress, }) async { - assert(currency == CryptoCurrency.eth || contractAddress != null); + assert(currency == CryptoCurrency.eth || + currency == CryptoCurrency.maticpoly || + contractAddress != null); - bool _isEthereum = currency == CryptoCurrency.eth; + bool _isEVMCompatibleChain = currency == CryptoCurrency.eth || currency == CryptoCurrency.maticpoly; final price = _client!.getGasPrice(); @@ -84,19 +86,23 @@ class EthereumClient { from: privateKey.address, to: EthereumAddress.fromHex(toAddress), maxPriorityFeePerGas: EtherAmount.fromInt(EtherUnit.gwei, priority.tip), - value: _isEthereum ? EtherAmount.inWei(BigInt.parse(amount)) : EtherAmount.zero(), + value: _isEVMCompatibleChain ? EtherAmount.inWei(BigInt.parse(amount)) : EtherAmount.zero(), ); - final signedTransaction = await _client!.signTransaction(privateKey, transaction); + final chainId = _getChainIdForCurrency(currency); + + final signedTransaction = + await _client!.signTransaction(privateKey, transaction, chainId: chainId); final Function _sendTransaction; - if (_isEthereum) { + if (_isEVMCompatibleChain) { _sendTransaction = () async => await sendTransaction(signedTransaction); } else { final erc20 = ERC20( client: _client!, address: EthereumAddress.fromHex(contractAddress!), + chainId: chainId, ); _sendTransaction = () async { @@ -118,6 +124,16 @@ class EthereumClient { ); } + int _getChainIdForCurrency(CryptoCurrency currency) { + switch (currency) { + case CryptoCurrency.maticpoly: + return 137; + case CryptoCurrency.eth: + default: + return 1; + } + } + Future sendTransaction(Uint8List signedTransaction) async => await _client!.sendRawTransaction(prependTransactionType(0x02, signedTransaction)); @@ -198,7 +214,7 @@ I/flutter ( 4474): Gas Used: 53000 Future> fetchTransactions(String address, {String? contractAddress}) async { try { - final response = await _httpClient.get(Uri.https("api.etherscan.io", "/api", { + final response = await httpClient.get(Uri.https("api.etherscan.io", "/api", { "module": "account", "action": contractAddress != null ? "tokentx" : "txlist", if (contractAddress != null) "contractaddress": contractAddress, diff --git a/cw_ethereum/lib/ethereum_transaction_info.dart b/cw_ethereum/lib/ethereum_transaction_info.dart index a0649ba25..f0deae931 100644 --- a/cw_ethereum/lib/ethereum_transaction_info.dart +++ b/cw_ethereum/lib/ethereum_transaction_info.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:cw_core/format_amount.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_info.dart'; @@ -34,8 +36,10 @@ class EthereumTransactionInfo extends TransactionInfo { final String? to; @override - String amountFormatted() => - '${formatAmount((ethAmount / BigInt.from(10).pow(exponent)).toString())} $tokenSymbol'; + String amountFormatted() { + final amount = formatAmount((ethAmount / BigInt.from(10).pow(exponent)).toString()); + return '${amount.substring(0, min(10, amount.length))} $tokenSymbol'; + } @override String fiatAmount() => _fiatAmount ?? ''; @@ -44,7 +48,10 @@ class EthereumTransactionInfo extends TransactionInfo { void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount); @override - String feeFormatted() => '${(ethFee / BigInt.from(10).pow(18)).toString()} ETH'; + String feeFormatted() { + final amount = (ethFee / BigInt.from(10).pow(18)).toString(); + return '${amount.substring(0, min(10, amount.length))} ETH'; + } factory EthereumTransactionInfo.fromJson(Map data) { return EthereumTransactionInfo( diff --git a/cw_ethereum/lib/ethereum_transaction_model.dart b/cw_ethereum/lib/ethereum_transaction_model.dart index c1260795a..3b5f724fc 100644 --- a/cw_ethereum/lib/ethereum_transaction_model.dart +++ b/cw_ethereum/lib/ethereum_transaction_model.dart @@ -1,3 +1,4 @@ +//! Model used for in parsing transactions fetched using etherscan class EthereumTransactionModel { final DateTime date; final String hash; diff --git a/cw_ethereum/lib/pending_ethereum_transaction.dart b/cw_ethereum/lib/pending_ethereum_transaction.dart index 35b0123cc..d47630fd6 100644 --- a/cw_ethereum/lib/pending_ethereum_transaction.dart +++ b/cw_ethereum/lib/pending_ethereum_transaction.dart @@ -21,8 +21,8 @@ class PendingEthereumTransaction with PendingTransaction { @override String get amountFormatted { - final _amount = BigInt.parse(amount) / BigInt.from(pow(10, exponent)); - return _amount.toStringAsFixed(min(15, _amount.toString().length)); + final _amount = (BigInt.parse(amount) / BigInt.from(pow(10, exponent))).toString(); + return _amount.substring(0, min(10, _amount.length)); } @override @@ -30,8 +30,8 @@ class PendingEthereumTransaction with PendingTransaction { @override String get feeFormatted { - final _fee = fee / BigInt.from(pow(10, 18)); - return _fee.toStringAsFixed(min(15, _fee.toString().length)); + final _fee = (fee / BigInt.from(pow(10, 18))).toString(); + return _fee.substring(0, min(10, _fee.length)); } @override diff --git a/cw_polygon/.gitignore b/cw_polygon/.gitignore new file mode 100644 index 000000000..96486fd93 --- /dev/null +++ b/cw_polygon/.gitignore @@ -0,0 +1,30 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/cw_polygon/.metadata b/cw_polygon/.metadata new file mode 100644 index 000000000..fa347fc6a --- /dev/null +++ b/cw_polygon/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + channel: stable + +project_type: package diff --git a/cw_polygon/CHANGELOG.md b/cw_polygon/CHANGELOG.md new file mode 100644 index 000000000..41cc7d819 --- /dev/null +++ b/cw_polygon/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/cw_polygon/LICENSE b/cw_polygon/LICENSE new file mode 100644 index 000000000..ba75c69f7 --- /dev/null +++ b/cw_polygon/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/cw_polygon/README.md b/cw_polygon/README.md new file mode 100644 index 000000000..02fe8ecab --- /dev/null +++ b/cw_polygon/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/cw_polygon/analysis_options.yaml b/cw_polygon/analysis_options.yaml new file mode 100644 index 000000000..a5744c1cf --- /dev/null +++ b/cw_polygon/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/cw_polygon/lib/cw_polygon.dart b/cw_polygon/lib/cw_polygon.dart new file mode 100644 index 000000000..5d4e447d1 --- /dev/null +++ b/cw_polygon/lib/cw_polygon.dart @@ -0,0 +1,7 @@ +library cw_polygon; + +/// A Calculator. +class Calculator { + /// Returns [value] plus 1. + int addOne(int value) => value + 1; +} diff --git a/cw_polygon/lib/default_erc20_tokens.dart b/cw_polygon/lib/default_erc20_tokens.dart new file mode 100644 index 000000000..132c52e4c --- /dev/null +++ b/cw_polygon/lib/default_erc20_tokens.dart @@ -0,0 +1,86 @@ +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/erc20_token.dart'; + +class DefaultPolygonErc20Tokens { + final List _defaultTokens = [ + Erc20Token( + name: "Wrapped Ether", + symbol: "WETH", + contractAddress: "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", + decimal: 18, + enabled: false, + ), + Erc20Token( + name: "Tether USD (PoS)", + symbol: "USDT", + contractAddress: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", + decimal: 6, + enabled: true, + ), + Erc20Token( + name: "USD Coin", + symbol: "USDC", + contractAddress: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", + decimal: 6, + enabled: true, + ), + Erc20Token( + name: "USD Coin (POS)", + symbol: "USDC.e", + contractAddress: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", + decimal: 6, + enabled: false, + ), + Erc20Token( + name: "Avalanche Token", + symbol: "AVAX", + contractAddress: "0x2C89bbc92BD86F8075d1DEcc58C7F4E0107f286b", + decimal: 18, + enabled: false, + ), + Erc20Token( + name: "Wrapped BTC (PoS)", + symbol: "WBTC", + contractAddress: "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6", + decimal: 8, + enabled: false, + ), + Erc20Token( + name: "Dai (PoS)", + symbol: "DAI", + contractAddress: "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", + decimal: 18, + enabled: true, + ), + Erc20Token( + name: "SHIBA INU (PoS)", + symbol: "SHIB", + contractAddress: "0x6f8a06447Ff6FcF75d803135a7de15CE88C1d4ec", + decimal: 18, + enabled: false, + ), + Erc20Token( + name: "Uniswap (PoS)", + symbol: "UNI", + contractAddress: "0xb33EaAd8d922B1083446DC23f610c2567fB5180f", + decimal: 18, + enabled: false, + ), + ]; + + List get initialPolygonErc20Tokens => _defaultTokens.map((token) { + String? iconPath; + try { + iconPath = CryptoCurrency.all + .firstWhere((element) => + element.title.toUpperCase() == token.symbol.toUpperCase()) + .iconPath; + } catch (_) {} + + if (iconPath != null) { + return Erc20Token.copyWith(token, iconPath); + } + + return token; + }).toList(); +} diff --git a/cw_polygon/lib/pending_polygon_transaction.dart b/cw_polygon/lib/pending_polygon_transaction.dart new file mode 100644 index 000000000..50f1f0638 --- /dev/null +++ b/cw_polygon/lib/pending_polygon_transaction.dart @@ -0,0 +1,19 @@ +import 'dart:typed_data'; + +import 'package:cw_ethereum/pending_ethereum_transaction.dart'; + +class PendingPolygonTransaction extends PendingEthereumTransaction { + PendingPolygonTransaction({ + required Function sendTransaction, + required Uint8List signedTransaction, + required BigInt fee, + required String amount, + required int exponent, + }) : super( + amount: amount, + sendTransaction: sendTransaction, + signedTransaction: signedTransaction, + fee: fee, + exponent: exponent, + ); +} diff --git a/cw_polygon/lib/polygon_client.dart b/cw_polygon/lib/polygon_client.dart new file mode 100644 index 000000000..86c2253af --- /dev/null +++ b/cw_polygon/lib/polygon_client.dart @@ -0,0 +1,34 @@ +import 'dart:convert'; + +import 'package:cw_ethereum/ethereum_client.dart'; +import 'package:cw_polygon/polygon_transaction_model.dart'; +import 'package:cw_ethereum/.secrets.g.dart' as secrets; + +class PolygonClient extends EthereumClient { + @override + Future> fetchTransactions(String address, + {String? contractAddress}) async { + try { + final response = await httpClient.get(Uri.https("api.polygonscan.com", "/api", { + "module": "account", + "action": contractAddress != null ? "tokentx" : "txlist", + if (contractAddress != null) "contractaddress": contractAddress, + "address": address, + "apikey": secrets.polygonScanApiKey, + })); + + final jsonResponse = json.decode(response.body) as Map; + + if (response.statusCode >= 200 && response.statusCode < 300 && jsonResponse['status'] != 0) { + return (jsonResponse['result'] as List) + .map((e) => PolygonTransactionModel.fromJson(e as Map)) + .toList(); + } + + return []; + } catch (e) { + print(e); + return []; + } + } +} diff --git a/cw_polygon/lib/polygon_exceptions.dart b/cw_polygon/lib/polygon_exceptions.dart new file mode 100644 index 000000000..2d08106b6 --- /dev/null +++ b/cw_polygon/lib/polygon_exceptions.dart @@ -0,0 +1,6 @@ +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_ethereum/ethereum_exceptions.dart'; + +class PolygonTransactionCreationException extends EthereumTransactionCreationException { + PolygonTransactionCreationException(CryptoCurrency currency) : super(currency); +} diff --git a/cw_polygon/lib/polygon_formatter.dart b/cw_polygon/lib/polygon_formatter.dart new file mode 100644 index 000000000..f016db7ab --- /dev/null +++ b/cw_polygon/lib/polygon_formatter.dart @@ -0,0 +1,25 @@ +import 'package:intl/intl.dart'; + +const polygonAmountLength = 12; +const polygonAmountDivider = 1000000000000; +final polygonAmountFormat = NumberFormat() + ..maximumFractionDigits = polygonAmountLength + ..minimumFractionDigits = 1; + +class PolygonFormatter { + static int parsePolygonAmount(String amount) { + try { + return (double.parse(amount) * polygonAmountDivider).round(); + } catch (_) { + return 0; + } + } + + static double parsePolygonAmountToDouble(int amount) { + try { + return amount / polygonAmountDivider; + } catch (_) { + return 0; + } + } +} diff --git a/cw_polygon/lib/polygon_mnemonics_exception.dart b/cw_polygon/lib/polygon_mnemonics_exception.dart new file mode 100644 index 000000000..c1a2fcc84 --- /dev/null +++ b/cw_polygon/lib/polygon_mnemonics_exception.dart @@ -0,0 +1,5 @@ +class PolygonMnemonicIsIncorrectException implements Exception { + @override + String toString() => + 'Polygon mnemonic has incorrect format. Mnemonic should contain 12 or 24 words separated by space.'; +} diff --git a/cw_polygon/lib/polygon_transaction_credentials.dart b/cw_polygon/lib/polygon_transaction_credentials.dart new file mode 100644 index 000000000..6611e15da --- /dev/null +++ b/cw_polygon/lib/polygon_transaction_credentials.dart @@ -0,0 +1,18 @@ +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/output_info.dart'; +import 'package:cw_ethereum/ethereum_transaction_credentials.dart'; +import 'package:cw_polygon/polygon_transaction_priority.dart'; + +class PolygonTransactionCredentials extends EthereumTransactionCredentials { + PolygonTransactionCredentials( + List outputs, { + required PolygonTransactionPriority? priority, + required CryptoCurrency currency, + final int? feeRate, + }) : super( + outputs, + currency: currency, + priority: priority, + feeRate: feeRate, + ); +} diff --git a/cw_polygon/lib/polygon_transaction_history.dart b/cw_polygon/lib/polygon_transaction_history.dart new file mode 100644 index 000000000..a06b8be4a --- /dev/null +++ b/cw_polygon/lib/polygon_transaction_history.dart @@ -0,0 +1,77 @@ +import 'dart:convert'; +import 'dart:core'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_ethereum/file.dart'; +import 'package:cw_polygon/polygon_transaction_info.dart'; +import 'package:mobx/mobx.dart'; +import 'package:cw_core/transaction_history.dart'; + +part 'polygon_transaction_history.g.dart'; + +const transactionsHistoryFileName = 'polygon_transactions.json'; + +class PolygonTransactionHistory = PolygonTransactionHistoryBase with _$PolygonTransactionHistory; + +abstract class PolygonTransactionHistoryBase extends TransactionHistoryBase + with Store { + PolygonTransactionHistoryBase({required this.walletInfo, required String password}) + : _password = password { + transactions = ObservableMap(); + } + + final WalletInfo walletInfo; + String _password; + + Future init() async => await _load(); + + @override + Future save() async { + try { + final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type); + final path = '$dirPath/$transactionsHistoryFileName'; + final data = json.encode({'transactions': transactions}); + await writeData(path: path, password: _password, data: data); + } catch (e, s) { + print('Error while saving polygon transaction history: ${e.toString()}'); + print(s); + } + } + + @override + void addOne(PolygonTransactionInfo transaction) => transactions[transaction.id] = transaction; + + @override + void addMany(Map transactions) => + this.transactions.addAll(transactions); + + Future> _read() async { + final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type); + final path = '$dirPath/$transactionsHistoryFileName'; + final content = await read(path: path, password: _password); + if (content.isEmpty) { + return {}; + } + return json.decode(content) as Map; + } + + Future _load() async { + try { + final content = await _read(); + final txs = content['transactions'] as Map? ?? {}; + + txs.entries.forEach((entry) { + final val = entry.value; + + if (val is Map) { + final tx = PolygonTransactionInfo.fromJson(val); + _update(tx); + } + }); + } catch (e) { + print(e); + } + } + + void _update(PolygonTransactionInfo transaction) => transactions[transaction.id] = transaction; +} diff --git a/cw_polygon/lib/polygon_transaction_info.dart b/cw_polygon/lib/polygon_transaction_info.dart new file mode 100644 index 000000000..f1976a601 --- /dev/null +++ b/cw_polygon/lib/polygon_transaction_info.dart @@ -0,0 +1,49 @@ +import 'package:cw_core/transaction_direction.dart'; +import 'package:cw_ethereum/ethereum_transaction_info.dart'; + +class PolygonTransactionInfo extends EthereumTransactionInfo { + PolygonTransactionInfo({ + required String id, + required int height, + required BigInt ethAmount, + int exponent = 18, + required TransactionDirection direction, + required DateTime date, + required bool isPending, + required BigInt ethFee, + required int confirmations, + String tokenSymbol = "MATIC", + required String? to, + }) : super( + confirmations: confirmations, + id: id, + height: height, + ethAmount: ethAmount, + exponent: exponent, + direction: direction, + date: date, + isPending: isPending, + ethFee: ethFee, + to: to, + tokenSymbol: tokenSymbol, + ); + + factory PolygonTransactionInfo.fromJson(Map data) { + return PolygonTransactionInfo( + id: data['id'] as String, + height: data['height'] as int, + ethAmount: BigInt.parse(data['amount']), + exponent: data['exponent'] as int, + ethFee: BigInt.parse(data['fee']), + direction: parseTransactionDirectionFromInt(data['direction'] as int), + date: DateTime.fromMillisecondsSinceEpoch(data['date'] as int), + isPending: data['isPending'] as bool, + confirmations: data['confirmations'] as int, + tokenSymbol: data['tokenSymbol'] as String, + to: data['to'], + ); + } + + @override + String feeFormatted() => '${(ethFee / BigInt.from(10).pow(18)).toString()} MATIC'; +} diff --git a/cw_polygon/lib/polygon_transaction_model.dart b/cw_polygon/lib/polygon_transaction_model.dart new file mode 100644 index 000000000..704d674e5 --- /dev/null +++ b/cw_polygon/lib/polygon_transaction_model.dart @@ -0,0 +1,49 @@ +import 'package:cw_ethereum/ethereum_transaction_model.dart'; + +class PolygonTransactionModel extends EthereumTransactionModel { + PolygonTransactionModel({ + required DateTime date, + required String hash, + required String from, + required String to, + required BigInt amount, + required int gasUsed, + required BigInt gasPrice, + required String contractAddress, + required int confirmations, + required int blockNumber, + required String? tokenSymbol, + required int? tokenDecimal, + required bool isError, + }) : super( + amount: amount, + date: date, + hash: hash, + from: from, + to: to, + gasPrice: gasPrice, + gasUsed: gasUsed, + confirmations: confirmations, + contractAddress: contractAddress, + blockNumber: blockNumber, + tokenDecimal: tokenDecimal, + tokenSymbol: tokenSymbol, + isError: isError, + ); + + factory PolygonTransactionModel.fromJson(Map json) => PolygonTransactionModel( + date: DateTime.fromMillisecondsSinceEpoch(int.parse(json["timeStamp"]) * 1000), + hash: json["hash"], + from: json["from"], + to: json["to"], + amount: BigInt.parse(json["value"]), + gasUsed: int.parse(json["gasUsed"]), + gasPrice: BigInt.parse(json["gasPrice"]), + contractAddress: json["contractAddress"], + confirmations: int.parse(json["confirmations"]), + blockNumber: int.parse(json["blockNumber"]), + tokenSymbol: json["tokenSymbol"] ?? "MATIC", + tokenDecimal: int.tryParse(json["tokenDecimal"] ?? ""), + isError: json["isError"] == "1", + ); +} diff --git a/cw_polygon/lib/polygon_transaction_priority.dart b/cw_polygon/lib/polygon_transaction_priority.dart new file mode 100644 index 000000000..dba1dab55 --- /dev/null +++ b/cw_polygon/lib/polygon_transaction_priority.dart @@ -0,0 +1,51 @@ +import 'package:cw_ethereum/ethereum_transaction_priority.dart'; + +class PolygonTransactionPriority extends EthereumTransactionPriority { + const PolygonTransactionPriority({required String title, required int raw, required int tip}) + : super(title: title, raw: raw, tip: tip); + + static const List all = [fast, medium, slow]; + static const PolygonTransactionPriority slow = + PolygonTransactionPriority(title: 'slow', raw: 0, tip: 1); + static const PolygonTransactionPriority medium = + PolygonTransactionPriority(title: 'Medium', raw: 1, tip: 2); + static const PolygonTransactionPriority fast = + PolygonTransactionPriority(title: 'Fast', raw: 2, tip: 4); + + static PolygonTransactionPriority deserialize({required int raw}) { + switch (raw) { + case 0: + return slow; + case 1: + return medium; + case 2: + return fast; + default: + throw Exception('Unexpected token: $raw for PolygonTransactionPriority deserialize'); + } + } + + @override + String get units => 'gas'; + + @override + String toString() { + var label = ''; + + switch (this) { + case PolygonTransactionPriority.slow: + label = 'Slow'; + break; + case PolygonTransactionPriority.medium: + label = 'Medium'; + break; + case PolygonTransactionPriority.fast: + label = 'Fast'; + break; + default: + break; + } + + return label; + } +} diff --git a/cw_polygon/lib/polygon_wallet.dart b/cw_polygon/lib/polygon_wallet.dart new file mode 100644 index 000000000..66e6797c6 --- /dev/null +++ b/cw_polygon/lib/polygon_wallet.dart @@ -0,0 +1,540 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:math'; + +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/cake_hive.dart'; +import 'package:cw_core/node.dart'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/pending_transaction.dart'; +import 'package:cw_core/sync_status.dart'; +import 'package:cw_core/transaction_direction.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/wallet_addresses.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_ethereum/erc20_balance.dart'; +import 'package:cw_ethereum/ethereum_formatter.dart'; +import 'package:cw_ethereum/ethereum_transaction_model.dart'; +import 'package:cw_ethereum/file.dart'; +import 'package:cw_core/erc20_token.dart'; +import 'package:cw_polygon/default_erc20_tokens.dart'; +import 'package:cw_polygon/polygon_client.dart'; +import 'package:cw_polygon/polygon_exceptions.dart'; +import 'package:cw_polygon/polygon_formatter.dart'; +import 'package:cw_polygon/polygon_transaction_credentials.dart'; +import 'package:cw_polygon/polygon_transaction_history.dart'; +import 'package:cw_polygon/polygon_transaction_info.dart'; +import 'package:cw_polygon/polygon_transaction_model.dart'; +import 'package:cw_polygon/polygon_transaction_priority.dart'; +import 'package:cw_polygon/polygon_wallet_addresses.dart'; +import 'package:hive/hive.dart'; +import 'package:hex/hex.dart'; +import 'package:mobx/mobx.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:web3dart/crypto.dart'; +import 'package:web3dart/web3dart.dart'; +import 'package:bip39/bip39.dart' as bip39; +import 'package:bip32/bip32.dart' as bip32; + +part 'polygon_wallet.g.dart'; + +class PolygonWallet = PolygonWalletBase with _$PolygonWallet; + +abstract class PolygonWalletBase extends WalletBase with Store { + PolygonWalletBase({ + required WalletInfo walletInfo, + String? mnemonic, + String? privateKey, + required String password, + ERC20Balance? initialBalance, + }) : syncStatus = NotConnectedSyncStatus(), + _password = password, + _mnemonic = mnemonic, + _hexPrivateKey = privateKey, + _isTransactionUpdating = false, + _client = PolygonClient(), + walletAddresses = PolygonWalletAddresses(walletInfo), + balance = ObservableMap.of({ + CryptoCurrency.maticpoly: initialBalance ?? ERC20Balance(BigInt.zero) + }), + super(walletInfo) { + this.walletInfo = walletInfo; + transactionHistory = + PolygonTransactionHistory(walletInfo: walletInfo, password: password); + + if (!CakeHive.isAdapterRegistered(Erc20Token.typeId)) { + CakeHive.registerAdapter(Erc20TokenAdapter()); + } + + _sharedPrefs.complete(SharedPreferences.getInstance()); + } + + final String? _mnemonic; + final String? _hexPrivateKey; + final String _password; + + late final Box polygonErc20TokensBox; + + late final EthPrivateKey _polygonPrivateKey; + + EthPrivateKey get polygonPrivateKey => _polygonPrivateKey; + + late PolygonClient _client; + + int? _gasPrice; + int? _estimatedGas; + bool _isTransactionUpdating; + + // TODO: remove after integrating our own node and having eth_newPendingTransactionFilter + Timer? _transactionsUpdateTimer; + + @override + WalletAddresses walletAddresses; + + @override + @observable + SyncStatus syncStatus; + + @override + @observable + late ObservableMap balance; + + Completer _sharedPrefs = Completer(); + + Future init() async { + polygonErc20TokensBox = + await CakeHive.openBox(Erc20Token.polygonBoxName); + await walletAddresses.init(); + await transactionHistory.init(); + _polygonPrivateKey = await getPrivateKey( + mnemonic: _mnemonic, + privateKey: _hexPrivateKey, + password: _password, + ); + walletAddresses.address = _polygonPrivateKey.address.toString(); + await save(); + } + + @override + int calculateEstimatedFee(TransactionPriority priority, int? amount) { + try { + if (priority is PolygonTransactionPriority) { + final priorityFee = + EtherAmount.fromInt(EtherUnit.gwei, priority.tip).getInWei.toInt(); + return (_gasPrice! + priorityFee) * (_estimatedGas ?? 0); + } + + return 0; + } catch (e) { + return 0; + } + } + + @override + Future changePassword(String password) { + throw UnimplementedError("changePassword"); + } + + @override + void close() { + _client.stop(); + _transactionsUpdateTimer?.cancel(); + } + + @action + @override + Future connectToNode({required Node node}) async { + try { + syncStatus = ConnectingSyncStatus(); + + final isConnected = _client.connect(node); + + if (!isConnected) { + throw Exception("Polygon Node connection failed"); + } + + _client.setListeners(_polygonPrivateKey.address, _onNewTransaction); + + _setTransactionUpdateTimer(); + + syncStatus = ConnectedSyncStatus(); + } catch (e) { + syncStatus = FailedSyncStatus(); + } + } + + @override + Future createTransaction(Object credentials) async { + final _credentials = credentials as PolygonTransactionCredentials; + final outputs = _credentials.outputs; + final hasMultiDestination = outputs.length > 1; + + final CryptoCurrency transactionCurrency = balance.keys + .firstWhere((element) => element.title == _credentials.currency.title); + + final _erc20Balance = balance[transactionCurrency]!; + BigInt totalAmount = BigInt.zero; + int exponent = + transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18; + num amountToPolygonMultiplier = pow(10, exponent); + + // so far this can not be made with Polygon as Polygon does not support multiple recipients + if (hasMultiDestination) { + if (outputs.any( + (item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) { + throw PolygonTransactionCreationException(transactionCurrency); + } + + final totalOriginalAmount = PolygonFormatter.parsePolygonAmountToDouble( + outputs.fold( + 0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0))); + totalAmount = + BigInt.from(totalOriginalAmount * amountToPolygonMultiplier); + + if (_erc20Balance.balance < totalAmount) { + throw PolygonTransactionCreationException(transactionCurrency); + } + } else { + final output = outputs.first; + // since the fees are taken from Ethereum + // then no need to subtract the fees from the amount if send all + final BigInt allAmount; + if (transactionCurrency is Erc20Token) { + allAmount = _erc20Balance.balance; + } else { + allAmount = _erc20Balance.balance - + BigInt.from(calculateEstimatedFee(_credentials.priority!, null)); + } + final totalOriginalAmount = EthereumFormatter.parseEthereumAmountToDouble( + output.formattedCryptoAmount ?? 0); + totalAmount = output.sendAll + ? allAmount + : BigInt.from(totalOriginalAmount * amountToPolygonMultiplier); + + if (_erc20Balance.balance < totalAmount) { + throw PolygonTransactionCreationException(transactionCurrency); + } + } + + final pendingPolygonTransaction = await _client.signTransaction( + privateKey: _polygonPrivateKey, + toAddress: _credentials.outputs.first.isParsedAddress + ? _credentials.outputs.first.extractedAddress! + : _credentials.outputs.first.address, + amount: totalAmount.toString(), + gas: _estimatedGas!, + priority: _credentials.priority!, + currency: transactionCurrency, + exponent: exponent, + contractAddress: transactionCurrency is Erc20Token + ? transactionCurrency.contractAddress + : null, + ); + + return pendingPolygonTransaction; + } + + Future _updateTransactions() async { + try { + if (_isTransactionUpdating) { + return; + } + bool isPolygonScanEnabled = (await _sharedPrefs.future).getBool("use_polygonscan") ?? true; + if (!isPolygonScanEnabled) { + return; + } + + _isTransactionUpdating = true; + final transactions = await fetchTransactions(); + transactionHistory.addMany(transactions); + await transactionHistory.save(); + _isTransactionUpdating = false; + } catch (_) { + _isTransactionUpdating = false; + } + } + + @override + Future> fetchTransactions() async { + final address = _polygonPrivateKey.address.hex; + final transactions = await _client.fetchTransactions(address); + + final List>> polygonErc20TokensTransactions = + []; + + for (var token in balance.keys) { + if (token is Erc20Token) { + polygonErc20TokensTransactions.add(_client.fetchTransactions( + address, + contractAddress: token.contractAddress, + ) as Future>); + } + } + + final tokensTransaction = await Future.wait(polygonErc20TokensTransactions); + transactions.addAll(tokensTransaction.expand((element) => element)); + + final Map result = {}; + + for (var transactionModel in transactions) { + if (transactionModel.isError) { + continue; + } + + result[transactionModel.hash] = PolygonTransactionInfo( + id: transactionModel.hash, + height: transactionModel.blockNumber, + ethAmount: transactionModel.amount, + direction: transactionModel.from == address + ? TransactionDirection.outgoing + : TransactionDirection.incoming, + isPending: false, + date: transactionModel.date, + confirmations: transactionModel.confirmations, + ethFee: + BigInt.from(transactionModel.gasUsed) * transactionModel.gasPrice, + exponent: transactionModel.tokenDecimal ?? 18, + tokenSymbol: transactionModel.tokenSymbol ?? "MATIC", + to: transactionModel.to, + ); + } + + return result; + } + + @override + Object get keys => throw UnimplementedError("keys"); + + @override + Future rescan({required int height}) { + throw UnimplementedError("rescan"); + } + + @override + Future save() async { + await walletAddresses.updateAddressesInBox(); + final path = await makePath(); + await write(path: path, password: _password, data: toJSON()); + await transactionHistory.save(); + } + + @override + String? get seed => _mnemonic; + + @override + String get privateKey => HEX.encode(_polygonPrivateKey.privateKey); + + @action + @override + Future startSync() async { + try { + syncStatus = AttemptingSyncStatus(); + await _updateBalance(); + await _updateTransactions(); + _gasPrice = await _client.getGasUnitPrice(); + _estimatedGas = await _client.getEstimatedGas(); + + Timer.periodic(const Duration(minutes: 1), + (timer) async => _gasPrice = await _client.getGasUnitPrice()); + Timer.periodic(const Duration(seconds: 10), + (timer) async => _estimatedGas = await _client.getEstimatedGas()); + + syncStatus = SyncedSyncStatus(); + } catch (e) { + syncStatus = FailedSyncStatus(); + } + } + + Future makePath() async => + pathForWallet(name: walletInfo.name, type: walletInfo.type); + + String toJSON() => json.encode({ + 'mnemonic': _mnemonic, + 'private_key': privateKey, + 'balance': balance[currency]!.toJSON(), + }); + + static Future open({ + required String name, + required String password, + required WalletInfo walletInfo, + }) async { + final path = await pathForWallet(name: name, type: walletInfo.type); + final jsonSource = await read(path: path, password: password); + final data = json.decode(jsonSource) as Map; + final mnemonic = data['mnemonic'] as String?; + final privateKey = data['private_key'] as String?; + final balance = ERC20Balance.fromJSON(data['balance'] as String) ?? + ERC20Balance(BigInt.zero); + + return PolygonWallet( + walletInfo: walletInfo, + password: password, + mnemonic: mnemonic, + privateKey: privateKey, + initialBalance: balance, + ); + } + + Future _updateBalance() async { + balance[currency] = await _fetchMaticBalance(); + + await _fetchErc20Balances(); + await save(); + } + + Future _fetchMaticBalance() async { + final balance = await _client.getBalance(_polygonPrivateKey.address); + return ERC20Balance(balance.getInWei); + } + + Future _fetchErc20Balances() async { + for (var token in polygonErc20TokensBox.values) { + try { + if (token.enabled) { + balance[token] = await _client.fetchERC20Balances( + _polygonPrivateKey.address, + token.contractAddress, + ); + } else { + balance.remove(token); + } + } catch (_) {} + } + } + + Future getPrivateKey( + {String? mnemonic, String? privateKey, required String password}) async { + assert(mnemonic != null || privateKey != null); + + if (privateKey != null) { + return EthPrivateKey.fromHex(privateKey); + } + + final seed = bip39.mnemonicToSeed(mnemonic!); + + final root = bip32.BIP32.fromSeed(seed); + + const _hdPathPolygon = "m/44'/60'/0'/0"; + const index = 0; + final addressAtIndex = root.derivePath("$_hdPathPolygon/$index"); + + return EthPrivateKey.fromHex( + HEX.encode(addressAtIndex.privateKey as List)); + } + + Future? updateBalance() async => await _updateBalance(); + + List get erc20Currencies => polygonErc20TokensBox.values.toList(); + + Future addErc20Token(Erc20Token token) async { + String? iconPath; + try { + iconPath = CryptoCurrency.all + .firstWhere((element) => + element.title.toUpperCase() == token.symbol.toUpperCase()) + .iconPath; + } catch (_) {} + + final _token = Erc20Token( + name: token.name, + symbol: token.symbol, + contractAddress: token.contractAddress, + decimal: token.decimal, + enabled: token.enabled, + iconPath: iconPath, + ); + + await polygonErc20TokensBox.put(_token.contractAddress, _token); + + if (_token.enabled) { + balance[_token] = await _client.fetchERC20Balances( + _polygonPrivateKey.address, + _token.contractAddress, + ); + } else { + balance.remove(_token); + } + } + + Future deleteErc20Token(Erc20Token token) async { + await token.delete(); + + balance.remove(token); + _updateBalance(); + } + + Future getErc20Token(String contractAddress) async => + await _client.getErc20Token(contractAddress); + + void _onNewTransaction() { + _updateBalance(); + _updateTransactions(); + } + + void addInitialTokens() { + final initialErc20Tokens = + DefaultPolygonErc20Tokens().initialPolygonErc20Tokens; + + for (var token in initialErc20Tokens) { + polygonErc20TokensBox.put(token.contractAddress, token); + } + } + + @override + Future renameWalletFiles(String newWalletName) async { + final currentWalletPath = + await pathForWallet(name: walletInfo.name, type: type); + final currentWalletFile = File(currentWalletPath); + + final currentDirPath = + await pathForWalletDir(name: walletInfo.name, type: type); + final currentTransactionsFile = + File('$currentDirPath/$transactionsHistoryFileName'); + + // Copies current wallet files into new wallet name's dir and files + if (currentWalletFile.existsSync()) { + final newWalletPath = + await pathForWallet(name: newWalletName, type: type); + await currentWalletFile.copy(newWalletPath); + } + if (currentTransactionsFile.existsSync()) { + final newDirPath = + await pathForWalletDir(name: newWalletName, type: type); + await currentTransactionsFile + .copy('$newDirPath/$transactionsHistoryFileName'); + } + + // Delete old name's dir and files + await Directory(currentDirPath).delete(recursive: true); + } + + void _setTransactionUpdateTimer() { + if (_transactionsUpdateTimer?.isActive ?? false) { + _transactionsUpdateTimer!.cancel(); + } + + _transactionsUpdateTimer = Timer.periodic(Duration(seconds: 10), (_) { + _updateTransactions(); + _updateBalance(); + }); + } + + void updatePolygonScanUsageState(bool isEnabled) { + if (isEnabled) { + _updateTransactions(); + _setTransactionUpdateTimer(); + } else { + _transactionsUpdateTimer?.cancel(); + } + } + + @override + String signMessage(String message, {String? address = null}) => bytesToHex( + _polygonPrivateKey.signPersonalMessageToUint8List(ascii.encode(message))); + + Web3Client? getWeb3Client() => _client.getWeb3Client(); +} diff --git a/cw_polygon/lib/polygon_wallet_addresses.dart b/cw_polygon/lib/polygon_wallet_addresses.dart new file mode 100644 index 000000000..0a6a407c7 --- /dev/null +++ b/cw_polygon/lib/polygon_wallet_addresses.dart @@ -0,0 +1,5 @@ +import 'package:cw_ethereum/ethereum_wallet_addresses.dart'; + +class PolygonWalletAddresses extends EthereumWalletAddresses { + PolygonWalletAddresses(super.walletInfo); +} diff --git a/cw_polygon/lib/polygon_wallet_creation_credentials.dart b/cw_polygon/lib/polygon_wallet_creation_credentials.dart new file mode 100644 index 000000000..74c7c5ed7 --- /dev/null +++ b/cw_polygon/lib/polygon_wallet_creation_credentials.dart @@ -0,0 +1,28 @@ +import 'package:cw_core/wallet_credentials.dart'; +import 'package:cw_core/wallet_info.dart'; +class PolygonNewWalletCredentials extends WalletCredentials { + PolygonNewWalletCredentials({required String name, WalletInfo? walletInfo}) + : super(name: name, walletInfo: walletInfo); +} + +class PolygonRestoreWalletFromSeedCredentials extends WalletCredentials { + PolygonRestoreWalletFromSeedCredentials( + {required String name, + required String password, + required this.mnemonic, + WalletInfo? walletInfo}) + : super(name: name, password: password, walletInfo: walletInfo); + + final String mnemonic; +} + +class PolygonRestoreWalletFromPrivateKey extends WalletCredentials { + PolygonRestoreWalletFromPrivateKey( + {required String name, + required String password, + required this.privateKey, + WalletInfo? walletInfo}) + : super(name: name, password: password, walletInfo: walletInfo); + + final String privateKey; +} diff --git a/cw_polygon/lib/polygon_wallet_service.dart b/cw_polygon/lib/polygon_wallet_service.dart new file mode 100644 index 000000000..dafe3bab0 --- /dev/null +++ b/cw_polygon/lib/polygon_wallet_service.dart @@ -0,0 +1,123 @@ +import 'dart:io'; + +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/wallet_base.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_ethereum/ethereum_mnemonics.dart'; +import 'package:cw_polygon/polygon_wallet.dart'; +import 'package:bip39/bip39.dart' as bip39; +import 'package:hive/hive.dart'; +import 'polygon_wallet_creation_credentials.dart'; +import 'package:collection/collection.dart'; + +class PolygonWalletService extends WalletService { + PolygonWalletService(this.walletInfoSource); + + final Box walletInfoSource; + + @override + Future create(PolygonNewWalletCredentials credentials) async { + final strength = (credentials.seedPhraseLength == 12) + ? 128 + : (credentials.seedPhraseLength == 24) + ? 256 + : 128; + + final mnemonic = bip39.generateMnemonic(strength: strength); + final wallet = PolygonWallet( + walletInfo: credentials.walletInfo!, + mnemonic: mnemonic, + password: credentials.password!, + ); + + await wallet.init(); + wallet.addInitialTokens(); + await wallet.save(); + + return wallet; + } + + @override + WalletType getType() => WalletType.polygon; + + @override + Future isWalletExit(String name) async => + File(await pathForWallet(name: name, type: getType())).existsSync(); + + @override + Future openWallet(String name, String password) async { + final walletInfo = + walletInfoSource.values.firstWhere((info) => info.id == WalletBase.idFor(name, getType())); + final wallet = await PolygonWalletBase.open( + name: name, + password: password, + walletInfo: walletInfo, + ); + + await wallet.init(); + await wallet.save(); + + return wallet; + } + + @override + Future remove(String wallet) async { + File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true); + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; + await walletInfoSource.delete(walletInfo.key); + } + + @override + Future restoreFromKeys(PolygonRestoreWalletFromPrivateKey credentials) async { + final wallet = PolygonWallet( + password: credentials.password!, + privateKey: credentials.privateKey, + walletInfo: credentials.walletInfo!, + ); + + await wallet.init(); + wallet.addInitialTokens(); + await wallet.save(); + + return wallet; + } + + @override + Future restoreFromSeed(PolygonRestoreWalletFromSeedCredentials credentials) async { + if (!bip39.validateMnemonic(credentials.mnemonic)) { + throw EthereumMnemonicIsIncorrectException(); + } + + final wallet = PolygonWallet( + password: credentials.password!, + mnemonic: credentials.mnemonic, + walletInfo: credentials.walletInfo!, + ); + + await wallet.init(); + wallet.addInitialTokens(); + await wallet.save(); + + return wallet; + } + + @override + Future rename(String currentName, String password, String newName) async { + final currentWalletInfo = walletInfoSource.values + .firstWhere((info) => info.id == WalletBase.idFor(currentName, getType())); + final currentWallet = await PolygonWalletBase.open( + password: password, name: currentName, walletInfo: currentWalletInfo); + + await currentWallet.renameWalletFiles(newName); + + final newWalletInfo = currentWalletInfo; + newWalletInfo.id = WalletBase.idFor(newName, getType()); + newWalletInfo.name = newName; + + await walletInfoSource.put(currentWalletInfo.key, newWalletInfo); + } +} diff --git a/cw_polygon/pubspec.yaml b/cw_polygon/pubspec.yaml new file mode 100644 index 000000000..e99e6dbbb --- /dev/null +++ b/cw_polygon/pubspec.yaml @@ -0,0 +1,73 @@ +name: cw_polygon +description: A new Flutter package project. +version: 0.0.1 +publish_to: none +author: Cake Wallet +homepage: https://cakewallet.com + +environment: + sdk: '>=3.0.6 <4.0.0' + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + cw_core: + path: ../cw_core + cw_ethereum: + path: ../cw_ethereum + mobx: ^2.0.7+4 + intl: ^0.18.0 + bip39: ^1.0.6 + hive: ^2.2.3 + collection: ^1.17.1 + web3dart: ^2.7.1 + bip32: ^2.0.0 + hex: ^0.2.0 + shared_preferences: ^2.0.15 + + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.0 + build_runner: ^2.1.11 + mobx_codegen: ^2.0.7 + hive_generator: ^1.1.3 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # To add assets to your package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/assets-and-images/#from-packages + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # To add custom fonts to your package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/custom-fonts/#from-packages diff --git a/cw_polygon/test/cw_polygon_test.dart b/cw_polygon/test/cw_polygon_test.dart new file mode 100644 index 000000000..554e28795 --- /dev/null +++ b/cw_polygon/test/cw_polygon_test.dart @@ -0,0 +1,12 @@ +import 'package:flutter_test/flutter_test.dart'; + +import 'package:cw_polygon/cw_polygon.dart'; + +void main() { + test('adds one to input values', () { + final calculator = Calculator(); + expect(calculator.addOne(2), 3); + expect(calculator.addOne(-7), -6); + expect(calculator.addOne(0), 1); + }); +} diff --git a/ios/Runner/InfoBase.plist b/ios/Runner/InfoBase.plist index 6cea7a730..4f7036498 100644 --- a/ios/Runner/InfoBase.plist +++ b/ios/Runner/InfoBase.plist @@ -160,6 +160,26 @@ bitcoincash-wallet + + CFBundleTypeRole + Editor + CFBundleURLName + polygon + CFBundleURLSchemes + + polygon + + + + CFBundleTypeRole + Viewer + CFBundleURLName + polygon-wallet + CFBundleURLSchemes + + polygon-wallet + + CFBundleVersion $(CURRENT_PROJECT_VERSION) diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index fcb881943..1bc0d1ae2 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -271,6 +271,8 @@ class AddressValidator extends TextValidator { '|([^0-9a-zA-Z]|^)ltc[a-zA-Z0-9]{26,45}([^0-9a-zA-Z]|\$)'; case CryptoCurrency.eth: return '0x[0-9a-zA-Z]{42}'; + case CryptoCurrency.maticpoly: + return '0x[0-9a-zA-Z]{42}'; case CryptoCurrency.nano: return 'nano_[0-9a-zA-Z]{60}'; case CryptoCurrency.banano: diff --git a/lib/core/fiat_conversion_service.dart b/lib/core/fiat_conversion_service.dart index 479aa3b82..8a37175b4 100644 --- a/lib/core/fiat_conversion_service.dart +++ b/lib/core/fiat_conversion_service.dart @@ -16,7 +16,7 @@ Future _fetchPrice(Map args) async { final Map queryParams = { 'interval_count': '1', - 'base': crypto, + 'base': crypto.split(".").first, 'quote': fiat, 'key': secrets.fiatApiKey, }; diff --git a/lib/core/seed_validator.dart b/lib/core/seed_validator.dart index 95ccf89ac..8f65159e1 100644 --- a/lib/core/seed_validator.dart +++ b/lib/core/seed_validator.dart @@ -3,6 +3,7 @@ import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/haven/haven.dart'; import 'package:cake_wallet/core/validator.dart'; import 'package:cake_wallet/entities/mnemonic_item.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/nano/nano.dart'; @@ -34,6 +35,8 @@ class SeedValidator extends Validator { case WalletType.nano: case WalletType.banano: return nano!.getNanoWordList(language); + case WalletType.polygon: + return polygon!.getPolygonWordList(language); default: return []; } diff --git a/lib/core/wallet_connect/evm_chain_service.dart b/lib/core/wallet_connect/evm_chain_service.dart index dc22e3dda..b9849fdac 100644 --- a/lib/core/wallet_connect/evm_chain_service.dart +++ b/lib/core/wallet_connect/evm_chain_service.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/core/wallet_connect/eth_transaction_model.dart'; import 'package:cake_wallet/core/wallet_connect/evm_chain_id.dart'; import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_widget.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart'; @@ -14,7 +15,6 @@ import 'package:cake_wallet/src/screens/wallet_connect/widgets/connection_widget import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/web3_request_modal.dart'; import 'package:cake_wallet/src/screens/wallet_connect/utils/string_parsing.dart'; import 'package:convert/convert.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:eth_sig_util/eth_sig_util.dart'; import 'package:eth_sig_util/util/utils.dart'; import 'package:http/http.dart' as http; @@ -46,13 +46,12 @@ class EvmChainServiceImpl implements ChainService { required this.wcKeyService, required this.bottomSheetService, required this.wallet, - Web3Client? ethClient, - }) : ethClient = ethClient ?? + Web3Client? web3Client, + }) : ethClient = web3Client ?? Web3Client( - appStore.settingsStore.getCurrentNode(WalletType.ethereum).uri.toString(), + appStore.settingsStore.getCurrentNode(appStore.wallet!.type).uri.toString(), http.Client(), ) { - for (final String event in getEvents()) { wallet.registerEventEmitter(chainId: getChainId(), event: event); } @@ -138,7 +137,8 @@ class EvmChainServiceImpl implements ChainService { try { // Load the private key - final List keys = wcKeyService.getKeysForChain(getChainId()); + final List keys = wcKeyService + .getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type)); final Credentials credentials = EthPrivateKey.fromHex(keys[0].privateKey); @@ -176,13 +176,15 @@ class EvmChainServiceImpl implements ChainService { try { // Load the private key - final List keys = wcKeyService.getKeysForChain(getChainId()); + final List keys = wcKeyService + .getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type)); final EthPrivateKey credentials = EthPrivateKey.fromHex(keys[0].privateKey); final String signature = hex.encode( credentials.signPersonalMessageToUint8List( Uint8List.fromList(utf8.encode(message)), + chainId: getChainIdBasedOnWalletType(appStore.wallet!.type), ), ); log(signature); @@ -212,7 +214,8 @@ class EvmChainServiceImpl implements ChainService { } // Load the private key - final List keys = wcKeyService.getKeysForChain(getChainId()); + final List keys = wcKeyService + .getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type)); final Credentials credentials = EthPrivateKey.fromHex(keys[0].privateKey); @@ -232,7 +235,11 @@ class EvmChainServiceImpl implements ChainService { ); try { - final result = await ethClient.sendTransaction(credentials, transaction); + final result = await ethClient.sendTransaction( + credentials, + transaction, + chainId: getChainIdBasedOnWalletType(appStore.wallet!.type), + ); log('Result: $result'); @@ -267,7 +274,8 @@ class EvmChainServiceImpl implements ChainService { return authError; } - final List keys = wcKeyService.getKeysForChain(getChainId()); + final List keys = wcKeyService + .getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type)); return EthSigUtil.signTypedData( privateKey: keys[0].privateKey, diff --git a/lib/core/wallet_connect/wallet_connect_key_service.dart b/lib/core/wallet_connect/wallet_connect_key_service.dart index 2e61ebb99..bb0c9d14c 100644 --- a/lib/core/wallet_connect/wallet_connect_key_service.dart +++ b/lib/core/wallet_connect/wallet_connect_key_service.dart @@ -1,9 +1,11 @@ import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_type.dart'; abstract class WalletConnectKeyService { /// Returns a list of all the keys. @@ -32,16 +34,36 @@ class KeyServiceImpl implements WalletConnectKeyService { 'eip155:42161', 'eip155:80001', ], - privateKey: ethereum!.getPrivateKey(wallet), - publicKey: ethereum!.getPublicKey(wallet), + privateKey: _getPrivateKeyForWallet(wallet), + publicKey: _getPublicKeyForWallet(wallet), ), - ]; late final WalletBase, TransactionInfo> wallet; late final List _keys; + static String _getPrivateKeyForWallet(WalletBase wallet) { + switch (wallet.type) { + case WalletType.ethereum: + return ethereum!.getPrivateKey(wallet); + case WalletType.polygon: + return polygon!.getPrivateKey(wallet); + default: + return ''; + } + } + + static String _getPublicKeyForWallet(WalletBase wallet) { + switch (wallet.type) { + case WalletType.ethereum: + return ethereum!.getPublicKey(wallet); + case WalletType.polygon: + return polygon!.getPublicKey(wallet); + default: + return ''; + } + } @override List getChains() { final List chainIds = []; diff --git a/lib/core/wallet_connect/web3wallet_service.dart b/lib/core/wallet_connect/web3wallet_service.dart index c69692c9d..7a1dac6cc 100644 --- a/lib/core/wallet_connect/web3wallet_service.dart +++ b/lib/core/wallet_connect/web3wallet_service.dart @@ -9,6 +9,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/core/wallet_connect/models/auth_request_model.dart'; import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart'; import 'package:cake_wallet/core/wallet_connect/models/session_request_model.dart'; +import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/src/screens/wallet_connect/widgets/connection_request_widget.dart'; import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_widget.dart'; import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/web3_request_modal.dart'; @@ -164,8 +165,10 @@ abstract class Web3WalletServiceBase with Store { void _onSessionProposal(SessionProposalEvent? args) async { if (args != null) { + final chaindIdNamespace = getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type); final Widget modalWidget = Web3RequestModal( child: ConnectionRequestWidget( + chaindIdNamespace: chaindIdNamespace, wallet: _web3Wallet, sessionProposal: SessionRequestModel(request: args.params), ), @@ -232,12 +235,13 @@ abstract class Web3WalletServiceBase with Store { @action Future _onAuthRequest(AuthRequest? args) async { if (args != null) { - List chainKeys = walletKeyService.getKeysForChain('eip155:1'); + final chaindIdNamespace = getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type); + List chainKeys = walletKeyService.getKeysForChain(chaindIdNamespace); // Create the message to be signed - final String iss = 'did:pkh:eip155:1:${chainKeys.first.publicKey}'; - + final String iss = 'did:pkh:$chaindIdNamespace:${chainKeys.first.publicKey}'; final Widget modalWidget = Web3RequestModal( child: ConnectionRequestWidget( + chaindIdNamespace: chaindIdNamespace, wallet: _web3Wallet, authRequest: AuthRequestModel(iss: iss, request: args), ), diff --git a/lib/di.dart b/lib/di.dart index 0a7097b7b..e0faa6db1 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -18,6 +18,8 @@ import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/ionia/ionia_anypay.dart'; import 'package:cake_wallet/ionia/ionia_gift_card.dart'; import 'package:cake_wallet/ionia/ionia_tip.dart'; +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/src/screens/anonpay_details/anonpay_details_page.dart'; import 'package:cake_wallet/src/screens/buy/buy_options_page.dart'; @@ -750,7 +752,7 @@ Future setup({ final wallet = getIt.get().wallet; return ConnectionSyncPage( getIt.get(), - wallet?.type == WalletType.ethereum ? getIt.get() : null, + isEVMCompatibleChain(wallet!.type) ? getIt.get() : null, ); }); @@ -847,6 +849,8 @@ Future setup({ .createBitcoinCashWalletService(_walletInfoSource, _unspentCoinsInfoSource!); case WalletType.nano: return nano!.createNanoWalletService(_walletInfoSource); + case WalletType.polygon: + return polygon!.createPolygonWalletService(_walletInfoSource); default: throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService'); } diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index ec31b0539..45803899e 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -27,6 +27,7 @@ const cakeWalletBitcoinElectrumUri = 'electrum.cakewallet.com:50002'; const cakeWalletLitecoinElectrumUri = 'ltc-electrum.cakewallet.com:50002'; const havenDefaultNodeUri = 'nodes.havenprotocol.org:443'; const ethereumDefaultNodeUri = 'ethereum.publicnode.com'; +const polygonDefaultNodeUri = 'polygon-bor.publicnode.com'; const cakeWalletBitcoinCashDefaultNodeUri = 'bitcoincash.stackwallet.com:50002'; const nanoDefaultNodeUri = 'rpc.nano.to'; const nanoDefaultPowNodeUri = 'rpc.nano.to'; @@ -65,6 +66,8 @@ Future defaultSettingsMigration( final migrationVersions = List.generate(migrationVersionsLength, (i) => currentVersion + (i + 1)); + /// When you add a new case, increase the initialMigrationVersion parameter in the main.dart file. + /// This ensures that this switch case runs the newly added case. await Future.forEach(migrationVersions, (int version) async { try { switch (version) { @@ -175,6 +178,11 @@ Future defaultSettingsMigration( await changeBitcoinCurrentElectrumServerToDefault( sharedPreferences: sharedPreferences, nodes: nodes); break; + case 24: + await addPolygonNodeList(nodes: nodes); + await changePolygonCurrentNodeToDefault( + sharedPreferences: sharedPreferences, nodes: nodes); + break; case 25: await rewriteSecureStoragePin(secureStorage: secureStorage); break; @@ -332,6 +340,11 @@ Node? getEthereumDefaultNode({required Box nodes}) { nodes.values.firstWhereOrNull((node) => node.type == WalletType.ethereum); } +Node? getPolygonDefaultNode({required Box nodes}) { + return nodes.values.firstWhereOrNull((Node node) => node.uriRaw == polygonDefaultNodeUri) ?? + nodes.values.firstWhereOrNull((node) => node.type == WalletType.polygon); +} + Node? getNanoDefaultNode({required Box nodes}) { return nodes.values.firstWhereOrNull((Node node) => node.uriRaw == nanoDefaultNodeUri) ?? nodes.values.firstWhereOrNull((node) => node.type == WalletType.nano); @@ -575,6 +588,7 @@ Future checkCurrentNodes( sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey); final currentHavenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey); final currentEthereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey); + final currentPolygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey); final currentNanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); final currentNanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey); final currentBitcoinCashNodeId = @@ -589,6 +603,8 @@ Future checkCurrentNodes( nodeSource.values.firstWhereOrNull((node) => node.key == currentHavenNodeId); final currentEthereumNodeServer = nodeSource.values.firstWhereOrNull((node) => node.key == currentEthereumNodeId); + final currentPolygonNodeServer = + nodeSource.values.firstWhereOrNull((node) => node.key == currentPolygonNodeId); final currentNanoNodeServer = nodeSource.values.firstWhereOrNull((node) => node.key == currentNanoNodeId); final currentNanoPowNodeServer = @@ -648,6 +664,12 @@ Future checkCurrentNodes( await nodeSource.add(node); await sharedPreferences.setInt(PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int); } + + if (currentPolygonNodeServer == null) { + final node = Node(uri: polygonDefaultNodeUri, type: WalletType.polygon); + await nodeSource.add(node); + await sharedPreferences.setInt(PreferencesKey.currentPolygonNodeIdKey, node.key as int); + } } Future resetBitcoinElectrumServer( @@ -742,3 +764,20 @@ Future changeNanoCurrentPowNodeToDefault( final nodeId = node?.key as int? ?? 0; await sharedPreferences.setInt(PreferencesKey.currentNanoPowNodeIdKey, nodeId); } + +Future addPolygonNodeList({required Box nodes}) async { + final nodeList = await loadDefaultPolygonNodes(); + for (var node in nodeList) { + if (nodes.values.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) { + await nodes.add(node); + } + } +} + +Future changePolygonCurrentNodeToDefault( + {required SharedPreferences sharedPreferences, required Box nodes}) async { + final node = getPolygonDefaultNode(nodes: nodes); + final nodeId = node?.key as int? ?? 0; + + await sharedPreferences.setInt(PreferencesKey.currentPolygonNodeIdKey, nodeId); +} diff --git a/lib/entities/ens_record.dart b/lib/entities/ens_record.dart index 8cf62d79b..b2ce51806 100644 --- a/lib/entities/ens_record.dart +++ b/lib/entities/ens_record.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/ethereum/ethereum.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:ens_dart/ens_dart.dart'; @@ -12,6 +13,10 @@ class EnsRecord { if (wallet != null && wallet.type == WalletType.ethereum) { _client = ethereum!.getWeb3Client(wallet); } + + if (wallet != null && wallet.type == WalletType.polygon) { + _client = polygon!.getWeb3Client(wallet); + } if (_client == null) { _client = Web3Client("https://ethereum.publicnode.com", Client()); @@ -31,6 +36,7 @@ class EnsRecord { case WalletType.haven: return await ens.withName(name).getCoinAddress(CoinType.XHV); case WalletType.ethereum: + case WalletType.polygon: default: return (await ens.withName(name).getAddress()).hex; } diff --git a/lib/entities/main_actions.dart b/lib/entities/main_actions.dart index 46865cbcc..1ef388d31 100644 --- a/lib/entities/main_actions.dart +++ b/lib/entities/main_actions.dart @@ -19,7 +19,8 @@ class MainActions { final bool Function(DashboardViewModel viewModel)? isEnabled; final bool Function(DashboardViewModel viewModel)? canShow; - final Future Function(BuildContext context, DashboardViewModel viewModel) onTap; + final Future Function( + BuildContext context, DashboardViewModel viewModel) onTap; MainActions._({ required this.name, @@ -52,6 +53,7 @@ class MainActions { case WalletType.bitcoin: case WalletType.litecoin: case WalletType.ethereum: + case WalletType.polygon: case WalletType.bitcoinCash: switch (defaultBuyProvider) { case BuyProviderType.AskEachTime: @@ -124,6 +126,7 @@ class MainActions { case WalletType.bitcoin: case WalletType.litecoin: case WalletType.ethereum: + case WalletType.polygon: case WalletType.bitcoinCash: if (viewModel.isEnabledSellAction) { final moonPaySellProvider = MoonPaySellProvider(); diff --git a/lib/entities/node_list.dart b/lib/entities/node_list.dart index 53facf18c..6d1cf299d 100644 --- a/lib/entities/node_list.dart +++ b/lib/entities/node_list.dart @@ -133,6 +133,22 @@ Future> loadDefaultNanoPowNodes() async { return nodes; } +Future> loadDefaultPolygonNodes() async { + final nodesRaw = await rootBundle.loadString('assets/polygon_node_list.yml'); + final loadedNodes = loadYaml(nodesRaw) as YamlList; + final nodes = []; + + for (final raw in loadedNodes) { + if (raw is Map) { + final node = Node.fromMap(Map.from(raw)); + node.type = WalletType.polygon; + nodes.add(node); + } + } + + return nodes; +} + Future resetToDefault(Box nodeSource) async { final moneroNodes = await loadDefaultNodes(); final bitcoinElectrumServerList = await loadBitcoinElectrumServerList(); @@ -141,6 +157,8 @@ Future resetToDefault(Box nodeSource) async { final havenNodes = await loadDefaultHavenNodes(); final ethereumNodes = await loadDefaultEthereumNodes(); final nanoNodes = await loadDefaultNanoNodes(); + final polygonNodes = await loadDefaultPolygonNodes(); + final nodes = moneroNodes + bitcoinElectrumServerList + @@ -148,7 +166,8 @@ Future resetToDefault(Box nodeSource) async { havenNodes + ethereumNodes + bitcoinCashElectrumServerList + - nanoNodes; + nanoNodes + + polygonNodes; await nodeSource.clear(); await nodeSource.addAll(nodes); diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index bdd6c24a7..67f1aca97 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -6,6 +6,7 @@ class PreferencesKey { static const currentLitecoinElectrumSererIdKey = 'current_node_id_ltc'; static const currentHavenNodeIdKey = 'current_node_id_xhv'; static const currentEthereumNodeIdKey = 'current_node_id_eth'; + static const currentPolygonNodeIdKey = 'current_node_id_matic'; static const currentNanoNodeIdKey = 'current_node_id_nano'; static const currentNanoPowNodeIdKey = 'current_node_id_nano_pow'; static const currentBananoNodeIdKey = 'current_node_id_banano'; @@ -37,6 +38,7 @@ class PreferencesKey { static const havenTransactionPriority = 'current_fee_priority_haven'; static const litecoinTransactionPriority = 'current_fee_priority_litecoin'; static const ethereumTransactionPriority = 'current_fee_priority_ethereum'; + static const polygonTransactionPriority = 'current_fee_priority_polygon'; static const bitcoinCashTransactionPriority = 'current_fee_priority_bitcoin_cash'; static const shouldShowReceiveWarning = 'should_show_receive_warning'; static const shouldShowYatPopup = 'should_show_yat_popup'; @@ -50,6 +52,7 @@ class PreferencesKey { static const sortBalanceBy = 'sort_balance_by'; static const pinNativeTokenAtTop = 'pin_native_token_at_top'; static const useEtherscan = 'use_etherscan'; + static const usePolygonScan = 'use_polygonscan'; static const defaultNanoRep = 'default_nano_representative'; static const defaultBananoRep = 'default_banano_representative'; static const lookupsTwitter = 'looks_up_twitter'; diff --git a/lib/entities/priority_for_wallet_type.dart b/lib/entities/priority_for_wallet_type.dart index bf6f8157d..70b072c55 100644 --- a/lib/entities/priority_for_wallet_type.dart +++ b/lib/entities/priority_for_wallet_type.dart @@ -3,6 +3,7 @@ import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/haven/haven.dart'; import 'package:cake_wallet/monero/monero.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/wallet_type.dart'; @@ -24,6 +25,8 @@ List priorityForWalletType(WalletType type) { case WalletType.nano: case WalletType.banano: return []; + case WalletType.polygon: + return polygon!.getTransactionPriorities(); default: return []; } diff --git a/lib/polygon/cw_polygon.dart b/lib/polygon/cw_polygon.dart new file mode 100644 index 000000000..066b29d43 --- /dev/null +++ b/lib/polygon/cw_polygon.dart @@ -0,0 +1,156 @@ +part of 'polygon.dart'; + +class CWPolygon extends Polygon { + @override + List getPolygonWordList(String language) => EthereumMnemonics.englishWordlist; + + WalletService createPolygonWalletService(Box walletInfoSource) => + PolygonWalletService(walletInfoSource); + + @override + WalletCredentials createPolygonNewWalletCredentials({ + required String name, + WalletInfo? walletInfo, + }) => + PolygonNewWalletCredentials(name: name, walletInfo: walletInfo); + + @override + WalletCredentials createPolygonRestoreWalletFromSeedCredentials({ + required String name, + required String mnemonic, + required String password, + }) => + PolygonRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic); + + @override + WalletCredentials createPolygonRestoreWalletFromPrivateKey({ + required String name, + required String privateKey, + required String password, + }) => + PolygonRestoreWalletFromPrivateKey(name: name, password: password, privateKey: privateKey); + + @override + String getAddress(WalletBase wallet) => (wallet as PolygonWallet).walletAddresses.address; + + @override + String getPrivateKey(WalletBase wallet) { + final privateKeyHolder = (wallet as PolygonWallet).polygonPrivateKey; + String stringKey = bytesToHex(privateKeyHolder.privateKey); + return stringKey; + } + + @override + String getPublicKey(WalletBase wallet) { + final privateKeyInUnitInt = (wallet as PolygonWallet).polygonPrivateKey; + final publicKey = privateKeyInUnitInt.address.hex; + return publicKey; + } + + @override + TransactionPriority getDefaultTransactionPriority() => PolygonTransactionPriority.medium; + + @override + TransactionPriority getPolygonTransactionPrioritySlow() => PolygonTransactionPriority.slow; + + @override + List getTransactionPriorities() => PolygonTransactionPriority.all; + + @override + TransactionPriority deserializePolygonTransactionPriority(int raw) => + PolygonTransactionPriority.deserialize(raw: raw); + + Object createPolygonTransactionCredentials( + List outputs, { + required TransactionPriority priority, + required CryptoCurrency currency, + int? feeRate, + }) => + PolygonTransactionCredentials( + outputs + .map((out) => OutputInfo( + fiatAmount: out.fiatAmount, + cryptoAmount: out.cryptoAmount, + address: out.address, + note: out.note, + sendAll: out.sendAll, + extractedAddress: out.extractedAddress, + isParsedAddress: out.isParsedAddress, + formattedCryptoAmount: out.formattedCryptoAmount)) + .toList(), + priority: priority as PolygonTransactionPriority, + currency: currency, + feeRate: feeRate, + ); + + Object createPolygonTransactionCredentialsRaw( + List outputs, { + TransactionPriority? priority, + required CryptoCurrency currency, + required int feeRate, + }) => + PolygonTransactionCredentials( + outputs, + priority: priority as PolygonTransactionPriority?, + currency: currency, + feeRate: feeRate, + ); + + @override + int formatterPolygonParseAmount(String amount) => PolygonFormatter.parsePolygonAmount(amount); + + @override + double formatterPolygonAmountToDouble( + {TransactionInfo? transaction, BigInt? amount, int exponent = 18}) { + assert(transaction != null || amount != null); + + if (transaction != null) { + transaction as PolygonTransactionInfo; + return transaction.ethAmount / BigInt.from(10).pow(transaction.exponent); + } else { + return (amount!) / BigInt.from(10).pow(exponent); + } + } + + @override + List getERC20Currencies(WalletBase wallet) { + final polygonWallet = wallet as PolygonWallet; + return polygonWallet.erc20Currencies; + } + + @override + Future addErc20Token(WalletBase wallet, Erc20Token token) async => + await (wallet as PolygonWallet).addErc20Token(token); + + @override + Future deleteErc20Token(WalletBase wallet, Erc20Token token) async => + await (wallet as PolygonWallet).deleteErc20Token(token); + + @override + Future getErc20Token(WalletBase wallet, String contractAddress) async { + final polygonWallet = wallet as PolygonWallet; + return await polygonWallet.getErc20Token(contractAddress); + } + + @override + CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) { + transaction as PolygonTransactionInfo; + if (transaction.tokenSymbol == CryptoCurrency.maticpoly.title) { + return CryptoCurrency.maticpoly; + } + + wallet as PolygonWallet; + return wallet.erc20Currencies.firstWhere( + (element) => transaction.tokenSymbol.toLowerCase() == element.symbol.toLowerCase()); + } + + @override + void updatePolygonScanUsageState(WalletBase wallet, bool isEnabled) { + (wallet as PolygonWallet).updatePolygonScanUsageState(isEnabled); + } + + @override + Web3Client? getWeb3Client(WalletBase wallet) { + return (wallet as PolygonWallet).getWeb3Client(); + } +} diff --git a/lib/reactions/fiat_rate_update.dart b/lib/reactions/fiat_rate_update.dart index 141401e6a..2b757ad44 100644 --- a/lib/reactions/fiat_rate_update.dart +++ b/lib/reactions/fiat_rate_update.dart @@ -3,9 +3,11 @@ import 'package:cake_wallet/core/fiat_conversion_service.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/update_haven_rate.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cw_core/erc20_token.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; @@ -33,10 +35,18 @@ Future startFiatRateUpdate( torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly); } + Iterable? currencies; if (appStore.wallet!.type == WalletType.ethereum) { - final currencies = - ethereum!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled); + currencies = + ethereum!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled); + } + if (appStore.wallet!.type == WalletType.polygon) { + currencies = + polygon!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled); + } + + if (currencies != null) { for (final currency in currencies) { () async { fiatConversionStore.prices[currency] = await FiatConversionService.fetchPrice( diff --git a/lib/reactions/on_current_wallet_change.dart b/lib/reactions/on_current_wallet_change.dart index 5f956dc1a..42fbd182e 100644 --- a/lib/reactions/on_current_wallet_change.dart +++ b/lib/reactions/on_current_wallet_change.dart @@ -2,7 +2,8 @@ import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/update_haven_rate.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; -import 'package:cake_wallet/nano/nano.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cw_core/erc20_token.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/transaction_info.dart'; @@ -107,10 +108,17 @@ void startCurrentWalletChangeReaction( fiat: settingsStore.fiatCurrency, torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly); + Iterable? currencies; if (wallet.type == WalletType.ethereum) { - final currencies = + currencies = ethereum!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled); + } + if (wallet.type == WalletType.polygon) { + currencies = + polygon!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled); + } + if (currencies != null) { for (final currency in currencies) { () async { fiatConversionStore.prices[currency] = await FiatConversionService.fetchPrice( diff --git a/lib/reactions/wallet_connect.dart b/lib/reactions/wallet_connect.dart new file mode 100644 index 000000000..d0ff37267 --- /dev/null +++ b/lib/reactions/wallet_connect.dart @@ -0,0 +1,46 @@ +import 'package:cake_wallet/core/wallet_connect/evm_chain_id.dart'; +import 'package:cw_core/wallet_type.dart'; + +bool isEVMCompatibleChain(WalletType walletType) { + switch (walletType) { + case WalletType.polygon: + case WalletType.ethereum: + return true; + default: + return false; + } +} + +String getChainNameSpaceAndIdBasedOnWalletType(WalletType walletType) { + switch (walletType) { + case WalletType.ethereum: + return EVMChainId.ethereum.chain(); + case WalletType.polygon: + return EVMChainId.polygon.chain(); + default: + return ''; + } +} + +int getChainIdBasedOnWalletType(WalletType walletType) { + switch (walletType) { + case WalletType.polygon: + return 137; + + // For now, we return eth chain Id as the default, we'll modify as we add more wallets + case WalletType.ethereum: + default: + return 1; + } +} + +String getChainNameBasedOnWalletType(WalletType walletType) { + switch (walletType) { + case WalletType.ethereum: + return 'eth'; + case WalletType.polygon: + return 'polygon'; + default: + return ''; + } +} diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart index 1aa7f6c4a..59c31aa62 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart @@ -33,6 +33,7 @@ class _DesktopWalletSelectionDropDownState extends State { this.ethereumIcon = Image.asset('assets/images/eth_icon.png'), this.nanoIcon = Image.asset('assets/images/nano_icon.png'), this.bananoIcon = Image.asset('assets/images/nano_icon.png'), - this.bitcoinCashIcon = Image.asset('assets/images/bch_icon.png'); + this.bitcoinCashIcon = Image.asset('assets/images/bch_icon.png'), + this.polygonIcon = Image.asset('assets/images/matic_icon.png'); final largeScreen = 731; @@ -54,6 +55,8 @@ class MenuWidgetState extends State { Image bitcoinCashIcon; Image nanoIcon; Image bananoIcon; + Image polygonIcon; + @override void initState() { @@ -219,6 +222,8 @@ class MenuWidgetState extends State { return nanoIcon; case WalletType.banano: return bananoIcon; + case WalletType.polygon: + return polygonIcon; default: throw Exception('No icon for ${type.toString()}'); } diff --git a/lib/src/screens/receive/widgets/currency_input_field.dart b/lib/src/screens/receive/widgets/currency_input_field.dart index 1241b2ba7..84b2a7bca 100644 --- a/lib/src/screens/receive/widgets/currency_input_field.dart +++ b/lib/src/screens/receive/widgets/currency_input_field.dart @@ -1,5 +1,6 @@ import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; +import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/currency.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -23,6 +24,13 @@ class CurrencyInputField extends StatelessWidget { final TextEditingController controller; final bool isLight; + String get _currencyName { + if (selectedCurrency is CryptoCurrency) { + return (selectedCurrency as CryptoCurrency).title.toUpperCase(); + } + return selectedCurrency.name.toUpperCase(); + } + @override Widget build(BuildContext context) { final arrowBottomPurple = Image.asset( @@ -74,7 +82,7 @@ class CurrencyInputField extends StatelessWidget { child: arrowBottomPurple, ), Text( - selectedCurrency.name.toUpperCase(), + _currencyName, style: TextStyle( fontWeight: FontWeight.w600, fontSize: 16, @@ -83,7 +91,7 @@ class CurrencyInputField extends StatelessWidget { ), if (selectedCurrency.tag != null) Padding( - padding: const EdgeInsets.only(right: 3.0), + padding: const EdgeInsets.symmetric(horizontal: 3.0), child: Container( decoration: BoxDecoration( color: Theme.of(context).extension()!.textFieldButtonColor, diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index ca86cdccc..67cd689b1 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -2,9 +2,9 @@ import 'dart:async'; import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/core/totp_request_details.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/payment_request.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; @@ -169,7 +169,7 @@ class RootState extends State with WidgetsBindingObserver { ); launchUri = null; } else if (isWalletConnectLink) { - if (widget.appStore.wallet!.type == WalletType.ethereum) { + if (isEVMCompatibleChain(widget.appStore.wallet!.type)) { widget.navigatorKey.currentState?.pushNamed( Routes.walletConnectConnectionsListing, arguments: launchUri, @@ -179,7 +179,7 @@ class RootState extends State with WidgetsBindingObserver { _nonETHWalletErrorToast(S.current.switchToETHWallet); } } - + launchUri = null; return WillPopScope( onWillPop: () async => false, @@ -205,7 +205,7 @@ class RootState extends State with WidgetsBindingObserver { String? _getRouteToGo() { if (isWalletConnectLink) { - if (widget.appStore.wallet!.type != WalletType.ethereum) { + if (isEVMCompatibleChain(widget.appStore.wallet!.type)) { _nonETHWalletErrorToast(S.current.switchToETHWallet); return null; } diff --git a/lib/src/screens/seed/pre_seed_page.dart b/lib/src/screens/seed/pre_seed_page.dart index 947099983..a45d81fc0 100644 --- a/lib/src/screens/seed/pre_seed_page.dart +++ b/lib/src/screens/seed/pre_seed_page.dart @@ -13,7 +13,8 @@ class PreSeedPage extends BasePage { PreSeedPage(this.type, this.advancedPrivacySettingsViewModel) : imageLight = Image.asset('assets/images/pre_seed_light.png'), imageDark = Image.asset('assets/images/pre_seed_dark.png'), - seedPhraseLength = advancedPrivacySettingsViewModel.seedPhraseLength.value { + seedPhraseLength = + advancedPrivacySettingsViewModel.seedPhraseLength.value { wordsCount = _wordsCount(type, seedPhraseLength); } @@ -40,14 +41,14 @@ class PreSeedPage extends BasePage { alignment: Alignment.center, padding: EdgeInsets.all(24), child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), + constraints: BoxConstraints( + maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ConstrainedBox( constraints: BoxConstraints( - maxHeight: MediaQuery.of(context).size.height * 0.3 - ), + maxHeight: MediaQuery.of(context).size.height * 0.3), child: AspectRatio(aspectRatio: 1, child: image), ), Padding( @@ -58,12 +59,14 @@ class PreSeedPage extends BasePage { style: TextStyle( fontSize: 14, fontWeight: FontWeight.normal, - color: Theme.of(context).extension()!.secondaryTextColor), + color: Theme.of(context) + .extension()! + .secondaryTextColor), ), ), PrimaryButton( - onPressed: () => - Navigator.of(context).popAndPushNamed(Routes.seed, arguments: true), + onPressed: () => Navigator.of(context) + .popAndPushNamed(Routes.seed, arguments: true), text: S.of(context).pre_seed_button_text, color: Theme.of(context).primaryColor, textColor: Colors.white) @@ -79,6 +82,7 @@ class PreSeedPage extends BasePage { return 25; case WalletType.ethereum: case WalletType.bitcoinCash: + case WalletType.polygon: return seedPhraseLength; default: return 24; diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart index 50881dd57..40a04b0db 100644 --- a/lib/src/screens/settings/connection_sync_page.dart +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart'; +import 'package:cake_wallet/reactions/wallet_connect.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'; @@ -8,7 +9,6 @@ import 'package:cake_wallet/utils/feature_flag.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/settings/sync_mode.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -85,7 +85,7 @@ class ConnectionSyncPage extends BasePage { ); }, ), - if (dashboardViewModel.wallet.type == WalletType.ethereum) ...[ + if (isEVMCompatibleChain(dashboardViewModel.wallet.type)) ...[ WalletConnectTile( onTap: () => Navigator.of(context).pushNamed(Routes.walletConnectConnectionsListing), ), @@ -101,6 +101,7 @@ class ConnectionSyncPage extends BasePage { ); } + Future _presentReconnectAlert(BuildContext context) async { await showPopUp( context: context, diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index b1927648a..dcc41254e 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -87,6 +87,14 @@ class PrivacyPage extends BasePage { onValueChange: (BuildContext _, bool value) { _privacySettingsViewModel.setUseEtherscan(value); }), + if (_privacySettingsViewModel.canUsePolygonScan) + SettingsSwitcherCell( + title: S.current.polygonscan_history, + value: _privacySettingsViewModel.usePolygonScan, + onValueChange: (BuildContext _, bool value) { + _privacySettingsViewModel.setUsePolygonScan(value); + }, + ), SettingsCellWithArrow( title: S.current.domain_looks_up, handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage), diff --git a/lib/src/screens/wallet_connect/widgets/connection_request_widget.dart b/lib/src/screens/wallet_connect/widgets/connection_request_widget.dart index c73c4bfa8..179bd6b93 100644 --- a/lib/src/screens/wallet_connect/widgets/connection_request_widget.dart +++ b/lib/src/screens/wallet_connect/widgets/connection_request_widget.dart @@ -14,12 +14,14 @@ import 'connection_widget.dart'; class ConnectionRequestWidget extends StatefulWidget { const ConnectionRequestWidget({ required this.wallet, + required this.chaindIdNamespace, this.authRequest, this.sessionProposal, Key? key, }) : super(key: key); final Web3Wallet wallet; + final String chaindIdNamespace; final AuthRequestModel? authRequest; final SessionRequestModel? sessionProposal; @@ -52,23 +54,26 @@ class _ConnectionRequestWidgetState extends State { return _ConnectionMetadataDisplayWidget( metadata: metadata, + wallet: widget.wallet, authRequest: widget.authRequest, sessionProposal: widget.sessionProposal, - wallet: widget.wallet, + chaindIdNamespace: widget.chaindIdNamespace, ); } } class _ConnectionMetadataDisplayWidget extends StatelessWidget { const _ConnectionMetadataDisplayWidget({ - required this.metadata, required this.wallet, - this.authRequest, + required this.metadata, required this.sessionProposal, + required this.chaindIdNamespace, + this.authRequest, }); final ConnectionMetadata? metadata; final Web3Wallet wallet; + final String chaindIdNamespace; final AuthRequestModel? authRequest; final SessionRequestModel? sessionProposal; @@ -114,7 +119,11 @@ class _ConnectionMetadataDisplayWidget extends StatelessWidget { const SizedBox(height: 8), Visibility( visible: authRequest != null, - child: _AuthRequestWidget(wallet: wallet, authRequest: authRequest), + child: _AuthRequestWidget( + wallet: wallet, + authRequest: authRequest, + chaindIdNamespace: chaindIdNamespace, + ), //If authRequest is null, sessionProposal is not null. replacement: _SessionProposalWidget(sessionProposal: sessionProposal!), @@ -126,16 +135,21 @@ class _ConnectionMetadataDisplayWidget extends StatelessWidget { } class _AuthRequestWidget extends StatelessWidget { - const _AuthRequestWidget({required this.wallet, this.authRequest}); + const _AuthRequestWidget({ + required this.wallet, + required this.chaindIdNamespace, + this.authRequest, + }); final Web3Wallet wallet; + final String chaindIdNamespace; final AuthRequestModel? authRequest; @override Widget build(BuildContext context) { final model = ConnectionModel( text: wallet.formatAuthMessage( - iss: 'did:pkh:eip155:1:${authRequest!.iss}', + iss: 'did:pkh:$chaindIdNamespace:${authRequest!.iss}', cacaoPayload: CacaoRequestPayload.fromPayloadParams( authRequest!.request.payloadParams, ), diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index da5df874a..53a9b3eca 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -49,6 +49,7 @@ class WalletListBodyState extends State { final ethereumIcon = Image.asset('assets/images/eth_icon.png', height: 24, width: 24); final bitcoinCashIcon = Image.asset('assets/images/bch_icon.png', height: 24, width: 24); final nanoIcon = Image.asset('assets/images/nano_icon.png', height: 24, width: 24); + final polygonIcon = Image.asset('assets/images/matic_icon.png', height: 24, width: 24); final scrollController = ScrollController(); final double tileHeight = 60; Flushbar? _progressBar; @@ -256,6 +257,8 @@ class WalletListBodyState extends State { return bitcoinCashIcon; case WalletType.nano: return nanoIcon; + case WalletType.polygon: + return polygonIcon; default: return nonWalletTypeIcon; } diff --git a/lib/store/app_store.dart b/lib/store/app_store.dart index e814ff44b..46ac2cf1a 100644 --- a/lib/store/app_store.dart +++ b/lib/store/app_store.dart @@ -1,8 +1,8 @@ import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart'; import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/utils/exception_handler.dart'; import 'package:cw_core/transaction_info.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/wallet_base.dart'; @@ -44,7 +44,7 @@ abstract class AppStoreBase with Store { this.wallet = wallet; this.wallet!.setExceptionHandler(ExceptionHandler.onError); - if (wallet.type == WalletType.ethereum) { + if (isEVMCompatibleChain(wallet.type)) { getIt.get().init(); } } diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 4aaa44e13..3e38fed1f 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -12,6 +12,7 @@ import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/seed_phrase_length.dart'; import 'package:cake_wallet/entities/seed_type.dart'; import 'package:cake_wallet/entities/sort_balance_types.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; import 'package:cake_wallet/view_model/settings/sync_mode.dart'; import 'package:cake_wallet/utils/device_info.dart'; @@ -88,6 +89,7 @@ abstract class SettingsStoreBase with Store { required this.sortBalanceBy, required this.pinNativeTokenAtTop, required this.useEtherscan, + required this.usePolygonScan, required this.defaultNanoRep, required this.defaultBananoRep, required this.lookupsTwitter, @@ -101,6 +103,7 @@ abstract class SettingsStoreBase with Store { TransactionPriority? initialHavenTransactionPriority, TransactionPriority? initialLitecoinTransactionPriority, TransactionPriority? initialEthereumTransactionPriority, + TransactionPriority? initialPolygonTransactionPriority, TransactionPriority? initialBitcoinCashTransactionPriority}) : nodes = ObservableMap.of(nodes), powNodes = ObservableMap.of(powNodes), @@ -165,6 +168,10 @@ abstract class SettingsStoreBase with Store { priority[WalletType.ethereum] = initialEthereumTransactionPriority; } + if (initialPolygonTransactionPriority != null) { + priority[WalletType.polygon] = initialPolygonTransactionPriority; + } + if (initialBitcoinCashTransactionPriority != null) { priority[WalletType.bitcoinCash] = initialBitcoinCashTransactionPriority; } @@ -202,6 +209,9 @@ abstract class SettingsStoreBase with Store { case WalletType.bitcoinCash: key = PreferencesKey.bitcoinCashTransactionPriority; break; + case WalletType.polygon: + key = PreferencesKey.polygonTransactionPriority; + break; default: key = null; } @@ -245,8 +255,8 @@ abstract class SettingsStoreBase with Store { reaction( (_) => moneroSeedType, - (SeedType moneroSeedType) => sharedPreferences.setInt( - PreferencesKey.moneroSeedType, moneroSeedType.raw)); + (SeedType moneroSeedType) => + sharedPreferences.setInt(PreferencesKey.moneroSeedType, moneroSeedType.raw)); reaction( (_) => fiatApiMode, @@ -342,9 +352,9 @@ abstract class SettingsStoreBase with Store { sharedPreferences.setString(PreferencesKey.currentLanguageCode, languageCode)); reaction( - (_) => seedPhraseLength, - (SeedPhraseLength seedPhraseWordCount) => - sharedPreferences.setInt(PreferencesKey.currentSeedPhraseLength, seedPhraseWordCount.value)); + (_) => seedPhraseLength, + (SeedPhraseLength seedPhraseWordCount) => sharedPreferences.setInt( + PreferencesKey.currentSeedPhraseLength, seedPhraseWordCount.value)); reaction( (_) => pinTimeOutDuration, @@ -388,6 +398,11 @@ abstract class SettingsStoreBase with Store { (bool useEtherscan) => _sharedPreferences.setBool(PreferencesKey.useEtherscan, useEtherscan)); + reaction( + (_) => usePolygonScan, + (bool usePolygonScan) => + _sharedPreferences.setBool(PreferencesKey.usePolygonScan, usePolygonScan)); + reaction((_) => defaultNanoRep, (String nanoRep) => _sharedPreferences.setString(PreferencesKey.defaultNanoRep, nanoRep)); @@ -396,34 +411,32 @@ abstract class SettingsStoreBase with Store { (String bananoRep) => _sharedPreferences.setString(PreferencesKey.defaultBananoRep, bananoRep)); reaction( - (_) => lookupsTwitter, - (bool looksUpTwitter) => + (_) => lookupsTwitter, + (bool looksUpTwitter) => _sharedPreferences.setBool(PreferencesKey.lookupsTwitter, looksUpTwitter)); reaction( - (_) => lookupsMastodon, - (bool looksUpMastodon) => + (_) => lookupsMastodon, + (bool looksUpMastodon) => _sharedPreferences.setBool(PreferencesKey.lookupsMastodon, looksUpMastodon)); reaction( - (_) => lookupsYatService, - (bool looksUpYatService) => + (_) => lookupsYatService, + (bool looksUpYatService) => _sharedPreferences.setBool(PreferencesKey.lookupsYatService, looksUpYatService)); reaction( - (_) => lookupsUnstoppableDomains, - (bool looksUpUnstoppableDomains) => - _sharedPreferences.setBool(PreferencesKey.lookupsUnstoppableDomains, looksUpUnstoppableDomains)); + (_) => lookupsUnstoppableDomains, + (bool looksUpUnstoppableDomains) => _sharedPreferences.setBool( + PreferencesKey.lookupsUnstoppableDomains, looksUpUnstoppableDomains)); reaction( - (_) => lookupsOpenAlias, - (bool looksUpOpenAlias) => + (_) => lookupsOpenAlias, + (bool looksUpOpenAlias) => _sharedPreferences.setBool(PreferencesKey.lookupsOpenAlias, looksUpOpenAlias)); - reaction( - (_) => lookupsENS, - (bool looksUpENS) => - _sharedPreferences.setBool(PreferencesKey.lookupsENS, looksUpENS)); + reaction((_) => lookupsENS, + (bool looksUpENS) => _sharedPreferences.setBool(PreferencesKey.lookupsENS, looksUpENS)); this.nodes.observe((change) { if (change.newValue != null && change.key != null) { @@ -562,6 +575,9 @@ abstract class SettingsStoreBase with Store { @observable bool useEtherscan; + @observable + bool usePolygonScan; + @observable String defaultNanoRep; @@ -651,6 +667,7 @@ abstract class SettingsStoreBase with Store { TransactionPriority? havenTransactionPriority; TransactionPriority? litecoinTransactionPriority; TransactionPriority? ethereumTransactionPriority; + TransactionPriority? polygonTransactionPriority; TransactionPriority? bitcoinCashTransactionPriority; if (sharedPreferences.getInt(PreferencesKey.havenTransactionPriority) != null) { @@ -662,9 +679,13 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority)!); } if (sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority) != null) { - ethereumTransactionPriority = bitcoin?.deserializeLitecoinTransactionPriority( + ethereumTransactionPriority = ethereum?.deserializeEthereumTransactionPriority( sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority)!); } + if (sharedPreferences.getInt(PreferencesKey.polygonTransactionPriority) != null) { + polygonTransactionPriority = polygon?.deserializePolygonTransactionPriority( + sharedPreferences.getInt(PreferencesKey.polygonTransactionPriority)!); + } if (sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority) != null) { bitcoinCashTransactionPriority = bitcoinCash?.deserializeBitcoinCashTransactionPriority( sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority)!); @@ -676,6 +697,7 @@ abstract class SettingsStoreBase with Store { litecoinTransactionPriority ??= bitcoin?.getLitecoinTransactionPriorityMedium(); ethereumTransactionPriority ??= ethereum?.getDefaultTransactionPriority(); bitcoinCashTransactionPriority ??= bitcoinCash?.getDefaultTransactionPriority(); + polygonTransactionPriority ??= polygon?.getDefaultTransactionPriority(); final currentBalanceDisplayMode = BalanceDisplayMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey)!); @@ -749,12 +771,14 @@ abstract class SettingsStoreBase with Store { final pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true; final useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true; + final usePolygonScan = sharedPreferences.getBool(PreferencesKey.usePolygonScan) ?? true; final defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? ""; final defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? ""; final lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true; final lookupsMastodon = sharedPreferences.getBool(PreferencesKey.lookupsMastodon) ?? true; final lookupsYatService = sharedPreferences.getBool(PreferencesKey.lookupsYatService) ?? true; - final lookupsUnstoppableDomains = sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true; + final lookupsUnstoppableDomains = + sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true; final lookupsOpenAlias = sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias) ?? true; final lookupsENS = sharedPreferences.getBool(PreferencesKey.lookupsENS) ?? true; @@ -774,6 +798,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); final havenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey); final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey); + final polygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey); final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); final nanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey); final moneroNode = nodeSource.get(nodeId); @@ -781,6 +806,7 @@ abstract class SettingsStoreBase with Store { final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId); final havenNode = nodeSource.get(havenNodeId); final ethereumNode = nodeSource.get(ethereumNodeId); + final polygonNode = nodeSource.get(polygonNodeId); final bitcoinCashElectrumServer = nodeSource.get(bitcoinCashElectrumServerId); final nanoNode = nodeSource.get(nanoNodeId); final nanoPowNode = powNodeSource.get(nanoPowNodeId); @@ -824,6 +850,10 @@ abstract class SettingsStoreBase with Store { nodes[WalletType.ethereum] = ethereumNode; } + if (polygonNode != null) { + nodes[WalletType.polygon] = polygonNode; + } + if (bitcoinCashElectrumServer != null) { nodes[WalletType.bitcoinCash] = bitcoinCashElectrumServer; } @@ -841,19 +871,19 @@ abstract class SettingsStoreBase with Store { }); final savedSyncAll = sharedPreferences.getBool(PreferencesKey.syncAllKey) ?? true; - return SettingsStore( - sharedPreferences: sharedPreferences, - initialShouldShowMarketPlaceInDashboard: shouldShowMarketPlaceInDashboard, - nodes: nodes, - powNodes: powNodes, - appVersion: packageInfo.version, - deviceName: deviceName, - isBitcoinBuyEnabled: isBitcoinBuyEnabled, - initialFiatCurrency: currentFiatCurrency, - initialBalanceDisplayMode: currentBalanceDisplayMode, - initialSaveRecipientAddress: shouldSaveRecipientAddress, - initialAutoGenerateSubaddressStatus: autoGenerateSubaddressStatus, - initialMoneroSeedType: moneroSeedType, + return SettingsStore( + sharedPreferences: sharedPreferences, + initialShouldShowMarketPlaceInDashboard: shouldShowMarketPlaceInDashboard, + nodes: nodes, + powNodes: powNodes, + appVersion: packageInfo.version, + deviceName: deviceName, + isBitcoinBuyEnabled: isBitcoinBuyEnabled, + initialFiatCurrency: currentFiatCurrency, + initialBalanceDisplayMode: currentBalanceDisplayMode, + initialSaveRecipientAddress: shouldSaveRecipientAddress, + initialAutoGenerateSubaddressStatus: autoGenerateSubaddressStatus, + initialMoneroSeedType: moneroSeedType, initialAppSecure: isAppSecure, initialDisableBuy: disableBuy, initialDisableSell: disableSell, @@ -869,42 +899,45 @@ abstract class SettingsStoreBase with Store { actionlistDisplayMode: actionListDisplayMode, initialPinLength: pinLength, pinTimeOutDuration: pinCodeTimeOutDuration, - seedPhraseLength: seedPhraseWordCount,initialLanguageCode: savedLanguageCode, + seedPhraseLength: seedPhraseWordCount, + initialLanguageCode: savedLanguageCode, sortBalanceBy: sortBalanceBy, pinNativeTokenAtTop: pinNativeTokenAtTop, useEtherscan: useEtherscan, + usePolygonScan: usePolygonScan, defaultNanoRep: defaultNanoRep, - defaultBananoRep: defaultBananoRep, - lookupsTwitter: lookupsTwitter, - lookupsMastodon: lookupsMastodon, - lookupsYatService: lookupsYatService, - lookupsUnstoppableDomains: lookupsUnstoppableDomains, - lookupsOpenAlias: lookupsOpenAlias, - lookupsENS: lookupsENS, - initialMoneroTransactionPriority: moneroTransactionPriority, + defaultBananoRep: defaultBananoRep, + lookupsTwitter: lookupsTwitter, + lookupsMastodon: lookupsMastodon, + lookupsYatService: lookupsYatService, + lookupsUnstoppableDomains: lookupsUnstoppableDomains, + lookupsOpenAlias: lookupsOpenAlias, + lookupsENS: lookupsENS, + initialMoneroTransactionPriority: moneroTransactionPriority, initialBitcoinTransactionPriority: bitcoinTransactionPriority, initialHavenTransactionPriority: havenTransactionPriority, initialLitecoinTransactionPriority: litecoinTransactionPriority, initialBitcoinCashTransactionPriority: bitcoinCashTransactionPriority, - initialShouldRequireTOTP2FAForAccessingWallet: shouldRequireTOTP2FAForAccessingWallet, - initialShouldRequireTOTP2FAForSendsToContact: shouldRequireTOTP2FAForSendsToContact, - initialShouldRequireTOTP2FAForSendsToNonContact: shouldRequireTOTP2FAForSendsToNonContact, - initialShouldRequireTOTP2FAForSendsToInternalWallets: - shouldRequireTOTP2FAForSendsToInternalWallets, - initialShouldRequireTOTP2FAForExchangesToInternalWallets: - shouldRequireTOTP2FAForExchangesToInternalWallets, + initialShouldRequireTOTP2FAForAccessingWallet: shouldRequireTOTP2FAForAccessingWallet, + initialShouldRequireTOTP2FAForSendsToContact: shouldRequireTOTP2FAForSendsToContact, + initialShouldRequireTOTP2FAForSendsToNonContact: shouldRequireTOTP2FAForSendsToNonContact, + initialShouldRequireTOTP2FAForSendsToInternalWallets: + shouldRequireTOTP2FAForSendsToInternalWallets, + initialShouldRequireTOTP2FAForExchangesToInternalWallets: + shouldRequireTOTP2FAForExchangesToInternalWallets, initialShouldRequireTOTP2FAForExchangesToExternalWallets: shouldRequireTOTP2FAForExchangesToExternalWallets, - initialShouldRequireTOTP2FAForAddingContacts: shouldRequireTOTP2FAForAddingContacts, - initialShouldRequireTOTP2FAForCreatingNewWallets: shouldRequireTOTP2FAForCreatingNewWallets, - initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings: - shouldRequireTOTP2FAForAllSecurityAndBackupSettings, - initialEthereumTransactionPriority: ethereumTransactionPriority, - backgroundTasks: backgroundTasks, - initialSyncMode: savedSyncMode, - initialSyncAll: savedSyncAll, - shouldShowYatPopup: shouldShowYatPopup); - } + initialShouldRequireTOTP2FAForAddingContacts: shouldRequireTOTP2FAForAddingContacts, + initialShouldRequireTOTP2FAForCreatingNewWallets: shouldRequireTOTP2FAForCreatingNewWallets, + initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings: + shouldRequireTOTP2FAForAllSecurityAndBackupSettings, + initialEthereumTransactionPriority: ethereumTransactionPriority, + initialPolygonTransactionPriority: polygonTransactionPriority, + backgroundTasks: backgroundTasks, + initialSyncMode: savedSyncMode, + initialSyncAll: savedSyncAll, + shouldShowYatPopup: shouldShowYatPopup); + } Future reload({required Box nodeSource}) async { final sharedPreferences = await getIt.getAsync(); @@ -934,6 +967,11 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority)!) ?? priority[WalletType.ethereum]!; } + if (sharedPreferences.getInt(PreferencesKey.polygonTransactionPriority) != null) { + priority[WalletType.polygon] = polygon?.deserializePolygonTransactionPriority( + sharedPreferences.getInt(PreferencesKey.polygonTransactionPriority)!) ?? + priority[WalletType.polygon]!; + } if (sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority) != null) { priority[WalletType.bitcoinCash] = bitcoinCash?.deserializeBitcoinCashTransactionPriority( sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority)!) ?? @@ -1027,12 +1065,14 @@ abstract class SettingsStoreBase with Store { .values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? sortBalanceBy.index]; pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true; useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true; + usePolygonScan = sharedPreferences.getBool(PreferencesKey.usePolygonScan) ?? true; defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? ""; defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? ""; lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true; lookupsMastodon = sharedPreferences.getBool(PreferencesKey.lookupsMastodon) ?? true; lookupsYatService = sharedPreferences.getBool(PreferencesKey.lookupsYatService) ?? true; - lookupsUnstoppableDomains = sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true; + lookupsUnstoppableDomains = + sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true; lookupsOpenAlias = sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias) ?? true; lookupsENS = sharedPreferences.getBool(PreferencesKey.lookupsENS) ?? true; @@ -1045,6 +1085,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); final havenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey); final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey); + final polygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey); final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); final nanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); final moneroNode = nodeSource.get(nodeId); @@ -1052,6 +1093,7 @@ abstract class SettingsStoreBase with Store { final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId); final havenNode = nodeSource.get(havenNodeId); final ethereumNode = nodeSource.get(ethereumNodeId); + final polygonNode = nodeSource.get(polygonNodeId); final bitcoinCashNode = nodeSource.get(bitcoinCashElectrumServerId); final nanoNode = nodeSource.get(nanoNodeId); @@ -1075,6 +1117,10 @@ abstract class SettingsStoreBase with Store { nodes[WalletType.ethereum] = ethereumNode; } + if (polygonNode != null) { + nodes[WalletType.polygon] = polygonNode; + } + if (bitcoinCashNode != null) { nodes[WalletType.bitcoinCash] = bitcoinCashNode; } @@ -1110,6 +1156,9 @@ abstract class SettingsStoreBase with Store { case WalletType.nano: await _sharedPreferences.setInt(PreferencesKey.currentNanoNodeIdKey, node.key as int); break; + case WalletType.polygon: + await _sharedPreferences.setInt(PreferencesKey.currentPolygonNodeIdKey, node.key as int); + break; default: break; } @@ -1141,7 +1190,6 @@ abstract class SettingsStoreBase with Store { trocadorProviderStates[providerName] = state; } - static Future _getDeviceName() async { String? deviceName = ''; final deviceInfoPlugin = DeviceInfoPlugin(); diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index 9366985b5..5c95ab3ab 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -1,5 +1,6 @@ import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/sort_balance_types.dart'; +import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/balance.dart'; @@ -81,7 +82,7 @@ abstract class BalanceViewModelBase with Store { bool get isFiatDisabled => settingsStore.fiatApiMode == FiatApiMode.disabled; @computed - bool get isHomeScreenSettingsEnabled => wallet.type == WalletType.ethereum; + bool get isHomeScreenSettingsEnabled => isEVMCompatibleChain(wallet.type); @computed bool get hasAccounts => wallet.type == WalletType.monero; @@ -123,6 +124,7 @@ abstract class BalanceViewModelBase with Store { case WalletType.monero: case WalletType.haven: case WalletType.ethereum: + case WalletType.polygon: return S.current.xmr_available_balance; default: return S.current.confirmed; @@ -135,6 +137,7 @@ abstract class BalanceViewModelBase with Store { case WalletType.monero: case WalletType.haven: case WalletType.ethereum: + case WalletType.polygon: return S.current.xmr_full_balance; default: return S.current.unconfirmed; @@ -272,7 +275,8 @@ abstract class BalanceViewModelBase with Store { } @computed - bool get hasAdditionalBalance => wallet.type != WalletType.ethereum; + bool get hasAdditionalBalance => !isEVMCompatibleChain(wallet.type); + @computed List get formattedBalances { diff --git a/lib/view_model/dashboard/home_settings_view_model.dart b/lib/view_model/dashboard/home_settings_view_model.dart index 66620f951..fc2c27a7c 100644 --- a/lib/view_model/dashboard/home_settings_view_model.dart +++ b/lib/view_model/dashboard/home_settings_view_model.dart @@ -2,10 +2,12 @@ import 'package:cake_wallet/core/fiat_conversion_service.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/sort_balance_types.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/erc20_token.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; part 'home_settings_view_model.g.dart'; @@ -42,18 +44,41 @@ abstract class HomeSettingsViewModelBase with Store { void setPinNativeToken(bool value) => _settingsStore.pinNativeTokenAtTop = value; Future addErc20Token(Erc20Token token) async { - await ethereum!.addErc20Token(_balanceViewModel.wallet, token); + if (_balanceViewModel.wallet.type == WalletType.ethereum) { + await ethereum!.addErc20Token(_balanceViewModel.wallet, token); + } + + if (_balanceViewModel.wallet.type == WalletType.polygon) { + await polygon!.addErc20Token(_balanceViewModel.wallet, token); + } + _updateTokensList(); _updateFiatPrices(token); } Future deleteErc20Token(Erc20Token token) async { - await ethereum!.deleteErc20Token(_balanceViewModel.wallet, token); + if (_balanceViewModel.wallet.type == WalletType.ethereum) { + await ethereum!.deleteErc20Token(_balanceViewModel.wallet, token); + } + + if (_balanceViewModel.wallet.type == WalletType.polygon) { + await polygon!.deleteErc20Token(_balanceViewModel.wallet, token); + } + _updateTokensList(); } - Future getErc20Token(String contractAddress) async => - await ethereum!.getErc20Token(_balanceViewModel.wallet, contractAddress); + Future getErc20Token(String contractAddress) async { + if (_balanceViewModel.wallet.type == WalletType.ethereum) { + return await ethereum!.getErc20Token(_balanceViewModel.wallet, contractAddress); + } + + if (_balanceViewModel.wallet.type == WalletType.polygon) { + return await polygon!.getErc20Token(_balanceViewModel.wallet, contractAddress); + } + + return null; + } CryptoCurrency get nativeToken => _balanceViewModel.wallet.currency; @@ -69,7 +94,12 @@ abstract class HomeSettingsViewModelBase with Store { void changeTokenAvailability(Erc20Token token, bool value) async { token.enabled = value; - ethereum!.addErc20Token(_balanceViewModel.wallet, token); + if (_balanceViewModel.wallet.type == WalletType.ethereum) { + ethereum!.addErc20Token(_balanceViewModel.wallet, token); + } + if (_balanceViewModel.wallet.type == WalletType.polygon) { + polygon!.addErc20Token(_balanceViewModel.wallet, token); + } _refreshTokensList(); } @@ -83,7 +113,8 @@ abstract class HomeSettingsViewModelBase with Store { return -1; } else if (e2.enabled && !e1.enabled) { return 1; - } else if (!e1.enabled && !e2.enabled) { // if both are disabled then sort alphabetically + } else if (!e1.enabled && !e2.enabled) { + // if both are disabled then sort alphabetically return e1.name.compareTo(e2.name); } @@ -92,11 +123,21 @@ abstract class HomeSettingsViewModelBase with Store { tokens.clear(); - tokens.addAll(ethereum! - .getERC20Currencies(_balanceViewModel.wallet) - .where((element) => _matchesSearchText(element)) - .toList() - ..sort(_sortFunc)); + if (_balanceViewModel.wallet.type == WalletType.ethereum) { + tokens.addAll(ethereum! + .getERC20Currencies(_balanceViewModel.wallet) + .where((element) => _matchesSearchText(element)) + .toList() + ..sort(_sortFunc)); + } + + if (_balanceViewModel.wallet.type == WalletType.polygon) { + tokens.addAll(polygon! + .getERC20Currencies(_balanceViewModel.wallet) + .where((element) => _matchesSearchText(element)) + .toList() + ..sort(_sortFunc)); + } } @action diff --git a/lib/view_model/dashboard/nft_view_model.dart b/lib/view_model/dashboard/nft_view_model.dart index c5acf5523..f00f929a3 100644 --- a/lib/view_model/dashboard/nft_view_model.dart +++ b/lib/view_model/dashboard/nft_view_model.dart @@ -1,10 +1,9 @@ -// ignore_for_file: public_member_api_docs, sort_constructors_first import 'dart:convert'; import 'dart:developer'; import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart'; +import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_widget.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:http/http.dart' as http; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; @@ -39,23 +38,26 @@ abstract class NFTViewModelBase with Store { @action Future getNFTAssetByWallet() async { - if (appStore.wallet!.type != WalletType.ethereum) return; + if (!isEVMCompatibleChain(appStore.wallet!.type)) return; final walletAddress = appStore.wallet!.walletInfo.address; log('Fetching wallet NFTs for $walletAddress'); + final chainName = getChainNameBasedOnWalletType(appStore.wallet!.type); // the [chain] refers to the chain network that the nft is on // the [format] refers to the number format type of the responses // the [normalizedMetadata] field is a boolean that determines if // the response would include a json string of the NFT Metadata that can be decoded // and used within the wallet + // the [excludeSpam] field is a boolean that determines if spam nfts be excluded from the response. final uri = Uri.https( 'deep-index.moralis.io', '/api/v2.2/$walletAddress/nft', { - "chain": "eth", + "chain": chainName, "format": "decimal", "media_items": "false", + "exclude_spam": "true", "normalizeMetadata": "true", }, ); @@ -94,7 +96,7 @@ abstract class NFTViewModelBase with Store { @action Future importNFT(String tokenAddress, String tokenId) async { - + final chainName = getChainNameBasedOnWalletType(appStore.wallet!.type); // the [chain] refers to the chain network that the nft is on // the [format] refers to the number format type of the responses // the [normalizedMetadata] field is a boolean that determines if @@ -104,7 +106,7 @@ abstract class NFTViewModelBase with Store { 'deep-index.moralis.io', '/api/v2.2/nft/$tokenAddress/$tokenId', { - "chain": "eth", + "chain": chainName, "format": "decimal", "media_items": "false", "normalizeMetadata": "true", diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart index fd7971001..bc7f70517 100644 --- a/lib/view_model/dashboard/transaction_list_item.dart +++ b/lib/view_model/dashboard/transaction_list_item.dart @@ -3,6 +3,7 @@ import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/nano/nano.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cake_wallet/store/settings_store.dart'; @@ -91,6 +92,13 @@ class TransactionListItem extends ActionListItem with Keyable { cryptoAmount: ethereum!.formatterEthereumAmountToDouble(transaction: transaction), price: price); break; + case WalletType.polygon: + final asset = polygon!.assetOfTransaction(balanceViewModel.wallet, transaction); + final price = balanceViewModel.fiatConvertationStore.prices[asset]; + amount = calculateFiatAmountRaw( + cryptoAmount: polygon!.formatterPolygonAmountToDouble(transaction: transaction), + price: price); + break; case WalletType.nano: amount = calculateFiatAmountRaw( cryptoAmount: double.parse(nanoUtil!.getRawAsDecimalString( diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index bc7f53af0..93877a525 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -28,10 +28,7 @@ abstract class ExchangeTradeViewModelBase with Store { required this.tradesStore, required this.sendViewModel}) : trade = tradesStore.trade!, - isSendable = tradesStore.trade!.from == wallet.currency || - tradesStore.trade!.provider == ExchangeProviderDescription.xmrto || - (wallet.currency == CryptoCurrency.eth && - tradesStore.trade!.from.tag == CryptoCurrency.eth.title), + isSendable = _checkIfCanSend(tradesStore, wallet), items = ObservableList() { switch (trade.provider) { case ExchangeProviderDescription.changeNow: @@ -155,4 +152,19 @@ abstract class ExchangeTradeViewModelBase with Store { isCopied: true), ]); } + + static bool _checkIfCanSend(TradesStore tradesStore, WalletBase wallet) { + bool _isEthToken() => + wallet.currency == CryptoCurrency.eth && + tradesStore.trade!.from.tag == CryptoCurrency.eth.title; + + bool _isPolygonToken() => + wallet.currency == CryptoCurrency.maticpoly && + tradesStore.trade!.from.tag == CryptoCurrency.maticpoly.tag; + + return tradesStore.trade!.from == wallet.currency || + tradesStore.trade!.provider == ExchangeProviderDescription.xmrto || + _isEthToken() || + _isPolygonToken(); + } } diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 80c331ab2..fb7019885 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -23,6 +23,7 @@ import 'package:cake_wallet/exchange/trade.dart'; import 'package:cake_wallet/exchange/trade_request.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/monero/monero.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/dashboard/trades_store.dart'; import 'package:cake_wallet/store/settings_store.dart'; @@ -287,6 +288,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with return transactionPriority == ethereum!.getEthereumTransactionPrioritySlow(); case WalletType.bitcoinCash: return transactionPriority == bitcoinCash!.getBitcoinCashTransactionPrioritySlow(); + case WalletType.polygon: + return transactionPriority == polygon!.getPolygonTransactionPrioritySlow(); default: return false; } @@ -626,6 +629,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with depositCurrency = CryptoCurrency.nano; receiveCurrency = CryptoCurrency.xmr; break; + case WalletType.polygon: + depositCurrency = CryptoCurrency.maticpoly; + receiveCurrency = CryptoCurrency.xmr; + break; default: break; } @@ -713,6 +720,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with case WalletType.bitcoinCash: _settingsStore.priority[wallet.type] = bitcoinCash!.getDefaultTransactionPriority(); break; + case WalletType.polygon: + _settingsStore.priority[wallet.type] = polygon!.getDefaultTransactionPriority(); + break; default: break; } diff --git a/lib/view_model/node_list/node_list_view_model.dart b/lib/view_model/node_list/node_list_view_model.dart index ae0edba30..0cd4d7491 100644 --- a/lib/view_model/node_list/node_list_view_model.dart +++ b/lib/view_model/node_list/node_list_view_model.dart @@ -72,6 +72,9 @@ abstract class NodeListViewModelBase with Store { case WalletType.nano: node = getNanoDefaultNode(nodes: _nodeSource)!; break; + case WalletType.polygon: + node = getPolygonDefaultNode(nodes: _nodeSource)!; + break; default: throw Exception('Unexpected wallet type: ${_appStore.wallet!.type}'); } diff --git a/lib/view_model/restore/restore_from_qr_vm.dart b/lib/view_model/restore/restore_from_qr_vm.dart index 4ffc81cef..c8637c4be 100644 --- a/lib/view_model/restore/restore_from_qr_vm.dart +++ b/lib/view_model/restore/restore_from_qr_vm.dart @@ -2,6 +2,7 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/nano/nano.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/view_model/restore/restore_mode.dart'; import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; import 'package:hive/hive.dart'; @@ -71,6 +72,9 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store case WalletType.ethereum: return ethereum!.createEthereumRestoreWalletFromPrivateKey( name: name, password: password, privateKey: restoreWallet.privateKey!); + case WalletType.polygon: + return polygon!.createPolygonRestoreWalletFromPrivateKey( + name: name, password: password, privateKey: restoreWallet.privateKey!); default: throw Exception('Unexpected type: ${restoreWallet.type.toString()}'); } @@ -95,6 +99,9 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store case WalletType.nano: return nano!.createNanoRestoreWalletFromSeedCredentials( name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); + case WalletType.polygon: + return polygon!.createPolygonRestoreWalletFromSeedCredentials( + name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); default: throw Exception('Unexpected type: ${type.toString()}'); } diff --git a/lib/view_model/restore/wallet_restore_from_qr_code.dart b/lib/view_model/restore/wallet_restore_from_qr_code.dart index 6085f4354..bfc9b7980 100644 --- a/lib/view_model/restore/wallet_restore_from_qr_code.dart +++ b/lib/view_model/restore/wallet_restore_from_qr_code.dart @@ -26,6 +26,7 @@ class WalletRestoreFromQRCode { 'litecoin-wallet': WalletType.litecoin, 'litecoin_wallet': WalletType.litecoin, 'ethereum-wallet': WalletType.ethereum, + 'polygon-wallet': WalletType.polygon, 'nano-wallet': WalletType.nano, 'nano_wallet': WalletType.nano, 'bitcoincash': WalletType.bitcoinCash, @@ -157,7 +158,16 @@ class WalletRestoreFromQRCode { return WalletRestoreMode.keys; } - if ((type == WalletType.nano || type == WalletType.banano) && credentials.containsKey('hexSeed')) { + if (type == WalletType.polygon && credentials.containsKey('private_key')) { + final privateKey = credentials['private_key'] as String; + if (privateKey.isEmpty) { + throw Exception('Unexpected restore mode: private_key'); + } + return WalletRestoreMode.keys; + } + + if ((type == WalletType.nano || type == WalletType.banano) && + credentials.containsKey('hexSeed')) { final hexSeed = credentials['hexSeed'] as String; if (hexSeed.isEmpty) { throw Exception('Unexpected restore mode: hexSeed'); diff --git a/lib/view_model/send/output.dart b/lib/view_model/send/output.dart index 2e696e16f..73fb535f2 100644 --- a/lib/view_model/send/output.dart +++ b/lib/view_model/send/output.dart @@ -4,6 +4,8 @@ import 'package:cake_wallet/entities/parse_address_from_domain.dart'; import 'package:cake_wallet/entities/parsed_address.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/haven/haven.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/src/screens/send/widgets/extract_address_from_parsed.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:flutter/material.dart'; @@ -27,7 +29,8 @@ const String cryptoNumberPattern = '0.0'; class Output = OutputBase with _$Output; abstract class OutputBase with Store { - OutputBase(this._wallet, this._settingsStore, this._fiatConversationStore, this.cryptoCurrencyHandler) + OutputBase( + this._wallet, this._settingsStore, this._fiatConversationStore, this.cryptoCurrencyHandler) : _cryptoNumberFormat = NumberFormat(cryptoNumberPattern), key = UniqueKey(), sendAll = false, @@ -65,8 +68,7 @@ abstract class OutputBase with Store { @computed bool get isParsedAddress => - parsedAddress.parseFrom != ParseFrom.notParsed && - parsedAddress.name.isNotEmpty; + parsedAddress.parseFrom != ParseFrom.notParsed && parsedAddress.name.isNotEmpty; @computed int get formattedCryptoAmount { @@ -83,8 +85,7 @@ abstract class OutputBase with Store { case WalletType.bitcoin: case WalletType.litecoin: case WalletType.bitcoinCash: - _amount = - bitcoin!.formatterStringDoubleToBitcoinAmount(_cryptoAmount); + _amount = bitcoin!.formatterStringDoubleToBitcoinAmount(_cryptoAmount); break; case WalletType.haven: _amount = haven!.formatterMoneroParseAmount(amount: _cryptoAmount); @@ -92,6 +93,9 @@ abstract class OutputBase with Store { case WalletType.ethereum: _amount = ethereum!.formatterEthereumParseAmount(_cryptoAmount); break; + case WalletType.polygon: + _amount = polygon!.formatterPolygonParseAmount(_cryptoAmount); + break; default: break; } @@ -130,6 +134,10 @@ abstract class OutputBase with Store { if (_wallet.type == WalletType.ethereum) { return ethereum!.formatterEthereumAmountToDouble(amount: BigInt.from(fee)); } + + if (_wallet.type == WalletType.polygon) { + return polygon!.formatterPolygonAmountToDouble(amount: BigInt.from(fee)); + } } catch (e) { print(e.toString()); } @@ -140,10 +148,11 @@ abstract class OutputBase with Store { @computed String get estimatedFeeFiatAmount { try { - final currency = _wallet.type == WalletType.ethereum ? _wallet.currency : cryptoCurrencyHandler(); + final currency = isEVMCompatibleChain(_wallet.type) + ? _wallet.currency + : cryptoCurrencyHandler(); final fiat = calculateFiatAmountRaw( - price: _fiatConversationStore.prices[currency]!, - cryptoAmount: estimatedFee); + price: _fiatConversationStore.prices[currency]!, cryptoAmount: estimatedFee); return fiat; } catch (_) { return '0.00'; @@ -240,6 +249,7 @@ abstract class OutputBase with Store { maximumFractionDigits = 12; break; case WalletType.ethereum: + case WalletType.polygon: maximumFractionDigits = 12; break; default: diff --git a/lib/view_model/send/send_template_view_model.dart b/lib/view_model/send/send_template_view_model.dart index b881ed71f..007c4b8c0 100644 --- a/lib/view_model/send/send_template_view_model.dart +++ b/lib/view_model/send/send_template_view_model.dart @@ -50,7 +50,9 @@ abstract class SendTemplateViewModelBase with Store { TemplateValidator get templateValidator => TemplateValidator(); bool get hasMultiRecipient => - _wallet.type != WalletType.haven && _wallet.type != WalletType.ethereum; + _wallet.type != WalletType.haven && + _wallet.type != WalletType.ethereum && + _wallet.type != WalletType.polygon; @computed CryptoCurrency get cryptoCurrency => _wallet.currency; diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index be822aff3..885e2efe0 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -5,6 +5,8 @@ import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/core/wallet_change_listener_view_model.dart'; import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/entities/wallet_contact.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; @@ -42,7 +44,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor void onWalletChange(wallet) { currencies = wallet.balance.keys.toList(); selectedCryptoCurrency = wallet.currency; - hasMultipleTokens = wallet.type == WalletType.ethereum; + hasMultipleTokens = isEVMCompatibleChain(wallet.type); } SendViewModelBase( @@ -55,7 +57,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor ) : state = InitialExecutionState(), currencies = appStore.wallet!.balance.keys.toList(), selectedCryptoCurrency = appStore.wallet!.currency, - hasMultipleTokens = appStore.wallet!.type == WalletType.ethereum, + hasMultipleTokens = isEVMCompatibleChain(appStore.wallet!.type), outputs = ObservableList(), _settingsStore = appStore.settingsStore, fiatFromSettings = appStore.settingsStore.fiatCurrency, @@ -119,7 +121,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor try { if (pendingTransaction != null) { final currency = - walletType == WalletType.ethereum ? wallet.currency : selectedCryptoCurrency; + isEVMCompatibleChain(walletType) ? wallet.currency : selectedCryptoCurrency; final fiat = calculateFiatAmount( price: _fiatConversationStore.prices[currency]!, cryptoAmount: pendingTransaction!.feeFormatted); @@ -372,6 +374,9 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor priority: priority!, currency: selectedCryptoCurrency); case WalletType.nano: return nano!.createNanoTransactionCredentials(outputs); + case WalletType.polygon: + return polygon!.createPolygonTransactionCredentials(outputs, + priority: priority!, currency: selectedCryptoCurrency); default: throw Exception('Unexpected wallet type: ${wallet.type}'); } @@ -412,11 +417,15 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor WalletType walletType, CryptoCurrency currency, ) { - if (walletType == WalletType.ethereum || walletType == WalletType.haven) { + if (walletType == WalletType.ethereum || + walletType == WalletType.polygon || + walletType == WalletType.haven) { if (error.contains('gas required exceeds allowance') || error.contains('insufficient funds for')) { return S.current.do_not_have_enough_gas_asset(currency.toString()); } + + return error; } return error; diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart index b3ffeb353..e4dd86b37 100644 --- a/lib/view_model/settings/privacy_settings_view_model.dart +++ b/lib/view_model/settings/privacy_settings_view_model.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/transaction_history.dart'; @@ -12,8 +13,7 @@ import 'package:cake_wallet/entities/fiat_api_mode.dart'; part 'privacy_settings_view_model.g.dart'; -class -PrivacySettingsViewModel = PrivacySettingsViewModelBase with _$PrivacySettingsViewModel; +class PrivacySettingsViewModel = PrivacySettingsViewModelBase with _$PrivacySettingsViewModel; abstract class PrivacySettingsViewModelBase with Store { PrivacySettingsViewModelBase(this._settingsStore, this._wallet); @@ -58,6 +58,9 @@ abstract class PrivacySettingsViewModelBase with Store { @computed bool get useEtherscan => _settingsStore.useEtherscan; + @computed + bool get usePolygonScan => _settingsStore.usePolygonScan; + @computed bool get lookupTwitter => _settingsStore.lookupsTwitter; @@ -78,6 +81,8 @@ abstract class PrivacySettingsViewModelBase with Store { bool get canUseEtherscan => _wallet.type == WalletType.ethereum; + bool get canUsePolygonScan => _wallet.type == WalletType.polygon; + @action void setShouldSaveRecipientAddress(bool value) => _settingsStore.shouldSaveRecipientAddress = value; @@ -120,4 +125,10 @@ abstract class PrivacySettingsViewModelBase with Store { _settingsStore.useEtherscan = value; ethereum!.updateEtherscanUsageState(_wallet, value); } + + @action + void setUsePolygonScan(bool value) { + _settingsStore.usePolygonScan = value; + polygon!.updatePolygonScanUsageState(_wallet, value); + } } diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index a8c892284..4e17866cb 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -51,6 +51,9 @@ abstract class TransactionDetailsViewModelBase with Store { case WalletType.nano: _addNanoListItems(tx, dateFormat); break; + case WalletType.polygon: + _addPolygonListItems(tx, dateFormat); + break; default: break; } @@ -125,7 +128,9 @@ abstract class TransactionDetailsViewModelBase with Store { case WalletType.nano: return 'https://nanolooker.com/block/${txId}'; case WalletType.banano: - return 'https://bananolooker.com/block/${txId}'; + return 'https://bananolooker.com/block/${txId}'; + case WalletType.polygon: + return 'https://polygonscan.com/tx/${txId}'; default: return ''; } @@ -148,6 +153,8 @@ abstract class TransactionDetailsViewModelBase with Store { return S.current.view_transaction_on + 'nanolooker.com'; case WalletType.banano: return S.current.view_transaction_on + 'bananolooker.com'; + case WalletType.polygon: + return S.current.view_transaction_on + 'polygonscan.com'; default: return ''; } @@ -237,7 +244,6 @@ abstract class TransactionDetailsViewModelBase with Store { items.addAll(_items); } - void _addNanoListItems(TransactionInfo tx, DateFormat dateFormat) { final _items = [ StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.id), @@ -250,4 +256,21 @@ abstract class TransactionDetailsViewModelBase with Store { items.addAll(_items); } + + void _addPolygonListItems(TransactionInfo tx, DateFormat dateFormat) { + final _items = [ + StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.id), + StandartListItem( + title: S.current.transaction_details_date, value: dateFormat.format(tx.date)), + StandartListItem(title: S.current.confirmations, value: tx.confirmations.toString()), + StandartListItem(title: S.current.transaction_details_height, value: '${tx.height}'), + StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()), + if (tx.feeFormatted()?.isNotEmpty ?? false) + StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!), + if (showRecipientAddress && tx.to != null) + StandartListItem(title: S.current.transaction_details_recipient_address, value: tx.to!), + ]; + + items.addAll(_items); + } } diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index 4d5eefdb7..ade279124 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/core/wallet_change_listener_view_model.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:cw_core/currency.dart'; @@ -139,6 +140,22 @@ class NanoURI extends PaymentURI { } } +class PolygonURI extends PaymentURI { + PolygonURI({required String amount, required String address}) + : super(amount: amount, address: address); + + @override + String toString() { + var base = 'polygon:' + address; + + if (amount.isNotEmpty) { + base += '?amount=${amount.replaceAll(',', '.')}'; + } + + return base; + } +} + abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewModel with Store { WalletAddressListViewModelBase({ required AppStore appStore, @@ -216,6 +233,10 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo return NanoURI(amount: amount, address: address.address); } + if (wallet.type == WalletType.polygon) { + return PolygonURI(amount: amount, address: address.address); + } + throw Exception('Unexpected type: ${type.toString()}'); } @@ -272,6 +293,12 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo addressList.add(WalletAddressListItem(isPrimary: true, name: null, address: primaryAddress)); } + if (wallet.type == WalletType.polygon) { + final primaryAddress = polygon!.getAddress(wallet); + + addressList.add(WalletAddressListItem(isPrimary: true, name: null, address: primaryAddress)); + } + return addressList; } diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart index d9de9473d..56ca190be 100644 --- a/lib/view_model/wallet_keys_view_model.dart +++ b/lib/view_model/wallet_keys_view_model.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_info.dart'; @@ -19,7 +20,8 @@ abstract class WalletKeysViewModelBase with Store { : title = _appStore.wallet!.type == WalletType.bitcoin || _appStore.wallet!.type == WalletType.litecoin || _appStore.wallet!.type == WalletType.bitcoinCash || - _appStore.wallet!.type == WalletType.ethereum + _appStore.wallet!.type == WalletType.ethereum || + _appStore.wallet!.type == WalletType.polygon ? S.current.wallet_seed : S.current.wallet_keys, _restoreHeight = _appStore.wallet!.walletInfo.restoreHeight, @@ -98,7 +100,7 @@ abstract class WalletKeysViewModelBase with Store { ]); } - if (_appStore.wallet!.type == WalletType.ethereum) { + if (isEVMCompatibleChain(_appStore.wallet!.type)) { items.addAll([ if (_appStore.wallet!.privateKey != null) StandartListItem(title: S.current.private_key, value: _appStore.wallet!.privateKey!), @@ -151,6 +153,8 @@ abstract class WalletKeysViewModelBase with Store { return 'nano-wallet'; case WalletType.banano: return 'banano-wallet'; + case WalletType.polygon: + return 'polygon-wallet'; default: throw Exception('Unexpected wallet type: ${_appStore.wallet!.toString()}'); } diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart index a36d68482..5e508d646 100644 --- a/lib/view_model/wallet_new_vm.dart +++ b/lib/view_model/wallet_new_vm.dart @@ -14,6 +14,8 @@ import 'package:cake_wallet/view_model/wallet_creation_vm.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/haven/haven.dart'; +import '../polygon/polygon.dart'; + part 'wallet_new_vm.g.dart'; class WalletNewVM = WalletNewVMBase with _$WalletNewVM; @@ -52,6 +54,8 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { return bitcoinCash!.createBitcoinCashNewWalletCredentials(name: name); case WalletType.nano: return nano!.createNanoNewWalletCredentials(name: name); + case WalletType.polygon: + return polygon!.createPolygonNewWalletCredentials(name: name); default: throw Exception('Unexpected type: ${type.toString()}'); } diff --git a/lib/view_model/wallet_restore_view_model.dart b/lib/view_model/wallet_restore_view_model.dart index 058948c2f..8d1e3b223 100644 --- a/lib/view_model/wallet_restore_view_model.dart +++ b/lib/view_model/wallet_restore_view_model.dart @@ -3,6 +3,7 @@ import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/store/app_store.dart'; @@ -28,7 +29,10 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { : hasSeedLanguageSelector = type == WalletType.monero || type == WalletType.haven, hasBlockchainHeightLanguageSelector = type == WalletType.monero || type == WalletType.haven, hasRestoreFromPrivateKey = - type == WalletType.ethereum || type == WalletType.nano || type == WalletType.banano, + type == WalletType.ethereum || + type == WalletType.polygon || + type == WalletType.nano || + type == WalletType.banano, isButtonEnabled = false, mode = WalletRestoreMode.seed, super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: true) { @@ -36,6 +40,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { case WalletType.monero: case WalletType.haven: case WalletType.ethereum: + case WalletType.polygon: availableModes = WalletRestoreMode.values; break; case WalletType.nano: @@ -107,6 +112,12 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { mnemonic: seed, password: password, derivationType: derivationType); + case WalletType.polygon: + return polygon!.createPolygonRestoreWalletFromSeedCredentials( + name: name, + mnemonic: seed, + password: password, + ); default: break; } @@ -153,6 +164,12 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { password: password, seedKey: options['private_key'] as String, derivationType: options["derivationType"] as DerivationType); + case WalletType.polygon: + return polygon!.createPolygonRestoreWalletFromPrivateKey( + name: name, + password: password, + privateKey: options['private_key'] as String, + ); default: break; } diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 329732075..c1659f4cc 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -41,6 +41,7 @@ PODS: - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS + - tor (0.0.1) - url_launcher_macos (0.0.1): - FlutterMacOS - wakelock_plus (0.0.1): @@ -59,6 +60,7 @@ DEPENDENCIES: - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`) - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) + - tor (from `Flutter/ephemeral/.symlinks/plugins/tor/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`) @@ -91,6 +93,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos shared_preferences_foundation: :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin + tor: + :path: Flutter/ephemeral/.symlinks/plugins/tor/macos url_launcher_macos: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos wakelock_plus: @@ -98,7 +102,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308 - cw_monero: ec03de55a19c4a2b174ea687e0f4202edc716fa4 + cw_monero: f8b7f104508efba2591548e76b5c058d05cba3f0 device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225 flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea @@ -110,6 +114,7 @@ SPEC CHECKSUMS: ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4 shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 + tor: 2138c48428e696b83eacdda404de6d5574932e26 url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269 diff --git a/model_generator.sh b/model_generator.sh index 50cb3d353..32d863aeb 100755 --- a/model_generator.sh +++ b/model_generator.sh @@ -5,4 +5,5 @@ cd cw_haven && flutter pub get && flutter packages pub run build_runner build -- cd cw_ethereum && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_polygon && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs \ No newline at end of file diff --git a/pubspec_base.yaml b/pubspec_base.yaml index f71d38578..d0a295047 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -147,6 +147,7 @@ flutter: - assets/bitcoin_cash_electrum_server_list.yml - assets/nano_node_list.yml - assets/nano_pow_node_list.yml + - assets/polygon_node_list.yml - assets/text/ - assets/faq/ - assets/animation/ diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 6158342f3..45ad96764 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -745,5 +745,6 @@ "seedtype_polyseed": "بوليسيد (16 كلمة)", "seed_language_czech": "التشيكية", "seed_language_korean": "الكورية", - "seed_language_chinese_traditional": "تقاليد صينية)" + "seed_language_chinese_traditional": "تقاليد صينية)", + "polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 8c3a528bb..d52843798 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -741,5 +741,6 @@ "seedtype_polyseed": "Поли семе (16 думи)", "seed_language_czech": "Чех", "seed_language_korean": "Корейски", - "seed_language_chinese_traditional": "Традиционен китайски)" + "seed_language_chinese_traditional": "Традиционен китайски)", + "polygonscan_history": "История на PolygonScan" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 64f2b45e5..3e1d68543 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -741,5 +741,6 @@ "seedtype_polyseed": "Polyseed (16 slov)", "seed_language_czech": "čeština", "seed_language_korean": "korejština", - "seed_language_chinese_traditional": "Číňan (tradiční)" + "seed_language_chinese_traditional": "Číňan (tradiční)", + "polygonscan_history": "Historie PolygonScan" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 2bb9e1404..62a73361c 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -749,5 +749,6 @@ "seedtype_polyseed": "Polyseed (16 Wörter)", "seed_language_czech": "Tschechisch", "seed_language_korean": "Koreanisch", - "seed_language_chinese_traditional": "Chinesisch (Traditionell)" + "seed_language_chinese_traditional": "Chinesisch (Traditionell)", + "polygonscan_history": "PolygonScan-Verlauf" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 88949525c..19c435ce8 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -750,5 +750,6 @@ "seedtype_polyseed": "Polyseed (16 words)", "seed_language_czech": "Czech", "seed_language_korean": "Korean", - "seed_language_chinese_traditional": "Chinese (Traditional)" + "seed_language_chinese_traditional": "Chinese (Traditional)", + "polygonscan_history": "PolygonScan history" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 7a3907fb2..2b94e51b9 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -749,5 +749,6 @@ "seedtype_polyseed": "Polieta (16 palabras)", "seed_language_czech": "checo", "seed_language_korean": "coreano", - "seed_language_chinese_traditional": "Chino (tradicional)" + "seed_language_chinese_traditional": "Chino (tradicional)", + "polygonscan_history": "Historial de PolygonScan" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 0b2f54c6c..0c71ba06e 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -749,5 +749,6 @@ "seedtype_polyseed": "Polyseed (16 mots)", "seed_language_czech": "tchèque", "seed_language_korean": "coréen", - "seed_language_chinese_traditional": "Chinois (Traditionnel)" + "seed_language_chinese_traditional": "Chinois (Traditionnel)", + "polygonscan_history": "Historique de PolygonScan" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 107599684..0eb9bc7cd 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -727,5 +727,6 @@ "seedtype_polyseed": "Polyseed (16 kalmomi)", "seed_language_czech": "Czech", "seed_language_korean": "Yaren Koriya", - "seed_language_chinese_traditional": "Sinanci (na gargajiya)" + "seed_language_chinese_traditional": "Sinanci (na gargajiya)", + "polygonscan_history": "PolygonScan tarihin kowane zamani" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 20cf5dd40..c4c11fa58 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -749,5 +749,6 @@ "seedtype_polyseed": "पॉलीसीड (16 शब्द)", "seed_language_czech": "चेक", "seed_language_korean": "कोरियाई", - "seed_language_chinese_traditional": "चीनी पारंपरिक)" + "seed_language_chinese_traditional": "चीनी पारंपरिक)", + "polygonscan_history": "पॉलीगॉनस्कैन इतिहास" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 156d885ea..82df37e69 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -747,5 +747,6 @@ "seedtype_polyseed": "Poliseed (16 riječi)", "seed_language_czech": "češki", "seed_language_korean": "korejski", - "seed_language_chinese_traditional": "Kinesko (tradicionalno)" + "seed_language_chinese_traditional": "Kinesko (tradicionalno)", + "polygonscan_history": "Povijest PolygonScan" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index c6836b65b..de04ecb12 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -737,5 +737,6 @@ "seedtype_polyseed": "Polyseed (16 kata)", "seed_language_czech": "Ceko", "seed_language_korean": "Korea", - "seed_language_chinese_traditional": "Cina (tradisional)" + "seed_language_chinese_traditional": "Cina (tradisional)", + "polygonscan_history": "Sejarah PolygonScan" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 1d6d355b6..acb7a71c3 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -749,5 +749,6 @@ "seedtype_polyseed": "Polyseed (16 parole)", "seed_language_czech": "ceco", "seed_language_korean": "coreano", - "seed_language_chinese_traditional": "Cinese tradizionale)" + "seed_language_chinese_traditional": "Cinese tradizionale)", + "polygonscan_history": "Cronologia PolygonScan" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 595a348d3..7907d3835 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -749,5 +749,6 @@ "seedtype_polyseed": "ポリシード(16語)", "seed_language_czech": "チェコ", "seed_language_korean": "韓国語", - "seed_language_chinese_traditional": "中国の伝統的な)" + "seed_language_chinese_traditional": "中国の伝統的な)", + "polygonscan_history": "ポリゴンスキャン履歴" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 0b0fff282..e9a54974e 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -747,5 +747,6 @@ "seedtype_polyseed": "다문 (16 단어)", "seed_language_czech": "체코 사람", "seed_language_korean": "한국인", - "seed_language_chinese_traditional": "중국 전통)" + "seed_language_chinese_traditional": "중국 전통)", + "polygonscan_history": "다각형 스캔 기록" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index fea305f2d..02e3d38c2 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -747,5 +747,6 @@ "seedtype_polyseed": "polyseed (စကားလုံး 16 လုံး)", "seed_language_czech": "ချက်", "seed_language_korean": "ကိုးရီးယား", - "seed_language_chinese_traditional": "တရုတ်ရိုးရာ)" + "seed_language_chinese_traditional": "တရုတ်ရိုးရာ)", + "polygonscan_history": "PolygonScan မှတ်တမ်း" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index e400de4c6..4fd0fbab7 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -749,5 +749,6 @@ "seedtype_polyseed": "Polyseed (16 woorden)", "seed_language_czech": "Tsjechisch", "seed_language_korean": "Koreaans", - "seed_language_chinese_traditional": "Chinese (traditionele)" + "seed_language_chinese_traditional": "Chinese (traditionele)", + "polygonscan_history": "PolygonScan-geschiedenis" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 698115f8b..bf3cc5329 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -749,5 +749,6 @@ "seedtype_polyseed": "Poliqueed (16 słów)", "seed_language_czech": "Czech", "seed_language_korean": "koreański", - "seed_language_chinese_traditional": "Chiński tradycyjny)" + "seed_language_chinese_traditional": "Chiński tradycyjny)", + "polygonscan_history": "Historia PolygonScan" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 9a926834a..ba4beb6c5 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -748,5 +748,6 @@ "seedtype_polyseed": "Polyseed (16 palavras)", "seed_language_czech": "Tcheco", "seed_language_korean": "coreano", - "seed_language_chinese_traditional": "Chinês tradicional)" + "seed_language_chinese_traditional": "Chinês tradicional)", + "polygonscan_history": "História do PolygonScan" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index e2a09009d..83a1aaf2b 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -749,5 +749,6 @@ "seedtype_polyseed": "Полиса (16 слов)", "seed_language_czech": "Чешский", "seed_language_korean": "Корейский", - "seed_language_chinese_traditional": "Китайский традиционный)" + "seed_language_chinese_traditional": "Китайский традиционный)", + "polygonscan_history": "История PolygonScan" } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index a4d7f405e..e046eaba8 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -747,5 +747,6 @@ "seedtype_polyseed": "โพลีส (16 คำ)", "seed_language_czech": "ภาษาเช็ก", "seed_language_korean": "เกาหลี", - "seed_language_chinese_traditional": "จีน (ดั้งเดิม)" + "seed_language_chinese_traditional": "จีน (ดั้งเดิม)", + "polygonscan_history": "ประวัติ PolygonScan" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 04ba2af6d..06ee4bc89 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -743,5 +743,6 @@ "seedtype_polyseed": "Polyseed (16 na salita)", "seed_language_czech": "Czech", "seed_language_korean": "Korean", - "seed_language_chinese_traditional": "Intsik (tradisyonal)" + "seed_language_chinese_traditional": "Intsik (tradisyonal)", + "polygonscan_history": "Kasaysayan ng PolygonScan" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index b7b5d33f8..f300951ba 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -747,5 +747,6 @@ "seedtype_polyseed": "Polyseed (16 kelime)", "seed_language_czech": "Çek", "seed_language_korean": "Koreli", - "seed_language_chinese_traditional": "Çin geleneği)" + "seed_language_chinese_traditional": "Çin geleneği)", + "polygonscan_history": "PolygonScan geçmişi" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 900e95acc..6f8d87e86 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -749,5 +749,6 @@ "seedtype_polyseed": "Полісей (16 слів)", "seed_language_czech": "Чеський", "seed_language_korean": "Корейський", - "seed_language_chinese_traditional": "Китайський (традиційний)" + "seed_language_chinese_traditional": "Китайський (традиційний)", + "polygonscan_history": "Історія PolygonScan" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 5535bdf73..f75d287ef 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -741,5 +741,6 @@ "seedtype_polyseed": "پالیسیڈ (16 الفاظ)", "seed_language_czech": "چیک", "seed_language_korean": "کورین", - "seed_language_chinese_traditional": "چینی (روایتی)" + "seed_language_chinese_traditional": "چینی (روایتی)", + "polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index a867778f4..b5937a49c 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -743,5 +743,6 @@ "seedtype_polyseed": "Polyseed (awọn ọrọ 16)", "seed_language_czech": "Czech", "seed_language_korean": "Ara ẹni", - "seed_language_chinese_traditional": "Kannada (ibile)" + "seed_language_chinese_traditional": "Kannada (ibile)", + "polygonscan_history": "PolygonScan itan" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 7762af3a0..b487f83f5 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -748,5 +748,6 @@ "seedtype_polyseed": "多种物品(16个单词)", "seed_language_czech": "捷克", "seed_language_korean": "韩国人", - "seed_language_chinese_traditional": "中国传统的)" + "seed_language_chinese_traditional": "中国传统的)", + "polygonscan_history": "多边形扫描历史" } diff --git a/scripts/android/pubspec_gen.sh b/scripts/android/pubspec_gen.sh index dd9852072..0277922d3 100755 --- a/scripts/android/pubspec_gen.sh +++ b/scripts/android/pubspec_gen.sh @@ -10,7 +10,7 @@ case $APP_ANDROID_TYPE in CONFIG_ARGS="--monero" ;; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --haven --ethereum --nano --bitcoinCash" + CONFIG_ARGS="--monero --bitcoin --haven --ethereum --nano --bitcoinCash --polygon" ;; $HAVEN) CONFIG_ARGS="--haven" diff --git a/tool/configure.dart b/tool/configure.dart index 7d50ddf53..e3efb3275 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -6,6 +6,7 @@ const havenOutputPath = 'lib/haven/haven.dart'; const ethereumOutputPath = 'lib/ethereum/ethereum.dart'; const bitcoinCashOutputPath = 'lib/bitcoin_cash/bitcoin_cash.dart'; const nanoOutputPath = 'lib/nano/nano.dart'; +const polygonOutputPath = 'lib/polygon/polygon.dart'; const walletTypesPath = 'lib/wallet_types.g.dart'; const pubspecDefaultPath = 'pubspec_default.yaml'; const pubspecOutputPath = 'pubspec.yaml'; @@ -19,6 +20,7 @@ Future main(List args) async { final hasBitcoinCash = args.contains('${prefix}bitcoinCash'); final hasNano = args.contains('${prefix}nano'); final hasBanano = args.contains('${prefix}banano'); + final hasPolygon = args.contains('${prefix}polygon'); await generateBitcoin(hasBitcoin); await generateMonero(hasMonero); @@ -26,6 +28,7 @@ Future main(List args) async { await generateEthereum(hasEthereum); await generateBitcoinCash(hasBitcoinCash); await generateNano(hasNano); + await generatePolygon(hasPolygon); // await generateBanano(hasEthereum); await generatePubspec( @@ -36,6 +39,7 @@ Future main(List args) async { hasNano: hasNano, hasBanano: hasBanano, hasBitcoinCash: hasBitcoinCash, + hasPolygon: hasPolygon, ); await generateWalletTypes( hasMonero: hasMonero, @@ -45,6 +49,7 @@ Future main(List args) async { hasNano: hasNano, hasBanano: hasBanano, hasBitcoinCash: hasBitcoinCash, + hasPolygon: hasPolygon, ); } @@ -572,6 +577,93 @@ abstract class Ethereum { await outputFile.writeAsString(output); } +Future generatePolygon(bool hasImplementation) async { + final outputFile = File(polygonOutputPath); + const polygonCommonHeaders = """ +import 'package:cake_wallet/view_model/send/output.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/erc20_token.dart'; +import 'package:cw_core/output_info.dart'; +import 'package:cw_core/transaction_info.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_credentials.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_service.dart'; +import 'package:cw_ethereum/ethereum_mnemonics.dart'; +import 'package:eth_sig_util/util/utils.dart'; +import 'package:hive/hive.dart'; +import 'package:web3dart/web3dart.dart'; +"""; + const polygonCWHeaders = """ +import 'package:cw_polygon/polygon_formatter.dart'; +import 'package:cw_polygon/polygon_transaction_credentials.dart'; +import 'package:cw_polygon/polygon_transaction_info.dart'; +import 'package:cw_polygon/polygon_wallet.dart'; +import 'package:cw_polygon/polygon_wallet_creation_credentials.dart'; +import 'package:cw_polygon/polygon_wallet_service.dart'; +import 'package:cw_polygon/polygon_transaction_priority.dart'; +"""; + const polygonCwPart = "part 'cw_polygon.dart';"; + const polygonContent = """ +abstract class Polygon { + List getPolygonWordList(String language); + WalletService createPolygonWalletService(Box walletInfoSource); + WalletCredentials createPolygonNewWalletCredentials({required String name, WalletInfo? walletInfo}); + WalletCredentials createPolygonRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password}); + WalletCredentials createPolygonRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password}); + String getAddress(WalletBase wallet); + String getPrivateKey(WalletBase wallet); + String getPublicKey(WalletBase wallet); + TransactionPriority getDefaultTransactionPriority(); + TransactionPriority getPolygonTransactionPrioritySlow(); + List getTransactionPriorities(); + TransactionPriority deserializePolygonTransactionPriority(int raw); + + Object createPolygonTransactionCredentials( + List outputs, { + required TransactionPriority priority, + required CryptoCurrency currency, + int? feeRate, + }); + + Object createPolygonTransactionCredentialsRaw( + List outputs, { + TransactionPriority? priority, + required CryptoCurrency currency, + required int feeRate, + }); + + int formatterPolygonParseAmount(String amount); + double formatterPolygonAmountToDouble({TransactionInfo? transaction, BigInt? amount, int exponent = 18}); + List getERC20Currencies(WalletBase wallet); + Future addErc20Token(WalletBase wallet, Erc20Token token); + Future deleteErc20Token(WalletBase wallet, Erc20Token token); + Future getErc20Token(WalletBase wallet, String contractAddress); + + CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction); + void updatePolygonScanUsageState(WalletBase wallet, bool isEnabled); + Web3Client? getWeb3Client(WalletBase wallet); +} + """; + + const polygonEmptyDefinition = 'Polygon? polygon;\n'; + const polygonCWDefinition = 'Polygon? polygon = CWPolygon();\n'; + + final output = '$polygonCommonHeaders\n' + + (hasImplementation ? '$polygonCWHeaders\n' : '\n') + + (hasImplementation ? '$polygonCwPart\n\n' : '\n') + + (hasImplementation ? polygonCWDefinition : polygonEmptyDefinition) + + '\n' + + polygonContent; + + if (outputFile.existsSync()) { + await outputFile.delete(); + } + + await outputFile.writeAsString(output); +} + Future generateBitcoinCash(bool hasImplementation) async { final outputFile = File(bitcoinCashOutputPath); const bitcoinCashCommonHeaders = """ @@ -783,7 +875,8 @@ Future generatePubspec( required bool hasEthereum, required bool hasNano, required bool hasBanano, - required bool hasBitcoinCash}) async { + required bool hasBitcoinCash, + required bool hasPolygon}) async { const cwCore = """ cw_core: path: ./cw_core @@ -820,6 +913,10 @@ Future generatePubspec( cw_banano: path: ./cw_banano """; + const cwPolygon = """ + cw_polygon: + path: ./cw_polygon + """; final inputFile = File(pubspecOutputPath); final inputText = await inputFile.readAsString(); final inputLines = inputText.split('\n'); @@ -850,6 +947,10 @@ Future generatePubspec( output += '\n$cwBitcoinCash'; } + if (hasPolygon) { + output += '\n$cwPolygon'; + } + if (hasHaven && !hasMonero) { output += '\n$cwSharedExternal\n$cwHaven'; } else if (hasHaven) { @@ -875,7 +976,8 @@ Future generateWalletTypes( required bool hasEthereum, required bool hasNano, required bool hasBanano, - required bool hasBitcoinCash}) async { + required bool hasBitcoinCash, + required bool hasPolygon}) async { final walletTypesFile = File(walletTypesPath); if (walletTypesFile.existsSync()) { @@ -906,6 +1008,10 @@ Future generateWalletTypes( outputContent += '\tWalletType.bitcoinCash,\n'; } + if (hasPolygon) { + outputContent += '\tWalletType.polygon,\n'; + } + if (hasNano) { outputContent += '\tWalletType.nano,\n'; } diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index 163b80135..e6f625426 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -41,6 +41,7 @@ class SecretKey { static final ethereumSecrets = [ SecretKey('etherScanApiKey', () => ''), + SecretKey('polygonScanApiKey', () => ''), ]; final String name; From 3c28e2525970f380be9610367ceb9262a1c73b08 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Mon, 4 Dec 2023 12:52:43 +0100 Subject: [PATCH 061/241] Remove polyseed seed workaround and fix properly by just storing the wallet (#1215) --- cw_monero/lib/api/wallet_manager.dart | 16 ++++++++++------ cw_monero/lib/monero_wallet.dart | 9 ++------- cw_monero/lib/monero_wallet_service.dart | 17 +---------------- 3 files changed, 13 insertions(+), 29 deletions(-) diff --git a/cw_monero/lib/api/wallet_manager.dart b/cw_monero/lib/api/wallet_manager.dart index 260b420c5..0aa694e9a 100644 --- a/cw_monero/lib/api/wallet_manager.dart +++ b/cw_monero/lib/api/wallet_manager.dart @@ -1,14 +1,16 @@ import 'dart:ffi'; -import 'package:ffi/ffi.dart'; -import 'package:flutter/foundation.dart'; + import 'package:cw_monero/api/convert_utf8_to_string.dart'; -import 'package:cw_monero/api/signatures.dart'; -import 'package:cw_monero/api/types.dart'; -import 'package:cw_monero/api/monero_api.dart'; -import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart'; import 'package:cw_monero/api/exceptions/wallet_creation_exception.dart'; +import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart'; import 'package:cw_monero/api/exceptions/wallet_restore_from_keys_exception.dart'; import 'package:cw_monero/api/exceptions/wallet_restore_from_seed_exception.dart'; +import 'package:cw_monero/api/monero_api.dart'; +import 'package:cw_monero/api/signatures.dart'; +import 'package:cw_monero/api/types.dart'; +import 'package:cw_monero/api/wallet.dart'; +import 'package:ffi/ffi.dart'; +import 'package:flutter/foundation.dart'; final createWalletNative = moneroApi .lookup>('create_wallet') @@ -175,6 +177,8 @@ void restoreWalletFromSpendKeySync( calloc.free(languagePointer); calloc.free(spendKeyPointer); + storeSync(); + if (!isWalletRestored) { throw WalletRestoreFromKeysException( message: convertUTF8ToString(pointer: errorMessagePointer)); diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 924a987cd..71c7e3967 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -97,8 +97,7 @@ abstract class MoneroWalletBase ObservableMap balance; @override - String get seed => _seed; - String _seed = monero_wallet.getSeed(); + String get seed => monero_wallet.getSeed(); @override MoneroWalletKeys get keys => MoneroWalletKeys( @@ -114,11 +113,7 @@ abstract class MoneroWalletBase Timer? _autoSaveTimer; List unspentCoins; - Future init({String seedFallback = ""}) async { - if (_seed.isEmpty) { - _seed = seedFallback; - } - + Future init() async { await walletAddresses.init(); balance = ObservableMap.of({ currency: MoneroBalance( diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index c71d43e83..a6b3227b2 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'package:cw_core/monero_wallet_utils.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/unspent_coins_info.dart'; -import 'package:cw_core/utils/file.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; @@ -134,12 +133,7 @@ class MoneroWalletService extends WalletService< return openWallet(name, password); } - if (wallet.seed.isEmpty) { - final seedFallback = await _getSeedBackup(path, password); - await wallet.init(seedFallback: seedFallback); - } else { - await wallet.init(); - } + await wallet.init(); return wallet; } catch (e) { @@ -295,8 +289,6 @@ class MoneroWalletService extends WalletService< restoreHeight: height, spendKey: spendKey); - await writeData(path: "$path.seed", password: password, data: seed); - final wallet = MoneroWallet( walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); @@ -304,13 +296,6 @@ class MoneroWalletService extends WalletService< return wallet; } - Future _getSeedBackup(String path, String password) async { - final seedFilePath = "$path.seed"; - final seedFile = File(seedFilePath); - if (!seedFile.existsSync()) return ""; - return read(path: seedFilePath, password: password); - } - Future repairOldAndroidWallet(String name) async { try { if (!Platform.isAndroid) { From b95af3a649fc4f28701f6d8dd173921a95b95d10 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Tue, 5 Dec 2023 02:35:33 +0200 Subject: [PATCH 062/241] V4.11.0 v1.8.0 (#1216) * V4.11.0 and v1.8.0 * Add polygon to iOS and macOS Minor import fix for monero.com * Remove Polygon temporarily * Remove tor temorarily [skip ci] * Remove tor temorarily [skip ci] --- assets/text/Monerocom_Release_Notes.txt | 4 +- assets/text/Release_Notes.txt | 6 +-- configure_cake_wallet_android.sh | 1 + cw_core/lib/node.dart | 11 +++-- cw_core/pubspec.yaml | 8 +-- lib/src/screens/settings/tor_page.dart | 66 ++++++++++++------------- pubspec_base.yaml | 8 +-- scripts/android/app_env.sh | 4 +- scripts/android/pubspec_gen.sh | 2 +- scripts/ios/app_env.sh | 4 +- scripts/macos/app_env.sh | 2 +- tool/configure.dart | 2 +- 12 files changed, 61 insertions(+), 57 deletions(-) diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 2830ecdd8..90be3b8e8 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,2 +1,2 @@ -Monero Polyseed support, under Advanced privacy settings, create and restore from a 16 words phrase and without the need to remember the wallet creation date -Minor bug fixes and enhancements \ No newline at end of file +Monero Polyseed support, create and restore from a 16 words phrase and without the need to remember the wallet creation date +Bug fixes and enhancements \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index accdbb080..655d59a7d 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,3 +1,3 @@ -Monero Polyseed support, under Advanced privacy settings, create and restore from a 16 words phrase and without the need to remember the wallet creation date -Add Ethereum NFTs tab to see all of your purchased NFTs -Minor bug fixes and enhancements \ No newline at end of file +Monero Polyseed support, create and restore from a 16 words phrase and without the need to remember the wallet creation date +Add NFTs tab to see all of your purchased NFTs on Ethereum +Bug fixes and enhancements \ No newline at end of file diff --git a/configure_cake_wallet_android.sh b/configure_cake_wallet_android.sh index 6998555d5..da794a35c 100755 --- a/configure_cake_wallet_android.sh +++ b/configure_cake_wallet_android.sh @@ -10,4 +10,5 @@ cd cw_haven && flutter pub get && flutter packages pub run build_runner build -- cd cw_ethereum && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_polygon && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index cc749f23a..bd96e1395 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -6,7 +6,7 @@ import 'package:hive/hive.dart'; import 'package:cw_core/hive_type_ids.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:http/io_client.dart' as ioc; -import 'package:tor/tor.dart'; +// import 'package:tor/tor.dart'; part 'node.g.dart'; @@ -214,14 +214,17 @@ class Node extends HiveObject with Keyable { } Future requestNodeWithProxy() async { - if (!isValidProxyAddress && !Tor.instance.enabled) { + if (!isValidProxyAddress/* && !Tor.instance.enabled*/) { return false; } String? proxy = socksProxyAddress; - if ((proxy?.isEmpty ?? true) && Tor.instance.enabled) { - proxy = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}"; + // if ((proxy?.isEmpty ?? true) && Tor.instance.enabled) { + // proxy = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}"; + // } + if (proxy == null) { + return false; } final proxyAddress = proxy!.split(':')[0]; final proxyPort = int.parse(proxy.split(':')[1]); diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml index 533b578ad..04a840d4e 100644 --- a/cw_core/pubspec.yaml +++ b/cw_core/pubspec.yaml @@ -20,10 +20,10 @@ dependencies: intl: ^0.18.0 encrypt: ^5.0.1 socks5_proxy: ^1.0.4 - tor: - git: - url: https://github.com/cake-tech/tor.git - ref: main +# tor: +# git: +# url: https://github.com/cake-tech/tor.git +# ref: main dev_dependencies: flutter_test: diff --git a/lib/src/screens/settings/tor_page.dart b/lib/src/screens/settings/tor_page.dart index d1d5c7e83..ae1ef1677 100644 --- a/lib/src/screens/settings/tor_page.dart +++ b/lib/src/screens/settings/tor_page.dart @@ -4,7 +4,7 @@ import 'dart:io'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:flutter/material.dart'; -import 'package:tor/tor.dart'; +// import 'package:tor/tor.dart'; class TorPage extends BasePage { final AppStore appStore; @@ -40,44 +40,44 @@ class _TorPageBodyState extends State { connecting = true; // Update flag }); - await Tor.init(); - - // Start the proxy - await Tor.instance.start(); - - // Toggle started flag. - setState(() { - torEnabled = Tor.instance.enabled; // Update flag - connecting = false; - }); - - final node = widget.appStore.settingsStore.getCurrentNode(widget.appStore.wallet!.type); - if (node.socksProxyAddress?.isEmpty ?? true) { - node.socksProxyAddress = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}"; - } - widget.appStore.wallet!.connectToNode(node: node); + // await Tor.init(); + // + // // Start the proxy + // await Tor.instance.start(); + // + // // Toggle started flag. + // setState(() { + // torEnabled = Tor.instance.enabled; // Update flag + // connecting = false; + // }); + // + // final node = widget.appStore.settingsStore.getCurrentNode(widget.appStore.wallet!.type); + // if (node.socksProxyAddress?.isEmpty ?? true) { + // node.socksProxyAddress = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}"; + // } + // widget.appStore.wallet!.connectToNode(node: node); print('Done awaiting; tor should be running'); } Future endTor() async { - // Start the proxy - Tor.instance.disable(); - - // Toggle started flag. - setState(() { - torEnabled = Tor.instance.enabled; // Update flag - }); - - print('Done awaiting; tor should be stopped'); - } - - @override - void initState() { - super.initState(); - - torEnabled = Tor.instance.enabled; + // // Start the proxy + // Tor.instance.disable(); + // + // // Toggle started flag. + // setState(() { + // torEnabled = Tor.instance.enabled; // Update flag + // }); + // + // print('Done awaiting; tor should be stopped'); } + // + // @override + // void initState() { + // super.initState(); + // + // torEnabled = Tor.instance.enabled; + // } @override void dispose() { diff --git a/pubspec_base.yaml b/pubspec_base.yaml index d0a295047..a4738bf82 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -98,10 +98,10 @@ dependencies: url: https://github.com/cake-tech/bitcoin_flutter.git ref: cake-update-v3 fluttertoast: 8.1.4 - tor: - git: - url: https://github.com/cake-tech/tor.git - ref: main +# tor: +# git: +# url: https://github.com/cake-tech/tor.git +# ref: main socks5_proxy: ^1.0.4 flutter_svg: ^2.0.9 polyseed: diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index d241c4421..63a29221b 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -16,14 +16,14 @@ APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" MONERO_COM_VERSION="1.8.0" -MONERO_COM_BUILD_NUMBER=68 +MONERO_COM_BUILD_NUMBER=69 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="4.11.0" -CAKEWALLET_BUILD_NUMBER=182 +CAKEWALLET_BUILD_NUMBER=184 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/android/pubspec_gen.sh b/scripts/android/pubspec_gen.sh index 0277922d3..dd9852072 100755 --- a/scripts/android/pubspec_gen.sh +++ b/scripts/android/pubspec_gen.sh @@ -10,7 +10,7 @@ case $APP_ANDROID_TYPE in CONFIG_ARGS="--monero" ;; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --haven --ethereum --nano --bitcoinCash --polygon" + CONFIG_ARGS="--monero --bitcoin --haven --ethereum --nano --bitcoinCash" ;; $HAVEN) CONFIG_ARGS="--haven" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 874501cb5..a831396f1 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -14,12 +14,12 @@ APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" MONERO_COM_VERSION="1.8.0" -MONERO_COM_BUILD_NUMBER=66 +MONERO_COM_BUILD_NUMBER=67 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="4.11.0" -CAKEWALLET_BUILD_NUMBER=200 +CAKEWALLET_BUILD_NUMBER=202 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index f69670c9a..f6fa8b5e8 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -16,7 +16,7 @@ fi CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="1.4.0" -CAKEWALLET_BUILD_NUMBER=43 +CAKEWALLET_BUILD_NUMBER=45 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then diff --git a/tool/configure.dart b/tool/configure.dart index e3efb3275..67732faa9 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -590,7 +590,6 @@ import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; -import 'package:cw_ethereum/ethereum_mnemonics.dart'; import 'package:eth_sig_util/util/utils.dart'; import 'package:hive/hive.dart'; import 'package:web3dart/web3dart.dart'; @@ -603,6 +602,7 @@ import 'package:cw_polygon/polygon_wallet.dart'; import 'package:cw_polygon/polygon_wallet_creation_credentials.dart'; import 'package:cw_polygon/polygon_wallet_service.dart'; import 'package:cw_polygon/polygon_transaction_priority.dart'; +import 'package:cw_ethereum/ethereum_mnemonics.dart'; """; const polygonCwPart = "part 'cw_polygon.dart';"; const polygonContent = """ From d370c754c5dd39d1cb30fde643882fd106a3dad6 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Wed, 6 Dec 2023 06:53:26 -0700 Subject: [PATCH 063/241] allow manual builds on any branch (#1219) * allow manual builds on any branch * small fix * see if this works * test fix * test fix * fix * fix * test * fix * fix * consistent variable naming --- .github/workflows/pr_test_build.yml | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 8fef4fdb6..5b2bb11d3 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -3,6 +3,12 @@ name: PR Test Build on: pull_request: branches: [main] + workflow_dispatch: + inputs: + branch: + description: 'Branch name to build' + required: true + default: 'main' jobs: PR_test_build: @@ -12,6 +18,14 @@ jobs: KEY_PASS: test@cake_wallet 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 Up GitHub Actions Ubuntu Runner Disk Space run: | sudo rm -rf /usr/share/dotnet @@ -40,7 +54,7 @@ jobs: cd /opt/android -y curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh cargo install cargo-ndk - git clone https://github.com/cake-tech/cake_wallet.git --branch $GITHUB_HEAD_REF + 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 @@ -141,7 +155,7 @@ jobs: echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> lib/.secrets.g.dart - name: Rename app - run: echo -e "id=com.cakewallet.test\nname=$GITHUB_HEAD_REF" > /opt/android/cake_wallet/android/app.properties + run: echo -e "id=com.cakewallet.test\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties - name: Build run: | @@ -156,7 +170,7 @@ jobs: # appcenter distribute release \ # --group "Testers" \ # --file "/opt/android/cake_wallet/build/app/outputs/apk/release/app-release.apk" \ -# --release-notes ${GITHUB_HEAD_REF} \ +# --release-notes ${{ env.BRANCH_NAME }} \ # --app Cake-Labs/Cake-Wallet \ # --token ${{ secrets.APP_CENTER_TOKEN }} \ # --quiet @@ -165,7 +179,7 @@ jobs: run: | cd /opt/android/cake_wallet/build/app/outputs/apk/release mkdir test-apk - cp app-release.apk test-apk/$GITHUB_HEAD_REF.apk + cp app-release.apk test-apk/${{env.BRANCH_NAME}}.apk - name: Upload Artifact uses: kittaakos/upload-artifact-as-is@v0 @@ -179,6 +193,6 @@ jobs: token: ${{ secrets.SLACK_APP_TOKEN }} path: /opt/android/cake_wallet/build/app/outputs/apk/release/app-release.apk channel: ${{ secrets.SLACK_APK_CHANNEL }} - title: "${{github.head_ref}}.apk" - filename: ${{github.head_ref}}.apk + title: "${{ env.BRANCH_NAME }}.apk" + filename: ${{ env.BRANCH_NAME }}.apk initial_comment: ${{ github.event.head_commit.message }} From 2138c35e38680f021b2f23b716a65d5e0e9673c5 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 8 Dec 2023 16:05:52 +0200 Subject: [PATCH 064/241] CW-532-DFX-buy-provider (#1209) * dfx buy provider ui * fix signing flow * fixed provider determination based on wallet type and app settings * update localization files * minor fix * Fix BTC, LTC und BCH signMessages * Add signMessage to monero * open dfx in webview * Update dfx_buy_provider.dart * Revert merge conflict * Update bitcoin_flutter ref --------- Co-authored-by: Konstantin Ullrich --- assets/images/dfx_dark.png | Bin 0 -> 3515 bytes assets/images/dfx_light.png | Bin 0 -> 3502 bytes cw_bitcoin/lib/electrum_wallet.dart | 5 +- cw_bitcoin/pubspec.yaml | 2 +- .../lib/src/bitcoin_cash_wallet.dart | 8 +- cw_bitcoin_cash/pubspec.yaml | 2 +- cw_monero/ios/Classes/monero_api.cpp | 9 + cw_monero/ios/Classes/monero_api.h | 3 +- cw_monero/lib/api/signatures.dart | 2 + cw_monero/lib/api/types.dart | 2 + cw_monero/lib/api/wallet.dart | 22 ++- cw_monero/lib/monero_wallet.dart | 6 + cw_monero/macos/Classes/monero_api.cpp | 7 + cw_monero/macos/Classes/monero_api.h | 3 +- lib/buy/dfx/dfx_buy_provider.dart | 179 ++++++++++++++++++ lib/di.dart | 6 +- lib/entities/buy_provider_types.dart | 40 +++- lib/entities/main_actions.dart | 81 ++++---- lib/src/screens/buy/buy_options_page.dart | 82 +++++--- .../screens/settings/other_settings_page.dart | 5 +- lib/store/settings_store.dart | 28 ++- .../dashboard/dashboard_view_model.dart | 6 +- .../settings/other_settings_view_model.dart | 35 ++-- pubspec_base.yaml | 2 +- res/values/strings_ar.arb | 1 + res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 1 + res/values/strings_en.arb | 1 + res/values/strings_es.arb | 2 + res/values/strings_fr.arb | 1 + res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 2 + res/values/strings_id.arb | 2 + 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 | 2 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_th.arb | 1 + res/values/strings_tl.arb | 1 + res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + 50 files changed, 456 insertions(+), 109 deletions(-) create mode 100644 assets/images/dfx_dark.png create mode 100644 assets/images/dfx_light.png create mode 100644 lib/buy/dfx/dfx_buy_provider.dart diff --git a/assets/images/dfx_dark.png b/assets/images/dfx_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..cbba87372adad4c0c3f5d14dec996aacea01ee88 GIT binary patch literal 3515 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 literal 0 HcmV?d00001 diff --git a/assets/images/dfx_light.png b/assets/images/dfx_light.png new file mode 100644 index 0000000000000000000000000000000000000000..e4836be3ebecc08d3d0dee8fe3af672c511c7c2f GIT binary patch literal 3502 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 element.address == address).index : null; - return index == null - ? base64Encode(hd.sign(message)) - : base64Encode(hd.derive(index).sign(message)); + final HD = index == null ? hd : hd.derive(index); + return base64Encode(HD.signMessage(message)); } } diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index e90f9cda4..a50ff68ad 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -22,7 +22,7 @@ dependencies: bitcoin_flutter: git: url: https://github.com/cake-tech/bitcoin_flutter.git - ref: cake-update-v3 + ref: cake-update-v4 bitbox: git: url: https://github.com/cake-tech/bitbox-flutter.git diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index 5f2a33ab6..fa41de767 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -302,10 +302,8 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { final index = address != null ? walletAddresses.addresses .firstWhere((element) => element.address == AddressUtils.toLegacyAddress(address)) - .index - : null; - return index == null - ? base64Encode(hd.sign(message)) - : base64Encode(hd.derive(index).sign(message)); + .index : null; + final HD = index == null ? hd : hd.derive(index); + return base64Encode(HD.signMessage(message)); } } diff --git a/cw_bitcoin_cash/pubspec.yaml b/cw_bitcoin_cash/pubspec.yaml index 30ed49e80..eb1f057d8 100644 --- a/cw_bitcoin_cash/pubspec.yaml +++ b/cw_bitcoin_cash/pubspec.yaml @@ -24,7 +24,7 @@ dependencies: bitcoin_flutter: git: url: https://github.com/cake-tech/bitcoin_flutter.git - ref: cake-update-v3 + ref: cake-update-v4 bitbox: git: url: https://github.com/cake-tech/bitbox-flutter.git diff --git a/cw_monero/ios/Classes/monero_api.cpp b/cw_monero/ios/Classes/monero_api.cpp index 6162375b2..87be785ac 100644 --- a/cw_monero/ios/Classes/monero_api.cpp +++ b/cw_monero/ios/Classes/monero_api.cpp @@ -926,6 +926,8 @@ extern "C" return m_wallet->trustedDaemon(); } + // Coin Control // + CoinsInfoRow* coin(int index) { if (index >= 0 && index < m_coins_info.size()) { @@ -1020,6 +1022,13 @@ extern "C" m_coins->thaw(index); } + // Sign Messages // + + char *sign_message(char *message, char *address = "") + { + return strdup(get_current_wallet()->signMessage(std::string(message), std::string(address)).c_str()); + } + #ifdef __cplusplus } #endif diff --git a/cw_monero/ios/Classes/monero_api.h b/cw_monero/ios/Classes/monero_api.h index 74258ba4c..fa92a038d 100644 --- a/cw_monero/ios/Classes/monero_api.h +++ b/cw_monero/ios/Classes/monero_api.h @@ -32,7 +32,8 @@ void store(char *path); void set_trusted_daemon(bool arg); bool trusted_daemon(); +char *sign_message(char *message, char *address); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/cw_monero/lib/api/signatures.dart b/cw_monero/lib/api/signatures.dart index 17099db91..bc4fc9d38 100644 --- a/cw_monero/lib/api/signatures.dart +++ b/cw_monero/lib/api/signatures.dart @@ -149,3 +149,5 @@ typedef coin = Pointer Function(Int32 index); typedef freeze_coin = Void Function(Int32 index); typedef thaw_coin = Void Function(Int32 index); + +typedef sign_message = Pointer Function(Pointer message, Pointer address); diff --git a/cw_monero/lib/api/types.dart b/cw_monero/lib/api/types.dart index 1d3904870..40a1e0321 100644 --- a/cw_monero/lib/api/types.dart +++ b/cw_monero/lib/api/types.dart @@ -149,3 +149,5 @@ typedef GetCoin = Pointer Function(int); typedef FreezeCoin = void Function(int); typedef ThawCoin = void Function(int); + +typedef SignMessage = Pointer Function(Pointer, Pointer); diff --git a/cw_monero/lib/api/wallet.dart b/cw_monero/lib/api/wallet.dart index 1680918e5..ffa5fe13b 100644 --- a/cw_monero/lib/api/wallet.dart +++ b/cw_monero/lib/api/wallet.dart @@ -8,7 +8,6 @@ import 'package:cw_monero/api/types.dart'; import 'package:cw_monero/api/monero_api.dart'; import 'package:cw_monero/api/exceptions/setup_wallet_exception.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; int _boolToInt(bool value) => value ? 1 : 0; @@ -128,6 +127,10 @@ final trustedDaemonNative = moneroApi .lookup>('trusted_daemon') .asFunction(); +final signMessageNative = moneroApi + .lookup>('sign_message') + .asFunction(); + int getSyncingHeight() => getSyncingHeightNative(); bool isNeededToRefresh() => isNeededToRefreshNative() != 0; @@ -296,7 +299,7 @@ class SyncListener { final bchHeight = await getNodeHeightOrUpdate(syncHeight); - if (_lastKnownBlockHeight == syncHeight || syncHeight == null) { + if (_lastKnownBlockHeight == syncHeight) { return; } @@ -311,7 +314,7 @@ class SyncListener { } // 1. Actual new height; 2. Blocks left to finish; 3. Progress in percents; - onNewBlock?.call(syncHeight, left, ptc); + onNewBlock.call(syncHeight, left, ptc); }); } @@ -382,4 +385,15 @@ String getSubaddressLabel(int accountIndex, int addressIndex) { Future setTrustedDaemon(bool trusted) async => setTrustedDaemonNative(_boolToInt(trusted)); -Future trustedDaemon() async => trustedDaemonNative() != 0; \ No newline at end of file +Future trustedDaemon() async => trustedDaemonNative() != 0; + +String signMessage(String message, {String address = ""}) { + final messagePointer = message.toNativeUtf8(); + final addressPointer = address.toNativeUtf8(); + + final signature = convertUTF8ToString(pointer: signMessageNative(messagePointer, addressPointer)); + calloc.free(messagePointer); + calloc.free(addressPointer); + + return signature; +} diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 71c7e3967..4b71fb5ff 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -651,4 +651,10 @@ abstract class MoneroWalletBase @override void setExceptionHandler(void Function(FlutterErrorDetails) onError) => _onError = onError; + + @override + String signMessage(String message, {String? address}) { + final useAddress = address ?? ""; + return monero_wallet.signMessage(message, address: useAddress); + } } diff --git a/cw_monero/macos/Classes/monero_api.cpp b/cw_monero/macos/Classes/monero_api.cpp index 6fabc29fd..fe75dea98 100644 --- a/cw_monero/macos/Classes/monero_api.cpp +++ b/cw_monero/macos/Classes/monero_api.cpp @@ -1020,6 +1020,13 @@ extern "C" m_coins->thaw(index); } + // Sign Messages // + + char *sign_message(char *message, char *address = "") + { + return strdup(get_current_wallet()->signMessage(std::string(message), std::string(address)).c_str()); + } + #ifdef __cplusplus } #endif diff --git a/cw_monero/macos/Classes/monero_api.h b/cw_monero/macos/Classes/monero_api.h index 74258ba4c..fa92a038d 100644 --- a/cw_monero/macos/Classes/monero_api.h +++ b/cw_monero/macos/Classes/monero_api.h @@ -32,7 +32,8 @@ void store(char *path); void set_trusted_daemon(bool arg); bool trusted_daemon(); +char *sign_message(char *message, char *address); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/buy/dfx/dfx_buy_provider.dart b/lib/buy/dfx/dfx_buy_provider.dart new file mode 100644 index 000000000..d5cf50d10 --- /dev/null +++ b/lib/buy/dfx/dfx_buy_provider.dart @@ -0,0 +1,179 @@ +import 'dart:convert'; + +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/utils/device_info.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'package:url_launcher/url_launcher.dart'; + +class DFXBuyProvider { + DFXBuyProvider({required WalletBase wallet}) : this._wallet = wallet; + + final WalletBase _wallet; + + static const _baseUrl = 'api.dfx.swiss'; + static const _authPath = '/v1/auth/signMessage'; + static const _signUpPath = '/v1/auth/signUp'; + static const _signInPath = '/v1/auth/signIn'; + static const walletName = 'CakeWallet'; + + String get assetOut { + switch (_wallet.type) { + case WalletType.bitcoin: + return 'BTC'; + case WalletType.bitcoinCash: + return 'BCH'; + case WalletType.litecoin: + return 'LTC'; + case WalletType.monero: + return 'XMR'; + case WalletType.ethereum: + return 'ETH'; + default: + throw Exception("WalletType is not available for DFX ${_wallet.type}"); + } + } + + String get blockchain { + switch (_wallet.type) { + case WalletType.bitcoin: + case WalletType.bitcoinCash: + case WalletType.litecoin: + return 'Bitcoin'; + case WalletType.monero: + return 'Monero'; + case WalletType.ethereum: + return 'Ethereum'; + default: + throw Exception("WalletType is not available for DFX ${_wallet.type}"); + } + } + + Future getSignMessage() async { + final walletAddress = _wallet.walletAddresses.address; + final uri = Uri.https(_baseUrl, _authPath, {'address': walletAddress}); + + var response = await http.get(uri, headers: {'accept': 'application/json'}); + + if (response.statusCode == 200) { + final responseBody = jsonDecode(response.body); + return responseBody['message'] as String; + } else { + throw Exception( + 'Failed to get sign message. Status: ${response.statusCode} ${response.body}'); + } + } + + Future signUp() async { + final signMessage = getSignature(await getSignMessage()); + final walletAddress = _wallet.walletAddresses.address; + + final requestBody = jsonEncode({ + 'wallet': walletName, + 'address': walletAddress, + 'signature': signMessage, + }); + + final uri = Uri.https(_baseUrl, _signUpPath); + var response = await http.post(uri, + headers: {'Content-Type': 'application/json'}, body: requestBody); + + if (response.statusCode == 201) { + final responseBody = jsonDecode(response.body); + return responseBody['accessToken'] as String; + } else { + throw Exception( + 'Failed to sign up. Status: ${response.statusCode} ${response.body}'); + } + } + + Future signIn() async { + final signMessage = getSignature(await getSignMessage()); + final walletAddress = _wallet.walletAddresses.address; + + final requestBody = jsonEncode({ + 'address': walletAddress, + 'signature': signMessage, + }); + + final uri = Uri.https(_baseUrl, _signInPath); + var response = await http.post(uri, + headers: {'Content-Type': 'application/json'}, body: requestBody); + + if (response.statusCode == 201) { + final responseBody = jsonDecode(response.body); + return responseBody['accessToken'] as String; + } else { + throw Exception( + 'Failed to sign in. Status: ${response.statusCode} ${response.body}'); + } + } + + String getSignature(String message) { + switch (_wallet.type) { + case WalletType.ethereum: + return _wallet.signMessage(message); + case WalletType.monero: + case WalletType.litecoin: + case WalletType.bitcoin: + case WalletType.bitcoinCash: + return _wallet.signMessage(message, + address: _wallet.walletAddresses.address); + default: + throw Exception("WalletType is not available for DFX ${_wallet.type}"); + } + } + + Future launchProvider(BuildContext context) async { + try { + final assetOut = this.assetOut; + final blockchain = this.blockchain; + + String accessToken; + + try { + accessToken = await signUp(); + } on Exception catch (e) { + if (e.toString().contains('409')) { + accessToken = await signIn(); + } else { + rethrow; + } + } + + final uri = Uri.https('services.dfx.swiss', '/buy', { + 'session': accessToken, + 'lang': 'en', + 'asset-out': assetOut, + 'blockchain': blockchain, + 'asset-in': 'EUR', + }); + + if (await canLaunchUrl(uri)) { + if (DeviceInfo.instance.isMobile) { + Navigator.of(context).pushNamed(Routes.webViewPage, + arguments: [S.of(context).buy, uri]); + } else { + await launchUrl(uri, mode: LaunchMode.externalApplication); + } + } else { + throw Exception('Could not launch URL'); + } + } catch (e) { + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: "DFX Connect", + alertContent: S.of(context).buy_provider_unavailable + ': $e', + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop()); + }); + } + } +} diff --git a/lib/di.dart b/lib/di.dart index e0faa6db1..493ff84b9 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -227,6 +227,7 @@ import 'package:cake_wallet/core/wallet_loading_service.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/entities/qr_view_data.dart'; +import 'buy/dfx/dfx_buy_provider.dart'; import 'core/totp_request_details.dart'; import 'src/screens/settings/desktop_settings/desktop_settings_page.dart'; @@ -795,6 +796,9 @@ Future setup({ getIt.registerFactory( () => RobinhoodBuyProvider(wallet: getIt.get().wallet!)); + getIt.registerFactory( + () => DFXBuyProvider(wallet: getIt.get().wallet!)); + getIt.registerFactory(() => OnRamperBuyProvider( settingsStore: getIt.get().settingsStore, wallet: getIt.get().wallet!, @@ -940,7 +944,7 @@ Future setup({ getIt.registerFactory(() => BuyAmountViewModel()); - getIt.registerFactory(() => BuyOptionsPage()); + getIt.registerFactory(() => BuyOptionsPage(getIt.get())); getIt.registerFactory(() { final wallet = getIt.get().wallet; diff --git a/lib/entities/buy_provider_types.dart b/lib/entities/buy_provider_types.dart index 90c070e86..1faf2b281 100644 --- a/lib/entities/buy_provider_types.dart +++ b/lib/entities/buy_provider_types.dart @@ -1,9 +1,11 @@ import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cw_core/wallet_type.dart'; enum BuyProviderType { AskEachTime, Robinhood, - Onramper; + Onramper, + DFX; @override String toString() { @@ -14,6 +16,42 @@ enum BuyProviderType { return "Robinhood"; case BuyProviderType.Onramper: return "Onramper"; + case BuyProviderType.DFX: + return "DFX"; + } + } + + static List getAvailableProviders(WalletType walletType) { + switch (walletType) { + case WalletType.nano: + case WalletType.banano: + return [ + BuyProviderType.AskEachTime, + BuyProviderType.Onramper + ]; + case WalletType.monero: + return [ + BuyProviderType.AskEachTime, + BuyProviderType.Onramper, + BuyProviderType.DFX + ]; + case WalletType.bitcoin: + case WalletType.ethereum: + return [ + BuyProviderType.AskEachTime, + BuyProviderType.Onramper, + BuyProviderType.DFX, + BuyProviderType.Robinhood + ]; + case WalletType.litecoin: + case WalletType.bitcoinCash: + return [ + BuyProviderType.AskEachTime, + BuyProviderType.Onramper, + BuyProviderType.Robinhood + ]; + default: + return []; } } } diff --git a/lib/entities/main_actions.dart b/lib/entities/main_actions.dart index 1ef388d31..4c629e768 100644 --- a/lib/entities/main_actions.dart +++ b/lib/entities/main_actions.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/buy/dfx/dfx_buy_provider.dart'; import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart'; import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart'; @@ -44,48 +45,54 @@ class MainActions { isEnabled: (viewModel) => viewModel.isEnabledBuyAction, canShow: (viewModel) => viewModel.hasBuyAction, onTap: (BuildContext context, DashboardViewModel viewModel) async { + if (!viewModel.isEnabledBuyAction) { + await _showErrorDialog(context, S.of(context).unsupported_asset); + return; + } + final defaultBuyProvider = viewModel.defaultBuyProvider; - final walletType = viewModel.type; - - if (!viewModel.isEnabledBuyAction) return; - - switch (walletType) { - case WalletType.bitcoin: - case WalletType.litecoin: - case WalletType.ethereum: - case WalletType.polygon: - case WalletType.bitcoinCash: - switch (defaultBuyProvider) { - case BuyProviderType.AskEachTime: - Navigator.pushNamed(context, Routes.buy); - break; - case BuyProviderType.Onramper: - await getIt.get().launchProvider(context); - break; - case BuyProviderType.Robinhood: - await getIt.get().launchProvider(context); - break; - } - break; - case WalletType.nano: - case WalletType.banano: - case WalletType.monero: - await getIt.get().launchProvider(context); - break; - default: - await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: S.of(context).buy, - alertContent: S.of(context).unsupported_asset, - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop()); - }); + try { + await _launchProviderByType(context, defaultBuyProvider); + } catch (e) { + await _showErrorDialog(context, e.toString()); } }, ); + static Future _launchProviderByType(BuildContext context, BuyProviderType providerType) async { + switch (providerType) { + case BuyProviderType.AskEachTime: + Navigator.pushNamed(context, Routes.buy); + break; + case BuyProviderType.Onramper: + await getIt.get().launchProvider(context); + break; + case BuyProviderType.Robinhood: + await getIt.get().launchProvider(context); + break; + case BuyProviderType.DFX: + await getIt.get().launchProvider(context); + break; + default: + throw UnsupportedError('Unsupported buy provider type'); + } + } + + + static Future _showErrorDialog(BuildContext context, String errorMessage) async { + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: S.of(context).buy, + alertContent: errorMessage, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop(), + ); + }, + ); + } + static MainActions receiveAction = MainActions._( name: (context) => S.of(context).receive, image: 'assets/images/received.png', diff --git a/lib/src/screens/buy/buy_options_page.dart b/lib/src/screens/buy/buy_options_page.dart index 930878544..62dfc4ec4 100644 --- a/lib/src/screens/buy/buy_options_page.dart +++ b/lib/src/screens/buy/buy_options_page.dart @@ -1,18 +1,26 @@ +import 'package:cake_wallet/buy/dfx/dfx_buy_provider.dart'; import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart'; import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/entities/buy_provider_types.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/option_tile.dart'; import 'package:cake_wallet/themes/extensions/option_tile_theme.dart'; import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; +import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:flutter/material.dart'; class BuyOptionsPage extends BasePage { + BuyOptionsPage(this.dashboardViewModel); + + final DashboardViewModel dashboardViewModel; final iconDarkRobinhood = 'assets/images/robinhood_dark.png'; final iconLightRobinhood = 'assets/images/robinhood_light.png'; final iconDarkOnramper = 'assets/images/onramper_dark.png'; final iconLightOnramper = 'assets/images/onramper_light.png'; + final iconDarkDFX = 'assets/images/dfx_dark.png'; + final iconLightDFX = 'assets/images/dfx_light.png'; @override String get title => S.current.buy; @@ -22,11 +30,19 @@ class BuyOptionsPage extends BasePage { @override Widget body(BuildContext context) { - final isLightMode = Theme.of(context).extension()?.useDarkImage ?? false; - final iconRobinhood = - Image.asset(isLightMode ? iconLightRobinhood : iconDarkRobinhood, height: 40, width: 40); - final iconOnramper = - Image.asset(isLightMode ? iconLightOnramper : iconDarkOnramper, height: 40, width: 40); + final isLightMode = + Theme.of(context).extension()?.useDarkImage ?? false; + final iconRobinhood = Image.asset( + isLightMode ? iconLightRobinhood : iconDarkRobinhood, + height: 40, + width: 40); + final iconOnramper = Image.asset( + isLightMode ? iconLightOnramper : iconDarkOnramper, + height: 40, + width: 40); + final iconDFX = Image.asset(isLightMode ? iconLightDFX : iconDarkDFX, + height: 40, width: 40); + final availableProviders = dashboardViewModel.availableProviders; return Container( child: Center( @@ -34,26 +50,42 @@ class BuyOptionsPage extends BasePage { constraints: BoxConstraints(maxWidth: 330), child: Column( children: [ - Padding( - padding: EdgeInsets.only(top: 24), - child: OptionTile( - image: iconOnramper, - title: "Onramper", - description: S.of(context).onramper_option_description, - onPressed: () async => - await getIt.get().launchProvider(context), + if (availableProviders.contains(BuyProviderType.Onramper)) + Padding( + padding: EdgeInsets.only(top: 24), + child: OptionTile( + image: iconOnramper, + title: "Onramper", + description: S.of(context).onramper_option_description, + onPressed: () async => await getIt + .get() + .launchProvider(context), + ), ), - ), - Padding( - padding: EdgeInsets.only(top: 24), - child: OptionTile( - image: iconRobinhood, - title: "Robinhood Connect", - description: S.of(context).robinhood_option_description, - onPressed: () async => - await getIt.get().launchProvider(context), + if (availableProviders.contains(BuyProviderType.Robinhood)) + Padding( + padding: EdgeInsets.only(top: 24), + child: OptionTile( + image: iconRobinhood, + title: "Robinhood Connect", + description: S.of(context).robinhood_option_description, + onPressed: () async => await getIt + .get() + .launchProvider(context), + ), + ), + if (availableProviders.contains(BuyProviderType.DFX)) + Padding( + padding: EdgeInsets.only(top: 24), + child: OptionTile( + image: iconDFX, + title: "DFX Connect", + description: S.of(context).dfx_option_description, + onPressed: () async => await getIt + .get() + .launchProvider(context), + ), ), - ), Spacer(), Padding( padding: EdgeInsets.fromLTRB(24, 24, 24, 32), @@ -63,7 +95,9 @@ class BuyOptionsPage extends BasePage { style: TextStyle( fontSize: 14, fontWeight: FontWeight.normal, - color: Theme.of(context).extension()!.detailsTitlesColor, + color: Theme.of(context) + .extension()! + .detailsTitlesColor, ), ), ), diff --git a/lib/src/screens/settings/other_settings_page.dart b/lib/src/screens/settings/other_settings_page.dart index ede816893..cc92641f3 100644 --- a/lib/src/screens/settings/other_settings_page.dart +++ b/lib/src/screens/settings/other_settings_page.dart @@ -1,5 +1,3 @@ -import 'package:cake_wallet/buy/buy_provider.dart'; -import 'package:cake_wallet/entities/buy_provider_types.dart'; import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; @@ -42,9 +40,10 @@ class OtherSettingsPage extends BasePage { handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.changeRep), ), + if(_otherSettingsViewModel.isEnabledBuyAction) SettingsPickerCell( title: S.current.default_buy_provider, - items: BuyProviderType.values, + items: _otherSettingsViewModel.availableBuyProviders, displayItem: _otherSettingsViewModel.getBuyProviderType, selectedItem: _otherSettingsViewModel.buyProviderType, onItemSelected: _otherSettingsViewModel.onBuyProviderTypeSelected, diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 3e38fed1f..3984bd81a 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -36,7 +36,6 @@ import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/entities/action_list_display_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cw_core/set_app_secure_native.dart'; - part 'settings_store.g.dart'; class SettingsStore = SettingsStoreBase with _$SettingsStore; @@ -123,7 +122,6 @@ abstract class SettingsStoreBase with Store { isAppSecure = initialAppSecure, disableBuy = initialDisableBuy, disableSell = initialDisableSell, - defaultBuyProvider = initialDefaultBuyProvider, shouldShowMarketPlaceInDashboard = initialShouldShowMarketPlaceInDashboard, exchangeStatus = initialExchangeStatus, currentTheme = initialTheme, @@ -178,6 +176,12 @@ abstract class SettingsStoreBase with Store { initializeTrocadorProviderStates(); + WalletType.values.forEach((walletType) { + final key = 'defaultBuyProvider_${walletType.toString()}'; + final providerIndex = sharedPreferences.getInt(key); + defaultBuyProviders[walletType] = providerIndex != null ? BuyProviderType.values[providerIndex] : BuyProviderType.AskEachTime; + }); + reaction( (_) => fiatCurrency, (FiatCurrency fiatCurrency) => sharedPreferences.setString( @@ -244,9 +248,14 @@ abstract class SettingsStoreBase with Store { sharedPreferences.setBool(PreferencesKey.disableSellKey, disableSell)); reaction( - (_) => defaultBuyProvider, - (BuyProviderType defaultBuyProvider) => - sharedPreferences.setInt(PreferencesKey.defaultBuyProvider, defaultBuyProvider.index)); + (_) => defaultBuyProviders.asObservable(), + (ObservableMap providers) { + providers.forEach((walletType, provider) { + final key = 'defaultBuyProvider_${walletType.toString()}'; + sharedPreferences.setInt(key, provider.index); + }); + } + ); reaction( (_) => autoGenerateSubaddressStatus, @@ -333,6 +342,7 @@ abstract class SettingsStoreBase with Store { reaction((_) => totpSecretKey, (String totpKey) => sharedPreferences.setString(PreferencesKey.totpSecretKey, totpKey)); + reaction( (_) => numberOfFailedTokenTrials, (int failedTokenTrail) => @@ -494,9 +504,6 @@ abstract class SettingsStoreBase with Store { @observable bool disableSell; - @observable - BuyProviderType defaultBuyProvider; - @observable bool allowBiometricalAuthentication; @@ -566,6 +573,9 @@ abstract class SettingsStoreBase with Store { @observable ObservableMap trocadorProviderStates = ObservableMap(); + @observable + ObservableMap defaultBuyProviders = ObservableMap(); + @observable SortBalanceBy sortBalanceBy; @@ -1003,8 +1013,6 @@ abstract class SettingsStoreBase with Store { isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? isAppSecure; disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? disableBuy; disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? disableSell; - defaultBuyProvider = - BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0]; allowBiometricalAuthentication = sharedPreferences.getBool(PreferencesKey.allowBiometricalAuthenticationKey) ?? allowBiometricalAuthentication; diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index fbb2fc76f..84ba54202 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -282,10 +282,14 @@ abstract class DashboardViewModelBase with Store { Map> filterItems; - BuyProviderType get defaultBuyProvider => settingsStore.defaultBuyProvider; + BuyProviderType get defaultBuyProvider => + settingsStore.defaultBuyProviders[wallet.type] ?? + BuyProviderType.AskEachTime; bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled; + List get availableProviders => BuyProviderType.getAvailableProviders(wallet.type); + bool get shouldShowYatPopup => settingsStore.shouldShowYatPopup; @action diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart index b4ca46f70..4e712dae1 100644 --- a/lib/view_model/settings/other_settings_view_model.dart +++ b/lib/view_model/settings/other_settings_view_model.dart @@ -13,14 +13,15 @@ import 'package:package_info/package_info.dart'; part 'other_settings_view_model.g.dart'; -class OtherSettingsViewModel = OtherSettingsViewModelBase with _$OtherSettingsViewModel; +class OtherSettingsViewModel = OtherSettingsViewModelBase + with _$OtherSettingsViewModel; abstract class OtherSettingsViewModelBase with Store { OtherSettingsViewModelBase(this._settingsStore, this._wallet) : walletType = _wallet.type, currentVersion = '' { - PackageInfo.fromPlatform() - .then((PackageInfo packageInfo) => currentVersion = packageInfo.version); + PackageInfo.fromPlatform().then( + (PackageInfo packageInfo) => currentVersion = packageInfo.version); final priority = _settingsStore.priority[_wallet.type]; final priorities = priorityForWalletType(_wallet.type); @@ -31,7 +32,8 @@ abstract class OtherSettingsViewModelBase with Store { } final WalletType walletType; - final WalletBase, TransactionInfo> _wallet; + final WalletBase, + TransactionInfo> _wallet; @observable String currentVersion; @@ -50,15 +52,19 @@ abstract class OtherSettingsViewModelBase with Store { } @computed - bool get changeRepresentativeEnabled { - if (_wallet.type == WalletType.nano || _wallet.type == WalletType.banano) { - return true; - } + bool get changeRepresentativeEnabled => + _wallet.type == WalletType.nano || _wallet.type == WalletType.banano; - return false; - } - - BuyProviderType get buyProviderType { return _settingsStore.defaultBuyProvider; } + @computed + bool get isEnabledBuyAction => + !_settingsStore.disableBuy && _wallet.type != WalletType.haven; + + List get availableBuyProviders => + BuyProviderType.getAvailableProviders(walletType); + + BuyProviderType get buyProviderType => + _settingsStore.defaultBuyProviders[walletType] ?? + BuyProviderType.AskEachTime; String getDisplayPriority(dynamic priority) { final _priority = priority as TransactionPriority; @@ -73,7 +79,7 @@ abstract class OtherSettingsViewModelBase with Store { return priority.toString(); } - String getBuyProviderType (dynamic buyProviderType) { + String getBuyProviderType(dynamic buyProviderType) { final _buyProviderType = buyProviderType as BuyProviderType; return _buyProviderType.toString(); @@ -83,6 +89,5 @@ abstract class OtherSettingsViewModelBase with Store { _settingsStore.priority[_wallet.type] = priority; void onBuyProviderTypeSelected(BuyProviderType buyProviderType) => - _settingsStore.defaultBuyProvider = buyProviderType; - + _settingsStore.defaultBuyProviders[walletType] = buyProviderType; } diff --git a/pubspec_base.yaml b/pubspec_base.yaml index a4738bf82..b87347630 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -96,7 +96,7 @@ dependencies: bitcoin_flutter: git: url: https://github.com/cake-tech/bitcoin_flutter.git - ref: cake-update-v3 + ref: cake-update-v4 fluttertoast: 8.1.4 # tor: # git: diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 45ad96764..269400ffc 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -746,5 +746,6 @@ "seed_language_czech": "التشيكية", "seed_language_korean": "الكورية", "seed_language_chinese_traditional": "تقاليد صينية)", + "dfx_option_description": "ﺎﺑﻭﺭﻭﺃ ﻲﻓ ﺕﺎﻛﺮﺸﻟﺍﻭ ﺔﺋﺰﺠﺘﻟﺍ ءﻼﻤﻌﻟ .ﻲﻓﺎﺿﺇ KYC ﻥﻭﺪﺑ ﻭﺭﻮﻳ 990 ﻰﻟﺇ ﻞﺼﻳ ﺎﻣ .ﻱﺮﺴﻳﻮﺴﻟﺍ", "polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index d52843798..27c54cde5 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -742,5 +742,6 @@ "seed_language_czech": "Чех", "seed_language_korean": "Корейски", "seed_language_chinese_traditional": "Традиционен китайски)", + "dfx_option_description": "Купете крипто с EUR и CHF. До 990 € без допълнителен KYC. За клиенти на дребно и корпоративни клиенти в Европа", "polygonscan_history": "История на PolygonScan" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 3e1d68543..10ed3b0e9 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -742,5 +742,6 @@ "seed_language_czech": "čeština", "seed_language_korean": "korejština", "seed_language_chinese_traditional": "Číňan (tradiční)", + "dfx_option_description": "Nakupujte kryptoměny za EUR a CHF. Až 990 € bez dalších KYC. Pro maloobchodní a firemní zákazníky v Evropě", "polygonscan_history": "Historie PolygonScan" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 62a73361c..eef930971 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -750,5 +750,6 @@ "seed_language_czech": "Tschechisch", "seed_language_korean": "Koreanisch", "seed_language_chinese_traditional": "Chinesisch (Traditionell)", + "dfx_option_description": "Krypto mit EUR und CHF kaufen. Bis zu 990€ ohne zusätzliches KYC. Für Privat- und Firmenkunden in Europa", "polygonscan_history": "PolygonScan-Verlauf" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 19c435ce8..053ed0488 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -751,5 +751,6 @@ "seed_language_czech": "Czech", "seed_language_korean": "Korean", "seed_language_chinese_traditional": "Chinese (Traditional)", + "dfx_option_description": "Buy crypto with EUR & CHF. Up to 990€ without additional KYC. For retail and corporate customers in Europe", "polygonscan_history": "PolygonScan history" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 2b94e51b9..fcdaf17b1 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -749,6 +749,8 @@ "seedtype_polyseed": "Polieta (16 palabras)", "seed_language_czech": "checo", "seed_language_korean": "coreano", + "seed_language_chinese_traditional": "Chino tradicional)", + "dfx_option_description": "Compre criptomonedas con EUR y CHF. Hasta 990€ sin KYC adicional. Para clientes minoristas y corporativos en Europa", "seed_language_chinese_traditional": "Chino (tradicional)", "polygonscan_history": "Historial de PolygonScan" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 0c71ba06e..3fe73f0b4 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -750,5 +750,6 @@ "seed_language_czech": "tchèque", "seed_language_korean": "coréen", "seed_language_chinese_traditional": "Chinois (Traditionnel)", + "dfx_option_description": "Achetez des crypto-monnaies avec EUR et CHF. Jusqu'à 990€ sans KYC supplémentaire. Pour les clients particuliers et entreprises en Europe", "polygonscan_history": "Historique de PolygonScan" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 0eb9bc7cd..d35f3a89e 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -728,5 +728,6 @@ "seed_language_czech": "Czech", "seed_language_korean": "Yaren Koriya", "seed_language_chinese_traditional": "Sinanci (na gargajiya)", + "dfx_option_description": "Sayi crypto tare da EUR & CHF. Har zuwa € 990 ba tare da ƙarin KYC ba. Don 'yan kasuwa da abokan ciniki na kamfanoni a Turai", "polygonscan_history": "PolygonScan tarihin kowane zamani" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index c4c11fa58..ce4ebc453 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -750,5 +750,6 @@ "seed_language_czech": "चेक", "seed_language_korean": "कोरियाई", "seed_language_chinese_traditional": "चीनी पारंपरिक)", + "dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। अतिरिक्त केवाईसी के बिना 990€ तक। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए", "polygonscan_history": "पॉलीगॉनस्कैन इतिहास" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 82df37e69..4ab734f9f 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -747,6 +747,8 @@ "seedtype_polyseed": "Poliseed (16 riječi)", "seed_language_czech": "češki", "seed_language_korean": "korejski", + "seed_language_chinese_traditional": "Kinesko tradicionalno)", + "dfx_option_description": "Kupujte kripto s EUR i CHF. Do 990 € bez dodatnog KYC-a. Za maloprodajne i poslovne korisnike u Europi", "seed_language_chinese_traditional": "Kinesko (tradicionalno)", "polygonscan_history": "Povijest PolygonScan" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index de04ecb12..041bbd93c 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -737,6 +737,8 @@ "seedtype_polyseed": "Polyseed (16 kata)", "seed_language_czech": "Ceko", "seed_language_korean": "Korea", + "seed_language_chinese_traditional": "Cina tradisional)", + "dfx_option_description": "Beli kripto dengan EUR & CHF. Hingga 990€ tanpa KYC tambahan. Untuk pelanggan ritel dan korporat di Eropa", "seed_language_chinese_traditional": "Cina (tradisional)", "polygonscan_history": "Sejarah PolygonScan" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index acb7a71c3..250edda6b 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -750,5 +750,6 @@ "seed_language_czech": "ceco", "seed_language_korean": "coreano", "seed_language_chinese_traditional": "Cinese tradizionale)", + "dfx_option_description": "Acquista criptovalute con EUR e CHF. Fino a 990€ senza KYC aggiuntivi. Per clienti al dettaglio e aziendali in Europa", "polygonscan_history": "Cronologia PolygonScan" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 7907d3835..37b5e60fd 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -750,5 +750,6 @@ "seed_language_czech": "チェコ", "seed_language_korean": "韓国語", "seed_language_chinese_traditional": "中国の伝統的な)", + "dfx_option_description": "EUR と CHF で暗号通貨を購入します。追加のKYCなしで最大990ユーロ。ヨーロッパの小売および法人顧客向け", "polygonscan_history": "ポリゴンスキャン履歴" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index e9a54974e..611915f56 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -748,5 +748,6 @@ "seed_language_czech": "체코 사람", "seed_language_korean": "한국인", "seed_language_chinese_traditional": "중국 전통)", + "dfx_option_description": "EUR 및 CHF로 암호화폐를 구매하세요. 추가 KYC 없이 최대 990€. 유럽의 소매 및 기업 고객용", "polygonscan_history": "다각형 스캔 기록" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 02e3d38c2..cf12b9b16 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -748,5 +748,6 @@ "seed_language_czech": "ချက်", "seed_language_korean": "ကိုးရီးယား", "seed_language_chinese_traditional": "တရုတ်ရိုးရာ)", + "dfx_option_description": "EUR & CHF ဖြင့် crypto ကိုဝယ်ပါ။ အပို KYC မပါဘဲ 990€ အထိ။ ဥရောပရှိ လက်လီရောင်းချသူများနှင့် ကော်ပိုရိတ်ဖောက်သည်များအတွက်", "polygonscan_history": "PolygonScan မှတ်တမ်း" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 4fd0fbab7..b36a5a234 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -749,6 +749,8 @@ "seedtype_polyseed": "Polyseed (16 woorden)", "seed_language_czech": "Tsjechisch", "seed_language_korean": "Koreaans", + "seed_language_chinese_traditional": "Chinese traditionele)", + "dfx_option_description": "Koop crypto met EUR & CHF. Tot 990€ zonder extra KYC. Voor particuliere en zakelijke klanten in Europa", "seed_language_chinese_traditional": "Chinese (traditionele)", "polygonscan_history": "PolygonScan-geschiedenis" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index bf3cc5329..afb9bf9ec 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -750,5 +750,6 @@ "seed_language_czech": "Czech", "seed_language_korean": "koreański", "seed_language_chinese_traditional": "Chiński tradycyjny)", + "dfx_option_description": "Kupuj kryptowaluty za EUR i CHF. Do 990 € bez dodatkowego KYC. Dla klientów detalicznych i korporacyjnych w Europie", "polygonscan_history": "Historia PolygonScan" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index ba4beb6c5..c2fe03ad3 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -749,5 +749,6 @@ "seed_language_czech": "Tcheco", "seed_language_korean": "coreano", "seed_language_chinese_traditional": "Chinês tradicional)", + "dfx_option_description": "Compre criptografia com EUR e CHF. Até 990€ sem KYC adicional. Para clientes de varejo e corporativos na Europa", "polygonscan_history": "História do PolygonScan" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 83a1aaf2b..107cbf596 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -750,5 +750,6 @@ "seed_language_czech": "Чешский", "seed_language_korean": "Корейский", "seed_language_chinese_traditional": "Китайский традиционный)", + "dfx_option_description": "Покупайте криптовалюту за EUR и CHF. До 990€ без дополнительного KYC. Для розничных и корпоративных клиентов в Европе", "polygonscan_history": "История PolygonScan" } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index e046eaba8..134868c08 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -748,5 +748,6 @@ "seed_language_czech": "ภาษาเช็ก", "seed_language_korean": "เกาหลี", "seed_language_chinese_traditional": "จีน (ดั้งเดิม)", + "dfx_option_description": "ซื้อ crypto ด้วย EUR และ CHF สูงถึง 990€ โดยไม่มี KYC เพิ่มเติม สำหรับลูกค้ารายย่อยและลูกค้าองค์กรในยุโรป", "polygonscan_history": "ประวัติ PolygonScan" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 06ee4bc89..d12e89378 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -744,5 +744,6 @@ "seed_language_czech": "Czech", "seed_language_korean": "Korean", "seed_language_chinese_traditional": "Intsik (tradisyonal)", + "dfx_option_description": "Bumili ng crypto gamit ang EUR at CHF. Hanggang 990€ nang walang karagdagang KYC. Para sa retail at corporate na mga customer sa Europe", "polygonscan_history": "Kasaysayan ng PolygonScan" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index f300951ba..30a354caa 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -748,5 +748,6 @@ "seed_language_czech": "Çek", "seed_language_korean": "Koreli", "seed_language_chinese_traditional": "Çin geleneği)", + "dfx_option_description": "EUR ve CHF ile kripto satın alın. Ek KYC olmadan 990 €'ya kadar. Avrupa'daki perakende ve kurumsal müşteriler için", "polygonscan_history": "PolygonScan geçmişi" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 6f8d87e86..f977308b5 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -749,6 +749,7 @@ "seedtype_polyseed": "Полісей (16 слів)", "seed_language_czech": "Чеський", "seed_language_korean": "Корейський", + "dfx_option_description": "Купуйте криптовалюту за EUR і CHF. До 990 євро без додаткового KYC. Для роздрібних і корпоративних клієнтів у Європі", "seed_language_chinese_traditional": "Китайський (традиційний)", "polygonscan_history": "Історія PolygonScan" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index f75d287ef..be7525c1b 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -742,5 +742,6 @@ "seed_language_czech": "چیک", "seed_language_korean": "کورین", "seed_language_chinese_traditional": "چینی (روایتی)", + "dfx_option_description": "EUR ﺭﻭﺍ CHF ﯽﻓﺎﺿﺍ ۔ﮟﯾﺪﯾﺮﺧ ﻮﭩﭘﺮﮐ ﮫﺗﺎﺳ ﮯﮐ KYC ﮯﯿﻟ ﮯﮐ ﻦﯿﻓﺭﺎﺻ ﭧﯾﺭﻮﭘﺭﺎﮐ ﺭﻭﺍ ﮦﺩﺭﻮﺧ ﮟ", "polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index b5937a49c..63d21666e 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -744,5 +744,6 @@ "seed_language_czech": "Czech", "seed_language_korean": "Ara ẹni", "seed_language_chinese_traditional": "Kannada (ibile)", + "dfx_option_description": "Ra crypto pẹlu EUR & CHF. Titi di 990 € laisi afikun KYC. Fun soobu ati awọn onibara ile-iṣẹ ni Yuroopu", "polygonscan_history": "PolygonScan itan" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index b487f83f5..25710eff5 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -749,5 +749,6 @@ "seed_language_czech": "捷克", "seed_language_korean": "韩国人", "seed_language_chinese_traditional": "中国传统的)", + "dfx_option_description": "用欧元和瑞士法郎购买加密货币。高达 990 欧元,无需额外 KYC。对于欧洲的零售和企业客户", "polygonscan_history": "多边形扫描历史" } From 72777fbf2c33086d21c74bff45e684ed4973e594 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Sat, 9 Dec 2023 02:37:39 +0100 Subject: [PATCH 065/241] Cw 534 monero wallet generic enhancements (#1225) * Fix word count for polyseed on pre_seed_page * Fix naming of advanced setting * Set default Seed Type to Polyseed and disable bg-sync by default * Fix inconsistency between seed type field in restore screen and the one in advanced settings * Use pub.dev release of polyseed * Add Legacy Seed to wallet_keys-Page in case of Polyseed --- cw_monero/lib/monero_wallet_service.dart | 3 +- cw_monero/pubspec.lock | 36 +++++++++++-------- cw_monero/pubspec.yaml | 4 +-- lib/di.dart | 11 +++--- lib/entities/seed_type.dart | 2 +- lib/router.dart | 12 +++---- .../advanced_privacy_settings_page.dart | 20 +++++++---- .../screens/new_wallet/new_wallet_page.dart | 20 +++++------ .../wallet_restore_from_seed_form.dart | 24 +++++++++++-- .../screens/restore/wallet_restore_page.dart | 5 ++- lib/src/screens/seed/pre_seed_page.dart | 16 ++++++--- lib/store/settings_store.dart | 2 +- .../advanced_privacy_settings_view_model.dart | 7 ---- lib/view_model/seed_type_view_model.dart | 19 ++++++++++ lib/view_model/wallet_keys_view_model.dart | 29 +++++++++++++++ pubspec_base.yaml | 4 +-- res/values/strings_ar.arb | 3 +- res/values/strings_bg.arb | 3 +- res/values/strings_cs.arb | 3 +- res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 3 +- res/values/strings_es.arb | 5 +-- res/values/strings_fr.arb | 3 +- res/values/strings_ha.arb | 3 +- res/values/strings_hi.arb | 3 +- res/values/strings_hr.arb | 5 +-- res/values/strings_id.arb | 5 +-- res/values/strings_it.arb | 3 +- res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 3 +- res/values/strings_nl.arb | 5 +-- res/values/strings_pl.arb | 3 +- res/values/strings_pt.arb | 3 +- res/values/strings_ru.arb | 3 +- res/values/strings_th.arb | 3 +- res/values/strings_tl.arb | 3 +- res/values/strings_tr.arb | 3 +- res/values/strings_uk.arb | 5 +-- res/values/strings_ur.arb | 3 +- res/values/strings_yo.arb | 3 +- res/values/strings_zh.arb | 3 +- 42 files changed, 203 insertions(+), 99 deletions(-) create mode 100644 lib/view_model/seed_type_view_model.dart diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index a6b3227b2..9b9e254d0 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -13,7 +13,6 @@ import 'package:cw_monero/api/wallet_manager.dart' as monero_wallet_manager; import 'package:cw_monero/monero_wallet.dart'; import 'package:hive/hive.dart'; import 'package:polyseed/polyseed.dart'; -import 'package:polyseed/src/utils/key_utils.dart'; class MoneroNewWalletCredentials extends WalletCredentials { MoneroNewWalletCredentials({required String name, required this.language, required this.isPolyseed, String? password}) @@ -275,7 +274,7 @@ class MoneroWalletService extends WalletService< {PolyseedCoin coin = PolyseedCoin.POLYSEED_MONERO, int? overrideHeight}) async { final height = overrideHeight ?? getMoneroHeigthByDate( date: DateTime.fromMillisecondsSinceEpoch(polyseed.birthday * 1000)); - final spendKey = keyToHexString(polyseed.generateKey(coin, 32)); + final spendKey = polyseed.generateKey(coin, 32).toHexString(); final seed = polyseed.encode(lang, coin); walletInfo.isRecovery = true; diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index 46ebe8028..0f8f2c90e 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -266,6 +266,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.0" + hashlib: + dependency: transitive + description: + name: hashlib + sha256: "71bf102329ddb8e50c8a995ee4645ae7f1728bb65e575c17196b4d8262121a96" + url: "https://pub.dev" + source: hosted + version: "1.12.0" + hashlib_codecs: + dependency: transitive + description: + name: hashlib_codecs + sha256: "49e2a471f74b15f1854263e58c2ac11f2b631b5b12c836f9708a35397d36d626" + url: "https://pub.dev" + source: hosted + version: "2.2.0" hive: dependency: transitive description: @@ -485,12 +501,11 @@ packages: polyseed: dependency: "direct main" description: - path: "." - ref: HEAD - resolved-ref: "504d58a5b147fccd3bc85a25f2e72fb32771ddd7" - url: "https://github.com/cake-tech/polyseed_dart.git" - source: git - version: "0.0.1" + name: polyseed + sha256: "9b48ec535b10863f78f6354ec983b4cc0c88ca69ff48fee469d0fd1954b01d4f" + url: "https://pub.dev" + source: hosted + version: "0.0.2" pool: dependency: transitive description: @@ -632,15 +647,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" - tor: - dependency: transitive - description: - path: "." - ref: main - resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" - url: "https://github.com/cake-tech/tor.git" - source: git - version: "0.0.1" typed_data: dependency: transitive description: diff --git a/cw_monero/pubspec.yaml b/cw_monero/pubspec.yaml index 55e9b354c..a6fe7f967 100644 --- a/cw_monero/pubspec.yaml +++ b/cw_monero/pubspec.yaml @@ -19,9 +19,7 @@ dependencies: flutter_mobx: ^2.0.6+1 intl: ^0.18.0 encrypt: ^5.0.1 - polyseed: - git: - url: https://github.com/cake-tech/polyseed_dart.git + polyseed: ^0.0.2 cw_core: path: ../cw_core diff --git a/lib/di.dart b/lib/di.dart index 493ff84b9..15d008dca 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -90,6 +90,7 @@ import 'package:cake_wallet/view_model/ionia/ionia_purchase_merch_view_model.dar import 'package:cake_wallet/view_model/nano_account_list/nano_account_edit_or_create_view_model.dart'; import 'package:cake_wallet/view_model/nano_account_list/nano_account_list_view_model.dart'; import 'package:cake_wallet/view_model/node_list/pow_node_list_view_model.dart'; +import 'package:cake_wallet/view_model/seed_type_view_model.dart'; import 'package:cake_wallet/view_model/set_up_2fa_viewmodel.dart'; import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart'; import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart'; @@ -719,6 +720,8 @@ Future setup({ getIt.registerFactory(() => WalletSeedViewModel(getIt.get().wallet!)); + getIt.registerFactory(() => SeedTypeViewModel(getIt.get())); + getIt.registerFactoryParam((bool isWalletCreated, _) => WalletSeedPage(getIt.get(), isNewWalletCreated: isWalletCreated)); @@ -850,7 +853,7 @@ Future setup({ return ethereum!.createEthereumWalletService(_walletInfoSource); case WalletType.bitcoinCash: return bitcoinCash! - .createBitcoinCashWalletService(_walletInfoSource, _unspentCoinsInfoSource!); + .createBitcoinCashWalletService(_walletInfoSource, _unspentCoinsInfoSource); case WalletType.nano: return nano!.createNanoWalletService(_walletInfoSource); case WalletType.polygon: @@ -879,8 +882,8 @@ Future setup({ getIt.get(), getIt.get(param1: type), _walletInfoSource, type: type)); - getIt.registerFactoryParam( - (type, _) => WalletRestorePage(getIt.get(param1: type))); + getIt.registerFactoryParam((type, _) => WalletRestorePage( + getIt.get(param1: type), getIt.get())); getIt.registerFactoryParam, void>( (derivations, _) => WalletRestoreChooseDerivationViewModel(derivationInfos: derivations)); @@ -911,7 +914,7 @@ Future setup({ getIt.registerFactoryParam( (WalletType type, AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel) => - PreSeedPage(type, advancedPrivacySettingsViewModel)); + PreSeedPage(type, advancedPrivacySettingsViewModel, getIt.get())); getIt.registerFactoryParam((trade, _) => TradeDetailsViewModel( diff --git a/lib/entities/seed_type.dart b/lib/entities/seed_type.dart index 0a1a191c6..ab9965528 100644 --- a/lib/entities/seed_type.dart +++ b/lib/entities/seed_type.dart @@ -6,7 +6,7 @@ class SeedType extends EnumerableItem with Serializable { static const all = [SeedType.legacy, SeedType.polyseed]; - static const defaultSeedType = legacy; + static const defaultSeedType = polyseed; static const legacy = SeedType(raw: 0, title: 'Legacy (25 words)'); static const polyseed = SeedType(raw: 1, title: 'Polyseed (16 words)'); diff --git a/lib/router.dart b/lib/router.dart index 313751ab3..11eeb582b 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -56,13 +56,13 @@ import 'package:cake_wallet/src/screens/support_other_links/support_other_links_ import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart'; import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart'; -import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart'; import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; +import 'package:cake_wallet/view_model/seed_type_view_model.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:cw_core/nano_account.dart'; import 'package:cw_core/wallet_info.dart'; @@ -147,9 +147,9 @@ Route createRoute(RouteSettings settings) { case Routes.newWallet: final type = settings.arguments as WalletType; final walletNewVM = getIt.get(param1: type); - final settingsStore = getIt.get(); + final seedTypeViewModel = getIt.get(); - return CupertinoPageRoute(builder: (_) => NewWalletPage(walletNewVM, settingsStore)); + return CupertinoPageRoute(builder: (_) => NewWalletPage(walletNewVM, seedTypeViewModel)); case Routes.setupPin: Function(PinCodeState, String)? callback; @@ -535,9 +535,9 @@ Route createRoute(RouteSettings settings) { return CupertinoPageRoute( builder: (_) => AdvancedPrivacySettingsPage( - getIt.get(param1: type), - getIt.get(param1: type, param2: false), - )); + getIt.get(param1: type), + getIt.get(param1: type, param2: false), + getIt.get())); case Routes.anonPayInvoicePage: final args = settings.arguments as List; diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index 4b61e7889..a4bd6c7b9 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -9,6 +9,7 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell. import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; +import 'package:cake_wallet/view_model/seed_type_view_model.dart'; import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter/material.dart'; @@ -18,25 +19,30 @@ import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; class AdvancedPrivacySettingsPage extends BasePage { - AdvancedPrivacySettingsPage(this.advancedPrivacySettingsViewModel, this.nodeViewModel); + AdvancedPrivacySettingsPage( + this.advancedPrivacySettingsViewModel, this.nodeViewModel, this.seedTypeViewModel); final AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel; final NodeCreateOrEditViewModel nodeViewModel; + final SeedTypeViewModel seedTypeViewModel; @override String get title => S.current.privacy_settings; @override - Widget body(BuildContext context) => - AdvancedPrivacySettingsBody(advancedPrivacySettingsViewModel, nodeViewModel); + Widget body(BuildContext context) => AdvancedPrivacySettingsBody( + advancedPrivacySettingsViewModel, nodeViewModel, seedTypeViewModel); } class AdvancedPrivacySettingsBody extends StatefulWidget { - const AdvancedPrivacySettingsBody(this.privacySettingsViewModel, this.nodeViewModel, {Key? key}) + const AdvancedPrivacySettingsBody( + this.privacySettingsViewModel, this.nodeViewModel, this.seedTypeViewModel, + {Key? key}) : super(key: key); final AdvancedPrivacySettingsViewModel privacySettingsViewModel; final NodeCreateOrEditViewModel nodeViewModel; + final SeedTypeViewModel seedTypeViewModel; @override _AdvancedPrivacySettingsBodyState createState() => _AdvancedPrivacySettingsBodyState(); @@ -59,7 +65,7 @@ class _AdvancedPrivacySettingsBodyState extends State( - title: S.current.disable_fiat, + title: S.current.fiat_api, items: FiatApiMode.all, selectedItem: widget.privacySettingsViewModel.fiatApiMode, onItemSelected: (FiatApiMode mode) => @@ -114,8 +120,8 @@ class _AdvancedPrivacySettingsBodyState extends State( title: S.current.seedtype, items: SeedType.all, - selectedItem: widget.privacySettingsViewModel.seedType, - onItemSelected: widget.privacySettingsViewModel.setSeedType, + selectedItem: widget.seedTypeViewModel.moneroSeedType, + onItemSelected: widget.seedTypeViewModel.setMoneroSeedType, ), ); }), diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index 5c9533ace..8f913e229 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -7,6 +7,7 @@ import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/view_model/seed_type_view_model.dart'; import 'package:mobx/mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter/material.dart'; @@ -23,13 +24,12 @@ import 'package:cake_wallet/view_model/wallet_new_vm.dart'; import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; import 'package:cake_wallet/entities/seed_type.dart'; -import 'package:cake_wallet/store/settings_store.dart'; class NewWalletPage extends BasePage { - NewWalletPage(this._walletNewVM, this._settingsStore); + NewWalletPage(this._walletNewVM, this._seedTypeViewModel); final WalletNewVM _walletNewVM; - final SettingsStore _settingsStore; + final SeedTypeViewModel _seedTypeViewModel; final walletNameImage = Image.asset('assets/images/wallet_name.png'); @@ -40,15 +40,15 @@ class NewWalletPage extends BasePage { @override Widget body(BuildContext context) => WalletNameForm( - _walletNewVM, currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage, _settingsStore); + _walletNewVM, currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage, _seedTypeViewModel); } class WalletNameForm extends StatefulWidget { - WalletNameForm(this._walletNewVM, this.walletImage, this._settingsStore); + WalletNameForm(this._walletNewVM, this.walletImage, this._seedTypeViewModel); final WalletNewVM _walletNewVM; final Image walletImage; - final SettingsStore _settingsStore; + final SeedTypeViewModel _seedTypeViewModel; @override _WalletNameFormState createState() => _WalletNameFormState(_walletNewVM); @@ -194,7 +194,7 @@ class _WalletNameFormState extends State { builder: (BuildContext build) => Padding( padding: EdgeInsets.only(top: 24), child: SelectButton( - text: widget._settingsStore.moneroSeedType.title, + text: widget._seedTypeViewModel.moneroSeedType.title, onTap: () async { await showPopUp( context: context, @@ -217,7 +217,7 @@ class _WalletNameFormState extends State { key: _languageSelectorKey, initialSelected: defaultSeedLanguage, seedType: _walletNewVM.hasSeedType - ? widget._settingsStore.moneroSeedType + ? widget._seedTypeViewModel.moneroSeedType : SeedType.legacy, ), ), @@ -277,10 +277,10 @@ class _WalletNameFormState extends State { } } - bool get isPolyseed => widget._settingsStore.moneroSeedType == SeedType.polyseed; + bool get isPolyseed => widget._seedTypeViewModel.moneroSeedType == SeedType.polyseed; void _setSeedType(SeedType item) { - widget._settingsStore.moneroSeedType = item; + widget._seedTypeViewModel.setMoneroSeedType(item); _languageSelectorKey.currentState?.selected = defaultSeedLanguage; // Reset Seed language } } diff --git a/lib/src/screens/restore/wallet_restore_from_seed_form.dart b/lib/src/screens/restore/wallet_restore_from_seed_form.dart index f31657743..6f8f9eb2b 100644 --- a/lib/src/screens/restore/wallet_restore_from_seed_form.dart +++ b/lib/src/screens/restore/wallet_restore_from_seed_form.dart @@ -9,8 +9,10 @@ import 'package:cake_wallet/src/widgets/seed_language_picker.dart'; import 'package:cake_wallet/src/widgets/seed_widget.dart'; import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/view_model/seed_type_view_model.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; +import 'package:mobx/mobx.dart'; import 'package:polyseed/polyseed.dart'; class WalletRestoreFromSeedForm extends StatefulWidget { @@ -19,6 +21,7 @@ class WalletRestoreFromSeedForm extends StatefulWidget { required this.displayLanguageSelector, required this.displayBlockHeightSelector, required this.type, + required this.seedTypeViewModel, this.blockHeightFocusNode, this.onHeightOrDateEntered, this.onSeedChange, @@ -28,6 +31,7 @@ class WalletRestoreFromSeedForm extends StatefulWidget { final WalletType type; final bool displayLanguageSelector; final bool displayBlockHeightSelector; + final SeedTypeViewModel seedTypeViewModel; final FocusNode? blockHeightFocusNode; final Function(bool)? onHeightOrDateEntered; final void Function(String)? onSeedChange; @@ -52,16 +56,28 @@ class WalletRestoreFromSeedFormState extends State { final TextEditingController nameTextEditingController; final TextEditingController seedTypeController; final GlobalKey formKey; + late ReactionDisposer moneroSeedTypeReaction; String language; - bool isPolyseed = false; @override void initState() { + _setSeedType(widget.seedTypeViewModel.moneroSeedType); _setLanguageLabel(language); - _setSeedType(SeedType.defaultSeedType); + moneroSeedTypeReaction = + reaction((_) => widget.seedTypeViewModel.moneroSeedType, (SeedType item) { + _setSeedType(item); + _changeLanguage('English'); + }); + super.initState(); } + @override + void dispose() { + super.dispose(); + moneroSeedTypeReaction(); + } + void onSeedChange(String seed) { if (widget.type == WalletType.monero && Polyseed.isValidSeed(seed)) { final lang = PolyseedLang.getByPhrase(seed); @@ -181,6 +197,8 @@ class WalletRestoreFromSeedFormState extends State { ])); } + bool get isPolyseed => widget.seedTypeViewModel.moneroSeedType == SeedType.polyseed; + Widget get expandIcon => Container( padding: EdgeInsets.all(18), width: 24, @@ -208,10 +226,10 @@ class WalletRestoreFromSeedFormState extends State { void _changeSeedType(SeedType item) { _setSeedType(item); _changeLanguage('English'); + widget.seedTypeViewModel.setMoneroSeedType(item); } void _setSeedType(SeedType item) { - setState(() => isPolyseed = item == SeedType.polyseed); seedTypeController.text = item.toString(); } } diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index 445858f30..899aacd19 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -15,6 +15,7 @@ import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/restore/restore_mode.dart'; +import 'package:cake_wallet/view_model/seed_type_view_model.dart'; import 'package:cake_wallet/view_model/wallet_restore_view_model.dart'; import 'package:cw_core/nano_account_info_response.dart'; import 'package:cw_core/wallet_info.dart'; @@ -27,7 +28,7 @@ import 'package:polyseed/polyseed.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart'; class WalletRestorePage extends BasePage { - WalletRestorePage(this.walletRestoreViewModel) + WalletRestorePage(this.walletRestoreViewModel, this.seedTypeViewModel) : walletRestoreFromSeedFormKey = GlobalKey(), walletRestoreFromKeysFormKey = GlobalKey(), _pages = [], @@ -37,6 +38,7 @@ class WalletRestorePage extends BasePage { switch (mode) { case WalletRestoreMode.seed: _pages.add(WalletRestoreFromSeedForm( + seedTypeViewModel: seedTypeViewModel, displayBlockHeightSelector: walletRestoreViewModel.hasBlockchainHeightLanguageSelector, displayLanguageSelector: walletRestoreViewModel.hasSeedLanguageSelector, @@ -91,6 +93,7 @@ class WalletRestorePage extends BasePage { )); final WalletRestoreViewModel walletRestoreViewModel; + final SeedTypeViewModel seedTypeViewModel; final PageController _controller; final List _pages; final GlobalKey walletRestoreFromSeedFormKey; diff --git a/lib/src/screens/seed/pre_seed_page.dart b/lib/src/screens/seed/pre_seed_page.dart index a45d81fc0..64ef5da97 100644 --- a/lib/src/screens/seed/pre_seed_page.dart +++ b/lib/src/screens/seed/pre_seed_page.dart @@ -1,6 +1,8 @@ +import 'package:cake_wallet/entities/seed_type.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; +import 'package:cake_wallet/view_model/seed_type_view_model.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; @@ -10,19 +12,21 @@ import 'package:cake_wallet/themes/theme_base.dart'; import 'package:flutter/material.dart'; class PreSeedPage extends BasePage { - PreSeedPage(this.type, this.advancedPrivacySettingsViewModel) + PreSeedPage(this.type, this.advancedPrivacySettingsViewModel, this.seedTypeViewModel) : imageLight = Image.asset('assets/images/pre_seed_light.png'), imageDark = Image.asset('assets/images/pre_seed_dark.png'), - seedPhraseLength = - advancedPrivacySettingsViewModel.seedPhraseLength.value { - wordsCount = _wordsCount(type, seedPhraseLength); + seedPhraseLength = advancedPrivacySettingsViewModel.seedPhraseLength.value, + moneroSeedType = seedTypeViewModel.moneroSeedType { + wordsCount = _wordsCount(type, seedPhraseLength, moneroSeedType); } final Image imageDark; final Image imageLight; final WalletType type; final AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel; + final SeedTypeViewModel seedTypeViewModel; final int seedPhraseLength; + final SeedType moneroSeedType; late final int wordsCount; @override @@ -76,9 +80,11 @@ class PreSeedPage extends BasePage { )); } - static int _wordsCount(WalletType type, int seedPhraseLength) { + static int _wordsCount(WalletType type, int seedPhraseLength, SeedType moneroSeedType) { switch (type) { case WalletType.monero: + if (moneroSeedType == SeedType.polyseed) + return 16; return 25; case WalletType.ethereum: case WalletType.bitcoinCash: diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 3984bd81a..4078827d0 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -877,7 +877,7 @@ abstract class SettingsStoreBase with Store { } final savedSyncMode = SyncMode.all.firstWhere((element) { - return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 1); + return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 0); }); final savedSyncAll = sharedPreferences.getBool(PreferencesKey.syncAllKey) ?? true; diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart index f62815346..483f0837b 100644 --- a/lib/view_model/advanced_privacy_settings_view_model.dart +++ b/lib/view_model/advanced_privacy_settings_view_model.dart @@ -1,7 +1,6 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/seed_phrase_length.dart'; -import 'package:cake_wallet/entities/seed_type.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; @@ -20,9 +19,6 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { @computed FiatApiMode get fiatApiMode => _settingsStore.fiatApiMode; - @computed - SeedType get seedType => _settingsStore.moneroSeedType; - @observable bool _addCustomNode = false; @@ -44,9 +40,6 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { @action void setFiatApiMode(FiatApiMode fiatApiMode) => _settingsStore.fiatApiMode = fiatApiMode; - @action - void setSeedType(SeedType seedType) => _settingsStore.moneroSeedType = seedType; - @action void setExchangeApiMode(ExchangeApiMode value) => _settingsStore.exchangeStatus = value; diff --git a/lib/view_model/seed_type_view_model.dart b/lib/view_model/seed_type_view_model.dart new file mode 100644 index 000000000..e3597be1c --- /dev/null +++ b/lib/view_model/seed_type_view_model.dart @@ -0,0 +1,19 @@ +import 'package:cake_wallet/entities/seed_type.dart'; +import 'package:cake_wallet/store/app_store.dart'; +import 'package:mobx/mobx.dart'; + +part 'seed_type_view_model.g.dart'; + +class SeedTypeViewModel = SeedTypeViewModelBase with _$SeedTypeViewModel; + +abstract class SeedTypeViewModelBase with Store { + SeedTypeViewModelBase(this._appStore); + + @computed + SeedType get moneroSeedType => _appStore.settingsStore.moneroSeedType; + + @action + void setMoneroSeedType(SeedType seedType) => _appStore.settingsStore.moneroSeedType = seedType; + + final AppStore _appStore; +} diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart index 56ca190be..f931fec19 100644 --- a/lib/view_model/wallet_keys_view_model.dart +++ b/lib/view_model/wallet_keys_view_model.dart @@ -10,6 +10,7 @@ import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.d import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/haven/haven.dart'; import 'package:cw_monero/api/wallet.dart' as monero_wallet; +import 'package:polyseed/polyseed.dart'; part 'wallet_keys_view_model.g.dart'; @@ -74,6 +75,15 @@ abstract class WalletKeysViewModelBase with Store { StandartListItem(title: S.current.view_key_private, value: keys['privateViewKey']!), StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!), ]); + + if (_appStore.wallet?.seed != null && Polyseed.isValidSeed(_appStore.wallet!.seed!)) { + final lang = PolyseedLang.getByPhrase(_appStore.wallet!.seed!); + final legacyLang = _getLegacySeedLang(lang); + final legacySeed = + Polyseed.decode(_appStore.wallet!.seed!, lang, PolyseedCoin.POLYSEED_MONERO) + .toLegacySeed(legacyLang); + items.add(StandartListItem(title: S.current.wallet_seed_legacy, value: legacySeed)); + } } if (_appStore.wallet!.type == WalletType.haven) { @@ -207,4 +217,23 @@ abstract class WalletKeysViewModelBase with Store { } String getRoundedRestoreHeight(int height) => ((height / 1000).floor() * 1000).toString(); + + LegacySeedLang _getLegacySeedLang(PolyseedLang lang) { + switch (lang.nameEnglish) { + case "Spanish": + return LegacySeedLang.getByEnglishName("Spanish"); + case "French": + return LegacySeedLang.getByEnglishName("French"); + case "Italian": + return LegacySeedLang.getByEnglishName("Italian"); + case "Japanese": + return LegacySeedLang.getByEnglishName("Japanese"); + case "Portuguese": + return LegacySeedLang.getByEnglishName("Portuguese"); + case "Chinese (Simplified)": + return LegacySeedLang.getByEnglishName("Chinese (simplified)"); + default: + return LegacySeedLang.getByEnglishName("English"); + } + } } diff --git a/pubspec_base.yaml b/pubspec_base.yaml index b87347630..b85171ed0 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -104,9 +104,7 @@ dependencies: # ref: main socks5_proxy: ^1.0.4 flutter_svg: ^2.0.9 - polyseed: - git: - url: https://github.com/cake-tech/polyseed_dart.git + polyseed: ^0.0.2 dev_dependencies: flutter_test: diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 269400ffc..d1c59cfbb 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -747,5 +747,6 @@ "seed_language_korean": "الكورية", "seed_language_chinese_traditional": "تقاليد صينية)", "dfx_option_description": "ﺎﺑﻭﺭﻭﺃ ﻲﻓ ﺕﺎﻛﺮﺸﻟﺍﻭ ﺔﺋﺰﺠﺘﻟﺍ ءﻼﻤﻌﻟ .ﻲﻓﺎﺿﺇ KYC ﻥﻭﺪﺑ ﻭﺭﻮﻳ 990 ﻰﻟﺇ ﻞﺼﻳ ﺎﻣ .ﻱﺮﺴﻳﻮﺴﻟﺍ", - "polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ" + "polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ", + "wallet_seed_legacy": "بذرة محفظة قديمة" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 27c54cde5..e0ec30144 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -743,5 +743,6 @@ "seed_language_korean": "Корейски", "seed_language_chinese_traditional": "Традиционен китайски)", "dfx_option_description": "Купете крипто с EUR и CHF. До 990 € без допълнителен KYC. За клиенти на дребно и корпоративни клиенти в Европа", - "polygonscan_history": "История на PolygonScan" + "polygonscan_history": "История на PolygonScan", + "wallet_seed_legacy": "Наследено портфейл семе" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 10ed3b0e9..00de47f3a 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -743,5 +743,6 @@ "seed_language_korean": "korejština", "seed_language_chinese_traditional": "Číňan (tradiční)", "dfx_option_description": "Nakupujte kryptoměny za EUR a CHF. Až 990 € bez dalších KYC. Pro maloobchodní a firemní zákazníky v Evropě", - "polygonscan_history": "Historie PolygonScan" + "polygonscan_history": "Historie PolygonScan", + "wallet_seed_legacy": "Starší semeno peněženky" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index eef930971..ca3cda44f 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -751,5 +751,6 @@ "seed_language_korean": "Koreanisch", "seed_language_chinese_traditional": "Chinesisch (Traditionell)", "dfx_option_description": "Krypto mit EUR und CHF kaufen. Bis zu 990€ ohne zusätzliches KYC. Für Privat- und Firmenkunden in Europa", - "polygonscan_history": "PolygonScan-Verlauf" + "polygonscan_history": "PolygonScan-Verlauf", + "wallet_seed_legacy": "Legacy Wallet Seed" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 053ed0488..c8667afa9 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -752,5 +752,6 @@ "seed_language_korean": "Korean", "seed_language_chinese_traditional": "Chinese (Traditional)", "dfx_option_description": "Buy crypto with EUR & CHF. Up to 990€ without additional KYC. For retail and corporate customers in Europe", - "polygonscan_history": "PolygonScan history" + "polygonscan_history": "PolygonScan history", + "wallet_seed_legacy": "Legacy wallet seed" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index fcdaf17b1..335090eae 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -752,5 +752,6 @@ "seed_language_chinese_traditional": "Chino tradicional)", "dfx_option_description": "Compre criptomonedas con EUR y CHF. Hasta 990€ sin KYC adicional. Para clientes minoristas y corporativos en Europa", "seed_language_chinese_traditional": "Chino (tradicional)", - "polygonscan_history": "Historial de PolygonScan" -} + "polygonscan_history": "Historial de PolygonScan", + "wallet_seed_legacy": "Semilla de billetera heredada" +} \ No newline at end of file diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 3fe73f0b4..916cc935a 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -751,5 +751,6 @@ "seed_language_korean": "coréen", "seed_language_chinese_traditional": "Chinois (Traditionnel)", "dfx_option_description": "Achetez des crypto-monnaies avec EUR et CHF. Jusqu'à 990€ sans KYC supplémentaire. Pour les clients particuliers et entreprises en Europe", - "polygonscan_history": "Historique de PolygonScan" + "polygonscan_history": "Historique de PolygonScan", + "wallet_seed_legacy": "Graine de portefeuille hérité" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index d35f3a89e..32de934c2 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -729,5 +729,6 @@ "seed_language_korean": "Yaren Koriya", "seed_language_chinese_traditional": "Sinanci (na gargajiya)", "dfx_option_description": "Sayi crypto tare da EUR & CHF. Har zuwa € 990 ba tare da ƙarin KYC ba. Don 'yan kasuwa da abokan ciniki na kamfanoni a Turai", - "polygonscan_history": "PolygonScan tarihin kowane zamani" + "polygonscan_history": "PolygonScan tarihin kowane zamani", + "wallet_seed_legacy": "Tallarin walat walat" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index ce4ebc453..0ecbd9816 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -751,5 +751,6 @@ "seed_language_korean": "कोरियाई", "seed_language_chinese_traditional": "चीनी पारंपरिक)", "dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। अतिरिक्त केवाईसी के बिना 990€ तक। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए", - "polygonscan_history": "पॉलीगॉनस्कैन इतिहास" + "polygonscan_history": "पॉलीगॉनस्कैन इतिहास", + "wallet_seed_legacy": "विरासत बटुए बीज" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 4ab734f9f..bbe2c14ac 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -750,5 +750,6 @@ "seed_language_chinese_traditional": "Kinesko tradicionalno)", "dfx_option_description": "Kupujte kripto s EUR i CHF. Do 990 € bez dodatnog KYC-a. Za maloprodajne i poslovne korisnike u Europi", "seed_language_chinese_traditional": "Kinesko (tradicionalno)", - "polygonscan_history": "Povijest PolygonScan" -} + "polygonscan_history": "Povijest PolygonScan", + "wallet_seed_legacy": "Sjeme naslijeđenog novčanika" +} \ No newline at end of file diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 041bbd93c..8dfe60db8 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -740,5 +740,6 @@ "seed_language_chinese_traditional": "Cina tradisional)", "dfx_option_description": "Beli kripto dengan EUR & CHF. Hingga 990€ tanpa KYC tambahan. Untuk pelanggan ritel dan korporat di Eropa", "seed_language_chinese_traditional": "Cina (tradisional)", - "polygonscan_history": "Sejarah PolygonScan" -} + "polygonscan_history": "Sejarah PolygonScan", + "wallet_seed_legacy": "Biji dompet warisan" +} \ No newline at end of file diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 250edda6b..8ea3e3e0c 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -751,5 +751,6 @@ "seed_language_korean": "coreano", "seed_language_chinese_traditional": "Cinese tradizionale)", "dfx_option_description": "Acquista criptovalute con EUR e CHF. Fino a 990€ senza KYC aggiuntivi. Per clienti al dettaglio e aziendali in Europa", - "polygonscan_history": "Cronologia PolygonScan" + "polygonscan_history": "Cronologia PolygonScan", + "wallet_seed_legacy": "Seme di portafoglio legacy" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 37b5e60fd..f940bf37f 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -751,5 +751,6 @@ "seed_language_korean": "韓国語", "seed_language_chinese_traditional": "中国の伝統的な)", "dfx_option_description": "EUR と CHF で暗号通貨を購入します。追加のKYCなしで最大990ユーロ。ヨーロッパの小売および法人顧客向け", - "polygonscan_history": "ポリゴンスキャン履歴" + "polygonscan_history": "ポリゴンスキャン履歴", + "wallet_seed_legacy": "レガシーウォレットシード" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 611915f56..75d079a63 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -749,5 +749,6 @@ "seed_language_korean": "한국인", "seed_language_chinese_traditional": "중국 전통)", "dfx_option_description": "EUR 및 CHF로 암호화폐를 구매하세요. 추가 KYC 없이 최대 990€. 유럽의 소매 및 기업 고객용", - "polygonscan_history": "다각형 스캔 기록" + "polygonscan_history": "다각형 스캔 기록", + "wallet_seed_legacy": "레거시 지갑 시드" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index cf12b9b16..da26986c9 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -749,5 +749,6 @@ "seed_language_korean": "ကိုးရီးယား", "seed_language_chinese_traditional": "တရုတ်ရိုးရာ)", "dfx_option_description": "EUR & CHF ဖြင့် crypto ကိုဝယ်ပါ။ အပို KYC မပါဘဲ 990€ အထိ။ ဥရောပရှိ လက်လီရောင်းချသူများနှင့် ကော်ပိုရိတ်ဖောက်သည်များအတွက်", - "polygonscan_history": "PolygonScan မှတ်တမ်း" + "polygonscan_history": "PolygonScan မှတ်တမ်း", + "wallet_seed_legacy": "အမွေအနှစ်ပိုက်ဆံအိတ်မျိုးစေ့" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index b36a5a234..c3573dee7 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -752,5 +752,6 @@ "seed_language_chinese_traditional": "Chinese traditionele)", "dfx_option_description": "Koop crypto met EUR & CHF. Tot 990€ zonder extra KYC. Voor particuliere en zakelijke klanten in Europa", "seed_language_chinese_traditional": "Chinese (traditionele)", - "polygonscan_history": "PolygonScan-geschiedenis" -} + "polygonscan_history": "PolygonScan-geschiedenis", + "wallet_seed_legacy": "Legacy portemonnee zaad" +} \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index afb9bf9ec..da60d8fe7 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -751,5 +751,6 @@ "seed_language_korean": "koreański", "seed_language_chinese_traditional": "Chiński tradycyjny)", "dfx_option_description": "Kupuj kryptowaluty za EUR i CHF. Do 990 € bez dodatkowego KYC. Dla klientów detalicznych i korporacyjnych w Europie", - "polygonscan_history": "Historia PolygonScan" + "polygonscan_history": "Historia PolygonScan", + "wallet_seed_legacy": "Dziedziczne ziarno portfela" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index c2fe03ad3..08a2d05ee 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -750,5 +750,6 @@ "seed_language_korean": "coreano", "seed_language_chinese_traditional": "Chinês tradicional)", "dfx_option_description": "Compre criptografia com EUR e CHF. Até 990€ sem KYC adicional. Para clientes de varejo e corporativos na Europa", - "polygonscan_history": "História do PolygonScan" + "polygonscan_history": "História do PolygonScan", + "wallet_seed_legacy": "Semente de carteira herdada" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 107cbf596..cad832ae0 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -751,5 +751,6 @@ "seed_language_korean": "Корейский", "seed_language_chinese_traditional": "Китайский традиционный)", "dfx_option_description": "Покупайте криптовалюту за EUR и CHF. До 990€ без дополнительного KYC. Для розничных и корпоративных клиентов в Европе", - "polygonscan_history": "История PolygonScan" + "polygonscan_history": "История PolygonScan", + "wallet_seed_legacy": "Наследие семя кошелька" } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 134868c08..ee84b011f 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -749,5 +749,6 @@ "seed_language_korean": "เกาหลี", "seed_language_chinese_traditional": "จีน (ดั้งเดิม)", "dfx_option_description": "ซื้อ crypto ด้วย EUR และ CHF สูงถึง 990€ โดยไม่มี KYC เพิ่มเติม สำหรับลูกค้ารายย่อยและลูกค้าองค์กรในยุโรป", - "polygonscan_history": "ประวัติ PolygonScan" + "polygonscan_history": "ประวัติ PolygonScan", + "wallet_seed_legacy": "เมล็ดกระเป๋าเงินมรดก" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index d12e89378..1fd59d29a 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -745,5 +745,6 @@ "seed_language_korean": "Korean", "seed_language_chinese_traditional": "Intsik (tradisyonal)", "dfx_option_description": "Bumili ng crypto gamit ang EUR at CHF. Hanggang 990€ nang walang karagdagang KYC. Para sa retail at corporate na mga customer sa Europe", - "polygonscan_history": "Kasaysayan ng PolygonScan" + "polygonscan_history": "Kasaysayan ng PolygonScan", + "wallet_seed_legacy": "Legacy wallet seed" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 30a354caa..687f741f2 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -749,5 +749,6 @@ "seed_language_korean": "Koreli", "seed_language_chinese_traditional": "Çin geleneği)", "dfx_option_description": "EUR ve CHF ile kripto satın alın. Ek KYC olmadan 990 €'ya kadar. Avrupa'daki perakende ve kurumsal müşteriler için", - "polygonscan_history": "PolygonScan geçmişi" + "polygonscan_history": "PolygonScan geçmişi", + "wallet_seed_legacy": "Eski cüzdan tohumu" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index f977308b5..ee4af583e 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -751,5 +751,6 @@ "seed_language_korean": "Корейський", "dfx_option_description": "Купуйте криптовалюту за EUR і CHF. До 990 євро без додаткового KYC. Для роздрібних і корпоративних клієнтів у Європі", "seed_language_chinese_traditional": "Китайський (традиційний)", - "polygonscan_history": "Історія PolygonScan" -} + "polygonscan_history": "Історія PolygonScan", + "wallet_seed_legacy": "Спадець насіння гаманця" +} \ No newline at end of file diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index be7525c1b..d50cd62c6 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -743,5 +743,6 @@ "seed_language_korean": "کورین", "seed_language_chinese_traditional": "چینی (روایتی)", "dfx_option_description": "EUR ﺭﻭﺍ CHF ﯽﻓﺎﺿﺍ ۔ﮟﯾﺪﯾﺮﺧ ﻮﭩﭘﺮﮐ ﮫﺗﺎﺳ ﮯﮐ KYC ﮯﯿﻟ ﮯﮐ ﻦﯿﻓﺭﺎﺻ ﭧﯾﺭﻮﭘﺭﺎﮐ ﺭﻭﺍ ﮦﺩﺭﻮﺧ ﮟ", - "polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ" + "polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ", + "wallet_seed_legacy": "میراثی پرس کا بیج" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 63d21666e..538f2d4a9 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -745,5 +745,6 @@ "seed_language_korean": "Ara ẹni", "seed_language_chinese_traditional": "Kannada (ibile)", "dfx_option_description": "Ra crypto pẹlu EUR & CHF. Titi di 990 € laisi afikun KYC. Fun soobu ati awọn onibara ile-iṣẹ ni Yuroopu", - "polygonscan_history": "PolygonScan itan" + "polygonscan_history": "PolygonScan itan", + "wallet_seed_legacy": "Irugbin akole" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 25710eff5..ee6e9efd9 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -750,5 +750,6 @@ "seed_language_korean": "韩国人", "seed_language_chinese_traditional": "中国传统的)", "dfx_option_description": "用欧元和瑞士法郎购买加密货币。高达 990 欧元,无需额外 KYC。对于欧洲的零售和企业客户", - "polygonscan_history": "多边形扫描历史" + "polygonscan_history": "多边形扫描历史", + "wallet_seed_legacy": "旧的钱包种子" } From 7ce387c13024df974c327128003853b76b339b8c Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Mon, 11 Dec 2023 09:47:22 -0700 Subject: [PATCH 066/241] fix dot indicator color (#1228) --- lib/src/screens/dashboard/dashboard_page.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index 2552f4a4a..98b24f783 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -191,7 +191,10 @@ class _DashboardPageView extends BasePage { radius: 6.0, dotWidth: 6.0, dotHeight: 6.0, - dotColor: Theme.of(context).indicatorColor, + dotColor: Theme.of(context) + .extension()! + .indicatorDotTheme + .indicatorColor, activeDotColor: Theme.of(context) .extension()! .indicatorDotTheme From d5b9af1c193a130264b4a1d8336ac2f9a23126ab Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 13 Dec 2023 13:55:22 +0200 Subject: [PATCH 067/241] update localization --- lib/src/screens/setup_2fa/setup_2fa_qr_page.dart | 3 +-- 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 | 3 ++- res/values/strings_es.arb | 9 ++++++--- res/values/strings_fr.arb | 13 +++++++------ res/values/strings_ha.arb | 7 ++++++- res/values/strings_hi.arb | 9 ++++++--- res/values/strings_hr.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_yo.arb | 9 ++++++--- res/values/strings_zh.arb | 9 ++++++--- 27 files changed, 154 insertions(+), 79 deletions(-) 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 237107783..408e9e14d 100644 --- a/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart +++ b/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart @@ -27,7 +27,6 @@ class Setup2FAQRPage extends BasePage { Widget body(BuildContext context) { final copyImage = Image.asset('assets/images/copy_content.png', height: 16, width: 16, color: Theme.of(context).extension()!.titleColor); - final cake2FAHowToUseTitle = 'How to use'; final cake2FAHowToUseUrl = Uri.parse( 'https://guides.cakewallet.com/docs/advanced-features/authentication/#enabling-cake-2fa'); return Padding( @@ -183,7 +182,7 @@ class Setup2FAQRPage extends BasePage { mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ - Text(cake2FAHowToUseTitle, + Text(S.current.how_to_use, style: TextStyle( decoration: TextDecoration.underline, fontSize: 16, diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 207e95968..7119d1796 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -621,9 +621,9 @@ "totp_verification_success": "تم التحقق بنجاح!", "totp_2fa_failure": "شفرة خاطئة. يرجى تجربة رمز مختلف أو إنشاء مفتاح سري جديد. استخدم تطبيق 2FA متوافقًا يدعم الرموز المكونة من 8 أرقام و SHA512.", "enter_totp_code": "الرجاء إدخال رمز TOTP.", - "add_secret_code": "أضف هذا الرمز السري إلى جهاز آخر", + "add_secret_code": " ﺔﻗﺩﺎﺼﻤﻟﺍ ﻖﻴﺒﻄﺗ ﻰﻟﺇ ﻱﺮﺴﻟﺍ ﺰﻣﺮﻟﺍ ﺍﺬﻫ ﻒﺿﺃ ﻭﺃ", "totp_secret_code": "كود TOTP السري", - "setup_2fa_text": "كعكة 2FA ليست آمنة مثل التخزين البارد. تحمي 2FA من الأنواع الأساسية للهجمات ، مثل قيام صديقك بتقديم بصمة إصبعك أثناء نومك. لا تحمي Cake 2FA من جهاز مخترق من قِبل مهاجم متطور. إذا فقدت الوصول إلى رموز 2FA الخاصة بك ، ستفقد إمكانية الوصول إلى هذه المحفظة. سوف تحتاج إلى استعادة محفظتك من بذرة ذاكري. يجب عليك بالتالي الاحتفاظ بنسخة احتياطية من بذور الذاكرة الخاصة بك! علاوة على ذلك ، سيتمكن أي شخص لديه حق الوصول إلى بذرة (بذور) ذاكري من سرقة أموالك ، متجاوزًا Cake 2FA. لن يتمكن فريق دعم الكيك من مساعدتك إذا فقدت الوصول إلى بذرتك ، نظرًا لأن Cake هي المحفظة غير الحافظة.", + "setup_2fa_text": " .ﻲﻧﺎﺜﻟﺍ ﺔﻗﺩﺎﺼﻤﻟﺍ ﻞﻣﺎﻌﻛ TOTP ﻝﻼﺧ ﻦﻣ Cake 2FA ﻞﻤﻌﻳ", "setup_totp_recommended": "إعداد TOTP (موصى به)", "disable_buy": "تعطيل إجراء الشراء", "disable_sell": "قم بتعطيل إجراء البيع", @@ -737,5 +737,8 @@ "unavailable_balance": "ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ", "unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ", "unspent_change": "يتغير", - "tor_connection": "ﺭﻮﺗ ﻝﺎﺼﺗﺍ" + "tor_connection": "ﺭﻮﺗ ﻝﺎﺼﺗﺍ", + "setup_warning_2fa_text": ".ﺩﺭﺎﺒﻟﺍ ﻦﻳﺰﺨﺘﻟﺍ ﻞﺜﻣ ﺔﻨﻣﺁ ﺖﺴﻴﻟ ﺎﻬﻧﺇ .ﺔﻈﻔﺤﻤﻟﺍ ﻲﻓ ﺔﻨﻴﻌﻣ ﺕﺍءﺍﺮﺟﻹ ﺔﻴﻧﺎﺛ ﺔﻗﺩﺎﺼﻣ ﺔﺑﺎﺜ", + "scan_qr_on_device": " ﺮﺧﺁ ﺯﺎﻬﺟ ﻰﻠﻋ ﺎﻴًﺋﻮﺿ ﺍﺬﻫ ﺔﻌﻳﺮﺴﻟﺍ ﺔﺑﺎﺠﺘﺳﻻﺍ ﺰﻣﺭ ﺢﺴﻤﺑ ﻢﻗ", + "how_to_use": " ﻞﻤﻌﺘﺴﺗ ﻒﻴﻛ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index d253d19f3..536907a85 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -617,9 +617,9 @@ "totp_verification_success": "Проверката е успешна!", "totp_2fa_failure": "Грешен код. Моля, опитайте с различен код или генерирайте нов таен ключ. Използвайте съвместимо 2FA приложение, което поддържа 8-цифрени кодове и SHA512.", "enter_totp_code": "Моля, въведете TOTP кода.", - "add_secret_code": "Добавете този таен код към друго устройство", + "add_secret_code": "Или добавете този таен код към приложение за удостоверяване", "totp_secret_code": "TOTP таен код", - "setup_2fa_text": "Тортата 2FA НЕ е толкова сигурна, колкото хладилното съхранение. 2FA защитава срещу основни видове атаки, като например вашият приятел да предостави вашия пръстов отпечатък, докато спите.\n\n Cake 2FA НЕ защитава срещу компрометирано устройство от сложен хакер.\n\n Ако загубите достъп до своите 2FA кодове , ЩЕ ЗАГУБИТЕ ДОСТЪП ДО ТОЗИ ПОРТФЕЙЛ. Ще трябва да възстановите портфейла си от мнемонично семе. ЗАТОВА ТРЯБВА ДА НАПРАВИТЕ РЕЗЕРВНО КОПИЕ НА ВАШИТЕ МНЕМОНИЧНИ СЕМЕНА! Освен това, някой с достъп до вашите мнемонични начални точки ще може да открадне вашите средства, заобикаляйки Cake 2FA.\n\n Персоналът по поддръжката на Cake няма да може да ви помогне, ако загубите достъп до вашите мнемонични начални стойности, тъй като Cake е портфейл без попечителство.", + "setup_2fa_text": "Cake 2FA работи чрез TOTP като втори фактор за удостоверяване.\n\nTOTP на Cake 2FA изисква SHA-512 и поддръжка на 8 цифри; това осигурява повишена сигурност. Повече информация и поддържани приложения можете да намерите в ръководството тук.", "setup_totp_recommended": "Настройка на TOTP (препоръчително)", "disable_buy": "Деактивирайте действието за покупка", "disable_sell": "Деактивирайте действието за продажба", @@ -733,5 +733,8 @@ "unavailable_balance": "Неналично салдо", "unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.", "unspent_change": "Промяна", - "tor_connection": "Tor връзка" + "tor_connection": "Tor връзка", + "setup_warning_2fa_text": "Cake 2FA е второ удостоверяване за определени действия в портфейла. НЕ е толкова сигурно, колкото хладилното съхранение.\n Ако загубите достъп до вашето 2FA приложение или пароли, ЩЕ загубите достъп до този портфейл.\n Ще трябва да възстановите портфейла си от мнемоничното семе.\n Поддръжката на Cake няма да може да ви помогне, ако загубите достъп до вашите 2FA или мнемонични семена. Преди да използвате Cake 2FA, препоръчваме да прочетете ръководството.", + "scan_qr_on_device": "Сканирайте този QR код на друго устройство", + "how_to_use": "Как да използвам" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 1bc65f213..99fb6d3e3 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -617,9 +617,9 @@ "totp_verification_success": "Ověření proběhlo úspěšně!", "totp_2fa_failure": "Nesprávný kód. Zkuste prosím jiný kód nebo vygenerujte nový tajný klíč. Použijte kompatibilní aplikaci 2FA, která podporuje 8místné kódy a SHA512.", "enter_totp_code": "Zadejte kód TOTP.", - "add_secret_code": "Přidejte tento tajný kód do jiného zařízení", + "add_secret_code": "Nebo přidejte tento tajný kód do ověřovací aplikace", "totp_secret_code": "Tajný kód TOTP", - "setup_2fa_text": "Cake 2FA NENÍ tak bezpečný jako skladování v chladu. 2FA chrání před základními typy útoků, jako je váš přítel, který vám poskytne otisk prstu, když spíte.\n\n Cake 2FA nechrání před napadením zařízení sofistikovaným útočníkem.\n\n Pokud ztratíte přístup ke svým kódům 2FA , ZTRÁTÍTE PŘÍSTUP K TÉTO PENĚŽENCE. Budete muset obnovit svou peněženku z mnemotechnického semínka. MUSÍTE TEDY ZÁLOHOVAT SVÉ MNEMONICKÉ SEMÉNKY! Kromě toho někdo s přístupem k vašemu mnemotechnickému semenu bude moci ukrást vaše finanční prostředky a obejít Cake 2FA.\n\n Pracovníci podpory Cake vám nebudou schopni pomoci, pokud ztratíte přístup k vašemu mnemotechnickému semenu, protože Cake je nevazební peněženka.", + "setup_2fa_text": "Cake 2FA funguje přes TOTP jako druhý autentizační faktor.\n\nTOTP Cake 2FA vyžaduje SHA-512 a podporu 8 číslic; to poskytuje zvýšenou bezpečnost. Další informace a podporované aplikace naleznete v průvodci zde.", "setup_totp_recommended": "Nastavit TOTP (doporučeno)", "disable_buy": "Zakázat akci nákupu", "disable_sell": "Zakázat akci prodeje", @@ -733,5 +733,8 @@ "unavailable_balance": "Nedostupný zůstatek", "unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.", "unspent_change": "Změna", - "tor_connection": "Připojení Tor" + "tor_connection": "Připojení Tor", + "setup_warning_2fa_text": "Cake 2FA je druhá autentizace pro určité akce v peněžence. NENÍ tak bezpečný jako skladování v chladu.\n Pokud ztratíte přístup ke své aplikaci 2FA nebo přístupovým klíčům, ztratíte přístup k této peněžence.\n Budete muset obnovit svou peněženku z mnemotechnického semínka.\n Podpora dortů vám nebude schopna pomoci, pokud ztratíte přístup ke svým 2FA nebo mnemotechnickým semenům. Před použitím Cake 2FA doporučujeme přečíst si průvodce.", + "scan_qr_on_device": "Naskenujte tento QR kód na jiném zařízení", + "how_to_use": "Jak používat" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 41488a6f9..3e35f2a2a 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -625,9 +625,9 @@ "totp_verification_success": "Verifizierung erfolgreich!", "totp_2fa_failure": "Falscher Code. Bitte versuchen Sie es mit einem anderen Code oder generieren Sie einen neuen geheimen Schlüssel. Verwenden Sie eine kompatible 2FA-App, die 8-stellige Codes und SHA512 unterstützt.", "enter_totp_code": "Bitte geben Sie den TOTP-Code ein.", - "add_secret_code": "Fügen Sie diesen Geheimcode einem anderen Gerät hinzu", + "add_secret_code": "Oder fügen Sie diesen Geheimcode einer Authentifizierungs-App hinzu", "totp_secret_code": "TOTP-Geheimcode", - "setup_2fa_text": "Cake 2FA ist NICHT so sicher wie eine Cold Wallet. 2FA schützt vor grundlegenden Arten von Angriffen, z.B. wenn Ihr Freund Ihren Fingerabdruck verwendet, während Sie schlafen.\n\n Cake 2FA schützt NICHT vor einem kompromittierten Gerät durch einen raffinierten Angreifer.\n\n Wenn Sie den Zugriff auf Ihre 2FA-Codes verlieren , VERLIEREN SIE DEN ZUGANG ZU DIESEM WALLET. Sie müssen Ihre Wallet aus mnemonic Seed wiederherstellen. SIE MÜSSEN DESHALB IHRE MNEMONISCHEN SEEDS SICHERN! Außerdem kann jemand mit Zugriff auf Ihre mnemonischen Seed(s) Ihr Geld stehlen und Cake 2FA umgehen.\n\n Cake-Supportmitarbeiter können Ihnen nicht helfen, wenn Sie den Zugriff auf Ihre mnemonischen Seed(s) verlieren, da Cake Wallet eine Wallet ohne treuhänderische Verwahrung ist.", + "setup_2fa_text": "Cake 2FA funktioniert über TOTP als zweiten Authentifizierungsfaktor.\n\nDas TOTP von Cake 2FA erfordert SHA-512 und 8-stellige Unterstützung; Dies sorgt für erhöhte Sicherheit. Weitere Informationen und unterstützte Apps finden Sie im Leitfaden hier.", "setup_totp_recommended": "TOTP einrichten (empfohlen)", "disable_buy": "Kaufaktion deaktivieren", "disable_sell": "Verkaufsaktion deaktivieren", @@ -741,5 +741,8 @@ "unavailable_balance": "Nicht verfügbares Guthaben", "unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.", "unspent_change": "Wechselgeld", - "tor_connection": "Tor-Verbindung" + "tor_connection": "Tor-Verbindung", + "setup_warning_2fa_text": "Cake 2FA ist eine zweite Authentifizierung für bestimmte Aktionen im Wallet. Es ist NICHT so sicher wie eine Kühllagerung.\n Wenn Sie den Zugriff auf Ihre 2FA-App oder Ihre Passkeys verlieren, verlieren Sie auch den Zugriff auf dieses Wallet.\n Sie müssen Ihr Wallet aus dem mnemonischen Seed wiederherstellen.\n Der Cake-Support kann Ihnen nicht weiterhelfen, wenn Sie den Zugriff auf Ihre 2FA- oder Mnemonik-Seeds verlieren. Bevor Sie Cake 2FA verwenden, empfehlen wir Ihnen, die Anleitung durchzulesen.", + "scan_qr_on_device": "Scannen Sie diesen QR-Code auf einem anderen Gerät", + "how_to_use": "Wie benutzt man" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 54a78863f..35c2ef890 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -744,5 +744,6 @@ "unavailable_balance": "Unavailable balance", "unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.", "unspent_change": "Change", - "tor_connection": "Tor connection" + "tor_connection": "Tor connection", + "how_to_use": "How to use" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 41a13288e..446a8f376 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -625,9 +625,9 @@ "totp_verification_success": "¡Verificación exitosa!", "totp_2fa_failure": "Código incorrecto. Intente con un código diferente o genere una nueva clave secreta. Use una aplicación 2FA compatible que admita códigos de 8 dígitos y SHA512.", "enter_totp_code": "Ingrese el código TOTP.", - "add_secret_code": "Agregue este código secreto a otro dispositivo", + "add_secret_code": "O agregue este código secreto a una aplicación de autenticación", "totp_secret_code": "Código secreto TOTP", - "setup_2fa_text": "Cake 2FA NO es tan seguro como el almacenamiento en frío. 2FA protege contra tipos básicos de ataques, como cuando un amigo proporciona su huella digital mientras usted duerme.\n\n Cake 2FA NO protege contra un dispositivo comprometido por un atacante sofisticado.\n\n Si pierde el acceso a sus códigos 2FA , PERDERÁS EL ACCESO A ESTA BILLETERA. Deberá restaurar su billetera desde la semilla mnemotécnica. ¡POR LO TANTO, DEBE HACER UNA COPIA DE SEGURIDAD DE SUS SEMILLAS MNEMÓNICAS! Además, alguien con acceso a sus semillas mnemotécnicas podrá robar sus fondos, sin pasar por Cake 2FA.\n\n El personal de soporte de Cake no podrá ayudarlo si pierde el acceso a su semilla mnemotécnica, ya que Cake es un billetera sin custodia.", + "setup_2fa_text": "Cake 2FA funciona a través de TOTP como segundo factor de autenticación.\n\nEl TOTP de Cake 2FA requiere SHA-512 y soporte de 8 dígitos; esto proporciona una mayor seguridad. Puede encontrar más información y aplicaciones compatibles en la guía aquí.", "setup_totp_recommended": "Configurar TOTP (Recomendado)", "disable_buy": "Desactivar acción de compra", "disable_sell": "Desactivar acción de venta", @@ -741,5 +741,8 @@ "unavailable_balance": "Saldo no disponible", "unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.", "unspent_change": "Cambiar", - "tor_connection": "conexión tor" + "tor_connection": "conexión tor", + "setup_warning_2fa_text": "Cake 2FA es una segunda autenticación para ciertas acciones en la billetera. NO es tan seguro como el almacenamiento en frío.\n Si pierde el acceso a su aplicación 2FA o a sus claves de acceso, perderá el acceso a esta billetera.\n Deberá restaurar su billetera a partir de la semilla mnemotécnica.\n El soporte de Cake no podrá ayudarlo si pierde el acceso a su 2FA o a sus semillas mnemotécnicas. Antes de usar Cake 2FA, recomendamos leer la guía.", + "scan_qr_on_device": "Escanea este código QR en otro dispositivo", + "how_to_use": "Cómo utilizar" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 1c44c9513..acb3c2706 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -625,9 +625,9 @@ "totp_verification_success": "Vérification réussie !", "totp_2fa_failure": "Code incorrect. Veuillez essayer un code différent ou générer un nouveau secret TOTP. Utilisez une application 2FA compatible qui prend en charge les codes à 8 chiffres et SHA512.", "enter_totp_code": "Veuillez entrer le code TOTP.", - "add_secret_code": "Configurer un autre appareil à l'aide de ce secret TOTP", + "add_secret_code": "Ou ajoutez ce code secret à une application d'authentification", "totp_secret_code": "Secret TOTP", - "setup_2fa_text": "Cake 2FA (Authentification à 2 Facteurs) n'est PAS aussi sûr que le stockage à froid. Cake 2FA protège contre les attaques basiques, comme un ami fournissant votre empreinte digitale pendant que vous dormez.\n\n Cake 2FA ne protège PAS contre un appareil compromis par un attaquant sophistiqué.\n\n Si vous perdez l'accès à vos codes 2FA , VOUS PERDREZ L'ACCÈS À CE PORTEFEUILLE (WALLET). Vous devrez restaurer votre portefeuille à partir de sa phrase secrète (seed). VOUS DEVEZ DONC SAUVEGARDER VOTRE PHRASE SECRÈTE ! De plus, quelqu'un ayant accès à votre phrase secrète pourra voler vos fonds, en contournant Cake 2FA.\n\n Le personnel d'assistance de Cake ne pourra pas vous aider si vous perdez l'accès à votre phrase secrète, puisque Cake est un portefeuille non dépositaire (non custodial).", + "setup_2fa_text": "Cake 2FA fonctionne via TOTP comme deuxième facteur d'authentification.\n\nLe TOTP de Cake 2FA nécessite la prise en charge de SHA-512 et de 8 chiffres ; cela offre une sécurité accrue. Plus d’informations et les applications prises en charge peuvent être trouvées dans le guide ici.", "setup_totp_recommended": "Configurer TOTP (recommandé)", "disable_buy": "Désactiver l'action d'achat", "disable_sell": "Désactiver l'action de vente", @@ -728,7 +728,7 @@ "exchange_provider_unsupported": "${providerName} n'est plus pris en charge !", "domain_looks_up": "Résolution de nom", "require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes", - "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", + "camera_permission_is_required": "L'autorisation d'accès à la caméra est requise.\nVeuillez l'activer depuis les paramètres de l'application.", "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", "importNFTs": "Importer des NFT", "noNFTYet": "Pas encore de NFT", @@ -740,8 +740,9 @@ "seed_phrase_length": "Longueur de la phrase de départ", "unavailable_balance": "Solde indisponible", "unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.", - "camera_permission_is_required": "L'autorisation d'accès à la caméra est requise.\nVeuillez l'activer depuis les paramètres de l'application.", - "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", "unspent_change": "Changement", - "tor_connection": "Connexion Tor" + "tor_connection": "Connexion Tor", + "setup_warning_2fa_text": "Cake 2FA est une seconde authentification pour certaines actions dans le portefeuille. Ce n’est PAS aussi sécurisé que l’entreposage frigorifique.\n Si vous perdez l'accès à votre application 2FA ou à vos mots de passe, vous perdrez l'accès à ce portefeuille.\n Vous devrez restaurer votre portefeuille à partir de la graine mnémonique.\n Le support Cake ne pourra pas vous aider si vous perdez l'accès à vos graines 2FA ou mnémoniques. Avant d'utiliser Cake 2FA, nous vous recommandons de lire le guide.", + "scan_qr_on_device": "Scannez ce code QR sur un autre appareil", + "how_to_use": "Comment utiliser" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 8b6f38d05..9c25ce24c 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -720,5 +720,10 @@ "unavailable_balance": "Ma'aunin da ba ya samuwa", "unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.", "unspent_change": "Canza", - "tor_connection": "Tor haɗin gwiwa" + "tor_connection": "Tor haɗin gwiwa", + "setup_2fa_text": "Cake 2FA yana aiki ta hanyar TOTP azaman ƙimar tabbatarwa ta biyu.\n\nCake 2FA's TOTP yana buƙatar tallafin lambobi SHA-512 da 8; wannan yana ba da ƙarin tsaro. Ana iya samun ƙarin bayani da aikace-aikacen tallafi a cikin jagorar nan.", + "setup_warning_2fa_text": "Cake 2FA tabbaci ne na biyu don wasu ayyuka a cikin walat. BA shi da tsaro kamar ajiyar sanyi.\n Idan ka rasa damar yin amfani da app ɗinka na 2FA ko maɓallan wucewa, ZA KA rasa damar shiga wannan wallet ɗin.\n Kuna buƙatar dawo da walat ɗin ku daga zuriyar mnemonic.\n Tallafin kek ba zai iya taimaka muku ba idan kun rasa damar yin amfani da 2FA ko tsaba na mnemonic. Kafin amfani da Cake 2FA, muna ba da shawarar karanta ta cikin jagorar.", + "add_secret_code": "Ko, ƙara wannan lambar sirrin zuwa ƙa'idar mai tabbatarwa", + "scan_qr_on_device": "Duba wannan lambar QR akan wata na'ura", + "how_to_use": "Yadda ake amfani da shi" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 075fe14da..31fa7656a 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -625,9 +625,9 @@ "totp_verification_success": "सत्यापन सफल!", "totp_2fa_failure": "गलत कोड़। कृपया एक अलग कोड का प्रयास करें या एक नई गुप्त कुंजी उत्पन्न करें। 8-अंकीय कोड और SHA512 का समर्थन करने वाले संगत 2FA ऐप का उपयोग करें।", "enter_totp_code": "कृपया TOTP कोड दर्ज करें।", - "add_secret_code": "इस गुप्त कोड को किसी अन्य डिवाइस में जोड़ें", + "add_secret_code": "या, इस गुप्त कोड को प्रमाणक ऐप में जोड़ें", "totp_secret_code": "टीओटीपी गुप्त कोड", - "setup_2fa_text": "केक 2FA कोल्ड स्टोरेज जितना सुरक्षित नहीं है। 2FA बुनियादी प्रकार के हमलों से बचाता है, जैसे कि आपका मित्र सोते समय आपको अपना फ़िंगरप्रिंट प्रदान करता है।\n\n Cake 2FA परिष्कृत हमलावर द्वारा किसी डिवाइस से छेड़छाड़ से रक्षा नहीं करता है।\n\n यदि आप अपने 2FA कोड तक पहुंच खो देते हैं , आप इस वॉलेट तक पहुंच खो देंगे। आपको अपने बटुए को स्मरणीय बीज से पुनर्स्थापित करने की आवश्यकता होगी। इसलिए आपको अपने स्मरणीय बीजों का बैकअप लेना चाहिए! इसके अलावा, आपके स्मरक बीज (बीजों) तक पहुंच रखने वाला कोई व्यक्ति केक 2FA को दरकिनार कर आपके धन की चोरी करने में सक्षम होगा। अप्रबंधित बटुआ।", + "setup_2fa_text": "केक 2FA दूसरे प्रमाणीकरण कारक के रूप में TOTP के माध्यम से काम करता है।\n\nकेक 2FA के TOTP को SHA-512 और 8 अंकों के समर्थन की आवश्यकता है; इससे अधिक सुरक्षा मिलती है. अधिक जानकारी और समर्थित ऐप्स यहां गाइड में पाए जा सकते हैं।", "setup_totp_recommended": "टीओटीपी सेट अप करें (अनुशंसित)", "disable_buy": "खरीद कार्रवाई अक्षम करें", "disable_sell": "बेचने की कार्रवाई अक्षम करें", @@ -741,5 +741,8 @@ "unavailable_balance": "अनुपलब्ध शेष", "unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।", "unspent_change": "परिवर्तन", - "tor_connection": "टोर कनेक्शन" + "tor_connection": "टोर कनेक्शन", + "setup_warning_2fa_text": "केक 2एफए वॉलेट में कुछ कार्यों के लिए दूसरा प्रमाणीकरण है। यह कोल्ड स्टोरेज जितना सुरक्षित नहीं है।\n यदि आप अपने 2एफए ऐप या पासकी तक पहुंच खो देते हैं, तो आप इस वॉलेट तक पहुंच खो देंगे।\n आपको अपने बटुए को स्मरक बीज से पुनर्स्थापित करने की आवश्यकता होगी।\n यदि आप अपने 2एफए या निमोनिक बीजों तक पहुंच खो देते हैं तो केक समर्थन आपकी सहायता करने में असमर्थ होगा। केक 2एफए का उपयोग करने से पहले, हम गाइड को पढ़ने की सलाह देते हैं।", + "scan_qr_on_device": "इस QR कोड को किसी अन्य डिवाइस पर स्कैन करें", + "how_to_use": "का उपयोग कैसे करें" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 9d5e2af2b..a877a5030 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -625,9 +625,9 @@ "totp_verification_success": "Provjera uspješna!", "totp_2fa_failure": "Neispravan kod. Pokušajte s drugim kodom ili generirajte novi tajni ključ. Koristite kompatibilnu 2FA aplikaciju koja podržava 8-znamenkasti kod i SHA512.", "enter_totp_code": "Unesite TOTP kod.", - "add_secret_code": "Dodajte ovaj tajni kod na drugi uređaj", + "add_secret_code": "Ili dodajte ovaj tajni kod u aplikaciju za autentifikaciju", "totp_secret_code": "TOTP tajni kod", - "setup_2fa_text": "Torta 2FA NIJE sigurna kao hladno skladište. 2FA štiti od osnovnih vrsta napada, kao što je vaš prijatelj koji vam daje otisak prsta dok spavate.\n\n Cake 2FA NE štiti od kompromitiranog uređaja od strane sofisticiranog napadača.\n\n Ako izgubite pristup svojim 2FA kodovima , IZGUBIT ĆETE PRISTUP OVOM NOVČANIKU. Morat ćete obnoviti svoj novčanik iz mnemoničkog sjemena. STOGA MORATE NAPRAVITI SIGURNOSNE KOPIJE SVOJIH MNEMONIČKIH SJEMENA! Nadalje, netko tko ima pristup vašem mnemoničkom seedu(ima) moći će ukrasti vaša sredstva, zaobilazeći Cake 2FA.\n\n Cake osoblje za podršku neće vam moći pomoći ako izgubite pristup svom mnemoničkom seedu, budući da je Cake neskrbnički novčanik.", + "setup_2fa_text": "Cake 2FA radi preko TOTP-a kao drugog faktora provjere autentičnosti.\n\nCake 2FA TOTP zahtijeva SHA-512 i podršku za 8 znamenki; ovo osigurava povećanu sigurnost. Više informacija i podržanih aplikacija možete pronaći u vodiču ovdje.", "setup_totp_recommended": "Postavite TOTP (preporučeno)", "disable_buy": "Onemogući kupnju", "disable_sell": "Onemogući akciju prodaje", @@ -739,5 +739,8 @@ "unavailable_balance": "Nedostupno stanje", "unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.", "unspent_change": "Promijeniti", - "tor_connection": "Tor veza" + "tor_connection": "Tor veza", + "setup_warning_2fa_text": "Cake 2FA je druga provjera autentičnosti za određene radnje u novčaniku. NIJE siguran kao hladno skladište.\n Ako izgubite pristup svojoj 2FA aplikaciji ili pristupnim ključevima, IZGUBIT ĆETE pristup ovom novčaniku.\n Morat ćete obnoviti svoj novčanik iz mnemoničkog sjemena.\n Podrška za kolače neće vam moći pomoći ako izgubite pristup svojim 2FA ili mnemoničkim izvorima. Prije uporabe Cake 2FA preporučujemo da pročitate vodič.", + "scan_qr_on_device": "Skenirajte ovaj QR kod na drugom uređaju", + "how_to_use": "Kako koristiti" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 234585064..a84ad29de 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -613,9 +613,9 @@ "totp_verification_success": "Verifikasi Berhasil!", "totp_2fa_failure": "Kode salah. Silakan coba kode lain atau buat kunci rahasia baru. Gunakan aplikasi 2FA yang kompatibel yang mendukung kode 8 digit dan SHA512.", "enter_totp_code": "Masukkan Kode TOTP.", - "add_secret_code": "Tambahkan kode rahasia ini ke perangkat lain", + "add_secret_code": "Atau, tambahkan kode rahasia ini ke aplikasi autentikator", "totp_secret_code": "Kode Rahasia TOTP", - "setup_2fa_text": "Cake 2FA TIDAK seaman cold storage. 2FA melindungi dari jenis serangan dasar, seperti teman Anda memberikan sidik jari saat Anda sedang tidur.\n\n Cake 2FA TIDAK melindungi dari perangkat yang disusupi oleh penyerang canggih.\n\n Jika Anda kehilangan akses ke kode 2FA , ANDA AKAN KEHILANGAN AKSES KE DOMPET INI. Anda perlu memulihkan dompet Anda dari benih mnemonik. OLEH KARENA ITU, ANDA HARUS MENYIMPAN BIJI MNEMONIK ANDA! Selanjutnya, seseorang yang memiliki akses ke benih mnemonik Anda akan dapat mencuri dana Anda, melewati Cake 2FA.\n\n Staf pendukung Cake tidak akan dapat membantu Anda jika Anda kehilangan akses ke benih mnemonik Anda, karena Cake adalah dompet tanpa hak asuh.", + "setup_2fa_text": "Cake 2FA bekerja melalui TOTP sebagai faktor otentikasi kedua.\n\nTOTP Cake 2FA memerlukan SHA-512 dan dukungan 8 digit; ini memberikan peningkatan keamanan. Informasi lebih lanjut dan aplikasi yang didukung dapat ditemukan dalam panduan di sini.", "setup_totp_recommended": "Siapkan TOTP (Disarankan)", "disable_buy": "Nonaktifkan tindakan beli", "disable_sell": "Nonaktifkan aksi jual", @@ -729,5 +729,8 @@ "unavailable_balance": "Saldo tidak tersedia", "unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.", "unspent_change": "Mengubah", - "tor_connection": "koneksi Tor" + "tor_connection": "koneksi Tor", + "setup_warning_2fa_text": "Cake 2FA adalah otentikasi kedua untuk tindakan tertentu di dompet. Ini TIDAK seaman penyimpanan dingin.\n Jika Anda kehilangan akses ke aplikasi 2FA atau kunci sandi, Anda AKAN kehilangan akses ke dompet ini.\n Anda perlu memulihkan dompet Anda dari benih mnemonik.\n Dukungan kue tidak akan dapat membantu Anda jika Anda kehilangan akses ke 2FA atau benih mnemonik. Sebelum menggunakan Cake 2FA, kami sarankan untuk membaca panduannya.", + "scan_qr_on_device": "Pindai kode QR ini di perangkat lain", + "how_to_use": "Cara Penggunaan" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 73e5d01bb..77ff9a14f 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -625,9 +625,9 @@ "totp_verification_success": "Verifica riuscita!", "totp_2fa_failure": "Codice non corretto. Prova un codice diverso o genera una nuova chiave segreta. Utilizza un'app 2FA compatibile che supporti codici a 8 cifre e SHA512.", "enter_totp_code": "Inserisci il codice TOTP.", - "add_secret_code": "Aggiungi questo codice segreto a un altro dispositivo", + "add_secret_code": "Oppure aggiungi questo codice segreto a un'app di autenticazione", "totp_secret_code": "TOTP codice segreto", - "setup_2fa_text": "Cake 2FA NON è sicuro come la cella frigorifera. 2FA protegge da tipi di attacchi di base, come il tuo amico che fornisce la tua impronta digitale mentre dormi.\n\n Cake 2FA NON protegge da un dispositivo compromesso da un aggressore sofisticato.\n\n Se perdi l'accesso ai tuoi codici 2FA , PERDERAI L'ACCESSO A QUESTO PORTAFOGLIO. Dovrai ripristinare il tuo portafoglio dal seme mnemonico. DOVETE QUINDI SOSTITUIRE I VOSTRI SEMI MNEMONICI! Inoltre, qualcuno con accesso ai tuoi seed mnemonici sarà in grado di rubare i tuoi fondi, aggirando Cake 2FA.\n\n Il personale di supporto di Cake non sarà in grado di aiutarti se perdi l'accesso al tuo seed mnemonico, poiché Cake è un portafoglio non detentivo.", + "setup_2fa_text": "Cake 2FA funziona tramite TOTP come secondo fattore di autenticazione.\n\nIl TOTP di Cake 2FA richiede il supporto SHA-512 e 8 cifre; ciò fornisce una maggiore sicurezza. Maggiori informazioni e app supportate sono disponibili nella guida qui.", "setup_totp_recommended": "Imposta TOTP (consigliato)", "disable_buy": "Disabilita l'azione di acquisto", "disable_sell": "Disabilita l'azione di vendita", @@ -741,5 +741,8 @@ "unavailable_balance": "Saldo non disponibile", "unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.", "unspent_change": "Modifica", - "tor_connection": "Connessione Tor" + "tor_connection": "Connessione Tor", + "setup_warning_2fa_text": "Cake 2FA è una seconda autenticazione per determinate azioni nel portafoglio. NON è sicuro come la conservazione a freddo.\n Se perdi l'accesso alla tua app 2FA o alle passkey, perderai l'accesso a questo portafoglio.\n Dovrai ripristinare il tuo portafoglio dal seme mnemonico.\n Il supporto di Cake non sarà in grado di assisterti se perdi l'accesso ai tuoi seed 2FA o mnemonici. Prima di utilizzare Cake 2FA, ti consigliamo di leggere la guida.", + "scan_qr_on_device": "Scansiona questo codice QR su un altro dispositivo", + "how_to_use": "Come usare" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 7cd82ef14..38f1f2b7a 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -625,9 +625,9 @@ "totp_verification_success": "検証成功!", "totp_2fa_failure": "コードが正しくありません。 別のコードを試すか、新しい秘密鍵を生成してください。 8 桁のコードと SHA512 をサポートする互換性のある 2FA アプリを使用してください。", "enter_totp_code": "TOTPコードを入力してください。", - "add_secret_code": "このシークレット コードを別のデバイスに追加する", + "add_secret_code": "または、このシークレット コードを認証アプリに追加します", "totp_secret_code": "TOTPシークレットコード", - "setup_2fa_text": "Cake 2FA は、コールド ストレージほど安全ではありません。 2FA は、あなたが寝ているときに友人が指紋を提供するなどの基本的なタイプの攻撃から保護します。\n\n Cake 2FA は、巧妙な攻撃者による侵害されたデバイスから保護しません。\n\n 2FA コードにアクセスできなくなった場合、このウォレットにアクセスできなくなります。ニーモニック シードからウォレットを復元する必要があります。したがって、ニーモニック シードをバックアップする必要があります。さらに、あなたのニーモニック シードにアクセスできる誰かが、Cake 2FA をバイパスして、あなたの資金を盗むことができます。\n\n Cake は無印の財布。", + "setup_2fa_text": "Cake 2FA は、TOTP を通じて 2 番目の認証要素として機能します。\n\nCake 2FA の TOTP には SHA-512 と 8 桁のサポートが必要です。これによりセキュリティが強化されます。詳細とサポートされているアプリについては、こちらのガイドをご覧ください。", "setup_totp_recommended": "TOTP を設定する (推奨)", "disable_buy": "購入アクションを無効にする", "disable_sell": "販売アクションを無効にする", @@ -741,5 +741,8 @@ "unavailable_balance": "利用できない残高", "unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。", "unspent_change": "変化", - "tor_connection": "Tor接続" + "tor_connection": "Tor接続", + "setup_warning_2fa_text": "Cake 2FA は、ウォレット内の特定のアクションに対する 2 番目の認証です。冷蔵保存ほど安全ではありません。\n 2FA アプリまたはパスキーにアクセスできなくなると、このウォレットにもアクセスできなくなります。\n ニーモニックシードからウォレットを復元する必要があります。\n 2FA またはニーモニック シードにアクセスできなくなった場合、Cake サポートはサポートできません。 Cake 2FA を使用する前に、ガイドを一読することをお勧めします。", + "scan_qr_on_device": "別のデバイスでこの QR コードをスキャンします", + "how_to_use": "使い方" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 2ef5d3577..e6c140d74 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -625,9 +625,9 @@ "totp_verification_success": "확인 성공!", "totp_2fa_failure": "잘못된 코드입니다. 다른 코드를 시도하거나 새 비밀 키를 생성하십시오. 8자리 코드와 SHA512를 지원하는 호환되는 2FA 앱을 사용하세요.", "enter_totp_code": "TOTP 코드를 입력하세요.", - "add_secret_code": "이 비밀 코드를 다른 장치에 추가", + "add_secret_code": "또는 이 비밀 코드를 인증 앱에 추가하세요.", "totp_secret_code": "TOTP 비밀 코드", - "setup_2fa_text": "케이크 2FA는 냉장 보관만큼 안전하지 않습니다. 2FA는 당신이 잠자는 동안 친구가 지문을 제공하는 것과 같은 기본적인 유형의 공격으로부터 보호합니다.\n\n Cake 2FA는 정교한 공격자에 의해 손상된 장치로부터 보호하지 않습니다.\n\n 2FA 코드에 대한 액세스 권한을 잃으면 , 이 지갑에 대한 액세스 권한을 잃게 됩니다. 니모닉 시드에서 지갑을 복원해야 합니다. 따라서 니모닉 시드를 백업해야 합니다! 또한 니모닉 시드에 액세스할 수 있는 사람이 Cake 2FA를 우회하여 자금을 훔칠 수 있습니다.\n\n 니모닉 시드에 대한 액세스 권한을 잃으면 Cake 지원 직원이 도와줄 수 없습니다. 비수탁 지갑.", + "setup_2fa_text": "Cake 2FA는 TOTP를 두 번째 인증 요소로 사용합니다.\n\nCake 2FA의 TOTP에는 SHA-512 및 8자리 지원이 필요합니다. 이는 보안을 강화합니다. 자세한 내용과 지원되는 앱은 여기 가이드에서 확인할 수 있습니다.", "setup_totp_recommended": "TOTP 설정(권장)", "disable_buy": "구매 행동 비활성화", "disable_sell": "판매 조치 비활성화", @@ -739,5 +739,8 @@ "unavailable_balance": "사용할 수 없는 잔액", "unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.", "unspent_change": "변화", - "tor_connection": "토르 연결" + "tor_connection": "토르 연결", + "setup_warning_2fa_text": "Cake 2FA는 지갑의 특정 작업에 대한 두 번째 인증입니다. 냉장 보관만큼 안전하지 않습니다.\n 2FA 앱이나 비밀번호 키에 접근할 수 없게 되면 이 지갑에 접근할 수 없게 됩니다.\n 니모닉 시드에서 지갑을 복원해야 합니다.\n 2FA 또는 니모닉 시드에 액세스할 수 없는 경우 Cake 지원팀에서 도움을 드릴 수 없습니다. Cake 2FA를 사용하기 전에 가이드를 읽어 보시기 바랍니다.", + "scan_qr_on_device": "다른 기기에서 이 QR 코드를 스캔하세요.", + "how_to_use": "사용하는 방법" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index e409d1ad9..fa8867636 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -623,9 +623,9 @@ "totp_verification_success": "အတည်ပြုခြင်း အောင်မြင်ပါသည်။", "totp_2fa_failure": "ကုဒ်မမှန်ပါ။ ကျေးဇူးပြု၍ အခြားကုဒ်တစ်ခုကို စမ်းကြည့်ပါ သို့မဟုတ် လျှို့ဝှက်သော့အသစ်တစ်ခု ဖန်တီးပါ။ ဂဏန်း ၈ လုံးကုဒ်များနှင့် SHA512 ကို ပံ့ပိုးပေးသည့် တွဲဖက်အသုံးပြုနိုင်သော 2FA အက်ပ်ကို အသုံးပြုပါ။", "enter_totp_code": "ကျေးဇူးပြု၍ TOTP ကုဒ်ကို ထည့်ပါ။", - "add_secret_code": "ဤလျှို့ဝှက်ကုဒ်ကို အခြားစက်ပစ္စည်းသို့ ထည့်ပါ။", + "add_secret_code": "သို့မဟုတ် ဤလျှို့ဝှက်ကုဒ်ကို အထောက်အထားစိစစ်ခြင်းအက်ပ်တစ်ခုသို့ ထည့်ပါ။", "totp_secret_code": "TOTP လျှို့ဝှက်ကုဒ်", - "setup_2fa_text": "ကိတ်မုန့် 2FA သည် အအေးခန်းကဲ့သို့ မလုံခြုံပါ။ 2FA သည် သင်အိပ်နေစဉ်တွင် သင့်သူငယ်ချင်းသည် သင့်လက်ဗွေရာကို ပေးဆောင်ခြင်းကဲ့သို့သော အခြေခံတိုက်ခိုက်မှုအမျိုးအစားများကို ကာကွယ်ပေးပါသည်။\n\n Cake 2FA သည် ခေတ်မီဆန်းပြားသော တိုက်ခိုက်သူ၏ အန္တရာယ်ပြုသည့်စက်ပစ္စည်းကို မကာကွယ်ပါ။\n\n သင်၏ 2FA ကုဒ်များကို အသုံးပြုခွင့်ဆုံးရှုံးသွားပါက၊ ဤပိုက်ဆံအိတ်ကို သင်ဝင်ရောက်ခွင့်ဆုံးရှုံးလိမ့်မည်။ သင့်ပိုက်ဆံအိတ်ကို mnemonic မျိုးစေ့မှ ပြန်လည်ရယူရန် လိုအပ်မည်ဖြစ်သည်။ ထို့ကြောင့် သင်၏ MNEMONIC မျိုးစေ့များကို အရန်သိမ်းထားရပါမည်။ ထို့အပြင်၊ သင်၏ mnemonic မျိုးစေ့(များ) ကို အသုံးပြုခွင့်ရှိသူတစ်ဦးက Cake 2FA ကိုကျော်ဖြတ်ကာ သင့်ရန်ပုံငွေများကို ခိုးယူနိုင်ပါမည်။\n\n ကိတ်မုန့်သည် သင့် mnemonic မျိုးစေ့သို့ ဝင်ရောက်ခွင့်ဆုံးရှုံးသွားပါက သင့်အား ကူညီပေးနိုင်မည်မဟုတ်ပါ၊ အထိန်းအချုပ်မရှိသော ပိုက်ဆံအိတ်။", + "setup_2fa_text": "ကိတ်မုန့် 2FA သည် TOTP မှတစ်ဆင့် ဒုတိယအထောက်အထားစိစစ်ခြင်းအချက်အဖြစ် လုပ်ဆောင်သည်။\n\nကိတ်မုန့် 2FA ၏ TOTP သည် SHA-512 နှင့် 8 ဂဏန်းပံ့ပိုးမှု လိုအပ်သည်။ ဒါက လုံခြုံရေးကို တိုးမြှင့်ပေးတယ်။ နောက်ထပ်အချက်အလက်များနှင့် ပံ့ပိုးပေးထားသောအက်ပ်များကို ဤနေရာတွင် လမ်းညွှန်တွင် တွေ့နိုင်ပါသည်။", "setup_totp_recommended": "TOTP ကို ​​စနစ်ထည့်သွင်းပါ (အကြံပြုထားသည်)", "disable_buy": "ဝယ်ယူမှု လုပ်ဆောင်ချက်ကို ပိတ်ပါ။", "disable_sell": "ရောင်းချခြင်းလုပ်ဆောင်ချက်ကို ပိတ်ပါ။", @@ -739,5 +739,8 @@ "unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။", "unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။", "unspent_change": "ပေြာင်းလဲခြင်း", - "tor_connection": "Tor ချိတ်ဆက်မှု" + "tor_connection": "Tor ချိတ်ဆက်မှု", + "setup_warning_2fa_text": "ကိတ်မုန့် 2FA သည် ပိုက်ဆံအိတ်ရှိ အချို့သော လုပ်ဆောင်ချက်များ အတွက် ဒုတိယ စစ်မှန်ကြောင်း အထောက်အထား ဖြစ်သည်။ ၎င်းသည် အအေးခန်းကဲ့သို့ မလုံခြုံပါ။\n သင်၏ 2FA အက်ပ် သို့မဟုတ် သော့တံများကို အသုံးပြုခွင့် ဆုံးရှုံးပါက၊ သင်သည် ဤပိုက်ဆံအိတ်ကို အသုံးပြုခွင့် ဆုံးရှုံးမည်ဖြစ်သည်။\n သင့်ပိုက်ဆံအိတ်ကို mnemonic မျိုးစေ့မှ ပြန်လည်ရယူရန် လိုအပ်မည်ဖြစ်သည်။\n သင်သည် သင်၏ 2FA သို့မဟုတ် mnemonic အစေ့များကို အသုံးပြုခွင့်ဆုံးရှုံးသွားပါက ကိတ်မုန့်ပံ့ပိုးကူညီမှု မပေးနိုင်ပါ။ Cake 2FA ကို အသုံးမပြုမီ၊ လမ်းညွှန်ချက်မှတစ်ဆင့် ဖတ်ရန် အကြံပြုအပ်ပါသည်။", + "scan_qr_on_device": "အခြားစက်တွင် ဤ QR ကုဒ်ကို စကင်ဖတ်ပါ။", + "how_to_use": "အသုံးပြုနည်း" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index a1afb796b..22d8a7289 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -625,9 +625,9 @@ "totp_verification_success": "Verificatie geslaagd!", "totp_2fa_failure": "Foute code. Probeer een andere code of genereer een nieuwe geheime sleutel. Gebruik een compatibele 2FA-app die 8-cijferige codes en SHA512 ondersteunt.", "enter_totp_code": "Voer de TOTP-code in.", - "add_secret_code": "Voeg deze geheime code toe aan een ander apparaat", + "add_secret_code": "Of voeg deze geheime code toe aan een authenticator-app", "totp_secret_code": "TOTP-geheime code", - "setup_2fa_text": "Cake 2FA is NIET zo veilig als koude opslag. 2FA beschermt tegen basistypen aanvallen, zoals uw vriend die uw vingerafdruk geeft terwijl u slaapt.\n\n Cake 2FA biedt GEEN bescherming tegen een gecompromitteerd apparaat door een geavanceerde aanvaller.\n\n Als u de toegang tot uw 2FA-codes kwijtraakt , VERLIEST U DE TOEGANG TOT DEZE PORTEFEUILLE. U moet uw portemonnee herstellen van mnemonic seed. JE MOET DAAROM EEN BACK-UP MAKEN VAN JE MNEMONISCHE ZADEN! Verder kan iemand met toegang tot je geheugensteuntje(s) je geld stelen, waarbij Cake 2FA wordt omzeild.\n\n Het ondersteunend personeel van Cake kan je niet helpen als je de toegang tot je geheugensteuntje kwijtraakt, aangezien Cake een niet-bewaarbare portemonnee.", + "setup_2fa_text": "Cake 2FA werkt via TOTP als tweede authenticatiefactor.\n\nCake 2FA's TOTP vereist SHA-512 en 8-cijferige ondersteuning; dit zorgt voor meer veiligheid. Meer informatie en ondersteunde apps vindt u in de gids hier.", "setup_totp_recommended": "TOTP instellen (aanbevolen)", "disable_buy": "Koopactie uitschakelen", "disable_sell": "Verkoopactie uitschakelen", @@ -741,5 +741,8 @@ "unavailable_balance": "Onbeschikbaar saldo", "unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.", "unspent_change": "Wijziging", - "tor_connection": "Tor-verbinding" + "tor_connection": "Tor-verbinding", + "setup_warning_2fa_text": "Cake 2FA is een tweede authenticatie voor bepaalde acties in de portemonnee. Het is NIET zo veilig als koude opslag.\n Als u de toegang tot uw 2FA-app of toegangscodes verliest, verliest u de toegang tot deze portemonnee.\n U moet uw portemonnee herstellen vanuit het geheugensteuntje.\n Cake Support kan u niet helpen als u de toegang tot uw 2FA- of mnemonic-zaden verliest. Voordat u Cake 2FA gebruikt, raden wij u aan de handleiding door te lezen.", + "scan_qr_on_device": "Scan deze QR-code op een ander apparaat", + "how_to_use": "Hoe te gebruiken" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 4cb30bb1c..33a540477 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -625,9 +625,9 @@ "totp_verification_success": "Weryfikacja powiodła się!", "totp_2fa_failure": "Błędny kod. Spróbuj użyć innego kodu lub wygeneruj nowy tajny klucz. Użyj kompatybilnej aplikacji 2FA, która obsługuje 8-cyfrowe kody i SHA512.", "enter_totp_code": "Wprowadź kod TOTP.", - "add_secret_code": "Dodaj ten tajny kod do innego urządzenia", + "add_secret_code": "Możesz też dodać ten tajny kod do aplikacji uwierzytelniającej", "totp_secret_code": "Tajny kod TOTP", - "setup_2fa_text": "Cake 2FA NIE jest tak bezpieczny jak przechowywanie w chłodni. 2FA chroni przed podstawowymi typami ataków, takimi jak udostępnienie odcisku palca przez znajomego podczas snu.\n\n Cake 2FA NIE chroni przed zhakowanym urządzeniem przez wyrafinowanego atakującego.\n\n Jeśli utracisz dostęp do swoich kodów 2FA , UTRACISZ DOSTĘP DO TEGO PORTFELA. Będziesz musiał przywrócić swój portfel z mnemonicznego materiału siewnego. DLATEGO MUSISZ ZROBIĆ KOPIĘ SWOICH NASION MNEMONICZNYCH! Co więcej, ktoś z dostępem do twoich mnemonicznych nasion będzie mógł ukraść twoje fundusze, omijając Cake 2FA.\n\n Personel pomocniczy Cake nie będzie mógł ci pomóc, jeśli stracisz dostęp do swojego mnemonicznego seeda, ponieważ Cake jest portfel niezabezpieczony.", + "setup_2fa_text": "Cake 2FA działa poprzez TOTP jako drugi czynnik uwierzytelniający.\n\nTOTP Cake 2FA wymaga obsługi SHA-512 i 8 cyfr; zapewnia to większe bezpieczeństwo. Więcej informacji i obsługiwane aplikacje można znaleźć w przewodniku tutaj.", "setup_totp_recommended": "Skonfiguruj TOTP (zalecane)", "disable_buy": "Wyłącz akcję kupna", "disable_sell": "Wyłącz akcję sprzedaży", @@ -741,5 +741,8 @@ "unavailable_balance": "Niedostępne saldo", "unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.", "unspent_change": "Zmiana", - "tor_connection": "Połączenie Torem" + "tor_connection": "Połączenie Torem", + "setup_warning_2fa_text": "Cake 2FA to drugie uwierzytelnienie niektórych działań w portfelu. NIE jest tak bezpieczne jak przechowywanie w chłodni.\n Jeśli utracisz dostęp do aplikacji 2FA lub kluczy, UTRAcisz dostęp do tego portfela.\n Będziesz musiał przywrócić swój portfel z nasion mnemonicznych.\n Wsparcie Cake nie będzie w stanie Ci pomóc, jeśli utracisz dostęp do swoich nasion 2FA lub mnemoników. Przed użyciem Cake 2FA zalecamy zapoznanie się z instrukcją.", + "scan_qr_on_device": "Zeskanuj ten kod QR na innym urządzeniu", + "how_to_use": "Jak używać" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 98cc0caec..9f761c799 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -624,9 +624,9 @@ "totp_verification_success": "Verificação bem-sucedida!", "totp_2fa_failure": "Código incorreto. Tente um código diferente ou gere uma nova chave secreta. Use um aplicativo 2FA compatível com códigos de 8 dígitos e SHA512.", "enter_totp_code": "Digite o código TOTP.", - "add_secret_code": "Adicione este código secreto a outro dispositivo", + "add_secret_code": "Ou adicione este código secreto a um aplicativo autenticador", "totp_secret_code": "Código Secreto TOTP", - "setup_2fa_text": "O Cake 2FA NÃO é tão seguro quanto o armazenamento a frio. O 2FA protege contra tipos básicos de ataques, como seu amigo fornecer sua impressão digital enquanto você está dormindo.\n\n O Cake 2FA NÃO protege contra um dispositivo comprometido por um invasor sofisticado.\n\n Se você perder o acesso aos seus códigos 2FA , VOCÊ PERDERÁ O ACESSO A ESTA CARTEIRA. Você precisará restaurar sua carteira da semente mnemônica. VOCÊ DEVE, PORTANTO, FAZER BACKUP DE SUAS SEMENTES MNEMÔNICAS! Além disso, alguém com acesso às suas sementes mnemônicas poderá roubar seus fundos, ignorando o Cake 2FA.\n\n A equipe de suporte do Cake não poderá ajudá-lo se você perder o acesso à sua semente mnemônica, pois o Cake é um carteira não custodial.", + "setup_2fa_text": "Cake 2FA funciona através do TOTP como segundo fator de autenticação.\n\nO TOTP do Cake 2FA requer suporte SHA-512 e 8 dígitos; isso proporciona maior segurança. Mais informações e aplicativos suportados podem ser encontrados no guia aqui.", "setup_totp_recommended": "Configurar TOTP (recomendado)", "disable_buy": "Desativar ação de compra", "disable_sell": "Desativar ação de venda", @@ -740,5 +740,8 @@ "unavailable_balance": "Saldo indisponível", "unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.", "unspent_change": "Mudar", - "tor_connection": "Conexão Tor" + "tor_connection": "Conexão Tor", + "setup_warning_2fa_text": "Cake 2FA é uma segunda autenticação para determinadas ações na carteira. NÃO é tão seguro quanto o armazenamento refrigerado.\n Se você perder o acesso ao seu aplicativo 2FA ou às chaves de acesso, você perderá o acesso a esta carteira.\n Você precisará restaurar sua carteira a partir da semente mnemônica.\n O suporte do Cake não poderá ajudá-lo se você perder o acesso ao seu 2FA ou sementes mnemônicas. Antes de usar o Cake 2FA, recomendamos a leitura do guia.", + "scan_qr_on_device": "Digitalize este código QR em outro dispositivo", + "how_to_use": "Como usar" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 83227b70f..795e5f83c 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -625,9 +625,9 @@ "totp_verification_success": "Проверка прошла успешно!", "totp_2fa_failure": "Неверный код. Пожалуйста, попробуйте другой код или создайте новый секретный ключ. Используйте совместимое приложение 2FA, которое поддерживает 8-значные коды и SHA512.", "enter_totp_code": "Пожалуйста, введите TOTP-код.", - "add_secret_code": "Добавьте этот секретный код на другое устройство", + "add_secret_code": "Или добавьте этот секретный код в приложение для аутентификации.", "totp_secret_code": "Секретный код ТОТП", - "setup_2fa_text": "Cake 2FA НЕ так безопасен, как холодное хранилище. Двухфакторная аутентификация защищает от основных типов атак, таких как отпечаток вашего друга, когда вы спите.\n\n Двухфакторная аутентификация Cake НЕ защищает от взлома устройства опытным злоумышленником.\n\n Если вы потеряете доступ к своим кодам двухфакторной аутентификации. , ВЫ ПОТЕРЯЕТЕ ДОСТУП К ЭТОМУ КОШЕЛЬКУ. Вам нужно будет восстановить свой кошелек из мнемонической семени. ПОЭТОМУ ВЫ ДОЛЖНЫ СОЗДАТЬ РЕЗЕРВНУЮ ВЕРСИЮ СВОИХ МНЕМОНИКОВ! Кроме того, кто-то, имеющий доступ к вашему мнемоническому семени, сможет украсть ваши средства, минуя Cake 2FA.\n\n Персонал службы поддержки Cake не сможет помочь вам, если вы потеряете доступ к своему мнемоническому семени, поскольку Cake — это некастодиальный кошелек.", + "setup_2fa_text": "Cake 2FA работает через TOTP в качестве второго фактора аутентификации.\n\nTOTP Cake 2FA требует SHA-512 и поддержки 8 цифр; это обеспечивает повышенную безопасность. Дополнительную информацию и поддерживаемые приложения можно найти в руководстве здесь.", "setup_totp_recommended": "Настроить TOTP (рекомендуется)", "disable_buy": "Отключить действие покупки", "disable_sell": "Отключить действие продажи", @@ -741,5 +741,8 @@ "unavailable_balance": "Недоступный баланс", "unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.", "unspent_change": "Изменять", - "tor_connection": "Тор соединение" + "tor_connection": "Тор соединение", + "setup_warning_2fa_text": "Cake 2FA — это вторая аутентификация для определенных действий в кошельке. Это НЕ так безопасно, как холодное хранение.\n Если вы потеряете доступ к своему приложению 2FA или паролям, вы потеряете доступ к этому кошельку.\n Вам нужно будет восстановить свой кошелек из мнемонического сида.\n Служба поддержки Cake не сможет вам помочь, если вы потеряете доступ к своим 2FA или мнемоническим идентификаторам. Прежде чем использовать Cake 2FA, мы рекомендуем прочитать руководство.", + "scan_qr_on_device": "Отсканируйте этот QR-код на другом устройстве", + "how_to_use": "Как использовать" } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index f47b11d24..d564f7ac1 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -623,9 +623,9 @@ "totp_verification_success": "การยืนยันสำเร็จ!", "totp_2fa_failure": "รหัสไม่ถูกต้อง. โปรดลองใช้รหัสอื่นหรือสร้างรหัสลับใหม่ ใช้แอพ 2FA ที่เข้ากันได้ซึ่งรองรับรหัส 8 หลักและ SHA512", "enter_totp_code": "กรุณาใส่รหัสทีโอที", - "add_secret_code": "เพิ่มรหัสลับนี้ไปยังอุปกรณ์อื่น", + "add_secret_code": "หรือเพิ่มรหัสลับนี้ลงในแอปตรวจสอบความถูกต้อง", "totp_secret_code": "รหัสลับ TOTP", - "setup_2fa_text": "Cake 2FA ไม่ปลอดภัยเท่าห้องเย็น 2FA ป้องกันการโจมตีประเภทพื้นฐาน เช่น เพื่อนของคุณให้ลายนิ้วมือขณะที่คุณนอนหลับ\n\n Cake 2FA ไม่ป้องกันอุปกรณ์ที่ถูกบุกรุกโดยผู้โจมตีที่เชี่ยวชาญ\n\n หากคุณสูญเสียการเข้าถึงรหัส 2FA ของคุณ คุณจะสูญเสียการเข้าถึงกระเป๋าเงินนี้ คุณจะต้องกู้คืนกระเป๋าเงินของคุณจากเมล็ดช่วยจำ คุณต้องสำรองเมล็ดความจำของคุณ! นอกจากนี้ ผู้ที่สามารถเข้าถึงเมล็ดช่วยจำของคุณจะสามารถขโมยเงินของคุณ โดยผ่าน Cake 2FA\n\n เจ้าหน้าที่ช่วยเหลือของ Cake จะไม่สามารถช่วยเหลือคุณได้ หากคุณสูญเสียการเข้าถึงเมล็ดช่วยจำ เนื่องจาก Cake เป็น กระเป๋าสตางค์ที่ไม่เป็นผู้ดูแล", + "setup_2fa_text": "Cake 2FA ทำงานผ่าน TOTP เป็นปัจจัยการตรวจสอบสิทธิ์ที่สอง\n\nTOTP ของ Cake 2FA ต้องการการสนับสนุน SHA-512 และ 8 หลัก สิ่งนี้ให้ความปลอดภัยเพิ่มขึ้น สามารถดูข้อมูลเพิ่มเติมและแอปที่รองรับได้ในคำแนะนำที่นี่", "setup_totp_recommended": "ตั้งค่า TOTP (แนะนำ)", "disable_buy": "ปิดการใช้งานการซื้อ", "disable_sell": "ปิดการใช้งานการขาย", @@ -739,5 +739,8 @@ "unavailable_balance": "ยอดคงเหลือไม่พร้อมใช้งาน", "unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง", "unspent_change": "เปลี่ยน", - "tor_connection": "การเชื่อมต่อทอร์" + "tor_connection": "การเชื่อมต่อทอร์", + "setup_warning_2fa_text": "Cake 2FA เป็นการรับรองความถูกต้องครั้งที่สองสำหรับการกระทำบางอย่างในกระเป๋าเงิน มันไม่ปลอดภัยเท่ากับห้องเย็น\n หากคุณสูญเสียการเข้าถึงแอป 2FA หรือรหัสผ่าน คุณจะสูญเสียการเข้าถึงกระเป๋าเงินนี้\n คุณจะต้องกู้คืนกระเป๋าเงินของคุณจากเมล็ดช่วยในการจำ\n การสนับสนุนเค้กจะไม่สามารถช่วยเหลือคุณได้หากคุณสูญเสียการเข้าถึง 2FA หรือเมล็ดช่วยในการจำ ก่อนใช้ Cake 2FA เราขอแนะนำให้อ่านคำแนะนำโดยละเอียด", + "scan_qr_on_device": "สแกนโค้ด QR นี้บนอุปกรณ์อื่น", + "how_to_use": "วิธีใช้" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index d68124fb1..bf15c0c09 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -626,9 +626,9 @@ "totp_verification_success": "Matagumpay ang pagpapatunay!", "totp_2fa_failure": "Maling code. Mangyaring subukan ang ibang code o makabuo ng isang bagong lihim na susi. Gumamit ng isang katugmang 2FA app na sumusuporta sa 8-digit na mga code at SHA512.", "enter_totp_code": "Mangyaring ipasok ang TOTP code.", - "add_secret_code": "Idagdag ang lihim na code na ito sa isa pang aparato", + "add_secret_code": "O, idagdag ang sikretong code na ito sa isang authenticator app", "totp_secret_code": "TOTP Secret Code", - "setup_2fa_text": "Ang cake 2FA ay hindi ligtas tulad ng malamig na imbakan. Pinoprotektahan ng 2FA laban sa mga pangunahing uri ng pag -atake, tulad ng iyong kaibigan na nagbibigay ng iyong fingerprint habang natutulog ka.\n\n Hindi pinoprotektahan ng cake 2FA laban sa isang nakompromiso na aparato ng isang sopistikadong umaatake.\n\n Kung nawalan ka ng pag -access sa iyong 2FA code, mawawalan ka ng access sa pitaka na ito. Kakailanganin mong ibalik ang iyong pitaka mula sa binhi ng mnemonic. Dapat mong i -back up ang iyong mga buto ng mnemonic! Dagdag pa, ang isang tao na may access sa iyong (mga) binhi ng mnemonic ay maaaring magnakaw ng iyong mga pondo, na lumampas sa cake 2FA.\n\n Ang mga kawani ng suporta sa cake ay hindi makakatulong sa iyo kung nawalan ka ng pag -access sa iyong mnemonic seed, dahil ang cake ay isang noncustodial wallet.", + "setup_2fa_text": "Gumagana ang Cake 2FA sa pamamagitan ng TOTP bilang pangalawang kadahilanan sa pagpapatunay.\n\nAng TOTP ng Cake 2FA ay nangangailangan ng SHA-512 at 8 digit na suporta; nagbibigay ito ng mas mataas na seguridad. Higit pang impormasyon at suportadong app ay matatagpuan sa gabay dito.", "setup_totp_recommended": "I -set up ang TOTP (inirerekomenda)", "disable_buy": "Huwag paganahin ang pagkilos ng pagbili", "disable_sell": "Huwag paganahin ang pagkilos ng pagbebenta", @@ -736,5 +736,8 @@ "unavailable_balance": "Hindi available na balanse", "unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.", "unspent_change": "Baguhin", - "tor_connection": "Koneksyon ng Tor" + "tor_connection": "Koneksyon ng Tor", + "setup_warning_2fa_text": "Ang Cake 2FA ay pangalawang pagpapatotoo para sa ilang partikular na pagkilos sa wallet. HINDI ito kasing-secure ng malamig na imbakan.\n Kung nawalan ka ng access sa iyong 2FA app o mga passkey, MAWAWALA ka ng access sa wallet na ito.\n Kakailanganin mong ibalik ang iyong wallet mula sa mnemonic seed.\n Hindi ka matutulungan ng suporta sa cake kung mawawalan ka ng access sa iyong 2FA o mnemonic seeds. Bago gamitin ang Cake 2FA, inirerekomenda naming basahin ang gabay.", + "scan_qr_on_device": "I-scan ang QR code na ito sa ibang device", + "how_to_use": "Paano gamitin" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 3207c2c01..8d400900d 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -623,9 +623,9 @@ "totp_verification_success": "Doğrulama Başarılı!", "totp_2fa_failure": "Yanlış kod. Lütfen farklı bir kod deneyin veya yeni bir gizli anahtar oluşturun. 8 basamaklı kodları ve SHA512'yi destekleyen uyumlu bir 2FA uygulaması kullanın.", "enter_totp_code": "Lütfen TOTP Kodunu giriniz.", - "add_secret_code": "Bu gizli kodu başka bir cihaza ekleyin", + "add_secret_code": "Veya bu gizli kodu bir kimlik doğrulama uygulamasına ekleyin", "totp_secret_code": "TOTP Gizli Kodu", - "setup_2fa_text": "Cake 2FA, soğuk hava deposu kadar güvenli DEĞİLDİR. 2FA, siz uyurken arkadaşınızın parmak izinizi sağlaması gibi temel saldırı türlerine karşı koruma sağlar.\n\n Cake 2FA, gelişmiş bir saldırgan tarafından güvenliği ihlal edilmiş bir cihaza karşı koruma SAĞLAMAZ.\n\n 2FA kodlarınıza erişimi kaybederseniz , BU CÜZDANA ERİŞİMİNİZİ KAYBEDECEKSİNİZ. Mnemonic seed'den cüzdanınızı geri yüklemeniz gerekecek. BU NEDENLE HATIRLAYICI TOHUMLARINIZI YEDEKLEMELİSİNİZ! Ayrıca anımsatıcı tohumlarınıza erişimi olan biri, Cake 2FA'yı atlayarak paranızı çalabilir.\n\n Cake, anımsatıcı tohumlarınıza erişimi kaybederseniz size yardımcı olamaz, çünkü Cake bir saklama dışı cüzdan.", + "setup_2fa_text": "Cake 2FA, ikinci kimlik doğrulama faktörü olarak TOTP üzerinden çalışır.\n\nCake 2FA'nın TOTP'si SHA-512 ve 8 haneli destek gerektirir; bu daha fazla güvenlik sağlar. Daha fazla bilgiyi ve desteklenen uygulamaları buradaki kılavuzda bulabilirsiniz.", "setup_totp_recommended": "TOTP'yi kurun (Önerilir)", "disable_buy": "Satın alma işlemini devre dışı bırak", "disable_sell": "Satış işlemini devre dışı bırak", @@ -739,5 +739,8 @@ "unavailable_balance": "Kullanılamayan bakiye", "unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.", "unspent_change": "Değiştirmek", - "tor_connection": "Tor bağlantısı" + "tor_connection": "Tor bağlantısı", + "setup_warning_2fa_text": "Cake 2FA, cüzdandaki belirli eylemler için ikinci bir kimlik doğrulamadır. Soğuk hava deposu kadar güvenli DEĞİLDİR.\n 2FA uygulamanıza veya şifre anahtarlarınıza erişiminizi kaybederseniz bu cüzdana erişimi KAYBEDECEKSİNİZ.\n Cüzdanınızı anımsatıcı tohumdan geri yüklemeniz gerekecek.\n 2FA veya anımsatıcı tohumlarınıza erişiminizi kaybederseniz pasta desteği size yardımcı olamayacaktır. Cake 2FA'yı kullanmadan önce kılavuzu okumanızı öneririz.", + "scan_qr_on_device": "Bu QR kodunu başka bir cihazda tarayın", + "how_to_use": "Nasıl kullanılır" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index c53aa59ae..2789f9347 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -625,9 +625,9 @@ "totp_verification_success": "Перевірка успішна!", "totp_2fa_failure": "Невірний код. Спробуйте інший код або створіть новий секретний ключ. Використовуйте сумісний додаток 2FA, який підтримує 8-значні коди та SHA512.", "enter_totp_code": "Будь ласка, введіть код TOTP.", - "add_secret_code": "Додайте цей секретний код на інший пристрій", + "add_secret_code": "Або додайте цей секретний код до програми автентифікації", "totp_secret_code": "Секретний код TOTP", - "setup_2fa_text": "Торт 2FA НЕ такий безпечний, як холодне зберігання. 2FA захищає від основних типів атак, наприклад ваш друг надає ваш відбиток пальця, поки ви спите.\n\n Cake 2FA НЕ захищає від скомпрометованого пристрою досвідченим зловмисником.\n\n Якщо ви втратите доступ до своїх кодів 2FA , ВИ ВТРАТИТЕ ДОСТУП ДО ЦЬОГО ГАМАНЦЯ. Вам потрібно буде відновити свій гаманець з мнемонічного коду. ТОМУ ВИ ПОВИННІ СТВОРИТИ РЕЗЕРВНУ КОПІЮ СВОЇХ МНЕМОНІЧНИХ НАСІН! Крім того, хтось із доступом до ваших мнемонічних початкових значень зможе викрасти ваші кошти, оминаючи Cake 2FA.\n\n Співробітники служби підтримки Cake не зможуть вам допомогти, якщо ви втратите доступ до своїх мнемонічних вихідних даних, оскільки Cake є гаманець без опіки.", + "setup_2fa_text": "Cake 2FA працює через TOTP як другий фактор автентифікації.\n\nДля TOTP Cake 2FA потрібен SHA-512 і підтримка 8 цифр; це забезпечує підвищену безпеку. Додаткову інформацію та підтримувані програми можна знайти в посібнику тут.", "setup_totp_recommended": "Налаштувати TOTP (рекомендовано)", "disable_buy": "Вимкнути дію покупки", "disable_sell": "Вимкнути дію продажу", @@ -741,5 +741,8 @@ "unavailable_balance": "Недоступний баланс", "unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.", "unspent_change": "Зміна", - "tor_connection": "Підключення Tor" + "tor_connection": "Підключення Tor", + "setup_warning_2fa_text": "Cake 2FA — друга аутентифікація для певних дій у гаманці. Це НЕ так безпечно, як холодне зберігання.\n Якщо ви втратите доступ до своєї програми 2FA або ключів доступу, ви втратите доступ до цього гаманця.\n Вам потрібно буде відновити свій гаманець з мнемоніки.\n Служба підтримки Cake не зможе вам допомогти, якщо ви втратите доступ до 2FA або мнемонічних насадок. Перед використанням Cake 2FA рекомендуємо прочитати інструкцію.", + "scan_qr_on_device": "Відскануйте цей QR-код на іншому пристрої", + "how_to_use": "Як використовувати" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index d974c4ee1..4e920aad3 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -617,9 +617,9 @@ "totp_verification_success": "توثیق کامیاب!", "totp_2fa_failure": "غلط کوڈ. براہ کرم ایک مختلف کوڈ آزمائیں یا ایک نئی خفیہ کلید بنائیں۔ ایک ہم آہنگ 2FA ایپ استعمال کریں جو 8 ہندسوں کے کوڈز اور SHA512 کو سپورٹ کرتی ہو۔", "enter_totp_code": "براہ کرم TOTP کوڈ درج کریں۔", - "add_secret_code": "اس خفیہ کوڈ کو کسی اور ڈیوائس میں شامل کریں۔", + "add_secret_code": " ۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮟﯿﻣ ﭗﯾﺍ ﮦﺪﻨﻨﮐ ﻖﯾﺪﺼﺗ ﻮﮐ ﮈﻮﮐ ﮧﯿﻔﺧ ﺱﺍ ،ﺎﯾ", "totp_secret_code": "TOTP خفیہ کوڈ", - "setup_2fa_text": "کیک 2FA کولڈ اسٹوریج کی طرح محفوظ نہیں ہے۔ 2FA بنیادی قسم کے حملوں سے حفاظت کرتا ہے، جیسے کہ آپ کا دوست آپ کے سوتے وقت آپ کے فنگر پرنٹ فراہم کرتا ہے۔\n\n کیک 2FA کسی جدید حملہ آور کے ذریعے سمجھوتہ کرنے والے آلہ سے حفاظت نہیں کرتا ہے۔\n\n اگر آپ اپنے 2FA کوڈز تک رسائی کھو دیتے ہیں ، آپ اس بٹوے تک رسائی سے محروم ہو جائیں گے۔ آپ کو یادداشت کے بیج سے اپنے بٹوے کو بحال کرنے کی ضرورت ہوگی۔ اس لیے آپ کو اپنے یادداشت کے بیجوں کا بیک اپ لینا چاہیے! اس کے علاوہ، آپ کے یادداشت کے بیج تک رسائی رکھنے والا کوئی شخص کیک 2FA کو نظرانداز کرتے ہوئے آپ کے فنڈز چرا سکے گا۔\n\n اگر آپ اپنے یادداشت کے بیج تک رسائی کھو دیتے ہیں تو کیک کا معاون عملہ آپ کی مدد نہیں کر سکے گا، کیونکہ کیک ایک ہے غیر نگہداشت پرس.", + "setup_2fa_text": " ۔ﮯﮨ ﺎﺗﺮﮐ ﻡﺎﮐ ﮯﻌﯾﺭﺫ ﮯﮐ TOTP ﺮﭘ ﺭﻮﻃ ﮯﮐ ﺮﺼﻨﻋ ﯽﻘﯾﺪﺼﺗ ﮮﺮﺳﻭﺩ 2FA ﮏﯿﮐ", "setup_totp_recommended": "TOTP ترتیب دیں (تجویز کردہ)", "disable_buy": "خرید ایکشن کو غیر فعال کریں۔", "disable_sell": "فروخت کی کارروائی کو غیر فعال کریں۔", @@ -733,5 +733,8 @@ "unavailable_balance": "ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ", "unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ", "unspent_change": "تبدیل کریں", - "tor_connection": "ﻦﺸﮑﻨﮐ ﺭﻮﭨ" + "tor_connection": "ﻦﺸﮑﻨﮐ ﺭﻮﭨ", + "setup_warning_2fa_text": "۔ﮯﮨ ﮟﯿﮩﻧ ﻅﻮﻔﺤﻣ ﺡﺮﻃ ﯽﮐ ﺞﯾﺭﻮﭩﺳﺍ ﮉﻟﻮﮐ ﮧﯾ ۔ﮯﮨ ﻖﯾﺪﺼﺗ ﯼﺮﺳﻭﺩ ﮏﯾﺍ ﮯﯿﻟ ﮯﮐ ﮞﻮﯿﺋﺍﻭﺭﺭﺎﮐ ﺹﻮ", + "scan_qr_on_device": " ۔ﮟﯾﺮﮐ ﻦﯿﮑﺳﺍ ﺮﭘ ﺲﺋﺍﻮﯾﮈ ﺭﻭﺍ ﯽﺴﮐ ﻮﮐ ﮈﻮﮐ QR ﺱﺍ", + "how_to_use": " ﮧﻘﯾﺮﻃ ﺎﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 220db628b..7009282f9 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -619,9 +619,9 @@ "totp_verification_success": "Ìbẹrẹ dọkita!", "totp_2fa_failure": "Koodu ti o daju ko ri. Jọwọ jẹ koodu miiran tabi ṣiṣẹ iwe kiakia. Lo fun 2FA eto ti o ba ṣe ni jẹ 2FA ti o gba idaniloju 8-digits ati SHA512.", "enter_totp_code": "Jọwọ pọ koodu TOTP.", - "add_secret_code": "Fọya koodu iye yii si eto miiran", + "add_secret_code": "Tabi, ṣafikun koodu aṣiri yii si ohun elo onijeri kan", "totp_secret_code": "Koodu iye TOTP", - "setup_2fa_text": "Cake 2FA kii ṣe nipasẹ aisan tabi ni akoso aisan. 2FA ti ṣe pada ninu awọn iṣẹ pataki, bi atilẹyin ti o fun iṣẹ rẹ ti o ti jẹ saanu.\n\n Cake 2FA kii ṣe pada ninu atilẹyin ti o ti ba alabara kan ti o sise gidi gan.\n\n Ti o ba pọ akosile rẹ 2FA, O YOO RI ATOJU SI IWE IWE NA. O yoo nilo lati yan pẹlu iwe iwe ni o ba ṣe iṣẹ rẹ. O ni aṣẹ iru ki o gba asise akojọ iwe iwe rẹ! Nitori a ko ni aṣẹ pẹlu ohun ti o ba ṣe iṣẹ rẹ lati yan pẹlu akojọ iwe iwe rẹ, nitori Cake ni iwe iwe ti ko se iṣẹ itumọ.", + "setup_2fa_text": "Akara oyinbo 2FA ṣiṣẹ nipasẹ TOTP bi ifosiwewe ijẹrisi keji.\n\nAkara oyinbo 2FA's TOTP nilo SHA-512 ati atilẹyin oni-nọmba 8; eyi pese aabo ti o pọ sii. Alaye diẹ sii ati awọn ohun elo atilẹyin ni a le rii ninu itọsọna naa Nibi.", "setup_totp_recommended": "Sọ TOTP (Kẹṣọdọ)", "disable_buy": "Ko iṣọrọ ọja", "disable_sell": "Ko iṣọrọ iṣọrọ", @@ -735,5 +735,8 @@ "unavailable_balance": "Iwontunwonsi ti ko si", "unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.", "unspent_change": "Yipada", - "tor_connection": "Tor asopọ" + "tor_connection": "Tor asopọ", + "setup_warning_2fa_text": "Akara oyinbo 2FA jẹ ijẹrisi keji fun awọn iṣe kan ninu apamọwọ. Ko ṣe aabo bi ibi ipamọ tutu.\n Ti o ba padanu iraye si ohun elo 2FA tabi awọn bọtini iwọle, iwọ YOO padanu iraye si apamọwọ yii.\n Iwọ yoo nilo lati mu pada apamọwọ rẹ lati inu irugbin mnemonic.\n Atilẹyin akara oyinbo kii yoo ni anfani lati ṣe iranlọwọ fun ọ ti o ba padanu iraye si 2FA tabi awọn irugbin mnemonic rẹ. Ṣaaju lilo akara oyinbo 2FA, a ṣeduro kika nipasẹ itọsọna naa.", + "scan_qr_on_device": "Ṣe ayẹwo koodu QR yii lori ẹrọ miiran", + "how_to_use": "Bawo ni lati lo" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index c3678bf41..175e15093 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -624,9 +624,9 @@ "totp_verification_success": "验证成功!", "totp_2fa_failure": "不正确的代码。 请尝试不同的代码或生成新的密钥。 使用支持 8 位代码和 SHA512 的兼容 2FA 应用程序。", "enter_totp_code": "请输入 TOTP 代码。", - "add_secret_code": "将此密码添加到另一台设备", + "add_secret_code": "或者,将此密码添加到身份验证器应用程序中", "totp_secret_code": "TOTP密码", - "setup_2fa_text": "Cake 2FA 不如冷藏安全。 2FA 可防止基本类型的攻击,例如您的朋友在您睡觉时提供您的指纹。\n\n Cake 2FA 无法防止老练的攻击者破坏设备。\n\n 如果您无法访问您的 2FA 代码, 您将无法访问此钱包。您将需要从助记词种子恢复您的钱包。因此,您必须备份您的助记词种子!此外,有权访问您的助记种子的人将能够绕过 Cake 2FA 窃取您的资金。\n\n 如果您无法访问您的助记种子,Cake 支持人员将无法帮助您,因为 Cake 是一个非托管钱包。", + "setup_2fa_text": "Cake 2FA 通过 TOTP 作为第二个身份验证因素。\n\nCake 2FA 的 TOTP 需要 SHA-512 和 8 位数字支持;这提供了更高的安全性。更多信息和支持的应用程序可以在此处的指南中找到。", "setup_totp_recommended": "设置 TOTP(推荐)", "disable_buy": "禁用购买操作", "disable_sell": "禁用卖出操作", @@ -740,5 +740,8 @@ "unavailable_balance": "不可用余额", "unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。", "unspent_change": "改变", - "tor_connection": "Tor连接" + "tor_connection": "Tor连接", + "setup_warning_2fa_text": "Cake 2FA 是对钱包中某些操作的二次验证。它不如冷藏那么安全。\n 如果您无法访问 2FA 应用程序或密钥,您将无法访问此钱包。\n 您需要从助记词种子中恢复您的钱包。\n 如果您无法访问 2FA 或助记词种子,Cake 支持将无法为您提供帮助。在使用 Cake 2FA 之前,我们建议您阅读该指南。", + "scan_qr_on_device": "在另一台设备上扫描此二维码", + "how_to_use": "如何使用" } From 747a760124cd4129561659f202744960b15a0d7a Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 13 Dec 2023 14:08:18 +0200 Subject: [PATCH 068/241] willPopScope fix --- lib/src/screens/seed/warning_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/screens/seed/warning_page.dart b/lib/src/screens/seed/warning_page.dart index 7bd87113b..79560b3d4 100644 --- a/lib/src/screens/seed/warning_page.dart +++ b/lib/src/screens/seed/warning_page.dart @@ -31,7 +31,7 @@ class WarningPage extends BasePage { final image = currentTheme.type == ThemeType.dark ? imageDark : imageLight; return WillPopScope( - onWillPop: () async => false, + onWillPop: () async => !isPreSeedPage, child: Container( alignment: Alignment.center, padding: EdgeInsets.all(24), From ef7762eaca5ff53597777242597272374b7d6e5b Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Wed, 13 Dec 2023 15:03:07 +0100 Subject: [PATCH 069/241] Polygon-Wallet-fixes (#1222) * fix: Fix issues surrounding polygon release * Add polygon generation command to pubspec script * Remove unnecesary cast * fix: Remove unneeded code * fix: Adjust workflow file to pick polygonScan apikey * fix: Issues noticed while testing * fix: Issues noticed while testing * fix: Transaction should reflect the token name * fix: Remove unused import * feat: Add alchemy node to default migration settings * Fix sending Polygon delay Remove alchemy node Minor Enhancements * Remove scrolling from multiple choices settings row and make them fill the whole space [skip ci] * Add USDT poly Add icon for USDC.e * Fix ERC20 tokens overriding old wallets Add USDC.e to exchange * - Remove unnecessary code - Minor Enhancements --------- Co-authored-by: Omar Hatem --- .github/workflows/pr_test_build.yml | 3 +- assets/polygon_node_list.yml | 4 +- cw_bitcoin/pubspec.lock | 17 +- cw_core/lib/crypto_currency.dart | 4 + cw_core/lib/erc20_token.dart | 26 +-- cw_core/lib/node.dart | 2 +- cw_core/pubspec.lock | 9 - ...art => default_ethereum_erc20_tokens.dart} | 20 +-- cw_ethereum/lib/ethereum_client.dart | 36 ++-- cw_ethereum/lib/ethereum_wallet.dart | 7 +- cw_monero/example/pubspec.lock | 36 ++-- ...dart => default_polygon_erc20_tokens.dart} | 10 +- cw_polygon/lib/polygon_client.dart | 23 ++- cw_polygon/lib/polygon_wallet.dart | 161 ++++++++---------- lib/core/address_validator.dart | 4 + .../wallet_connect/evm_chain_service.dart | 6 +- lib/di.dart | 9 +- lib/entities/default_settings_migration.dart | 2 - lib/entities/node_list.dart | 7 +- .../provider/sideshift_exchange_provider.dart | 17 +- .../simpleswap_exchange_provider.dart | 4 + .../provider/trocador_exchange_provider.dart | 4 + lib/reactions/wallet_connect.dart | 11 ++ .../screens/dashboard/home_settings_page.dart | 3 +- lib/src/screens/root/root.dart | 4 +- .../settings/connection_sync_page.dart | 4 +- .../widgets/settings_choices_cell.dart | 47 ++--- .../contact_list/contact_list_view_model.dart | 5 +- res/values/strings_ar.arb | 3 +- res/values/strings_bg.arb | 3 +- res/values/strings_cs.arb | 3 +- res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 3 +- res/values/strings_es.arb | 8 +- res/values/strings_fr.arb | 3 +- res/values/strings_ha.arb | 3 +- res/values/strings_hi.arb | 3 +- res/values/strings_hr.arb | 8 +- res/values/strings_id.arb | 8 +- res/values/strings_it.arb | 3 +- res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 3 +- res/values/strings_nl.arb | 8 +- res/values/strings_pl.arb | 3 +- res/values/strings_pt.arb | 3 +- res/values/strings_ru.arb | 3 +- res/values/strings_th.arb | 3 +- res/values/strings_tl.arb | 3 +- res/values/strings_tr.arb | 3 +- res/values/strings_uk.arb | 5 +- res/values/strings_ur.arb | 3 +- res/values/strings_yo.arb | 3 +- res/values/strings_zh.arb | 3 +- scripts/android/pubspec_gen.sh | 2 +- scripts/ios/app_config.sh | 2 +- scripts/macos/app_config.sh | 2 +- 57 files changed, 320 insertions(+), 271 deletions(-) rename cw_ethereum/lib/{default_erc20_tokens.dart => default_ethereum_erc20_tokens.dart} (95%) rename cw_polygon/lib/{default_erc20_tokens.dart => default_polygon_erc20_tokens.dart} (90%) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 5b2bb11d3..88cdc6f6c 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -119,6 +119,7 @@ jobs: cd /opt/android/cake_wallet touch lib/.secrets.g.dart touch cw_ethereum/lib/.secrets.g.dart + touch cw_polygon/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 @@ -146,13 +147,13 @@ jobs: echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_ethereum/lib/.secrets.g.dart - echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> cw_ethereum/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 robinhoodCIdApiSecret = '${{ 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_ethereum/lib/.secrets.g.dart - name: Rename app run: echo -e "id=com.cakewallet.test\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties diff --git a/assets/polygon_node_list.yml b/assets/polygon_node_list.yml index 10654356a..34504269d 100644 --- a/assets/polygon_node_list.yml +++ b/assets/polygon_node_list.yml @@ -1,6 +1,6 @@ +- + uri: polygon-rpc.com - uri: polygon-bor.publicnode.com - - uri: polygon-rpc.com -- uri: polygon.llamarpc.com \ No newline at end of file diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 43391881f..3344cb807 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -79,11 +79,11 @@ packages: dependency: "direct main" description: path: "." - ref: cake-update-v3 - resolved-ref: df9204144011ed9419eff7d9ef3143102a40252d + ref: cake-update-v4 + resolved-ref: e19ffb7e7977278a75b27e0479b3c6f4034223b3 url: "https://github.com/cake-tech/bitcoin_flutter.git" source: git - version: "2.0.2" + version: "2.1.0" boolean_selector: dependency: transitive description: @@ -244,7 +244,7 @@ packages: source: hosted version: "2.2.4" encrypt: - dependency: "direct main" + dependency: transitive description: name: encrypt sha256: "4fd4e4fdc21b9d7d4141823e1e6515cd94e7b8d84749504c232999fba25d9bbb" @@ -698,15 +698,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" - tor: - dependency: transitive - description: - path: "." - ref: main - resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" - url: "https://github.com/cake-tech/tor.git" - source: git - version: "0.0.1" typed_data: dependency: transitive description: diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index 1936a87cf..35d42f6d2 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -93,6 +93,8 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen CryptoCurrency.dydx, CryptoCurrency.steth, CryptoCurrency.banano, + CryptoCurrency.usdtPoly, + CryptoCurrency.usdcEPoly, ]; static const havenCurrencies = [ @@ -202,6 +204,8 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen static const dydx = CryptoCurrency(title: 'DYDX', tag: 'ETH', fullName: 'dYdX', raw: 84, name: 'dydx', iconPath: 'assets/images/dydx_icon.png', decimals: 18); static const steth = CryptoCurrency(title: 'STETH', tag: 'ETH', fullName: 'Lido Staked Ethereum', raw: 85, name: 'steth', iconPath: 'assets/images/steth_icon.png', decimals: 18); static const banano = CryptoCurrency(title: 'BAN', fullName: 'Banano', raw: 86, name: 'banano', iconPath: 'assets/images/nano_icon.png', decimals: 29); + static const usdtPoly = CryptoCurrency(title: 'USDT', tag: 'POLY', fullName: 'Tether USD (PoS)', raw: 87, name: 'usdtpoly', iconPath: 'assets/images/usdt_icon.png', decimals: 6); + static const usdcEPoly = CryptoCurrency(title: 'USDC.E', tag: 'POLY', fullName: 'USD Coin (PoS)', raw: 88, name: 'usdcepoly', iconPath: 'assets/images/usdc_icon.png', decimals: 6); static final Map _rawCurrencyMap = diff --git a/cw_core/lib/erc20_token.dart b/cw_core/lib/erc20_token.dart index 75bf1aad0..830ce383b 100644 --- a/cw_core/lib/erc20_token.dart +++ b/cw_core/lib/erc20_token.dart @@ -18,6 +18,8 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin { bool _enabled; @HiveField(5) final String? iconPath; + @HiveField(6) + final String? tag; bool get enabled => _enabled; @@ -30,30 +32,31 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin { required this.decimal, bool enabled = true, this.iconPath, + this.tag, }) : _enabled = enabled, super( - name: symbol.toLowerCase(), - title: symbol.toUpperCase(), - fullName: name, - tag: "ETH", - iconPath: iconPath, - decimals: decimal - ); + name: symbol.toLowerCase(), + title: symbol.toUpperCase(), + fullName: name, + tag: tag, + iconPath: iconPath, + decimals: decimal); - Erc20Token.copyWith(Erc20Token other, String? icon) + Erc20Token.copyWith(Erc20Token other, String? icon, String? tag) : this.name = other.name, this.symbol = other.symbol, this.contractAddress = other.contractAddress, this.decimal = other.decimal, this._enabled = other.enabled, + this.tag = tag, this.iconPath = icon, super( name: other.name, title: other.symbol.toUpperCase(), fullName: other.name, - tag: "ETH", + tag: tag, iconPath: icon, - decimals: other.decimal + decimals: other.decimal, ); static const typeId = ERC20_TOKEN_TYPE_ID; @@ -61,7 +64,8 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin { static const polygonBoxName = ' PolygonErc20Tokens'; @override - bool operator ==(other) => (other is Erc20Token && other.contractAddress == contractAddress) || + bool operator ==(other) => + (other is Erc20Token && other.contractAddress == contractAddress) || (other is CryptoCurrency && other.title == title); @override diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index bd96e1395..2c43dd21a 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -214,7 +214,7 @@ class Node extends HiveObject with Keyable { } Future requestNodeWithProxy() async { - if (!isValidProxyAddress/* && !Tor.instance.enabled*/) { + if (!isValidProxyAddress /* && !Tor.instance.enabled*/) { return false; } diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock index f351759ed..aacbd9ddd 100644 --- a/cw_core/pubspec.lock +++ b/cw_core/pubspec.lock @@ -616,15 +616,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" - tor: - dependency: "direct main" - description: - path: "." - ref: main - resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" - url: "https://github.com/cake-tech/tor.git" - source: git - version: "0.0.1" typed_data: dependency: transitive description: diff --git a/cw_ethereum/lib/default_erc20_tokens.dart b/cw_ethereum/lib/default_ethereum_erc20_tokens.dart similarity index 95% rename from cw_ethereum/lib/default_erc20_tokens.dart rename to cw_ethereum/lib/default_ethereum_erc20_tokens.dart index 8c38e2e64..a8f82d181 100644 --- a/cw_ethereum/lib/default_erc20_tokens.dart +++ b/cw_ethereum/lib/default_ethereum_erc20_tokens.dart @@ -293,17 +293,13 @@ class DefaultErc20Tokens { ]; List get initialErc20Tokens => _defaultTokens.map((token) { - String? iconPath; - try { - iconPath = CryptoCurrency.all - .firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase()) - .iconPath; - } catch (_) {} + String? iconPath; + try { + iconPath = CryptoCurrency.all + .firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase()) + .iconPath; + } catch (_) {} - if (iconPath != null) { - return Erc20Token.copyWith(token, iconPath); - } - - return token; - }).toList(); + return Erc20Token.copyWith(token, iconPath, 'ETH'); + }).toList(); } diff --git a/cw_ethereum/lib/ethereum_client.dart b/cw_ethereum/lib/ethereum_client.dart index 5e408bb9e..fccbf778d 100644 --- a/cw_ethereum/lib/ethereum_client.dart +++ b/cw_ethereum/lib/ethereum_client.dart @@ -78,19 +78,18 @@ class EthereumClient { currency == CryptoCurrency.maticpoly || contractAddress != null); - bool _isEVMCompatibleChain = currency == CryptoCurrency.eth || currency == CryptoCurrency.maticpoly; + bool _isEVMCompatibleChain = + currency == CryptoCurrency.eth || currency == CryptoCurrency.maticpoly; final price = _client!.getGasPrice(); - final Transaction transaction = Transaction( + final Transaction transaction = createTransaction( from: privateKey.address, to: EthereumAddress.fromHex(toAddress), maxPriorityFeePerGas: EtherAmount.fromInt(EtherUnit.gwei, priority.tip), - value: _isEVMCompatibleChain ? EtherAmount.inWei(BigInt.parse(amount)) : EtherAmount.zero(), + amount: _isEVMCompatibleChain ? EtherAmount.inWei(BigInt.parse(amount)) : EtherAmount.zero(), ); - final chainId = _getChainIdForCurrency(currency); - final signedTransaction = await _client!.signTransaction(privateKey, transaction, chainId: chainId); @@ -124,18 +123,27 @@ class EthereumClient { ); } - int _getChainIdForCurrency(CryptoCurrency currency) { - switch (currency) { - case CryptoCurrency.maticpoly: - return 137; - case CryptoCurrency.eth: - default: - return 1; - } + int get chainId => 1; + + Transaction createTransaction({ + required EthereumAddress from, + required EthereumAddress to, + required EtherAmount amount, + EtherAmount? maxPriorityFeePerGas, + }) { + return Transaction( + from: from, + to: to, + maxPriorityFeePerGas: maxPriorityFeePerGas, + value: amount, + ); } Future sendTransaction(Uint8List signedTransaction) async => - await _client!.sendRawTransaction(prependTransactionType(0x02, signedTransaction)); + await _client!.sendRawTransaction(prepareSignedTransactionForSending(signedTransaction)); + + Uint8List prepareSignedTransactionForSending(Uint8List signedTransaction) => + prependTransactionType(0x02, signedTransaction); Future getTransactionDetails(String transactionHash) async { // Wait for the transaction receipt to become available diff --git a/cw_ethereum/lib/ethereum_wallet.dart b/cw_ethereum/lib/ethereum_wallet.dart index 21bde1233..5c6cc4448 100644 --- a/cw_ethereum/lib/ethereum_wallet.dart +++ b/cw_ethereum/lib/ethereum_wallet.dart @@ -14,7 +14,7 @@ import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/wallet_addresses.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_info.dart'; -import 'package:cw_ethereum/default_erc20_tokens.dart'; +import 'package:cw_ethereum/default_ethereum_erc20_tokens.dart'; import 'package:cw_ethereum/erc20_balance.dart'; import 'package:cw_ethereum/ethereum_client.dart'; import 'package:cw_ethereum/ethereum_exceptions.dart'; @@ -429,6 +429,7 @@ abstract class EthereumWalletBase contractAddress: token.contractAddress, decimal: token.decimal, enabled: token.enabled, + tag: token.tag ?? "ETH", iconPath: iconPath, ); @@ -492,7 +493,7 @@ abstract class EthereumWalletBase _transactionsUpdateTimer!.cancel(); } - _transactionsUpdateTimer = Timer.periodic(Duration(seconds: 10), (_) { + _transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 10), (_) { _updateTransactions(); _updateBalance(); }); @@ -508,7 +509,7 @@ abstract class EthereumWalletBase } @override - String signMessage(String message, {String? address = null}) => + String signMessage(String message, {String? address}) => bytesToHex(_ethPrivateKey.signPersonalMessageToUint8List(ascii.encode(message))); Web3Client? getWeb3Client() => _client.getWeb3Client(); diff --git a/cw_monero/example/pubspec.lock b/cw_monero/example/pubspec.lock index 3dd2b5b61..c9ca8d92b 100644 --- a/cw_monero/example/pubspec.lock +++ b/cw_monero/example/pubspec.lock @@ -153,6 +153,22 @@ packages: description: flutter source: sdk version: "0.0.0" + hashlib: + dependency: transitive + description: + name: hashlib + sha256: "71bf102329ddb8e50c8a995ee4645ae7f1728bb65e575c17196b4d8262121a96" + url: "https://pub.dev" + source: hosted + version: "1.12.0" + hashlib_codecs: + dependency: transitive + description: + name: hashlib_codecs + sha256: "49e2a471f74b15f1854263e58c2ac11f2b631b5b12c836f9708a35397d36d626" + url: "https://pub.dev" + source: hosted + version: "2.2.0" http: dependency: transitive description: @@ -308,12 +324,11 @@ packages: polyseed: dependency: transitive description: - path: "." - ref: HEAD - resolved-ref: "504d58a5b147fccd3bc85a25f2e72fb32771ddd7" - url: "https://github.com/cake-tech/polyseed_dart.git" - source: git - version: "0.0.1" + name: polyseed + sha256: "9b48ec535b10863f78f6354ec983b4cc0c88ca69ff48fee469d0fd1954b01d4f" + url: "https://pub.dev" + source: hosted + version: "0.0.2" process: dependency: transitive description: @@ -383,15 +398,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.1" - tor: - dependency: transitive - description: - path: "." - ref: main - resolved-ref: "09ba92cb11d4e3cacf97256e57863b805f79f2e5" - url: "https://github.com/cake-tech/tor.git" - source: git - version: "0.0.1" typed_data: dependency: transitive description: diff --git a/cw_polygon/lib/default_erc20_tokens.dart b/cw_polygon/lib/default_polygon_erc20_tokens.dart similarity index 90% rename from cw_polygon/lib/default_erc20_tokens.dart rename to cw_polygon/lib/default_polygon_erc20_tokens.dart index 132c52e4c..deff285c0 100644 --- a/cw_polygon/lib/default_erc20_tokens.dart +++ b/cw_polygon/lib/default_polygon_erc20_tokens.dart @@ -29,7 +29,7 @@ class DefaultPolygonErc20Tokens { symbol: "USDC.e", contractAddress: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", decimal: 6, - enabled: false, + enabled: true, ), Erc20Token( name: "Avalanche Token", @@ -73,14 +73,10 @@ class DefaultPolygonErc20Tokens { try { iconPath = CryptoCurrency.all .firstWhere((element) => - element.title.toUpperCase() == token.symbol.toUpperCase()) + element.title.toUpperCase() == token.symbol.split(".").first.toUpperCase()) .iconPath; } catch (_) {} - if (iconPath != null) { - return Erc20Token.copyWith(token, iconPath); - } - - return token; + return Erc20Token.copyWith(token, iconPath, 'POLY'); }).toList(); } diff --git a/cw_polygon/lib/polygon_client.dart b/cw_polygon/lib/polygon_client.dart index 86c2253af..876f4c60d 100644 --- a/cw_polygon/lib/polygon_client.dart +++ b/cw_polygon/lib/polygon_client.dart @@ -3,8 +3,30 @@ import 'dart:convert'; import 'package:cw_ethereum/ethereum_client.dart'; import 'package:cw_polygon/polygon_transaction_model.dart'; import 'package:cw_ethereum/.secrets.g.dart' as secrets; +import 'package:flutter/foundation.dart'; +import 'package:web3dart/web3dart.dart'; class PolygonClient extends EthereumClient { + @override + Transaction createTransaction({ + required EthereumAddress from, + required EthereumAddress to, + required EtherAmount amount, + EtherAmount? maxPriorityFeePerGas, + }) { + return Transaction( + from: from, + to: to, + value: amount, + ); + } + + @override + Uint8List prepareSignedTransactionForSending(Uint8List signedTransaction) => signedTransaction; + + @override + int get chainId => 137; + @override Future> fetchTransactions(String address, {String? contractAddress}) async { @@ -27,7 +49,6 @@ class PolygonClient extends EthereumClient { return []; } catch (e) { - print(e); return []; } } diff --git a/cw_polygon/lib/polygon_wallet.dart b/cw_polygon/lib/polygon_wallet.dart index 66e6797c6..5749a95ac 100644 --- a/cw_polygon/lib/polygon_wallet.dart +++ b/cw_polygon/lib/polygon_wallet.dart @@ -16,10 +16,9 @@ import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_ethereum/erc20_balance.dart'; import 'package:cw_ethereum/ethereum_formatter.dart'; -import 'package:cw_ethereum/ethereum_transaction_model.dart'; import 'package:cw_ethereum/file.dart'; import 'package:cw_core/erc20_token.dart'; -import 'package:cw_polygon/default_erc20_tokens.dart'; +import 'package:cw_polygon/default_polygon_erc20_tokens.dart'; import 'package:cw_polygon/polygon_client.dart'; import 'package:cw_polygon/polygon_exceptions.dart'; import 'package:cw_polygon/polygon_formatter.dart'; @@ -42,28 +41,26 @@ part 'polygon_wallet.g.dart'; class PolygonWallet = PolygonWalletBase with _$PolygonWallet; -abstract class PolygonWalletBase extends WalletBase with Store { +abstract class PolygonWalletBase + extends WalletBase with Store { PolygonWalletBase({ required WalletInfo walletInfo, String? mnemonic, String? privateKey, required String password, ERC20Balance? initialBalance, - }) : syncStatus = NotConnectedSyncStatus(), + }) : syncStatus = const NotConnectedSyncStatus(), _password = password, _mnemonic = mnemonic, _hexPrivateKey = privateKey, _isTransactionUpdating = false, _client = PolygonClient(), walletAddresses = PolygonWalletAddresses(walletInfo), - balance = ObservableMap.of({ - CryptoCurrency.maticpoly: initialBalance ?? ERC20Balance(BigInt.zero) - }), + balance = ObservableMap.of( + {CryptoCurrency.maticpoly: initialBalance ?? ERC20Balance(BigInt.zero)}), super(walletInfo) { this.walletInfo = walletInfo; - transactionHistory = - PolygonTransactionHistory(walletInfo: walletInfo, password: password); + transactionHistory = PolygonTransactionHistory(walletInfo: walletInfo, password: password); if (!CakeHive.isAdapterRegistered(Erc20Token.typeId)) { CakeHive.registerAdapter(Erc20TokenAdapter()); @@ -80,9 +77,9 @@ abstract class PolygonWalletBase extends WalletBase _polygonPrivateKey; + late final PolygonClient _client; - late PolygonClient _client; + EthPrivateKey get polygonPrivateKey => _polygonPrivateKey; int? _gasPrice; int? _estimatedGas; @@ -102,11 +99,11 @@ abstract class PolygonWalletBase extends WalletBase balance; - Completer _sharedPrefs = Completer(); + final Completer _sharedPrefs = Completer(); Future init() async { - polygonErc20TokensBox = - await CakeHive.openBox(Erc20Token.polygonBoxName); + polygonErc20TokensBox = await CakeHive.openBox( + "${walletInfo.name.replaceAll(" ", "_")}_${Erc20Token.polygonBoxName}"); await walletAddresses.init(); await transactionHistory.init(); _polygonPrivateKey = await getPrivateKey( @@ -122,8 +119,7 @@ abstract class PolygonWalletBase extends WalletBase createTransaction(Object credentials) async { - final _credentials = credentials as PolygonTransactionCredentials; - final outputs = _credentials.outputs; + final credentials0 = credentials as PolygonTransactionCredentials; + final outputs = credentials0.outputs; final hasMultiDestination = outputs.length > 1; - final CryptoCurrency transactionCurrency = balance.keys - .firstWhere((element) => element.title == _credentials.currency.title); + final CryptoCurrency transactionCurrency = + balance.keys.firstWhere((element) => element.title == credentials0.currency.title); - final _erc20Balance = balance[transactionCurrency]!; + final erc20Balance = balance[transactionCurrency]!; BigInt totalAmount = BigInt.zero; - int exponent = - transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18; + int exponent = transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18; num amountToPolygonMultiplier = pow(10, exponent); // so far this can not be made with Polygon as Polygon does not support multiple recipients if (hasMultiDestination) { - if (outputs.any( - (item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) { + if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) { throw PolygonTransactionCreationException(transactionCurrency); } final totalOriginalAmount = PolygonFormatter.parsePolygonAmountToDouble( - outputs.fold( - 0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0))); - totalAmount = - BigInt.from(totalOriginalAmount * amountToPolygonMultiplier); + outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0))); + totalAmount = BigInt.from(totalOriginalAmount * amountToPolygonMultiplier); - if (_erc20Balance.balance < totalAmount) { + if (erc20Balance.balance < totalAmount) { throw PolygonTransactionCreationException(transactionCurrency); } } else { @@ -203,35 +195,33 @@ abstract class PolygonWalletBase extends WalletBase>> polygonErc20TokensTransactions = - []; + final List>> polygonErc20TokensTransactions = []; for (var token in balance.keys) { if (token is Erc20Token) { - polygonErc20TokensTransactions.add(_client.fetchTransactions( - address, - contractAddress: token.contractAddress, - ) as Future>); + polygonErc20TokensTransactions.add( + _client.fetchTransactions( + address, + contractAddress: token.contractAddress, + ), + ); } } @@ -294,8 +285,7 @@ abstract class PolygonWalletBase extends WalletBase _gasPrice = await _client.getGasUnitPrice()); + Timer.periodic( + const Duration(minutes: 1), (timer) async => _gasPrice = await _client.getGasUnitPrice()); Timer.periodic(const Duration(seconds: 10), (timer) async => _estimatedGas = await _client.getEstimatedGas()); @@ -348,8 +338,7 @@ abstract class PolygonWalletBase extends WalletBase makePath() async => - pathForWallet(name: walletInfo.name, type: walletInfo.type); + Future makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); String toJSON() => json.encode({ 'mnemonic': _mnemonic, @@ -367,8 +356,7 @@ abstract class PolygonWalletBase extends WalletBase)); + return EthPrivateKey.fromHex(HEX.encode(addressAtIndex.privateKey as List)); } + @override Future? updateBalance() async => await _updateBalance(); List get erc20Currencies => polygonErc20TokensBox.values.toList(); @@ -434,29 +422,29 @@ abstract class PolygonWalletBase extends WalletBase - element.title.toUpperCase() == token.symbol.toUpperCase()) + .firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase()) .iconPath; } catch (_) {} - final _token = Erc20Token( + final token0 = Erc20Token( name: token.name, symbol: token.symbol, contractAddress: token.contractAddress, decimal: token.decimal, enabled: token.enabled, + tag: token.tag ?? "POLY", iconPath: iconPath, ); - await polygonErc20TokensBox.put(_token.contractAddress, _token); + await polygonErc20TokensBox.put(token0.contractAddress, token0); - if (_token.enabled) { - balance[_token] = await _client.fetchERC20Balances( + if (token0.enabled) { + balance[token0] = await _client.fetchERC20Balances( _polygonPrivateKey.address, - _token.contractAddress, + token0.contractAddress, ); } else { - balance.remove(_token); + balance.remove(token0); } } @@ -476,8 +464,7 @@ abstract class PolygonWalletBase extends WalletBase renameWalletFiles(String newWalletName) async { - final currentWalletPath = - await pathForWallet(name: walletInfo.name, type: type); + final currentWalletPath = await pathForWallet(name: walletInfo.name, type: type); final currentWalletFile = File(currentWalletPath); - final currentDirPath = - await pathForWalletDir(name: walletInfo.name, type: type); - final currentTransactionsFile = - File('$currentDirPath/$transactionsHistoryFileName'); + final currentDirPath = await pathForWalletDir(name: walletInfo.name, type: type); + final currentTransactionsFile = File('$currentDirPath/$transactionsHistoryFileName'); // Copies current wallet files into new wallet name's dir and files if (currentWalletFile.existsSync()) { - final newWalletPath = - await pathForWallet(name: newWalletName, type: type); + final newWalletPath = await pathForWallet(name: newWalletName, type: type); await currentWalletFile.copy(newWalletPath); } if (currentTransactionsFile.existsSync()) { - final newDirPath = - await pathForWalletDir(name: newWalletName, type: type); - await currentTransactionsFile - .copy('$newDirPath/$transactionsHistoryFileName'); + final newDirPath = await pathForWalletDir(name: newWalletName, type: type); + await currentTransactionsFile.copy('$newDirPath/$transactionsHistoryFileName'); } // Delete old name's dir and files @@ -517,7 +498,7 @@ abstract class PolygonWalletBase extends WalletBase bytesToHex( - _polygonPrivateKey.signPersonalMessageToUint8List(ascii.encode(message))); + String signMessage(String message, {String? address}) => + bytesToHex(_polygonPrivateKey.signPersonalMessageToUint8List(ascii.encode(message))); Web3Client? getWeb3Client() => _client.getWeb3Client(); } diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 1bc0d1ae2..558d14f6d 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -32,6 +32,8 @@ class AddressValidator extends TextValidator { return '[0-9a-zA-Z_]'; case CryptoCurrency.usdc: case CryptoCurrency.usdcpoly: + case CryptoCurrency.usdtPoly: + case CryptoCurrency.usdcEPoly: case CryptoCurrency.ape: case CryptoCurrency.avaxc: case CryptoCurrency.eth: @@ -141,6 +143,8 @@ class AddressValidator extends TextValidator { return [42]; case CryptoCurrency.eth: case CryptoCurrency.usdcpoly: + case CryptoCurrency.usdtPoly: + case CryptoCurrency.usdcEPoly: case CryptoCurrency.mana: case CryptoCurrency.matic: case CryptoCurrency.maticpoly: diff --git a/lib/core/wallet_connect/evm_chain_service.dart b/lib/core/wallet_connect/evm_chain_service.dart index b9849fdac..836d1a7c8 100644 --- a/lib/core/wallet_connect/evm_chain_service.dart +++ b/lib/core/wallet_connect/evm_chain_service.dart @@ -285,10 +285,12 @@ class EvmChainServiceImpl implements ChainService { } String _convertToReadable(Map data) { + final tokenName = getTokenNameBasedOnWalletType(appStore.wallet!.type); String gas = int.parse((data['gas'] as String).substring(2), radix: 16).toString(); String value = data['value'] != null - ? (int.parse((data['value'] as String).substring(2), radix: 16) / 1e18).toString() + ' ETH' - : '0 ETH'; + ? (int.parse((data['value'] as String).substring(2), radix: 16) / 1e18).toString() + + ' $tokenName' + : '0 $tokenName'; String from = data['from'] as String; String to = data['to'] as String; diff --git a/lib/di.dart b/lib/di.dart index 15d008dca..f3a03f03b 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -19,7 +19,6 @@ import 'package:cake_wallet/ionia/ionia_anypay.dart'; import 'package:cake_wallet/ionia/ionia_gift_card.dart'; import 'package:cake_wallet/ionia/ionia_tip.dart'; 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/src/screens/anonpay_details/anonpay_details_page.dart'; import 'package:cake_wallet/src/screens/buy/buy_options_page.dart'; @@ -752,13 +751,7 @@ Future setup({ return PowNodeListViewModel(_powNodeSource, appStore); }); - getIt.registerFactory(() { - final wallet = getIt.get().wallet; - return ConnectionSyncPage( - getIt.get(), - isEVMCompatibleChain(wallet!.type) ? getIt.get() : null, - ); - }); + getIt.registerFactory(() => ConnectionSyncPage(getIt.get())); getIt.registerFactory( () => SecurityBackupPage(getIt.get(), getIt.get())); diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 45803899e..22868ae28 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -1,6 +1,5 @@ import 'dart:io' show Directory, File, Platform; import 'package:cake_wallet/bitcoin/bitcoin.dart'; -import 'package:cake_wallet/entities/encrypt.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; @@ -186,7 +185,6 @@ Future defaultSettingsMigration( case 25: await rewriteSecureStoragePin(secureStorage: secureStorage); break; - default: break; } diff --git a/lib/entities/node_list.dart b/lib/entities/node_list.dart index 6d1cf299d..aaac8a5c2 100644 --- a/lib/entities/node_list.dart +++ b/lib/entities/node_list.dart @@ -85,8 +85,7 @@ Future> loadDefaultEthereumNodes() async { } Future> loadBitcoinCashElectrumServerList() async { - final serverListRaw = - await rootBundle.loadString('assets/bitcoin_cash_electrum_server_list.yml'); + final serverListRaw = await rootBundle.loadString('assets/bitcoin_cash_electrum_server_list.yml'); final loadedServerList = loadYaml(serverListRaw) as YamlList; final serverList = []; @@ -141,6 +140,7 @@ Future> loadDefaultPolygonNodes() async { for (final raw in loadedNodes) { if (raw is Map) { final node = Node.fromMap(Map.from(raw)); + node.type = WalletType.polygon; nodes.add(node); } @@ -159,7 +159,6 @@ Future resetToDefault(Box nodeSource) async { final nanoNodes = await loadDefaultNanoNodes(); final polygonNodes = await loadDefaultPolygonNodes(); - final nodes = moneroNodes + bitcoinElectrumServerList + litecoinElectrumServerList + @@ -178,4 +177,4 @@ Future resetPowToDefault(Box powNodeSource) async { final nodes = nanoPowNodes; await powNodeSource.clear(); await powNodeSource.addAll(nodes); -} \ No newline at end of file +} diff --git a/lib/exchange/provider/sideshift_exchange_provider.dart b/lib/exchange/provider/sideshift_exchange_provider.dart index 7a466e213..261aeedf3 100644 --- a/lib/exchange/provider/sideshift_exchange_provider.dart +++ b/lib/exchange/provider/sideshift_exchange_provider.dart @@ -159,8 +159,8 @@ class SideShiftExchangeProvider extends ExchangeProvider { url = apiBaseUrl + orderPath + '/fixed'; } else { url = apiBaseUrl + orderPath + '/variable'; - body["depositCoin"] = request.fromCurrency.title.toLowerCase(); - body["settleCoin"] = request.toCurrency.title.toLowerCase(); + body["depositCoin"] = _normalizeCurrency(request.fromCurrency); + body["settleCoin"] = _normalizeCurrency(request.toCurrency); body["settleNetwork"] = _networkFor(request.toCurrency); body["depositNetwork"] = _networkFor(request.fromCurrency); } @@ -248,8 +248,8 @@ class SideShiftExchangeProvider extends ExchangeProvider { final url = apiBaseUrl + quotePath; final headers = {'Content-Type': 'application/json'}; final body = { - 'depositCoin': request.fromCurrency.title.toLowerCase(), - 'settleCoin': request.toCurrency.title.toLowerCase(), + 'depositCoin': _normalizeCurrency(request.fromCurrency), + 'settleCoin': _normalizeCurrency(request.toCurrency), 'affiliateId': affiliateId, 'settleAmount': request.toAmount, 'settleNetwork': _networkFor(request.toCurrency), @@ -274,6 +274,15 @@ class SideShiftExchangeProvider extends ExchangeProvider { return responseJSON['id'] as String; } + String _normalizeCurrency(CryptoCurrency currency) { + switch (currency) { + case CryptoCurrency.usdcEPoly: + return 'usdc'; + default: + return currency.title.toLowerCase(); + } + } + String _networkFor(CryptoCurrency currency) => currency.tag != null ? _normalizeTag(currency.tag!) : 'mainnet'; diff --git a/lib/exchange/provider/simpleswap_exchange_provider.dart b/lib/exchange/provider/simpleswap_exchange_provider.dart index 091c3a913..5c162a995 100644 --- a/lib/exchange/provider/simpleswap_exchange_provider.dart +++ b/lib/exchange/provider/simpleswap_exchange_provider.dart @@ -222,6 +222,10 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { return 'usdttrc20'; case CryptoCurrency.usdcpoly: return 'usdcpoly'; + case CryptoCurrency.usdtPoly: + return 'usdtpoly'; + case CryptoCurrency.usdcEPoly: + return 'usdcepoly'; case CryptoCurrency.usdcsol: return 'usdcspl'; case CryptoCurrency.matic: diff --git a/lib/exchange/provider/trocador_exchange_provider.dart b/lib/exchange/provider/trocador_exchange_provider.dart index 52e38ecc8..faa4cc060 100644 --- a/lib/exchange/provider/trocador_exchange_provider.dart +++ b/lib/exchange/provider/trocador_exchange_provider.dart @@ -271,6 +271,8 @@ class TrocadorExchangeProvider extends ExchangeProvider { case CryptoCurrency.maticpoly: return 'Mainnet'; case CryptoCurrency.usdcpoly: + case CryptoCurrency.usdtPoly: + case CryptoCurrency.usdcEPoly: return 'MATIC'; case CryptoCurrency.zec: return 'Mainnet'; @@ -283,6 +285,8 @@ class TrocadorExchangeProvider extends ExchangeProvider { switch (currency) { case CryptoCurrency.zec: return 'zec'; + case CryptoCurrency.usdcEPoly: + return 'usdce'; default: return currency.title.toLowerCase(); } diff --git a/lib/reactions/wallet_connect.dart b/lib/reactions/wallet_connect.dart index d0ff37267..4f5923e26 100644 --- a/lib/reactions/wallet_connect.dart +++ b/lib/reactions/wallet_connect.dart @@ -44,3 +44,14 @@ String getChainNameBasedOnWalletType(WalletType walletType) { return ''; } } + +String getTokenNameBasedOnWalletType(WalletType walletType) { + switch (walletType) { + case WalletType.ethereum: + return 'ETH'; + case WalletType.polygon: + return 'MATIC'; + default: + return ''; + } +} diff --git a/lib/src/screens/dashboard/home_settings_page.dart b/lib/src/screens/dashboard/home_settings_page.dart index a08b8a8a7..618ba49ff 100644 --- a/lib/src/screens/dashboard/home_settings_page.dart +++ b/lib/src/screens/dashboard/home_settings_page.dart @@ -8,6 +8,7 @@ import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/themes/extensions/address_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/themes/extensions/menu_theme.dart'; import 'package:cake_wallet/themes/extensions/picker_theme.dart'; import 'package:cake_wallet/view_model/dashboard/home_settings_view_model.dart'; @@ -91,7 +92,7 @@ class HomeSettingsPage extends BasePage { fillColor: Theme.of(context).cardColor, child: Icon( Icons.add, - color: Theme.of(context).dialogTheme.backgroundColor, + color: Theme.of(context).extension()!.titleColor, size: 22.0, ), padding: EdgeInsets.all(12), diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index 67cd689b1..5f7fcd205 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -176,7 +176,7 @@ class RootState extends State with WidgetsBindingObserver { ); launchUri = null; } else { - _nonETHWalletErrorToast(S.current.switchToETHWallet); + _nonETHWalletErrorToast(S.current.switchToEVMCompatibleWallet); } } @@ -206,7 +206,7 @@ class RootState extends State with WidgetsBindingObserver { String? _getRouteToGo() { if (isWalletConnectLink) { if (isEVMCompatibleChain(widget.appStore.wallet!.type)) { - _nonETHWalletErrorToast(S.current.switchToETHWallet); + _nonETHWalletErrorToast(S.current.switchToEVMCompatibleWallet); return null; } return Routes.walletConnectConnectionsListing; diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart index 40a04b0db..bec2e6296 100644 --- a/lib/src/screens/settings/connection_sync_page.dart +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -1,4 +1,3 @@ -import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart'; import 'package:cake_wallet/reactions/wallet_connect.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'; @@ -18,12 +17,11 @@ import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; class ConnectionSyncPage extends BasePage { - ConnectionSyncPage(this.dashboardViewModel, this.web3walletService); + ConnectionSyncPage(this.dashboardViewModel); @override String get title => S.current.connection_sync; - final Web3WalletService? web3walletService; final DashboardViewModel dashboardViewModel; @override diff --git a/lib/src/screens/settings/widgets/settings_choices_cell.dart b/lib/src/screens/settings/widgets/settings_choices_cell.dart index aea5ecbb9..79f74699d 100644 --- a/lib/src/screens/settings/widgets/settings_choices_cell.dart +++ b/lib/src/screens/settings/widgets/settings_choices_cell.dart @@ -31,42 +31,43 @@ class SettingsChoicesCell extends StatelessWidget { ), const SizedBox(height: 24), Center( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(30), - color: Theme.of(context).extension()!.actionButtonColor, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: choicesListItem.items.map((dynamic e) { - final isSelected = choicesListItem.selectedItem == e; - return GestureDetector( + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: Theme.of(context).extension()!.actionButtonColor, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: choicesListItem.items.map((dynamic e) { + final isSelected = choicesListItem.selectedItem == e; + return Expanded( + child: GestureDetector( onTap: () { choicesListItem.onItemSelected.call(e); }, child: Container( - padding: EdgeInsets.symmetric(horizontal: 32, vertical: 8), + padding: EdgeInsets.symmetric(vertical: 8), decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), color: isSelected ? Theme.of(context).primaryColor : null, ), - child: Text( - choicesListItem.displayItem.call(e), - style: TextStyle( - color: isSelected - ? Colors.white - : Theme.of(context).extension()!.secondaryTextColor, - fontWeight: isSelected ? FontWeight.w700 : FontWeight.normal, + child: Center( + child: Text( + choicesListItem.displayItem.call(e), + style: TextStyle( + color: isSelected + ? Colors.white + : Theme.of(context).extension()!.secondaryTextColor, + fontWeight: isSelected ? FontWeight.w700 : FontWeight.normal, + ), ), ), ), - ); - }).toList(), - ), + ), + ); + }).toList(), ), ), ), diff --git a/lib/view_model/contact_list/contact_list_view_model.dart b/lib/view_model/contact_list/contact_list_view_model.dart index 0dcd8108a..b53b67c43 100644 --- a/lib/view_model/contact_list/contact_list_view_model.dart +++ b/lib/view_model/contact_list/contact_list_view_model.dart @@ -91,6 +91,9 @@ abstract class ContactListViewModelBase with Store { walletContacts.where((element) => _isValidForCurrency(element)).toList(); bool _isValidForCurrency(ContactBase element) { - return _currency == null || element.type == _currency || element.type.title == _currency!.tag; + return _currency == null || + element.type == _currency || + element.type.title == _currency!.tag || + element.type.tag == _currency!.tag; } } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index d1c59cfbb..c2cb7c060 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -748,5 +748,6 @@ "seed_language_chinese_traditional": "تقاليد صينية)", "dfx_option_description": "ﺎﺑﻭﺭﻭﺃ ﻲﻓ ﺕﺎﻛﺮﺸﻟﺍﻭ ﺔﺋﺰﺠﺘﻟﺍ ءﻼﻤﻌﻟ .ﻲﻓﺎﺿﺇ KYC ﻥﻭﺪﺑ ﻭﺭﻮﻳ 990 ﻰﻟﺇ ﻞﺼﻳ ﺎﻣ .ﻱﺮﺴﻳﻮﺴﻟﺍ", "polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ", - "wallet_seed_legacy": "بذرة محفظة قديمة" + "wallet_seed_legacy": "بذرة محفظة قديمة", + "switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index e0ec30144..f0da8a754 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -744,5 +744,6 @@ "seed_language_chinese_traditional": "Традиционен китайски)", "dfx_option_description": "Купете крипто с EUR и CHF. До 990 € без допълнителен KYC. За клиенти на дребно и корпоративни клиенти в Европа", "polygonscan_history": "История на PolygonScan", - "wallet_seed_legacy": "Наследено портфейл семе" + "wallet_seed_legacy": "Наследено портфейл семе", + "switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 00de47f3a..60a37d9d0 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -744,5 +744,6 @@ "seed_language_chinese_traditional": "Číňan (tradiční)", "dfx_option_description": "Nakupujte kryptoměny za EUR a CHF. Až 990 € bez dalších KYC. Pro maloobchodní a firemní zákazníky v Evropě", "polygonscan_history": "Historie PolygonScan", - "wallet_seed_legacy": "Starší semeno peněženky" + "wallet_seed_legacy": "Starší semeno peněženky", + "switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index ca3cda44f..9d5b171d3 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -752,5 +752,6 @@ "seed_language_chinese_traditional": "Chinesisch (Traditionell)", "dfx_option_description": "Krypto mit EUR und CHF kaufen. Bis zu 990€ ohne zusätzliches KYC. Für Privat- und Firmenkunden in Europa", "polygonscan_history": "PolygonScan-Verlauf", - "wallet_seed_legacy": "Legacy Wallet Seed" + "wallet_seed_legacy": "Legacy Wallet Seed", + "switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index c8667afa9..00848da1f 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -753,5 +753,6 @@ "seed_language_chinese_traditional": "Chinese (Traditional)", "dfx_option_description": "Buy crypto with EUR & CHF. Up to 990€ without additional KYC. For retail and corporate customers in Europe", "polygonscan_history": "PolygonScan history", - "wallet_seed_legacy": "Legacy wallet seed" + "wallet_seed_legacy": "Legacy wallet seed", + "switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 335090eae..e77462740 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -749,9 +749,9 @@ "seedtype_polyseed": "Polieta (16 palabras)", "seed_language_czech": "checo", "seed_language_korean": "coreano", - "seed_language_chinese_traditional": "Chino tradicional)", - "dfx_option_description": "Compre criptomonedas con EUR y CHF. Hasta 990€ sin KYC adicional. Para clientes minoristas y corporativos en Europa", "seed_language_chinese_traditional": "Chino (tradicional)", + "dfx_option_description": "Compre criptomonedas con EUR y CHF. Hasta 990€ sin KYC adicional. Para clientes minoristas y corporativos en Europa", "polygonscan_history": "Historial de PolygonScan", - "wallet_seed_legacy": "Semilla de billetera heredada" -} \ No newline at end of file + "wallet_seed_legacy": "Semilla de billetera heredada", + "switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)" +} diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 916cc935a..e45a6d90c 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -752,5 +752,6 @@ "seed_language_chinese_traditional": "Chinois (Traditionnel)", "dfx_option_description": "Achetez des crypto-monnaies avec EUR et CHF. Jusqu'à 990€ sans KYC supplémentaire. Pour les clients particuliers et entreprises en Europe", "polygonscan_history": "Historique de PolygonScan", - "wallet_seed_legacy": "Graine de portefeuille hérité" + "wallet_seed_legacy": "Graine de portefeuille hérité", + "switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 32de934c2..e1369091e 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -730,5 +730,6 @@ "seed_language_chinese_traditional": "Sinanci (na gargajiya)", "dfx_option_description": "Sayi crypto tare da EUR & CHF. Har zuwa € 990 ba tare da ƙarin KYC ba. Don 'yan kasuwa da abokan ciniki na kamfanoni a Turai", "polygonscan_history": "PolygonScan tarihin kowane zamani", - "wallet_seed_legacy": "Tallarin walat walat" + "wallet_seed_legacy": "Tallarin walat walat", + "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 0ecbd9816..32e2cba0d 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -752,5 +752,6 @@ "seed_language_chinese_traditional": "चीनी पारंपरिक)", "dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। अतिरिक्त केवाईसी के बिना 990€ तक। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए", "polygonscan_history": "पॉलीगॉनस्कैन इतिहास", - "wallet_seed_legacy": "विरासत बटुए बीज" + "wallet_seed_legacy": "विरासत बटुए बीज", + "switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index bbe2c14ac..4afaa410d 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -747,9 +747,9 @@ "seedtype_polyseed": "Poliseed (16 riječi)", "seed_language_czech": "češki", "seed_language_korean": "korejski", - "seed_language_chinese_traditional": "Kinesko tradicionalno)", - "dfx_option_description": "Kupujte kripto s EUR i CHF. Do 990 € bez dodatnog KYC-a. Za maloprodajne i poslovne korisnike u Europi", "seed_language_chinese_traditional": "Kinesko (tradicionalno)", + "dfx_option_description": "Kupujte kripto s EUR i CHF. Do 990 € bez dodatnog KYC-a. Za maloprodajne i poslovne korisnike u Europi", "polygonscan_history": "Povijest PolygonScan", - "wallet_seed_legacy": "Sjeme naslijeđenog novčanika" -} \ No newline at end of file + "wallet_seed_legacy": "Sjeme naslijeđenog novčanika", + "switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)" +} diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 8dfe60db8..b45a45bfa 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -737,9 +737,9 @@ "seedtype_polyseed": "Polyseed (16 kata)", "seed_language_czech": "Ceko", "seed_language_korean": "Korea", - "seed_language_chinese_traditional": "Cina tradisional)", - "dfx_option_description": "Beli kripto dengan EUR & CHF. Hingga 990€ tanpa KYC tambahan. Untuk pelanggan ritel dan korporat di Eropa", "seed_language_chinese_traditional": "Cina (tradisional)", + "dfx_option_description": "Beli kripto dengan EUR & CHF. Hingga 990€ tanpa KYC tambahan. Untuk pelanggan ritel dan korporat di Eropa", "polygonscan_history": "Sejarah PolygonScan", - "wallet_seed_legacy": "Biji dompet warisan" -} \ No newline at end of file + "wallet_seed_legacy": "Biji dompet warisan", + "switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)" +} diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 8ea3e3e0c..770bbc9b6 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -752,5 +752,6 @@ "seed_language_chinese_traditional": "Cinese tradizionale)", "dfx_option_description": "Acquista criptovalute con EUR e CHF. Fino a 990€ senza KYC aggiuntivi. Per clienti al dettaglio e aziendali in Europa", "polygonscan_history": "Cronologia PolygonScan", - "wallet_seed_legacy": "Seme di portafoglio legacy" + "wallet_seed_legacy": "Seme di portafoglio legacy", + "switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index f940bf37f..35d4d3905 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -752,5 +752,6 @@ "seed_language_chinese_traditional": "中国の伝統的な)", "dfx_option_description": "EUR と CHF で暗号通貨を購入します。追加のKYCなしで最大990ユーロ。ヨーロッパの小売および法人顧客向け", "polygonscan_history": "ポリゴンスキャン履歴", - "wallet_seed_legacy": "レガシーウォレットシード" + "wallet_seed_legacy": "レガシーウォレットシード", + "switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 75d079a63..9224e49fd 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -750,5 +750,6 @@ "seed_language_chinese_traditional": "중국 전통)", "dfx_option_description": "EUR 및 CHF로 암호화폐를 구매하세요. 추가 KYC 없이 최대 990€. 유럽의 소매 및 기업 고객용", "polygonscan_history": "다각형 스캔 기록", - "wallet_seed_legacy": "레거시 지갑 시드" + "wallet_seed_legacy": "레거시 지갑 시드", + "switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index da26986c9..4c5441d2a 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -750,5 +750,6 @@ "seed_language_chinese_traditional": "တရုတ်ရိုးရာ)", "dfx_option_description": "EUR & CHF ဖြင့် crypto ကိုဝယ်ပါ။ အပို KYC မပါဘဲ 990€ အထိ။ ဥရောပရှိ လက်လီရောင်းချသူများနှင့် ကော်ပိုရိတ်ဖောက်သည်များအတွက်", "polygonscan_history": "PolygonScan မှတ်တမ်း", - "wallet_seed_legacy": "အမွေအနှစ်ပိုက်ဆံအိတ်မျိုးစေ့" + "wallet_seed_legacy": "အမွေအနှစ်ပိုက်ဆံအိတ်မျိုးစေ့", + "switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index c3573dee7..f22001ab9 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -749,9 +749,9 @@ "seedtype_polyseed": "Polyseed (16 woorden)", "seed_language_czech": "Tsjechisch", "seed_language_korean": "Koreaans", - "seed_language_chinese_traditional": "Chinese traditionele)", - "dfx_option_description": "Koop crypto met EUR & CHF. Tot 990€ zonder extra KYC. Voor particuliere en zakelijke klanten in Europa", "seed_language_chinese_traditional": "Chinese (traditionele)", + "dfx_option_description": "Koop crypto met EUR & CHF. Tot 990€ zonder extra KYC. Voor particuliere en zakelijke klanten in Europa", "polygonscan_history": "PolygonScan-geschiedenis", - "wallet_seed_legacy": "Legacy portemonnee zaad" -} \ No newline at end of file + "wallet_seed_legacy": "Legacy portemonnee zaad", + "switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)" +} diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index da60d8fe7..9f4fb37be 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -752,5 +752,6 @@ "seed_language_chinese_traditional": "Chiński tradycyjny)", "dfx_option_description": "Kupuj kryptowaluty za EUR i CHF. Do 990 € bez dodatkowego KYC. Dla klientów detalicznych i korporacyjnych w Europie", "polygonscan_history": "Historia PolygonScan", - "wallet_seed_legacy": "Dziedziczne ziarno portfela" + "wallet_seed_legacy": "Dziedziczne ziarno portfela", + "switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 08a2d05ee..e69a07024 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -751,5 +751,6 @@ "seed_language_chinese_traditional": "Chinês tradicional)", "dfx_option_description": "Compre criptografia com EUR e CHF. Até 990€ sem KYC adicional. Para clientes de varejo e corporativos na Europa", "polygonscan_history": "História do PolygonScan", - "wallet_seed_legacy": "Semente de carteira herdada" + "wallet_seed_legacy": "Semente de carteira herdada", + "switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index cad832ae0..75523482b 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -752,5 +752,6 @@ "seed_language_chinese_traditional": "Китайский традиционный)", "dfx_option_description": "Покупайте криптовалюту за EUR и CHF. До 990€ без дополнительного KYC. Для розничных и корпоративных клиентов в Европе", "polygonscan_history": "История PolygonScan", - "wallet_seed_legacy": "Наследие семя кошелька" + "wallet_seed_legacy": "Наследие семя кошелька", + "switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon)." } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index ee84b011f..e682cc4a1 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -750,5 +750,6 @@ "seed_language_chinese_traditional": "จีน (ดั้งเดิม)", "dfx_option_description": "ซื้อ crypto ด้วย EUR และ CHF สูงถึง 990€ โดยไม่มี KYC เพิ่มเติม สำหรับลูกค้ารายย่อยและลูกค้าองค์กรในยุโรป", "polygonscan_history": "ประวัติ PolygonScan", - "wallet_seed_legacy": "เมล็ดกระเป๋าเงินมรดก" + "wallet_seed_legacy": "เมล็ดกระเป๋าเงินมรดก", + "switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 1fd59d29a..8a1a50a0a 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -746,5 +746,6 @@ "seed_language_chinese_traditional": "Intsik (tradisyonal)", "dfx_option_description": "Bumili ng crypto gamit ang EUR at CHF. Hanggang 990€ nang walang karagdagang KYC. Para sa retail at corporate na mga customer sa Europe", "polygonscan_history": "Kasaysayan ng PolygonScan", - "wallet_seed_legacy": "Legacy wallet seed" + "wallet_seed_legacy": "Legacy wallet seed", + "switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 687f741f2..88399e713 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -750,5 +750,6 @@ "seed_language_chinese_traditional": "Çin geleneği)", "dfx_option_description": "EUR ve CHF ile kripto satın alın. Ek KYC olmadan 990 €'ya kadar. Avrupa'daki perakende ve kurumsal müşteriler için", "polygonscan_history": "PolygonScan geçmişi", - "wallet_seed_legacy": "Eski cüzdan tohumu" + "wallet_seed_legacy": "Eski cüzdan tohumu", + "switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index ee4af583e..d291e00a2 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -752,5 +752,6 @@ "dfx_option_description": "Купуйте криптовалюту за EUR і CHF. До 990 євро без додаткового KYC. Для роздрібних і корпоративних клієнтів у Європі", "seed_language_chinese_traditional": "Китайський (традиційний)", "polygonscan_history": "Історія PolygonScan", - "wallet_seed_legacy": "Спадець насіння гаманця" -} \ No newline at end of file + "wallet_seed_legacy": "Спадець насіння гаманця", + "switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)" +} diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index d50cd62c6..cae2abd69 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -744,5 +744,6 @@ "seed_language_chinese_traditional": "چینی (روایتی)", "dfx_option_description": "EUR ﺭﻭﺍ CHF ﯽﻓﺎﺿﺍ ۔ﮟﯾﺪﯾﺮﺧ ﻮﭩﭘﺮﮐ ﮫﺗﺎﺳ ﮯﮐ KYC ﮯﯿﻟ ﮯﮐ ﻦﯿﻓﺭﺎﺻ ﭧﯾﺭﻮﭘﺭﺎﮐ ﺭﻭﺍ ﮦﺩﺭﻮﺧ ﮟ", "polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ", - "wallet_seed_legacy": "میراثی پرس کا بیج" + "wallet_seed_legacy": "میراثی پرس کا بیج", + "switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ " } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 538f2d4a9..e42f1d58d 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -746,5 +746,6 @@ "seed_language_chinese_traditional": "Kannada (ibile)", "dfx_option_description": "Ra crypto pẹlu EUR & CHF. Titi di 990 € laisi afikun KYC. Fun soobu ati awọn onibara ile-iṣẹ ni Yuroopu", "polygonscan_history": "PolygonScan itan", - "wallet_seed_legacy": "Irugbin akole" + "wallet_seed_legacy": "Irugbin akole", + "switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index ee6e9efd9..493498e98 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -751,5 +751,6 @@ "seed_language_chinese_traditional": "中国传统的)", "dfx_option_description": "用欧元和瑞士法郎购买加密货币。高达 990 欧元,无需额外 KYC。对于欧洲的零售和企业客户", "polygonscan_history": "多边形扫描历史", - "wallet_seed_legacy": "旧的钱包种子" + "wallet_seed_legacy": "旧的钱包种子", + "switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)" } diff --git a/scripts/android/pubspec_gen.sh b/scripts/android/pubspec_gen.sh index dd9852072..4b89c4afa 100755 --- a/scripts/android/pubspec_gen.sh +++ b/scripts/android/pubspec_gen.sh @@ -10,7 +10,7 @@ case $APP_ANDROID_TYPE in CONFIG_ARGS="--monero" ;; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --haven --ethereum --nano --bitcoinCash" + CONFIG_ARGS="--monero --bitcoin --haven --ethereum --polygon --nano --bitcoinCash" ;; $HAVEN) CONFIG_ARGS="--haven" diff --git a/scripts/ios/app_config.sh b/scripts/ios/app_config.sh index 8d999f594..81752a015 100755 --- a/scripts/ios/app_config.sh +++ b/scripts/ios/app_config.sh @@ -28,7 +28,7 @@ case $APP_IOS_TYPE in CONFIG_ARGS="--monero" ;; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --haven --ethereum --nano --bitcoinCash" + CONFIG_ARGS="--monero --bitcoin --haven --ethereum --polygon --nano --bitcoinCash" ;; $HAVEN) diff --git a/scripts/macos/app_config.sh b/scripts/macos/app_config.sh index 48b680330..2e6a945bf 100755 --- a/scripts/macos/app_config.sh +++ b/scripts/macos/app_config.sh @@ -23,7 +23,7 @@ CONFIG_ARGS="" case $APP_MACOS_TYPE in $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --ethereum --nano --bitcoinCash";; #--haven + CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash";; #--haven esac cp -rf pubspec_description.yaml pubspec.yaml From faf151a4dc5213a395da8c63606ae07538f9d0a2 Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 13 Dec 2023 16:43:26 +0200 Subject: [PATCH 070/241] CW-531-Bitcoin-Fees-issue (#1218) * SegWit transaction size * [skip ci] fix electrum balances layout * fix tapping area --- cw_bitcoin/lib/electrum_balance.dart | 18 ++++++++++++------ cw_bitcoin/lib/electrum_wallet.dart | 2 +- lib/src/screens/contact/contact_list_page.dart | 1 + .../widgets/home_screen_account_widget.dart | 1 + 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/cw_bitcoin/lib/electrum_balance.dart b/cw_bitcoin/lib/electrum_balance.dart index 0a9a33d54..a4824db0f 100644 --- a/cw_bitcoin/lib/electrum_balance.dart +++ b/cw_bitcoin/lib/electrum_balance.dart @@ -4,7 +4,10 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_core/balance.dart'; class ElectrumBalance extends Balance { - const ElectrumBalance({required this.confirmed, required this.unconfirmed, required this.frozen}) + const ElectrumBalance( + {required this.confirmed, + required this.unconfirmed, + required this.frozen}) : super(confirmed, unconfirmed); static ElectrumBalance? fromJSON(String? jsonSource) { @@ -25,16 +28,19 @@ class ElectrumBalance extends Balance { final int frozen; @override - String get formattedAvailableBalance => bitcoinAmountToString(amount: confirmed - frozen); + String get formattedAvailableBalance => + bitcoinAmountToString(amount: confirmed - unconfirmed.abs() - frozen); @override - String get formattedAdditionalBalance => bitcoinAmountToString(amount: unconfirmed); + String get formattedAdditionalBalance => + bitcoinAmountToString(amount: unconfirmed); - String get formattedFrozenBalance { + @override + String get formattedUnAvailableBalance { final frozenFormatted = bitcoinAmountToString(amount: frozen); return frozenFormatted == '0.0' ? '' : frozenFormatted; } - String toJSON() => - json.encode({'confirmed': confirmed, 'unconfirmed': unconfirmed, 'frozen': frozen}); + String toJSON() => json.encode( + {'confirmed': confirmed, 'unconfirmed': unconfirmed, 'frozen': frozen}); } diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 894a969a0..4c5ecc7f2 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -82,7 +82,7 @@ abstract class ElectrumWalletBase bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/0"); static int estimatedTransactionSize(int inputsCount, int outputsCounts) => - inputsCount * 146 + outputsCounts * 33 + 8; + inputsCount * 68 + outputsCounts * 34 + 10; final bitcoin.HDWallet hd; final String mnemonic; diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index d9e3c0c85..99f2aa251 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -135,6 +135,7 @@ class ContactListPage extends BasePage { await showBar(context, S.of(context).copied_to_clipboard); } }, + behavior: HitTestBehavior.opaque, child: Container( padding: const EdgeInsets.only(top: 16, bottom: 16, right: 24), child: Row( diff --git a/lib/src/screens/dashboard/widgets/home_screen_account_widget.dart b/lib/src/screens/dashboard/widgets/home_screen_account_widget.dart index f548a8737..fa036978f 100644 --- a/lib/src/screens/dashboard/widgets/home_screen_account_widget.dart +++ b/lib/src/screens/dashboard/widgets/home_screen_account_widget.dart @@ -18,6 +18,7 @@ class HomeScreenAccountWidget extends StatelessWidget { context: context, builder: (_) => getIt.get()); }, + behavior: HitTestBehavior.opaque, child: Container( height: 100.0, child: Row( From 049e4def274132fe2e902a7c7d6d36e5e776a63c Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 13 Dec 2023 17:27:30 +0200 Subject: [PATCH 071/241] fix accessibility issues (#1224) --- .../settings/display_settings_page.dart | 2 +- .../widgets/settings_theme_choice.dart | 100 +++++++++--------- lib/src/widgets/standard_switch.dart | 40 +++---- 3 files changed, 75 insertions(+), 67 deletions(-) diff --git a/lib/src/screens/settings/display_settings_page.dart b/lib/src/screens/settings/display_settings_page.dart index 505573f80..ba59df3af 100644 --- a/lib/src/screens/settings/display_settings_page.dart +++ b/lib/src/screens/settings/display_settings_page.dart @@ -76,7 +76,7 @@ class DisplaySettingsPage extends BasePage { }, ), if (responsiveLayoutUtil.shouldRenderMobileUI && DeviceInfo.instance.isMobile) - SettingsThemeChoicesCell(_displaySettingsViewModel), + Semantics(label: S.current.color_theme, child: SettingsThemeChoicesCell(_displaySettingsViewModel)), ], ), ); diff --git a/lib/src/screens/settings/widgets/settings_theme_choice.dart b/lib/src/screens/settings/widgets/settings_theme_choice.dart index ffb9d7e7e..abe9a4eab 100644 --- a/lib/src/screens/settings/widgets/settings_theme_choice.dart +++ b/lib/src/screens/settings/widgets/settings_theme_choice.dart @@ -54,57 +54,61 @@ class SettingsThemeChoicesCell extends StatelessWidget { return Padding( padding: EdgeInsets.all(5), - child: GestureDetector( - onTap: () { - _displaySettingsViewModel.setTheme(e); - }, - child: Container( - padding: EdgeInsets.all(5), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(cellRadius), - border: isSelected - ? Border.all( - color: Theme.of(context).primaryColor) - : null, - color: Theme.of(context) - .extension()! - .secondaryTextColor - .withOpacity( - currentTheme.brightness == Brightness.light - ? 0.1 - : 0.3), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - padding: EdgeInsets.symmetric( - horizontal: cellWidth, vertical: cellHeight), - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(cellRadius), - bottomLeft: Radius.circular(cellRadius)), - color: e.themeData.primaryColor, + child: Semantics( + label: e.toString(), + selected: isSelected, + child: GestureDetector( + onTap: () { + _displaySettingsViewModel.setTheme(e); + }, + child: Container( + padding: EdgeInsets.all(5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(cellRadius), + border: isSelected + ? Border.all( + color: Theme.of(context).primaryColor) + : null, + color: Theme.of(context) + .extension()! + .secondaryTextColor + .withOpacity( + currentTheme.brightness == Brightness.light + ? 0.1 + : 0.3), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.symmetric( + horizontal: cellWidth, vertical: cellHeight), + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(cellRadius), + bottomLeft: Radius.circular(cellRadius)), + color: e.themeData.primaryColor, + ), ), - ), - Container( - padding: EdgeInsets.symmetric( - horizontal: cellWidth, vertical: cellHeight), - decoration: BoxDecoration( - color: e.themeData.colorScheme.background, + Container( + padding: EdgeInsets.symmetric( + horizontal: cellWidth, vertical: cellHeight), + decoration: BoxDecoration( + color: e.themeData.colorScheme.background, + ), ), - ), - Container( - padding: EdgeInsets.symmetric( - horizontal: cellWidth, vertical: cellHeight), - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - topRight: Radius.circular(cellRadius), - bottomRight: Radius.circular(cellRadius)), - color: e.themeData.cardColor, + Container( + padding: EdgeInsets.symmetric( + horizontal: cellWidth, vertical: cellHeight), + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topRight: Radius.circular(cellRadius), + bottomRight: Radius.circular(cellRadius)), + color: e.themeData.cardColor, + ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/src/widgets/standard_switch.dart b/lib/src/widgets/standard_switch.dart index 064faea48..b80d487fe 100644 --- a/lib/src/widgets/standard_switch.dart +++ b/lib/src/widgets/standard_switch.dart @@ -14,25 +14,29 @@ class StandardSwitch extends StatefulWidget { class StandardSwitchState extends State { @override Widget build(BuildContext context) { - return GestureDetector( - onTap: widget.onTaped, - child: AnimatedContainer( - padding: EdgeInsets.only(left: 2.0, right: 2.0), - alignment: widget.value ? Alignment.centerRight : Alignment.centerLeft, - duration: Duration(milliseconds: 250), - width: 50, - height: 28, - decoration: BoxDecoration( - color: widget.value - ? Theme.of(context).primaryColor - : Theme.of(context).disabledColor, - borderRadius: BorderRadius.all(Radius.circular(14.0))), - child: Container( - width: 24.0, - height: 24.0, + + return Semantics( + toggled: widget.value, + child: GestureDetector( + onTap: widget.onTaped, + child: AnimatedContainer( + padding: EdgeInsets.only(left: 2.0, right: 2.0), + alignment: widget.value ? Alignment.centerRight : Alignment.centerLeft, + duration: Duration(milliseconds: 250), + width: 50, + height: 28, decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle), + color: widget.value + ? Theme.of(context).primaryColor + : Theme.of(context).disabledColor, + borderRadius: BorderRadius.all(Radius.circular(14.0))), + child: Container( + width: 24.0, + height: 24.0, + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle), + ), ), ), ); From 1c53229ea0cdc9196263e620140cd14af35cf512 Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 13 Dec 2023 17:33:51 +0200 Subject: [PATCH 072/241] minor fix --- lib/view_model/advanced_privacy_settings_view_model.dart | 4 ++++ lib/view_model/wallet_new_vm.dart | 3 +++ 2 files changed, 7 insertions(+) diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart index 483f0837b..75d7a9eb4 100644 --- a/lib/view_model/advanced_privacy_settings_view_model.dart +++ b/lib/view_model/advanced_privacy_settings_view_model.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/seed_phrase_length.dart'; +import 'package:cake_wallet/entities/seed_type.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; @@ -37,6 +38,9 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { @computed SeedPhraseLength get seedPhraseLength => _settingsStore.seedPhraseLength; + @computed + bool get isPolySeed => _settingsStore.moneroSeedType == SeedType.polyseed; + @action void setFiatApiMode(FiatApiMode fiatApiMode) => _settingsStore.fiatApiMode = fiatApiMode; diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart index 0a80a279e..d4a0c4c00 100644 --- a/lib/view_model/wallet_new_vm.dart +++ b/lib/view_model/wallet_new_vm.dart @@ -38,6 +38,9 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { int get seedPhraseWordsLength { switch (type) { case WalletType.monero: + if(advancedPrivacySettingsViewModel.isPolySeed) { + return 16; + } return 25; case WalletType.ethereum: case WalletType.bitcoinCash: From 2ff81df9e790ba29e043ec3ab4ccfbd4c163dd72 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Wed, 13 Dec 2023 13:58:43 -0800 Subject: [PATCH 073/241] CW-512 wallet sort (#1195) * add shared preferences key and make list re-orderable * macos sonoma build fix * everything (almost) works * add translations * more translations * everything works * fixes * translation merge file fix * fix for mobile platforms * fix filter icon being invisible on bright theme * first pass of adding ascending/descending to filter widget * small fix * update ascending switch * fixes * fix * reverse creation sort * review fixes part 1 * refactor into function rather than tuple + color changes * more fixes * remove unrelated file * updated wording * cleaner callback * undo sonoma fix --------- Co-authored-by: fossephate Co-authored-by: Omar Hatem --- lib/entities/list_order_mode.dart | 34 ++++ lib/entities/preferences_key.dart | 2 + lib/entities/wallet_list_order_types.dart | 22 +++ .../dashboard/widgets/filter_list_widget.dart | 158 ++++++++++++++++++ .../widgets/settings_choices_cell.dart | 30 ++-- .../screens/wallet_list/filtered_list.dart | 39 +++++ .../screens/wallet_list/wallet_list_page.dart | 69 +++++++- lib/src/widgets/picker_wrapper_widget.dart | 5 +- lib/store/settings_store.dart | 34 +++- lib/themes/bright_theme.dart | 2 +- .../wallet_list/wallet_list_view_model.dart | 105 +++++++++++- res/values/strings_ar.arb | 6 + res/values/strings_bg.arb | 6 + res/values/strings_cs.arb | 6 + res/values/strings_de.arb | 6 + res/values/strings_en.arb | 8 +- res/values/strings_es.arb | 6 + res/values/strings_fr.arb | 8 +- res/values/strings_ha.arb | 6 + res/values/strings_hi.arb | 6 + res/values/strings_hr.arb | 6 + res/values/strings_id.arb | 6 + res/values/strings_it.arb | 6 + res/values/strings_ja.arb | 6 + res/values/strings_ko.arb | 6 + res/values/strings_my.arb | 6 + res/values/strings_nl.arb | 6 + res/values/strings_pl.arb | 6 + res/values/strings_pt.arb | 6 + res/values/strings_ru.arb | 6 + res/values/strings_th.arb | 6 + res/values/strings_tl.arb | 6 + res/values/strings_tr.arb | 6 + res/values/strings_uk.arb | 6 + res/values/strings_ur.arb | 6 + res/values/strings_yo.arb | 6 + res/values/strings_zh.arb | 6 + 37 files changed, 624 insertions(+), 36 deletions(-) create mode 100644 lib/entities/list_order_mode.dart create mode 100644 lib/entities/wallet_list_order_types.dart create mode 100644 lib/src/screens/dashboard/widgets/filter_list_widget.dart create mode 100644 lib/src/screens/wallet_list/filtered_list.dart diff --git a/lib/entities/list_order_mode.dart b/lib/entities/list_order_mode.dart new file mode 100644 index 000000000..b9eae6820 --- /dev/null +++ b/lib/entities/list_order_mode.dart @@ -0,0 +1,34 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cw_core/enumerable_item.dart'; + +class ListOrderMode extends EnumerableItem with Serializable { + const ListOrderMode({required String title, required int raw}) : super(title: title, raw: raw); + + static const all = [ListOrderMode.ascending, ListOrderMode.descending]; + + static const ascending = ListOrderMode(raw: 0, title: 'Ascending'); + static const descending = ListOrderMode(raw: 1, title: 'Descending'); + + static ListOrderMode deserialize({required int raw}) { + switch (raw) { + case 0: + return ascending; + case 1: + return descending; + default: + throw Exception('Unexpected token: $raw for ListOrderMode deserialize'); + } + } + + @override + String toString() { + switch (this) { + case ListOrderMode.ascending: + return S.current.ascending; + case ListOrderMode.descending: + return S.current.descending; + default: + return ''; + } + } +} diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 67f1aca97..2d5e64817 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -20,6 +20,8 @@ class PreferencesKey { static const disableBuyKey = 'disable_buy'; static const disableSellKey = 'disable_sell'; static const defaultBuyProvider = 'default_buy_provider'; + static const walletListOrder = 'wallet_list_order'; + static const walletListAscending = 'wallet_list_ascending'; static const currentFiatApiModeKey = 'current_fiat_api_mode'; static const allowBiometricalAuthenticationKey = 'allow_biometrical_authentication'; static const useTOTP2FA = 'use_totp_2fa'; diff --git a/lib/entities/wallet_list_order_types.dart b/lib/entities/wallet_list_order_types.dart new file mode 100644 index 000000000..f848170f4 --- /dev/null +++ b/lib/entities/wallet_list_order_types.dart @@ -0,0 +1,22 @@ +import 'package:cake_wallet/generated/i18n.dart'; + +enum WalletListOrderType { + CreationDate, + Alphabetical, + GroupByType, + Custom; + + @override + String toString() { + switch (this) { + case WalletListOrderType.CreationDate: + return S.current.creation_date; + case WalletListOrderType.Alphabetical: + return S.current.alphabetical; + case WalletListOrderType.GroupByType: + return S.current.group_by_type; + case WalletListOrderType.Custom: + return S.current.custom_drag; + } + } +} diff --git a/lib/src/screens/dashboard/widgets/filter_list_widget.dart b/lib/src/screens/dashboard/widgets/filter_list_widget.dart new file mode 100644 index 000000000..cda4f5f10 --- /dev/null +++ b/lib/src/screens/dashboard/widgets/filter_list_widget.dart @@ -0,0 +1,158 @@ +import 'package:cake_wallet/entities/list_order_mode.dart'; +import 'package:cake_wallet/entities/wallet_list_order_types.dart'; +import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/src/widgets/section_divider.dart'; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; +import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; +import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:cake_wallet/src/widgets/picker_wrapper_widget.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; + +class FilterListWidget extends StatefulWidget { + FilterListWidget({ + required this.initalType, + required this.initalAscending, + required this.onClose, + }); + + final WalletListOrderType? initalType; + final bool initalAscending; + final Function(bool, WalletListOrderType) onClose; + + @override + FilterListWidgetState createState() => FilterListWidgetState(); +} + +class FilterListWidgetState extends State { + late bool ascending; + late WalletListOrderType? type; + + @override + void initState() { + super.initState(); + ascending = widget.initalAscending; + type = widget.initalType; + } + + void setSelectedOrderType(WalletListOrderType? orderType) { + setState(() { + type = orderType; + }); + } + + @override + Widget build(BuildContext context) { + const sectionDivider = const HorizontalSectionDivider(); + return PickerWrapperWidget( + onClose: () { + widget.onClose(ascending, type!); + Navigator.of(context).pop(); + }, + children: [ + Padding( + padding: EdgeInsets.only(left: 24, right: 24, top: 24), + child: ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(24)), + child: Container( + color: Theme.of(context).extension()!.backgroundColor, + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Padding( + padding: EdgeInsets.all(24.0), + child: Text( + S.of(context).order_by, + style: TextStyle( + color: + Theme.of(context).extension()!.detailsTitlesColor, + fontSize: 16, + fontFamily: 'Lato', + decoration: TextDecoration.none, + ), + ), + ), + if (type != WalletListOrderType.Custom) ...[ + sectionDivider, + SettingsChoicesCell( + ChoicesListItem( + title: "", + items: ListOrderMode.all, + selectedItem: ascending ? ListOrderMode.ascending : ListOrderMode.descending, + onItemSelected: (ListOrderMode listOrderMode) { + setState(() { + ascending = listOrderMode == ListOrderMode.ascending; + }); + }, + ), + ), + ], + sectionDivider, + RadioListTile( + value: WalletListOrderType.CreationDate, + groupValue: type, + title: Text( + WalletListOrderType.CreationDate.toString(), + style: TextStyle( + color: Theme.of(context).extension()!.titleColor, + fontSize: 16, + fontFamily: 'Lato', + fontWeight: FontWeight.bold, + decoration: TextDecoration.none), + ), + onChanged: setSelectedOrderType, + activeColor: Theme.of(context).primaryColor, + ), + RadioListTile( + value: WalletListOrderType.Alphabetical, + groupValue: type, + title: Text( + WalletListOrderType.Alphabetical.toString(), + style: TextStyle( + color: Theme.of(context).extension()!.titleColor, + fontSize: 16, + fontFamily: 'Lato', + fontWeight: FontWeight.bold, + decoration: TextDecoration.none), + ), + onChanged: setSelectedOrderType, + activeColor: Theme.of(context).primaryColor, + ), + RadioListTile( + value: WalletListOrderType.GroupByType, + groupValue: type, + title: Text( + WalletListOrderType.GroupByType.toString(), + style: TextStyle( + color: Theme.of(context).extension()!.titleColor, + fontSize: 16, + fontFamily: 'Lato', + fontWeight: FontWeight.bold, + decoration: TextDecoration.none), + ), + onChanged: setSelectedOrderType, + activeColor: Theme.of(context).primaryColor, + ), + RadioListTile( + value: WalletListOrderType.Custom, + groupValue: type, + title: Text( + WalletListOrderType.Custom.toString(), + style: TextStyle( + color: Theme.of(context).extension()!.titleColor, + fontSize: 16, + fontFamily: 'Lato', + fontWeight: FontWeight.bold, + decoration: TextDecoration.none), + ), + onChanged: setSelectedOrderType, + activeColor: Theme.of(context).primaryColor, + ), + ]), + ), + ), + ) + ], + ); + } +} diff --git a/lib/src/screens/settings/widgets/settings_choices_cell.dart b/lib/src/screens/settings/widgets/settings_choices_cell.dart index 79f74699d..63ad1ef9a 100644 --- a/lib/src/screens/settings/widgets/settings_choices_cell.dart +++ b/lib/src/screens/settings/widgets/settings_choices_cell.dart @@ -17,19 +17,21 @@ class SettingsChoicesCell extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - children: [ - Text( - choicesListItem.title, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.normal, - color: Theme.of(context).extension()!.titleColor, + if (choicesListItem.title.isNotEmpty) ...[ + Row( + children: [ + Text( + choicesListItem.title, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + color: Theme.of(context).extension()!.titleColor, + ), ), - ), - ], - ), - const SizedBox(height: 24), + ], + ), + const SizedBox(height: 24), + ], Center( child: Container( decoration: BoxDecoration( @@ -49,9 +51,7 @@ class SettingsChoicesCell extends StatelessWidget { padding: EdgeInsets.symmetric(vertical: 8), decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), - color: isSelected - ? Theme.of(context).primaryColor - : null, + color: isSelected ? Theme.of(context).primaryColor : null, ), child: Center( child: Text( diff --git a/lib/src/screens/wallet_list/filtered_list.dart b/lib/src/screens/wallet_list/filtered_list.dart new file mode 100644 index 000000000..7149833a8 --- /dev/null +++ b/lib/src/screens/wallet_list/filtered_list.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:mobx/mobx.dart'; + +class FilteredList extends StatefulWidget { + FilteredList({ + required this.list, + required this.itemBuilder, + required this.updateFunction, + }); + + final ObservableList list; + final Widget Function(BuildContext, int) itemBuilder; + final Function updateFunction; + + @override + FilteredListState createState() => FilteredListState(); +} + +class FilteredListState extends State { + @override + Widget build(BuildContext context) { + return Observer( + builder: (_) => ReorderableListView.builder( + physics: const BouncingScrollPhysics(), + itemBuilder: widget.itemBuilder, + itemCount: widget.list.length, + onReorder: (int oldIndex, int newIndex) { + if (oldIndex < newIndex) { + newIndex -= 1; + } + final dynamic item = widget.list.removeAt(oldIndex); + widget.list.insert(newIndex, item); + widget.updateFunction(); + }, + ), + ); + } +} diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index 53a9b3eca..8dcd23d29 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -1,8 +1,15 @@ +import 'package:cake_wallet/entities/wallet_list_order_types.dart'; +import 'package:cake_wallet/src/screens/dashboard/widgets/filter_list_widget.dart'; +import 'package:cake_wallet/src/screens/dashboard/widgets/filter_widget.dart'; +import 'package:cake_wallet/src/screens/wallet_list/filtered_list.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/core/auth_service.dart'; +import 'package:cake_wallet/themes/extensions/filter_theme.dart'; import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; +import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_bar.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart'; import 'package:another_flushbar/flushbar.dart'; import 'package:flutter/material.dart'; @@ -28,6 +35,53 @@ class WalletListPage extends BasePage { @override Widget body(BuildContext context) => WalletListBody(walletListViewModel: walletListViewModel, authService: authService); + + @override + Widget trailing(BuildContext context) { + final filterIcon = Image.asset('assets/images/filter_icon.png', + color: Theme.of(context).extension()!.iconColor); + return MergeSemantics( + child: SizedBox( + height: 37, + width: 37, + child: ButtonTheme( + minWidth: double.minPositive, + child: Semantics( + container: true, + child: GestureDetector( + onTap: () async { + await showPopUp( + context: context, + builder: (context) => FilterListWidget( + initalType: walletListViewModel.orderType, + initalAscending: walletListViewModel.ascending, + onClose: (bool ascending, WalletListOrderType type) async { + walletListViewModel.setAscending(ascending); + await walletListViewModel.setOrderType(type); + }, + ), + ); + }, + child: Semantics( + label: 'Transaction Filter', + button: true, + enabled: true, + child: Container( + height: 36, + width: 36, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Theme.of(context).extension()!.buttonColor, + ), + child: filterIcon, + ), + ), + ), + ), + ), + ), + ); + } } class WalletListBody extends StatefulWidget { @@ -70,11 +124,9 @@ class WalletListBodyState extends State { Expanded( child: Container( child: Observer( - builder: (_) => ListView.separated( - physics: const BouncingScrollPhysics(), - separatorBuilder: (_, index) => - Divider(color: Theme.of(context).colorScheme.background, height: 32), - itemCount: widget.walletListViewModel.wallets.length, + builder: (_) => FilteredList( + list: widget.walletListViewModel.wallets, + updateFunction: widget.walletListViewModel.reorderAccordingToWalletList, itemBuilder: (__, index) { final wallet = widget.walletListViewModel.wallets[index]; final currentColor = wallet.isCurrent @@ -83,6 +135,7 @@ class WalletListBodyState extends State { .createNewWalletButtonBackgroundColor : Theme.of(context).colorScheme.background; final row = GestureDetector( + key: ValueKey(wallet.name), onTap: () => wallet.isCurrent ? null : _loadWallet(wallet), child: Container( height: tileHeight, @@ -117,7 +170,7 @@ class WalletListBodyState extends State { maxLines: null, softWrap: true, style: TextStyle( - fontSize: 22, + fontSize: 20, fontWeight: FontWeight.w500, color: Theme.of(context) .extension()! @@ -137,13 +190,15 @@ class WalletListBodyState extends State { return wallet.isCurrent ? row : Row( + key: ValueKey(wallet.name), children: [ Expanded(child: row), GestureDetector( onTap: () => Navigator.of(context).pushNamed(Routes.walletEdit, arguments: [widget.walletListViewModel, wallet]), child: Container( - padding: EdgeInsets.only(right: 20), + padding: EdgeInsets.only( + right: DeviceInfo.instance.isMobile ? 20 : 40), child: Center( child: Container( height: 40, diff --git a/lib/src/widgets/picker_wrapper_widget.dart b/lib/src/widgets/picker_wrapper_widget.dart index f69bcd514..f4e52c5cd 100644 --- a/lib/src/widgets/picker_wrapper_widget.dart +++ b/lib/src/widgets/picker_wrapper_widget.dart @@ -4,10 +4,11 @@ import 'package:cake_wallet/src/widgets/alert_background.dart'; import 'package:cake_wallet/src/widgets/alert_close_button.dart'; class PickerWrapperWidget extends StatelessWidget { - PickerWrapperWidget({required this.children, this.hasTitle = false}); + PickerWrapperWidget({required this.children, this.hasTitle = false, this.onClose}); final List children; final bool hasTitle; + final Function()? onClose; @override Widget build(BuildContext context) { @@ -45,7 +46,7 @@ class PickerWrapperWidget extends StatelessWidget { children: children, ), SizedBox(height: ResponsiveLayoutUtilBase.kPopupSpaceHeight), - AlertCloseButton(bottom: closeButtonBottom), + AlertCloseButton(bottom: closeButtonBottom, onTap: onClose), ], ), ), diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 4078827d0..95254e557 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -12,6 +12,7 @@ import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/seed_phrase_length.dart'; import 'package:cake_wallet/entities/seed_type.dart'; import 'package:cake_wallet/entities/sort_balance_types.dart'; +import 'package:cake_wallet/entities/wallet_list_order_types.dart'; import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; import 'package:cake_wallet/view_model/settings/sync_mode.dart'; @@ -53,7 +54,8 @@ abstract class SettingsStoreBase with Store { required bool initialAppSecure, required bool initialDisableBuy, required bool initialDisableSell, - required BuyProviderType initialDefaultBuyProvider, + required WalletListOrderType initialWalletListOrder, + required bool initialWalletListAscending, required FiatApiMode initialFiatMode, required bool initialAllowBiometricalAuthentication, required String initialTotpSecretKey, @@ -122,6 +124,8 @@ abstract class SettingsStoreBase with Store { isAppSecure = initialAppSecure, disableBuy = initialDisableBuy, disableSell = initialDisableSell, + walletListOrder = initialWalletListOrder, + walletListAscending = initialWalletListAscending, shouldShowMarketPlaceInDashboard = initialShouldShowMarketPlaceInDashboard, exchangeStatus = initialExchangeStatus, currentTheme = initialTheme, @@ -257,6 +261,16 @@ abstract class SettingsStoreBase with Store { } ); + reaction( + (_) => walletListOrder, + (WalletListOrderType walletListOrder) => + sharedPreferences.setInt(PreferencesKey.walletListOrder, walletListOrder.index)); + + reaction( + (_) => walletListAscending, + (bool walletListAscending) => + sharedPreferences.setBool(PreferencesKey.walletListAscending, walletListAscending)); + reaction( (_) => autoGenerateSubaddressStatus, (AutoGenerateSubaddressStatus autoGenerateSubaddressStatus) => sharedPreferences.setInt( @@ -504,6 +518,12 @@ abstract class SettingsStoreBase with Store { @observable bool disableSell; + @observable + WalletListOrderType walletListOrder; + + @observable + bool walletListAscending; + @observable bool allowBiometricalAuthentication; @@ -717,8 +737,10 @@ abstract class SettingsStoreBase with Store { final isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? false; final disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? false; final disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? false; - final defaultBuyProvider = - BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0]; + final walletListOrder = + WalletListOrderType.values[sharedPreferences.getInt(PreferencesKey.walletListOrder) ?? 0]; + final walletListAscending = + sharedPreferences.getBool(PreferencesKey.walletListAscending) ?? true; final currentFiatApiMode = FiatApiMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey) ?? FiatApiMode.enabled.raw); @@ -897,7 +919,8 @@ abstract class SettingsStoreBase with Store { initialAppSecure: isAppSecure, initialDisableBuy: disableBuy, initialDisableSell: disableSell, - initialDefaultBuyProvider: defaultBuyProvider, + initialWalletListOrder: walletListOrder, + initialWalletListAscending: walletListAscending, initialFiatMode: currentFiatApiMode, initialAllowBiometricalAuthentication: allowBiometricalAuthentication, initialCake2FAPresetOptions: selectedCake2FAPreset, @@ -1013,6 +1036,9 @@ abstract class SettingsStoreBase with Store { isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? isAppSecure; disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? disableBuy; disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? disableSell; + walletListOrder = + WalletListOrderType.values[sharedPreferences.getInt(PreferencesKey.walletListOrder) ?? 0]; + walletListAscending = sharedPreferences.getBool(PreferencesKey.walletListAscending) ?? true; allowBiometricalAuthentication = sharedPreferences.getBool(PreferencesKey.allowBiometricalAuthenticationKey) ?? allowBiometricalAuthentication; diff --git a/lib/themes/bright_theme.dart b/lib/themes/bright_theme.dart index 0ea2bb6f2..42510a389 100644 --- a/lib/themes/bright_theme.dart +++ b/lib/themes/bright_theme.dart @@ -78,7 +78,7 @@ class BrightTheme extends LightTheme { FilterTheme get filterTheme => super.filterTheme.copyWith( checkboxSecondGradientColor: Palette.pinkFlamingo, checkboxBackgroundColor: Colors.white, - buttonColor: Colors.white.withOpacity(0.2), + buttonColor: Palette.darkGray.withOpacity(0.2), iconColor: Colors.white); @override 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 0abebba15..3df6491bb 100644 --- a/lib/view_model/wallet_list/wallet_list_view_model.dart +++ b/lib/view_model/wallet_list/wallet_list_view_model.dart @@ -1,5 +1,6 @@ import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/core/wallet_loading_service.dart'; +import 'package:cake_wallet/entities/wallet_list_order_types.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/store/app_store.dart'; @@ -19,7 +20,7 @@ abstract class WalletListViewModelBase with Store { this._walletLoadingService, this._authService, ) : wallets = ObservableList() { - updateList(); + setOrderType(_appStore.settingsStore.walletListOrder); reaction((_) => _appStore.wallet, (_) => updateList()); } @@ -43,11 +44,14 @@ abstract class WalletListViewModelBase with Store { @action Future loadWallet(WalletListItem walletItem) async { - final wallet = - await _walletLoadingService.load(walletItem.type, walletItem.name); + final wallet = await _walletLoadingService.load(walletItem.type, walletItem.name); _appStore.changeCurrentWallet(wallet); } + WalletListOrderType? get orderType => _appStore.settingsStore.walletListOrder; + + bool get ascending => _appStore.settingsStore.walletListAscending; + @action void updateList() { wallets.clear(); @@ -57,14 +61,105 @@ abstract class WalletListViewModelBase with Store { name: info.name, type: info.type, key: info.key, - isCurrent: info.name == _appStore.wallet?.name && - info.type == _appStore.wallet?.type, + isCurrent: info.name == _appStore.wallet?.name && info.type == _appStore.wallet?.type, isEnabled: availableWalletTypes.contains(info.type), ), ), ); } + Future reorderAccordingToWalletList() async { + if (wallets.isEmpty) { + updateList(); + return; + } + + _appStore.settingsStore.walletListOrder = WalletListOrderType.Custom; + + // make a copy of the walletInfoSource: + List walletInfoSourceCopy = _walletInfoSource.values.toList(); + // delete all wallets from walletInfoSource: + await _walletInfoSource.clear(); + + // add wallets from wallets list in order of wallets list, by name: + for (WalletListItem wallet in wallets) { + for (int i = 0; i < walletInfoSourceCopy.length; i++) { + if (walletInfoSourceCopy[i].name == wallet.name) { + await _walletInfoSource.add(walletInfoSourceCopy[i]); + walletInfoSourceCopy.removeAt(i); + break; + } + } + } + + updateList(); + } + + Future sortGroupByType() async { + // sort the wallets by type: + List walletInfoSourceCopy = _walletInfoSource.values.toList(); + await _walletInfoSource.clear(); + if (ascending) { + walletInfoSourceCopy.sort((a, b) => a.type.toString().compareTo(b.type.toString())); + } else { + walletInfoSourceCopy.sort((a, b) => b.type.toString().compareTo(a.type.toString())); + } + await _walletInfoSource.addAll(walletInfoSourceCopy); + updateList(); + } + + Future sortAlphabetically() async { + // sort the wallets alphabetically: + List walletInfoSourceCopy = _walletInfoSource.values.toList(); + await _walletInfoSource.clear(); + if (ascending) { + walletInfoSourceCopy.sort((a, b) => a.name.compareTo(b.name)); + } else { + walletInfoSourceCopy.sort((a, b) => b.name.compareTo(a.name)); + } + await _walletInfoSource.addAll(walletInfoSourceCopy); + updateList(); + } + + Future sortByCreationDate() async { + // sort the wallets by creation date: + List walletInfoSourceCopy = _walletInfoSource.values.toList(); + await _walletInfoSource.clear(); + if (ascending) { + walletInfoSourceCopy.sort((a, b) => a.date.compareTo(b.date)); + } else { + walletInfoSourceCopy.sort((a, b) => b.date.compareTo(a.date)); + } + await _walletInfoSource.addAll(walletInfoSourceCopy); + updateList(); + } + + void setAscending(bool ascending) { + _appStore.settingsStore.walletListAscending = ascending; + } + + Future setOrderType(WalletListOrderType? type) async { + if (type == null) return; + + _appStore.settingsStore.walletListOrder = type; + + switch (type) { + case WalletListOrderType.CreationDate: + await sortByCreationDate(); + break; + case WalletListOrderType.Alphabetical: + await sortAlphabetically(); + break; + case WalletListOrderType.GroupByType: + await sortGroupByType(); + break; + case WalletListOrderType.Custom: + default: + await reorderAccordingToWalletList(); + break; + } + } + bool checkIfAuthRequired() { return _authService.requireAuth(); } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index c2cb7c060..251afa409 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -727,6 +727,9 @@ "require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ", "camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ", "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", + "order_by": "ترتيب حسب", + "creation_date": "تاريخ الإنشاء", + "group_by_type": "مجموعة حسب النوع", "importNFTs": "NFTs ﺩﺍﺮﻴﺘﺳﺍ", "noNFTYet": "ﻥﻵﺍ ﻰﺘﺣ NFTs ﺪﺟﻮﻳ ﻻ", "address": " ﻥﺍﻮﻨﻋ", @@ -746,8 +749,11 @@ "seed_language_czech": "التشيكية", "seed_language_korean": "الكورية", "seed_language_chinese_traditional": "تقاليد صينية)", + "ascending": "تصاعدي", + "descending": "النزول", "dfx_option_description": "ﺎﺑﻭﺭﻭﺃ ﻲﻓ ﺕﺎﻛﺮﺸﻟﺍﻭ ﺔﺋﺰﺠﺘﻟﺍ ءﻼﻤﻌﻟ .ﻲﻓﺎﺿﺇ KYC ﻥﻭﺪﺑ ﻭﺭﻮﻳ 990 ﻰﻟﺇ ﻞﺼﻳ ﺎﻣ .ﻱﺮﺴﻳﻮﺴﻟﺍ", "polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ", "wallet_seed_legacy": "بذرة محفظة قديمة", + "custom_drag": "مخصص (عقد وسحب)", "switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index f0da8a754..ae83da481 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -723,6 +723,9 @@ "require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли", "camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.", "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново", + "order_by": "Подредени по", + "creation_date": "Дата на създаване", + "group_by_type": "Група по вид", "importNFTs": "Импортирайте NFT", "noNFTYet": "Все още няма NFT", "address": "Адрес", @@ -742,8 +745,11 @@ "seed_language_czech": "Чех", "seed_language_korean": "Корейски", "seed_language_chinese_traditional": "Традиционен китайски)", + "ascending": "Възходящ", + "descending": "Низходящ", "dfx_option_description": "Купете крипто с EUR и CHF. До 990 € без допълнителен KYC. За клиенти на дребно и корпоративни клиенти в Европа", "polygonscan_history": "История на PolygonScan", "wallet_seed_legacy": "Наследено портфейл семе", + "custom_drag": "Персонализиране (задръжте и плъзнете)", "switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 60a37d9d0..da22f9f6b 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -723,6 +723,9 @@ "require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek", "camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.", "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu", + "order_by": "Seřadit podle", + "creation_date": "Datum vzniku", + "group_by_type": "Skupina podle typu", "importNFTs": "Importujte NFT", "noNFTYet": "Zatím žádné NFT", "address": "Adresa", @@ -742,8 +745,11 @@ "seed_language_czech": "čeština", "seed_language_korean": "korejština", "seed_language_chinese_traditional": "Číňan (tradiční)", + "ascending": "Vzestupné", + "descending": "Klesající", "dfx_option_description": "Nakupujte kryptoměny za EUR a CHF. Až 990 € bez dalších KYC. Pro maloobchodní a firemní zákazníky v Evropě", "polygonscan_history": "Historie PolygonScan", "wallet_seed_legacy": "Starší semeno peněženky", + "custom_drag": "Custom (Hold and Drag)", "switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 9d5b171d3..69b7e47d2 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -731,6 +731,9 @@ "require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets", "camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.", "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut", + "order_by": "Sortieren nach", + "creation_date": "Erstellungsdatum", + "group_by_type": "Gruppe nach Typ", "importNFTs": "NFTs importieren", "noNFTYet": "Noch keine NFTs", "address": "Adresse", @@ -750,8 +753,11 @@ "seed_language_czech": "Tschechisch", "seed_language_korean": "Koreanisch", "seed_language_chinese_traditional": "Chinesisch (Traditionell)", + "ascending": "Aufsteigend", + "descending": "Absteigend", "dfx_option_description": "Krypto mit EUR und CHF kaufen. Bis zu 990€ ohne zusätzliches KYC. Für Privat- und Firmenkunden in Europa", "polygonscan_history": "PolygonScan-Verlauf", "wallet_seed_legacy": "Legacy Wallet Seed", + "custom_drag": "Custom (Hold and Drag)", "switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 00848da1f..e1a7fdebc 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -498,7 +498,7 @@ "bill_amount": "Bill Amount", "you_pay": "You Pay", "tip": "Tip:", - "custom": "custom", + "custom": "Custom", "by_cake_pay": "by Cake Pay", "expires": "Expires", "mm": "MM", @@ -732,6 +732,9 @@ "require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets", "camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.", "switchToETHWallet": "Please switch to an Ethereum wallet and try again", + "order_by": "Order by", + "creation_date": "Creation Date", + "group_by_type": "Group by type", "importNFTs": "Import NFTs", "noNFTYet": "No NFTs yet", "address": "Address", @@ -751,8 +754,11 @@ "seed_language_czech": "Czech", "seed_language_korean": "Korean", "seed_language_chinese_traditional": "Chinese (Traditional)", + "ascending": "Ascending", + "descending": "Descending", "dfx_option_description": "Buy crypto with EUR & CHF. Up to 990€ without additional KYC. For retail and corporate customers in Europe", "polygonscan_history": "PolygonScan history", "wallet_seed_legacy": "Legacy wallet seed", + "custom_drag": "Custom (Hold and Drag)", "switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index e77462740..21de24163 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -731,6 +731,9 @@ "require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas", "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.", "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente.", + "order_by": "Ordenar", + "creation_date": "Fecha de creación", + "group_by_type": "Grupo por tipo", "importNFTs": "Importar NFT", "noNFTYet": "Aún no hay NFT", "address": "DIRECCIÓN", @@ -749,9 +752,12 @@ "seedtype_polyseed": "Polieta (16 palabras)", "seed_language_czech": "checo", "seed_language_korean": "coreano", + "ascending": "Ascendente", + "descending": "Descendente", "seed_language_chinese_traditional": "Chino (tradicional)", "dfx_option_description": "Compre criptomonedas con EUR y CHF. Hasta 990€ sin KYC adicional. Para clientes minoristas y corporativos en Europa", "polygonscan_history": "Historial de PolygonScan", "wallet_seed_legacy": "Semilla de billetera heredada", + "custom_drag": "Custom (mantenía y arrastre)", "switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index e45a6d90c..2d3895351 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -730,7 +730,6 @@ "domain_looks_up": "Résolution de nom", "require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes", "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", - "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", "importNFTs": "Importer des NFT", "noNFTYet": "Pas encore de NFT", "address": "Adresse", @@ -741,7 +740,11 @@ "seed_phrase_length": "Longueur de la phrase de départ", "unavailable_balance": "Solde indisponible", "unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.", + "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", "unspent_change": "Changement", + "order_by": "Commandé par", + "creation_date": "Date de création", + "group_by_type": "Groupe par type", "tor_connection": "Connexion Tor", "seed_hex_form": "Graine du portefeuille (forme hexagonale)", "seedtype": "Type de type graine", @@ -750,8 +753,11 @@ "seed_language_czech": "tchèque", "seed_language_korean": "coréen", "seed_language_chinese_traditional": "Chinois (Traditionnel)", + "ascending": "Ascendant", + "descending": "Descendant", "dfx_option_description": "Achetez des crypto-monnaies avec EUR et CHF. Jusqu'à 990€ sans KYC supplémentaire. Pour les clients particuliers et entreprises en Europe", "polygonscan_history": "Historique de PolygonScan", "wallet_seed_legacy": "Graine de portefeuille hérité", + "custom_drag": "Custom (maintenir et traîner)", "switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index e1369091e..69e118f49 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -709,6 +709,9 @@ "require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje", "camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.", "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa", + "order_by": "Oda ta", + "creation_date": "Ranar halitta", + "group_by_type": "Rukuni ta nau'in", "importNFTs": "Shigo da NFTs", "noNFTYet": "Babu NFTs tukuna", "address": "Adireshi", @@ -728,8 +731,11 @@ "seed_language_czech": "Czech", "seed_language_korean": "Yaren Koriya", "seed_language_chinese_traditional": "Sinanci (na gargajiya)", + "ascending": "Hau", + "descending": "Saukowa", "dfx_option_description": "Sayi crypto tare da EUR & CHF. Har zuwa € 990 ba tare da ƙarin KYC ba. Don 'yan kasuwa da abokan ciniki na kamfanoni a Turai", "polygonscan_history": "PolygonScan tarihin kowane zamani", "wallet_seed_legacy": "Tallarin walat walat", + "custom_drag": "Al'ada (riƙe da ja)", "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 32e2cba0d..5774203db 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -731,6 +731,9 @@ "require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है", "camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।", "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें", + "order_by": "द्वारा आदेश", + "creation_date": "निर्माण तिथि", + "group_by_type": "प्रकार द्वारा समूह", "importNFTs": "एनएफटी आयात करें", "noNFTYet": "अभी तक कोई एनएफटी नहीं", "address": "पता", @@ -750,8 +753,11 @@ "seed_language_czech": "चेक", "seed_language_korean": "कोरियाई", "seed_language_chinese_traditional": "चीनी पारंपरिक)", + "ascending": "आरोही", + "descending": "अवरोही", "dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। अतिरिक्त केवाईसी के बिना 990€ तक। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए", "polygonscan_history": "पॉलीगॉनस्कैन इतिहास", "wallet_seed_legacy": "विरासत बटुए बीज", + "custom_drag": "कस्टम (पकड़ और खींचें)", "switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 4afaa410d..5fde4d6de 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -729,6 +729,9 @@ "require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike", "camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.", "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno", + "order_by": "Narediti", + "creation_date": "Datum stvaranja", + "group_by_type": "Grupirati", "importNFTs": "Uvoz NFT-ova", "noNFTYet": "Još nema NFT-ova", "address": "Adresa", @@ -747,9 +750,12 @@ "seedtype_polyseed": "Poliseed (16 riječi)", "seed_language_czech": "češki", "seed_language_korean": "korejski", + "ascending": "Uzlazni", + "descending": "Silazni", "seed_language_chinese_traditional": "Kinesko (tradicionalno)", "dfx_option_description": "Kupujte kripto s EUR i CHF. Do 990 € bez dodatnog KYC-a. Za maloprodajne i poslovne korisnike u Europi", "polygonscan_history": "Povijest PolygonScan", "wallet_seed_legacy": "Sjeme naslijeđenog novčanika", + "custom_drag": "Prilagođeni (držite i povucite)", "switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index b45a45bfa..208569b31 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -719,6 +719,9 @@ "require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal", "camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.", "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi", + "order_by": "Dipesan oleh", + "creation_date": "Tanggal Pembuatan", + "group_by_type": "Grup demi jenis", "importNFTs": "Impor NFT", "noNFTYet": "Belum ada NFT", "address": "Alamat", @@ -737,9 +740,12 @@ "seedtype_polyseed": "Polyseed (16 kata)", "seed_language_czech": "Ceko", "seed_language_korean": "Korea", + "ascending": "Naik", + "descending": "Menurun", "seed_language_chinese_traditional": "Cina (tradisional)", "dfx_option_description": "Beli kripto dengan EUR & CHF. Hingga 990€ tanpa KYC tambahan. Untuk pelanggan ritel dan korporat di Eropa", "polygonscan_history": "Sejarah PolygonScan", "wallet_seed_legacy": "Biji dompet warisan", + "custom_drag": "Khusus (tahan dan seret)", "switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 770bbc9b6..51beaf576 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -731,6 +731,9 @@ "require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni", "camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.", "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova", + "order_by": "Ordinato da", + "creation_date": "Data di creazione", + "group_by_type": "Gruppo per tipo", "importNFTs": "Importa NFT", "noNFTYet": "Nessun NFT ancora", "address": "Indirizzo", @@ -750,8 +753,11 @@ "seed_language_czech": "ceco", "seed_language_korean": "coreano", "seed_language_chinese_traditional": "Cinese tradizionale)", + "ascending": "Ascendente", + "descending": "Discendente", "dfx_option_description": "Acquista criptovalute con EUR e CHF. Fino a 990€ senza KYC aggiuntivi. Per clienti al dettaglio e aziendali in Europa", "polygonscan_history": "Cronologia PolygonScan", "wallet_seed_legacy": "Seme di portafoglio legacy", + "custom_drag": "Custom (Hold and Drag)", "switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 35d4d3905..ca197adae 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -731,6 +731,9 @@ "require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要", "camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。", "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください", + "order_by": "注文", + "creation_date": "作成日", + "group_by_type": "タイプごとにグループ", "importNFTs": "NFTのインポート", "noNFTYet": "NFTはまだありません", "address": "住所", @@ -750,8 +753,11 @@ "seed_language_czech": "チェコ", "seed_language_korean": "韓国語", "seed_language_chinese_traditional": "中国の伝統的な)", + "ascending": "上昇", + "descending": "下降", "dfx_option_description": "EUR と CHF で暗号通貨を購入します。追加のKYCなしで最大990ユーロ。ヨーロッパの小売および法人顧客向け", "polygonscan_history": "ポリゴンスキャン履歴", "wallet_seed_legacy": "レガシーウォレットシード", + "custom_drag": "カスタム(ホールドとドラッグ)", "switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 9224e49fd..c657dad7e 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -729,6 +729,9 @@ "require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요", "camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.", "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요.", + "order_by": "주문", + "creation_date": "생산 일", + "group_by_type": "유형별 그룹", "importNFTs": "NFT 가져오기", "noNFTYet": "아직 NFT가 없습니다", "address": "주소", @@ -748,8 +751,11 @@ "seed_language_czech": "체코 사람", "seed_language_korean": "한국인", "seed_language_chinese_traditional": "중국 전통)", + "ascending": "오름차순", + "descending": "내림차순", "dfx_option_description": "EUR 및 CHF로 암호화폐를 구매하세요. 추가 KYC 없이 최대 990€. 유럽의 소매 및 기업 고객용", "polygonscan_history": "다각형 스캔 기록", "wallet_seed_legacy": "레거시 지갑 시드", + "custom_drag": "사용자 정의 (홀드 앤 드래그)", "switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 4c5441d2a..690f59ccc 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -729,6 +729,9 @@ "require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", "camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။", "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။", + "order_by": "အမှာစာ", + "creation_date": "ဖန်တီးမှုနေ့စွဲ", + "group_by_type": "အမျိုးအစားအလိုက်အုပ်စုဖွဲ့", "importNFTs": "NFTs များကို တင်သွင်းပါ။", "noNFTYet": "NFTs မရှိသေးပါ။", "address": "လိပ်စာ", @@ -748,8 +751,11 @@ "seed_language_czech": "ချက်", "seed_language_korean": "ကိုးရီးယား", "seed_language_chinese_traditional": "တရုတ်ရိုးရာ)", + "ascending": "တက်", + "descending": "ဆင်း", "dfx_option_description": "EUR & CHF ဖြင့် crypto ကိုဝယ်ပါ။ အပို KYC မပါဘဲ 990€ အထိ။ ဥရောပရှိ လက်လီရောင်းချသူများနှင့် ကော်ပိုရိတ်ဖောက်သည်များအတွက်", "polygonscan_history": "PolygonScan မှတ်တမ်း", "wallet_seed_legacy": "အမွေအနှစ်ပိုက်ဆံအိတ်မျိုးစေ့", + "custom_drag": "စိတ်ကြိုက် (Drag)", "switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index f22001ab9..426341bc4 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -731,6 +731,9 @@ "require_for_exchanges_to_external_wallets": "Vereist voor uitwisselingen naar externe portemonnees", "camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.", "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw", + "order_by": "Bestellen door", + "creation_date": "Aanmaakdatum", + "group_by_type": "Groep voor type", "importNFTs": "NFT's importeren", "noNFTYet": "Nog geen NFT's", "address": "Adres", @@ -749,9 +752,12 @@ "seedtype_polyseed": "Polyseed (16 woorden)", "seed_language_czech": "Tsjechisch", "seed_language_korean": "Koreaans", + "ascending": "Stijgend", + "descending": "Aflopend", "seed_language_chinese_traditional": "Chinese (traditionele)", "dfx_option_description": "Koop crypto met EUR & CHF. Tot 990€ zonder extra KYC. Voor particuliere en zakelijke klanten in Europa", "polygonscan_history": "PolygonScan-geschiedenis", "wallet_seed_legacy": "Legacy portemonnee zaad", + "custom_drag": "Custom (vasthouden en slepen)", "switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 9f4fb37be..5b6581bad 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -731,6 +731,9 @@ "require_for_exchanges_to_external_wallets": "Wymagaj wymiany na portfele zewnętrzne", "camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.", "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie", + "order_by": "Zamów przez", + "creation_date": "Data utworzenia", + "group_by_type": "Grupa według typu", "importNFTs": "Importuj NFT", "noNFTYet": "Nie ma jeszcze NFT", "address": "Adres", @@ -750,8 +753,11 @@ "seed_language_czech": "Czech", "seed_language_korean": "koreański", "seed_language_chinese_traditional": "Chiński tradycyjny)", + "ascending": "Wznoszący się", + "descending": "Schodzenie", "dfx_option_description": "Kupuj kryptowaluty za EUR i CHF. Do 990 € bez dodatkowego KYC. Dla klientów detalicznych i korporacyjnych w Europie", "polygonscan_history": "Historia PolygonScan", "wallet_seed_legacy": "Dziedziczne ziarno portfela", + "custom_drag": "Niestandardowe (trzymaj i przeciągnij)", "switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index e69a07024..5df592837 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -730,6 +730,9 @@ "require_for_exchanges_to_external_wallets": "Exigir trocas para carteiras externas", "camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.", "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente", + "order_by": "Ordenar por", + "creation_date": "Data de criação", + "group_by_type": "Grupo por tipo", "importNFTs": "Importar NFTs", "noNFTYet": "Ainda não há NFT", "address": "Endereço", @@ -749,8 +752,11 @@ "seed_language_czech": "Tcheco", "seed_language_korean": "coreano", "seed_language_chinese_traditional": "Chinês tradicional)", + "ascending": "Ascendente", + "descending": "descendente", "dfx_option_description": "Compre criptografia com EUR e CHF. Até 990€ sem KYC adicional. Para clientes de varejo e corporativos na Europa", "polygonscan_history": "História do PolygonScan", "wallet_seed_legacy": "Semente de carteira herdada", + "custom_drag": "Personalizado (segure e arraste)", "switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 75523482b..e6d149596 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -731,6 +731,9 @@ "require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки", "camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.", "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку.", + "order_by": "Сортировать по", + "creation_date": "Дата создания", + "group_by_type": "Группа по типу", "importNFTs": "Импортировать NFT", "noNFTYet": "NFT пока нет", "address": "Адрес", @@ -750,8 +753,11 @@ "seed_language_czech": "Чешский", "seed_language_korean": "Корейский", "seed_language_chinese_traditional": "Китайский традиционный)", + "ascending": "Восходящий", + "descending": "Нисходящий", "dfx_option_description": "Покупайте криптовалюту за EUR и CHF. До 990€ без дополнительного KYC. Для розничных и корпоративных клиентов в Европе", "polygonscan_history": "История PolygonScan", "wallet_seed_legacy": "Наследие семя кошелька", + "custom_drag": "Пользователь (удерживайте и перетаскивайте)", "switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon)." } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index e682cc4a1..b445562da 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -729,6 +729,9 @@ "require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก", "camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป", "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง", + "order_by": "สั่งโดย", + "creation_date": "วันที่สร้าง", + "group_by_type": "กลุ่มตามประเภท", "importNFTs": "นำเข้า NFT", "noNFTYet": "ยังไม่มี NFT", "address": "ที่อยู่", @@ -748,8 +751,11 @@ "seed_language_czech": "ภาษาเช็ก", "seed_language_korean": "เกาหลี", "seed_language_chinese_traditional": "จีน (ดั้งเดิม)", + "ascending": "จากน้อยไปมาก", + "descending": "ลงมา", "dfx_option_description": "ซื้อ crypto ด้วย EUR และ CHF สูงถึง 990€ โดยไม่มี KYC เพิ่มเติม สำหรับลูกค้ารายย่อยและลูกค้าองค์กรในยุโรป", "polygonscan_history": "ประวัติ PolygonScan", "wallet_seed_legacy": "เมล็ดกระเป๋าเงินมรดก", + "custom_drag": "กำหนดเอง (ค้างและลาก)", "switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 8a1a50a0a..5b9af5243 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -726,6 +726,9 @@ "require_for_exchanges_to_external_wallets": "Kinakailangan para sa mga palitan sa mga panlabas na wallet", "camera_permission_is_required": "Kinakailangan ang pahintulot sa camera.\nMangyaring paganahin ito mula sa mga setting ng app.", "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli", + "order_by": "Iniutos ni", + "creation_date": "Petsa ng paglikha", + "group_by_type": "Pangkat ayon sa uri", "importNFTs": "Mag-import ng mga NFT", "noNFTYet": "Wala pang NFT", "address": "Address", @@ -744,8 +747,11 @@ "seed_language_czech": "Czech", "seed_language_korean": "Korean", "seed_language_chinese_traditional": "Intsik (tradisyonal)", + "ascending": "Umakyat", + "descending": "Pababang", "dfx_option_description": "Bumili ng crypto gamit ang EUR at CHF. Hanggang 990€ nang walang karagdagang KYC. Para sa retail at corporate na mga customer sa Europe", "polygonscan_history": "Kasaysayan ng PolygonScan", "wallet_seed_legacy": "Legacy wallet seed", + "custom_drag": "Pasadyang (hawakan at i -drag)", "switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 88399e713..948415da9 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -729,6 +729,9 @@ "require_for_exchanges_to_external_wallets": "Harici cüzdanlara geçiş yapılmasını zorunlu kılın", "camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.", "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin", + "order_by": "Tarafından sipariş", + "creation_date": "Oluşturulma tarihi", + "group_by_type": "Türüne göre grup", "importNFTs": "NFT'leri içe aktar", "noNFTYet": "Henüz NFT yok", "address": "Adres", @@ -748,8 +751,11 @@ "seed_language_czech": "Çek", "seed_language_korean": "Koreli", "seed_language_chinese_traditional": "Çin geleneği)", + "ascending": "Yükselen", + "descending": "Azalan", "dfx_option_description": "EUR ve CHF ile kripto satın alın. Ek KYC olmadan 990 €'ya kadar. Avrupa'daki perakende ve kurumsal müşteriler için", "polygonscan_history": "PolygonScan geçmişi", "wallet_seed_legacy": "Eski cüzdan tohumu", + "custom_drag": "Özel (Bekle ve Sürükle)", "switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index d291e00a2..f01afeaad 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -731,6 +731,9 @@ "require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці", "camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.", "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу", + "order_by": "Сортувати за", + "creation_date": "Дата створення", + "group_by_type": "Група за типом", "importNFTs": "Імпорт NFT", "noNFTYet": "NFT ще немає", "address": "Адреса", @@ -749,9 +752,12 @@ "seedtype_polyseed": "Полісей (16 слів)", "seed_language_czech": "Чеський", "seed_language_korean": "Корейський", + "ascending": "Висхід", + "descending": "Низхідний", "dfx_option_description": "Купуйте криптовалюту за EUR і CHF. До 990 євро без додаткового KYC. Для роздрібних і корпоративних клієнтів у Європі", "seed_language_chinese_traditional": "Китайський (традиційний)", "polygonscan_history": "Історія PolygonScan", "wallet_seed_legacy": "Спадець насіння гаманця", + "custom_drag": "На замовлення (утримуйте та перетягується)", "switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index cae2abd69..c8d46bc44 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -723,6 +723,9 @@ "require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ", "camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ", "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ", + "order_by": "آرڈر بذریعہ", + "creation_date": "بنانے کی تاریخ", + "group_by_type": "قسم کے لحاظ سے گروپ", "importNFTs": "NFTs ۔ﮟﯾﺮﮐ ﺪﻣﺁﺭﺩ", "noNFTYet": "۔ﮟﯿﮨ ﮟﯿﮩﻧ NFTs ﯽﺋﻮﮐ ﮏﺗ ﯽﮭﺑﺍ", "address": "ﮧﺘﭘ", @@ -742,8 +745,11 @@ "seed_language_czech": "چیک", "seed_language_korean": "کورین", "seed_language_chinese_traditional": "چینی (روایتی)", + "ascending": "چڑھنے", + "descending": "اترتے ہوئے", "dfx_option_description": "EUR ﺭﻭﺍ CHF ﯽﻓﺎﺿﺍ ۔ﮟﯾﺪﯾﺮﺧ ﻮﭩﭘﺮﮐ ﮫﺗﺎﺳ ﮯﮐ KYC ﮯﯿﻟ ﮯﮐ ﻦﯿﻓﺭﺎﺻ ﭧﯾﺭﻮﭘﺭﺎﮐ ﺭﻭﺍ ﮦﺩﺭﻮﺧ ﮟ", "polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ", "wallet_seed_legacy": "میراثی پرس کا بیج", + "custom_drag": "کسٹم (ہولڈ اینڈ ڈریگ)", "switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ " } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index e42f1d58d..3323429a8 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -725,6 +725,9 @@ "require_for_exchanges_to_external_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ ita", "camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.", "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi", + "order_by": "Bere fun nipasẹ", + "creation_date": "Ọjọ ẹda", + "group_by_type": "Ẹgbẹ nipasẹ Iru", "importNFTs": "Gbe awọn NFT wọle", "noNFTYet": "Ko si awọn NFT sibẹsibẹ", "address": "Adirẹsi", @@ -744,8 +747,11 @@ "seed_language_czech": "Czech", "seed_language_korean": "Ara ẹni", "seed_language_chinese_traditional": "Kannada (ibile)", + "ascending": "Goke", + "descending": "Sọkalẹ", "dfx_option_description": "Ra crypto pẹlu EUR & CHF. Titi di 990 € laisi afikun KYC. Fun soobu ati awọn onibara ile-iṣẹ ni Yuroopu", "polygonscan_history": "PolygonScan itan", "wallet_seed_legacy": "Irugbin akole", + "custom_drag": "Aṣa (mu ati fa)", "switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 493498e98..148460ffb 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -730,6 +730,9 @@ "require_for_exchanges_to_external_wallets": "需要兑换到外部钱包", "camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。", "switchToETHWallet": "请切换到以太坊钱包并重试", + "order_by": "订购", + "creation_date": "创建日期", + "group_by_type": "按类型组", "importNFTs": "导入 NFT", "noNFTYet": "还没有 NFT", "address": "地址", @@ -749,8 +752,11 @@ "seed_language_czech": "捷克", "seed_language_korean": "韩国人", "seed_language_chinese_traditional": "中国传统的)", + "ascending": "上升", + "descending": "下降", "dfx_option_description": "用欧元和瑞士法郎购买加密货币。高达 990 欧元,无需额外 KYC。对于欧洲的零售和企业客户", "polygonscan_history": "多边形扫描历史", "wallet_seed_legacy": "旧的钱包种子", + "custom_drag": "定制(保持和拖动)", "switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)" } From 660cd442443a62e50c6e6fbf17391bfae65bb9c9 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 14 Dec 2023 12:58:02 +0200 Subject: [PATCH 074/241] update localization files --- lib/src/screens/seed/warning_page.dart | 5 ++--- res/values/strings_ar.arb | 4 ++-- res/values/strings_bg.arb | 6 +++--- res/values/strings_cs.arb | 6 +++--- res/values/strings_de.arb | 6 +++--- res/values/strings_en.arb | 6 +++--- res/values/strings_es.arb | 6 +++--- res/values/strings_fr.arb | 6 +++--- res/values/strings_ha.arb | 7 ++++--- res/values/strings_hi.arb | 6 +++--- res/values/strings_hr.arb | 6 +++--- res/values/strings_id.arb | 6 +++--- res/values/strings_it.arb | 6 +++--- res/values/strings_ja.arb | 6 +++--- res/values/strings_ko.arb | 6 +++--- res/values/strings_my.arb | 6 +++--- res/values/strings_nl.arb | 6 +++--- res/values/strings_pl.arb | 6 +++--- res/values/strings_pt.arb | 6 +++--- res/values/strings_ru.arb | 6 +++--- res/values/strings_th.arb | 6 +++--- res/values/strings_tl.arb | 6 +++--- res/values/strings_tr.arb | 6 +++--- res/values/strings_uk.arb | 6 +++--- res/values/strings_ur.arb | 6 +++--- res/values/strings_yo.arb | 6 +++--- res/values/strings_zh.arb | 6 +++--- 27 files changed, 80 insertions(+), 80 deletions(-) diff --git a/lib/src/screens/seed/warning_page.dart b/lib/src/screens/seed/warning_page.dart index 79560b3d4..f29f69a05 100644 --- a/lib/src/screens/seed/warning_page.dart +++ b/lib/src/screens/seed/warning_page.dart @@ -56,11 +56,10 @@ class WarningPage extends BasePage { : S.of(context).setup_warning_2fa_text, textAlign: TextAlign.center, style: TextStyle( + height: 1.7, fontSize: 14, fontWeight: FontWeight.normal, - color: isPreSeedPage - ? Theme.of(context).extension()!.secondaryTextColor - : Theme.of(context).extension()!.titleColor)), + color: Theme.of(context).extension()!.secondaryTextColor)), ), ), PrimaryButton( diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 79b385e47..f8b79957e 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -623,8 +623,8 @@ "enter_totp_code": "الرجاء إدخال رمز TOTP.", "add_secret_code": " ﺔﻗﺩﺎﺼﻤﻟﺍ ﻖﻴﺒﻄﺗ ﻰﻟﺇ ﻱﺮﺴﻟﺍ ﺰﻣﺮﻟﺍ ﺍﺬﻫ ﻒﺿﺃ ﻭﺃ", "totp_secret_code": "كود TOTP السري", - "setup_2fa_text": " .ﻲﻧﺎﺜﻟﺍ ﺔﻗﺩﺎﺼﻤﻟﺍ ﻞﻣﺎﻌﻛ TOTP ﻝﻼﺧ ﻦﻣ Cake 2FA ﻞﻤﻌﻳ", - "setup_totp_recommended": "إعداد TOTP (موصى به)", + "setup_2fa_text": " .ﻲﻧﺎﺜﻟﺍ ﺔﻗﺩﺎﺼﻤﻟﺍ ﻞﻣﺎﻌﻛ TOTP ﻡﺍﺪﺨﺘﺳﺎﺑ Cake 2FA ﻞﻤﻌﻳ", + "setup_totp_recommended": " TOTP ﺩﺍﺪﻋﺇ", "disable_buy": "تعطيل إجراء الشراء", "disable_sell": "قم بتعطيل إجراء البيع", "cake_2fa_preset": " كعكة 2FA مسبقا", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index b806d0f12..684fb0463 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -619,8 +619,8 @@ "enter_totp_code": "Моля, въведете TOTP кода.", "add_secret_code": "Или добавете този таен код към приложение за удостоверяване", "totp_secret_code": "TOTP таен код", - "setup_2fa_text": "Cake 2FA работи чрез TOTP като втори фактор за удостоверяване.\n\nTOTP на Cake 2FA изисква SHA-512 и поддръжка на 8 цифри; това осигурява повишена сигурност. Повече информация и поддържани приложения можете да намерите в ръководството тук.", - "setup_totp_recommended": "Настройка на TOTP (препоръчително)", + "setup_2fa_text": "Cake 2FA работи с помощта на TOTP като втори фактор за удостоверяване.\n\nTOTP на Cake 2FA изисква SHA-512 и поддръжка на 8 цифри; това осигурява повишена сигурност. Повече информация и поддържани приложения можете да намерите в ръководството.", + "setup_totp_recommended": "Настройка на TOTP", "disable_buy": "Деактивирайте действието за покупка", "disable_sell": "Деактивирайте действието за продажба", "auto_generate_subaddresses": "Автоматично генериране на подадреси", @@ -734,7 +734,7 @@ "unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.", "unspent_change": "Промяна", "tor_connection": "Tor връзка", - "setup_warning_2fa_text": "Cake 2FA е второ удостоверяване за определени действия в портфейла. НЕ е толкова сигурно, колкото хладилното съхранение.\n Ако загубите достъп до вашето 2FA приложение или пароли, ЩЕ загубите достъп до този портфейл.\n Ще трябва да възстановите портфейла си от мнемоничното семе.\n Поддръжката на Cake няма да може да ви помогне, ако загубите достъп до вашите 2FA или мнемонични семена. Преди да използвате Cake 2FA, препоръчваме да прочетете ръководството.", + "setup_warning_2fa_text": "Cake 2FA е второ удостоверяване за определени действия в портфейла. НЕ е толкова сигурно, колкото хладилното съхранение.\n\nАко загубите достъп до вашето 2FA приложение или TOTP ключове, ЩЕ загубите достъп до този портфейл. Ще трябва да възстановите портфейла си от мнемоничното семе.\n\nПоддръжката на Cake няма да може да ви помогне, ако загубите достъп до вашите 2FA или мнемонични семена.\nПреди да използвате Cake 2FA, препоръчваме да прочетете ръководството.", "scan_qr_on_device": "Сканирайте този QR код на друго устройство", "how_to_use": "Как да използвам", "seed_hex_form": "Семена от портфейл (шестнадесетична форма)", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 27015c7fd..4622304b8 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -619,8 +619,8 @@ "enter_totp_code": "Zadejte kód TOTP.", "add_secret_code": "Nebo přidejte tento tajný kód do ověřovací aplikace", "totp_secret_code": "Tajný kód TOTP", - "setup_2fa_text": "Cake 2FA funguje přes TOTP jako druhý autentizační faktor.\n\nTOTP Cake 2FA vyžaduje SHA-512 a podporu 8 číslic; to poskytuje zvýšenou bezpečnost. Další informace a podporované aplikace naleznete v průvodci zde.", - "setup_totp_recommended": "Nastavit TOTP (doporučeno)", + "setup_2fa_text": "Cake 2FA pracuje s použitím TOTP jako druhého autentizačního faktoru.\n\nTOTP Cake 2FA vyžaduje SHA-512 a podporu 8 číslic; to poskytuje zvýšenou bezpečnost. Další informace a podporované aplikace naleznete v průvodci.", + "setup_totp_recommended": "Nastavení TOTP", "disable_buy": "Zakázat akci nákupu", "disable_sell": "Zakázat akci prodeje", "auto_generate_subaddresses": "Automaticky generovat podadresy", @@ -734,7 +734,7 @@ "unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.", "unspent_change": "Změna", "tor_connection": "Připojení Tor", - "setup_warning_2fa_text": "Cake 2FA je druhá autentizace pro určité akce v peněžence. NENÍ tak bezpečný jako skladování v chladu.\n Pokud ztratíte přístup ke své aplikaci 2FA nebo přístupovým klíčům, ztratíte přístup k této peněžence.\n Budete muset obnovit svou peněženku z mnemotechnického semínka.\n Podpora dortů vám nebude schopna pomoci, pokud ztratíte přístup ke svým 2FA nebo mnemotechnickým semenům. Před použitím Cake 2FA doporučujeme přečíst si průvodce.", + "setup_warning_2fa_text": "Budete muset obnovit svou peněženku z mnemotechnického semínka.\n\nPodpora dortů vám nebude schopna pomoci, pokud ztratíte přístup ke svým 2FA nebo mnemotechnickým semenům.\nCake 2FA je druhá autentizace pro určité akce v peněžence. Před použitím Cake 2FA doporučujeme přečíst si průvodce.NENÍ tak bezpečný jako skladování v chladu.\n\nPokud ztratíte přístup ke své aplikaci 2FA nebo klíčům TOTP, ztratíte přístup k této peněžence. ", "scan_qr_on_device": "Naskenujte tento QR kód na jiném zařízení", "how_to_use": "Jak používat", "seed_hex_form": "Semeno peněženky (hex formulář)", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 0281ecc77..c2a80a1f1 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -627,8 +627,8 @@ "enter_totp_code": "Bitte geben Sie den TOTP-Code ein.", "add_secret_code": "Oder fügen Sie diesen Geheimcode einer Authentifizierungs-App hinzu", "totp_secret_code": "TOTP-Geheimcode", - "setup_2fa_text": "Cake 2FA funktioniert über TOTP als zweiten Authentifizierungsfaktor.\n\nDas TOTP von Cake 2FA erfordert SHA-512 und 8-stellige Unterstützung; Dies sorgt für erhöhte Sicherheit. Weitere Informationen und unterstützte Apps finden Sie im Leitfaden hier.", - "setup_totp_recommended": "TOTP einrichten (empfohlen)", + "setup_2fa_text": "Cake 2FA verwendet TOTP als zweiten Authentifizierungsfaktor.\n\nDas TOTP von Cake 2FA erfordert SHA-512 und 8-stellige Unterstützung; Dies sorgt für erhöhte Sicherheit. Weitere Informationen und unterstützte Apps finden Sie im Leitfaden.", + "setup_totp_recommended": "TOTP einrichten", "disable_buy": "Kaufaktion deaktivieren", "disable_sell": "Verkaufsaktion deaktivieren", "cake_2fa_preset": "Kuchen 2FA-Voreinstellung", @@ -742,7 +742,7 @@ "unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.", "unspent_change": "Wechselgeld", "tor_connection": "Tor-Verbindung", - "setup_warning_2fa_text": "Cake 2FA ist eine zweite Authentifizierung für bestimmte Aktionen im Wallet. Es ist NICHT so sicher wie eine Kühllagerung.\n Wenn Sie den Zugriff auf Ihre 2FA-App oder Ihre Passkeys verlieren, verlieren Sie auch den Zugriff auf dieses Wallet.\n Sie müssen Ihr Wallet aus dem mnemonischen Seed wiederherstellen.\n Der Cake-Support kann Ihnen nicht weiterhelfen, wenn Sie den Zugriff auf Ihre 2FA- oder Mnemonik-Seeds verlieren. Bevor Sie Cake 2FA verwenden, empfehlen wir Ihnen, die Anleitung durchzulesen.", + "setup_warning_2fa_text": "Sie müssen Ihr Wallet aus dem mnemonischen Seed wiederherstellen.\n\nDer Cake-Support kann Ihnen nicht weiterhelfen, wenn Sie den Zugriff auf Ihre 2FA- oder Mnemonik-Seeds verlieren.\nCake 2FA ist eine zweite Authentifizierung für bestimmte Aktionen im Wallet. Bevor Sie Cake 2FA verwenden, empfehlen wir Ihnen, die Anleitung durchzulesen.Es ist NICHT so sicher wie eine Kühllagerung.\n\nWenn Sie den Zugriff auf Ihre 2FA-App oder Ihre TOTP-Schlüssel verlieren, verlieren Sie auch den Zugriff auf dieses Wallet. ", "scan_qr_on_device": "Scannen Sie diesen QR-Code auf einem anderen Gerät", "how_to_use": "Wie benutzt man", "seed_hex_form": "Brieftaschensamen (Sechskantform)", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 91789e613..37ce99a91 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -629,9 +629,9 @@ "scan_qr_on_device": "Scan this QR code on another device", "add_secret_code": "Or, add this secret code to an authenticator app", "totp_secret_code": "TOTP Secret Code", - "setup_2fa_text": "Cake 2FA works through TOTP as the second authentication factor.\n\nCake 2FA's TOTP requires SHA-512 and 8 digit support; this provides increased security. More information and supported apps can be found in the guide here.", - "setup_warning_2fa_text": "Cake 2FA is a second authentication for certain actions in the wallet. It is NOT as secure as cold storage.\n If you lose access to your 2FA app or passkeys, you WILL lose access to this wallet.\n You will need to restore your wallet from the mnemonic seed.\n Cake support will be unable to assist you if you lose access to your 2FA or mnemonic seeds. Before using Cake 2FA, we recommend reading through the guide.", - "setup_totp_recommended": "Set up TOTP (Recommended)", + "setup_2fa_text": "Cake 2FA works using TOTP as the second authentication factor.\n\nCake 2FA's TOTP requires SHA-512 and 8 digit support; this provides increased security. More information and supported apps can be found in the guide.", + "setup_warning_2fa_text": "Cake 2FA is a second authentication for certain actions in the wallet. It is NOT as secure as cold storage.\n\nIf you lose access to your 2FA app or TOTP keys, you WILL lose access to this wallet. You will need to restore your wallet from the mnemonic seed.\n\nCake support will be unable to assist you if you lose access to your 2FA or mnemonic seeds.\nBefore using Cake 2FA, we recommend reading through the guide.", + "setup_totp_recommended": "Setup TOTP", "disable_buy": "Disable buy action", "disable_sell": "Disable sell action", "cake_2fa_preset": "Cake 2FA Preset", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 84647c28b..375ec593c 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -627,8 +627,8 @@ "enter_totp_code": "Ingrese el código TOTP.", "add_secret_code": "O agregue este código secreto a una aplicación de autenticación", "totp_secret_code": "Código secreto TOTP", - "setup_2fa_text": "Cake 2FA funciona a través de TOTP como segundo factor de autenticación.\n\nEl TOTP de Cake 2FA requiere SHA-512 y soporte de 8 dígitos; esto proporciona una mayor seguridad. Puede encontrar más información y aplicaciones compatibles en la guía aquí.", - "setup_totp_recommended": "Configurar TOTP (Recomendado)", + "setup_2fa_text": "Cake 2FA funciona utilizando TOTP como segundo factor de autenticación.\n\nEl TOTP de Cake 2FA requiere SHA-512 y soporte de 8 dígitos; esto proporciona una mayor seguridad. Puede encontrar más información y aplicaciones compatibles en la guía.", + "setup_totp_recommended": "Configurar TOTP", "disable_buy": "Desactivar acción de compra", "disable_sell": "Desactivar acción de venta", "cake_2fa_preset": "Pastel 2FA preestablecido", @@ -742,7 +742,7 @@ "unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.", "unspent_change": "Cambiar", "tor_connection": "conexión tor", - "setup_warning_2fa_text": "Cake 2FA es una segunda autenticación para ciertas acciones en la billetera. NO es tan seguro como el almacenamiento en frío.\n Si pierde el acceso a su aplicación 2FA o a sus claves de acceso, perderá el acceso a esta billetera.\n Deberá restaurar su billetera a partir de la semilla mnemotécnica.\n El soporte de Cake no podrá ayudarlo si pierde el acceso a su 2FA o a sus semillas mnemotécnicas. Antes de usar Cake 2FA, recomendamos leer la guía.", + "setup_warning_2fa_text": "Deberá restaurar su billetera a partir de la semilla mnemotécnica.\n\nEl soporte de Cake no podrá ayudarlo si pierde el acceso a su 2FA o a sus semillas mnemotécnicas.\nCake 2FA es una segunda autenticación para ciertas acciones en la billetera. Antes de usar Cake 2FA, recomendamos leer la guía.NO es tan seguro como el almacenamiento en frío.\n\nSi pierde el acceso a su aplicación 2FA o a sus claves TOTP, perderá el acceso a esta billetera. ", "scan_qr_on_device": "Escanea este código QR en otro dispositivo", "how_to_use": "Cómo utilizar", "seed_hex_form": "Semilla de billetera (forma hexadecimal)", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index df83bab5a..db4a077a0 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -627,8 +627,8 @@ "enter_totp_code": "Veuillez entrer le code TOTP.", "add_secret_code": "Ou ajoutez ce code secret à une application d'authentification", "totp_secret_code": "Secret TOTP", - "setup_2fa_text": "Cake 2FA fonctionne via TOTP comme deuxième facteur d'authentification.\n\nLe TOTP de Cake 2FA nécessite la prise en charge de SHA-512 et de 8 chiffres ; cela offre une sécurité accrue. Plus d’informations et les applications prises en charge peuvent être trouvées dans le guide ici.", - "setup_totp_recommended": "Configurer TOTP (recommandé)", + "setup_2fa_text": "Cake 2FA fonctionne en utilisant TOTP comme deuxième facteur d'authentification.\n\nLe TOTP de Cake 2FA nécessite la prise en charge de SHA-512 et de 8 chiffres ; cela offre une sécurité accrue. Plus d’informations et les applications prises en charge peuvent être trouvées dans le guide.", + "setup_totp_recommended": "Configurer TOTP", "disable_buy": "Désactiver l'action d'achat", "disable_sell": "Désactiver l'action de vente", "cake_2fa_preset": "Cake 2FA prédéfini", @@ -742,7 +742,7 @@ "unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.", "unspent_change": "Changement", "tor_connection": "Connexion Tor", - "setup_warning_2fa_text": "Cake 2FA est une seconde authentification pour certaines actions dans le portefeuille. Ce n’est PAS aussi sécurisé que l’entreposage frigorifique.\n Si vous perdez l'accès à votre application 2FA ou à vos mots de passe, vous perdrez l'accès à ce portefeuille.\n Vous devrez restaurer votre portefeuille à partir de la graine mnémonique.\n Le support Cake ne pourra pas vous aider si vous perdez l'accès à vos graines 2FA ou mnémoniques. Avant d'utiliser Cake 2FA, nous vous recommandons de lire le guide.", + "setup_warning_2fa_text": "Vous devrez restaurer votre portefeuille à partir de la graine mnémonique.\n\nLe support Cake ne pourra pas vous aider si vous perdez l'accès à vos graines 2FA ou mnémoniques.\nCake 2FA est une seconde authentification pour certaines actions dans le portefeuille. Avant d'utiliser Cake 2FA, nous vous recommandons de lire le guide.Ce n’est PAS aussi sécurisé que l’entreposage frigorifique.\n\nSi vous perdez l'accès à votre application 2FA ou à vos clés TOTP, vous perdrez l'accès à ce portefeuille. ", "scan_qr_on_device": "Scannez ce code QR sur un autre appareil", "how_to_use": "Comment utiliser", "seed_hex_form": "Graine du portefeuille (forme hexagonale)", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 7a31cd2e3..2d98ac1c5 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -721,8 +721,8 @@ "unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.", "unspent_change": "Canza", "tor_connection": "Tor haɗin gwiwa", - "setup_2fa_text": "Cake 2FA yana aiki ta hanyar TOTP azaman ƙimar tabbatarwa ta biyu.\n\nCake 2FA's TOTP yana buƙatar tallafin lambobi SHA-512 da 8; wannan yana ba da ƙarin tsaro. Ana iya samun ƙarin bayani da aikace-aikacen tallafi a cikin jagorar nan.", - "setup_warning_2fa_text": "Cake 2FA tabbaci ne na biyu don wasu ayyuka a cikin walat. BA shi da tsaro kamar ajiyar sanyi.\n Idan ka rasa damar yin amfani da app ɗinka na 2FA ko maɓallan wucewa, ZA KA rasa damar shiga wannan wallet ɗin.\n Kuna buƙatar dawo da walat ɗin ku daga zuriyar mnemonic.\n Tallafin kek ba zai iya taimaka muku ba idan kun rasa damar yin amfani da 2FA ko tsaba na mnemonic. Kafin amfani da Cake 2FA, muna ba da shawarar karanta ta cikin jagorar.", + "setup_2fa_text": "Cake 2FA yana aiki ta amfani da TOTP azaman ƙimar tabbatarwa ta biyu.\n\nCake 2FA's TOTP yana buƙatar tallafin lambobi SHA-512 da 8; wannan yana ba da ƙarin tsaro. Ana iya samun ƙarin bayani da ƙa'idodi masu goyan baya a cikin jagorar.", + "setup_warning_2fa_text": "Kuna buƙatar dawo da walat ɗin ku daga zuriyar mnemonic.\n\nTallafin kek ba zai iya taimaka muku ba idan kun rasa damar yin amfani da 2FA ko tsaba na mnemonic.\nCake 2FA tabbaci ne na biyu don wasu ayyuka a cikin walat. Kafin amfani da Cake 2FA, muna ba da shawarar karanta ta cikin jagorar.BA shi da tsaro kamar ajiyar sanyi.\n\nIdan ka rasa damar yin amfani da app ɗinka na 2FA ko maɓallan TOTP, ZA KA rasa damar shiga wannan wallet ɗin. ", "add_secret_code": "Ko, ƙara wannan lambar sirrin zuwa ƙa'idar mai tabbatarwa", "scan_qr_on_device": "Duba wannan lambar QR akan wata na'ura", "how_to_use": "Yadda ake amfani da shi", @@ -736,5 +736,6 @@ "dfx_option_description": "Sayi crypto tare da EUR & CHF. Har zuwa € 990 ba tare da ƙarin KYC ba. Don 'yan kasuwa da abokan ciniki na kamfanoni a Turai", "polygonscan_history": "PolygonScan tarihin kowane zamani", "wallet_seed_legacy": "Tallarin walat walat", - "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)" + "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)", + "setup_totp_recommended": "Saita TOTP" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 0cd69e82b..699c6d510 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -627,8 +627,8 @@ "enter_totp_code": "कृपया TOTP कोड दर्ज करें।", "add_secret_code": "या, इस गुप्त कोड को प्रमाणक ऐप में जोड़ें", "totp_secret_code": "टीओटीपी गुप्त कोड", - "setup_2fa_text": "केक 2FA दूसरे प्रमाणीकरण कारक के रूप में TOTP के माध्यम से काम करता है।\n\nकेक 2FA के TOTP को SHA-512 और 8 अंकों के समर्थन की आवश्यकता है; इससे अधिक सुरक्षा मिलती है. अधिक जानकारी और समर्थित ऐप्स यहां गाइड में पाए जा सकते हैं।", - "setup_totp_recommended": "टीओटीपी सेट अप करें (अनुशंसित)", + "setup_2fa_text": "केक 2FA दूसरे प्रमाणीकरण कारक के रूप में TOTP का उपयोग करके काम करता है।\n\nकेक 2FA के TOTP को SHA-512 और 8 अंकों के समर्थन की आवश्यकता है; इससे अधिक सुरक्षा मिलती है. अधिक जानकारी और समर्थित ऐप्स गाइड में पाए जा सकते हैं।", + "setup_totp_recommended": "सेटअप टीओटीपी", "disable_buy": "खरीद कार्रवाई अक्षम करें", "disable_sell": "बेचने की कार्रवाई अक्षम करें", "cake_2fa_preset": "केक 2एफए प्रीसेट", @@ -742,7 +742,7 @@ "unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।", "unspent_change": "परिवर्तन", "tor_connection": "टोर कनेक्शन", - "setup_warning_2fa_text": "केक 2एफए वॉलेट में कुछ कार्यों के लिए दूसरा प्रमाणीकरण है। यह कोल्ड स्टोरेज जितना सुरक्षित नहीं है।\n यदि आप अपने 2एफए ऐप या पासकी तक पहुंच खो देते हैं, तो आप इस वॉलेट तक पहुंच खो देंगे।\n आपको अपने बटुए को स्मरक बीज से पुनर्स्थापित करने की आवश्यकता होगी।\n यदि आप अपने 2एफए या निमोनिक बीजों तक पहुंच खो देते हैं तो केक समर्थन आपकी सहायता करने में असमर्थ होगा। केक 2एफए का उपयोग करने से पहले, हम गाइड को पढ़ने की सलाह देते हैं।", + "setup_warning_2fa_text": "केक 2एफए वॉलेट में कुछ कार्यों के लिए दूसरा प्रमाणीकरण है। यह कोल्ड स्टोरेज जितना सुरक्षित नहीं है।\n\nयदि आप अपने 2एफए ऐप या टीओटीपी कुंजियों तक पहुंच खो देते हैं, तो आप इस वॉलेट तक पहुंच खो देंगे। आपको अपने बटुए को स्मरक बीज से पुनर्स्थापित करने की आवश्यकता होगी।\n\nयदि आप अपने 2एफए या निमोनिक बीजों तक पहुंच खो देते हैं तो केक समर्थन आपकी सहायता करने में असमर्थ होगा।\nकेक 2एफए का उपयोग करने से पहले, हम गाइड को पढ़ने की सलाह देते हैं।", "scan_qr_on_device": "इस QR कोड को किसी अन्य डिवाइस पर स्कैन करें", "how_to_use": "का उपयोग कैसे करें", "seed_hex_form": "वॉलेट सीड (हेक्स फॉर्म)", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 7dcf30e56..63e5d6f13 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -627,8 +627,8 @@ "enter_totp_code": "Unesite TOTP kod.", "add_secret_code": "Ili dodajte ovaj tajni kod u aplikaciju za autentifikaciju", "totp_secret_code": "TOTP tajni kod", - "setup_2fa_text": "Cake 2FA radi preko TOTP-a kao drugog faktora provjere autentičnosti.\n\nCake 2FA TOTP zahtijeva SHA-512 i podršku za 8 znamenki; ovo osigurava povećanu sigurnost. Više informacija i podržanih aplikacija možete pronaći u vodiču ovdje.", - "setup_totp_recommended": "Postavite TOTP (preporučeno)", + "setup_2fa_text": "Cake 2FA radi koristeći TOTP kao drugi faktor provjere autentičnosti.\n\nCake 2FA TOTP zahtijeva SHA-512 i podršku za 8 znamenki; ovo osigurava povećanu sigurnost. Više informacija i podržanih aplikacija možete pronaći u vodiču.", + "setup_totp_recommended": "Postavite TOTP", "disable_buy": "Onemogući kupnju", "disable_sell": "Onemogući akciju prodaje", "cake_2fa_preset": "Cake 2FA Preset", @@ -740,7 +740,7 @@ "unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.", "unspent_change": "Promijeniti", "tor_connection": "Tor veza", - "setup_warning_2fa_text": "Cake 2FA je druga provjera autentičnosti za određene radnje u novčaniku. NIJE siguran kao hladno skladište.\n Ako izgubite pristup svojoj 2FA aplikaciji ili pristupnim ključevima, IZGUBIT ĆETE pristup ovom novčaniku.\n Morat ćete obnoviti svoj novčanik iz mnemoničkog sjemena.\n Podrška za kolače neće vam moći pomoći ako izgubite pristup svojim 2FA ili mnemoničkim izvorima. Prije uporabe Cake 2FA preporučujemo da pročitate vodič.", + "setup_warning_2fa_text": "Morat ćete obnoviti svoj novčanik iz mnemoničkog sjemena.\n\nPodrška za kolače neće vam moći pomoći ako izgubite pristup svojim 2FA ili mnemoničkim izvorima.\nCake 2FA je druga provjera autentičnosti za određene radnje u novčaniku. Prije uporabe Cake 2FA preporučujemo da pročitate vodič.NIJE siguran kao hladno skladište.\n\nAko izgubite pristup svojoj 2FA aplikaciji ili TOTP ključevima, IZGUBIT ĆETE pristup ovom novčaniku. ", "scan_qr_on_device": "Skenirajte ovaj QR kod na drugom uređaju", "how_to_use": "Kako koristiti", "seed_hex_form": "Sjeme novčanika (šesterokutni oblik)", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index c598c7f6e..3907c969f 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -615,8 +615,8 @@ "enter_totp_code": "Masukkan Kode TOTP.", "add_secret_code": "Atau, tambahkan kode rahasia ini ke aplikasi autentikator", "totp_secret_code": "Kode Rahasia TOTP", - "setup_2fa_text": "Cake 2FA bekerja melalui TOTP sebagai faktor otentikasi kedua.\n\nTOTP Cake 2FA memerlukan SHA-512 dan dukungan 8 digit; ini memberikan peningkatan keamanan. Informasi lebih lanjut dan aplikasi yang didukung dapat ditemukan dalam panduan di sini.", - "setup_totp_recommended": "Siapkan TOTP (Disarankan)", + "setup_2fa_text": "Cake 2FA bekerja menggunakan TOTP sebagai faktor otentikasi kedua.\n\nTOTP Cake 2FA memerlukan SHA-512 dan dukungan 8 digit; ini memberikan peningkatan keamanan. Informasi lebih lanjut dan aplikasi yang didukung dapat ditemukan di panduan.", + "setup_totp_recommended": "Pengaturan TOTP", "disable_buy": "Nonaktifkan tindakan beli", "disable_sell": "Nonaktifkan aksi jual", "auto_generate_subaddresses": "Menghasilkan subalamat secara otomatis", @@ -730,7 +730,7 @@ "unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.", "unspent_change": "Mengubah", "tor_connection": "koneksi Tor", - "setup_warning_2fa_text": "Cake 2FA adalah otentikasi kedua untuk tindakan tertentu di dompet. Ini TIDAK seaman penyimpanan dingin.\n Jika Anda kehilangan akses ke aplikasi 2FA atau kunci sandi, Anda AKAN kehilangan akses ke dompet ini.\n Anda perlu memulihkan dompet Anda dari benih mnemonik.\n Dukungan kue tidak akan dapat membantu Anda jika Anda kehilangan akses ke 2FA atau benih mnemonik. Sebelum menggunakan Cake 2FA, kami sarankan untuk membaca panduannya.", + "setup_warning_2fa_text": "Anda perlu memulihkan dompet Anda dari benih mnemonik.\n\nDukungan kue tidak akan dapat membantu Anda jika Anda kehilangan akses ke 2FA atau benih mnemonik.\nCake 2FA adalah otentikasi kedua untuk tindakan tertentu di dompet. Sebelum menggunakan Cake 2FA, kami sarankan untuk membaca panduannya.Ini TIDAK seaman penyimpanan dingin.\n\nJika Anda kehilangan akses ke aplikasi 2FA atau kunci TOTP, Anda AKAN kehilangan akses ke dompet ini. ", "scan_qr_on_device": "Pindai kode QR ini di perangkat lain", "how_to_use": "Cara Penggunaan", "seed_hex_form": "Biji dompet (bentuk hex)", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 5097d2e4b..50ad4d3c4 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -627,8 +627,8 @@ "enter_totp_code": "Inserisci il codice TOTP.", "add_secret_code": "Oppure aggiungi questo codice segreto a un'app di autenticazione", "totp_secret_code": "TOTP codice segreto", - "setup_2fa_text": "Cake 2FA funziona tramite TOTP come secondo fattore di autenticazione.\n\nIl TOTP di Cake 2FA richiede il supporto SHA-512 e 8 cifre; ciò fornisce una maggiore sicurezza. Maggiori informazioni e app supportate sono disponibili nella guida qui.", - "setup_totp_recommended": "Imposta TOTP (consigliato)", + "setup_2fa_text": "Cake 2FA funziona utilizzando TOTP come secondo fattore di autenticazione.\n\nIl TOTP di Cake 2FA richiede il supporto SHA-512 e 8 cifre; ciò fornisce una maggiore sicurezza. Maggiori informazioni e app supportate sono disponibili nella guida.", + "setup_totp_recommended": "Imposta TOTP", "disable_buy": "Disabilita l'azione di acquisto", "disable_sell": "Disabilita l'azione di vendita", "auto_generate_subaddresses": "Genera automaticamente sottindirizzi", @@ -742,7 +742,7 @@ "unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.", "unspent_change": "Modifica", "tor_connection": "Connessione Tor", - "setup_warning_2fa_text": "Cake 2FA è una seconda autenticazione per determinate azioni nel portafoglio. NON è sicuro come la conservazione a freddo.\n Se perdi l'accesso alla tua app 2FA o alle passkey, perderai l'accesso a questo portafoglio.\n Dovrai ripristinare il tuo portafoglio dal seme mnemonico.\n Il supporto di Cake non sarà in grado di assisterti se perdi l'accesso ai tuoi seed 2FA o mnemonici. Prima di utilizzare Cake 2FA, ti consigliamo di leggere la guida.", + "setup_warning_2fa_text": "Dovrai ripristinare il tuo portafoglio dal seme mnemonico.\n\nIl supporto di Cake non sarà in grado di assisterti se perdi l'accesso ai tuoi seed 2FA o mnemonici.\nCake 2FA è una seconda autenticazione per determinate azioni nel portafoglio. Prima di utilizzare Cake 2FA, ti consigliamo di leggere la guida.NON è sicuro come la conservazione a freddo.\n\nSe perdi l'accesso alla tua app 2FA o alle chiavi TOTP, perderai l'accesso a questo portafoglio. ", "scan_qr_on_device": "Scansiona questo codice QR su un altro dispositivo", "how_to_use": "Come usare", "seed_hex_form": "Seme di portafoglio (forma esadecimale)", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 6624a4f5c..151ae48e9 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -627,8 +627,8 @@ "enter_totp_code": "TOTPコードを入力してください。", "add_secret_code": "または、このシークレット コードを認証アプリに追加します", "totp_secret_code": "TOTPシークレットコード", - "setup_2fa_text": "Cake 2FA は、TOTP を通じて 2 番目の認証要素として機能します。\n\nCake 2FA の TOTP には SHA-512 と 8 桁のサポートが必要です。これによりセキュリティが強化されます。詳細とサポートされているアプリについては、こちらのガイドをご覧ください。", - "setup_totp_recommended": "TOTP を設定する (推奨)", + "setup_2fa_text": "Cake 2FA は、TOTP を 2 番目の認証要素として使用して機能します。\n\nCake 2FA の TOTP には SHA-512 と 8 桁のサポートが必要です。これによりセキュリティが強化されます。詳細とサポートされているアプリについてはガイドをご覧ください。", + "setup_totp_recommended": "TOTPのセットアップ", "disable_buy": "購入アクションを無効にする", "disable_sell": "販売アクションを無効にする", "cake_2fa_preset": "ケーキ 2FA プリセット", @@ -742,7 +742,7 @@ "unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。", "unspent_change": "変化", "tor_connection": "Tor接続", - "setup_warning_2fa_text": "Cake 2FA は、ウォレット内の特定のアクションに対する 2 番目の認証です。冷蔵保存ほど安全ではありません。\n 2FA アプリまたはパスキーにアクセスできなくなると、このウォレットにもアクセスできなくなります。\n ニーモニックシードからウォレットを復元する必要があります。\n 2FA またはニーモニック シードにアクセスできなくなった場合、Cake サポートはサポートできません。 Cake 2FA を使用する前に、ガイドを一読することをお勧めします。", + "setup_warning_2fa_text": "Cake 2FA は、ウォレット内の特定のアクションに対する 2 番目の認証です。冷蔵保存ほど安全ではありません。\n\n2FA アプリまたは TOTP キーにアクセスできなくなると、このウォレットにもアクセスできなくなります。ニーモニックシードからウォレットを復元する必要があります。\n\n2FA またはニーモニック シードにアクセスできなくなった場合、Cake サポートはサポートできません。\nCake 2FA を使用する前に、ガイドを一読することをお勧めします。", "scan_qr_on_device": "別のデバイスでこの QR コードをスキャンします", "how_to_use": "使い方", "seed_hex_form": "ウォレットシード(ヘックスフォーム)", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index eb21b9142..9404af569 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -627,8 +627,8 @@ "enter_totp_code": "TOTP 코드를 입력하세요.", "add_secret_code": "또는 이 비밀 코드를 인증 앱에 추가하세요.", "totp_secret_code": "TOTP 비밀 코드", - "setup_2fa_text": "Cake 2FA는 TOTP를 두 번째 인증 요소로 사용합니다.\n\nCake 2FA의 TOTP에는 SHA-512 및 8자리 지원이 필요합니다. 이는 보안을 강화합니다. 자세한 내용과 지원되는 앱은 여기 가이드에서 확인할 수 있습니다.", - "setup_totp_recommended": "TOTP 설정(권장)", + "setup_2fa_text": "Cake 2FA는 TOTP를 두 번째 인증 요소로 사용하여 작동합니다.\n\nCake 2FA의 TOTP에는 SHA-512 및 8자리 지원이 필요합니다. 이는 보안을 강화합니다. 자세한 정보와 지원되는 앱은 가이드에서 확인할 수 있습니다.", + "setup_totp_recommended": "TOTP 설정", "disable_buy": "구매 행동 비활성화", "disable_sell": "판매 조치 비활성화", "cake_2fa_preset": "케이크 2FA 프리셋", @@ -740,7 +740,7 @@ "unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.", "unspent_change": "변화", "tor_connection": "토르 연결", - "setup_warning_2fa_text": "Cake 2FA는 지갑의 특정 작업에 대한 두 번째 인증입니다. 냉장 보관만큼 안전하지 않습니다.\n 2FA 앱이나 비밀번호 키에 접근할 수 없게 되면 이 지갑에 접근할 수 없게 됩니다.\n 니모닉 시드에서 지갑을 복원해야 합니다.\n 2FA 또는 니모닉 시드에 액세스할 수 없는 경우 Cake 지원팀에서 도움을 드릴 수 없습니다. Cake 2FA를 사용하기 전에 가이드를 읽어 보시기 바랍니다.", + "setup_warning_2fa_text": "Cake 2FA는 지갑의 특정 작업에 대한 두 번째 인증입니다. 냉장 보관만큼 안전하지 않습니다.\n\n2FA 앱 또는 TOTP 키에 대한 액세스 권한을 상실하면 이 지갑에 대한 액세스 권한도 잃게 됩니다. 니모닉 시드에서 지갑을 복원해야 합니다.\n\n2FA 또는 니모닉 시드에 액세스할 수 없는 경우 Cake 지원팀에서 도움을 드릴 수 없습니다.\nCake 2FA를 사용하기 전에 가이드를 읽어 보시기 바랍니다.", "scan_qr_on_device": "다른 기기에서 이 QR 코드를 스캔하세요.", "how_to_use": "사용하는 방법", "seed_hex_form": "지갑 씨앗 (16 진 양식)", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 36754049b..30e4ed437 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -625,8 +625,8 @@ "enter_totp_code": "ကျေးဇူးပြု၍ TOTP ကုဒ်ကို ထည့်ပါ။", "add_secret_code": "သို့မဟုတ် ဤလျှို့ဝှက်ကုဒ်ကို အထောက်အထားစိစစ်ခြင်းအက်ပ်တစ်ခုသို့ ထည့်ပါ။", "totp_secret_code": "TOTP လျှို့ဝှက်ကုဒ်", - "setup_2fa_text": "ကိတ်မုန့် 2FA သည် TOTP မှတစ်ဆင့် ဒုတိယအထောက်အထားစိစစ်ခြင်းအချက်အဖြစ် လုပ်ဆောင်သည်။\n\nကိတ်မုန့် 2FA ၏ TOTP သည် SHA-512 နှင့် 8 ဂဏန်းပံ့ပိုးမှု လိုအပ်သည်။ ဒါက လုံခြုံရေးကို တိုးမြှင့်ပေးတယ်။ နောက်ထပ်အချက်အလက်များနှင့် ပံ့ပိုးပေးထားသောအက်ပ်များကို ဤနေရာတွင် လမ်းညွှန်တွင် တွေ့နိုင်ပါသည်။", - "setup_totp_recommended": "TOTP ကို ​​စနစ်ထည့်သွင်းပါ (အကြံပြုထားသည်)", + "setup_2fa_text": "ကိတ်မုန့် 2FA သည် TOTP ကို ဒုတိယ စစ်မှန်ကြောင်းအထောက်အထားအဖြစ် အသုံးပြု၍ လုပ်ဆောင်သည်။\n\nကိတ်မုန့် 2FA ၏ TOTP သည် SHA-512 နှင့် 8 ဂဏန်းပံ့ပိုးမှု လိုအပ်သည်။ ဒါက လုံခြုံရေးကို တိုးမြှင့်ပေးတယ်။ နောက်ထပ်အချက်အလက်များနှင့် ပံ့ပိုးပေးထားသောအက်ပ်များကို လမ်းညွှန်တွင် တွေ့နိုင်ပါသည်။", + "setup_totp_recommended": "TOTP စနစ်ထည့်သွင်းပါ။", "disable_buy": "ဝယ်ယူမှု လုပ်ဆောင်ချက်ကို ပိတ်ပါ။", "disable_sell": "ရောင်းချခြင်းလုပ်ဆောင်ချက်ကို ပိတ်ပါ။", "cake_2fa_preset": "ကိတ်မုန့် 2FA ကြိုတင်သတ်မှတ်", @@ -740,7 +740,7 @@ "unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။", "unspent_change": "ပေြာင်းလဲခြင်း", "tor_connection": "Tor ချိတ်ဆက်မှု", - "setup_warning_2fa_text": "ကိတ်မုန့် 2FA သည် ပိုက်ဆံအိတ်ရှိ အချို့သော လုပ်ဆောင်ချက်များ အတွက် ဒုတိယ စစ်မှန်ကြောင်း အထောက်အထား ဖြစ်သည်။ ၎င်းသည် အအေးခန်းကဲ့သို့ မလုံခြုံပါ။\n သင်၏ 2FA အက်ပ် သို့မဟုတ် သော့တံများကို အသုံးပြုခွင့် ဆုံးရှုံးပါက၊ သင်သည် ဤပိုက်ဆံအိတ်ကို အသုံးပြုခွင့် ဆုံးရှုံးမည်ဖြစ်သည်။\n သင့်ပိုက်ဆံအိတ်ကို mnemonic မျိုးစေ့မှ ပြန်လည်ရယူရန် လိုအပ်မည်ဖြစ်သည်။\n သင်သည် သင်၏ 2FA သို့မဟုတ် mnemonic အစေ့များကို အသုံးပြုခွင့်ဆုံးရှုံးသွားပါက ကိတ်မုန့်ပံ့ပိုးကူညီမှု မပေးနိုင်ပါ။ Cake 2FA ကို အသုံးမပြုမီ၊ လမ်းညွှန်ချက်မှတစ်ဆင့် ဖတ်ရန် အကြံပြုအပ်ပါသည်။", + "setup_warning_2fa_text": "ကိတ်မုန့် 2FA သည် ပိုက်ဆံအိတ်ရှိ အချို့သော လုပ်ဆောင်ချက်များ အတွက် ဒုတိယ စစ်မှန်ကြောင်း အထောက်အထား ဖြစ်သည်။ ၎င်းသည် အအေးခန်းကဲ့သို့ မလုံခြုံပါ။\n\nသင်၏ 2FA အက်ပ် သို့မဟုတ် TOTP သော့များကို အသုံးပြုခွင့် ဆုံးရှုံးပါက၊ သင်သည် ဤပိုက်ဆံအိတ်သို့ ဝင်ရောက်ခွင့် ဆုံးရှုံးမည်ဖြစ်သည်။ သင့်ပိုက်ဆံအိတ်ကို mnemonic မျိုးစေ့မှ ပြန်လည်ရယူရန် လိုအပ်မည်ဖြစ်သည်။\n\nသင်သည် သင်၏ 2FA သို့မဟုတ် mnemonic အစေ့များကို အသုံးပြုခွင့်ဆုံးရှုံးသွားပါက ကိတ်မုန့်ပံ့ပိုးကူညီမှု မပေးနိုင်ပါ။\nCake 2FA ကို အသုံးမပြုမီ၊ လမ်းညွှန်ချက်မှတစ်ဆင့် ဖတ်ရန် အကြံပြုအပ်ပါသည်။", "scan_qr_on_device": "အခြားစက်တွင် ဤ QR ကုဒ်ကို စကင်ဖတ်ပါ။", "how_to_use": "အသုံးပြုနည်း", "seed_hex_form": "ပိုက်ဆံအိတ်မျိုးစေ့ (Hex Form)", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index c588a8528..409aaeb49 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -627,8 +627,8 @@ "enter_totp_code": "Voer de TOTP-code in.", "add_secret_code": "Of voeg deze geheime code toe aan een authenticator-app", "totp_secret_code": "TOTP-geheime code", - "setup_2fa_text": "Cake 2FA werkt via TOTP als tweede authenticatiefactor.\n\nCake 2FA's TOTP vereist SHA-512 en 8-cijferige ondersteuning; dit zorgt voor meer veiligheid. Meer informatie en ondersteunde apps vindt u in de gids hier.", - "setup_totp_recommended": "TOTP instellen (aanbevolen)", + "setup_2fa_text": "Cake 2FA werkt met TOTP als tweede authenticatiefactor.\n\nCake 2FA's TOTP vereist SHA-512 en 8-cijferige ondersteuning; dit zorgt voor meer veiligheid. Meer informatie en ondersteunde apps vindt u in de gids.", + "setup_totp_recommended": "TOTP instellen", "disable_buy": "Koopactie uitschakelen", "disable_sell": "Verkoopactie uitschakelen", "auto_generate_subaddresses": "Automatisch subadressen genereren", @@ -742,7 +742,7 @@ "unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.", "unspent_change": "Wijziging", "tor_connection": "Tor-verbinding", - "setup_warning_2fa_text": "Cake 2FA is een tweede authenticatie voor bepaalde acties in de portemonnee. Het is NIET zo veilig als koude opslag.\n Als u de toegang tot uw 2FA-app of toegangscodes verliest, verliest u de toegang tot deze portemonnee.\n U moet uw portemonnee herstellen vanuit het geheugensteuntje.\n Cake Support kan u niet helpen als u de toegang tot uw 2FA- of mnemonic-zaden verliest. Voordat u Cake 2FA gebruikt, raden wij u aan de handleiding door te lezen.", + "setup_warning_2fa_text": "U moet uw portemonnee herstellen vanuit het geheugensteuntje.\n\nCake Support kan u niet helpen als u de toegang tot uw 2FA- of mnemonic-zaden verliest.\nCake 2FA is een tweede authenticatie voor bepaalde acties in de portemonnee. Voordat u Cake 2FA gebruikt, raden wij u aan de handleiding door te lezen.Het is NIET zo veilig als koude opslag.\n\nAls u de toegang tot uw 2FA-app of TOTP-sleutels verliest, verliest u de toegang tot deze portemonnee. ", "scan_qr_on_device": "Scan deze QR-code op een ander apparaat", "how_to_use": "Hoe te gebruiken", "seed_hex_form": "Portemonnee zaad (hexvorm)", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 452fadf8d..c5c8daf4e 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -627,8 +627,8 @@ "enter_totp_code": "Wprowadź kod TOTP.", "add_secret_code": "Możesz też dodać ten tajny kod do aplikacji uwierzytelniającej", "totp_secret_code": "Tajny kod TOTP", - "setup_2fa_text": "Cake 2FA działa poprzez TOTP jako drugi czynnik uwierzytelniający.\n\nTOTP Cake 2FA wymaga obsługi SHA-512 i 8 cyfr; zapewnia to większe bezpieczeństwo. Więcej informacji i obsługiwane aplikacje można znaleźć w przewodniku tutaj.", - "setup_totp_recommended": "Skonfiguruj TOTP (zalecane)", + "setup_2fa_text": "Cake 2FA działa przy użyciu TOTP jako drugiego czynnika uwierzytelniającego.\n\nTOTP Cake 2FA wymaga obsługi SHA-512 i 8 cyfr; zapewnia to większe bezpieczeństwo. Więcej informacji i obsługiwane aplikacje znajdziesz w przewodniku.", + "setup_totp_recommended": "Skonfiguruj TOTP", "disable_buy": "Wyłącz akcję kupna", "disable_sell": "Wyłącz akcję sprzedaży", "auto_generate_subaddresses": "Automatycznie generuj podadresy", @@ -742,7 +742,7 @@ "unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.", "unspent_change": "Zmiana", "tor_connection": "Połączenie Torem", - "setup_warning_2fa_text": "Cake 2FA to drugie uwierzytelnienie niektórych działań w portfelu. NIE jest tak bezpieczne jak przechowywanie w chłodni.\n Jeśli utracisz dostęp do aplikacji 2FA lub kluczy, UTRAcisz dostęp do tego portfela.\n Będziesz musiał przywrócić swój portfel z nasion mnemonicznych.\n Wsparcie Cake nie będzie w stanie Ci pomóc, jeśli utracisz dostęp do swoich nasion 2FA lub mnemoników. Przed użyciem Cake 2FA zalecamy zapoznanie się z instrukcją.", + "setup_warning_2fa_text": "Będziesz musiał przywrócić swój portfel z nasion mnemonicznych.\n\nWsparcie Cake nie będzie w stanie Ci pomóc, jeśli utracisz dostęp do swoich nasion 2FA lub mnemoników.\nCake 2FA to drugie uwierzytelnienie niektórych działań w portfelu. Przed użyciem Cake 2FA zalecamy zapoznanie się z instrukcją.NIE jest tak bezpieczne jak przechowywanie w chłodni.\n\nJeśli utracisz dostęp do aplikacji 2FA lub kluczy TOTP, UTRAcisz dostęp do tego portfela. ", "scan_qr_on_device": "Zeskanuj ten kod QR na innym urządzeniu", "how_to_use": "Jak używać", "seed_hex_form": "Nasiona portfela (forma sześciokątna)", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 5007d2ad3..979e7fe7c 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -626,8 +626,8 @@ "enter_totp_code": "Digite o código TOTP.", "add_secret_code": "Ou adicione este código secreto a um aplicativo autenticador", "totp_secret_code": "Código Secreto TOTP", - "setup_2fa_text": "Cake 2FA funciona através do TOTP como segundo fator de autenticação.\n\nO TOTP do Cake 2FA requer suporte SHA-512 e 8 dígitos; isso proporciona maior segurança. Mais informações e aplicativos suportados podem ser encontrados no guia aqui.", - "setup_totp_recommended": "Configurar TOTP (recomendado)", + "setup_2fa_text": "Cake 2FA funciona usando TOTP como segundo fator de autenticação.\n\nO TOTP do Cake 2FA requer suporte SHA-512 e 8 dígitos; isso proporciona maior segurança. Mais informações e aplicativos suportados podem ser encontrados no guia.", + "setup_totp_recommended": "Configurar TOTP", "disable_buy": "Desativar ação de compra", "disable_sell": "Desativar ação de venda", "auto_generate_subaddresses": "Gerar subendereços automaticamente", @@ -741,7 +741,7 @@ "unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.", "unspent_change": "Mudar", "tor_connection": "Conexão Tor", - "setup_warning_2fa_text": "Cake 2FA é uma segunda autenticação para determinadas ações na carteira. NÃO é tão seguro quanto o armazenamento refrigerado.\n Se você perder o acesso ao seu aplicativo 2FA ou às chaves de acesso, você perderá o acesso a esta carteira.\n Você precisará restaurar sua carteira a partir da semente mnemônica.\n O suporte do Cake não poderá ajudá-lo se você perder o acesso ao seu 2FA ou sementes mnemônicas. Antes de usar o Cake 2FA, recomendamos a leitura do guia.", + "setup_warning_2fa_text": "Você precisará restaurar sua carteira a partir da semente mnemônica.\n\nO suporte do Cake não poderá ajudá-lo se você perder o acesso ao seu 2FA ou sementes mnemônicas.\nCake 2FA é uma segunda autenticação para determinadas ações na carteira. Antes de usar o Cake 2FA, recomendamos a leitura do guia.NÃO é tão seguro quanto o armazenamento refrigerado.\n\nSe você perder o acesso ao seu aplicativo 2FA ou às chaves TOTP, você perderá o acesso a esta carteira. ", "scan_qr_on_device": "Digitalize este código QR em outro dispositivo", "how_to_use": "Como usar", "seed_hex_form": "Semente de carteira (forma hexadecimal)", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index c2c9c961d..a675cbb15 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -627,8 +627,8 @@ "enter_totp_code": "Пожалуйста, введите TOTP-код.", "add_secret_code": "Или добавьте этот секретный код в приложение для аутентификации.", "totp_secret_code": "Секретный код ТОТП", - "setup_2fa_text": "Cake 2FA работает через TOTP в качестве второго фактора аутентификации.\n\nTOTP Cake 2FA требует SHA-512 и поддержки 8 цифр; это обеспечивает повышенную безопасность. Дополнительную информацию и поддерживаемые приложения можно найти в руководстве здесь.", - "setup_totp_recommended": "Настроить TOTP (рекомендуется)", + "setup_2fa_text": "Cake 2FA работает с использованием TOTP в качестве второго фактора аутентификации.\n\nTOTP Cake 2FA требует SHA-512 и поддержки 8 цифр; это обеспечивает повышенную безопасность. Дополнительную информацию и поддерживаемые приложения можно найти в руководстве.", + "setup_totp_recommended": "Настройка ТОТП", "disable_buy": "Отключить действие покупки", "disable_sell": "Отключить действие продажи", "cake_2fa_preset": "Торт 2FA Preset", @@ -742,7 +742,7 @@ "unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.", "unspent_change": "Изменять", "tor_connection": "Тор соединение", - "setup_warning_2fa_text": "Cake 2FA — это вторая аутентификация для определенных действий в кошельке. Это НЕ так безопасно, как холодное хранение.\n Если вы потеряете доступ к своему приложению 2FA или паролям, вы потеряете доступ к этому кошельку.\n Вам нужно будет восстановить свой кошелек из мнемонического сида.\n Служба поддержки Cake не сможет вам помочь, если вы потеряете доступ к своим 2FA или мнемоническим идентификаторам. Прежде чем использовать Cake 2FA, мы рекомендуем прочитать руководство.", + "setup_warning_2fa_text": "Cake 2FA — это вторая аутентификация для определенных действий в кошельке. Это НЕ так безопасно, как холодное хранение.\n\nЕсли вы потеряете доступ к своему приложению 2FA или ключам TOTP, вы потеряете доступ к этому кошельку. Вам нужно будет восстановить свой кошелек из мнемонического сида.\n\nСлужба поддержки Cake не сможет вам помочь, если вы потеряете доступ к своим 2FA или мнемоническим идентификаторам.\nПрежде чем использовать Cake 2FA, мы рекомендуем прочитать руководство.", "scan_qr_on_device": "Отсканируйте этот QR-код на другом устройстве", "how_to_use": "Как использовать", "seed_hex_form": "Семя кошелька (шестнадцатеричная форма)", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index fecf0e4de..8ce9092fb 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -625,8 +625,8 @@ "enter_totp_code": "กรุณาใส่รหัสทีโอที", "add_secret_code": "หรือเพิ่มรหัสลับนี้ลงในแอปตรวจสอบความถูกต้อง", "totp_secret_code": "รหัสลับ TOTP", - "setup_2fa_text": "Cake 2FA ทำงานผ่าน TOTP เป็นปัจจัยการตรวจสอบสิทธิ์ที่สอง\n\nTOTP ของ Cake 2FA ต้องการการสนับสนุน SHA-512 และ 8 หลัก สิ่งนี้ให้ความปลอดภัยเพิ่มขึ้น สามารถดูข้อมูลเพิ่มเติมและแอปที่รองรับได้ในคำแนะนำที่นี่", - "setup_totp_recommended": "ตั้งค่า TOTP (แนะนำ)", + "setup_2fa_text": "Cake 2FA ทำงานโดยใช้ TOTP เป็นปัจจัยการตรวจสอบสิทธิ์ที่สอง\n\nTOTP ของ Cake 2FA ต้องการการสนับสนุน SHA-512 และ 8 หลัก สิ่งนี้ให้ความปลอดภัยเพิ่มขึ้น ข้อมูลเพิ่มเติมและแอปที่รองรับมีอยู่ในคำแนะนำ", + "setup_totp_recommended": "ตั้งค่า TOTP", "disable_buy": "ปิดการใช้งานการซื้อ", "disable_sell": "ปิดการใช้งานการขาย", "cake_2fa_preset": "เค้ก 2FA ที่ตั้งไว้ล่วงหน้า", @@ -740,7 +740,7 @@ "unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง", "unspent_change": "เปลี่ยน", "tor_connection": "การเชื่อมต่อทอร์", - "setup_warning_2fa_text": "Cake 2FA เป็นการรับรองความถูกต้องครั้งที่สองสำหรับการกระทำบางอย่างในกระเป๋าเงิน มันไม่ปลอดภัยเท่ากับห้องเย็น\n หากคุณสูญเสียการเข้าถึงแอป 2FA หรือรหัสผ่าน คุณจะสูญเสียการเข้าถึงกระเป๋าเงินนี้\n คุณจะต้องกู้คืนกระเป๋าเงินของคุณจากเมล็ดช่วยในการจำ\n การสนับสนุนเค้กจะไม่สามารถช่วยเหลือคุณได้หากคุณสูญเสียการเข้าถึง 2FA หรือเมล็ดช่วยในการจำ ก่อนใช้ Cake 2FA เราขอแนะนำให้อ่านคำแนะนำโดยละเอียด", + "setup_warning_2fa_text": "Cake 2FA เป็นการรับรองความถูกต้องครั้งที่สองสำหรับการกระทำบางอย่างในกระเป๋าเงิน มันไม่ปลอดภัยเท่ากับห้องเย็น\n\nหากคุณสูญเสียการเข้าถึงแอป 2FA หรือคีย์ TOTP คุณจะสูญเสียการเข้าถึงกระเป๋าเงินนี้ คุณจะต้องกู้คืนกระเป๋าเงินของคุณจากเมล็ดช่วยในการจำ\n\nการสนับสนุนเค้กจะไม่สามารถช่วยเหลือคุณได้หากคุณสูญเสียการเข้าถึง 2FA หรือเมล็ดช่วยในการจำ\nก่อนใช้ Cake 2FA เราขอแนะนำให้อ่านคำแนะนำโดยละเอียด", "scan_qr_on_device": "สแกนโค้ด QR นี้บนอุปกรณ์อื่น", "how_to_use": "วิธีใช้", "seed_hex_form": "เมล็ดกระเป๋าเงิน (รูปแบบฐานสิบหก)", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index e90191abc..84d0754d5 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -628,8 +628,8 @@ "enter_totp_code": "Mangyaring ipasok ang TOTP code.", "add_secret_code": "O, idagdag ang sikretong code na ito sa isang authenticator app", "totp_secret_code": "TOTP Secret Code", - "setup_2fa_text": "Gumagana ang Cake 2FA sa pamamagitan ng TOTP bilang pangalawang kadahilanan sa pagpapatunay.\n\nAng TOTP ng Cake 2FA ay nangangailangan ng SHA-512 at 8 digit na suporta; nagbibigay ito ng mas mataas na seguridad. Higit pang impormasyon at suportadong app ay matatagpuan sa gabay dito.", - "setup_totp_recommended": "I -set up ang TOTP (inirerekomenda)", + "setup_2fa_text": "Gumagana ang Cake 2FA gamit ang TOTP bilang pangalawang kadahilanan sa pagpapatunay.\n\nAng TOTP ng Cake 2FA ay nangangailangan ng SHA-512 at 8 digit na suporta; nagbibigay ito ng mas mataas na seguridad. Higit pang impormasyon at suportadong app ang makikita sa gabay.", + "setup_totp_recommended": "I-setup ang TOTP", "disable_buy": "Huwag paganahin ang pagkilos ng pagbili", "disable_sell": "Huwag paganahin ang pagkilos ng pagbebenta", "monero_dark_theme": "Monero Madilim na Tema", @@ -737,7 +737,7 @@ "unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.", "unspent_change": "Baguhin", "tor_connection": "Koneksyon ng Tor", - "setup_warning_2fa_text": "Ang Cake 2FA ay pangalawang pagpapatotoo para sa ilang partikular na pagkilos sa wallet. HINDI ito kasing-secure ng malamig na imbakan.\n Kung nawalan ka ng access sa iyong 2FA app o mga passkey, MAWAWALA ka ng access sa wallet na ito.\n Kakailanganin mong ibalik ang iyong wallet mula sa mnemonic seed.\n Hindi ka matutulungan ng suporta sa cake kung mawawalan ka ng access sa iyong 2FA o mnemonic seeds. Bago gamitin ang Cake 2FA, inirerekomenda naming basahin ang gabay.", + "setup_warning_2fa_text": "Kakailanganin mong ibalik ang iyong wallet mula sa mnemonic seed.\n\nHindi ka matutulungan ng suporta sa cake kung mawawalan ka ng access sa iyong 2FA o mnemonic seeds.\nAng Cake 2FA ay pangalawang pagpapatotoo para sa ilang partikular na pagkilos sa wallet. Bago gamitin ang Cake 2FA, inirerekomenda naming basahin ang gabay.HINDI ito kasing-secure ng malamig na imbakan.\n\nKung nawalan ka ng access sa iyong 2FA app o TOTP keys, MAWAWALA ka ng access sa wallet na ito. ", "scan_qr_on_device": "I-scan ang QR code na ito sa ibang device", "how_to_use": "Paano gamitin", "seed_hex_form": "Wallet seed (hex form)", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 89e042cda..6799ac585 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -625,8 +625,8 @@ "enter_totp_code": "Lütfen TOTP Kodunu giriniz.", "add_secret_code": "Veya bu gizli kodu bir kimlik doğrulama uygulamasına ekleyin", "totp_secret_code": "TOTP Gizli Kodu", - "setup_2fa_text": "Cake 2FA, ikinci kimlik doğrulama faktörü olarak TOTP üzerinden çalışır.\n\nCake 2FA'nın TOTP'si SHA-512 ve 8 haneli destek gerektirir; bu daha fazla güvenlik sağlar. Daha fazla bilgiyi ve desteklenen uygulamaları buradaki kılavuzda bulabilirsiniz.", - "setup_totp_recommended": "TOTP'yi kurun (Önerilir)", + "setup_2fa_text": "Cake 2FA, ikinci kimlik doğrulama faktörü olarak TOTP'yi kullanarak çalışır.\n\nCake 2FA'nın TOTP'si SHA-512 ve 8 haneli destek gerektirir; bu daha fazla güvenlik sağlar. Daha fazla bilgi ve desteklenen uygulamalar kılavuzda bulunabilir.", + "setup_totp_recommended": "TOTP'yi kur", "disable_buy": "Satın alma işlemini devre dışı bırak", "disable_sell": "Satış işlemini devre dışı bırak", "auto_generate_subaddresses": "Alt adresleri otomatik olarak oluştur", @@ -740,7 +740,7 @@ "unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.", "unspent_change": "Değiştirmek", "tor_connection": "Tor bağlantısı", - "setup_warning_2fa_text": "Cake 2FA, cüzdandaki belirli eylemler için ikinci bir kimlik doğrulamadır. Soğuk hava deposu kadar güvenli DEĞİLDİR.\n 2FA uygulamanıza veya şifre anahtarlarınıza erişiminizi kaybederseniz bu cüzdana erişimi KAYBEDECEKSİNİZ.\n Cüzdanınızı anımsatıcı tohumdan geri yüklemeniz gerekecek.\n 2FA veya anımsatıcı tohumlarınıza erişiminizi kaybederseniz pasta desteği size yardımcı olamayacaktır. Cake 2FA'yı kullanmadan önce kılavuzu okumanızı öneririz.", + "setup_warning_2fa_text": "Cüzdanınızı anımsatıcı tohumdan geri yüklemeniz gerekecek.\n\n2FA veya anımsatıcı tohumlarınıza erişiminizi kaybederseniz pasta desteği size yardımcı olamayacaktır.\nCake 2FA, cüzdandaki belirli eylemler için ikinci bir kimlik doğrulamadır. Cake 2FA'yı kullanmadan önce kılavuzu okumanızı öneririz.Soğuk hava deposu kadar güvenli DEĞİLDİR.\n\n2FA uygulamanıza veya TOTP anahtarlarınıza erişiminizi kaybederseniz bu cüzdana erişimi KAYBEDECEKSİNİZ. ", "scan_qr_on_device": "Bu QR kodunu başka bir cihazda tarayın", "how_to_use": "Nasıl kullanılır", "seed_hex_form": "Cüzdan tohumu (onaltılık form)", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index c250b6aeb..dfd996b2e 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -627,8 +627,8 @@ "enter_totp_code": "Будь ласка, введіть код TOTP.", "add_secret_code": "Або додайте цей секретний код до програми автентифікації", "totp_secret_code": "Секретний код TOTP", - "setup_2fa_text": "Cake 2FA працює через TOTP як другий фактор автентифікації.\n\nДля TOTP Cake 2FA потрібен SHA-512 і підтримка 8 цифр; це забезпечує підвищену безпеку. Додаткову інформацію та підтримувані програми можна знайти в посібнику тут.", - "setup_totp_recommended": "Налаштувати TOTP (рекомендовано)", + "setup_2fa_text": "Cake 2FA працює з використанням TOTP як другого фактора автентифікації.\n\nДля TOTP Cake 2FA потрібен SHA-512 і підтримка 8 цифр; це забезпечує підвищену безпеку. Додаткову інформацію та підтримувані програми можна знайти в посібнику.", + "setup_totp_recommended": "Налаштувати TOTP", "disable_buy": "Вимкнути дію покупки", "disable_sell": "Вимкнути дію продажу", "auto_generate_subaddresses": "Автоматично генерувати підадреси", @@ -742,7 +742,7 @@ "unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.", "unspent_change": "Зміна", "tor_connection": "Підключення Tor", - "setup_warning_2fa_text": "Cake 2FA — друга аутентифікація для певних дій у гаманці. Це НЕ так безпечно, як холодне зберігання.\n Якщо ви втратите доступ до своєї програми 2FA або ключів доступу, ви втратите доступ до цього гаманця.\n Вам потрібно буде відновити свій гаманець з мнемоніки.\n Служба підтримки Cake не зможе вам допомогти, якщо ви втратите доступ до 2FA або мнемонічних насадок. Перед використанням Cake 2FA рекомендуємо прочитати інструкцію.", + "setup_warning_2fa_text": "Cake 2FA — друга аутентифікація для певних дій у гаманці. Це НЕ так безпечно, як холодне зберігання.\n\nЯкщо ви втратите доступ до своєї програми 2FA або ключів TOTP, ви втратите доступ до цього гаманця. Вам потрібно буде відновити свій гаманець з мнемоніки.\n\nСлужба підтримки Cake не зможе вам допомогти, якщо ви втратите доступ до 2FA або мнемонічних насадок.\nПеред використанням Cake 2FA рекомендуємо прочитати інструкцію.", "scan_qr_on_device": "Відскануйте цей QR-код на іншому пристрої", "how_to_use": "Як використовувати", "seed_hex_form": "Насіння гаманця (шістнадцяткова форма)", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index f89835b6f..5809bf2ba 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -619,8 +619,8 @@ "enter_totp_code": "براہ کرم TOTP کوڈ درج کریں۔", "add_secret_code": " ۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮟﯿﻣ ﭗﯾﺍ ﮦﺪﻨﻨﮐ ﻖﯾﺪﺼﺗ ﻮﮐ ﮈﻮﮐ ﮧﯿﻔﺧ ﺱﺍ ،ﺎﯾ", "totp_secret_code": "TOTP خفیہ کوڈ", - "setup_2fa_text": " ۔ﮯﮨ ﺎﺗﺮﮐ ﻡﺎﮐ ﮯﻌﯾﺭﺫ ﮯﮐ TOTP ﺮﭘ ﺭﻮﻃ ﮯﮐ ﺮﺼﻨﻋ ﯽﻘﯾﺪﺼﺗ ﮮﺮﺳﻭﺩ 2FA ﮏﯿﮐ", - "setup_totp_recommended": "TOTP ترتیب دیں (تجویز کردہ)", + "setup_2fa_text": " ۔ﮯﮨ ﺎﺗﺮﮐ ﻡﺎﮐ ﮯﺋﻮﮨ ﮯﺗﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ ﺎﮐ TOTP ﺮﭘ ﺭﻮﻃ ﮯﮐ ﺮﺼﻨﻋ ﯽﻘﯾﺪﺼﺗ ﮮﺮﺳﻭﺩ 2FA ﮏﯿﮐ", + "setup_totp_recommended": "TOTP ۔ﮟﯾﺮﮐ ﭖﺍ ﭧﯿﺳ", "disable_buy": "خرید ایکشن کو غیر فعال کریں۔", "disable_sell": "فروخت کی کارروائی کو غیر فعال کریں۔", "cake_2fa_preset": "کیک 2FA پیش سیٹ", @@ -733,7 +733,7 @@ "unavailable_balance": "ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ", "unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ", "unspent_change": "تبدیل کریں", - "setup_warning_2fa_text": "۔ﮯﮨ ﮟﯿﮩﻧ ﻅﻮﻔﺤﻣ ﺡﺮﻃ ﯽﮐ ﺞﯾﺭﻮﭩﺳﺍ ﮉﻟﻮﮐ ﮧﯾ ۔ﮯﮨ ﻖﯾﺪﺼﺗ ﯼﺮﺳﻭﺩ ﮏﯾﺍ ﮯﯿﻟ ﮯﮐ ﮞﻮﯿﺋﺍﻭﺭﺭﺎﮐ ﺹﻮ", + "setup_warning_2fa_text": " ۔ﯽﮔﻮﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻧﺮﮐ ﻝﺎﺤﺑ ﻮﮐ ﮮﻮﭩﺑ ﮯﻨﭘﺍ ﮯﺳ ﺞﯿﺑ ﮯﮐ ﺖﺷﺍﺩﺩﺎﯾ ﻮﮐ ﭖﺁ", "scan_qr_on_device": " ۔ﮟﯾﺮﮐ ﻦﯿﮑﺳﺍ ﺮﭘ ﺲﺋﺍﻮﯾﮈ ﺭﻭﺍ ﯽﺴﮐ ﻮﮐ ﮈﻮﮐ QR ﺱﺍ", "how_to_use": " ﮧﻘﯾﺮﻃ ﺎﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ", "seed_hex_form": "پرس بیج (ہیکس فارم)", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 789253bd7..cc9e9116e 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -621,8 +621,8 @@ "enter_totp_code": "Jọwọ pọ koodu TOTP.", "add_secret_code": "Tabi, ṣafikun koodu aṣiri yii si ohun elo onijeri kan", "totp_secret_code": "Koodu iye TOTP", - "setup_2fa_text": "Akara oyinbo 2FA ṣiṣẹ nipasẹ TOTP bi ifosiwewe ijẹrisi keji.\n\nAkara oyinbo 2FA's TOTP nilo SHA-512 ati atilẹyin oni-nọmba 8; eyi pese aabo ti o pọ sii. Alaye diẹ sii ati awọn ohun elo atilẹyin ni a le rii ninu itọsọna naa Nibi.", - "setup_totp_recommended": "Sọ TOTP (Kẹṣọdọ)", + "setup_2fa_text": "Akara oyinbo 2FA ṣiṣẹ ni lilo TOTP bi ifosiwewe ijẹrisi keji.\n\nAkara oyinbo 2FA's TOTP nilo SHA-512 ati atilẹyin oni-nọmba 8; eyi pese aabo ti o pọ sii. Alaye diẹ sii ati awọn ohun elo atilẹyin ni a le rii ninu itọsọna naa.", + "setup_totp_recommended": "Ṣeto TOTP", "disable_buy": "Ko iṣọrọ ọja", "disable_sell": "Ko iṣọrọ iṣọrọ", "cake_2fa_preset": "Cake 2FA Tito", @@ -736,7 +736,7 @@ "unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.", "unspent_change": "Yipada", "tor_connection": "Tor asopọ", - "setup_warning_2fa_text": "Akara oyinbo 2FA jẹ ijẹrisi keji fun awọn iṣe kan ninu apamọwọ. Ko ṣe aabo bi ibi ipamọ tutu.\n Ti o ba padanu iraye si ohun elo 2FA tabi awọn bọtini iwọle, iwọ YOO padanu iraye si apamọwọ yii.\n Iwọ yoo nilo lati mu pada apamọwọ rẹ lati inu irugbin mnemonic.\n Atilẹyin akara oyinbo kii yoo ni anfani lati ṣe iranlọwọ fun ọ ti o ba padanu iraye si 2FA tabi awọn irugbin mnemonic rẹ. Ṣaaju lilo akara oyinbo 2FA, a ṣeduro kika nipasẹ itọsọna naa.", + "setup_warning_2fa_text": "Iwọ yoo nilo lati mu pada apamọwọ rẹ lati inu irugbin mnemonic.\n\nAtilẹyin akara oyinbo kii yoo ni anfani lati ṣe iranlọwọ fun ọ ti o ba padanu iraye si 2FA tabi awọn irugbin mnemonic rẹ.\nAkara oyinbo 2FA jẹ ijẹrisi keji fun awọn iṣe kan ninu apamọwọ. Ṣaaju lilo akara oyinbo 2FA, a ṣeduro kika nipasẹ itọsọna naa.Ko ṣe aabo bi ibi ipamọ tutu.\n\nTi o ba padanu iraye si ohun elo 2FA tabi awọn bọtini TOTP, iwọ YOO padanu iraye si apamọwọ yii. ", "scan_qr_on_device": "Ṣe ayẹwo koodu QR yii lori ẹrọ miiran", "how_to_use": "Bawo ni lati lo", "seed_hex_form": "Irú Opamọwọ apamọwọ (HOX)", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 336942d7a..aee2ed672 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -626,8 +626,8 @@ "enter_totp_code": "请输入 TOTP 代码。", "add_secret_code": "或者,将此密码添加到身份验证器应用程序中", "totp_secret_code": "TOTP密码", - "setup_2fa_text": "Cake 2FA 通过 TOTP 作为第二个身份验证因素。\n\nCake 2FA 的 TOTP 需要 SHA-512 和 8 位数字支持;这提供了更高的安全性。更多信息和支持的应用程序可以在此处的指南中找到。", - "setup_totp_recommended": "设置 TOTP(推荐)", + "setup_2fa_text": "Cake 2FA 使用 TOTP 作为第二个身份验证因素。\n\nCake 2FA 的 TOTP 需要 SHA-512 和 8 位数字支持;这提供了更高的安全性。更多信息和支持的应用程序可以在指南中找到。", + "setup_totp_recommended": "设置 TOTP", "disable_buy": "禁用购买操作", "disable_sell": "禁用卖出操作", "cake_2fa_preset": "蛋糕 2FA 预设", @@ -741,7 +741,7 @@ "unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。", "unspent_change": "改变", "tor_connection": "Tor连接", - "setup_warning_2fa_text": "Cake 2FA 是对钱包中某些操作的二次验证。它不如冷藏那么安全。\n 如果您无法访问 2FA 应用程序或密钥,您将无法访问此钱包。\n 您需要从助记词种子中恢复您的钱包。\n 如果您无法访问 2FA 或助记词种子,Cake 支持将无法为您提供帮助。在使用 Cake 2FA 之前,我们建议您阅读该指南。", + "setup_warning_2fa_text": "Cake 2FA 是对钱包中某些操作的二次验证。它不如冷藏那么安全。\n\n如果您无法访问 2FA 应用程序或 TOTP 密钥,您将无法访问此钱包。您需要从助记词种子中恢复您的钱包。\n\n如果您无法访问 2FA 或助记词种子,Cake 支持将无法为您提供帮助。\n在使用 Cake 2FA 之前,我们建议您阅读该指南。", "scan_qr_on_device": "在另一台设备上扫描此二维码", "how_to_use": "如何使用", "seed_hex_form": "钱包种子(十六进制形式)", From 31530dd566bd1f3bc329e685d93b56d7472ac714 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 14 Dec 2023 14:11:07 +0200 Subject: [PATCH 075/241] fix UI issues --- lib/src/screens/setup_2fa/setup_2fa.dart | 2 +- lib/src/screens/setup_2fa/setup_2fa_qr_page.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/screens/setup_2fa/setup_2fa.dart b/lib/src/screens/setup_2fa/setup_2fa.dart index d38de1f8c..3e175fe67 100644 --- a/lib/src/screens/setup_2fa/setup_2fa.dart +++ b/lib/src/screens/setup_2fa/setup_2fa.dart @@ -71,7 +71,7 @@ class Setup2FAPage extends BasePage { static void _launchUrl(Uri url) async { try { - await launchUrl(url); + await launchUrl(url, mode: LaunchMode.externalApplication); } catch (e) {} } } 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 408e9e14d..86fabae13 100644 --- a/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart +++ b/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart @@ -53,7 +53,7 @@ class Setup2FAQRPage extends BasePage { decoration: BoxDecoration( border: Border.all( width: 3, - color: Theme.of(context).extension()!.textColor, + color: Theme.of(context).extension()!.titleColor, ), ), child: Container( @@ -212,7 +212,7 @@ class Setup2FAQRPage extends BasePage { static void _launchUrl(Uri url) async { try { - await launchUrl(url); + await launchUrl(url, mode: LaunchMode.externalApplication); } catch (e) {} } } From d0e28b58ac7f8cbbb733d217d3ecbed65434d2f4 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 14 Dec 2023 14:51:52 +0200 Subject: [PATCH 076/241] [skip ci] update icon --- assets/images/setup_2fa_img.png | Bin 20129 -> 58037 bytes lib/src/screens/setup_2fa/setup_2fa.dart | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/images/setup_2fa_img.png b/assets/images/setup_2fa_img.png index 3df3bdaddaa907f7d908892dd15d3978db38519c..ce6f0d7333b5208a324d3c3b069b35534ce14a56 100644 GIT binary patch literal 58037 zcmd3Ng;!h6^EXhO7B8+LI20=scXuaHq`}?26b<%)R@W*`1l4nT^&|S9pU>fsKTO^hQZhRvQTk1%!n33L6s@ap%JHoEGti z<*I1tfrNxZ^xuVyl#@q>xQSw}q9BX(5}7#GjfAvms3a?;>$`Yl;uTENPx)0O!5LKv z8CeSGh+3+pjSu8NC6L9}rI3=8l$LIjl5T4!MlGG8U13~V!7vu>mPios_V)3%Y3|Cg zd490A@$UX&^EKaR_l-0VD2xBR>k-fX!)3O8?Q~ctDjaf%|L98JpSZKhV~cS+OR67E??^tnU4yzz0sP9=JYt{t{)Wo*iokq6*t1~kF5*?%mULG`ir->oW2eJU zu-LV4o-53Uu&1Is*uvTA2{@wY%7!$yX`fcABI?4|J>ox#UCeT2>x@7YoNz@v_a33PQ!%jET<6Q%ry7mq z5LxFj6-87e?9{K@h0~rJpW!i6oiBPN0)t8t=P^|HgoMv+)$SqHo65L|*Ph40ioH&P zes$~+oD;DEF(M(57dlQmspfVi(k^Bw*~)|2o>O=JduF?B$>gL{{*k1r?XIQ&y>+(p z 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 KMNUMnLSTZS4`lKH literal 20129 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 Date: Thu, 14 Dec 2023 18:41:43 +0200 Subject: [PATCH 077/241] Format code --- lib/src/screens/seed/warning_page.dart | 25 ++++++--- .../screens/setup_2fa/setup_2fa_qr_page.dart | 56 +++++++++++++------ 2 files changed, 54 insertions(+), 27 deletions(-) diff --git a/lib/src/screens/seed/warning_page.dart b/lib/src/screens/seed/warning_page.dart index f29f69a05..18b9b6248 100644 --- a/lib/src/screens/seed/warning_page.dart +++ b/lib/src/screens/seed/warning_page.dart @@ -21,7 +21,8 @@ class WarningPage extends BasePage { final bool isPreSeedPage; @override - Widget? leading(BuildContext context) => isPreSeedPage ? null : super.leading(context); + Widget? leading(BuildContext context) => + isPreSeedPage ? null : super.leading(context); @override String? get title => S.current.pre_seed_title; @@ -36,14 +37,15 @@ class WarningPage extends BasePage { alignment: Alignment.center, padding: EdgeInsets.all(24), child: ConstrainedBox( - constraints: - BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), + constraints: BoxConstraints( + maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: ConstrainedBox( - constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.3), + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context).size.height * 0.3), child: AspectRatio(aspectRatio: 1, child: image), ), ), @@ -52,20 +54,25 @@ class WarningPage extends BasePage { padding: EdgeInsets.all(10), child: Text( isPreSeedPage - ? S.of(context).pre_seed_description(seedPhraseLength.toString()) + ? S.of(context).pre_seed_description( + seedPhraseLength.toString()) : S.of(context).setup_warning_2fa_text, textAlign: TextAlign.center, style: TextStyle( - height: 1.7, + height: 1.7, fontSize: 14, fontWeight: FontWeight.normal, - color: Theme.of(context).extension()!.secondaryTextColor)), + color: Theme.of(context) + .extension()! + .secondaryTextColor)), ), ), PrimaryButton( onPressed: () => isPreSeedPage - ? Navigator.of(context).popAndPushNamed(Routes.seed, arguments: true) - : Navigator.of(context).popAndPushNamed(Routes.setup_2faPage), + ? Navigator.of(context) + .popAndPushNamed(Routes.seed, arguments: true) + : Navigator.of(context) + .popAndPushNamed(Routes.setup_2faPage), text: isPreSeedPage ? S.of(context).pre_seed_button_text : S.of(context).understand, 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 86fabae13..3ce10b596 100644 --- a/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart +++ b/lib/src/screens/setup_2fa/setup_2fa_qr_page.dart @@ -26,7 +26,9 @@ class Setup2FAQRPage extends BasePage { @override Widget body(BuildContext context) { final copyImage = Image.asset('assets/images/copy_content.png', - height: 16, width: 16, color: Theme.of(context).extension()!.titleColor); + height: 16, + width: 16, + color: Theme.of(context).extension()!.titleColor); final cake2FAHowToUseUrl = Uri.parse( 'https://guides.cakewallet.com/docs/advanced-features/authentication/#enabling-cake-2fa'); return Padding( @@ -45,7 +47,8 @@ class Setup2FAQRPage extends BasePage { ), SizedBox(height: 10), ConstrainedBox( - constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.4), + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context).size.height * 0.4), child: AspectRatio( aspectRatio: 1.0, child: Container( @@ -53,14 +56,17 @@ class Setup2FAQRPage extends BasePage { decoration: BoxDecoration( border: Border.all( width: 3, - color: Theme.of(context).extension()!.titleColor, + color: Theme.of(context) + .extension()! + .titleColor, ), ), child: Container( child: QrImage( data: setup2FAViewModel.totpVersionOneLink, version: qr.QrVersions.auto, - foregroundColor: Theme.of(context).extension()!.titleColor, + foregroundColor: + Theme.of(context).extension()!.titleColor, backgroundColor: Colors.transparent, )), ), @@ -90,7 +96,9 @@ class Setup2FAQRPage extends BasePage { style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, - color: Theme.of(context).extension()!.secondaryTextColor, + color: Theme.of(context) + .extension()! + .secondaryTextColor, height: 1.8333, ), ), @@ -99,7 +107,9 @@ class Setup2FAQRPage extends BasePage { '${setup2FAViewModel.totpSecretKey}', style: TextStyle( fontSize: 18, - color: Theme.of(context).extension()!.titleColor), + color: Theme.of(context) + .extension()! + .titleColor), maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -112,8 +122,8 @@ class Setup2FAQRPage extends BasePage { height: 32, child: InkWell( onTap: () { - ClipboardUtil.setSensitiveDataToClipboard( - ClipboardData(text: '${setup2FAViewModel.totpSecretKey}')); + ClipboardUtil.setSensitiveDataToClipboard(ClipboardData( + text: '${setup2FAViewModel.totpSecretKey}')); showBar(context, S.of(context).copied_to_clipboard); }, child: Container( @@ -140,7 +150,9 @@ class Setup2FAQRPage extends BasePage { style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, - color: Theme.of(context).extension()!.secondaryTextColor, + color: Theme.of(context) + .extension()! + .secondaryTextColor, height: 1.8333, ), ), @@ -149,7 +161,9 @@ class Setup2FAQRPage extends BasePage { '${setup2FAViewModel.totpVersionOneLink}', style: TextStyle( fontSize: 18, - color: Theme.of(context).extension()!.titleColor), + color: Theme.of(context) + .extension()! + .titleColor), maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -162,8 +176,8 @@ class Setup2FAQRPage extends BasePage { height: 32, child: InkWell( onTap: () { - ClipboardUtil.setSensitiveDataToClipboard( - ClipboardData(text: '${setup2FAViewModel.totpVersionOneLink}')); + ClipboardUtil.setSensitiveDataToClipboard(ClipboardData( + text: '${setup2FAViewModel.totpVersionOneLink}')); showBar(context, S.of(context).copied_to_clipboard); }, child: Container( @@ -187,18 +201,24 @@ class Setup2FAQRPage extends BasePage { decoration: TextDecoration.underline, fontSize: 16, fontWeight: FontWeight.w500, - color: Theme.of(context).extension()!.titleColor)), + color: Theme.of(context) + .extension()! + .titleColor)), Icon(Icons.info_outline, - size: 20, color: Theme.of(context).extension()!.titleColor) + size: 20, + color: Theme.of(context) + .extension()! + .titleColor) ], )), Spacer(flex: 5), PrimaryButton( onPressed: () { - Navigator.of(context).pushReplacementNamed(Routes.totpAuthCodePage, - arguments: TotpAuthArgumentsModel( - isForSetup: true, - )); + Navigator.of(context) + .pushReplacementNamed(Routes.totpAuthCodePage, + arguments: TotpAuthArgumentsModel( + isForSetup: true, + )); }, text: S.current.continue_text, color: Theme.of(context).primaryColor, From b316f2fc7b9c01a7f60406725d00051e2550a6d2 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 15 Dec 2023 17:19:50 +0200 Subject: [PATCH 078/241] minor fixes --- lib/src/screens/seed/warning_page.dart | 2 +- lib/src/screens/setup_2fa/setup_2fa.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/screens/seed/warning_page.dart b/lib/src/screens/seed/warning_page.dart index 18b9b6248..5df55ad5e 100644 --- a/lib/src/screens/seed/warning_page.dart +++ b/lib/src/screens/seed/warning_page.dart @@ -72,7 +72,7 @@ class WarningPage extends BasePage { ? Navigator.of(context) .popAndPushNamed(Routes.seed, arguments: true) : Navigator.of(context) - .popAndPushNamed(Routes.setup_2faPage), + .pushNamed(Routes.setup_2faPage), text: isPreSeedPage ? S.of(context).pre_seed_button_text : S.of(context).understand, diff --git a/lib/src/screens/setup_2fa/setup_2fa.dart b/lib/src/screens/setup_2fa/setup_2fa.dart index de2350c37..5fa5cabb8 100644 --- a/lib/src/screens/setup_2fa/setup_2fa.dart +++ b/lib/src/screens/setup_2fa/setup_2fa.dart @@ -14,7 +14,7 @@ class Setup2FAPage extends BasePage { final Setup2FAViewModel setup2FAViewModel; @override - String get title => 'CAKE 2FA'; + String get title => 'Cake 2FA'; @override Widget body(BuildContext context) { From d756b367d3f703e909ca4e3f083fc7be009ccc14 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Sat, 16 Dec 2023 03:20:56 +0200 Subject: [PATCH 079/241] Make the exchange receive field always editable and can be taken from QR or Address book (#1230) --- lib/src/screens/exchange/exchange_page.dart | 5 ----- lib/src/screens/exchange/exchange_template_page.dart | 7 ------- lib/src/screens/exchange/widgets/exchange_card.dart | 2 +- lib/view_model/exchange/exchange_view_model.dart | 8 -------- 4 files changed, 1 insertion(+), 21 deletions(-) diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 1f441ea99..b3fbd19a7 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -411,10 +411,6 @@ class ExchangePage extends BasePage { } }); - reaction((_) => exchangeViewModel.isReceiveAddressEnabled, (bool isEnabled) { - receiveKey.currentState!.isAddressEditable(isEditable: isEnabled); - }); - reaction((_) => exchangeViewModel.isReceiveAmountEditable, (bool isReceiveAmountEditable) { receiveKey.currentState!.isAmountEditable(isEditable: isReceiveAmountEditable); }); @@ -670,7 +666,6 @@ class ExchangePage extends BasePage { ? exchangeViewModel.wallet.walletAddresses.address : exchangeViewModel.receiveAddress, initialIsAmountEditable: exchangeViewModel.isReceiveAmountEditable, - initialIsAddressEditable: exchangeViewModel.isReceiveAddressEnabled, isAmountEstimated: true, isMoneroWallet: exchangeViewModel.isMoneroWallet, currencies: exchangeViewModel.receiveCurrencies, diff --git a/lib/src/screens/exchange/exchange_template_page.dart b/lib/src/screens/exchange/exchange_template_page.dart index 31f35661d..3a7456dd8 100644 --- a/lib/src/screens/exchange/exchange_template_page.dart +++ b/lib/src/screens/exchange/exchange_template_page.dart @@ -174,8 +174,6 @@ class ExchangeTemplatePage extends BasePage { ? exchangeViewModel.wallet.walletAddresses.address : exchangeViewModel.receiveAddress, initialIsAmountEditable: false, - initialIsAddressEditable: - exchangeViewModel.isReceiveAddressEnabled, isAmountEstimated: true, isMoneroWallet: exchangeViewModel.isMoneroWallet, currencies: exchangeViewModel.receiveCurrencies, @@ -328,11 +326,6 @@ class ExchangeTemplatePage extends BasePage { } }); - reaction((_) => exchangeViewModel.isReceiveAddressEnabled, - (bool isEnabled) { - receiveKey.currentState!.isAddressEditable(isEditable: isEnabled); - }); - reaction((_) => exchangeViewModel.provider, (ExchangeProvider? provider) { receiveKey.currentState!.isAmountEditable(isEditable: false); }); diff --git a/lib/src/screens/exchange/widgets/exchange_card.dart b/lib/src/screens/exchange/widgets/exchange_card.dart index b55e96e85..706ace7de 100644 --- a/lib/src/screens/exchange/widgets/exchange_card.dart +++ b/lib/src/screens/exchange/widgets/exchange_card.dart @@ -23,7 +23,6 @@ class ExchangeCard extends StatefulWidget { required this.initialAddress, required this.initialWalletName, required this.initialIsAmountEditable, - required this.initialIsAddressEditable, required this.isAmountEstimated, required this.currencies, required this.onCurrencySelected, @@ -31,6 +30,7 @@ class ExchangeCard extends StatefulWidget { this.currencyValueValidator, this.addressTextFieldValidator, this.title = '', + this.initialIsAddressEditable = true, this.hasRefundAddress = false, this.isMoneroWallet = false, this.currencyButtonColor = Colors.transparent, diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index fb7019885..afe617803 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -66,7 +66,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with receiveAddress = '', depositAddress = '', isDepositAddressEnabled = false, - isReceiveAddressEnabled = false, isReceiveAmountEditable = false, _useTorOnly = false, receiveCurrencies = [], @@ -108,7 +107,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with bestRateSync = Timer.periodic(Duration(seconds: 10), (timer) => _calculateBestRate()); isDepositAddressEnabled = !(depositCurrency == wallet.currency); - isReceiveAddressEnabled = !(receiveCurrency == wallet.currency); depositAmount = ''; receiveAmount = ''; receiveAddress = ''; @@ -201,9 +199,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with @observable bool isDepositAddressEnabled; - @observable - bool isReceiveAddressEnabled; - @observable bool isReceiveAmountEntered; @@ -315,7 +310,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with isFixedRateMode = false; _onPairChange(); isDepositAddressEnabled = !(depositCurrency == wallet.currency); - isReceiveAddressEnabled = !(receiveCurrency == wallet.currency); } @action @@ -324,7 +318,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with isFixedRateMode = false; _onPairChange(); isDepositAddressEnabled = !(depositCurrency == wallet.currency); - isReceiveAddressEnabled = !(receiveCurrency == wallet.currency); } @action @@ -535,7 +528,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with depositAddress = depositCurrency == wallet.currency ? wallet.walletAddresses.address : ''; receiveAddress = receiveCurrency == wallet.currency ? wallet.walletAddresses.address : ''; isDepositAddressEnabled = !(depositCurrency == wallet.currency); - isReceiveAddressEnabled = !(receiveCurrency == wallet.currency); isFixedRateMode = false; _onPairChange(); } From be285e7ebf9b65101c9688f620895ad7ba6b3c32 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Tue, 19 Dec 2023 15:16:15 +0200 Subject: [PATCH 080/241] V4.12.0 v1.9.0 (#1236) * update app versions and release notes * update build number * Fix balance page tabs UI on white screens [skip ci] * Vulnerable btc seeds (#1238) * Add flow to notify users with vulnerable seeds * - Show vulnerable wallets warning on every app launch - Change text * increment build number * add seeds sha text [skip ci] --- assets/text/Monerocom_Release_Notes.txt | 6 +- assets/text/Release_Notes.txt | 9 +- ...k_bitcoin_seeds_hashed_sorted_version1.txt | 8717 +++++++++++++++++ ios/Podfile.lock | 12 +- lib/di.dart | 7 +- lib/src/screens/dashboard/dashboard_page.dart | 24 +- .../dashboard/desktop_dashboard_page.dart | 21 + .../screens/dashboard/pages/balance_page.dart | 18 + lib/src/widgets/vulnerable_seeds_popup.dart | 91 + .../dashboard/dashboard_view_model.dart | 49 +- scripts/android/app_env.sh | 8 +- scripts/ios/app_env.sh | 8 +- scripts/macos/app_env.sh | 4 +- 13 files changed, 8945 insertions(+), 29 deletions(-) create mode 100644 assets/text/cakewallet_weak_bitcoin_seeds_hashed_sorted_version1.txt create mode 100644 lib/src/widgets/vulnerable_seeds_popup.dart diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 90be3b8e8..9b6348a76 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,2 +1,4 @@ -Monero Polyseed support, create and restore from a 16 words phrase and without the need to remember the wallet creation date -Bug fixes and enhancements \ No newline at end of file +Polyseed enhancements +New on-ramp provider DFX +Usability enhancements +Bug fixes \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 655d59a7d..87d1e1747 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,3 +1,6 @@ -Monero Polyseed support, create and restore from a 16 words phrase and without the need to remember the wallet creation date -Add NFTs tab to see all of your purchased NFTs on Ethereum -Bug fixes and enhancements \ No newline at end of file +Add Polygon (Matic) wallet +Polyseed enhancements +New on-ramp provider DFX +Usability enhancements +Bitcoin enhancements +Bug fixes \ No newline at end of file diff --git a/assets/text/cakewallet_weak_bitcoin_seeds_hashed_sorted_version1.txt b/assets/text/cakewallet_weak_bitcoin_seeds_hashed_sorted_version1.txt new file mode 100644 index 000000000..de54473f7 --- /dev/null +++ b/assets/text/cakewallet_weak_bitcoin_seeds_hashed_sorted_version1.txt @@ -0,0 +1,8717 @@ +000039088e7635bd3d088ff0376a2c12b3d14fc2714f3126f1b2f4c8cf919dcd +00010e2247ac2a27a3f266e1f7354b523e368e3790fab7529bb29d29b2264189 +000447f29779b8c3893421a796abd089a2fc9cc50297467be733ca64d5c3cb70 +00044d7e25a645f5da26bcb906df1aeb5ef35e1c86582579561240311bf8ccf5 +00090cb1f4794070340b8e6ba697711ff59545175b1acb69980a7f0c14f3e6a0 +000afe48e10afc15299e54e7ac3dec1cd6957903067eebc8424f68eb666f3790 +000f01e767f12f7e392693854b4e5e5cd79bc847fded720aaaefe885e00279d6 +001a911b00e9f1f201982ff86df75bbf718c46b0e441cda527a634cdf1186bcb +001d490eb469e0e93089485e7dbf477e872b24c680209f762d3501a8067f71be +0021a875205e02f95cf0f5fa2cb435c950f77a3c27e342afabc28c2aae2a7766 +00262b5e3444d083d2772b12b320f28c499f49a218d1e16af1a72f0221718554 +00289954798211fbdc5ae10303cc17ef5649068f12ced8ca73ba229896993fc2 +0028a1567f9a4a6c619db76dc9ff622d9e177848ea5c89413770426d0a705e7e +002cdc7c708744cffa707f5e161c64bcda06afeef254e730f28be35e1d866df0 +00472c6d9f5bcbedaff69723326965247d76dae59d0a8dfa3c888ff894ef96b9 +004ada6c6d9fbf968aaca13f9d3bc53c57dea45cf06b7a805c401375eac232ef +0051652606bbbefa01e6ff5abc69e785b7588263708690b06d85aca365000d70 +0053b9fc7ac7828051bf0d38d4e77f8920e80787e5eb316019ad7a700b0d8077 +0066a62953fe7aa63a0bd28796fffb1b6c888e337403f830747403be4a05792c +0066cb182adf7a9f3bf8ab07d6342c6f701f3e9cbd19fb09b67bd44f07b8fc61 +006f72695184e9f4eb694ea41049c0bcb43031ba396cc651f2e526b340e35e10 +0073dbc1905143eee9355dbb172930ff40bcaa07f4194128df88b415da0c9b63 +00748efa0448e91376bb58fff14eda5163e5d6f601b23a108a50a92261d8d8bc +00750a3efd0bb937a0a4abb99c4dad594c390ebc9cb09582b04be8b9539f1fdc +0077ff20158828edbac74a0c7ea8295201f8cf96a85bd39841e9afd49c884f5e +007a65ea4c15ef9a397fbbfa0bae4a4b5c58e53071102fb38f6b0f9f5f402032 +0084939fd209a3b90a1e09b69896de6cdddca9780cbf57b9379cad6ae3797636 +0090c2bdeedd129e587cc3dea4b744ffec9f5c2f7e7708e9df86ccc66e3adcf5 +0092e1c7c3dab725117d3f61b07be9d50b2f067434016680438dec20a079fdba +00c78b47ab7b699aefa6c78b0b045ffb7d99bbe7025da177b67803ad82259b8b +00cf7c07b20281c171a68dca3d517981ccb5823f5ea273a3e9bb218705e59f63 +00d71b0bb4ad85b33d62bf115b418a07b329dbe33dee1a9a93b016b67e4527b6 +00dcaa01b15b706918dd3a27dc0b1290cbe61d350d294ba8b5fb48b96fcd8a3f +00dda82b6b7ffb87052937555e6e5073ad5d3c492c4576de1a92c63948d7efc2 +00ecb86087cb1cc6ff59b4e6ea9394398ba12b10b48577dddc5e872940b11ab8 +00f16eb82cd88b72c0fe5a06661cd1f00e4f450eaa2a07fcda91d98b51b7de7f +00f57f9002890152916ab46b3d91f60f14d239e0b48b96f13374790fefb5f537 +00fdadc62e1139a21a0e0edf8bbb7d8e2c0c670831a98efd6a4d05ffae8664c2 +0103850d9fd1bd01510b026a795ee970619056ded7aac6df740d7625c5b41764 +0107338c9d85387be3e309dbb84569261d181b41f4aa693c3724981d6b99f494 +010986b900d45a5b2cf85e40ea783a35c90f0bb6cce682f4f2655d0975511077 +010aa6990557df1746703831acfeacb9e63db28109150cfb20d1b891da0839d9 +01198dbdca402406c23dcb946657a0743fd8966cb945bc4c0896931beb377900 +011a9c580fa0e7d69a177dfee0a7676e539ddc75e434617815c32282ac921866 +011ab37f89d19a791833ebf4c9c68fc1b2e02b0fae970d4502bb1c1de58cb816 +0121f8045225d48b8100e2fcc5c88f6b9e595cc8696450b8f24d92ee56b5b788 +012afda7d24835561f52770a3b7857db41f236878912fbeeb2cae712f5dd6a7b +013432372532de946523c91ebf29a358527f76c97d57f7dcd34ca1329993e0c1 +0135089b5f09fe3f68b796e9f3c5b7db1bf26de6f8f97e28824bc635f4d6b005 +0141fe7684497b1b5aa4d95776ba82f11614c357c99ba30c9b6117e54c50c623 +01436e653b2f03faaf845097e59174fca7fda63125fa68f44d2b40451a1ef340 +014391a1e04420975d3bbce0dd18797a7140433645ba892eb028e085d78d6b6f +015eba92a710c4e4b538f2d069c00da555bf57f8c38c4bd9afef9f37460383fd +01638e9d9c7dd0c49642514daa1076c9555b55c888b6dbb7efda2b54c927d36e +01649b21d9a781b778c80df37d59ef31de2bc5d45a2a80eb7bb8f788ef5a921d +016d30c1a01b24e780d28f6c552856936c643dca57d19dd20c00663894a8b2be +017b3056e5e7f90c72cab3d4c555fc3533217eb37b82cbdf4e796826c4653b05 +0184e29e10dc106cb2f5fa52da7d752a0c9bb8a4519576a8f6a7874c31878609 +0187025704e4b57dfeb0fc07948cc076c12c94635cb1d7c02c8d8f603bc2f325 +018a424338c2328f74de393628bd0d9e3306467d4cd6509bbdced15e6e1b05ee +0192a84c09abf17df69d7f07dcefdf658975b9dba98825ff3b64953c79823705 +0194437ef12f044f97106274940b681e816bfcdbd62345af13f8bfc1961add48 +019657da7cebdf8cd531a3874c924ba242b1bc2b7d863694de56a7f3b23240c3 +01ab967755e6f57d20eb7faafe6d28810b71788383b72d4a0ed6ad74c6cab51d +01abb622e29219767d909b038fa8ce7f4ba874ab0c14f71c111dd99aa714a572 +01b4e4ee78093925a73efc586c62db0a23eabdd0378aa2a109d2119a3437e7ab +01b6dbfac01fd182530f6e535e7f2f0da8f0dffa00006f5976b79f10ad6eb6a4 +01cdef7c54a1b8bcc91ea251cb89b0f88ab878c89dd08560485c8bf3438775f1 +01ce7b781636bed03a443549985215cb85f190dfb250872b443c436b61f14141 +01d91a3ac1c3f26e76bdff719b321ffe9fceb41a8fc5e1546a799632a1bae9f8 +01e65b9cf686a20207543a38a941fe6f593e0c7b21bfe4fdbfbd8722781c1284 +01e9b6850ef3b0f450652c7ef6c9a6939b78ac8c55b4b64274f7552af5e85f8a +01f01a1ae0983ae1d7d64858c6cdec0661fbcde54ebba7c05e88c4870a0f92fa +01f16ecd75c67e1b459aabed7c8dc3cbaf1e25d5fd3079b38dea7eba0ebc439b +01f5bb39e1a2efcd688db104f5d05b2b5f9f23a84fdc335545ee04e38e66f894 +02028d8ed82d2db379588bf14e48805adca0ce70104d4664230f333120105ea7 +02114ddefdcaf6d100e499fb3392967ab21da7e5cd1c01271822dd73dbb54e31 +021482b4e8ffc2906b2180d532213d1f197b02f6aaacc74580d2dbf07a4b6179 +0215e9c94001069afa2da537d68e09c5b5aba1bb36ac4fded93375702b45800f +0217ab4904ac9242722212bca9d460e05d99c5cba65ad096ac6dc552cecdd00e +02184ab24fcd25abce582bd6699b09e7ec7a2ce67188286b214596ee06bdb625 +021b58ed0ae7c1adc45f34aff3e338878641869fe241c115b562b8ef54bd33db +021ed0da8e92760cde50963654b23b53bf2496a89e08e93e61c101f040de11c0 +02256240ff566cfe79c676bbc773693c64672febcdd6aa6ea504b9bbd3b09996 +0225e5d9cdcc11c2c0837a44ef6a6bd7751d86503d9d301733ba2647c93af55b +02309f00b3243374a78972da1ff7df51f09e3cbe465ea3bc280e3e8db6d55e9a +02432a4134afd8c6be9844b446b3aaeecb98daef35beb89d0d0a5ab9739d4fb7 +02460db9708ac93ed17260bf81a7bfc12bcc24d52822ec277bae3d50b4c2ab0e +024b1aa80da00a026d776de396406b4e2bb7559ad312bf76fb8c144eaea7aca4 +02509d3516f8939ce59f3b6d29de933db4a21829d400f3c11240a1e60f01e376 +025b2edd014aa4b3ae16fdab8dc8b79a168eaf72af58bc71cbe65a9a6b0c0e13 +025b8747f8afc6e3cd281694025526684d6cf5091a22b89ce8e40ca8d60d3971 +0263fcbbcfc4f256579530fef1709f1a9c5ca9be886064d9d5dd57373631ad44 +027cdc52eff0c7114e82ac62d642300fc3143cdaa7e412f606248021bad81028 +028661ba0d98ebc3b8f3da7ed3da5d08bc58554dc231713f6f0fba366d4de056 +0293513ed8ceefc6529c51eac76fc297187f77abb1ad3b6dbc288e8b43ca7a4b +0298600936f3b6476d5900d3519ec197d16560af6f0108451dc9bd63298e8c70 +02999f15b404ad494ab5273e3d3eaef3dac0092f05849911e2808346c4cde5a7 +029a7b64570c3ceade3aa2e71c4e69059346789ca4953983dbf9d1b294c8ffbd +029b7b3640a35f2db6ce4de9b215a4c9c8f9d0bbbc0a7312fabc5012cf6cb0f0 +02a11a3d3aa640d840c7789761b3b06b7fbb9cc00534d79867f8914e59ef9654 +02a51316deb0764356c7d248084c305f8a10580035d2c56ec35c87213f1ef172 +02a9f55f904675179ababdfd0e72dee783cdc6fd22bb0b7ef7be9d8942155cf2 +02b65a80f14e88037656080865d38d39ca41194f1654adcbe36f41b8ef62bdd3 +02c3f217606a01eca39264f7a2da194737d42dec5b790617ffe8420a87552828 +02c92345c1095abb0d41233b694af05f39bff45782aa47b7879e7cb3cb0ff26c +02cb2261a4b8aa25ce341a0478c4158a0fc690cc09a4c35f7c8ba9b2d3624521 +02cea36dc91239b8748d82e7e2f4bb71b404275e3b7ec137c24461909b0fc95e +02d18db6ef9e055eae20d4882189b31deb664262f059fd21764eb80fb0bad196 +02d21b2e89f938b0ee84033210eff6800ef5da6968902406a5d5ca9f8c8f5162 +02d8c3a94c10358b2fd81936ff2cf890a6dfc6e57c8ae82a213e5258fc805420 +02db6d8c6530708392d3da5f1baf057ffae4ea907719e9e7b45e6fc2aafa7609 +02dbc3df064ba39a14fa74d9a8e435fc50807ef786ed3f5e458f1fce94dd78be +02e9c99342cab22c730b1d15dcad2afbcb5712ba6cf22e884206ed2c5f747735 +02f457d612ad9bc40e5a9294ef2f6779c2f3ca1d10f8e5750b29eea28b7a23a3 +02f9575e3836178517cebb3cccc16d39ceb3d7fe673a26fb6b8fb6a83126b2a2 +02fadb1ee79e91b40c715fa024a72c5dee1c1f872273d93621528d2f22134145 +0305a8d19dccd295173551437afd27cb15da9cdb4a3639307d1e13794435edce +030a73ff96fcb9ab7a2f1b02805992cebd2faf41caf6c5288cc1063b6ea96cd4 +031bd8149f49570af4ac6a9b2609005e5c2f83c1d760630ecd5da4ff1f3841ac +03269d089f5d08fd9c242cbfd173857c100ebbb595f3895da839f02337a6493e +0330a79af5742edd35389ca7280d215f7cb2fa366c1b99cba92d2cf2f9df3c7a +0335bff6c510add55c37cfeba308dbdf77afcc10bb664ed2c9b29117d005a832 +033f4f385331e34bab2d045790d3360d121078281a47fb5d348be79689cca7c5 +03462bbfd4a46e1db66c7ca1f1e78b1e9df52a79d520ff205a564c5a031bf8c3 +034dfa27d6db1c235b8aa4143f4d003000d6f698f4d58f85b91d5ae22fb69c7a +0350695c8149c4110a47f4f0a17e84008f2c27ca1c1ca57ca4d95965e2b89f26 +035249f0fd16678aecaa954abaec659e64235b474c625307073ac2e45a5ca4c6 +03543d282210b5bb24c92196450699b31425167253525dd52ac28f2bc73fab31 +0361ea4f9f70e051fdd7b1d90d1ef6a8e98e7bf7b841bd19bb4186bfcd7e54ef +03633b8089b373aca617e896f81045b73b0e0d6197bbf98656be1d7f19436671 +036ee09acb46e47b8ba441dd00b2c86d3049b7cc95d4145cb1da1fe8b4bd3b60 +0372da5987082416aeb0c194741c585ec7486f76c86443d2ef67dc05f54f7c74 +03746c1f7dc3bb267515846d752f4f02bd40f3f4c1ead4c8e88751c588e1a39b +0374aa439ef497473a09503ad3e82c944bb9cf7a72d75494d1d7be5a85b8d6b4 +0374bfc30a1ed92d6dd1cd8fccb0607bf395d594aa43ba89b5aebd7c6c4e9e3d +037f9c680266ca9d83b16fc700e55c3e50bdf37b1c2b162a825e8cdd67c898d0 +038105c0c9a2dffeb9866f40861c1c0769978f0404e9a223f9fd8edf8bd63731 +0386f1bb4d6598ddd5569123c4a605581083848e407f70c282f310e30c9b2262 +0391933ab24b2a2aa0b088d0b33656ae564f48acf4798e371ecdb88174076a6b +039c9635f12322c07dea5e392814c3c07bd9a505326c7f0a1225798aa66b728e +03b576f6e487153327f869bd4dc2873d6b4aefc272060ad859432e2173244da4 +03bb87bac9adc40de22deb878466b80f3def10b6158c2da4cb40a743dfe8be57 +03bdfbb8e8c0d35afe96db5b322f3ce5af43de023f6198482fde20835bfed396 +03c051f4fcf6fe77fb67ea99d098e80e4a713fe30eb80ef286db72434157dac3 +03c32e01f09fffb2ad0a0de0057d07b593da862e987b850505a0d6f19a42ce29 +03c4271444962ce30c98cfeb5d5878e18088a6d5f7df75af52a5295d8cb9eb0b +03c87428af54284e489e3d5878869b0b85ef3370c572203a77396b463d14b15e +03d6cc320c869e8f63d84a1fe744776f54642e2583c21d4bb8c4590be51a4417 +03de1ec76c94e716aa0588064886180c48f3519f5095e9981966d3acdc05d78c +03e49c2d24ecdd12a0c265965e0924cc694f3527eb678cb02fbc10bce6ea7563 +03f3b9885eb9dd3cbd93fd5f7e3c25887bd403baaf8a6a77791ec5d166b03cbf +03f66a39625e42189af0c0f5fe3f863629d50a33fd94912134ae4bc4a4a2c362 +03f849d69557bd5f60d42bcb4b72883599268ad9d16e94a43d1731f7eced4d16 +03f84d8dc0cf6a415f76c60308edb9584a1a6a3f12a769bc42a0358e27d445cf +040fbb780fe25fd30d58bc1428375a054cc88bb7c8bb66e5c1e1a119bd76ad97 +04100d4001f581ae1dd3528931892d3b38337eeaf9ee677529c33f0ce3406810 +0413ce625288ada0d0d6609285ff97c69689d6ecbafd1eaaca555e1b56cacdd2 +04182686a830e8719f09b4762c444e3329a111251ea160b7c6d7b335dec31d93 +04186834ba72c034b0885d812f239739885926f56e54831e22fc6d0dda345f6d +0426e87f5dece79cdf35750a06455685d06a5ae7aa7d86daa49a0bf726b53cfe +042809c65b6fee594fdb07040701c2c7e81919db9005fd1bf096233299f3aaef +044012f23e92bf935ce2118206851a00cf78f1e80b3062ca2a67a29415c838b0 +04451199b00988d48dfb745fe35ca369bfa1f7947c0c4ab3c9ee22e699344114 +045478ca6cb5485d8377ba2dcaf44706b9b13797f0ea42d23a24c5dabf860f19 +046ad86c5d3c8229c044024baf033d7a75c2bc9ca0b5e75f62f59a07df9da403 +046ba8f91579b9f0c91375308d5fc1474e38d6d23546d09dfa3c71110106c83b +046c9617113365a1e0edabe3eaf32dbebe21931617b589de93a3a17e3049bb35 +0478f06649ddddb07c677c3b99539a4fca0608198d0609a5891c924d2fb26a1c +048228cdcb498a1dafd8bf4293020f905518c902432cd4e778c56e1b6277a457 +0487dbf96b49409456d5769958e768816d5cc0d49bada3881ab6aa1a27ba1496 +04888123a859f8f1c99c0cee494ac186de9a12829b693d17a486ac029e114c9c +04941180d91544b64a41968bd4e44d52b656543b69980aa4342f735927d5af33 +049c2ee4914c5dda2f736ac9acb34dbcd5a29c3580982004bf28cc8fce5f927b +04a2cef1454824dc608489ed51cf4cad59ad2e0eed9e77cd3194bd518755ea9d +04b3a6e30db291bc6695caac4e329242625498b16135f6cdc9cbd6bb9763575d +04b76e701ad0980945d28360317df87dcfbd2eec46bf51acadc34ea15176b815 +04bb3a4a17c127e78aa4fd9ebdd2245c996d782daea248dc7a72533a66d2d83d +04c4b8d41617216af068faf852d956c95c26a9aebd6d7b4b67f9654faffcb417 +04d8a5a38bbe7ba6e619b4c9d27ce02e95e4a41dd1f55915ead929fb3b847c99 +05077947f347493d8c06b4dd9bd42f67c251bd3ecf9b04c696eff5087f08bd2e +05155913acb2e2c0cc6e21c47b2125883c79c2f6e097135da1567cc2f06933f4 +0516d529b7d6c29ca51f5e9e43db2c14192f29f3c6ce55dd14733095e7a3b108 +05173768fb647a471beb316312b0a7e67140de3835cef584c25ddcd196bd8d25 +05242124150e05aff1914d8731c77f6cc0e1080c5585c2b509e092ad8147eeb5 +05367f6d632c458312fb8e5782116372d1dc0f21c5acb2879e224ab86123dfdb +053968d4862c453243f3f163f591e9082450d2c58a96aad61bd95209612a7e5b +053ebd756f4acad5a18a3b5d638f9437c056dcb0be642c748e283d9467d3570f +05484895266fb2f54142d1fc85710a90950442b6fb144478b663c57c3121996d +0549d3cca5c7972a3a78172eb103e4d6a7dd9d11c46efc823fec5ae960afa6bd +054a734c424022c3ee898dd9afbd0d7854d84db91bfb2d60b1d2af16e879bd23 +055990de128d3c2184504e0dec3567f9b5b040d16520013a0de1d7c9a689dfd2 +056390158a4aba6bbc048ac7c3fe2792b025121e7ccf651cbf9a98315d47ada9 +0563cee4924684bfcf9f83ff091f640612e90a7df787ede7ad0cc30579e5ceb4 +0575e1d112baf91229bcf52d1ffa7dbca0c0ad3ac4553b04bae37f769aa0e39f +05863e650fc0deed0803bfd92746fec2b1c914f7ba3ace71165c6c1677e12e91 +058aca3f1bf367c1d3e73342e468f496da812ab28133c27a5b96a4761140a120 +0590cb4b1d49775e1f0c5ea557abfd89cce3c001b5a0a201754bdd501d2d0444 +059236edf2f7d9518b4fc3fa01ab1dd9ff1e25e8459b84495068cbf57d4fc356 +0594db5b902a25da02304afee9e3c7c1a0493785f992d868756fa72f3cba09a9 +0594fc24ec3209133ff90d72e3f969c33783f3fb8b2350898edd170ff9b27718 +059dfb1993a824317d583512f6072cac3fdd275352abc77da1c107c6395dcdcf +059f89c76ec40b05076e47b4b3e14b89d3e3272c60ee122f74e27537efa78c34 +05a39c963db9978b14cea9c85d868a2badd4958498a73a047232e8b6e70a15b8 +05a5f45c0aaa379c811f56d64d56de502f49c0086d946d57bb0c5184d11a86d5 +05a74b7cb3175732f8668541c29cf064f3f520f9b5d99a33cdf58ba3437a6f3b +05ad3f8cc4514ecaa3a9e5bc044657b3ec9c6033a1aecc9446aa3b2fd42f020d +05be62a10e2a4ce727a756b1b60fc09e4f82f63bcc7e115dc19325dfa6b4fde7 +05daed35611cf06308df9ed5383fc54863972c15542fd6fc834a277c8cbe8d8e +05de0102f7f07e40566d7ab346b95aa6a05b87c0aaaae42566350fad2ad116c3 +05e772545d3ac48cac9a4f2f71ac41e102c03df2eecb5ccfe0cd669964ec95c8 +05e7afad054a2e8b13891b35517fadb32a6556f8f48b40cebfe88d3caa844f9b +05e7b44dc734e8f54ce673caff49321c52e2a27a0fb276f3b7d12632394aee7c +05f8c4d4cec9b5e40b17371e4fd31a9578fdc52b8437c7008d23f316b23a57cc +05fdb1caad2e9496c936beee05ca4c8ca61eb47e09ee6d0903e2bb09ba50bc5e +060aa623da5b943ae2a44a68e1e6e1aa7423b02666ed63648027f3b36b457363 +060ddbdbc04867f65fb1728438bff362d1b89b27b89320ca9e6642a199cbbaea +0614fef14c50e542f4610c4b0c915ec0a9de58d0aaef86e2cb73406292c8867b +061fe3918274b66786fae5919ec038c11d8ec952bc12694ce11c4b8ee48c46ab +062b4b2ce5bbbbc861200b30529f98bc6aa13fe583428a1fe35e601e42374101 +063013ff0018d6005cb4485ad1c43c3c1b6e6ff939539ad84fe4287f954a8758 +06428b8d2aa9e4d7850e33085829b4910ea16c220de558927212ebabcf6fa38f +064ce20b230a936b7e083cca164172e61948312e2f73d01afb1c9feab451d9bb +064fa41fe471f009f003111f86f253991e6bd3a111e960f5ff2420f4c21d38aa +06522e5b5783e864a7270aa2cc822c449db73eba1ddeae9f941d0bb153411f79 +065350dcb7e189b5d9dd782d744d1643b52a5a4b591fced72aebc4f6de20c86c +0654954905b89a0ba48a2d0db1f6d6ef40425213ce169c09de86dfb4aeb341fd +065fb84f704f065ce6c497cf5b40c01590596d3052f6593a902187a74e3f6a85 +0664f30f1803cdaaa5c1a48586c7bf5a0ba24354ebd185a948631cbaf5e16b1a +06695db7e36ecfe4298993a0a5083b57ae4473a527f909f5e42200b751983543 +06702d364784a96040fe7faad17ed37d54b30a47153343be8f674228185d03f5 +067048717a9009cb98700b5fa72d2547fb1763ea19228ebf749213e7964676a9 +06732f214d050fd8507870649d077fb67e75d82de1cf2a3512f609ac047b8f33 +067d4db9dd62d21a379d1cc202af686a9914eda3d630b13c917c3c9de5d53b54 +068601df89aa1c212c681cb2524c0243613c6fca2c5927b17abd8c96bc9f28de +068a3d0ec7527621db5782acecc80e6f238a0df45889dea5f6fc4d808a632d4c +0693ab66b44fb6e20d5363e91779fa678fe58f8494a4855a0afe0b9be494231b +06982350d8be8af55458fb224ac141309ea41d2422b7ed105b734ed19d72ddd4 +06a30c9a6882ff0f8416d2ca26c1ee1c6b3bea7597eec44415376e69f1c099eb +06aa561fea0b5e5b0c88fb20f3a39c711ceeb326815b57f4d67240e8845132a1 +06b5c6811097aac10872af086c5ad55e018ff53d724a108e786f721d6bf4fbcb +06be301723e59bc4c24afc02cd1a4ed5457c073b0360af2e020bf31a6e52ad0d +06c9ce2b4f8a795970f30f06a1db140ed36a3e63a0d78769bd3d57fbe01f749b +06cd04027807920542bab041bda329cc273d1661c2773337c42627f88a088e6b +06dc6e02d2b8fd80af8ee0d56f60405420cb0e00d8d1cfdb9cbb86215bce0d75 +06e016aeeeaa94eb42ce1494c42aef820e51a76d1615003e4929d543064b4d9a +06e15fb4eb4bd6c66ad4cafa093f304b596aa680ff7b261dc5f0e3d5b4e8f3cb +06fc8a839a0d50846c34459644caebd9e1e489cd6e7619a25f4f68e44762073e +070025230c82b2aa3da0a02ebca48d20ee2f5c08493106f4cf1c204944be0c09 +0705305967a61138accf5938b5d32369771524c81317e645a6fd9ae6228e0075 +070e2cc58138031dbd5d92fd05aaf9c8a5b431ca4b1fca518d3524b9c20d0048 +070ec346f12a5526e350009daf540145324f536b26438281173af729f8f78f70 +07121c0b70bc4fa75568e15e6417005c6539af5c681ee4ae515404ecac762073 +0713065ae385ce486e38beafed7cb034a0549a9ea9fa020e2409d8a4aeb36ced +071c93bc1b3983d14d2365d8191149da91075416cf8083a4aa85b9426378c093 +0735ee5b86d4907900ac53b3be35e079ebff6f858136dafc71127ee2c9ce2799 +073df1a7231bc1d7bfbe4b9d7e69b544329cf375e710554d932d4e45990e6b51 +073fcddc204278088d02eefe51439f94c0f6edf7d4c61cfc373fbb6c59b93ff1 +0742f9b766d324756437345b49699527800bb32e82e662ca5a912bdef4b9836d +0747dee4936afac30fb17496b71ba5f73c3ff552040d56969e59c0816044e4d0 +074ef6aeb2af0ea564cf94f5d2190688f2fd42b3e95f616cf95ec77d0209f2fc +0751e5222c89f9f5ddc5f7b0b37051a3f2175df1c92a3ba985132db0592b14b0 +07698dacf7752fc46893a53eb523ae24fedf8799f2b047e867b9475783065aa2 +076e4b805d8b78282ec9436b857a580bd74218f335d59ba590c9415abe68b1ea +078059ec52d056617cc53d20f9a3d4ee19d366d776d40808df007740a6ebf5e8 +07809abd973e0f1812df8e229ed50ea85fea486b8416962b869cb2e0167de61d +07860f8fd4ab5817b2a8213e617d75c3ee6b57fee014547a5ecd3e1a071f6931 +078969b2010df6a2b1fa707989e33cafa1c35c5dd8da73ec70c8e586d90d2340 +078c1e10b62ae22d47cb9812e6f0b4201b0d194c3235aa41842919c5785d5d1b +07a1d2e8c3fd2ff8a00e75ae2aa7a18bab3b0a7fc74a63b2665b2736771c4f2e +07b1989d39d8b4e0d8ebbbc44a891ae999515a54207b4e2f50428697142d8179 +07b5cf3692c956fd209d1b439cb2471ca7ef9028bd93f736c04a0eeab98c231d +07b60f0b54daa140784b16ff7476027eeddfd78634445a690cb9a82b15a721d9 +07b654edc5c89aa0b652f126a35e14553a96485263eb2ea3ee204ba41bbd9642 +07c1df33db5cbdcbe27aa583632ee45368b894c69b50cd1b8e082610ce124ae2 +07dc302716b82790e8d84cc89caef581ff8764e9aba508a4e286c049606073cb +07e2a983256e5edc890b07015606de6250fe74bc88c4a07dce46b8ffa7d80582 +07ecc0f6f69e3c58dbb40a66ddda93f73423d1d338cf62a43d947bcad3028ed7 +07f22c12af7f38c4362f5bc11c1a0d6433f3cdb6e14c9bb90055ae3d7ab63138 +0805393a9ddbfd01e79d29697cc6464c9d5e60ef33ccc7d7123013a69c22c527 +080a27bb42b278ccd08b825c611f25463b2c0b7db0f81d69ae578d757ee4098c +0823481560e72eed90d56d069fdf65ebb2d1cd0192f04be3758baab80bc6cd8b +082447e59e1fc6b08338dbd56dc59b1058f2586899d7858982f2f701d57f2006 +0828706373ca8dd0bd88a8f41b08015ffb4bfe1ae725ebfe8e43eb95a9ee525a +0831efca1d4aad1cd08d883e2e70b2f3a7fd1f0d0f0eb85b780fbd3aa21409dd +0833543ef052c7138bc4e9621fa3685eccf5105b7ccbf7e704021d15ad0531a5 +08367b4a6da7ca5e0ac0811a445662c2efed6f1fe807b4ccd7e368fed759829e +083b2e07621b24e22a276fe58eea5548f0901f377241c36f60557182262d2827 +083e44bb9ad7ed4769177ce7d68c838bc679dd9096816ca363d0fd9d3ab75e69 +083e4892aa97360a2b13bb81138549b14d58b6c0c2ddeb008ec8e8b72e8c8ccf +083f09473dda97ee7e0949296d912be2bc681d3d5034e7d33c9386a14b3d3766 +084462e855e751966176bdd25e30ebe3f225410329816346823c30d6c6051a97 +084ae30994def7ec8baaecee5c16b336730bc90278224c266f84f48e3750fddd +08556a63e42d3fa5375a06d925c792cd91d0706a379dcb5138fa8ec761ceab5b +0856d8a51d004f58ce180b287b26214d1e5038d325e4d8c9f12e6edee491bfdf +08652ce9e29131f92b03b9b4937a75f2b1ef71771acde47eefac2af4cbfbe9cd +086c32b68eeda5ecc829f62a1aff368d4fbe5ce9e9665bfb000f9cc9119d7c2f +086d43560df06b20284dec5bfdc7664c79052b178d6eb70dd95c9dbe8f9efef5 +086e59db192ee7d333bc39ca05813dc6caeb55059cec22f21a908d9a06d08d6a +08708433e31ff0a97b94db2d5a954076214ac15d572f65c952eb22c60f564374 +0872c2d3dcea05aadafd76b88bdc9a8c3d5f568f6e6dc5bfa415d6c81a93ff52 +0874bb2548e83549b9fce1fd8af9ebb2c5d87acd7b01d163da8b8093858ea2a9 +08765fbe14dcd5a45a887249228c07fe6eadb356ce0a680acc4c55584e34bd77 +0879692755624cd839e288b473035e49c8f44bdd72e8c4601f42234ac94c3e6c +087b54432df80dbef2b48414bde08c327472a5a9d548e6f129c2d9cd96999447 +08896c1cb25b75a158875772ca2fee19bed77064bceb623c63f1c57d889621f0 +0897487b4fcfb2bd063412dfce99e2469686f2181bc07f12e4d1fb3451d7e50f +08976eec68469cca29621229a31060c547d5fa96f365c48b1b344f03b56a2bba +089fdad244246ab0b2d9dcabc5e419c58b544185e0f8d7a38cc238cd2e3fc132 +08a347414cbcf854e4f7c145e808ee733afdf9476524fbde69359f961887ab1b +08a498ee0f36b7b2edb5cbb27386d66a12b9bea0ca319f33e1eb7649c3ae0eb9 +08a7f132d91165ec5fda1832103f25a9cc9e04abc92a0e6d8833568009f47d5f +08aefadc3ec650da44bd24da0c32cf9c496eed87ea1f96b0b3fd71823f8fa32c +08b33384fd2bf69907ef15b7637475368aff808438ddf7d6fa01661405f45b66 +08b6fabb1622b258f7af8ed3bede949ec6249f3a1e2fdc0a1c601e7a11398424 +08c2587319fe93aaf1627245eb2709c076b20a6a98fc962cde8166c7f76ac011 +08c360060b6c87bd0d383cf42f579119495959d2099f49b8c27a388ad54789d1 +08cbac9612944b891e654d3bd233d5aa67b62e4571dc366182405653b6b49828 +08d139ad48bc0c21cd9f8ab721c09c63603cdad455147dacb17dc7960b354118 +08d4aa18e8a1fef29e741d95e9a66664db94ec1f068d27b3c635e0fbcd988e17 +08e7e84a9cbd313a1e03c66e3ef542e826cf4a5a995de3b964e2eaf26b4d3bac +08fed91262805f0a3fee90a66d66aea5696593d02bf33c8b5abc18d9e06ebb80 +09077a0e4caef161f9194e521f25151fd7b647824bc579e4dae0a652077a2d15 +090b23e5254eeb7928804b07d81989a22ec2742dc52a88714be8b577a85d2e7f +091b570f4868275dba0c65dbe45edce7c1c023ad170c5705a99b4bd3119f6464 +091d389ed5cb0af0fdcb83ee67019f385d79bf4974a721d3e3f1634ef0e9bb8c +0924557bd00814bb92076f8424216a4b27cf701511e8f95af7c538e69060f1c2 +093fad1a4f8ca4d1870a82262934b54626808e022389b9be7b2e2cff3d9f91f2 +09455c8cb0392bd0cb759c12ae0fbeb8ce5abd7898b29660350711e193699aae +095548dcc592c14e6443a0773b44d97886525c155d5b358543c34ccd42eff6aa +09579fe75acadb47714366e0bcac34727df7550930809f7ec362f097e5bf2543 +095d0e9083a68cfbb7ee1cc411d6a712ed682795cf5b5fc9c01bd365a369ac34 +095d49a5de862cf699b146db2172e149a22b36df95399b0c93b0d74c1fb7b6a5 +09623d68d894c17739845e70e1c6923554b461747734b2c4c1e68cff92e9b637 +096734c0ecc98b9af1e8af5a341316b81cc988e04634b694466a66ba36a85967 +096a882bb9250e0313a6887059f98e95dfb612e25c92e3e2b18af7f367bd6298 +0974cad608671463d46b37e85541a7181d8658adaab10addbf1f4a6397f8065c +0978ca20bed9e373d61b6b0f17aafa1b7820ad3868c590cf076d9cdc66963cb4 +0986fdd946ae9d7b9e2d48929bff694d9565cb7ba9fc7762a5c703499d54741d +09883f1dd8bae9a7baec4fa048c3db3e068445cee291781b7cce34b9d3793754 +099f1ce8a896970b159ac9396d413c673f54679c1e29eafedf8c563a40b6397b +09a6dce68fcfc37394e6f02aaefba88e96813ac93a7fc4ee6632acda580a7263 +09a8a4ffd987528c117cf38dfbba17898eba9ebce6574e17bcefebb520cd952e +09b13125db80a15ec9a6d1163e82053216c43215b3b25fb3712f990749a62950 +09b5a0276ff183937e5c3c08925b35774af7865017443f47fced5da95372aef8 +09b5b5e1a6d8447f0a5623c5e8218a07cace0810a0d4caa9509dbec3d0874169 +09bd9fb287a7779e230e11cfe30a90c6e90fe22524283160105feaf5cfe78c70 +09bf3954198dd762cf1c2903ae760c1dcf99b2506b0904725dfab71f998c7652 +09d01de4c403241c7166c21f5088745d23402cefdc2a5111713d288b6d837a72 +09d25c1a3bd507709bc1088206d5fd423851df0753f41b63f6bf3631f011d343 +09d44dac3108974d6b1fd8114705470fdfb95b5895ec821f12673c4a7deec47c +09d9b6f80623de453ca765ae3b6d5507a82feb486f3eb05c8a6418c5f073704a +09e504e676b6899f04743e2cd982e4c51a49152d850afadcdddb260f4e95028d +09f118c3377f1db098f43e12768eaa7ad1ad580431774f34134afec399929111 +09f145a6b0f3c6660159eb62140eac2d9693eeb4c7453d325a10359313bc3eba +09f688e259c8cccde2a5dabdfd3bb46a13c16e0a54e5d560633851db3d72a6b3 +09fac6a60677b29ef48997cc3a26792682cdea6eb177493adc8ced27da9e31ab +09faf60fb56d63cfdcd4f5f3797ef90cbb0ae3ed8cabf8059d4c018ab41f0696 +09fc931206ecbcbd54a209bbc3dd6d45e340187c709da0af893d17238b38083a +0a01847392e70812eac5005b064e3dea3259194ad24263b223e3eb230553ad02 +0a0457db9953078a0539538367dbf7b70d68fd867db8a49fccb71d2fdcd44941 +0a07aabde430c1ed43aed3432ca603fea749afebef03562bb7e04ab0a21fd4c8 +0a0d91be048549f88374e56f854dba1c7e8c7b1674ef6edf78aaafabd0d396de +0a15124036afbc1c37aff14fb3070bcebd2bdd71233db607c9e92c48d33aa112 +0a23f7c5418a96b00211599fad9dda41e5a7d3e1b93e89b6bdc01d3f74bb47c7 +0a280ff1aafa425d314f6a5694b1fef7c253e052ad8a57f57d778d09d898fe4c +0a288bfc64fce7789b64387f1b64e0cba23878ce8540492968e793ebc720472b +0a3d2cf39f0a113d7133f657ed9065e051038b95b8918d91ff8b681e2369152a +0a3d388797a893d3f58d53753fa201729f913d7af089dd4d98129c1044d7110d +0a3d6b6800b8c3e62e81260b26a9fd406bca20a6ac453614da03ed04e9e7ef67 +0a3e715105a2dbb42cd00566dba0a7b2cfb9171d73ed052bd3adf54a847c7f5f +0a57d8cf74a18360cfdc11f48c0c86d32fb4e6c19a35ab7d4f2e0c2eeff6dcd8 +0a5bde248f1b45a2185ca2221d5d0593c03cbcfd67f3e42337dac8e3544a2579 +0a5f386bc7afd1f7e71a5ef08c2def8f79b1c5078c61701e947db8b9c6dcfd98 +0a5fa6feef167a45be4d996431b0fff43d28112616d6b7ecf37e160584f3ee01 +0a654fe4ab795d6ca9c0476c6673da34c397f8cc8f599a04ef9d6960beabbce8 +0a6e5ea817c43b572b20110bce95963d2ee80c37eb6070812eef93e4626ef60a +0a6f31a77ae32557f041aad10944b9c1fb0ecf9cca8e9a8ea1dec556b584295d +0a6ff18a42774eef488f6ceed43ed9578499231b48a540680785beaebbe62fa1 +0a760af0d859cf77247c7ceb344ad983fb1ecc08548f902634c0b4f675cdd540 +0a9820eb81dede6bb238cf1771bac034dee63fc881bd52f338346a632fb816df +0a9f82e8436964cd9bc6f6c9c14d09a90ddb2e719f404545a28f246ce8763ba3 +0aabd8bb0d4798b3270dc04874fab0e0fd889eaa07f2d1c444f0135e3156e22f +0ab2519f453043e132e59df0edc33a77566938c3d47f2a9618436fb0950cb9c8 +0ab6662bbf060a7ff7eda4a33f20973ed758fca8c97dc86008f65d371c147c78 +0ab863f852e3f9b67a10ae7455db6ede2b96d42ad7d150009e03092234cfb6e7 +0aba79ff74b89bbe24b47db992a9285a9890775dd428d15880aa701dfd01a022 +0abc7d340258cb1110816d52533a17fdd395665539ca260e1b76289430510fac +0ac9dea425f14db08aa94345d1223b14cc635e3bddb16687fd39ae0d04e0f7ea +0acedd09af784d3f53851b87ee99a630fa0cee91512beddfe5ecc0c875111a4e +0ad114cfea0e4d55e9809b4338fd46568abc7a600c391ce965dbbdc97f0a1a3a +0ad3cbad64d2aa284d62cf32364468f1b72fc9314d16114287b2ed76882cba61 +0ad652cfe8c6d12f25c0c56ea1090a15b251367f1f77183ab3238d54afcd82f2 +0af1af70f75ddc074a6fc642085238f68d562341a9380db3848404e9e561a0e0 +0af2a1df2cb2aab17799b57c1c8f51f263d1cdd2bf85ba3ef01c87dd5b0b3079 +0af2ef1cf705048e77ebe0ecfbae87dbb7b169ffaeab4b492fa22ad21f87d1e1 +0b06bab63d4a90dfa901722ac17b5754d423d2c92beeb8141a662c34aae8d861 +0b07372c2ae2d9f92d2598e9cf1846a706d798ecc68880b9ed9f6818b4d13d34 +0b0747f9be3d0eed16b423dd10ead14a23cf8525798ce9e6c018a56c12b82d13 +0b10e557fe5a4350b3eeb3472b38ad2bfece1e48b0a9e6c056d1cb3e9fe3faed +0b1b7e8f2e05f6c35733fd71847940790efeaa3ace0d40ca07125d4ca18cd238 +0b1becc1034bcd3a0efca2f9b23a16c0611f3dd213602cde9d1b7eca39520718 +0b1d40ef48cef68faf858386edbedcac6d0b50dd077d147b324646d58873e1e2 +0b282fec163d7ca7b6108eea3fbe9190eb54e451be563112921d2ac9719e8334 +0b375cac56a9c075886e19e406adf9a2c55dda1c57ccdc622b3e942d581c65e0 +0b3f1e4c657dca8c1861814579ec1ce6c651ff43ae88e9589190810ae4833fed +0b4af5662df46c2133efc733b41fdd0a500726c2ac725b235bc451beb2498015 +0b564aaf56a69b42b78ac462eb622a8111ea00365adcb9affb7d05914996ba0d +0b5bf28c8038bbceca2c9e3d9839a6eb267ded39580ab7b099001b4d7b87d651 +0b5cbed090a2130f51bf232aead4578dc2e5b812ea4f395b95f64f4e0181b2bd +0b68893d34b95b7477a43fddddbae4093e57a952b0555de3eda8b4bd2f84f267 +0b6a0e9c269743241c1a595148df1f03d9ba5d7be29bdc59a314643fd6f6255a +0b6e458ed99acf85c6ba43e3acdf080697a2dc389b0caa7170aa8be77b29f12c +0b756c1b3c38cb8cf5583bac808a2df043d132c907f7185544860c9c5eff32b5 +0b825d8b2720184eb7d7221ae77621dde26ad4ca23605183bc5f8f79ca2cc740 +0b88eb2facb360efa418fc3eece855bd6f13638c31080ef48cb3cb6a10cabef7 +0b8bb30c443b849a36eb3dd3b929e7cce70aadcb17c2f121531111b3d5f42b91 +0b8f990e77c82f1c999934f3f93d57f9d55fcb3e423eb34503a1643c1e7bb521 +0b94ebe86979f7011b9e90f01f063129ee89bde3633231a294abb67f40537a42 +0b9519a86edab8ebf69bde672944be50d77f3367f1fb3082f74fa1a7fad30c91 +0b99720a903fb13b07d45a76e38800e33170bdd905c3c6dec49c734c86cbc5c9 +0b9bb8fcfef0128b9ad0f7140f79f7cf60c1c4e7dc039ecf97fbf7fdc03f9ca7 +0b9bcf1232091363ae9af829d88273f19b0880546e36b66d6b09f088d6ce8a17 +0b9d49f02dca925ccc8e7d88afa1fb4a7e065ee4570e4fcf906d6c327753fcc8 +0ba9ad68bb8ffb48fe0e74992d6b442828824bb63bc7a819ce18166f8243f8d2 +0bac19f6b76c3db0c0a82cc753350a027d999570b1fc2c56703efefaa9ff9170 +0bace2fcf574f0e0560106606c23444f07e6fc9e05b9f074258b1c7a36102588 +0bb5a743e6407accd192745855fd7035800b08324897dc0142bdb9a5893e0f34 +0bb73952f2168781a4acf74cdc65d710300ed0165f528b301a71378797570f67 +0bb78e7b46b09b55054dae53593997d2c1357c78ce7d817be045f9e7dacc5894 +0bc759de71afba50e06469dd382273bb99b7bbea0647c2130423613d33041105 +0bd02d1e65c231c904cc2d681a33cedd3b0b420433ad560bb5dbbc82393cfae0 +0bd41539680e07ed31e6f57d5ddccc822c4304f2644126f5ac4973ddab98a39a +0bd4270a4f55d6675dc87a9ad4c97d37593fa977e7027f45e43d0481d0b0096d +0bdd97d554c4bc7dcbc7b57464a0f0757d86b84735795065b707cf4e68e843e2 +0bde4a89b379f59a7c2daf4c0b01200f7a8f3aff85e9674a613b8cc0a8e6128a +0be0a0dbc961c3c6707c2b5248123d8f7f1c8c01b362ac08aac05a19e3480256 +0be14ae27059398300048e18570de0a31c3c7226fcd51e0c01422b206a8eb177 +0be1ff0ce1bdc60a1ac13fe9d40db374475946ad1485309914e9c3e4d774d2e7 +0be26c186254f95ff70984e445fe0c9444e82bd93dd26d3d43def4e0e503ba7b +0beeb08b22f9a01db4ee3f618fef87d5ce30e85384b8307ada340434c1cff6b0 +0bef61a470c418037457580392b17bd73f94d2d49203effce0d4db36fa173461 +0bf8856f5fbe0a709f78b60a53cf18b0bf8c6d2b0e109eebbc9fe5d97127aa94 +0c05afb02298c25ca7d8f70d48c03299bf62e73f886187f69a58495f638f1a91 +0c08669bf6bc38f1fe6a4c46a6f114f00871435390192b7b872bb11db8308170 +0c18bd3231508b98c7a54841fd1c7d74150dd0a4f596579844712efedab484e8 +0c1f2329815e733362ab988b3a6a6caf3f390d7cca520e1627c609a46b8adc30 +0c20a8a527d1dd12261610b7ab6325c7a9a655e160a78f342bba56a5c025f8d0 +0c330728b5f0aee6fcff5a9c68a835b541c51c0da73b22296049e59b9bf6a8be +0c3dacdb9ba6257c3c791a642a63b7733b8eb72346b2c5a24b51d0537648ebe8 +0c519bd01d25c926ee7b9c3ec5186c23da2a28f2a31e6905f5c85797be673345 +0c6cce02d69ae68fff8e781e50c7dfad992780697ebc3cc6f9a35e94999e9cf3 +0c6f736cc87b5291b8313852697136ab3bb02ea06d00ac364a282c0d229058f1 +0c7d33d09584b9590201f62dcffea61213c5399a37ea1a2e29c2e97a47427b82 +0c81a6324a233d2afdbf5f09362749345fe651da92733d72dc8b6c48abfe7ac3 +0c8f423e0d3ff395b068b24bb6f861fdb1cabfe94d3b15f5c7af90fa178b3216 +0c9b162aa86d5637f84aad5a96c8abbf8b05efd9e90af157417d2041d3ed98b9 +0c9d4f9c1c566d7b9fa9b21336f130d735dba340733f143c939d2dd19d4099c2 +0c9e7d2cb87bd076e0c6b8d69dfbddabca8b327206b6c4798753794128e7b589 +0ca4103621144439872755bb33dbcde00aafe42ae6127e17fca1ce3c3f32ee80 +0ca465d30967ba948a131dd776395598cbbbb75f855cd8d57ee5b231a079fb1f +0cb188897d51a641d2a798a275ec7254c539e9b26f5a6560f80ce4dc1f9c4c68 +0cc078afeff3b6a67ef24588f0871e4696ccacf165b28ee558dad85f8813e48f +0ce3fac3dacb4a1b3d04225e5f80b33cd02b6e8b26fe1af0a16f37513a4e26d5 +0cea8fbbd20984be9833861735ee1ab35d61cc3f68cc5e619319af55780317cd +0cec516d225cc4a560f232ad856d6141b5d755c140cae0e7f9d6875b1e238785 +0cf511e04442bda4c550aebafd0d29ad47c0f8062f1d6f73d2b95e07bc6a5a4a +0cf5d3a916489a13e379d3f6f1347d9ec1caabde3b5d30c77725c57efa115267 +0cfb40be305f7b6f935682e3f48956aa6658efabd4ee7db34ecbd6dad5760277 +0cfb4620b6fe64877465a3b6417b288e52f30773854d0cb1f3e9944783e8148a +0d05314c6dc310a2d8e124214c15d061f0922ba24c6a5c3ced86ab93e430a20f +0d079e387f9032fdbc4e82af9bd3ec24db538e34d1c1d36f17af407e306b818d +0d1730a8ae3098e05b98a2cc20fe935220c21288f57fd112d58f4edd29b8a110 +0d1e2b3bfae5d5e4c4611d539d84ae6f9177412336a6099af7344a120d8b6181 +0d2a3a963dd0c2e55ea12c58019c8e596ec7c3aef696ac6d35a25a91d92af46c +0d3d5d06a5f5c464321c873cf4a58076b160c97c68f5ceed3ea2687a8584658a +0d5118c40c97da53d3d3f3bfa9ab56e903b16eb2148622b79815094f23fdd5a8 +0d56259867909bfae7d1a93719dc19e9a460a9f2cee360f7212dd5027dc1f97e +0d56f79d52d4117a7e747f3fb158d3440bf2cde1bbe03a24b5c4409915e44962 +0d5c409f36475271b59abdcc0a545e1d22bfa240af5106cb65ba75516cce57d8 +0d626c04e8c70d719ad0f9ecf141f5bc86e51227fcfd536b59c6e938893dc574 +0d6c6ecfdde6d52ee352a7b00440baad6a3f3ac33690705d6e12130131b2d6bd +0d792a51a63b64696f7549198932dc1f3af5a7db261baf7bc042bf04ae906e46 +0d80c24e8805b2dffcffdfa42d7a8180a11cbf8c6b5256bcaef179a81198805c +0d956531d954da2f98e7b45b31202fea5b2466d3afe9356946884445a49f87e0 +0da5ec42ea152cd63d3704cb83054d636fa3707136b3ded5e5c74b767c9ac749 +0da7319729a692957b2320224aaad138670a41f0e99e7874d714cc9f9e63a50a +0da9e52cbe4cf59e2800cf7d0cff18d5f78a4d431fa579aae04dea1a23810bde +0daf04c44466e97578ff7b448b2006a022a13ecb4d7a0b484a975739f7ef2932 +0daf2e07f84d09ad526f1e12b29472fe66d41349f1b9e94eff83d17e167a3b8a +0dc7bdea69ce535ba61775fea77c2ca203468250f91403fcbc4449ffb06dd106 +0dd19c0df7ab7f5439142ce81c609fa6fd0c185e04b5ab8fd88491301c5071a9 +0de9ad69e765dd246c2f7714a423831049926087234ae52a1f38fbcf95e34060 +0deded4daacd402939394f668631bd9d675942ecd67d512035a2e2cdcb67123e +0df00e5070a4e6fa453b9bf30347834849cd8bf4acc3095844a1df2b67e093ae +0df0b96bb1cbd92244ccb841b040d9f3b2e4f5175ec83d56508ec0459a0b8e6b +0df6316a8173dce1754b026550ad371bb47395a8b6fe9fd8b9aec881ab68835e +0df6b83a39cbbf845805e13b733cfc88e8b65331f2fd1b4c48c328ad44e7bcc8 +0dfde2a1df7cd93d3d425111256546eca51db19c9d41bc6297c0430f39ad1ff4 +0e03e01fc61fe18829d28fb4b6bcc28034d684817ef36d747d477bc0dc51448f +0e11fe59c372fa50f5e97e02cb9dd9bd459a87454cdf1ba29536e59ea27a6be0 +0e136e88740d267a80d1f874ebd0bf5e99eb84fe4106455465e2010617076c41 +0e2c438e3ad54878715e2749f5bd98058ae49931c5e4eb691d3f372ec412ea5c +0e2f1fb4cfa3c8be9d97f309dfeecac77d3cff245fe7d6b36456d00b74b4340f +0e33aff9d2c594edc85d6ac2db6b8c3cbfa9711b1f973c2fa8d2ab5f745fc4e5 +0e3890a77ff679665810c12abda8dda1c4c55815eaa994afd2394cbb1b59c4ff +0e3c1c83c96ed8ebfffb4b560e1bc83bffce219a3a5e7ac98c4c78c90628cdd6 +0e41f0625e48da5c237d80c497253f225eccde02de6531cfb1b85a5d36e51eb0 +0e4cf82e5d6081344186dd64a1825a67c0ce5f149d23f690e9d3978786bb76b1 +0e4eec610f0ed8b9858b4a56fb44cf9ac68e29694eb680338cc5d0d3f1330749 +0e6f22a1e1bf262cb926b226a5633c8dba89fa626db350fe270dc9b379a85832 +0e737c14e22b4c6377d34f5b3b3fe6fb364f1ba7eb262431c9e33580c52303fa +0e88812a4b779eba99788a95c00b39169fd5a384f8b6721ff68fd27f5ec906f9 +0e889ca478fc44fbe43b7c5909f60a96c0a4dc33af89d9379565a541aa48b3f0 +0e93a4e57a6cd703a361db87a7eaea1cc95283f2f7eedeaf5b89abe783db1a8f +0e9f08e0a3e8d8a14ac2b6aa2b2f880d646036fa3589b1257ff9d733888e0f16 +0e9fd8ce7bd33c62078dcc4eba4cc5c8ca689a523fc6284f402b304becdb1c20 +0ea61d2b1b87584729a74b98dac1f60ecdaf6e0364c8c5034e7989d495f83429 +0ea87b3baec04821d5604d4a8e58115d9a6c345d0cdf0501a342306ff43296e4 +0eb7e2b30e7964e4000d0f6f805f4ef395214df6fb63c0186a575063b996ba2d +0ebe42c3ada4f4eed35280b6fae3e29f4ff127d1a4cad3b72714cc1ad714bdb2 +0ec6e82c28dd2119a29f77f8dc7e35a9d72f49de631ec882b3eb30135adb87ff +0edcaafd12570ce3e50d8de2699b478fda42660c61acf5651002678fd0a5fad9 +0ee843871a15b63e9d035103141fa179818666aaefc321409d9cde4d49318553 +0eebb57de9571a5674e35fdd04b67cb3c7dc9b816567815c703aedc5dbb56186 +0efc99c9360cfaf61476755c76875534322909455181d47dce9c84c398d2eac9 +0efdbc90e6631f8ce4cb2ff246fa7d17fc5a7f3864b77d456a50520d3f472396 +0f061ed23777f6e018023a9265b1940d282eee557c9b58f506b8ac26111031b6 +0f0723bbf43986d8285c8348df3f8df40a9340001dfd5a98e5b48b79324f26fe +0f0db27b5daadd9c0c6dd1378915fb01758191f036292ed809744b88e8c1e93e +0f1ad0c8ee31d0c4b5211a89a91fe97ae6cf1fea1f4cb85085df0ce51f230481 +0f1cd5ead4583b6e4a23971308ce5fb4aab8516f47a8787ac4e4f56dbc846eb5 +0f1f41f49178058a648234540522f9c9bd8a5e99592618214422a9c128ddee1f +0f243034f8bf1e57a44d973b074f4d80b1e8ae8bdda1e054396c375684e41b86 +0f26c8c69cd0ab675b57df945c9c0ffb6892d845097dbe895841f77a44375165 +0f423a8e11dae48436d10f742eb4cf5f4febf6a23d4d86d9d322ac1edd369399 +0f43e65dd4d1157ed77e10b6dbcbcb015718abdeebab6eb00ac69f7529b9e317 +0f52f2abb484e215fcc61263347036c143e961bdece6acbbbf0d840717f42bf5 +0f55a2e14b0bce6a8ba2c1ea5b20e25e53816b3cf33c80e6383f4b6f253aa09a +0f67000df73e3972a542a8b07e4d22746bfb747c5c10bde275a2f6fd8b2928f0 +0f6f9e3dac165cdbf753088e1b59942b82f8c6dc9f589631557984b668c571f4 +0f7b6d6d56765c611d9c3836b90fffd2befef3e65fadb41d1fb9e82b5ee0b7b5 +0f80e142aa78ea2601a5e810ef4e38b33a00a27c376e29785a4a7e73878fb29a +0f9486b6aa59639d199848eb0efa0596f017c28739112e6e5d39994fb4b0bd68 +0f957cd5614f5f2a2f4ee3520494b1c9d6fd5803f4f70e1aaa957ea9eebf3154 +0f99f3476bcdec6c983eb9376f92e28120b1b489f4fe6dd884a0b19060a998b6 +0f9c30a1e15cdce7f6bb59a16bdf148e3cb8fa9637460df1891257cc17e5c04d +0fa2b3c4db735115fe85d578d508cef2125ba835503b3393b0145667806887d7 +0fadfc9067b5d8d77caabcc6b4058475cafae02cb0c6648b77aac6a71dd11f93 +0fb3edbe411f25f90d71c6faf60a5e64190e20828bf9c8cb37bad3d4d24337a5 +0fba49b26bff2af41ed4a013ba3de244c10b52b76964b56f19ab03696e608e4a +0fbf1538d61732bc35e1c73d9cb428265e4564346e86b6beae19d9c666fa436c +0fc88e6fd738b150e115b07b11e27be66672e8f91d5a4d1c73406cb01c6ae551 +0fd99a412ea943e33a5fe0c80c0521686adda6b0ce8c107644e6cf2f90dd9b07 +0feca39673bb59523b72e354a6c6a663ea9c753eca83cf4cd8c62794484c8c4e +0ff9326ac4e7d1f254dac9e488f6a84d94df458e0ce88545c598870454c12ee5 +0ffbd3d17ed8f1461f46265c7d1a88374bddc45afafc39e7871a518666ded77e +0ffdfd01d440af1a78824aef783d179f411184888777668fed51a13e4680dcb2 +100329b164eb816b2a87d28845d49ffb0dee79728853397c6001f0dd5f073849 +10057842311aded999383514046cd9efd0ec9d9aa8a2fe36b902260b64e79ee3 +1007550eaaa43fe026aba79232c3ca3f829c50d17f099df07a25211067c1553d +1007b974a30442ec3f127c7dbaa9078937b1e12819596914ec49573e84f84475 +1007f91a19a63835e22a006652df052454fd7d5ed53367a3532340c26130b097 +1008aa1fc782be62141c00ed670e4ea94dc32df84279f59cba1d5a6e18126fa9 +100fbb6e4478014d6627517ffefa846d7cf657a662f17377745e2742237ff061 +10116cb15da829ac002d87f0e61f0065d9849ba10478a908851cec057d32f86d +101333e289b2dd64c611d6db446cd09dbc1516a68b6253ee3a53003c4f6f507c +101d8e63e560ed2cfe574084e7ba712c65e90b44649d06efb4032d026dd0b8a5 +1033e245d4a7545956fe9f723e215fabf2c53654b08207cc7bc7a3b0e1942631 +1034552a0b4863c942f7383786eafd7b2ea95361ff28a39b12cb3ad05adde9f1 +103b8763630fbd9963db2775647e2aef1c825182ea898e37a9b23c49f017b2cc +1042403fd010fc3670d50e6af305fb80249997922929506cf09a053c8013419a +1042e27a6f4d0b90daeb2fe46626097ac12efc83c17644071d3408ea2ef15d89 +1043dbb5648b0d7908cb6f2f20493acbc470725af2b814600733a44683352d93 +1047b8846a59b4514e1b6c9c6078ff864a45b0665d6b3f86e757e855c77dc40c +105c87bd967351afbc9dac3f753a72f20c0275543d42b966c226af78ba924db1 +1069705c5d645773d8b87e93cb07c2e03a3c3a177316d286cba066d6291224dc +107604c94b4259b2d3e09ade96fb94c0059f19bcceaf162bc40ecb962d7f560f +10784b4e3a22c8729d1eecb8e3278914aad4daba9607ae6740be9fe0a6601f58 +1078bf5c7cface7da013acffadb9944e21910ae188b8f7c2d0b8356c445fbde7 +1080b1014ee7c5c5eb9f8af4473e6a14c8e2fb2aab07e8621b5557e8baf9e67a +1084af5f0218e1c263987bd484092000946d9f5e71b306c99285fb7e7c73dfab +1085c6fe5789e09945a5bda156ad75f31d247b40b1b5a1e1e3b69780961bf350 +1094e5edddab567d026c07d82887125dfc72aa994718f94636ed99f92ba4567b +109e968e01d50eaa193e83e5413fe56a78e64671b002a4285c56df0f1db24d2d +10a06987479f4f9829f83ebd554f4dfec2455920957d8dd79c86f693672ade0f +10a175545d7697d0ae01f58ec68b152ac01c9cb81ee32abef9b448b999ad7298 +10b108127686e722c1f488fe9229cd24abe4ce2f9169ea2da3ff5f58a640564e +10b885a1b631798227d2c1add652f2a092f4dd721b5802b84fb5aad1716f7a01 +10bc557efadfa9d93a4a8810563a14aadb3309e039d3a2baf5e3c5163498da59 +10c951cb67b1dda551cd898e15bec5c822c05dd345d45e74e0f95683b8cc032a +10e3ac2ab668592f47e6b60f5d7b3783c02a7b3fa064ed2fec342b4086e10c2d +10fe7f2bfc1b7fa81ea1a3e1089dd42fbb7621b01a61f174bc29d3478c6bc8a3 +1101aa0d176b5e9129ee87c8b3ea2cb4c6beacdf29e22f722619d3d6e59130b8 +1109dd3457f983c38fb3d611eae0f9942f96e3d36908b5535562703ced22e4e3 +112471a583f0618aa6efc4b11b225a9383f03547d4f34ee8af7ef8629d2cdd5e +1128bdaef74d48f33fa3a15f6d6c758ae90cd47e591b05ee13733accc4d025bf +112c9415f3325d5afd49f41bc763a8cacc6e3f892407db2527081ae0cb173cd9 +11472ff513f1b8cf78fb593c0f50300d9c6112a483311017348bd03be1edb624 +114be39cc63af3e81720a077895a86b549cfca8ee4e0e214e17fc502b6246249 +1150c8ac2170035a42f7e8f11edc116ad2403848522a08d729b349681e565c0f +1158b5b7eac6b78c808b9cb3a6076545f3957df285dc278ac535d5466480c4fb +11613243cdc29efebc1bbd760bdec7960f0e3572ecfb4fdd5699908cc0bf531a +11713e1875b4070de327a89a5bb42d759af9e30614e121cd8935a47ba9138f00 +117799a5ddc6bf296f56755e8b8ec8663ccd41cb2f7c78e08bf055296cac8c8b +117bc2101558c0ee0d6a8abcf7217a52ed484bf493a23f1b9f066522a88fcccf +117d84749cccb6fbf81098eb04411f7b097891b065f4c727f181d1b62e142c81 +11885ec0bcf460247f4a1a6cb3562e351afd2746006583f0b1896077c6abdd0a +11892aba622e25e00532b4d6fb33539769f7cb311279ffcccef671b94d62b1cb +119bbd2684d2321fe65b6de36937ff1ad88a85bf28dac133e6e591f72d9164f1 +119ff0d03d40ed265576f72f89c00e8dcc76ccdd6849eaf70606ced2b473a372 +11a09baa49e2d5b68357a25951e333b529ce89e11449937fa3b380ff50446ec9 +11a17faa7543fa3719c4b3c3328d61048bf21ba1823aac512440f55b13c8e745 +11a266e18ea2570bac288cda1b644ab151f63a87ebe9bad2d4b0772668dd439a +11a673a882b0ae54522a6d982297c4f366889384536f22add3364b4b07dbc8ac +11a72d1f3d6aa8035f786cf7ef8807fb6a89540c49d7d5afec3e70b16252016e +11ac27ded8cddf49c9d38598de571c7ba5c29486a6db0fd6cd33f0a32994a302 +11ad81ca6b94dcd9d323479d0fdd355411fd53987df9922df148f609594a3b1d +11b6f4e6effb7474ab5c49b1db2adfac274e07b28d10de91e4bd06bb08864135 +11c26c5c0c7a915e5a6d7fef690a8f4baefddd513ae30867ff6b86e8a68cffda +11c5650a5e55e8d37431c3d5511d3b343ce1e1dbfad1e87ea941efdbf2f4560e +11c6c6a6cc29185e50e5d4aec93f74889e70876c41ad7f9edaf60dc56267c88f +11cd65e7985a6b9932e87e36e04fc8d1df281a690ae30ee851342d3ccb6cf826 +11dddb9470fd4a1daba1a08265b3334cca2b32655ad828b10186d2441a82346c +11de509c14fa04e01e7474744f07056cb0044bb0a0968ded372db91760d7ce5e +11debdb80129b0000530f30598cd8da13baf2c6a86e9effa1dcd71b3ca8ee06f +11e1425aa91b4b1e1d1b1d0805fdc02d5fd9b70f9619a21e9e5686b87ff61525 +11e4b3aab75b86e795d1ab769b1c448202dcde59dc3626f1c404cd926f98dc6a +11e5cc9860cde35223310e3475dbd59b566f556d70e997de25de34f204bc9a22 +11eb8e4e9588c6a15c3a81db07b9ff28935a25b7e880004dccc2e22d6df6b54d +11edd147595c65137a8cbb8ff5525a753c98a1ece95eba3fc88bf3a88cb2e846 +11f9d9d532c48327720bb369c5a4c6e94a171edb6307fecdbd167f3b78637d38 +11fdbb6bdb02a41915c7c6ad6acebe3bcd0d25fb58646cb7e75d96e2a1e44a3c +120959bc20b74c33e78872573162e0e94b06167f71321bd0e8f0c12f8cb5f659 +120da7c5f6224e334144390086f30423229eeedc5296cb8322da67217c80db51 +1211b7c81f1052052e2dc0cc5eebe0edf568fd895a4804c66b3548585a55cddd +121e2d9565ecf561f3e7e6d98e2ae6a2c49d11198d71e7d284a8659aee7d5096 +1221891650374406699eab079583c9747a856f496e9a9ccd0f01c7608624f4fa +122790f5f5827ee8232bd10fbc6477fe0269c90af96f587b16fb9696ead187e6 +122b3a571b98c5988b64554516d7818c6851bce897abda3a34c69abe3c6429aa +122e2d750364275019b0a06738b319c9bef6bcf036f10b02399ae585017d9278 +122ff4567df977b34c5ee817e09b28f45493192a92caea7678eec755db86f28a +123c626b0bc0254050097698e5252a15a824ef15c345a799468f905d985c40a7 +123cc5d86b4e7bb7736327d5a42c445fe66f721df91ca0435d60c73ebbff2715 +123dc12438f90aa2d12b6b7bb7980f32c7c5e025d1a7177a8c7fdb1a6acae40a +12401f1d3810dbc1acdc042c7bbc1783cdc52cafda9df943294c60770ce2fd94 +1241164a1b3e651f0dd03991bdb8400230da8b61f8d033ae3c6e1c0a4b24010c +1248c582c3b2053558d004dd06d6116256cd7b074cd5609cc02971e1b7e87737 +12496d90e17978788551c91993fe6d12a4d2f3e41bd06c395ffd797856f3e412 +1257176bbe6c09c15a1ae98d860b207b6e3d8ac614df776ce3138f685622f785 +1257afe79eb43476a80569de186dd31fdad3d2340f797a2f3ab3b965dd4928bb +126128e7306e48b9301f3a50a740b86f457a41118723186cbbcac0955448b29b +1268dceba3c0576fef38a332d6e7740305a9dc21b7cd577e0b688965ad001e77 +12759501e449878e2b668c48f15b36304333537cd407c7b98720c69373694c3c +127b7edb6a1cba95de69682293eabc3308c5ab040a7ac7f92367037769b38511 +128132e2ca4bf4a231f2e4ef27bbe1be040812fdc43a68389aa702306ae55940 +128b119b8fa294a54debad20f17f7635f088aaea313f28f3a54f1464c3281ac6 +128df13ed3ccc74933d8c00314e140acdf10a92d5bb18459396660fec8a43300 +12952acf91bcd21763ec39b06b45b018398248c2c598a67a7e7d71be696c4303 +12999f9f7cebcda08930c485ced2f0cb2dce58b04b8eebbbbec76c97e2696c43 +129b0faafd4c21f134885d191e1e50d9656ce2b8c6ff035c5fcf3f6ee3686927 +129b671dbcb91e69567af383ab1673eb79a879f86d92309240b84c2feac215c0 +129f87ae7d8de9b5785a420cbc656e94a480258a61d7e541e94d776e5c865929 +12a0792bfba1d9cc4b7ef1b626e3347896c299e092dc21c39ab5a5b80dcf95e3 +12a136d265ff710db4e84e87807d9a39dcfa211fb74050c909c8298ec565f88a +12a6ef639b434265f6ecab0a51c704dbca728ffcfa788b7ef4336969831a8e21 +12b266407642ef082643c30d528dbdeb78b462b3a3fca251b608215a62be0ec4 +12bbfe96ac2478921de24e525065c581f75fb64e225a9b6237b2fe76e574b183 +12c911cd260675df7044b2fb3aa48d68c6215cc2c6a5edf0119be5893b95e679 +12d1bab7f4258daad518cadfa5053e6b89c4224f1c6ac22778d2f244060cd36a +12d1faf5a380b4a99c5fb6ee16eb5c1de4aca66552fd1ed6e5ec77d2f29f1d88 +12e0644329773a327b9bfc3fe6b34fb3b3160ee27e029e68757d80d0d0a6edde +12e6814860a2a03f3b8764261872094824cab76d40f01f0c9f205d7320d9b14a +12eb488b09d99ba4f2398c90166efe09f6abc2e0351da6319acaf5538111bafc +12f41120eab79b7e81c1650a7be4359be107e85c9fb399d52e34780786864740 +12fb2af9ef04eb697551b49de9d9b50c82ec8a2051d3a524b21ee8618a4af3f7 +12fc21ca1cd18423280b41c93efbb58465e91c320a9e6514e8fbe1931e950470 +1301117848b275207601f757972c485ebf95d6d2b89ae7846d7b4c34b46e32b0 +130d36f306603904dd43c606397b369881ba3f1159fa93b4217ea055e24643f4 +130f193731ec0c63e1b9443b378d0b7c6020fe7221800ecc99f29c414af62ec3 +131117f92ccd5d936ec231974cbb1ea1dd059975fc4a5977bd2f44a6dd6a69b5 +13121c8f6876b131dfb68811c0e563f25978d085bb4ad2fa9640eafdd559b237 +131a2e95956ff195c4893e571455935b325e5d57db7bbf4c71ad34573a7a7db0 +1327b3a2d4a787016e5de7d9d9fdf8c4c326b23f4ab9aff1c607fcb16ef09f9e +132cf9aad939026c62838e0963863ded3aca18ba820145b296b77890e4aadc01 +132e31f101949bc0761e73e0a0b6ca61532808f8d984502692fd0908f38e0cd4 +1340d9062593b1ca3860bc51dc01e75f81ce680d2ed109c6a27c74dad3ef0a05 +1342075ebeca1ee22ea20dde347cb5c5544f4659c97fa9e4e12e6911d96b01c2 +1347237905ec82fb4cc980fe5b5ffef7ea81916fff7b466ea492983eb99db5b9 +1347e4cdd6ef61afd8cfbd3f941dc0acc6cb13252f27acb12904f41d83d43562 +1350cf01bbd4edfef75d1ccc3c06dda64f0478a6f2087108e4518b84c01104e6 +1352b4bc521ab556aaf8653c593e10c7123762a790193865785a57def0b328df +1360b657cae9c6eff52e413c99a82553d6be78d9e7e750d38d43668d3a0ad05d +136346cba103b1bafc2498514fb15b18747ea522470a1a7cb877dbe16a67b81b +136393dcf1875652b7ca733e4a80eb530c6a585a02660dbd645d7e662da215dc +13687dc848f33453ad7c939c7ae3f2c78513142dc32f51dd6dc38eed54618b0c +136b31b56a6f04c01a917fc53e2d7c75a310d32a5d07361ff836991fccd93175 +136de7180a62b71d9d959c75456ce5b9ea94d7712225b16cfd476788b27f243e +137e82f15530f53031a77fe083e09a9041958e797d056c20221a4b4577984902 +1387319a24a4a0ba8a21ff9ba53b153d6a6e741e1afeddb5d2f25fae29152f46 +138971e08ae33faa2fc46000354a8c6a3ff14d38a4e9a50192df788cf439c0c7 +138a6cb9edc1ab09615f9e2bd208d04bdbc78a7705bb212d11821b2d9ab72ca2 +1396ae4721a914dc346acb0d521a6cc58cad908bba54032a4981233bd3d578a4 +139ab768bef4debacc4885af7ba9dc1deaca8afe3aa73a72882abccd6df6c25f +13b1aaec8c9ce26e8b8191a0d2345f192104e2beec2c6d86602dd860fecae3f1 +13b3eb12e7124e7ab8f1538bc8a9546ced8d8a9b8dbf07e20fbf80da00799d97 +13b5ae4bc5b6ab32ad030e584afcd566ed0a22535306c7079e6027493906e649 +13b7c31e63ca06b5e39e5104d31d93f97d6915420eb0c844444e09b1d3778bdb +13bcfded3231c1317b9a4e71adc754b512bcb743a104ac11bae1cbeb2f8ece3a +13bd386f3fa37abd02df8699b413eebde8c6871ee48e34947df6813d55a93f08 +13d1ee274bcada854bfab75a61d74eb845eab7f1c4aaf001d2cf69992b8f4a12 +13d638d15d0e49f16d540f4dda92d0c74b34a75a909388d4ecdd3906205e2f58 +13e7904b0b0ce15cf5154cd57c2297671c50539227feebd45466e7555bed245c +13f4ed8d2ca98a87ac8b82e2f12cccba4aa2dff99731281d3e9f32996066498c +13f8bd068bed0c92fe90f857b0b4d8b4414d532c30589f5e691f0e12d4478307 +13f981a37573fadb062d36aaa4f1543ef9c0ae67f981e1be04aa354d1dbc3cc0 +13fb6f03d4a84678f2a46b312072c9dcb2ec43d914c67d789ecfbdf3d94d67fb +140a35b16a253d371350fb8e3a93eb51454bdb0572f2d88bb7c4c6c6df9da5bb +140d76fd63de47a84f4235a3c6a58719b3edec531fdf9f771e6833238958081c +141091296d8fd59449c9023a69c11ebc79fdc62866e3be652405c3dc751ff496 +1427a974068c34a753269221179c38c40df3b3cf3c8f94bc27b9f2550d4154f8 +1432220388c42d034b21ed84132c39fd06280dc49c186017a0ca04f9eb99ff21 +143fe88a62bb964f8e4acac354fb253c595d849866d14e0ba152e5d34403121d +14420a6f7b2bbbd7a90781b1b8d72148b754ba66d2b16e0f6dfcdc8db50922d0 +1446074c7e1398bb44139d41ac8acf2736e3df8feebcb84f8c1b88fdc6f03d69 +14521a15401ce994dd25690314638ed52dd087eea433da16737a94f2fabddd3f +1473e63297a1979475bdab13ee594e6e182b3abeaa1459e40c31ebe651880fe9 +14779418fae720a2c29f6f828c0358888a3d3a8fe3a1a356de6cceab35b9fac5 +1485da6ffde6976cf3fdf2274ae3108fc764c78f12b62a26fea63f9e93daeee2 +14884d32c976fd2b9804fba92726635cbc0f4a4390e44856961b72a1ed05382d +1494200891024b09770ec22a42648f95e687506a17eea24eb2fe38aa5af919cf +14942af7de9569ee1f6f238c6a0d0c4922297ebcd5b71deba188da338b67fb11 +1495b08d24eac30c03c85a9952c67125e43c48aac5fbdc1fcaa4cc773c767a10 +14a7a9f1eea7c685f35e0a0db68d8f05576a2263cb3b8a74a9f8db4daa3dcf49 +14ad813ef6d686db11d5e3da66b48ff85b916dfcba9fabcba6e6db5227d39f35 +14b80de84bfaf3aed715c94732069da7907f3433d79f5226569107f07bd307e6 +14bb1a814c2d5d0574bc85bf0ed46f7aaf255a78fe9917b49b2e3a2db8ab9360 +14c322a44e320d5585830594a6d43a9251b8917de026cdb1991ad0c949cfbaa0 +14c683051074951d70395df4ffffb780ba42adde48f2d28fe71da76abf9fb737 +14dea4cde51dd45bfb4637388548b4385f533288fac465112f8170f5faad1a35 +14e3fdc21410f462a6ca8a0646c1a2db64383eb3dd5833fbca5992a38d3cf99f +14e66944ff7bb446f4146a1b9c3a1d44e0db1d24768b1b6b004917887241aa18 +14f95232d1e97bd5cdf56b33693d8268adeab130516c53b01a6302d01f41ae8f +14fae5ca7b6f38adc35563ce46e8b7d756fb25df8cc4ef907e96c1cf31db8da7 +1507d1a4e8b996c566b76cf61fcec4cc58560a3c7c9a8ad61cb1b8aabf4c33ec +150ca147536d7e808ab7905fb5fefa4481e1b38f91eadedf6ac405d015249b8e +150f83596a817aaecd064133dada9b2fad255bc3715a21fbea26c6dc9fa184c9 +1514e48a4bee1a05597cb2e71d8c8844cad7a08fee1e775041321e3316ec2cb4 +151f481048ffe20b948713fec4de6704f0f7b3eb76523c805d9e83d53901eeb4 +152040ecf3366503e7277c13031fb56af7108d9535c30f295c855c48b32cba28 +152710481a31aa9252cb7d7a28b9e0f2260c9116c8faea1503777c28b8e976a9 +15345e016a0aee1214762a6b356255e0bce540bc16598a3e50710313f71c38d2 +1537137067a71511a41a88f1201e72b92b6b749f15c4e4f276ba43c37e0aba40 +154bbc6cb2ad505c5b6a530920d30d3aaf5576bd7d5a8c2d910841d2e34fe337 +155b0bcc6709069b6fdface89ecd23b0b32178b7c5d3d4066be14a62e5d56c4b +157068cd873fab755b180be602d130cc10fe5d774bd38e8b167a9a78f37a9e90 +157a65d42cc73357ae9a507cf7c72b51aaa8cb5148dfe6b1bd1f58e21f5cf438 +157b08855d2700895255dcba53f9ded5216fcaeed2bcebb15b1002531f992811 +1582e033d06550204365ddfa2202e653ba16f19b644484117fe84c833b5b7e58 +1587e39d2bfbeb5771fa87e303e9e422da2648a0a4828d06c24ac45adc127ee6 +1591d886aab8d9ba93f51a8ebcb73f9d94c46f12cdd0959560249d654878838b +15975241aa2b05a06bc9dcc307d7c450d7ce808ded71d97f07a438502bfa3943 +1598821f681a6ac9ef4bfde658aa99e18c46e70ab67f653b54f2d772297f4ba8 +159f30e6ff86d4e08e45131e53e0b3eef50981461bd0ee035f7e1a38fc436d33 +15a61f936f282ecacf51aabcf429b5894ff5ce2a0e358f301d7df95219d4bf51 +15bb24231f06fb115adecc03a6d0bb2d439ee09ac3d07ca78db8ff360529ee2f +15beaf57e79f83e778373953f68ffc90b664dbd28a2a1fa467bd76e99143d912 +15c0b9a148976ee19a48ac1a56dc4e805fddcb9df5fb2aefbb6d7627c1a34b79 +15c55318bd52ed5dc29edd598b85c71faf8b89c717bcc5718aa304d0bac0e43a +15c846e1980eb32bdf35087939b8c1014c6e11d8ebe975c2323a493b19a94068 +15d0fe2ac7fc4f5555ae167b0db9fcfd79d411a41530c362d273ca7ba0b9b52a +15d4316d06e146db379aa3747cd60d6a464ce95975f8e49cee5073186db26652 +15da69a97243b64768c9af9e5de0f003614b9ef76ca9eb5bbb3f177de3c88e4a +15dd8d059d92191b2ad91028ec79635b698cd54c6a8487bd999777422cfe86d3 +15e1a70c3fe122987bbefc4099d1935fbde1a3a14caee397112d720ea19bb40f +15e3250846be9ea154b1ed1ee8c6b742a388f40b962d073ae2f5b67ab3afa634 +15f1ef8a4500adfdfe0c4a1195ff0dd7bafa3a1acb802fe30e29f633865f7545 +1602e961be32584bb1a316163791e731733dc1f2f2d3aaffb7babead99658ab2 +160f3db92830eb745f8f7e1bc598d40ea6b7ca485c6bb92c817ae411598a3f71 +1626e20962eae650a0593d76ce37d70fa3188d0903da5ac9daa29bda6578f90f +162f5a31fef5b0b4368a8334bb9a136b949dbafc9333d3426dac6969b151c635 +1641590535913ef5d6d0e266f2d70f05f87ec46d7312b1f4148f2db0b1731721 +16446de9eaaf71b428c9b201d91795b60fe2d5830831c1b9e8bc5b3108722367 +1649a1e26cf4af53f9fd70432be6236d2e8e859c0528e65b898830d18b53ee9c +1657870e07bcfb625ac7709d819dbbd3c0b28a4f141694237d451227ec38250d +1660fc6abf80af80526261d2e547a30f343e2e38da36ba277ebde0c7764fbcca +1676473b0fb26985c630e360fa7bf9e82e2a234dd413664787c9e494315ee17e +167acaaf5c2eb3b3df31d1251ba148ef1e289d785d99f263516eb6e516d32284 +167b8e72ba05c652a4481748ca16528b4a4c94786b6ff7c2bf1fca67253a8167 +169238c60e75adbbc052fcdfff6c04c1fbfbe2512975bf76e2958aad5abc0a3a +169f2b87e9b698a6a3b50d88b66c737a0b1e7e0aa16ed5a01197eb3b87bf9836 +16aa373fbbaeed5b73366c4b9f8b40c4a43e69e8e802008b51ba2edb4cf53014 +16abe8ff6dc3e91d768b4788673225a5f633ddba5931284806b05c885759f3bc +16b5f74b9053c9050238f45b6a95de3100a563f32337d56d5922d48fc16df13c +16c0f32bf3bdf34a23cc0580bf9015b5b8e0c9a3c6c0a302294fcb706ce80821 +16d5039dc0241f8df751f120c6a9002dc80baaac197a77cf041f19ebf6febe88 +16db79e6ba1e6964787ee94a9f3ed19d81951b550144e70ae7d1261bb6b8f2cf +16dee607063777547c1ff926b71b1c7f712edfb1243f119f131a7ae109de2e16 +16e99365865f9519873848b753c653bb9d5f7bbef2679d511225d3c2652ff3c0 +16f2495e47fac7c73a75e6459d40a8dfc1156c1b327bc88a492ea581ef411eb4 +16f626eceba30a416c24efe50fa5d1a7f435c613f30d377d7ef50355f32d85e6 +170196686a3bfa30a885e7f6a54287f6503d9f3d01f69acede0791f993b2beca +171104b1b32ba885a6454dfd092609363838462dfaf25076765862106cb704f9 +1717c847bc2eaa6c118cbbe3ef437dcc5a1a0caa2561efa95eac47e0a56956d5 +173bb215758d9ec5839fdf2a3017268775d77f4ca280671b488ef37e9e6981a1 +173def979b6285e530088ac8fcf9fbd000f2c59bcc8eb18277bb57024005e9cc +1747b3dfecfed1f8e38dab1d8d88d889a017e5d7c663286c9460121a2ba3b59f +174f94f3e8bfd55a5813e50c49ce92b2e61f23b64c9a28b64137702d939cdc3a +175c18941876a29631cac3815b4fdbca921487ab9d42115f744b63be391de84e +176f414c6afb21d6e3ab780e32347fdb123fdd1526796c6007b3e71d9b6949ce +178072e20747f952d9ce8aedb33e7ca8fdca87a2ae5f214268e89be4da00c8bf +1785bb2f9c1bd1aa83184b73450bf7a042383f16b29651a9a286409aff4140fb +1794b8ff575cbb9b447cdcd59be0858a9870c76b7332bf69b91f6bda0b1a2f32 +17ad90bfa7499976d7984fb0b33886d9cfe1c34183182998195590fabbd6934d +17af650406218a21553eb402b8ca17518a9314f926e1262f7e916b29346f4890 +17b3b2f35ecf894392314f892b8eb7bfa24f1569d05d39cb88b83787a3250337 +17bbbd7306e0213558f6c6a716594469a057a0913bb516543d83ed27a3293b9e +17c4d4fd7ce97e53d9c5dbd946b8677eebd7b6952fd2751b29c1d70e558f1cf6 +17c62415f20dc81dbcb9df6693a021693c980ab36cb489f4d297755f2ed32d1f +17d0190df0f30d05b8b4a213b8267efeb668eef8ea3737039274fccd97b1e222 +17d67c9b742f0c683e4b831c888bcd68fbef8983549260432c2e3c57ba8d2893 +17e08317d99bb60719921cdcc66513583c6e9148de5ef801c6c8e1da46bdd218 +17eb6ac1fa06e9b15271796f35315541daee922ebff1524640d3f67fe0640e2b +17fe30256c51ddc9802b4090663b8e7156f883d991177165f290fb8f07c69f0c +1804697c632544ed70ffca2bf3b32ddf860dee65f65aabdd4d2eb51a735feaae +1807663c5a20f5d1c85ee4ea98a85760dc3614616fa12a623e7baf57480a7632 +180db89b7df89ad238594368b8fe3cf61494a741ad8bf5a56ec374044171f91b +180eb8818889fa76c2f6de4d2dafa3d03fabc5f79519c256b0670e462944d3e8 +18137729981cd85ff2d5ddfb9d26f71d0234ecf0c15069c36e503962514f8314 +181a01135b2e1f51ef2b196e287ed75249732074d1d01da3c0d77449021e4972 +18201f8ffe93d5a78011be5fe7ea4e56bce3a2c55a27a3b8d5e60c46aa99794a +1823c2aa2f07351268bafbd8bc9549c78cd4f512889f305e1fd6026eba157e01 +18282d09a64088acb4cfb669611a7ab7fd8bd19bae396529637106a06239cd54 +182a665b19c2d9335fe0dcc38af5a04ac8e3915bff3d2e2effcb0b1ac396e321 +184346a9205c0ef26779f06b8d42d242edce247149c69ab9fa20c62763e2fc6c +184655e1d8c264d67fa7b5c8d60d3c9d79dd7bad6d20c4a78fc2efaeb568a493 +1863967f135e54b9cbf83ff4cf6d883b76a518982b77f2ac410668ee5894928d +1867ee6ecf1cf174d6f664b5cf30d45ec6f199638eadacde0739710cc4e3a419 +186f9dea4c7b87755a6ec783729d6abcfaf126336ef98b4001248deb3c42459c +187d4b82fa397494d9aa76a3043a8969e23123eb60e9f027d13acba6c3424268 +187d8fbabeb65da2b2676447d2f3e3429e2554c08be15d1c2de988d12e8d92d6 +189e1ec623f96c6e4b3f5d3e9ca9f08ecb1fd8dfe41bc362f472f482d343c2d1 +18a18868b250f2e1fcd1ca3cc5946df1cd9c42069d8318053968d0a18556e570 +18a244758740e49169d8497e4afdaeb573e9cac0cebd8e27d1b77f428dfbfb91 +18ac914e3722a91ac9bacacd541986d21b981370b64cd1b2320cc76856deb5d0 +18c0400e34389023c74bd7c705a40c445231e7045847e1bd84da8a68b65047c0 +18cf8cccf09d8c3a26a76e26fd9e28cebf411f2269276b18636113048a94a05c +18da7d562a947797b5ed406e16cc1082d8184b63ce771292241b88de39a0cecb +18db51dda4102cc3ece2665c29aa1fcaa905a4e23eac4c32989c4919f8053cdf +18e0f9500eee2361473ab33cd223b575ca41bae28be63e9ee83ea01b22f414cf +18e75a561a9b7e332549c278dde5d268179705cdee040f38ef8eb8f9bb5fabd0 +18f19dc5864d51c6cf23f233c8d75a4015db938154a8ea88f18859d1d906607a +18f38566ca46a546c1eec0e55f27034d3ed9084ba3049a5ad36fb6782afa8a1b +18f42e57864529ec57bcd9e629e09f30a69f8adc2879a3d1db35ecec4ca3861d +18f4d3c827a4ce913d86784a211f7432e195649fe4795a844a5313fe66559282 +18fe249f716cce7a067934685003f2abbcfa821de294d0eb51e44696fd5ddb38 +190556bfde04273ff2b905129027f05a6cf01afa388472d5ff106fb1353ab375 +1912fe04d689dfa0bca10f7edba6d86908e23535da305f952f487a7d537b2013 +192c8cd0bfb81e2e5e919e2885fdd7c523dc7f52fbe764e022d9d1c07199f0be +192f56e4001c45e6657535c820c73ce2bcb682d95d62aa1d1b1545293493a24b +19450f329dcc0727e448cd4ff96224e5106b322d7f188f89d290cc286ab0997b +1947868bbf7bd877ba619e518f95b9c195dcf13fb81b4837e35e9f76360a79ef +1952fe302a711c2958954b9e0a75b8baa97831af5b8332b5e1e60e9824767dd6 +1965ef69231a5e57662bcb465dcf7579029e6ce9feaa897513018d8137398884 +19661ea0deb4f1eb65b147c46445dc7e6f3a28f61bb3822ad01f0044631e924d +1983fea9f10d8fd75da7ed12dcbe59a12cde092120de844e855ce15b67483c89 +199a9b838844113fbf643cf78961cef20918ca4af52eda76d855f06f4cfb878f +19a1710c7f11033bcea96395c06139253d901707924b48b84e37ad277ff4131c +19a612cdbc63bcf90f272787087fc56bdfe6336a5a2821060c2e12986e928c1f +19b4bf216ebaa4f7ccf55f93208d8f22c19f492a29775710fd453ed182ebfa5a +19c77a4ac5605749a41804e8f341a486b37739ec5459d4832f8477ca3b34c0fa +19d83d351a49c07ab307c4915048bb4674800b816fa2ae56e0fd3cf656396eab +19e40c4ca85c2dc6355ed93a049d062ed0f2c290e73b920fe72e6a2d0d7b0980 +19e68f0d75927008fdc14fc5b815963aac716e6e8380d4ce0d1b781ad98c376b +1a03370b7fd5efcf3ac342646379779b77d450cc41fb04c4bdd9f9141f2d9075 +1a0d162874baa6508c7953b3a091b87a6c78393b0c9e49f85f7ed80c8540e73f +1a12da96d247944de936803387ff8115a80363006c5dd992931e90ff2864d263 +1a194998c094db6c58e7a54ef200922f2e05bbf355d559c0109e67c50511bfd3 +1a254885d6559d1ef8f4b2fd7109c927fe58ecebc58ee353f155dfa6dbb68a85 +1a25deb3fd8a87527ca72ef10f605b4e79cbaa9033eca3a04697ee6af5667474 +1a318f30883295e862dab079e0625946076e43a3fe7f886742d4ab8c81c78a55 +1a35a1f2871f639db2fd4265e18cd0e66e50af30f292cd91a863bcfba3185e0a +1a396368dd71c1ab272c1f6e31fb2ed9bf6a5894e6109c40802e37af429095df +1a3f4fe09829ac498b00f6cd43119ae0c7318f5bf7af355b28c57b48564bfc90 +1a470cd78cdadd15bc81607ab15177543055cb3e63990565f6719796304fcdf0 +1a487f8d9f133079f5a05f87d72c8a2613b20925a5aff4ac9e998e34e4ea27da +1a4e9b6664f1f2aaf141fc5e18acc2f32abcf18a694bd9e3f829d0515cd102ad +1a5979b8188cf7d9d9e87726de68296a3168b9adfcc3c4c263a9369e2d7c44ab +1a5d10a1854a9f1d494b855fc12de0bf309c831455ca1b562dcac0450e42115b +1a5dce411ee2ce8609495627782519381330ea70e84c313f39dcbdb2b37e23c5 +1a623f7f7aace62d349c61183af10742c45d37675dd3cd4a9cfa2858e9f892d0 +1a695462323cb2ca296dd88bc8e04751075535794fb4b204f054605a7b6db1ea +1a6eddac71c4255f7a91580d77c7df05518df7296fc6d009e8cdd0a49cb38311 +1a6ffbabc647ff6bdffc4dd29a031861c509d086be26214547131a87772935d9 +1a733af2667d36a0948e9b3427ef0cb8d9a3254f98b46d0d2063dcba59350727 +1a81e70dd778315f04f94e6bd6306f4fb9f88f8a236218f8d86aa3e333838dc9 +1a971e5e1d0cb8b05618585e6986beb31b55d0a5336b7384cadc1c3e087a827b +1aa88d97e7595c98a2fc13134427f5986af2a0107158a23745077d20c2fa37d9 +1abbeac1b2628a7ecbbedb17ade6fb9b85c9535ef19ed5ec99b8e1d60ace9712 +1abd73784fa7951112c7f815bda9fa14ff66d8e3d2ee90a546fd4981cb4f1aa1 +1abef397c1759e88143f39f359f61c0950e5edd80601902af351432efda9a7f0 +1ac20aaea5262e24b84d190513f76c60ef04402b8227bebc44c974324eb203a7 +1ac23c1e1a2d13d5edc95f9bdcad9bed002bfdb02e456be34fc8a851bed21f38 +1ad977d9b8a621c97fd2844e27dd794b49cae1de2c0fe337c12a4b43d277bbc8 +1adba94af065e3037c60573f7541199997e8e88d6c5eee3873741bb43fab82c4 +1ae33ed55148822e525c134e57f6c29930d94297e9e6b5a5109fa4d5ea805f1d +1aefe3e139e9084f1ce4ac1c7f14ec085918a2007e1c214381aa699ef4057a21 +1af26dda38ff5d4fa64eb1705181e858c61b9675d7c73c83d3952578988668e7 +1af84f9143d1f91ef7208bf178b7d1933845086af759519f44558c363fc27567 +1afa38b9d45c30e6c7e82e9bcbf1195022a78bda46dc111d51e6d81319190487 +1b0595c7a62901bb9a40fdabe664d8ef7ac1a83cff5b5ed48a50afeff39e3d6b +1b0ad21d03389e62554a7b05ea0a19b2acae21cf1a3d5b10540a4d20c8e6f125 +1b0bddaeedfa227fc7fcbd726371798a5fbf3454dbb587d81b3498de410045b9 +1b0cc26f48bfc4aedc9360bfda24f6333522944e577436d6bbc3b45eb94ce53d +1b1326166fad2bed8f1d8b789a0a7b8c7e38b7f57b6da2fa11032320df2db2c8 +1b13f49d968973504d121f576c771d64a4249d82a03bd2a2851eaa7e9c4bbf5f +1b1ce4e0c9ae12b94c0a9570f2dcd35ed17ff5d9d1d6483dfab3f63242c41f96 +1b247759a8aad2792c3b2f469cafceaacbfa5e2f2abe846254fd9407067cd231 +1b2f16532fc7c0413d637f089c28deadcdef0f8648e9fca8a07bc9810029c741 +1b52d711dcab127884115c69348d3d09035e79860c841c859a485877dd6bf8d2 +1b578b7ac97188ffbc56d5b26072a3066d651792254d0710b609f39e880d0eff +1b61c23a5c1e452e7ff5545ae9d28b0c9fbd8254eab617b07b018bd7ead401a9 +1b6b1274bdc0c2973ebb1b46529731b3f254123fd811afa63b12c096040f1fd6 +1b7a83e3dd7ffa4a5462e77a4caef5d8b5738dab8ed79f899926a750aa5467f9 +1b869b3a083f3cce7cc60fe3be8f8f44d4c998562cef83bb0e65a9a0fb075d7e +1bb4f54fd7b860a1d539dd62c27611f7f2ee31b9a5d81cc90e447f7ffcb1ea66 +1bcc01ce0800b0ee13481668bbb9ffab55e68e78563815a720abd2ed67b455ab +1bce44baa6eded3627c604b6af68f5045003a01d3581620ff22eab422a3c5714 +1bce4b97361b3905a6dce201c0d90ff52bed6f2d161ceda8111462801ea6566b +1bce4e092462871cbd6cd5a38fc44f12fefa156cbddb4aa1825adfa3a1fd7a95 +1bd91ae94766730a6046d5c0309dfcd85b8d873e8ec3abf0fef0c55eb33162fb +1c08cad49a2b8084b158b1140435825b399fc8df167eb43cbfb9ec826bf4596c +1c0bad659c754ec55c3d1143351c4353279bdfa22e0f2d834ccff1cdfff7fb77 +1c10b1f157598a76eec298da287eef52b119211331087dcba2f3c8cc146b5655 +1c199e077fbe3c2961eec229714a6a48ae0cd8ad50b28b1c0d4cd8cfd790dbba +1c1a08dd6717668daa93f9ee1b90af1b05e4595830c552f733c3345ff7412626 +1c1cf0d32f8006ab7f0b81338a4d1ac272aaf76cb60e4f220afc4803ba694da7 +1c1d789cfec0d026db97a9a2119ba396c7a92d4f2efec7b8cf89701dd8957a51 +1c206f0343ba649b7fe19d86356aba6f28093520dd3b66c49b8b8388840328ae +1c23decee65039ad263d2e82f864f004da353377bd4ea8581d2b402f5dee0d63 +1c26fa3992facd4835ff0e82388b62a8c6b9c9b40bd912aa4174fc17e6da5a01 +1c2c209a284df2736ebb85da2361ec76c22343f8b9f97bb80ffd78c860bbbdf2 +1c2f40ee516ebd3f1e12bcf72573ef8d6cae7fcec6d4a2d1c8d471d0caa1a378 +1c3247cbf3b526215a4da5e95f53b77c85e4fb4a22f895104a8525e8d91867f1 +1c36a367fc9ef038aabf5714d61b861a0a786f23c601d3bdd296ae121ab50c58 +1c3cf009248e502f8a40ba3ea434fa65099f5aac9e5f0a54274d72beafc21def +1c4b5b05e08cdc4903b70423590e5ebbcd44c750216451e43f776288d53c17b3 +1c5238b3da64f427f686e008f7fc3635baae846c10b1a8cf90733436da275c34 +1c5bde5f0e2899a73fe05fbcd6f1ef3e680561773a962209166a7db5df0daaa9 +1c5dbcbd8266861db168b590c7b8590bdb125a7205552d1a91cf019d5f20cde6 +1c63b60c76a1764d481d6460189f0e6dcb34e24b4159f2acf613a6662b71855a +1c66e6cad878094d49c2a190604a18c361926a492b540d43a7cb39d0dfa6ab9d +1c690481dbe6d69d73654354635eb5d31a54312835e4d2b49fad788603f4ec92 +1c7098c368fbf6178edd3a8b2890d1e955fcd7467b000c4c98f7c838809a3a63 +1c70dbd14cbce5b547103952f2b542b734ee0db2cdf2442a6df71e52cbe9175d +1c72d2f93cfc0002d2e5bd6360b2405517d229f6cb499c6cefb691bb3717606b +1c9f5f7b6b8e6233269b126df931bbb9339adface1a5f083730ae869baa403f7 +1ca050a2846022e9c7b4d11437447a0054536075fb09990254a4d6098b0091c1 +1cb0594c50ddeab338449d7cf3d9ab73e033d981b9968ec47ac640002b50af7d +1cbe15acadfa518ab1a09d2e1ac60093501d494f142d021d3723145f76a13774 +1cbf4884809573fc8ba65990a3af1bff96e312b2f4dfd9b8b5b8bb26c3447408 +1cc4038d97c828c4962a5744253b7f3fe591aee819ad07fecf9352d926227c3f +1cc42fe259a96efeed9c7a3ce0aff65f7ef3b5d0875477da17d08fad262f338a +1cc57be625d0b78e5fde6c817898708d08a4221b43d51f8d934af97fd3ca6904 +1cccf88516c18547487d15a5d29d78bab3e9ead1f219ef5c2a951ca08ab414db +1cd7e9ab83e9ce637a8d655b1600b5943762725135b3c1fe4da13d636bfba0bf +1cda848ae864cf815d51a6735a3aa7698182a2afb002ef7a6bd4e1e8f5e46b86 +1cfbecd93bcdc6e36d519aba2d4625bf3a92b5805aa070f0dffea1dd2acdaa1b +1cfe27b80db0db58d3d6ed7651a59c430b89cab8ea1aa2bb6cef2572cf578e10 +1d0a8d65cd9f4f81b057df2b625e666e65642bf52ad3007c4885f1169b71ec41 +1d16cd711b7c74db8c06d54a3c7f8c7d7b5b8972c045c3723930e46966fd981f +1d1ef27eb7f3985a62909861c21375cdf318d91a3b5dd1f92794902fd9d1eb89 +1d29e28b127a53f0bbff4e0b977f9e927d2a3c9a21ae13a514e09cb817323d8e +1d3a66459a4dd800ab6b385512a9fb8971c69da7bc7c7e03ef7433459ad23f14 +1d4ae945094ec8156b539a246a289ce8da2d0690c2021ff9b6f7f41a1679647e +1d55979c44fcbef91ce968297447980a91c8df45a6e5f6d32461f84b3137e12a +1d5a2fd7eb56979b5eaab707ee44963dabb5d23e8aa39947b3ef6f46feec51ba +1d5b6fb1858d53656341e504242ea9eb9a701442e62f82fcb29033966c4645f9 +1d5db178f9bb454a5fa33086d1e993ae9c26c57f961dfd0350d4d573e3682cf0 +1d7145ee1bf52328861318d4f211491cd2fffa9204e3dbc5b4359c491bc361cd +1d73ae8ecea12e4af572d0d60e97a13b7c4dae4c17b619a49c2580ab0130f7d2 +1d74ded1b585659872758ffbcbc3880ec1bec4eb5c81cf716d58308dc4aeca75 +1d801271dc1a12e3550847ca4fae43af9a98f09bd612fd5e15eb5372e858767c +1d8d3ec43ba1551b9a900749609b9b9faf8761bf13efa39e74810b7c0eb0849a +1d8e9a0bf639190114b7010cced50be3b8f024df5417a1b1f2d715c92223f886 +1d8ef9df17ffbb6dd6c76c0c8a980a97ad885cd50632add51af78d35f18dd85f +1d8f19d20588796e738b2bb24ee814ac1dce67e28b8a2294e4ce443d7e01b65b +1d96174ad7007c94be22a7c1b61912688dcdb3ac9044bc32f8655ee8a63fba7a +1d97992d7fec418f739ec0cca3b42148917dc2aa7beb476898b7497832327091 +1dabb2630affb9959de6da18d9ffcdb99fc7f72b6ecc32541767ee588d09351e +1db22a95007eb0d6b6d0098e24d9c72a1c7168f1f642a8c60cdf214d9b24fee9 +1dbecbd87bd2c57ecf7c6ada23deafcd27f279269147a32edfdd5c5b9705d800 +1dd0b8d4a5cfecd3c19a0d448d1a4172d1104832e90f7cb7e84b2615a849281e +1dd127463c99d696529d7b494381b255ba6496876021aaecd3b5a9d431a895b7 +1ddd2eacae2c8d7d0076660a6e6c614b0cb40c2f00a518b953c738543263c7c2 +1de618af825d991ac6cf3db6160e24bf5245bcf0f838ace6db1abd69df8c085c +1deb0b39d8708e18c647b4bc8ae82a119ea176193eba1e02874364075ce603a0 +1def810717e69d6c66269989a1bedeafe814c45eb530c27a7eb1f06bc8ed8924 +1df3254c69abe1aaab64e9627688ded97f0943e5c1471f543627d8981464ed90 +1e0e832c5dee46a572fb263200380b6255cc746ba9a24fd14721e9d9ff00ceec +1e1277931faf2bf14ee6cb2a75588dc19dffb5fb76292a32670eeca94717f314 +1e12d1a794bb3df99a96514c54cc381b5f92bd7832beccceac6e29bd3148749a +1e19771d5138becfb8381c6c4e3017d258e30fab380d353d1b3c5da9af266065 +1e2449f86034813d65b890eba7506b38349dac93cf5ed568a28f120bc00167fe +1e26493e8c240e4da5bd636170702f883835aced1c929e345fe00e92a4d7abc9 +1e335f727d30a8a26f7f81d933dde15da9cf3cd1f9cf1571a3a1866686ba8a7a +1e38b2ebdca0ef879dba9944ae479cbf4fd36e524e41d5298fbfbc8cc0fd9c07 +1e3b481bff6ddda7dd0b0dfc90e80919b179f83eac7cf2a751f143670d8b2163 +1e4426307b701eacb4af8fa5077a8c0a10fb2267c90bf12044b8f44351c8b44c +1e4767c1a0236531b35fed35aa380889d17d67fa1ad797d22fccb5ca32f61f4e +1e4c7e2219178cb5d9065614c8faabdf3d36283b8e95dcd74b65ea16d6a85530 +1e4f5daa4495c99d74976a5b5dc9caa2343ab4f09141b59311aee6997dad9c81 +1e54205498d4cbe847cef89eca377a5aac6bb5b39b029c6306be4645160554cd +1e6287dabf363684a0c109a91b7c0eae2cb6dae826991b05110222d855481ae2 +1e62c41c8e7d11700ad91028ac467b88a73354af82c3920259892dcb1fa33b39 +1e6358c517612594029be7c643ef7ab47666251e1da5f6e71e25711f5d358840 +1e6c26f2a8c937c239d3f153244256196a51b785d842af4a1e3f0f3fa594ffdd +1e6c9ab63941654ff40a1fb3754d081dc9b2fc8135ab1f88792b33049667a5a3 +1e6e22dc23e34a24c15cb4f3739852ec93e416ee877e1c89d0e21a627d02a824 +1e70a10cb887ddf77150e94b8d1176af8a8b367103a369b6a77e3f0323c58657 +1e75eb94fea5a11924ae3f324e29eba5836ee5c9de38689944534abc41ef3533 +1e78428d80e5680290609ec9c7cfd3eab45c6d040a2f02b1fa193190dfab3b9e +1e8c1d50ef4ca034ec86ec3d1c9ee3eb0f21bc86c40752a7974bf1b17479c11c +1e9b22f63c6b6e8e29e5fabc2c32ad627ec5880480e18c47ec909dd63dafdbba +1e9d0e69528f8751a030ea00e75a89b5f9183edab80f3c7efff8281a3e29bde0 +1ebc343baaaf041d57a2226cd4663a7b0f8eda0ceba1c325532aa929c2701f11 +1ebffd6d8e77d25f30cbb7e66bbd860755a0cb5f49c27268673beef8703b2907 +1ec28940704833230db1469fb4c958cd3b890fa7832b3de5abe756f280c7e838 +1ec51a0d90fcabc52746f43ac93b4214b2e4afe24b7f1edbb260b53d3767dd3a +1ecc7dcaec866ee2782841af4f4f9bb6aa166f2c4e775b3929fd0bb4b902f066 +1ee05caadb2028c2b5de9b496d63b078c67013ff533ec175eacb837ac484171c +1ee2522c0d1840b0025d31e30905f1b13a98ec2b0d45399b79f2ee206e5be8e9 +1ee33ff95611a5f16fb094ba73bb92af50ea93d6ec4c35f987e918004de569e9 +1ee67ef9ba07d956e909c52b8fbe81b663ab1310c2fe93fceea1ea5b506e07b4 +1f0b73350113059d0017828120c33c102ad1bb240a7681943f395d349dae557a +1f19d6694cf986e4eade0393d1c65a51c42a11d6e2ade41d03fa84dba177d6f9 +1f1c4cd80dee4e81f9cac0492525e212aa73d83922a393019e69ec7481dd9fc3 +1f23ff05426f4f192b253c09c4b9ab59399cc135b29e52b7400474a2d9114677 +1f2e4a36b8c6c6d5dc676e7a40165c03b69692eafbb91e631a5875df97f40db8 +1f2f58a4601e273fe4b739edfa9dc468d6b2205e4fca085554430dcec735d457 +1f3a225bf18d7ff8f4610957527936aa2bab61068dbbf6488e6a9a3befa2be5c +1f476607d28f2dd96e619e9b297d38252e2e2ddac5e7f76fedef82f3e50ff451 +1f4d7ea16207f065eb5c168de835c5bd81c552d6691618d027c9f362e6b3f2f1 +1f54ace33d71094a698ae22ce5b5d09dc2776e3e075642be2fa2893e474a34c6 +1f57d0098ab8bfdd702d04b4ffec74dca2e7160d403c0021446b282b59d51a9d +1f582a512f479e3c9979a7dd0684a0d4ae0a65c94e16140872fd3f3ad8cee27c +1f5ebc1dc677dc128a8d9d1b94e6e3c5fcd2b3e3d06570211b4c5b320cd3dd85 +1f6948f9a59144a81dbaebff717ad81b1c9859eeafd82d74c01107837aab456b +1f6fa06d3d4a0c35838f2c6132e4df8ec8e05516e173dfa03148aa36fdc669ca +1f71dc3043e4131d878132bda49496d77f4273950ad45d4f53aca2a786095226 +1f75d6dc99c17c4ca2fb8d9e54ffb531a909ee3a87271ed8dd78809e3d84e496 +1f772cc98dc7edabf341d7b22ce1678d337dc5d5ee9030acd4c0103d1aee07b6 +1f78456d1dd292e51accf112b77bccbf070deaa3cfd7fd17d0c0e65c525b4c35 +1f80463c89dd53e08561c081e8a87b5f2437dc940cd5e1d67bca6e7c72315ced +1f8be3d87954adad1e79efea5e83fd9527beb8ca1ca7dfebd01787d84ffb30da +1f8ca800887ec9b7e69ac20ae518c2efcaf85e79c3c9a9bb20edc565e14f1460 +1f8fd2453428a8c20b3f21137d7cda099a91a4a6d35fd74fa3c2ee5cad14f12c +1f93662fb78019b3d606a00057479bd9736352781c3211e17f26aef97020cea4 +1fae8749456eec97bc8d71c3b4bff594b4a73f343839119bc22e66d051d3a59d +1fb2a6e0b878e2260c302c7f3f2859daba4ac440c2d27f00210347bf7cec0f33 +1fb5116f3fd3dd7821bf89e253caf65935ba3132f1a01b9b64b171b536ac2fe4 +1fbbec85016585e3e07bd51ae07c7d6c1c00fa502555385e5a4b78923cb0adff +1fbe7f70bfa7ffcf9e88e485b18e8720058ade7522c35cf01b51f7c8ea922dbd +1fccb8dc1ed96b3f04dd7ad7d7eceb2ea86a2eafa6223c37c6240bead72ae78a +1fd0f5cc4aa73320db5e209723a29dc30511b8cb90e861d8ea629603e5370111 +1fd9a1b1890d8f7f2b87df5b85cd404fbb6475329fd4cbfcaf02ad21df818b77 +1fde07c7e529ad71386c3bf089cebe5fab891e858aa1ac4e4c6280e676d32205 +1fe324a519207d195a57d5d789c246acc886b97e10022b5c3d53ac3c7e417997 +1feac8e438e7549d0a217fa3f1e74bc6660543840aa55834fca996b9fa501be7 +1fec27d0cc01385a88c4e92e1fc06b24a22dd264d4124a33f63c55e6e22eeb13 +1fecb74eef1e103a72ff97454b3d5614732a1ef23ef45e47dfdd926458f88297 +1ff11a6a96df8421cac1aa0c7476061556fc3cf68747a5aa5303772ecf957d94 +1ff3b4863d3ee7fc932461d44109d812ac88f5b114ba037442b57ff4501a937b +2000d83e77f3fa6e132583475a1f010afc9c3e4e2f1c87e67fc8abc73e12ecdf +2009526ca2b76418003a4ee3cb5b6f53fda08d3cac5a0f5495f513e51b65cb5d +200c00b3e0a3f76222b368942443ac6d3b7abab83a24bdac6f774f2bddeb7b33 +20102c0ace89c5786106d49cf81bccd8430268e4db95ac2cf5c6946e275c64df +20135702dc8325d2341f7efd8f27a82cc6c9c04d88a95758af4c64c825368d81 +20256f90466c71f9ab7da21c9ed66b7285eb32a903b2d50a66fd09d3b73627d7 +202f6c687967fc61fba64a82ff5c2a2991d339aaae138370cc1f32c1ed7aabdb +20343386786dd3e4887d6b96478c8521619d47d2bafcc5749be05f690e28c7bb +20386a22264420c8cd86f354cbb69fa48be437322f03a74f2c27629fc98e2035 +203d15a99f7ad4078198230bea61bfbdad963eb739ec1d78c85f534c0d29195d +2051ad97da43c12d0415ac8c3bf8e9aecfb5142688e16757ef4956a04b4069be +205a12242d08f12e71e4865c04f4afa1db9b58d7495d49f4c575d53508d2b09f +205de5d634d797385b2572880f0a73baa4cdae6e181c00b76b731bcb050c2e41 +205f8db71beaf8928d787e9ea7434c6878f5d6c666e1c0046bc28b963ada3f1e +206457b71fa828de047f4b208b81b065645b14518f5c398c10c0b56c11bf3454 +2064bdfaf6bcba7af933b20091e673df54baf6829bb5a46080823cf2dec82183 +206c25c6de92b1a888a983ae02ceb1935217ca37b5b500db4c9a094c4d995289 +20738a0210be45f413fd0639f4fb79edfa3bf63480cbc5d9f0c7e992c296064a +207dbf6668e038fcd08cefe13fec41fe7f89e0591d272c8ca114512b65c0aae0 +207fa19fdb133956967e2718ff599b7c0094cc7f2735b1b1d4d6e7a199ce39a0 +2081fe14eba4fbc5e5a059b184299fbbc6528b51a7427a8b8307beb329708891 +2084ad453b7afbea7f906c9f42614f9aa4e46628743dbcf5e8125870009ae966 +20854cc287f4ce5eb0e592571822512a5f93fae6ac67b3117a51e9cadea47bfd +208cbe8b70998b2470df63cb1c1559776a9ee63372d2fb1f04a771df4e1b0020 +209a4ab5e3eea503af350c7a384d2a1d30079476a976ba0d1e6e6041c46fec10 +209d83872495ab5eeb620b0edfa20a004d5a371c965b8e7efb3dd5a024adadc1 +20a23de07a115656ce39b717f47c4ad2195c608ffa83df82d02b46325f15bf4d +20a4afadfabc566ad89df085141f262a593a5818b0f40880fbaa8c14d28b219c +20a551bf81913e13819d2b30a0fb567ec935ac5a588aeae4ad4bd0ca1ed84a98 +20ac077a6cb72f575045f27773282cfeb172637021d870f047bd687b56b8f124 +20af335c511ce1ccabec4196320dd66b05a4ce5002b9edc6be7e57f4d4872cad +20afad0753edbcbaade5a621c7822331b8aaaadb78a31365e939585a6c8cdd26 +20bcf0838de62fbdaf76c7b4df3bf2807afacd46e43be4484a2dee3b70eaccf1 +20c4c554331e1232bf9c1a2b179a3c44aee1961bb5ae7814e23013155a615312 +20c8fef9c6bbb5390cfa52d28659ebbf2a7454c3477ec5a7c501ca7a53f5a23a +20c982b99798f42bd6bad4488810e96657a862d4800f0420b3a7999174af1dd1 +20cb1f8594b57cc83c086fdd6067381ecc1ad4959e665ff708a4fd8961dbe729 +20d02b6a232e1f280e32116f994f2cf2471cfec372381d0765169c4c6306ce7b +20d955ac4f1a7ef5b381da228671fca266dbe5b2d5eea8a6420f784419f9bb23 +20ddba51466fe6587088a58d8edde429f583af671fdd5c4ceee003861168ab36 +20dfb708f0cdbd062a74d22499f060da2acc80348a9c51db87cb68b797b51a31 +20e05ce25c3abd5f8ceb0cfddaddf2d2173ca5dc0d7d92b8586dd994270a83ad +20e981443a6081b3bf9cde7408860436ee8b8bf45d4476d64553a2aed1fbead3 +20ec34681aabd73a29ca01a5df05a46a6720094c8b8765c6c972d5952d297f17 +20f7a48dbf177efb83389fa074e06ad0756516fd4825a07cf599bea3e63bf8df +21017cd22bac9f9fe514c4fe192f901a7ac12d74b618dbff8495eb9f644ed0f7 +210504545e83256e16504d1d530f2cb1607bff1a47e37a4b64887171a8c2f328 +21068c482f8e99c4f143e3a555067a64a7345b9596c06fccb8e3c5a2f8e0ca6f +210beb283ea55a4944626894c89b4cf6c758ecbd3d7013fb2f0fc371dd2e86b2 +210c9098a6b6f1518bbbe034e63ce7eafd8344cb5fdb62f74fa80683b8ed0964 +211e3e13eae2ce240b9dab119fae72cfc9c354587942ea0985c11f8a04215cf1 +21206956e54fc29477a6578cc820e4388891edc2db865c3388bae77a65bf2cd3 +2141823dadaa7da76e3cbe334573d0e8fe55231fb05d57cd9fc94bd5cecbe089 +2144604a186c0c25c9ae294310bd833344e4b5605211e002616cca18ac65ce40 +2155d962113ab149a2efc3542cbb9f0df1f07924d4f7e45ab2c17075148f5b0a +215b6dcfb05c2fccd5d93bac65dd939f42154845279f0d0f5619498b1b5abfd5 +215bc19beb689b685e747dca91a999d6ffa6912776fd59d66626b666869611b0 +215bd97148502fe93d4256549821720f0f1a377794804403b2d17e266baecebe +215cc30ac6796c01efb12e1d6c57a64a69a56d8e1dc506ca4e4a676b984d1e47 +21658ac2f08d30f585f6522ab85431cbd04bc6d3f748a6c60e6ff447b23b1d79 +217182be44f9f7fe1e0ccfb8dadbfd11fc5b943c1df897d2168c5078b4d05904 +2174117d285f88dd5581196e56e4b9d0a4437ea079d1b9b1752e19cce251cbff +2179d57d8bfe50206480befc054ca387ebab63365a42462edba679721faf7891 +217dbb2db57ce33e20068f48aade28b697a8654fae2e8b822244289a38d26a1d +217dcd8ac138a52d15fdc34815b3a0e3822a4cc2756e81fa8e4babbca1f1277c +21852da3bdbc2e2e3b26c95205447fbfb0b58916403a9d77077b256bef3c2240 +2188a3aac1dc030e8458b2fa8fb288e0614f676c1287a023adb751e97e1ba6ae +2188e5a188b3e80fba033eff0a9f924c8453283c025fbb9718d61e64a1ec7fc2 +219617ccafacbd4e0c0d5e420627d725267fd8ae88fb2b4f357463de7f07a2d8 +219d744027e4475a0c5929c84ebaaef3a0b597e1d344293d12f4d23061ac0d0e +21a20da3c4501acb18d46583d3490565d48cac76ff9ef0354fe78ab01f1bdf7d +21b61581549c6d976520d9e63f7aa6b20679ede281360c52fa83cfd2389d3ef6 +21bc45c3d2d05e8fc5b81f6aa641916ba573d682faf27eb0a52db7b6528e27ad +21bee839c0356c0d82a1d49de3f17dbc5fc10e7912620adea107ea660326a28f +21c747c8baab2eb2d53275ea28d933b2a2cac875334ff6b80e4de9944fc0454a +21cad8adb19c5faf85a30330afd26edabf57e75beb39e0e8a22a4e6bf50a1a34 +21cf95436173c41216a9109f0fc3c86d57c3b739efd9f27f164ac5123a62d63c +21d1b34d2256cc32926f78eefa99451d33f4c0ae4df20c56475b4e4f97a07ebf +21d3b2c50d5341b169d286ad5b5f1e056637793e72bcac0b061c832d76866d08 +21df43ed3998412fc4f9ada7d5147b2f3ca0bfae2fe289f45f77fdf8377ec942 +21e30765ce3170f07e72b4b2f321d36e324fb04a206dfdeb0d9afb9546d3e5f6 +21f50f38c067338e187cd8d60f4787cf3eadd93aba13192d8fd562c26fbdc478 +2204741344c01a97459ea73016e308083b1d60ee5fecf9901d5c1ded14f88fa0 +220b98e4877545013f378ef822d8d75fdee2d979b82e22ebe0571afc539dd1d6 +221b042e2d3e8b5341e77f8ab8b83ca2b20691cd765a5aefb1c27a20bb1f88ec +221f802a981342a5ead76253070c58fb5cc46c6d5acec347856d5f9b92a91fc0 +222193a3a525ed239ebe4b72e7fec2cdb4e3acaf69fdecd15ea635ee3d8ab12e +222584ff4991475f505cba2b25a42a20f5ffcaf271faf1a5e2956f539a08b5ee +222f09faab8e5f34564fc8862e6d1ff05b2f388d2e0738effdf72657853a2367 +22313eb89a16e4d6e2d620835a1010d9b5da8e586036ba03ca783c4e295277e2 +2233353825ec6ec92c17c7ee58ba8da98b8f94838040cd373b7aca179734328e +224fcc371b2de1d47850671f3f3dfddb26d1c4c2972d9f3fa245f19220b091d9 +2264ba41e656db1374d19612f2fec52a9420624060af90973e5028da69a2f655 +2267feb5b0ada13eaa9ad742b257336d876f842ca4b3778b13896ae70fec21c4 +226a04d1edaa6408626e6257e02c16e7404cc6e451bdd55ea2aca6d65f4b97d8 +2271858a48c87f9299f38140f2ffccfbab027651560460ea9f3e38e96f2d1459 +2274f70e1671685eb0c2840a4bfd81cb98766b73e7baa620ec1fe950260e14b1 +227ca0bb0e2a4ee49a9fd530a472fd76eba76a8248fa43ac4d87ba3b28b31613 +227fdcc40260a610ff8ac1231989370d9180784f3233d17a650bb544e0dbc088 +2288990e3f5920c5485d5cbe764b814c51d86c0dc8747c3eff2a14c3dd2b305e +22892a85410b1166b9df969416bdbbd29e55bef722880871e42c341268e4539b +228efdfa4f00f339cd841b19e3c8a49a411a62f3efffd5c2719515dd7d7e852a +228fb306d9ee885a83669b65ac112885612e76bff85fbfb7a83fec96a443c349 +22904466ae1e501e4ff5a7b560b83ce598281cfacece54dd6ddde18850d60d46 +22921c9da32cca16b34ad23e017898c26923998f4defdc24b4a13a4ec76af5b6 +22a6bfafd292aa5c0ba63623c78816c7d9c7c9048b2dfbf1c3b8d3dafa286888 +22ab662128742f34fce508c3db0526cbd6ba4b18c6bdb5f52656ca871fda207d +22b6630b08e498f3c74200557254eea8653f5bdd9b78097d80e2ec76373189ba +22c4357d1f28de4dc6ffdc25a331fbb3975a9f51bbb93f7fb7080f9c0f35afb9 +22cc25786a7701092e55d39dd0a0148a8fb4f35db9170437bbe0e6a64be5ad99 +22dec70af1e04d4d3450a0d0125b90657a51c501196d9fa48a474ee4701f1e76 +22df2918a997f1c244327eca48f7176d324b277187c14c5db2ea1b53c22bcca6 +22dfe966670382dfd888aa918912dd358a6c0d6b401f894a61d1a8a27a19c771 +22e05722e6e1771cd1113fa79fc301e49c1a14a7f4d454bf95a30bcc20d3cc22 +22f1ce3581c30d7bf86706456692fdcb986271773b345f53e6ea0afbab95b15b +22fb1a4a941dab32374353cb4568c2d675bafcb1dfa476bf7afccf8f193b74d0 +23028d5736460e2fc7bb3acbec2b4c01b2f4546b45e0788ac81d34cd605d5839 +23078a26be7d0ad7dda4e7426f543bc3d5cef7799ee223d47da2c67d1a836011 +23164297d2bb83f7509911f785270e60a502a069618898073c17d80f5fac0af8 +2331e78e5c3fd387109d090df3dbcff1b3a5e3a950576a6db1281445180b5340 +2338adc87cc4928942615b848808e45d0bf1a146c6df822ed1af7ec4c14ea252 +2339d434617beee3de2b5ad5c86d633b94a06a67fcddb3690dcfb9f8043bfb2f +234e92461de3b933001000629139568fbdf841db7ef14a5522582191accfaabd +235dc178652480dc405f1ecea911ff5992a322eec6a23de0759593f23f32c711 +23602dc2055d26af923544eab5b400dd302187dd06f056857dbc461b232a2130 +2360618b92ec4e2718d841ece069cb1834916a69c612760d6cb9f8e21a054032 +2369430cdb64b6a3349860cb58b94d13bc505416a053eb11f2832440675c0e58 +236bdc080c486f467fc0a2c080be03e2ea0f063c5d20722b76db5a31bb21ce93 +237a0650351583281e52e2e473a896de12ea302294d97a8a056149328e8a3613 +237d4d78153ff456f9a89ea9189b655dc515471c40b59e47dab7dbbcd2d62cd2 +237df41b4bbff5da03de815035637052008ed7c8ce95049ee5c87ecc2466b0a4 +237fac8657d8911236dc79128d4fcba08c96417a6b7cfb095dddfab51ed2bddc +23963113da8e0fafaffe3945c5a26ee7736f6f690b9a4d4b826a9b05618d6fbe +23973df3ff21a5c29fbf965def9a00943ded118c0406073511ddc30da1cd91c3 +2398412c7cd1e7179e203abd866cd0fe01d4305db145ea529f3f09a010355477 +239f3d4d84f9600de30f22227e07306e21f3f23b677a41c36a32e58c467cc493 +23a102b52ff30edb0e7a495c4a68828b09c9882597d4bdfec985678ee9823f81 +23a5126a40fc8af0654c59c99c945841d6ea3dec6c306e22f1cde2e35fecac41 +23a7bd337ab26db9e1d88969883f4e11989010429a2637bb0f42f843534b8a9c +23b26c56e6c66c14582bc6513387c825f3e5331f34e726a7cab56825874f2e0f +23b6e978ee3b1f2ad71e9081892197bf34abefeaba24c182e855b3a8609d547d +23bb48687fb4b570f622d016297ca2d80bd404d5fac743971dd01d26619a43e3 +23c448fc946587727c7b1895b2fea7cec7616ad55dc7416b51cbf3799a4f2c89 +23c83678aa001f61bd699a09eba48fd16e906a2687559b875c9bc4f6c6a4d62a +23c95199086fda067da37d2fb4a9aa02cfad5803d51ab113bf5d80006b38859f +23cd2d2e7aaf33596f2c06ce8cbb5e45699aeaed9467c466243e0dba6f4d8400 +23d074e634393083e7f06929a1ebf87a50fd28a59ccecaa4c3d05a14195af5d9 +23d0a15352b26fafa37b055f972b9cc57b028ae85161169e234faec28c7e1749 +23d23c6eefd1a580eb8d3814b4a15c9724d3ad54a10c5308cb6801d127189a84 +23e508e5c5a29dd1dd44776b4102f9679e6ecf320e9b984592094e861ddc94c7 +23e9b49d19c8aba36c96c380201a5ec15092516ebe8ffbb1d1f258c760e20a31 +23fa55a9d945d6e3dc86c6bc610b349c0504f764cebfcf42ef71e9a7921a7019 +240705bea6d89ba5f655de8ed9dc224b1cdd78f32c1b2f05d3f8ac4e0221cd97 +240d00fba11a71c00e17b8cc8441a54aeb530932af61a7343d58b039b54ee8ab +240d7f22de6ff59c5b6a3fad0f86ecc8698af32b7cb21d37b4337769aa9675c2 +24188b49532383206662cc3284c10d8d1869b8cc074493262185eddb426201b3 +241d154dcf1c1d3768a94785f14e0eb38273cdb6b93c949c3f40008a4fd7f591 +24220ff3f2c79606ef14133ff5f72d3b82759feb59dc0eddc4c588308595feeb +24247f4cfe13c5915729277b0e55fad6995779a6ddb1c3bf5869d745ceec934c +243417abe5eb0b67a260238ee2e4642bd4fc82537f3e39df58de72cdfc07ed50 +24377f37c08109470e214f4b8250fcd5a2ba904f9e37654d44dee3bbf89f4ce8 +244425e821abb231a5f420320cbbf79e6be8bace69c77ede1b62aa0e7bf5088d +244cd1e5c9fa7360faa9c3792885f25a18ad02ca77311aca57567073654f9a04 +2456a96550c5d41a94381be6362a3bf68203ac3ce29cd2531f2333bcf293d1fd +2459354d2b3691e1acabab4c1fc8f28d7787003c2b24e93e66ef9171dff1191d +245a503e45152ad98896addbc6d3a4cf3eabc986a3d4361203557a85092d4ce9 +2460b82a74c0babe183a8ccd26bace38649c84baed9d0b55c742554f0fcf79fa +2462f64808bf900c967bf70b7597a1cf8803cbd2a755fd89ae95865491b7539d +24639ba041c13bf9ed40d1f5ed72f097ffda54ce3793f689e03fef8b32ed13c7 +246771d34da6912afebd64632742c7383d3f21fa63ae966217a16ed17bb806d4 +247baf6e032e5dbbd502ac168fb7b83b36d05d350fc0f4b7eeca2ce9c506eb54 +247eb6555611f9fc75ccab82fbc6ddfee955b1725d22469e6be8f7b8b5e91eb0 +248eb4d747141ed9fd4eda4a38fd19bdb3d01cf301166b1abb896f5250ba4b1a +249969c4a48a6190c83e04906175bf4a814391d76be6778440c0ad5f867113df +249b2d34a278ec42de3bdaab8c68f31ada74d82812c50f167ff968dec3ec5d9d +24a62c9ea0d95da6047bbbd8f0995564ecfe6b004f180b2d8ab6875abe4125ec +24accd4df72a95f4a422b66fbaeb46f22fa48da25fefdca3324062aae492f2e3 +24b111bfceba405690fcd9c57ba7125f27122991d2b4d1a25cd69dd0329020bb +24b378acd250f5fe17508f099e4aeed7d3c0d1eb2370e344c4ffbe4760dd888e +24c08bc465e8050c0acab05ea538097d9ff552d921879c831b62c39655d30852 +24d5c36338dfe4a7fc5929316a15a2ce41e1be2d73e068370184a22a17cea0e2 +24d71c7f5043bd31aa7de8e94c98d57049de86338d4c1b61f687ceffbdb8a9f9 +24d8d5478916842c99fca2ac0cbd666490fb5157135c36971ec3d1a6ab549289 +24dc9bbea77ddd9ce4b451605a91db25bd5430c4d535007d673bae1084aa1f6d +24ecc7c7b1112c4f138a9750f7197fe9e3c423cc27c684df3973f5edd5068596 +24f2f02433ccb3bd960ae4074eaffa2cfc670a28daf80e7b7bd592526f5ce330 +24fe4a7c9f63d74024102313784ac0b140f074ecf3a3dc29541731a5fdf999ed +25021dc44537795f1debfc9492add32e599de7df18c50d536850c81e43578837 +250c274092a863e35d4dca62af7c3001b7b2dea540dbc023751f6ed0833bbb5b +251ca2004d27240d404b6fcf373a72796e3c0c3e94cfb8066173490476481847 +2523e8feba869c621c69f3053080a4c5e33ef8777f4377af2345d587e97e7758 +2526af1cce3821b07e704772e649172d82b398325f9c24c5403400a024535e50 +25282efb31c32cff18d63f82b2b5ac86ca8acb38f67d103a8d62155f20073286 +252baa2355e59e046fe97b9ee9d0527debfce2471db6ec9d380f0d3ee426adce +25354ee377a1098a4f2c39d9a8f893e274189d4511596e544f78c87c0ccdace3 +2537d4b03c82265f007aa24abb997e576f4b92c05ffa3bb2068490629843b0b9 +254346eda1c5702cb9f44de407f0baea9a7ab00c7bf2a55e0fc3fcae208862c0 +254b9f64020cff1ec8d21b17de084ddc3964a6f21193d92581f2b25a1e07c2dd +254f902789ac2fcea0f03a1157e8800f09d607d7cf53a9c283887ffe4ae7e60c +25523b272efb5ffdbb9650ae0bb2278548c257d277d5d786a22a6e29427b6727 +255bc15e5b5cfffa12f8f28a146c94b33a69a24cd5abf1e36d0a7a052c7c852d +25705f1fe3afa030d4d80aa84c59c0826c7675e7626a848f7578679f1cbb5087 +2585629be7ef9c8a0028ee6eabb709f5dc585b5c4d2eadf5fca85c58e300cd2d +2587374b11fa1414b4f15f081712a3b167aa9c3ac7819c7e0f149e72c56de440 +2596da43e61df93ae45cc07ba135fcfa3c8f7dbdadfdfb858c4939f76ce82da0 +2596e283f1ebc78d1ad0ea3e32b48d9204dc54b848eeaddc6de2237bdd57c3da +259a8df1c416a8ae125a3c0615a32611798fa5407c3308e04ba710430a2e78f6 +259ef38770544a486782a3415eb14f9c961cf23ffb5a04e6f1db88b90bad86da +25a42b6777942ebaa59690850034a58c6b9b83e160dbc8750827926332a54c58 +25a9a062b7753e041fae8831d7e5cdf7f61499fdd3c4c113052bc966d60c1995 +25af1a6629c1b97e01ab5e3f8a562af38c24e985d5de5fe8c200cb36a5b5ff03 +25b0979ac11c91229b382be9587ee7440630f358846951bbd4770d6fa0ed64e1 +25b5429ce1cb6420c272b9e712c88b11ec942d15bdf9e33f2074f3e10eef50d8 +25b89cdc1b13b2aec52dfb2e805cea7fde4bd4241196e557246d6d507bc78817 +25b96e50d295b301251a08165eb214031286c91c496b93da6e57a0d38f3eda05 +25bd46bca72d9b9da13c2061f2e7c075fa682d68ea5843d22f9ae4bda7390342 +25c59d436526c4a0cc9c81793eaddfbd2b4f47e8dd6e8b5cfedf7be5da652fa6 +25c695ffa1d89b6ee69d86dd3ada201e8ce92bc66a1a79060aeeadfacc9070da +25d60733b20e1037136862478603b2315f00afabd1642650e72a94197dd981d9 +25db63bfab2e4d995487b8f4fe46bd2152d9d87074f364224cdc5943648a5f2f +25dee46057590a4994bd06a0a620a0d0360547bde5d6cfacae10ca120f4da32a +25e8709c324e126e864306074ba5ce730a688b279f54d7d0d258bc3ec03224ce +25eb1274a702d8e0575de8dcdac9bad18297d1ab5773e25f5c72f94b6665e48f +25fb948ca17e0cf4a9905906ef19142b5b67cc38f8b5484e92b0265a2da3bd0a +25fcf2a1204d24b384f5fe85c8d0792dad6c7037117066593476c0dcb6af0d5b +25fffed50712b4142641ab3876b1b9fb433b256045e946965231088cf44e5e55 +26045e6faa9036631adc56dc5265f53331569b57254dab9dd516eeff60ca7815 +260fc823ac76651544449aeb93b5ce582ec2925f0f3f80d8b4d3dd967d7c767b +2614d6650c0d28890dffb86bf4da37113e9b6d0334330a60b1cabab52ab367e0 +261bc05705af8d658ca928bf1d9afb8cd545b8be3e8ed279f1b82dbc8c24d0d5 +26244be784b9db9e98f61b2da8b1e8610582662044ae2274014c359075a075db +2628d1591c901b3741ca235058be30b93e753f5e2f319edbd70806413d527924 +262f0fbd4e81a834ef2223a5c7336c27efbbefa8858d72cbd6f0fc6e2f2f2c90 +263ccec136efd813da78d2899426e73d639cde467a5d77a84e56343b84d4e174 +263e71dcd7f57a19efa1752dd577191290ddd4c27193aa5b1820d76158f3a7cc +263f42b6522462854e38249854db6b80e69f9be8591ddf40c32cd233383af015 +264ce70a0dd42690625e2092daf9a5aa9627251c5e386e403b8a6b258679e92a +2652cda417bb4b874085543ad2b5f302c3fcf71a227d414ccabaabca86adcb20 +26546f1349e73c8a2b7c9cbb2f5f66e497c155f60104ee69f78047c4d233c03e +265a382c6c283f3dec057bb3c834239dd8c714ee8211b243a9c54b31563ba600 +265aa160e8b778f8b69206af405e69894bd5e961c74f9e80a3f5f1758015d179 +2682eb4a2dc4180ae52e94f4c4f60fe2aac15962889780c86284e4f6bf6e682f +26838c3aea405228cb24a18fa234f3c4ebb1876081671eb9db7a82f7ed0b6fcb +2689f9d8ca86a4cbdeca593071a2bad120d6dea4b247d52c167cb7cd4f34b922 +268c6c8916657bdbae96e2c7de4c49e0b256d028a13a3375b843b12533c853a2 +2691fa400ae4a1c4400b1e8ea354f693e261d2443bae07c477c91d68ba3b8e83 +269841dd8e1a9dfc3608eb7b316a759f16b55a02d091b94653b8dd83cf987d37 +26b049b15795401ca09bcbf50ffee0b98b52e6a235b584c1629bc39b12799fe3 +26b89bab4cbef9a8fe2d822bcc322dc051654ba27338c3ffa4de95c8cc5bfd45 +26d74ecbb77dd0ce4102e629997c3ea53a5c658e5376333ce311ccf68d889a06 +26db9581876cbf962c9d0136457cbca619e02780637e78fe73647c2a7bb3b9c7 +26ecfe2556c16f49a25cf1ad20372232e723dc7bd61950c7dbbe9ef24fb5a5a3 +26ee67a053a428d8472df61a0a3b945b5115a75f68fbc8f4b9a258b1f11e22b9 +26f1c6018b78166a7e7b4950b2b669b871f640a94e09aed48a33c58758b2e3ba +26f7446a57e0bb6f652974f76af87bb5a4f2098f0bd8d48ace5edc60696672a9 +2700d7f97415603971f21f63b1fae66e45936feff7c6b26d4df36984a22e96de +27029d24bcbfeb8c3f306cde90e8292feee9452097d4a65247cfb5b68539b2cc +270358841e350839e7be7f2485f5995463642dd20ff455db53d0c198b398fe8e +271cd503f547bba2b87c1216e1257adc5958e6232e74e103e6d0d612af3c4289 +271d0670934e92dc404d9587a2658a9626af162e3fc4ac3459d9f803dbdb1d25 +27225fb2d50ee8c4cae5452cbf38cc4ca956ab845eedc0a61901d7540ed17a6a +2723770b9c452e68ed1cd6c48f58bd8455a15dbce5ab8f77cf38a765e984f80d +272798432e8e3236148bb1ea06612555b86297b0594f8b2492699c20eb1997b1 +272d528e10511299bf7de108f274f217c74853b42f5343c6223af4a27c9e0cfd +272d843395f15c5225e49927b93bc273143a2b3b073c71c1253c547fb84fb9a0 +27347f1d54469b6c99bc871f1ba7ac4203135115b0ba1ec34355b690b8eab1ca +27364ac09e5b658460513b72a4f45cc1a277665e621376ba0e2071e8610cd89c +273d234a301924f1ec3287582694894949b94e5abac3bc2e6b82d53ff5d86f7f +274674ff0bdec8d30cdf34912b554ab736549c36299bee3261e1cfb676322398 +274a938469f99a090b62a3d59ab13cc2f21e0a9c141df033ac9f2a5c99ebadd6 +2755c30bf936f5735682766911accc60932355b87052fe8694cfc96358e5ea61 +27562a5c0a37090a16f648cfb9eee293ada1daec8382881999bc4ab9da9445d7 +2768605d526c0efb8f294471721edd9339bd830309f6214b35e56023fc61bc82 +27694d037176349812c51be4aa2f295faa9f9978f4fbd34aae1ed096933f3b16 +276edc16f25deed2c418892448333f070e1301c1031342c74ea152403da62bbc +27792dc5e65eccfb697f865abae9bd3ef09cf3fe5a3e46123767dbd3e7952365 +277961e62efd340c050d35b87ed56233b5679b74131eb06573836c3ae8ff764e +2780c140f9f5ac9d13e0b45fea6350fb1b36068c77fd52053056c463d8377350 +27868b2122d0ef90be78a2183a593aad0fb24518c455edd71b76c7105436e869 +27877ed76f58c2e8469bf88171f45591485158de1ae45723c2b65811e80c69d2 +27a01b7933fb41de0ddf29e4c4af203390b6962fccdd1320fb8a417c451893f3 +27a01da67dd60b619b4f93536c05364d13bfdf9450a1cd44dd52ae875a127d2a +27a5401049437e40d46ce57678bce28f8fb58c1dc112211227bd2faeec701bec +27b70c4c9554ac96fb0029824a1f5b9f22b8ae02dd46cd1815efe8c0ceb0d6b1 +27b79e200992a4d6bac2da2960ffa6029fe14405ececb559567eaf8f33bebeba +27bfb74105f5f6e579d09a8b2ebc4245081a1e3820182a9e2659afcee7ea471e +27c2578bd842b3dfcc13630417bb97574d0b9115f0107cf47c81942b16fd2445 +27cc10c2cd71c8cb6371a47adba8fa33b1cb49349757d90519edf7f01bbc40f6 +27d29cbf04b4ce3b7fa5233f507879dc9e22fb964d5e00ebe6172ba9fd43ff99 +27dc67503a67d508bff47f22b68e3c69840c988fe70ac042036371d96452b2fd +27e1d03600a0e3639abc43b881c9eb2040c29c3091603f23ca411ff1b02be5a7 +27e89b182fb31619c03d87409bb1341684b889b6e43010fa7ac69174c57fe57a +27f35b052ec0e0414d630a67cb6f126659802da1e5b3b8d18801fc5b17e9ce24 +28124e7c03c69e24c9833d2d5ce965658b054073503b224437a7d1563ce9b173 +281ca4df1e7d584fdeae4eba27add54f110a10fb73f16359a7412de03e02bddd +281fb0ed1906ee3983d084ff6dcc508baedcb23c406973da6450bcf2cb9d553d +28211d830da22358a44220b869fb73f36640c4ef6574bb4fb73905b09af41a3d +2821bde6806dc43bdb318bb3ed4c60fdecc9db9ef95f648fa2d014baba0f5364 +28274b04629ea1a8cde7973404cadf54356d1b7c919320f50eced06b17f742f3 +283f69f0e3a32ed52e0434972504157360ec8372172a0aa6b00c117dd7f53645 +2849c53845f2ca94179c2c06773c16032ba75741568613e7d194299568adec79 +2854b0e5de82f4d325bc3058e7dce18cfc6a6fd2a8136544356483357223e89e +2859f9e94d9b4e9b90b4c5b03afaa63ca41eea8680b591c13de6a7442f807c88 +28672ff60f2a35eacc5bf44ae6e01067c8e36ae5db59e813e6077fe2efb15a66 +286978865bd6b4db83e8240f0e8acb49e88495e7589249eae67ab91b69419301 +286e2f80ef88f254d7dbcf6744871247e32a37b708e1fed9bd166d8d6c8f3bc2 +287edeb8f5a5cb756b69692053dd7301d00afe00fa98d2242c8647ac026fdf85 +28924a7a4195e12294e5fae301d04f488c830d878f717cdfe2c52fa76bb4d388 +289515c98abefc291c356c333a0267eed8c4624e517d7c71c92b096eb353ba4f +28a2085e51c1fed289ec67fa14509e5270fbf017089e551ad8648d35336085f1 +28a4b5a8fa2d2634ca5eefce16cb1500038075c46500ef02f3f1987f11ca10b3 +28c0902c5fff77a83cef0481f4b16fc4be6e0c4027398840b9d89ed238f88c79 +28c33afc65867e5b33cb6889a49fa894a9b49576db52165e3925b8cdff1f44a6 +28c825f3802ccc27e56fec2fb74e07c26a3adb5c3b2a560a66d376c46e50a3a5 +28d1ada238ed177f5e7d7d9b36b4ec61b6855b86638dce42c349f5f621c1fdc5 +28d65a53ff00b6d304968545f51e7ca873e7e827e0323aa8843e543ca83306a5 +28e0859761374ce27241f99227353335130d7cb7af8f1c1d738b5e778e3bff98 +28e5577be6a216f52ae5241f7db02a8fd00211c2db83f4f29705bb71119c1b19 +28e626bb7d1a2639b33bd38e0d45f4e4ccf2653e9017537e7fb5f421132167e9 +28e725e18e889fa22d7c9bb6be215cff7ddec4902db7b771b75db912ad04b37f +28f6a8df5fd187ef40fad2e14640806cf60cfa7010659a52b7de27a96db2ca73 +28fe2588bd59f31917a7fd7d08d0422dd57579fd14ffceae82f83f7a7d506c4e +29013ec8802ac969e0deea93ab0a96bff2d3f425cf6080610c53ce57f4bdcf5e +290d4fa53860ec564fbf2f770406fb6ccb481fc2a48f6fbe21bb97e6bb73fa29 +29124fced18c09f1ff164ceff17d33b45a1d6d52bf80fb2166b78a19b8ba790f +291464a678f19f249571a7290add021a03488af3091f6285820cb71fb3a1bc33 +291a6ec2d182bf6edd47b12c371d1ba8a1aebc31242cc06890d56e93d8b9f221 +291d9e4e610cb9bc8dd0debbbb23cce11ff8a1cbdc998b32a1a63baedeac25f1 +2930cf8a003509aeaaac7ad763476cf58f6e6cf550cfbb34aa80de63ea62e280 +293c921236d9448e2c54fc3b0b42245e11b32a539e315df9914753a340b6632b +293db398c0909b31ba691dd153d2280740f2fd54d440a6f4bd32523ba0341537 +2946830a6aee78269979eb9e19a2705ec16fbebf7f692009bb9710759fa9e315 +29474be384b3b67e4831a2171c2d85e4101ffd7565e173abb38a8380ac843f97 +2950dc472a807a4d277131f46ff7f21d24415db42e27672316fc581c2fbc4a81 +2952a1e0a04776a5edbfcac38fbe5e4617e09340c6d00ca02bd6722e060e6609 +295c1349c18a2b439d4c44baf0c3eab68345a9593068d0ac1eb6f9ccee44b231 +2965f04d3279f465a6e6fc2329783aa2536a01bef0f44229ccb5b1d37ca97a15 +2969b0045a4330737f5a8ea1a0fb80320185e0ec35451b1464795b153c1d2011 +2976591677f24f0a351e442d9008e99d0e25b360c2cc50ef7da007b0ef9897e3 +297663e31e51c42eea7d8b423f19e270008de78748a64ceb72471fe1ab4947e2 +297a49d481c7fb7fa80f507a6f3f6685bc60a3367e258324c77829ddd0c7e3db +2984122c35bff472a286ddf3073985e8825289264bb0c331c0f4bf0315dc0742 +2987f15e5e68a7dc010839cd4b9a4740216795c7b0ff498037245cc83c5b5ff1 +298a4a3eb4dcf1f5fc78ab1d0557623c3861c252307956a6db7702f408780682 +29907dfa9aa21515b578540ca18eefcf3e83694d4f409865d36c5486725d01c9 +2993fde69e81dd210bd8a11293fb14fcb8eafedca636fb75da094e0a4ed44c41 +29987acfc03650897ed1f540eeccab493d927966e9595f2e539878866c5411d4 +29988a87448ce11ecad5f77f3f6166f71518007b27fc2d3cc95578369769669a +299b1c7160d37265009f82b87ca157de854e225f573f6aaad7deb7ec086d0bb5 +29a74ce1d9e28f29028f209d63b7eb3445a42df61ef490708521e20dd550cf8f +29bd519c7ad03d1171328546b38781d0145c8c04d3bc74adf3360d596e4de647 +29c13d30fc0406572a8d1f84b0ef00df659904fac5fea4eb5806c556204afaa3 +29caf0faf1047f2510c7bcad978a00079535017f4cb0397576f57c986858cbff +29cc6e5fa84d3d865ce98698adb3828c1a3d3a29534f93d005d20e720707ff34 +29cea3f0fe87b6f91cf1764723027332bf9ac6f4e4b6e38038f1c91ecb3edcea +29cfd3008ffae1c8fb94ddd40f9a83baa917db010092d3b0e674c5134d4f16c3 +29dba0231031a9531c5f57e6ba670a42f8a77960885d40005d4cbafe8c3a9df0 +29e07edf1233cf910cacff7d7766dea5ade602cf6d57581a7c519eff99eb5d1d +29ecb9af5cd5cf0bcfbb5904355e563d6aa538b8bcc3aaf6615fc356e3b15d2a +29f0acba45133898a82101a051a1f13ee00dd1af8b6316c9c465eb5dc7211ebf +29f3c689cf20ad6e04ccedacb2be0cf40768c9110fcfdec0c02e173ee7badecd +29f52fe0250d9dc78760584e3a1c0dfc35c85e7a875a4552da72aa1dc04d3ccc +29f5fec451ab2e3e89c6df826f5b29342e6dfa2293b66fe23a19ca8da50e6b1e +29f9771ec005bafe105dd2d6ef4c1e71046e0c5fbe622267c20f58bbccb499b1 +2a01e2291b6e5bc5127b44a51faef1974f044cbbb5f29ed0c1838e7bd9b93194 +2a05d3dd50713a4950d2b021304bea100af37f1c23d2f587fc6dd3bf80ad37d0 +2a08859dc977430e5c7f37a3384c254b9ef4330351522e6cb925f962b0f9fbb1 +2a164cb2e118b254b0e3e895002a0ffc2a1aa53127583ed62a817b954c120de5 +2a2742f602b167ecdb7474063926e4b7ecd7271bb4e7b33acbbbdb8a35416fd0 +2a2818076007b49771cab9ddf03d8b5eb2757bbb0fce6698c98a4e5139ee44d8 +2a2e9f6dcf276861ec0881749ab3c47335b878f5dad09b7e093b2c49c15bf41f +2a396a1475da44e6df9d6c249c169a98dc990b5479bcffea6f7f55f74de4c5d6 +2a3ff15ea937c5624f3b5cb520f34d9d23b2aabfd6f668c76f5c1c9d4fa08476 +2a40dcba4b7fdbdb9300e7f578e7acff60dd62d3d67ee54d5c289fc94d06c108 +2a45bb8484179fbcca449243f0857f7825a2cf1fd9654053de77a6245e76ca93 +2a48d797289aa92061656ba82c49a710c687fa7ae7c1052035c5993b605f5fa7 +2a53aafd87ad1565b05522498f373f26b87fcd41c53dbd1b5b93e46c8c1e3dfa +2a53c6b0f75ec25d7f97c4e5cf1bd905ff52e405b624ff749dafff6af70294fb +2a546dd80e54d8acd4af309357865dcd66a68458a22d52476a993a2c033a90e5 +2a683e7dcdb46bd1a1fa157851338e4562c5b3356fdb7c55654036149e89c9d1 +2a6affaa82db16edf2757961ff12034b43362db761f3df17ae1f4c9af6c4509d +2a711e81b8af9e33d4a03af1ada1d3696622a233e6369aea330ce3a26dc04a64 +2a724b83376c1259c2c3fc9d5488a9967d59a0834208590b5e05c5112459a4f0 +2a77b4d988b39945af6958089746640c3900f63566c74d9055bf21cfda5befa2 +2a7db7c3630a67e8d670be5943779b38404b8aeb293f3ec9688278cd77749e0a +2a8455443881c923450719531aa4da3d83b3592fcf91e09c03da7f0b2c6610b6 +2a85d43ebab017fb2b80d75790ab06683579601b9489b507c5bba58b02c79979 +2a8a8d5a61f3ca88ba47e7d4e308edcb97693924ea59733c494a9a2093c879bf +2a91706f75f95e423e4b8f69366b4fe7540093c7aaa2f01e592765d31112ad2a +2a98d8f123501049f69e154c114dcda31eee50f520466f103f0d1183da840c44 +2a993aaf5e0729f840e4a5f8bdc39e525d4b93862e70bde47f702eee4b9c859c +2a9dacc2b0e8f0664e29a77488d905d59a2066df390ff1a3cdabf99c7b72a234 +2a9dbcfdad69ed0bf36f834d48cd6c9f122aa4ec7185dd35ba6f7a2333fbc5c0 +2aa033b0d52f286fc23943c4bb29479918f2b0689f6f6eee2285908d486be600 +2aa250185068495950645e0f0b2506109bd532928e377999043589d19b640ad1 +2aad9d5a0f4149416831717e138e18a7dffd357bba63ea4a53c5d206aabed721 +2ab83a48d7aef9a364b45b44deefa6b75c8d7732e33677fa2bc40cc0f2b08e21 +2ac473c1fd218ee17cbf8c84a8f31e1ff74f6df8eea1888d1278809f327262e9 +2ac4c114d4f22b7ea151c692634e34cdf8a9e46ca5700ce7722b70d1a0a779d7 +2ac7f2af00c7d57c5308d8a35049673c067d3c7c0175b0f116a2edf1594b7490 +2aca0dd2fd2706aeaebcd18d4d655f4e36f4ee0b5229e624b5dc186d1be887fa +2accbff38146839c6e72c8207f46947e4a80c74137e55e3ad83c78e39ce08adf +2ad08244595b3f8d1a09c6bc26b8ab903a86abaf406c62d5f108f7fd3acb88b9 +2ad3a77fe37a00f06fbbb7eb53612497695213cef5c784c1347f559a57414d78 +2aeb71ca2099458ca69eb26a81b13f58b681ec6bd3a198dbe4a87f972cff4dd7 +2aee9c59405e0bba974d0ddc44a32da0ff7c21f3470210351d982c9ed4d327a3 +2aef3df7bb1b5191ccc321897f2683270f1d70e492a22a77341496c4dab656e7 +2af305961fee941f3c8a335d9560349952ba98da4aa608b45d604e5b0ca90a35 +2afdf8cef57b27193601d2e565a79e4ca2e3220b03b14c751f3f7acea3e84a35 +2b0212d4d1d2c494c64d8ecd4d874369ccdac45bcd6528396bcd53fbe25de3f7 +2b07a500c3209762d2ddda6c4ad600bba6660783bdf783b470db59d3ccf06591 +2b1221f17a3e1487df5378ecdae5d7067e6c8f772cd305994b6da9587358f0b1 +2b17101aa3c3c1d03999e229afca72aefc3d3db7934c90559a593a7aad5b3054 +2b17b2fdc91a8214ace6b226b160a72d15c963bee7e554787d2f67e37f5819da +2b194cb011579fcb10e757a4c85319e757a779371eb859aba981ee06d70f064e +2b1e02d4ba5eadb9527044a6494fe85bbfe7efa8704010b0561c0cf4155e8e09 +2b2414d1a45984e05c202bbb0a402c87a972142bc53889019bf1c448061bbb5d +2b2a10c8965da80f43231be2268d804054ed73d297b05fb969a0d4b303a59cbe +2b2c894d3b07d2310682fde06c2736dcd23790837d558e619ed7691836b2b5c7 +2b35b2f4f1dcdaae0151a090706d1a880d74490519fa801694fb7d0b54b723cd +2b3aac6c2f8f257fdaac11d7f333d86b40e65d254c524e2e9b9f0edd7be3dfe1 +2b4486309f22d833eb3622cced3976762f852ec9ce3007cd479c3fa6559a5ff2 +2b5ae202938b9642010caa22362eb37f7180f4a244f7395a000c720ab8d76f1e +2b5d792d7ef7fb07e2ffb8265e643d80197074848336909cbb2eb98c1b2bbac0 +2b6668404eefd7a1e0ad9553b699338eb677f6b875828f6c114070826c5c9a0e +2b66b02306936d4264239524cd0ed4abdececa8b84902332f8946e3fd9d95dcd +2b6c1575f1cd5bf7e5de6cedbabbd530361f69093e9d342e264ab59131b012ed +2b754d8e3303e5fd09774d37a2c4d55f837056ef9a9711224d54485fed99579d +2b822eb4568ec9b2164d9e031b6270e50997833fd07b4dc74880be3e6e2c6581 +2b8e35cc78df188365aefdf823738d866805a546930c242cfd315e89f7bd1fbc +2ba0b29c4423a4baff72cbd14055e8036969fa48e4d47019e8a8e543e0ec74e8 +2bb48a5a4b40446800eaf73f68afc5d6f0d3528e55ec63605e24c554ddea4ac6 +2bbb8ce667a8084fe386954af7e5571f4f6b0a12632b2472508f6b4f543127e9 +2bbe24092eb8a613d2949e9c0b6e9e9c5cc751893da23413b43ed46488cd7c6c +2bbf466f4ebf2dcf2b1e188ed050e29a771141c91e5c33d5864d6c4671906d6c +2bc0cd274d468bbab30d0e87d3e30631e7d97159a5873e64beb0ea4fac6132bd +2bc68ad477b3c3eb22868e5edb31977c3339aa323436169944eab5bcf50fda90 +2bccf9cd0087d29bb5d8559f75a343107514684e2415bb8a0761c8e5718f8f29 +2be0cc716e8b778035cbe0186768536bc9a246e397c205af4b2a8363c77f778a +2c01aac091fdbab045dec76ff3f0839f7dd4c3995418cf9503b2ac54379a3d7f +2c02a18c1be6a8f39da68258e4651192ca555fb03dedff2d2d170f64d4f38941 +2c03fc4be16f25dd1328fc40de47359673365c3ca47d6ae4d146c3fff569ac5c +2c068ae74adc7276ab32b552c9d6c9426c4b15feb69348ba40c04a47344aae92 +2c0899fffa7551d33ed37b2c6366c83707299c95e67d1823cf5338fb973c7969 +2c09c361bd9e49157696058973b93738726aa81c8a591d6269918883eabac69f +2c0ee28d2851cfc19016b00e3f0f2c19a3a43bad18545abfbf2a6fd290738c4f +2c1273aec6e02c642dfa543d5d105c2344b60888ef4d85ad5326db0c501cf51e +2c1ee34395ca87c1fb2264a14be0a134012719fc2e7ae941d3e9c8cd9f3513e1 +2c32a4bbd882ad7b6cab57c29524963ac03981c8e56a37d35d83163f1567866d +2c3d0e24d8be7b18947ee7be9cd5c428005a9c7d2ad30d788ab562b73f7d4dc7 +2c4f108a519d1c8cb103f7ab10aa1abd023d4fde7f3847b4c322758885a8988f +2c506aca96e0e83f6ec5a14a9acb6ce106dba38ae0a009605377e1499c632d79 +2c507418a82f5ea03aa000bc3d2efd0a0419b461bf564c8164781ba3034c87db +2c51916bec15fa5f6fdf40e0f05a7432e22aab6954994bbb389f8a8c75736ea8 +2c5ff476c1d8b08610578a8cab5511587258cec4ccc2cb2a7839ae55cfae6fef +2c61a0dbdbb43b365b2c9239689700dcf6518232d79b70848763aa4408ebf595 +2c6977f88667cd502e32ee7240c864ac9351e09fa9ba54bb83d8d2798189c809 +2c69c225b0453d4aba30f00e53a95e24bccec1a39cdfa39d0596ecfdeeb2a308 +2c7e56565d6e7581e9bb04703324c923b54c96724b65d9ae0b108627cacfa292 +2c7e589412a35acba5a2b9d1dc805f563b12e0d650d4f089cc4119cbd90d9ae9 +2c8181fec32d9af0e1a4d7386b069ffec9fb5ed8db222255ea36940c7d67f852 +2c819157e4e069471344835bc8098b6c4f8f294e014225ac6b48c38875893266 +2c819438a9035d0acf911c3834c3678c446e17d73394945fd8baed4f073bfef0 +2c8946dcf8c27e6cdf01369d2ef1277daac89f227847794ee49f1bde87671571 +2c91ab7650a4b579b12bf313f6ef6f5948ea1c23b6a7df5e641e965116fc9378 +2c99d5ae41be59d1f22f44640b883cedad8094cc405fd050176ee22591ceb45b +2cac6c262c0957f8d6d3e097b831b6a5a8bd4346d5bef5e284a226e9efe17d41 +2cb093d13ea7dda26ac913c37716a0e82f8bb2b36d48f2b9bdaf3327b0e45278 +2cb4d3c0c18c9f28f4fd558ab863e08c38231f925ba83f7afded185acd252529 +2cbba49825c2e37d5e7258d624f97c6dd292cd6092b10c297a59a5e574c410e9 +2cbf11c7c9c10ddaba64ac83a98fb423ac8f91680a5c0daee77bccdc0d8d05a1 +2cc833219dc324f40f61bc3538d26fef2e48cd5acf0ed7aa6c34db9e0191bb2f +2ccec602cb720eec4878955bdc9bb35c43d5c4fb299734675e723db1fde872ec +2cd38134ea798833bc7f61c28b62a3995a40d349e72d4486faa4e798dfed7a44 +2cd4648dcea46e3d1ca5dc12725195253996a65bd8e10206480c5ea27196dabf +2cd6f85d820c2c17d6281a944bfd229987d88c0a9e90b97b47d88aefa5ae4ddd +2cd9a8ab3fd1a793f6b997bd8e5e4d9272012b10d01a45df0cd471a233b65fcc +2cdced5cf0296704ff7d619a585044b1d2aa8faecb1dd3c80105a40d0165b05c +2cf158b1a5caecdefbdc1d11b9d9588cdac2e554c4ecf2e94c2e00de263978da +2cf20839f05da852691e3bf1ded2f180b96c89cf2e3514a0c3b41695dcece86a +2cf2998c55e9a13639b0c2f3557e7c29a3eff5c73a2b1ccd83ddc54493394d5f +2d09b4479b20d2f85c3d50262742b6ed1cee370cc9974bf7c063711dac36d853 +2d19997d2cf358d1748fe9b7c6719f9ce4cc833b3c8dce75e138eefa057af681 +2d1a8e8aa4797e5b64c5f29038d716b65099226cfd8c46cc9d90cff3a142c41f +2d1df705cb6f83fb569b94ec095a483593a8925a7a6c49ea4ad8df0820cd496c +2d2012362bf5143805fc2593d0521e00bf94e700513f3a7b707a636dbe467110 +2d380961feb30598b39380ba5d48decf1b4c7f89f971c7c6ecab54482628539d +2d405a5a7d207e672d45af0b2d43aefebc47afb6909c406a146642d35709409d +2d4251ed2d6d4c298c5b335664ff963603aac0bf2d0d9a44444a9f4bf953b326 +2d43759a522a42a4a0ed66e267bb4c08876d32881991a4d2311b8c60f6362820 +2d56a55300e3613deda0d47dbb67b2b3a1e1bd5a44485f86777b988a9fce4a0f +2d5936ae545197afb7da3a4dcc27717b97f028921c5d43679cb041a78624fa34 +2d5a27bf1c033ffe5e8933e66bf9be2ed45621c417e0b5017c5246ff134d9066 +2d850bd1bfbcf58fcf26bbbe97b3bab6e1327749e1b35e37b86e9d6af1f3512b +2d89439e8d0412d03885fefcdaa18bd7a4a429cfef01be0c183276827d288e17 +2d8c2bde4acf99ed7b420f92756188cadb79e1da4d00317f1111ca1402ef6da8 +2d9319ff1ef4287019c2153bf5936561809e82a6726d4e51d3248a10e506160b +2d9590a99f7949bd771f5c57a13844f4418fca47ddcec8959aba6b4ff8ec589b +2d9822472b73558ff2f1051b5d4171320803b4387c96b0eaa35bb15e5e90220a +2d98f5f5812162db4bfc9477a024c308816f00cd01d062dbde2297925eb17d40 +2daf155bfe3aeed5af62ef73bcfe729656ba6875bcf961b3bda1d6f813b7cb9d +2db1e456d7658cb4ca569ed4e15c7ec59448129cd77d3a04e9888a6c0f302852 +2db43f4c1e8fdbcf9d9f5563fe754e0769f31f35ca87021b214bb463ece10b32 +2db6fc10c1abd5781ee89efb27daf0e519714497cfbdf1f0cf4383bef3134311 +2dbddf6a1a685013bdd32f4dcfe6eb27269c7d39afb5922c2c8eb2026e2283a1 +2dc0e42591d35ed6ab7712858aa8be1ad3de3cb26e1e6fb8ad81fe0ea741bcb7 +2ddc251371cc78d9b224e5e4aca280f7860d0c6481c09bcdd0e2503fdba5c324 +2dde7676b5992d444ff69b0100345a008f6b7cbe806aa05758ed94a5265d457b +2de005b57e8a143889f7fd7662952577597b2e6581cb596f622aa160b880b825 +2de0cdebee6960004799b865a08357bc43c94eb0c3d89cb197f5046b7c82c348 +2de3aa3cc6ca26468f1b336da16b742b6554ed49e7b75cd4d901b39bad0ba6c0 +2de6b1c2c9d5611ff9cc878cf7c0cfb0b90c2a81536430c82af96f9ae98cee73 +2de7c6beb82e52717c01643a1eb4380bb4b51320b05f8946beb63513c1d5b5ad +2df98eacd0ee799d384cc0d7c849bbdbf61b26ed41048cee7179af5c6a34fbdb +2e0a93749fcac642200bc36b01366f138a1ee927ef30fd7f1a977a97a9e69a26 +2e0eb993291e4a856fbd63fece8d069f2c5e3e34e06d522eda4c07139281d32c +2e377762bd22a6f5935cc9a4f8732b3456070e8f63e6d7d33ec0f42990691d11 +2e428c1b4bc1f0b4774bb132b266a91dba6fe6db3fc9faaa56a31ec850409e24 +2e42c91250109732f6c5a83f5d52bde6a3c63cacfd973641d87ccccf6da11841 +2e48cfb10343776d11886003a921334c04c1ca620517bc743c91f9cf3c54cb14 +2e4de878ba8ee7e9173b8780febaa9f28338599fb6989dc42965a8adb00e04ce +2e53606c7febba004fa39d2d8f51183c3a8cc0c3018507009fac3f09dc710ca0 +2e59a8545be7e71f6d8f43459cb1a5ba341109dfb28143b144de6ae9bd03e6f3 +2e5f1b5f132eccbc065586b9764366383762ae64003fa211d787fb09223c4eae +2e5f8708e5796929428b75cf42606504766b8471c95f4b898637ca88474bbbbf +2e60f8a8aa583b0e89ca93950e4a52eea63dd216a929c872effb83d1898ac23e +2e61e1d3fc8838f4e34af6df2b85d7dcd47f6390599fb114953d4653eb263060 +2e643b88b3231825aa6f78fb6b8ed9f806aa20025ee15de8616f1fdfe2be815e +2e6a2c90a32293268c1e0e62c6c9cb71d028b57e0c319a41d2b5b78e38d76459 +2e744b0d7fa7a46da542040125b9acb33817370c21398ec44a4a7f44aad034c7 +2e7f7bb7e9daf62d4f22acc971fac8771553a5cd25be01b3f2b0a867aa2a4f32 +2e861d71928522c6e4adde861afee185192e7e929750546b969a81fd48315816 +2e970124abe1b8bcf9978d2e480edfaf85d8d6e54e6ece2d6c7ad3edf573ac72 +2eb4af6488edf1c3bc6de38b1fa13c783d6cd464b969697c75558f2770791098 +2ebb823ab4aad2fb63de965fe46904edbcb3476b6e0049531b63114235af29c8 +2ec7d0b4a42e009c5cc45fb763a2125437ebbb6f87e1a2efeb43db4883ba8656 +2ed89b4fac514c1f25da5ac2528b21ab483f2ac9fe79e8c3153c439ee1045130 +2ee5fa91a2dd54d95939b33ec2933f8d9d98f8245a2d7d937c06c1be3260ffad +2ee7311d9217d3c8d9c029a837a0e0681a362816afd262b9c113393a9fce795c +2ee7e751f577d1f3e60404e247747c97a9b14949bd427a791d85563001af62d6 +2eec01ee24786ede6e0bc13bc7011714dd68d7475a37746971c6f01014ef9408 +2ef690d5d4c35ea2c7e2c13153faffc4f03ca1c15f1b99f4b028c09de29119bf +2ef944eb124307efa55bf0d8e748524ee0110859faa4a8a1fff285e6493d0fb3 +2efaf8a48472d37c69b8f244890d56ec81d252a6091ba86afbd9ed3b23f19538 +2f1488035699ddfdb6a90fd654946a74c475c5bc3e813ab98330f2684f1e9226 +2f1569c703e68030f702771586f203d4c7181a30be604b1c9b7f2d4b78f72d91 +2f1957224b9a44d6b32fc3290326f968741497e0eb97f2a807f23d6adb74f41d +2f234c7acb6de76f21d001c7e447f862cf845fa280e7412748159dfcd572f8c9 +2f2651f6d733f435f1087c46a4b0c547facc09b40fb0de47e65613136a31e903 +2f3534e41515e5d71c0b52767efccc4e84463afc79f231f59acfe2e84f7c0c4d +2f416b950a9e57845fd1c51752c16c1917565b805cdcce6afa2588d9a712e1b9 +2f437b6c63ed6f8fbdf9986aa435802f28303f87b72cbeb458b19dd83cf66550 +2f556d353b1154a790ee9d36867c5ff3c4f52f6d2f3baba0a82c41ac79456d49 +2f5a6ba03ea394c6aa0991c1826ac76e38e0053a15328e949a2b4bd2170c16e1 +2f5b29dfdffdf24a64bcb539111a54b44b0c1052338e730ad002bc8d3a3a5a77 +2f639723a2dd995d0b0f9f5ca49602a60852de877930b0651da829e0e67e7629 +2f723d2ceb8e74543ad705413ef89bfe1a6459440cda429d96627709bb31a92d +2f78feb669f186cc5a3b21b96e2394f5e1e2d6a32c50cc88c63ebe00c36c929e +2f843e3df6b1bf344504a3a67b07b05068ce2ca947ed4d2d2885cede6b60b8ff +2f84725fc84bb96b75368624621be3e4cce25f41fc72c249d61998f10fd873d8 +2f8f5f5fde5467236a46484a92e43fc808a58e81f0327126669ec23e45be8dd0 +2f9046fe50600cbda7db91b6541c6a91288a9e49388abed8acd565a224bb0b89 +2f9772c11a79ed99a57381dc7949f18c08026c041572a17c777b7085cdd6a1a9 +2fa731941c92391f1dc795e1994b5db983d43bbcd48baf615e71a1089fa64884 +2faa623f3fbe3bcf2f4f12f4889065e496ca8d4715809c13f4adeb5c0108806b +2fae9fa23091b0a5ea6da2a5f930f9f822f3ff80458cbf1e2c2cfbb7d65e1632 +2fc571c0a7cdd170e28b3d3bf1ef8f0b5b6e1a45b09d01af2ed0872b59310064 +2fc6cb14ac25d9468c258a9777b2bbbf09b03c29e8920f295942f41e8d6dd413 +2fd86ff122d1982451eed76ecd2d9f68ae1a79ebef2bb2cf36851ee767ce3cc8 +2fe1c2bf93f5ec1fea63908cb6442bedf483a1c76eff02f15db2833cba45b01b +2fe97524a32f73c04260929b6347a28de5a21bcf3e07349ecca0f1c9a35e358f +2fef0639ddb96b1afb8cec72f823436d30ba697f527191de2d965b26c0c8ee92 +2fef728ff392c1648b9fc4593be23a29a5e4f8a4dd911664e4ed86abf394774f +2ffaad633a80380797d9cdb802e175254d175253b2ee1057a81c1082c32af524 +2ffc3137dfa42182b9be46609a7816f797d521be83d5d0d5a06ae68a42dd1dfa +2ffd81f8442e33a1849bc3f8d15c010c488f2cd8a405999fe79519232083276c +2ffddd69011ab7db595eb01b589384914434d24cb637907274b976036b58d804 +30095bcba4718bf6dcd91c4bc18c429b1f2ae16e12008032971c4df53568b7b7 +300b892ca6594e801638f113615cc62adffb5c9299d693bb46df8f66fc17a975 +3013ac265b82164374e7f8b5fde3ecefb13f2494fa6b923265714869f305eef8 +301eee33e6680e3900cb4d9b560f7a6b6652659f0d7ac79038e07b673c39667c +3027baeb5f7f7fb94f094a028951a3bd220f8fdb4e12504fd9580ad37bfdb0a6 +303a8e4776b7e9b9f17d47e393496b44741d4bc8ab7dd905924e8a3327035167 +303d251ced436ee1c493320c3b7fa6e4cc60efebe7770165f4fc82bee4e40ea4 +304494fceb42ac01dde908c256d333f7bcb95696c7cdd0826562c09e9b676ac5 +3049fbd41c8cf972ff4a5dbf4f9839f5bfa1c7de0c2092bad05f5bbddad91476 +305b0c31a585193aef56d8e5d3e028cf4cfcff2a3aad71a44c934d3c2677b92d +3061a3bdfb2d03052d86d4dff0db47c34d9708d28dbf46f355211ef4979bafab +307690d6e99a67cdd3712a16fe3231d571d56e20bf74de1add43e1241f949e22 +308115ba64e57c9f0a67bffb7b360a7669be7836dbefd2ebbb2c9a577a0c2e4a +3086d5d1cbbfd71e99f02ed238f3ec7955151a39ece89f513d29a3d3eee96529 +308f1fbb21cce241471cf66828fde7cf00467eb56e44f708ff06a7153f041cb5 +3090fc958c17d889ebb76a581b37d3370e2d6b0f272444d00f86e176e9f81a24 +309c0c2c8f3aea34417d251cfaa73581b6df3a6c20b79dc420b9e47ee762c3fd +309e16ec743844c59d36b1cc9c4e54e57f26521d8c4b8ba0e64d93bb47c361ee +309ecfa438fd307d2c348b5311467bd581134322f30f79332d1df10e57af9b55 +30a910ea02137cf888028f174aeee9188dd825439dcd9ada76e81c01f011c403 +30afdcca7789b285b0acb0248876edcf9d74ef7bb86c34752801e2e1fba7862f +30b129cb525fb2284d4e68ecb801570cda0b332ef7c810afc39e0a59608dbabb +30b153e549f745a4d3cfe2c23eadcf3f436256735637d7817d588589dfdd71d4 +30b99a90e7f200beee2ad37a9cd71dd12f1efddb57ba57e4c4245adbacc1cc12 +30bddfc80a6e25ad9df26a3e92e4b0f8777fe4beb6ee7ddfc2f5f89f7f5eb4b9 +30c6c2afb4b3226bbf8bb7660b9e6bf77a71cfb0a1dfd2eff3b5658c799224be +30d6c521f9fe72ba99424ae7de76f129f016ded180749b208f2fec732929f6aa +30d6db396d917530a9f51e8d5072758afca90bbec4dc46b9aa444f565b19886c +30dce52379390d134126cf0c6240f2a3f561787123cb8b02928c8c7413a81ea2 +30e573e93592661fdb7cf8175915ee887cb2eee24ef47aa94a6e53cf370fe96d +3101c2769f441e7afffe2221c19b1a5de6dbdc752b17e3ee8c6dd02cc2704e7e +3102d95a8b3309587c6d197946b03e6c6f3595434ac360fee040d5bbc6310996 +31048aecf6b49b4c353d2c5d6bbc69b831ae7980333adfb55a3116e8977b4610 +31078847b1a38cb04f71d8892c41e18c7ec18b75c9ada2e04d3eb68b4451808d +31082cc23ef0de72fbddaf7067f6a734b7a98ecbf01980188b599cb81d5a2dae +31094585cd38c8064f490580bebba23cb3e821bb6fbd2a59c57a53a8349af0ce +310a5534722c8ae86ad1e5887a4c871ea092a6ee7e836b83824aa2cbbffd400d +311005439e6225f38945b3a99214c5f445327966dfbaee597e591dfa4164f05f +3111417b397aef4e3a520c45785bb7f71d46d32b7d4e42d5b52bfee27035f264 +3115665350e896b8723d76a6d8565b72f957659515dd6221c30d760263b51fa0 +311aa4f37b858dfba2035432b4f82049b207dd535d8c31458c7aa72abcc76992 +3123a07c18e3dddf865deff0605f860183a4155eaccf94cadf574d50f04deb6f +3123e54ce315aed022777e0011b9d5363725a096adb492d83de2b138e72b0f8a +3125bd961e4f665ef62964a74fcf0c5d33705ff06cd41dd6bc2408b28debf084 +3125c8d26824c6668fe3b2ee755fb35bfaf0190cd935e377712b5408707791da +3130c48efb594a6e139d79cc8fc1438c0e8803c817213dc4da1a23c4f96bec0f +31321707eced2bd34c168a02b8102531eecc847630f58e06f98adf769cbec8d9 +3132735445d4f0f6864c8a3beb03ba5e26dc56dddf5d9ce9db94f2c7862f95a4 +313c10fe22c2eb5cf20e4a4418975e9212137fdbfdb0fec7d2599107cb11e124 +31421b48e4cdc496464ac1e0b61014d7dec31b6c6fc595a1e1619169a0b9a68c +31596f3f05e373b004f504ed07a834120bc6e1ac12cf110503860cc82d6e33b5 +315d60276b56ab5a04a7d1babb0c779784ca70bdbcb6a2b62753e003e7257b3e +3166927d2189d02a55b7e30b20536a0dd3980cd48ac808a0550b8000b5e488d2 +316740db2d3b9bff35340ddcc107a0e0d6bcd3bddfb93f0ab80aa20b8c9b3eed +31694c9d6b864d50341439c98c3701017024d3567f3e21e1cb987b26e66d9960 +316a7fbd7a2793238878fef6618d414f62fb86848236f4ae2d6848915200e820 +316a8a5faa19f86e011578412e66f93cef6cf60111dc9a273c5983f251487ddf +316bde79387ddfb467fd82ed775da01ff6201fdef689a7ca50410aa34c3a6fb1 +316c4359fc20005d72519763b7898318a6329d1505a44fbd49e362b3cf19e702 +317736101dbb9d4e39ccbd902e466288e0fbe6603a9234aa55ecbe6c55ba020f +317d9a33c50c63bf53053a20751ff633d07af3d8baf2640ea7fc6622b1a12fa0 +317f8d02d574aebdcc0dfb9e0801875aa8e84ce4b6bc0a8849cbc3a49a522f8f +31840f035afc6b0bc923fa8c322d78fc723486da58f94b47318cb67af7c1bfc6 +3187ad6c7831eb3d15b75619de9067943a8403a60391f7f4f112b78b2a123f45 +319440f70e90b285894f106def5388bfc4b38e634dda3ed518f572bb87b845ae +3197fffd404f3b9209f3a9e011c134e04424726a01d8125865470619305a03dc +319e591e2761be8d24da19eb0cb306b6517f36fa084084d0962b64ba117daf9f +31aa4cacaa723d5f62244e274684e590531b395b11fe5dbb6f988a834d85a23f +31ab4ed39b4c02850d4b14093e54abb591ff4fcc9d57bc6d973ca0fd4555af28 +31ad06b0833f2da9b9153b4eaff23e55609b851dbf476dcc9cdc3a2d330a9fd1 +31c6ca952bebdc492d77220e9b5f55f5c32ccda327311e13ed6ae109ceb383b8 +31c8601471d03ebe0f5bddf93f3601eb652bbd7554ac9f28bbfdafbc8b71e2d2 +31dfd2784ee818065232a48971d6bc3c8987140e708f2ee59b7b2bb5fd49f7cd +31dffbf273617547b98ac9d562fef877204451a3cda2e7d841fdbfbfb330f2a5 +31e3270b9d665f35b0f27b05814dba42f2b015c4249ddc239d85f03642e8b46b +31e608e6e0f3d513af537dcadaa65c6012f9c679d4926f0b3775043729d59b89 +31f3996879bd0224a4b3f794cf4d3aca609eb64ff0d6cb77da56a7a99aa49472 +3204415c7a09ee8e8d77171b25f92d4811e0e0a92c5b3af65b68788c39cffdb2 +320817dbed73d4d5c1a8dbf44ab33fd20ffedd242a66f68b6390357f68e16d5b +3208afaf5e0e9059ddf9ac8dff965d0b33bce587bdca455ce0abca5ed88468e8 +32094efad37386377fe800a65fdb85e227de838a71fe474fec47eee7e33fe249 +32279739c39a5465e32635036a2c2a9273f80037ea225e34964b83c7870b13e2 +322c6d081f740c8e638c01447fc819ac69a1871724fd965149aa51fd4a44786d +3232202d7000077d948526af659b1f43ea3f540b8ae35309789981ac8451ad92 +323462692b7e8d966da52afd95f862c5ed423bb8f3a59b4051b5fc3301cfa479 +323bd8cd4657c983aa3ba1d4061b0413045c99a9a2db8749c0909d8f6375fc44 +32594e707c84948cd9ed7355c182586d01c45a3e2553489e3ace42608a81e97c +32659fe3349460f114ec60595a73c3bb6b030a27a26a44f8111bb79375add41d +32738bd4ba0861c80cb6b005e3f9289386099e66feda8358229084238c02061a +32750f0b691889737be71b461ea1e065291f22ac6c615f66305dbddba808dc8d +327a3280799b65b5964c3199df296e24ac687215992167b8b5e26e1ba50c5cec +327b934913ce54cdc1b79814122dcfb59382bcbc02afc8540642d5a128eff8a3 +3281c98c1cc4d4bd2bb73de6e118a38d37363bfc315a3bdefa1c8491d25ef032 +329829e1809b86b835dd283c228cddba750e3d4588972dca6bd19530670b450b +329c592dba05766cede05ba9bdc4ee78774db5c67a6738fca141bec48037a8a9 +329e2a0bf57a11a238cc9d0bcd4351e4c46d6de9964fb821736f0b7b4264c8c2 +32a1d9efd89e5d2cee12e99f3b3ab50441c23a2c8d66f10cd1eb9d5c55be1a44 +32a1eeda05d8e74df58cb617a5cafa41905d5551cc5b9a459a0ed8290a79856c +32a6020d3a65258c356c9ca6edf34cc642100f09b96bfd43634cb5c124b953d4 +32a785d3453b0b86cb7e7d1ee72d43f1bdb77264320a1fbff21203ff4d35ca71 +32c1248471f427e6258d5bfcff66f83b0292a549a3dce11000e9281d92e00dba +32c1d6685bf2463e9fa589c6e997d2db25664b87bcdf79acb733999a919b707c +32c8e21c093886eb0c5f652aac14c0688adb25d8e85cd5819937d132474182cc +32cf87548099d8940f08576572a64fdec3e34103d27b14d3b6efc37a3090e724 +32d0651ef6e259f1f15783a5301ef39989973c4d8dd23271978d894d3fd12883 +32de1d360aaf7cd1ff58e3092fc1cd570f0c8e7c09f0f898812dc6732f1c9a58 +32e02ea13b6bb6241b864b28a1c17bbdb879d468210a10b0859166babd29ac8e +32e9e0d6f02df8159addbcdadc12736d2f4a8a08d88f9714c68f91677d619d10 +32f023ada5991920f19ba2cf0fd8b3674eaf6941b75b9a9a54072f840192c4f4 +32fac7cedb355da1d276fadbf67ceb05410aa42b74bfe253966cf3762d0784da +32fce7bf42671706b3e3e87ed2cf4bd5f11cec1599a5744ed10d8777b040e832 +33083a4f7b6601754fe2971a1c081510b356b8a2dddd729f44a825fa8753d544 +330e9415e753526941bdb75e9e66f4630dc3e287864633e7eb0b82aee3eea20c +33174831aa08688771b2ed1d17079856650515a6734b5764a6f8229f0bb135ca +331efb4822581bf072bc36b9893ccecf26dac869736a3b75aee22f18469cbb92 +3320156fbd6ad051b9ea2f18904ac4d6637f7edd75963cb9bfb75bc83e07ed4a +3339e95890b23168eaf77885edeb1e1db1e2c712a1c39345193d3667d8069951 +33433ddac23ff581b91880bf29135cfe642369dd0ed5c2c0ab1cf80068a5a8a8 +3345d6ce68f2ec67bfebfe6227b5ad46ddadf8ba4bad2785967398788db7acf7 +3348cfaf8b1d60533bc0a3467ecfc3e96f8e8d6af6e8ff0a60277cc9b1b8cf7a +334dbb3de54624bee2c425c8512e7602aa93baaf3859e8561eb34d4eea4972a6 +33557ffbf6040ca473e49fe30794a32b6e3081949bc956daf4e46577fbc73cfa +3359480bf63e6b630d2832d4f00d8ade2938c8b0393c5e506d0a1517bf56b5a8 +33599d9df52788c4e1eea1bd3a689d067351d76531ef71e0fecb3da11601cbf0 +33614e6f37c7f95ce48bfda0698c4f6d63eccdbf66b491de5f49fb67a1df1d78 +336c39c3b330bf1252d4e65e3284ad3171252ab5eab605275663d74d258a7372 +336ced33716595945deeaaec39ddd886b39789ec053c370f0f0ddecb192d1f7a +33a1305bbea03dec47f4cdf0170c9d31d175facb8c17a6f8ed6cc3ab96e0223b +33b38c18d28f31388ea1ef519674b035b2197fa029e4bf5b8a408047022dbf8a +33b50bda5d1ce32beeead2eb035b6d012d7b454e227746fe2e6f862ff8cdab87 +33c924e15d7520f5add776386a527f9f52ad02c5fcf6a352751e676516c15ec4 +33cf16a3b3b9dc7478cabf6257c7a9ff20717817ed1aeba45dd76d533fbd468d +33d14a54cfade9fdb661b594d9ec95ce4a93b056abccef79f7b90be77d0a7ac1 +33d2512e87dcce51686e473a26e81d8fa9b79c85c6e8ca667cfee152fb6e96bd +33da35f283ea69b00418cdd91b9f1dfa578fc46393a43ed29cdf66a080822828 +33e0413d42de13eb9029f62529eaf985a23f9146054ab6466d99125702071227 +33e0469779057455f14a0791ba981b0f33866ae9b3cc35398af4470c2b58193d +33ebdb6d7e3915266d11fef5097df642338f39f85e87d18ffa18d12417b85f26 +33f9264e229be2cd506faebe732be4d4275b97a3240a3ed343554142c2cf351b +33fd9f908e2606798a765994788c9defc981b2275f0335ea5a871257e0e87e01 +340bb5aa2994ab8eae435cb0d70be2110047fd18f928e1b80f7ad82de22f38c8 +3414751c22365ad1495e53b2cdbb4d17f00058a04f2d19d1bdb66dd829b4d3ad +341db76ab6c04b32f6779a6f2739ff4444ac2d47aae7540f4a86edea433f4738 +341dc6bbf7f96a19d637d650a2885ab474607c1aaa267a557b8d790eaeb637a3 +34236d70578ec08b5a4bf93a9188633fbf36fc808907f2d2abd90b8d9be410e7 +3424cff9c172314bf62df5fa8e3cc2cf91431081f46b04bf22114bfca2b9c2a5 +343250d178df628eb26ab957f9aa89970cafd918ddf75056ae2799d9a0556d93 +34460ca650af3355b6f5f918b3156f322eef85ba1cd597b0d8869181fdeb51f8 +3447464642d0c25bfab3962552b79d68a5649b2774c1f88005d027cea57f8216 +344a74b1182a2f503ad16762fb4f2d65182e06f473790a10d7a52ee37c2a31f4 +34542b78d7e5edcca1a9f014237997f8835219392f50c7a1f472b012cc60df56 +345afd2a6304f26c6600a10c8cd4b261f78ad6d613a7bce5b3c8e8bc0174ade6 +34615282e53b43f87660ff965c9492177738a93c281e7b5a3ea2ec91abe3a066 +34632b75292917c4211a76c43cf3388b956fa5265d45cb6fe19df4b5fcd8e27c +346352a65ffc84751b84caa5c1993708e6ebdf57057a3476757d53cad356c0cf +346d4fed9b1bbcf475ed62ee4afe320afcac61dccffe0bd3ba941dea600ff221 +3475b9ee6cca0b240217dd328f4f47023ab329e54260301922904dee40d32f44 +347dc8cfa686db00dc18af11958d89be4b12bb6d75dd0109388fed03ae5aaa5b +3495f2c9a90c6e291487bb81f1860b2fc21d1f156f49ef9781ffeb7c87fae82b +34b1b2348a403eee9ab4ffd00391f4e830c564acbcab0dd33a1708403c97519a +34b474304233418e64816af72cb3511f2cb74d3b3977eb321585412a41584cba +34b6c9af985d3210538cc474d0ac9563f342c98883bcd2dfd3e4b85c29d737ea +34b815779bb7be27a2c4f11f3eded9dd02a530d627bc6cb65cc393650b108d64 +34c3cca9ceac0e3aff1f778d5e6d8f3370f2ae0c77fe01341c1dda2308d6be80 +34caf9199d462010fbce5776ef831621e40b658975cfc4cc9d5e86d6c0c42ee4 +34cfd17a285681728360729db5177db6bdb3bc933a2655fcc8e66381977a8628 +34d187eee0fb3fb8f14926777752c7bf41661cc4820c82f3477df58b12c9e1c8 +34d3176146d8cddfb0e75ce5ee6bf5cf8def213a5af39ce8c5db9d7f28ff06f9 +34d3306b0f1cb65a19076b5604219e7b0c44bd57a0a0536abda8c4321e6eaab3 +34daa4ee43905ea0c84e12ff1906b97b6f5a0a6e487265c7e91cac6a0938f147 +34f4a51b187b1810e18b92580da908b8d055f24e28791d0cad6a753582bcccb5 +34fa91c3886597d94d884f1d06269e1f8918578701388e3cd67ed084a11a267f +35086616ece1cfe99d1eb750697cc1694fb1641949fd075d797ff5ea923728c4 +350f8ee8e0f5f652a71d4ed1af2ca8f7385ded2b9939de758723d9cb960f2d86 +35146e6fd7f2fd9779d41e23e0381ba7e3b83430160de565239cba0e54b2de33 +351b4de22af262d2c2392071c5e45d8008c1a14a02de2ee3b4c949a0bbd2423d +351fb6c48629dae76170e3e5621a7675c982574d6a6f93afde21074172f2ce1b +3523bbc7f9d16492f9020d75c52d33b9804bd4b9e0a7d3ea32179971b915def9 +352ef648d3c29a833c90f5770809a7b603a3d05b699822640ae9a844098f6e92 +354a0cf546cda85c1ec60e0bc5d4b39a1196128f0e61e11a3557c9d82c3c6c31 +354ac5083f6b4871faa16eaf6f04dccaab5ee83d839d9a3af87b50c5a7401ef0 +354dbba5ea4e5aae08e146f26c38a3bbbe8b6b838b3c3e57b6af06821b98e471 +3567f52323f8b5a357e7cdb049fd56580ee69d4467a932f6c2d0c63ba8a8d6b8 +35717c0d2ff83bfad00041e7b3bfab580539bf68d934a9ca7c96849f461219dc +3572e7c01763bc8d5b76978552a4dd426da24c2f74bd484e98971d18fa63ceef +3572fa364b4bf2f3e14404f30c85bfc065d275b878990778b929d80bef776416 +3574c34b8d3fddc098537f3786de337636891ebc1a63d85208d79fc5e481a87d +358375b8a070a8eed103d7b08213d919af4dbb3b9127edc02b5e614a8f00a9a1 +359d8c6af852c02637c1210c7eb1223bae841ea43f25cb4e8356cfdd19e04341 +35a05c5d1c3cc47bf5536d1880ccaea16e3d8d568ba4d1c2497bdd8baf5bb902 +35a116648def36024a61e34e0af6eaaba0b46688307697810c2b8d668ee41791 +35b31ec8b8f3fcbb3f6561337faae4ba681ee4c0f7570e29928021997987f095 +35c736488decfeaf9835935c903e61c0094014ff6a6a1e0dd1db37431977b1a3 +35e0ecd03515a9a2d47ab9f2d9e348a7667d3e25d436ae16ccc943e518ed760e +35e1d272741f38ede9baa0a33603125c694f924bdbf601bd6740aaf89547867d +35e742d5fdf7be040a589f0e344780677913870c820d667225e134b3b17e2fd7 +35f4ad5549d0cc5e388ca76d591844b2ad552ebfded4dc6f25804979e8886243 +360441846dc16cadc44e484c0a146b989e69e76c7e8db673df42e9a58f3304d9 +360647cba9e560cb9eae05493953b44db79121e870eb87f5df3f41af81b248f2 +360946a68947e2fd3b682a388b7b606b9f4190b386229ea8d929af6aefb1f8ff +360d1195c100a38546d83b8e2c410c5d31edd9a56ea1d633181a6f4a0ea0597a +360f53f9b67f8f2af932d16c5c99e6e0b2706287352cb81b70cad697113643f5 +36110ab2cdaa66ee12625af8c40a3fba99eb564b148485a52787906fa53b11f8 +3620f6202f9446baf2d0713859483ec4d8d6d3bfee4aa7281c44ce0ecbc126df +3623dcc88fe18ab45560f3edb5e0a9db058fab47336b3cefd606bebce497bc81 +3637bd5f7ee61fbc1d1e886effb381df066240731b3ed83d3a569974bef123ef +363bd49914ec1a80917a0199c76390ebb0560e13c38e17308157cd9d13629986 +3643a8c4325babdb7c19b99e0939661acc78c54f02aa39af9ece268897a8c3c5 +364686cf47e1b891d9f9fe99d9a35712788f11d15627f3b4a0d78a1e240e0a47 +3646e9a55e190a792b0578930d2f1a78488726a00f9ee385d41846bb4f3630ee +364892023bac3d3c206e173add5d7fff7cdda043cf7988b3990a98d7cc708618 +364ceee5166d1657c27e4b1970846dc19539eac53d7a16b542f1cf53171b92da +36615bb76619a27ff860cad4d489ba8321e56cf4c44e7e7797026d9d353f02a4 +36736255e4a255228539867bd2b6f4b451f8ed1c74feb6299b33a348468f6eeb +36736e3334572f6dbb4e005465ee77478ad1cd247562df8500da7e9113692054 +3674cfbb098cc650d07f2ba8668c324c097fb385af3890f11912cdb665c82fd0 +36773d2bcd489ee6c8ce34dbc0f225353cb6336ea0d585d76e75a45706906cd8 +368cfcc69e500ab4ba062635d487917e6e5f9ca8f183ff3edb54a41059b5fc11 +36933f3448fc9d867027f3ca08763d6762f49157ae287b76fa9dbe9aca6ebf7c +3693eb41fb7f9fae2cf7cf92a173ccd441dd9e27ec8a7c453697ceba7d76bb7c +3694f344e9c3a1e35950c25ccddd89b56913fcdbbece88deb162997ae0b4f55f +3696528c6946fb46537670570383289cffb3c34833c54ab7de37f358b71ae22e +3697f20ae0473d9b8ea22301f437aa82775c91692687ebd6678c8317207c0958 +369ad8fb68fa1bdb87916b27a7b5d940d03787607d604ed61ecf8be1fcd3a213 +369ca4621ca72d124a826a3165c8baaea6998f47d1c02e1bfc5a7a1bb1d24555 +36a3d15cfd010da0cb8632bcac0ff513448211d248c18729a5e7088631ec25c0 +36a85c99f2d02c2226819887b22c010d5eebf2b4875ebd94b9f68725845f6700 +36ab45745a19cb6f710a10cb4ad16edf5d32a1968a20a2ecb05fe66f2e883ec8 +36be42a7e7d0e9f59be2fe1ab5323bb066c9c28644213d907a9270ea880ce304 +36ceb801b8f44bb64878857296480436ffa3d67b76fb297b0fb8be34ee5fcce6 +36d6045b3828473e0dfa4dd20c9a3a275d7ddb275e3897bf7f7191c172cb7c69 +36db33e3822c436ddf2eae4cca48150ae363ada0b7e09850564ccc36e0ba558f +36dc236226c95759fb03ecf4322b7bda4e7baa842df58272830643ffe1ce553a +36de02c9c13d8730eae31ff292576fb3afea7f007dd3d00353ca8142896a159c +36eb9fcc2356d4802f41981e92af62861c2674c8fac47fdc2d01398bf706d4a5 +36ef7e15ac7488cf1b33963a56d6d6019b021123f6f04b1e2ff2f8e9bde3d1cf +37015c6fd717fac30e7faf027ecac401b2bf0afd212c4426d583c325d246f8e6 +3707eb1176b7180765833bcd491e489bb597439933d685325dfbb0f495a39a7e +37225967bc853da0d5d495bdde4f31da40a3678e354a6ad67fd64da4cfa811e9 +372cdf71505209a37ace33e30de99bddcb3fda25a5450a0baf25e9c401e84a5c +372cfaf3a545cb70afc4caff10ca80dbbcab3ecc280dc9d551de0996605b49a2 +373f2dbc946ae22ae5f8bd15d6b98731f5960249d3d44bc8e19d9d9f46eef9cb +374713152bbfe2a766c5462e712c0f00e72ef96b0f9573a12421543cf9cb002a +375db66fb7918f9bab7ecf18bc9093dabd4cc536d0a941efca78dd42eda0c851 +376aad0bd0309a7c7699fe0fc16c30e20ef70a98bc8ee6690f707675cdb76a43 +3774ce22b99a9648b5abd49229dacf13993ddac8056a38915ec463aadd23a812 +3777affaa188307d7c6aa8b81fa7088918c0552c0ae98237b586e6c1670da365 +378147dccf2f4f314184d103a5a3e56c047c0d52c5bd32ab72ef90dd472fc527 +378206145705eb7c2eefdf7d321614a8fa9ae9c909701f28f5cbb62890c4eaea +3790e8b316b26ea5e41e8cc8f904c753c766905c1c534f3e870bf3f2ec6b5b92 +3799601c7dfbcc4d5c013612f756218988a5a25e73167b04c4784352f47382aa +37a1b77a46c71b1e52b5f42852e2f1132eb124ab31d455709802dc52f6fe4d50 +37a3b1db4149dda12d7a2e8f65280aecdfd49c3ed368212b7fc15ad08050ccce +37ab83cee62fe6ef3602380cefb3d3d9ae65fa7e67c35cecbb1a61c05766c821 +37ba8d8158b34d6c759147eaae87667c65412dd3380195a811ea357a3aa56e39 +37c18e8b1c929974b07892f7714943380389264faa5279ddee4e912bc7cf2401 +37e36aad54b2b4b1dc7fd3166d006752341af693e7063ae4b6ea05170de4c7a9 +37e4ed2ce2842a5c6d6905fdd0f7a6c8f38f90907767bd97727bbe7cb3ef3cc8 +37eba7dc9ab410e1f9dc63c980df349f0400c15142ac3415ff836d3d30518bbe +37f4294701e5a13e8ac0623a6a647a4c092923644bad94a82d43bf42b4237128 +37f78733c4924a24b55ed9f57e597bc625cb51130088d5d78e3ecab0e828d7ae +37f88305f030403b40f7702054ed623587c4369d86a8c64e73681922f1d57660 +37fbf4021489f95371bb744445c7ba952c10e5806bd1512eef4d5887e7dce1b8 +38047caa5f5998f15ef17bf068407eb3c8447ebdde45c0d0baff9ca180b42882 +3804f5c58b05246d3ea0de9d442b8d3af10f37443096e6281c083a7668c6fdab +3806622605140e0d41d455f75d3acdb8d6f595a14af5749253df368aed6ca3aa +380b7dcdbda293ccf150e1ca27cf7f1eeca8b4b5bdcf972be66e7c7f03500c5e +380d4857a84b1bf787dadf5af108be2210921d90b5248b2659808544815a644d +380d8ac7a006053bc5d6bdf3663b901b378ec2553d5476c81435eb8b10c1d948 +3833ce8b8ce341952a2bcaab606b825d88d7c5213e176781f580c02cace557ac +383aef97207818a8cd8c2464c4dd6fc59d0bed398b449ebf60cbbeb2e1037cd3 +383d8981a0fa2013c49f3e48b160158499dea6cef69a572a97e4c51034b8c266 +3849821944ab2c111b6e0cc7fa057faaf56615cc5963db4695dd3bc8d7e7721b +384d0f225d54aa47eec8a0582d03c6126f76589f04ff88758e3a99bcdac44555 +385479e5a904d5e23a26ded8f422847b6c6c2b58cc05e4bc73625b1a7576bb4d +38555c9bfff744d7967bcd59f43a91aac78793a1771e2f42eb5be91a4a99f92e +38634d2fcd7d095933a0637bc3c403147685ac934dbf647f453281455ce9044e +38676e31042f9becf7b919960bbe7e0a10ea1d706b046f98efe7c6244b68d39b +386c00ebb54cd4d9f76af713b7799b6c93506cd919aa128aa7e035a55f7f1c73 +386f712df04604cb772af3c10209e0f7b141d645d16353c959edde1fd57c6b28 +3871aecae86fee829d4febc91ef397d7202e90d814a5dead13bc38293251363e +38726101f5c88fedce19895ff75abbf1f4c83dd6ee75e4934fb5d7412f3b96aa +3877c5fc887d52b571f95b4ed1da4fbbf80efa0a682037ee026d588e483a3c0e +389abcd746343586910ae84cbff203503a9ba8ebf47162415f24d0c76b776189 +389bc915a5b700a98f117976f3b0d4af9c8c54fdfd5027cda807d74775f4f11e +38a22a44569d444556c0aa44642229f9d65ffe0b579f7ca1331200d07c8dda3f +38a619b88f98ed5024d733bf52868f2cb374b3219f72599f6a18ff1279200a91 +38b61924cdee68f5d4529eda3cca5c0a63dc9ce850891caad95973b2107a878e +38ba270bac9881ade299e9108f41f7d105b20210f6de017e8a6f838c9546dc15 +38bf2e9b344b592826f207c5b704ace68fab41f00b7dc4f9d02b647aa3de2146 +38c1f68e908e418da4ab402afd17c66264128898d075853dd6503808ad858c96 +38e985a037be7681d7cf0cbc104ea8b7b68ff858784f1f8f7f765af1921ec771 +38f258bca3721b57a6ac3a9ab9a0b5ba0c0c47604bff2c13b2ec16956bba6819 +390ed798f7590be327a86aa2ae7c4eb65ffba462881fdb14e7761bc7e885fc82 +3914478d16d30a8e2acca31ea842a4f61d66fddf1417603f288bfe9df92e0dff +3922f4582b8813294846e7be79a09db3b24e04ac5400adfe230005ea5b5e1579 +392b4f73dd574ea1d898f1f9588ffc95d46f0da7e74658725136304f4a603190 +393d8dc6310dd2f69fa24d085c3f10da5d14758d4539daf51a64bd22141aff64 +394cc68f6beb96bf01e741f13adbe333e789fb340721eb31a962d45622a0f0aa +3951639861a049381a848c0532e1ce4300b86c74a11f5b133b661e6aba6f5879 +395342c7fe763a3a1d3b3a0a6933fd5c178f2765db0a45eb3a16be0fbf96c23d +3969c66a3526a9d50041be853b5b0b3038ccf0af9385bb478d701ff0c250d0ea +3970a0f7e53dab979ee18ab838cb060967d2757e2f10f79aa0fe1cf376ef23f2 +3977f0e4343fcab8814dd1eea9f45595cc6ce6a9da4862929b33ecda9628a6b9 +3979f860e24c39cfa7f59249a19b54716d5ca8ca966d4b0fb284c8f2f1ef14b8 +3980455af258dc95985b94ee5ba3ea1e44fe08db32d62fdb550ce88e95544af9 +3990226fe88c89ab1b0103e815e27207f9592105a40d04505459846fe9d50b71 +399a31f806433228e719c0824301e4e1f376178c54977b03d62d0e374c22104a +399a3c6b8a5f679bd5da1388a71bd086a315f64d2234011fa57bd7bd399fe780 +399abf9bb1684663b8bdede66c56fd1b7d035d88f9630aea3604624a3af03085 +39a3241a401d1c06edb831ad46d471fef75ed9cd49f19b49c74bc817202ed5e1 +39a3c6871d117555099e55024ac641913591bdc677b60589309b574cf33248a6 +39a7abddadc82f2b836ad8d4ea6a045204c0f84782c8bb470aa62b521f599128 +39aba87d328640a48cecbd13066cd3d2fc4b881a69ce937e156101a0b3c649c4 +39bbbb2b546615f0362e18fb68ab87d30001df548f9115bae5cc66a7ae1d1746 +39d1c60cd74de4e5f4fd55eedfddc04ebcc8043ba2f44fa793615b10efcd2069 +39d38f305ceb856097e6ac3b440f66bf157b23a4e0e3cbccff137a11ec983c1e +39d4361f3a1e949e02a1663d9bc1062627650edae325ec6887814262e59ac7ec +39d892542fecedac3e3944f087192e3dab12ba9dc7353bc401b2cf2e58338b0e +39d9ff3760a071602b8ad7d68a6ca21c753c55b4769c29e18b03add1a4bc9884 +39dc9689ef731d5224eed7e2299399b49a54dd47e7a023dc105e19b083f22c02 +39de0dea45b89c3fa9bf77b05c2a4a03a99d496d15b09671f124e87563450839 +39e255338b1ce0331f77145704cd0d32f0497773df81f0d2037557fae34027eb +39e909fc2b77fc1760b80f9592466869783f07649f47093ec10ed97b42e11f38 +3a0d3b559f89eb238075778de74e64bd5ced100283684124932e5250e47eeee1 +3a0dd2ac5ddb39d767a3c21e6d8e30f63f43bb7a52692a8d88c0646a1d022d51 +3a15e7a0e9b1b9e1c3858314af0c7dcbfeec3d75f36b7b321c5c0e27f8ec42eb +3a1bebd82092609133d6eebb5ba8f8710b5425077171dfc0f5c4eb3d6f7f2294 +3a2851b7e812cde96c7d3089829e42f095cde7055df35686bb0ad9295daac6c5 +3a2e17bc884c4738c01c111686e0c28f61a9b00cdb2a25dd5fc1315a40f57bbd +3a341af241d1022166f65b0f54f20e2d7d074e848409c596e791bab7ae96b8ec +3a3a46940f49baefc63a19da5b6365c81ab7c2cc8346e72a34d7c5de5c220a89 +3a453da021d15e3e200e5ab079283d52ab485c63d53b6ec86aa9a0d3ddd33353 +3a51bdf19bc3a40c631a3af15aca22377d88bd722079c179bd8123cd801d6178 +3a52df1ef71547edddaedc59c0990fa4d2a09817d97e5068d03d6cfc26f232ca +3a5be8d73cdbd96d6f0226d134cc33efa0f6d489d24970a1fc4c08c0c3fcf04c +3a5cca518448728bd878eb6fb38b86cc0563549a7707ef87d85f769bd23a8ad9 +3a5ccb2a4cb5d3f2e5bbb1f787457651a3b78744ed282495c673ac9c2f8aca27 +3a6b7d19dfa3e2169c0ff914c4ffc256125c341329adbab7a8fdfddec8eff652 +3a7b1403458ad65d2f786233bfa5fb11a632ad3321419eab57c3d28c2b91449b +3a7d762159a7d974a06e97d4e354edf75a2fc16d1fc6d286e636578cc9f2d936 +3a8c0580ff5caee0126094b6bae5503d5df0507ae17f61b776d01207fa6436a4 +3a8f2da8715cb66f83d38ca9b654eed02324ad0b024d721488bda4c56e82d1c2 +3a91a769c8a59dcb098b245127541d92fb19e786ac446c84f0af00dc06ec06e0 +3aa7a507d060e6aa04ec1717e29782b1d2288747af7d53c37b27e9d453762378 +3ab6e8ef84858a4d69890843c4b3f99c70bd8dbafcf216da718972d8c9dbfe14 +3ab888062c5e7009c86d693923a74b0b4a89a93fded14e6845fd84a16732f16c +3abb9c360bf4f926d184646b82cd4405944501ff3c4917c762bbd8440d66e0d5 +3aca4395334abebb408112d95adfbc51e7c0bd47e53570140f2089cbab0350c6 +3aca84a0ebda2b7a3f5000614c4e6bbbc0f9c53d7c586f951ba70b2be87544c2 +3adb951a441fdf5edeb69eb3b79cf1d840368ed190b123e214cb7e1a46ff7fc8 +3ade63a5b9cdb64a740dcc6a53773f1d562b19fd6a3678e3ee94fe022aae1e52 +3ae147967ab4b1d5f72dfb2268e783ace373f4d3f1854c9f4b306255e383d6e5 +3ae751ea3f6c344d461665f3e1aab6803b887810dc432870bf2d02861685b469 +3ae7bb4369f33b979c3d09afb7b5b59e829aa13c1446ac6585a57351befc40c1 +3ae864b06a78680fa577adcfabadeee9794ae830dbd14705377eec3c0f059160 +3aedef5d03aa547cea7644460db6fe3661a5a652e2e9658e3303f687cfe44a7c +3b005ce19f3130963c36c4a3e9b1a5a2a26f6f73d0d95cd10c77092a240dce59 +3b159d3ac09f37bdc31866a56100bd090d2a54894428e34a80b3cc4345261865 +3b1e16c08bf38e8b7e61864efab3b47804cb095c718a1bb0e767c73b84ef6dcb +3b249c2830778bf6db21d4f038e79f34d49a30373defdf2e150050d77f1c4621 +3b2708585e7f188059cedab0900277c09199c28881256a7bb053cec89ac4c41c +3b3a0f6b820b1070f54da319c9e2dfe36489b7659d462b5eb0be3388d2ca0589 +3b3fb1a6f55d36ad206521ef17150412eb28a170377b31490733ccc52f9ac35d +3b45bf1c827b9c953a47485485072dde6d60f80842c7cd4111fed94a76af6f36 +3b47a3d845a1fe513a3316b8fedc521dcaf0c0b244ee8c3084203e98a0ebdad1 +3b4de2f9c2686437a6c91725bc2db442bdb0f827e53ad871fa14aee2c3185824 +3b56cf57e6addb046f99cd1e61b9100a91df9c3bc127dcf2881a077ce8037c8c +3b61fb93179f5669c056a3194e847482d21502d761f4a818c742168158ad7095 +3b64e5df9e924512acf78b5bcdc8e36bddcd735cc939be15fa8b256c7acf0728 +3b661396aa47d8b4911a98e9f319c0447dbc8226e0878da6ab74724ba0bb23bd +3b6ef35a61cc52ab4e50f71c4320e0e5a592da4ecf77e7d0b58642fed948b7ef +3b77ba6a9a3494a5161ca7aca9b2801859acaf40076457f944d5eda963b0cdca +3b7c2de4ab07bb32a3da3c63666ef8bb0a075bf8c856f6a94c1aa521772e1123 +3b8094be9ad943e2b4fa6e4b098f16ede7a89c3d36101025dd07267581571679 +3b84e2e6ab8ab0809a40ecfbb86c819e42960d36b2fb7454d2d9481abcde008f +3b863a811f95268e7678de56b24c56f119a3f9c03ef52fb3b433a1bb6e83c074 +3b88b28efac4c125a50c1383b8c49c208698e67b4f89bc2479dedbc21cb1dc2c +3b8c3ce9fb7af3000243f8d3e25cadd3244b2f0e287b089d3774ce765b5aa249 +3b8e665139e8b58cfca248aa82485c35f46d6a443bca88efe205ab5b108587bf +3b91560c68b0d79692f82b292d8af1e3cbfddb15441ecb3e28a2246a3c554389 +3b9a68d10319ea7b8ed18df006fd2d55d522e71815aa399b34c59d73fa65409e +3ba59f37f928026651c95b47973f1e202a42676b7b779ecf31bfce04198b0cf4 +3bad902c846311447d6503d0d9385f8178f892dddbdc2844935ce0407e4b3f56 +3bb2dc89a9e6f1e334b7d0e4784014ef32f4a7161d55d980151c6f9aea1f8643 +3bbaa1488599b30ebcdc7ac4acd6292817249b6a3b96be696dd42cc4aed944c9 +3bc82ee917163f4e87145c4dd443d0f33e0c966eedabed3027392de2102ae06e +3bd7cba1bd488525541f0e604490375ddd3d8b1bd47222c2f5070769fd6da0e9 +3bda4a575b8b306a80fa0d4a7b9a3e1c91baa35405901f50e5da8fe8020538f1 +3bdde1104a064647da729fdecb24ad416b4971b865ad2a48f741d3427e5cf9c4 +3be6bf02d2418c1f1c626d6cd55c9d52b4a400f72136a662aefb3ac6ce2ae5ac +3bee09bf77d281662ac3b7175b9860c116c7a0709954d91c3e2760aca7c00e74 +3bef4da48f23560d9fef08e33d85bee280751b78ecc79f298fd88a5319478c43 +3bfd31e2cf246dbbc60621879b25dcb77c071df1498b0903827b6dccf4d50dac +3c00dbe225056d1028fa2119390f7b6c9cab1f4136f9ba11512a9a7c3ccdc7da +3c089cd05f8e60a4336446f90c1449496a1a70720dc0efde7f3085acdc2a796b +3c08d5b0af6a4f4bc42d0f3370cdc3279364f926730a4190b5e3e452ea1aa342 +3c19eb42ac4c491db219712e64caf90ec7c2aab003991ed1c018c6f9986ab1dc +3c1f68baba708d92b08b921b7008abf09deb59c4bf0884ac2a1a5c667b3077a1 +3c2bbb379a4b1ef283a6f11c45ff6cf78715296a36e848eb27f3564ee77fe383 +3c2f93317860f6bb0590d5fc4b229c0b4ab889fea5c03c93b0c3978fe0afc1e9 +3c34f192596177a45d1a7893fec798fe73823c268a3a4bbb56cf838831abb352 +3c39b6c05a3a2fedc0b010a4f4f76ef3866d57a599a078f0c4e32bf516b0283f +3c3b632bf15edab4e0d25689c48a2e57f464661b0b3565786836b44d3d7fb067 +3c3dd03254f9b801837c54b2197c571f52ceac90b78d90da3d861dace7260ed3 +3c468b89e6f401953c9e0ead1ed4e6c5891d3f99a3ee763839f8ed550cb83678 +3c572fb98ebee4800a0777d5a4a2cfc60fbf9200cc50a55717918ecbcecd13a5 +3c58b7e5b8cea79a0e8f5f6232da0627339272c3ba95272dce67d36799746afd +3c5982840de49e96d80eea559c15a71072b6ff96528e7be81fe78aa3f07a0770 +3c5f5ca2c7fbd50ee42c3a906bc87e8382c4f068c9c189beb39d230b17e10790 +3c6bb18799e9fe19668a0c63fb73ecda98a8eb82cb800fefd665d7655a4b7561 +3c6c9dc7a35eab9a00b847aa28e5f37122daf9c69400e881f14979bb1c9b7c3d +3c6ee8e06229bf5c9ffcb97ae7c412aadf86a98e62864e069238bc4079d7e4c4 +3c79325a4541a445691da6e93cbd654d2eba7106f75d3de15ad1a1924b35b7cc +3c7b7faae3fd69179b4650eab239d40435ddf86887fde416c8943690a4f67b7c +3c7cf9ec7bd3efa422a1d138656922224835560fca1a63bda78cc94b0ba58ee6 +3c8af236539abc018dab41b2466ee9e419fa204c2cda587f23450e681ff35947 +3c96a25b2fac520b5b14dc6813da497c63b5c528a8ff91f5d74b93c592f138b3 +3caa6c654e3fe0e2d80955ec6c7278d44b55af64725d4706108a882392a6f026 +3cb8e4c1216faf2e811295aae6084f8c94e9bf8a9d28b3cb5d56e64bdf482de0 +3cba52c43e33e862bf8f49aeb61f992bda90eb156767c91cbdcec97faeb22d85 +3cc431ac28b8a8184390f759dfb6622c1a55edf309adedb4c7f4ef9b3c157a90 +3ccac64abd8eeae582f42754ca2a63e58e234bde47f5779232cbccc8b499a40a +3cccd11c3c238acc3b60081c88bde53ecf93584d3a638951ee1f41586de0f2d3 +3cd4767348fb47855cad8fddbb19cf922afa2bea24ee2c85a503a748bdb329a8 +3cdf7013ddf16a17dffaf1023523c2a454c6b997099dddac26b900f63e59f6d3 +3cefc637af58a4e2970e84b072b3e1517f0e75166039fffb700f3658ea781503 +3cf5b949113eb9f8063d49393f095fcd80691dfa93a7196e5593e5ec59acbc7d +3cf8ab0c0666013ee5716dd3a53236df0f73416058b5d5accabbd81baed04ed8 +3cfbcd061e09fa7c8a9c93b0cf780edf87e338a6dcc8faa23378a152f99e6ffe +3cfe98898a17fe6de12b1468d9b10637e96857d7ed08cbb78fc2415f3c08068f +3d03ec89b8fade28b4ceb64b0593afef3a0afc6f6aa2a38cc8749e53e5070efe +3d0a1e576e9c9214b0cbfac6a779d499f26764adc08345028119ee4f8f5732a2 +3d1e3fe01e7abd559159999c494274cf7b0ad7872d94fa644b72b4329a8a7914 +3d220c796f07b1b74a1e95e4e0b8ba3b8d9955230ca9fdfe3521f2ff0d23d0bb +3d22c4e5e969687f2c5b61cff956a2e38fe2b9994e1818f557479591fdc79a65 +3d2a67dfdb0cdb594c2a52d14af6900ba459a4237522448691ad4e30d6ee1ac9 +3d2f000c87f4cae6bc9956dcf2c445dcb136bdba94dac60969634abddf62df24 +3d312415b0dea4db36dd78c06afc2eb1913d4403dfd5fc720329e36ca41dfacb +3d32fee70ffcb0268202f788a2a563a20919e871f3f13d460ecd3046b8280e54 +3d365db476e9dbcc111c09358a80b89a32e0b1498b1b0bd2586c549bf8fecc96 +3d372235181122033ea7a06016709b8547151e58415e640fee618df03063b4f0 +3d3b2ad36f21b8d3491192c8668691a458c5d7e4dfdf315efadd83c041df4273 +3d3b690ade2e51f114cfde14a87daec014e2ef1b12b20353ece7b6e253362c13 +3d46ca7e37f6544f4ebec2afa278536b641f9e2962bc92bd4b9987bc44f62027 +3d4ec8a351f4f12a81dbdf9bfa78a2b2635519ce4dd81c783dbf467883bf0c88 +3d511edffecaace24e6d18f96d9305aea0d36abba870a13825e12e8a88abf619 +3d608dec990f21634840ade12d89a1a3f716114aae80dbe6ef8dbdc5b9db0ee6 +3d627a285bec4ac1b4bf27d057a2db829e8d8b6bd0762485430b88c73fffe173 +3d691fa2f1493f2e2e39a81f5e10aee0abc4a011c0e042bd656e4007ee428f51 +3d6d03b438def602aaea4f8064b91c90335c15111c1eedfb548e9f504934ee5b +3d7682ea1cdb4b12065914115310c5932932cba0d7978e31ae2b5209710d4736 +3d7b9aafc61914af9d2d732c27d73a8dd2131ae6337ff6fb1e19734b03cd5c7c +3d8e997337437fa9c797f667130d91beadf5ce4168dc6cb4540ed403f512a303 +3d8f094d798175137252670e31b7c6a666af2805d0d96bcb06176a15b5f397d4 +3d9064c9bc54f07b043531fae3f65274419ce6232210880ed466090496fb2919 +3d9088a62c398c2633d284107e073f909393c837de19fe92729bf3b681bfb5bf +3d9c180960d1c900b8e946fcfde52b41659bffd0ae543633738b76e732b8af61 +3d9fa9ae6f4d9bb9d78504d03cac9588e83847c384b2fcb35d81fa46668e679c +3da5583623af81eed88c951019faa6cb482fbc170bc53bf311e088af43819d4d +3da5c0307220332236ae57dc6a8aac6316b306e4798057db81b4545525213842 +3da6d18ecd349dedb2552146cb68746af2397cfa26166d56bdb11ae37cde7928 +3da761dde3ecb27009fab650839fb3a7607e867519f7922f31ead7ec75f5cc8a +3dbbe3d8d5ec151272c66bcd7570b61347ee1ce31ce700ca5a4b32edaf3dfc70 +3dbff21096413d1b0e6ccc19cc37911a5073bde7f0db0c6583a160f875793577 +3dc3fb7cc8ef54b95d94348044467ba667cc323469e307411b54505beb20bed8 +3dc94bb7af6905e8562360a53b8106e5deca5a82b64c4b35e630f7fab428077a +3dcc982852e663741146e1988e09728280c447b526574424a55790ef7b2a060e +3dd967fc0f1b7b8c89ab13f86e118405cb3ca3528d0d3156f31c1cdcfe8f7d88 +3dd973aa6e7ad841d2a139bb702781534cd84d190caba368aa011ca4c1ea180d +3ddebc189d8aafa476295948c9b289e8fd94c94556ffe9ca4647c0b45f13e0c4 +3de118c1ea7b473c785acbde07db5e714982dbb397800d24dc01e499e3390a62 +3de2d6468c6fdc189240dc267bffef80307daa7863e967e569027ae2508ea4cb +3de810e32a93c3ddb343fb2ea43785d078a88cbe23ed6539f7d225f9ac985980 +3deafbd56fdfa6b73643847d125ec5fb325314c703b584aba6d98c2cfdcd94dd +3df89e3e38fd9818c1d6e048c5c9a0305954f582f54199f18e6b9f2feabdc9c0 +3df9c95d6f1eb84f0540f4246ffc3ab46ff0d6026891850982b2ee9dab616a3a +3dfaa9c78ccaf054fae84322dcc3ee11c42bd3e598f38845bc6e4ea880e9e676 +3e06171006f6cd25e50d4c648a5ba67c200aaea41cc23dbbc9566b776e379955 +3e06ecf7e6cd0846011d919b33212ef333d62cc61118e29330696b01fee9cb95 +3e15e282d71e30c8bc7c7f80a9a255e0d0727c72776758bd6b797ea125e629f5 +3e295e78fb6f8b68ed8590c20ed53d6e03ed0e6538aad51cb3c879a657989721 +3e31357f30861af661b38924301eb94066dd869aca7086edf8735ca41d81e588 +3e4825c120c46252e61fe750b6398650461c4780752d8af943571726d487c30a +3e5268038cc95964e0b0c2a26d7b7c17be4c79e4124c42f4682c37b6d192df7e +3e5353fdd7e01a2d0f972cce0ce8dac16bb10bddb30a479b1dd0dea3411dbf93 +3e676f534064519ec37f3f706a50cb8f530dbd0325b01e69330de6588948cd64 +3e79d0a463d34083769d0a11c8168c3f45fd97daf55ac15beb85f453bd7965a7 +3eb5dc749223a42a39dff803fbce823c3b7f385e468b10cc484dc363a2c4586b +3eb814e7b3bd0d3c2142a41290a1c76c372c72ebf49ba00b118306e1ada7b9d0 +3eba7c38c4e4e614bf481ea6e96ea0fd66517ce0d40e203fcc329bc416c83f0e +3ec17a72a05fc002b69532c3a37661570eb87df6611e521b7c74e47b8e25727b +3ec655157f07b630ded2f1399dfe3da69a5ca2f3ecdd3c7573782a64ca16e2d6 +3ec9644f00b972ee81d885982a4a6998967c404c448037c709cd95c022227c33 +3ed218bf4789fe3bb7b0b21237ddaf1ba10a093a2a822fa7923620aeeb369495 +3ed6405bfe5f02a6d65ef2446159ca296793cb958b9c5920cbdf8afd02a0d446 +3ed6b74943a97552a7ab6e5edd0f33727c04dbf6de276efceb0fb0c5444371e2 +3ed7ff0272139be091787dfe504e8971d454fd0ceb024bb772286f3f55db3f1e +3ed9d004b4a238af0ac25768c288c5c0dbe2629017e30cc969cbfe6f4704f58d +3edea2d2964e2b8ccc28951224a33eb61fcb0a18622fc9df5a30651d33fe3b1e +3ee027559ccc6581f475f399d6fa339c699a6d5eb8b99ec1c18a0ba2f42a2b89 +3ef2c014fcacdcc88b68dd6a8cfd3a1a58440129afa52cbeaf98192499d3b13f +3f05156a6b865575aa2975c38dc3d880c2fa3d557df48bd32a9f2508b93607c4 +3f0e8f7e16eea7478d8e122d9e29b98f093f2d2c288df06db83d22774cbb2a9a +3f1448f091a26db5e3c24d2ca2848792e6d23990e9a6a58d0acb67eec480e1fb +3f2ef5f4c546ed5031837cef72b11a312469bb9578db14b88a54c287ac3932ff +3f2f1d877d6f8a4a72d802ed9b57160d1f4d5075b5a9821c16d74f5958b69da5 +3f35f0e6ea1955cd2f5cae8dfe132f233b75f5ca85a76b6b0c31249d51ecc664 +3f39c5b76b6a0afb400fde34a6f25bccbea91ae0ce9f5e4fd251aaf5894509dc +3f3fd19320889b801411004912c7674c45178b8d95b23151284e66aa5149dd6c +3f4fe4eb1c887f409a0a3841b6d548d56feb8b64fe4891ba9213223ca9837841 +3f5e9add3e26d3ff0c52bde1a8a0937772b3190ffa1ee8b07d271b7470f6d157 +3f68bde0a326d5f5f28a2347722b5669abf818f1831acbddb420d838ad289e53 +3f6aee119abf40b59f9de6deb3740efe84316b137f4ad073cf9d9df22950df46 +3f73efd194648a47ebf8436654a3b0d7b6911c9ba347687026c6a11859960961 +3f74b08ea74668a1305afab8c3c6e6f0db682ea97f9097e7342e2072ecb6b74d +3f77558be78ad11289bcb90f87fe6d376f608218f51215ebf1f34c607d88613e +3f8cc385c5e63d20829d03ec6d5c1340661a6045e92b7b3937c62a292d31170a +3f8f4f78e8cc1b451bf3a59a91a3481b583893c33cee1fe816a30f9b6716e9a0 +3f909faeea1faa47316f68db698b713c56c387dafc2f0f716d3fd7c043aee79d +3f90bd329da9146f9126c7c8e28470e94254c7063959ac10a6d826d31e846151 +3f933b7724a11806e6838b7cfbb0063154a9592d4f6954805904802bcfdf6e7b +3f968f9dada3427192c558feac579ebe8ce0b9c07975b7b976b4a272d77234dc +3fa66d0effe721e12b1be2f023d5d2ab34fece19126cfea2dc5ac1ee9a7a6019 +3fb9ef40d059926c6ca03f9a237dd35f6b7b3922b0a5db169269115008cb4197 +3fcf63219a7ccbbcf7d987a193f6c84459ee6f82aea737a7832917c882d9103c +3fec87cd91b515ce88df7a40025b1122f5bc51d40ca4c9f8e971513cbeb451d0 +3ff098cc98f4eca49893798bc11bf9032b04df35586334e68222088e4311cffa +3ff1d6f7af86afa7a049dc843dbcfbc8ad7968f64e76e5a30fb1dafc0c138bc5 +3ff346f9017582170ede4003fe5a5e75d8ec4f22b44722c76eb3e1de3ff2e5e1 +3ff6c4b9afa67e88705f774e86c786ef126f874a032703e4f5cac8af4c1052c2 +4006ba85d2abd477b25f677a99daceb29c8046652fb50a2d6327e03d7cd4e9e6 +4007222ec8547246a1166e0b32d313877d83b1d7cdf301fa0b7e00da3a6c6ac3 +400acb4f0462d5040a34c399908cdb1411bb2d3e5d2db9da0e638004a5663c25 +4010c24ce668f558b69df38dcb7e31ae5cb9c6091b1333d17d6c3c56103417bf +4017effa6029694195835eec414e5d585e98aa2aa0fb63222d7de124bbec3c34 +4018c1beda54d5ddc64ba276299aa1511c47e6a60482e5cf8582b7c578ec441b +4019fca1b330ac0db5a608b25c301d56373dae35d63fc1c09eb924c1a6b3100e +401de293454f181cd606c645df346091b0eec4aca42ab2b5579a1f0e320db1bb +401ec85f0671084d3613bd84d2b0a9070aa41a2baa53a9a2d7ed5d43dc572bc2 +402d4e168ec957ac8e7c73315e5a2f83cff53baf3d2603c0b3fa360731ca1634 +40307ff1007410d8d3de26d38e199d5b72dadfa6b8f5ae2a522c90ac1268acf5 +4030f68ee324f29c0a5ce730c346f0d22d726ec5ff724dbe601429f105a03a36 +403538678bbd5e4a1ab1a7580d7594cfbe9e3be93c20eec85f1325f5275e6baa +40434773a641fb0991144db5318722443c416b17a6ffacba497fbc734a8c69ba +4047ba59f3ebd7838e50eeef989e1784562532b996ec934711e3d62a29f921a4 +404805218cec6cea8926d116f129bb4a5f30368689d19f1ee9ff1982552a00ea +404c3024913f5e99808d0053227e8e83823d4a1cb2bfa1c1d22451398ac8a3ec +4067d213a77b2c1b9ec67bfef24bb5ff92b47bb553b3893e3e1c6ede436231ba +406d43769024e5551aeb243f8bef8edbcf9b6dba030d452bfc2663c631d75fe6 +406de82bee677edaa2f0939a26ac357858f9208b2a9453d919e477451e3f111e +407372bb641468c7b85cddb6185d7fcd2650680e05a6e5a6471fd62e5ca70c4c +4080a12a93f2a69e88d19518365635cfb0c0ff81e54624d6376ce286ff830670 +4083b31599bb95497e57710c4883f09665c92312c545f45dd1826af570c4e0fd +4088bcc3c1790350eded8b52c4c729a8a6ea392af40244d3308f6d23ceaaab81 +40928ab178f8468f40c245696dd074a3db4fad13ccfecfd4bc252ff1e2b1b382 +4098e7710b4d18480963c8cfe33505754e5da1a25a3088f964305cb6ea04c007 +4098ed89ac9fd989651bfd715f7e9370a2c4caab9b5d35bfe24330832f3faee4 +409e3d7a2fb1f3c5c16286e1f4b1d1d8853827200fc6a46cd3d4fb587859fcde +40ab00a467dfb55614e8062781286c654aa905b011123c123bce649ae1dc881c +40b0ff3fe608f17954849effa0bac6ceb797f39d13b218e5f07f770b512c819f +40bdb859f0a9e71a98be3155b01293bb711b4d40d044b2867388c5211c77930f +40c3def1a241786663ea4d147c7db89e34f489d7966a6a07aa8669dc6977ece8 +40c72e2f6c8884993b8342c79bb6e037f601854e94caac3e22ab7f8034b47886 +40cb9855c1b516b62026b421f06ec1631c70d52ad4cfab2e030787e554615396 +40d403c23ca5f5875dd442f7ca45f66d1571fc6b70d949b90a2a9264c6c0f62d +40d5dd4b8977b133b6df59cbcdfb6534c7122249495b403bc10bca60c01717e6 +40d66ddb04223d2316e7efebc24e5b86cc7ed9f3833d6beb40c408d6941ae471 +40d876c11dd8472b534c34275e6313e9a0b5ebaa78ff19caa21f562047947f61 +40efd1d04afbbd9961ee53a7afdea571a2a11568549ed464a81b3350853b01c2 +40f4dc0128bdfefd8a85f8fc0965d4f81fb303312fdda8702ccebf58b921af57 +40fe7b270ba59e01c3e204f9b73e5d9e7932ae668eee8343a44e93cfa6407205 +4106184111b24c35fccdbc8d5bb729ea021711fef3d556997f0a55bd5c16131d +410678a7fc231a70eadeb756bc301434a04002f4173378bcd7e10a27a83a6104 +4117cbb29edbc97d96380b2519e4f693f77b3cdcee837d89a706672d7df7c82f +411896549c3b5b741dcbef2a22c17f27969c4fe4f3f7bd8b8c49d140fbe2f728 +41315261b963ee2b4a706bb5b7fbfbf5996e8ed4f1c62d309bb9a1f2a652d019 +4137824217f279831c08735ba23316ddd2d77a02faadc604d9fb44295ec5d696 +413dd0e02de3edb7755193078428708e5b3590a4950b2e02785b8d6af5d0f246 +4144468c64d7e4ae056dfa366430374039af1ac3fac9bbe1eaa5656cd7cb8e15 +41496631975555b0f20163b9700a80830de88b460e7e56ec025c61c97634d775 +414d5f2999f3eead375625fb00b0dc10f857a4ad24a9d32be07ab28b251a98ff +415635d6f9b1b71cde5d04c551a7a03ff551f56308dc7fe0253c3d02c48887d5 +415e0c948be5e554f3a7e3e73c364821d3d3acc7c8fc5993cba031815e4d9b23 +4168ed870f753287b6c87f1d7b3f4f85d56904cfd262e06304c4f0a6f411c4db +4172fd0d73d8b648cb1782de7c2581e67d00e6f76f67dbec29e1279c902ba131 +41794773c13cfc7433544fb011ac84f3b8ebd63f323f9ad10c3eb7d17352769d +41896bfbaadd43447c7d61f63c639c6e2343f4d03882ed221cb463b83f2d0ef3 +418f2a362d499d0e8352819c0d1d4bbe78717ec312e8d859c9324c4cc7244693 +4193c4580bd20d7aea9ccab09cc2686bba94c05a9efb932125bfec8ba81787c5 +4197fca7d1aa01cd75738df39f31ec4710e84208465fdb5a7544c8aa1f72715b +41a33a4c88c92a479e4e56b23fc011493e378daa230e8f9da4869d147a342972 +41a8ef820e87643a02d46c51d1b5f065d7558fe5026e5572e82cc940b040ad99 +41b23dd0e0699eda3dcfd6cd333704bf36976bbc20b90f709fad9d9e8cfd83c5 +41b39ae1ec2276708f7b50560d16f7b9ce64fa93ec848ecf4cd611bb9abedeaf +41bbd6afc7d6e3e6db1b51a5db737599125d030fabf05c7b29a82bc2f2567482 +41cabe0788ce798d7d4225c4563343c2eaf8529dbcdc0f2a28eff6206daa30da +41cefea372cfb5f795757bb1106f0eaf445fb42e36435dc7e3fc41f8c217c7a0 +41d4a0316cd0b11c6dd04c9dfb6e7fafccd134f4688a007e788ffeee9244786c +41ea13ef660e00ead0aaf43b2246da69f8864a113ed39868b0eb0231c40a0228 +41f04be0cafdc133683e9270764affcb77218e70d5f22af5ad49978fd29937fb +41fbeda89641921ab04a0ed211fbc7d5593c0ec20228c13d6e1e67a7e603977d +420ab7d61ce15d22ded14147f918f076b3fca3e187e03964302843d414d661d3 +421115631da4185d809a2c1074c0176dcce56bee853b77402d09d9f953be1156 +421896d86e89fd5e406fd7b1ca8c12bc591658436453bc4ad53eca74fd4f5599 +421f2131c2910aeb31af919b810011ed21b3b0b0ed312d3640707188cab9deaa +4226d33153a176978c7a54203f65f0dce06f20f8139391bbffdf50385c1828b0 +422b5f6eba96249d7e11f8e13dbc71a73b4a1345727016e1cd18f515e31b658e +422cecee7e1abc31041333fd3b37ab488745073355b5cc81b391ce7b71ef11a1 +422fb7d9dddd4ae5eab56fc3dd26b60553158ea740c50cab984d5f48d67222f3 +423f53f675e765a38535c1231b410bf83bd54986b68f9235ce97350b6d44c974 +42435e1738563619d3d5a3042e0cbf55e00953e92e086e377b5f9b03c09c1008 +4246f9bc83ff7263f800721957f34a8e34768813f41b269d23d569640faf1f46 +425cf5573ed2026043477c860edd00b3066496db2505144d122c233dae99c616 +425f764a53a614d269a608ae4d85f66596709f6b9f9e34806cc47027a8b3bc42 +426c9edb16bebeb8dce7bce2f18db8d19a2e566f064b0d17fb184210b4b163cc +42742ade2f99e48c82eb3cf4196908a6790eb23d3644bfd40b87a932dd1ab7da +427aa4caac035b7ed1f4eb975ee3d0d3748e0a66c658ac34a57b93309c08e040 +42811c9d00a1c41bd9ffc0d414d08abe1e3d36e06db282e7b0a39e6a9330cefc +4289c373ffae06c0a0d3993706deee29062275fe37a28537a406829d055fcc0e +42939ff3c92ab1b1f14a82d0c91255d070e490732ebaef9c85806aa489fa8dcb +429879cc721b1ec56b03952966f8c7a26428f1faa17e7c9f369a67073d53233d +42a52759754cb162471991f1f99a7d37fe90811230df9caf41e4d622c7533fbd +42aa8928f52abc63f40df682ca95cc961fc7d0d6ef09d9a18107cd4e25fbc2bf +42c8592ae6876393873ea927c1df065388b4b6a524c0cea6694f4f8f07022fd4 +42c9bbd1e6e0932d0e5f8f65c1e817ef34ed37c5845954b01d08193c53b0f3e7 +42d7b948365945999b91ecde5f90dcec7269142f01d211518c165ed9fa88a2f8 +42dd71da0c9a58188613b657267e3507206f5952176f9cc60840c0992763b074 +42e01125f35f234d1353a5dcb5e9efb7237881ad48409a8566b1685861b33cc3 +42e1181983e3a71352eb7fac05fe1d939a650a6df72ff288e2896eaa44d4d651 +42e78727138914797e6e86d217ebb183e3d7e3f594100af9fb40fd65852865e0 +42fe9af69c90a8e658124133284dbca09e8feab768dec8d77e371b2368019f9d +4308de77939f766deb666080f95cd95ba628c874da6806c078ab12b80111db71 +430af0ae6fa3d482ce2fa62329ccad408df40303d083251f176df943cba68c63 +4316c3d6f5596547edb638d8f3aba03a10eb508610b901d72d42896b2596b6bb +431717d40fa64293a085d5a0180b295edf42bba5ed134f22e59d93667cdc9d23 +431ba5d71dfc6e93a8f0e9c1ebf3faef9cd797e61753d07e96577a63210dfaf2 +431d83499ae4689c637e5c154b20d8f1df6021b5eae02eba45c78650d433cf57 +432ce92ff114320f9a1dc4644d9a156e9f1b48340a1aacd46f1161fb99064f40 +4333b5d4e8f1c7e9ab057e184620cf5d5f2f15fcd01d740b9d5764b6ac39bef7 +433ffbfea65ed432719dbcec05bc6d39e34280d7fc6f3ff591c33b23d48b020d +4340a5e8b37e0a687bb2e45944e79aafbbbc6ec6dde104234b95af9e9ec7f0f0 +4341b8eda2cea8b1b43d1f8d5128384a98eb18a98fed5c57a7adc3631c0e2c72 +4349ac5e6f6f9ff59636a84d20dc49788549f76a5b7dce67409c94d5bfa01db4 +434debc4ebfbc0e53c774347142dfd1b764d9e9c295e4be8791dc75ef0875ead +435228fbccf5d605a52dbdf1090364f25df12a4e069d7e70cfdcaf2ebd15b1db +435a56d60cb472d5154165a43a089ff7800e7f2958de56ce13a61a01b518e064 +435ff2f9dd8df45f46af786d388f71acf9526592cf11f03ac38649c75b4c02c7 +43626d0d6be19cf27512192884402661f47640cf90d43f4619453c375b235240 +4367fe2b561319658b412537922c30e897288b8fcae0494eb8c760e781e51a91 +437c87373b58cd15865e113a0b647a5f87f418342b6b21f84242a20542cca812 +438cadaabc7914e353e76fc14f5623b7aafb873fad4be7e50818045ec230af53 +4394e0b4c3cb9641b13c328806b3067b1d900da947f814508714129a4bcaac2c +43a9083ea650a8e10866bb0fb11e0b2553cfe385612ca1becf7ceabed70bafe5 +43b24e9c45666956174c2f8bf667b7f307c29f8796522672ff70e90712c61d24 +43b3fa1ff2e61da9f05ec08818c2983ca4f95d7b4c2c27b83bfc41e080c53e5f +43c28946fbb6a03c2e2c6c8e918e6beb408caea4975459322c8349514d71edd9 +43c369a90c4e7d941f27c568fc3fa35ce5531508a724d4bebfd562f9970025eb +43d5f277d4075910102d3930f3b37b1a968fd1521219b0ba62ebbdc6cf30300e +43d8812cbbc299451f6d2bc37161cdad4d3e4c6e700ea6f27079517463223516 +43e381863013ff289d3d77ea0b18eba874941d4f40338e0d05ce255b0600ed6b +43e3e0601dc4e3b060f5949faabe381be657f7d117c9cde8c5db02c5d1f855d8 +43f007f30ebdb67645f24458f3f1971be6b81397e9a9dea20f5feb26f2cdbc0e +43f7b70448c7f74a33c61f530111f121465879bb6f1493c34469b9e8f03a984f +44079501ac825d2e6497ec18eab50eb9247db394d32b608423c21320eaf5472e +44088cd4c049e44a8aaf5941a9100734a1065874feea3a6a1cd4b6a14a0e0728 +44091b4e4d2a8fda6313b66970976f6ec6503ea04c4999cca086221e21a8d7c8 +440b29077ce05bf4cc7608c993db115807d23d2694189915bcb09e4bd093cf8b +440fe7fdf9474de1cee5862adc3e46896435f887df9bf92af4abe4d032829eb1 +44129e263896e1efefd50df66cae0468fb2f59dfe3876022878d3b6781c20278 +44258de4b2bf1a80630c6f90833a3ee00727ea6c4d6aec59f4319e47b69faf70 +44340929feb0437352f8281f809de71159b1c242708714d3455f1ed65d53da4f +444f046674d549dd3d7b949ec4fa28fd40278c9ea4cabe0a06065bdb6b7a62ea +4459fd4b009c03ca62fdd01ed79f441889820937a269ff8c3228aa4cfffbaef5 +445e255e4e0e4d944636bef5864c5f0d433b97672dbf94c13a73b14bf05ea8b9 +4468f65393e92a5af04cb2f4d942e218aa14ac49eaabadf5f7d50c70218306a1 +446a81c90e6063ae5b18a67ada4057f94a3dfee026afcd04440f57c111fd86ae +446ce2664b6a495912d1daa5047562dcb03dec1ef9b1a6c65ba636adea1a52cd +446ec76126744d541b1efd270c71c076313f077872ae0275695d8b7d3647bf18 +446f07d7a4d815953b5c385235922e1ce4617a71f4d583bd380d0b4cecf0d5b6 +4475471f54bd9ba27264d3ae5dff6460567a20bafca5f495984f07012ad3c581 +4477d4b92769ab2cacd70ef1c3dd42eeed01210e199b9689f0956475871cf9d2 +4478a755f2c9e05a0a7e121957ccec7b3ebebf4e8c367f46194fe503a20fc36f +44859b3cdafa864a0a44418611e0f4ae44207badb48691bd73e0ea2ec09009dc +44878e0d438feb7f68ca41f16100dcb6438d113db0239f584a6d622b5f2439d2 +448857e75e302bb4124fe05f3e1b1df19bd944b68c1abad817a862a5b200049b +44940b9355c44bfa03ddd2da4e4b44e066cb7c1d062f75ebdb66c4fd4ff237b6 +4496c6e58edc742d2b8b0e7f6db9751a3beefdddaf3e10d68015ce43b87ee29e +449b20627a7a987ec5b2b4993b4f8256f1a693e8b9d04ecea2ca0a7bddfad4ac +44a0cdbf21785ad9c814a46376ba32bd851876e6c8fc7cadb8e0e9c3769ec3db +44ad57a8f5cf75c5a6b03b4fb0f54cb49d970a44d72cd4fbace940f8f4d63997 +44bc45aa67a1f1b6417f26db76d3161c7573b69f1f46f6a39a9289ac6f7114f1 +44d73575707579adea9845f3c9cdc2bbc34aa562341f0b2b30aea12b97a18504 +44d91ff33a75267a9f7972bda696709b573ee2c8aefa7a66193485a3ccdf914f +44db14af1411eb8d70cfbc12a444861a52f4c35a67a90c704ca48558be3bf48f +44dec7f1287991e2fb8dcd67691cf0d3246c949a941a5ec9ad9131833a6a9b61 +44e1031a5e735e3b9f0cb69b35bcb96f2d776747711b5a743f1065d609ecce0b +44e46e5a4494b43bd839da3615d42d1b9e416e0ac076963647babc7ebddf6bfb +44f924fc63c3200a451721bd19bbb83aa486f04ab265518c1f6313168510792e +44fb5e17e94388b4535b2fa276a2e7593e9b4491bab59d78690583cf214456ab +4502325fb49130ba4121b9c7d1bfe13abfdb631ebcc2c1019a0a80dc438e6db7 +451890f5a467be7e16aef8a39a6cf7a66abc21ce85483a14ffc9ecc32c0d787e +4521c673f08c6cff33f26c4158d7084d31e2321a3faae6b81cc43129ae6872a1 +4548b153d2ce6e738fa910883543598d294d9bd9e1869009d557b6ae66511e59 +454b3e9ed23289d50b25be75606de4eee164833989b044bfac999048b7add97a +454c8c503a1fdbeb0aee166923642858fe0f3d300af982afac36e3e107fe7ea3 +456e346805608952031f699b6ad0a3557bbeaa3a4329c9f0c10cc87bba5886c9 +4576abc865a0ef8a5c047c1014b32c270f006c3421a16d6ced9dea63d211f550 +457a0dc916d518d3031e2dd904136ea529db8fa4f344211d734082071dd2a676 +457d52ebe0a785c7733a65c7434de2c78d6411fb1f7d6c77e2235d85876dd10f +4582f0c2044ce40c8ea399f8ede3c938ad5cec3dbc209fc3e9b31c0edc2445fc +45868317058048fc0d26007168501f3c48723ad781b06a3c9e4ad29ed72f7d7e +4587fd348aba345d545d31a08238cb21a42faf48d79bae8fdf1258b9c0457f2a +45900822972c3147d1cdcc536d486f3d6c5e7f1166b185283f9f21ed53f92612 +4590483a40abf7fe7e3509b4e1a7ce48a0be18d2f97c0f2ea9ed9bf75f5e6973 +459509da8dae9a5d11feb7ee630db63b43c742da8eec83c73a5d4759d1507ff4 +459cd7aed2d2683bb2810564ede0b1a7031af4fa3ae10419bcbabadd1b0e82fe +459e8481b151a42354835491e984459619b0e3292f32d197bb3d349e4c171204 +45b36e9f69cc3e551d7d10e38d744a9ef45f97d2265b46928e823db951c0c9f9 +45b9b18ca58100f98ca0b66a6f7c82ae3c3203d7fd56c9d933361c2b1f628d66 +45bded0b5549bc1767961d85f12df6eafb253f4907b256fdb21861d999d55680 +45c3fdeb0e63a3f389566c22ea9f8711278e2f4412700755a18fa260923acaaf +45c5ad5c536d81a78f9c6c2ecbd2919f0a5c408853f7751502ee05ae2f35064c +45cf78f49b0c88bb21bab012d4a5e5bf7476d909534e32c159f30257970a7674 +45dd46bd5fc5830637d516519256d6681ac8cc44534a280062385c1088d6d5a5 +45dd4cae7a0f525a9f9b3cbd07820601d1f71fc783f60eb7239002b80d81b816 +45ddeed33568f19a3a65a40b24b050a7c6e415c72b09fd2a0322a742bda30937 +45e0367911850e9f59c73258a706ef3480430b47c9f80bd9f4444cc2eb687a1b +45e1b935cd22e726caac5e00b67edf423471b7e35a4dfa39d8d74d7a9eda9676 +45e3381db21103072301969dd661d7caff374aaa14258b0e8fac72aef20a6196 +45e9e722005494c314dbf1658535828cb2f0365786a1b0a0b15d854c37ce3cf3 +45f3d0fbe2b427e50365835002cbff21658eabd0b46b8084dff4e061a3589fc9 +45f99bf9e73346e2bfc3361f849b244d2728a1b3a943ab0762d1251858701070 +4600b3de699082b727f8bbe120342ba6cd3586a9a39bb5714d8da2fd46f09877 +4601a25f02ba0c1f2f341c814cbdfbca74205827f7371e574d4a4c3ded8350e2 +460b8825cf8266739ba011239a43f2842e65443eeddf56d83f3f479e0ba09430 +460bc40db740bfb5d8eb9e6d438d9e8ee347ede0672ab2ef69a5d03df0514cc2 +4618599c5c3ca548148bff086bd9f0e9998b47bed10306fd67a17b5ad2df6e5f +4619738d1b99c8c281222ada6970fff92b940b4496f18533585013a558c73c82 +461b68e13081cf16e7b5829ffe39c7698611620590f3f0c0af45394dd728834e +461e027cb14bf32b96e9c5d4f486a2fec4a5a2865b4ce8476a7df64c26ff9e57 +462b628aed5e762b54866a3a83e90597ca35d0142c08cc7af166b0c6cf7f2c0c +463244caea086a9dc4b8123917ce4f3ac2ec0713d188964f01352aaca38e7ab8 +463bac339824081532c28800a75f5c9c31be046af6fd4a434310a2288cb5ccec +463c29e8337c541ca878bbcd7b49ffb8b12b5b5545ab35d1886e01968feb19dc +4645a8182018113af190bc1c0be7d8f702697e31bc7a314b572f20256efbd2ed +464b72984e6844e2673bc8f769966c118086745236d9f68777d3147c4932c905 +465293d833696280da06e006577cd2e1848d8909e9e4782c1109096106e019b9 +46639d21d06e79334aab9854c66babb19d60b70396f9628948e48026e7586469 +4669b885e63ce577a3e7ef35176075e73213db48f4f244356f70cce1f644d4f5 +466b1d95d3850f4dc3e54d684a45b78682f093842f98e2bf4432ee48eea6ce77 +466ce1f044abf27180c5bdec980b64ffb757694cf6137e24a5e3336c2401d0e1 +466dd3c263d345c46b0e25d8e677314d5011534e489c036dffcffb6d24dadc3c +46752c2352810feae91fee9099875564ebbc6beeda0150cde3b3cc170fd35f9f +468639c908c2af96720fb79aea226d219a425ec0febbd928e0ba54396152ec69 +46884c91312e7231205a9dda5a2e8f2fbb8ed7e54334b9c41dda467bc22de568 +468eeeb59584c99fb9386d37ca46922dce4e9ce387de334d6857d98d861429c9 +469cc0bd943319862cbd7084a6b36deb5bc2e6d7637fb1e7e0ed69ef6d5d5ca1 +46a83fcbfd18dfee0a1e6fe9548f05e75578c5dd4caeda74125eaceb7cf9ec31 +46aadfb4291c9e88bd742eb9e0844b130856ede7fb7f73c64cc282a7406a0c02 +46ac5a1f7eae7b8a362a15ce0e45e99e4fbeb4afd4a270a3aea42be18af1e42b +46b7ffb1e1b073ee8f99d21ea074ab1a4ac82e683348ac3f27c96b15ceffd235 +46be36cc96edc16e8555853ad97d308ed84fd380a0da685cd7825f2d36afe9c6 +46c452b9634c79e923f40abb27bb7430ba9461d545133c6ec74cbcf2313e0932 +46c7d445bfbe7b69a09483f2dc2383e90dc79f85509114d77dd6d8c24905bb8b +46e44cc796bfe018ba8b80f68cfd2473d765fc46b473e9869c40be6392f0a369 +46fc3447217adeffe3c5983c496c060894a973d627328ba86c74c806864242fb +46fd20ff8ff60f5bb2661e9ee66565f213c34357fb278ff52636c83f979d549b +4700fab4b56391e604e8997859b2338f3cc9f1ae63f8a7aa8b65c52133be1686 +470dac805db24a2b4ddb7b0d86771270261dbcb4b6e7779b6133032ac78d09cb +470f494a4928f066f7ed030433d8b63fa03da6b7e870ed587811be0e6c2c2797 +470fcd8d5dd52392e2437253cf06c48238313346c4483c84b6f07d68686ddd37 +4714d9e55403f04bbb9736a38855fcfb6b3c8a0fd8f976c334a390efd26d2f7e +4717d585a84c338e6b4b2103361de1ef54648318db826058a0f9d9592b06515a +471af6b00acd237c97203a30f60a3873e7b78276c71835656df48bb2c76330eb +471eaef403502c26b81f69feae8eafb9ca708f723f56b40f52bef61df64c42d8 +47293201dcc933c02b984e73f951d4a71ca24d8c5769bd90dbfb2c0148ab601c +472d9236a1b383a03b3a1b2446f101eed4f43582afc1867fc265d53dca381171 +472e32e4f046a98acf48e7b89697a6b8d6a9c9b4a2e2d2a70cda480452882aa7 +472fca5910db544f665b479ba55d1663ae413664fc6fd3b54507e4eb26c981f7 +473c98551d88cf848765baa4a4f6ac8643bc5eefef4d33a97143726a1a9b585f +473ded38448b05677dcd9a142b39aea8732069ff69aaeab92f5df50b6a8f1df2 +47434d676d08e78bfd9c2701c3f8f9eae18016c4793ad18964c8dbd46ab1f1ee +4748bf8f350add1fb8c33d493f140d1616b0346d67eda2a1a14c9209c1167380 +4760414ca1f0c52f16fae16b820d8023f9c3c5016b82a520da578bb60b1bc1b5 +47698fede91053bda054742edb88c9a17cc1c9dbbd61da2e8154d5fd3cd3bc87 +47761e4d40520d5187342bfade93b4bd123dcc5e45357a808bc388f670767fb1 +47854e524dc16617f18821822eae8a44d46e5b4954651e0c50c64eebff299e7f +478930547a0614909af93716f30cd06f69153e25814fcf1fd9d80c5022b9552e +479116d88429b1086e1f90ecb65f5c4ad36b04cccf710d9d925347a7894b24d0 +479c21b9690ccca3ee92939e8545fd621b6a71d61a142d56bbd2e2edf528f971 +47ac0df367efaa8384c3de2e2b113970625c0a0b1fc62659763212cf098f515f +47b2d227fc43f6ae1850d9ef820805ee41639a51fbdb7182861172fa0f2e2fe6 +47c80107ea650493edcd2abb889674cca0bb21913300210bf706e2cb7c1df3b6 +47c825734377a018eb1452f266be6cfe7932716de689fb36886c3002ece889f7 +47d5850743fdfe67b87cbd35b278436a01ff8e77ecaa6d342ce3ffc901018435 +47e21cfb5e5a7e372e51ef4a4b6b8b43c6ab4e6253c410a50d8184c0212de3c1 +47f4b03d2b40c0419ad097f1fc9f66b88ed37b5bc80c164481735fd45c37aad6 +47f883e8686b368ef68cda1751c6a6d9daf4032bdb9d731eb062c4b288400388 +47f919b6d5b6ca03f8d8388cb65957b30ed0afa5aad04cd397e56470524dee78 +47fcb002583daf73087828c656349779196f3672ed8eb35a8e16b9c683397944 +48162890a2d95b5e7073a0f906a46f401421b33fc2f79b1747e9a4d23ce30f2a +4816429a69131f859a294d5c6f1810974b886c34d3cdd0104c1230fb9ea010b6 +48197dc3af1b0790596350371c42c3d2eb466a2aa0600395de33cfbac05a17f8 +4828c719f371ef552f91dc2985f8662bc94c2041df3f7427cd750b7805440ffd +4830bcb78712d10c3203ade630d826eedd9e8023cc16a7eedeb8af5730df0b47 +4832885c197dc6d2b5cbb5bb3a925caa40aa7d86aed93e5a6c2c7ee8222b0c2d +484362b3fef040e3ddbced8d77879e2b54c49d18ee8fdb9f80f1055b987556df +4858c35808e7230b740c1c2dfefeb1e38df57847731ab73c55a361eacbe7a268 +485903cbd59d20b3bf7dd74725f2655c0461e3ab2366e17e8d9036f83519097b +485d68aa49d9361ce459d76ac1cd2f0858f3f1493a0cff60502f0585b39292e0 +486058c664931b99b3e1b19fdb1b2eacca57ea877ced386ee29a321f463a8490 +48640d959d4044249e416cd7d1a58754199c55a4226374a7c362bc8b7cf120f6 +4868988daccd6e118d9f5d60dd80bfc1cddbad18b25811be5e284fd47684a6ef +4875b0b8203324705fb54882736dc4cc7074ab82f1f15bb468ebea458b693722 +4877485eccf0dc1e532ca1d44a5196d75c5f6f4e7bc9fa236680510909388042 +4877c02b407a389eaaa7ce02536196a05844ab76bf04928f90e63cb4ac99fcd1 +4877ed2d9733dd52874c988084bcfa62314541e3a7b2af049e4f7eaf89277fe1 +4879928b665133f33b9e7a87d39a317ad478de973d26ead531778a0125817235 +487b2c23e80d53acc3513645ed2f8590359aa9d966c928668e6b462499dc9383 +4882a4c226cd0f7d5e61ed6e6e4f85d62f81a2914180f020185ebe7991f2d020 +4883140d3103f7b24c8444737cbcfa890d35adf574e3cc4973a9ce6294c3b6ee +48838bd275895d92610632b4b90d7fc363ab00c29848a2efad97568d48bae125 +488805c16bfa04668c527fc1d72e3564f3b4bababb3ac31ab40cd8b72e076aa4 +4889f66c093e4052edfa9126ed98cc360a0d0f0867af4e0c29fa0b5e7e5cc0da +4892cfe6e1b7243955a4ad1702f1402f2aed3a50f6644acbd8d59afc65f2e836 +48957f3a451b67df14bd3b3362f11f731d39d740d6ea4503b8095e0bf84885f6 +489b32b3c2efa0710ef000d7ccdcacd35e79e2fc9f4d3079f0b2a4998f160190 +48a1e8026eef94490db40d988d3684c32a979ef8503275d8350e167374de7422 +48a4ca62495bb29f9bf4edb8444eac6f9644ad8b1864a3672536144bb5ecfd1e +48b07f79c7f3f49435b7f527de1fb581b76079fbe26c6f313ac8b4db804faab4 +48b2b480853676bfbe68813fad333439466ffebb03b85ff47d9a3325f36dd7db +48b2ef9c2913f71cd1dadbae9f0212b039cb808f540eb2b40de4d505a2c32341 +48c5194f93244807df553b733a5162087e0bacf89509919ac746941cff75d1b4 +48d3648f72b946ebe7b856c6eb9449239a5445ecdf01951529e678450b755129 +48d55fd33b073c428df3cf5039b7b4318896522098a30ab3a47d9c4a9b0d5a12 +48d67257f8bc6c584b9aaefd1fe33f13fb4ec0c179a6f389e75ac45454db17e9 +48eaec9df8ef440953cc0e14c4214195157cf5f8677aa79c525a2b1e86e387f6 +48f2a692457a9bfb81906288c87004a4f86b1082086351dc725e9bbac6b50fe3 +48f35eb4050024c99ab49467dac5a8718561648a4faf11abcb080825a9e73e6e +48fce1c2c22b03eec33a1e1dd619dd9040c26bb44b5fca597a29f64ce812436c +48fcf2ad0e63824b4f2f79ae7d75b081fd6cea89eb4022dcb69c750e2ba9f436 +490136ae73aaaa45f42f174533433f441e755f2da59c85f3d9c3bc7439fd5f71 +4901804b7de96449affef5ddad4125fb726801e6557fed6a7264399420b48b53 +49029546820946f907aa9f6d5a49469869e0bff30ce33b3a2d42cd9bbeb34a94 +4909a160aded877b723cede972d447e0b4c1cbdd691e6e78671480f7831bcb4c +490a030c28c513bbd13773a3fd4f3b148ddcc0cf9aea92ce6d355214495ed7a9 +490dfce57625a8f81c071f16f0172cd4c6e548201621afc782db76e42e59ab49 +490fda7e7f5aa43bf61e74d3524cabc93cac6eecb302b445966d4ec43589d634 +491caf394c9dd1e6692f0f3edf19d06782644c17ce837013e2b1c6a73a0d7e1c +491cd7b59d8d34b696b82f5653eb23f88e520060f7fc4b36a9b7cad4a2422735 +49249e1b5a9dfaa8c4d78f55b53a1788f5c8677ec03c23496a2a85ef509e08b4 +4928ebb9cdc882a31c2104b1c6bb478e31bc0787ce86f68f069fb3ab223b271e +492d1a8083d6e962059dfd6602ef29df03419de0fa902ff40e017b5a4cc213dd +493335fbbcd4c0cdd6767e42117adbddc05599001b0d281aa38a259d33f18dc2 +4935ca7b53ab417e8a2974b2bce6c0e66a8ff64a3a2fc29b5797fe9ec2c513d7 +4938938c1074502a896d0f635742272e4107c16c3d786e25094edc863b85e386 +494532b829a0074084cc58ecb04ad5625fe26eabd5df8f74e844a28be791b44c +494fa687fba340fd4a9bc663c0bc913d2b4c385ce3b81c9d887038287568f00b +495465b0c1ddfc7f5cb301c5319c598032fde5862d8287577618e8423973e318 +4959e6b6ec0a5f37895cf673f1126d65f78e7f2661b1f19c5c25bd8703dac79a +495e4d70b38018ac8ffdda4cfe1308931f257308672c58c392d341467d8e187c +496a7b86cc3b90a15489544ab94ad8399a731eb95bc4ee1691a70fbc68e7f254 +4970606230b5993ee5d38b841ac5fb15c9b79f5ff032eb00e49530b6b6b65fb9 +4979dc890ac7d635d93a289fd9ec8c060e2d133cbd061f2fd65c61c596f61c65 +49845547924097c80040c95996d0c04a5a6c0f9625ce4c008fc29b3d416660aa +498a8fb68f2dad29ff589913a8e590629513c46ba356201b3d1acc38e5ed3e91 +499355ba1619bfd75ea2bffeb56a6870b87a8dee419cc85e65b6d016eac925b7 +4998e965f74f87c975bbe98a0e81921d75b2fd2186876fa6c2cb120e12cfc657 +499e358f4b4763d1e804f49d5068995fe643f5d72a330152d30a90fe732ab635 +49b448185228021eb025d2778c1b19131c8306f955afe8f53afb5f1575607806 +49b4ef15a0e5a4e92f6a88b9c98a90329339a8c32caefda5175ba8731e6649b8 +49bcc2b7f5dfac0e10e5266b9d28922f4860e6474dfe3ca0295ebc363b6ad8f5 +49c022f5f3250ced0f29b08306d84ff894edca8e6060a63d4e3205ffc4190bd2 +49c07ce75639eeb3ae43c16f75f143bc526bb4a4269a52aaff3a20af90426f02 +49c5265b56422a0861d5b441500dcc1f41bd50591d8a05ee3e36e5ecda7a11d5 +49d279281eced61c4cba30b5c29ab48a68d7ba188f535d320016617413cf5b23 +49d46a79767a822d35420c012aa5e8ef2b0c0e35c5e2fe5dbcc7de32a89fb59e +49d5924a76d13a0ec6de6771da2346ccfbc3386ac65445db4b334e9befa17489 +49e293313d7f9d70f02b9ce1d269b60596bdc9414280c5eafccf0fd15c7c3bad +49eb96eec947916fe81dc5581dbd4ef93aee7a5c2ddef2d6de5b07d4dcb159e0 +49fa2d2ab6d1f2b9b72fff6094b9a5557c2277b6e7a8d10a5a33f02179a0d9e5 +49fbc2d2cc21b4489e132a4db6c3b8f70f6ef82b38962a49d3872da54b5f9ed9 +4a00ce4c091e004706d4088132f51c31a3ad9399757b8a59483812ca08904f60 +4a014be87d1399877ada3f300bd4e4684da3d54971853d64a9fa841ec6ec5203 +4a01ec75fadae73489f217c3177e549e99ba9f604bbc0483ed4ca8efa97031f3 +4a04ad76479afa26833ddea6b0d08935ed54cd6163225102f4f5ce3a88a76515 +4a0f237be11fb725cfff174b2f74bb0a95ddc92f3f32fa63aa9e56e9912c99cc +4a15152946ef31502b0d4740666e3c22dcc367f11865f07146e570d04495827f +4a17bede49066dd1c0374d6563b4914979d44d9940200bb1c0fecfc71a2e2263 +4a236b979007306f8a38e1bccc0f229d0b5697f77f5315ae3de248cfaf1674c4 +4a278b295230a108d9e787dbda06bde09ef89efb80ec4bd9606e1c95af09f1cd +4a28a8bb02cc641bee4a41a2e6c4cf9dbd17825d7e9c31bc6bcb55c1c47af963 +4a2f015e780918462ad3adaaf5dab69c516a98ff3978964d6da8d9a606d5b47a +4a37991514985fbb2242bcabdd85d81976ab945e0982df706ee9a19ef4a4e47c +4a3cdb022efe52fe9900f2d34d96aef536cbd3d700c4b536be84cecbd45e961f +4a43e1fd889378494e89e36fe1aaed4aeb3c0ffc077198bccf6639ed0cb2f4ab +4a537cd636a5ac235390fa2c23ae1bfaa8913092f8fa76f9dd24364135ed945c +4a546bb8d4f06ce27a2d156e035b776a01149854023332c698dea4b09ddce582 +4a5a64499ef8c004a527b0557cc8457fe5a8d16317e3d735ab6a2998cb5009c5 +4a67d5ddd0d916e02f99e759a79fc527c293c8c98eb1d01a60ed4f193d869788 +4a6a26647101346bd4a67efd273653ca6639286ddcd942dff08a4b09c8a57e9a +4a6e4f943d577eef0dbfd351551a5993e7c3c42560054a18f06b065d8a72e152 +4a7597bf34e57c375097b086c40b59e8e615334b8255b882e157d53e8c4efd09 +4a7dbbca75689c33f5ce643b743a1eb9d4c7c6741978ae1167fdd75bc9139ca9 +4a8410ac0153f94af52e382808b79844bbf63f6d613e0ae7b2c12594b8307e8a +4a84f9f1fa7c6949fdd88375a2129c0811b4f1cdabbef178d352e37cb8c12ab5 +4a9ac4f99cac0767edc268285e371c53d4874aab2a99fac2cdb85f7161d92e1e +4aa73278027554e61798aefc361ce10116d8e8bab6fdb7e987424dfa04fa8280 +4aabfce0733b78672d1fef1252392a17e036abe946ff2238612e55142aee5e4d +4ab35ecccac97bd877eda1d33b31a818144e9cd95cfaac622fe4b4d0e734b190 +4ab8e77c810dff753ac04875d8d26837fd1335eaf756962b403629a0dcb3ba8f +4aba47478cd67b29430eb01162ab71054e24766855fbc85a1cccef878259dd88 +4ada01e9ea879f02ab54f3f0529066c8bf779d97bd5a3bd3c255b1ea297db152 +4adf11e3deec3c75a826962c7c2bf83c86b42f5a18bfaf574cb7b96ec35b3fba +4aee1253a238ba42632f2e4b5d86adf42c2a2395551aa45036b902a54de5aa66 +4aef8e3fb3cd9750628add6d4f693875075bfe3d5585470f521487c8a42f9686 +4af796bcdc2bee8f3f45d19cadf069f4874d10864788ffead2ed1c8ad6185596 +4afff8313270a4f9e0a7759582b78ae193484c735a5dec262e55a3e5b83578b8 +4b05c98eec1b6a64401318cb60b8e4cf4967beab61bcda503246d1a989e9aa36 +4b08dc3f2e83b462247ae5abc25161b03131df551376369692e01c4c7834aa9d +4b0b104bc3783b6bc064b7ad034468c531fcbf44a486435eb03cc2425f4f8eb4 +4b0cf312346abc0f97eb8e68765d413dafcf35b9788a7899c6d89fc742208ca5 +4b10cc85a42d1a5574cea4edba73c352bf0925f3ce6dcf98030819664a3ee597 +4b12269ca81c54e45ba172cde16a5f98300a2ec03136cdd9cc87a7b64ab3d403 +4b12506cf01380c9a988be4ce1fa10ace829ef988a11ad0aacffc517e31fe65d +4b12fa031366116610ccadda864eb4806cb369ceb99eb964e809ad08c9db657c +4b1b2e98294f6bed9c4607da58dcde4d1fb3716bc50e9ffa59e4f2cd57c1b51e +4b1fc4e1160ec91b6fb0879501018185a01426a2fc897729a54c6c79f812e115 +4b277c5d03126ef3542056edbeb9625c9b71abf70d51ff1417565b3361b2e2e6 +4b28bc7cede1fe5f2a82806a88846f3036f7c9202b11df5f17b44b312299169c +4b2ca9d579aa0f19b07d2af2f5ae4f11baaec168b145af21227834f473fc403b +4b409e6e875ad21c0cfe900dbb92657c716a78192155ff589c6ab995b80b5531 +4b46b7931ab289943933fedb78edccce947e6a315a47fb7222999a1c1a49809f +4b4ce64cbc7bbcfb4256806a11a35462622b2b78aebc88ba09d406f214514aa5 +4b53ec1fb0fdfd7112a68e1f8c2e335f483fd97c432c61045977dfbfc94d6e68 +4b67b476b8f277c9a4f5f42a329463d8a089bc72b30a767944f6782517e73874 +4b791ca53c2a2beed2c2593fd32169151854f3619b70f57c9d3e1a9bded9223a +4b87ee9a2d42d6ed5e033f14031622010d8f090a82a47f9b42ca9a579fdb132f +4b8bad16c23ee95008fe66c3277779ac023bf174a90b048430f8bf0239aa10dd +4b8d38d95db7fe0659db8c5e9b8a304af0c59510b08c004b9058ad31c891142c +4b9afbd696c76fc0ca79ac7c91f202428a63373ab698ba8f3dbac606c1aa15f4 +4b9cba0854124098292cdc89fcbb235449502a3bbcacd281a3f6775735a84db1 +4ba66992d6cd030c9592a006b288a0f47f295d10dd7cd4f0d4c1851eef3b2d64 +4bbb5262acdb19ac8ffec198365dd52e5ff91374f4da14aeb663163da03fb6ea +4bc3bc23768d36825046218e3ce4638f2410e6f4a850e838aece84deb385c7b4 +4bc5baf7bb609869713aa38ac204128482fa3b9549db10129c80aafa85ea431b +4bca62cb5e5d91ff86c7ac7336b879b6eca31ae25daec951fcfbd55b2dd22693 +4bcefd48bae6b64c36e6c4970ff914215bed86fb4593fb767509f6980aecc10c +4bd7ae2a1f91fbaad93177617376e03c6e73ac0feed0b9312001ec565c336753 +4bdac644e5ffb0a3bd7e9874d406ee60717a9b7e6d799fd14f7fd1dd5ff5250f +4be66b1fa0d2f2eb3ace6a5842d11169c72ad1dc3704ca13033adb8f76fd28ee +4bf4157732a7848bfd7a646dc658fe3d86169d3a64052bb554c4e9f4b0f632c0 +4bf81a039d17bb192b0ee9ca2ebf2ecbcdce3bcbe4d0d34e4ed7959fce87d3a1 +4bfceb22ef5f40744316327e8cce314c76a1a0a49701625a5ad2f4e279a1349f +4bfd4e7884474bf6b775d42de6d78ab9a21ef5b09ccdd6485c44573c9fed5a8a +4c0147a24d040ce905f73bf3c198e4fdecd4eaba062e4b7bbf2ef1686bb90ad1 +4c046ad72de1cb398220f2352afdf8f3343b48c22762c711d509f13a9eb65f03 +4c17636072cb8a849cde8907af254894dab88cf49a1429911c8aec420c22ecb1 +4c200190145976363b19d82a4bbfbebe6a3928d469065c5e1502787409c23604 +4c213180d2848413f5a57ceb8339d5703a888d372ff489e004b1d62689900a6a +4c2bac35fb3a8aea681a879af141e44d3cfc22254ffe62d5ede0862ae327efa4 +4c2d0e1fd940f27e7e26eb027fe1f5a162dcfe5bb423b04251482f91ed2b20d9 +4c39d4407e3ead526fac40ea8eaf2c1881b40f44be2cf21b365057d7023c635a +4c3cea49bedc10d49952fed8e00f1fc0933515bf3ce841bae6703be1a14e03d5 +4c3eb182606e6460542c8ab6d34557e967aca67294283eaa6e0a0fefd1356927 +4c41289141bdfa1c38fa93e16c801b542192613e61a28a96059734118e215a0b +4c46cc36811a8bcaa3627dca544f9f19a390d4eb0227a7812a07957f4f52e02c +4c4be838dc60a8a97a753d9e9160554ff5550f6ab8d7759537dfb69c0c391779 +4c52ec0ae805a749b3615b1aa9b054fcfc47830a027cde104ea76df35528c612 +4c60b6f973805dbd5a66e8d78593c6751580b88f426f75815eea4ea83b5deaff +4c620a880fff5d6a223b0209a43164990b944bf2d09a865153390bce318baad1 +4c6d6c9c8e83d29816df4d50aa97dfe8224cd39095850591d20c84e879253b81 +4c709e19469cd5367755ba4dd5f074899c8d7bd9743355ee7c839dffe399e2dd +4c71b1a8f3d3ca6f4afefa729c4d862a456438e3c0ebaf94186284c56a718ebc +4c79a3adad16320bca755ba0da85df70c422dc2a13b11e2e2c3c54582a9cb924 +4c82ca9ba44a391f7ab5d8f689541357ec07d8acc7367843118a648f1cf9c9e5 +4c88a46939708f6b53cbc2ad07e98a3db2861ae04de9a984bf915174ebd02e42 +4c88acd0dc0d49a7323732b88906045812948e3691e42adb628ed37b76811879 +4c91a38fc60ad5ea32eae1ec9139eb05c8f8109c0bd1beb5b9dbd24e55be7fb2 +4c93fae636d0f13c612aa668db79c747ce36f020cfd5fea8b7abcb50ad767385 +4c9561bcd3884b3cdb52cf70e4d907df4399ef69db0631eed6c1b0e69ef75d08 +4c9ec5abffc458f60d697cf48faa440f4153acf29e679feae957665264091d29 +4ca4c0dbaa2f7832de12d42ca358e332904142c4e725f4962e3732432c7b2276 +4cac2ed879eea9896d4b3fbd9234186d5e15ba54aa064e80b138153f28d107e9 +4cadcb9d4638e6aae3e5f59bb4bfaef1e433a2f56edbf90dce1a05bb2575c317 +4cb25053f1e079a406aee1fa0e5fa41a037be305e529fc7c10aa76d35249c44c +4cb59bb67251ca88cb6aa554fc88748ece22ad200b7cd57b437d340e034e5811 +4cb66fe2d205a727b13da445a17e9134c35e77f3a6776b719e9f1d89f318e142 +4cbaae3e203c0fb0d820bd36a8a92f2c2becfa49909affebe32b04a07a755598 +4cbc05d39236fe07c9ef3cab562361d07b9f22177257fd242f544b386c860c0d +4cbce6c87c151b0cc4c1a4a04689e208260cf5e031e118ef74b2194529df0b76 +4ccc2cd2dc4c27aeb6b3d2a870180796ec85dbf14ddca949be09de62b7396d0e +4cd5ee40efa6bbaf7a70bcb7f897ae8887b791e171ab8712c74c1cbbf46eafd7 +4cd9341541367b042728b0b31c1027042f9d9280c349c65e672e8a7751b68cd7 +4cda1e13048c5b252223cb53ec05032fee89cbad59fda0529c89b98168650bdd +4cedff17fa5c0c3dfacc5946f841774ecba01420bf233a19d6bb8add4bdd7402 +4d10a4bef54175a13eaa2cb9c22d4a895417a5fc040ae0a52dc5783307bfc092 +4d1a1a326349070b9cebcf4be13a609aa94cbc69c403200ffe1e473005bb432e +4d1b853684678e963475f7f7cf04e36e9e201bb1514a6960a837b3d9a933f046 +4d1d7162e1daab06b519d6afd55908dc2bb5c0ff6cb4e02fac3ed33064cf219d +4d1fa9ecd2b2b171fa25f0af68f1703bd6f8307e0e9fcac8935f8076485df2a9 +4d21d0048c3cdfd2ae05bf3ee22c6b64d6aef3fdc046d14a9d99b20809387a76 +4d24490aae47efbd713c1df36cfb5ec2ea566be6ad164e77952bd4ba71a21f07 +4d259bde235f58609548fd985e50402f61dce535f371a44bdcb9f7a39189c45b +4d259d4db27211cd0ef730fdaaae39b50734b38702290af2e42bd38185ee2cd1 +4d2613e7bf593827281aa684f6ce4f7533487db17d5e31f045a10611b372940c +4d27f4a59049138dcb4f1ade0fa89887679f5ae8c3c295e492694e5079508e63 +4d2ab3944c02654cb796e2e7ccfbaf7b76cb5869306d493a81c8a6abd9b42446 +4d2ce683aa18410c56cb5dc052a8613eb7dbefa3e6fcfb6f32d72453d16064e4 +4d3ef3a9e8928b9b150897b58ee5ba7255738e9543ce8f2ae9056985b870b309 +4d4237e293d7e383df7418a7137391c8315f66ded6f83954f1e273cef7dfe6b6 +4d44d8af36ff213bfaacac5f0f9a33c7b4c027455f9ef503c473ab83acb38b2d +4d505d8169b3bd98dd99bd18a1375b91826561442c6c95f9a0d561d7b03c628a +4d52c8b7a92197ae08c02db5192a8a3afb6e9829a799dc4b9e607db0eabdb4d1 +4d54f8b8e6cbcd0346b5b5cfe02dd73cf4055764b40a49661e75a109737fc5ae +4d598c440d0e03508e6a3c97b33f36ae93dff9a1093e6c04daefefc49d07d80e +4d6653af781e057e2ff67d31637f9ae7cce18d0e42282e24bdfcdeb93c667226 +4d66807fc619a9191bf73339614636f3163915e2fc9bc5dbc65a52c4a74c0927 +4d670fae86e2f19c8ca79ca8dcd86f3511cc57521a442c1dd87f6d7522eb26c5 +4d71c2487b3e4f78d3c4b6cc22bbb84be2665aacd1d8190e861f265e10b02638 +4d7873cfb97c1f4042ad3f3ca87aecbe64d5426fae692c78d183cb2161ecb7d7 +4d84b278efabbfb20b17db491d80473560200bde3e6b546d87e3f6684b4c5aa0 +4d85ac1061d6552862e9740cee072368d1134ad43f8c1f4ee068ba569ece5387 +4d87b79b0d31035eed8cf4e95fd1b6625471de3a23b1b39d8b6b3b8f02cfb9bf +4d924b7b96ef28243d0dbe3f486375898016c9dea078af18e833927a7eaa00d3 +4d927227a2ecfa1c845cd25a4c13632d9d4e40f46a8958aa1ba480a239681d02 +4dae8f358dae36bb6614e20fd13558502b22be9fd56e530058792238bdf8c59c +4daece7352560bfc27ceeaea7d08b0183e9c7caf2f63afe41db530cf408e73e9 +4daf4e14553b627121c578ca5015e79b00f8796d158c55f1ce1e0ab5bfb3f6b6 +4dba046a6eeaaf3763d0a3f9d05683b3477cf03ecbdef0a1c4c0a66cbaf54935 +4dbca8c64061cc9bcdae9b6d91272bdfc25f61d206566b4969330a3afa6e38c7 +4dbec363ecaaff9d3683695e889f324233c45bd044a3469943dcd0a1c3cd46d0 +4dc46ca9eee893128212568d4349dfe7d17ec7e4b17ccd6dc4758956d326757d +4dc4bc6deb064afab0c9ae06890456b0d664e973e8ce4546acd3e32b12a0cfeb +4dcae2d692cbd30ba38df0a8057015765255c27b012309c6856a473c7d640387 +4dd30c16bd3203bc53945b9153d0259174a63ea2b740ff045a2db387e9c9496f +4dda357f120fbc9dadd85468c0ee122b24086616f3b81d945d0c0834bb3dad9a +4dea2e21c59409f8d500a295f4d57dfbbe222364f036533a312ef4b266a99325 +4df3257239a067b67d8fa3ef05ec60df757544dd457e4e88b3932c268e759f4b +4df7b592f81368b2427d0842221f18ec4e76d6557872f229ceb8d398ba6d4774 +4df8d5d16503ed1fae58c3e0ff46c85523a08184e93b191317ee66d62b43d688 +4e10a31c6790a254ba44627728af778053984bf40b340de64238d3f45163a662 +4e1957a1b830940900439586c14437ee5b56df068392f6a60ac4b59cfc38dffd +4e25573d06c8dcc615977699159dd2109bb80b87ff56a9852b5963eb56cc17bf +4e28f0b1b31daa00166deb7c7ef33f32d5dae1bc08cc2115d7bdcac9d6faf4de +4e346ffc03ce3e47109409d5c61ee6fbf98e560fe5753186beacf6d4d91fc350 +4e37e043ed0c15fe88c1285fd4404c71e32c198dfeffbc914806087566bdbda4 +4e3c7cc9a9333749dfd02a312915955b71d767da98592676de6bef907e79b766 +4e5a5a99b58cde7bd651b983f3357f107ccb5334e7ec0ebf67250c80a0878c5a +4e5cec1fea6ae2253feaa28532250ab47459dded6d710eb2deb43246bbd710c9 +4e60f8e6111c480f9a13ea8f7bee0a59de7539cffaeaae40e4614d5031f8de11 +4e6419939c76ecd6248704662929510429b011293ecd9cec6b2dd083e02773ad +4e6cdbf0b9798c05b9bfe09e343e5c67124c5f3f6fc3f043b89ef5dc51cd8749 +4e70bbb598d63848f189df54dc21d61e1960e5be1400dd441ec56bbcfd39d0d9 +4e79b10956a7e28a18e6592072ef1ed73934bacaf62616d24de06691c21212e6 +4e8368eabc578d2ad150f46c19c89b5866c31809a02511281a11f554bafc4344 +4e8886bcbb25b7687243ce07cf7e5c856c0c7335127b2db646ac409b7c40b843 +4e8c9a0bfdccc347da87318a6a91d05c6b16e45eb66754e71cf849d8a316e842 +4e9b057adb8a8b5344ecf26daa5724fc9d2cabdd08288aaa433fb8ea3804daf1 +4ea2fff28d8d132eb037291677ffed652eb729e197a9147b61e578031d4909de +4ea5a3b180343259f9279cc81dd371e65c734d0d4b8b98ec8c352e39c5b7fa40 +4ea8280e461d032f7b726dda8f3b7896702fb35f71dfb5011c5f2c99c8164a25 +4eae6412c7b3196940b6f9333572b10b567be1604cbe6f474f15a485dd548387 +4eb546424d04712cc72da26628b9bb6bc230518815bdf75424f41133e1da8aa5 +4eb7e3c802a2fccc8683b4f25d81fe18db04ca7ca964b64d05f1fa8962adaeea +4eb8b2cbe89f46e9f828603e59d18e7a17a355ebae2a4edb0cef6cd5f7a05afb +4eb948fddfbc38e87168caa168aad3274e3cf91aaea5b4ae708ffa1716058721 +4ecf8f6ccb7d8f8d45f795494cbce8d70ad54104a47a6a2aad7322c7bf021268 +4ed2ddf4c5b00013da07c8c757055a179b709bd2e841e3235fcc7fa4f3997763 +4ee407186e96c482ff2154cf4a91cff1dbdae741ba17b6de19def8cc089f3b93 +4ee894264e9e093b3cc22bad958e8c92f0df1c5378b469d23d042112247aad7d +4f0385dbd35f49e5862c02727591ddd179d0f706759ee8f0da20c6fab85d0ab1 +4f09be0e430fe5f4ca99d9dab6cd4d59aa0181b6894800dd1d417778b6995ab5 +4f0d1d878c5cd060db1dbfe72eef406ee41212339e1b0516a4792460f64a7c3d +4f360da5522f8a20f6baa955fd8a867f204bfa40844fedf301776db30935a092 +4f37e1f3891b5687a44956591c74c24357e51d0d5dda9aa2c496f43f825f18f3 +4f38814011f58be79f318e67149b5e878a6c1f48080a164503d3c8d5263e9f69 +4f39d34836f6cf682db9de1d2faacd47a5a8d707098077cc18b88abdd710ef92 +4f439845cb0bb5ac333f4d36deb516cc149727bf2e737af077d0c1df0aa1712b +4f4bd9e1560dc047eb6bda318008a94422b1f39656b1eeafee56742a0d8ca18b +4f5355c6237f14aa4912f083ed99d4b2d3019f1241f94d23bcdd4fe01479945b +4f5d2b9ed6f7c18869299d12bf8e4c9a084fc9630fadee44d2d95caa688bf47a +4f62c6e7b485606aa7aebae11e4d5ebb3120a7713418a6544cc76e80ba112fb0 +4f68292c9f904f674595f835f58e15feabe19f241942a3d7a4076c5e21e19f96 +4f6a809428033ad3570b679b41e93d3ca25238b47c663d1761ad6003a51c3a0e +4f7a6ed551a0884af3a262eb21179a096f2051710dda4165da4d85b16edf6dda +4f7e8563e8314ba6bcf365ad4eea34ee48d036fb7530a33ba36430ce2de871c8 +4f8cd89716487a37d78c8203714b2b3e3519f3e75c9c6fb84b066300835aaeff +4f8e1b483857d6121981775c72c55a1f9f34ba7408dd1c57603f879f0d891a75 +4fa4a689a05e80baa54184d807d65c77f6a4481e71604c9ef6b2629ffe5a8648 +4fa5def82fc5f39de878e0150452c37727bb0629bd1741f804d5471f5d6558fd +4fa67b7d0b3c5160e6ad61e2a4fedaff349dfe65288a83071636e2d35790f454 +4fa9f1e697a13b19d2c3f373fe22336c5a504fa16d84a8dc26e52dd8ff646fdf +4fbf9bb841755bec933a3ac1a93af5da31f38c76b7d372dc139f5345fd8ffc5f +4fc4ea85a29c715d2d580a1e791f375b144893435d2025415f6ab95bc8afb8b1 +4fd258eb072c51da78a80fb5c41b3d25ce5c35e25a32ad64a8503688bb12397a +4fd89794b17ff32250b1917dd9a48cf3767dce250fddc0d1f7e166de4197a77d +4fda3ce292f4edcc8ec3198f839c28ca024ed5d05e14113091caa1eaefdeab8f +4fdfb562ad816975c0f9b7c2da4b6fa5223281b0f9c71ef164221f83a4b01fcb +4ff8394cbfefb8522496e1ef0b5e4dc3bdae5e4694a16fe52eb8f85f173919e0 +4ff91216466616754d19b69a049563b3cebd747bc6b6d9ad0a1bc8df8227d5fe +4ffb894a1e9ea1b63ee51695474520bccd2ebfbb957e404f26283e4da29d846a +4ffc9c29cc26a3cd3e9cc8050a0242165468acd9d91fd3165d3132a9a979f59f +4ffd479f629ac648818411ef62a0f09c7954c644bf7ebcbcf817a6bd00112153 +4ffd73c264706f17f6d37e9a5c6910c24a90c75a783044e6a9ce19597f7999e8 +50108df3ed32b14166f6d48e1ea8a7780f372c33a13ca609a8187eb01543df6c +501a49e2ca50412bc1950e40387c5d3204cc635505aa3a235df40ba623e911a8 +5028b3ebd25da6897fddc48039c035131ca43aad9dee1221c4159506d7a37a96 +50339a1027fc5a2ed68fcb75b99aefb374293b7a872ea2847034a5851691a8f2 +503600e8f553e5c863154c1b7f76e65a2482c3f7deddec4edd9b4a4111e53937 +50362d3ac50954a051a00d628440f8d5f7f2c5acf4c9bbcd5264d6324afc8442 +503b61708bf22ae8504f0a9defb4b5a47c4961097a385c1876a7ef5187204be8 +503f61537e7fc2cc3079e0ec8b79340b1579786d226e7c5a9c8023d82f2fb9e4 +504444ee59b42f6ca5cdd3a3077c2ae48e4ecfccc4240044ddd8aae8fb81433d +5047c628be3cdcb2681fb18c56a781156a3271bf22c86fc9063d6ac7fd665cb5 +5055a3b77f5c21de450523bf745c7e812a817b52fc747cbca29fbc1f1c218d41 +505ab3e98a0c37c33a1cb65249276e68daa0066a823d3fdfa03355a0517fbf8e +505ddbaad42a77f5444ab0fd67813e5dbfa8f2e8c97c57db3268892705641523 +5068b3ddbe1900f62ba172b162de0b8e062ef030bab762bf36bfcb720c07dfb2 +506c5e37c81d21904b72528f810085e3f07e41692183abcd80ba064139feb225 +506f7cc54b0050b75e85945fd0b1a9e10937a5245a0c90e80f7f5f761ca0dc18 +507a4fbe9595b4dc235cee4defaca7d4f9a8da72a6b5ddca3e50e7254ad1208c +508c2596e6dffd9d5c364f7cfcae01a277620f0a3ff219a7e049bc8d36d01f41 +50ad8f622d73f13cc175811d6555f3d8d464bf0f64bb7796b20b695d3a01c0f0 +50b5e8d3c3e7e7d1da1b3aefc1d38567cb79b2c16440e80a5b95b35178a7b9ef +50c2ce22d16c9593f2d2981c20d82d46610d11c9a37dcd73cef65b3a5ab056a9 +50cae0b5b828aca9a3aa2f4bcff3cd2fc17fb09a24a4087ccd00d2433ce9a8ed +50cd0cbbccf09935a22232d0f145f689fc08faaf81d73c4daffe122aaa2609fb +50d002b05287dd63a0dc1e40d8b07dc51c6aeacf4d9088df23340863b0edc255 +50da1bc9a57218a664594c395cf7d75b7307f3e218bececb92320c2a8f32fbad +50e2bbce7c47534f28c0bd5bbad371b404518084f872af61de2019d6eedccfa0 +50e64d6bccbdbe6c732ad35ce6bfddce5f68d763d96361a97e91f3ab96f1919f +50eed73f3d17f6a55ff70758d7d06b981d988f97dc6ba539bd8fc35fb67a48f0 +50f119b45e2d3ef82a055e0695952a16dc63e56d0c11ce1b024c2d12d4cade1d +50f22bb4c9be992bf8855f5a8ec38b2c2b1caa6d15f22981bfe41bcc2ca364fb +50fc9ca3470b56f0250e5292d23570da178bee49e91c75ac2398d6cbc23e1a23 +50fdbd644eb241f29ec23f8596ac6e498939767ef4396441f9632b1e56397364 +510aaff733845d09d8e906ebcce3bebe416c0dc4e05ab59a1f5fffe5dfd93d37 +510e10f595bc131deb52b05ffa87350bafc8a87e25c80dfd60fcfb44830403c8 +511a45a865cbd4ab674f1ed46aba2be85177ae9a88ca9418466c14081a5b2ce9 +51375ebd641ed0390652772e436be7d0cd2ebe2d7b9933248685a4fb7485ee35 +51401010b73e63590bb2d683dd2d010569a4b884f532f6e0ad8afda4d069f11c +51427d69ebc4a0973d31546ec84518f0dd1109ab689869b9abf7a137ffd26879 +51465d8c9310069efb36ee596a97f05dc86a272e7fb97636340fb99ea0f65e30 +514baa6c0f522de2998c2f0ccef4da2293a76a5193d73c5c84cb89b488f8a347 +5150f67683f99b020732eb983b79a6b2e91cc5c98b04d64a66b22272d4ef7331 +5151e63adf2e08bd6903f9a6e67fd4297f64f687efb9c98ca467b11d9221ff80 +5152e716b48511d23e1ff7bdd054f0cfea34aff49d90be175c1a42a1e844114e +515a839423dbbed01b79889d904849182aa7103e7155d33a0916237d55cb7a38 +515b27c3e2fd6f19f807fa68f4b818b89a3a27a3ab439e100d2e68a0ef9a1ccd +515ce320ba99f1b868f3a0ff5279169c5bef7ce7ca11313d081a2d7ff43aec2d +5163e242cc5eaf06e79eb3d607d17d3f514a6d5f9a25ecaf547f1d24826f957c +5168df1442c1f6441e0c0010df6449c051124d62a8119cd4511e7f1b7985894b +5171c0438c87a9f944207005055b078e6d3783961545f28bbd30499cf4e9f7ae +518a7877b4c1f772c968b9279aaacebd4985a46da80699465bbb06f738713e90 +518c83ec88293011548f25aa47b30f8fb665476733eae9740fe17a8049473b70 +51950f518aa40143660d2870df1e40f12719789f92621fbf1fe4276ca82f3dd6 +51a0b8830472a47b67d9331af7e2140b637dc9422aa5d2eb77040c032ae3859a +51a8f5fb9c21cccef48fad422d3ac84fbf9855acbbc23eb6690857f16d85c34d +51ae6c24dd81b5afec8f1583ce5bfaf17456762c1ab1bae4871f6af0e20b3d9a +51af2ce31e1b5df7265b9601b76be28b1e647088bba686782ac58c0a4376a9f0 +51b5d2db1006349cef18e7f9c9b67ada5c7b9d95e13622b708e2a90b8c503db2 +51b6ab22264b5598edf8178db30715902b8f7f73fa3075485d78d8b11822dd42 +51b86e04be91a1334f2a0a94775b30e379dc1393eb4a1e96b5b5ac8c29566675 +51c0a302bacc869068fbf69e594e15247cf28f09abfc27a89997678b2d348294 +51cb19f6534304e8c0ac82c600b95954146bd40067b96d66067c07a07dc54a45 +51d783a301233cf0fc1bdcf74b276b9f7ca5fa64339af96db555c16a66c9ae9e +51db822476c333f6575d765a34dd0d6aebab1127f38b2842d5e2b17166537cb0 +51dd171bbd38f03261e669db6cf6c54b2c9fb5879ab1ec8bac345ca8460218dc +51ebbd53c2422db150104e1a2cfb1433e4105f8da9ca09084725f34da145b84b +51f646081861cebd1ee6c86ccf106d4c980ba0123f70795ab94ecc58327c99c8 +51fbd570e6ded203609d39c406419316f866e28662e0deb94f278ad89ef0d35e +52049553ec3a027726a83f650c50f904dc60e3f1d13e03d1627010c9e13ca51b +52050036f1748d7861b29a45e5bf06c227ddc55c03d3789c256ef9b491b4aa00 +521291ef1c11e2fd5bc9ae5a3cf90b122aa4015c19bbe1757201e682a3bc4384 +5214b68e8916c594af3be673084c4d656f8d45a73d7e598b9f7db55746c200bb +5217bd83dcaad57e16598f7467413b872db10b9c022db318fb18a20ebb093867 +521eefc5d4422e973ddcc870b72721b687f4f8786e9c1a6673b4ae5fb4df1794 +5221fb37603a47febc416976dd7efe88f247c4c87584dbf0cc5ab28ea0a5666f +522286323953b0ef12ce853d37b3bead114d61246e85b09e3e57f616cff8b502 +5225e1dedbd7d54bacfcf7959ba5ba09755e5774946eb4ad202af53aea2e18f3 +5225fabc3a6487ab3a1d49a768b59b041e4bf957581c13f2beaf52d30bae988e +5227f9da500290518b5e17fef8873447769c33ab111a581702ba5bfbd890084c +522a652e1e16b933c74395ff282166c703e7b061acdb6e3584631b3bb696ecd7 +522d2816b53fcb2c1594da70f9d053e4d330765097d5aa780443c57dfa4a7e9a +5242fac048f195052bbe63ea837ff0b5d524958190c7bf0801670861e628a549 +52435f96284473c5de798a0267498f5d1a995a51759bc967a3f8e1bb3fde6ae6 +5246738da1bc23e7dfda91539321cee8050c647165ab01a9277d2c5904abde41 +5248e74d0f9326449019c9d66e7f331558a996a564462d58339052f1902a5dbd +524b45bee2a8bcbfca2e5f94061fca9b305be5114ac98b6bf1a15f756545b315 +524d8a37e08f6e67881445f37ca404ef73f28644307518559c550b9680b1e670 +5260dd34ec28b5b50ca0f3399028e358acee385abaf63b4d275df102c9ca4ee6 +5262328ebffb0e50af52a2b7d2e1dcaf6d7417d8c8da31e82a0ec8076dd06b0c +5265785e5e7a573c7f5c2705cab49ca94feff144d50519224e4f9812f6cd44f9 +5279b28d2e6584d446837992f027b5653574f5617aae16d7e503b312eb3ca544 +527b65ff207fc182b03103e6c8365192aa3d3723b217e42cb5aded9a931f6ecf +528104d687f45d33a6e06fbeac4bb89ea4e9f5d73088bf6d4f5c1e17e60f54c1 +52968819482f60d3ecf74a2fc002ccf4cc898bfd91e5a3275c3155a0fe0f98f6 +529b54f41a65c2ad4660b39576b8d282ce08897d271f06a67fc85596584aa354 +52afc9cce9d3e99828f49053a8b2831e518f6f83aa162d881a8f31a9d714bff2 +52b2bf9da1951e085f945fe5858e4d8f612919fd3bec6560c3553b4ee18a6943 +52ba24bcb35fddaa18766ff046ee950dc364d26998f4042b31910fe58b100bd5 +52bbac7f86a748a9b4efa891a494d9d0b970f97e060056f252695293d353909f +52d42e569087d77559a855f1460c01d62b3e22a523a76fa233f05c8963c72f16 +52d8a4b2be67478f63370680bd828e49c675152cf70fa89d053084585d88c0be +52f463a3ad4dc9478e7298ad19130398f01cfa109dc4b11eb6243a5ddfe3ee35 +52fbef73b4f3c9abc0052d47f28a6c634461ef184e7ca6548ce319fa7dacfccf +52fc2be2d9affd3d245d47f64cea3034fe7a54306c092f4db6b3aecfa2ec1c12 +5300747b3147f90a60cc4d7cff7f01311de737fbd0f8c722b8957c0b120d0a32 +530d4183dc0e43bb102c467abaca564883f1de0b546d11ccc9bf955d1c7cc0d9 +530e15fa1718530b00bb17a63eb0fc3dd82d491bfcb90e952ed8767b5f69ba32 +531a8e890933de8a4091672a09e1d8877fbc0cc76b5d0e4737e2ca3a2bc1de7a +531e78796d4a6095e08d1acaa7d543f8f743364d7a688da18a632b17f6c0d8a3 +5321265dd2537208bb8747cef88326bfb7fc3ece0677b262d05a34fea9ec53fb +532c3f18f72a059dc45684520ac6defbc04aab26f48fe9d956d7b2dcdedb8115 +53377577c4dc081f5a9fd1ca1393042ae66639eeeda25bc880d49ff242b0493c +533b9a0523423326cb537b225964c07f31a30a6fc845eff54d4f17b63f33f19f +533d1ed5a2060501f3787c52c0be54b6e47d7e7b7753aabacc0e713443e30f8a +535a0e8c563cd2d65cfb63b7c372265a96326548c68f3bb5991dc28b63bc2b85 +537291bd94c04e9a0b31b086f7bcdfe81d1f15d88fc53e1354444954cbe6aa92 +5383d11e3615a211aee0aeef3b0555a2f7587c74395b6e496536236b63dd31dd +538d0d050a1230db6707e70a54b3f0a7f26d937779c8660580510f8ccf7f3ad5 +5394b5ee0c8b2fc1689da58a61db1d246de46ffa9ec642749091248c2acacec0 +53a4d5058fccaae514275845bb108569efe0cf0c52f7d3bdc10e6af6eb67d852 +53aa1029e7f41a66edf7328bc7f8a3a98c167a616bbfab71dd8fc291908908cb +53b4c1536c14a2807f1abb809d836ead60fd629aa0f3f3028e5e9b2d9628b6b5 +53ba97b06b29e5af8dbf01779ab20df0ce3c7d7f9defc9d1469d0244f7b86559 +53c363a2a4638a86ae3abf5938acf5bdea60e345568cfe88bb75f5c0a87e58ac +53cba20466e9e3d719e3abab13fd28d0a1fd1b6d91b1c14a9aebd7abf1eafbe3 +53cd227a92b1e0fefa2e5eeac548fc58c80c34e844b83f60531dc356c7984747 +53d12277d477b69ff1724da158c77e6e3658677904eca2e7b89928bbf30c11a8 +53fc00d14e8c3a0fa45d1b137ad16aeafc6d045ca4f4679be4adb28f4bec0584 +54017d99fdb8e1041e35bc71070501a7173f930bccba4f545994b3906ba59c70 +540b162184b75f720db02ae3eedd4736dbfa1bb6ec7db4a8555e2b7b772f69b5 +540ea0a3c72308995cc79031998e680887abae08ae823d6c687d58be2da7f8a8 +540f101ac5bd9fa93e3c897c5f3ed627de018e43e4145443a830e2e653a643fd +54144604de5814635b8c39902fd24bfc6a03d0373c7bcdcc6fa5a5bca0e51a6d +5416f82686d3036b113d759397731436ee8e2140bee26b6ab725ce8228cbcc7d +541793648e798f1b4d9f43734c5d090ead6447006f868173bee7eee34207aede +542093044e2e8ed2255b1aaa5b3fc9e8489113673117299604ea273d00455f7f +54242edb7c036449938d43629947b4a752e565318bccebf0f8ec4ee790bc389e +543667adc4b76135aa67b6fcb48ece0f34671ae6ce185f91109cb5916541be96 +543d5dd8e65d998166ae357377fdc3f8a7b0922a09b7d3d34b67147965494180 +54429006a8aa91ab4ae12a49298f629366c557798a4a9743540fc451718cb6be +545020c7ccbf1a3438c874a705a1e86374779f845c2ed640726f1e5985c83801 +54505bca67a3b34d279df560f2a15e840fbdb9239cb161952fb7e2e2d2c8ab1f +54507f0b29f0d616772eda42b05b0e2783f83828a84eef14f6c1e0c2f2c2a8e6 +54543c9c2afbba0c3ad4b30f78b365abbe5a641b79f840e0d010540d798aabca +545641231136def75e79e9a7688faaed31c2f01d7adb81a162c71d079560d830 +545729b88c1e19c88caf482b92024385e3877ef7aaae622869687122d6db6b21 +546e7f434e7967ec14c5635c7b5606b5da3bdf4c4976b98f4851006844cf895f +546ff64463585d171bf9e2dbda6121193c3f79ae9d9fba1dfcc43cc829ae7afa +54728a8b4ca8981cc9f36d854b32d6110f4efc209f3401631801e97e29a8e8c1 +5475ca79f8a06f0ac74654d2adee0943ca58e792c122e8f1d72016a6e2d6ff6a +548457c5f7720a0195496039eea67cc85bb250e31d9e131e1b3625726e9fb666 +548dd53fded681422f5bde9b6e126fea72ed47790ee962034287cbf2c05775af +548dfd48247eadccc6cb473f84c7d03ce700f08478c30504a083c96184682b4c +54a3b0db9cc64470b9a8eb30a32b6c8c96c86669de67ca3bc00bacc87b348f55 +54aae8032ca447ea81ed961764c67c63312bd00da834c40af39eaa8b0046b38b +54ae0f3694f9ee7a19f2ffce0c281d8b4ec0a189b71c4b2f08956bb74866f079 +54afdb77f9524b2b459ee2e7665cf85cbe218fc44c6af805222c19905ac53373 +54b74aab26ca14f89cfc96518a240f7be93a238858f710068f6c4b613bd4a0a2 +54bc65cf8ca59eca1f998fc0b0dba8a8c6fdecc510f185c5152bd0a3a602dafc +54beb5b3a0163f68dd0e5c735f008ff43c7c8c3ff44fa6a4d190c9a0aba77dcb +54c0e6fd9ae37974acc13af0f8933590383af87aadf9bf97279eed7795f49558 +54c14aa3c50b3f8870753e937b4ffc00d2baacf0a964be089383f2b64eaa4d98 +54c441e37dba43a7bc8c051c3128fd82310539cefd5f45d19abd9db2d3091e6d +54c7c3eb632cff16851b6ede0173bf4d006bb4d637ec732b25250a4d80a7c589 +54d2a980f54c77407fc220b3ae421eaaf2fc8e55a7407b15916529c8ed0d55e7 +54da3f0b844b0ce69c9f4f804b475ce61b862dc76cf257db413f5f2006178c2b +54de965ec9877f09717619cff6e887f85a76cc648a50e7adf364643e8742bb39 +54e33d30f759fd6518a0fd42af9cdf8961e2a0609920089fb2af8a02ee8c690f +54ebee04a913e7d9d1e731a3dad4903517bdec5e586501c4ab7cbb2374a06d71 +54ed72aa382f1e0859c33c31a96e656959a8ebc444badb0815fb2dbc7b2a9f77 +54ff8cf08f4cd26e6de71bea728419dfbc92bf3ba81bfc17f190163c20cc238f +551444030d364e1d2a64d1c6854caa5f62f683f63bde8f6279e40307eac7f010 +551e83421151db4672138239c2b0930224f64981f77de7081ad90e679bd612f1 +5520be3e5ce39a1b3bc8a29403563edcb707e049c7a92f7ab9865bc94fe51ddb +552eb7b0e1c740e38678bc5e90221debc669cbf6e39c0e0b35e78611eb0b8362 +553264c6b7a4393a96a1eb768ea70bc0e23efb4dec87fc768ed703941494a763 +55547e8ea4bc0a2424a661a7ac9aa6048eacb189fcd31af74485ba9db1e9b402 +5554dec89566d478fa4c7a4f4fdc852337a71088540791b35499c8b32228d92c +5566c26ff9b45f276e5003fcc4b2f448be35993f73c0377d2df07da294660c6f +556dc1bd99dddd552fbe828d719e128e839bf55823aa1d52b0bc5ba7c028d845 +55702a56b53670d10d248baab3518211bce633ff4ab1c48cfe54b08b23792053 +55778eb72c51f1b226e31b9cf485b512fe01164d609e1447d0d053588ec009ef +5580a676f7ceb6042398d030754025910bc4308ce46026f3fec11013d08fcd70 +55851a0906d31bd77c30180434c8a942c6e8ee56a16b76a66f5137d8e233f77e +55916854e256b14c5389fb25abc2c15dc33c40ffe5826334cb78e06f2e21daf5 +559629e03d980925803d35a2f409c3afb45d2f05c75820ee2d3767ded8102037 +559c732f5b6b6a151dfc6500069f83f18f1484df05cbc7f82914dfa0d2180991 +55a037b1d440fee919bc893ca58d76ad19f2cd4d2e57e34604dbbf88612d871c +55a1e35ba91908d2868aeac1e3d80c257fce3e513ea4e65bbedea8cc60d1e8b1 +55a4057b181f54c2f83ae0f2e9f2d5ecb9bb5fc967f58d368bf55475de3c417c +55a66bc4b672bb9ec4e09ef14c3b9035ca7a2f8ef306de249dcf897bd06f5624 +55a983a2eecb711cdd48c8ef41c5e88bace4366fcf064301a586d01d4aa61701 +55b9055156a04865f4e426a7abcc3c597c8c712223da65c625e5be1390874472 +55c4be13eb72aa52e72abed19adf06c01c4ebe6cd0ce0a3142833f7d5ed23f57 +55c9ab1661a6f58a5e0e973cba1b3307466ba418266e01738976f70bac1cf283 +55d452778061ea689ae0f2a73415d587b6c0c482475ad0064eada3f9483eab92 +55faff6eaf5001d994ba44829961c596e556cb7620e1dcbe7ef89a63ef6d4788 +560a173b866f7f62af2b2e8667be869714438d7045aefe80a8da5feb5301f838 +560bdc87251de5f9586a6a85bc170149a7065ab8e6a77e24bfa958bf1d3b97fb +560d3346427582414c8c7eab7904d6fde3d365f740ab964f5d674ee1839d762c +56175b002fbda20c3ebb3f4dd09e567dc6eed0367c4a3809f537696304dbbcf1 +56188380dff48c54388d0759bc928591ff8aeeb23133019933337a4371dfcc96 +562036e80f853626c20e1f1e68bb3710742c9d2ba5d3d5e1641e321cceaaaffc +562ffc5d906487ff180da9d3ba99a112b1b4cbc57268bff6c7df1ca083517471 +563b8e35ae307f55a4d4cbf146dde522f59acefcfcd1de91ef0069347ec2e382 +564ad3412f05e114ecdd4fd1809aa285e1077abeb21d87d2c4ce51af18c20724 +5653af5996003b1cbbba24e68da5b9ae7366400824f9d115bec4ad2ddf21db26 +565a8d396d284218b646ec89754ead145ad98600b920daa6c75acd983a502a63 +565dde9f4e4c286a8770e6f3b0efcaf6351c45fdb7b0cd02068060e834fc300a +567ce94894479b7b4e603dd7a73c6cfb9a72fbd74b7336b2bbc429bf2d3417df +5686c68d5ada8694a455c65707cd050e9a77f558e226c3546e0c5ebf3a381743 +568bc8f1a3e559d1ea66cb6bd88a3cadb56b233fc034a289432d7fc058a1712c +56957bfc3168520b2eb810889df518e57070bd6c00e45785913fecd223fffb6f +56977bd9a60f3b813baca7d4ad6c9b1bc72a6417926147807e51ca1503306fb8 +569bb870adffdd5e2bf9d2b39bbf679cc28bb8cc501f9b12ccb55ee1daeda9bf +56a637579ecce26805d52342f474606b6c1d56070a835079e5cd85d5376a72dd +56a6fa0b4230610e142d583ee514feae141422a7ede6313e940b26a1b2b3aac7 +56b26dd9d660e4d578a076dba14aa159fe314ac8bc3ba40037bf3a9a9eecd809 +56b90feda3936617bace9252ef4b04d31adb299921ec76775d1b6f96deb40d0e +56cb3713a9ac7d1c4cb43701f412410dfdc14029695f9559cdea4c01d484137f +56cbbcf6eda77e9e6acad8e96a6821449e8832de28b535550fa40d00aa3d6ba3 +56d337a3f300b509651196285fca0a38bc98963e7dd5790af3d322fbf4346663 +56d46cedd080845cbfb160a53fe74e92468906f99877a2019d619469ce1f104a +56d75ac1d992f110dbddf6e7ea5871eae2a4b3038e38cff5687edcb929ff7ac8 +56e01707851cebf8f3a287d5377c7864a85c1a5c5dab315919f6411d5ff9f2f2 +56eadfcc368f9b8c70408aa9d7c89afcac8caa810b2a11647c8a3f9a8e436ad8 +56efb3e00a58165e81328dfd2c0c2c50c67c03da22fac3cb06864aef96335d59 +56f94c0377ffb30a1783feac6fa7be5cca609cb113349fd27b45c9496ed861cd +56f9dfe8b325e73e9a069271a3039ac0a5868c66f3a95934d59fe934bb146e8b +570269b7d7ca7384a922093e20f8cb445a4f12419121f109f0775cbeba17ffa1 +5704e2033bd9df946c0299b0acdf2f79b711443139925cda334442f63c44e176 +570be1ba50639a51c2808ba9fb76bc7dd471267d377f80fd67ff7c9a2b691481 +570edbb005268265796df8aa73feba453104a0bfc04d5eb1fdf7ac2d4ee16f21 +571106555ddbafb1d18d42daf79f5fba6a6898eaf41789b195c32933ed8c95a7 +571a5e1487ca778dbcb4be0ecb439cbada432ed34e4cfe34e2664c56d3bd1175 +571acb93556b179ee98d2aea72b52775e947b8285b846a3f6add3906cd6c579d +571cbc6a1fdb82278ca9343e02f0ab1edbcf52e1b085d8513cf26e39f701941a +571d52a8f9996ed1a7a119d9acc6579d42d1b2919bff3237bd800dc03c8411d0 +5726d15aa1108540aadb58cfc1e125d50710db773f6e6f080b41c6f417d81fdc +57335d4024c9171eae830268eef474b0838aecc7922ff67a87549f3aa5278584 +573ed32c0150d96153c44bb7223a8dc9092793bb16b23cf75f82343e2802ff25 +573f8d04d3b6f50b88ad8bbe58e6973d8b35a3bfd5e7525b5d78a8feb86a91ed +5741940a8666c34e07d4b62e903ec7a15c2cbe8690c9bcc6ba06389622873be1 +57558ed38b191d075ed20d1295a941560aaf65e5e693a0186d69e42d77fb7027 +575d7046ee44537aca217d03ee37afa641991959d340e55ddeabbd54e23b320c +576aa78c6c0c35c6a446a05dd1855f8c8068e47db04ff22511da47d98686c7ef +576eb833973c3673ed7395965bf1c6dc5eee0df4fd6d47abc31601de41e2d1fd +5775d18f59fce6a6285eace4fbf09d1dab8e75a4dc51daa844fc36f0835cac0e +577ddaaa14578fd761584e04fcb047589f9af769587b8272988080d53e5db3a7 +577e0d64701b79c53386887a8d09883a64f1fba00ab8e641473ef45df37f540a +578baafd958259c85c4961eb12e11fa40aefccd26fd2094cdc1b0ef54873aa34 +5799c790fbd287cb5b2198780455007dec2582a35b11c52ee6d2a83039ab39ab +579df21ed6df8426b248506c0f605c7572f9361a4a73e5583642fab813767243 +57b6d3b961d5764be9b63ad9990c33029e0863697e7d1ac0235411f25d6cd3e6 +57b95faa8f298793317296960ec5421d37db94a756428a87cf79dd49ff1a142f +57bbd14dba31aceccdfcb017676d3fd564645743e43e6f871539dd12b8d14c76 +57e0b3cfa2c0ca610eea35e6682f3a6758fd336f687e3f29cd44feb11d3174f4 +57e151a1b3e22da615c392f7c0a2921472150988729a210ca0906bdc68ce212b +57e33109971f27914cff60097070c1b1da72beb555265b76764dcca2a408ca03 +57e6a0b1a4ffda2376cc2dc07d3fa49d2f3bee82c8374a6bfd0a19104172958c +57ec48cbc95e7d085e4fbee06189e7e8aebbb468de54993123d0f09d3f623ec3 +57fbadb1199efc6551b921d7a820147fbc97721a8d0fc0ae9617bfb2d2b8d3f2 +57fc1a35e2581a51cac637a57d82742499170a43a33fd24e3731f2bc1b7369ae +5801f6d2df47b1424ca9e0ef7c392c51db1c534dc6231189f4d95a8a74c00ce6 +5808a5268da7f77db97581a255e603839b354f0c78437dbf6c696522f39d69eb +580aa9be1f61de7b0e220f629a84397ed041997ef428086ebf148899764df580 +580b69a0a5bc226448abb1002b8c1b1529b1af677796dbedf4f637926278cc40 +580bd53bc208ff26f56a7343f904546a203a4b0bedfbf14e311809325278b239 +580bfbfd776546ce0977d8f205b83ce045d4f20c80155c408e25ce217a4e0c3c +580f77f3ddd1f786ccad17ca109bcd251e7ae52fdca370ba4d033cd24eccb2be +5847d8285e48ddfb854fb800f1a7be8d8df2bda9b7a3653219505fe430e2d230 +5847f53416e92694d92ac1301d1b0ffece9be522f675b8542cb512b71b522f42 +5856ea5a9effe2389d71afb29199b0c68dcff2e7ddc43e53cbd076250aba2cb5 +58583808fcda42aea8d85284ee5480b64503d9c91c45478615044befbee88711 +5858d66666fbdb51aee00628de6d3b4fd3482c17ad27032b843a31c8ef749537 +5859b21c57647424c0dfbf39c585302a42e57f09dc93c284209455711d529ce2 +5861c3daab9b17289dba96ae360728c22699b44f8ebcebe8076dbe8057a0debb +58620c7418cad3e2807696557fa3b89a5c1e402d554b28617f4bc7d0fa638c1b +5868a4f4c06af9a284478f2524a953ffa3db9d8c100b2a769b87b8b7a25deed4 +586cc702d87fa765d00673eee2b616196809167d8d3616449ae1a7abf30843e2 +586ef42b002eef460ff5ef3f24bdcb81b6af66be2a846f96b82b73b1151b29d0 +586f100db372d26c3dbf621f2cfc739903de1b466b684ede859a73f8d98e22e9 +587d295c7b1ebca94e0d736c309e4faed96cf582718116c8e5d7848120eb6f30 +588e84bd5825c603147ba1dbc60e7095585b861bf6b85e86172b5b0953cc8318 +5891e19d887891066b1e955d96c40abd661a9e4ee91aef841428990dbe38cad3 +5896cc54a1abe10abc961446f5c144b6025d34e704295a8173495855d4897a43 +5899466eab1ffba672d04654f062bfa385ed497a078fb104e1c1ed5a2e76f303 +589f95bc36c322b1e5588ad19d053b02f841dc80885fde126a9ee95e783f1670 +58aa5368aee8fa5f162f5999926ee2601b117f2d49626f163a18a51a74ad1888 +58aaee5dec65017894d0136afedf40cd43eab6731a830642981b77f54dca2c6f +58b17ec8fb1e851689fd91f0280ebb4d7f77a6a84b19c92e1bd81b3d58cc1b08 +58b2f5d2f05ee5628e9dfafb937602686c557d88249a6010c61f90bbdc4bf638 +58c5878877c9b9e4a9520eb8678841370b013412ecbd97692b6dd0c0955a568e +58c718a5aa97ce2b63108b8ea12c2e20f073489ad699e4cb0b912c84f249a8d0 +58cd6f2b6a9934144378688449e508c29c87641cf7d4a108bf3b02b8681f2a5c +58d2988725a1f5ebeeef40841609f9c56baa0782d57517848c21fb2fd8d15d2d +58dc45f337b74e346ead5ae70f529af066051869502a1f4da917e8768a348a2d +58e231b3ba9e22876aa56fcabc23e5f252779f679a38c4c47f0fb62f2b2adad8 +58e5104df14d0cd4466ab7a8823e1920d5fa191c016e0e27a92353313c7aeec7 +58f79391b5b5722c62b876841206263217436690618a61870736c55f69910105 +58faec27e4065b1f6b1e56ff82a966377f047190318be92af82d660de1780ebb +58fc09fa7c96e80ec3060e22d6d24a8f42572e18c64c58ddea28fd16db7492c4 +590796d6d4144b51cc0ac3ce2b7ddc88c16fefc7177cf2145a793cacb26b8801 +590c250bb5e4e587a67bc5bdc06fd5b07b3f72e1948ac689a771e2c8c4b10ecf +590ece10d493b34db52aa82a69d8e8606faaa7607ce3a5e1bb5b463a88758f51 +591220c3ffc2815759e1913950420ddc6bf3b2360d6b9878beb1add270c734ca +591585422201016cbe04d337128f07fc931ec0724e04f04c9de5372dc8b4e541 +59264be040a699f109c0a535ee3427d0acbde43c986bd62401287a680e079fae +59297625273b637be01253b3739a3b192497d007415837f49b18c549c7c509cf +593635d5baf25c8a493ee4fac6a8e2a6d6761c894f3e7d256abb433111faadac +5944f1c881bbef1a38beb8737b37cbf0c4aaea8db46c87fb019253b2df953690 +594893a64229fd71b8233c1e8d8b8accadc2461ee9abf929ad7a1fac37fa5160 +594a14d11ef6c5df8a4f0930b351654841f7a2503d211ce5e77dc4665ba8faf1 +594ef4751274b077ad995e10f2ffa2aeeef75dd3af83a86b2fa2362933464586 +59502893665c22f4adfd14b3c375ec024f02acf5d75fb6101d976f87b8ba3001 +5957ee0e9be1fa10ac6241d64371e0d960f59e0b76994ddf804c5727d3b2dc29 +595ae1c0a7922a301291abe9824aafdb934d35baec2200415e02f0d6270b0e9b +595c025aec56209ca2fb34520bbef56827074afc0f7090f3071fd65a5327259a +595ef29c342710e9f05a97388ec7835e0ced389404d7765121dcc8dbd9675c4a +5966ebc3b9348b953e0300c719cded656ca7cc9d4588bb8a225165ba11062f49 +59693670329d5a6329638c4d798a731370ae2c796eea19603dfb78c2cbdb0b86 +597969392988204ae1567c328d30806e7260d1e5e418b81e6eb0df262ba029da +5982cf5e9aa1c1fffafd1197b070570c04090030df98bf8ab97a919d42cbd82c +5989c8a729c7f18377790390b7d2fe0e5bd4745bd479323405eec2a7c48b9502 +5992530b3ebba6b7dad96ebb8c590a557188c4109c8c09072c1454156daaab27 +59926e9cffdb35ccced10eb7d17d7049a6ce57db5d8c9e597d019b59060c597d +59936f311ac08bc6850c6b3a384cb363827d6db862a0602d57cad42718a836bc +599fcf99d3f17795313cb1947fa1de18372af7c49d16a6270c97d759b49cca14 +59a14b7d85e0fd412fe09bc1b21e7cc59cdbf7063ded1556a2365857f280fda9 +59b49acb2297021fde1855a60aacfb09ba3b883cac662ddaed1602b8edad385b +59c2a043b396f189eed4388f40e70c4f48fa53eb0b8d978f44e54a2a0f5255ef +59caa825d96dcbb3c04109a433fa57bbad325c2ef1376ac5ed444bb0eccd20e0 +59d32e343b6670fc001e1c36002c0536257c2f296ec1f4b7ee359ae5125cd5c6 +59dd38577efbf8a1130e58e81d57245935e0bbfbf755517f3055fbb0e706a69b +59e32abfc0b470f9334bd1f4fae92e503251f42dcfcaf70a6272426b88e9dcbb +59e5ea8275b470609a18feb49decc136de01a321ec5592ea65fc8c094a328f24 +59e692da28646aa1b1cdbaeb11b6bc714f892ffcf2181760814dfbb1b61a7f3b +59f4ed0b7d505c65f889dee8d3bfc575168f4dc1a1fc8a1412f95835228c38fd +59fa823c998916ad02595bb3526128f94130e7b14357c1c8ec8889008c46b1cb +59ffd1332664631f852966ff8e7369d32cb31aabb5e7e8fdf0149226c1f8f1ad +5a1ab6d7473e5ff2d70045ec3d1a5488dc7fd19150dd2ff56f0b489318553c8f +5a1ddc4ea90773fd8daad8af3db501b2709ea1342f902f25c9a0a7c2ebd53028 +5a2b94fc649de3a7d41ccf69096f3bf0435de34f4a1c571c3f1ba60ecf35f71b +5a3031635a41fc488c2ca90530acb51f79aa95c73d5c47c78f4a1af80800729f +5a3416ff9e987fce76248306a1c7a05f916386756ced824b1be0c82c122a8a1d +5a345a5a4017bd473e9f7b2539374bf7fb7f039f00228730d4f62c8fc7843f57 +5a42a14443dc476bbf7f5be0eb9b96dd6fe8579424405b71d19987b42ec37972 +5a5073dfd7ac34f27077c3a06f1d7fa85a8aed80867dee2c9cadf341d3dcfe74 +5a5b9eec02526ec0b77bd3e5ae8a18c127f3637c40e8bc6ded26a7e3fdda553b +5a69b3457efa6401c8f1ace74d34003bdd0fef53a494d019bf9a7a2ffe936f20 +5a73da5fe9b7195dd9bfef48291e89ac22fd73c2d5883d672613af48cd88621b +5a8879954826bcf30daac4b8a0bfbc602475b9b9017153acec45a5ff4de796ba +5a957463bf4f69cff7de1b96a1c34de90f0a0397c58e64e69cac84c95ff6208f +5a9a6c94e531df76a9a4123548a2b0affe3a294a916a02070fa18d401052a1b5 +5aa455d6fb5a8cca5e58522088310ecb67c654fbdd663cd6305c6e877079d0ec +5aa4c46daaccbc44d2f9e11a2d42478e79f6dc47044da9ed88bd222a561f60b4 +5aab081d9c5f9ae996ab61e2d9c6db5d9b57658979534b6c031f4aa5ac72d349 +5ab71a938edb5f4ef7f978528f9ba088bba835125759053f555bc1164e78579b +5ac49ac4abfdf88dc18fafc6623e123658a5c65222172f4f60b3899e48c2fa4e +5ac6301f2bffcf50627f25851a7d8d7ae01d030afd391f68e9f65d3a0d5c8500 +5acbb601743cc930bf493f4131f3f54926f12befffdd11353f9a0303d78e6d85 +5ad39790084ff40aed9259d2f5973da7a7d7caef3f361f67ade54e527120641d +5ad802307e5ddf2c531a129edb6f5f32d74d9e90776ca4ce27314277a735c746 +5adb35af00c86fb3b1b0c42a62f4c55a031f1f223a1bf99233ec121338e02a85 +5ae080452c57218fb33d2f06b4e4aa47c4dd9bb53d04c0d2c0a73ab533f18e10 +5af801991724fa2705347104bafe59176a898df965afcd56602b6edb328593aa +5b01ff507bedec977c474ed31953e90fd82a88f77fbceef188f989c100271d69 +5b0b29083e083d5f92adde9bdf6297b7910434fccf71bc784522fb33f5ebccae +5b0d57d45d19ceedcecb5c55bc42b30001ce804dafc17a75aa37e8daec58609f +5b0d6d6262fa0478095f58cd8fc598a5fa4d99a6f6835e482e96db933efc2b16 +5b11aef17b9aebee07a9367d1e02c37ae04da2c861716b37a794648a6a237c38 +5b14f065103c3f3653d7404b00ba521048acefe1b5acaadcb9dc3052c57b556b +5b167654fb1679d82db6296f8502deedc79595cf5cfe5d17adb6f018b6a9d9ea +5b27a899c5ed10ca4a27ee6104c16068c281b41acf2775b2fc4df31bc044961f +5b2a949a1df4eaf826a6d21e61701e8a90a3ec345b954536335fe5d51ff05b46 +5b33ed29d9a4b7b354c365bfa59ad20682f29709e075e1a4483f43e9473bc7d0 +5b3abccbee47a33d453ce2beec7e8c1ca5b9bc950336cb75ef42951443e99b46 +5b3b31fe6db5e2d0d8778ae4d76b1a858a5a1c1ee9c3a81ebf7597ab8d3631a0 +5b3e694e26a46df94f79ef07c639dcec0be82ca770bc1c7f65a0b91a71819ba1 +5b4238e306c8d95a829cabe9375004605b788891017ccf437a042c3e93ff7bd0 +5b574b247ddfb7a2d83409315d0a4bd9520c0e35b96a700a98ec020b2e15f290 +5b593f4634f1de9fb00e2752d589a3d6497c90544fe564094b8a1a3a81635a59 +5b5a62cb05dbac1a2a127289a9930fc394cfcdd65627a03e70bf9a6fd2999bb0 +5b62a9f91fdaac8ba3ec76b9f3c21ff3d50d62f09a23b62ff333059932e5acf3 +5b77dfcdc1e26b7b64cbf8bd9e7667de9d724930fff3d8f247e9f3814cccd062 +5b7e7ab191f5362d76dba6a275780f033fe7dbbb9e4ca08cf240ebdcf3283f45 +5b7f1ca6da259b57572c9b9040b5952b72c858bda22f3bd0bbc5042edcf41392 +5b94f2be354b1b39bc68c91ea72a3dc910c1b5ab53138bb77e432df62fd7e782 +5bb757b9c26de06b27be480f26f7913a1ba88bdc0676abafe2f6d76c6d0fd0e2 +5bc6c2516e0733a7e6240a6f4b6c3a20c119dda5a64726d4a3d206bf86c68a37 +5bc9ef2b3d6411113c6065e74e4506c7ae7a9c2a89df2cc5e186c5d5fce0d0d6 +5bcdbac1120f964c2559501f5977fc9d927af6f0420a55f170ff99a75c7d217c +5bd015efcb0222547eb4a24e3d508bff5f733a451c6ec25a2325b4a3354939e4 +5bdaa6afc10eb40cf99e7fa379bef435f231fcecac7145565e21b4d0f1d81f2b +5bdc6443410eff135bff97c920e34d05bf2f32b9a9cc9316d34bf03e68da07fd +5be3dd3ab60b378125a9370331b63e9b8b2069f5a3661ad4f9d4230a2689a038 +5be7e93bf321cb66d2a8ff6cec2fecf0e5a041808b55d22b2730b76fa6fc15ce +5bf20315e9e710b3bf2e179f34f00e5ca49e2a44186faa3a529826902de17736 +5bf84456113000e2c398e84fac7b402f009c8a70cf7d517d819abcce4892b7ae +5c020caa5ca3e59b1424b687fbc912aab6ac2755545f8b314748e7cbee8b0863 +5c026fd11c32d31385fa82858035f492538a40aed7da70ce41d08130b35f98fb +5c0f7fc3aa3f1f1298b73dc7f251f9af80c1692e07047cc6cc8c7076b8d41086 +5c1f7a2b58ac3e18f50d252dbd35688bd32d33ac0cc6a3549a5e97a4751e6eb4 +5c24cc60bb209bd963778bc09bb6af6ce8505b4fa994163283b4046e4d7becb6 +5c2da7fa9b38ee464bd102499bfe48f7bf8fed0d77678269d4829705117818d9 +5c2e237077d63c3098cc0e2e0e8355a0a3699b0d3287e7a5a774021da452ebd7 +5c347158497075a3e0821860c9e4919109a9c0936bd350c5fdc696e449337e82 +5c441fb942ded260bdf07dce5c4d231c0c5444d2218c5d6e3b044127116cdd2b +5c4744b21a7fb59142f89a479771498aef1991536c3a50714f882e903883f4c5 +5c543e96efab2054f91286a1d467be18d35b2fa52228293441e5e1fbc68d1b6f +5c5f8f65f46475fdbe5d6fb3c28ba610a4976d2d6828b6ea57f0806640d8c276 +5c7d0b19d109a6411657af62253b781b8be7bedf211aa2b527de1f8c7eff48df +5c823618bdce0425a634db726fe161fa00bc56c7ba5141142a13985d187fd4ed +5c8f4edeb2e29bda483dad1a48bbb1e86d1e8076d3907d8a04a41b3c5d9ad10f +5c900257cd069cbeb56c25ed125844074b9f8053a250608880cc06df7ff21d64 +5c9cc44e65a976b8bcc43f1b65905d7b274a1bb13818de43832133523d5ad545 +5ca4ebeac8395fecf2111d37c8a2ee9397b803d590cf2742afd337ac856e1caf +5cb3648aba7f5513eb9e62b744920c17a3f1bf63261075c150e0ea41dbeef5cc +5cb81d676c2e45d5d075b0fc1b93756ef285531821f73ed8227910ac78d7be4a +5cca541162557c363387e9a59eaea04bc3ecc7d5eef0d56c5d7b0bd59a2c6ea3 +5ccb665d84fe49c98d994162b5e015d0047a722b34b3437d214f3112ee494962 +5cd6a376fdf51b20cf30df8ce9bc7d1bf93f0764a3f7bc2f7f5e9052d0fde99b +5cd79cc72e91cb15745658f99cb013d0ede8ef9744cb9b9e55c22615bb6b90fb +5cfd2f0f0ca24f996cf1928ecabe1f22d088dfe42784970e372093c75075aaa1 +5cfecf9d1163ba03106f5079407b675fdd0dfe6419451c32132ce586fa820988 +5d02181ad127acd57ef7daca5a2921801b90f331fc29c93d700cd4e3370a757d +5d07dbba4cdff6144d5eaae44214f3babda8b9779393c39a24cb329a51e6b37e +5d0824d7ea9c183891c6f6293ecc0d16ff49d2ade210b009050161e11a935fad +5d0a395b4c39d17126acb8477455f59e09eec5e5b5cc2a2f65a9c08eab9476f1 +5d1d4ba074339496e8f531535bc8894266bf2e17da5f8c3dc5d43897bbecb0bb +5d223df5a6d6f8f0517e20af78619d52d7c7ca427801c5d658db34ffa16bc0de +5d23cc4dccba3367869f812bae363de81d95dc716dc3dec51a404e024c956656 +5d2a3080a9b02e5341473041e69d53e87da29168572176a5b375c74619f48693 +5d2cba6abbd01b9fff6aa013462c7f429919b87e331f0136e0a2020da8a7ab1f +5d340ada40da150de9d1eecbf5c373dadb14212bc2550c5559a717025adf55ae +5d39de44d44a79cd2374a21f46d21f117500085ce464d321a391c9567c742807 +5d40d455a217a1a80a79bae6473ceeea02e7bd84c9c28701323f40339c6884e5 +5d41e451c374985675af83bee885b8757b1d4f83a834d2b12e3552a18516ab2b +5d59be2645a2ca3d35145fd64420067dfcb693d7349232ea68d4c95fd25c8586 +5d5da776f173ca7e626b915467224eafdf9dd1a962a5049979ca8bf66ac1f3aa +5d60d89904ce7a27602f86e701b080652396bc7cb2f6aa12fcbdfd7a0bd7eba2 +5d66acf71c77654450866af0a14bcb90bdd365df5664e200c3cea84c6ed0ebe6 +5d6715377d239eb459f0b1f30ececa93e368ec85c17c7279927b225af6d8749e +5d69d8054b4932095211fe50f6a966b990892bd228fe005897718356f67e35d2 +5d6e63d27991c6554198ae97187ad04efe51f941428a244edf821487101258f2 +5d72817a2ec58aee51f4cc34c95fb3687b4acd7cd8f218d89f6ad3bb4ffcffe3 +5d7c4509708534ea4c15ec0c7b13a1d679ca7893bc6f26bb8256d3b13efdc682 +5d7d8b5556061781eea13d7b9b92ffe53af2a35675e1276a46b1d8382cabca5d +5d80cec9d96e2a5f84008f21c2e8181a3b89f38f978ec6faae64c861ff1fa3d6 +5d8e4e701475f7c6983c55393a205746f9b6b2bce51d2713a427113c2ee2a031 +5d8f9337e792ef4682ec31ed7ffdad0246a9bc972bdc09557684cbb9dab313bc +5dab7e4184626bbd1bb72165a3b6f10b5c3d9dd67c3b083abdc29c478c5cbecc +5dc935c77f581e7817fbf25a14a8a314733e10ad322ccb427b12d33513ce7840 +5dcedf2b700c33d38b091ac7e1b2b5de9cf26742aabe5dbf9bae923ddfa24e1b +5dd385f594080846fd67c903009f2d978f332e1dd3be3053faed9ad6277d223a +5dd62104f054f83572c96644b44d5f4096ebb68c3c89550e39ce509ca30fcb29 +5dd7ce8f663eaa3f7927074230228ac553d077f71c62ea359dbb44c416656583 +5de42bcaaacf7d548bc38833ecb4d9996e8d8e3e1abf5ed4c93fd3f914a46552 +5de89c2b4830bd5513935d8fb9ba7354f10697aa8ecefdf5eaf81a66b3b27036 +5dec56940995b64f5eee9da9f9e18c659b55ae3baa88dcc055286e81fcedc20c +5df3e2a04fa1be7747418e4841bb06d890840f1b111ce2c7c56ac2db7f9e5e71 +5df62a236129a79ea75624d85f06929b1d4d59ffb62587d4ae1aeece147e81ba +5df9bafb9a2f02a84d37acbb5344d77d156bc5a25de8f90faeae1061f1a82b16 +5e0369ce160ce15e88db473df7f4cd7a1cd2804491b72036f429e25a65356385 +5e03c41e165f61366cb3a252f8aba8c694ec9651d7b39c75e04711ff1fe44d0d +5e09a1aaae3a08686a5009f349c656904ed476cf3e91e28b563f1b27d5a80039 +5e25a836af74db188f6ba6026629ce4c9667fe304398cce514fca30443f259c1 +5e3b54eb564b5e579c48835cced9d7f28eba161da73283757895931dee5e0d04 +5e3bc826bcbe50bb22f9b30d29795bb35502e30cd4a9e85555cf6f35240fb8d6 +5e3e7370a91b059b14308790c436814d3f2ac7ba26448ba8b096cdf6588a840d +5e453115224eac9fcb90782d8cee0dfeff89361eb614b725af90efb7f93d55f3 +5e482724ca8fa809e5033a8103641b28a28de9ec72bcc7e2dccb54895928a93f +5e5c1bdac5e2d74737fee7f2f59ae374c73c4bba7e799bd8d25dfab9e8f973dc +5e659ff260d039ca4c5d077362b9f7a886b5b506dd810bc2914199fee56057b1 +5e66b1cc9ea47a4988968e37706eeeb1dbfd132a6c102593337cacffafde102a +5e6e39caa9bca6e708414e9b59131adb8bb35099910097783961ffc84b39fc13 +5e74ce990c1599562c64902e82824e330f2489ba196025fc0a722845c99fda57 +5e7e8ab6c1305c5abc0ecd794c37b4d94ac33675dc4afe258a83d32dab6eb2ee +5e96e8bd2d9a1116bd31051400071126e03a67341a72b3133abe181e3b4f7d4f +5e9703663ec9191513e747eef2803b7ea54c281f107444db8687546cc5aecdf1 +5ea141cc5968343e55753b12e28f86d7e42e5218d0478117e684161f575bc6ba +5ea328db18e40759bbc2d36a6c36c8c0cc14642283ece5a14c6f7102f9b35ee7 +5ea72a9c56defa1b22c33568ac30105cb899d749a6d82fb579e7ff73f4a5cae1 +5ec05671cec9a478b8857e76d380ae20e23ae7d74bb32f347181494be15cfa5b +5ec310c20fe68e9f66726c0c1a73c56293c570f12cd086585f0f2acdd00aa2ff +5ec7330561524926a0fa41bdebe1684280afe5fdb4246b8f4c1944e5a2688ded +5ecc7b2416c79d4ad6b6b73e52d58c35ea922ae3d6e1b4ecbfb32b49e109676b +5ecdd692362cdd16e7fe94008b762ddd530ea9c1d9e96cf5e9f9ce030ae99860 +5ed2c0fce131b91b58071db46b9c3890de29f3ac824cc2c5f1bdf9775c804ea6 +5ed80be36d052d1518f637679738c695988fde1c8011e535bbca700cf491c1c0 +5ee779c837a947056434b72bb1baec747dea91ed37cf5cb8f39340154c597640 +5ee7c14ecba412069dd59101b0421a3abba988f2c1c98f1a20742c0853d1930a +5eeb79603e570a0cead8a7c9753a8b749b9f9a7aca9a13d15fd1dc6d0fcec5db +5eede6f8482fda3931a7db9e714956aecf23955cd9853251408efde57baf017e +5eedec8253f7eb6a2a77ff8dc102ed0a71e0d47cee4353d77964f9626381c183 +5ef965a1733b475e5a56f48e0b99db5d75a7dea8df0421629f8a803e52c344b8 +5efb2458046efa7e8c3dcc5ad0546efb785c75698824527076b31e8c1a384b09 +5efb40639a2c24669f06ef6622d94b9952dc92b14eb062749a95f11d2f8c1270 +5f061a9a22775c43ae13a0a9e3aa8fbb2004b4a97de7ac1ce7dd1526566a9feb +5f0db6f65c709713aae00817b601c17519e5edd348f4791eba7530bac76e1198 +5f1e02d051a862c65b87149484f34fb727d124a3d5885395df5f9ec9b75999ad +5f28490aa64922eb4180169269e7a1c3bfd1919b97d476c6fbe7dd49a049d218 +5f28904acd286b75af77f9936aba1bd1c7c8b3051f076d743a866fc30b6175c2 +5f28c4a99b78f2f2f71c6c96711d8271228d33bd9206eb7dad7261b5340bbbcc +5f2b20ee269e7121cc479c6447a7a78b7dc2690bdf20555111a4bd333e382824 +5f332834f176430709361564381cb79bec2d7047432188b88f9d66ef33187481 +5f3ef043a87834cfc1b23d1be3a5ca4c3ee01200c95540667bb7ebbd5de5b4f2 +5f4c1c18fdfef56dae9a22f2681006cfcd96c97522a83af2631147881dfb3966 +5f4d2612a9fc0976123eb88ea1625740064655f6d06b583ce6c9dd6dd33ef0f4 +5f5eea23d96385fe381310fda48c2387c80a348b9d8ff79799930ce9fe41a2cf +5f603c6d8bd0eb6b2fdba94945055de814a93924981ecad38ca0998c45a3f9e6 +5f6f5bf0221b7567186d7777bc20e57aa2f5529039bfb8d6d8d0b91362073115 +5f735f4de2f083a8e68847646033045ee800f86ef4ec7e72ed48bb46c95759cf +5f806c8e46919c8a05bf8077e44b0a0e92c21f58c916824e53abd4f121125a57 +5f83ccd5c94dbc4c12ff454d783c5261550d5e4ffa3a04476f3f9a74a8e682fd +5f9583320c348a2950d5b6aa70f328147ec9766dff25486f4167ba7acefdd7cd +5f99bfd9ad0878f55f568cf956611d1b395b5ffd3fc0f11c4085fa31126aa66f +5f9c382a9d8eea9fbee5749d676c55a20ed5a359df9c8c379095f4a5678224b8 +5facec55753ca90714878023e5779da5cda4527b43830251c7a2ee33d3e3197e +5fb07759f7d26deca30cbe2d16480a77850726511d109315267e78a057d6ffb6 +5fb7cba6c3b61aae1b6384784fe2d34dd72b501c2cc10dd5741c53c895720e03 +5fbeb84a4c2afd177f2277a83d09846755585eaff7c667057ef370a28b0b8790 +5fc03ebc9ee336c6ab5da55eeae6ce716cfd885fc1f80bf4e086bee96fc6a166 +5fc481b157a8ea087045f568e50e1466270631ffd957030bc3b0471af19afe5c +5fc9b2cd23b2a4fb4e87d0765885b651fda26fa46cc64a607f421091b33548db +5fcaef2b8ef61ca96fbe325ac5bb37f4f76eda7537c11b0da12afc04fd5aff22 +5fd81bd2180792fcb933d6ba93acd6c3ec2cce2f7d3df0d47e9b7a332a751885 +5fdefc118f1854d8b242953a17a3333eded138530f712fe8b29c218e3e90aa57 +5fe0e234b1c636fb216b8c8974e8de285c9f55d58ab133eebb15a4146490bacd +5fe57ea052c0704f586713194a8a8962eabc5b018abfcb3910bfbf79a7b814a8 +5feb5ba9fcd2331a2d0d0e75c8f4ffd985a234bfa57c9a6a2b93759c30b52ba3 +5feb8b274218a6d3373a134e5e72de6b42b98e7c28d9efd0fae088a48af0b682 +5fedecd269ed2df51bdae12a6ffe94270a5210b8763508990e6d60c6a93a50be +5feef68c095c8be8fccca6c2e1b5c2502053fa208396957b826f7053d2837b88 +5ff033f7ff7b50c44a97f5448124c718b10e3e457c2ba1a0c5df641c1cc913ff +600fb27af272550623c3b247ded004aeeed1b301a09c69799dbf9930aa186ac7 +6015a9a35d9044fe890f802f1290a1c435f240cb6c0d7fd0d9b81be6466b397a +6017ceead1f298d9e75c2d4ff5c40c5c7d8286cc5616648472c08ce5d5fb64bb +601ae4c899d09647348386641afa8dab380daefdfc0bc44075c825a6f9d1ca23 +60206b992028873003876e99487da8793ff570d38195a366d750fbe9a9bf4203 +60346656b2f47f8adda169b77ab8ba9ec5a22a0a1150c783f16849dea33f649e +60369a1b6a04ed313da804de98e0c26ddcfa74387b808734b58f4f95e95b27d4 +603a6a742f0ab25593451728cc41caacf81125f1a2a864add2cbcb0578b99287 +604d960f4bde6e179818bc8c0af6a9da8a49d61b660c650cc158b47de2733699 +60564a42803fc1032915ef848dc5455a6ed22159fce5485ceebeb23edb0aba38 +6057e91feed68d19c01db4a5cf0dd43b1646f7e61de3b5877c032aefdc2ae0d4 +60659ed54e0a028e42284a178c51207a286bd03d1a26214589f91856f689c95f +6068a8030879b8391b320d63a5d09cae5f75dad101f3f4200a84394675a5a2ca +606f398125cd67ff283a061f105edf0515b88c6989803f61763d1a28644af1b7 +607b2eab6e93f31ddb5e9794b1a573dd17ce590c14cfb024c990960bb6fc7884 +608242f96410f42ac7b33cd5bf7cee0d21c641da6f8d09988f538dffd736871e +608552540b3f0b41b4142b38a90b71f4a6902e03a7b098a8f055bf8c71441b69 +608bfd13ccc427aea005195cadafe5011a8a6c68b305690be2c4c10a11a4767d +609166e5e5d79cfde4f5cc07d1daac7405f48daa7952563c74f2fc387cf863bb +6096fdc5b8ee9d5c18a9c2653ba7a198a29c4bb22365e187e417eed3e7724ee4 +60b40ac800f1aa1cafa904526a9073892dea9f939b3c62ce6fd91f357acf1f80 +60b625642f4c632862025532b991ed9ca385b0151cd079ba202885328bf1541e +60be7f0ae72e1a6c7c5ee4d2b961e9dab0844c8d575b75aafc6d05ed4eb2f6cb +60c263ed5d632aa07541aca981cbcb5e3e7da85aa7626b1631170ac5154fa898 +60ced47299ec7f140aaca183458063f846259e03edeb8cbbe4916aa2c8f2e1fc +60dc688beaa0c9ae422c1275d07bd1e3b2bc4d1fbe9504758ecdd4b029e232b7 +60e0adbcc90d93a1d5c4eb6e4e34d4e012c1380e6903046549488e890de95424 +60e3400d35299e6fc5faeafcb01fb6e0ecbfa2aafbac6b68bbe0063728bab9ec +60e452073057281808cfe4a582d0975f2e8bac317ab623cbc3c8e53c899b43d8 +60ea4436452ba00c95717a342a4a98510802d8ee35b6c37ee0c2f3fc272f832d +60f2feb3a62705961fe206e6d84e7357ff1c646a2a88f615c99078ed86d59c16 +60fa2dcfba703f4148ac60577bb581eecf7620b37073d69cc367ef6820943faf +610e1ca14cffd23c38fd8ebe9c1ff9cc1f106ca6d1658ec21bd3da81dcfc2642 +610e80a81a3a17a8e873189dc677d9e1522ab1ad110e3daec08fdfdee03cd550 +61199dae99942223d65538015c8638a57b98e22abf3304c84959984dc8b88796 +61214312b2155ea524f7034d55cd678417d780b616b80ac657432d3a958ace35 +612babfccfc233318148ff3471b9aa27587f003ad9bc7ab171598829a5f84068 +612eea18da3b22743186b400534cde98296f387ea210d33f22c1853cbb5b25b5 +613078c0ff3cdd370f9b4c65f8a2476e4db1f33f4b9c8d40c40a58e2946cfe27 +613192c323a9626b8c8d75e310a6fc9089a580dcc34dd64642deb9b064a59ec6 +6151caa4def92f24f553f9f5187eb3a3c71f4e110343a29e7a7181886570792b +615477c07cb3d983d46a2d99f0ef25a1f5360ed3c71d07e667fbb4a264701eee +615f31ac2e13f9679e63e0c600447ce712fbc01d2ce5e2ca4ef8b386de54eb72 +61607040e22fa68fe243ebbfda14d6dbcc85b22a8b8094c0a708b0b23a05e14e +61661a668d2fa7fe087f95be8fa0618442a29a373adef09166e8e1fcce6b7868 +617211dffa0285db3f73c5d44234f408e0a094b7ecf2793942b20644c0f23054 +6172163f6f7294f978ee15c6409da65908a35a3331442679acae3cfbea7a8b4d +61889b163781b61952ade2804ad9db1f48d6a256a380619a6d88d7fcd4ce66ac +618bf95d749e28ec8e45f7e4c711f67844adef7e2cd4318477742b284d23069d +618e4255ee993f7048d70c66a1ab2f7e72dd465335ab48909caede8d1317e662 +61a0662121a87c1d7db831d035553831f7b8a57445e97b9414f065a4d7b259f2 +61a451fa0cce89831eacd119db3ee9ac79b2d73c4df10065965f0abfe469ce1e +61a862d8d4c5793628cbb05ea49d0606364a639ded7085f8588dbe1d1f1aab96 +61a9b4f701ac981ed76e2855a20f9af9715da9d0cd65f09fa1c23a813d8b857b +61a9bad1fe9e937d9b31ee3b9881b8365d4768ada54ab0585e716262dd8ee955 +61aa6a0720a1a624a399e0a8746a3fcf2075765f8b96b3eab622ee85c5763dc4 +61bbf3126ad54683deda8536a6c7053a90d50e6bac35cbc577054f411160168d +61c7f8635b5d52b85f8d707591843742dcef55c0ec014a4116b8424419f34daa +61cb70505d5658ab662819828ad07df48731e336bcf8ef7c19336b104997fa59 +61cc2926a25aeea855a5b0a99b66a2a429d12d68260b8c782bc9865a2f2e5696 +61cd0556fdf4264b436431f3a588632db1315d5108a7730063451589f36c7832 +61cf57bb39fe88ef9443a325bd265646aa3b2b4d82541a007b394f8e8f6ced1c +61e03f97708b3376109e95f58208e015a71eeaffb4b39efb0e1e9a4215394006 +61e0c6d1753c2c50865542761630b4a1792cc27c67cf2f069faa8596931ef9ae +61e1fc48776dc4045b3395217e3e8d4658fb446485fea5bbe30750824470eaf3 +61e40398bcf1a767df5771227bcea24547bbfb7187f5b31b6dac58358dc01764 +61f8beadb8f837d12265b64736e466eecebcf674fbbf701679c3f9bbd75ffda5 +61ff4f535bd14b2dffbde4e061c2c664f9a0aff2ae44cf51db793585d8425e3d +62050007761924ae320c8be9fc4f926ec7ee04b8dce730087128fb7d82b740b3 +620f135ec735e4e829d02faf902b3b3a4a4102c296698cf59daaa774b41f430f +620f54a957c5dc011488f1a78981ba170b9f5b2663a6fe48ff473ff0134b1ecf +6227456f1919e77ce75c1ee35b86287cdbbb8acd6aa12ac87ebdc6dce7544295 +622df28b1fe6e78bae215c2b52b7718b0e96abfeeacc677a9dfa2dadb76f5b4e +622f7004f5dc3f5a2e9b3c16e8733fe58aa323d580dacee615dd2f142905535a +6237885a861e2ab59d348c44412b2320c9095bc72d1f1661a6ed045f3cda6648 +623cdad7841068267a83caea1be5e992c54965ae0177bd00c908a6c19bf91999 +625288b395dcc8c7b01f5da9d0b1fc09fa00efaa8db4ffcf19785c93211ad010 +6252da087864a2413582d4a18919a7ed1d8fb59e4e900b32837725a2de951f46 +62535e3c2b78fe6c4811c3c1588cfeb4561b8550dc332dbaeb33ecbe6f7bd115 +6260cb8f248a19e7f4cf6d99e3c8a8a64f9c73c120a6ee1d2530ddedfdb39295 +626a5e896d4f87dddb223b66062ef229758cbb7655aba3af0e3a4b3e7bbf5350 +626f961771c000242dee537b9034df54c48acedeb83e0affdb344cf48ca62e2b +6280a90d500503c96480bef8a03d928d56561da2a990b3fac5825c60142aae14 +62850eda586840d3d7f9a0295dc3031d8aec9c5d14b320fdc4ef79ee51256220 +6287e3e8e99b11834615e11903aef1f8a753b6aa0081a2fd02580c0643c9ae21 +6288fd2e27be95dafd0f28ed9e3c9031bea68a15ee12068d910e2fe8489c155e +628b6321fe27774ee9f45f5cb6228f954453efaec5140c05f56ec63ac281f45c +628fe8181605a0324b4cfbabb266a7345e8efe8cffbf5f5ae1475c2a6a8fb29f +6294d8949bdc19ae94307a1ec9f41628a0e964501945dc542f7ae35e452565e5 +6294fef74e5ab547500aa537dd5d0af19ff0904a462dfaa2962423ee7bcef28e +6295c512edefe4d1534e4472af97b4ea02bd3024d0871fd6f48bf66e73fe96a8 +6298eabf7c24347df416bc43b0fa14a743053e0ee701743944ca8a2c21845743 +629b506fbe5ac3732e704b662781602029014b84d551a8011a6779e63842a869 +62a1c4eb34148627eee6ee5a6ccf2cc17be755816ef305516b352eeae72e5ae6 +62ae000d1084e1be097ca1754de5a233305588f2fd8419c95af9c342c90addc6 +62b433ce304cb4d7ebe838c64d636fe488b3c0037eaf9e0e663625967e067703 +62b5b5cccae4faee1e9466cf49862126c9f77721b42a384afdb291153e819dfb +62be39ce8db67bb058082f12a81ffce6ce7d00359e66ab8ff0d127e4ac72fa08 +62c2b692c72ed7d84a4273dfb6545d0ac1182080f46ef77778d0225cf01736eb +62c5250e3eb6a4ff29d1a2ce994ef030a51f150085bc3e7765814dc47159a1bc +62ccaf3196df33fba3bf3f64dc9da88af2771589e62e26c2e44d9e8ee391da42 +62f7eebfce4378e59abe3c361e35437f26c6ce2bc6aa50205d9dc6f363933961 +63006e92e2c599945d80bad153f5acf3f066b95f58afface9ba535cbc7222865 +6301a14e98c8fe385c8ac5d29033508270ac42e84c4d0ab468594738d73579fe +6310532a2d1380733975e88bc52fcc20b2ffb21c448845d67cc379e25b5733c9 +631695ac3c6b41404a09ddadd605c0d3e3bc464f86a8eb8be78f92a7112385a1 +631b8ed8a2db616799d45bc3b28401cdb7829ca699a11c48060aba193061378f +6327e282a3372e63c029883f4cd561af3336f9f8e0b236123eac2b1a6822bc42 +634fd2fd7d26414ba5abf67cd02f6cf121abf3bfa81b34ec9a5350e5f0af2db5 +635b7e5db8aefa1628f7524877876e7de10c127064a70218660d614c82bb3bf3 +63656c3fa12b9a814b1d92ade52a7df4039b441759bb3a5f222c8079a0daf69d +636a3bacd2387c6a3453ab3562d8b85bdd2abfc359541c8aca33765b63bb175a +63709af29a73a92cbe63f3b6ccad1cbbf7dbf456245e8b92e45a3a8977132c9a +637178a71c0403ac13f280da0207e2ce8ef6edd0543e43a1d33bbcb6b99c97ac +63788e9855b6afc2c82634f567a86680aa18ea6ed5d353d52328866a3cebf535 +6379579dde36a9e9e83072dc2a8124725ad9c7cf7c2e7d8bf2f055227b2fc377 +638810e320645a4b122a38529d21b17d5dfee0d848f74364e385b77ba5082041 +63933de0b958970a41686349bd373c2214c77985cc163a4675149a96d6a72cf4 +63a33610279114945eed8812829ca6cab6a7cbb3206ff406c108acf1eb4f62d7 +63a4637201ef1537cea43329334d1ec99ceac7f50499d0d7b4a5a46b326ddd11 +63a53f1ae4f8df6cf37c5f818d7c489ffa6f96bbd0a8b10d72b4d1e63f4ae95b +63b003bc3d4bd9e04bdd0f9976a968fb85bb94fbbd9d56849318fd80f6e82446 +63b1593157b285729de7a993a92a718ceaac40a074a2e1dc6f78fd139f7c4454 +63b491dcd9e2d53dd4f705fc8c8306bb6acb7d3a7d2a415c7ccb26bd7fd1e9bf +63b7a1cd3b2fbe368079ba7c59b07b472480d63674125a99566990108081fd83 +63b99dd03cd12474d25e00691f86a4f0b8b248016708b275efe3b51b6f8614c4 +63bdc99a95bd245ad234319586d2e37d1e53ec0a44a1c1815b04edd0302a1e71 +63c3a1a5b21aab7f375a31f399cb48e0195f8bc448388bdefed080bb452e4719 +63cb8dae41419d66f2ff49b6f270ad54d9f744cecf64a8ab54c092e7f751894a +63cc696b42e349089c801e1637b5428e2dee4fd72b4a4472d6f034daca8646b2 +63cc8c1da80b260cac3e458ff697598c528274407f57be3488dccc4adb7915da +63ccb12f426dea0ab9ce956a33e4607ba5070ffcbb25dac78154a11cb2b4274d +63ccf35d4727875e8531da4ee70ffb61f553ac7baf9ef7e66783b43f954c9fd4 +63cf4939ec482298f28d9184534b088b5ff2ad0e92b129044198a7818f8a5da3 +63d2a97bbcae4142e00a74b597b35e6c4f97c567627aaabae92603096290df76 +63e1f141caee64aba1f44b67bc8f2163da987a42d3d3154fdd23cf2b2e381031 +63e37576198bc57346f99f08c18beb6f81cedaaa6ff586b80e73388919e9e56f +63e7aeac07992a5511ba486fc076791f82bec3fafed8964943cbfaa54427f8c6 +63ea1c3ea2d91a77ed50414a277f2b142eefee3f9ccc88e3b6a5a0929039084d +63f1c63e19743b1aa934b742e00051ea0db3dc8e8b14a55cb4fc96f01c7d2342 +63f467fa1c47b0e5d64cd4a7eea7ec7880ee71e14addbe653167000c7fe6dac6 +63fcd7953d9765cc0be4e9b396ad6656a5824e9113d0f78247d2badbcb1fc26f +6404229eff7038876da3297e086f4536af09fa765abccbbc9e410b3f2ae38601 +64099770ee978e8c7144a1c66720e7cc00b5ab8dcd0877f74032380ab3a3f579 +6412876077f8e116e4ef8dc3b1beb00a86b8a190903bc36eb06a8b020956026a +64168d8e01c860b0d3364baaef94531f70bee1604ca584a492204f67e4f4e899 +64168f371fe25ef41eb78e6918e359868d7820e534f8dfb758068266920a1bbe +641760448a164c0e08cca388909b0286235b8d43ad4936928e62b443287e0fcb +641baab59d653a2ae7e92b7540d5d4340fa155cb39b70de210f00613e849ad8e +641dc4719e9d780e789c7310c8393d126785eec153635477fbe5c086b2fdfe54 +641f9ef2f766eda896c34cdecb3099e1e8da556032b1e934d1394c85fd9adbe3 +642f62c4519fe912e8bdd25cdcd3fec2b69b6c7d9f587dd35d18fa3b9abef1d3 +6436d4cbfa38722dcd529b4dafba45031681e5ceff718b1c744d9ba04127e48f +643bb66d5afa803ad22f9c62bd56a0c8a9c4ec66957972d1e148be687fda1899 +643e83a477180db5d234f457ad9fe39bb69a57aa9f0461a299507edc4ba8b690 +645e376b86854a68ac436b4bf1273dfec2366088f0ebf5a5348a39fce081a7e1 +6467ff64baf6506f0dad2e1047ae0dc0b87bc9eaeb284e165a417c5795fc45dc +647159bec5a04e358bbda77ba669d4dc9ed0e5ee908e1d8f6f111bea31de9360 +6474e5300f5c2adec0da6ef005a3512c6911773691ee99a6c00a50c2af796ee8 +64760ca5e092f1610e745e8a74a2902fb8669d24d49b4efa72ded358c6f9d0c6 +64801364f85b9c722f91d3b0b36ecf6322bbfea28908cd61cca4fc47299efef0 +64809cf8b782529bac4855853fb252de53887ec6c60d3ab4b75b087f9d359a50 +6481ef0dd259bc19fff92d128d1ed265b082e2d0bc15a8b09a50a3cc3b00176f +6490019755e03220857d952145903028ee16b3549893261a1ee8bda19fc72700 +649838b3cc9a2a30522ea0fad5e85bf6cca26193fc01a98208adf61c888927f7 +64a78c2613052836571480cc5bae8630ab153a799f8764964152f4bb5582701b +64a83114e221743fada9f2b2a114555410c01a018a2ca1ae036e225e3667a104 +64b510f92a7272fab363ee33467dcc8207dfa30f37437c4c46eebc8f4347c6ab +64c2d42a1b2b64407dbeef952e1c38c474316a9d51ebc69d3341d94ee63fd383 +64c3250a7073b34eb39e7661096dd266bab69718caec0ec71efd0a9e221a69b5 +64c83802f593501b1f546c0cc571d66d227c57837b80beb6e0eee7a9fdf2e036 +64dff90f0725111a0d89df1e66684e8b4c85f2925db5f17a613e5b5feb3c91f2 +64e667165ea9d802f3af3b4d1f29ae246a04e2e10e1179d434040bc961259b98 +64f0fbe05bc1a632807e12239fa9fe0ff18557511d214f973d4849f24f3ef66c +64f59959ad8e00ff52145ed374c7122719d89ea24335a439be0000e086d055a6 +64f7556be5c3ca9fa3a240e232141775e20cacd8d851ab48f30dff988d596796 +64f7b134ffe44b0923e9326cba83bdd7d018bde570a5118d1b8b3e29416e3088 +650189a88a226369c79c5b6d4d7432ff2694cbb6e3f960b534102e25744e33bc +65103c50d06091ddd114df913e5f74665d27df5404c07d4ae61db69097b79e16 +65490dc07994d27ce860401a1078a82a022d54229516a62d27ce0638fd15049a +6551f57a8fe2858db85d7d8aab1649af9f8c16661264716b7c223c423185592d +655659a8d484eb5514b0ad8033fe4814a1a2f0f8ff4a18c09cef8ce4aa9f4a65 +656507b85bc044dd26fb05fffa758ebcfc7ce298147fd5717b6b149ed6df9f6e +6576c09dbb9ab58291cf9bbce71c1ac8777e80507a5920aabfafe7defdd7ce40 +6576ffbc65ee0050214e7d3f78320ba9f57deaa903ed74ab0e542e85f06c867a +657983d2cf53d0ea72da20b0fce1952094b1ac499b1ad602b7144eb5384680ae +657af8228d3fd85fc11d3ad4e8de97101667feeab3b20a715ed4010a0d6c391c +65806142101ebc815697a0151424f0abfdbb86c518092c6f4bd0b96773dec843 +658d71c536bb5d29b7a2d4d25cc460a0c8513ad3776e4bd838d77e5b93e46e97 +65a042962edb8fbb4b45e3118dd190050d0f9096efed6d527db5c64b6a560141 +65a088295cefb58a4d356930b569f14ac6619ae21d5862ca6afe6c9b0e58111b +65a2ca5ee3bfc23d51ff8cafc6fc826d0ce666bac12499d193e74eb914a479c6 +65a71505d15fc03a8fbcc5fd0eeb185bbc5785c190683d2263faa9ccd59a35cd +65ae19211f09bd8e149f6f5abb5a0384707dd7b9f4bf3e66cee5afafc06253bc +65ae9a175db0affbe91d7212879bf9eca185c4dd971ba5273224b60af383e21c +65b63836dde98ad89ae08708f159cda54c31971f57ec0393e03e5e406683a9e6 +65b7324e1d4f28b13fddec2415826de701f2416b601eae94fcef95a9374351a5 +65bf5a80291bea917e08de59e336d3555421fa9730b8b10aefc52a518d22436d +65c025e45012a39cbd0e00fb7cd0700825122e9bdb167dd6596108e87cde583b +65c514dd8bed5ba8c5d0b70ecde2ba60f8a990ce6a603cf145058cddef58745b +65cba998ed1aa74162c3468e5026b65354ee62cc08071b13e2cc38806d2e87d8 +65d6e654b58ded84cefe7becb8e8f97e400f8bfad912935da74275937233b8e9 +65e0dc6b3529f625cb3ea56a36ee3c13fd8e298ea8634246bf4bba6c95e66507 +65e93457412bc4c835ed7f0e22156f84e8848bb78c4e53c3b3fb626d53010ce7 +65fb3fdf52ba136d42f14cb8596a6f9ce8db8490a9f28553b982a8717a9871aa +6606256a57e480d72645e8f66058252b9c4389e6d80a1780f376e3fef789467c +660933d3779b1724cd1bb57b57647433048046b09b7072d36f84b1d98c63172e +661b6a2b10ae0ee10eff56bbbd99f1e34c5168affe74b00789e6b07fc2286288 +663055e6f7db4f3d82b038849b63a1efb3920526db9391808246aacd85c94138 +663f2c6a97fa4715751441d59ad0198fd148c71370ea5d444da08cad0a76d623 +664323fd6f19f794ae8b5df8a9935ab1aae0e5025115b7ddabb68b74be9ac428 +6645c5fbcb88c3a475ff66909a999af650fb1cdee5284b4de6818a4a23d753ee +665014eab948f82f781bbdbd5725d3331e146244056dcd61fb3ae8c8cbfd270b +666670f7c8df4c3e28dd6aff0776b7df8e056f24b286e55b40c89556a6827b10 +666790d1682e32418b047abbc9cd27a4028ce697947b9d1ba865847e7712f477 +667eae83d8c101074419e7f198a9ee0c1629909d3ace4d71a1e00130444d7199 +667fa39c52d919e54fe3f74b6cf53d9a927976ee346636fe64d46a2a18d846b2 +668ff4924c7ec1934d95b2bf8216cfb5a4de274929866d2b22d965b74699512d +6690803681cad739a22e0b08eddd70c67367e145b7707f0b83955293e66889e9 +6698c2dff130a4bf316e24475e84ab03933ca7cfed95fc45fc90ee3641ccd11d +66a50d6f4b03dd197d5918125e8b08da11d9c34611a750255a06cc2350e1b1b4 +66aab03bcd8013f327e64d4fcc9e63b9143ce0e00c6c93b439a69272cd2232a3 +66b815f602c4f6705efe6b0a31acc95fb7f9fdd5ca8b9c6204d625a33f874d41 +66c3928dc11dcdac958ce5bd2533d44fd172e2ab25de55abe93dbbb0500ac298 +66c7dc83c1130215d62a960b3fe533a251e16addae63422793da944e33d90c58 +66cae1d4a583754bc1e4d9f257dcb2a2c8ed0044540f2b6c263d8dcbc33f2208 +66ce386b2d7f885e4a47278b74a64c874241f4cca9cf659aef85d180ab85aa8c +66cf71225f9af5d2d02883b5145b186ddab65c3e524e79f897e5efe5e592e89d +66d2e4f1c355379b01c12243d459999a59c05f6a8e4fa7b73b4efb4766fb0665 +66e9394c1c192ce5375b70fe37c628b4195ae933cea1252408b0339a77c51eb8 +66ea473fc38a87d503aefd9166a497395164a66cfca75549eb97bd4c2568d878 +66fdec063945c3cde3c20a0522e5ecc794a80641d8b788de63ba917bfc1936f0 +67016d76edfd9de94807cd91449db1d6ba295b7e0927370d3cfcdf4064fd4dd4 +67044defb061874ceeca24c6147e168f359fab873e48322876d9b65a4a3b31e3 +6714f157c69e0249ad777f4f811aaf7a4e77367f80a236f081c65af36ebff70e +6718969d8372d90394ee2f69d816f9cfc0e6acaa07d00f5683c73fea9f2321ce +671a208481fb7aa0bcd3ed64ef9b83a11002ee78ebea2be04b31dc241aaf9db9 +671a7dda336035bcca4fc9a64bcc1b738da3c605ae3034bd3424bdafea2fc6fd +671ad1d59ca86dda49b80adb02bfb5f199b23b2880845a0676d3fa16100e2a93 +671ad9b7306c4e563be231182dab3ef33e615dcda0461bd467b345fcb5c1293f +672924bdad8ad188dcc6c5bf45e347ee06416f5a684fcf057a5bd69bb2283fdb +672992b067ba38f2e353e67382104ce8822ff38f6093087c8a17666a33899d94 +67359ee3e0d044a109e3795fb1951b1dbaf33dc1f7be14ccb37772d482f890e1 +67378c81eb74f8f0d3f26b04e739e836286249171e7cd0ee40bdc4cac02e2ef8 +6753ce679e6f3becdbf040f3563b91c5c9e6d1817e914a8b5a0bc11d497319b7 +675acc8fe7cb03f17623c400bca1d9611b7b4dfaddd19430b04631569b02c25c +676df5b5f705dbc555add00b0b994bb8fc5526e247f481d5e18c93f911267781 +6778b4a61835b589f84931b41969ab862972d255485e7071be5f7ba5bf6ed178 +677942a0f7484d97a03a69d2bc7f342e6537c5352b0577d6e90ed5b03876ceb9 +677c55305584698b8cd87e039096b3ec3a12b355cf7346c93592316ae1ddb5e7 +67856d2c476840a3d20cdf76da0c6a1a8f505a57ee5b363848cdddfa3b4aec36 +678a47c916f731c0ccd3fbf39bb7f15572bd7877ca40a794bf1c62626e4228e7 +67a7610a385e5f81aad376c2ea4f0d8d648e5ea5457df93d7568dba719e97cb0 +67bda5c528c0815889ccecf534b436ea2e807083eb0353a47d7bf428ba620dc9 +67c624d5952d551775bf96f2b7e901f104f0171213622ee32dee266d480003fa +67c9a0d985a732e27fb900743f4eed1d33e947e47ad662c8a1d286e7f23df451 +67cbfd923aa4b270547b5f22079f83d9aa1de6243af62ec393f8c1b4bfcff4db +67cdbefb06f967e79a52a54ef71f21cebd86c545934bea0f60a265bab3d712f2 +67cfd8b12b1759a3e0f6991ed77ee7d9e90553ba93677e8074d91ab8c6330b0f +67d8ae12cca3096c3550846b65d0e2dd0fae9b25a3556793473fff5d88bca1fa +67de7d73fdc7e6c70196e781662657368c215861f8cd9c61eb6e67f5ba72066a +67e2fecfac3b9d6ff16189f6f5c8208844113c8db687270b27c2f608d48d8215 +67eb40c3fa680ff77078e0c15f78c64722d3202f82be03e86a6420962bd9161f +67f90a72e92b40cde583b8da66bdbad3f4b7c9ae086a98af179fdfe51879fab6 +67fb467051b9e4ae75635a64755a1247991877db2033231cb8f239d3d946ba1c +67fc4cf8845e1d7a1c1a47bd20389a1c89e17508298025eb200b40a179937ffd +680273f23ab8e2ec4a80765161750bc9fefd11c33205ace9b9790fc2aad36003 +681c06c74f1ff57e893c98bda0c0bde0722cf7d053d799273da5c58c632aca7f +681e5744a8544b3e7773aa856720c5d71e1d56b70997a6147d253056cd988a32 +6827a447d85df0c17e9b300ac8bc1f638770e840dad76a28fc7154351dfd5e30 +6838c4a41ea2d720ac53ec8b1e671bb8436e6058d503c7d08dc1441efcae1f32 +683ad98ee5754339f2a74ea8c334e5f98a0ca0c42d67c3c23699a8ceb427d060 +6842e0f715e4e9371c85b5391e3083f2aceab84c59b58050e940de64b887b44f +68551c3f040f2ad1616ae3303fb71e189658d1e3b91759537c015e066e40b647 +6855a94657409ef3f3b4b4e0f04d4ac352ca0407bb1bcc91242fdcf4ab65cfbe +6859df0ceff12c394a8e813e3426c8d21ab19d477964ac23e58119c0272b7026 +685b52d6f0651851588d293b07b0d85c8d160e8f0bbbc4a834b645556871a452 +686309405a0d7a28f37fbe9cb7c6a69bdf034c0284bd222ed283c49a9902380e +68648e3baf5b72d50cd27a61ff929688c046b9077eac0c3a3ef6da14d7df3f7e +686a54852b3a61c1fdb98d01a6f1d8e6a3d7d9ed25e9ddb11a70d83baa9de5d9 +68701ddc30a693b2851167288afa219e976452e963605feda5dc9a5323a575cb +687c57645a001c5727db4a23d62e97e2f934be7edfe40d42ef18d12554e899eb +687e3b0b9ee9bf527c4fa0c10f2cd7716c008cd0a2df2ef338592660ef0b06e6 +68842e1347340ca0ac5bb31f68130f18cc6b98f22e8d914cc2a65cc6d2d4910a +68865659da1218916ea016a0da622e562993045952cc89fc2461909b93c3b54c +6888b8d2f0d3e736b5fefe03401eccaa0a5bbd7bbee1e70f95064e68b104aaad +688908ea48e0f375abda62175b58c2e4eb12ad304df4fb690f6d03daa83ab2d6 +6895e44ec80f0e75b550fc0f38006579beff6a73fad00746a6181b0ac856e434 +689b4a18ea75ce12b0b24b2d237bfd2f17f8fc3162c1706fe5e0c24dd706e60e +68a8f97f5768bfe9da244306857a3e76df6e3342d2815de58a4658cc95de7846 +68b574da1729da3d57315bd45e8002617f3fde2ee0e0b158dfd4d85e3e9d0bab +68ba360152ece847b9a880a3d3f837c8a075b8588de2b9faf58f2eb64307e5f7 +68bd996b833292645361f9c3459700d7111bb3fa762ed7a2709a3aa7f1923e00 +68c32dd952dbdc9be940df63411409e2d7be2413939f111713749307238db2aa +68c6a84fe05b013841b99f9a565ae389473c8a784e1e2c1a98bf3de6e74baf5b +68ccae3307f1ff17e5feaece74b24ca2c55bff3116eabe09cde111148739f3e3 +68ceb211b8ab7f0eb24067819f8d0579f44e77ba5db8a8c4c55366b7d2949b5d +68d843c105ef65da95377a992def9cdb2a200370ac8ab6655faccd8e02302144 +68d994d4301e1d1d0ff851a40d6abdd51f91faff26c167b780e22f8eecf0e805 +68db58ea0798f61329c98594433f7e150ea28e04fa9cab90072f905cc76f1274 +68e0e25d5d77c7e8b74175533651648eb886789ce3ebdab10d2ece58f4e2612c +68eb67827d441d13be5811676224b8f92ab6461b16e9511d4924754f91ba8366 +68f39a5e2d19cace699b78f5155ee54e6a848c5340deb06943a32c8c3ae28702 +68f6886d1f172bd68333e2862652483ef3c555bdb5e2ec9fc0885145f38f83f0 +68fa2c23683c3db750552e7fa7384d812b957b3817031cdd616546a0917c2525 +68ff05947974193ea80fb3b08085ee9e59b22603b4e36eff64f7958e4d1441ad +6900f21cfa685153546737ce9ff65a6dea704c839a34fb5bd03200180ea50e6a +69064af91baad4eeaa5299a7bdb246a0269442800d9e5a874caff9b0bcd5b71a +690f4ce570b483534899aa092a6c7a13967db69540cab93e443089e3735f69a4 +691ec2cdf2a079c35059112b674d33307ee4261f1471268e709162e7cd5797a5 +6920b1c0fd0c1f2235ff56a57feaad3c89449838fabbc1b2ad8288a10cd000fc +6929707b6bc749b5fb0c8cd439c2822aca8ba68b0b179203ac2dcac5e48758f2 +693028a8f5caf65b12d5756e05501fe834b04c7270a9ed9b519cfebf4f0b8e20 +6939737ce97e4a9da9d23f0d674b1941d2fff940d6b5b73530cd6d082b395842 +69427c9b239caddd6bd2ccbf74a666f029fdcbb120adffcdc6fd5b6f82043e30 +694ecd5e438e37b7d565df1bf48f3790a13fd97fa6f1449a63df00fc13fb2149 +6958161bd18e2abe5113cbf707ab77b8e7be5b42bc69d91a38498e4853de00c5 +695a24ad34fbddbc4b51cd02cff6a67dfbbdf2069b6623d65a98429b16510b02 +6962e65b6f0f012d3925eb3da6338c56ef83c1c765379717470baaad5f994d58 +696bf32f0caeb5dfe4aa834083648bfbf5e64505b32c7f453e2bb9a2b8ad3d26 +6976e39de1f4ae91a60d48b70e5632f4c7105900d62e0f3fd0de2a97175e9a41 +697b82e618cc88b927c1aa277d872d5b29643da1294b8cd4a665c255380de21c +697cb515c2dda0ef4c08db4788d9c41198c24e10b3e997bc1abf4245f6f08887 +698983d5e3c02f79f26736975932707fa4e39f7172d5a4b4357f95317b0d6b03 +698dfa853f26a7fc20ad3235a660e6ac6d623d51d09814e04881563a743e71bf +698e3dc510ba7d9350b39898a33cca2f84265600e524ebbb627314ddf4691ced +698e65f8b7642f3d8d2d5aee968ef778cb2a4ea15526a07b6a4699ee33995f6e +6990dc2e259e597ceda47bd5dace00ce7764d475873bb56fc280c78159a9f87c +6995a324b129556f467a7f5b807bdf3bb4f4474d0682ba85e170375d9b7e3d36 +699cd5dead6c911ee72f230dd780b6a9de6ef7f2beeea05617cbe2b0adcc097d +69a8dab85426f2b9655203280b943e229fe2afc467f54288643c8e29ca5b7c15 +69b34b030c139259eeb8fbf87d33e1e856aba87ca0891b83385f3d535426c454 +69b39824874d5165a634011f31b600e719c6fe1ec9860c76f476682d60226494 +69d1ed2ea39f7b91e8d91626b63f934e7d283b699512c603180df33e4da62ac0 +69d3a9de44a4a017d9263c287d6f4129efbfe2766aa2e89e5db1e18e70057186 +69dd335cb3faae89a5b92a0dcde5ff4b1788b956e41e3a35525475a4bfe878e4 +69e0819bfdc35523215a9bcc4618fd19c23e24dfe11fd245134a43fd1836eff7 +69e3a95d4aaef5668285d820501ccff978cc972317e727cbe0478bfb987c34f2 +69e46dfeab1957c91db823e2cf939fd8985a95c1542ede099a1dfc2e0ef58fe7 +69e54c4b0b36656385e9047c05cf2cfa9e7625b6ffed6b451f5383a401ad6fa3 +69e8c1ed92522a3a5d2e22c593601583dff53b100079a68ec1bfcb91ee14d291 +69ec2165aa653c2d0e333a7b535abaf1c82a395562141ea0e3c360069c53ed28 +69f20ccd65c28abb6894a3c9fb4937104cf9c2f4df561e0f98b5c6e67ee303b6 +69f344721d527f213183e97c3828461c6b6c748b8f02ecd6c5e49b7db25180ef +69f92da7148037ec2a81e001c27242f3b3bd5a7f92a2f06c7cb7addfae3af1fb +69faad1449307c380add928aa0faddd86d8e4b49ebbc0eac2868b14fcdc8bdd8 +69fb875aaec7d2a3187e7e7ad41698e5853dcbf185bed85bc9b0878e2dae60e4 +6a03de07583363421541c72f26982d51003a77833120b9e7cad1fe188617ad8c +6a05f79655dd506747c460742de4274733d5fd1beaab503262e1e0a178dab5cb +6a0fa6d73b799df26e0bd2d1b871b60d73b1ec5e04d95904239498ad08afbf1a +6a15194b0396d92e8e2ae0791f8c4c783f01dc5c320a75e87007be34b5362d9d +6a23b9711a5563d971bcadbcba49c1a34087653f6114daf80e2309bdd058a3ce +6a361c487cab49cee4446d5fcca5fd0fb792241f25492b4ed1c53a1158daaa64 +6a37b90dcfb4aa347de061e7ad879d4911c540f989a77b0ed6cd05927c12bde1 +6a3b4e80ff50107312a0d6870790e1fba29b3f538bdb0714c37f376b4cd9ac2d +6a404fa96940245ff0345c853e8361568b2fcf8451537083caded7627a64175f +6a46e6d76386faa5d5c77e4ff6eb5468e4df7e4116298ab711010ccd37a1d261 +6a56cbeff1347aaa7e277c1f72739aab2f60f531da129304f78db5885dc56f25 +6a5aac75853522c81bfab8346a86aa43769002152256360b9b4e2c1172375124 +6a5e0aa012e338e595a05b686779aa4b113d36f1368f7c131a55d2a7fddde1bd +6a5efe5fd852dfe80fcab0d69153e8270c12c00cf93d6cbf2ffbe173a12835ee +6a651078a9d4e5773fd4a89b0e0110cd1b81e1aef539ef1a03229ad0d7464575 +6a6ce58276d00c34feb3db6bb384d14b9d2135501d1bd004e2bc0a7408e3f269 +6a6e1a3223973ed4300136f566395eda1782ffa7121264e6cc768821f9c00c6a +6a71b9e61f94227cd35117b51ab25a2ce3dde45ae131735b0e65779819e455e3 +6a8f18eb35455d35659f50f33e92df51288e71ccfdc32a8592e08d6d03bc5a2f +6a92487fd86b9eabd4cded9afe4b8343c23e62ab1a7dbeccc4a5bbe03ab26439 +6a98cabeff53565e34f88528454d4947ab75ef63ae3f62f65a2d20e49af8d0b0 +6a9ec4184d558120a80a05b96a1886f1bc992eb4775be263cfb1e9d77c71a0a5 +6aa696c970e2b7518f0e7f95cadcbd58bdb6c7de2db42e39e3650f50b073c189 +6aa9b747ccf024b0dd7a7a75cf16b639961d066952160b1f2afa571b615d0753 +6ac025d36495f29a0476f74dc449bd84619a01f1ab843d4746d8df45687e7a48 +6ac5abd74897e3f6a54afde53b319ab548046f0241305dff0e33f031ab36e350 +6acce706704a0b417da0b7190d6d0e8ae94c008c152710180ee3ea5af7527ee1 +6ace3b7a39912e63a3eda1d82fe3e6aad380c3e7949f45ef9416db43f8f87030 +6ae130505b0ae00f5a084fde89420ffe54fc63d1973559cabc49cb9cdf08f5d4 +6ae560e9b1a7f2daf8fea6ba22444df397934e7232057ab2338a404c0ead0704 +6aeedd07c760e8a2f2cc46751d57bd473137dc9d287ab3848f98cd160775aa09 +6af0205947aa91be146b639023fcddce33d176915753285adf81cacb0f83eddd +6af5d1d8c74bd5e2f2929c083135d95aa98eb18df5e32e9e334c4db95522151f +6b02fac902adceb3db594a4b8bba8687498d7da1d506e265c36bc6fe3348d4e2 +6b2a6bbb9a2adbc48df09312793ecdd9b888f65abd949963abb989d2f7a48316 +6b2a852953bce89207449ac2687132aba27d9e99bd1a7db8d8c43d15bd3893b4 +6b316ca55a665de4dcd497306c8a3a33d2f210f898f3d4efc3cd7f75d7e5f5d6 +6b3a5f230c31ecd47b3ada227f2d82c2faf19ccc906188d8ae7256d445ecb6f4 +6b499442e2bda2f344993d96780eba25cec4fffa1da0d3d75ecd29a0d37b35bb +6b6116b8d308f88d7d59424ad3267ea51bf4a811261b46496e868a7121460eec +6b61fd07a9edec4bce38a70c9d7543ba304f434aeb2bd9509af84b62f08bd6fb +6b662320b5b41f7e024a3dfae6a9aa4c3244b728879ef225268727ada1b42c39 +6b6d101e6e3c63429edf76bc9a0dbb428c436182eb32082f30806e0ad98b87c4 +6b6e5b66e0c151be4799c823f48bcd4adb397119235a4c2cab3fae2cbe5195ff +6b76aff49934fa5612f0257ff7b38b21d6582eed56a430e334fab17b96009474 +6b788b1696e70716863e8993d823039ce2d8cbd51a1eecc00b0dbdc5e202ae3d +6b80bef5175aec05865b51a73dad45b0a29ef7a3f2f8f0efbeec415e36b5c355 +6b88b52c9056c60c3113c26e511ead6551112e32b29d4d74844c4906cc0b0194 +6b8ad534948b842c4da8a358119cdf62bbdb04bfbef8e08f3b0047a8bbb05dd9 +6b8bd2138154a2a31b9cb9714e8f229a0e733464ddef92e1b651019bfee215d4 +6b981a1f988ae1a465edd01bef651952a84c7ed80ace8026524fb9bec29d853a +6ba4bbaa3d373c808ed06b387462b96d9e2365a9213dcf63aaaabaebc0ad1635 +6bb2782405a47c39e78857622e0a8830d9ab603ff356dc1d70eed231caae4dea +6bb3384e3447a62eec787e202fe6a34273a210b4593704ce5ecc638325390a9c +6bba100f21226964f7d3d69aaa8f61cf4cfc2b6ee1d218826656687d0f583e51 +6bc27efcfee892c6c20d0172760d8a550eb29d708f84b09d2f5ad2e3f87292f6 +6bc2d613bf8819c5fc154b048a0a613fd0f5f5986f2acc7a0adff0e591ff43e4 +6bc78c71a31ed6b344f155324abb2c304c06b41687e0f3e5fa1c97d5b0a772f7 +6bc8b1e36dbd4c184d435af19aacb2850d6242482ea0a29a2ed42021d19d6a05 +6bcae83dca1e521a0ffdaf7f0eafe04f54f964fa6c8452cc7e6278aec2201a70 +6bd933b3fffe4d51bc9dd08ad10a3f31b3583b01257b3bbb7f95f86a37f21bb8 +6be95b5ae404cc430cff337fc143eb3a6aaba9b26d3933e0334a5525752a3c7a +6beae6f227b0025e977b4f09f122a13e51ea0c456c7402743753d5f2dd1520e0 +6bf71d222d08ab9057bc4487d4477aa465e85ddc86ca54f43415ac670fd58a07 +6bf7a5cfa13f895f75f45d9467bde92e7a8f12e83990d730af2afa5df7fbefd6 +6c01f5bb8c40256f3f53c207e3877edec8f0238415b1863b7ed704b46c797c4a +6c031d712ce4ab8fd994226f26bb7ffa52ce34ef32035151422461883ac0529b +6c05b10396460fe7d94751ddf463077899230e5106ce131e9bf1dfef6a707188 +6c0a5e3071a34609fa58ce6ee1f06cde84873822df6ef76366592d8b0076fb35 +6c22f1c053314ac47120ee3217d637402cf0149d79863f914eb930a8c05302f4 +6c32905239920fc1bd9dd70c01462ed976faada718169ef28854346b00e9e6fb +6c38a67dc99914be9827558e03be25a4cea308db038621a26bcf113443b31559 +6c39431c5381d577172a7aa6de06d60375d3bf10f1ba9aec7bc0cc7bc1b19a46 +6c39c5e1b1b021a5e8a9378d628183f0f66128ec38fc740f01f2b03b95ac07fd +6c3a64cabd5a3f0cfc1002d2e615ca1412792a79c2313cbf484a81f85efff24f +6c3ec0ae81285b6f344c1f67eb9585d1252f349d64068e82ed482f5bb16f92eb +6c3f37b99d7d3d0b0ebbba6fd5b82aa895124658a62a698f545a26b5d7c6f222 +6c46892024f6b73ec335749f83835a63a5b708275ab9d32f3b6c9087919da56b +6c5cd60e37f18e4499b6346351dfd4f0c72316d5b8160cbdbe6b0c2eee96ff30 +6c5fac9d91d9c8036ce04e07a74042dedb52bed534facfad3247185b314340eb +6c76bf8de298411cfc63c0bc936cd4df38d5ecbb39eb91c9d8b38b6fb448c52a +6c8ff32c42cf5a4f96cfd7257222d6c5f0093d30b1eeff0dfa072a2cdec261b8 +6ca2a2172fa9263668c58f80a4ebcbb6ad3e9af9e70895162d92feee6352d98f +6ca9c928a8cdca347833e29667981c99b2ba87a46fbaa92e555f89a7407409ad +6caf01c70f96e0f295c754bbb87011de732a42721eda1d95f61ee26c16ac4807 +6cb383f7877b15c66b3a41468e1cd22810f66b08f967b36d04029af987577b05 +6cbddc8a93844ef341ca3f5cd70f6999c0ab5f64ea4c2254fdd5cc6947e66f46 +6cd0f0b8c421b5c0318efcb5e68194fed35f5b17f71b443b530eae444d196e68 +6ce40d768a9c1bc8094697274a25ee109b54589de2f96f659eae6d6b1ca3290d +6ce52196786150bfd428a3409c0c2589263d3d21e38b8ba5c11c3af452fb8308 +6ce5282b086acbdf1429c2e888a1e9f9e218fdcf9c96f8066add5fef37d665e0 +6cf06d6405edd049b83fd4f2047b6123466bac304add6c1a2ac1d70f3aa375ae +6cfd0b231ef966cc4139ccd420df8c78f64d19451f2ffa11b7d699ca52d6795d +6d025eabc9a499b085cb433bb89e3978548b0d3e2af1d84bb95950e8d68198f3 +6d05238e22289c9cca433130f6a4e37c4a835ca18c90ce74f47718ac11e02046 +6d0e4f3578a836faa0004f22543059bb96bf98640de5b60b682c4bbe088edeff +6d1059aaa574025baff8b9674702cbb0436a657671a1141b57427899bc45edd7 +6d36dfab38e13285e23d9df40723cb3a3e6a7225b8817eed84cbdb8f05cb367f +6d40cc589bd942aa4f29e61cdf7bb44e47328d62f289a009cd1915e1fe213ab4 +6d456b6f4b73b5e19964bc29287bedea2af1d91af646fe0f34fdc7d5b692c1c1 +6d482f902dc2a906d3327db35537e6ae3c8f0f9b080224c85a566d42a1e7bfc3 +6d52d4805e0cd6dcfc443cb91d1df4368a8ec0a593232729498c643cbc2d08d8 +6d5be59b35d629bf4562febf1c9425fc0855708ba4f4fb7fb96269d58ae67643 +6d5c69f358a95d2855dc722ec0c54042e10130ad2de498cf355610e6345db805 +6d5cfa35db2339724b894df53c83a93c9cb30a15b1a0f1cd1b14bc15d5ddbbce +6d5e47cddfc408af56ba1f4dcefe3088ff03dc750fd570956f995442741c05fc +6d6470236a3c7d20285129f5d5bfc88bdae8fbcbda7a9f7552767065077fbf15 +6d6ac9a05c42e31b007914441ec18aa638e6e8d5a2c3bf74d46ed4ebd8047092 +6d7a36a476c1d8a125dda7efe018b487108ce18901f0c3cfa2c3c98e8697df54 +6d7a6401e84de777bf2c099ea404858cca655b5643822ad455988b923941c26f +6d7da165c2792967f3fd60c101ff6c26b3f06c11cf1f02349afabea9703bd7b5 +6d8588af16983b078f9f17ac7f056452bd68d218545203668ca96ef1ddc7fe56 +6d974c0e20cd2f8bf361508a02f94f21db32c6263620b68e1325d4d99a064f4c +6d9849798cf05f2e13f2434baa6864cba95908fa8c586b303cf69bcf52ec996c +6da03409c657d5e0063b64849e616e69c11bc46974d255ad8ce6a1af546b6892 +6da5c3f6a1edf1076acbda13660e6ba97f1ad42197a7b12e4c519bbdf391f2a9 +6daf5c0b15634ce8756c8d66f4162556deee6ccc9cf3d5ad7f54eabef2f315c8 +6db21be3bb680d67413c8c2d6f0cd7fbe9444b7eb64f19c4d0d5ef5a6be1ca08 +6dcb005df37e7b0f450fe656aba45a92f99de5d77ce3d96850f25264bc8dbe01 +6dcd2cb8fb89118a804454f1b1b48a35bb2995af8605d3685fd1c9258e8f1e89 +6dcdf201b6f895a0ada9da5577127e726c64714eb3135cde083c93d201303c29 +6ddcd6f83a1fdcae6f66cdd616933b7d7e0a26b3d883a09db4ef600e7ce0d952 +6de35e65ce616cfbfb84bd6b91f43dca127701c91a7a4cab09e6bd9e53cb6646 +6ded36d301996d9accb2fc1b864148a428bc48c1ffd53f8477dde5c36903d8c2 +6dfc7f9c23f25d183243beeb0690fc2e1e6cb400d14fb11e6d785ca2ee354e79 +6dfec56e7aaefd80b1fd2dc621334ab9944ba38b7ae16b926f7244a579d5c96b +6e058d102bb752b018e15cb64b604436e84f176518f13f3be77302a10f80cb78 +6e08983983d992d8e89e435defcf1d17fec042594c62674f83a16102874c3f69 +6e0949cf67e40e3fdc7e9585f46c5a7cafb2fcfa14546abfab279df0230dc5e4 +6e1e4e8d01f2fcb896fef6bdb8aa40bd4f2b6de9c2aac845630fe5d5030cdc40 +6e23ecccf332f88bddbb4e83750bf8c28c90d2a4f73b978dc30cfe8f3af1a71f +6e2e112af09a198d82ca404478e185904dd9f90274ff4321edb0d894278935ba +6e47a56bd79d2fc63a6a02cc2f0e6a1835aa02fa1af97b959a4c73ad46bbb137 +6e496600e31c6eda3ef0415349169917cf596b748be2fba1403a8e6f13f4b3cd +6e4f2b4df712bb918e3753ec03a87716317eceb6b8f5603693d53c29de584f95 +6e57c8f620b9c2366353340db95015f613d151cf0b0e27ade9251ffc8279c928 +6e5c68fe951ad17da8bca9868ba86509ab159cf3fc7b36cb2a425dd2de81b1f6 +6e66b28a4abb279c5859cdd2dbd2e9b27d803f36690dc394e647beeba01131df +6e6a01dc3719da6bed956cabc99131c2702657bac7ddddec1d18acfc07059bec +6e73d68710a661aec9f8df3915e4c51b3313e5ee21478a4433e5909369f6d2bd +6e7c0f3649c9fb52580b39daaf318c3e6d747d8162e1591af08c0b267eb03486 +6e7cbabaadf558ee0f6bd14b596aff059e1a362f1f0e76cebfea4dab23e932ed +6e7e904af3ead70dc3fe2592e1ed387f06fc733a50b9825b800f7e748ef01872 +6e88d53a91f84db9af862dac2ccf473a3fde40173048fcbe1707e1d964395ec3 +6e8ce58b8599f409a121ac09d2a2bd0a4fafff8341fa7173ed9fed5216d0a296 +6e8ee5e047ad79edc2fe5864dd628687ab1790e5367e0f926138b1b30ade2445 +6e9967bd11a8e3fe7a2667394207a10c9689b9c3c3bfd92f2d0aa7ee5ab70a73 +6ea6b7084a73c2a63bd47f080c4a2970cfaf4a1740b666f25470cc3ca4785ca6 +6ea760278d11397f67113f775764a09b51be52e46e2ebf7844475b292bca7d56 +6eabe4b592a27ec599e06fa2bb7236573920fc607882733872bcfe3d6d30076f +6ead1a90da1d26560bf028665988b3772693c5b542ccb5ba85c9f0e0bb82369f +6eaf202b6388d2e4eb8efc913f798a780ffe38279aafff93ce58864c3fbf6e3b +6eb08b1da7258310b6e630c4432fbea422b863f0ee2b4dd88c02b29a7694652c +6eb23c2b56abe5493af35c0a7107a80f183ce7bf6789d751314e1f8d045f9ab3 +6eb4fa854f00108477c60d44c036a309aca5258b1d94f2548288eba0cdaf9594 +6eb5311ca42e97627da3079e0e01de23453b94920bed4055c8538a848c184910 +6ec4eb57986e44f71c8512e349b5d408078ea28bf059a2fb956566dce9376f8c +6ecc3091d198fd7c16cdd9cfc7f18921a50552c6749bb9311f08ea4ab563067d +6ed29f24cdd6113e07f1ed64c49558f2b1a9d6b934324f7b522c85f53fa40656 +6ee080d942299f59c4d20127fa7a5d08d28c1dee7ac57a6b5418f2d8f185c258 +6eeb63a333b86c375018a0873a4301ac6422e860887a96990f67d182686e6e02 +6eef11330d97c08d4e4c2969fd7cd86535139090684434f29411778b9b685f2e +6ef15a22a5d1b9a6a807d829cd8d04439ad3eb1cfc8bf742e22bb637ed7c2665 +6efaa1215360fda3e6b13232b469310d9b41a06581b3d3eb0e57f897411f6681 +6efb67032aa7fbb50f7ce3b54a5fbf930ac546f2195f01530f01fc40d70902c6 +6efb74bc76f74afd16971103a194c1867385be5b3b92f294e72d208d55a2113d +6f05733b6aa815f0fc73afcad6c34d6c9add7a81ed4656123aef03984e9fcdd2 +6f07778a8b087d6ca69dc47b3bce6cbf70affb974faafd7c44066c290172219b +6f09cafb873f7299231ba9494c32ae9b5ffc8616039ce2de8c9dadf52e5038c3 +6f0d65ce516c55176a6c7af46480d7b4ecb5e32fb2a2e7011829a15f75852ef3 +6f201745713a581502fb14b8757cd1230065713d65da0a052f868abf5dc307e3 +6f2eb1820aea77e81a06233f3ae5aa9ab4994881732b6720f67144777b4f71d5 +6f3617b21df86b5f4eb3b01ce72bda8a09b005d7615c4dae5635b4cd7378db24 +6f3fea44a04cc75620006e222361dc36360ad3ecb11c5f7c6c39447c0af2c9b9 +6f43d147145267e381eff3110353eaa955569476d4cef32b309d43890e7209e5 +6f4501105f8818e4d11288aead9614dec2861d68603463c3196fdd0a49679d02 +6f50f2f7cf42fb5b34bca004b80c19d85cbccf5db7e643e1e804f030bc7db4d3 +6f6b4bd8ca9c7e7a665d9e465596e7763db9f9261f5ca6ed8a38cf982c244edd +6f831bc07cca3b4926f15efc4addb64296df4097ab29c2a6b0382fa563dd9e21 +6f846674e8d602e524708a4121b2db0573a0e2f1237c33eaf778085a1e27bdaf +6f89bc9cc5c9360e1a83bda3430e4aa4ec30634ce9da0a2e4399bb68cceff20a +6f9e56d17acf84ba434b9860620ad29cece63669947771dc11bf912af95b48a1 +6faa2249290fedf5fc466be71717f665ca9241bb0cce72caad940e7aa3cca13c +6fadad6d3aef25981406769b6ca4da67ab85f991d0bb864e0be26aec5085feb3 +6fb29916a1232a9d30d53bdd0e5c145032208e080677c9895794cb2f26152c28 +6fc63ee38ec803aeb9e8a9287f4ccd6b2fc5cee6fd9ae64f7778653c028e23ac +6fe8dff952607fcd119291eb0b21fde436265f761b729da5c20fe0de238ff5c9 +6feb9c1c6b01263b22d3e7ff691bd21aa13e802beeea97dee3c28647b73ba4b4 +6ff0c24e665a6623a74ea854c8976d9001899ae258781d39ed7bb5c08c0e10e8 +6ff8660378b7a6012fbe6b62dc8f27ef38fca83d91512a7353eb4d7d76e6d099 +700178bdffc12fe9ee83f2094c58d6be40f1c353748a4661b0fe8f2a62e0f8c0 +70356d2a5f5e5e5f11e1c7d1fe820b6de04167918750df90e3a8d07d15ed9298 +703768dc8524b7c1b13017dc46a73c7f128b34c1ee6337985f4ba65960713cce +7043e8b26fe257d26f5409fe566a4fbf4470b36904e2877a2e72b91dd40cc4aa +7047d274601743db36626bed6bbdd703e66269667f1aa7eb78cc5a25e9924859 +7050f641d46740a3416b447e0e702c272f32a1eb24891bed55a78c75180ad0ee +70551e05b4acf2ce4f752dce75c496e3e4af264e28fd65d3c07737e8d930f476 +70584a68c07be86d0cecab6132d6a59c380d2ce117da13ed12c75321aab58cfe +705d9414f5f635ffe146d855f05807c35bc77422c3f2771369df670af3fc0a92 +70603d9a3cb3d7e222020580d6c75af19be0be65f4219c85491b8249cbf44adc +7065e81091ea86fbbd596a32c737cc6872c1b17c574420c58cf081b9e3979279 +706d260542e7682fc87f64561c92e43677418f7f7a303923f15b9e6e69623c13 +707bcf081484016f38c4c9282bbc35e6eed60912b1158c574185b575179799f9 +7080e415770879142efd8ca8456a04fd7c43b2f91444e556d9e3d9fa692496ce +70844b71201744750eab6894c38cdbfaa033c9a2ab6baf818a4f29e3db5a0569 +709568dfbe2ab93b47c16ccd43289e514954a11acb579b9c7219a5206b9e32ea +709e62141a4abf384b03045b4c636cebabf13bf4ff2b28fde3e06c62418043b9 +70aa7a960c496f7acf5d7285aa845bb0963f663465f76d0f42c1da85c5704111 +70abc377372f5e0346ee451d95d69b71db9f62afde8f647ce7dad658cc563126 +70b361283302d1c50f6cfbf3cf5f3fd0755ff1df11a3e812fd28bf728f293f6a +70b8d816bcf87edeb52dae41d1b871bad546f05a680f5489b1c78952fa8a7e0a +70c221ff62c7852566e7c9f4671a7c586cc7658e88de7e97e500ddefb6590207 +70c5665f6efbaf1d528b5bbc3a859a6d02648629cd56f27efae66919d9f31d36 +70ca90a694f55515b087667d16298bdb14536fc4a08236c902b0ad6858643812 +70ccec4edeb1003401f8ea034014678c1872b50524a8c15a36fb5e4259ab0f96 +70d10336907760230d34e147a00a66f77ef4d7cdab97c16e86e6daac9f9a76dc +70d1f0e45f6f2117fa0fae33769d4a0b1c0b580c170c3a764135b1e3af002786 +70da315d6d3dd1be85d534f72676805a9258603d05f12562226b0f4ab3a79284 +70db091f3ca1b2cd0c2d20c7c036c5e54f6cccfb20aeb681c42169af3999ba81 +7102e02fb92fc5955ae6067a613b4fd2b2a1b9c6176c257e49575bad45f0c7d4 +7105fe4644110cc9e0d59295673aaa7225348138307cd814209c3906f0a342dd +711e0666e99b19a4c96294415a840b971f9ea7a14ba990a03645537fa1d37252 +712c44661718dc597a4b32c2bde5de499874a7202d6ef82ba995da24dfd91881 +712e1fdf3a26ce0a381bf147eb918b22020d2cf6d22069714bdcc7e6571c64ba +7130e0b71594642ff221547702a5a9052ed5d8969ff657e4f107b0903f39f318 +71341bf98bfddf152ca6296929fcebd2df3009df7b3776d259091a8fd862bee9 +71365bfc9a65a581b9707540b3617ab7dd939546c878440b4c6d913f47d52a50 +713d0dc01c2c822d01142215e70b3b8a2a6ced72bcb96f2916a6059381354217 +714914352ea3909f6bff77c1c66170f5c39cd1ed8a56c85866eb03be3ec1a07a +7157724c1f9c3a42f41f85fd44842a4f8bc7d49097c99c42f13e8e4ee6e8219d +7158af073d512b102a0c230f64fb72f11d8dae127763c37539b0e1f8d08d95b6 +716e59aae1f58875312128f70f35c1fdeb9ad64043adef70d4531bd83d956273 +717aaaf275c2f00e54b6d701274ee63cfe38a0e93e908511f5053b76d02ec1e3 +7189b0c027f8febda24041185e288a3826fcfbc9ae9d0d6d9775fe00c2d20b55 +7193192ffd786d13f4b1af98b7b4f7d46a6b97fadb9ef56493377317ce57b6e8 +719c5f416aad5aa9f996f70ae01643d68bfb4b26e9253f80ec77da47a639dc66 +719cda0b5838f5b459e782981697cb4348e27840085a6e8f48f4ebbb8fdbb166 +719e766642d03d4b0b4146e8ea779394ff029fe34fb86e6b1a4374503c0e977e +71a31a0195e8fc1b54c103effc4bd3bb87e4bc36825fd707e63c7921a6ccd4fa +71a8be4c4f29cc5172cde3cdc32faee4d40afb265dfc6f03f882c7dc42d756b3 +71b4c857876bad0e308630fac800c31f11eefe922ed2460f0a1ed6b31f29074e +71b60f2e47e25172886b4a48a6b277baa215b5127920384e170aeca84bfa3499 +71b6ba2dd6ec028be5e24314feafd3215cbab5ed95f55f327b153181f216bfad +71badc4d61558b3b4a0cfd0fb5a7ca8bdeadef7c257212ea7598099c2d41292d +71bc66d87311f8fd18f75fa327c536263d42c8593b679b049f5afcfb5f57f380 +71be3e278b47755faff90a871e0e7980f012130608e0201c54668c75b1e3ac63 +71d00b26f98d7e3aa980ab577f8791545a34642e409ba36ace81569e8ae704b8 +71d8a3f48d73662d1a45f4d1b25265abc4614e424acb395c06424ca9fbd66a92 +71e30e8fdee6d7bca203d3761b84bbdac7f419cf2a664befe70782c152d7f033 +71e786afaaae83d3490e38bc1b0130c31ff3e21be9b6d352abb184c87327a310 +71e9e51f05185931cc8835478654376981b57307e0bbc101065d5a48ea7f3e8b +71f5c79d29f126a5bf4c9bbcc72ed81084abacd436dedfb12ffe747ad251909e +71f63ee06d1fb03f44d1a0baa9ceb59b3a2d7de5b449e1efaf8e323a7c15a295 +71f7766bbc5b55abd84100c314cba1513c66a07ac0499b05f4808df516fd4993 +71fcb2f5b6082de95fe250ad8d4ee7db9f5c24bbf19fa3031c21664803aa1bc5 +71fda2f63f1560267dec9a7fb856e407d68aec91138a1bbc9f026c4bc121ef50 +71fdb59b54c51ff6c6a80133fc6c50c4a3ba6675eeb95e3a8fac487488a53189 +7208809b357db5baef7ed8e8f60643b6c9a75f09977332192472a884545fefbd +7208dc776d43aed542fda6bfc718ef1fa46b2c4bd5107d3bbb12078b9c7c1f0a +720a41fee54b4fbc30036928a23307c3fcab8db5280782c9b46e1695da7754aa +720a6af7c3f111d4993ffdb1e8a188bf80bf4545070c6c0ee69d42749b011ed0 +72127b66c29d845cbd6ed8f9f099f42a7a8e5fc77d3b738f7e82e0802e4508db +72162a791bfb963133d4510f60d8d03d9eb93c9873a0def6bcc0a46eb1c00c56 +7219d0501b104b313528f05beac11baf24206f321c1ef7b42417421ac7d9adfa +721bf550cb69d22241351a03fa33690bbc04b91d8556bc3f30c741df1a2652e0 +721e3c630839803017bcb8375a1c79b36f5874c4e72d1fc262cff18cf174f70e +72354b88652e4f6a5b838cc3b75b9a4613239363efdc061abbcef67def686682 +72366d98ee392d507cfc2ab3c3cfeb6142599ed4bef7bd0e0791ddd6b487661b +7236e4ec5b81dad4a1e8494458cfdd00dcbefb9496ef0b4be90194032ce03582 +72486bf7b343dc8ce5bcbd1aff76db1c743023a829e832fcd75ef225a64b461b +7258ee6a213180cf912a34204d3371d0dbd164224ccb6195de1a3ca1f536ea22 +725b386c6429fbfba5d19037f583dd8f0d573a4dbd0c62dab52147b358069f10 +725e73093a82de4c580d6cee07e93af705a58fa66e195b429d758a58d46f68c2 +7261f80ede84be8a716b7dfe735cd9a0a8d5375d84f1ba3a35fed742fd168237 +7272d2e145dead2ffc755fc4679fb014f25b3c46c2a2b8f653a508fef806e1a0 +727461e76a1aa6274367c340fd8ebbd2ea08e9eecaa8ee7fad15da661b95a0bd +728015eb171689d8cab6a91e30c8577383960498a8738d62a117d9afab1cc4df +728138f2e719edc39daad0c75a56a0d3ad6508c8d5670efd87a704cf8b11b214 +7284b7f39dccb039181fb6d17415eaf00a627c219a5c952027329b4da12b29cc +7287892b76e48ac74d8965cb4aeb88831d802d9dd23d41c6dbeab70955672b34 +7289b5c62f50a4fd14715d7c290e62cc0355fff385f7fbc78e9b806815ac10aa +728d2b5f99ad1b649f102ef8b5089438a09ec261ded3340d968a06323a8c4f6d +72965e5d3cb228c9264cb69b2ef17575ac76c7b23df5a753198363e56a86a604 +729a5f2eed46cc929abfc25f7835422ea9169eadb3694c0510ad8fd8d0fc9304 +729b30d0033d00895e749977a7b1b76aa15c4ccdeef83b62f3792f14705377dc +72a1f93b78a47c81913e0d77b5497b7b7b6e06a40f231d18ed67e0a5ffcfcf3b +72af2cd73ff31ffa59b623322d7414969e7e5ca3bc4d8dd9b60a9e621214febb +72b492b110424e63fa71696121ad5593efa0eb3631c7766c7625395fb684a533 +72b7da18f2242c31a6110fd36c9194eb8a5df001eea53108d5721224e54f4afc +72b90086f95a200cfe83450e7223041bcff11d76ccc35ead582c3ab67d4e0834 +72ba52372b344c8bce29d25966b54f4e9576ae0ca084128d3090422aa6b76eb4 +72bedad8c1c89eebcdbc995ffaa2eab422d14e94722e318589e460e1a5351700 +72c6ae9b7a0e57a899875a328b0216fd24a0ab383697f07fd132439cbe53ed26 +72c6b70285a74e45b58e1f9926a5023985190e2c0a8abeef56ecafa440f78706 +72ceb3b1a161f5b3ebaf6692933cd6072b1e5bffbe686f7b854ebdc222d92314 +72cff9780fc45b0565080db857c9f70f717f071e1bd4e8f850e20960b81bcf90 +72daa3df7aec152467bc219a556503860e99c5207d3ed3a8973a48e6a43909f7 +72dbc1bc6a1af1ce97497862a714e1c1ad3723547bcd532902e6b258bee821e9 +72e1089e20763501ab01a9af24b2950ab2ce2424566366d94b967a5441bf5dd0 +72ee25f8e956e6e2f327704f30cda5ce0c6c4c16c361dcfa4b409e59f7787896 +72f267aaa294a358a72860f6c18f64d296daeb1ad6155dc8795ba8e6c71e8e51 +72f7ba094e74fd750448d9f4503509e04ee464069814df97f35a5d69b51e1545 +72fa228c6c5a336dc1343daf666736124f4f375d3dc7dfe7868cb74b178e42b3 +7306e14c516141da9c41dca895fd03a5cf0fc6c35797cbea2dcd209d36c812dc +730ad41074989844ced76260c9f6228b186783101fa3215af57daa0c9555f6e7 +73185d610bef8f2f9e909ffd4342fac7eb98f8fec31f4e5c7f53893a441dc069 +73208c0c4c261a0611089b629fcc2dc71694887fa1c74cc3233ebbe9a06e53d9 +7322a94d8dd10353837d2f202b69283b86dd49a351492a5df773d508b09f5968 +7324a1840685b707a8f2b27dbc2f13e05588a87079fc1d744935c8cc04c2b3bc +7326b847e09d78ae4b2f93a637f3107cfbab843579fd3740cf5f88364511e6ed +7327252c80bb5f73b297ba6fa4bcc420733d0600e098e7e3aac058d0558a6e98 +732e6ab3f6ef25fc8f2f06a4540a98e12d67e4b74c03eec3f3e39bed70c80714 +733332fa18002eff3ad91d66dccda61c6bed698d8a46435a354081e0dccae1b1 +73351ff0f36a25faea7ee68f96d938070d9407124b935010a2d8990802496521 +733c83d7fab13a1e0ab6241fecc2f29a44067e87a39ca4ffb3f2ccd3b5a767bf +7343df444949151c44c7cbaea8d884664b5e13f228c99d73f2adf70a37c32c20 +734a68f79a49f3399fd5c6efbc65b46eaee77c27047bed880a16bcdce0bed205 +734bcbf26debfc54078a1a3aaf781f10f41b702348dfb1584362cd5227998d03 +734e6416085636275476e491acb60354f59a27065396fbac80d764b5c08a43df +73603a7342531d7f577ddcae810bd036d2c6c94399bbc21cc3b1a41f9d698315 +7366695ee304fff4514a7a545a97470dacacff742d3ae5d963e8697d1fe77842 +736a36d09852296608f71378ccd87fa1631c25e1879248296554bfb11307f719 +736db43f385713fd112fe890e73c6acf4b627a739ca0524aed5406a20e2b85e4 +73881e0144969a66fcbdc65fc9344a6bd0a947ad287cec70bb7f7e9260d3ad5f +7389cc8c195dbba6bdfed64c45c3f743c6aee84a7dfb2dbf83bffa6c0b33621c +739af3ee2d8b5b2194e92b519bf46efdac452dd66e81f435a3b4b30d8aa9ee3f +739dffbf0b559afd51c4a64c4a29df7a571f3ca17486ec68c698d284d7d52026 +73a5ed1c294ec74dd1db8e57b801b22e8100e36c7c0be5ecb3082569327dc588 +73b350aaff04d309d4038bb6ac466c07b005cb90c587d8c0b7c8f1ab5b5e2683 +73b8abff9c13fc04519c78322296f31603e32af550b9f1ea443f77853343d9d4 +73c9c34e0238fd179ddcce388500f5e4cbb640ec3da1930f0f051029548f00d5 +73d04484d0b707a5fc853f0d5fa0d62ba060d6a09878073cbccf44f4ae19824d +73d4aea1544a80f89702195473467515490e2dc3da55b5c2e021a1b009f163d5 +73d8b4b32e0357583d373ed32b8ff105caf17182f55eb70b8693beccc486722c +73e581b278c345c0db21b71cd85993a70b9ac3ad329d81ac45c62dd2b50963df +73ede197bb8d74a19199fd12fc6a0ee7b163864e314f1334ac88170be10a88d6 +73f102683d14b8eb4594e3885ae495cef45d365b69dbd94d40ba792a01e3807b +73f577c43fb7181ec996210702a65c95d33799c3bbab9301dc50b81b60287d26 +73f83d0ad7a593ffcc870cea197414f2dae4b688ff74c59a204693e0b2132ebb +740a5ca588930dbd1c152c11b08d477986fcaeb74238e1dffb9c52a83874e7a1 +740bf5184d28f0b47bed4d45abd6e90f2a398e50024381188cd6f34d0cf82308 +741032d6bf99883c8acd90c1aeb04389f87897dc2e0e56e8d71b8e9a31207ef3 +74226bda84a267dfbd85e158d9772191e03f8da85b835315d73073cb2f599665 +742880a3809163ec1325edc364743687a5a838b564e5c7e362a8cba8dd327218 +742c44cf4e6a74cc10e8964ca1937bd0dfd2d12d9b29f21a8a4958e76b9efccc +743234cbf285bf1f719cff2d72e09835f49e9375144144469cabfb4a5c362dbf +74324eda97ce85d5318ecdbae72b98a3ade690a4057567f41ee1089f059557d0 +74336895dbc2e6611d9f7c20b88c4968aee3df7f6bac0f04d6d4895df45bba5b +74419d3cdfc909aacd0faab34fb98b6c54a402e5ed234b171b9fa6c6de7599ae +7445011b4c415fed9eb5f2d3fe771c31cdf4b2ceb28eae603d2cdf9db5e47d16 +7451992601e51f6cc4f7640c1ed513dca8147ac9559b8b6917a301c4839c8f3b +74551b22371ebc7a09b1d968fbe1cedef7fa8ef1c20dc7b9a743b044ff98a4a0 +745a8f695d6fb65679f61069b1ca30dee91a588ceb65dec06a9cc583877b5aec +745cfffdae66b415aa049a9ff5f8ec3ad173f2805a328d84bad1995647f4d750 +746ae252bf0b78092f6a9ad3fd59389b16709d70fd42814471d579c1accd7a17 +746d503332b46bd09bac28698688a88882e8387f0b27cbb731a9805e6b7c118f +749469924ec91633ae851f821210e92f5bb3facf39863a6a756dbb95142285d8 +749c80ff3826267667d3fb28fc97f100c1d8a1ef3c1397cd6333d4786e7f6e9e +74a0e9d9da7082a234129f4a04a4bdd8eda8f0b22dcc7cda10feb0bfbbbd0d3c +74a1012d0c227c8c0cdda4f4e8b12568d4644b76f6fa822bc1ce167110a845aa +74b4fb1aade46de01b879cac65ac3ad5d385cc1f624b9d426abfc0c48e355017 +74bd769fa3f961fe87143f1ea994da4ac0a1bb5806f2516568f2691d2f36c541 +74bf84842f10da466038a01912ad6186922faf576b646fb3eca8877e8fb64e44 +74c242292961f2cd5435e90ad728d097e686df530b83a5f13053ebde372e4572 +74c41ba047fadfb54b30741bb8ce4a4102bd06c9e6ac4731637f39d871843749 +74c56030bde4ef3bf94ed8c1aef481b72982c5d9e03a8b00df0ea495bd6d5c85 +74c7512336acf6430e1501a437f0a67f7d8579bc9ab5abac4e9893c59d831b06 +74d734d3d12243b3957368134ba15b1a63bccdd5b60b6fac13e617a4904bceca +74dcc6163120deb24bc7d231d8c3fe440fa86b0d6d6dbc77e4cd5fc789fb7ca1 +74e6fa70b385f11cd613ff2f48576c7355753d95a600508ca7e3a42fec745efa +74e9317bab0ba376127427589c943f33a59e4a4b44738ef82d481df94cf76493 +74eddb6c644900a35123af5c6ad5c0a065ada87b30045bf53ca7bc0ad2b2e395 +74ee9de7d33090a0e4976ea60dd72d0eb12604a1e96a99769ab51a3319cd4ee2 +74f4755060a5028ef297f3454ba1dde4e15c70eff389108e57fdade96f502126 +7501abe7f93f54630b087dc0d221ebf76e9e51cf80a07ecc7c214f5b760d25a6 +750dce75d5d74c56895123ac59baf38d9e81969dc6ae113ab5bd154d5ad1e681 +75128e208dec6e592850430e0c519abd3688de14e728a9afd15679e5eaa27044 +75135a28de4c6e022b29f4e0fd29f4303303396b33f076f57655feffc140560e +751c60dae3ac7aaf08c28750aeb4411ab8a489c3e967dcd08d346f510c43634c +751dcf72cb2c29e1d821d359df482e021c941eaae076ca2a2bcae05243126580 +75216bf53d16061a2338b9e3e69324ae741db48e6d51b2fba4620e299efe9433 +7525ec73fc824a173e02c700a9f54bc29310979d5f299371b6022648ee345a16 +7529ed145cb76c4bdde68d8c9028129f084e8a930725eb8a0a742b4d9b9e4fc9 +752bc250e67c77485a325d8e80f9355875e766dbf908ca6bd4484c127ae06202 +752d37b99721fd7096fe6e471ef13058110018bb1781d0c7f965a1a89b355586 +7548481ab9118273951599b35423c58230c38a93d2b4f76d0c3a7221f74221a0 +75550de7fe6950dc90660eda16be97c51dcfa65814965cf7ab5c074fb3e51dde +7559fcb3c9229e9524090d20379c5fa97f0932da8c8ae064549bbac55e06354c +755a04ba4238a1498f9a3a2846716e848514a4af7388b1ea32d2248dea71e14c +755a4df12a42f2ac316770b0fe9ae241e984cb30aa70d15ca813bb678253dfdb +7565f6c4f70fa1fe99c9c161e05a0fa795705ab5709d819b0093cf5115531cfc +75717c7d000a525bacb932aa35f9c214ddfab4db910477ee2b465d6612a5e0b4 +7574ba005b332231441421f1aef1f40bf5b370da63713454fb7c6afd8c883306 +7586686d7f4e224b2276a55e687113d8c856cf9fb6d2558651a7afa0385349a1 +7591e6c080b97cf9109387a2cef0b27f052269b2258a1604da25a12e9f2220a7 +7593e3b4a672ba77b7f49b79637ede2d6ed85424c7381fbd8d12f0b7db0e7996 +759540022bc85ea8fa16714cd5b4e9e59633268f46f69af2494904d63260730b +75a3db73d237fcee6d24f4d8f5e24778a97af54bae685d3208a8a110ac13a1fe +75a5096a379a751b4e36513fc3dc1a786444836f10ddf1208965868d10777c6a +75a61500f45081b688c9d8fc932417d3cc73657fcecd88a9308abc6f9113def5 +75b79856b1206ce2a07e9126e3c9992b814c5ca2b399f063867d47883eb7a7b0 +75bd9f8d5260e620d4ef8fc81a1cff0f3fc27fffa1bef32a8ee4ce169195b414 +75c2babca32f3317b6e56ef24dca37407f5d4114185a06c16d03ca9e0814fa19 +75c9e25149bc0c1033078b08b661822b2de4e2ea9375e7271436122714e6dc9b +75cc897b1d23f7179f17e9834afad2f5c95bef0be19aa7cb0eb3e6aef42af697 +75d286a7930d8539c3d406f0425a4193851b4982caf613aa719f0ac9fad959b0 +75d32b2c67b9006ec7e649f2a2ad059e86dc4d65da4a93eb7360e74b05010e89 +75d6ee917f302256dcc2744fb6a26dc798439b4b377cabbee225a35ad3375b86 +75d7507bbe012ee7113033b86c8d5b55bb0a5eeddfa3e1bead1518c5b20a5222 +75e7cf87d48cfff5d715c765e05139c872f9a04e18c35b7a945fb232e66507d3 +75fcc15775779241ff00b494970cf9809359a4b0510b7ac1fd9799a6d7d4b62c +7607f223203f978f2e2a54c8d4b3c084f0a33e9b5a27c1fcb2eb2124c5b2e70c +760cbc56b6494ba5127e3a3ae768e45b8327d06703d9362b95c4795b2dedac59 +761bb00f79842b3d45cb6554c1295e31dea9ab0e0774c648535f02382a5ed986 +7624e1710c3a12a936479df88ff0ea37fc77040116ef395e0054e809f946fe93 +7626562b03e7eff751425ca2e945871f158ab4442924b9b59903ea7f0c589a0b +762f79c8b5d49db05bba300cac24b34abdebd2cb71d2cfdb6a440175f79411dc +76322dd04d4ce9b158d6e99d42e8a37ddebefa7aee2e59ea61a80217f8267401 +7633631f3a349d443788a64779694993ed90ad33c070e3ff43ee32c54fd74ff9 +76392155ed084feacda86e90d6aa595e392e577d2f9c2a4acac9c1e6278583ca +763b1cad85fcc29cafd79512be37063294eac6e62ef466b87cb92495da62692a +763b53d95cc2c1365ce8228350407d4d8df8d1bd8d2c7cc8e42b2b5ba5b7f7e0 +76456c625c15b931111123bb47deaeb94130ba891c70210651c0b59a52215c2e +76530ceb1bb03e8d1c6b8180788da20a0fa7f8fdc2fdb443daa91a4eea626799 +76664abcc538931f041002bc31c96cf9d17d16c8bab218f7f2ea3d4b91e3313e +766a06ee2b919eb6fe5fbb29659605e3d5de786df549baca44bd0952d9362c07 +767376379c372a818a2ce625fac0d325f949935958f158f460b8a48522e71444 +76907578f67f33a1a4bc190e12b70194bc3f1ecd0eacc0ec72e3a29f73cde964 +7694f37bdf8fcad17f28be162c5b646689f79681022de86f079580b84e34db93 +7696351807b196c1b8c49cfe466a5ba16e69d027e79926ee02d45c04918b4480 +76997b03ffa2ffd0d0af5d3f5705721a24cf94e9be59f595984e89a0f54cdb00 +769aeb7aace3a9ff8c71010b0aac6e7667306cb95eea69d758ad651b4684f158 +76a1c19725cd1ff4382ae7244afba9154b44fa374f9efb32143b46fbac32cc24 +76a3df426c078efcacb5009a035a391cbd7511a0218de39ac5483ff02eaf57ca +76a54858e2745093fde89bc6c921089442c93cfaf1cadae3e8e548b77b469ca0 +76a92143c4761d3494d2f5a1be65a72e433f9d9d524ec2f75b6f5ae786b940ba +76b035609cbea3cf30156de7d6dfd8804e75c32d0dace1b39e623a3f9528aeea +76b6367f388701ee0378076f29e67fd0c26fa5664a65465ee930ca54df5c91ab +76b6b9ae57625fde5f28ac78b282ea46c56ccc5a474d77c20ab94c84d1bed63a +76b783695cb8b7ec37d3561bf55b5dbe4db1f8c6c1b7875cdb790f398e068654 +76c241c06dabdff6f41fe4c614149603562342f7503b8279cded559812622048 +76dd0a7f5188d5ce9042e633e936ab6b2c8a2e54e01d988dabeef4aeb8fb49bf +76e0fdb5bacb66c0b2b25fd1d0dcfd8b1b32968a3efe903408025f1dd723c518 +76e10860126d6992603482e523078cd8c6f2f98700b17b9d44793c2e24022414 +76e6936a6ea79188f00c33ce57e3596be64a6e7cc642f6c59893948be9ea0024 +76ef68e4fcddbb2ff7aacb41bc303efe527261dfc79545b392803f36a05df3cb +771d2d17e88129bc84f563e063fcf74ddbc9f079ffbd1ed062a4062bcbc4bebe +7738474b01b167f62d2b79a3e0325cc49056b13a174d740b3e28606d739dc373 +77485d79920af39d6f66d1b2b8665a0bfb76b3141fe8f0e892b6ff2c948f0d78 +7750f60cff073e07dd86ba2079f8f0ceda74ed213c79d930039ffe7de86d7811 +775306b235b8bb6ab9b9fccd72d53092dea923d1722dd87ff246d1ad8820a82e +77550ccee25e398e81583dbbfc3b8686483f62a07f2ee77fea588397f4b8a7b0 +7757dda644874d2dc118e704319833bb7bed0617542af13eb6dd2c711c1c8ee9 +775a8b8274b12830866d12f8aef3303c586970500b82a58917efa0a36e97c77e +775b4614685d28035cf6c6b13c188b8c261be8119ae6f1c1f59826fdd2c19d58 +775fbe305b56a0ec7485c037a4857b4c75f2d6f16c3823b33bc14c5dfc306170 +776a2e5d59b350634141d1703727a0b5cbcc34a503bef67e94c9c17ad006e5d9 +77827cffbeda4a0e964a7060255043b03cc6d98b57686e42bd83a7415cea2920 +7785af6e5a1d423e2ee75884be135ca37ba492bb799e049d71256d7364f5a726 +778f9dd398f07a18c4ea70b2483302fa9c8e71c022fe1bcf22b72d8b02525f9d +7794c6d1d257ce364ec7f717dc9fbde3402913e11b07993995fd20ca667f7e0d +77a0eca3b262327e33d1f229892ff07b2f20d41868b452e48cf6d014536d876a +77ac42f34921dc60a1c884f3bcd755a961958f4c5ef2f8f320f353ba1d188cee +77b1ba6f726e06de15fd9248fe0d7dda7a3b2199e9bcec9b6cc9b1de552fa433 +77b4de0e14c9cbfe953144684e77c113f7bb7cb779f79828b0c3c02dbb36c884 +77c46e45eadb3fd4e9dce0b469b548c18c833b8a6fd0eae802ee97f2bf42c181 +77d51b2c905298763c3f812cae659c368db268b7b04379e9afd33ed3c4193903 +77dffcb8a051bac52c6f65daa36251ae954eabc11d0277950f6df37b236a8d09 +77e73fefdca20b4ddfdc7f843eccc02224a6528a4450aa6edf7f369b5b7e9165 +77f4fe0092e81cf2b38a6585d0b482d3e60b6abed3ef068ff74fcb1f2ad48237 +77f6b9a7dc3c9303caf10db46850b22a5e1b13cc30f05b2933b6c6524dcf97c9 +7801e18e92eccfbca6f087277f006839a8d9b4995b710d1e94e617cc8d9d7866 +78065f75e9682979f01e70c2e99a89d3c709f81384557f8c92c3e4c1fec07079 +780aa55667a07d8ff28c657fd8f99142e71960a846e53ce7fb78d44e0fa2b6ea +7818f83ed9eb377600d4337074e34f8ef15d146b40defc5dff1a1269d71c47ab +781d8240f9db9a1cd229040dc43b805a830129f5fd6902900b98efadfcc60572 +781e84537d32a1aafa57aed7dc60ce0f837ef42eb8fe7eb31d0d89c645e3fd68 +7824c9440c2d39ed5812bbaadfdbfe8c491a9bdd1e58160fe95e57446eead195 +782db8350cc9eb5fd9b21c05f127c68b47d781548d9a4edd706e7fec11fedcd6 +782efc81282f92f31169caad53d7f1bebd47310b86be574845d636ae6a69c0e0 +782ff65828c5bc6e4fd50bb70828ef0ff8dc1912235abb134038322128d9e97b +7848cbcf9f084562b0249e54fd367e673e57755421783132e5c0db37089b79e4 +78503689a77ae9c290d02de820db7f108d67f84218c348f7004d57725f3e6c96 +7852c00550e2c09054a66b116e5c3906b2c3ba34de58de2c073f06abd9f3e83b +78654c1b73423ba84dc2b209cc1ec5a3d849f04633315acc836431aecf10d95f +786f350e4cc86935481fee3eb9e7e5483b0a1de7d0f819840416e1f3d058f47f +786ffb58c245297d4192e12341cbe02923bcaede3b4c30b9a872263323b1aa27 +78786fc42e8cb3ac162ccb40788aadfd99d1d914f698f7499cf6edd6ad9e5c82 +788457e99366b391cf241fe8ecebdc23fdebcec76bb80744b0c0579e195baf22 +788ea884a4d6966b3c21428c6ef3fec89d258db6d7f48eeac35aa8622cfddfaf +78a12a844800dc13363ba2b116cc57a1e04336bb1488e1364e4477bfa1c84718 +78aa1e6e9ec3d6af7d987f854dfb3f0735d2ae438e995311f1b2a9fcec035550 +78b51d7657310cc0e326edc7e43a64d916b5a3a38d3c9ebbddd42206db5e3e0c +78c0a70df20a356e8a67ca8bc1724e63557b6479773081f1823e61f5dbf01a89 +78c15550850d24ad16724cbc573869c940c701de7867a605a8eb429690aebb69 +78ccb10433d3741c728d78ae859c55cdb8090adba9f1a5547abb714f6fd46c87 +78d359beda2c2f703a07a7c7af6ffd4e052d336eb140e8d1ff88ca5e7338a7a1 +78d3c41a319f84565c8423023558678d52ad628570ebce28758c7047d320edc4 +78d43684db7aa8f0c899d8886bdfcbc5f9c604269d40eaa2b6290dc93b4c911f +78d472205f1b988812bc7d297d4bcfc0bf795e9e9a4aeac7af3e767d1ee85634 +78d83f03ef888baccbff2af28eff91a6fccd16c35989c1f8cca9762f0e001dd5 +78e501b28b5eca4d1ec50b3130d65e1850a76570b230b992ed93b4b2cc518bab +78f41c7d68713b7fc84307ea32f0251778fb309409a8a64cca1f4a48bfbc9248 +78f65051f5f0902d8ef66cb921c874ed0596282cc6086a6dc572066441325be8 +78fd99e5cb7c8b5a12cab7a854789b5a1427568a4750f08f01f211ad1647655c +7906458ac8e27a25b24cd7a1cafe7fa2e4585801741ab368c33212e50d83ec03 +79185162e055a04dbd00ba8c6604523164364831bc06779487ace21be0cf4a0b +7919fb8acfddde49d406187b9ed2f466dfc62ecd5d81623c1e159806adc5d17e +791ca6e1b6b021d96d66ed133366bdcc4db972306d698eb80092a25637dec999 +791f9d7acf60a6256a9fcfd79c271740c005d7f91d753ab2a2e55ef529ce0a37 +7921b75f55b1d8b4bbb60684b4b226ec3216b3b1a58f9f0811f4e1a8b1e3e951 +793311b8e13f864b471588c5e4e8ff1cb31ef2d7515cac879d8fa576df0f1f8e +793cf2513cdbcecc09639beecf78a4c580bddeabe392082d84e1c563198da512 +7944475889b919bf984121f0cb5842c5e6456c84b2b84fc51601a794f422abf8 +7946eb6dd4a45fe455b00e8209d0aedfa9a8658e78325fcd57cfeaa1455fc0e9 +794738dcf74f305d76649a8cc25cc7dc8597aa3cf0c5532b9f40bac63dae7584 +794de10effc8f6687f19b9d7ce088d350f992b9cce7e7fbc88715a1338278fbe +794f7f552c71747605ed2a85264a762871d7ac74e68bf2550de34093d145d245 +795448142babb02766ed68dd1b748f211f6bfdd0fbe03ffd88fb76df75a79330 +795a9447bb82530375b36b3f740ca7db8dff1b52c5b2857293c0657ca9a2ab32 +795e76cfd0477282dbdb22f389a2a80574c0b7af1f9f95a4f9e284afe24e66b2 +7962e5a30e75d41f72a0b88a2c91f67f47ddf003ed10200925bc6eedf611754f +796567635a55ce19c1374113e9575e4e46e6e8bdfa64bdbe7803be49abe23c30 +798e46492331cdb3331e1c645cfb0d0073c53f41a2dba09028aac5a6023cacc0 +798fad17531a347b087e5e7829fe2c351272460ac1b0c3c72bdb9975b017c938 +799b502a19379bb2120f0945c005b9bc7a12a4324aac0abad961a8a185ae49d9 +79a286b8fbbb750157e4bd785e75d802f51df378a1ebf1f4627c322adcdefa11 +79b002124e016bb884b2b4acee5ddc4080a32f3e107ba92e1b66a976597cae5f +79cb081c423b083abe165fd321d6427bdab670049c386da1b47db28462ad34a3 +79d30b55d74e404357f61caf8b12eb68ff888f1a35351c56bb26882bf3b29b8d +79df779acc146ac7f75db4207351507167c286725a9ff9bdc663114f1befaf0d +79e8a9aa04a211dc36bf1354f343592c06e5f1d0ecad00e393bb30f2d013a4d7 +79f5091e3fede40eef34427c8e7eda53cb91972e61d394036e2e76014dd9a024 +79fdf823ae23e498618685f3d4372b1200f85714ac6312ddb15ac5624ed8b802 +7a068e374ae976916222b1ef071f0151fcc97cde8378c12f40365e8065e0b4b8 +7a08831e7904b5f98f9a994fc7a2a93fe2ed8bb3226066c465e5b9dd54d4bc24 +7a0b7994b34a28374fa735752fa84fce7bf1281b91d99338d67514d4410a7675 +7a0d504329f76fac1df729fbe85b9194b125ffa98ffe90bd594ea602ed34f09b +7a13e3838de75bc597f760293f65afb7471572a6550e3635eee11349a757d2b4 +7a2185c1203a9b1b65b087925d20474201b71af13ab8ad70f4443f15b2854004 +7a2bfc4ab60f5be014fcae73db19dd3ba4315dd07450cdebef03cd5f2d6bec92 +7a2d400c67ac8d1eb01ea794f2fe1403ffa575fb32976987b722d63c32628ed5 +7a2f867e913bd2e726699ee77b0c61ed8ef6c948fcc2e693b5efe5a67d0d2e0d +7a3c0bef68b743cc1311013929dcd9fb098d898ae092e1ba1f00ec52115e2c1d +7a3e78d6ee5447a2345e807b402f5b50201cbcdbc5ac31b9c570bd832d93e926 +7a4083514ae9a2075832e2416523e7ee804861f8ebbf4bfb84ef67bfc6b5dfec +7a488f9aab6f276dfd1000dc7cdcfd2d414cc00ae1d156b713f82ac6792da57b +7a4fd4f06d20dab6ea1d9c79f5833d38edd65a545425d2c113555391bbb544c0 +7a584b54e4f29590ae75d30a809de4e9bbb23ad6a5b20377cbb4f0ebf2a06dd8 +7a59f6889f21daa39646acf772444d299fa8cd7553d40277f992c1d1d1fb1824 +7a7a0f3da3a9f3021b93e45a28a011b3f559cfda78cd17983a36feed63773e02 +7a7ccac5476621fa4b25bf277e8e9f3758643feb43b18cbc48f3cf694be70b74 +7a888d37c7893d03fc39da69cdb08736fd97e5c2f26fdf41951810369fff192d +7a991140d2579e66e9be48252ba369c48dbbfbcf68b9a8baf09e895932aa5d1c +7a9a4a81d4e6ffacae196b3490b72b4311d72e98c9891f4741758cedb20b5098 +7a9d1811d097dae80dcf4a18de0350b7460a04c8c51d01dda652878c2c2a10a8 +7aa05b0356cf7ec8e284e46f3f5caa060bb37ec18e39bbdd129f1a824362af03 +7aa9d3c1410220b047e15faa9c7d12a622d80e1fc6ce428dfd1a59cc4c1c49fd +7aad8014b05688606f0373a469559b093760da9fbfe2f2c233456df66415d574 +7ab159354469d3e43130e77b6e3672b05e379d2f38e665d691ab153bb672dc39 +7ab8203583159b35810cc08810a4b216b603923cd4c6185d2ad1b4f2c4be51fd +7ab9d03146f64957ed3f93fe7810ac8914e081b0bed0a9a40a1c782c82bf5076 +7ad4c1e481c301b89038c08382afa6881d2072d9695b0889805b307988b0c2a5 +7ad4e5c3b96725075e73d07e3668ebdac19da74401070dcb4863d0ddbced3bdb +7ad62d0b02b7e2ce658407731ee583cfdd9476bda39475f7cc38fa7bf80a4cf3 +7ada745728d3adc302210d2e0a383a5078c5b2a9ff224d6417ea1a82169824b8 +7ae193b494f42df4f0802499a99ff8923a40eb8609c13611dfa0d64a0a3e1a9d +7ae2a4742be7ea0190d28b5abcc69a46e8050478bfcb05def424324875784de6 +7af61d866fc90d9898bf7abbff6e349ed4b31545b5c3b9bc5c25402becd2aa67 +7afc8b0332be8725c59d22df3bf8d0220818d44266c8d814823991d24e560d3d +7b0771f78575c3780a481d58735d96749bcaa1d191ba6e67331b2905dca8e075 +7b104a8a691cb62c0b09767cdd70e9f8a818a2ca42ba526e4a5d07964bafef02 +7b12cd93dd2c5aa2b10f0fd21cf634efc3952f98e93ffb22b2c6ac86fdc0c299 +7b15a66036efbd09de2973a9e23828eeae94162c18b1dff57a09dd588a2dc42d +7b23636cee2c0cc654650d45a9a1de39d35f97507079bc45c910d322020b56d5 +7b3916244c6b12621756530c9047b2992c7734dd1e294b44c1ac298fb6107951 +7b4c95ccc04f82ee95a0275916a9683072399fdaea52f668a1bd6682b191ce35 +7b4f585c3379620045afb521c99296592dab858c6271914adb81750a130b17bd +7b5a055baae02099795d0e14c3ff0a6a1862c52b3ca2d8647def2a1f5704e181 +7b65ae179d014b7313affdc284a16ada85f2410301227a9decd9be7b0deddac2 +7b68beecf2a446863bfe336e71f6fdcd3aaef7ec5d2ae2ebce99ebea2c16cc79 +7b738179b255f64628b24c19e59e0d145f434d3c0dfb019b7572cdbbc93edf1f +7b7ef2468fddf757a15f2cf87f6b99d5f49d28edda4f2d751533cc9c58bce39b +7b9139623dc1c6828447a9da807abad81653e0a94d54627f768a2c62d4a3ba38 +7b94a63d2d9f3c6462bab7ce465da8dd3d76eee0e8167d9a68e748647fb63ba7 +7b9558fe45c41f1ff54fffd7f76611fbbb13094dac32c303314cb232a1b59aa8 +7ba09f0a9735de0ca1cb3d73da31c30cc61f9ef9c35419a8adbeb97ecfb05587 +7bb2bb3991372dc272d1742b0b7435c2f764ef603e107cb5cc7c41411dd6291f +7bc8f10a210ea617c26aee80bc84ad86a608821af4d1e039617e775acfbca8c3 +7bc9424a18a6bb1943b66a327647381281152037aa64081de5945e314038ed4f +7bce4d4ed5bc5c86495cc2a25b6b7b2f8b8539e8acc9e45e1f265fc5258bc319 +7be42a010698e525201f3da4d6be7b1787a50153737cc0358912b158463ae972 +7be530d62b2c8d768000f468d2174409d826fd7c6d666edfc2baaac26dff2cff +7be5498a7526bf2102ee286ca1d33566cac3208d56d63687dcc449d7ff2b4b16 +7bea56c1ba8319e03e5e0a1ecca7de0a90211e6b0c221ba27826c7907d98c9f9 +7bec6f20ce87c99d33071973220f4287b28598235899fce20638d1f2fb4ced2f +7bf7b5606b299f85efa2922c3635392b41553b9b0e7e70a9c3cdf4e645359520 +7c0b86848bf6292ff7239b936ed23d1de8666a4c8fdc1274ce42efce892c4ca2 +7c17011ee3547606760dfd7d0199d4837dd75fd4a7259b2a5ccb3574564df3f5 +7c27210fda86ba1470c1eed1ec37f157612a3eaef5e3be12ea91ebe5236108f9 +7c36eaf04bdd47bf051dad9d0981b39f0c14ecd88cc638e98df8d226758b910f +7c392b377e6b5f78f75c583c2cfd61659526f3ab5242cc276eda24e70a808eff +7c3e99c6155df2ea0599e72c700a15540e9a00267063f2a45329d0744e2db4cf +7c47aa6d4365807a10152a1c7221ef01e924518f78e5977475370517fe2ef8bf +7c4d1fe8d03b437db3a5e9aa9d0c0e3ced11e525433ea6b203feb41126f360d6 +7c4de95a4953517f3ef6d115e078ddaefe1666fdf29539ef18b26bfe02c43e19 +7c4e72d1a54ac687e32a34a50e8f1161d4220818fa081f54bf1569f0f781f7af +7c4ed3b1fab598d8da6a287be2c5974892f08e32f41d7c274ea6ac0c02a2fe17 +7c53bd4a1ce1ef7a72cad4d0a3e91c30f8b04625d2166ac21d7eabb986767340 +7c54a124067fb9a81bb071edeb60ffcf284a53698414c57e431c06eb0b3325c3 +7c56950f06bb00651f5e56eedaf59cd11682fe99a175148aafd858f037ac72bc +7c5b777f7e7dc09a91baf491e9a3427a9ca754f426ee2919c4cef52cec574a17 +7c5cb2903711e165995b11a6bd6e5fc5e47b454b36d0ed4b8b9ad8ff45127a6f +7c5e43554b5196aedd448177c79c80cd3f9cc16c86adb3544ac5fdd87a5d93ab +7c6804cf478cc191c7d0f092b73a218f6987ed9172033640121e2dc3a1723794 +7c6e487edd42deac7f5d4728cc9da7d8ec14e3de272a4644f6ed1eb597182a9c +7c703c59fe5eb580a47bbf8eef99e9bb59fb16fb0de7562ea1010f0fb0c793e6 +7c72f8dd135ea8352eed18d9c062ac4b0a6e0f0cb37ab11c8c8ef438559b5563 +7c7c05cab9c63223344c34746847080a34e12a73448e8e0b7ef0db43ed57c5f1 +7c8c1e845617023610ab5eb8b1e3bf9512d0b607143cc21ea055a2db7e5d42e9 +7cac30a06958aa0c4fa65a8c517ceb56439485ec54002a4c597a2955dc2aa0c1 +7cb8481aed6cb01404889b7322a681c5ccd3b3ab606182411def6d1b433c23ee +7cba48474900a9675a2b6bba57873cbd7916f5fd4afe2591df7f59a1b73c0ef1 +7cc8331f8f1104272d488b6b06f9aeaad82ca61fd6651dfab79ba0dea308a97e +7cce27dde79eaef3cf2db001730ca3a36b65465c36602ff548107c9a4bdd5773 +7cd8c862469178587b4d07b2b4e3d5aad003f7e147d9cbaa82d981c2f8bd839a +7cd8fcdcce0d1f104ea0215336d220d316130d868194ea4d694e13e9c74b85a7 +7cdbbfd7f57df3b798a3724c0f8ba1f058b422eac0be14b05cfd37b76e715eb2 +7cded0af8f2325fe6c9e0b775eaa69776d939d1d6e38df6f759cc5810424d9d4 +7cf68b59699ebeb2d9700ce205bc91ea2715e6a16b4a5014d148c601fdde8d83 +7cfa33904bb136b473743c6632d6f788e1725d589fc9d6ffd252cf6efea92236 +7d0ee206097584350a0240b7bb602ab080fc7fcb51f240ec78efff9a0f81ed91 +7d0f5def1b5dacc2edf43b5842e361ae55d56c4849657f0e573c7e561dfc3b32 +7d100eef87d040e0b1d5e95c88760189c23d31dff943a4edaf1b789d46c20383 +7d2ad99e6e7afc558b58ddd592e912f43bdb36f85abce484d6be096da543b2e5 +7d2b3f96b1251e45687258593ef5553cd484d129330522c26b66fded55eb3ad4 +7d2deba91a3f29114c2b2f1689b1ea37fa37f093b114fb8412a6e00f398c28af +7d2ea24fdc50612b61d67aaac4207f38e2792fbb4344e561b6b50924bb4d0162 +7d2ea6a6b3c4b0c21b589cb3ef8cedc46a839244c888f5eb14baf3796540c20c +7d3629a9ae8766fe317620c9eeade901010ac3b812317fa5579929194227cda5 +7d38ab1c4a94723f07f7152914f98e712789526d1fbd9cfa30fa79c7485b8f40 +7d3df64c162da15f9402d140d4e366079d1c891315e6301c144c377745239336 +7d404c1eda2d7c7abede6597c425c0268ca5dd2d61e7bf87736f301236590a57 +7d414ea21ff5fbb5e71397d9849c8e9c87092a0ed65ac8a9eb87c4d4ed42b896 +7d422f326768cbaa6adb4815560762efb60ee6d6ba05368dd7e92058f040b677 +7d450df2a6ca07ad73cee558e35453afb2a90fd2f43fdabdf718128949c59f3c +7d4c4b44c7ca20c70dfd53503493e00d11a43830f6df730ab892c2ac4e9954c5 +7d5233fce05cd9b71b752a98c07297849ee55cf7cb44049528dbc877d3998c20 +7d57290f7448e87a9f10eebb28817c551468176f2a06341c15be6c196369c3d8 +7d61562cd01b05c89608c0f5456252bda051ca84454bc43505822915cf134a50 +7d7d052c7295ea13f0e1f9ef48fc8b0eeff17950b1b881728f50de9b6d7bca70 +7d7fc9523bd06788d5f80cf4a33e9bf9c5da0cd3a9d8e44123dfb9e82d50cae6 +7d847e23a78ed67119b24e8d24a191ac156a4fb0ab0fbee18933edf56c1c35ad +7d85c415df8925b4a2834069bd473b13a96375e03753892bf25ccd7ff3ad8015 +7d8f4e7af272d76e9ef6ab90f7a7a46881befd79b97a3267564512780dae1f80 +7d90e578496c8040e2adc461d47f160bbb09d02babe50cc385e8d10e07883079 +7d91cecc9429bc47d7b5495e8ad367c021b4d2a8756f5337cc32009a4fbfc645 +7d93afe9fda9072be4bf9ed36b4a0e44cfbbe3bb91162a0242db965dd66298cc +7d9d17063a955a6f9a766a08478f7b4603a4cd287bba056f777db0ae0cb8b0fa +7d9eb7c67d3cca33ade3f74080981c49496152e3cf8c6ff1dc66ecf581ee5e51 +7d9f4b3491dededb7620be677645078bd49c19c6e0c4dddc3ed3f615f7cac00f +7da31f2b0f820272e236b187dc7f71112ce3f85518a37a0aae7915e2f0e5fa68 +7da61f5b5c7f5baa6c7a94f971b465f3a123cd10f477a6c18837f5bdbc225ed6 +7dab4072440fc200299b683a022b2510937ff90622f3535a940ba97eb5b7612a +7db6ce4dfabf251bd5bf04627ec048210d79b1e5c357589c2f75ce1bbc2ed9c1 +7dc5d473825448b9da75a92da6792a6bf19a90956b9acb405c918c6b3ba09658 +7dc5f407ee4f5125f2d56ce55e735ef96a03d959ea328323053a32ab2af53678 +7de8146a47bc379dc024c1b426ba643790480c7fe47e9838e4ad6ddd6ab569a2 +7ded7f9885884b31a16d49acf9be0d9d6cbb4984a13875a8ce0c09e53a3415ab +7e0ae66dd94e3fb780f7b361998bfda45f100f2c094d02e73dd25abf6cd117da +7e0c6397555de905018a91763916558ad4f47d4d27bff26a6363767ac20fb100 +7e14218fb42824dddfefe15400b168906d3ec8a222d6642d597f66cf6c48520d +7e152fd76130211cdd3b21e063ca7b21231d6e1112f7e58ee692c36eb3e2a7f2 +7e1930c8c940235b6583a5d8a1ee062ef1cebc09ed3066e3fb56a9e979e7cd49 +7e22413ebbef4626a5dc88b0a89961f51d6af3cd99a76b6396871907b4e26015 +7e240492cae7dbe09d118d5d5f6bc40292a6463d069222225d5e95ff68a4588b +7e27e1fa79b261dae6f33ed173ae1601f840276e32e7ff730381229ec5b1ae76 +7e3c10724d3f074d25e7fc67e04f98510322db532f848d29f7c57dbbb81d3d4f +7e452a290d6a8cd5f5d3e63dd8eb59f43d6bb1f47d1c233009c396a5f7995d64 +7e4655e5cb4204e302f695b7527fdc0d339564b169b39a766aa2b5e23fa168b5 +7e577c02708569695b0367f227f4517d54618c97b21c00f277108e7281fe8e2e +7e5e530f6e095c6aa889e48346854262cb4a86115c412510048a7a71ec9ed70c +7e625ea2f27ef9b359d77ebc1ff2d2545bc91ad5588835aa372017bbde201a81 +7e6adc4d583464cffb8b907a3d6780283ec353a11f8d54b9c90acdae11198be5 +7e6c4619b6de0aed514ee343c4993187ff5e477179dad9fe03e9a857161b5b0c +7e735c9740e3f1f4c9f59aa5336c4ac6a483a2accb6c3984783780eaa3804f6d +7e81fbc7cc147c12667da624b4563f9e88803c261c6cbb86fdae6ca555a8d0c2 +7e921ffa28b337527d8bcc3dadb90912ef440cdd60f6930221537d0dd0db40c9 +7e959d77ba0f16b353d46dd1ee6e5323431a0e3e97f926c37aabbe8928fac643 +7e9a805c91bc4548d1b148bc0c87a88ef136d10a0fc4017b470f9bfc3539a36e +7e9f359fecdada4058763abc936e29939e15a815bb936696a0bfcea3293bbd71 +7ea3c43de64d2da64bff3aa588518379f8820d86f1cd24dfa68f75945f0f340f +7eb5ca425f0cfbed00c8132ddbd145c142761b50cf53ac3521a3e23a61e1991a +7eb8c0362bec636cda7cb7521228063bc2e753810c168abc4d39a608b6b7134e +7eba08c449266b93ed87833169abe0206858c3be5580082af5ea3f7e2475515b +7ec04c92e102982770b745def804bfb41ce3c6c4ccf302aa381349127e84feae +7ec6e76284afbf509e52005bb6af22782c7e66dd87b44600e24f58ec166f460f +7ed4d7cfd3fd8a874324d101d852e92ee5049cd80bf251947171b04587e885e5 +7ed59431ec0a8fe762a9a1ed9c1f03979c59c722b4a7f4ca1a5fbcef20b2d013 +7ed618f42230406455f9e4595382fd904409e552982065e279a68cbdaa046ca5 +7ed8803ce8d425a40a8202e491fd5a3906cc74287ac9876661784c15318e7f21 +7ee6a7f6ccec49e3491b51baea965e599fe7d2c613c82141824e330ddce1ec69 +7ee77fbfc2a263530afc4c647482ef7ac1eabae2f2f76177c3e02657bf2080bb +7eef57cdbaeda2ce1f72e206dd3b8122c6117c8209dbdd6d5a0bc35c15dca5b0 +7ef6e6246fe8d26b4db15e8ce3a39f7b0c1e7b98a0d520379c3a221fdfd21ce2 +7f017278d14521e8097746f1a689a2a1fd4d5837b14211e8c06bf1bd3ecec754 +7f10770dbdfcfdbfa214455934eaa91909d59f66b1534fbfcea7a3beaf66a2fa +7f141fc62e434a75ad557ff67e38973fa298a0948cb17f1f400b3ad2c4a5aff0 +7f1510e6749bf0be72b344736ef0c325204e39b1f7cb14aa06a175e807e2e992 +7f2b4b3580cc7c2ad75dd954487bf8ba27a79cb70dfcaacdbab7e6b96bd74550 +7f2bc30aa23d5c527e27fab69bded2e503ac9c38caa3fbb8821f9822f27e54a0 +7f3a1bacac8b838b8b83e91a130a9251c8b3af1ab7167cfc06d787ccdf501938 +7f439caac6b1301bc2a6a7b4a383af5443b33094a691f8e6fe0df9816e21dad2 +7f4d0d71324678b0b52bdb45fb627fc75dd189a97322e776e2fb1afb22b2e19e +7f504bec4a3e97b19dfd006ac6e14d7d51dba9ac2feed4b0b41a710665d1dc1f +7f5cbff0a6d64d1f76d58b69c49504d3ce0f94017d9d7410c4d70042bcef5786 +7f65d4ee60b4e9df2b010380d0fda3cdc9e68e13aab5aeb9f11ee23e236cdc63 +7f730eaf87b3dbf7dcd8375a7eeca2217acd3d422ffd513c17334ae92d5af9aa +7f8503d3e41303697d25051663fa33d2b28264fbeb135d0969e1a658c30725de +7f8ea2535b61a527dee808ab114f6b3ee2f3814ba9878349834f7a15d7572568 +7f950201de2baa43e96d066264cd5a8a6faacedbea1f06ce2a3cc95649540886 +7f9690d624be939ac51f193319aff64d1534791a2e46ba7582caf5ba6922111d +7fa257db4b6933c1d863ffab09b96c225b2f14361d53a1842b2612fcb408f612 +7fba3898f4a1aa39b86583e5f4894dc6d070083c0ec183319f25c57a4037079f +7fbb7cac96be68f220e1810875494438703e50ea888239ed0e3c5378ab5f29e7 +7fc721f330ef4a9c70a38d809f860d861cff69ba124ecd5976e35003533e0023 +7fd1821678a009799b7d2d313169268602b16e86c2455ae79e4fde7fbe83dd6d +7fd4be779b63c2973c78c1f625a72fc3d8e1124a84da35754e254ca1e596b5ba +7fd5d18e32b3b454f6587ac7a8fe413da6a2987f9e9c6b9cc7765c9768fb8ac0 +7fda4074a39f4dafa8ffa5c8d8d5f8b4df7b825eea87ffc35b4b2bfe95f7eaea +7fdb5119312c5d85c037876d635e140240216b2cec3b8c2f2b407cee0aaaa1ac +7fde1677a059e9372a4d0e6d6558799ddd7697fd840837c5806c39c09db27ffc +7fdfcff149a32140db01044ed1e07c07c8c4394498621a27fb8be7d7f7b5642b +7fe05ba049d56c532a246bc560be64d3464d267f8010672dbd34718b4714d623 +7fe41c9837f8519701680de26a0207e78a296f01e3574869f6e3b94e8a0cb9eb +7fe5a31d5480390b104a345a05c7d907699a0ba7dc2a0bd8726fbeaae0644975 +7fe5b504be9e013570a8685482c9769ff5ee0e16dd31f5b43cdb12ea87ed42a5 +7ff60e3a86610905c6bf4aa7299b8fb4d6abd6d3368792a124b65eecf81a02c0 +7ff6878fe24db6a61a1e863a09d0a2505f329f4493c83d50d6e8e68366aa533a +7ff79b05386f1f23711e1750ce6cd5203d361ddc71c0bc06708ecde07e25f4a8 +800032e582d5ea857c292508b2acc9bc2a466635b12b15311e601f14be0ab28b +8031c5552a25d80280eca45ec2e84b6d99ddd2670e3ff61a8aa009adff2438d4 +803a12b89ebe2b9ee04ceabe39b20dd8ce8828e99ebf6d2f4d74724f819d332d +803cd5fd2f70306bc09fb815968c81d035013ff405bc7061e1e951dcdadb55f2 +80476b4be81e859fa1b11aadcad84101c131586b87eb0fd12c0cb7f446d4f6d5 +805021df7103e554d485dbd30ea1028d0d7e8efe4289cd4e7f19f138afe72e55 +8053a866aeba1b9aa056700b6769d0a2e848ba0de56c4071a6e33ac9ebbc4684 +805b320f0dbc6c0d3eb56a0992c23ab0577686de83c9fd40589c3482e6c0cbf4 +805cb62034d320650541f60d2a4382a4263098165371d69cba9dd0c0850d0240 +8063671ba8dc304ff7eb8596ed47daff8cd0df541e85c22aaef56655c9e5f139 +806ab17037265785ccaec5db5037a88dc24c6b79f304c561c433c5cf0e8958a5 +808058a2d680c41c92ce204fd1f58d6574aea4a7153d937348a3c31912b1183c +8099bce323ad271ab6e0aa3f666dbb4dad55a2c308cfaaf51974025d022f9ccc +80a2f9ffc964f4b40fcfb6e34b04312aab4f3d086b84300f374530353684b3bb +80a489e54b22093d6843f41ea5f23229fd50afa6895317802ffaef0c5abc5d75 +80af1ab68c88eb12d38f9ef80bad47ac08b6baabaf2f126816b2d8122cb3b2bb +80b0950b4251030247d08109628395b456ca1a55559952b55e73ad57bb07da40 +80b19b88ff1199b85bd5e66218f8934172523333f38637c9000f87bcdaa1a299 +80b1d8df12c08c98eecde5280500a90667e5131263a23549c1276d7b7a13a2c4 +80bc8b71000d7908816b39eeb0735a6b1bd52cda7216e5600134a46e4a51d438 +80c0f564f4de731159e978e80f909234500239488858aabc43f17e9df5bc6fc1 +80c842e5aab8e884b9b10699ce916ec53ae33c87851c9d1491bec4f2bd495fb5 +80ca6cb98903dd4c3bb1d27f0c7db5314f004e49fb8013aae0796418040eb03c +80cefcd8424f7873217fee519cd4b39aba1db2e5b3a70c5c5074005b267c8140 +80d4d64420954c8ac912baa1bae1504aa6cb3ffb169d705fa41ec29faac09977 +80d967ecce3d54562aa58b92e46d461579c7609071e1778d0e3dca879746a30d +80db1a13e3ccf9cb422b9d9117a98d65d8f89fcf55b5d8305c50e268b8cacb06 +80df81af12fe12c48910023eafc8d3efb07bd5e2c19f510aae3f4a5a5cd25af3 +80f41416e1e02d20468f32f8290aae23eabbe665773126e94ab6301c1325a388 +81039826610019d24323153d8070a35b9cbb70176c7547a5a2d1fb89f4928ce3 +8109c54e5c601a3ef686b2c902244535e194d765e0925311ef7b966bddb136bd +811dd95cf96d416bc2ae85bb757438cc6195f66a4844be85929fe0b26b462aae +813290c175f78fe5d7f3946744398636c8de53a6c633873d8a26a7932c421b4b +8136cba520d9c0d25caa9573fb3c8553ee7c37f023ebb58470b860cc4d9ec741 +813a0f00452244fdb41231f584f3c19283f3d2f19dc2138dd31b848830b2f77b +813b1b0872d2476e7f42d199499df65ebcf985beaa18b45d7e8b57b81156d1f1 +813c89bf251f436098608c5d5d638979fb264ad2c5ce64199c3658326f4d7877 +814dcd9874913f3962744720beb3879d3bcb34a15293699db0dbb9004edb35f0 +814e31e7610a162a83a8c730aef2a8281b14f85b12032889dec52cbb9c6386e3 +815c64424dc00118cd2775cc171325c32e14a861506bd1c9113c4522b345f1ac +815dabcc0bc21211ba892718e0f23fc6f6cc23d2f207209d1fe013c1f1428494 +816354ca9949fe17e7d8e3ca2b0d09913e92773518e6204065c8d8ed92e0dc24 +8163c42102165f1aea78e2c3ac18e36d0b385465770fd856eb97ab9ede216039 +816f59840d0e455729507d7163c788e66b140a0c26817db2bc022eb55038216b +817d37cbff0c8459ac21f991afd5c21a4831348306d20cae15fd6bde2e33f5e1 +8182e9e47fed431d340ae4ce865b94a8b40c23b8de01b01ca1aa16f39da0e198 +818df3dec357c19b384e29e1df6af8b1543cdd4743887f82ded9e67887d05097 +8194c9b78cb23dc6fffb214ead70ba246bed5093c7b15a339835fae7c02ff769 +819623730623a8b6007689b7748570293f312f8915b276005e42f7ea43fb02db +81a63a6c83374812b614b9d380079baa317748242fff3c6f20fb577d7c024b46 +81af07ded78346266ae14c1be99efa0a68af78c2551f193ce5491044ef746395 +81b0789153592aea8575df1672034e936a633fab96a4f050f3002359954a27a0 +81b0d7459c845c07dca8e81b7258b3c0739e36bab6e6d2173326d2019b3bb1b7 +81b6333b09f97caad7f6ccf12e010d3077995668582ee5dd0385e88c9af1d301 +81cf5e758c36cc06968975b84534cb2ceff6bbf10ac28caf455010e0182e6b5e +81dad76b75e9ab1a88164b988c76dfe358548e63903bdc28bc1d401c13e0e949 +81df2afab9903c7c0c5ae956d3647d54b766bc954cc0c905ae211adea574837c +81e56e333a7dc094ded6204fca7bf50f48135609f91d1f5a8c4c443c19d5b19e +81e6a52433429a1263cf40a44ca5eef94fb62fb8244b595e5c7d456c5a6ea52c +81e7c1d5b74435fa3237ba588a3a99bfcda1b2c5d2e84db3e4d472acd4884bad +81f31c02dc0e75443b7ea38c57de0bac3387bf0ab79cacbe8ad01bd75ec1323b +81fc1b263220ec775e3a731667b42bbb82d1d60d6cb50f60cb7c49abf014db5b +82009fdd1bd7b5e620828701288a39c8fcf438aace6e534408c20a8950ab632c +8207c4d3b3d4958a7c7ca0bb44dbd0e317985e76a65d64b38588dc17d49a1d1b +82105ad87b25a99fa012e5d74587257b2ab5c2d64f79304351e334479c8f61f9 +82179c27faaa854a9230c2f40fad536a58f17e2382020c5edd2857c8c51104a2 +82179d7b613043a216fd13871e761919fcb634260233289a4a24f94ba475be0f +82290ea0a8d5926ac113ee9b2be724059cb6cdbb0aa181d8516d19ba8894f4ee +8229e9751df88bce3b07256df10ee790b234552fa4257a3c5c680231576a2ff7 +823579ad79c0d79cef4f2bc410f43587a01314550c493ea4697fa2f140542c6e +824571045ce55f023ddcec2425f96bbdabb0e9318f7bf15e6f6dabf5c1157e4f +8258d5a18d36f5e8c13491378d560adb434562668d0d895a6138926d1c37e428 +825b5dec36dfe556b8454f93faf411ace2a38916f9b72dda81f9220a08930c15 +825d33389c390bd1575cbef4f56b0ec31ec5384f43ad8e9f50ca02307b2e3f2a +826aae1a76e7d56dcf7faae62b4362291366226ff533052033cd6c59ffc320c5 +826bf2ba6ab4978c4a51104edaab90663ccc645188c74ed95c2b0f96f4cbc18c +826cad06930938966b484b483c5bb5695ddc92bf9599dac57736d8ec5a5f05c3 +827365f30c13e68b31ceeb1665b1acf6d951e701d9a8d58edb9fdeb34e799501 +827db4e165f05e550a150842204f323c9971d82946538f47d06d1396af5c9c9c +82823ab845dc025cdb28b15b724e000220027c197c82781ddd38f6358060bb73 +828743953f0ecc96ec0c5f37660635fd11c5b3f765bbb9fb598bf30c7e94cfa6 +82997afdb246737538a54f5fa50b042136745c29da3154fc3b37d4c15ae23f75 +829aa5fbc4f14984a0b006e3f91ebeb9acf74d663ecf1fca8092b36d3c92e732 +82aa7068d802a3a67431be0459bb9ba93670db64fd84232a894c0b93be81ca02 +82ad9da18ce96d4c5d325bdfcb9bda311b8726d5f6333b3866f9eeb43d1e0158 +82b514f06e3558d5b7cd5843a7692bcf552a3ec592e7f5706b4dcaa81dd64768 +82b55ed76275137b1680657e2d545c4d9c5eeaf9d76099ddb8fb6dc5e4420ff4 +82c872c44575c5e6ad9b39fd9b1fea4f18f1a3b0b0dd576bb8ce4fe049c34b6c +82d221b6278732eff71117cf8f865c2296e67db87858ad7960a19b127fce7c7c +82d2c2cfeb76fbcc1d753227b59b3ddeadfc1aa90d84ec70d381459ab901b044 +82d6342f19fb1ff0eca9dc9b382750f89c581abe503587ce41e8974a7aa0763f +82d9e324508be3342bbe646cdcfadabcf8fad01d76993fb1b6bbc473b00dd14d +82da587627224f0c51749702e07350f5ee546584c914f5ef8126cf3ef996b4d7 +82e67d0c7502191ec8acfaba32d671c38c3adca5c124a772b536f36fce2f1cba +82fa5e641d581d7ffa624fd55e3eb7cd018ad1aca42b52220defa4d53dd21f30 +82fb60b15786533897a682365c292320057ecb685cefeb0ba69ed7453eff1cbb +830c0912b28dde4fb3b0d006ba412e0970d4c35f60adebdaed9bfc7208d96861 +8314bf261274ea77c50500cff02dd0171ab8305206225bdfbd8299e48d2d5b00 +831ad77f6ec3f2b03e3460ac1fa265bb6a5e906a27f0c78b6d75c670f483917d +83213c3783f6425da86a8c79c36e2e51dc7eeb82569aa4fad567a9fcaca1fea8 +832537270695dfb4f4428623e7311c1a9968e6207fadf6b487f95d3d82d40242 +832d8166938a361dcd454fe41b8213981ddb74b53ebf2d82dd3cdbbf9472920d +8330a01d29bb9ec5bdfd9f6491fc5c97df80a5246ce5cb61861f3a2e3dbbe59c +833e059b152c45cd2d843e42781f590c91a76e4466aa64ee6b4a4f58c00b25c3 +833e4b1fae26f8f8950dcbbe9137be08f24b07a988dea07bd9f737684eb5a6d9 +8340e5fe713ef462809ddc35bc7c4f48c4661051b38dd1f13c6b7f8863775510 +83468a45d168be82a1d03a7be475a4f46f83c2636a237301938e8b3f6ca3bd2f +834efe10771777305fe12fc5cc993fcd3010110cd5019275440e02e3b0323445 +83537400736423e572454e9e480098966050f5d3c914f747ce8a7f5974b7500f +8354fe9e9ade0d789a56662685f6efd2aa60db9611bedfae3af6d3d6d28e5deb +8366021977d8ca7712119af42a3a6976069c324bb317c8b63521321e03577d5f +837b4db352ddbdf3cab31d230706a9f948ce04d307b9b7107aa2b4839a5fba6c +837e86e3397262a5926f67e3f68e42ccd2a8d4194eaade6f8c507398876e3497 +838a2247f22e9ffd171b625bbfa79dccbd178b52538ab54e3584c66eebecc1c4 +83965703ccb1ec54a30fb419a22c21780ecf8f4a7fc162f665515dac7aa5c857 +83a35f55d7e9da4695f8ce27242f442964105edd9b6bcca8883a89c54b07fa8a +83a52101ebd8156e9cfb573e9814262555a12821a74c992c4aae9bb1b463e419 +83a6ae6d513e67519e9733aab543d115aad15879b4fbfc1f881755e2e71f6dd6 +83a6c6f5c7b1824782b14d42a295411dba8fc06c3e6a7da2a88e2e9a3a81df28 +83b26b686379c05fd9078ad00f5d8e16f2feac3ae23334541243f6bb21584f4e +83be45ed14854b0a87ca44554add07ea2f67e5bd614a2701b245f1bcb117281c +83c594d6ee1e33cb8c7fc0853f35d6faf57bbb6e6725c05bb8baf5dde50969da +83d1baf81a119344d175eaae5d17646bf4ffc97fcaf93760507afb64db7f5dfd +83d3a76c61b384beca179fbf8768639455ac9153b6c6d341e6e9e27537121513 +83e3ae34b75adcd6ffada0779d88f36d9e45ab6ac5e8f1ed7e6175d2837f9936 +83e3d01980a4a6d3b7eeb86c0908b477c4adf17c9656421972e065f84ff9fd43 +83e5ff5d34ec5a6eb527ba3a13aab6c5120554e6cdb9d9d8702b074d7fe4cf08 +83e7b0da48c30afaff4e70adb23a4f4b90a32eb0223dca750928665e467fade4 +83ec275caf75cd95ff4b6f45289ba0017279df6767f73ceb59d19ee0bbfbca06 +83f1621260371fe85227e7150c2ea1d3a2f08b5a1cb4501d204e3907833ab41c +83f389ed7b547cec4c4ff7a771ba0794c878a717423f7bd494fc2ba34aaebe1f +84006bd8dc24c1108c87b6ec8e0edb2a006b04e3bef8394f7b1f82eef7dd2591 +8408064f8097e4a445ae862e26eade9f4e16c4cf0d48a42957b97f3dd84abd98 +8417d603a5bb301a60d0e968e875096013fb777079f2a3a4fb5a4111dea57c27 +841e97842a9b235932ec2cf1200eb269063f1027907ae6b5b21de469bb122229 +842997f43616aaf65f702b1c1b865d8fba665fe579ade57a9d84b8622de0ebb7 +8433a2cd2c28d92741e569366f160e54d415f1f319b7605373fa9e7d78c80ee7 +843659180c5c7fd3e94cabc88f5be6c64483390f28c55a3b4540216e20b141f7 +843f27e9906376e56591a558c6cea777f932fb3f639a98b9c50bfddc219d5f7a +8443a7e471aafa87732b384dec23d492af63c4e149172702f63d8251cd690159 +8446fd0b19231d95581323261a5150ded9a00ccebe0fe13b0a4ef55fc9c85937 +845272b9bed64b013f0aa1722035af238e66785c6c8cf448470e100f59bf80e2 +845cf3aad0ed9c310f4ddec149f58ae286db1da55dbf652110db01bdf8c7bb1a +845f5f34c3e4a6c951ad7d1505478f05342d554de502116008d32e00f5059712 +8468e4079c63a535f7aac11183680c97e9ae4304519b488cf951c83b3affd0fe +8481320c4f8f4770b8dde4388475c2b9da8b79d357e26313a1fae9454c777c51 +8482381a5029864664180045b1eeef77e6dbd4f252fc198e602b9357a660fb66 +84856841cfb1ec12173f2f64db74a3024b5820491e622b4e3a5a4a160099998a +84895649e73fc3df8097729a5beafe0c2b8cb75c35af7cfbf3fad898c89c3e1c +848d12de5ba0e9d93d9c53b60aaad7422881d56094c2d621edddac482ca580f9 +8491ee81cbd5bb51f76977896457829c6e302498f6cd66be0f54f88dce04192e +849f658111db356a859424a255b03f2cc48334b2699823a18ebdce671f7f437a +84bef94bdea5fbef2351f6671fe888249d8826eba152f19e3dd0b082e70ab962 +84c57c98d23a308dbec9a7d1b657128bd77bb20d0890e2dd8737f5b44ff4872a +84d8bbf5503ee1ac97adeb366599bd1212cd569f0e95477c7f60c80530a6627a +84da61a27e777a0cd20dc721a47946d0ebc025ee524bb694d43a12c816c6d24f +84e22f84536c36f15ecca2f29802673ded2eea95fe850ebd2451c2ea95f77c8b +84e45bc1f32b9905237191f58b4a05b189fb779b87319a1ba4cc0a538ee9ebc0 +84f286b2a0051243cbbd5c0aaf323158948cf03b8b1be12bf44abacbe1fb5643 +84f475b70e0ee99b0fa6eee1fc8243701f346c447a1446466ed12ee0eee09d9a +8504152e2a3c3cbb7d63f3baa75d0ed7e7f272bfdf2666eb0e18fbfbe01dbea6 +8506c3fa4628603e190906ef29a3bb418987cbc925f1515605ce01cd96a822e6 +85134abd875d966fde282ea5a2617c98b1b1a6422eb6664b4372752d52d45cf2 +8517f9066cd2e6e489b53312c5e22ccc32664628b32cf4a2ca3cc24761222960 +851e83062c20c6b3f83bbe080f7ae2562b14e96f5ddc96985bbc9c331004aa76 +8520c802dd9e57cf57867db14855022abed8bdcce32f40e18f202496f7464def +852b219e3bd9fee50c0c31dcb5fbe5f25007de97292c20194aa2a8a4b2ce0e16 +853157759efbf3dc1fc56af5adf9338ec8163051ab61ac27e7ae5305276373f6 +853402091782f1cbd25a78792f1c731580651e8b3639311be8429137ee6d2c2f +8537b808744ee68b8aa546562c571392d6611f0cee26ed2b33a68e2697823ced +85471d228fe2af1103fea7076603c2505ab20a4290d2757a3c9528e10d8b9c29 +8548ccc1bf58bc6fa38299da784446b3aa3b46795e517591ce75349508c82e3a +854978fff1942577fd7a83dabbeee7125a819a9150b78a5acb3f2602ed38273f +8549ad888280e7ba5f4f6984f175508ded4b9ce852d61730f712a30fd417af63 +854b57ee720a69a252bfd614c80a5316707e69d411e4c6da8d58bd4a92f23b7a +854b96bd3731e0c0d68ac472283d32cb6836bde639d5b56d4aa9864c88ad2895 +854ddbb1225b306bd2686a8ff75a38eb19e4e667276367dcaf804e1e0439f17c +854e09cb0fa81067f8180ffd9b0a22004861b1ee7129cd94696ba4d8b614fbe0 +85558b757d45d0e55846db1b1cc80e6a6974e618bad8950c1ec8a3d3acdb8e73 +85589625e63dd226c872407e9634108b88f8454cdca00bc2e2b3a68851ef4c9a +855fae35c6173a85f0bfefeacbceb8b10e8adfcd5363dce915b0a1b75c69e3a9 +8561ec1d79b71ec536c11a7af019c6cf1148ffab0b5a3c42f6eb689ef5f5338f +856378e53d502fedc3f7d9ab0885c1f3e7cb6e80f61f3c150ff0fcacffa43a1e +8568a6d88f6f202ec0b5436629cdcc4385e1c3f58d69bc4dc6323c5a59009fe9 +856c52206c5bccdd2cc470e5f294903d266901318e0d29537043493e71adc75d +8570f9176e828df97983db2801a4c316331a5b883e6d1094581bf8f9b4fc537d +8574b57dce3f43e721d43bed62c31915bf1b50b12c5f23e0ff3a0b41f66a609a +857a2b8c51fa7ae85202348f1445354f47da1d54520069bbe02dae1c89dd29bc +8582370d15e9e6120fc7b4bbcd47d58ed5a70632457edf6f3a8ce8265085d344 +8587b7ead18b83ff2f80412e3df3475b3a924ef16a9aa8bef73cf6426f8ee6ac +858aef9c3a6d42d6ad15147a9dfd751118feeac436ea381db165c82948de6106 +85a04457af092ed67ecf9333e7fdd0a7c58491498f86f977f4b81de13bba7974 +85a19bfa5e852ea211c8ca69a9e3410a0314d62b2d8bf07314c8e5108bfa3e94 +85bd1aee967d749e3b88c1130be6b1f524e555db0fd8c906d12e678734e441cd +85bf4ef425fba7bd1f727d929d611c88375c7c0aab1d617a5b7033f46fb95740 +85bfe748a2850cc7bcdc5f8ecd249c5d84bef52a30872fdffc14cf0a41ae1fa2 +85c0acaf6ea94d58af83caac91fedd0aaf0f9fb8b9a94477abac79ded83dd86f +85c63d1d06a3b23d4fa9428832e988815d4ebce84589a9fc8e1c1b27c088f061 +85c6a634d2a74c4fdebd92efefa4402f69ed8fb4744c59423e032f3efe8efe32 +85c96d83074cbbc7044c1058af1997d5aec2da3abb0fcf6e4119be6fd88b3a46 +85d341c2b3478a8fbb18f8818c94373ab68eeb0bd3a7f9e84cbd115df7dfb2c5 +85d694613b2efe443bc1360d6f036031ec5882b1920f412f8c58549999c23ed4 +85da1b4df6443da615edd392296480b80420b44b782b6041d8262bdb7f4a3fef +85df8fda0c77d349c89eaeb86c3362ba9068b94bf5850c97249969d694ba2fbb +85e4ff6630aebe8ab821650062add6a2d5afc5b9dd464125fe640e178738f955 +85e543e70e3d04ba4f234b7292961c4a0871d7f89ec5cdab120d0d85212c41ec +85e73328bee95a43499fd15e381b067ca35004aae357079b4d99d8ea3258268e +85ee2b7f4c33d5228cea5034f214bfead6fe50396836b45e819ae93e5d5ed5a0 +85f2a3d30eed516d5815a4407dea2172ea401d06096952c18a31dce95c2b6a60 +85f510e563edf2b6cfaa9e69e8e71c4cb20e6ccb1a9a0f2a21e56b2dacbef133 +85f8bea05f53193b2d9dacf663fedbf55f1d546007bf3ed3910e60dc49a40b48 +85fc165d2e6b04d5c69e8a85cf7fc8394d6c1de59aeefb65938599dd1a103b85 +86046d77486c23a87d1a4b49759cb7afb1f5132767400a2a8e5c9504efcb238b +860548ad9bf887f1a3ede8bdacbd393d3eaed3af073bb0d2068ebf9117f72c10 +8607f3fa017b10c721c8c7117bb72e7b0e1c0aded022280fd1959e9e3ffd7b82 +8607f42b8f5b3b546c144f072573f0a5398d1095f3a3dfe80aaab563b1766406 +860af8b5c62f822da80bed19e6711f1964e6d83911b5e6378a708c9aa43c7b59 +8613f4ab751a08ce780f2460add0e323d59a8bfb69dd395c2cdb473925846831 +8618e989b0fcf23823772378391b06ef8c7a7931b35a9ce3f9a59c2cfb20cd6c +8625dbd83ceecd67aa8236918de1458674e9cfcdbdb0c66f13d22320b5618db9 +862a67dc229834b0d368629a3bf2a490f0fd03a1350ebc7785d7ac77457fb7f0 +862b5cdf24d16dd959e2585c9beee2496cc302bbe2f0844aea3595b383f95642 +862c37566fd856b3915471ebb0d3671bc644a472ce9dd5286c9c8fc985a473a1 +862cd522d01d55bf05f0ef40a9dbbf4f722867cfb5e82646e59388ba2c3e0bb7 +86306896edabbc3fa8b1faf65347991347912a4767202e9d4275ecce7a668583 +8647ad3beee126878b632688622e5a1e01df6115d147574fff56946f5928b614 +86551659adea0b4be0c9231c0308b191f480d9c875b7c2d93fca223170b59cca +8662f8eba856a393d856170204888d600821aa28a590524393b052328a3efac1 +86668d5ab1eb299129859efa774d517e45db8fa6476104e10908c22832e98756 +86701bd0e59e492f049becef8406509d1f4ae77db688aeda6b5258d0f5399523 +8676c5b7fc0318e528cc84201af9cae7844aebee4a84a478b8f5df193d1d204a +867cadfc919e5572e96ee3a3c667d20a201894adee9f2a713515d399e65ddead +86906b73f17339600415303a59f796f6d841afe00ee9333424b29eba3b198dff +86a0ca09c4d06d5f61bc1a52f0f304f8d9635a36297f724bd6d1fa3d87dea646 +86a356884da5989e123f663bb0f764c61b2af867f35a7ca0e841b97d3c7a760a +86ad9732b0e0e4b68fd7ca72978071dca6731756aeee4908885b2dbae52cb65a +86ae7928275ad239a048775adfa3271b41e08546704e1020d0406e240e6ba6b8 +86b02db07cf18176d139d828a916a8dfc259f769d42348c5acd4888e44f81a08 +86c0d37ac167f67ba45bfa33c7159020e4486cd09bcb3a50aa5f6f0916c65ef1 +86d56e43d4cb7fcebee82e0afc18ee93aab9a5f50d6a20d4fb8039581113ea52 +86d71e5ec2b9d83a3c14ae352590316873ff774cd4d1782c89f9400d9eee25c4 +86db19e6033fc7cf7e2e6f1f25070adace58e492df1f263b1e4af2740730cb02 +86e34791c0ddf8a9f085601698c2bcdf76a34c37aae14587a0ef35a6049b8f3d +86ed23779fbe7443d6dc181671baef433651af4e4765fec5fa2c054eaa58484f +86ed8657993fdf82c8d7f9445ddef9ebea33c3b101e7ddbf7ff1715fb4fe60c5 +86edfa2b5de6217f0f3bef0f46b74f9bd859650e838edb0efd7752529370be5f +86edfbe5d26b8e10bf56a94631920f4e40967ec1e407d795b7467b17ff2cadad +86f06466e77138928dc320f912722ead6fca4c26ea7a7b7490a124742993d1ce +87025376cc455ccc4162c2fd778eb3938a59c8394289cc8701ac40503f5d4c5b +8704feccbc7ea49cb4654950f5f2d8a2f8a991795b04d3328ec03634e9312fee +8707ae49633b064d033c02eb32f9077881a62cbd01f0f4a9c7c771e8f21d4e2e +870a32dd3397392af84b9b823b89db4937c96515b5369540709ebfbb3d76934b +871567ed77fa88ff53cf301841e4cc59b92db7c16a44d0b6f6553234e722549b +87232d9171cd2d073b779563f3eebdcb32fa0eaeb11aaf95e7ebff8243e2034b +872780e3fc218aae35d7540f073c92b040829b1571bc24bd207585d6e22c1e7d +87331a7a696760a69fc01a7d1da18c609e01ebac4024b91c7a21da99d0738055 +873bb75c0ed1d25fd1ed85777fa020dbe6ba10482653cad5d58a232329d50500 +875243de245a2081ecc3f40e8598be1cc5664d158a554f4ab33b3ab1086561e2 +87688b7721cf9984e9d486f92066b0dddad6b5261379583d270f7cfd4484d72e +877098387ee8cb2416023dd7572a7483e625c73a97d8d1776649737e694f094c +8770cee7ae7ca7501dc0d7b19c0fb2f84f531cf9416850c2974402c29501b2c7 +877e948c8663a6587d9ec6c2a3ba18da649c4f161ba1725b9c662a2ac0f7cb25 +87812ceca39991322821729694b04c40a6e55abd6e516eded1c9c898c8624059 +8784f68f0e0d9329b6c354aa9325a89dda70b7f933018be5d543d0f96e08e8fb +878cc754465d176e2a1426172cbdfc882e7fcddc3a402074f2c7251df45cea26 +8796079c4a18a5a60c8b497da5505f67e0dfd53657cbd9d1a939f757ce4202b5 +879934bd14635a85eb74049b3fa19fe24106624b4b77455ca716b556f6a1ec8a +87a6f450fcc01e5728ebd9fad3086cccb3577228a85520ba3a761987ab148310 +87ae46104885893bc99dbac4edc1e7db7e05e936609f59b778cb2ff41a758244 +87c8896cb4bf3bcf1d627a27f250e8a7f40c75f9c97a710e51e4dacba99981bf +87c93df5a9b69e2b201fdbe8b2d3593002e49edc0f109be78cb16c635e3e6e21 +87cd7194660b38acc82fee512937bb79be3bbf17b472652b7e8edff6c086dfc1 +87d4251a1cfd071781c6b30231aaa1b2f70c1aa5b9c9521a052a7e74bcd8b7d7 +87dbbf1028c082620f4558efec771b5ca1d7d55df0627a78c05175afb1d81390 +87dcdf0eab8b4b2d23264b6ade92a8315850a770e72c890f12c7a8e5b44aed5a +87e10e5c27f90794e4fe53395f886af01ecae6fe7430a7674fac22aa3531516b +87e4a5d944a7ae25fc9ee6b1f1c9cdb5adda30e68ca1fa956adaed3239b3c4c8 +87e84c0b3dcabf89a01b0a79ac71429b8dd0888984090f5b52973a97601fe5b4 +87eb9bb9c9c152f985fbb91146266b8c3521f8ccfea093f901085ce20f3408db +8804ed6ca3c6fd9c06bc513c7a449bce2f8c5d35fc46539bd7f2ca6cde57296c +88071955564b5ce1ab170ca07bdfaacd5499d20ddbc3f47420b6af7a5b99f14a +881073e9d0070f8057711d6c37210100284c30144c8adac76438c1dddbf5ebbc +882492cf9af08de5f2823bd32006fee99264890bb0cbe7ab120b079352908375 +8828b37967c74d7af40a5ffa950589aa23edb16ada3143be2b5f155a5cbc2eee +882d1e15924b59a3c3f666f952a6df3b3c90dae071187a794ac9400828e5b3fa +883332ef82ba41a7c0e5b15b25c6ae081ce8fd4690e90f9e4f5ae004fbc2c8c2 +883791b4e3f89a482a7957abf4aafaeb38a11198d7be9800c7c0aa61a4733afd +88443302039608c9f59c0f80335156022ec028b917cada88d64b28c607d0ed88 +884a26f679cfabf85310122c3690d432fcbd091b8e091df284ad73d72e43939e +8853c4ac1e8745950854d87da5daf1acdf895d8e4d21648c225686fe7889acad +885a32acd95bff685d479059daa882b9f278cbed0cae0fe774943d27dfb0444e +885d35be2913a402c9feaf255d75310b204edf5d1de2a793bf51b3cedd0033d0 +885d6e99d3b0de658f63c786410825b7f7474aacf61dda28a39f4bd19daf8925 +885e43f0f7bc7916b44fc54c48201752445783c0224e11eccc76a7a880c3855b +886257b0ae5b377537c8e8e394b7a31f9904b5cd1971c8216e353b2f93f97d60 +8869efc9cff4eccda4d730bf8cf27e1f87a1f3ff998d0b9348b53e38be8e5f76 +88813d751cd3c03e678de3ecda34cbe2f1a9d4020d3db9ae77ccf2e522ae3148 +88822cc4933d70f19f3cd004801efe2d0d5f75592936a2426d25c051129a652a +889192731990ecf68b3bcd4b98a71690a54dd8d5b129339b06719f6fdb04cfde +88b23e40dcace54067cbf851eb3fa2bf8a67d133ca0ec12152259617683a7ce3 +88c45f5110016afda2545ba5871ebbd7d06145c4a80dea23094b2ae60933f272 +88d6182b6ca0aa317baf4b87906a8567c3873e62c6d5d458bf830fdd49348cfc +88dfc516e159be1650d49337af5c8a2829cd89d72eadef430786cfad952656f2 +88e5cdeaa7450486db005e493b204c11350c30364450da4aa6b67baf7b3ab609 +88e86b3e74f3cf3dbdb340b9c468d17cd112c5e7066fea69c5b9afcd1ded796f +88ebe5c724f21b540fd547faeb7312ab05ec5ab928f056463682c3b43adb51eb +88ef3fd185b7a50dcaf841710ad87fa8109336658541a627e81c74e1c3f84cb1 +88f88c168675bc094a476a5376bc99a8d9ac5bdc11bb992ff8633e592a1f9406 +88fe7748bae8017aadc6a4ce977c4b49f97711dbc459da0dfbdd5e33fcbf427a +8906ffd831de533ea40dc4499b0eac91e9041b6994a0b480c8465e675d3ea2df +891053caee73359fe2e4fdeaf2c6731dda7916a6b267ac3944d66edfb53eeac6 +8910ed2873e3835a7d5f8e3b635395bf8705213dae239b36fbc3f6bdf85fef7d +891715a2bc1693952c61f4e51433a47301cbee7ac764038c25c57d8327179c97 +8918760f2f61ec15e40d24d270a15a26d83c054e9b2dd42e4172b56acb6ddf6e +892066e1b9124ec157ea11392e07ba3a1d8408f4891bb3efbbc7d44993f9eea4 +892392cca3506f5d393a0f97dd27a762d339a0884dbdb0e2e62c86937b632672 +8925b201f3fedf6838ad09024950744611f802c18a1924f71d7173bd4fe7f6c9 +8937937ed7e713ea138887375f5317e1437600a6c7c6d39e36b4aa88e40de2a2 +89390a82cc1ec2e8076a34dca2d539879bf5447aec7088eddcb47e3012498a75 +894f3038517037ddc32dcb895edd197c14b07f84238d27078b1fe7b4e646bb60 +8955065af4df1b777f9c5063bf3946e28c302e3ac37ec2057255c144eb9f614e +89563336d462dcb80d03a7f9ad05c5b5534cc4fb0e7ea0500c1c5e3cc046922b +8956be43a0932061bd256ea52534847e15cee84b3aba3139bb24e2ce166811c4 +89579b0cc3a0b67c519e3dbc0a880c1701f53046d7b94182a9c76ff215c8895b +8958ad0ace694dec7734d0146c645ff7d214da3ef31c4481d4f35a82931db49b +89596d86fb0e93695160bb1be677daa25f66098fe89485c4b3034b286dcaf2fc +8963e4cdbbd150e9109358c36a475fea24f97ca76fdc2ef887c488cd08dc9bdb +8967899ff027aa69bed2ec0fad77a9e2911b3cb866b769ee9a0255aa1a376fed +896e59b4350fce734343493c6da6b73c30981fe8f634525607689068c3ec4a5f +8973beba18071ca2f3e2212e85a2a2225b377bc3098d2143367c2ac109ec68d3 +897a58045d6b338cef4da1dce18ecdcdc92406b953826bd454fc558153f8db14 +897e6a683964d402277c64e0c7a3d2eb41743e3b692d7b29d5abb9ab89b52160 +8983c466be8aca62e5fcad8be6920a9609ba043f7ca78e2e30d940eae74df8ad +8986c0e2c58584a7b901fdf54b633cfcb380686b81af28d2527355fb9b9fbc55 +8986c438d35ebbad9a81fa42bcea6f2f2989728951ee5f855fc96ee47297040c +8988ec652b2084bfbff3d3d813308ab84969b6b47664abb4ede56a9b19d80827 +8994ff035af396162cf0b01c734d7f0b1d7ad585e0e875100fefce12a8cd5016 +899fbe3cfa2c3bd915b38d0abe30a29adc54013a2530d5754e8febf5fcbbb64b +89a28b9df52f64c16abb4fb118d4263b7ca6391866849fa4780ee59371f33607 +89aab9c9e712c9a6494f825a95626ab2f5820c410390c213b0362e5a6bce2be9 +89ae8d48888226111461f0180766d9e831771a331371c52bcd4ef55eebe7b696 +89bbfd22e9fa9b0ce8d5f25c27f86f76316248bf9f67003e01e5f001b1ed32b9 +89bdcf7a95747895a68d6960d8cb19938834908f6f3feecdd424851d8127519e +89beba49ac83440e74a42dc5240cb6bf1779c6cb8edb97ba0e2952ce25a70a83 +89c8ca72a441659cf5e20b9198e9c6f9d93c94fab31da663463b6a2f14036df5 +89e6884d6853204e8c4090756561b11964e51e3c7a1ec1c35d1852f639eb3596 +89e77eff3283d7b1fb5425fb7c53d14877f18b0f847923a2f673b7eb24d32d4c +89ea84c2efbc5a569bb246a6f7f5ae00f52ad225d8c55c4b0490faab289cc6cb +89f150d6538f3916d0759bd768f25e7b6e8b3456d11dc815621480109ee80a13 +89f2afe1051e1072b5cbbf1098f378469fe4666555de185c1a7dc13fd21c7350 +8a12255bb00bd77100a30ea72ce5ac1fac93ce84eadf21518e29073d5163be84 +8a1b0238d6ee8b8ee1af5220ba21f60ee3e0ee33f4b95b23f79e89c0300166cf +8a2d1eefaa60109cac4b64a61474bee1e730f1edef4c781151060de975eacc31 +8a2ff51d527b0314ed1f0992f89dcdab7337be52b09f561fc7cfe7148746d412 +8a3534d64c7c7816ed5e536e96235db4668d454842d3ae1ef2d45c951e51bf1c +8a3bcf9059d1fa5a6c04110751e45823ea3881a097d93360d4b00fbcceb6c302 +8a42d4df26be91beeb7dd8f9b1d0c2d5efa2bc2dc44da1041fa6a01e250961d4 +8a4d203a2df71db449bc6b99dd83e064365a5d3bfb8afe8b23f167d5f082e84e +8a4f16d441f35665efd3d5c9bc8886b148e72adb060f574f10a260a0fd79efc1 +8a6351f0d1f8b13a90fbbb25d38aebcf81809736b16ddb638fc497edb954e32a +8a76046294038bdbade8b930fa6f7e67e74a6729b3ee81196c7d32280475aa5b +8a7d833ccc381864f0cdb3b4d38bc2ecca9528b9f7936796d0b06efd8b0a5fc6 +8a98808d675daec74685fc3d6ff174e0010a82fe7513f7f0484cbed35d8a598f +8a9e50920d6adb98abcdb3c1c00e89175acbf2788115bec65d7a9c9caf71ee2a +8aa1bfd55517dfa4b8cd0749d9021eb1e8726f99c89ebe61b5e52fd9c74abe6a +8aa702700f42049d8d9bc18a54d0ff5ec269c13b383245a9286d7f70e0747084 +8aa95887b9a6871ce9f45f98b4f615e36b2b9f3b1a97e75ee0df0a2650de2c6a +8aa98430178e7da2b14b42ebad9fe68b33e21381a26d7b61e3fd23534217fb1d +8ab37cb4f6db794cf99e8d3b6973db2d264d9ebc7a8fb8dbbd8241ad84ab12b6 +8ab577c41b167d68bce78c4906da2b865f6dff7c5b02308207724c9b0092d3f9 +8ac360c0ed4ec3216bb58013b68a83ba956a4eaea45fd987b388cbe1b646759a +8ace04732d2444b763f985010bf63d072f134c5d13741d9d1c1a56fd74fb0cad +8add23f42bca4a7ed58e01429e4bbba7874df3a33f2320c773fb38ffed0d290b +8aeb6a7e35c5cd0752581d92f23ebba309cdb2f028d4dfcae07af0348cac3894 +8aeedce465fc1a0c2414e67e62cbcff47fbe2bfee39cbb7c33a1b6bddf87f5b0 +8af59583ba534da6da15a10b8b8847781fc2650d3ff98317cf67c69fddfb1d7b +8afa44cad69212bc43d534b0863229c55ec7bc05f9a84c5c57879b3089297072 +8b02d0f143f092924a38506985c7dd671693129fabb0eb8cd5158eb5226ea3a8 +8b11d7026cf3eaf4e5680b307d206b5419421db24938b16c6878f2a093b904a0 +8b13876d21e10ada406055aea75d0808e5efa902813987c27dc01497fef1d81b +8b2367191017105b2c14c88be0e68b0e26d36182e80daf9bdad4f2b4fd73e3ca +8b247efd445c6113db32c033c4967daf642f10a5ed10eb6fc76fffa36c8e1340 +8b266f86fa3d1488c2e779b50e716377e6d2871c985938a03d4ea9a2028620da +8b2de9f9d44ba375bf2e510390f4d7d60877ecf4c2e3188b3a045c520ada33b7 +8b36399af3b8da270db640587913092789fe84469de61f14144bfb18f462e689 +8b397a52015311114cac2ac189cd6764b820d6ef671328a225498c004f092be8 +8b4647a5a3a663ba8470c0efeb906208fb5c6a21dbbfaed1ccce1e675f01f6e3 +8b488e679bb216da5679e5db05b4616a5149cb5d2626fbbd29809f5352649dc8 +8b5881a5f1c759a1a1ae80fd661da1d252f24aaea13fa82087ff5272b63bcf4f +8b58edf4137036e3da30e94f3c92ceeab41a2ab241ca3b994d7bb3bf35abbfab +8b6203484bd189d8464296015659778eeab5c6da907bc5b083772043365efb4a +8b69af47b4184042aded239d4438155a454889f06ba9b86fde7c295f09917b65 +8b6e1e6b2d9b13f7cc7d3c927d515eb094fa324d66e267f73676d854de526dd1 +8b7026480afd91f98007bf673e70cec836cc453f77a3ac96cd31f52aec4e889e +8b76c3f6125321ef2d09d84a5ccd893792f8e20d5023665c7c109db28969c4b6 +8b82bb7a74813bfbc989d9a355008c717d42ff6af35f50c1a2a9d77fdac766dd +8b83751fa011fda23ea30e13e29dcc055d4ae77d3902a31137f80804e6dee5af +8b90e59aad2e8fcec69a839b0bd9593971351f22a27b43431bc6768f981d2597 +8b94ffd8147ab3bd5b41c554a7dbcca69ee9c053a44fce0cbc834901ae2c0bb4 +8b98064c448fa7522e92873b114647267c9fa7a20a86551c6f8d440927ca51f0 +8ba7a7d75e15644ed74fb8f842cd185aa1c03513196e76db800867d0c0aaa3c0 +8bc33f7d97163c8a3103885d707361183409a4d8920ebf9157ea5c57e38a05d3 +8bcf6e6cd16ecaf12c7e43aab0ef2b9a1c846d7dd45db3980ba2cdd31ead111b +8bd8506a521834c6b7ba8498347a39cf37bcaec7987734c4d8b5ffd363637da2 +8be20064b10dce4f6f81537c46a3519af7db1c13fb04f7a320cddeaf2e89fdab +8be3e402d1ba28437bba5f948d6637e0fae628e4db0f2123108a2db7628774e9 +8be63feb8d68ce26d902bcafc9eab1351ac577c100cba0fed6e097faf788afd4 +8bf4093ee644f9fff719fe9d3550ce5b31c6c21580d78306468a00acf4cd1979 +8bfc028b868ce3f4099f864d27bbc35459b754938c6e70938ff6e670cfc4a320 +8bfd96e92d3b6f1a0a17714328260a0c2eef9ebb2a3d8d7dcacbba30585349da +8c0112048461ce853ce823cc84d20a6d9c08effb74757a046bcf1b3e8ade224b +8c09df859d9f4d10b08426f20b6b4f7068eea07a1458687d08a3613d04f0afde +8c0bc2e8a19da1d8fb65ec30a6cafb134554a40041738c77ba29e97242231d4b +8c110194096d213ee7163def258310620aba47dbef8bbef96064b587d310d0e5 +8c1ddc8a39b0e5e42e92ee4fb81e2808083381f612c1ae507516ed790694a780 +8c2d6156ad49e0aa3c06b4d25b1d9cf90e6c4afbb70eb8e568f1a2b2dcb50ef5 +8c300152186a77e1042bb718b3cdc28de627acdb08731d5d5b1363f6fef88cfd +8c414b2644d9a809b78fa8cf4d4c388103c95118262959a3c473b1d48dba0689 +8c4167bcbd2ba55e79f06cb1f4f758b19248a8ff952805a8212604a3843c89c9 +8c4f86f14e3d4829db83fd50118fdfc7aa484eebe95f95086e614965ce4c2825 +8c4ff44e566ce0c55deb2b9f5005f6a53035e21c4a6b941b330624843618d1bc +8c5891772cde426cae8ab220956a61e73e151d186a0a544b3a79ebc56d6956f2 +8c64a11d47dc4a89d04475f8db75d1cbe9a640c41c97ea308dad7431728afa38 +8c6fe8387ff68120211876b8e39d392cb35390d675def8d8a4a09b373d131885 +8c70ba302e8dfdf413e72d09d6d53c2bdf9f44a33877840e8ae0c1f8aa3a86c2 +8c75fab0aec71d2f45601e0b53156452bdbcddd2d4b18e57baf4950ce4ff43dc +8c85f6fabe846b14b61e9dc52c2d25f881aafc675ddd9ca3551e238935157811 +8c8698ed9d24d31fbd1dd681a751442352178c5e6005629de9a4d6bf8bda073b +8c86c26010f99726d7b778b166f90be450a34a62620ccde86423b0a86fe59daf +8c88b614360d38f429cfa0d6450ca659a844446bc209abcde04f5b7a5f984ea0 +8c8afe70589eddf522af787fb9ad24d2bdb1ee81d37fec1256d5377be8e2637a +8c92df08bd15eb4837c56a4002fa54468a4a0be4914dceead4f8f94c06b610e8 +8ca34e3175e2298e0118986abf0343545d918eee9a0d644ae33be1df1e0b4ecd +8ca6a14d6ef0781a14c32d2d376715707450a23e56c7660acc91d5e6e3d21700 +8cc4e60d16a0be18db7af9b68c63ec31863803e62ba9f783cda07eb601f9556b +8cc866c5f949d01ea9bbccf6b3e67122d82dcccf8f5f8bac33f743aa1ccd0a7b +8ccf09c2e71d466690e42ebd8f7fa38c0ace73bb68acfe3c5dc91d10d4b77cf6 +8cd541e30833d3a8d4e2c132c362a6f893bcb8c43096620909cb9cd1ec3c292f +8cd65061b373b933b7248b8c4ded203872d16eb399e2bf168c3026fd776ff482 +8ce850585e50097ab54ed06ac90c07a6d676edd78090323e48cdc8871ca4b718 +8cea6a56fb33fde544d31ea352083dd57ceee735ca756c3b1269c61f9eb32399 +8cf02949ea03d3c50fd90c5d4bc16c7263ccd28a84fc86cca9629022a8b3e2e2 +8d028039df903855a6e450720c9472bbb1730f81edba243e8eb1dcb4f693d16d +8d05233bdad2a0bd6380ed1f2e0c885295627fe794f549400deb0fe92eae0060 +8d057ee7183b7c1764dd462883575b1ffa9087c26acfa429a516810b70e6ef3d +8d0babe83ba07126421df23085ec8e6ec48f955846ea0a6d8ea539cec173d679 +8d0e3a1a6e7b3bb763f6c852074a2d450debeb2a7fcd61b70c922ffc021e40a5 +8d1375f36cb6631eabe8de4fc0ef22f0cd949d0af4bbd9303756afe4e4758694 +8d14cecd96e0b387b5b6094c9262b866d02e6c43ae05b42331c1ceec4834893e +8d15ce86b92066ee66f0402146ad99af1d6125ac94899ddfce7ab6e9c0bb8347 +8d167a0e89469c6a7c415a992cacec369af68c0f81fb76685566f79e34c575f0 +8d17c91680a2e62ed6c9c3bca4a6488ba8aad16127d7ccc002d1c39bdebece11 +8d2dc2b103a2c696b6e3fe7686501bf8aba02ddb623fe1a96486109601cc6e23 +8d2e371d2c4c842acbba5170178c0fc369993eb0d327e5b97aefc451252400d6 +8d3c00da2ef5a0e8837e46e3148e99200143ad2638994816fab102f7453b28d7 +8d4c4722eefd8e1e5f8bfbedc65c354234e80455835f34890de19b277ef1143b +8d5101440673055a2112928a9d840b2f6035118f47d5e46b42361a3af1866b11 +8d57f63e55fa46edce3a4872c57fb7e882a1640738dcb1e08adf31b48ae0cc0a +8d69bb9dc108b85d62de16b4e0052b751e5a6991a2b21ff15c59f773bd5833af +8d6cf8b402705f1d2d05fa53bc2167dc587b5a63cd454de8186aea176eca9994 +8d72dea6e7274bc3f0a651e0c3feeaa2aac27290c66c926d790d8001139fe8ff +8d7f9fefd644404079b83dd098103431ec551d8e66378408319a77d8c99beda6 +8d83b273112990986fa90702aaf1844522d4512341e90b8eaea251e3f2e0db4b +8d92819324d80ec2b96be244096fb5197c2fb45f238f1bffd5be8a6692477614 +8d959dfa3310dd089c46c66f4a63c0e6a1138836f6330cce05201fb8a54237ac +8d9b77393663ae0124e7b4adb10171197a138cf5ba9d14f37ad0428b3e109727 +8d9da206f76c54727d956dc3da02dca44bb95f2503f16156e75395032ebc8200 +8db59f4024b3b52aef43ef0b79e261bc10611e3c5f61a4826e6cda91118042e6 +8dc81af526820507ddfcc0899808452146f1731cc547724a0d6fd18607a249c9 +8dc8cab0938e32f4c207eb05a732999a21a8a49c761d0d7f64c96246dd8d23eb +8dd8d737b2b090b120cc72e5cca243885b828dc5ab2e738ca04bfebcb8a3510f +8df216b2ed5fec55dfb8f36c316da7906e030c57b9fa315999c1538e5b0cc9c9 +8df4bac374081dacac8196fd8a19c4251acc47f59f1c805b65b35552512501b3 +8df9a8eb7192ca1441d9132bd620c7512114719a3c48a053f2e1cc54b2758a97 +8e01704982dfc199fcb52d426ce00582bf9f5a443c3c7b1d1c3bb9f668f9a322 +8e02cf1df6b3c6d45176abc45808e9674a88893f629a37ec5680ce770bafd1dd +8e145faed1bbbc4a62e079a084ca23417977862efaa516befa2af3d39c515305 +8e14cc56bc6324ea88a4cf2e6724820585be030a3ba13a147319310307afc680 +8e19dc9148dcb362541d88ffa0477b3864b18b791dad01bbaeefbac4ba56049b +8e1c4e12dd37992d49a783999f24c44b4daefce2d5b76537fd40e3030aaf8ca6 +8e2cb30929752fa3535c18d65d90cd11b9e0e4e1fee77b219c86a3df86fff597 +8e318a48e7080b26ea47f09dc60829afa0801a191950211857d227fdc80ee2c2 +8e33e2477ebe9ea601d62a915af5842583e34bf9312e5eef9329579ef56f29a5 +8e38f76553d0099343703a7ea2444fb449696d4f7e9d766d0705aba37f701731 +8e3913cbd1f305f7172197db1cc13d18dc5b23c5a281dcbf31296e5d4b655e09 +8e406d5ea8d58c91948cd19005ba18bdafa0e85117684a62c133a2808d750873 +8e50b1d05684be7f29a52cab5bc5d5e9650b3c747faf5c153c25a9657b7233c5 +8e552bf0bac38702fb3b1c4a9baf3adde6306e361d389cb3781b6f9677742936 +8e6f2ee2d675a0d65a0badad70f7415b7d1f76f4a52ad06e11f9c6b19186dee6 +8e76a854a923129f810264b9a9e22a2959a67d76c61b0293f200a47597a920f6 +8e7a8e0a9827f4f4599d81d24936decb0f05eb9c0dc8d4d923ef597820dfb431 +8e7ba429d748d92fce4aad01f0ddc2a56ca4a004ea0a4aa330e05f2bbac3bf42 +8e7d4884f4162747b177922732aa4f02e9dcd49a024cf18d888a07efbeb0663f +8e9ce4ad836cda3480c57a80d6d93a617ace04f31fc80603e2f56da2fbdf4fdb +8ea12a37c15a049e72f912dde5ba598703f6b85627faab62e189aaf66d53e4c7 +8ea29ce286d18eaf245fb44ff4c14e4c417f396707696a71bdbd015b00854652 +8ea57ee8aa6e4d7a5568def02656b06e9708111d31f7dde48dd50f704f24394b +8ea688ba33052e6b79e6bd88013d4297aef04a0b2f13e59545aa1267d2ca09bb +8eb4f27668a8b16054b816e45b50b245e03859eef136edf854128c90d0a4f13c +8eb7bcc479e09210b06878feeb122e81755881711caccfe08784820f01be26d4 +8ebb45992109631adb8625474350999fdd5745e43819e803570f7005c5975ab8 +8ec224812550fd4a251d230aadf90164304f5411fae4105d521914f7c34fbfbf +8ec27d43adc5e0f6f1e9585a3ba81d124621979a322eb4ff9eb3e3c5e3d1773d +8ec7a645b226dd825056cd9bac7fe7189895a5306b49110aaef8effb3432b855 +8edba483219d2807454401c124d19b2612742b96b3d412d40a0230daf8032ea2 +8eded787b93ffef641fce0552d795db81c3b8188d4ebfecac35798b33956e632 +8edf436f83b9127da385eda60d2a13fbf4109a240c3fa4801b0e9c5b36cf5b2e +8edf7f3270dcb73d1e238679d6ff054123ba5c1c540fe31287f93e1434ada0fa +8ee3c029918d5f201731e782da5541fe7b40dc86c441e3650672c844d97bea75 +8ef23470459d278fbafb0d53b1eb322ce02c11cc2816da86c363c7d1c8e69807 +8ef5eb6e17b78ab37bf70e5a9b14ffc65e714b69a90992584bc3c6f220095486 +8f0ee4ef4cb56d38086bf7eff4554405438457e68dc5ca69cd8d516fd5e931c7 +8f29765016fefc804c8c3bba30c2d45ee5c6bea090362f15864f896e5b529fa6 +8f2ac7efeb04c07f16751b9aa12a691a770f54e1536bb9cc935728c93c58dfbc +8f425fe30f7732b7d5222cabaa2d995c58b6250b949850b8930db607a2f94209 +8f4c24caff4ea6a40c23f123970821396646b5c19f45b82c425f50cbe4a44e66 +8f67bf1bfadcf48eb03e42eee2d1848774a561be0a70e12167e5d5df954cbfd1 +8f72e219818fb2256fd86dc6781a64afcc53eed983a6a06f7cfa30c4031fd76f +8f74bf29a0dad00ce12dea66e0f246bfc7fae3f757606e4cfa024dcb975ffff6 +8f7b2a73ac08cb51095a312909764240efef54af32eb007ebdf3bfdca1aa55d4 +8f81e2c6b95d8c32c38cb3411ccaec6dc9b75c896c3d09e1448f8b3956758287 +8f8543e0269d8acd01327c981b4faf950948c85a7029994460392307554c3477 +8f93de3fb49d4a22c2ab23dd36589ba43370b17e5298035fe0c55c751a35584f +8fb206c63d4263f8334b10a6ba5699c40aea95d52b8d10dc916e5ce7ebac5f94 +8fc16b1342ca1fdfaecebfc9bf71597cff9a5dc00cc5634c00b656e952884ebe +8fc3aa74ff84fac62b33bdcc6806d5c5c2adbfe71b1e3166a06c9ad2dd433cf9 +8fc9ba184229e85ebcf27d0c622111da892b4c6805603f48b9a7980892791181 +8fccc070d1335d6c2220a3331632c3c930659618ee756ee75a1cb8efe2410310 +8fcfe419d8450cbd1850dc08c4a7b7084356de2f74cd3671a42cc85a3ce4c370 +8fdde227a449432c0fe4a09ae894d2b8d5bff6d76f203869a4df992929a4bcb2 +8fe0b758585a8e861a53d45c43445342ac31b9a32e42f63bea5ce6ee2447a7e5 +8fe933b869eff0bfae92dde4497547462c9658d23b039dfae25f318f303baa23 +8fea93a27c0821be309f989a859df10d468c6e61d1910885c289e9e7850dbe82 +8fecad8ee2bcafa1c0dcf3fc2af22664ab8eea89bc2dabf40162ecc355e8c32b +8ffba7a6a1b2ec50b0878b884fab06966a3d2599d0443955b335b20014ed41e5 +8ffdfee23d8703e9ac820e88643181e3fdeb42633674776340520563739a59c0 +9005b7c56ec6161a93e35771d3a9ecae12ef4fdbf75bacff67a3223b277d4248 +90143d3d083237736ec3bf31e409ad2253f0f7da418c77e3ae8a9b15e23d5a42 +9018066c6d7182b501674ce4677f9370b8073fa581cf085564d00bc4f7b60b67 +902d4105c5122eac6a9cf7f9e37bc3cb8f9531cb3d580ca4bb3b2b0e736cb970 +9038ddfa38da760eb8628c447467e955d5e3738b94c576f139ea0a9bb9d86abb +903c5c701d85ebbbf88283fd091ae673a65b0f7d5c75b1496cd613f82c006239 +904946aa56ff52c86e2e7dcc891cef9fa197203e1a4df4ceaa3a3d7912cc9735 +904d812291211711db747226b6d65567aed2355060b4135a5625b47cc62b1b28 +904f0bf1141f5b85605bd69a231d3bd5f5b98a8e814e01f3cdbd2e8df0be19d1 +904f248629b50c08983f8bc322ba87fcb1d069fae1fa5ca8b1377455f0c5143a +9052ee07e6779bde40eea5cb07286e29bd2ac44638dba8fef9a88322105e17de +905d25a6e41778cbc01224b5872e1140a588e4a264e52493eec40f7f758eefb4 +9073e527d520a7820fb0d62464fc59e98e4b9f81bfb3c9f7104f5acc3b5f68d4 +9076a2ea346004159a0a30f83a066b463929db71f4dffe11fdb039f27100433f +9079bc6258ea704b6da722750004a445c2f9bad832375d9482bbe44b3269aeea +907d879cc49852af168c74d3f4e8dee849e0117409361031ed48c2cf0eea5898 +908141635012dfa09de724687428894e03aff476bd254361e141ce77fd35d933 +9083ad6d11aa80b450ae51e1062463b8ba03cffd7ba50e36584646fd1876ddf0 +908d727ec15ea41071d24bbc0f3ed1af66da261c7b7617bfa57687fae35ab38c +9091f3ac59e7a35babe626d5cba1a8060970271d8354e220668b0290bf4c8064 +909294ea66d6fa09fea0dbd189be92d452ad0b03f7bab893ffd1485180af5a67 +90a9f77f2b7c922b85f409aadc163fde14be3acd98663b1a23c638657067bd61 +90b6b07ebc02d6ed55859d0b80c712b902fdf3a80291d7cdce9a71a9a75f068e +90b7d6365b22dac621b9163766f629731b31d8a17f0f898e82580cdf47a8c8cc +90bb1775b7d90d9b395d38173415a0d7db0eabb7d4f7cdf7d95390a754966ca3 +90bd8212e142f79a76c2b5a0a79e638650d59e30d6b8857778695d0b14cd0228 +90c1e975293148ad14456bfcd431567364eef50a1dc5a46f193da370a1eba9b1 +90c3a2939ecfd598b61810f2a14bc1fb7780fe5da31f3acaaab478ce04e2f6f7 +90c45610806e38fbd17d0b4840fc21ab63385eae3c8df083be8f9a261c0e8674 +90c6c04363232b8c9750e9e8d677f2c7ef14e707cf24432d90e982d0a16d3ed1 +90c77f29087f2d51c548c00d01c2020845ff6651ec2b1fa78c546c9c878e0cb8 +90cf548d52b79ec48446c2ffd993cfa115d45e509a724734195caaebfbe5342a +90d01f259ab15e02f41197ba40cad65ff4abc5ccce2d02836a23d13c1fe634f0 +90d47dbae0a5de03b5edcd38a184cdaf80985aa3e1201e7fd5800371e3fb787c +90d4b19a9304a137ce97714afad820089dfc8c16e8bb8084ed9e03bad2e258ce +90d882e3c4fbbd67a464f6b2b459692e349a7aab0584df01442febacf513f096 +90e1a771d2629ad91f8959cd4e7590c971d7b1b6cc2f5cad4b4a3628cbf57114 +90e9b150aa4f3861dcb7e23037103804ab338807db1a72d661dc2152fd372a3f +90f54665bcbce0473c26eddeadb952b99577515a29d5008d50d815a0f983d508 +910286347c801d08e26fc711aa924612a1fe19f279edf5957a3584c90fcb155e +910892b55d083c7314cab65f53e5af2fd184e45257d3f080a7e529b3cd7c64d6 +910ce79dab8b92549da077fd2eb191aaa553494c0a6b9b3ef90223e63669740d +91123a4a14e06f9373d716c561a3d759e39d1b9277a8e4ca736db87b04ef7d41 +9118f64ee9dde3b118619232412649bc768a3358f19b067ca5e9cdeb3736d670 +9123798d4ab70ff062e904d578f7f600640c44cac30727bc37c4e6fbea8798eb +91287658aed90dec5be7f631a6f1a0cfc24622b1294420983c9c8e3d54604db0 +912c2310d5bf97c08b400a1d8ead4eb3803ab463e63c675985644dbab8294bca +912fe38d0465fbff6d74aff51d09182408f93f33ec1cdb0ef70b0a7561e3256d +91366c2e82731835a1717c1c63b3bb0e03b1ec90709adc0e4c2388e046be5313 +914977354cc1c4ddc881974559361f36429a9e28b230a8e982bb4878b9f659d7 +914a75d2ea9f9208bef2f47c296ab431f3e8ff30d835cd0f2a786b45a34d133e +915976a2d6a30717e51833fdf0bf5f18f4f6b714dc89b29efa089d12b5130e9d +915d3d2805af7b223bfaa4846944c3270cccdd8468ffda784b37591ff597c4aa +9160b26f5fa14e78eed89f9f3ccbb7e96ee2fcee99949364b4d7cf0885b171dd +9168e5997dedf5045b3239008b6160a8d118cda24b5449c0fc8bbc0b63276f67 +916dff862d20940646d0772f7756a46f9abdc4095a7487ce4373093849f4677c +9176f0e0ea0ab45ef37b462c9deac240a6b21564a812af62b031d5686b32a849 +917c4eab6bb396223cde628f21319e1699abae1897f169639f4fa34967907d3b +919524b54da24444a67677ce62a8325f8bd4b5cf4e4ff1fbf19fa989a8f8af99 +9197bd990ad08f021b6327f5bf74ce053d827b299d3c6a77b4fda9ae8d2da218 +919d9aacf1307de9478604195ed7ba7679fef9d9c3f46f6da9661f9161302a00 +91a8db396706f900c7e1dce1344143f03fc3d5cfabf0d00c545bb3bdfb15c62a +91a9c9a7fa89ab12b47ebdd5d2d36f636de4445afe3de12e417908cce92631e5 +91b6b7dc164359e8c0348d39fe5ee587ab3cabc2b5daf7850933ba15b06218a8 +91bb52e0120c0f6f0898f8d8160610d6caa1f83388af2c6cb9b98a9a0341f456 +91bb9d90ed05f519c00853c2f2d4353e419de012ddf989b109a0e15317ef0b5d +91bfffc008173c4fa273eb0536dd5f5243710ba19d9d3388a05e40699ba141b8 +91c063c59d13ad1b5f7d29e652e3f8f9f97ac1d6470570739fcd432f6cb46e4e +91ca7f46fd31cfc356cc13d52d1002d87c63bdf211be5a8d182f3c0a6ad7729e +91caf2c64d0300aec9ff9533803cc92a14fdd773772d0d97e1937580c40e144e +91d790208c96097b951b212b645db6ddb3f031e68f958bc274d3232429c64dd7 +91d9bd72e919283e6f64116416cac7fc159f81d6ec8b5b75e9ce0a4988c9f0bb +91dc4a3a849c094b32e6c3b9da5f5da57e5ad4c17033081e2ddc332afe16dfb4 +91de5bebefd8bcb5da331b5410f706104317bf087bdc9aecedc12b0a701960c5 +91e430bac374efb7d943f6019ba62122bab1097237ce4b01fd3a5e32a98a9fc0 +91e4c7d0558758bf1b048b19244cd422a20d912aa7b811c78999b9870df76426 +91e52e2229879a42714240bb58899e57ae9967b6b135fd9a0262874060c44ef7 +91e57b369502e522c899d9b99570085ad37b5195a583f55c8bba7bc04b212e34 +91ed61607ad7a6c40c829b590b78c2b83474fc218184821f8a449f903e553e36 +91edfbef4039de35e851102ec22894420932772e5c4e5482c2d914a07fa87e60 +9200b33a382ca158317a31ab06e5b90b6613cc74d207361a3889d54f488fbb4c +92102b5e17b86b06928ef26ea7799ab94c7e499677558214da7470683b6f81ef +921610a15b38d3d771df505482f5c9b40f98bfbadd70bddec39e0a974795e851 +922608ef3e569f55dcde69d2845e41292bce504225515acfc5b9be7508e5f63d +92267051aaaf439c9478cf47c2183a7fed9b9ae318afe4a1687e67925a5c96c1 +922afeaed2b7fe794b6532bab2692b5cbb0418f2370d2a6c2721d9013909a006 +9230c7fc62bb7e3599e14c30e773e7e8eabf472791bc9bfff4c447bedb676a17 +9233dde4f348c4e80352a951faada231e249c4b8d3fb4ef14ff54468915a9c54 +9234f2b9361b98e535ed38637bc12882b6771192b56ffb5f4a511ecd11a7efa5 +923b807154d0f895fd6d20d2db2121426dba739b8e68b421a08802bdeda8a09d +9241a5093fb3bbf3d51ff54ef7d289fa2a153ac861b0fb292a3655a9c97ec532 +92435a9972b00e130028968c199e39951ce32ece7700549f142cb764ee45e5a9 +92586fd604bd08b8f2c8e4af722f6b1d61e13ca236cc9326ad88fdbf85b3836b +9258f9b20db505812ae7dbd0d4acd75e08475592a4bbf84ad22b77267abf1952 +925f694e1ab7fa1a9337adeab960a6d294a246b0388d57374143d15da51c9bcb +92632485803799880195cf1b3e8de79e2a47dd9d9d7952cee4932205af5b809e +9270e12f9e99046968c7e9da4c1fac76a6ae8806f11844efb524007aa6d7b0d5 +9272ca788da480bcf5ed2e544e6a2a9b77ff4be64d2c3e1fac4c2a1e44d21b01 +9277ffe2641f04433c85d6074808e54c27bc95584edcfeb69fc68484649bd9c7 +9286dae8993a82a87f3d0328622fb61f07f7b1a27f425bf536596c05ce940e61 +9289b7bd0ce198b5f9db368abb2351f92151e8cedc219dde9969d95d27fbba29 +928a77616eef3f05e8b9e0f8410acee897f0b507bde9608b1e3f8bf62d5ac862 +92a77d0f84c52f2d6ea3c611e75ba46d8f1a03fa61d8a93594ff2d15ac460c2b +92c0b44993e59f3d09e7f7eb5539bae8cdbe6cba292d22cc48fd5a474c9d454f +92c97792f7214f4aa5b3b0f572a5250a1d32c85f240b7e65dbf804c817b7573d +92d24c6baa21a153df933aade4a8379d50a5b742c6eae4089dc8323a5877c971 +92d2ef8e380444eb8dcc54b30bdcd155f07d8890ad340a7e942d97fa087e28d3 +92da3a0bd45add320b3ee3648afb6128d835b53786fe489f6280a3c44892415b +92dd6882f3faeecad4877620f809f5620105875513f930466d6a36e27ff83db1 +92e24082d38841f951cf288e36c81217b702456c84f1e39b48494d02250bb75c +92ecc3b5aa8ee0b37e96f5a77ace94b6ec99a7c48f944e069123eebf3daabcdd +92f5cff06ef7c0cf1bac1d8e8781e4e5d76a7a98806e4d871b82654c453b9bfa +930953c7d3a91cad1745331e775c3461c2994b42b2183b9a933bb6d0e83f8cc6 +9309f90c24de34a8027d11438819f413b1e1efe8f7297a38ffd4a565b71851fc +9311ed577d4664cd72ba43fd1853b75bfb5849be00910a333d70a537f4c62588 +931a99410304372eb69c00c1b786383d3b58933ed2425ea6eae1770ef78b506c +931c98dfd1ef5fb28175867e7fef2a9d8ea3f2e5e87bbf0015ca55312ad3e9ee +9322dd9141262b8598e07ee5bfbd6ed0087f67f5cb07e04ecd1ad07e53e91926 +9323bfe67208af28b0a15762be64ae5b820e2aa9ffb0b7c581bd8a635b25aed3 +932b33c19a39baf69c0dac2c20162cd165a3150af4d4573bd4d92e3a76293504 +93346596eccc6f9932e65a95fa0feec4bb8c98369178ab4e11347eec5a1b3333 +93533f15cda6a6dff2a1f582b4e4c4a55738f2c07e99fad55835b1237ce6e7ce +936eacbaf31ab3b35e23a8f4a1a713564e2191d855275259c1941feb9737feaa +93747b750b272b9eed27c0e3fe48a96011af6955066777b0a80e68658c167f48 +9377f8820d94b1815e44e520d5a026030acab61e2c375b24f52568d400bd7c88 +937cc6c974855ceb8ad23530d737893f38c1d037350b2df920da37f164dfe2da +938d83fc49f8d8d7827237d44820ac864911d9203de05f3653d4d6143d4f704f +93a75b23ffa8c6da004c1921b2b12b15fd083fd86b2b2eac2830d0e27d12f4f3 +93aad0b6591d428808a81d7697a3d86bf4806661778beb6894f8a547d032aa1a +93b19d84e9aca692c75cb160a050fb53d1b211686b3f4c867a4e09a9b0380027 +93c2c439f48db81651d6e6c6241cf0865f08a52b5925309bc314348745f71cee +93c63ab5e0863e5ba86be4b1f9fa0463eb4b8d10f6a2ff3f6bf91d6e43ca5dd5 +93c86597394e3410565d1a310bf97099bb7c1883d4d5b5dcedfb95ecc33d70b4 +93d03ef70f78b59edc0cb0dd76c05a0e812ef4dc02a918aa755eec09f40ac26c +93d128126403257c96c8966a7bda097bb9188ef35c420696fbb82b5c82d01f7b +94102b4565cd4af3587aed1f4d3c83d8e63778b70bd4d1af6583204e15eeafa3 +94123ce5546af7e18dd6a7bef1391e5a9049d9c05d9d2f77eb283365f9f3015c +941e2af55e334cb43d53ead2254503679fd63426ae3ee4f7f3b800b3e586a0dd +942059bb56ef161541caebec257f0f02159e53c3539d9884c3d84fd2ab9470c9 +9427b78dfd6cfa14ea0770d31336e7215e1d6050bc8070d85519843049862332 +9427e8b5f2160ca54d7454658529bdfe182d04d7aa755d29426cace45447781e +94297b82934468d7b1f05773c5a978f25f1c0fe22fc8f528bfc03aeaf2ca60a1 +94313b8dee74f27cfc183e9dea118ca4073290dc98ff6e4190306dabd91ba661 +9432dc71bb273f82fe3c032b302d39d5f327968e5b4641287d7b7ff13598a1cb +94382144ef98f4aea8f3f3fd641beee9bc54c8d53c184512c9ffe1018634b6a8 +9446d788319fbdda6508ba91d2efcf0a06f051f5cd28fa3a3339836a1cb7a380 +944fcb5bb940e5bc701bdf4496008fe6844676287fd87e3478cdb4d67c8b5b78 +9452e4ae8e09a61dff1ff724c1732a16d3652bb4a3370365ae1fe4ebc65ba364 +94556743c4052ad8c972474182efeb90e659b6b1d1ad07e94d32d09ff4807d7a +945630484aec2124f7d216ca72372a68cdb556620eb435049e9452a4ec9b27be +94676bcf9e272874eda032e29344011d188615b4abac356fe646192d833e08d7 +94707406abbc7b6ec1b8974e70c7a70cfbec55b2ec2848ae321eb3b569b6bf5f +947330c773409cdb0988c8c06b7f466dc4ac2233c12e14a17276eefa17ae661b +947a2d589e5f1e57c1d8bc18879800704afc34fc15ef7b471c4d33c53f0167d1 +947aa58a33dbd9766881c00ccde4167fe1129e62d70f942d1859f8374acd970a +947ec5046a70816176d171c5d38af4a6d986b1d9634fb05aa3d77576fa441476 +9488e7d55e48447fb3a88b9e75fec9b3bb7692005315599080c91a8f6d2d52d5 +949a2b5d8d85b67fc936e00c80cb9c643565a1ebb25c27fb6f8d472ba23a2444 +949a74e0ce4d6ae0f2c73a3c510c73f4a9f466c652536e29c066b2eeb6259d3b +949f4be6f6f146f56ed3236bbfbe0cdb4369f2051ba5b9d4fce3f767bc33c884 +94a2f93130cabe4676817587e66ab026b0dd77601d16532b4922f60505c4faa2 +94a54709bdd59f1b204d797b058c77de702555e835eb29e5d93987c0261da860 +94b5cd8e9dfa77daffc009983f5b7b426c0158987532e80ecc018e4650d976f0 +94b633f40407f2854a8be1ee1571545eed87bd68ae055590ef6ed55d741ebb9f +94c8c9059143ddef3d628251896e81a7766f68363c02ac45131a092c125d9776 +94ccd8c9ffabc804e994c1ace40f00006e305af88138d49490020d1728d673c2 +94cd1cc90d6a27f2d3fd338e23577b18edbe9cb2be6f1f4f8e892ee73aa8cdae +94d66cbbfeb551ce717a1f1e58c0a87beef381cab451a3ec39673447e1ca864a +94e11228c54c36e819f758862fc4acd75b4b3d033d27717cd842aa3a3ed607ab +94e82c1f92d33e1d93575d28da618c7a8a4808487d9ad5e68e780fa453a51822 +94ed9fa21d06bb27c0a88a96dca84cb0a5ed94e1f3d11b819278bf804fe3d915 +94f197e92be351e981dbb3bafc8c9b5468f84022928e55995a73c32b333f74a3 +94f34d995c12435a9ea1671e3c4992f4d96af7f255c8f6d9236f01e19ebbadf4 +94f59b224825a6e489f057a385e5cd24fcf8d294f57a26c7ac2b2cc82b7a7d75 +94f5eefa4e58b497940134de85c5f3d33a0faf9a0c20ecbcf03218f607bf51d3 +950e5ac8c572ff506ff56ac57b42951aa149332103d1f7285edc84c55d297079 +951279a9e6a5e1aa00cded0870d1f88edde080ea3072886dae6c181cdda0089d +9513a80c715c4ab938ca90d31d2e20f06eb98549dafac082447fe86b23bc5c81 +9514dcaf92b5e5ca6e5e941eb44de031fa4e2f52223ee6230c4c5851e756f800 +951783855e759701d46ee10b5c82f7df5e8264cc21ce37ff56253d12e1c2174a +951e2c6fae90e3516cf27754fcb06a2b93242c5b6de7b781b9ce9438da363b81 +9520517233935fb57b90d11b801717a0076b77cbb8b6aadc29b4383047e46dce +9526edc8442043c655d2fb5ac939d0e5d203811fae0b437935a34a535616da6f +952af151eb660f7eeb77d42e3a86d455abab6c3384bb7dfb0db4925417eb1e70 +952efd4b6f05431f13dca7bb582bd771ebf27bdedde60b4353140c4aac10192e +9541a21c5de1b8b8ad7e6413f2735366a15d5b025a8575e69c14c3e212c669ee +9548219a8235997f7e60060f415ff1e8dc19d3ecaf3c00302f1730a793e67ea5 +954bd0d9a114ee1d2c96dcaecf06c3fe20697733f2d35eebec346c35370bb281 +954bf2711a14f7f6f6b6fc036baf757d05d8ed9fff8ec1590caf1c6112a7c462 +954ca5fd903a5e7daa24e75b295018a9bf5ba63bbf6f59bbe093134f9d09efa1 +957095eb388ac9f26a222cdf66759ce464343203f49e34a57306e2aa694372ac +957d098b0c2f6cda1f6806b96f72ff18ecb7e1a8e31c6cf20b0cfec1a467f451 +957d4c61c3322e4512350b2172eade8de2d7753a7c1d203c6289a1e6457b715e +957f448319660f30f53554bccc248172ef9ad23e168d5b64e4065a3cb66c859d +95866e8a99578410be5bb6accb3b2070413abacaf4fc257b74321ab76042a0bd +958785d307c5a2ca53deb5c3fd5d702c498152f04b649a59543f4674465d0219 +9598560f72878acdbd5ddc766a4075b93981d3898d4d56735a633f504e43dff7 +959ac17e68f21e18b4e5e78356be8607c25721b2fb1d3e601b099b4ad16f16f3 +95aa76a10ee2071d078adc7081b5dacd8e5aa7c07384e6938521ed6d1e88b55e +95b0cc24b563738634f69865ac84606fdf209d46f15d80e5e045676ef9ff5421 +95b464255e699c121f7162c080b30ca8792d52db9f9a12fa34f054c90ad1c38b +95b8acb0aeb747d0002cd31054abbab1341272d247667aa881d5c4861fe0c3e4 +95bb6dcc4a608e8db2b44c7a7fc52530980199c893d1285cd8e3dd35fae57cbf +95c6a9dda11fc029e041a590c7761b73ed843c99504bc3a10aa4e0b4cc15d4e8 +95cc4f1a32bfa7c7baffdc1982cace1505203bbda841105ce2c3fd2f5429c8f7 +95cd83186afa909c68b24bb212eca34cbcec24025316a3eb87a39e0e52dd506f +95d0f25476918e43924be137c17abf1839598010cfdebfd5a3436141b6a2a6d0 +95ead86e17cd26e9b7c8558e3d7e7902b25b5015b3f55c727c1f685ad6fe5d15 +95ee621d59d679324bf57926242ee1119f4fc83fbf47d8d529a71ef85f737321 +95ff63a1b05e7435f26a1ea1df089d07ee013f7af2bc10e79e986081f538425a +960da285833f3cae0a7327b46fcf33009c92be9fc455b5468cdd994da176c3a1 +9612b587f63e523e5c3908b450132342cec88dc06075b5ae1a71a40bf0f97273 +9620b848a9706b218b0625681949897c230387a278ed0f83002bc2e1da096add +9622b3054606d4d68bd0952bb5a1949f8481755ecf82bc83c270cd37eabdcb92 +962f8de1f73aafd650d469a4e011e84d965f5e7f814ff06f3ec921a761e910e9 +963266626fb122b429490aea0f79bbc7f6feb400a2fe74973c1bf631402a36a3 +9636c9eadfdf0f30c7169f6bb2a8d5656618f708d9d7cd9858ecddf9b449a405 +9644dd53030f22ffa3ba730610cd44a68150bf49df01be149bac53250352f2f6 +9644de0e6ab7e9cf07ac34dfa10ea802d85f9fbdbb2e7e0042e69bff3184f875 +9645ec53aab386da03056884d02932afd7510a8fd55706d35382043d2d47480e +9648fa2733e50d0c7d78d28e3b355ea7c0eb817c6580ddc1b7b19f7281762bc2 +964f980f7aaa138e70cbe1860943363b053489d95039d418c46908298130f502 +9658236a94b584f56c88d89ac6efe35d78e31ebfe81cc3cf91847cf80eeeda04 +965e4190bf473498fcb80d59821ba1a631a7384358da1a1616ec41fed7bb75e0 +96731e5a3869d90aea79b3b3e10186b3142a6d3ace02234fc4d4b082402dbc15 +967373357f8718de4b428fe70076b699a5c22570448a237b285bdf20c79c4509 +967a3266694e01d63e23058a3e25abf5d0d8079db662545f48b45fc4dcbd3018 +96836f80083438292c4938470c773dcb5f8ddbae5876e6cef09bc2289b01f9fa +968514d4e7abab05f288fee095237a874207475f70565a4a337f8b943341ba52 +96907ec095f1cbe8f8570577b7f028deb8c4425bc9d2c4864a849889920d0349 +969c43454345078215f9b056b6e373c34d29747d3c960d6bb31f2832444f4108 +96a1544b8f0d373aa682f0f368867666f1d9c062b2dc2d9f3cc458c1fde44ec0 +96a22e7c12b4f826c060ffab7b068cd8fbd2077797f512adec788f6a3464d2f5 +96a2d4b994e3daa9dd590a7a038441686ce337e181371649a075aeb00b677483 +96aa692860361bd4eb8aa7338fdf859aa78124c2c653ed2fadea4790fda53769 +96ab05eb57e3a8b383a695eaf74169605a300420c902ec7b6b5f2abf0d13aada +96ae76394785f68677e9bf1de4a3df75c851c16b4560176d47992cbd89e40f45 +96b1fcb8b96baba1c7431ccb0afefbf027fb49eaac3511cf3cbf4eb9e2181d35 +96b5bc336b60895d4bc7702d5d5d243a3403ace7af72271f86a0a7d7d6aac72d +96b60a1461c4ed533825320365546cd58c96fd1c364bcfe8a85179597ee1ae04 +96ca94acb8df57bd3c2d4210b125cf351ed2cbafe51a1a999eedb6da221fe877 +96d3d53d1753764187d1d22559d0c2229d1fc0971912b3dcf32bfdabf101cef1 +96dfbdb09f43649ce1616bd5cb26f23c0b82c1e53b1f08a61ed5d86890314dc5 +96e4689ecf197e113d3b99174923bfaa2a4723a1b243c79fe5e0389192a58d98 +97026bbf2ce7de17dab6e845f184cddf97810337984c9f6977b13cca02021a37 +970b972fe561f9738f0a87911f4873f19db5051f4cef5512624fc4e6dd140ec7 +972486fa949fb236cfdbd825f1ecb62cf9715e461dc7182776df47bab5618b5e +973b5a5ca6184f1c300bb894a0b8fdc5de0ade214ba2c7a199596996abdf1d9f +973cf8ef8e43230590355e3b54f68e18820571f86a3e1e7f5c106559f6e083aa +9742be6dac034ef552847c1422c9664d330a7d44dfc73d5984d97eba812c3d2f +9744eda1502d4576dc6f8f4af379464517c84c306dbcca750adc8c995b658d3f +9760b88a120c143805a1e0ac2b3708f079d41385d86e99ff265ae076f5f6ddb4 +9763d013c802c4f18cfda359493a9b40d4e6add8712f504fecfdd3c2ffb0d123 +976745390641b5b44370308e1098565065644e275f733eb019ae17edf18830cc +976ad0347e95f5d8e0b8b4e3f4b89521f63d15d0945960c435123b67d4421f7d +9772b3adb04f0b4c21d8a6096ea0fd1b8230e124cf000220838d88163d36a1e1 +9773b4856de6e213e79390614dbbb788ba70d825e0041bef40975edff9328c1f +977420dd3857610aefba5aff916fa87de8c6b556fd774c7bff0161120432ccbf +977daf61cf430466798f8fb18904f0231c579f8c6a53dd834c6aba069d0049ce +978a4b5e504a2118cb38daba92aa8c9660c3b35d17a2eb0077b51b6338457458 +978c5e9c27d60eb8ba2bf9afeede3f93e58f01779d2ab658e686baaf582d073c +97928935321e986972ca963ca633cb33c3733e36d1fd46fbca425a447dda5956 +9793b1dce616db5760aa2734238d08291e89c8dfa6e86d54648f2d5c0c15aea8 +9797df1d9ec1aaac62b30487189124744da4b4a736225dd7122d12f37a841431 +97980f311899c139c32ab8c6fa3a3fc3cc4a5abd5175c31d2e5f5390e7d243bd +97a245cbae50fdda2fb30092787e3b3298c009f006fc1df428cdeb9758bed743 +97a2c2cff16db628b6536249a42997b98d91dddc3fc19339b812cc787c61ccf2 +97af5cfe5a1fd01640e2cd6ebdb739f34afdabad0b6e839ae37ab67fc8502cf1 +97afa88c1acc47cb42f0e646dba38608a37f4c66181219d93ef1c9a660f16879 +97b7c3d9a7e1bf5cf82e00a77da5422212a2db2d80990008fab17875364320ff +97bbaa98b35a3188da63059f835ea280dd8d55002905728ae9e3f39804c4bf2f +97beb832ce301bcc93897f881235782cd363253f98c9271a9487c0e5b87bae6d +97c6c2e32f03678c70446379a3936eab2c656951a3455199e53f2d349269e812 +97ca5d20688b199f531ae8759488bbdc0c1ea4b574f7f1a4dd43e9b25fdc2eb2 +97d7bd891a6e96f35ab1dbb3ac2f335351796c820d0bb2254a4d9affe0880d2a +97d7c4442b12d9c2e307a2d597a8ebe011b1a856fdd52e52dd2a4cc23b7017ca +97dfbab59ca920c6229e5820515471fa7b23fc515f03bce512c857d4c6a3889f +97e6e1e29b1baf50bf71efb78f15f364ad660ab7ccaaad158a916ddfc10e7352 +9800dff8ac581c370764e0bf67e8ee7e2690dec616401bd2a4eecd944be9aab5 +98028a435afd31477db77eb44c8b7141cfa3ceaac10b6de3ca8e1551e85edf05 +98057578f14016906acc6e052f71887f9e446373046b0d37fe354ffa856f3818 +98164a6507099edd2e007f4677055045263f2384f8b1f070770365199b5377d3 +9818aea8be5faa64be197d264ef652b16e3bbed6d8b865308da9a1f04263de0d +98196f7a47f237ebae33a3aed9e3462fc787cc2c129c014d049ee8afad3d176a +981badc6ecf4547605c7b88a25e2839095c695f914b86bc98a369aba36bd3f8e +9831aa4c519fd0f8a855d0209afd1597b42564f0926a55c2c5e3ff2cc4b7d731 +9832c762842d7b4b7306d301f07f39b4a554a29abfe5b4895e9834c68f3dbcbf +9841f21652dcc1df339c6c89db9a788648f3cd2a77b5148bf61b57e959c27ace +9845a75b8831c3a53104b43c9bc898c986fcbdfa2119868304bb706beaa71376 +9859932cecd81281a790b528d1f627a41eaa5bd742f2a64e5006d35cee27045a +9862b15c6195d0dc9fbc1a6a44d549185155ea84bf37acdbc977b8c93c414d13 +9864014a690353fff549cc1c8a0f005beee6cbd91d150dd5b3f3e257f64b33a4 +9870b5c3484e4971c1458bafe9afcce02f9a68d4231ea3ace9d9fa2986d2d8da +988073da44602f9259bf13779af85b71d98838e1419944aa52e4c05b02198902 +988cd2c286dda7a518929ec0a19dea647fef38d9426a33cb34c4670abd027708 +988e2160ece7bc11172a8a7c9652b31d6b8c7a22789a8ea7e48eddabc0f86ea7 +9893c29f245610e57d7939025ed9eafcfee57af35566517711f580627366321f +989a100141ea4d58a6925d292becb8083ee979ca1ec3de671d2abdabfaf3c454 +989af2bbbdaa466bf985632c6b104e8f2e054363f126f77c31d1047a8881b3e4 +98a30b78fac80753414e0b0d8500f483483adb96b60a2702e35b73c7183fad3e +98a39cfa4192cc60d5536997539d8d584802d4e4436368c1ec24089b7b8d00d3 +98a7c68627357ff02082968ec3ad630e62de31aa1782cf0be4ac34f3bbcebd70 +98acb56d955563c241669b75c21fe4b9d2ea81a75c48f53e090bef5b5b86cc46 +98ad2b0d1ffdb2bf319d4b47dc2522c16fdf683b89b5c348327bb0be60c9e4e3 +98ad3697271df673f81d8068f5aa85fc4431231e5e3042f7d0459dc6a213d014 +98aebce4bc39d8986b1bc1fdc0a4beb63cfaa9c77ec47d226efd4a468ed39d3f +98b4ced7a8dfb9c23b42b934ca289d9a47802ad8396ee9d819a13b4140fbe295 +98b9501afb821ead6ff56512e29b5517a6f0f95de2ed5b0c93cbbd587fb6ab04 +98ca3eb5cb4de99474c0e8a6ad136ca74e285218bd9b54f02672fdecbec1db01 +98ca9b59c43cecbec8e04db91bb8bc1a8066e197815125aa08097b7db0637f8d +98d3458d9367213ce25507f3cf94741cd29fdb5c718d2b8261dfa4423dd222f3 +98d45bee0c2933f3922b047d0a1acca4f8ed40cf2f4839527002ff32f492631b +98d6a6c891cf9dfe4e1d06c88b92ba14c220e7728aaaea837a52693db44e8e91 +98dbda5f2501489e8ed33d9594513924da3b4568a0b294e2e72be7ba8ea3811a +98e62da79b3633b1243c5ee79ccbeabf6491dc13466a10faf2711cfa5e6d0979 +98eecf24ed681239a73e72f2ed7a401af9a07aaeafe3c7c7855a0445d22218ae +98f3bb9c8b56fc628b2c8d3aaf42dc0123143aeafda581b160ad35d49de73c7f +98f461285ad8fc54ee6468ac0d1d339418acf8048f8ea6bce185abc69120541c +98ffc61ccd8e212484b430a0d5386e2b924fda2be2e16fb34e72f92c567718d2 +99056578029a58d1fa1d9dc756b106e6148afd6415ce13f5985f1e5ee204d4d8 +99134543f1ed66dc91c9cbcc70a6d4f9f8ea1af2045f307b0ba03d08305018a8 +9915e3736ea8544f8d437fde32908b7655e3ac89d3f2fa8487cd06671030c962 +991bf7bdb2561cb1784ddf6e34b09a8cc157235737b1db45550d0cdf541fb90c +993726ddc3a041bd9e87688cb74bd53c94fbee90e050922b59841685d363385e +993782b18e1098833f9d1bf748fd8c6b4dd0cea376cc6750da6490ab39deb64d +993d1c3eff3aa9e4ffe5ca142bef6dbf1606f7ebce2e790b58970ee77fccc822 +99631396ccb5e1e66b1b6a462ba4f1fe6dd1977c79f42b0a4c638be3c0e05a69 +9968746ad1fe6db2ff4621b3d67b84022d9dcbe400ad922a1db3a0583c375db0 +9969669dc661e991ffaf6960c1d61148a63ad9ccb0c64568a066bf9f7864571a +9976922d4644dbf8a1a8e03e152409a9dbd5aaa992a6d2b7a9889f83ea3c9df7 +9979a528f5830d5b68f435bd5cf010a4e6b8a7c8eff874369095bd647a2c48c4 +9981d93d44b3c818371228ecf7dbacd9dc831f6fd383aae189cfdeee5fa0ff13 +9982a7556b650eb6c9e7e19c6681f881f126a74df922a7a0478bca87eafde5e1 +9987628506cc69a3db11eefb9f5d1ca6da499e418b6105804b3538b19a32d749 +99907c9a8e547db9d4cab9c3cf82f5660b60e3d4004e499a53b4d0a7bd8e34ee +99a143ff874ef6aa08fc3c5a864a8dacf2c5aa00ea8f07216c753b69bf5613e7 +99a8ee70d5a096062870e3a1e1a27ac8c1e6af9a19a73eadcbe37264d7d371bf +99ac0f61243006eaa9af81a43a09fba17b6e4b1448d38c9f1237cfc3d6744f41 +99b4b252b6e9645909d4bd0f258099dd02f799aec2b459d45e06bcb9bd079850 +99ba1120d1e730296941e02d47c71a244716d73d0a7f41ff83d62b236670840d +99cc4c5f36d0cbb22a1046bcd573bd481c62cc49e7ea041e2f511aecfbc42a7e +99d260b993865aeb1f58453ecce72f8592fa6d05434b839a6b8fdc07958a09f6 +99d44fa5e8701cb89fe974a6c2157e3a716b73fc8e79828b4674a556f9542077 +99dafa0429d4f6db6c0f573502cbfe1a8c7fe804c321be1afc32fa6a5a71743d +99db4b2a2832652c6ed3a81042bf730215d394c82f22369422dd278fa59ab9ca +99ec88d5038e97c56ab70bae41e2f9615668c55a83ecaae24e81ae760306119c +99fec4955dbcafe82051ac478af8010c2b17983d9e323e4922e8718b4b46dd89 +9a0564f64f4fa5cc4c6d79755bc1dc2c6a6f9e3f8cce8f25599e0639cf02663f +9a07bef61ab469b9bf1fc487a22db1e6efb87c186a0fa34b520c22cf5b414285 +9a17f88d0a22003c2cc67e8015f573fefc7dc00d432e8c6ac943c89d4dd37a11 +9a19193e8688668ea794b05460d4975fd931fc5de93e0ee33e6e1d2b0f399c21 +9a1cf27df5b0ee04bd21098bfec7dda525cdb2d766ec78265f3e7a57f9778870 +9a2945d59b1869ec12849f45b3a5edea11c09d9788b2358e2df7dd4e91cb0724 +9a31d444922c7f452160a2f64d140508bd8cc62accfc948d1db310ea72b45df3 +9a3997ec59bfdf981a5cec0cba87e2e4da1b3151a9822e6390ef9ed256430034 +9a3a6746eea5e18b56107efaed1156d125aea587fb62b03800498f04f3aa1fed +9a4a2ab501d6d9e3386b7828d8e718de8f2bf5350aa09b76255ecd50bc5d1401 +9a51f328b67d30404597bae74d981d25fa595e0345ab19fa32db8d1b942ff049 +9a55d0b480c02bccf63c408e041ffe2e4106a38864d5326805d883db6d0db236 +9a5cb3864fb25a94eab2005eb3aed44330df0963f9c157dfaa39e64a0e6e7fe1 +9a60252ed00eb47a4064a57141468711c33de4baa419ce6f5f0a899cfdec8009 +9a651db4d117c6f6359ce0bce16c7c1d27baac6bc3b9a194021c96e57dceba2a +9a6ddf7dd9170c459ac48a569a8f4ba617a6855f3e93a6668b5d3a60de955133 +9a6e6a18382fe7b4ece58a4880c18740f275193a5c31d9285cc5de9e2a9dd5e0 +9a73e26ab611b67e2441cd9baa419be547cc9b1aab94d76716e18ae038174695 +9a8832813e268a82a9f2a65782de0d40ed90aa8bf0ce5a1a3f068f28b9a9e972 +9a8aa1df12340078022ac5adf0c9579a792d8f5382571cd0e885d51c82bada4a +9a8e99e76be72fe4d11353bf29bd202ca5745c7f9b21859d4a382edec71a41f4 +9a8f0b4ab4018e98f1e7dd5a878c7583fe8b64b8dab43e93b632203491767fe2 +9a987fabd712f9e3b5cd425aa4a2fc0e16a283f6f9f72cce6096967928eed4c8 +9ab43aabdc8f1c836891994b5505e332bec2845c3a14e379c6561c5ffa59cf1f +9abd576d30d6f177a85e141aa3ed1eb75003377d13d9f13c782edf631ae78347 +9ac02e372bcec8a45d7853e24dc7cf9affd2f6625d7d18925d9b5e1d38592da3 +9ac54750446807c3debc8084d2aff1b783213860a8f00f711f3df41a666b3db9 +9ad885cf85be9a130dc8435a643b5933017ca828e0fc7dba28b0c38e5f659c18 +9adb6ead27a4055270cc5718cae5841db47ae92cc445af4b302e6291f43f7388 +9ae8169596b7742af8e30e809117edf699cb15fd32976b7c51e9a06fcec49557 +9aecd95591b3239ce9bf1d592d93b3fa61be23476981b6f31c383a61e2670a35 +9b19e2f33ef04c6722e6e3e5bdd84196912bbc974c2d2b0b1caca19e64b0d118 +9b2a740581a0c3d3413f6ef81422ef708ce2473cf97569c642e83bfbfdefadef +9b40f3fd3f1c0d79b2e2a5f7b0ed13cc92d8c80e387c4303aceb9298aeec946b +9b496210b907c2eb1eed6d12c1552654bbce4485417825a7eaa633e2d66db774 +9b511bc411fdf71b94a160c1e79b03fc5f622f82d9da530414216b052ca1c80f +9b60597fd0898b7e47b1e416551bf7340d8bbce4e4a5ca8e64d3b202514d5347 +9b61d9f01d5cfda0f4ad96972c77838814c613385778b8295667d981bf5b8ab1 +9b72a0bc3bdb4f8a95219ca95645823a24b13824bf9d671ba9eb794848bad1d3 +9b73fe3006c771634026be2e8f92935878b1d51a3bb6c2caf0bb22f70e4ab9b5 +9b79ecac8ddaa01f313cba7f8b3c0a42f1732e701e1b75a28ea0333692b20d34 +9b7c519295ee8c428454c627a813b32cfb71eb34b74e723a10c570f138edfa53 +9b7ff09861c931fef89745eb245846ccc0750ee4f939feaf8e510764402a7f1f +9b83017a1838daadbb085b1c393fea2e1ee6ccf4b8d66c3ef8c17069ec21fa01 +9b8303a71480dd60f4d9b64b8dbe6d810ccc7ab07e33d9b22db5905bef850a16 +9b85560f481e6cefe66210a40df8af78aa46767e7ec50a2e8103cebfba793946 +9b95a20a617046d62aa3a45c91786c74edb82c6825a3c71b07b985f4e13c7620 +9ba532490d81068b382c0f8e573024ec71a1f264e10ac8320888590fc1c1a3eb +9bae917ab83ba11f8b6102891b4dd8566598c3ac49ef4663d105074491427acd +9bb2f60df1309a6ccc599f4420e9d8f80f655238ea0fde3c054c076b538e3485 +9bb467761522cc8d5035cf93df88b28955bd7d3f91b33589596c605e4363a2e0 +9bba5ab796c916e428729c94a1efcdec132b442d0d74cf1660a6a96d4e95242e +9bc64e4b38daa31b182268a3ea9b64cc3a021dc53593111c0abfd9d088ad6abf +9bcf91e03b7dce8fff9732d699dde2d703ecf816cf2dd314424dcaa7359ccefc +9bd65d7491459391d0e946543e6cdfde011bffd08fdadd810149d17802bdf8c1 +9be440d0b4ce1ab3fcca5b8a15c648413a6c2c8562dab543bc2a7be672557690 +9be740064784156036c93c65bb737a72bafc244ec5f1e5379b94a1c8776ec9cc +9be7bf87edbbf32d10fe7c04283b751db954d8b6e88ac284bc2f122b3c674aa5 +9be7ddfbe6a25e519424b290b533e9b77c2586926672c271fd3ceaa4900326c9 +9be9bce50f32c1b97ecfa29945aea6f81f8005c9b7bca4210a2cd4e3d9dc5ea3 +9becd8be59c38c8add5774bd3dccac8c0e86e9e7b0b71cd891fcd9cd5e6c83ca +9bf00b9a6004b62bd676c3755954a6e3fac477fe988967dadec74fe65659559e +9bf1c739a16ca93980e7490e9b818092ab4c47f5f92fc29103f624184fd3e535 +9bf59fc5bbd27ec348e07e58719229bddf8ecbb1ae780cceb1c9a99ba2f16996 +9bf6929aa03c60dcf663dd2dabf69870f7be5f8f66b3725ed6ed021d427cd735 +9bf84653ed76f74fcfdc51d6301725593297ca2d27494757d52890f1ecd02925 +9bf9ca7b2b8fb88186574ec5108898a7f99e906a80c81b31b6e19c69b075e9d5 +9c00c94ca9a14e772b44eea8d0096aeac0dc3e1d7db1e4b2000e3762355f2ed7 +9c0bc9dc7e49dad20ca6d7eff9a540df56926bd6775b6b53bd9d271f1e4f8d85 +9c0caddde6cc3721310f24969960b19a96f9e117359446b1429504bab17749ab +9c1bb801d0f5cf05b4699ff7d84d991c5036af789d16e094503f8879ce58a1a7 +9c1bcfcd77bab3e5594c048c2dcbb09775cda61e831d4ed4cd31f909aefd248b +9c1f37abc657f480815ed27cff1b8e5607ee88cc3fa9ed4f769f34121a64b873 +9c1f5f5c6bac71ce97c17e9f79d49f8eecb8fe6eebf9798ab07bcd0a32f5f456 +9c2ef788b07d7b8ccb84a41dd6104a97800207a7d0003c5df7ff411c69a80402 +9c378a25c822978a0703e9290a494d1359aaa7afc94921fb9de6af1e8cd70928 +9c3a80d52ce9d58456a8b920850606e4ddeab0f31b352df4a3202f9508affd29 +9c4e08280130c68b5083aae9f5b8c60a3d16c1aeb1d0e00d5c3609c3974e877a +9c567b6f515e5cb5a54b4f1c3bb832a529884d2543c3c13da799898b3b7d078e +9c574f3051f6a73878621f2225d1f802263264e1a2ce8f67b57d36767f24e029 +9c740b196cc2f5dce487bc50b204a538b160399c30694e444b399f3ded530ecc +9c753c9b5d8d21dbfccd9d7bd095dbdf812f5de0b4979e6711ec440034812b08 +9c775e49e4ee0731e6bc35fcc2a734dbaa4dbd335f0a2c3b67d83012ce7b726e +9c7e4a044f391b06a21da2ab1176985d808f5810c88cb37daf919d6967dfef43 +9c8a5db9c0a754217524cc12a9e483d9daea2518f360e26d000eb63c12298e64 +9c95771541aed288682aa324a1bd687b1db07b11df7705ee31f9ccf21f2453fe +9c95efa694bc43492eb7a739a303e68173d302388b4a97a0703d0283ca65ae00 +9ca5251fc72982f702e7fcdec87680ccdb1f77e36e49cd05f41e9e51dbf77642 +9ca850d9a917c3237a67adf2c928dfce6fd514f68ce0b36c1400435db58e7d8d +9cb362b1bc3eaff402b59b74bb98c4846053aad3d43114c33ad018e779968aef +9cbb6451cf3d812f266b36e176f33b10d60cc521943aa6a8a29bf4680699b3b4 +9cd117f35fc6978471b9483137645f31a832f30711cd87bb937c31775ca4c057 +9cd75e4dc0989f481a5f02cf9fcf5c7646357f9ccc3fa76e0f99e376c393faa6 +9cd7c78b2c83b3996287d96eef0951a548d33f67fbc7e1aabd624b50898d5825 +9cd8ace79e3cb4c286c3ccc49543f904549ab64b2b3354ec0d6765c6132277a4 +9cd94dc4d9c8e95537afee1ef842e6b20e2ee0833931e0929cbcb4613aea1ae5 +9ce26f14c35e66f58774cd3fdd739d453a78e1a677498c9d84eb7e1b8fbef6e1 +9ced8aa942bcdc6c3ce514ce10c5f17e58ec29aec9bc36ae103869769fa3c7ee +9cf1ce8b87c4ade49c58214594c4432cb039850dfe658c4c96c1c62493c7850d +9cfb63a6749a2d1f1a25fef0bf8789fce5c4f7d1710376e4490c9f8323e61054 +9cfc3fec5867aee38cf85fc39e63c7c5ed5722728f7f6c1ff252dde6eefebdf1 +9cfdb557b5e6da25467af91f189c9b466fc9bc4c20ec32f6032b1796c2ef3917 +9cfeadbc3c160506a1db0b4029f2383b5ecb290df21b40a75b5875a1f08de717 +9d01b1d36748785039358f7f87b8fdaf84e8fdc576e5d5f9361a877677f5a42f +9d069f72a28c16b1e5860f54198186fe1a10677d39cc7ca7eeecf838d0813222 +9d0e16d9de15755557b7a173396221a25f2defbe8d131d3010392eb9be0859b8 +9d1d866e7dfa58341d98e1d271af22cb0c8198f51bae8d2b8c51b38efc30b01a +9d2b5137333f14c668998c20eb90346caa47fe59f3fa79bab437b6ec56f4ab03 +9d2b686a0f838c816a00e8390541bb35d37ded3e88b37e25643bac11be06ae7b +9d38d03501776d222d5286e0d7022e5b444a359dbb491f4c4dfbb90c8f60bf3e +9d3beb75def3464833a4b79e201085489ce91df42c2444e54d8db1c7cbcb3068 +9d4508150982e9c1ff0b1847e98292d2176e72c37903f7f6be2119d3427238a4 +9d4d01431ad08e982a4d1534dbb206f2e570e19b9e4f410f2186b8f2cddc89a0 +9d6b988065628058c6282ee14e05c0d464e8a4991d0bd2af3f8eeeb2ff259992 +9d6e13302d850082114d38576f0794cb931668ca7e2c4a66dc51ccc3e50891e9 +9d6f1fb41d24f76c3d9d18d0a3d0ac331476febf4ab4d2b806d9cfe6f4b2d36b +9d6fd9510b1af7086d072c82f1cf621b02aaa6d98fb28b97cac3883e24465b10 +9d7dad75bfe51d0e038d17fb931781867cc8662a5f325001dbef525f77bf0e8b +9d7f817fbd30d26eec069f25471b22e7a8f57e089aa09bcd5d1a18e958ad26a2 +9d875fe79eceb572f667868ba271ccd17acb809cca864ef420b90fd393f2d3ef +9d87b8f3cab4de3566cd1ec9fa2134617a8b41be9a9c5b5dbf0e45aa4467074c +9d89cf0a1f7d7b089503641f48c1427b04e732230736e3c5eea606fcae5761c6 +9d8b545ecc9914093519e29391efe3528c68179177019e4157eebbedce4588bc +9d9007efa2f9cc0b0b768d4ce837ddfea3fa5de25375a74d7880c1f608ee9357 +9d97cad6ba0ec3c5aad0df20ddd6a199a4246386c2f34b2c2ff535d489bea56f +9da2264046f0b7a4684778f6986c7ee5f26fe933619a4066160c841fad4675a6 +9dac8930cd02fdb26f4108a6fc532575f3c28224b9e9f15c19eaebeaf3d40cfe +9db11ae6a90c51331acae4716e660995dfac1c2c77d9df75a09a0bd4f6eb33d8 +9dba5c3bdf6e112db785e6cfbe8424a975e9471fa17d766e52d9675684febd3c +9dc32c5e6f1e4a2364b5683ead3d30a336b3fbb649917f49faed622466b77aab +9dcb513b0caf96efa6878030dcf3f66395142630af8cf16126c422b69372b87d +9de5b0f651dff3493d49116dd4b45cf7f85e3b8ac12b61418bc13f1ad7969ad6 +9de8dcb8294ce398711be99ab80dbddd4b2f11a14f029572b0e4354514df3e38 +9deab98efb0514fc03a4ae64d9feec5afb4f3ce5da31ea3d047f0dd048251894 +9dee01603ba9fdbd2ad736ef37c7aed3e7613fd2fa9d3c5c8d4c0cf43ae83472 +9df252950333cbf124d51510b72fdad4e4aa59a9a3e3450632803532b6eb26e4 +9df5b7f5e769acae1327adb4dccaeffe2baf37d85918a31925926ccdbc09697a +9dfa17cfb42169fe997c2e2729524b1f02428666405d688978f8f3c493a39e5c +9e0bf354827c0bfcef9079a10320f80e89c965556e0a48499d43077df4b640f8 +9e0d751d1e58924681ebfca99a03035bd00ed41696150261875f93091c57226f +9e0dd562aee58a81c9460b54fa8fb2ee9c9a1ae4ead1dd7a0ef952263c7e3e7d +9e1a4858c9f8b366179d490ba553fab867c4be7d6d837ad0846931dc56e05a36 +9e1cd2f6ddf40ef67254904d7358adadc8d791ec4bce2af78e90e9c9b9d9691c +9e1eb7a0423b297c7bdc28ceb58b70ddd88c01d63149131e62a4c11804750d3a +9e229d0cf8284d54ff7c62cf1f90b1a827cdfd25b2c1023ceec8f28bb6a72372 +9e2a6024a1a9e8a6e1a675b80fcb934cdf6700175b93198a5dd5c10673477a0f +9e2c1b170d12cf375c636009268078131743367cfc9b01028db3e7a16e3bdee3 +9e30e34f773524fedd7f856ae2bef12522dbcfd319bf31983f45d1a1a3e61011 +9e330360046b92bbc2e2e7d73f4eef8e8ee489159ec79c5ab79041611acafaa6 +9e368596caefd167d50271251f989858eae0489ab650fca4db4b488347c0b4ca +9e37fa0a01802a07875f879870ba892652c2f8f496afd10ce8282f279a4090aa +9e3b2571f5894ceef4ee0b1a706d4337f1eac9cab5c32f3273097fa81a02ab41 +9e474b65d29281728d1d5c901b3aad1f62920be812e0d48a4b5706f9a970e4b7 +9e49433ff12aafb55aa03ccb67a56bc701bccc92ed03e63ffb53a49b5dc1200f +9e5523b364150fe3059ce2594c8a2c3b2518df5c5721ebee7024534d69a46d7a +9e57b1fbc524f06d973d682a491cfa04774b48cca8eac40a6044101bf3ce7461 +9e5c197f0637ed960379bc2c289b7a04647f1540797b0143f428f7ea4e40cb81 +9e5ef356bfecc4aba521b1da87920689f16bd12d9eca6f91c583fb89a32f56ad +9e68eb7796771156acaefd42246e752be681980fb8db5bcdf3f92ee64cd01450 +9e6c706086e9016b61be5cac5e1e3d73a7b4e39da8c6c494314a66f9615739d5 +9e6e355e9b49d4d20f09fa0f13c55b83b2d3628bcb39731049b538dbb62cfd90 +9e872feecc516ad1785d472f74d96734fd651537f9bba37c7076325d95f84b62 +9e87f4218dbc8a2725aaae5f700d35e62f8ba285452224669910ce58ac0dcacf +9e911ea8a9737744d80e0b0995a632e5f538d7bda7bc23181809e37d5dc7609b +9e97a86cef9a829b947e049feec66360477621bd5148c9f5068d565eaea480c9 +9e98c94a126b99647c3e1c5ebc40a2c2d5e0458a2b4bfa4690adce18f1a1305f +9e9bf7cce4c052a736b050cc102865f2a51353cb3412add65d1ff45c45cd95be +9ea3497d0f66a39289fd7be112d0a685b2ee9676115f3eb2498720f22794135a +9ea56fa011c62ff4a63c234bd53c428056ff7f8e34d3dff3d8f1d10fea9782ad +9eac49a86a2dd3a68f75afb533f3401de53c7d73ed562d6961d0c036c4651986 +9eb4cbffdf04203f2bfbb0f8da51d39680acfa1407aca60c574c774baf0155cb +9eb66e09c9c476fec6de50e00742aebe738908f6605df9dcef55b0967f79f1bd +9eb9473e058aeb7c694d219c4f4dd2b012d6605ab6c654778f1c47ce23109bcf +9eb969cb22c79b7040004596c9ddf11fc2bfdf94942583ac2b37cc37ecb0d9e4 +9eba1920eaac83e01079681cc9e86ee16b54d360a791536d2c1c82e0b1b1f5fb +9ebdf1cbe42ed4f6196eb2bb3216c251e2830cc3ea2dc8a3f4c218cd5ea22e59 +9ebf018c89404da9ef9227752b6c1685e30f72297c9c58e1e34884ec9297c458 +9ec3d5a1ad10df074e3b9e6d648a02c77314c047e2f49a92a70b5c8cb6839757 +9ec714dfe1187d4c2e0952c239a4f44dfabd9506e17fbd6e9bb6e2da653f1e8b +9ecb6491863f486298a126f8ec61f35aa2046b5f0d212695b0fe7859b1e35662 +9ecec8bfe0a9660235372bcf925163f5c189ab91b4918ccfea03adf55fdd5be7 +9ede3acc6d2b983b1556d8d725a958c61ec5b56dc2cc91e631558ec72a521531 +9eec6d0e060428dcae68ca77404c97115d29bb1eef6f0c2dbcda82a1441be355 +9f0523f4c2d9942d58f2ea81f8a298a3319c749c6e5e0bc36e4ea90b6e5f2093 +9f0f5093675e40514d03678442656c3d150a1f0d7429e16a1f2bcc70c9c0fed4 +9f10c72271e7a4c026c873ef9cc7abc40687739734d930fbd190e01b18cb5b0a +9f1207a508deb0c08ab9df4482aa1c04cb918873933ef3e63d499052fb7a2b8b +9f247228d473a669276abcc1b2070fcf5cd3755dece32fb180ef650eed76ba2f +9f251d570ffeedee8b01f17688d0c0cbda3b16896378f5731fdc132a87a8e876 +9f260b40db319a909ac7557f874fffa9d65fb7ea4a7d657d720ac26d7f718dee +9f271b045da6faffe61924dd238a6c2157c347560be8d676abc10a7c2e566300 +9f28a87787f08017b7879aaa40d5badfa64757ad395cd8372878d62202015dd2 +9f336183e706632b3fc7d7f36cc7ba0145611c1e5614f33f684a435aed6415cd +9f3f47860f3e1a674573ea483ae4af0590dae65f9d694b3632c39ed0faeffe72 +9f4030f144e5b63743e9b633b89848a14970448b551ad8b3ccf364e552ce2213 +9f4dc37c535fac702e05d4bb01194838d2244eb59f5c096c126821f343298513 +9f51350e03b0e2673edefcab96275be43a8e7863ad0234d26affc90b18d6ed5d +9f65874da39e9ab2925fb0218cc674a50cc6ceacf48ebf9fb3e73b7c3513e537 +9f76a9bd8107de5c3f9ed43f732c7c8182a06623261fc8fc51643de6d2d78dc0 +9f8fb9010fc059b4e88b4646dc9e106dc31140468b8fb2dee877faee15f13fc6 +9fa885219c97f15ac29ed97f21255d39a12dabf56cbd1df001da53e3e4b0e0cb +9fb644ebb630d573f6860a2d1dcddfc981e3ac637e04af6913d537e9f686ca2c +9fb79586b7d6e7b115e2ca768534f53c3d183638284fef6be79fce2866ab2c2a +9fc40c88af5dcf4f40a7d85fffbfac4609a02288431eeeb970e23757a8089ecb +9fc4554cb462f3ace8abf1c67d43bfc6d541fc17e81463e8d3f0810df91e754c +9fc473fd402e3f9acee29b02f492294b382006f5d70eb1d78f2bfeb4f4779a07 +9fcb788a6ebd8de73e6570d73ab78daf5d6062b62e601bc7bb747efe6a2948e7 +9fd03f2c9504e0bd5421cb6eb0b50f55b9d635aa784a28375160b5c1b3b40c05 +9fd3595dadd18ec19bad19c45973d771d7712e209bdac36ca9735f03793a6d73 +9fd559a49517cc6e98ef88c11c0de522e6e5c8b359bb0b8b01e5a95f7fa5db35 +9fd85b5eb0414b6e13e433d77855a4bf02fa42282e99b9433a11b9befe940d7a +9fe4fbe58bc66f44e5c9a646d4f30c7834ee83f0c5cf6e740d82e6ceec28b2c1 +9fe55780e76f2c8cf075d6c7f8a52cdab28a0dc117f0693022dc34640b485cba +9fec2dc24e42aa40d49e02729a60b97049f301df1c70388796ba08c0d6747571 +9feda246a890933d4ff7fff913fa979e8b81d088972b3191e43b93ae0d4e912b +9ffe2aa2cf181d247b59c652c82dbb5b910e2dc5301cfe4b84580e117bfeccdf +a006bcbe1f55ca2635c9588f860432fd7d76ebff38bc7d7586782153f151a5c2 +a00c8b1074fe2fcb8631324d9e0370616b039e84cffe90141ceec977afc3033b +a010652084398eef7e419636061b8a8f0c86da50f20fa42b914c71c63c6d8617 +a012dcf6df1105e78293cb7588fc4a854f930649d44d132f1ac1fb8e3680bb4e +a02032e46018c95aa43c4f8eb119d916e1a4aa126b806842f150392df441c8ef +a0228c070c871d01e866e8fb689438d9da6cd5b74a6ca2556ce1781eaf9a5ec2 +a0242571670449b8f1fb5f9146d20b45ab4e45290cfeb4bf4c58cf48091dbc21 +a02c8196259f8718df4d0cbc662fa5bf359c2a42cafa062e1bb8a9300c391256 +a042b60b601b322eb10f244b8f7a863c548fe1eb73da3ccc0071051eeafca88a +a047b4d5c8c9f89c6a2bb11ae83829620cf36c7073d00904335b21f9b23eb828 +a055e918f3b77cfa9ac58351fbbb00af4fa08a0332c4cc9cad57fd68331f39ae +a05b2d4846ca580cf7fc9bd903ea363148ab02c34308c246853953009eedc571 +a06a69621df2b2fae4b529abb7a27946c1c3358e32f4e6293a38af56c0c4c6b2 +a06c95492703615ace7b8712e772f595d1fcfa9320ef6a81c269338d75c5dc62 +a08a53d697e1126694a3f490dfb07ea685d0d6045a0b21d07cc05ace0dca1f95 +a09d52421b93c09588543ecec88522fa254db7eab70d8196984564a6c92badbc +a0a156f037c192d5b2e4708a33585ef6bcf86b237e96b84d80e59c15f9f929a3 +a0abf3e221f807874e019fd69dafcc08a0ba8a81da9ae359392636bf945527c9 +a0ae4eaba59741bdad6325513fe29f521656ce2c76e31d0ad9505f07a1874b56 +a0ae6bd8e272fe4115f04b35f1f4ba2b9ad102a7392e17e7b0ebd12c6f11e1c1 +a0b24daeef6b034f5c01cb228201754ee35bd29b4be4f777beebb3b532be50f1 +a0b8e16381a58d454b44ec1079d9f499f16cb148b60d5697984fcea37befa84a +a0bb8b957da0a059f0c68f4e2099c8f2c1e71c4f6fce41bd2a88d8bafb102d36 +a0dd8afd5fb043eb27c51ce1e039dcb25464ef0e18a94f9cd66519d919645650 +a0dec67bac2e869256ed7962ba367c9ebec3d7ab7a292aa89bc953c338c3595a +a0e2997de41e7d6a57016c6c4b4638bc2053210ef62af1726d665bcbbcae0fe5 +a0e2c24b4553fe5b6e475a30cb5f71a5123615c3dd62fac4f53dc7cb040c6d22 +a0eeb74f415c015d453c324b38ee6f4d41ba11311c915157ec5a7836bb6cf4c9 +a0f91c95e8b7f2457a9ab3c732b48c48237b5def359d48dde079b5c57a218a4c +a0fd66ce23cf2d354ce8dd307c2bb84475705f818a19649d6cf844d95d321ac5 +a111602b3c2f1c92b9b353fc088ec01ac3c5fe988cb246686e76dbf847755b8b +a1180c620bea7bf21f9b803e81c18bfc488d44e29c8d027f41734480885613f0 +a12c5a55aebf377d189c1455d4a3f8d6094644ae85e18547ab619fabce3b6730 +a130550a7cf9eb8fa95cff15701e7a16ea2b06902c610b6d600e8f836ada83df +a13097c13aeaf31c1661f1dcc6fa7bc8ebe57b4b2bc6eef67b86c52da823705e +a1361cde3cc5c82459dd97e7d278a99a215bb31438d336addb3f4c030533cf28 +a143ac67620ba248dca85120c4268f1873040e74ab9528b4deed7486bd2e066d +a147891b3eeafbf54535bfbf120db3f92b1b9f9947ead1bc0d4517be926242d6 +a14bf841477e0854b7133769e5eba5f8944df4b01efd3650d0a225e69f5b95ad +a14c8b7a457699c02d8140df988c11a5f3e505289940555e863a09a19e6576d4 +a15b4f8a214028ad9c1e99372025208552bde9e5a86a126c8c164b5f504df1cd +a16a35a85f21d44da5a361415084b47b273705f71a0199fd9eff5d5c6d3a7b10 +a19770fed87e15bb183255ca12fb1ba2d67d5e9900ec5c3ab8ecbaa1ce2564ab +a1b46c8729a539efa2b329a695c97e4a8c325e1873d44e10f62a97681ebf54cb +a1bf41d7e0d8dc25486539d98f8b4a41217fd7b0de1a249d52f2093668efab3c +a1c75e90642b0ae0d8df315061073dccc7b29b9cc89118572865d234dc03be51 +a1c7c82a209ea60a54662d0c33f72b2e09ae9351c2f814e435c84de698d15903 +a1cc8c1577bebcc8e477995c67ab6dcbc48fb7a2c819919ac0dc9635455505ec +a1d23bc2ddea2a8f7a5146385ba3bc0ae62c4e1ec99e32a53b8adfa3b3ef8193 +a1d33865e7c4ba8f0364328fe602b088b03b4d914a9c96d0152a0736d2f4acb1 +a1d84bbf07a4c39ceada5e80dddd0b10841a8a09baed68409914b83305ddbdac +a1ecbe244e9dba97096392640c42183f6c15cce07d148d6c6e449e35a301d823 +a1f3ceee5c4cf303a54d23b900438455ddd2109f30b2d6bdbb712e8ce31675e9 +a1f72442c7bb978649ed34d46d9acc13731560633595fa7f92caf5e637ede52e +a1f94e83df8ec375a1c62b9ef389846489b1f3f2c22d3d32071f621ebe2a1673 +a1fdc0894cf3f30f6bb7b7939fd3cfd1d6b2ddefc368370fba84eadea62c52b4 +a1fec135551cfe990460e8a8fe9f282f6ded02b20987a69764e28f9c4933550a +a20468644dcebbdd1e7d175d34d1c0fc8b95d499f3ce27599794544c31aa3a23 +a20704be0fd2eb110554531746e5bc3a988e9d45472099bdac4635d8975d6ff7 +a20e58ddc0bd2a0ea7b6a8f991b64f509303700b3594f27a666b4c792aaab982 +a22503d864f3a04dcef580a645ee7f57c017289e7521c47314a04c55293d11b9 +a24d1781ec519ccdbd82051a6690c025b8f02ebcbf2545a09f105d6e33dccf86 +a24fea534154e96d0aff3001ff59abc0b95bf7a582a2f716e3a158aa24865ad7 +a25d02ef8c52e9b00a56cfd74eed6bf230b4541b0ddfac6a3e167aa8c4c58d88 +a261a8dcd7538514a387eb63d59f949c50044249da3b760c481f278603d28a71 +a2666b8a60a77112dc8a674b9d1d041ed8f915f5430260425ab01d7ed83ecc9d +a267417fb2fed516e019490582e04dcfe3af68f0b589c7ff0db01979d947401c +a2968ff575e6948f1c8c95ad28104301dadee206a52cb4ed3d6c14e629dfbbbc +a29847abcfa6d9e85200cb27ba5f7b2d02385f12ba22ac92bf5c30fdf37c693d +a2b0f2fcc088658fb57dcb63a267f6fccb6058f5a67a9f28e26789d3283552a6 +a2bc9094f43605a1db30e9950bb9f7e1cc6f2c35da94f691de8599ea49361fe3 +a2bf01dd13d825aea1b1f774d983f7589a3045d6ae51164a99ad201dcea9e916 +a2c02ee21be13af4f0ee49a79fdfc4e81c75c8c112be77e109a56d793540b692 +a2c2c0c62e775c6a8da6f906df3ef194165f4fa1b635fc1bfcaa92272f397360 +a2c96c0539768f926e9d3a68af52f8b782a2d5bb0c4ef2b609d856ff75584235 +a2cb870e2bde367b921c2fb54268ca6dbc886c4b882c5a31abeeb9f8c9ddf851 +a2d756fed32d8ab6a9fc0c5f98cd0a7eb86ccb01faa0c35f871fde51d8f418c3 +a2e024402bc690efe064713567410a074abc9a012a98f54cc20365f87fc47d52 +a2e5dd37e7bd697205848eea18f0c5c7d1c433a97044329d3c6e10d37cdc26a0 +a2e8bddcc45b6d7f56f7a9791a5f9b09132ecaa7288a25dc48bc4803e2d8aa84 +a2eb75a0e96f3ca0b52554edd37b20baa50c1912c820b12f427ef7b79a12795c +a2f8c50ea09e3d0820ea54290123d4097a6a4cd725255f1dc6a46cdeb4e6c097 +a2fa01eea4248e1d7cb28f145d55796f36d22041e745e608e322d99b45efc421 +a2fd7431d0822b78b6a6d662d1e043ee0b40cf6440e4f43c7e3a5757d60b46a6 +a2feb0f78a336564d2be3724866ca03227d372c106d1658ab9974daff64a0bf5 +a302824d8f6602586532d7099a18c5da97c4899f07599c80cca0c11a475e5a33 +a3030af3d3efd54a11d3e613a2d2896e446914b74bf57ccc276838ad66b216ee +a31070e3a684ad932d3cdfe8800b04800e6ae1491d677f2576904ff2536ca105 +a3127516ac2b88751aa24237baf87cc30bf30f98801308a0d852e0a2727b30bd +a3134f069a7d127fec546b06ea44ab02f4a184d13837dea1a764df1eca98c6e1 +a3203922eb4312f4969348ba8a2f64bda82dd87ff1d429ed6123d19b8f996671 +a32fa6ff793d369bca82a7e8000592e7145b15db7c8192b5b6a7131c23c60b6e +a3321bff7df67ed7a032d7e7a1c52afce5ac228213215482d76bba59cb350d35 +a33262a7f779d50b951670c166df32000074ee0b12dae39f98171229d260ea5e +a3334dd23c064c9ac8b405c28b0d2cae5931dc080955ec5f52d59102f2b62d9d +a34b218051fa18daceb62c96e5bde4f476de3f757971ac961f1d6127ea570ed3 +a34cbc49ce0e84d6c48fd0660b1f5385da4ace847ea79457be26242effb55e75 +a34d96f6fd537c18f08f7fdd6c43d3b3ee13bb48c0e9ff810fee3802dde078f4 +a353c8199b54750aafd9bcd2762749c7724e3b5b00c48ed4b0fb9d8821b8be73 +a356e46c65595946fec82713076fb32aec8c0caa88e81ccd602a09cd969b131a +a35bc469bb20afda2922a46429ffdec68675a24c30806b849beb439bb1ea7cdf +a360edcb925707a7260b88ed8f19f6c2c376f68d0ccf95a06f60f6a184fa90ea +a36d32dcd55e2f0cceed9c305c51babdffeacce0dca35778ecf3302993d937a2 +a3716c74ceb9184749aa6c1ad60a5223b5c14a497ef11fc97ac5ae1c6d79eb5a +a378e3affd20eba61f1bfba94f9170bceb4d6b0bf44fb5e41cfd798b61e7ea0e +a37f33c1894f2f98e7428c69cd562cccbbc3bb1d91c9324a31348710ee720fa0 +a3814f0a4e21129cb6566c3f4e705115a79c96be8655155573951ffb469a37e1 +a382685476d60e3daeed856f4c8269f43d33c34ffdba3699ca21c3b5903f95fd +a3864de4f53149dce8e1029fdef1c19c6f0033773bbd74459b51415c777719aa +a399bd0d87303ee9539643d048316beadb71749c9c42f7ce0b08c045b451c1f9 +a3a2352c3905bf8600825683dbf274af2b9bf793ce889adef8256b63c75a4038 +a3ac14a58135fe37c6df8ba2b8f41599864ae4771c166a23fff4296b038ef9b4 +a3adb47dd1e3884b664e2ad3e74e0d37d38d4206351dc9ba02e18ba3cc138d0e +a3b7862d68777a44f155ca769be17697c9bba25cd07e73992aadbaf2228ef28d +a3b792eca244df82a5066735310bdc2971fe6ebc4f216f03052332b4a3120a23 +a3b7d79c28322c758be0b26f4593ef09f9ea72aaee545babcbc4f5ef13fab222 +a3dde0e4f136b2cd72442ade8d6274b9461f648b44393901fe426ff6cbb6da25 +a3e771e0664f482e9017aa385ddd0e77950d33d278da2b80165bfa0d18136b4b +a3eb4d06520e2a3479d8b2f4277276c10f66a235994eb93142e72f1d7f3911d8 +a3ecc4a5bd2451e65e5a477f90f3a9a330c1a293a64427270318c88ee26d1043 +a3f0edfcd2e832abf28f46c1c2133e2a4e8d5758ed40f6495b8b7f2a14a2481a +a3f7f4e8bcdf69c2dde1cf86fc0f56033acd934a5d5cc0476a980e0c2203b1be +a3fae7f0370dcb4e7f0a47d2b1fc70175daeb583e328d918af1d1b8a894dc6a9 +a3fc26cc4247b74829f29eaca9ef8c7f2a577ef746efde4430446bf3afc1085b +a40028debe32421b1bf81bb3777e807f20e1e509c2a7d08295b2ba82a3f1c3e8 +a40d348e61ba9d08b76af34c9e075e87a5ef9f672d2bc1b28b52555b114347fc +a414e8488f32f32765a719f7a4b011fae0721d4a169032ee450d531d331f0673 +a415e714372a9a7caf979ea3833692f76d90397b93ea2496e1ab7ccad0ba25e3 +a419c95258790ddf9aa45b97109bd3d2e9a2556cc0c8e0b761c84d3f1eaefbb7 +a41dd6c8b1c5f0ae73a607ae16686920f40301bd10dc7a47541de977316ac44e +a44052c9de382ad5deeef2a17345b2ab5ec090d1679fe88b04418e5e2d8a062d +a448cee2cdd21b702c30f112b2a318e93f09d07be31987d50138f67fff0cda35 +a44937a3a99b237f45b32ae0455aff56150dec42d9cb4ce3325a39b415303803 +a44a1defe17230e75cada30d7305791a6e51ee5bd16e0ed66ac5f99a5ad0c01e +a454beb85ac97b209a9ec0b018f57c697de3cd65cbf69dee7180fe894cc06616 +a4595978d4ab4247e3aeea4f6c8f83272c3993355f8693c459dd928a6d3bcea8 +a45bca1288d5525b77b01f0804d829b42889a155cedf9420bbe291e7b8f9e549 +a45ccd612cdff8952720adfce4a12afbf3ba9048d6951080242812180ffc15df +a45f8042feb92c734226378c719acb94eb1c10e650aa54631a0e6575b2d23569 +a468a3cb6a26838634e3c0283aeb9b1c197659e284b4899b9beb896176905528 +a46cdd607f900cd9679356ea65e5f14bc0399940ecd3b7ea06131d533ae20602 +a475e00dd1a095c8c1533055bedabb9fce8dd3fe80ad9f44e6ae655c6a4605fd +a4763a745e974c12389c3bde33068661183be25806f62b88abc9becc8f080acf +a48ace20fd289f423d13d2bee3213d6dbdbeaa9e6efe50dca841846000daf1ed +a48b5e65ce31a0828c20d23bb730af8a966cff5e43e8217eb760799ea125ae4a +a498b9ea4e72299c9be3420d03cb8d656940e9637add3d82724743adee6e873d +a49c9e3f409ceddb41e41b7e03456a3995334d704c1b7b418f5ff0274e4a2e25 +a4a2bd8a702e897fdacab60504df9cdc44c2d61b2697c2e91105fa457d88e044 +a4b78dc74da652159eb72f61374f3570b101ea6adf5f9b473fe95f00a63017e6 +a4cb048346b6cf0f615a333912bf744c3ef6f9eb4f3b5575b2ae1e16d8e8cfdc +a4d2ce00dc4c94ea1b10b99340237d8d924a6ff413b1dfee44b0f74335e89976 +a4d45fdf196b1d2f0b27eed996a785dfeaba9359d9e37a1202e72353ea57eabb +a4e67955700c96da550fd917bdb44a04c588a463db01a69d30ac28d181ee0672 +a4e88ba1dbe71b57a73f589b3bf6c826bf0b7c8f1a403ad1e9fd64484aba149a +a4f079956f4dbd92671c877d90c0440a11620074980c91ab3e5c7337dd872f0c +a4fb8b6382cad907ed9fc734feeeca3f5221ab9d414e8ed4f728eee82fa2ed32 +a50073389291f03a62e0aa59727c175120c54a753b4ba276f861aedeca231281 +a500dbaf2eae318bee8882020c2e3e8dad504d179cc177ecbc782630e1664491 +a5047a4ad116104b2e718141c2f879abe6075d33a684018acb07880f1dd68225 +a5079c6b105e9182cf90bde90b38d3acdba2925c1c7eeff83d124b5a96b04ce8 +a5223f9df1caacbbc28ffcadb3ba39b0c78747c516c645a6b7dee5ecf0f4f203 +a530883a1e82c261d224c03fe6776ce4f3be56a04e8f76482adb3accf96bee35 +a535e586562ed345a5741f56bdba0fff4644b83e34c1c0662012793656ca8b27 +a53b747ccdb757f7bce9c0f12ea7530d44acb2002ea4c90d546395fc9bf884b9 +a53c38212e076b32adf9da14eb18c531f8b1ea9167a6b8c63e6b46604791900e +a5472a111e3a3f56aca3d0e8ecaf760fcd71a798e08164affd1e48cfd060ec71 +a5569201dfc9d4e52a00e947c88c1d1f086c84ec34cb0b5b0b06650d0052f946 +a55987958ed066695c302e9dce64be8b9eb7579232eb8e88e64fc452c162838d +a560e952f38637bd074af8a38a26077115fe9d0cdb93a1766840a57d2994d4e1 +a5790bdc36606bb055245713580fd91a65b669d4ccb45f01b3b4ee49f947bd04 +a583454f89c1821696ae1901d4e7c04e243fd95274c62c8547ec79674fe80148 +a584f724fb7cc4e2ef90a7f2baa197ccdfe418d7a11bee897c54ecad2d1dabcd +a58e57dc9ee19461816d9fdb729d0a9bbe038a76f9d50a8540c5aedf58ec6fba +a5945a9488fe7cbb8a3a07da70f9aa1ee49b9277301bee44c44b5efd4b067012 +a595a7ce1b1d6261fedebb015ca9e83d05c9b1be792caa6e1f3cda7f169f9714 +a5ab98b3a541bf112fde7f44f5167617f191997937052572523f596e973e0fc0 +a5aec28766e594ed0468b1803b9e8a496d909e7003f26f472d9bf25f24fd5f16 +a5b0ebead0880909230e3b06be64347c29b919dda0964a3ca32f3322b51b9013 +a5b4c807928bcca4c3f819b32439b1ed7e85e9ed7b80a7c230357f859d094c1a +a5bc351073c11ed7b429bf494375e103d97168636b5a711ca2dc40b64c4d4df2 +a5bd155590c4a39b7b484fb51bf7bb28ef25b5e520549fdc3dc61e411e458b30 +a5c17e4cc77d852f35f135a42e4958dd8c915e4ac5bb3c2c0c204099f69757c1 +a5c4a8488180cab0bc61b67b19a8600bb1a78b612ab2b9326387fae67efdba20 +a5c61f775600ad7db232b5e687279d9333b2b4074f056121420d877ed02a2ab4 +a5d8b4620d18f23d15fc081c7ef2e56b1156d6fe6a86c0f8ca48304b77505eb6 +a5e03129556e99e401f534608da8a50d89b6566b5f3aa5caa5d10ef4c2d92539 +a5e141aaa0afb0889893e76dc6b6fbeaad4156fa136df8b973751640b149bbf7 +a5ef9c9da3d7e04a55f7d25c1c04c687567be5dee75a90c744a42466e2204ba5 +a5f0e2cd4dede72d1bcc23f9419091517546434e6b747b3c2474673d2cc2ff90 +a5ff5a5e5f461587f3de7b816df2f5d92c1c32e8ad3a9223938b0efef12de6ec +a60208c131a814fbf1dcabbbd141441772ef5a81dd9a84590e4ab4254ef33520 +a6031580f7c3c70b69ef7239c658a14f573580e4c20ec0a0c5a86da720f34f84 +a6048a2246f0f633f7afa262d7c08a2b98f9ff0173d7a9a2536009e2b3ae2b5e +a60e9f1457fcad53938337537fe383a784535a316afd5077c0952e3c13a0cc17 +a612a3801adc05785638d1f80b783a5376697da9bf954bb578b141e3ec2ecdec +a6245bbbd798f5b5e87eb22e7a6036ea3ff855ce7846c44dd92a3bd4940ae037 +a624e6d3526b5e0784b69c58316158411a42a7e656bb06ea8efb0cd4e80a1a0d +a63109bdc131c09c0e00971964506cbdc42065425ecae7384191de37d421a3a4 +a631677b1956bd66de78dc773391bb190bd74851c0d73aa7bf298cfb34114307 +a63642883d59033e7556824418a5ba2d649bec7ff3e2ef75886c0b441ab50fba +a638965f6b2fd64afa90ae25d6b535e147cae164d69532c894dbd78e456fde24 +a6502b9ea7fbcb5da1073ed8e163b1643f46036a4c0ef1ee04ff690c4c799b50 +a65132987028dc70bde3907b06197613bb3a3d1c8e2bfe487275ea1b379a1846 +a659b1fad5b36f2f46bd3fd25c9da886b7fa8e7bede6af616d7d5f31ab588b73 +a65b6925486943ee872b054dd78dfb75798e33c2f85a2fa3a2fe76177cc07b75 +a66912028ba873a31061ceffb84e2abd51601266b6b47d540c714fc93d8e5c87 +a67a1ef9c038399cb558f8e765ba8d2b3ea6d8b818e4577fb0740a487949cad5 +a67b23bb95619a17037914e41da44f66d1f3b9dd7336ba066d2bb9228e022641 +a6804a6cb29f1d16af409662a31e309d69b24c4d505bfdcc6c24370598df9e69 +a6871d2bc34ea6e1e56c0d6adabe4e8ab53356cfd47b56d07456552b937dfccf +a69847bca6a71d34a858291dd49e0677db0c1d7fd0ff2da3ebd2503704173613 +a6a3b4ffef76ddd901e64de445986fd7c55e752c9d1a1f9d4367b2d65cef328a +a6a4074501a19c06c1a9418f74b7c7c902628b177d6c65a78ef29eea13f15d72 +a6a4cc4acdac66fc3d3655f98cd6f12cc6e19f1e097d8d13075d285d516bb190 +a6aaaccae60db6bddaa171031477f783f1bfa3d749e5ef1f046323841f6f4a81 +a6be8c3df5e8679ade7b264d16b19e3dcd3b473352285d36556684d90c61b564 +a6ceac5d56bc3d9b76210b86a9f8ecd0ebbeaa63881af770ae5471568f1a4afd +a6cfeaaafba2f72419d1582552f6f5652b0a894dcba09fc6ff963b73541c0352 +a6d048adabfe90f9e11de298ae836fc6bf06c7a43cec8251c7dfb0375d5c707a +a6d2c10fc81009befd4b14d32a26632e0e071664843525878adad4e34fa2f773 +a6d60dd2d0f3b9efc5be01b395459f4f09e230ce57e77e94c6872a87d36d673b +a6dcb1ea4fea9925009ebb2093d82b12867449db1a43342c9422de791e8045f7 +a6e7851c51e279f2321ab29d90a2d94d607cbc94fcf777c32e58b51c5ad5ac27 +a6f1415c28d45aa2dc4f9d72aa7da4800b99eec6a2df38029691fc4e16b13c6f +a6f243ecda83152b779fdf6ef02482025c68c755a20d3f45f45635bb47046251 +a6f6aed42e8b96f173b4702a6ff43e6d0912b4703fc9c78642d01f8bfe92a795 +a6feb2425a0e44310fce444b562a4f3eed32c50f37d94f210f2842bf467f2c25 +a700024323e2ba87d1ed295b7da469df518ccd5e15311368a9773d9a13278103 +a70af95c43fc4a8fcd58074b58b80639d5e04868a0e0b42f0e8c126a3effbca6 +a71095dbf1cc241c7959df24c8a9caace2ff42d8a5a73a7c464794bb290170db +a71730508c4f4bedb695762c1117f91c1a7ace543d2977dc89e28cae7fc7aa42 +a71cc1736568ecc0cebdf9270b748b00494c5904d267dbf92f51ea264377839f +a727f3b5b05f4aaee75db195ca179a6dcb3674b40ec68dfcf0dcbfb80a2e23eb +a72db3414386cfb839c4705d78251a8724ca2a32171515725b156558e59387b8 +a736502bf1b79e78302af307b6bdb4b26d38302ebde529d6451c63d2f58ec97e +a7366bfc736d00e52ebef886994713b619c38502851ed637c11f5c750c504c9a +a745bc907c9b4a3a02f5a52a2ba3133dc6b197544c7491266d7163e7f8c6613a +a74739ae341a7420a1e55234f309d12c469cf5b4f1bf56a8fc3fe35d49ec9cf0 +a747a4f230444c317aa29d217d27fef277e941f6bccf7340f3c0380703ee8f3e +a74b0c59d283f897c9f121bfdd80b79be736bb9c0062bd757ff9c71d1808372d +a74d5257cc9322c948d93504386c412b2aed29cc0b92fd2eeb9f764806dc0ff4 +a74d686ce274c2f13254395bcb09c644986c1fadd7ed7e1a43d84c3f552d9308 +a7571b88feb391e5e4636940e589b8a11daa5f8d61d535b37cdeeff6e73e10fd +a75913b0055b2d1e43f391610f285483c78f614d5d8349641fcbe92b3d2010c7 +a761e089ba8b69869fcf4bfe46b16ee8cad0fd901058a8248d93c199b99e3df4 +a761f878390de1fea236087377a2374808bf8262118131be8484b34555aa203b +a76e6880011ebfb312835afe0a14b7f8bb81ab6185ee62c7fe8b0698431ae857 +a771415ae51f3826d4d0bd0af8de7f7b38ffa18b9f35f529da1ede0105d0b566 +a77a3614dc3537013049b3a9ec683a254e6c38a5ff65e0f92f3094aa1b5a731b +a78a587b9b2788e34b11738e449ee239aa60d7a28b201b78c1277d30dfb4c7d6 +a78ff276078b34227e10ec133d8a571e1d61edf2e1b6e6233abedbc2b9b31fe5 +a79911a2512a2c3d3f5f85f2d022c467a4ff43cefd6cb6cb7531b0b713daa47d +a7b83891bbf331dfe7cbe5cbc9ead7ce233b64780ed2075e810457d860241189 +a7bd19ea4c36414d9a4cbc543a6d9b5d60a1c674720d99d7555121600869eece +a7c0fa9f3a0d764f31c8f5ec0aef88ebe945a8ae08c4bdcc5808b28e5025a7f0 +a7c8ab4bcf8890c93c29b6f9d337d83acc1754580db0c18155b40b59704a54fe +a7c9e12efa6283cabf6b97f5169441a17506ce57477f3ff350d5b31b52176f31 +a7d50f003862943a16207d59afffe265c82d849033269393b85869fa2650fb8e +a7dddb65900096ba36fa166e384809f997af2a630aac977b3bcd294d2396dab4 +a7f4f288d0ef37d91961c7fb5527c07a21947ede78559fb812771c9e2fe23990 +a7fd50811caa25eda3cecc61b0c63097ac646cef0a6c8ae8a574db6d7adb4a77 +a803698797efd783d058d4730030e6b08dbd5947bdd7dc52649f60ffd90d7264 +a80a13a469ffe0d8f20c4331a94ad57af391ce13c70dfb0094b3699b14b22a1b +a80ae099145bcd79bbb53d33e5581fb7bafb8fc7492c9b03afc55eb19a9a9cd5 +a816cff22ab324ed9d3c7793e8ae0c5dee7180e9094de1f35d4db1ec217b41e8 +a822a37c541d2b023131e758ae3c306bffa8eb8fb4b28cd70bbceb1106ed10b1 +a82656dd4560521bf7200c58d4a24cf5addf2d54ff1cafa2dcedffebbf234be1 +a82a3612c4e1d97adefd27ac61009914e0ed1fad1c73ea6d5d07d2ba4dbde279 +a83a90258bee19257d97bbd003e08b76258aa3931648b3392d454f9384c63ecc +a8473c2ab8337d4458499ae33be746e6d6ad5fb1897356d8808145a8f40321f5 +a847b15c8f7328011a27aef98dcf2496a5a31385d812c9b29a208a9fd6536121 +a847fb3ce38fb2ba26b053b55dfad3bff19bf4219a6021b098e8e40ea1d136be +a854fdaaf4f3b5f7ecf00e7635dcf6e330a402f03c8edeef7fa239aa682b9a46 +a8593a3ce39b864921fc2b49216a29f217e183c7fdda11681bade3fce04f0add +a85fafd53106b76fc40f9234c76ca4340b4855330d6afa41bf22ae685c5d4754 +a87be7d8c7da6c38833944139bcd9f08c692f285343cb74439a7489d7abdc9bb +a87cf80ebc83d8f3377da194b57ffa0e823e094d48785fdc24bf1fb62378c013 +a889f8cc8c5ee668061abd996f8caa78e515fd17e2072050b5bf629a15f0fa54 +a88ea904efe6077f2b07b37081a7a79a1b3ac15bdecddc74a23a9969bf7982c9 +a8946fb4dfe4cf465acd55f95757bb1264ac4c74499a1536814d4421324202ef +a8954ed45286c6709421135621334d0657ba7036930c64a9985b82eec48fe898 +a8959a94ef21707990a1b6ba32acdfbe3f8ed9cccb07d335932e7e0ab792be36 +a899d4e0cbacdcf9180979f4f0b3c1b5dac0b022a53fad775080e7d54cad2a91 +a8a1d3dfcc98099157ffda2e6c0449820dc00a20f9f6eabbe546893cda2ce2eb +a8b06554a97bb3cea3c5684e16f76d7d9104128f89119531079f52ca59636984 +a8b205d6cb8cc6f32a10f7fd776ffc06e4811014af35612d8c6296715376370f +a8b52378bf07d215690a0dcc2646c7c79116224bf17108c7a0b6af1e15e8b4e2 +a8b791a884a2ebf2eb9f9f0e9ccc67edcb50998a357d3dc602ac5b38bb4203b9 +a8b7acfb9d932c25086960825d603edc730a705b87672f82930f39027eeb310f +a8bfb3b697ba8b56e86543652638b8b74d83cf3138bcf9525f61dc5f6d91743b +a8c478fa541f6cb69c623bfb232de98fc23ee36139be4f9b6457e46c4bd6aed9 +a8d05cc17d3b0c5cbb3ef1cb2cba184dd37235c3e6669cde35fff23b373ff4fd +a8daa6ba603d5dd1a2c2222f8289697d0211ce4bc7e0915e3af45c93200b9504 +a8fe7b5aa73bca6fd7c5f17dea5c097298de3d0214886a9dfbae9d87dab6d534 +a90e565779ef0f3dca859e500eb9a8389421ea256a595585d0c87952e80ec91a +a914b80feb46dd8ac4c66611dfc2ec549965ae58b06251b56c70d5fd0a1af83d +a915ccd9bb38294de96aa72d483b677f634245c7ce295c80bc906688a0ffd8af +a91c819466da7b3ea8264340d9aa6bd5c4a5d298330152e385f91321a4959017 +a9319eb1baab749683bfbb9d5f8e16231fabc0e680d3d03a34c6dbc17218c9e1 +a9328fa26055be5dec49a28fb9f4418d37aab9ad3e1b2a9647318da6caf4480b +a9370fc545c16d859322bc7cf75f97408b91c4a4beddefb57895335898bb4ca1 +a937902311065cf0fc9770be0b46eea8d07ce9eed2472eedc9e59c11ecacc68c +a93f50c52fe593c1e7e07b71b0049aef82257d5f956fae0e563767002adabbe1 +a941606468e1b1ad03445cf4d5a5ecc223a629fe688022cf29b6e117ff8a035b +a942beae11eba4bf1adf17c9ea5df84a259ac98aa810c29142cc2978696473da +a942d229859e80b6a6f3d638f22802990e4597ecfcd1c5f7bdc50205ae83adbe +a94681bc03a7cb56185ccd490ec52ee3a3a1a9606815354d6ec64102b992c960 +a947d7696c1f3220e14db1dd6fb9ec8f196784a21a4434e5d07dc65b8abc29d2 +a94812163fdc2ffd3430d00340a91b8cb88de428c40bcc98b2b874a770cfb238 +a95d05665fc0de8f98c6e1c574e4fa8997a8958b78ae12e33fb1ff9f7f431c29 +a95da1d8d41e2e12bbf0fb4b7e4f1e0175c339367bc896420b46fe42ba1c9e54 +a964d8aa98e5fe91f8758382fe315fe86abeb6a82df9b1a2c47b6d63b33fee33 +a9664e44c077ae19d89f25250d970a4ed5491aca68ea44464f49e86e16ed92a2 +a968b23c78eaa52b10d70c6cba82ccce8966451c042134d80c57742d24b6a194 +a970988697f12e544fae4dd1d3aa183cab2619bf07744e716a6cb2ec7362bb4c +a98ced21d5c2b56d5512e577eef109c410ed6071aa10610349864f308ca29bb8 +a98efa5f4b8ece3dd49b321055e5b995af5c884df98ff6ea71cf25574ea4c1c3 +a99233d570011ebd1e8f769bb5455e34e2192908c3bb22616f3520e61fafd07a +a993556f47044cd77689d7ec00a4b4485ef52601929e34d3849b4c4318d4fc87 +a9ab4424b2e8279133de0ccdaf350cd280e16727528065c12578fe7e3d5f79de +a9abfffda7a5b262927712d2b69d0dad527384d358419f182eca71022cc201e8 +a9ac17b58521a6482792303fa44c919868ec6158cc0db91d4369a089ae0b8f07 +a9aefc6375880f31d5ea77071f9451d4fb50d30e96e9186d5796b0ae526f00e7 +a9b28c6a2e5c2efbc09d2656fd6729a9c007a1fcd293dd89a5678116a834cd35 +a9bd077d0701199cd102ad7c2a357abf7436352d663f5aa87139cdc95e8d4633 +a9cfefd3f653828603a24d5e7dfc741edfedcddf25b805b878330772de7a0f25 +a9dac0c6c8836e52ed6a6324d8be68ea7138f6071e20d3ef771cf55e99979bd9 +a9dd8731652eadec135651c3b882b4e4acc374eebf6ddca6b1ae99d05bc4a0a8 +a9ef163ddfaff097a24c4de33f050cd3f8875970e4ad5efecfeb8a1d48bf462d +a9f1b914606ef51464778f8b72d83ef85795af520d4fc70e87b46de4cdb96c5c +a9f215a07f322d2ec13fe5016b5b657390698f2a629f325b40dfa2df1072bb1e +a9f666dd6b1ea62ca0eff32d77f45c365f4e20d67f5002a70a379165752feaae +aa0d91671840c2c44c1103e4ffdaad2c45635bb796cae3417fc385bc23fcb3db +aa1eab199c68e0169541884c3e609a2cccc53c02eec0184d630e78eaafe1610e +aa34619c52f6feff55ebc6b4a430796e712de5213da609b0b077309b5745340f +aa3741994e3a75856a52a847b72b333caacc6c8ebd172d2534349e95afcf3d52 +aa38e8274f00174ee405a4c66ab4d4ed575856b1cbda8f131aa4b002c7da7f19 +aa3d73cb4510ea57f628d902f90a6c4d33640f7d628f02317f883d9bd8d1fdf6 +aa4315dcacd9d93eecf692dbd30875ff8880e2ef308c82933301c909cfb017a7 +aa46a02dc7574de38d0d5864dc1917e5b5d22916e166528dc7e75f8c6395c73e +aa4a40e1bc790238ac2733c5c194070c20f7ab3cb8e53c3136fb5aad32dc0bff +aa559de5583bcf69c6af34a4ed4dfd90046369b28539b74ac79a1efbd750135f +aa5ca0ebbe5c347fbeec549c3a729a3f5ec3bc672ab66622922b924420ef94af +aa682721ff13986e9a4e2d91fe0d8262d47cbbc3214c39670424010307a35a25 +aa7089049bf19f4abeefc1147abb90d686ae097543f0cb62fd4f07ed75a13430 +aa986b90f76b6d0ad8214e05b96af205d942e1c56fa058b5689cdba61c99ffb5 +aa9a6e82e610b5db5283a1af943d869b2eaf4f9ae458b579f2a4a65bab03d0c7 +aaa70051bded33c42c252907b8c36185ed0253c4e458756df02ac40ffc64e92c +aab81867c40d116109678db664ef41c99d68c30bcf96a4b84836a94879649e26 +aabb1df788e3e573907e45c36632f0c5c96714a7a03e5723fe9bc3ef3c848ad6 +aabeedbaff731a005d01152367d78d30525bfea50e682440b2ee14eaac4f9989 +aabfadef5444886ade7b33853c72ff2383593f5f204f0b63c7258ec908c31a02 +aac79b24271d761b92087cfeef0d14ac91d3dfaede0345069f2dd8631b2b5115 +aacee4170bb07985bf29645ca8406d3f04eab50a1b692d306378300ad87c6e8e +aadfea4a8fb0d9834b8e83af6eedeb13f7105e2758637269144e1992445cb0cb +aae0617d9470fd6e4531fbe7d2a02978ee18491f1eaefa8b2beb7a2f1a74c9e1 +aaec645667a113473f0546fea088abeae1ff7ed548a37caf1ac916fe0ee6c5a9 +aaeddd76248c12bb6ae73d1989e86cecc82aef1e39f16b7d9f0c618d3b8a42fd +aaeebbe62c656d0619a752c2a7f3c26c9e189bd9dfec871e98dbb7603e67526c +aaef03a96e6e65d5f39bdc09befc5f0bd45eecc397c16b0641f422d0b79eeef8 +aaf7583741735fb6006ba1e40a1d9f0d1d07fa8d1b04e49c97bb85634aa3e66e +aafb322e99a987fb44ea7d5a11acb4f9effc282b9bff2b2c03ec522d9597cf9f +aafd26e4420a309a40d1993b75dc8721783737f3d36724b09a298b8ee611dd7c +ab001952f1b0e9175d97bb1daf9ea0e0a6af231595bc592daa4f50044b38b7d1 +ab101fcaa36f685f6e46e84e87d31989e6e272a83d3149820660412fc9d6d52b +ab1ca6ec35c99a1981756f677d2a785077cab97e43cbc53f2de8acdaf99b96dd +ab39bb28cee3cb9ff9445fcb074d114d7ab4e21b6dcea069884b6af92de03b73 +ab3c142a084ca6f0620ac8bf80c7265fd1eb6d333876100364498414cf829623 +ab435f4eb2e50b13e4c0fa832aafaaf0c92c890fe9d0ab35074ec2c5188adf3c +ab4743ef30f09012b77810ad9ef4dabbcf812ee53776a83a6c6943b3eb76341c +ab483c0d4a126fceacee37299322fbb3ed265165c7ebfcd8f36edff75f0875b0 +ab538c54a0b94543edc4cfd40fb195254be70450649e0e6d413efa3a00fc3f0d +ab5df6c61747b98eadb2ccb80408b51fd194499538a8b2b92d7f53f8757ba477 +ab683c92b8aa2866522331c2f40099c4de78e486c8bdff536cde958a6a1c2871 +ab6df1b70c04819b51129aba0f16caa1d419ff34e9afceb78c8174a31cb3841c +ab6f0a028cac3844874c3dea3b46e3b474cbe8dfa02d843ae1d4c8ea82365a32 +ab8e4a5171a5291b0c8a5119efdd6e1033283542fa63a2407128b15a94cc6334 +ab95acd1332a4e2a4e1e697f9ff93a01410a1a633a4f864d9fb745ef1a3e3fdc +ab95e048a6637b0715ec9207d9625245f13cc76683d9c2db42d09c6f7cd5e548 +ab997ee043c7182e62677f1336462ce1934565953df2fc0d4f2d2a0756aaf07c +ab9bf9156219600f399eb989d429d5e0971e0a4a8bdde33fef4bc352beee6f79 +ab9e52a1b973c4d7ebc124f986ce8cabfae1c21508c895ab792cbc5141d07260 +ab9e52b08575dcde1efcaa7295e219b8f45bbdf9a0aa171b19b322da4f42990b +aba1bbea59675b7c42da774efff9306a765da80e11e0ff30fd7aab5134877f9f +aba5250d79d678c289f10495293f48820ae2cfbd06a3909e4ab40e9b26f94553 +aba67f3e2cfb3767a821991f36ab95bdca31edea97585870337ae37e84c02525 +aba90909ef60b9a09d8965e727fde1714a7f299d4252261beaf3a8b4a1df3cff +abb2d79f1ab6af2eb107593a6888f4727898d09fcbeab1e86c3ff254397d2cab +abb872cb69e9fcee5bd37eb034da01eb4236cfaa9fe89970ec03c235002e4241 +abbb390c99b027b5d9ba23860d8a8f6ac9ae725167410ef5c6baeadf8e9b6327 +abc23bd8ff2852c4bbe6edf64ad3fb6da6465b7153396e0ce9bd15c6566c747e +abd732ca9062d1d650b3f1ae49be5e0da9de608f514f4dcc8e64f7e5b9515bb7 +abe73c77c8c610ae48610df3717408c08b24a70594d69c4e940ba4316e243b05 +abe7c5ea9546b1f4e5daa2e074101237e7e830089115e2270756cafa6d6e4d96 +abf7f0f225be4582de2f4cfb3ef206098edbb5b1a130283160c70381d6e7637a +abfd7c4d83a72db00ef4b3a9c827fb5485917039b2b70cb826f41afe1b1e9d01 +ac0cc147f28cd7f7d0fffc005040908cddcdc6bd572ec2c0ef4c91d783bbb73f +ac0ecf1600dde95f337092156e12c64c9e50c903dad4f2f5bcba22b1f7e0fb42 +ac103c53b2ada73c865dd35654833f70720578c9a5ea84aa7a60100333847eac +ac12c67ec4a8c519e118483ca1d00b7317efef70dd79541fa945d6bd1d3e8d19 +ac1ae65c2d0b2fcfe45ee139f11e1299e53b77ab92f4ea7912d914241d6e4869 +ac1ef44b0b266fdd93bbf0250cd667f2572f2ad8da35af83389bb8a2e6e9f92e +ac22eada172880696b42f0eef008ce5d190e622ff022db4e8637d5fdd29696f4 +ac3aaba56f22ef62c63d0ede3c67d0f8379d7e2b94397875f726bdff3b69a616 +ac4c257ca87a2cf48c6d18e00e98a7c689bdfb9ba5292cb375a7e032e73c1281 +ac6679f5db92343cb449ab0818aa26468c5fe4ede6ffe9a5770a78b2ab8fec08 +ac6c5f1d88762a3f60a80453fd547b7fe32311398e603c141cb8409c1366066b +ac6df7380bc06cccd428abf2958bee8c9392c34ecba6600ebed6c6b677d88292 +ac75bffe93202b42db54f794aacf3c180366bfbc7d16c7a85ed5d1ccdefa5000 +ac778f5858aeff52d23dfe15d691e679979b499bb724240305751eee236fca6f +ac7bb367f6b13932fd78f38d9da1e2cda482a4a367ec4897ebf31846ddcd141c +ac8d26caa953f17d5deb081f28e63d3802a7c3a2aab51415f248eae00e64a6c7 +ac8ece7f8d76aa6f2ae5c65a4cad34ceb3cc361a705f7f8a47c9e57920e8c3d6 +ac9241b351158671fdd4b7e6aeef604c07b8d381f96f308ebea51bffc2c94fae +aca2a93298dd11b7ca96954b916b5da0da9d76a567ef1caea93b350626f09f10 +aca462b7544a24ca694a7f31f7dd5b6ee8886025258aa076342809d002852cd6 +acb2bdfe98f1e71332a6f65019fdf13c3c0b259d3ea6cf53fd69001a2ce765c4 +acc2d6c6e279e4faa6edb9ce7cfab9df406c6b02076810c17ac2f072faed08de +acc965e51faee0ed40592901cfc7cbfb20eead108a5661e949ee1a4383e1265e +acd1e29c89247ce271da4e19d534c8c7ea9b81cc321aa3cd6cb3291896976673 +acd7910fac925d12d6571aea4b093834f5f183d5dc3294f5807b3442c5d40e1a +acdb77fb004844727818e5207927e0330cc1f86dc9a5b0ca28150734e2c89a32 +ace1ee428018bb8c3ec5f6c651d5f803f411694c39409690e05aac4dab83444c +ace2731785dc592088eca07c3acefe5799ea453f2de33fe9a51cf314e123d386 +ace3ca9a4b181561faebf1b56073b9abba7fa68fd5d3443089e7b68ce12bafb2 +acf2ec416474b9c441eb5b31912d5369b3ccc7aafbc919495e97cc37a2601d95 +acf7944ad58aacb66a9315b1112894d6b6fbad005198c03ac44b55e727eb3c7f +acf94cdb48e7602af9a10b8d3055dec97da5b1fd1f3577ad61aceca15096db1b +ad00515327d09a6e56bff69c5221b2cdf2a8ada5de35cd86e8f535d9ca885b7f +ad0569b5464c6e28d1588c9b9c52ce039219e9be6564c46db82d5775a8bdc4c2 +ad1863de45cc622d9fa54ee3189313c5c14a53cbf13bc18f5bfd35344bc57471 +ad1e5845c0c7736fa0ad824349ba7ee156966c7ef0d0f42558a45157873f14d1 +ad1e8a111379c159209360bfc252ee24adcf8a794e2b687526bf491f6adea98b +ad424eb0694213290d24cabb620283a2ae854b75caced6436a866f3bb02bdee2 +ad4b06c69277a4279d91e209a2c0a5005843bb4e421366588a9fcdf6993d93cf +ad4f61bc139c3bd508fdedc3e3618bacd448258570393076166ccdad0bed8520 +ad673225d87ba1d3d0c7e81c3d6e72050cab6207ed1ce47464f7b56652fcc48d +ad6bdd9f17071cf9239939622e7e040dd90f3f2643847536fbb40b5d0d7e05d4 +ad7de7a5af27043029c53e6aec8a10a8416f6d26835c8718409eadfacaff6956 +ad801716be1116388db09cb07ee619ee1647db9e8b64e671f2e81497893cd198 +ad84379b37cafe250663a87a2c9c4de3853ba3a7187d8c5edc4161ea81d5b7c7 +ad92f469b9026caaefa6f9e493da64f4ecd7f8157ad2f117422f278816640b9c +ada17e734217374c128a85e46e09c06a5febf8da5fbef73565279b08cbce8510 +ada189becf583ab50fde37b564876aca67f13748e1427c0c2405754d108b070d +ada73edc7f522aaa2881eb19d7239cb57420e646262742cc897b4f8cb35c6336 +adb02281f4b91569a6aa0ea8990159648176048690842c69434b8ccfac107b7d +adb44fd81dc3bc405b8265c9791f50ae021f877da0a0ef26eefd31c035d986a4 +adb7f008b2cbe873a6cf056acb528ecebdb4eebd2ca1498443423c05bfe84f68 +add338d9d7f2a813f57de5b5d961cce1f08c5122a438d30edf90bd78f6ea5667 +ade31909049defa387d626a89edeea66f0cfdb82f5881caaa2a5ffad7cf56f81 +ade445206f3aa4d454672cadef19274506f56aff5bc5675b688bd0f344254e40 +ade53102c94a737bb5f37d8147cae9e89407a4a19e26f6184c7dbd593bc7373d +adedb6df641f9cfc6c52972aeb9147e4e8648c971a41ccd33cb3ef34a3277235 +adefb34a0aab124345ede9e8e4bd9b4bcac91b86ded810a6fdd67297c3db3be3 +ae0c48548e25e45ac07f9809d5f9d89cd0aa9c389379616043fb69f4320943d1 +ae11a5803e4866a1d8d12fe263d0d045f1b064b3150eae3594f8da5db780fb93 +ae1c1bd53f10813b22edfa5624422ecb519b15ff20c3cb64cbac02f20a79062b +ae205ef21807c6a1c5fb196dad3c7a81c0733f31598bbcfd6c2c965f5a42f48f +ae322fe184b852b2c8ccca9a55d4ea87190ecb6a572608d1066d94577bed5f1b +ae43785b3d68b7eae5ca45ef52e266d50e9aa4a08b08863bffd8841b29913eb0 +ae46914829ba12822886e04bf5716bdb602c5c6e8cc19a58cd6f3bb9ea510110 +ae5fe7d4332e98ff958c3f3e257bc1c9e345587e6ca6993d11cb12d6a2626d1f +ae689cf5011223a7ac12a88a2c46908c765639607e2d3341f3fca4fd2f502ea3 +ae6ae79196b2d68bd64a36be497837c2bbb8140fb68b5a386a706bfe146e8bfb +ae6d2347c4c22b4948d05c9b90c400640fc9a3b743496a73bf7ac30112f65bb3 +ae735d54896714d4d9101fa5597dabdab96fc7822eb5869d1fc9925a40c01946 +ae73b76d8239aa24bce6b801a90943597d10e4bb4b5c792264b91c395426f2e5 +ae784383310a9c73f55a49ec47738ede7d37fca800b473a8ae84fff3179c7dd8 +ae86a68719fde548e9187588e816c12c92feaf18fc2d8afc7f369271752e8177 +ae873040bce5f05563fab379f0198a93ed21566825b1984d380fbb745cc036a6 +ae8d8537624c2604e2dc4b26736c03f76f1c4e7655d489b694aaed3e0cfaf66b +ae8da980be4b7177bc9e7fda069d2023f016d7fdde3d301bcd1080dff1c7b054 +ae97c6bc4c3d5c72ec42ed7e9259ff1d629d3c7abef964a03b9539c760c3e5ce +aea5f4ae4ecf71ab6f6b72dcd68093c393cc2834b2f32e58be5dd5741269fee9 +aea771f88a170a422d136d34646aeea69be0f37244baf83969c1a676ac099970 +aeaa49ad685c7a55f08f5845ca9a6a7deb1855b3220eaf911a968e045dd05de5 +aecef1476b2c139b6635850f69fdbbb231e8cd1bb27476f66fe1dbba28a94d1a +aed4572e8210625479677e535ee71d50bf0cc745973f1eaecaee1d7aef1a418e +aed8f7040441086bb22b4972d590a7ff3726d666bc84992831f1a81a3f15d487 +aee3a86d4b7da89d86c0ffa8b5251d33200f0fd3899d5d826ecda5f60782e505 +aee8e80518abe5b191f2e5d13b89f28bfe58313609593a6585f78526a16122a2 +aeee3dafa6485f3337ef97ed82a3d77a65e70de35fdfd9ddfcad1ed3c9368c71 +aef747f21a9efe7dec0d6f11f0a19adafbb6ba37217b8d500fea34b1b15e9d67 +af06fa195df777dd27018f7831082911b2ffefc3a922b6d5d8ca2106d48c902c +af06fb0a4b5221b7eec2e19bdac65e8ff8fedfcd2acac7d0f1d7ebe4a45e3f89 +af0aee9b653a8c99bbd5841f7ef1d5bf85760649712211046af22a5c1e0085c9 +af0bc86d9918ca40265637ec04c7faf74ab3215929218b7816e12f82ded651e0 +af0de3088c45e5450df1ab2abae32e076f1bf836aada1619fba2d13b53cd6a9f +af15472e360e7c1e0affb3b02b05b29001126b3acd3819b9f1a5df65caaffc2f +af1d4e1ef16f7426d995f5dc76b55fdd0279f8434372b55581ad386d0cc818cc +af1d9e70dee3e24f8efd7fd64f60ced708028fbb4d75823a4409426de30b8199 +af204cd0bd29cc84d8097f82cbb87ac179a964feba4db8263fcbfce9b4f0bbc2 +af2e9335d97c58b4442a790315eb4288d1344a2530ea423edb4822fa9016835f +af3051d001bcf98cd2d024bff2b0f0e2b8dd30801e8bcd463239fdc8062eaa2e +af32c040f82e006832adddb0a9ef391cbddf30066fac80d7fcb0f6dfaae54352 +af34209956c3935ea1303ffae06ab62c40ab3f8ee59da649dcefa9151ba96c7b +af3840dac84b78aa749278e1f3f13e8947d8632f1809afadf17a1a45f5e7675f +af44609c18738cb922f5e533ded315fb0193c32564e4fc4aada48b1d0d88762a +af4d4c792bdeb8307f29b58e85cc80cfa7ef40ca8ff768b9cb5404a533941759 +af5256b323b8f77de1e72e496c05e1cecb828c808c2ae4b291eb8e0c6465052e +af5488d8dda5064bd84f4c16381eb500c3275bec1db4ff2352ad12d42c0152f7 +af715af24202e70e0613eb2cdc7ff5bb948d68375f2a874dbacafa32b6de78a8 +af740e7f04178851c0eb11b0abc0cab00438a2f620d08d9291cccade1b968cd5 +af7d18d517f929e7281e25da961cf9fda2321bbedc55c5fc1754e2bdfa383636 +af8006064cb570ac0c4ee45875c03d15baabba7733b9841d30012ee58d53a0e9 +af8356e1831025ff2b805a135b7684cf66a6c4f8b7d3e16228f7e162cf94e6d3 +afa565f464fdefc3a4bc6f81c17a7b664ac77c8f0ca49db65ec59b8623fc7e43 +afb0629d91641a2984e8cac1272ed11b1769fc475d66c3315d6ae586469d3ae5 +afcad3a96733dd9bece6f64f4d7fcab2c1d96790e2dae5031abbc870d240e28a +afdb7ba982c9430986542ddda1c61fc61e993c24cf770315de9cf1965285632c +aff0fbbbfc79d947417f293d2b8841e5706edbb7475a8e22c89f723a6f639d1b +aff2e712a93b1397063a6e883397293a2e42c7b870eced007cc071f34608b02f +aff549a4530dbc46a1c042452d5dc16cadfc5fa7a5b113f4ff3117d7bbb45102 +b0036e385ada5464b0f1b8ab577397ce9cb6df5dcfb971f3219c16657435d485 +b01469062737d762abb0044015307bf0ed87380c92e3eb94b0d323c715c7743d +b017b6b1fc158b35a6486d6e5492704cc02eb926dd41f26f6878f5a734048fbf +b01a3d828d98476b925fea26fb7cc06f7fe52dba081c5778fc99d0487b0ffaa7 +b01a4e51f7a8f96110535c5473f8d5c5b362c55e3750655d95f9560172837668 +b0201f76e8c968c7244fc34f29dd7e61a8e42c2396202853a9f36fe29ee6e880 +b0218fd1ecbc321d55b7527b3fa41ffa6862259964fa1ff4fa464501512ba24a +b027d1750fcc960f91f2cbca4aa9030dc3bf798e8cd18b857cc891811465fda3 +b0384c7d206c35f4716422aa2f900a056a05ef6454556e21c0156c7b98ee9df9 +b03bc8c9214de06d2961aed65d86346684abbf1c9bedb040b67609817a4d90b6 +b0489c657c72bd82607ca4d0e605f44f53ce1212d41d0d78f7ead210239aeb04 +b052c207e46638fd8873a3eb0f159b546db25577adbf424c8fae601a31039f51 +b057538f8e5730f6a3671d167614aaf60dc22541ca500f7eddbf3c2f7d58c6a7 +b05d0b0e2a8cf123b94cc00ec51861b0e47f3603021551566395b11dfbe8d708 +b061e6e77ec3a68b7df0c34b2fc1a12eaf05070352069b26288cf84a10e5b2bb +b067f9c1c8ff5b21953a6d1a43bd7c9acd30d095a4fe7f89ce25eaaed8404727 +b068dbcd053a30277e85e4d8ec60d15d497f3bcc8d4a5e3b7e080391bbf8688d +b06cb8a276a8fc30d6a4f5cd8548647966af30882b5bce59c89e5e9b82b6b360 +b06dd2c09e3e477f3e1a3067a242f09b7cf5a87c151d62469cddbd2b9adc1edd +b073a45be2c612cc2c6d00f5008031b858d69cb2f1c3c949a2a77a3c46fa1c09 +b07ac6b37df7e997d90d5bd72dff0bbc03363c044e7ce2c179e12c2683edcc65 +b07d0b7c75dc7fea118b227d2de1a9e99d4a0a6ccc989ef2dcdd238a15532f8b +b07d915295b1bfbf590a268b1414838ecfc44163460cd1e1382c07338cd7c85e +b08000b1dd2f21a0dff343fa74e392b9e781582085789007ab966a080abcee9c +b080d2c5b87e55f47e4fa795caab8bb73cb4d24b827c2ceb69589a531a48eb9c +b0819bb8b729e91a3faac1d9ad7e89b3b6f6a24bfe6b51fff9ee5e4ff3a342f8 +b095d5f6716c8f760dbb4c9c522a45db99e51afbdcebb19850eb00b058211248 +b0a3805506ace0335c0b47e6ea9013e6f8d5f487436acae01046469c4a0174d6 +b0b44723bbafe90c20a1b59adf33bd7224143fec063f0bb7df2945644db2d09b +b0c0945c7593034840d0337df74105e77062085b1f400c14c47b3cf030269027 +b0c20ab98167349c6e26c5f613393c05bc547a3869fd4fd0cc3e7f819593ec84 +b0cb3051459c2c3911bb3ec97756d7b56c22eb499c3e0933645988da10cfcb35 +b0d3772d907ffcf03100aed2d59620fddc02027609f4aba76e760f3480441af1 +b0d5a981181e9a354b3fd2fcdc4dc39d4de9996a386c63430c38fa7d1c58081e +b0e0288c2d519ef59eb16d2c910f90ad6f8d61bd9b3ccdf37f6a380f945005f6 +b0f59923380b0b23e0cfbc45da7aff49520de054a21e8fd356a1bcf907f0641c +b0fa7783efb69f757cd628e7187d224c7363b80064ddcfb3b371585ca3feb5e9 +b0fb0552b8e842073c4b97dffa61405c883a3e925cb43a41d7c379b2e86a5013 +b104775f677748ae310813608060406ee4111e80f1d1f157374c98bfe911eb36 +b1078795ef31f6ed26b7728f546ee36e048808defc16e1fd0ebda7c5634a8a40 +b10b81937dcbd3484e6f610b13775dc513e5fced64c95c8c4140971c3ad6f53e +b121cf78f9a957294d707b624ffde496d54e5deba9ee71810a10ea46bb4c3a77 +b13bb67609242c0ea87a5b581acca6c9ccdfceb52a68ee61eb9e79f0a2b4a0a0 +b1478911561708384180a91b58779a5d7ffbb20729f78ebb48090ca72621dc5d +b14c91683551741c5896d0d9e69734d2907e85c85fa94a5ebdb98cefa904ccf3 +b16213c86d10994c6d78c4ba2d53624ad36f1586a3dfa4016dc8941573dd7e28 +b164fe917c871534c3abcbe40242ad4d497eb6022be55bd91b51777f145d87b3 +b1705a53d8de97613a40e7ea45caf7f86c4578e781fae6409121e782a6bdd5eb +b1773e6310fe885409df468529d53c31cc539a8eb287f65261838af8b37f1358 +b189ce6f11664e2262c2fc2bbbe9fb60a6ce0790cef5d5836567feac0cff8256 +b1904adcdbb8fd454c8f8a94c2ce94dacabd61190f860c0b057ca37e9569d7de +b195dff26294f938033c26661c8c915e902fe2258be69a2aa03f9c3471daff42 +b196fd86ad22f7ca79e0f93dbd4ccc0a9f54493e07eca161337ec0bead96a65b +b19d9a6de4605686e8afe8efa9c5eae96087346ece98cbc8ffd7529a3a089ce8 +b1a012205d327ecafc2b2c941a3bbfac03bf2c66c2e658f9b7bff279f943b29a +b1a4212eaaf4fd2d0df25fa2cdd6a1a1980122d0ad3e2367ccf353d811dc34c6 +b1a9452e8be897d3ddbf626c33b0f2ca214c4326e5df5fc3d13a8cf114008ec3 +b1ab12c5d8c9524239a7728271402bc19d4a468238c851885751cae6cdaaa070 +b1b2300ee359a8ca271cb89397b5432272b18ed1f10794a094c66d368efb0a31 +b1b25178b1b027191e2951ffb8981f1cef31158491c6ed35a6d71583a474a8ca +b1b43bbcb629aaa02c1f12eb6a6f8f3d82457e2a9586df229e0c452d6cd22fef +b1bd77dbda0824fd7b8379f2e48adff0547f8608de4d0076b9d6dc08a5d1c93b +b1bf759bd303cddaa9e7d75faaf55c9dcaa70ac5d361837ef53daa242543051c +b1c2bcf1ab8c19c9ecb545447e5b8fb179a563e2f42572cbb9935978d6287e17 +b1c2eb120fb16704ad2cb1084b0d4371fd390a0fae5c2cb8dd362f3f68617e49 +b1c2f382d30800a8bf7dbed8616c44e4f46578e9cfca2c57d56fb6a89e68b897 +b1c4997d7e9025a404dec32147e73f516a36198b929b45178ea970c20e188e71 +b1cd22eba5f453f31f676f212f1c2268c57257ac41ef9d57e042faa1b4c382fd +b1e1dc6af906c29088aa7c91232ab71698310e5d83b7863ceb802acab934d5c3 +b1ec39189d90804a0e8b4a16b871b3dc09ceb2448702507116754086993464e8 +b1ee0fe29e4c49416464f7c956c16403a2340bfa51748c7e045697c7edb40551 +b1f60f58ba7bf0a82b9fb3adcd7817cea3b0d8fac2f35c76ff85ec93feb6a59d +b1f65a834f2e165a6791183a2ca05d018307560021e7c3a95d8386c06f0746cb +b1fc7f4a2a9de552d097645a30c4ae207eaa8c9ad7137f4fee59abebcdbf5acd +b1fe38663e6c7fce073fb329245f6115f58e9efc0e82942d191a9b20241eee04 +b20ba293fa4c9db89a48ee1a9c5d4be3f82bcd46688ca17b5a95a198d2e5830e +b20f53bb7317f104ef7e1b40ea65e824569f4551e63566f5ce6083a0c3b8f04c +b210691172b1deaaa071f812ff2460592ea3f9db2f4ed4c2a28aab312807360d +b2115f297cfadcd3a5a80503a8acc9c7d2b73e6400ab49e3a0ef77096765c5cf +b216e1139b38349d4f0d47dacceddbb9d471d50a36fcdde5952d7227104ab707 +b21cc78c4aef212bddd794134fedaa0e21fd6e7d4cab02f3063fd0e1c0931a2a +b228cdcae208506c45e0006ee658cc58a9b402894b38f25e042f6b1e887a12b6 +b22952def51efc7293084b09f0f25a42c7d04980e52ffd8f70ae2f11abc98b26 +b22fa00c290e98492a80b6994afd1daf3b8564871c2c1e6469d1bedbc6717178 +b230dd1d22a729065ee49bf301d82c50b103b91979e008f1af52835bbdda7ece +b244335ee6b3dda78c6cd670988a8967b8a6bb29b41e5543c353ca06d4871904 +b24ee3e04e313c2803399336f5fad820887cdf15b7f99713444fc00577726745 +b2535c2b94ab2540fa935777cb61092a26259e12b76ca1069d9d3e2b0121e4ce +b255c21d1bd8a3f264c84dbc91aa8be24cde5d8879069bc7d076209c7aa78f9c +b26eb776f00e7674924e8d58dc852f07c45898bc732b6a67b9b63c87c96e95a5 +b273d412b4d53c242f2f2f77332f8bf1eff4650305a67f3764643f25db535494 +b2778801042a04ea06ae7a1726f98ba833eefed74d88b5330983f367018ef03a +b2780014a0fe3abd4bf64dca70eb1bcc8d5fc9e9c8a6add5452309789eaf9ca1 +b27a1935ceb563da425cee1c47af0e657ca7e5d6fe96873fd3808557e35502b2 +b27b0366b4c5e9317871fd15bc5fe311df1f238d3ca14cddb683f5fee9923396 +b2836b79ee0b83f9840787e034787138ab241cccb8f349b3d81a2ee835de123a +b2871bbea950acc9fd6dbf46b13f9bfe94726a4d017eec4121fc4405f63c82cc +b28f30a0c487a1e8c2eceb819cd966f21af5c5118b7f03ac59fa8cbf0915b3ff +b297d136cd857263919dab2252d78413aaae4a449dc45f1c4ffea76302946e49 +b29ae16682afee0742675a418855f662ebfce70aeef68ff3c2468bd08e5c415b +b2a2f7a7a4bf71d296e896141998bd169e53fba403f984cbf8e34e5a959b9055 +b2ad0dccd0a7de8f6edc8a1f05535381783b7aa9036e470d74530b5795d948f0 +b2b06be3cad6e504629fb16e749406322aacefa4c2f46b89bdb57f3031fa4400 +b2b1926876f62094be68c35ae28899e1d1d488cf269e9f4f4957d7318bb1f7a1 +b2bb8c9f3ea41a662fbc930a2afc69b60f048e07d7df59ba0954dc6efba522be +b2bc2036305051747e4212df0ad5afbc31c4887c1d7ec1a19a4912146db31ca0 +b2d12fa949ab15218cc7540ed700c61ba0d1a8da473f7e722e6daa9e55e279ed +b2d4a7a3b8f81a4cf0a76e37234c1ae7fd8c5970c99296818cd0e956802904f7 +b2d6d4314272934de992011566394a13ef551c26bffaa988ab4a09d33e923b82 +b2d7ec6501f813a21f749f1d18793f692ba840198590658c39d4a73dabf01c87 +b2dd3b1129d89ea6aa72090a2830effbfc055bede0fc21b6e47db0b1701340b0 +b2e5719164c4211500e1bd286c26123939c98e06f6cd6f86ebc8de9ccfa02d35 +b2eb08ef27504c16d2d989fe7dc4204b4083a769528621ff2fddbf6addfcf733 +b2fcd12be8adf8c33b67fb97f9f948f770a7b0056ce5f0598cda7003c0919188 +b2fcdbf5f7bf6ebf2e31f8a52b2015b1a970835ef50f78bfebb5b686f1297f46 +b2ff81653cb54c09a1853fa75dfc4511bf202fbd3be04c2cbbc9a078cb2115cf +b30969285a0e20f94697c8f9e86c2807b0c0c1073d429cf8d4e8512827a0839b +b30f72ea5919ee37469a3e33eb80dea0dc3b976c549bc24340e1c2d265afa53a +b317d0bc1f36836b6c83724d688a1e95bdc20f9be0ba964a169d7ccea5862029 +b3185beb91dc5adbd48a4831a03a2f1557354b158eca6a07a681ef26cecb43a6 +b31c83b24b4aca9333c047add759f7e0a90040d4104990534956d490940d19f3 +b31cc7eecda3d4959b4de0e685b0a515d74fa87951584bf58dba49af680b1863 +b327ed167925eff9ab19aac76b70d6c966ac8be59ebd184deaccd6d768628c20 +b328dd194128ebaa36200af88cc623fd387d1b68f3d5001a5f45e7926630b9ad +b32c48ec9779810d05b3f3c796c76c25056cd71eeb213abb6c6fba43d8506758 +b32da176c7f1a46594d0566ec878dd12845a29f582e252a9f4be92c38f473f4f +b339fce54e17c775924ee7e228f569494bc917261dc02c36a49a6c332f358e37 +b349e837d48041a1af38c69b3f8721a8c1cfc9b9064a1908ef7533ea0e1c3a29 +b35cabe36684dd86b97c5fc3158915c3f3ef4e38bf8a4fa8a04934fdf591fa69 +b361c682e029490aa0acf199991d977ac6548bd8be9a45ef625384491ee310cb +b362e7788ecce392f934f3c0d10530f8dcd1f3cf4a0791ffb853faa8aa926a89 +b3681a59aeeab7281f34fa1911acf50aa31239e0ee67d0617c9e7fbf7a6e62f9 +b37068e5a654d5e6457e3b3d897a192bdf6a0283eb317483f40d9d43c0fee14d +b373dbebc8ecaf520afdaeef1f80e707dd2a8c688c52384777daec1d89b078ee +b39592c70d3efe54a7116d86b5138406147472036ab32d0d644b9ff14b4740f7 +b39c19666e5bf8863b8887786199abed724805316607554539995fed2a02e61b +b3a331c89db0a56050b2c20062bef6091351f98aa1d15962eeb91125b0c6b6a7 +b3a9e817219afef81a465ddecb496e2b4d2bc8f1b3ecca7cf55ad6ba0568c1c3 +b3af69b85bf9020f4e8e241724fb2226ea6d58429504297485e174c6fe19fe06 +b3b2585fbcda4de7c526a96cc77e42bc98c9827acc8777474c60d32c7e361a26 +b3c13b5718f6d8a89ed041b16fbed0dbfe721801c5db5c14e1705d82617a9d5e +b3cbffdec037fa4fc372c6651d4faca8d4b5523e5f50922c21755065ca68cbe5 +b3cdf59014838ab2320bf942fc886a472c1a893f6b691eeded7e6d4c19304e7c +b3dc31ee0805ac8e04e9aab80cdb615e84db496373856f9f56f2559e57d14604 +b3eafe55637efa550ef2686c3c924689f5a451a6e4350effd220fb7457e306d3 +b3f123e78a951479ddcd643ea3634b9776d278860cdc7a2a4f062aeac9b0fcfc +b40243a762d4f4a5b5aa0bd2395016e7664bcdf17a440506b024d36af0d1e82c +b409e2ae6b89eafa3a58d16fd3371aba3f84a9041165b95ba619f4934ea8e2c7 +b41bb9012cbbc9991d2e48fec6d934627fbfe3f3969cdb25027bd1f0f3672451 +b41bdf063adddc3e08192deb39dda994a612c06bff7c46d15a9b60cccb30dcd9 +b421f94416b8a3a2ef676d3dfb2b11f529b5fd74c5572f0d62c5c83674513a74 +b4282bec4d16d498ab56b9c7885e9b59df8a9f9800b5b5ffac22f706bdfefda5 +b429afa603ff6ca0fffb3f8f007d9f39a3570cc77b12ec88a9ed798f4009f1cd +b43375f888225d0bcd9d327e3abd0cb7790751b1f275df8066b12ae61f6b05fe +b433ea4e5631334de011549fc91e76c1b7d028a0e5b142eee637942b4e29a75e +b4395994babf1bae53176c9b70c26671408b9dc30e344113b203d3801b16a3ff +b43d5a26132b80f9aa3af9f88aac6109c4c1290ea7025b85cf2cda96263a39bd +b43e5fcb320850567f88b34caaa9bd635c17cc30455637332a562f6932f508ed +b441814a98f297c36b8221caef6abc33a7c728a4ce66189f97c714407c858e21 +b4521507de96cefec049f7ffc87724e72fb35bceff015e94b6141b12a2898b5f +b4630a53a8e03a57d9500a3c6e62761b17ac1fa86a22bc5e1a0ca985e6ef365c +b47aa42f7bad16982b0cb062d9551cbea90083a34fccf39a2f976e4be8659684 +b47cb82d3ac5a01100f42a5998a831ced3697558203b62d11fdcf374bb565d7a +b48967c2d2ce0760b24fb5e2c8cf1c04f73ea23b9fb8c5cba4b250c0ce89ad9a +b48c5aea51dc232e28727a112c3131c31fc87a3a523f0653ae178750c90bedb3 +b48fbc17c88c28fd46a8600c4dfa9419c89a089e8e3d3ade8cdae3f25141b0e4 +b4914149b7d67c756689ee019713d252d4636da56113564b57361570238b5589 +b49ce309bbed7e63ce1e253c09705303fd8772f36fbe865a1dff5141e01e3bde +b49fd774ddba9580bf920f182a2558fba0a34ef488c632ebe99be4a88009aa07 +b4a18d1bb7a88a4ea141ef61627bc580ec27b25754479321e6ebe2ff5cb22e07 +b4ad023ae5cffc087a2fd961373ade153570f5ade548ed9bd73e8df397633e58 +b4b3e928c5daf228f7705314f3d2dd5cb9efac2b34c7b3256c108c4617a20af5 +b4b3ffd465cd0d0a8c012a67a7bc042b6cc3582cc77c0e2df7b113fb43a0d910 +b4c705686e7fe424fdfe78b2d7af64c8f21ee4bff321c3d82c75266865ed6bbd +b4d65b50b3b8841d0c61f5613f7def344c67c272c8674a0cb90bd79738316778 +b4d84947d00e98ca1869303ab0aecbd28eeffb0bc132a7f9672377fd16c2e172 +b4d8978f9d84e32229b9dbf37240586cdb5c3b428f82813b609c271209ef348d +b4de0ee6889014860a25212cee96b1c2442d191f00a1d63a096253dd2c1d7590 +b4e1858267071c9b0c2f4366f16f724e8d43bb5381c7f3b1f1dce703548d842c +b4e4bd1a473d806abe4443728a916ef96c3435bc96e64b4462fa94fb64ec6b9f +b4e574e65fa528ea7fd7945e7f214630a499798d8b0f3b2b139c4752c3b486f8 +b4e605fdd48207d0b5b3b37954d421a4ffc4a9eb6ed30012679865678e19549f +b4f74bff5ece77c8eb513384708e41de3e3311918763bf70256d1b67c25df957 +b50a0b5d2b243eb4daabefcbcf58a97d4992a43f6ede4774eae2375d7d7af318 +b50b9deec044dc16eff2b0bee69073230d014c5fcab7d6d257ea134de94a3297 +b50ec5a738103634ffbd990beb0df493c6d93167651b5652340236455e09e35a +b51496adb4e5f07e8bc308fb63f60e6c54e79148d0f693a79140d908c5121dd0 +b51640c35fd32ae19f40738555e9fcfaa3c6a920404cca9a12304f925fe51da3 +b522cef5c7329e7677933d9aa24ba31ec14ffd2b977666192a66e3c688f63550 +b52366e9dc3325043d5e9fd51b8e5d144cb31e2570796fb50c937a6eb6996615 +b524c5b3091d6e55d61a6e98eaf64ab1906357c76ecce48864fa9607b0b511a3 +b52b673fe2eba96f7ca3ca6c0111a4f79c3f62fc6d8e2a0be862a4db096cd19f +b52e8016b699cf15396ca22a45887ef8b442c47af368b21fa8a2e93a6e97bf67 +b52eb28cb5cfc2657a85b9149f5fc28cac7af87a25784294cb69045a831c6687 +b532feaf49cc28dcda6f4bbfb78984812b371604e24657e1914b12625a992105 +b5351f77d8b6ae2b7df2b17e70a314e3ee4d3cd01edc1b3aab65fd99471226d3 +b536fe4025e366d9995d96be7ba5304149747cf4db92c848975bbd6eb4473370 +b53d45a09bed11116e31b07d85cc1b3d8062c36ffd63d87b8a20c4964a1ecf9e +b5418e5da436afe7a5b3efe53d70a4c35e74b0a471646c6c905e2c0137e0e1ba +b542b27b82ed3424992fb3c0bf5ac8699e84651a693bdea1a3300b084d51a9de +b55556d2c5b18e0265eba0b168536a84b76ee3694e6ed8ffa1b1e4e3affc312d +b5564d96de50d02e057c7d11ee02edf8d1f5a7db1f50fddf74a7730b94757dbb +b557afa24661a3b85324b2687844f69a3c781364a59e02f7e84da9f27a5d7842 +b5596d7142d80d49961ba9ee7a269eb89633cf815252f4be62040a637769d42f +b55a473586bde7ca668a6050236f5e35f290ce3f59f766f22ca264f9c3c7fd1d +b55d5bb5a3d84f4edaae7aa3e33a1f03dcbffef58c1338ff73f292861d77bdf4 +b5626ff0c956e850dbf0297d15864588d52930264880bedd66e3522fb15c7223 +b56581760e7055bdf5f7cd8a5d0e9629de47005718d5185182a8fa8542bf73e6 +b56ca5a9918ea7907e2d981e7ab45865eb867fdf67382dd8ced5735692b0bc03 +b58694ec7463696cb3caeb610f3d21f99bf303fca5c04da1fc48e8a33fc6ee1a +b588224c1a294af6469c1f88bb2d232240c30c27e7dbce9a05a14eee1259c663 +b58dab604072689933055ded08b5779cf47e891902657e2afc310308865dc46c +b58f8e33c35e59224a6674026c8f3931f16e292433b8b2489ad2acd71730e362 +b5919d497144af7dc91313fef93e058d6c8c150591fb471af6ee9f8451469c07 +b592e4dd201c360d8f3b6d9fa10c2b0c4873d82158ce3905fd474f45b0ee4fe0 +b59410bc39bdf56e0dbda48125b4c8f6413b63f9d018f8044fd771528e4ecf3e +b5965c2dd9d7e067bb185bf2c60c68a4c6e6845e4999cabefc0a578202229d04 +b5983b39220e9a826419d5f91f3c49ec620cb5dbfb48cbc345c585657b992f8f +b59dc88f18dd5d6ebf0d7235b7f7499a482aec6f9a1500d6b390f6f71064ae3b +b5a2481875cf58fc1ffc06a76c797ef505cc26ed44d233d1d1dcbe748b851580 +b5a4ba0ce0215d3f21f1c994cfeb0a6e06a559126b45bb4b16d4afeb7d65c736 +b5a862e44da3f495d5564b4c419d80b8fe06c81da8ec02dec4bbea7ce6ba0c06 +b5adef97b0cf965c100ad8c31678d8fbbe17151d80d40ec45635fcd1ad79891d +b5bba56b56e73762bb4f2e87acf071f75222ac7fd7325b7491239f4f1d32fd8c +b5d31316e6476d296d66a3a0577b6614bdce883e1b3a7a416b049f3ec67ec1a0 +b5d8749489704d7a021065f11fc1bfd63d3ea92211ec9f63f6b68ce25ab217f9 +b5d9516054f7f93174fc95473b242e084c609b63c81aa7ca516b68c5ded16b30 +b5dd88b4a868445ac5711e7ede11e44d97daf5a5aad7aff717840721c7f11932 +b5dfda921ecaa970343107018cc5a117ef108512a86a8e6b83d3d62a1b816d07 +b5e55ab8466bb83eb959381ab4272157c8b901d63c277bf7285d4088f500b040 +b5ebd64d669787d2387dbfb82857fcbda1845d9ba2fd468561ba716ac37828c7 +b5efaba4a474a3cc82fa025225d8ccfce2bdf82122bcb51f8f02ee5e2a6dd2e3 +b6024abe7f1601c67de29cb7696dd3ae74ab03ceccb42d0034cf08a6c5f4ea92 +b612c5b08a510ab3d485e6ab060ef46a4d1ac107f2812a6ec5d23b8ef9412bb1 +b6161a27a9acdab3cb7f11f99d76ee312d58f202f2644612d68ad6ef88e850ca +b623b24c155489091cda9504deb8eac1ed80d73fc3358f5b55f233fc6f36a0f7 +b623c4b1d4771f0ca0f7566663dc38efef0b5b22ca70a7b6925dfc423b3c72a9 +b62a94ab1da34dbf15fe97902ca6350afc34de964102a47e53e09c5ae92f7f65 +b62c06cc82fe41d142194c4d851127d028849d58637fa7b6084219d0573586ba +b6325770b6492bac7399199509a603d3fd34365a64f532b57de47f697d1317ff +b6333167365ef794112be238edaf3aa31f9e401b93e57d5afb7ab9b5bba5a9e2 +b636ea49ae04aebe384bce877590e616fe98ca4da42cd14fdd7d8cb1d8e48db8 +b63ad6b2c8b7e4eba9fbc7da32c7aa8dcb564108389d391c191f0d0f18b7fb4d +b642c0e422c4824bfa4be715fbc54f1935181c43b85f955b44107832fde79713 +b643d0beca0c5fe6481d0f30c7accb537885fdb9351a3c5cf3b6046031d6db2a +b64f4bb80397055e34e834368c934b640a9f2422863bff9f30e98eb0c36a473e +b655bcadcd032b1429259dab9e548189fd1adac54c8519ce749b2f041bb50004 +b65694ba4e1cc1d2a3925cdcca5fe466ba81d589246c4de56c3677bb0c220b9d +b656dc330e0589ed94627906e2e6625c29bd7cfb008199752c2dc9abb2af72f9 +b65c85b483a11499c13ac17cda2f88a5afa79c2d37ebe445d81a1165cff43ce2 +b65e191c6b129da4366ed806819ca4818d8d07c5b3410dc1db13d6ad91a932cc +b65fb815b4053ca560095f30df96df42998e5c1aeed3077689834f50597ee3bf +b663411c4a234e45903598130f9d38fb1999b8cc4116cea781e316914ab20ff8 +b68c3277564af75f3ef165f8961b7e0c568c92f55c07c29fd9177285c1130e65 +b68fdfd77c3ed85b67a4756c5a668c56b10cb0141aa50a206b1181ff87c2f447 +b699c6549e283567364b4f79d29e464d9ac3ec099ab6b63303d0ef6fa9a31841 +b69f7d5c5cc692f9304998ec4cb9811dd83ef0140d3490c6f55d0be31b58fdc4 +b6a397f023d7f53d1be23a5d10c3a153415334be60fbe0896b9ff1eac8055d22 +b6a3e3992ac0fac9a87424ccbad82d8f903ff1dc030a3bc21e9977bc2d8cc81d +b6a8d129c9a43dba453d4fae041f404139edec0ad4339ceec5c1a039c0d0b748 +b6abcd6d2321f81be3a3c60bd415cbbad80b49b0831721d8959c311d1e57fd5e +b6bbec15dc86b3522c80d1fbd189dbf9e533fb11f6ca959b9e40c58bdd2b46c8 +b6c98240f4ce7b95ba3fad096e3e1d96933f0de522b196a8e9186340858f68ea +b6cbfb62480c513d855ef2f200ad73f9a4e19cb0da1dfa4321af146aa3d253d7 +b6cc41655d299d899485ecf11ac8d02d04faf22663abe4e728ff4015aca13b00 +b6d1916e10c90de55cda2b870a3144cc16f8c7d9bd59e52538ccf716b53902d8 +b6d4c1531cd30b5cd1f2c382f4a4c4db7ca9033eb76f795b61fbe36b1c53fa7f +b6df802151e78569127b992a8a404807723193f7767d48fe5cdda6c1444136d4 +b6e06ae75b2a5f155d393a95854d7a173f2e2cccdfe24d4ef216f7df56b01bd1 +b6e840c8fe904be8b108dcb18148d38ef26618fc2464d2119237e6bf586b89e8 +b706ced1a8330f4f595bb6da20eb2fd4a39ec8c9f61bca706bffd5975542ed39 +b70956ab126c9918bcfde37b0e2548f9bb404300c67d9f2e67cf297d3c5f2d18 +b70a09aec60be3b328d453f286faf1a30bfd22161bf252e5fc1e87f3a0e36422 +b70ab83480335ad935b82e73c612be8d0d9bedeb0fe76511fcfa0de687d303c5 +b710150831c7553bec47e62fa3dbbb3979903d9679198087a46479e24e73b0f8 +b710930e9fecea8073509ac645c29c783011a02c8041c6dbb1bf0262a58b2da5 +b717f5b6778874da3028267c944bd0f5e41cdbf52a8821ccb1b39ddea031b7d6 +b72202dee5fb48f9f9070e736370112ff43587af7e69c8e26e9e4368e17f2dab +b728330d9f1929262a1bb3b36e15360b90e0d1fdf95f924d8a1fe03bbca28d12 +b72d7f1ae8bf7dff31c8002dc411491f4bc344593dbdff2e889155d0d02f7237 +b734b5b1a63a485b934fca64a993143c2c0a9a9812e973d1ae36db8736ed89d3 +b735c0960172adfd89307f209a16f3a702ab4fca5e58d6030e56d88fe8eab943 +b73b34878e1346a99dd35123f585df9ca6b5bd317826ff4ebd05fb850bbf8cc3 +b73f9349ba692b893f2e9971571f7288252bead44af1f4dc61c51fe517e6c723 +b74296deb8fdfb5c07ff2185815a0d214ae19a756c09e378db8e7222826899ba +b7583dafad0b04928f73d2a737c6f128d3412069662516a5eb4a78085845e400 +b75e156289444f0946fee7901bd4f201f7bfdc8bb01233b2081ca25cc2e4c569 +b772b72f9d30cb3d960942fb24d84ea8102c9204eebc95787c8826205d5d0a25 +b77b8441d39d0c0033641877b0d180bf3f293c1e079a40ba92b9b2ae03cee310 +b77c76b90a3e04793d79f493c8791c35ec39ea7d7ce3ecd60875ec80e0eec9f8 +b789222aa6f4d6454585b0d4c990a25a281c777af410a5d36a10e6a35f50a0a6 +b78b435e98f9ad2b05436616527c7e51b9a72872174472667b3471768454882d +b7940b49c9433afbe92c1ca0a555c0ca75650d9f40b010859d7731a59487dd89 +b795fc2938514972c4c0e7c3140fd25b4955da89d71ecd89134e155ca0355148 +b79ce3889c835da38059f64a07f8f4d42a0f9db40980fb56b0acd2fd204a689d +b79f73a41b322838f0d72901f37d4f08521246eb9d0a1a734e7a27ebfb41a90b +b7b72b71e0c0cce09bdb95aee9b705e861215b3735f361064b06e97f8981871e +b7b9d286e03081fbd3eebd7b9cc81424cbd2f3b3f86dca96f1687d1bfa14e55c +b7bfb961b12ba745fd1135f7300b4a18c020b8e8e35a1dedaaf3fd15f45ca736 +b7c13dc3c51c0522a5c84c1b784576d0fd63fc7debd9e14e8a7e5d0ba4aefe0c +b7cd71effdef3f3fc42115379a59148bbb5ab2c3e5c31b42c0d9d77a1e8bd9f3 +b7cfb80399dc09e25ee1b3905253deda8d98455b60d5ea3162a21766d2180226 +b7d391dd456303b1a2323c4ed5c9be4d74b60557e4d9cd192aecf7647132bee9 +b7d5e58c02f3a3f9cda7815aa3c38a4cf0eb222cb3746997147a8ed14fe62356 +b7de5a09c2bd3db80534615dd92aeb7d3fe5781bb3b40074c03fdcd6062589fe +b7e734e67a66b8a61893ab9717064e3a778355a49f84943f3f2b0f68ca0d7a4c +b7ec678e2bec400df3f2264b3b56482d789bbf879815d85f7034584078d9c335 +b7f47981af597e216e35380f242ebd0d2f575c34a8546e13b8949ced3bf5c264 +b7fcc0156199721e8f27fd7e2eed19db455adee226e42cf38c85fd0a57289367 +b7fead881d11f43f79f7f6609452c1a4d3be5316fd56422f6660e1ff57e496ea +b8018d30c4b165897fbf0e756bb6d8570207daaba314a02ec3bb42f9596211da +b8070263556177dade15ead3ce4bb4166af01342fb16cb1c6759c30121d36dcf +b80a3db83273be1ff40ae078130b6b7026f682537d2325446e8855a2879167f2 +b81f0ad33c2e11b832127d05c0650889b220fa3e11390ae4ce9b3d42227676a5 +b825c923cd9eb6e932a095551bd1cb8b32a4525acc6e90c21aa975ee413c9ff4 +b8278d0494a06e689851bb0c3b5c86755c94c4879a0b3563d79b515102db1d87 +b82838134bb5cb4efbaebb53bbd0f928ab810d5cda984e4c057a26a75fe0010f +b82a98b73fb121d206164a1b2a6a271f7bc5220cf683ae9bfd7ef3edeec965a1 +b82aaee436925d6f64e543e0039111b17b51806b0357d2e8e6cb039753877bd9 +b830bdb8182b9ef8bb088e51823080fdd24380e974fc2248f68cbcb6f4aed8b7 +b8470e0a77696987acbe8f21920c5a7baf2d0e1aecafe911dad00ae119be7109 +b84e875c082b730440541faabdf0fd7af120939c648e4db04cfbd78729f2b3a2 +b8605b396195bee8d3b8664d06dbaa7efb37cdaaec4df48adea60b35edc9b3fe +b860cd964429f220b006044a58cedcff7b892313f6f79d3d9a6e7fc4cc5f17dd +b8615d7661464ff324c41f336e3e6ab56fd1aa7aa44ff9adf3cdc00f85771f6b +b865bff32f149308b5bb75000a703851b70d6d4c92a1ce352c7b50c78c5c2ba5 +b87283c499cd5ff7dcf6bbac23f0cb32b1522d2cc8e6db4665ee424a2798c271 +b887a1844648455b718ad6a5f929d01de9c226e46e55c45dc3f82dacf58a18e5 +b88ea143aaf475ab0dd9318b2ff914bec7515641f9ddfcbf81456719cf3043fb +b895575311f3f9b09717ccf79395c51799924f1d60a6e53634e1a980619d1da9 +b89bceb3b9dee74719b3cc67949c4cc7dface6dc26bb2133358f3bd93635feff +b8a2e80c3fa4ae47fcdad28c46123f33276e44232d4256d2aed7509fa51bee17 +b8af75168706075dea9c8acdf2dedf2de45e46dbb375a467a247d0528fb73599 +b8b443e7230e652918012eaac8ff9add289fa4b185ef28f0476790aac284e1cb +b8c3ed246a80591c94e2d079f3f2204f5893f9fdf458cb2d7237463bd6b8a623 +b8c5f16c9fd21d1fd73ed40036c98c5e83d356e2d8e4d33a75b5672823bccad3 +b8d08da38c8e753b3f315bdab298888e4ec2e7bbb4471933ec1d1fb0ae49d399 +b8d4d880ca7e0e47795b5f23a887ddbb0d7ccd1e5dc0fc91a1dcb5379ac27586 +b8d624c80f57ba44b4d8224c6180cff8bbd2222a1655d3ec96b47feff5a5eaeb +b8df4a9456956f3ba0111cce24a37a6224dc06aea97adba9a074213b48b5bb1b +b8dff0477d895cd088ad2be3fdcdbec5b3fa433eb5a94030b99e50f1a5cc6ad6 +b8e14e076e1d9f51d8b127f36196f8af7034aaa476d13319ef7aa8a3511ace23 +b8e7ae9c43286f50ab10b32fd3d3cfde46b5c1e7be8958be325b9b6cbd28d08c +b8ef30114c6a8b050af3a9a670d8d12365d25946a2316203d6fabd86a85b5b0e +b8f37be6b019de1f903a28fb7799bdfe6ca9b392a9f738bd1d649ab95f655506 +b8f54e5b7d00f1afea9ccbc5b28ff3707a5a18f3a6d09398fccac1eb66ea582c +b8f96e6843a1867ef56a62389364c88dd11fd7a09f44170cc72458841ee8cfb4 +b8fb965a9e77c860232d3255f1e59ca845f9b5bd55351c343647fe95fa9314d4 +b9011f6cfdeb19e0e352136fdb1234c5f94ad6f3e2ab889f17eb6dbce8c5730b +b9022efdec95d143cdd39870f00ea1a318f0ae3a5cc0c8a47914cef968511ecd +b904dd521b70ee3a2d8bafa741106fcd309b9f6bc47c89c4eb5244169db01a8e +b909cb959eca886beef2c94d193004bf85486480a56637a2897db1c02cb1db1e +b90a2e8c188da72506224b404a8ffff0125bc5ce33166432591eaf556953748a +b90cafd21f73126c305f624dca599827c26b5df70f2a9c8b849110607175b18e +b90f0fb47dcb21cf105dda2e7295f47ae5f6acbbb2ab6751736edd04bed7df93 +b90f8a982fc1d2503daf63dacd35bfc714b22106590a11549fe4d74e85989cfe +b92a327d365d610f72b20bb27845e9390ad53e1066edaaf2bfa673ae274b12eb +b93092c25fc95895189b1ecc8f13fc99ebcb54911b361a093205edf3ec83cf9b +b930c6ceddb6ab9946cc60ccab66842b984468004fd68e404b9f8bd870cb1b84 +b93c720aa5467e92aa9edabe41b46a611dc96127343f8c13c876e6b4057da52f +b93f3ca6d04baa233fb9227923ff93beabbf9831214e8a4e24a6cdc996e719e2 +b946b4f853a943566fd25da6d965723eaa393b997f116a6d10d2df9c6cfea66e +b94e6265464d9be80a0fcb31446bf4442573b66ed41a0a420b1fa705d089d21e +b952b6a49e85ead3a34b331ef07b25eab62c5c4e1985b1b1e2e79e49a188d900 +b95a4966832ad096c0c9c02ff1812ebe191b9f8dfbae995e60de728b873737fa +b9618569184fcfc37fa5726a86d17591be79d7be356338e0207592bfc9a647a5 +b963cca41748f1805f52ba3a904e735f1b780529c4124c340a424c3df5e1346b +b967b949349f220d26451869ebbe4116ce64a419d62885baed877a979d22b6cd +b979115179c8d7742b4a61c6a66576ae2be2e6a63799d42352f1ae5844ab77dc +b97a2803770f4bbf508b13ecfd56455d32c8444f534a5e8befecb160cd916d7a +b98319ed4e8733d8da2868d70945e10aa0f0a8a29968a7a68f57ce53561c682e +b98d66d03de8dcc568e26060681fd18808db448f13cf91d3e9327a7485036d6b +b99189abab0f10c82bc2ffc0650ca085b7210a03506dc56f824dc5c2b20d4bc5 +b9983117d1992d0635f35fe81a650f7db5484b4d07d706abdd01e14fce32730a +b9a6db2c00fa08bcc921cf8561130022d02b3c61e343a1625a81d65c92cc86d8 +b9abfcacaa782b71fe24eb945df308eaf6cc0cb755a77856bef7a59ace16702d +b9c2bfe122ad75efa4e7f14bb983e6f7a6e489d5facc72721ca9c2de758713d2 +b9dce12865e44b2cc19fa6236593cbb48d70149fc2fbe7c01d7846367d30cd7e +b9dec7a938281c1dc3e0d25838bfdf65856369917ef16d5a17b447c609e1517e +b9dfae18b445c7e16c5e1db0fae4bacbef7c5adb69bbbf95b4d0ec2f4bb31be5 +b9f7fdb5b1a53ce2a949a495fe5b91a0b413f96aa6126552ccbcd53958f962cd +ba0604917bf3b9f0169d0b4a2edee9681932e9ef343af71e078711555a57a53f +ba172989eb7c823f72ff8e640e519945aad03f094dc5eef40b2e8d3c1d02dd6b +ba19acabb81652bdc5c38dc65e67534af7ffdf579bce77b9f16a21ab18ed7029 +ba1d0008f3298c9a529fa72190283b04e1cacd7f2aafeeb02d11c58efcfd67d8 +ba1da615185ea49c60937b7e64da9152fb5141c47b6a5969cd9d80679c294409 +ba205b242cda799f3eae71910331bc9521ae4572b63728e7a1e85111eaa6b560 +ba295f8bf687c9ee9e34d1be546e118cc61d41f3829beaf3350a7352374f2b53 +ba3dda8847fa1c5b2580365af27d42e5c2f425b9d57972aeeda9883b8420c9e1 +ba482207dbe2b217dc23d28197611fca0d83d166855f7259f8eb7dd48a1e4e57 +ba4bd9c9bfa6ca72b86b212ae78f3da0b4714f82da3db83849dbde77c67c07af +ba537ac477a66fd8a11f116a9cdf3eb8032d6cc3831a2277352798ae3a188fcb +ba595bbce71f08dcd7ac0b7beebb59ab3b4091aa50a1b00f10fdf8b70c569b39 +ba5c1a25f161412d7bd5d5c09c7111ec690a1c159093e83e9e052025ccc24afd +ba61a6caed94d9b539f086433c17a5fb3ee74932b657df1eedbe930c856d4255 +ba6e4e20669c82641ad0bb685e7cb657f690cb6c4e3f4647836542a76013a1d9 +ba876258f30b98ec3111bba6446a0b84967a1e68635f251b082cce4807c1784f +ba8c2e2f0eb621053311dbf1e09fa1a8be1ec64a600d8f6c883618ac0d744e87 +ba99b5bc4f77d41722772bec485db21e9966114531004c20d67791c60d9c75c1 +ba9aabe13028d3850b0c42f8e4f7949733e96942b283a72d53140ab189f2da85 +ba9c1d4307722d16c4b4c6e01ac8c2bcdfef4cee8002db0753d0e8db6d46f7d5 +baa87bfbca84d5e72cc479819f56f27a8960ae9ea0deccdaec23180b73542d5e +baaa6604fb4705739eaee1e962b176ebb3c96995ee245747db8ae7aaa15a52be +bab0f399111ca2186e1a326a41e1e5e79013acca6eff8a5d4bbfd8798ec3bd5d +bac559ef891b39bdebfad4a62681010aecbe5efc424ecb27d8e52070f84c5cb2 +baca686da5f7ad71044b235ab5f93aec8367ae3980874e9b3d4d6d27d6c622c2 +bacb25d0a7b08ac5e9cd17f238dacecfd5f371235cea64526dc46b63d47e2aec +bad6173a95c9288cd84601266ce420ddc4df5dd9a26a7d37444cc3703fb5ccc6 +bada558bde83bc4da875072e519c8544611df586296ad0b793d702872d2ec66d +badc155162d0cb4058d10f5ac6c5be70f08b6ea01a8db4af8b3a891cee1f4f31 +badeae0dbae8662147a007f9995d3b2fb5fff79e7a46804bf927480fede05b70 +badf1848c90123c9cfbab349a3f482bbb2223e73a292b2aa74d007da11f65b9a +bae379ff00c6b17aa91d5aa1d2604949a1bff87e8a94663a71f08729eb6f0e09 +bae93ae43cd6a20b037a4df22f89fa5e9b9fd129126af4dc8fe695b4fb0c206d +baed7622ce42cc9b16adfa6d24801f05180f7c747f1b3ae1de8b1f4dfd974e72 +baf543f87857a5d3d5f1c9c07df1eaf4f19fb70522a3b83ade108dceb838c94f +baf880aaa994aed203c50fbc4f76410e034478933116c87808199003db4653d9 +bb01523222666bd0fb737bc69336b12d1bfa08732c000d46376a85c243872988 +bb05985ac47e9d3f5beb30c3d387328f242264159109651550c1434a22fb0f0b +bb05c3321d121ad39df1d132b1366893ddb2db5274748baffb72a5d36b029356 +bb0d66c2c7fa456108f8b29ca3cd39360a0d04f9b9cf610aab04646a3e671874 +bb16899bc07b7bd9cc2048ad606c79c123e44508a555e9feb71a0ec71f966894 +bb2b7d1d38d405e25b783fd5c99b7bc185e28c507891d4cfb9cf9af4f532ecae +bb44f54b7bf09c38160d1f647750cbed3d72e0f5e13a21ea1baeec04db13e40b +bb56ccbb563e9d67205d47f5fedfd17784daee1031f2d5af5d61072f1b734881 +bb61344157a2c9f88896220e8893ab97ea2df598db58929249ba031ee346af57 +bb6bc2074ee51b086a6ff02b30d02fe3395b522aac03608cf8d4ac19abd2729d +bb76e4a8d4420f42563ead57e16d830b8c4a8c99a967883e39542d997b21e5c6 +bb7c009dbb5c234caa8f83170fe6184764d41400cb92c23c65235dd951de987f +bb83bc1e33280cddc3c5b8cfdc368f67bedd2b6edb4aa53323714bc70a4407b7 +bb83e476d2f1a6199a3f8b610caecaddc4fdbf99a1091d900ab9a0848493889f +bb91c6ad311d26bbed7aa8aad0aa90df11889cb5593c87bb6a2285ba88feaa8f +bb93e635173c40d8105d5bf3c710f69074c7b0731a90d9cf97d9eaf5fe072bbc +bb94e29b6e578bd46b02e66bf3b49743287f205c51982efaf192ff2a25ee0937 +bb95d85c831e6f14e07da384a7d22a1ba55a3a1643d1621faca2659a64528079 +bba42d1aded7dc8a226ae11b5061d3f1611f2233e995a5557615a3cc472f790a +bba43f6a41ab21bbdc61e4577d3dc8972c28aa89527832e45bfb26f0fb5440b5 +bbc1500ee416a90c4b8ce254a977d0ea0cfe585ec853c362a9485c8b1d2e4e90 +bbc2ff2c1c67e6bea96463f44b395cc6ddb4181ad6d81097fb85373dcfbb2904 +bbdaaf303391dc46957566e2a683eab6285241fe71a25aafe4bceb0a0020cbc3 +bbdb2c2e837ca7188c214f4476d01a6101806e1d53ab1fdf7dbc7bb870226d45 +bbddbe3bb077ec707f9a45e564c1c50b6b1c15b48f63b7e1f3c535312672c308 +bbe02e1200e2a871f16080d6de53dbc0aca4a73132e38079bade82c2d615172b +bbe5d0fd11205787d98ed8a1fc0579403acf1c19d228d602d6b58208a6025a97 +bbed75ab2b988407308bf8171e996100befc0295a780fe9f64da8d845934fc6b +bbf74fa3e504cd9eb2fe416d58943de16430f046df505b840913f9464a821dc5 +bbfcbc1e79c97ff661389e660e7ea00cf516ad7b9817ed40dda44f18d5236d83 +bc04cf51e2263925b5c6b6562379d77975a9cfda33ce01fdb4459b5fa36ba5b0 +bc0acb0993e95f4aef0fd95aa73a561fc8ff8041051ab9be2e1f90367d9ae166 +bc10ea43381942b6642755d2c4611703f2f738b97915027d051be3238a661b83 +bc15b34ea36e124614fc37abd37cbcf0cef2f6ef66a55a73e56c22c95ca7b29e +bc1ba99982ee64d19edaeb92d153b94fa3ea64f8fe6674e52760574d711c3bed +bc2abfc668e7c4a2989eb672a162ba97657e0560ba960fe3c01bce13bc990e8c +bc3292e5ae03554854a68f2afe80c2205a3875bcd766b20764d1d29ce6c9d79e +bc33ae8457e6105f67a465b835192b94df7bc136564ad646d0ae46447b28583e +bc504cb276daf4abef1269e4ddf003bbae4fcb73ac5413708a62f0bff23c698d +bc575873a2649a4f47c5b6bd7f280271ac59748c24e2bef0a8345c59a6500e69 +bc5b19871152dd2bbafca4fb505b4649bf93b65276124925326a6faacbd18fc1 +bc5f4d59baabfef6b9ee25956d043669365653505a23d67e8a057bc4e34e819d +bc7aad34bd6b1d5bd6ea64cf46cf79394e15b7952441fdbd17d5e12c975bd661 +bc7e6e6b157d938df4ff019e2eded0d91beee87bd77391fcfe43f554926db8ee +bc80d7df7599923ade141b9fb4d16a35fa19ea5f29008c8681c6d8458cbf05d2 +bc8db92eb6a2065f5a7709c72bce63fa0dd91e060216ab8ea9cd5e59f8060ce0 +bca3e64142c73ee0addbd2cdf18843520cafc5871e98405cb1ef28b8866aeb80 +bcb0e5019bfe65f958e22c9268d5732fc65933fd3d9ca1daee578c929ad5919a +bcc530cc03af35385b3b828400348fe8d681926681831da3a16312be388a4f10 +bcc56f48e2dba0c6acd65d7ca58a9cc0cf74f8eb5f9591f652b2428e3a1bf9ec +bcd5513c0fe26e384bc3c56ca005e29effb654e65195e1aae9be14586c7fbef1 +bcec5806a0105838819daabbac1d98b8381a5fa2a54849442fae02e0bc59b53c +bcf8ddc59c3395e03f29db19b8a9b009cf93efe5b35b09a597a12adb767e211c +bcfe77d466ac31a629321bb2b4ce83bb44c2bd3f292e33905a36adb09daceec7 +bd02a3c972dcc193cb3853ae36a1e177c49c91ba1a5f2f6851e4383918d2b1f8 +bd0894c3dc516640d0ab34821dc6e09a67b0850027920c2dfaaa4c88bd106f05 +bd09927e5524105d04aeacf5788dddfb75aeb4ec8eb15d89ed5feb2032d85c04 +bd0dc609e8fa6a4b45d82e42d6d8095409688573bc341dfff7c6acd7384a84bd +bd1043a072a1494f12902ffabfe00a8f6c18a040eacc7ba93258c43d67c88faf +bd2cc857e96a84d1601917fef2c72215aa3ee5d57c1052de168979f7c44856fe +bd3449d2a4953bf95ac0d1498de2a2fca5a09eda2bb064c4013455fbc1ab04c3 +bd3c35257c0cd601c515b6cca04f4fd7b6b7be476a6b0d244f3aef27531d1ea8 +bd3fb2c0a37da551866ed9af0ec6e1b83a8522631b00a11eae091fa9b79508c8 +bd41d0762c11445da824aaf0bc47b75936eca85e90d31557e07a578c9f6ef794 +bd4fcfde4b9684b675e9de6a3426b4db9502249183e89bae03a5df3223c4ceae +bd51c94e68f392e1a0cf40a3f98335d4c1a581614db1aeef203f7c9123ffb436 +bd5a5aa8146fb1570f4d50a887b07046f6955b21ad8f5a5b945044c98d99cd8a +bd60cfe1252cfe32b71fd51fdd8bb4e6238709580e2e22ee49a9daa4d9bb10c4 +bd6498934a37d930d2e93d8579f459752d41c92cdb024e35a7e4f13ee4cce006 +bd70ac3875b8309563d009a713397b8f0adc8160c38127dddfb905bd11418cb0 +bd785a65bb3a56ce45d7d94ad8ca2b2ceda88557772ba6df5a354826745c9ae8 +bd7d1e7c1304ac80967e5c856edc9f1e31b96b8d7034594360e6f3edd02ff5ae +bd85e6e0076caf5b69cd10c9632db87caa5ca609a94919ab6b30af248b7e876c +bd8841df4c0595a9e4e64ac5995fb50e2c6202a0ad1639d2fb796a3efeb10c6d +bd8ee5c2521d824fbcef1106169014c120b8694591e3bac0988236fe0075ba5a +bd93a02f219ef2569c7541ee5baefafc983a7b5b293c5177a21434e5a2168ac8 +bd98635999e6f2cd3f57916367510a077d69eaa4137fce7949ba17f8e4f89d8f +bd9e0f4fd94548ebee588ac4c5b62c8e0e29acb7c3779d4baec7f8b866c4f36c +bda2c2ee18dca25e1a5883b619585653c83f6335cb88421cde26be19298bd0eb +bdae1495721c53f4c6c4bed5c3179f63bfcad4374c8cc73d327ff0e4aea6f635 +bdb256b43f965a875d88ed33b61f3e657ef6fa253c99d58d9693ae6cfb00a564 +bdb897232474ffe0e682d39f25aec0b65082101ebc796f6a1315ba6275fa63c1 +bdb97cb9cc416b6808b68e322201a3bd8cf87864ffe33b043a2b6dc5b900d62b +bdbc7e01ca9486d2e1576862c3d8762a45f9bd33932b209937af0ff27c56cd5c +bdd187018cb62d3a90941db0b2e155af0f4add42dc220818390e15c413e7de4b +bdd5af9e6e47466dee8641805eecfc3b6da28a3d7798d4b98a628cff24c15bd0 +bde43f762113e77ecb522c21a4e54682fb4127cc0bbd53a21c2116f9a0388814 +bde9c0f4e2610141852952a42c25cd07dd5153ba74b44ebe323cfe3ad4b79589 +bdef4426fd357fa88e2842736711970f9b85d59e1c79faecd6d675b9ba0f0820 +bdfa2d18479215fc40876b4adfcc178123ba0dc7d33c7fbe78fe51b25aac49bb +bdff0d46472b7e21f71fc2f879a687db13984ca12176d6aa9fd2a84b52255f19 +be005ed68e141a2b69ce81d9632267c450e4a2ac8266be8f424fccba4bd6994a +be02175bcefaa92168fb0502aca8b116bd982d42e63160e383f8b2a240214ba2 +be272529727ad5facbf5ee39212aff865fe6347e14c3e651980a2368959fc0af +be2d93c2095258900306703ffcc6dcd460e8f774a10b1319d229d6b3c56e64f9 +be32d521051d06645a3ff563f7c1a28df7d3373be3706ce0553788cef0be64c2 +be5feab18cc219d6c3a7fe9e33e86ac4c6d8924f900cef675de5b9165e5396dd +be6d9e56592348560d20c94207f0acfef3b88095a661963bd97da5f17e235cde +be847daf0c03ff776ba3b523de0e1dd62be330d7c35a6584f764564424e1c0d5 +be88ece8d892857291f32c3b836fbd87a3183a829d20c8ef307fc5b7db42189b +be8cc60082f3d07a902b59db9ba6aab6cdd279f0725da387647a62642cd23829 +be8ffd8c48ea29e4df537cf7068695a54db2c2c89e3f49722851f7290059bfc8 +be9e1ef9cbeb1e5b69545c50ed011dc5237b92de26f84ce6786846cb53ec2ca6 +beb0308cd1e2be0191607373ae3794864b44126ae5ba4466dd7c6b0c071502f0 +beb6b0d1314af5c03b8ef7528e353a2e0171b0112959472c6a2e093b68f2c250 +bec46317c0cfe01dd007e8a27bf64439c5ca2ec8064b80b8194e0532511490c7 +bec74405e36ff63fbad4830ad89c47e710ab664ac21037acef4d08b1a40eb11c +bed0152995df4a62878e7bb3c59c8f564d0866436bcdc0a87a2abf9d73517926 +bed46ee65124c8fa3e53bf1df0b8b03d857947c7b59dfbfc0858feb8d26a20b4 +bee17fac582bc724bc0762837be9a2d56f7a6e21d5890c225ca19ef954d05dc8 +beea46c30a14b3ca82bbf7a9317a5e8f444272c8118ac8c1de7b794b91240053 +beea68b789439db718c9adbac5af942848fa0a8a1c0774fee354cc14c5d26d28 +bef6fa2915b27094125018eea5cdcd043e618102babe3a8367d898ab4846c8f6 +bf04aa5ec26e4b8fb015cf5abec1f7c6b77f4ef9a7f0f0e8dd6eb6e249dde31a +bf04cd2a71e1d740d4adedc5c5bb59f7fbe57f2148a963d1dc4cfff9a723122f +bf1630622a668fc8684b04a431649475dcce2920db5fa9e24219be8b74f5a23a +bf20ddf618553d14a76356589f8cf1787c7ca090b2e69d3765d172decd9112f0 +bf22a7414734a617bda1c4e48219337aecda7449d8731ad447c70b30d815798b +bf337adfafbe1cabe72972048882f0da56c6e02139fadac7f0e1f52b2432fdb7 +bf339dd0638634b8a4afc848b45997b258b9277d17061939c8b6676c376e48ad +bf38191e283d03d9de86018c76f31cecf4526a1afc8d0af15b5d892d3c46e4e5 +bf39d9e7491f874dc28e5c3c7aae37937062d888df3ca577203f563769888fe5 +bf471da5333f281ac6a8a9e8281b293411711e6113d42975e2b5cb40e8a481ed +bf4b92694008e5e954e703715e52861efd91d32f8b2964336649eb466ad9bf36 +bf519e6d973d8bc2c6cfb59195a63ca6a83adb9ef6cdb1b5e34d580db796d645 +bf6456591839ef4b1f65448554cdcd89709098617624ca71b257c45a6d09872f +bf6ab618c12f9e1525f6e3b702ad460bbf28babd98060ae1ac91f9690c064115 +bf70899865bfb8b3630850c9fe392f585966fba4f2b2639c6d416d7163a36a82 +bf79bffb6ddafb05babf4af8d11232e86f608d251538964cd96df71c1ad3ccba +bf7bb5039b9aa14335b053d255773c830e481cac46bd1e3b1776db8627c11653 +bf7e001309077704756b51209f5f78fd55b8aca6bc8838bc946bcd0c7b5cd6c9 +bf84dc18af096a13fbb3db728e8ae5af47e69318b907086d9a194a2f507f4d1f +bf8f4a0f89beaf545f64a04b90074c7e4a3dba482df3d8c8d9c3bfe1f859ff75 +bf90c7000f360a4d6844ccdb46f55cbba258d0fe44e4029980c6b559562150fd +bfb032b4b3b686899d00c4f1607a507d032b7ae9f6432ac56a459fa51af67ea6 +bfb0c97770e6fbce055baad77e050cf9ebb5345720213afc1963d84a590600c8 +bfb6e1f22ed632ab9de0b523d14abd93d3c221a3f6796c1e02418c33d6accd4c +bfb763221102e182e130368796778fc0be5eb7ca01322b24c2631dc34c90ad13 +bfbb4abd77b78d9e225ca2cc9e78edd1c5af7685d27d2fb1b0370b3e42e4262e +bfc379b212f88c83f22c38cbdc70b8fef9d91c26844423a92d537901044e4464 +bfc461bdbd869d48958885c1f2219998f9311bf52b805d49200ef50e9ca0dcc3 +bfcadf1bbea913e96d18b765e4233329c47e02be97e17dbd87718e1581609d5a +bfd3297a0658baee8083b4bea39aa9c54f685be60e169c4809f80b1fb8f6360d +bfd3bed2f62902612f378a0b80247939d09a6faf3e4d1f674ed93f697461736c +bfda193755905997348506a9503d49df9bc2da7b9386dd027e493380c8ab87ba +bfdedd3a03a682149fb5d97d4b519403631706e83a5e7403cd4efc5a80dcfbd2 +bfe3e39bc0efe8ee75e8116c3d6663d239ea6263235696194f5979942498723a +bfe930021f84c5ac8bb0fb27fca0d78eadb09fccb17aefd707d9dc87a31a2477 +bfea26e2f1f17b6137a7f85e0cbbdabb14834b3f4b01df50f327c3fef36e9b24 +bff1b32326a212c7b894e6c1b431604229ef0e26ccd2c17f64b30b06fd851aa9 +c0023113a5a79ae49779aedd311d7902c0d79ff60628e7e73de9476832b85700 +c005ae0b7cd14e6dc398a35b295a1a1624a7785f76e1af440a7b4d006969a0e9 +c006ef08932a813cd7beb4904971ed702234e3f7598529915393a8bf620c2048 +c0191bb33c1dccca63d1f75d70e9b7808a42b670e15b23b0de917bb45df53866 +c01d2baa56fe1e2311bcaec4f980a360c8526b104b06b14bc7614592c5af4132 +c022fc2974ff6341bda61f0333f82837685c692183cfd13b690945a9614ad841 +c02e91fad2d5b385a689a63b76b43b3ee224534c58678852d52cc87872bddca9 +c0379725872670014187198d083a342aaab1e6c253eb2a903d3116b0b93789a0 +c037ca8f3fff4b12188abda0a5ec12035e7a15306cc58cf2dab94c39bde904cf +c042fed7ad2fa74bccffb9444176d28ddb9f50008edc3e648176620a3d57895d +c057e3412c20931e008269457f488c013fc3eba32ef9ea7189674c77bdd80d91 +c05b80b99c92b2a6665092602410791aeacb1109f7f4ba9833ff87f36bbf8724 +c062aa813b7c2669c670de208fe212070f343c2e6fa285d358c4b5363526fb16 +c06334e37418113e50fb7994e7f571540dfece758ed620e2e6fc4afc28b28157 +c067e5a33981925333c6711eda40e3fa0ce8be6b11b48da8d359eadca46115e5 +c0692723895b4a1eda0b5c82fa8c53dc1f78abcb31cea6eb3874ecdf1f66299f +c07aaa6d04f5e55da7aae9205ad12651a6d4a812bb33251003249ee3ce28b49d +c09216e9b583a2ae677f18152af39063bbd9b1a32d44a244bc3e6e3a3efbc445 +c0984724549da8ff450a345f615e1114a08674298753e364b60e8ba95cd9d9df +c0a0c39300a268efcdeef375616c26a09fbb3bc132d338d20c59c27dd492aa65 +c0b37eb283dad3b49aa8b76fc700ff08de87296f5d5dee223e1490ae5888e693 +c0b7c6d3c75eee3d65472729316ab0a155af883a84d909c5fe3af3f798cb1b9d +c0cbf6fd5b6b6b08e6c3dea0f7211a7c644a59c0860cb4643a24e6d34719e48a +c0cfc210fa245a58bafd58b9453553cc87feaf5cca5a819a72802acce411d6fc +c0dabbd504fd3ebcd41508992a7e78ae1d0556b389eeca8a0c667fcf4f221df7 +c0f0921c67a87320f58aa2ec19fdce362c846b11f560a9fd2fb68c6a0fe13e84 +c0f2aad84dc178513ea7c139f84a7533176a65b225e8b4e63dadd6db46b0da7e +c0f7ee6c3974e1a805ceeccff2f550368b8894891534e7fae80a7a5c1610d61e +c0feed282be7b138abeb68b9b9c8c9388dbed3b5df1b55710661248a805c2e1b +c0ff501a6106ae3f0b90f2907b3f12398691a044d84280e61bbf875b9629f6b7 +c1080e633cdb83f33561a9487def92a5bb942d8aa19690770a3a35ecd865919c +c110e140e61098152fddbd6e808570a3e821aeba2258c15cc9d2ef41ab9d01bc +c1117cdd75f263b9605f988568c17ee9634a737ba133512be459f9c412266d17 +c1123ae7be4eea177d6e11ae7b7cc1b2aa7e67e9e9bbd2837eaf0a53326f9d52 +c124f5f9cd72b966b2f7a88508e5bbb5bfd8d8c24ddf6073695c5a5d638c8646 +c129d2cf6bf4eb55dc6afe3645eb50a0ba0a0c3a8407fc214492cd4e82db082c +c12b139d37e10beee15be82cf8c9c4362c492071b79a877e4b0c62acf00dcc5c +c13d59caee6c1b790f12ba3007d9dbf0fa4551f413b7555961237906431af0ff +c143bd4b4335bbac1b90fc88f6b3acdf9a54c4e27999c631ad76a62d1e907749 +c15af218494e9258ff5e5a3f6e766cdcabc058e5112355b3e0c17b52075ccd83 +c1635a41dc1c6a1f82bbe64142481ed5eef08542fdb32eb19328e4f540f8dd27 +c16c6f4bf728693f5f92c6f54619e9363591a9b2cc10e47a73f18c63e3d166a3 +c180cc825b6241f11d7786c3035b6eba1362ab34f1cd2ac65f1f862604ff15ad +c185285c4849b301e095fe63ca25185fb9742a355f08c474b3189fdd71991586 +c198ef2fadfc135599fc2ff85860e8376761436bf7d7295e00f70a1144d6bee6 +c1a585abcca9ca03ffe2a99695e4c975384ded45dda2783678476ad3d3e36a85 +c1b03e01d96b36566a1583d3571b18d973495a7bd1231512827c884ba2c23b0c +c1b2e348b9045f2f2b6fe70cdc55d94b25d246abe0ad2ba34bb88c23995494f4 +c1ba2d9a637fc6d09930698352f06e36f7d57322299151da435e68c623e57a3f +c1c2435b5b0598ae0add505145dd82e506f0cd2a4dc9cb44057a03ee5f3f981c +c1c57fd0d0522359fb3b9f622a8307b23c7369a4a7d0a5d83c2a71feb7ebdcb5 +c1c7aec8f65c3c55af11e400508a6add9b070c974f605f31dd80f56ccda3dad2 +c1c9d2d21acae1a6bcd5baf935f5452995087c3e5e6d05a7d7fb80e853fa6668 +c1c9fa8c865df3d8e3891603483cc46fc2d82f35efbc57bf78529c1a9e97da31 +c1d5d4292acc3780fd313609209a9c07a5dcc30c90d060c61deeb213db425c38 +c1e151dedecc9b3bc277d6b41143cdeeb58bc3ab067f94987c95f91549c27623 +c1e8d9204c66df0a2d1e4e8c614c811b747f4dc336fb65b866b4c42282b22b3c +c1f48416f8aeb9b060d42a50fd1808c59ec927b0f76890d606aaa59bdaaf7662 +c1f6ff65c137c66ec7fe4848ec83dea3a4af0de8be8de1227ddbed9440977e38 +c1f92d0276b6a3b379bc4a5f10c1c01be486c22994521d1c8d9a1838f72a6714 +c217ce4df0c70f9e74022e1f4dbcf5311648741ffefaf6ed49b42513a282245d +c217eaf424e82259332cc9f735297205d216580e7269fc75a1a96a6e243438d5 +c21bd98713fe2ade6a2e7b7dbb273b02e99f4c04b3f10823f0ed04ab7410f8bb +c22cf3960c084440b22c49809177144d4c6811d99ffe4d92ae63d2f4bb917737 +c232150b2c0faa38708a63010e0bd713fd80a7e16881b2a72b4a9a91ad654d8e +c25709b17eda01d25e2f5e1bb426f2bac4a35be40f4963f1549a9c67189bffbe +c2573a8c66ef0683ad986a2f704cac1308b811c513dd723a06f673a893065771 +c25bac5f3f7e98f0ab7abf1bfd59f5e66501ac9b1631cc18547b25a4af1dd656 +c25ed4010d851fde795135f2e659e59e973190147f01c3bab5e8758ea870e953 +c25ee1b04c968f82ba8da833be820a69bd03714eabf96cb3ee685375192608b1 +c266caa1298354042555c56410afd4e1e5c61eb4eff1510a02095a1bdb5f3b9d +c267cd5ed60482793513bb8314f6edde5ab1e3d99132cc69827550beeb3c5cd9 +c26c88c109f65a98c573bfae283ff68b001e1d9df9dc0473d441fa3d22739d89 +c27c5a65bde76dac5abfac8eaaf7837729a872d4c66f910fe65a20f2ee78bc16 +c27e97d9f04ba88aa86d6b78c21bf80123d98b6ebfa7f3dc8e9f9c04b882a7c9 +c283b30b5919f220009f2b6909c06011ec966642c52a045ea03d32e9bf09e9d4 +c28bfb0e757c42b5f5b52a0fa9e74547d0bf8395e050a7f90c027c56b465ce26 +c28cf133e257ef67c7d7be7012ac5ad659dd019e30427c4070465c3b1ea1a02d +c28e761ec954fcfd6a57706795487730a15b35a44ce67e21b2a41935f6c4bf94 +c28ea2d08b57fc5ae4acdd2920b34defb249b4e0719902a36752279422b28f74 +c292b3ff3c042c748e913f90f82bd452539ab22399d0651dd074a7d1c5e3364f +c2933c259ca8e0398ce96213abe78ad71027ff40f283880d43d0345fddc28b62 +c29386bc3494a459ad6e21ae3d3ba3d079f9c14725007a60fa9814b91fcad628 +c2aa0085ffdb0ae4ead485bfad97f80aff00ee1c01272dec5288c15db54fb786 +c2be405b8f7e4ad115e37b9b3a840eeb3588ae887cbf4d1e65bdfc8462bf397c +c2c0b766fa03804c1ea30a775174c789b6f7a55a74b801c6a82c655afe609dd1 +c2c4bce3d17b88de0cfaa1f13e30c099cce009f5de1f3fc4f175809b47461161 +c2d8a7f2db2600db67d4afcd08079b65a6b523db810e370a239369f8b075c792 +c2deb4bea61fb976d0a739b22bfbc01796cf00d8c27b8bffb45abcba44289a86 +c2e097972625d86713d10ae93c3d02d24cb142477d8bb3c62a2ae2d8d948a313 +c2e3c333204993c214bf62ace80c9ae304df850b108f2240956e2b05319be206 +c2e3de2705571a4752a8aed72b6aa59fa01dcee5b83dfa82e0101dfea3a05a5d +c2ee31026d9d4ff851f7f5e93b36db3dc57203b5564b4b4dbbbe4bb7253f2935 +c2ee455bcde94419d28d5744b80536df5061b6ca384334a168ce3dcf7e3051b9 +c2f05e77783c5a7be337424f587e63accac797210783ea4bafdb1a5340594611 +c2fd0def08a9c4e2be0ffce17072839dcb73c62c5d60fdfc0045531ee726ad60 +c2ff3e69bea93f5feebc12bdf643998f6fa8a2b54833a47ef88e97d19da6ccad +c2ffb9beabf63b3496cc642cb87b210a601131e1733f0158eced597979a70fb9 +c304319ea6957a85280a21b8bdba77903c5ba164e7c1bbee31c976a304ded63d +c304d6ec9e0c93e37abd898853544eac82cb87bbc743c71fabc9b7c4d94293b3 +c30798faf7cd2023a73a6a5f5a008e7390c99a7fdf5eed4efcda27d2103c89cd +c30da80c1db9c601023e208522e76b26aa36646ef4d19aa42a84e9e07a1c5870 +c31589714549076de8d879530039c97cd5bda35dfbef4dcfe3e7fb84c01af167 +c3290056f77dca461d2128744424b6cd216b3576eb86e9cce221266773ca8173 +c32cc4c433857e8ae2fccbfb0fbf05c4cc287b2c23675ed2d70d190326535955 +c32d325fd4196f11f78fe03ef9f533308a18b98a1364d4279cb48161a2ef4047 +c33b6acab0f27035fd1fa1d79678fe26958c6fd2aad27405df3825f5d5ddd5af +c33d40a49f7b17d29224da0759b6db66ab749c6fb4ee87b60ec7afb791b9008e +c33dcb8d3bcc146ffdf0c03ea10835cb67b454ba38191d10a00b0c7843650c79 +c341f0248a744c3d14de167234eb2b08719f7f009c0f231b2e4c4c805f40bd79 +c34564a1c4a8fd67043ae6d03d626b1f21b50eefc279fcce706ba392a2b083d5 +c34fe8e78ea339a2883d24b51b8bbe3c95943321b60194c8fec013bb5813aa8b +c365a44bd459cabf7055770f9ebae5c0a693a7614ecc92944c3a4fae3ce9ba7a +c367bf38a2870b3a51bf0f927b0ffdc04b2bc9c9bbd8ab1c37179c29ad622452 +c36da11603e572d7021300894110840e8712a068398c57d59f3bae1287552a63 +c3711bd48acc875c9efc2779df1349151fbfc39d322d06114e1bdea3ff387a7f +c374b24fae716658bb1df052bef144231846850a7765a1d8c80676d2323c1327 +c37ca4b35a0a86700525ee360f0332f115495bc2133f9f6d69953ea5c058f48b +c3978d348ddfe6a5c3082582c36f37ed1ab4e80294e9beaf2d08acd2d1acc6c3 +c3a6c340779ee11cd9ae1c278c6095b70cb25d6b43bba3bb0b405802190f98a1 +c3a9035d9a0039af790d9c66998c5cc14bfdec64bc5ed959f7b07b3aaac89c24 +c3b0f2f68c7fa7bed8a2583dd2676288f69ba41a348739ff9a08869362d14ed1 +c3b32c52fc802de0cdfcfb906ffe5ab10ec6e92d42aa9a213166730e070067ee +c3b984b36b56567ae98bd4c3f5e54c5a8b66f85f18e8d3b36a39aad791d77f65 +c3c05bf7c12a550a036b116b18c5a71bc846f7d602d3611f9225615bf46c7781 +c3d11542008cf261d609df1ab4b1a706893b79e5dc23462c7a75eb2c28d7ae7a +c3d72708446cd478bb067f459fa8a3f740b1b1c6d92101e5886e3566b9c000b2 +c3d9c13ec7a9732656a0d39616b2ba043daf1fa4dfbbb73ed154e142163697a2 +c3e6e466e14def4e731c1b51f9eeefc645f4b1e44871981e85677ed573afb413 +c3ea980ba8eacbfba3d5707ee476cab6fd925f8bbe4c288923be35f6eeebf26c +c3f74825c6c0b764c4ee75cebe30f2370c039be90cd87d2243d7327a7cec957e +c3fa496ab94954be418434a86188cc80eebb60ecbb8ae2898b56cd228d495582 +c3fbc3ce474573fed2ed2dcd4e2ed37ccb9eda475763aabf3cf809dcd8efd70e +c3ff22fcdd9307e1b087e4318cfd2be263d6c4d6df821a06174f4034dba7e305 +c402d36f0f3a2dd2965569a5f8cb99e82020d8be2b00e70e16e08042e4138c8b +c40d19e0366d54b8a9824ef7f3777085373f4e3dc5b5ae52350f41c66c6e49f7 +c40f740b719e468deba8c6406c418a13eecdfb1fafda0e4e011540ffadf9ab2c +c41a4df42bb26ccd3c9a663d8decb567bd90e5786ed782f15018a824acf8fc4a +c429eb77ace20f1f565479d1e08ca404680ba9e4db9f665d87b40e4bd3cfeaeb +c433713b70b9dc30c012147b1077614e4c3a3d8ece0e00915479b67ed2d8cf85 +c43623d586e809ccd5d4d12e00b5d08a4123fab69dac5533861e9f549f5c18fb +c437bfc38145d0a366c823d4fe77c07fb91d7c6d11dd06f903da665175236875 +c438d51edb4de50a119b2f37fc15831e7fd2d007efe025779fbbf8ae0c28ab8e +c4562edd4681ba099d8b73676634e2c491364b3ed2d8dd2c5fe2ece805df0fc6 +c4586d1b375eaf4a9cacc65f95c30dfff51dea770a4cf7bafa34636d8b6c0c84 +c45aee7cfe2324fe1a1271bce8b5c2eda77d8fdfbc7e61a6e701963e171fe0e8 +c465d814b032fc7d40dd129e19b528463c0697f95b1c5c3fd8616a96160cb7ed +c47365586c8234698a60ca0cdf83ca29b63d89877bd97e9e8f4ff4b3c812e8d0 +c47f3f671fc7889d02f8f49d3ad941606dc3746ae3a19084762288c15522d7e3 +c48a9e67442a69453a997e4571dc2d211f7092b0661d5abad588fd57324bb530 +c497af0d0a42e08217086c209f2e979792cff48be5c80c640ffac321b785e787 +c49aae504f9dd5f55ee8c5e2fa4b9ad43144754bb6f3308f1e445d840a4cf3e4 +c49b7b56b14060370705440445cfcd2f13c1c158d12980d952940ac3f6818b93 +c4a22f56aeb8ab50d70dd2941fea6823e9244e983c75f6fbd9c46b44261453b6 +c4a26d8303595c82181a569f5087b7e4beb10cdfa0030e84639e2fc0a59e39f4 +c4a691bba1b984578190216746bfa628afe9dee26f2de5b8cbf54d5d67d66e98 +c4b16a1f3b3faddedaa70b5e17a95789e9b0eb06f46571fd2a4cbc4914fa9939 +c4b6487114dac6e504d82d0cd600c0668545b9daacf7215a287eac5c46101a5b +c4bf915f6644bd5321226c299855ad1a422cdea8df11bbe629e5abfbbe4441da +c4c2ad991c146712b52584e11da011f4913f6d3c807ed1ca326b782be91d3249 +c4c3a25397ccf86d1ea4fbcbfaa763268c15f47a5eb77695ebd4d098ad978a27 +c4d6bf55353da3e12f9c15a78d7c7aa5571501c0f3466199fd26fb1c7f6be8d4 +c4dfb01dd24fdd0e3df355a333a0ed7da85f58752dce424ed408ee37f611a42a +c4e502cb637ff36010ae5f517bb4309c8c6abdcf7e717ee821086de00aeffa74 +c5106422bc4e2a7fd1ca029986a97774c447a86b422879115deb12f7abdcb61a +c5148d5ab99556c2b90156f66b957e8a140e89fe8684b99bb3c0a46f6c13edc4 +c51777d6fb11cc7461b52460a931a71716af3e5708bab9d23e6e5dd1d2dba232 +c517e2379955ed7d1887278f04ef13873c59f936025668d92bed6dccd3467201 +c51f7db1b479a7f0181495fd189f04d15fd4ecce5d1c8a3bb1d74f823f8e03f4 +c52b22509a5e2c83962a9d0de0b401ddf3a8c72df99bedf1e27d0083b8b0e4c9 +c52b65ff30c32ac1dcf4a3ee41549e2b91d3044f0ea13429c7e6759884083875 +c530bc503d51e5e9d1b2f40612f80fa629a9903aaba860e93844a0dc4458aa82 +c531a8bda5a3fd14b51f19a931b47178d4ea5f0d2c5eb71c5761761a488fd7d2 +c535d8dc45639c542ba01c455674522149611d8690c04cf0cd6e12a0ef11d5e5 +c535df030feb4c981a82f8710ed915da2f7bc0c41e732ac87e242f3c2a270e2a +c53c2d4a6054d2aca49197e15779a3064e448a35a9dc0908a6558198371c370d +c56402b0b41e50397ac6f3b757006dada64b79017d1da27ff45b374eae88cd7a +c5670f269c0bd6589169a54d0101202973799628f2c27c2328cb476881906a69 +c56b3777b3173d2bf166cf9864ca0e2692beeaa8b3f61d07277198b1d2d96310 +c56f022623c6010232758cbd4124e226e1717d734cc7e152f741e133fc1acd3d +c57f3a07365df8dbc448310b0c074e37e2d8c679ff1ab610a7b9df91d9a8ecfb +c580833c78712ad1c18ef12072d0af77c2b87935d238df49ae1d34be4dcb004a +c58338237caabb11691fafbdf23b2f078b4081f1e8591caeae0e2d688cadf6ff +c589cfbc023e7f7a56f6531146405d2c127564c28b3c18b933cdd8b509e9110b +c5a39aa254678fb9c9da125f1977ef5607310e983917d1bad3f266617980203b +c5a5ce51da9bb849c6148ba2eef280db83c96a31c2cf29ecfca79bf2af83a6d6 +c5a60b02de2b6578184aab58b70434b6cf66d84ef4fecbc98efbd8e6d7add71f +c5a7e507d2b9a50f2f755c57ad321bf8dce38cc993d7d7ca74f9717d29d363c7 +c5ad064c78475d141ee68f1dc4b276fb85daa63d3c3e9d2c3f92f533392ccd78 +c5af22231d9256216091214cd8a5f55cd3441fb86f9f7b044f0d8e06dcae7340 +c5b1423b7e189e94b28267abb9b5fa8ce6fac0949733e26d978d1c09a5b8b759 +c5c5e3bdd978d76f041bbc2f4a45cfca830e514b79aef190aaede0d4af85cd99 +c5cccc6dccf73e102426e3afc73e823667d42e5192e139f2b5fcf0375f9ea57f +c5d0b8eb717682293a4b00281fa5ea46813b59225278546c9b6ad2367d87c99a +c5d48f46c987b05242d9ca62412fe1aed86ffe763ef174a156be19f3ed35262b +c5d78ecadf3a154927c9f1186c21c2fe97974c23075a3a7f8b42b1f79bad725e +c5db6bb53fde1a0efc684316cc1470182972676874b4b954c591b3bee662481d +c5e18daaa71a8e49771b25f324973192dce0250876dba2914ddaf595bd7ac3c3 +c5e942ab47bf7af4469d1600304eb11d3633175323ed45338fc8761c11907c8c +c5ece4f585d337089ec5e579d979a968afd09f957e6b16285120045d785ba342 +c5f671960b105218514796ce45224fc6ce2da5a280faa54dd7ddf15a5beb07b9 +c601dcee185347f39ef66d338e08c702fc5ba6007c25368a6b54f66890790da3 +c608c1f531773a5acfcd44d728d352648c6f4743c0c1d2318f07ef22605de6a3 +c614ab0711ec4984d2ef6a7f945e066c2efe27678e37f555231737a7a40abaf7 +c61cd8f3369bd089749f1aa9a2598e661ee40e574f46032821da432c3a3409fb +c6213c0dbd9daad5a3d138b4f3c3b0c5947c557e649ae5b8c9fe08d7483b430a +c628c7bace1e4f2d1e68324f44709224c953b8b05f30d50fa28991a0eaf441a9 +c62943cd1e13c48e11341c161a248b62e2bca3988808e9c739ebb8115e553938 +c63d29eb6c05dd42ac58672d777f1269b3b842996b2eba604c075f2a15f0a288 +c6517722b3d2c7526a6508155475e4ef48dde0cd2e10e412e201e7f1022cdeaf +c6554ab0fafcc9933510c4688ace29ddc0dd5ba3ae3f51f36f9f058353d47ef9 +c663e6f197f940bc54719563b7b3aaf57cdb115a17a1e9de30e883a937cf7af1 +c66e247a286c0cd926381e02ab0dad2824944bc988fd165d27f669aaea4e1b87 +c672400a44aee864bb58064774c20b4bd962ca4d7b6d4d8e76dcffe573717db4 +c673d13c80285cc981fab0a9e3f753ceb14cbb9206d3621e10bfc92acd641ca3 +c6744a13ba88110b3212f57d162de2f6542b52ecc9aed13a5571fc35eb92fa10 +c677927782963fc060cf010d4f520fd0792ce603afd6a4199ebbe5ac575925cc +c687026d341a11501e2427870bbff4bbdd05c4d69ea468f7705ef6195dbfa639 +c689c3a53a05303d848d21e14576b9f34af79400fac1d36f9dc228fc113f0c0d +c693a29f356c221b709f9934f43d6da96b30e5260856f929d5f2e4630904b2d6 +c693ec3bd752b1b30fb75065eb458a3473720f2f4a21b2ec8a5acf116b8ec5b6 +c694ac4948600365b1f7f3fd6840568670c92b223b291880f457adddec5a4764 +c697ccb68686526c43779cf3d2063fcc76ffd76cd6831108d4d1a3251c69522b +c69857689f7cd9dfd12e66acf99243061d57e85f75d5d6c5656cd1adb2f92b1c +c6988d7342d397be313cb38518266ce1905bb57b0b5b27ff9b5ced896c9d3bd0 +c6a02d28c91ed71cc363f387ba6d95e8b8f9d5311e66bbd2d52090786d93a539 +c6a38ce24a9d1a801495a9449572431038d23a43c8de7320c6d2b280e5153d0e +c6aff63ad969b5d30075989e8edac515d2003af204948363bc63046c2115e24c +c6befdb85429747dc73ab0012a41799a0c0d7ec90206878b28d6c980e1597681 +c6c6657d79e549e55055cbb6ff3b0d18f65754526f7ff0409ba867db5f0bd0f1 +c6c8adb52f67d6bd3dbfa24891dbbb3d529decf93da2b0530573f9cbc9456cf3 +c6d0346aeb444e89e6ad0471ffded541ac5d6ce74d6d61ec945c79b99d31cc3c +c6db826613f1a643274cbc3a616e6bba78b3d2ccb93d7206b3fa135d95dc4a51 +c6e0e23d1e5a28aa78fc42b9f5818ef0e3f955641f321b6000d007532f7d4366 +c6eb9083b04e8ba058d2c51c9345592d364f47bf6640413d0e698e976c0acb3a +c6f32bb8811ad9530a1f8019482361e3ed399f49f77107c5a76420284cf7b734 +c6f480854def9357960dc6a3fb1223b73ad07e6a71627841ad71e4ada4713baf +c6f50ba7485fd50cf39bb0dc6146a72dd8bf546d89f0c571e68b4599e880a6a5 +c6fb800edb43fc29887604ebad38d4776099dbcbf0c91833e0cca4f3e2dcc3f7 +c6fe5944e2f6709c2bcd0e16658b2963fd1aa56dd40485439daaebc2f401a2f6 +c7001071aebbbe2c959aa991638e74e88ad586e5f2ad1067bd0d4a5b333a3b5d +c7019e71f62e560adad72051b1656ffb65067795506f7727e25876dd0b51f92d +c70d0354a6a19a417fae9f98e52d2a3fcffc32e73f7eec01b215857c8b69312b +c71345c6b7170620556ab227767a47234bb09ad74dade4ffd15458f39531925a +c719eaf14d93445ef16c959e7b130aad1842d0001f0d21f8c757b32bb09786b6 +c71c26e8981c0f65df9e2d093ad85566c08361198ce6b5006490e9ab93c2b1bb +c723c716a2a68d701b16c30683241508d43fbefe09be77d1c09edd1abac1855a +c725657ace22015787ec8673e2444640306f90ba87ef455172837c0a8efec601 +c726969bd74f11a8fd7cc93d35ecba3a27f5b38d2e52abe582817a071d3d0463 +c7377f6f9cbff4fa0efb9b73d1989906e4884b91fec4fda8500727c019d83cb3 +c748fa32a28ac1be1d6248b56568223b7e90002785d52c2defdd1b5c3619ac66 +c75e9cfa4667a25752cfbdd8cb4b650e9aa38651186b48d8eb61ba144eeaf845 +c777a35cd8a207b56c4b98104ec2784eab76b1db17149664e4253977670f1f3e +c77bf538c0b6c3ac3641b174a422e3c063e138688089c3ed807a8693b217cf74 +c784123e6783f7a8020d88185e6f7332fa85be2fab96b2312bcb58702eccb149 +c786d575950b0c9f06cb016faebb5d1b1bcd1f1da21f1bb57aff1a16e62447e7 +c789229335724ae47ab3c18860abd5fe1dfeb72061c3689527c96415e109f946 +c79715015c5aa89a1c0cf84887ba5b978584c63053b05bd98d6102c876f3759b +c7998e35204fe6c816fe4d5ef25c12c4bca1931d5a977e6ed51284105878fb2a +c79dccd698ed707e84c5a2f10715404d8938195591effd2c1acc4e731a68f789 +c7a877330ff3ada05103ee3af1cb4091969e6478cd9567ea1d2632c756850b01 +c7aa55d116e2687abd67b13bcd40076fcd5784840fc8dd282be4b9aa636cb63d +c7ab7f6df04d845196d7e36d46eccf8dc4e63f8881d89dbee9baa7a4b048b265 +c7b015d63f71d0802c585fe665b244bf1e5b41e97124a61fcc083bf9573a51d6 +c7b1b270743e3c6529ccae40ad4431f59a6b1bde4355774906bf6f054d45ebb9 +c7c2face5c077c9889964ffe96d05336bcc878ac96be1b2c5efa6e3cb245e2c2 +c7c74026851ae75cd99323da2bfcf918147f5b10f414789528d2a2e4c467ca00 +c7c80018fc084d2246ae3d088051ec1b674ef01eca0d7db884a9dc3540c5887c +c7cdc931fd688b50a79f09d91649e7a5fcc3dcb7d82d3b66395b1e522fb8d2a8 +c7d9752106e05861b3a2a99fd6b2a7a862028df215502d5d58ab55284071d01f +c7dd2182f1ef745df90de23c0386cd3476ac98c48674dd7a82e472170f4a1f00 +c7ea5c0bb44a1b7e3520b52af271fd8692274e30824c8bd279baf339f3651a8c +c7ed1d56e9ca1f549ab41aecda012a2f4a46eefdae904f12b87066d975045211 +c7f3312fac17621bb7423bf40934d380a1f158da9136609ec7ffd4537061b01e +c7f794025146651e6bb704cfdeb4bdae812f26c0c32a04e209fbcdee06b4239c +c7f8f7f1714bb0beae67bd69ce14fc8340f7f51bea7139117e2c8494cea711d2 +c7fb05a25fc913a608060e5dde2bcf0c06d3f3fe1e6291e1020c5e0b34c5ddaf +c7fe69bd3b13dd61248ef9e998381230d7c5508b6a38ccb1f8086d37a2aff48b +c8173bf30a4f98ca9757182ccaaf796380d81a97f97e0a3b0e7fd80c1180bc57 +c81cfbfd1cd1b69358f51609d1591b47bc181ab0e0929e9d8899574b888fd7c1 +c81e3eb2bf8edef1dc62c54f22039be333498dec6aacb8af71016b6104699050 +c82d4ad21615c351c228230c9c111191d21fb4245fb22efdb0a2725ca82a8765 +c8403ed0f7dda91fbf866093aacc975e4116f965b2693e3cb9a86bf3bf4fdbf2 +c845ce2e67d58d944b68ae313fdf47773cc60776fa4183aa3477633e11e2252d +c85d5baf711709e6f50385713814537c95eea5d57ff24a41a250289f78138358 +c85e2d5f190633ee5c1a6ce992589a631aa7961a195030e86c3c242165e38b9f +c8678d3343942915756abd34f11c6e2db3341c1faf3ddd25093a362ae2ee125b +c86a58e5cd03635f2c0fad92abce57ef5b988b3fc9e97fb797c7498f676c9037 +c86deaecd8ce50dbb2a8f4a9173300ff49bc264ba0bcd5bff4584e725ab92d5c +c8701dc8405ebf961a186ddb27a09dc6f13ae63f132d21d595e5d27366a74fd8 +c8775af2efa54481aa54867d955a5e33c14ad7c2ba29e3f0b9a036c629f9b7c5 +c882d9abab581edc1f7a79deb087343386fd1ecd7df812b805e83962fb1a89ed +c88c9f31171c73a4cd20e5c365823e51ebd4eec481cc6a34a8ff929cdc818fa5 +c8913be4e8997e1fb488ffee4e2b39933bb12545197b4609ac9969869626e52d +c893434203b27143875c120c4774eb3ab154ce5086cbb18e2f784fed5686b122 +c89e4c04e8a00acdd06e7746249569299f400b6aef42a702e31b7a2064b049fe +c8a5dbae4014df207ee8f957da98cf632bf5e9f48350f42238ea82689d382687 +c8ad605444e89abc492d1bc9f4ae426e4d9ed9542262801c88366a355a918a36 +c8b627d0f76fadd5e55c723d644e760c80b33488fd5f74afd6d121b48785454c +c8c324a517c7383024e7e3e814b7481664aa85a06d3822fafa758dba13993c9c +c8c81f859a135087451e52e8b5285e14640c57640a3b082f07573114ac7abf94 +c8cbfbf4121e79caa98d83a76a97050e900815218778d52b2bf2e35bd61463fd +c8d3039611136d3ee6ce1faf5e35eb0bb5147de8cf369f539311c181cdab4954 +c8eb42cdb909e5c0db6bb84af48e4399d2a07530566d6b28c523cc11a5425311 +c8ec535f10050434bcca85de676c47152cae7b494759cd1f3cefac2b9c5c3ad8 +c9027b9660c741f80a3718e7fb5b446ea25bdd22e2b49432eca92ba8f5958c6a +c90df76b21cad3ed49724801d3d8d6eba574934e7f5cf9910c5ade8ee25aca5d +c91927d8caacc849b454587fbc0607e2d19d849be145e6f364674adf15fed01d +c925c4dd3700d366e50cd0bb724cb341d581f5e8ea0534180156a7356c64afca +c92819a4f9e58335027afaf8bc35dcbed88c3c2aa4e71185b7a163f22f076a17 +c93c849c5f4bf810150368e8c038726b589ea7bf1f718dac7f1641e9dada917b +c93d34e05ab3383ee31e388dacb6b934ce5da45fabdbc9ddc31483304f7304ef +c9462664997b60a79d2fb866fe67bdf7c8e0b22c2597e58e390aaf6b1431b68c +c960f37b2e42c98b0ab787b0fcbcec6f46a252f6f061d42d69de2bb5e5c813fd +c96609f63123fa08d6247d3c1baf7b983e4a8317282f1f12416be006408f1096 +c98fe794c0921d39e28711d177f3a632cab6eabafe25f51eb48da4da26664b6a +c9925a2393a617cb496dac8557b2b3b18beb116ac2b3a8239004596482ecb441 +c99ccc6e7fdd6c2053a8f71371abcbf59b5b09e3e0a9ba9e1c675c6020b1de9a +c99f46d66cd4f63a8754c32c9661f0282643d5ceee8e156503b89392266136bf +c9b10c21779e12190f0c150de7aaa4fe8758a3013599e56d6b7ec8db17d97a00 +c9cabcc9b78fc04196720c737c826478218af50a6dbdfc877ab994c28380b12b +c9ceeb4977df35f40dd6cf27b60e8ddd75eb8344e2f5b088beb37890af361208 +c9d040bf4d263ba0168a53cdb8e49e8507e503592b7d8a65bcd870172dd3cc18 +c9e1175412f46f13c43352b4709e3db756281456c951bdc6793c5761ee832ce5 +c9e4079b4d3f3991e223e01cf79f77aa4a83bc6f43bdfc480efb952ee41b8aff +c9e76dbcd7f5cafe2fc0ee8db293a7c5254d2cbe56d4fe7cff8ac331492fa1aa +c9f425a59ded0fe16820c6688dddb2da14e3bed6d22fa7a060950baa4f748ccc +c9f758ee95dcd6a870794c04189ef5812114c5419ff238621c0e1dbe6719eeda +c9f7bc4c511de073dbc1050d9315faafe3bd27272955b7b1247f6f5662a1e227 +ca0c4d16bc95d6625e91dffe6a9b5d3c7b0aedf8774bd593bd793c4d656aac6d +ca12ee4b68f1c2929ac96143fe3012e2fd9d66306a2ef66c870fbd030238e437 +ca26db57baa233f7f26502ac132afdfe809928e433394518189c18c4db25a088 +ca296cd60521ee467f260f1f608316a4776a51dc525473ecb226e9d1f51546fa +ca352ea77b19eb477109875b3a94067a61b8a62785e70a5e943af206c4a76600 +ca3e1fe7f255e58703911ab60569d327f1eb177943093ae2be0be335755e8274 +ca446154688011ba24fb3b659f56e386f21ef4391469ecc3343f06541c6b9482 +ca50248e61d8ae0cd78d031052ea9d3cb4f4f8eb1f82a4e98624e63837f4e09e +ca52f3cebb7471e634c946e82009970a6e6f302f74b3d4c600238ba96f8cc73b +ca540da66d833782d083731fd5088c11930cbf2946af3c0921cd4c6608ad22da +ca557d7c7df7137a65ec12134e595cd1e9c43d8901516e4ddaf620d69900d91d +ca629ee783d9aaa6b6d3223fec5d875a5d8887cc7004bda298711011288e014a +ca64313be19481ba3092772ce4de5543362e20c363d772211d5d433a5b5c2ceb +ca6d3837771fe06dd208e925b648609e1f266313e1bb6d5cfdbb859992a1787d +ca70633db93d365e5932a96a6e293910cd069ddacf67388796e8eb1579cca6db +ca7108309884c11e370d457d690a48e35cc8608f5ad98bdb8a36cdd134368ec4 +ca72cb3cfa949fe52e54f8fbe319ecbef2cce6ca8a9ed07733ab1a562c2eee20 +ca7a592939f10233b3fe9e84a7f60f47a8804fd3b916d8c820e3ee0bc75f2ce7 +ca7aab4d0dbfdfeea4e03d69e5ed30590d548ff5e023dc67d81cac963f436fff +ca8054d8afbac4cc560e8496dbc7fd27d1d6562b00843a6eb717dbb9369db6be +ca8d1af0b808046c10e0587f6eb4c583016b5f03a145e34da11798632913885e +ca97fdf6f1d0deea6e72694f40262b3399aeab93ed8c59fc205d5b8db3d48684 +cab32c3a6f5d5e7e7ff6142609745f7bd7f9e5751a42157ded013151482c6473 +cab3ba1bbecbb8adc50e235e9ca005bfd49306fd84aec7d7d28c25b1dc87ffff +cab8a6b9bd3751b48691b290382bdf3b854265a3731650cfb7b9eed7d5e83130 +cabe210c69f369ed1dd66d5f6424fb704fcb0fd15b9afeb60659d70344f7a9e4 +cac25ac356c53f95de0343ebeeb11d7d0a5a49a6ecd03d71be7ac7b82d3896fd +cacd862469f322c4c829534e05ce15e5bcb0a99025366c3189af49e41a2ad947 +cacfdf52304337cd5ded84d09ae98c3e2fc3fa4dfbe67e7e9a95d1fc35a89dde +cad8d48ae8c7a72dbf6cf15721b593711de8dc464412f64b240ae6dc704f84be +cad8f4a6b20afb0059bf7af5dd30f65e38640f87022e849f892bb82ef2c4c722 +cadb7d18ce6816b0d435e781f9444ecb4631b64a0cdfa2f169852a5f9da81a89 +cadef24c47a16973529d632717e75e4af58cea8277e8da82b9c269e68893dbfb +cae0b90bf3b3d3708635edea51112830b2b18fbffcfce32121b808fed4253301 +caede997bf0c1db03b3271680a01628a11b2cece33f017f1971dd09805159f89 +cafe2d27bb352bc7ca1f4de544e207a141b939de2c85237dd59d06de689427a4 +cb0b0d9da61976d4e1a4ed57e0b52e140a741c4ca0b53ec227d4481886ddfbae +cb0f1bca151545a639d63856c1aa9b7d0a6eee8a1c015639dd37a2809321fcd6 +cb100b7dc02eab8ef8a6bb85ff9e52e64ed5224ba498bbdc71c9312c139113b4 +cb1d41c94d5344ca09cd8171e824368e895f956bc16ff3140f009253244e5887 +cb1d8d8d8ee8793bbe2459c1d2af86664d55bf14dc87fdef714a3cfa645addd5 +cb2a1cc5087d7268b948b8b39910d76efd655fe49bc3764a533d7b9e162200ad +cb2d298d502fe1026ca5e065600f08a993c92997ac45eb6d2d4c0ecd2cd7dcd3 +cb46581379f744badedec79c06a66baeba296990146882925cecbdf0910b367e +cb4931484d4077f7ce71447d10bac23e6bd9a5b69db5a08ccddac782dcdc20ab +cb4df9f46cebbb2046c3e9572d0773b91dc4a801c693d9501a31607eb865d161 +cb53015ed327a825970a03838fffa9a2dee360bafd0c46a3986e2d2ae82e481f +cb76a2db7e5295bbe60ed4a90baa8b4fc634eea29bd6f5e3548a1bf4c9894641 +cb81d4c1813f0af175a04db4a3def0cb5e81aa9c137b85d9242e70fb60fcfb53 +cb830bb73e8d8273e26177c1fafb8ae9bde1614ff17716bfc3c33e84e66878e3 +cb859ed9cc89750a0cdf974d50ed81a49168d65f9248dfd072dd800440ee8934 +cb8e26ed04954106989280d1d9c39aaf4f94f0048099e8cec9f337a7bf1a8dfd +cb927fd23d9c9c61c224ac025c5c1da644f118be5e34fa2587569879c09d785f +cbae248809b16fbbc1e418930d6e2e09a6e8330700fe7759b086418ed63a17c7 +cbaff4afa798934e35e85021b947c67c75460bced347be68d79359b46cc89233 +cbb4cccc7a811cee35c8f61517aac3f7957a8e3a41081f1c49cffa2f44d890cc +cbbcb6055dd6ff42fc92a8cd5f8753c4105b069d2c0ff989e2691720bdc6cde5 +cbbe94e5b909562176ae91539929ba0dafb00a222b325cbbda020b3379693d71 +cbbea8840a87478db72e6243767f9065f42316ca5f7ef9d6641f104ee9e32713 +cbd7931b762a56523d3ab44708df5341b93b31142fcd9d81a47df309f7f4df42 +cbf70f6aeaf0a61eb0f6b5a759ca08853b7f8cb7fc1939906fffeaffbfbe6b2e +cbf7e68b9f0579f868a045967ddf80457b87289d14a2009beb6cd62efade0701 +cbf840de606ec45738f270a9cc385611ccaf5edd3d20edbdf4b9a32f082141c3 +cbf9247608bb606454f6022c389e6ec61c7733ad36109c864bba92d910c7eca3 +cc05a49a15b7ad604973cfc667b7a3acf63555a8be2805f8e703ba8f5cbb1f5c +cc160193365769054c57c829e7cdc2e81bd0f7f03e96510264211b8f43724278 +cc22a913bfdf38fd423e42fa2be608fdee71f58b5fc7802768d1ee3c1f904939 +cc3216ceccaaa47b2f849e72e2cfa2b212202215abf8072b68ef3ec280c56d23 +cc42727b2c9c636888f924a151483380a44f72e585bf889cb39ebad634598437 +cc43b59d99a5ec46c6dbe72667d6867f9042b9b3aaf884c402ee5166616abb26 +cc455ee35a787e8b1e6a53df612a1368c5bbc13a61e9758cbf926a56fdeb94be +cc515faaeeab6f0fe6d55bd824efa9d016b9fcc69b4789d6709fdfd829841363 +cc55386e287515b96f09bf7496a785cf5d92b6f5f5fe553530b53dffb445a8f8 +cc5bbc6d0da8d83f597a77ca95fcdd4e93c17d1d00f903a097dbede7903f6d6f +cc5ef4f0705d4f00cd4a767758bc7f2bd89516945cee3f7df893e57f65f3d320 +cc626b15a145f9c5d37e2798683875e858fe4968f876d98e47528766418ba31b +cc6cb4391938ad38c8230fd1f83f62bbf5bd3a4c14b0f13571e03df9d3e98705 +cc78d4910e19d47664665443e2bd8854204f6ccd51639c02a3985b99a9cad611 +cc7b802288751c828dd0f77d0dac6d481671658dbc53ba62bcaaf9be9c6b241b +cc8364b194d22ab82ee342831a9cd37975b4b70a7e12758c576aef3706066000 +cc8662ea7b055c552b093a24dcea0c90fe72d27f1f4e6b82481a9b4c13dd5af0 +cc918893a9125c33b32891b436778544cddbda010885064782934ebf65a87263 +cc98b6ca89732e70b065a8f9b6cbfcc72973b233d9402c0181a30985752ed2e3 +cca747f521c9bfa023a58dff8c16738d9758aab98da5cf2e571f3874dbacf4cc +ccb51b0bfe1d09dc21f123fbc5b5ee599b444e89f48961c6d068472464c9d96c +ccdb9b53933481eb99ec13750c478ee65f7164a83115aff2b8060fb12800b216 +ccdd81b9cbbbb7598c64797d0b2c5c103e6114e5ba545fe6934d1488bef2f134 +cce3ca21b84eaf23bf0f2bb9aaeddbdb281251cb50acc062ba5bbf25a771e5dd +ccf7ddfa87bc2a8ad774e9e7d64011275f5a3c8be7855ed11baa522925a36224 +ccf9a42d3359d1a890381e562c6693e61e1a6baac68c131d172f551d9e98e206 +cd026cab0e012c9871a45279f369abd2d9dc185a98350c6972cce37911b6ed55 +cd029fff26883c46ebc9ae5cffbd53b420d1617458b8f6f62475be908625fedc +cd16f04c66f12329981ebc3e0e3565e9602f7797072b6b50d75522e5b8270a9d +cd2f47ca41a81ace5dc5be9ff08f042a5a6c653138be311fdb7bd34c5b7cd502 +cd37f0c22e62d1e7ec4d1748596ed6186c54b6de4efeb54777506cc75690db83 +cd392b0830ff29a09bc1f3c376bbd206895d0bf09ff534b679a2b3451daa08e0 +cd459756149b5030c79a66abc9c8631bb45617ab206543e17188ece3fc4298fb +cd4ad31e2e7bf7200e17d34f26b22b8d7bae8b4950931230e3da11e6e1b82c16 +cd4e6307bdac44bc7a6ba437f1b73bd97d97ca709499fbd9db6f889324263557 +cd54b9ac483fb05ce385bff39720ddb72f202d1f3e4264c7218510f41f9f61ef +cd68460544d5ae1e34bd6a9c3b12166ae42785c7714e829eba6af3c9d38d4b25 +cd6b481ddb831a18edf84a2e01696afa232681775c244301e890ba3a1dd042d4 +cd6c119a44a647652172b2d1f0bcb2ae1f280643af94fd0ddbd63f31f50a1fb6 +cd773590d44a2db9a6d86a91267966baedc6172fab992ee57b58d92dc186e644 +cd7e81a0f82a0d2eca840d09b7c816d2d94d25cfca2a3fafd4726b8c20e223b0 +cd8654da61224cf599fcbfa5bb8d08d9601ee7c96152b3f5a25baed004b5b24a +cd893819d51bab550f4e7cce44ed2872f6f7a62fcd7685dec9212e3b308e1689 +cd99f8588818325169334316e42160de0190c3d48aeb1db3edb9dae6a5d8fbc4 +cd9d011c7e7a249a634907be24f3973a1f2bcc8b0772cb5090c899a20608ac64 +cd9dbd569f759aaae24acf6eee5207fc8b4deda2eb0bd263811fa85f97b9e31c +cdb4d85b9b53363d73406a943028984f6cb879af88871149c5eedebfaa8ff945 +cdb6afaf6131633aa1be8c1100b802e01934add113e955531a71ea853bea75db +cdc2acf281d74cc61e84a59c59ac067aeff33e4aeb5773bb35a923e9a01ecb79 +cdc4cc68e676db421207971e341e6ac53a175860fc020bfa433f6c04f4c9d9e3 +cdcf1f6e89ab1eb71bfba29eee6e650b675b8268f1316b6c3d6d36c3044e154e +cdd2d825910d2ebaeeeb79b06ee80971dfb03e71ba5643e6ad6014de491fd645 +cdd816c2d9ccd4ff94301f363032d59f0c6fdd38969a3e90216a82e9aa14ced0 +cde27db34ce3f7f2203519fcb8d82d88645afbda2ac2035498e32d044528981b +cde6e12435d51f18d713c2262b848649abd9995fd004a2999ff91da043b91455 +cdee593568477f13230193caf838cfa187b037ae7b1fcdaea9525a9592c3a0dd +cdf5cdd72dd4dacdb4bea2fe98276eea8d972a216667b967931227da9a6ee620 +cdfd5d53d9cd4684a7fae8ee2b0e1a5e88eddb813dbf1bd6f3301baee2788fa2 +ce00216c6e9afb7febf26c69b441f237338f5379bf29b089a54608cfdf63dd5f +ce1fe14f7d954dad829cb243be1727356d047a8dfea47c230a673c0a4be1ae38 +ce2fcaaf2138bbac507e990e7b96ffb906999f665591ccb8a7490645ecfd6d12 +ce3f67bf2a3ab12c48c40091606c0ddc4c29c5aefef4ff7298573d485d314c97 +ce4f47eb63ed791883f97f9336bf274d53ebedeb21f646cdd516d29bb4d78966 +ce5c4f9e2355bad50ff4bf8f3e48b27567cf286ca47fb8e53bb3e6e3a5ee9df0 +ce5fa1b63d82f4697c0cd85280d526faf2a3dde12a3ae86979f6904258d68cf5 +ce643f977c75d033d709a822cc60bf91b3c8c71fcda78b63423c512c1f34b074 +ce68fa1c5d2d63c8071eeef19e505bdc6bbd89e19963d132e6d322f1b3a02692 +ce777fb091453887ce79cbc72da4681d23ff68c35a2a79bf12ba58641681501e +ce7f8732c48f1664d0a5e9f840e3abea575f088cb6b463c8882111b64c3c944e +ce84031bae32726c3c8707052ef5c0d5513be6e33013a1d3e7582d0c51aac77a +ce846949335e885dd180abe4fa32ccea837215395ce66bb78503ea0b51855b46 +ce9a530898bc9d88a0a6efd8d2ff83b4ef0adf68c28edcf11c8fce520141c0c6 +ce9a8da38a304479a77b3d18d6f0cc6accf5b4404916537ef4ab37fe04d3649a +ceb7dc754edb50d6f03e1a3dd491cd770fdba6704881743f1d29923349765b2f +cecd20828487500e495bc82cd43b7b4222e81424d9712b6351a0f41b3243e689 +ced6dce15c090ce16a673f46c0d5a2fd36fc28da8530ff0ae3f3de0a1d8598b8 +ceea8d0d58cf8d24c1eaf8fefdf5bf75fad9020be5576c73f4e9e71de6995cbc +ceeb246bef57838bcaab217e773e0a1f65fbe73ff7e654a10341e4229bda7e12 +cef3686bbf96841ba9dc34f3c0b786ba3613f4de57e4274d4b78710d6aff1ee7 +cf0d0226513705de05fd08cae3c6d29d7bdfc473291c68e7ed73ab2491bf03da +cf0ed6da8ec581a093bb55401c65ae27147e6ea0aa7e35da268e31c09b1bfcd3 +cf1de5675fe016d5daa32c3159291df1a81beb5b0e739e7efe0dec07da679625 +cf1ee1a6405255642f45a73852632443b4c13247db76069a99c1b58049b82c8f +cf20cecf4a289203eeb75e988d43b5ca1dd1244eb30763e5eada67935b2d754b +cf2c0b1d4c45f7def3e3928daf159159d1332ee5a4b82e7d95baf2e254575517 +cf3c8c5feb57a919ae2705f01ca5790b5962ede1f7efb161847786c446c4392f +cf54a8cd68772558c67678e061a0a5447f944c7db7269785d91e2683b27cc28b +cf5b296a47e579f639e0a13dfcbfa9f8df29e8ad04b0cea01b5990e746eff9b5 +cf5b96b5520e78f758d649982fac5b53968e20e95e00bd89db6438fa85e7df80 +cf648c8ea59212f0679eb975f096931ad043dc5a8bf1c95cfff0eb83a79ece6d +cf64ab0da866516ca2d0c6a4086f6054094fccff59bcac17b98473679105defc +cf6dac7825602b1b15c8f4c9c9becf5a46cb7da2523e4e6c62f35d02e72b4a11 +cf7515b6bb258693fb2fedd81813d04fcd11cd437b75b7ced3ab4ea9ea9378b7 +cf775a6e374d97b890647f1c4b214f71dbbe9493e1b4a5104c913e905fb98fae +cf88fa481f08f9b17f144f6a169228ce913219cb0e93e67ebcfe0fcd2911be75 +cf894a9f8b3294864ddf528809ba1b0c10da26efbb07dc21e10742ddfce295d9 +cf8c7efd7ee145bc97a71b7f39fa4c1073073b4651a728dca2d9d825c246fb8d +cf8f1bf780c93cae3d6ebca97bebfbe84078dfc2db0b0375ad5fb1641b98fa13 +cf90ff32976faf7fa5d20d1689619087332c578e7187cd482f00c2e19c7ec688 +cf92313057dda268b8e0576bdb1e5d22c485c366b327f7617579e565dceb0ddb +cf9b0718a7c346b7314e12356d540fdab1bb22eeff756d95c044773e78d898c2 +cf9d5f78ae30c80e2f32913a7e8b6f02cd5387b3333d036e592d961f4ef77109 +cfa1a06146e281e7e946c9097574a21eb8d89fc145611f43fb2de61b89ea73e9 +cfb13dd2b5246b142c24124e8ba4565bbcd8bec6ae471a6091c8bdb92f3c1c5d +cfb20198d2cb93457a1907e83872a4de7917d20a3b11967d321d05cfaab2097a +cfb6002995f46b1daa13e2a23de1e29fb6dc2b2ed22707fd337f491f402a8dd2 +cfc4057c0ac95a394c39d1efa3a290d9dcc5a429feacd647f7650740d96e3c79 +cfdaf6c189a7f1a47f854e95e7a53ecc7db89c04881606c755bf2009b1a1633d +cfe0dff80c8296f55069b04254fd20988df07630fed058ca9c0c2909612e4485 +cfe0fd9a37891d570edfd43e83ef95df48823e5763c247610f870e5ddf122873 +cfe1f14fa9a9bc52d0f8aab5b7efacbd082faa8b96bcf1f6af2003dd3d7e3cec +cfe428276f57f5e3aa51f8452ae0e8aab9a71c2ea764670d0c4432fad6c249ff +cfe92b9f65121f1f6e6c1c9f8fba4782c71cf9c5926cf940b14f45ba72c99734 +cfeb08fd79b5665735aa00e7ded33e2c5c7910d4a6348908616530dd562ffd85 +cfeb73bcb2171adde6abb358c3023c918e5b31c2cf08d513dece49770542958a +cff0a6c62fd549c52a102536e44cb982a763caf88fb8ccb1dfac4ae11291c05b +cff5b6630b7fa6b637ebec917aa3ebbe1df2274a0beab5b3c444b811334342a0 +cffb494fcfcbb04cfe05302158e905caae4312816791086a3c354041c94ba026 +cffdb23137c404799d6b3832798153e9b603c6564a5aae790736d6a79db1759f +d0006cceaa504ab14ec05eb04f9ff8e302311b9a4a5ade0442a585bde26bc33f +d002265af8d09020f20185a7df9fca1ac8267da456b69e1a133cd3151a90cab0 +d0158489fcee2307ee3dd030cacf942e029b1af1a988d32a62127eb700b17546 +d01596bdd6a266fd5ac930075783865d51d9b5a1206d1089f3e393bdcada383b +d015e398232551d50c62bb1463286141aad78df17a5685ea9220b17c78520bea +d017c3115851ccaf7abef7e0dc63eecfe8c1f5a92c59061e5617d94c30e681b3 +d01d03c5d3ff43097583dbd9f3a68eb5a5239093dfab409ed9a28f1816d80ac8 +d01e401943e4ba9754bebe932507b91184ddaa4bec2b507a257f6584238645c1 +d02a87ad20d80db0529d53292c95a15a1d77358bfbfa896d304eb94cd588fe3d +d04a9ec18406c4e0fb33932aaa029ca31336d48c3ff77948326021cf1f13e13d +d04eee02c542cb059950459e8db4a1725c8693f3bee9145864e0abc2d6adba82 +d0553858de3c33f67244103cdae1ab098fd338b18728d7333c303101bfcfb778 +d05e33c2667ec943ee4fbd1fa7ba96071369de0dcaa6493b3f0fe48b754b6691 +d05e7413d55dc72bd4ba216b7b268b9b4c588ce860ec6e507eeff7a6a330a4cc +d06289c15233defb30e5c42af6cd8ee024c9ed28c2e1228b384d4c8fb3c622eb +d062f8273d891431421333d9562317146460e1cc31d71696bdc3d118352c84b4 +d071e756e3f217e29fe3b6ebf215cbf61374b7066c4c6ae9054e0fa3e1d6ccbb +d075067885266778059cfb94b270d81ae570209c274b570cada5901d84925892 +d07c5f1d1ab0302d128f97ae800842d5accc2057c871347e08c100c9bf55c1b8 +d07c736412ffb86cf58efc5592c30e967cc99ebf426a767ea6339bf2b244a16b +d07f28fbe0e72e05ae00d308bcb298cc1bf238fdd106d48b9ec97831dca2925c +d084a6173a678ceec25657ef8e54b598076a391e5aa550d2ac09417324066089 +d085b38e42e3eee875709e8546e04acd05f7788e9a16b1bc0bd4cb26fdc4a983 +d08a134ebec0dbcb0da851ff4ee1b3650c4e9d7637e05a31cd62eb41107ac7b8 +d08e05c4e4f924b62441a7ed20d15fd870009f57a92a1e00f4a0c92e973c39cd +d091eaa1c126f6e931c9eecf018ae4b878a686ac664fed85fc6c5e88b167e0ba +d093682b674317ce1d1c09c2f099e1f8eab1ca0a5d0f9b8ffcaa9ea34cb4779b +d0a54e73f28a1b26a093352b91a1f2427b0aa516b8082793e46571ee915ecfa8 +d0ab5fab5a4e1baf0f9db3d1481c324a27fbe05c06ff5d27dcef7a1f1edba70b +d0af3743974d9d6141383b4301b43133c9811b1532da81b97233dcf3c8616172 +d0b88f38344be6e53d8f1f7d9abe6679832c162ba82f4ba3557870c224c9a60a +d0ba787551b89418b9bbc2b4cf55f0bbd756e8482ed1e7eba223a35d9d1a02df +d0bdd9bed819c0012089b185031409a065bc65830e3588b6ce334606a07ae861 +d0c58dd7952d128f7041a773beae772aa521bad66072adb4d86a14e4690918e5 +d0c59e31ebdde27a2b8c88a5354edaebeb6c50f3321c8bbae6976d75f4bde7f0 +d0db030d4a3bdaf0432d226003640c1cdd0f6f216ae6671626160d5559d9c52a +d0e59e209dee2c9f41725854e377eb8587d255abf2a855d97e99ef14fc0a2f3c +d0edaf6fcbb3b23783db117492a6154441e12c5aa8f40ec0e842f5c79ad21f3e +d0edb61e4b50f88c86626eec3a6b64b9bc7456b572ef337be00b47ef0aaf3cf9 +d0efa3d1931ca2b12a360b299ca85328b27d04c68c3b7243f16c6ede0182e6e6 +d0ff9e604f33fda3634372d10fa9ec3ecc9a8c626bbcd5cd99b05cbca61a6525 +d119e42e34f31664eb805e66d0a80b482380eb02de23083195a0c909424c7057 +d11c4bb0172e64c18eb9a7453e6f8085ac363aa7fdb768a2d1b5822913d0b368 +d11edcbcf262c35d7f91470da513650a48d494aca7b98c6fd2ab7b61ed39136a +d1252d2a7b464c8d1f1b6ac2ce1212fa561e0f68f50b07441febef536be8ef38 +d12a11119e413f62187b82b517d0e578411d553ecf5d3cde8f5f0d8677e145ad +d12fe2daa6dad80176ccdea7f3fc972e63389b4c70a609cde3143737ae410a65 +d13f0db1f26f98bfd2f3ecd17fd42e3fd7b6a24f47d5d97b3a75d0ee8a257b85 +d16e683c06871abd174e6bc0676f912cbc579f227e4a1ca09d58901c7e4759a2 +d18205410b8019a3c51be8e88b2d18b735e07654a219be423530418196fa115f +d1870841e289767f53d6477410c45333c67b60e45dd3446080e6203f69339eca +d189a2aa2eaa1dd22a5f3791744836eca188e5ce2a710778499b883739e0211b +d1a0e753b9a969a1347241783c57c31e979b4534c687b82ef164cc68a9154083 +d1a65831aa30b4437d7416bb395212a81cc4c109810d31a6a8e142d33eb1bdb2 +d1a74acff8c3113d3724e49d7b317b3e93f32e2f75ca388f0b13b8d0501d4ad6 +d1ab55841bd5cf20a824dd852e1e4e2fd00e8522125fd424852eb3bb03f366d3 +d1ba08c9a70d22cca125567e29c929af7ab7af5958adf2b9ad63fc59b9aa18d2 +d1c14b15a7faa51ab1dbbe08afece0bc929fbac483783bf06d8ae05ace3293ee +d1c64933016ee2ee734b175b4f0eb2aee20607fed4141fc381fbab93bdac13ec +d1c6ecc1cfbc23fc7f328dd1216bf2d925173aec6a63adadec534e05b2e5a05c +d1d5a90de947b7d539f4cf8f2d966cfc328b16251b6e4d26ae879a23cd605a31 +d1da4bc0dd45ceb9cae1900cf2c9e9544d24ef7c6b36243013e90d2b0a2ae335 +d1eabac3f153a378c4f04535a8cea8ab335fccbebf7cf6ce7b4733fb1f5c5115 +d1f5a719a3473bed7c7bb51f8d0a782aac5993c65a62f02fba429be6ac3d54cc +d1f606d5ff6bf9ce1b4e989c54e3f10b738324c4765aab9c796fca0b7b3753c2 +d206a3a53fdd4857e87895a307e012fad19421619936786961092f96e48bb1c9 +d208ae53a64427da37aaefbfc84ae9c657a12078d4450f0c14e0e1d238d1ed73 +d20a7de628370ac668d83d4695529ad83889e4877c94ffa52f3e50d73e2c45bc +d20cb1961cb8c1e7305257e15a0583941b379e8eac5744147624ed795a539724 +d21e5a86f743997bcfae2307eb19ed080a19cf8d8d4f909f3f65120be7bc799a +d228ed539df40b747d1543f38e6032bc2ef889262b7c6295642ff1089c5daf0c +d2337cb965c1341ccbf592b7109535f3b75526de617b71fda66f23023880f987 +d2380fe5c98250fd324912bd22e4b25e8fe03ccf41c2ea19a97680ac07ce9c3b +d2430ece22b9f65e7a052a4483093af7d48943af07bee7013b16c0c666bf808b +d24433a0cd15cdeee25e982000415e79930609379ff8e256b451d5a9cc4052e2 +d247785520f31cc190da0f79487be7f5e4f2ba6858c8ddec95b1b888e34963ae +d24febbce6163f598e1a4df843ce4ca4bb53f06f7dde08ccece8b22738128e72 +d258e53bb7acb1d199b7d1998272077d6a4ca72a46c1dd2011344b0e419c191c +d25a69090129316ed2a9f0b5b7fcae8cc31f12b89c10632dba15f4b19722dbfd +d263c5b9e67c5fad125b33d6cabe6589b007db275d54a94bddcc5495d51f8a1a +d265f82a03744833273339eb192e202d469aff9acff90ae7d205b00297438b80 +d2684bc4d29e9faa6195b1fe27b6f96328b814e9bb80576b38168e2436a2f50a +d26bd88fb7e5e996ef78451a9891771c404646e67ce1e222be510e61bb950871 +d26e85221177133c6391e53b3ae1c97a6c292c5df54599e013afcfbb630ca522 +d2720ff9b95f2d4732eef08c2ed8a6be3d1a393525ed031e5a4b92053079cc19 +d28fb30ad54af9a295a8d96bfc76d9ab5f5e17e76d077395aa5f3a7d3f99ccd0 +d2904ec875b2e2dbafd2fe14073b46c0c9797b1c0153e717198e5e29162c65bd +d29bc0faf208d948235ead21ad3f7b5246d99b6e4d7ee1378d18252be94f3936 +d2b20878662143b03e11143d5f9e17de8febc80d96bc749cc88f1a1164312d42 +d2b7bf0645cc0baf9727886e233cdec73800765b1e2142243b5b2682f3241e51 +d2bcc1eb10ae1241ffe141292e154f5b0a29f9e2ea645eb32dd49b461335f577 +d2d35c8acd0b03dd237176ad0cab0d17c78a67fb75f4d069ddad3cd2679d1d96 +d2ded6c2384eaeea22d98c3cd7b6a01730703710f4911f8e9715cc6b77e374e0 +d2e544ca93d7f63a76782c808da92b4da0e1621e441b342ab701b300da0e6499 +d2ed897e0a40e51dc3d3def9528bb21358b227a2d690b480e85908e5cb6496d9 +d2f2f07c12d7a7e5a389d063a6b75a14df801133cfe3d51ddd24cb1972f83590 +d2f48d00ffbfb3b86141013f198b2b5fc974101b796c3b7d0172cff49f207daf +d2fd5facff566e0e206d6fbfaf76491b175ab97cd81a31cdae9503dad128f49d +d3151e606bf9e1b66d89dd636ec47511d1eeece937dd75a84c4d5d1c5eb70f2a +d3461c3ceb9e06a512c70c4c059c3d4d8ee16d20cc6b0674e1e4014b36efce1b +d348275e39af9c2bde34c7d9a54d79cd4a009ef1735865d11ea0cb9c5ef7f426 +d34c7db29f620e09202db4bcbf8ab74fc72d8b15a58d5b6e76730b32170fa120 +d35cc84010be4e4ea952a30796817366976c7b347fd1ad3fce67017bd4f41bbd +d35f30194547e2d66066c3e77ee3cca58c78d1888eb930a7f8c85e62f3ee11b4 +d363984aa981bc3c5c50cd5697733dd91e3e5acc9f45f196a65a2828325c6d89 +d3768169ab630a35f7d79a55828369a8ce53ed02f4aeaecd68ff4255c05b6621 +d37779b5adaf76b6ac77fa35b3fe4520aaad6f7ca0442b0c166e50f90c73ad2e +d37a723dffc3b896a8a07a9bcf5acd055934a1a8580daf0d9260b1057c38168a +d37cbf48bf7e62da571be0c66b60e7a2ac08f70aa395f30e07c5df673f304a1b +d37d799546d59c24dc4da5290566d0dbabcc7b21ef4892254ddbc1967e1bca1f +d37dcb2b12a7582942bff593a98797e0cd2a70c0e61ae2ff1840c1c3750b4724 +d38b90e7110b3e88e7aea907b5151a8188f68736567b6db9eac886f7f2ea6828 +d39a1435c0833da935511183e8d42e6e3418403eb488ebaa434802061d39969f +d3b64aa7dc7f98785863165671d429a168585a234952384c76f065d233daa6e5 +d3b9cce54d7b5b264f04cb9d78e59b564ad58b9abca9b551df51eca0099e0f58 +d3bd234af290372991ac1c6135f97a04b3720c2f738b0c4158dbcbb6eca8f29b +d3bf489f44e2198951ff0c232412673988249020dfbdb8cd251b40f9cd84d9e0 +d3c3ce7b29b83008523d4153c720c091205a6052fe1c8af938ee6c65d3751d0a +d3c3fa92c9144d52b5703c7f2aa386c29a38dbeb3904a33ef76467d03136fe9d +d3c7def0c75b29fa9d6da5e4a0c9d41bbf832e05d13c324f0aa6e916ac2b49a4 +d3c8c6c94d275a88f42ec3bf32c1b0127a0b048df8ac15c1e19b00c0f2e76281 +d3c95670b4e034cf6f1a7f35c41b5d4c32572cd5bc8172aa08f637754b195cba +d3cc7dc55d950d36071bbdb856efda2598b288c835e8d820f5c2939fc69c0576 +d3d3368f7a426371d39b2d436286ad20a7772b7f728999e66d641091ae1ead9f +d3d3b4f0a5beafe5bf3f5fa8cef11b861d4c6ef1f16e4eb4a424aea050ef2334 +d3dca45eda88b18cfec048787e9bea0c02f0e4781d6df2ca81ba0bda62cd4b79 +d3e4d52837830eb1f47234b812ca0ea70b3bb7aee799945ef88359a00bf469b9 +d3f36aa28936ffd679f398d45a449de09d8406ff79038f08007ca794c3549bc3 +d3f37e195e83fff5d40c9805cff4fabe00313f452b25190484d92513c2b7b276 +d3f501e6aaf83203bc278ea08e643a14fa18601621610a8b696e9132a2ac1e25 +d3f5ea54cd5783bc708c9b537707cc1e765bc5d64cd3332453818aefaa182f02 +d401a36354757b758321476948b1bc2f393f73cf3cc68ed3743cbf4d461011d8 +d4066adec89d2e08d555f0e252b0ac15373120ad5c7193fddfe7b8a0f0dcd132 +d4096ac3baf9c4068d7185715cf466c143442c029fe182dba004c9e75d066eed +d40eac1e9fe7edd926f2a836859c56541bede995fcaaf3c4ae7ad39761c88de0 +d41a2ec226cf66332c3ed478a1038cdf76a2a3e1bd9cebc4d4197e6dc1e8e93f +d426b01f7be7af8da9d50d1e67d740ef167b75ba63c0b920b306703f1973cd87 +d4290e6a8eeedbdaf6b06deb77d5588094fb616c04f33dd67a9023a88c9182a3 +d430dd2fcbaa0b5dd7b24ce47d4349220f7f447a1de8dc49a96096c6171afbe4 +d43770660e79db5060ee1eca30e516ce2d146073913caa4bfbcad45d8ec5561e +d437b032752666328c9836008b9aaf2e3d3ed4fd5eb62d9e9408eb66c29e6730 +d442b3d9249ec3a0bc8f956805f7fd02476d89dbda623297d77f6eeb46eb41e0 +d458ccdd90202dea71db9309913dfaf8a021e03cc0168d4c61b079f9b2c72fdc +d4643e2262f71d0a20efb9e3e329d3c13406f8eec9d5a1a3e1e4753a04021f50 +d47b2d5dec08171699d61872c81f2035b7b5cfc02a1057385cdf07d4c2dfe14c +d4817870eb2781a18aa5c51719eb7a88b4d61aeedcb8132ffd57f0c445d1956f +d48388574a32a7f865b9f6dab37db00bd461648baa8effc2baad541b2ba7cb62 +d4890e15521dfd3cafe87fbc2dae5508440e189edf18e51f96769709f26247a8 +d49e374c8c496055993b04129dedc886975a9fcc4b45f8ff3cb8b3dfe1dacd74 +d4a0b6cb2b9bab1a3fcb413c9d6c632e98f6023765866a838651c28b27269e04 +d4af15cb298ee852a563b01459815d9b49c837a0a2f453462139cb529c86a401 +d4b040b1a1ad9ae64d723e776af00d784239c6176d5fed76c602426c675ececa +d4b439af014645b2528ace211b0f67a2b3acfa9cb22ea376cced5392ad212628 +d4be063bd3036ddd1d716eb5fb541913f3b52b5d09ca9126d0a2f21c6906d714 +d4c0b8843a1dbadcd74a6513a3b42aa6c221f632be89472e416be57ab48ed5e6 +d4c4ed0a716a2420596f3c5aac2d4973c438c95769b0fa3f5d89e535c10c7105 +d4e8682845bb4e1c630f211081160135f10fec0ae5ee645bae187ec6eb1277ba +d4eb6ce39711dfd8031f53252e5998c847c881da8e11160e2344bf97f02f0a7e +d4f10664383d8516ae19c729839012afdecaca78525bebbe69dc3ae6ee5a182f +d4f44d6569d94d9a60972decec10e44c20367a5248673f6ffdcacf15586db262 +d4f7d9a11fadaae862b9abd906c341d00566793995a2e7f600ae197bc22f29a8 +d4f97e37bf7a5e9ac80ba9fd2ec18146dcc9130e774daff409e5350a1be269d9 +d4fc2b8047c94795fe1c9a8904e37b0b2e40d6fb37a1473ededf26c2e5c479e5 +d504acbbd3ef226f78478675f4fde6e307451bb8809138d8f90ff98ae0449dc8 +d512026612848ab5436639694140ffbeeda7f48826423a8cbbdf282e225107a3 +d512a9aa0f968c3a3fc2436ee08c57c102dd515547ce7da475b8d8f8ed6d6c1a +d52f088c493afb0280d150f6e0e8dbdae3050ef9181f3e084f644f761ff426c7 +d53280fa129913850aa53d45d1f39695c12fcf1bd761ae537ec9f91175fb7399 +d542571c514dde6d1f80fba512a9778534ee30ca65368a6a515d949e0f11cf29 +d5438b653e704f6a47d0a101eacd8dfe5ab1499d7387a103b1e082802cf2a97f +d54d79003b08a1c9e27fef4cb8d97ee8db04e4dfaf09316bd33246c741b8a5ac +d57b0cd97779e9fce88a5180061b5b5acc27e4986c6e6a2c38676bb2b8a606c0 +d57c2b0ad7ddcac264c51d0c981266a6543eebef9f65477b9a6e297c851a1cac +d58e1a19cd9c781112fcac2be15fa5c2df635fdbc5d689afa9c95ef992d8c8ff +d597527f167877d92aa18fa6068ed2f648604a2b97bad62b9ac6dcbebb4248c3 +d59fa2aa3c1603f72949a768f5f979505d4ca3add4db024239f1b6a6c25c554b +d5a0cde2ca147365ae8c948566d867227c2c0e76ffa0fb919c27addbf1abec8d +d5afc01fc6e83daec1c0c27e5de7e1172fbfdb69d263082cf079515a64f5eb6c +d5b035207f6eb3ae2e9204a01692aa04b23766a799dab8e9bdda497b296f8894 +d5b1842661e89c3fce6f63031d0c2244f983cb5222fb9ce96778fbe3c71e3fb1 +d5be7646f88937d1ea4ea6ba66b33e16210afb784a5421db497d1f1e798b85bb +d5c1bd61f4d38b8abf204e62c8513c0d7fb21699965cd3361155b94b3ad7cd3a +d5d0951dc8b3f597f0d1730386b8ada675500fd8601f6480b164a84aa59eb1cc +d5dee52105eae293959ed642abe0007fa2cf4d6b147294e8b00bae00cbbfb82e +d5df45f8c42a15ccfc4d6a537a7c726db483b55a5e18a7949ba9efc233b0a227 +d5e1e9de16a3b79d7fdf5be2389e7b323c1b27283ae7eb64b927915c7fcd0467 +d5e44d143a69f29ee2154d00470443931a7ad91750b98a659edbc5aecc9c9dde +d5e640b0e99e18275819940fbf25b6ae08857c1af9bf680f0c62d4c2a58ace5b +d5ef23a88f16bafec1b6f5d3a74041cee8bb2164463c9c25f272769122875d52 +d5f4e3d67e8079346a5d7adf90cfb8b019ee5bf81f6e5ff56fb72ac763b8a464 +d5f9ad75c18758670d41a18cfe057d6ea7d65c490487a4d3575104ef9182cee7 +d5ffcae9121c0cada857f7069fa81d57a3e3fdd2a3553b1e8f9c7e369d208b1e +d605c54f2b27473726a35dfd74ef2c38f4ee8bde3c9c9274ec2134e1078f8730 +d61a6e3c6bf6c416c3cbb89533df0ecaf462b117afa54840f34d1b928914ae93 +d61c0dd1fa397556ba34e7d5da161f02fc58595d55f81339c0284d94b395645d +d61dcc64d0a1782e06cb3bddfbf597663843559b782cf17c6969bb347a8cef17 +d61ded516c3c0be95568ee618b7d7a04ea724cebc702b227dff74c3b608d495f +d627830ab2dbf4369a134e0f9291e65dfc9fbb0d67d86ae41c352abf952ac693 +d627ef18318854291e6594466a659e65ac5d6c8b41254eff6b604aaca3dc1548 +d635156c18ec40a89acfa68ccd98f51c8a34f366611d1d0cdffaf491bea1630c +d64dc4f0d3284b9757725fd6adc80a372bf8e94e7e2d1ba20a8bcf244899747c +d64f2f76cac19c2a36db3eff2bde5ecdd2f887cdad43ee137b1dc217f69eb944 +d64fc8cfd1eb00aa0fae15f9dcd60efd609546dc093a53715510858e4bfe2746 +d65afc7c703ea483f088ee06066d1d5956ffcfdfd55c51ffb18f34c4aef2025a +d65ff73ceaf0f59b41b0aee80d7ead2f3a82ef3b7879cdc4e4a707e02d00d592 +d666b50856e043456229f282ba380105beb94c818b809e514b8e01f836c1942e +d6725d5e38865ce3adb8ba92780294c691a1a0b66071a77d16e178187c099542 +d67a3909709591ee82d5b3ada4e51cf882ab1faee34475901baf0b9efd10085c +d681da0138a7e562e35a370497b6a6fee8463a8dd3f4437c863b42e90bdd877f +d69337966812f960b4ba0ae821a937e102dd4d95fd355ba7f00cef6f73a4bf95 +d69afc56565f0ddb430fed1d4ebbea3c4d62008cc7ba9e03159831810166cd52 +d69c8e89e2aef48b13a58d3f87b2cee355d770119fb2d178bb32341794f275b5 +d6aabccb385eb37b3e6245742668744917c07920f1c54e4b5f31fa519bba1a87 +d6adfd424411d1f4c186fe425362955c6e8ce37fa1791f23182644defe3aba9c +d6c17d211b4899869cd5c22ebaf4ebbce828de021b6a6c0eff3b32faa0da373d +d6c1f05132f67474ea223339ed35b53b193bedf203387c391bb75d0d8f3eaf18 +d6c9a3c9c3963ffe3d5128c8eeea96526afbf72aaf0b83e0638385b5c81d9ea6 +d6cb4cfac88031e7e4eb796c6801fa33d4d0e225d6be548894e9a447191f22a6 +d6d2b2fe64f0d05ab7418576f2a429bedcc9b64b2e232b4235e3e30d96e3ec78 +d6d867e5d0fedf4520a472f4a1a0d747a316d13032874c65bb63e720036c734b +d6f3ec276cd9fd540e4d4dcb7aa0b43ee3ee1c9ece9ca797c0683eedd589b85f +d6f86f0713a30593cce16daf465a21a2be637ed556af8abc0c88e1e6779392ee +d70fa8670b51075b278eda63362355a32d348bff82a2db2ca30b9084e91b5caa +d72cd04c91245462fa71de254ef424ca593edb68bded14876f7e0b613f7e218c +d72e172c01cb3ad8f88afca15540939325f2b415ce51330fa7578ab494410592 +d73a3eb18aee995709f88f0a9cdfae7b286e9b0e4c4fd2044bf5ab53e3e89f18 +d744caa93781f23b3b778dbdfce5ad9ef13fa4ce6b928670fd1cb064429a33f7 +d746edad6930914e4926a286b4e8f76474363b6267d24933a82668b3304b50e5 +d749ed6781e4497c69dc47ae0e00b79f3bd8cde4f6433e3925dd5aac38cf8911 +d74d4860a31d4f30a9404188729a18999f521df0dbb1e3741a7d29fb9b28ced9 +d75c26ae4dea18602f04f0026e2cb51ae40cc0ac26f3bf363e63057d184350cb +d7669b78b38402740d80253327313f1c01b40bbffeb2ebd18535f5db88f7248c +d767e55f47f5734eb14aa26ccbd6c26ceb24e928e223f02da8374acd4d06bd1a +d767ff8a0324c14909e229980dd69b1f74bb3081902024b5a48ec1234d872c1b +d76f25f64fee71c6061192ebda3fea6060fa4afff65edeee125224bc2da7b959 +d779a9e8d3712ee161f1c84a1f579e37801b8d7d19fce9266356c1d2c9d16bc5 +d77a9cdafa0a76168d716334f77910bef20050163f318e4708c715549ffd7e17 +d77dfe2d253a01658c88d0709b34bdebb7c469f7865ef22a6e7c220de9066940 +d77fbbbdcbb9e5cc9d9660bae8fbb52cdf4a16da604f4030f2e08fdbf2f534d1 +d7872d2be6322721d30d6a5e9562dd66db46945249c09dddc5de1a6149e86068 +d7a72675e2c3045b9f4c6c6e2f1857ce043f8143d919959fe49efe79ea9fc057 +d7ab09e4ccd1c3e353814bffcab9526803696cba830dc319c2ce60f7f90bd34e +d7ad951d85c2b9b6295a3ef6670747ae7d59c915d094f63b4af52e2f6d91e54e +d7b76a2e044962fa7c21f1079de891d475ce90c5c4a86aa7f7a531d8184fd296 +d7ba4e442f6c7da8b774a3963e6c08428e3651cc009c4975c2f2b31767dc82d9 +d7bce6d7ba26ca4e982f9a578cecc6b8bf910174dca511d7eadb07ba386ed32b +d7c5c3839ebaadb9668454901f937b1e435d2d2bbe0f5a6e9834f1688d5b4b3d +d7c7c2118fbfcca827b128b6dd0640b114e33c49912a76864e335ab92ad16321 +d7d03445a70169f9d79d0cf2527fc8eae46d1e6ca95af9284890db519be32bf3 +d7d498707cabce1dc4b668ffb768ef1cb1fe70332046ffe22e4db383d571b911 +d7d4d85b3e447d1d37cf02de7639859a7ac6741871cee53612a7cf919a63dacd +d7d6d10118f789f2313eee001fdb0799faf8dd6331307571e6b004141ba4b639 +d7dc42d98faf7390ecfdda87acc4191d5ec1efdbdd2772bce15f2e21c6e4f6ec +d7e2867a53a981c30e8816390010a786e14aa80116dfaf13c4232d530da83dae +d7f47606381469eabeec0e89b5be0a2cc261e535fac5c5f3fc76f557c7040f9e +d7f84292718d5f995566d024a1085b5d577080ebf1f3831c174b0de3ae016456 +d80fd9c60a00a48ab477e184e17db595913dd5e3f0684c001aacc7d63d091994 +d8150491dbc89e7e6180ec696aa9c1eed0f9cd47fb636ddc3ee5bd64f967948f +d817c4f64bc93614e5b2df64e9818e7a99855987d372d149e6469c497b199332 +d818cf310032c103bc0c58c96c015a76dd5732cf4a1039e66f0e237e6e8076e7 +d81aa203c26ee993fdb1376ee0a4eb1d8c45b14bd492d5fcfaad5ecf64c99921 +d81ada2fbf452f1deefe51be2fba7b4a82b64a5ae14c3c2f00a1f2e7579d8f37 +d81f677a942a2070f7ff19afdda0d76a5caf2a6d7aa1ec9e5bb8c37f16583914 +d8250921422ef7168a2203807106b6c4ea6a540d77b51940f559dc89118b1b7c +d82c6fe2efc833682b6e7fc3727e52ef505004772e6b9f51718e4b92053028e5 +d82e7e47fc5e260f5145c8391a6f18c925641c1f2bb12ea2e04b1a98fa5eac96 +d8372a154a8a4a6452e9cc27aa07ae05399cc77cef0c9ce05e35acf302a1ac35 +d838cfc738fee6fa658c094d27a11c343f236629d14b6e3880ef623d678e5b5c +d83caf72854dc1d1b753a6d2c0af7d3b87898b29531e03459b510aa6adfb35e5 +d843cc28abeff1d0f2b1f92e9da0b42657feaedb827c776b1f0ada16e20de079 +d845bf85e4389585819b95631ac25dd984e03f6732b923e1f00e7d2a2a8c05fe +d847a6617d7a7ed86b4691752013d581f9f23f73264f62da56d8fcefc6533b19 +d8562d212613f00cc209a8f468b7f42c46ee239deb54a2990da13773889c6e2b +d85925ee460ea01135b3c69a0203344baa9721bab5a369c47158f9f37e79c7ca +d85b0495aec10caa4f352e7e5f3c7c1f18e46be0bc46ecb673f485ab28d9a56d +d85f119e2d1f6e4edc07d5fc38fc76ed70b5c83be40ff50f9feeae9e56d1d90d +d863b235d971b2ebefa3686e7baedabc556ce674e451c2b6009e0a02b832b2a5 +d867603a16f9143928ed5e09fff0f0e537ce66893de803e12d244f75266c184f +d869ee7e3d74a1e0878875c7b47d9d7246e11da694d538ae18153583cf68ee97 +d86a5b114b7b0fe1208e924cf20225fd382f8cc7cc55423c766166b1554eb145 +d87541036e5dbdf608c7da595998905ce1779fb386857db663adf145a80dce6f +d875459acd3c55380af7c8c3cf2fc4bd7e18fd7314725a0e6a4b19d65b1eb74e +d87b6ed996e8911232ab4a2145ae335db203b4e009906ff4f512a2174be50e6e +d8890a7d24a0b1fb56f57c5e51ff5e260340c98d6b4b7faf34be0d55fa1b2673 +d893556377bc2efea5018240b524c52566042340f0039e4aa286b4cb209cccfe +d8941cb7a8922bcf9430b9765f2d7f8548668f5a600afcbc8f7d5d430b6da937 +d8956919e5407f93247428c5f14cd62e68b5e2b7d749bf175e83a97c5deafc3a +d899d7fd2a66fedfe5a4e81eb445bbff299275e5eae10dca41f25b6b152feb44 +d899e02103e3df065403b66ee98191224f30f8f51a4a95f8325d7fb534cddb22 +d89dc30e0617a5db2c52142b4e88b92fd672cc6850eea6659c017fd0614ba49d +d8a91fc26ba35b1d95f4881f439b90ea3a9129b6b632a9ccc132eb211001e797 +d8afc2bf670b02f298c07f459cb384e960a09bde41ffda24c8c9d3d3f4ed73c7 +d8b0eb99543cf3684baa2f72ef377fa0884358138c4b59cd052e4dd2c3ee838e +d8b59dae7e30bbff89e12a1e52fada87906980cddd9f11436ba139aaa85096bc +d8b7a9114a9b27f9fdba994bb9911da9d42dabbae9ac7408115a7b9d4a926eee +d8baab1da943b001cd746c004dc935a0e5f1cc5bc6ab8abecfc35cdf888d2f14 +d8bc0367c478666715c856513f560cedcf38477a316a1cf55c7470f7515e30a7 +d8be57d114474ee41c509bb385a21e402278af610635ea84cc7e9516c7f74a0e +d8bfe7cf5364acebe4983216301fe74c2d50e34b21cb441472e704810bbcdbe3 +d8c5af189c7208244bbdd2f5e107b84159efb208bb675c83f1b4d402e951d662 +d8ce1b23512930070a31a78495f82d79082d7c2199a5cf51a4615bf8b592e197 +d8d421fb2c9e8274001b6335ce0f895249d44b03ea008829d8fcee7eb2cc99bb +d8d699e0ad7128aa9b3758b8b55e27e4e6c453fa34da7b0b6ad686076d0bb033 +d8dad96e9fbe9babebccb20448bb8429d890c26114a2d279d82d65eb79bd637b +d8edffa6a4df4595562a615c5e699d6fdcf952ad763ba80e97d18a2dd9d8f525 +d8efdb5b466a3ed964f9c377995b6136010e6fe2604c2ad96039803263e8a698 +d8f2593bf71e51404d2a8dbf8064864f680cf57ee71267bcf15aa4c84ac6d30f +d90f9db297e4ad79344f5d0dafe018b39ddada049320a9dfcb058bfeeac18694 +d91348a7cbb41a388538dca62b4d18cd29c3a4b5f8987a1884bb16823cafabfb +d915ac79d8bf60cbe437ac7324c389a572589d32426056ad317454a3ee8d2cce +d91ac2e8029bea5f65b1d4e6f13a41e1051665ac07d14a1bef9a08fda57f2f5b +d92f7fcc8880e70cb61ab39a88985af6810bc533a5d7bd9331701484201617a7 +d92ff746e0c29e21713a66a31390fb360d20cf1294e8c09fcb7372e7fde2d0cf +d932adf3e250e8824e4e7d3b62a434e9123e8f0108285ab2ba0a21a10e06a10d +d93617eac26f7a742dec579bda95c59bd8df215c0e31e83225b0f70dc2a10609 +d936694c419e84ccf57d2f35d7df44a8cdeaf4f6af1a35830d7e63713876490a +d946ebf777d87abcd1f1ae9a483152093e3e4049209776bef83a38fe38245bc6 +d94cc9636a8063fccd7fa289f3a10b086d585429d20c906dfcb66145f8ee6331 +d957f28a73edaacb2edc1506fa3150648531a13a394b91eb758acc32bd3a98c8 +d959622f1df290de9c658c0289de5397f282d2af4050c863e9a6290746557325 +d95ab0c20527d7feca22c8b41f011a5c0a2e89a0e30190d4c8e58e5b9f10a6d0 +d95ccfeb3bde1410a490f1d9e64f0b8c9087da75b31c4f776b448b747b836c53 +d96193dda8b8d69d24a0c48d79571f46fa125baddc0044bcb110aee6a1cc55b6 +d9678ae6bb566e7fd804d37a180d5396af01ddf65d7eb5fc6a6bb2c85423c80f +d96a8107f458d06583f12dc302fddd90d2bb8d08e1cfa9931d451221bf7b5965 +d978a1b03586aa53768caaeeddc4f160d62944a89d96b83073f0b8290415a135 +d97a33275e92cb0ac7e8b4c3fb0e7b6a7796eaae0a28617b19d67c4b6e88da1d +d99b3253958c7ab1e4f2e292a9337e8fd88b217de0275eb180952a03c5d6c53d +d9a73ee56d20aaf146cef59f547720550b4a263c232b08e67d84e81caec4c100 +d9c816cbc69769dd35a2a22ed6813babe2a0b5572260277752c1645aa108ad14 +d9e93b7b244a0fbf95c066014ce742418098c0c98e95c5dc147cee97218f42a8 +d9f28dd8005bae4cae375a827b86d4b07f6ec3b7d2adfb85db1b298451e1dd93 +d9f73b8d03e29d8844631647277a9dfd78a96022f5d0009b06cfae068a7b0232 +da02d6ec3074a45c1f4859ae1b762ee49e13d71079fdfb27ea04fb6438c760bd +da2386fe27b324870904b01e9d7c40b2c8c11ee2b75792c16a8301f8bef7751d +da2f4c52dd8f87286c1d8a0598202c6cdcfc4fc37ca88233d33fe73204f7c562 +da2f5889581dc33def26009b633298cf1b0e4fc8a66b64517cbdb4b65cc66de6 +da390178b546f086b8079a0234bb843d474174e6b9b58f17e3a9c2c9883e98ab +da401d6e70a00d0029613e7875738ae5024dbaa128875ca5393e90220a234e80 +da43e0f542ab22623281b34cf659528a52d1d6f18a68d2c3bef52576bd9659f3 +da4c09ef658681d21cc2c7b08a25e9d3435c83469a0d432aaff02fc298034cf1 +da53c2a06f5905546a5ebb0deecf646f0db819d1b72487478cbc867d4e4f158a +da560f901646493b8ee35e84de2d268f5af60798b521c24f69192997c264c0b6 +da5cb26de4b0058bb0b06fd6d341312f6e45abf4830fcebcc8145954bb495792 +da5ec23821f1d664f98f12d8d6210c26669104705c5c3a1729edd9ac2feb7c28 +da6c902c43b9cf538e7b36f89f50b217a1fdf93de10cbb16bc538d1a8f548e60 +da6caf5b1a7f66a328dca0ebe3524085a837c98dd33a09085d5467b5be641875 +da720d354dc82516688e1c326d3ea49d02a12c68b930f4453dfa35665627d8ad +da7cb1611fe56e42619b590f19060ecb5df847c92ceafc68a1176db82407338f +da870ee36a9259d5032fc9be70db98e633e113e19b52f0e92c3ac00283d13385 +da9895f48f1075a2658da9e7b47b2c8836e10c4d8ff4b4202af43ffcf6860220 +da9bcef7d1eb341b478695f95ef59e9e7f78b4371613aa449a232b71d7ce2df2 +da9e90898f8a0e1a01676aab7fb9b8c09e3eb7d151455182fe9368ec6d64c7aa +daa28015ac380f4a299907589260e836b96daa676992161d0eec098ec70c86eb +daa3f636fc27fab3dc0d576ec37efd0e4b89af08c88236f56ec9c0856b725d73 +daa8992b3391f42d5bb2483ad5e60e170a3f38720a5eca160c369b9ea678f7ef +dabd3f9e10f62183c72dedb1ad7d3f1199ae4b49095215543d6fb72a22df7dc8 +dabda894259209767d014087034bfe7cd77479e7364f79ca73d976c0e875fad4 +dac150dc20867c314794186a19f91bb6a8ee29739ac8cdb3f49cdc2772dcd8f2 +dac9797eefffd3c5df81f3b2cc134c3ebbcc3882312b0bf13ec1368e1612940b +dacb71c3574a1be1b5aeadb17d6d9914a6ef765b38197f97d31568c1c31f225f +dadfa0db0664949e217dd16f89378800940a707f48f1e1cff10d57d97d81c547 +dae28ee9472be7e82f1f2367d552d64174a1c2dfc2c7c4b5b8747a8c2435157d +dae5de908ef168a61304eb5fae448b11a1ef03e0e4f5c0d5a1c604c3714bce10 +dae83c9a77988feb23fd418b86aeda4b7b4a40a6ff62116b52b4a1b6fffef767 +daed9aac49491991c27f0342036453ae92f8a6f191c6f95acf6d30a247d4ef26 +dafabe9df07bd6f4e04b2344057329bf97c430a4e894afc9fe27a89fe71d1d3c +db0acb70be9c1f5e356373c534e327c7bc0c6e2474e3aad23f21eeb30d666cf4 +db12cbb2a8d3e4402b9ad07bfe531c06ec1ec69364684069545bc87e1ab43f89 +db150eb99e20c5f78534a720daa3b35ac85599b229f75bc718f4351947b34983 +db1ddc496aa5f447e8ce161f6fdeb5011d7111ac87def075e7ec2ef4f698e1b5 +db23b258e4f9bb34b22d7a2e4c495999fd2b52e3e028da9113563600a68361b6 +db273fc40751925f2969a17b6ac168777a963516e96a1587a7c48548907ecfdb +db27a025184810c08855e14ea41c5aa59052fdf06668db8fbd7b732181146e97 +db3cf788359228775f31f753cc78595d1cbb2592b8f48b926f355836b8609954 +db4db797786e3b3f355e4a894d46675a6e5456e26a38db03b76df2387e9c7006 +db56638a90f0b36fa4bdca0e5c4eaa420cb67db967b294a7696e6a37a9cb7798 +db57ecf389c14af8fa5702dc48993474b15d7e344ed1d8ceed9194ab5dae4f0c +db5c6543b047a06cbcdba36f53393cf213318b2468cd32dd67d7873f61c562fc +db6aed2df8902eab1981805532322bc4f0c2d02e7aa12ef15a96a40ed8f75fcd +db6c2639861fe922c512f163f326ad3d70529b22acba651918ef0c96794c0c00 +db74697568902a232038690788c6b8d50024b994a1e1c3b0391d0709de220519 +db7555116cd31d4049385f3068f219bd30546c9e821458e98fd4a51f0fcb3407 +db7789efec85fce499ba8a7111639d3dae496ad38a510c7063df1e48edc89072 +db7c075097ce901ca4f64a7e00e6d25bf03c6f2d521dd9c2b7740bd7f8322bdd +db7f83440128904672783506c9d3d1c3fde2cc5b3eb9adf44cffca5f3a2f778a +db855e706871accaf50d5d38cd037773e4e4f9ea112aa1bb7267fa62b17ed6ea +db90f8cfa7b02cac54683d66d77f51503ae2c1e528b2248e19d1ab7789f489a5 +dba319368a3d15fa3ac07f28e2e57559be2f66df7983049a9342920c8efcd790 +dba394ae79aef959d72f2a11b6c6f1800eb8df55af2de2fdd6ae07e30078301c +dbc5515a8242df56ef615697efa3ca54459f22f49f78db6e91f96a25e0a90a20 +dbca77f74e0395b6fe66326d5f4f447cb6d69136e14aa789719934bb0705c021 +dbcab3fe207766e57f5827c115ce2d14ba81563678620027b0e7f5077c350845 +dbdc39d477ef6cde071d33da9f2279a33bc8f98793c984e9ab59985924c7d412 +dbdfb9d6e12a68c71ee00a5cc84c6979b99709e2b7582e30e8e6a0f9d311e002 +dbf05a510947fd07115ae594de9ccb46ff1b6175c30da127b08f636d0839004c +dbf1fc23ee23a1f1c785b94db9e55d9d07eba4f5755e826a7665240fafd0fa47 +dbf24e9d127adefbe4454242e42308eb9dfe9f8b999a9e6c01898523635b435c +dbfc7dc4aee8a2ce5fe3ef40b3df75fddff9435f9b6d778aba1f29d2d690e9e0 +dc180142593ac7e1653dcdf4a30ff330fba75f3ea86ec46e049d1290a31d1aef +dc1cd3cdf5c94f3e349eba31285d700588cabfd1061b65d48b3b27a46a5726e7 +dc1de9299a92b49df4bd1a230bb25aa35f43f16c2b5ea5953119e710d9faebaa +dc2175cd6ef9a5612200b47e3cee357ccd42fd093a4d2dcf199c26ed3f7fd3e7 +dc2890ab56309ec665b5e6672bf2c774487f07d8445ec9c0c0f18b5595414eff +dc28fbe695cc85a163e201bae3d3c5cd3faa0cfbbb4fb6b22838cb70079a1f8c +dc39715e4f4d744300b525690f00b767561638b553371601839d8909694e96eb +dc3ad24e6a0c43bb22a2076e5e01aa6ab5b5e2ecc40cb15b8121495f8fd09099 +dc4e3d13effdaf340cd89155ad26b67d91ad564b17308f0bb42c1e8b61fbef7b +dc59e4a18130683f7181292193166fe44438b7737aad48fe7112bdc26fe88848 +dc646a053fdc5d0fb9bc811ee78f5873f330870f73cb64a11a5b1d307815281d +dc72f4fe6a9f1905f2e18d10acc775a1086504c55d5a4d4aa065f3ea02b7ea66 +dc76857d1b640a3383342b6f9cf8fd3f216352cee5d447ca02551e96c9788d61 +dc79d8b0fd0dd7989c0a08f07c8f2b81bb1d2bdcddffb1c11186dc17d040ce52 +dc8926f87c12d7d3b308f6ab6392b8126266fe4fad79aa78feed90e942c2f5f9 +dc8df444b306ecdfb79cd8dcc6417feee073d3c450a34c3c4e1f66e1f2d478a6 +dcae47a8f0cd10ed1f1568b3b9d43b79adf86a3ad668d4aa6f7371b0f85a046e +dcbf430a4c7b2a9ea9eedd252a09d732aff6c4d8645c916a27d339992596398d +dcc16b793cfcf38cf024b39bb996aadd7c33a2a0d9c799bfe192262442142a39 +dcc8b184ec8379c35a96b46012d1ea0c7ec5db708c859be8d71d9fac12770209 +dcced4a3c023425ce24eba059d71c006e2b12f1513e0e834d6141292cc025aac +dccef20e6fd5af1b0ceb6f2591899e1db3e13a655a0ecb3dd0519fe2d39a1225 +dcd787b75e3bd24b67779a55478ed07b94821bc47e7360717295fc3f1d7db7da +dcddbe592c6425269b70720f6bbd3bb8214950b672fdd4a9caf5273d2a0b5126 +dce25b52eb9407894684e013f565717066f5adcbbc9518344cc2b82df818cf0b +dcedbcf2e34a5ec59cdd99bd24bf77240145aaf00b071f4cc488a81711fbe921 +dcf112ac7ac78bcd70b7dcd913966e5015ce80e40b1428330a78280a52c8d817 +dcf136e9156d1c2488cc93ec7a4ffa07f28ba76e6c0a48dc3608caeba9225b7e +dcf7bc681f12c5eca2459168bc8f2639388a2390c3ddd263396123fb116ed234 +dcf7c97d31297bcd262d9e628bca887e9e64735685e863716271c98b62daccf1 +dd0b94a4ef89877b42433fe81b3c1f525f09ca53050baf2b58ef4843e01366a3 +dd1854034a54e521be2830f67218f9824ae129c8f8331d715df2ebbea9a67363 +dd221201941638aa2879e723d3217d1813ff92fb822460b110892350852197c9 +dd24096a7e13e3760f19a53b617e6c2a6533374fed3157af1f7b0d4c1546be37 +dd266024b6bd795ba1711a21ab999f4983c54d9f37fa860d2e273dd7bd9611d4 +dd31984af777963aa15930c7314976954469626da3366e40ec30f00d665d99f6 +dd380080964c6d7e1f3dde0c9b9def4a91a0da911f3367267003c42952ccefed +dd5172780d4072aae735664aa9b6d6a6ebbf82e59b91ceb1a943a882a8d8fe20 +dd5b4bcbbbcaa65b85b5515ebbc0ee87c27b594e336f7065c77e96e136937561 +dd61de4204bd439fafc062db69c9e94079c6a30d8179b3da7ce122874a70d7b6 +dd639d9ade96bcd60424e79b9a1d7af5165ac09642b1705192bd8a3d8ee8a632 +dd7e2be93b804cb1d891eced45546632f520b0e3d37ef266194270f9d4b4643e +dd84004272631073994bdcde773fa6d200cca0720a85a22759163bda2d0f7908 +dd908787bcab9b4a155f79970959916216769769382b69a33f918a8a8770de96 +dd94e05068fe2530371911fd2d633c9805316dbf9b94b99c6f257b532426f9ee +dd998e006a2a76f9622c911d10a44391e9fd08f0923f202d146109ef8d00d5ad +dda15a181ce161e2e923dd706a4b76790c8c3226c0de6c9868ae7bca093f224b +dda46ad882c13f84a537ead2b824c8fc87b893f53db74c84ca55da1af251efd4 +ddaeba022e20bf6af720f6477fb520435c26400b55a6095ebcd60ec4edc8e9ff +ddb3d25da60487836ddcecd6249784cba660cc1f16cc123016eef350f1a28954 +ddb8c386d2bf789ddfa92b0e102893851b2761ae8734581e0726b47fe083554b +ddbc75bd97f27befd8a22fa1a4110ff41e9aff867fa41fc6adc246460ed1e5f7 +ddbd4ce0261538d5228bdfd160e6c236c5b85031c3e19d12b94d9a94c34d0767 +ddc6311ba2a6232c23ea24c286eee63025342bcb123d573198c2155ecc495c43 +ddcffae90fe35e5d99374f492274cc9f5330f8aeaca0637e51eb1577820e49d3 +ddd85d1978f7a85c38a0a7fb7d2318cda9d3185f5dc4620ad52efd35b3dfe490 +ddd91dbe5df2ec1b6eb9ab528590a81c9a164f5f0e28cf720aa6c232c255c647 +dddb0839f1c14e53b9f39dc1a54f00de60ad649e5e0da54ae503b144e7dc4077 +dddbc2104a958004d0e3f9d3a6574343aa578234be45c9428d1fc218c9be382c +dddced964d5c9de26e507a20678a70eebb388792bc5c742fc130745074bc481e +ddddb458a1bea6d1232022c70edbeefedce86f92174f9579a2f584b1f608eaba +ddddff24caf45818918a10140f9a0464fc67569bca2ece737d6ea4575f9994ae +ddf97d918fa3db0705e13f21ef1fecbada4984b6b2960093034db4098ba4316f +de070e22f0806e4a9eacd65234ee0ef0d642d2074222b55e34cb8acf771afb92 +de1aec8dddc28221b3cc8e617b41bbfb4fef08e53cfb2a049bd360e2f3de8415 +de2158b4f650078785ce801cd3c99aeac156d1cf735cef644d34dca9231b6e09 +de217606168bdba9a3f42afc4533fbce4020a228cfb5de63d2bb507a53ee863f +de28d3b0fec20c14ae5a29354f461fb56f28bd94bf36002d30f29312b8aed0d2 +de2c599239026038f475559485d273daa8466b7d7a996b3aa0ec91e94d382165 +de2dbe975210c088089d6c09b4d8b9ac1b51df2a8b6123cafce7b5850acfff2d +de314f211837989810c8fc1969e45bbd53e74c6d50b5f4e41904c43e91e42c84 +de328f39b382502e12fe7fca9c0f027edbef49aaa81fb115a56de182f3c91bca +de34d477a41cb4705c4178b5af9ff762c14f8fc3cee6c95154ed28874e9a8ec5 +de3bce9798b5c563aeabf4a7234d4d240ac20382ea166e1e23a59cd1fe3a1864 +de40bd4a88c345ac59092e3dc1321903f7025328b4333046b999dd022c445a8a +de42793ecc0c2f555f856e600653fd8e0b9cc09cbe595c72439290e8a5fa1780 +de477837a230c243eddd83b6f1ab7cadc6021a6952d55bb437708502a32b481b +de4a3081a6416bbea6f2beeae55ed525d13f2288683b4fb5ea34842b67f98c42 +de4a876d12553a06f79730e80574b800f3cb55d304c5ec3fb33a5adbd6d3949f +de4b036278d9912dc5818b41ed17b452d9bce043b4c87c792aee95e27279c591 +de5707f22264e22b47be9050f22e12b29397484cf93145636054b6546c4ca7b6 +de57446fe7c3c6da913c59a9975dfd9cf42368bc0bfbaba67e2b2a3909ad9c42 +de617b2dd98807c227400de1612fb77d0ad7818d6ccf9557d59b34c03e9b5420 +de64417e1a451458322a13f6a4e8c9481a2af2425ce01c149040778a63965976 +de64cbfbd781f8e86487bdfed13f88344ab5fdbb64687139b4d8b644c358a4d2 +de74a1a97dc5be158cc07771997492630fd54afe71cc07f677a2d64dff068e0b +de7701e8f7ee860bc3b2e75b108c355957c04e6351156d7734438862a7838e1e +de7fd3792e53c0d9dc1c6c22f09619edc3c6ffc3de57bcc7bc85490eb85ffacc +de94733d83ab47b933a22d2b51cd5d501c269abd534ee5af3645d3b47924d5cf +de96ef980259e07507e31fe7f24c0b93547ab4a737f321f7c76221eb2f5765cc +de994c81ad2d78150c4ca6f127159fa632b96e020c97dfa9f9929e491bcaf58c +de9e492c814f908ec970b237ccbb59823c83ada4f993ee7970b5b8a191efbbc0 +dea26b7bf413c88c32c21aa1a7e2dad685661edc93ae95892aea6223e92c5392 +dea6a53533517b6fdb87d951fb2d050c08dcac3bc2f58f8d739bd80c110e6435 +deab6369ae4391628b4db12c77f20254b5923312beca87eb39467e5bb5add7bd +deb6b2f8c88ae09617befe798843f94fc4e00fcc8d37c41825ae8d743012748b +deba3f68c234ac2f5eede972d8f50559378497b07b5bc98054e454f33d66c90a +debcd045e689fcbe3a4072de7e68466ea2748a69ee5128763f1ec8c7ed0c2ead +decb6a5d34c47ffcabdacb63a403a0bbdf99019b689812253919e5eb6cecd310 +ded359b49b3155bf77c5bcfc5497b7930007e1ce07c97b1d7d1ae6bd6825ab96 +ded44d5220954fee3566ddb51c9aeb224b7950b3c938a23ffb1c6902fbb63360 +dedc49dadafaee872402e111af1111dcfba59d679b43495ec0b2c2c50b38240d +dedfcbf44d12c9076ceae99b3f0266ffe308f0159f7cf4c84a9c6a3f53554a56 +dee2c0902f2477afae3af4b28d7eb2ed4a1568bf6be1e359968548876377bbda +dee4017a940c91e3e518f8aa02ba5012397d1eba06481078310bee329fcd5ebd +deecf2d76c40c5fa11631f74da70d0fe13a6e89d8835fecba39d7c77a5fbf18f +def23883e803a9ad61b30f055157801c22af59fbc9d895bc45fb07d8b7a73bfd +def9c696c788d879691f9592ffe6ab73abc7ac0a8b27cc2152295f7ea744bff9 +defd997e9875c7c46ded662aa77b63d815c7f2df91a36d68ea5f73aaabac6bab +df091a9ee5149b36cd1824116aeec427f6a652310ae42c0b98c94afbb7ced885 +df093975148ea4a263754e7d9ee661081de760c293cf0e07069ea199a139fb69 +df209d538e603fb88c6a48fb1460755dd3c604734e82e0b6490d2d4cb74f9f44 +df220c13333c38fd31cd9818328a8f8b3ecd9054f3d83f8fc049082ea8995fce +df25a773de4bbc5eedd20da8a683c11398c9a5c054d0d77b6202afd90fd2dbc3 +df32b4eea5962c3cb78ccf128a664d93c6f4f42ea42d965bd6aed46861152155 +df3877705d62bdf23e7538d5f9f86728f65768f4db9b496b491611306d0ee064 +df419779a6a351888c6f2b7dd164fd92c7b6b115adf084b7559087f49beda84b +df419e0a0548213c392dab092039f77fef6919299e3dbb5ca4fbcfde3cbbe109 +df491ec381aa8d4a21ee38e205c529ca237566212645bd90ef0866967cfcc976 +df5e286071e6fe2d25c9a26e7115461c7476dc34bd00a274c7dc95c964a1ce73 +df5f62c45d47db14284dc7ae2026cff567b3cc205f69c6550a89959a310dba3c +df6037ca36b4a20dc29e1449e0b1087e6e2f20abf2e56f6ef60ffc4038bbaf0a +df659f37348e19524cbde49f888bc123b34369724da50449c7b8cc8d7babd1c1 +df665e586a34b2b38775f5608da4fb450d568e0251b28900083e220df869fbb0 +df6c3753df2fecd5c920345d9fe1e8d17cd933972c2912e2daf71d76d21dcd4b +df6c634d86a6767bb603b99008eda3cfdd6eeae31f61f8bd733a96ceb30e2de2 +df70c99f25aad679725885402a35d431b72ffbcbff48199628ea665aa0258292 +df748aa395af972289b73a9be51d469431732c6b65d6241ee001b5218f238bdc +df7c3ad45f6df85a7f7b4d022cba7ab4bb65b583369cfd0c9ba304bc3ded0a19 +df871a595dfd256e2c349392e91acae9f415ca1f42ff1c77a2578fe62b634d24 +df891d2f66e48ed62d60c4b8c0fa3c087115d1f4b21858879096fd3b67caeda4 +df8c852f13df22a5fd00e53e28be9403a4574a705c1ff9b70dac5c2bd72c0d3c +df9092f42928fd125198503947d083d98bd965eb141592531891a96de4e2ec16 +df95688c1359556439961acbfedf32253c52818083b4c6d55416b4a16f3b44d4 +dfa1eab93e901da052953c4bfe73187f91e80d2199e83d6b6cf281c11fc62b29 +dfa6d91f313107bf23a4b70b8ccaf8df5b96f114e4efb0a1ec80ccf72e8b8fa8 +dfb3e964865d77f7ef3f83cbb513d28c23313e4705226d52dfb813104639c0b0 +dfc61e49ebb902c2f06f9cc3e76c44bc42a77be8b68666d90949560cca8e153e +dfc8fbf28f9e113fd8fbbf51f9a73ea7e3742655d0d227edc8222c487a50cdab +dfc9a0f0191f0c77c6c832548f87732f0a8bdcfe68a6601654c12ea688eeb0cc +dfd188aa6f6dd56aa7122d76585ca80293ed1ed732acdab0114e650e1e90506e +dfd28d28b21269e5b0b74d685ce2b5a717acc38297cd921bd93687678a8768f5 +dfd7d2388588884ad49a1b64e92d6e76ab1ebec2396061ff766756da32e69edf +dfd7fd3f94cd2c1fffddc6350fd557167dedd83494459f0820bb46c1f0539583 +dfdf1ec8d69071051305176c7e335a7460222b0bbba28a98f82a79837bd75b52 +dfe9bac7ef8c74ae6f38f569c6bc73e2109dbc9e1f7de203f7f36e2b9ca7ea54 +dfecc1d0ef1bb9052cc8d5a60f41e9ebc7a9957050c19be797c8d83736bdf449 +e00c53b7216c45c360db532124f7bf27577e204d13e04ea0207ba82145a4fb9e +e00ef970264f871a11c5e26cf51e5823fcead76811589b4585e625c7b7c1ee0a +e010f37c71f53ce41bad01c0aba0977008a2f9dc884e58742bd70c7f9e8617ef +e0190cde98023f7930417635446ec91f745d56c9f8adab137dab1be46bb7b8b2 +e01941ade3eb9f5bd5ce3e0872e4567294c72fa798610d85a62837bbf22d476d +e019e1c664d8f3018851dbc3dbd7571509a38a4e28a685b9d833441f3ead39f9 +e021c77dcd8bfc03bf2bc484f89944f456a1bf681890329aba5a3f0d04ab7eb9 +e02501e472c6f8f752b573eaf32ba7920cd72672b2267cfea6beebec9402615b +e027cd17bd57784c1856c5ce8e6d8428bd83471ee352ffa727a1a06c4c48400a +e02f749a8d85532caa55d94dd21d7c0b4deaef5c64974cebb53b0022ac490f13 +e035915ce906679129bbe005cff41134078f722691827d37f6e8f253938d00b1 +e039e6f518cf9b994d8721129b303e8958ca43ec4b4d9945d4daf39519360842 +e03e6824a73e092906ec14060e0d03c8e79c86e5a8180f1a154bce105a1e764a +e043a3eab461faf592eeb3cfdc39a489f14b9709d4102541b1d8d17938060a6f +e043b219c20780daca129d6efcc0162e4d50ca6dc759b5dcdc2a0cc418ccbc09 +e046c1a04b37cd9838100a3a9fd16a484242ba8bca5465a24714619a40b489ce +e04e5e8bb2c10a956dfe9aad3ab2630ac513ce6d277f72a3bb03820beb788bdb +e06ca4b85e83d5fed31df0cdcefec7137d6f1066b8ad36450ab5b6c9ad0c482c +e06d8c1b44e68aa63282daf40de8328ebba47f421ebd2a951bbea4f53f4c347f +e070069a4f9ad9cc18e77cd4dd99fd462b50a5c0c088b8a35997a0a4c6a9efa8 +e070dfb966d6a2c3bad0a83db1815400fa9a8f2eba0ffc23813c4292ae9c686d +e0819e2c5294e5f4ea80fb5f879293748806d76a24efe20fc0ea67a6c09cd0f5 +e086abe5b2b50917680e6666752648b53dd8e157a45be67cf5fe15eddcef3dd4 +e0882ee2fb9f31cebf41c7c756d0055ebdf660e38abb3cb30bdf265c6cbc156b +e08c7b013f007b41635b368a252b2b62692cfe00fa9859689e882c86948ba0d4 +e099d24fe6c2c0aa4184492bfc1313b62b2cd901fccb50124627e82ea85670ee +e09f0b7b39d8c4aba8efbc566ad30ca476bd61d1250c556c4b7d33fb93941fce +e0a4e11c840d2f0d7ec499a369744406a79d80f852cf79e80ec7c02a63b666df +e0af5a885e922bdacaa906baca218eceb8246b245a214372d9cc24a3c3739ad8 +e0b6b8fe5e00c6640ec52ca0caf4acf7a724e54d77397b23d78006269916f6e0 +e0cf1842e831fe26a6f03755d5e075cd38689646633ff60b99b3fca7f2299a6b +e0d038d9699ba76886be0d154644452dc1576dabb30a6e6ff6db477fda309e0b +e0d073cda5ac898a85c100a02aee2d2ebc1240c4daf98d929a7fe2aac589ec9f +e0d29d9e9b7493784d02508006237868ed52e21f7e11337166d89ead112a20c9 +e0dd090f6ac9462efb68d1dffa06d690e2ca6c5aaf4098294a95dce6375e52a3 +e0dfcb433f8230eb1db73cd6661efee6629e510a50d52be3bad6a649e8588516 +e0ea36f4715cf9ebdb65d00d5b56226d81eb0c30e06c557c87615910d573229b +e0ef539c3af785909d30d57f21cc891f79bf5937e5bae652751a0c9cc6b58b77 +e0efab415a700a40434381e0ebcff336a304745b1b59cc74cd2998ce90de2a5c +e0f63a9b23ad3934bc81f45c07ae4413d232f7159989ce9ce4ca0c4f1b3c2050 +e0fc8fcd5b755c2be2e763c15d29033fbbaa79da45824ae0faebe33b9af0d986 +e105055c863edc175843ee53d4d602c5b93152d0bab1fd658bcde55a2f610059 +e11733147f835da05b3861d300326b1d3e605acc6a3bb4eeea1b2a8f38675cf1 +e1275d77ea349718b27e18a9668f5559381b5c84c6f3ebf30b41d59629209e00 +e13d421168e920cddcb40da558d8403711d14c7c6ff93ee605504b8459f31f1b +e151c01853254c63634dd2becfc10168b3b8823777ab1d94e4880e46efcdfcbf +e15ad6ed2f69c2a59a77e8a6fb1696a7fde139e46dd842b64ca2ea3661d94256 +e15aff33108a7ef0dc2068e33a7859093844bacd6161e1ac3a45ce88ecf0dda1 +e15c87429bed591a83589f6ce9b68e931fac1b4e86f8f18f4bf548c79d2e7dcf +e15e43187f731caf4e1b9db898acbcfcef62bbc60dfd3059ac6902dd64f89594 +e15e7ae2dd2612139953c9d8a2ea53e6ac5c30d254141d116b5e52b124779216 +e161c33139311557186395d9676fd8e30d08f383a1b519769e2de9256920bc22 +e17366cabe496f3af9aa97726c92fff1ce05fc50f2006bbdd8323c1c343fdb52 +e17451f6ffea720d081d0b37bad2e8ee39b5d3aad2bad0301938bf352c8f31dd +e18c1f39b0c307c89230b9a79803f8c9abf5a2e61234af6ca38136a41ea7a8ad +e194d806e9af60da93cb3c975f86e0502b3a4613ec944884befef6a1657ff542 +e197d2d94db45503da05df2b90d482fdc754037810179718cfd674127561d0f8 +e1bdcaaf46314c5b2ce0c66eced44490b2edbdc46f80b7ea959c8f81b29d6428 +e1c0f2dc9933dc13091062494589da17f9c7c56d7c25c55c8fc2ea50af185d88 +e1c75e02001d4ee8bb09f0690795e42f01d27289560347bb8c618fbe107c5dd5 +e1c7d40c7993a1345f244e2b620daf7669830a242cc21a24ee15ca350502ed50 +e1c9e316d107fc7d3f4760eb063043c8c68065ebfc8abb985ab36e7898079bde +e1cdc7e0431d04f2acf0331aaada877337d180c8414bac8104c5cd346272e37e +e1ce5be3a72eecfa11f80065c7eced6c07291d7570e87a3e07088427925d1d54 +e1d81498edcacbf4c1d55e81e7bb88f837860e97f26d7618d638e890417b6d22 +e1e02215184d60290ae603baec2d0b0d286db28c8c75728762304a27dbc4a69d +e1e115e49bfbb633a33914699968391478e05cf81009bf099c990f14b0f7229c +e1e3f5c042a6339e4d437ff2436f2ba58df725c178558cac17c1d980eda67012 +e1e46ada33a8f3846751d1f006a60247adc46ecafd1a07bfd85d591258811f75 +e1f7502930bd999c5317f3d46eb41e178abe0db0f03a93845452cf2d68b3906d +e1fabd853e186046dff70bec69c604054f729432dbce74bf84aba1da2cba0a0f +e20c4d6bda60036b2546f453740dbeb6601e5a325389dde90277f0c2c8e4235e +e214f30ae6de0e651186692b2d083913a4311dcf6453730e972da322192464d7 +e21bc60e55dad2537aa5d9fccc576e77e3a5df0b68e9d9586e638ab58edf9396 +e21f1f432e224919fee8e6d8d38465dcd13950264795333ae2a8500b4820af81 +e222b6c2e22847c09d7c4940ec33f27544be7752cb046e4a81af75a97e81e42a +e22ed323d82327d55a75e7e4ede74d397ac0f652a7e652b1a5de8a94332af424 +e2326209a7b573877f82555ee53a889e6cc1b656e9f7d03616903ede551d2873 +e23d43af67521c837b9f1d74a733908bb817120d87546f67f570075fd2101f1d +e255fd2cde8b80d13d904cdb869d871325842b1be8c0401bc2b109b472675178 +e257a59aefb47451d779ffaf07d91744d7b807c10196cc122c6c54f231ae7fec +e2631911c9b039ade3760d25736ae3066b7bea891740fa68637a8818ecbfb75b +e26b9b1608ec6c2c693abbf931ab0ed4c2750dddd84becb47ab4ce1b969dda08 +e26d2c889cd81a9f69869afbc11ab8dba2246f18193d169c79ca5c38669c2b3b +e27cc7ebcdba15396fb4d2f1c6da3af9a5549bc9e65506ee9d6003848fdfa39f +e2809371de02cc90f4e22b2979dd66e6a738c16c004d784804dc0c027c0bf2a1 +e28a4a26033bcbc1d400940bfa76b108a161218797a8a1fcf88f314f61e668af +e28c8979784d5794bb46dc0c432460ffa1e74e8a2749c99242e4301a115273f0 +e292969e7aa860ed132c7269766acb9446529c68b89ccb684e2f9e3d4c38f2fe +e295a815838234fe183a87ced71554d1d1eaa24e27a42044f396545e23a73c76 +e29b15935fc33cbe00f6e5a057f48ff0a30f165f33f5c489dd7e7f3a05da4216 +e2a1525222bd89d979f78befe8d9c6089ae34e9cad4016110b13d6a3c5d7e5fb +e2a678086ac415db97491afda650e4de98760261bb8a146d23c672ebca1d092a +e2a817a53321777df1591a5198ca55c95087f87bc537ab947c7c1fec0d321e89 +e2a9a68c8f8c8f8a79da4c6883423b0276770bd43d7cf966100124f6f2dd8481 +e2baec9651ba2a98c3700d2e9ad45e885233608fb2b9784d1864f4ed24250642 +e2bc90d82aff164dd54445c8125aaaba57c0b879a3e4e13a45cd148f4acca564 +e2bead567029da25a6732289c347ea394d2d80d7fa91207501e7626b725fe7fb +e2bf9feb17fe784f91ae8fed66cf98746976c3902d6acba86c1264f59331df05 +e2c19bf8ea19eb0e7fd930f8898251c447c96269289c6bcd40b87293b2a509c6 +e2c6a3090eb27cb1c0b9fdcfe56e047d099767fe8255688fad9827f7ca1c3e6d +e2c793e12565f254896881ba04c07602e0b9cb69afc7a08c922d2684837d4b10 +e2d1c1fd0ed438959c12e422dab349e5be19ebcfe2d5656d0cfd58d571a836c9 +e2d42c4b0fc8cbb0a3d2349bb27371a12f7fdf191ca4281ddc83c74bed93b28b +e2dd120e0c2a12f6db71b1b54e2605adab2f4d118d1b5d66de2e452de7277936 +e2f8f82bea6c2def9543f1f561486b1faab90cd2ce9be379fe738acf1997944c +e2fa1640fb18ec42acfaaa0f1b5cc2efd53fcd1cbe79e6dff35b9f4df5f27989 +e2ff98571502bbd532da3f5f1b2804ef0021791064ecdca331d6f2d422e4ca5a +e306b28c80913193179fc80045a1138fd3804434c832265266df12932ba17ac6 +e30e5510c2b98fc91f54d6f0014cb42f04bebc3bb6ce6b9a10d1454923ccc673 +e3182b67ff04141147921d3f2b7aeb20f7b7776815e7176f7178428a06742a6b +e319418849ec3f90ca731bf9b28d641bc14077d7beb5dc84de80a541bb1a9b40 +e31e6111bde13a915cac10ead5782b4c55cbad37fb94d36e2419dd123037add5 +e3526800aeb82ea92e74dd02648200bd3118458771c23bb7cf7441b0607999d3 +e360929f2c54065ac2430e8df8f40b4f581cae1eff463cd0e8d835d22847e50f +e3667acfb491de68594a28f592991af3722d1ad17ff549b5dcdecca1a6c7319f +e36f49efbeb150957bd82bae812346f64aa2a6aae93ca1eebf305af6547d1732 +e372ff16b6dc52846fc7b8b47543461741cbf740b73614fbbc58ef49dc5dafd9 +e3740ed3f54c445d3f3b1bfe1c08dbe15cd5184b5b63c47dcf6d779ea106526f +e375ace8abf795b81134105c4cd6a7227b3d521d44a8d9e090eddbb8cf09b0a1 +e384a3fd861ef6df7713c854750f71a95fa77587902e61e85486791f14c45a9f +e392f43779319d016b408b5908dfec61bced28ba693d280f7fdd43e6f7d495e9 +e3969e3b356867ee54105b3b1290b77a1b341c4929d5df0498861c00f58d6616 +e39d0b294803b2ff8fbf024a6b345b2b75578a221608ad7f9a723c186b3f59e5 +e3a38d12401fa7f18c1cab21487c98cf20a7fdb050cdd74574dc14180e7f6c1b +e3a3a946d42641c1591cf740211891b8f9c0741d2055dbcd67f282a51983b2ec +e3b27fb5252372c57ae4faf6fb84b1cc2a7232ace49f451c6556f15527ae2826 +e3b391c5b38a6ed3e98e1d8ed6c27a8587cf36bbb5c04a6fa57c1d37933295a5 +e3bc324aef62420b8524583a6febe7c2b764709e47f4feec4f05186a486a91e8 +e3beab1aa775fbeeb58e29d87d2d914589cff1e904b62703f55681af605bd78c +e3d01f48e2e136924a71f1d7d4a1b0dcdece3f6049459f96814e87a35e1d56cd +e3db1bb5bb62a8f02f2bb93b756cf11c9885839f3c6a8ac73698d5ad0beb2a71 +e3e850dcd0cd893612c6c91d522b48d394abee3bc6db0919b3a5ef5722f29e85 +e3f1a29b7bade10fed9ef1d847cb5d0693f0cf9245bc092d3e35acfc6bab58eb +e3fd67f91dbdeec42c131d6fc7497afad0889bb96b9df10da91e609b5a627998 +e40626fc4fdbbcd7e95355c8b5374c3459eaccabff6d9f899deb6b9ea7d1ee7b +e4065314baf6af42d2f63cdec4268c6cbfcec96cec3d833cda2c61e57de82e30 +e406b951cd187b17e7d04dd3c4af77f70f45a0e5dd9292b587aab1da67ef35c3 +e40d624b29f56716cec8c9124522bae80a590ecd91fa623751124dead552c4c9 +e4127da4123e615e79bdac5cb0f2bb6e2bec65cd4d070bb51620c4f62c0e31c8 +e41b349a76bd5e0c0a78c5b2e1c4947af77637ac021eda84ed591cc9d08489fe +e41c10b6dabd191683ea42dae2eb327bed664a8b0ae2af07530ed21a804512b8 +e41c9f0acd0f4bd84b24146313f71a5b5e2a7a8205bfdb582d80bfb52f5e978d +e4241cb12c6ecc14e09e74881a71feb1f7ca900ed155296259c120c9bcb0dc32 +e42b66e27a8b05d84ffad1cefc817cab83b6d45ad969a619996ce3a4aee8552f +e432f67c0453c667147b2734f13c45617b484b863ee4548df0ad497b99539a49 +e43af18c43daaa7e51f76f90322173b153fc51c3a4af40cd872c14fe65b5023e +e46afbedefcbcb9194151984efc5061b0eeff72db865ba16254e7710275fa039 +e4707b887b7dbe9e6e757ad8c2295bc76e867b15189f56ad1c69cd4de92d1edc +e4718353705fb132a43704b5bf6fbec76818e1cad94316863fc38e70dd864a23 +e473be706a7c30068a7f76179b30a4267c3f836e755afa72e4d594e5e2f7cab7 +e47d67c65e8144f9f6c7dc25c83aab0ee5831ba8f1e2c968f26bd48a5d17e4af +e484656389ed33975328e27298b2e867ae6d4e31cc7f75b3d2344ab28206b2a6 +e498a40d1321cafbc260c66dc0ac163860a8a8c6e6799655c9e712eb0c9443ae +e498d2cd651888b3b8ce291dbaad3fe273f24f455d55a5499b0087f8e86cdc40 +e49d757cc53cc4401e9a92493eaf3560cc1d95a5566e8c53daa6b8b1917fb5d1 +e4a08024a237974b28bfca940cc9344582e04fba4de9d917f8bbfdb73d801a1c +e4a608d41e7c2def5549545ce7942513e6d8193c46e56d82b170a77cb5d6e793 +e4ab4b79835c24eef46851629305ca2928e45c3de8ba0778515fa7b16582d84d +e4af82449455e27e6cfd8b0a0e257c6aad68d0569c0eff6a25aad9eda50c872e +e4b0437b3a43c91f7a990be649ea73b41fe825d94f39be7a6aa3b0ed152496ad +e4b3a82f37cc23bf6c0f6b182f4a0d79533f96cd39adfec7cc8c281981fe7b3c +e4b778bf5aab9b78565b2fc58f740bfc44c3df980ff96113d51676db6f887c6e +e4c9229dfc69d83151624564f1f1401fa55ab31429b22895a3ae41a587fc511e +e4d826889c302d4cc3ccd3b4e49ec81d4f5712760b1c90d8144eb2857bbaeee1 +e4e24d89208299d7cec446a966f85773d944e9fb438a8b76f5ef60883eb06246 +e4f923f82fe12eaca9be3f69227185df663db6ba454aaf340f038c8c86f3fe6e +e504fc1368d3b771d810c312073c49ebb57379f8399b7dd80a625b78019ae7dc +e508a0de94e7a099d55baba9b02d2355cbf1a72f31c7d44b9f9ca3b2e0615921 +e50e558a8ef3ad7abde198b941e41e5d7043d46451bd4b6cab5c9497a3921979 +e521d94f73777b6ec76ee05b851e820219ad343e74d0f948869d40a153a124c9 +e5275e84b7bd01f6968c3ce232890322345d760292ec79b4dc2b8d30d999a4bc +e53f1e62298ad3e7d2370e855edb5e314445630b1dfbaa4a2b07ec06dc816c61 +e5443923198cef148d11542ee41a260a00a2cac0f3b8e7ca2741bfae687cf683 +e54ccc777f4de11343c0f7425adff4f26bf6db239c05bbdbcb9346667aa3d933 +e55273e63ad7d3c8be8976a940408728f3d6a3b1d3a9e870dbbe9c749cc366c7 +e554dc012b0a02df8e02fa1571200547947be8178a25564118c22db106b7f78c +e559e45795932b4ab634d3f5af65a6d4cfba8c1010cf7ad8275ba40a3d5dc6f5 +e55bc5f6520870ce7a1ef96592d3571bf5e330df3775f24f564b9889e051d476 +e565fc6b5001c8b26d9594fd905ac767a2c9fbb98c6284cee87d42a97c27667a +e56fbb68c08dbb9acaa61d6e83f726865617898ad4bfd5096096692b9510a6f5 +e57f88985d0e558cf1f5c7084dd5fb533c1208d27a9462846ce01d871b6fc40c +e57fad1f3f601dc484bf26c41c6408a5191b8521b0229d2bbb44b44e0a6552c9 +e5ab5a71efc05045e42563d411a5cea64d29c8e30cb03f6492e2db33a6b3ad01 +e5b405094bda608cbf74996b5202afe93fc4a8f60c92d3b931c607b58b85cbe7 +e5b4872602e8c8157584323ba1449467024fc6d840ba40e5d96a1d68255dea51 +e5c0fac6ce6294026cec63a90648cddad8326ab2af75c3316c1f605315e2a107 +e5c2bd4caea2c00064359ddebed3f7bebd69752c8ca0d6f2b30398756afaf53c +e5c619fe607110944c4429a2b9260707ab72fc13afdb9622ee54b281a944ff46 +e5cb42c5497bc75441218d04206f5ddede6549dd62b27b104c71d0073a7454ed +e5dba8c1f10247d742aee85329e24922ab09bbcfe936a4f4d480c43169935cdf +e5e5982cee3afa898a9be431f11bc4d5e2abe92c6435f7d0b7fedc0d6865278f +e5e8db6b13cd031bfce8fa24fdde97ed235d95df56cdb9bb1c6e31c52480bfc0 +e6016a7fa235437b5e53f2fab13083a61a356d670159db3fe768872203ebf410 +e60457a5bc50b7ab8af05f37a0761183e8cbc618d2471f699f797946279347e4 +e608085d71e748e434b66ea5bdfcee2a0e0f66d5c28261e4d2e322f0a0c621f4 +e608b1fccaaa5a00e158ba98ebbb646504bda79d86c28eb79ad6e83e4b854eef +e617a7d0a6083b9eff53219350a849e6b1a1541bd0979eb7de4979b5c85915af +e631893a5df86cdf222521ce5607a5dc3f9ed1113b4a6c3e665995a2e3d4496c +e6329e096ac52e48c6170ef2e31160e29b4dbd13c309adcbac0469ee4d0e6738 +e6335e43d8354c60c87b93b56be2178f29c526504ac48d0c9a742a8febb71bc1 +e63866472d3d223226f6e4e4e75a5796ab8bfba3a6a758e73907ea00d4194936 +e63c41599b310c56d85b5534db852df83d6a83028bf8e5e618215142ef994d10 +e63d1eb4ced02390a68d9eb8d4725bfade04764783b2c027fa4082aa2dfc7c03 +e63f525f2c7a5dbcd0790177df014f95e9b5a648282913636657fe228197f048 +e6447d38fb64a227ccba30310094c4b8954d5bed70d45e3c6a7947ef5d3508f0 +e64d1657d824ded865af12ed8b5d677bfdb0dabd33d89ffffaadda781c00870c +e65170885cd329f9b3c19358f75b719237b60316ba2fe5cc88996a141f4cb5b9 +e653ced61f72c5e155e9c3cfc227647656fff2e68477fab8e0677c5c6ba34761 +e65b05a3bf88a9fce99c73d8aab3a5613d33addb729018736700e98905dc976d +e6698318ed586c5c2ffff25faa5f29b57cd92dddcfb3d6416bdf9c409f8ee5d3 +e66d25de3eaf3f1ec7e5c707d05f68410f687727571a102892d3f40e46cd6aa1 +e679563b1787658cdb458af5e47aba31fa7e52326b291db230e74bb9e24437b9 +e67edb746d4f922f601b959626412bd0edf2a2fe354502a6997d5159e1d23186 +e6863f20d86598cc3fd258e86ca6e7cd938833811c80c614f1822d5f82fab1f6 +e68ff22a1886a6dcb4578c6ce3d2e59e5e21d36fda16eb1e759159724e4370a5 +e691313432ab6d149ac1255d1c37b19d7bdf24e08ab9e38ac86e71ae244b9f0b +e692e4d3d06d8bd2ee7a3c0bdeb6bc0957d0d727b763375db57e12ecd21c3189 +e69b19687e10c442111f6ad0c650c32cbe561d841453c0960a08f566ee7a8430 +e6a06247651fd260ad58a162ce3a4d6932f077307a610da4d82dcea42b7d3dc5 +e6a2312bdce6b381b89a19277800734e0d83927df62be46c967a994f193e3d6e +e6a5c2c0748cf3eaadd6399be6dc43f9a8c9b4717dccda23be73cfc7d22f559e +e6b1b3f98041a1a7498778f4d6a2b1e10c051ba7fd0d78729bc284b7b367a96b +e6b8ad93d19c69aa93ccc5c21474122fecd5d0dd41b57d8773588397f233f825 +e6b8f0d27d61b07037978e4be2dd2f337c369b1b4f1cff30c57d040aa336a25c +e6b9b5dec63c44e523ae2173a7804d138f7866000bfc94f6cadfc8efd117a6a4 +e6bb34bc14635ec08a2f292bb7a9d38c88cbaba52a42b17328ef2ce32dca4530 +e6bb5df4f339a2b9350504b53bfe2080d5dd39e13cb392ddfae032e8024ec9de +e6bbb9e68f49d674fa90e1b05919a8398a9cc37e8fd31815445de3b17f3b0b3d +e6c9285ad3255049efbb296ed38f8c3f024423c5ab7ffba5899ae8c7f18d534b +e6ce8fe4b95748363a50b3cef89aec7d3aa2420b86301479e0783bf5411c0a85 +e6dbc34ba2e0ffc55ceb78fdb783afa13f90196d31157c2fef17d7ef5663dcd4 +e6dd97ab827a4b1a9e005a4696ac7c8c0cdea7c5cf21d746d0a55653f977b284 +e6e69fba90a6835e4eeb33e885d592d3e22c1149aa2cb7da82e5a6f04c8c8bea +e6f6e0a9311985e18b35f6723298b35106752662e972d8cc19dc984d2e7638d1 +e6f84771cdd6cfe8c5388ad731fc9d5a7b850d4eb38b88ad89b30a0d8505529d +e6f8fd083bf3912cec89c84295bd4759235e289864aea3555d0f0831cfa23626 +e701c8f9e4ec7a1f845359636a99fbef89572f19076df717190b8610aefc7dba +e71213343e94fd32972b23c46c84bfec3740ef62b954dc9cc50eae4e4979fb8f +e71432789a9ce7ca0a606ef56491a93569534a551eaf827556fac7e2ca7e0385 +e71a18190f5675f315811a3655fceefb481c792c0327c8494d53226649997e23 +e720adaaa6a6655f44b43ac8e8b80d3c55bae74984231e1fb90559305151a257 +e720f9725e23baaccec27fb6f035ae2f360ad5bdc6655a6c90370319cf1ca15f +e7210c4fe93fa0a033e169995732f7379224aa6852264fb6a5baab3c85e819da +e72e2a5b59a9187152a75d47c7e42a8f3335732e055c396ee90eae741bd30583 +e739f6fbeae22b285484fab7b46b36d3723d7ef12bd498ad72cde3829ab3fa47 +e74a6d56492b7ba54b7e729f658a991450c0a5c4837ae3b79e40d962aa7b2b33 +e75ae0478419a31b43b8fc66a0fef52378e05d9e2e16827e1288177cea81cd10 +e75c798dac695a2428dd61259417a948779205776239f2b0351b69c27f465185 +e763d141d54e619bfbdf50ae1fc720bc9199f175ccc3a090a3e5a84f5b3f4ad8 +e767addeb5637491a60c4a2d9edddd0b74dc0667bcd0296d09a1357cc1c81450 +e7683b05678103111de2248fa1399c9119f70af24b521dc041bb43deaa0d9036 +e76aedb0652c1802455a66b5d34493ed1ef738f5c4ed556658f670d307b9b333 +e775b166bf0d3d47ee6dd5a3a36583a88aa28f0eb22b61c47589e7c015d17c9b +e77f0c5ceb1f5d9dc1427b8d7847f7ef9340076509c5f5ba508e75a86d2ef9bc +e77fc5f62aeb303dd4ccb45ee7556e997f643cc6f7043f806c4c19325223c395 +e7821f7cc97ff6217bee62797d3810c3775f2a2e4007377da4ccd6f6447c4c5e +e7885ff8aaeb1f51571e5abfeb315dec037782fc3928e881e237f5720a5b66d0 +e799ec331fa1f8511cfbd082b6a87f9b9484c28037e533eb3bbdce23b43652b1 +e7a0003b08a091cbbf0429cc1f8038e8d3edecda04e6ad74a0be86665706cff5 +e7a59f32c842fd33b2bc51eaae8d2ad833f5834dbe45175c76fe5fd2b3977a29 +e7a970793bdea42a5f789f18dff1d75a55aa47970155c39db68c4772d2535468 +e7b9a6d8dd35f05dfe7254ae3b7274ae71311f115fc3ca893c43b839a4145233 +e7cab4893a70bcedebfa9abdb62c82c18acc07c10fe46d7f380567df3a3990b2 +e7ce9c59a45e3c8790a019057cb3c30555de803a7595a301e9ceaf1709e9ed0e +e7cfc9a786413a17a9199702b5d83905b996fbd4da4d78d84bbe9301b3d9c7f3 +e7d00802b42a0fb54d47380142d5f869fc7151a0227c6f42c9e93e6428842e36 +e7e45b777de22879b9bdf0315527cf1428fa65d5fc15dc2d1dcc49aecb9c5d7a +e7e66a8f9ef9a05d8a7952c0b1bbff575619c067b4d9837ab5747dc05a52030a +e7e8122337e7b3d2c446e405dcfb482d15c34ec8ee7d85cbcb4bdf2ef1e7e285 +e7e9267cef35aa782324b7891bd0f8eb43e6b0488802573afa7342dcb80f5665 +e7ef9ac7c1ebb4d36d76b7049924efe178eb3c54d6995c4e55d08df0f2bb7e66 +e7f614afa66cac30a22ca555067eac62d393e0ccfa1090979ac126e6dbda851b +e7f98bb2f22b8999d52bfe4be89e147500f804018c336160abad7f135396b54c +e7fcf9d5821eac87b4b8904df761b9b824b3c3ad0e9cf1f77bc07abb4cacf447 +e7fe172e9f148ea185cc04137f91cd93df02f8812ec5cb93a3c0e0d65ef31ee8 +e8001c0ba49d1344096972839e1c10a5943fcc0ea7833bb376d5b928b38246e9 +e80500579af3265067976e56599c99d24d076a2c4395e7e06343e4afe59d0e09 +e80a01dc9e71c563868da37368e0e57d28cc26746f21c8295af414168c565a11 +e814dba7f90f4dd535edf54c9339ca6e6e69ae12c439a6f9c8669a72c8fe8d00 +e82b7606e3b6f32162852e48ad3edced75f2ae103fe0e576b1fbfc95cd6dfcde +e86843f057a097f910e5423737af0fbcc2442323a2b06b00fcde321c67c2ba60 +e86a717bf88bfc9ba4ffb827a66428f8c3ddc6714f8a7ba6adef247cf6e1981f +e86d16444e729a2361423c910263276c8914bd9576ac11cf6ec585cd812ff5d2 +e870d58f098d5781d9442db61ccde8bd224bddc410ac5be3724f7240cfdaddf6 +e8748e211747d613c508b88c1332ed7ce0068b3305f2e911a52d18a7f9e76e26 +e8756a124bb68504a2507e619cc5847882d6a17f487580bede620dde0a7c2cb7 +e889e62107016f59d53d106294084017f3e2789e9cb2f8a7116c70c957ad6d38 +e890828bce95a7a17baef248fbc1b651c78abc14f17227cdb2c53ef5c6ff5a04 +e89795164442ebfff06f3a2441c32f361bc4cf3b371a96fe0fb6cec27d919d91 +e897b493091d515b57776d13995a421df4e39148b3fbf745932ec27519cc3934 +e89c963b8522bbb39b4e49f2f957b8e9cd6ac14d5ba650a21d89fa7a32808ca2 +e8aa5b4fce54313c083bd328b8956008b37652079d8c95439456dd927e6a064c +e8aee0c4c42959c8b2d8970efe19fd25473744ff693b5bc790130feeecb0c640 +e8b8146acd4723a86ddbfa44fbeee6a49e7599b4c12965d26c97a1d7b51a5b37 +e8be5b8923b1b48579b39898207755fdb1deb144060db543c780722d86116371 +e8d0147be0cdbe9af572bfb7af01abdd70f88f94eae7ddf8e674ba4899cfe5f8 +e8da26b79235fc44dde6cfb5eefdda93e03d776c8417f7d92a6b3be03c74679b +e8e0dbccefa29d8337879e7adda0c2013f6e2963432621c4025e7a2d9d32f2f8 +e8e14e93923e96c1ebeda019dba08916f66d722cd7a03ff0b194a3b2bb093ac5 +e8e2b2393a3bce83046dbd6840155c65d2c78e4f746d88f114363c8e0b122704 +e8e558e1b09b3e322a2aa1740c537d7560e4c3cb9a3aadfee5638d07e144f0b4 +e8ef8ac108aaab7ebe6d6b56cf7005b0515acf603d01937edd990ad1ede83927 +e8f9e3b33eb24a9ac245b6281bd17ae9e0aa04963537d87c9cee5a85c37a4edb +e90193c1ff0bf3c80d9b58ae663cb64d9af61b58222b25f3788aef3ef66feb6a +e9040020dfcb61e5c4fb4ff3a409ab189d55d21ed37690b457583ecca8d51558 +e91748ffd0d02b3e106238a0f9788979a4706aaa27500b63b8b190db7873bc6e +e919ef314f1f753bf8004a29ac40652bf0941192fe18e26339c1b3a005ed584e +e91c7d216966ebfdc07b8df46e6c355210240d817c5f9e31ab4e37fd5e8aca7e +e91fc8f720a538d33ed3571e83d8b1ff9a3e42d6498c3e92bbbe7b9e194fbc33 +e92b7178b0cc5350bb7e2aa55a97cbc2484e5489d20a4077313a627bfe47c428 +e9364b30322b3826c668cce54aab9ee8c755e5764d04e00af06653c98e0a784a +e9441ae41fe13e2801063621c34807761d630994899d1dd2d3c1476f3838b8a1 +e963f121a493ae4b7699b15ba8008152e15ff2479947fd2ffd19da6a563bb5b5 +e96a6b96b3f42916526e10c611a87ab4014fa34ee32e5ee7603cea859b5551c0 +e96d38e63f662e88ca3d9a3cc9729bc789a25f4d07e1c480356888d143ae8517 +e96e0100e3a0974fd3b273b0fe58e8ec576ed3110b96a22c2e26c4438f74fc7d +e9768a1c9db24d6ed13684958b7bd81e3f0a948cbedd3ec15b0370a2fa7b0820 +e9842d042d284f171d5253d4fdbe5b6d241791787a02f0d818452b48da48d4ff +e985a64d7448457cf510dcb7c831ae6520a09acc0e8e6a3126d4c5f2a3c11565 +e98ff95732a579608f2dd825c8dded1cf9f276c5eb229662d5b09319dd4de664 +e990ea7414b1fbf6ed8c8c539e3a0e2d9014e6925f91a0c07024e7ced544da79 +e9a632d5a547cee8b2ede38bdaaa649265e28494569bcf16163952eb90964c0c +e9abc388ccd744d4d5cf17e22261c94c7ac0e46946fe52cc0ee44a7a2f12d8aa +e9b5804306f993a9910e5e6140daf3e46b1c71bacd2b274fac8b97c3cc9b288b +e9ba591d9c92c40d0ca8992f58c721d61cc67383940e5bccc6a759c40cd4fc15 +e9ba72b411c7da3cadc07aec039716468eb7692261a193d2c2eb6ab0ad8b4467 +e9c0f9bd3af62f95555aed592d5c187fd3ad7b07b8e96d5fb8be1a6eddf8ee9c +e9c15bd4ce57b98e0cf906315fceada24f017c72bc597969e22021a8401e2827 +e9d157238fabc0cf3b5969fc2554496e6c3816656f0c7ad42146a39c2aa7064c +e9d643556937b21109848b245c2fc7415bcf44ae9a1bccfcb7e8b51b747ee0f3 +e9d8d5e004c3b3c7872727766c785f31be7878343f87536f59b3a39c2f090a88 +e9df3c799a71abb5ed1609a45c1b56f7cad2e5b8588497387b2d8e6686c24458 +e9f1e9e1ee7fc349dbe1d1e18a692065a2fc306f0ed2ee805908cd1a1b6f14ee +e9f221ae53a10d4d2f195305ec1594c49041a33dc8f6c3167c982ff935ce44ce +e9fbbdbcf289d8bd55453365e6b36a5a449bcff8ec8e231c5ac9bce704accd79 +ea067654a270895fb8b2234cc0d54839274ab7ce993ff36b39f813495e575bba +ea0b657bafc14076bc01ef096e56fce73cadbf91e5aba2723c1588a0c439559d +ea0ebb2dfa162ea4008f50c9f4045af4ec86bf7b7013143e173572797555c02c +ea0edb95db903a75c6e77f5b132e10950513be5ba86db1b32bc0cdd75abe6e9f +ea16a4c9b5f8a3261caf6e23b35153bfd713d67ceebad470c2253d0bd4e8d64f +ea223d4af02f87e98d423e506f2502282915d057834e98e3fab820a0dfc4f1f5 +ea22d01ce22410179e0d5c84f0c55f27cb821113885c919432d944f8413bb4fd +ea40d77ac9a491fa14eb122b50166612b4044e0ecceb42a1058fe7ad975d7e9a +ea4161422802deeb8dee411727a0b1f358433f6b88aa31b02b357bc8be8e58c6 +ea43472e164d86342e1274ec3ae5d9beccfc67f616fa7da0d8285fc61a0992ff +ea55fbf3d365507a867285c100381a1682664734b06f0ce3eddcf2aa0ebeb9e1 +ea57e17defeeaedde7922c0b209f65b37241af667c43ee982f1fdfec00d277b0 +ea5a687aeeec7dff94dfef8feaea37be0284deefdc099c5c614bc73023efda61 +ea5ed575fea551c556ee5330f509040a52b4a4ebc5502f0526178d966cfc4ff4 +ea60a72cb152406e8147540809cd34f9a0bfb05c5a428b18d8244a715a0919af +ea68d44872f84b2bc79a48e2ee470ff43ba3869bb2de06553bc4e544e4be36a5 +ea74f47dff7d85d6d40242a07ac834771de28e66b891a34681321f866809f37a +ea7544a21de6bbbaa8b31a0ddae8c68314242140210a19c98ed9aa3ea87626c3 +ea7658c15c4db5b9c5b3106e1daf7bd0b9f544442a9d26765172f3a33744b3c0 +ea7975e3272552c5931dff35b832ed3090f358147d233537550ed2819f181fa3 +ea8095b51e63bab37c96bbaa25ab52cd367c1a797aaf9b95a8323d8e805682b3 +ea8b66a2c3b27d5f5ff7bb73fc67789d6a47dc14d6b61f6dc4ec18484085e45f +ea9658a789e336d286cbdb70c41297bc0b93fe568e61c54066635ec54c963c10 +ea990bf6f6f1665a58601c6ae52cb9ae976e163a08e6f3399c9fd3d412f5133d +ea9a731cdb9fa77cb6642e64f17e567c225f5a5b1f54c922e203350e95b8ede0 +eaaee5c0a5c5bce09d46ec744eb3ab2861abe7f667e72e0056f150464b4e5e8c +eabb9ac58d949568cf4585426f1f15309a49f8cd4d55cd76be8eb46169e57ec2 +eabbb9615b73090e3518d9c83348c95b160bf5ad3534af3465634b3f161fc8cf +eabffb638d85278e98b506d9859d2ebed0ee3f28038910945b34c771d5091fd5 +eac3c790655c02fe30e2792aa6d62eb2ab7b25fc9a5e6a75d0d91b93eed2bbac +eacc973ab852046e40817b1db84770e4a3e8b50b4b8a457d45aec1a3494e7f5c +ead797ccfbb75c7ee2f00cb8a2109cedf05acc96012aedc27f06a78726f26277 +eaebddc3741acf6a95d455c795463b698e02ea165775ae1d425dff5480d918c9 +eaec52bfb8da8e83fb3fa62e579090a90056462e4a1ad11956a9beec5c2b2d36 +eaed2ec1ece16c73495503ecc7b998b7ef910d34490d16c6bf3dfddb0eb15ea9 +eaedd99d714daa85379004c810fa19ec049eb3b73f603b487eccf16c73c55cf6 +eb0060c775386760fc8008cc6d9e44d9c89961b9b38db2b7f84f884e458ccaa8 +eb00de1344646284f076dff2a8a14833e71296373a6f6fa69c1e54c8bcb450e4 +eb11759223d13d742eef2817eb847fbc19dd2c7b42ff6fd0cb747187febca613 +eb1217785690aba35188f032af3421c3674857d0b730f4d17048016cfb942ebe +eb13674c54d2bdd0492b266fe9d57c468c71ee5895f38f73c15b63a6802437ee +eb1a21bba281728ab4bd5abb5b4f3eab6cb691b2e951fa449a196f72e5775502 +eb1d5d8b33a585d59b7f89502765fe4ca4750c9a8f37427bb4e1be9bad977a16 +eb2dbd26343cc5d7f91ab951710aeb7e9133400831475ab77a9adec920bbf67e +eb2ec79838c98d3958e3a5d0d780352a18a43b41d4fe2d60bc3a0f69763a497e +eb4b4d45379862a8af88a1625a10f9dbbb68ef33831354d1fd484fc4f6fab451 +eb4f3c43c034b4052205fc770f0db040f6146e531a6341991200597bb031d530 +eb5999511c370c8a3afc7b35989305e77d5acc5c3da8944011114a762e2a18d3 +eb60ae46b47260bca2e0aa47039e95484c262b028b7066d699174a3ea7a0d2ce +eb62bb6007c7c63c962b0d5a0b0a07f358d9e846b803f26e00290b9c56450da9 +eb62c4d77814b568773b8b4894f9361e02383c86c86406a7326a10b098ee3459 +eb639dd0c0aac077b01dec79b5f4425d9375a8982943d568b035be0b50bd525a +eb69f29d0ad0b7bf0724ab282188c4b42aeb878ad2a7600c2428769f298a59a8 +eb6fbe33ac40c19969f754b7f0b6be4083ede50e87c4b40eef7e75ad6c882a98 +eb8196fa6f1800d0ae2b03a778855d37b66db72cf6f078718cb32aabe1f38654 +eb872cc706a2d9280bd56068883e45594c2f518a872a5d8ebb2ba3cdb70fb9f8 +eb8a509d58505d6720b77f6823defa28a240e471b44f4653214714846856bceb +eb90b4ab505559c2a1751d8beb36dfc41c73c55f4d53752f8b5e89451c918084 +eb95de1c4a36c3b8ccd55f4b3bcec56edcadc50ede52ea6a62bdfc987b822d24 +ebca6d94db09c45d552d3d38f424261eb744054cd5dd001f8573e9187ff5bcb0 +ebd0a0b875561ae8b60dc2e4de44cf041ecda09471675cce6bb2ef4855709b30 +ebd2479ecc29491b5965db91671e889e628b6e0d571a51f4cc7d322094d718b5 +ebd92780b7870e3dee08fa3dd3f481dd5c4e6bf5ae075f74d32a80c5989915e2 +ebdf59aec4ebebe981ec2276ef09cb06c188be838622a57b7e4c65184bbd4b89 +ebe0f7290c5ff1402457beda3b61fd622431f7c41f5336c24337ff56d96c575b +ebea911680a435f6b0df520b4d9306bffa1860aca60b59a61d9dc3ecef8dcce9 +ec00f8110dab263185545606c79904556b56cf89fc659ebe3d7e9451e6808e4c +ec04cc71eb0bdb437fc1e69581637b3be986b33316218c72066de6801af1bc2d +ec0a46d746f6426adfa986becd5a61bfd06ae243073d41c6decebdb9bbb05db8 +ec0c694ff2272514f1a8c34f8166e90f1ce9b0325d21c2e8f73064bc2453f578 +ec0d6ee94b8b1ae99dcc52102927ad90ee2ce56577ae52853e80ac6febdfa5b8 +ec0fe7bf445049857fc98bf2f83f03a64a2bad7696d70d6805ea7dad2fecc614 +ec1210bbf5d135da4ec774949bcf63674157d80dbaee51a6a3d693ad5d0403f4 +ec15c0bee39f0865d6b5ab24608ebc36234b9f7672d23383e16d7485622d19a6 +ec176a91881b3cf650573ce76ca934a5f4ed343589e3538f8c2364676e3c3f8d +ec1b6ad916337b58a4cbc7bbfa6bb89bf980b5c70dce6a76006ea4578fcbdae3 +ec1cc18c5490f4328925b4fa414a44ea68ff9c0d3ca80fd6164416b48fa2fdcc +ec2373390d42fb08d13832816d4c20a3aded42b2464333e30d579cb7c667e58e +ec2a4e602ede703b7afdbd3cfce85ce8c331ef8f3ba34e81e362e6ad6a0b91ab +ec337223526531deffe197c8eb8ffa42cf0b50d6974d1f249a36edb45817542a +ec38a440886aab831ec1403b3b6ec0f84bba5e19146c7d2fcf4f1edcc052455d +ec3e699cebbf71b28c8a0b77f00f6c51721a3c502804969fead7de11dd030dbe +ec51720291552f4d725bb128d96b908e6c7a4b333adc88eac1e3ebd651e5dc67 +ec5c2b30820940cf06845a20f1a37d6900c0be2f6e47fc49b14120b39f636d57 +ec62601a80489a151b41b23302c26cb97e7e72b8e127fc007f1f70ad12a2480a +ec6491ccbbf57168fb34cf16958f5fa0d3fd924f47b4d70a85007d8e19b3f75d +ec66dda5aa72f57ea108f4522ecf2898b0044cc183983b9607005a52b596b3a8 +ec72389397c4a5e3ac828a699b1c8543285e2e1867b9483ba6a5c9734ba5eec5 +ec73ba1f94266cadb19c228d9b537c56b1efd5ed06080bacda5b39b63dfca48d +ec884d1f4032da7d3134c56380b44d4737efe4863b4c7505998508c5781e1b86 +ec8a6a845200313b3d86d6b7428ab3b7e369700789ad254211c548d6c73f4817 +ec8ba244d320eb12c26f200182ee8f139497b02675e9514edca7177a0d21decd +ec8e5bd246f8fcf623584d0c93d12d36c973934b13a26257715153a8134b3411 +ec9333dfce79f757ef4c85a13a45b52cf5cdb7eb585c16c04b8f1e86fb57ca14 +ec990854327d96986bfd212ba29eb932e784de2cf289ddc488e742a0a6f7f274 +ec9edeb7ea8bde0866e6bcb0c8fbcf639b481e21ace2de527275a421d883b9f3 +eca8f516792af653f8c5dd53f12846fb80676db5d975f2fdba7cfb8f3b3c5543 +ecc2881f5d6128c0b7f36895e7d03d3de42046d07dad5928925136f1b0099024 +ecd688231a157add4fcf6deb687add1d2c973ae0117697f0a9054bb6b4b96175 +ecda30135e19624f394d26e8107d792eea32ebb827d1f4d07cbcc4ebc87b34f4 +ecf1ce7eabb28d3d4ba5f0d0c438758cf1fca082b9ccd84df7a939a56b819f46 +ecf53ba340bf0160b4455d496a41aec308c74790a868b7a3089f226270173c90 +ed00a3ca77301127cdd10a03dd0208b3ff4c98b0f64a03555ced00479ff561fc +ed01175420b72d79a5929e10be3ed56eb2a26ea2a3167ec87ebce5157451a52e +ed0186178a11f8610bf58436f9a4cea06633234e3086605991a41cf046576363 +ed02f024c8b71336f4da89f0f436d94e7548b7e3ed59bc04e2a1020cdc7d7f5d +ed041675d2ffaa91a994873636fef8c46290ce448e87af745dbecded6de7f059 +ed0a55f5d5dfeb6d74e7ac01b70472edca2dd4d4a92faea197ade9575506c9ca +ed0f07bd4d3585657870bdcf585cb6ba69adfce996f62be0e888ef975519745e +ed12a6de5510a30b984bf7f6439a19adac4b541d1a30ed999a459d0cc0adda36 +ed1391c80679c27f14d7cf9d8a54194f7e48ef0678e1c1bf7089f8f821fefc13 +ed15c80a46a4b250a19826ca599bd33b36b0b2803c988a5ed099e46b1ca5158f +ed25562778ad9d53cf357bb4788d2ea64c0deb54958913f957028131519ffaa1 +ed265dc758e70a2f7eb4a5f9334bbd94e22890cf447b9c3613c05596221250e4 +ed29074fdda2a3d4c515bd490e0da86320d3a6590314c597cc9668275a8e1e53 +ed32eb67763a74db7d3c0456fbf3def860f392d9cbdbbafad95a8c8610b6950d +ed363df98bd32d509db66a98760b53e4f00f95d34e1e1ed459ab38f5beebbb63 +ed40c4fe184339306661f009dbc9027d6b3f117dff16990d503d20c14a688af1 +ed41ea6a32268fd9444d0624563359684a75350fd2daf5dc936c8c85d79051a5 +ed4262a85c69fc23d23eaf1131115cb925d9a6d6af4d52a31fc53c17a26e116b +ed4f055ea7f0949d0ae2555005a29902ecb2da57cffa9d230351408c548f1054 +ed5931bd81d4c694f16b3cc5b0126f4a21f9700882d56ee07ced44ce829399e6 +ed5f772487747fc5a4599be4540bdc66b9fa14cbda8f6ee23a9c2b49cc5c4014 +ed81c043e432b654904c1214bad8c5e13ee2091acd5e30762a32c9d732d640d5 +ed84932aa7ef218841414c86f115f11294f4d655f9d530cca561b13b392f0c7b +ed86d5dfe95e7260b06be4f60ec895e320f51b813e2d819ef2e09c6edf92b864 +ed8dbccbc63b89422c79e0ae172f0f3082f701eb67d285d1b7d4a12c88d83157 +ed91922645ac4a68668a6af5e4f1b8e46d316bca92e8b235990766344119f798 +ed91d15c55992636440628e02f4d2e9715f85c4b82bdf3084e912fb7ae7a8fa8 +ed932306247ca5fd7020bbd4a91dbbb82c27d7f177b1da3776095ddeacd1e53a +eda0d4f05dc397b26b456008733b3612f1baec3804b40526e7913b89a14581a8 +eda5fc73d9ec51bb42700c4e09d2277cc926f250616f9b7c0b6147e8d24cc5ca +eda91483f686b1fbee2806f3840a52e9acdec0a05827a769d3623536232ed432 +edb055a0fd667b87ef8f0bfd9a2f05989c243371ef550b2e852a3701f1d31fd5 +edb32f72c162133a2028d09d6da48c8139321f106fd00c450d71b28dd27f7089 +edb582fa7c973bc917f663fcea42b7fbc69770c40882c98e393f35112f208b53 +edcc103050b769c79dc20852568d96658fef5c0ab2080bb6c7874fe2828b6c3c +edd1363ee95377a86444147c1143ef277bfed61f8f48b3eb47d13d085792b4b8 +edd1c9356ebfb88f96b8badc1513f84873c615efc259a75b85983dbe2859d2c1 +eddca62dc58197a55bcbc9f7bd2a5898c36d32e059717da452241effea8185d1 +ede7cf1646ab2bcf4d862a0d6b9067490d827bb4dea7959bf6d79c465fbb8fbb +edec6b7f80ad374572de3a68147b11bd16be345fe074acce9c6af0365c2d68aa +edefa616c4e7596b649b30c32adde9e3542bbf54177586d51f7ee93ec56f796e +edf480b3491fa38dcec6f4b3a9ceb00d1a1b0b5ac0fbb8baa68413a61ba4cba5 +edf8235d4e80728bd16af95540902b1a9da66b5b2612be8b1377ca937b8c6cd5 +ee0018fafaad4421f964f1f6a771cd70055d7a864a649f81a7241dd13e01c413 +ee05cb22c66028de3c22a61bfa3066ae01d40718959b25562c65407261cfa598 +ee0bd36a6b663f9ce9b4bb6f78a58b8dc3378dbe6fe934693c4cdcd40125b24f +ee0dd8c890236df8081ec54d92704cd34f58a646fd2f5dbaabdff79c9a4bb8e7 +ee1044297784ed2fe053f3ea9241238c53b817f266dceb0159d4516a433eba94 +ee11d81ec21d93b76c7be4458335e2f4d9af9dc5c258ae945f2b0c277c80e8f0 +ee1339242485609b1bce2e5eefc04fcb6b9419e14e67b022c0785e073fab1e7b +ee1348efbda4b677454b971c03a51315f0f309971a5b464eff2d51ca65530a09 +ee1a4712ecbbdda59c5366d12b33fe4eb31fc57b0575741df9432bca38a0032a +ee1d6bfb981ba80af5ccb57ea71f31c0629c17eed6bdf60e0c6bd741c3de6f88 +ee1e607196b26bea9684a7efa9902085bcd97ba77e8536798fa369ee1b00408b +ee2bcd20e17eddf611b90e431721f9e38260963b3cdf5e2121cb20befa55dea3 +ee2f4a27cf3fb879aa19e4b0b091591b3ada03111efe31aa90df140a778f711a +ee45084afb98f6be31c64833c70f8361d68df389ab812e43f56f6b8ebb658402 +ee4649bbdf35bdb9c45c3f0c2844e5c29fb635c417f3f3384ab7c3ac64b2d503 +ee47c22b78182a5e15630e6451a63ebfd313222edcb688608cb3a630150356c1 +ee506eb25b4d823f75f013e82ce828da6a13f1f1eb620d922039fbebb418b851 +ee55ebccc472c190ed504e3f5d13d8a180fc2d7a3c3a22556c1cf57eae9de8b3 +ee583131e5ecb2002fa2af93aa6efae28937364010d38bffa1c47cfabef1aec9 +ee60fe9bfe66d72f681635c89a83ab4fbe4c5f09ed8e348ece0b799785372b33 +ee6c4e5f653608cc77abd8b8a9e786b55870a78d9f55094f745bc54d6aad10b1 +ee6ff1cf7e72ae218685803ee7c4880373f879325dc94aae71631e6f2a5bcbf1 +ee7d5179b5972f619828b70b6833d8ab4dc6919ae86632c76a979baf249ac0a5 +ee887099318569afb2b0cfc23f87968d0b685b17b11b6d52f8272af1f8641709 +ee933b1ef217833b57b5e3ba70b9cb3189f65fa5efb074f8746fa293f2104997 +ee9572890cc4673854cf8ce11ae0e5ea91cbeb4d235558fc0eb9c654841c2fa9 +eea7ee1bb76db52e69c02afd67d34ae59fb49a25121177d00ebbe44f4e0036ad +eeb2ac57d6bf49aae2074118f9bceb313b511ec24dd3a7a98a5b6f2a5b3af542 +eeb79373c37abfef14a762b0e25704709936972c228aa7b6b56b812dcbd040c5 +eed8cecb9617865f2c62c3c2f04162aedab3f3384b49ca390ff22efdcb1e7c36 +eedf38eb8ee7fcd5a8d4d6cd4703d4e72b00e87d783f847a1e79ada614d6fd03 +eef34237b79ba44a224deef61dc7870ca3f9f575aa17ef1c12c6b492962966f8 +eef5b74398c1df09f8c5ceb7f9b4e0453e41438ea5bc26b12e0933c4fa68e93e +eefee27866ef499a424ea0a9195320ad4f92352a36750ec352cc44d0f20fd71d +ef03bc54591b29010ff282cc886a6437f32ad19db33265dd15481028e95645f6 +ef13eb52baa66e8ad271fceb24597d50b64ba90dccf4e64d6da223b048e6c603 +ef2e0171587cd669b4beae4e48b44651aa03e2a1eeff34c9a710c16cbaabe356 +ef37596aef1fc36d90982fcba5b7619bb4b813ba8e912a12d7213a0f36762cdb +ef416f48e049fd6f3ef893dc4e8e65b9a04a3ddd610110e05eac2af685a3f004 +ef5cae572c5f87978a3e1b80b566c80d448e76ff08e3e51c706e7e3c5d9ceea3 +ef5d599c6c0219b3d234141c11c9f9a94edf766f66c60aa5d92dc7c43fb3808d +ef6877f6e77feccade4fd89efa0aa78f3fa41069a5298b5c538c4d8416782467 +ef6882e85da4df118e5186ceedf606c51b5109fc5ae77ff092a66ba284f60d6c +ef6b999963fae202eb5713dae536ca4031aba694c08d7192213c41708e1444b6 +ef772cad53f4fddccb2c9e28f73103e0f4d20a3626939a246d983cae836d9de4 +ef8242be22e8dd8b23797146d2e429e1f4c908bf163100fd27edf035e6e709a1 +ef85951160ae3d364cf3fd56b3eaab57a01985eb88a1ad6d34f06426dae5f681 +ef868cf5049c1b70df8cd59d06ae45de19d050d80626c0870027185ea60cb2fa +ef8c2b26ec7026da096bc15b0997f0d53c777711acf06684f136b0c85cdc6dab +efbdc3bca47895ade9ad71aea30b6767bfcdb5af09287f49e5800d8b11105338 +efbf4112a164336e00c6a6a6eacb339512df1245b8efd01528b9b0f107aeafa3 +efc30f56595c4c7d23cb5c7298d03bd34fc1295fc8a9d2a38e9cc93721738e52 +efc609aa68b3307555d82d1a9fb20a2e287f86f742791843fa461dc86a1ca4ec +efce449c943d68679020efd4f61db1ddd7afa24dfeb3d88146600b910c6d8664 +efd2c553a5182ca05b98b6135778ae9a3c5409fa69f430974afb931535927d28 +efd7c19eded4cd39c2a7a3240897ccbabc05565fb90427818b22ebb7bfe61866 +efe7aacee3de1a2a503664a4436f25be0a55fcbc3f99375e024a96f0527c4658 +effa581c20fbc614a4e4ce923f6f8fbbf9dc0e1d0ad722ba2a301f611d14b12d +efff37e9582dc818c678d01535f46c1519cdd88cde87549335a39b7864ac5a30 +f0019505e3d00e709c0e1f75e913dc38efb2ee87437dd99ad8ca1dafe0f5f4f0 +f002459850f75572d208458582809675094dd373bba64871f18b8168dd07152f +f00a221483c7afdd90419ccfd99c436e1e0c0cf3847d6f8b9cdd6f0f12c06157 +f0103983944e3617c08c9bc4287ecbc42831d66aa21bee297ea8e307e3cf4dad +f0149781fbe19495a8d19f74ce94a3a00b39f7c627b8ea80bf1d0b6f9e20b619 +f01b9ee5ae4c6cd0d786b4a1a9bfbef972466713fc243b906ffc12198810ecd2 +f02fe60fe1b46f4bf42688b05f9060b6cec7eeb667bec15f0551f7da3112aef6 +f030ff658ed95afdba4d6ee5fc5b2592ce1ee1eadfb16e87432fb6fea88347e1 +f04b3752ded6ccbe00ed57298b8d4b7180053a20a3daf7643b05da6344c577ca +f04cfbc126ce9463e80478268b97463f940203e9db34cf114515fd490452eaf8 +f051d3b98861345109806d19cfe3a364dbca165a41984f7026ce81a83091ed37 +f0555ed14abe3e020feb621316774ff4d5d8a7abe0f69291ab94206d1f3404a8 +f057b62dcac8b2c1cb9b28c025b7ac66792ce4d751ef2b16ea905cc1c06573c0 +f0591ad40a1ed57b63a6eaeacbf0dfbde6c8f656b6632b8fdafa093a369383f3 +f08280733b4d314f0da2f585cc212960f1b99c08120fdebccd387f98f486810f +f087fec64c7915b5eb2e4c74f010131b2a901db1924d521c54eabb83d5aa3015 +f089add8c256858166b8d54f5d6365cc6937589b42956de50c06d2d2b3b9eb19 +f089bd164eca8392c64ee2077fcc44df0423b8b686fbd8d969d30ae3bec7c507 +f092d96bdab98b800f0b5cf066a450a5d8105092c231ebb8ee6eacf708183ab6 +f09702a17d835c9c6186337c9da32d46cecb169adbfe32593d178b003291ebc5 +f097b7bdb330bcf5ecabadccb20f924badf4460800699c07594cf673e9c63f0f +f09e1edb4e4a7146f529ce7f284b794f7d5cc125946c76e1ef45d7ca55773d3a +f0ad7386df6b42bc0b5107084941b8d8a6e12faae62fcbddff365a509d289117 +f0ae64c358574f55a16fd6a6a733f887c6142f2cdf044e1649b15087bd87918f +f0b9d4aa6a0af768d915491267d255604044f058e5f347b5519bb74e2d5fdf0f +f0c30a3940ef93b3872df3521734dc1fcb4a9498dad72f02c2b12c1491a5b512 +f0cd3c561e4f37a7d9009fa215d8f236b76f6bb35b776dc22831e7c88e5a0a7c +f0cf1dbd898166e4f7aa729d037d7b4649940bac9ad0525d5470ae67d2b849d1 +f0d437a8d7753935b740e7d7a5d3e5338c919034dd3a1c0805130fbcd38fc24f +f0e0dd447097e81a8630a542510e0e1fcbc1a4e9bd9654bf69ddc88757c2f6b9 +f0ecef0b68842b90cd0151eec8b0c5dccf9b72c33eba0909503869de33166af8 +f0f1ddc77c17ca8851999a6043ea3b1a22fbc9bdde14d848c9403b6c0b95e7a6 +f0f202d025ba75e26b03b39d64360ee3ea3b7c85ca62e4d0cf4dae8d59732696 +f0f78b5c44e7a79b1549bbf05c1e8eafca57a4f0ad724a374d27f1af068d38d2 +f0fc89a5bf851906955a97882481e345ab1f62f52856b96e6a571f9a0a083582 +f0fe5b2ff448f35b8c79df5dec9549054071fee815b619c02d7c595afe03f5ed +f0fffac4c009e61079e5b0a5d95960090d1350f86287829cc4330c8fe5de2319 +f10144a9a42a35262bcd4e3064047be6a8635283b473600d6577c08b7290d1bb +f1093b178f71e8beae8b0f3314791260ddae5a869aaeb74e5a3d3155162dac5c +f10abe9599dc387693fc1afcd50e347840085d2840cb0a6f5333030256626bec +f10ae0d4d83018722b875949b654802cc90991ba237a2316c8441606adb2d646 +f12fe448626badc46c47fa2c06665ba5063e10fc8eb5082571ab554b7d7a7e90 +f146c046fa31dee8f7b8e630a13705b9670924a9b6711230a9de44628b3e8f4d +f14a31afc625c9223a65076dffd0554382577fb46bd1bdc93a4ce05de1d8f47d +f14f03e538f8bac90512ba3b917680653bd267ebcd2ecd5f72e0ccd0b49b11d2 +f1528351a702550cde25abe1c303f58e845a4ae3ee71ce40cd3338b43fa6ba0c +f159716991a5022f8b5cd9439c28e1e88e98f2e12c112bd20309f1d5e4bcfeb8 +f15c58a1cad5f6c12f30b56857e940bc1e79c2478a24326a82e1466972addcb5 +f15dce853ae0c3c21b48518f33dc90beb5c9f5f3b1ff06dbe1833b24c1541b7b +f16864ea868ce5a9d7936dd7a07b7d9a1d96e9df6e55afc6b5d8f8e25dc13f6a +f16fd5271fc39bc86fc3e763961933f6250a5f1dfc8ab7b5816dfe635e679de2 +f17ee9f1d34c2e342c477658285d14a8f19b58108617ebe7793728e964cd18a6 +f188d0d736418b1e36a52d6a445f6f6008d32dd2fa9e08f6f394ce7a03520661 +f1a241378a919bf9c15d3a443a036e0b68caa531115c53b40e8ad0d578bba3ab +f1a26bf68e8b412e7c8d7bb7c17305bc39398e6f8c2a6ff8c16254ed6af1a552 +f1a5ac360cc944603097449b61d770d55c01f9d3ee450104557c5594921ccc97 +f1a8641fcbcfe88e81b6c632c68a42aef8adde12164ed082b29369edc61e12b6 +f1c000cba6d25204705bf2d53b70a5be4d2b3a83f332e23e43590b89f13322cc +f1c6326e9fa4a387a224a2d0b5108cc8973883fe0a87392597626853d138e5dc +f1c9d6924ed05e56e8024c64b6fcbb6fffbf562118ee925e6423fddb36528da4 +f1e0cc415b4f01f1a56a883224ec44ebf137f7dcb930a75eac17fe47089ebf36 +f1e68e04a4c58ecccb253a31f7f7cdf9172c4b9df8c57239240a5cbf1d590a99 +f1ec36d999a80e66a1570cbb6c0153ed62f43d8bef32e46a513dde5d1da3ca00 +f1f8f981d765afea950bae5fb3f997d0f5fcdee9a8a965fa89886454683b93e8 +f200a5a6cb7452263341cb84213e00830a65f97f0daebc820f3414eb6509d852 +f2063dd66c634a10ea920eb3f593cba2365f50604e09b16c494f58fe5e511b67 +f21480e2fbcbc1cc881623763dd7886787e8675fe1e6d67317e083642cabea68 +f21ee32bfb5dba35f081b65a2c44f849fe603bacebf8b51e5e2cf1ea63c2a333 +f22399807a87aa72b907cb1f5bcee49b52b2467baa58b5772f645903cba378dd +f22c6a23ce90dbe90d1f2cc42a4e8db82f6ba90d9bdc3d0fbcbba3e960305323 +f23115acacbafe8965c90ed7575095bf8b13864690f944e5170c5671e8359234 +f23de5859fadef8c3efbed5acffec782d120117728b3d8ad9b6726cffe695c3f +f23e21950e241cca17d9fbd13e207863169762a096601e6c41f30686ccb8450e +f23f9c006633b59f383b927bdbbaba1a33ce8de3464480ff8be8690a2108ed8c +f23fd858c1748330c2d9fe117ffedaf005090a8a1d21565106b3e0376de0e402 +f2450e9c97db34cad6e342db1779b3b3d6e4585c6aa35390855847719e632501 +f247a6fbacec2dda2a6fa869ad45b39565fd63726d0bb41961a2e31c3214db43 +f248c35bb77a1642ed91938051848453f9605027d7934c804a19d290ea5cef9f +f25a329ec2fe819fd0f7ee004d5de7f52511c4cea3bc1ea6d951d20da8090050 +f25f20551758f4b98ca979783e440ae6ea9d95b026d187692cd853449e50094b +f26122aa16ed27d50204501069e6413d9b86f6eb668d43d86913671ad358f7fb +f277b4571969b5c2432ba1f9ac92b4830cf744e58b796d10d867d67ec2609b8d +f290efe4f6fd011a5598cb9650d6ee91bfedb15ce7edb4b7fe9b5fce98af3552 +f2924516b80faea98dc72d6ecee9514758c8dfbb32329eab4518a015cddf4aeb +f296075a94fabe06c404309730e88245c66166d265db70e40568d30dd81c70e0 +f2a8c99c7be1531df210aa5c7acb98d33b31f0948aa389a5e4d4120f0015ecb3 +f2aac7cfdb6cc99676bc383b0ffa8f6bef7412c430e9990d977f451057fc7c5b +f2abc196fb8379b792095d5283326d943d9e173889a8f712c087be70b612a9ab +f2ad01019f45e1e5ea7979c93bd4c8c92b45e661d786a7f0877ea17dbfe3aa4a +f2b0cc76d4825701f975adb3f8db2026aa7ff98a12c3318aefe7105728764fcd +f2b55966f5a130acb8bff4c971bff4f06ef282a76328f4072a9cebd4c76bea25 +f2b67eacc62440408f6dbff59585a18b88266c338a1e125861890ee09f43a8f3 +f2b8c6364c3c060cd23112e284cdd09c86e576d6f3648216da31e09a81f38237 +f2bacc46fc8373b08e19f042c8e5864f980624347c069d28f375b23077e9e3e6 +f2bc42503e6a737b808f833f7bb407e62eb7942d78898a1dcfc770e5ab1b65ca +f2be65640e0e133ddf2b4dbfed2ba8b730fdff8f477311fcdb0e405472c0dd2a +f2cce301aec9bc18080eb59213137da56917240e3112887cc8df57ca66b02d1b +f2d539c7ea497e235bd717b612a995fde3b0cecfc3a3ef4ea96ffb0114589206 +f2d83fe0d18fb819a250565ea7a485d665132c9fc845417a9d53f7b8c18d7eeb +f2d91f3ecc057b958282582500a7fc49421b21cd91d142b633c248e816fa4a04 +f2dd513799eebd4df328e10cc88e1e93e4dbd44f2450a1c83b8c9bcb562d90da +f2ddb181b3217d8aaa44ab8ac19fea86ed047fcb456f9560b9d754bbbf055532 +f2e6269c470e0d7eeb600e85612a94cd9a9b7149e5c8889dfe4ad195b3f7ccb8 +f30153812ddcd7c81e401bccd41409c727d3094339f605aa1c18bd64fcd99d94 +f312f85b1a0eae9a584c200681807a2c767d83b151a124cde14ccf015d621da0 +f31aeb2252d7308752391ea37c206ae13a7b3f9400a7bbce2b2a8dcf3b9be3e2 +f320e6aa921c22ff1f980c59c9946bedd7f8ae9602637b744525d20fb4d35da5 +f32376bb590c45c10fabb75f4144d4b3831101bcfb9eda31f3ea1c708972246f +f332655e779bf4826356d8855fecfd25d6f7e74c75ae138613669bb6555329d5 +f3329dc4a2b78c4a59e22a5e5947331370caffd260f12d6a2ba5db87d841e381 +f3389bcd5327a47657ed19e75bda76fe5ecf89d18c56251e4bcc92b08b2184a2 +f3538e40d35d313472c80807840032fcb30b66548d9ed490961958b81914c2d9 +f365ddacfb516608b38a0ffd6c0aa9a29c7fdc7e84579736f78586cbe3fb1d59 +f36c3164e1740a6ef2b2b474c0a4aeac837f7408078b475e4586305f3cff0ca4 +f374fe0546994a70dfab2acaef1241e2c84382755bc0beb28bb5985ebd094e6e +f37d7dec1312abc84ef12a23dfc6b1a43ae7c0a0f04424e2cc270a03c6e3bf28 +f37fcf98692250c6785113438d944361eea14d393a26130e9d48ced1a655a75b +f384963480ed1bc58820fa24f3533ad8bbe9dfd6ef0e01c9cb21e08e677e1791 +f388cb537dc67cd06eaaa50c2edb7166a358b51ae93510405eb5975cad814c8b +f38aab37397302e45022839443114da8ca509e794a88b470952077ef3ad6b405 +f38f85af9dd964d329305934c8a0d1131a53b8b4af2174b084820a81eb306668 +f39a8d0c44ddec55cd7c50a6e09d7a3fc1b447896f994c9283519a9eb6f86d72 +f39be354603f92c6b0af71db62a6e7baa947ff52e7cf3fc5e9bd10e26e766ddd +f3a28f551c78e6d20599d49a3fd28c5da3c8fbe120940e1a2290bd8ac3c0a9c6 +f3a5b3f255dd20b332adb3a6b85f62b0028e59aee5cdb9b0ae817a3c829fb3db +f3b190751cdc73664c7480a413b6e7ece69d56a56d53243c7932b90255aac6d2 +f3b36a4b56b8cc15cccda93c2ab39da760a514bbc78c0f9ff359d6a1940896d3 +f3b93b5fb98fe04e37fd96c45199d4d5ec902a071890df8605d61d5df2445788 +f3b952b4366953db72f794431b3728b56a69b5eceaf1ef651e4c4bd6968c18ec +f3bbeb3049921446f5311c07cd0cdb6c797416616bf5717af6de6c852e64f18d +f3c12207d2e0ed57ba5a01bd8e281570230d0cfab61412bbeb6be831ccfcc139 +f3cc1747b8734a06a0c94ee3b616ee3d4f7a919f566d73c4cfc18b846f01b804 +f3da41cde0a9d37b7c7d3fefa9e75b99bd67aefaf5369a4d12286322721f34eb +f3dd29bb90fcfb591f587f15d97a84a59867e73df1e786e66aba50092a347de2 +f3e9f0ac7ff8107f5c51e0d55087a056e4c8d6a32e1f7986227f9e777ee9bf76 +f3f85baf5559b23d8dce362621385cdb2d182aaf21d613af97df17bd4ac06c28 +f3fadfcb8ca8d3fa6c70e4f0e3c309f7645ee559449b812e110e54f8d0d9278a +f400d83a528bad2db943fa903a4b7bd13914c035a3eeccd113591bf217082b28 +f41a3a57f0535ab51d52776425a81a81d06583e1d297f543d98598e266654262 +f41dc7447c8aea4db5cc37c066d3e3b305db8ca4d0dd3dc40f4362f4e2607e60 +f42ccf62b347a3c11bb13689325d96d1781a2347aaa0411d15887fc1cac5b6b4 +f4340bf14755b34e6ca5b9ebd723f92a6fe2429c4f00dac45054a087478755b9 +f43af061e9963c9f034ce4523de227babe74699973497412e8b4f17455dfb388 +f44c664cf1f5e6053f627e6643620531cb043431eaa34bbc22f9322d9d68b31d +f44d15031c89373d59d82ac61b8bbcb1b4f78476b6bde3755521a12e5ddd0850 +f46330cab9daef8ac8d4f742239998f71feb6b8d0fa06aa23de0f97634178b72 +f4669cbbdf3eb65f6cf77e7270e526d16185eb6365ebf66dec14199bc841b43a +f46db3ed7ab3c11d93720c0999e4c3d66e3850be25cdf1dfc6817d0663a5d3fd +f46f94269f1979535d868dc5061c447ace6a494d9ec83a80a91524f4f72278eb +f471825500e5c9e75a40ad0f3eb3dfcfbfcea0d8d9ba979e72ec144d52a2058b +f47b6b6cf66535ec684254f28fb8912b0b4f5aa2d8b5eeb19ac5c90f22069f8b +f47f9b6528a546da80bef3eccd8dc123291fa6deabdcdabbc127133a9ace9095 +f4869020fffd3eb9cd8e69a82e85eabbf52c97c29acd566e09b37ac784bec62f +f4889c428cefe4a3e0fc54cd34e2ce2f1f9ecb324061a0e4617617ad0926525b +f489206e9c10e96b33c1b5ceede46806c60b76b1aa98c38e9d5916984638d853 +f48ae410f4a29c05332617fba2ad8411ebc615bee759160cd80b1f01bfdc7498 +f490415943d4ea46ac08dcbd5a63acd08e843cd130c60fbe1654759c830e5786 +f49301d93cfd60e0a098b211f0280a0660b1117dedfb7395239f992cd662f74f +f49e8ff00a65f52e463d1775337a4c620d4a725d605dff6048662545d9492cd1 +f4a137426d6143209400c799b3d22895d2b25dfc532d28318e1dcd8c9b24577b +f4a43ded2f986346f96db1f5d45d6f4afe271cf8807f67ff7d2180a41aca4099 +f4a6f283b051bcc823ac6280e868b5443d4493223a8c33fcbf75f66d1ee23b5c +f4b492ac636e66bcd70bd2717c86d5f64fcd2d923d7ec5ce646b8f47a13fd057 +f4ba7e39087bbe6adc263c9edce0b5126427890aea60465e2833bc140bc4e702 +f4c4f4878c73b42b7be9fe2c553a8111b9eed403cf8f349ec016a3b1a8c05a1a +f4cf355cfe7a75b8d03ad9e4ae3b558715e3f9bc352d0dc597b5fa14faa12474 +f4d0e35b37a69cfdbae745317c80c5b7cc833b0fed9f84e785423de7fe667f40 +f4dae1f4b5538719c4495abced0357bc4365abaebec85f26a19ed444d00e5517 +f4dcaf43d3372f21091495a4bd9c26af95b935fe59685fb8bd873109ff01c4f0 +f4e01e956361322ea2cdb53b7e885903ce90d63e6639c7ec09fe3f58daa70e39 +f4e7031c8c33466cc43844d618f73301bb069ad78c2afe384cbbbf1aa847db47 +f4ec13e75a8f33513fb27f64a947ee5ffd0bfcd51b2fdf881cf8e1bbaa7c05a0 +f4ec2ca5934c5a3ecc9b86b8245eee528ce46669739a7696b9f83e2491c5a37e +f4ef2a4c9c422d295f4dc55eaf9c5ba29a37b1a63665fdecf41a5c35164ae4ee +f4f6fbde68081a97f533e65c4f783fd4ca7c226ff8c5aad4541c77d731ffbafe +f4f9b647af0104e4eaeed34a59b05a20cf64bc91c826b8444122fa6d7d812a88 +f507b427fe4f20d8d246333dceb27a5e770e25dd94cac2675cfce918ebb424c3 +f507c53f5273ef7eaf62bfc10a56112333b55812ec0e13141587219aaac473a0 +f50ae9fa3b200e84c4e7002ea52802fbfe74998c36a3a523a36ed3d433686694 +f50ddca26e89c77ad400035eab1910e200ba9487893ce2f50d2f12c942daf87f +f51afbfaf9988edced7a0d47b9a7d32df67ccc62abd21fe197bdcb2c6813aee9 +f51f34849d60b51852bcb72aa6f51b59514176eb389c94756406e22a1a72bd08 +f52c6c1f9f103bd0ee7fc7d9caba7d2c93e2ac4f07a0a6d69a383a343bdf32cb +f53d7b90d97a6394032e44c7916178bd81c5ea0c6656033d5b6b5ea993721ea9 +f5402b9beffa88025ee79be05ef86aafc879b2d13d191df047cfa20292fde408 +f5424ad5f55d549d8e1dae40bf52cced664a1de33f0b141fc30263f28c7c69a7 +f542b3db965bfc2d07af654784982c1476beb499f6b75a6851b18c8d1e278977 +f546f14324efc36bd66e2f1c5b2d5a4cf3afecd96a829d6b1ffd0c4ab3ac309e +f54822fd2db39d9d3d6986eef28cb670b0d7b4ea5905de5d634351b463d276c3 +f54a4199b7de088793fe75fd9cdff73178fc08154139e072cadaf621f6a3af04 +f54de606bdf79bffc83a869239ed36a2916251946c38546f520b89b4189fac97 +f54e53fb7fa1793f311b81e4c71313cd213ed67605ed16fea58688574656af7d +f55dbabc0cc51d4dc128f446fd595e48133b0da5764526753608584a007b7c55 +f55fdeccae919fdea4fdf3bb271b20d780133831c7513074a16718afa1b95c8f +f5680cc0ff2a759f7c8a5bb374b17e384bb125a41df186d1621673cbc1b34031 +f56ddf88b76ec5de4a39c005eb5adf7d17e7bcbbdb987c9e087a6d2dc339198c +f570795f1d5bbe5995a955fe3117817767823d8561c4541394b0e518e9515290 +f577ac76a4b6b0156e07843876b07910982bab07b714949caec629fee34e5bd4 +f5797a4fc375f9e5abaad3a0dc08876c9ae184c8539a01379b1d30ddff9a0908 +f579ddfca9a728a805133195dafd0c716b7e64eddb4c56e257ac079908c626b0 +f58d9aebd101d301f400a14bddb76518e78a6047c868ad807d9ad19b2d0e3716 +f593193b19e389df1e992b1307883657f83cc3dc905b84cf0b4b42378c6c2077 +f59b36b1ea886f1f4512959a49736110aa37decee2d2ec7f28a1eb27e8a51dcc +f59b6f89d26ef3cf6d97bcac5e2294cf35f58b4014e48b662d31c3a7c5e37cde +f59d18872675e2c8abf57c21b50127c0f0a3e6edd8f4382bd8e5616d7cfb0f12 +f5a9ea97988a5037fb79b5ac0a49f2ef36453e59da2195ead1632ddf1626b5be +f5b33b1bd84e7058af036c93b1011d26d2299aa56b9a4cb8dac7eb1c5e34c7c5 +f5b39359a69d3148b514f8184a7f180f984a3d03fc0e446ac223488ef2f8eeaa +f5b8a613d83006fe33ce5cc2ef91870e8207a8f147aa55b971aa6463ff4ae7a0 +f5bea482f876c88bf318c9337811229aff11d75d2bb5e6cfb9e734bd3f1db5af +f5c588e9703f37b5f272e216329af97c251d78d13d3c7676a6a71f6ad78a1edb +f5c6fc9ba43f08cca87259e7a7dc1bce39a9f9ecd955ad7a3cc78e3714d49778 +f5c91c581481f3f53ca7f8987a1a3573e24770bb90483c86ee3fe1710dc5a54e +f5cc69b70eea7c995845a0414032e9917b134b11ac887a0d48298a5fde974957 +f5d1db3ef1ca0910cb468d3fdfb43586fe6f66f9b95ea40aaa0e94b863e2020d +f5dd4bf8ef5fab4c7f25e3359161dbaea342fdfc226d533302fd3065a27cd320 +f5e348425b2ddc52c26094a71dfbec6271c2f499d5f1f7f3151388e85bb06443 +f5f26726afc7fc19f40d38c7e6d9172616196c0401ae15da7d55741dc363f2bd +f602945730369dcce9d235cb56e8dafe74873e897f6b0739f4194a9adcecd8c8 +f6045160429f3b3ebd1fc646d04151d12341751344ef84e388d5b6ef894c82d6 +f60ed1587a857a8eecd493103a20338e0cc6d86d11ac991a3354b746f3ccae31 +f62397aca92872ede1db9c1e3d031f6e858b3400ac5d764744775c5b74ff61ca +f624622d8ba13d9c004afb53c469e8bb81316f0f210e06c1d9bccb7a4b06a521 +f62938bf2d7ebf154f1a06b2fd61a097390faee5f9bccba06a39966d1e08add4 +f6297f79e8ac113b75547628cd1fcb4c48ee3c30ad3b8d464f7a858614ba420f +f6461e948e90c0829e14d93fc247fb979c4a65ea2ede10c178fd13599fec5233 +f64b96540c9c2fdd4841ee4b0a794bdb0a56317d76a96ada71ae0058558a1bef +f652c2057175885d7970fdb76af37e08e4c435f1b43b2f05498ed01444449bd0 +f6549f8c752812db7e8c7b33643b8daec60e708c9da7485b0dbede89194c3675 +f668434a1379364deee0dac2f5a8ce330d80d1488c23c2b4c9a0eeab66b39f3a +f6698cff10f0eb0886f326e3902450d6d4554064a400841f07c2199587f0283d +f66a5f1457df3bfe890ec6a5e2fe5b675059d3fd51970d4fc9104056cd6adfcc +f67dfcce9126ca9be8e36ad020a5913d605987b05083309798a6af3892973a9b +f683662b61384118f64040cfc8e73b083ab2724f1dd23f74a5c9ba6c3e064103 +f68730a26ec0fda6cee1be1628c12d688dd8151be179f2391f59734957022ef5 +f688ce4ccb0d30d81d86b3d8822f68f61436353f6c1571618804620a2368bee8 +f690e579bc21372746d89a01128e150991bcad7e250877011632d02a56cf31dd +f69344ee99f6a13e181f0c4997f2a5102d188b08454c52100f6128c64276657d +f693b07ba5231154865f1d2576bb283ffb25361132867538d3bcd1e7215bf4bf +f697e7686a3f9261af955c3a58b7142471ed90c805413c8f9968b2d7ea9b5abb +f69ef20285c5048eb946032056d7666f18f8253c4a6d27ce101ae81960bcaba2 +f6a8cf514c7905fbf4630fc1df49de7b73d596557ced5d62d4a83bdc97efe2d2 +f6be1c5aaeb8766981128e4bae9790efc23313ce5885ef24af5acff4815c3f4b +f6bfc99c451547b16fc1d97f11b0f1de78d4356a256e6e2f160b6fac9993ae0f +f6c287b1b79350219f23a485f51bfce4a19deb9b0f673ab36552e2cfdd071c5d +f6c5c618e4a99ad78fd5c9916747abe485f96a2a27a6eef3fda47bf7632222d5 +f6c9f23098d0219b3e72d846779339b7d08fa9d42866652562c818ee20623e0b +f6d51d1a6740d635d4ca1a4a808c7691b41110ffa91e87ed973212c674f92d30 +f6d8897a6a2c517ed18bba27bc5447da3c37d108f09a68f36c38e2daeed4d628 +f6e188e8314bca908366a5c2a2ac527485813e5dad0f942094ba14081ec17579 +f6e3a7dfaea1fa722d9a255561fb52c6330c0d386b7f397b86684a2fe55f913f +f6e5921a8a73477f7457caab3ad9f1afebfb7b4ee81fb9cb963af494b1062e9d +f6f3df5059cbd3b308fc859dd9faa802395259f4a79a8e25475cc91e7838c236 +f6f8a69e5e973797f38b5691f9f088256f2543a9fe14acb1f733de1a936fd5de +f70d8d00f95518b2716e6c77c4c9893c8e4a94cdcccfe6c468122cf44f7a43cc +f710a1312c8d8e5676b707c05f869ff352fa0d652316586c43a665ae8d95e8bc +f71872b173763c63c797ceb8698acf0d48d2834b798e6e253618edaef499fbd0 +f73045af3f1f7b973c6e02a6cc25470f6c1ecac75788f4c2fdc047a337b1b36b +f730d24c04ae3fab39e0e7e6849cb10d84430243cd65fe0236707b349a90d261 +f7330df8832f8eca9f65ebe8a3614a4280a66e9af436b5869739f0019ac6981f +f73a3915394bcc9500033739859190fbd98d97042eefecab106b7f739bddaa53 +f73b76a978a3eea1f50bbe252d6f072b0888939e424e42db177709b3b102d644 +f740c0704a3192ad4d825f94f4699bbc8fb6da6472565684df14445ccd996b25 +f744e7f47e9b3fa7925bb64c978425bfde0c588a649969e421884417e32e66ba +f75c9512579c13674235d61c194e3dedba12819c8c3a4c2fbb33e52d45f9484c +f7666deee14b8ac178a659f63fc57a86ec62a86d004129b11d3c6743b0a556e1 +f76e0aa4c982d9255892e2cd84f7d35128c15ea78951fb66fe16f16fdf045705 +f7702e5b15137ede44d411bc27a4f2c009375eef7592ff8fba92cb9877f17704 +f7708651b0fdef4cbca3ea2d7ab54d0f4804b2be949cb350ab4830119204e82c +f7724488fbd424e1e081da22164ddbebc75df9765a556d148110d4a822a36495 +f77836a793916aeea63b8e4c6d0711af5aa3a7413d3d09e4ce8b2f394ffb4beb +f77c538d5f2c5ffad903142aa0a3b7989aecbd7efc9cebc3562c1ccf0bbf819e +f77da16ddcde365bdf6cd87dcb98fcf76a8bcdf6f2ba8b0837d576a544fc852a +f790a4b88bf26cb5d3620f4bb74b777d6badc268a9a89b567243a946bdfbccac +f794ed4d535e22471913abc1d8f4daf780c5bdabd4def86e510a945bc0956976 +f7999d0984d45c4097568570524fa5f527f2b1da67c452577e28de8ec5fb05ed +f79b620afcd78052a80fca9f8a58dc7015ee2cfc1a60d3fc96abcb5e170741b7 +f79deb828a16971cc6942d2d375d24912a48a3ec9acca804b58120e21b25f794 +f7a793ae93e86bda367ef380a525d6c20626563965b7cc11fdff80b860be90d8 +f7b269be12ae10d081a480ec47f2c6543c06fed28840e633a2297fa6e6f56bb3 +f7ba0a19e5f0d3e28198fd268bb48837827c6ce003ed888c03bbdc87bf0e67c1 +f7bf59b409b0756788057de2809d0cc87fe31bfa1fdfdc89b2a8dc5db326b79e +f7c538d348f6933e3de5bd3d6bf1767720da07996c2e9ee69bfd634fc25e951a +f7c746e7da259b409096faa71e346571c79639f8208eb73f1d765aaf210b855e +f7d678d7181921206751cb74e6a4ca95927e74a43ad4f02d29caa55e05f2bb90 +f7dedb9ee717f1742b5435b1f6fefbb4a0153f6e48039149ad8f29f2295122b1 +f7e08ef3bb6a5c44368d6d65475cfdf6b461d66c7ca43219ed18795a0992d757 +f7e39df83e75aded8881095f8e2cd6fb542572bea3d5f87a0f2887364d7b9f70 +f7e7224ea7794f0f3df700479aaabed5ff2f18fd3a09ed70bfa41dfda17c89df +f7ee1ae084b9a665e160b4b1be684969faeca69214513bd33f3bb6036e5861f8 +f7f2d7c3f7e21c24c153c95ad61749f687f1f65ad978762237003bd1a5b9619f +f803f9c6bf80e93ea5e1e7904ef8d61cfa5e5017e04065bc2ef2e01567fc1148 +f81290bc788b17dc6558722ea3df96a0ff93e93914c3a5d58a6827a1012b3482 +f81700e30368e0d5e94f7a8c25baf9e548fed9607644cfaa8c3013dce82fae74 +f81c98afb8f9fef750a9a2de507d4a7b41d548b3ef43d4ed253a41efacac3a35 +f8363eaec5b4d18f0f6a8d2de07b51fb9297fb8b529759c6e33d15274e615ca0 +f83ab32c3a4ed013b0c3242e54ae1ffd21015b96d97a2fdb9882bbe4e19af4a2 +f83caadc1f858c7b8d163bd1f851b393f4fb93f0ca30b4662074e4863bb9a4ac +f840aecb0c41ab7ad5155c96a48c92eeff06986801f77136ff24b92de2780ed1 +f84555115ef0644b7a7ccd0c39aac6e9e9eeec8f9834fc7631ee87788c133e7b +f8496c3a8400754fd5a3384b21c785b376ddaed92513927f74944a7387d34bc6 +f84b928f406e30b1b983295314a7de17caba8441d81bc7f6931005ec030840e6 +f85294d81d99024322744ad44745cd505d87c9c9c6b93a94ed5c0fcd6cab68b7 +f85bb0d402035530d6e45dd9ac25db43aef66c9473ce01a3fdfa0c5bc60aab2d +f86073b0ce6e3b18d5298e7eac1a82657db380c290c0f5fb5a5c775a19da2b71 +f8632cba817eb90196e2d7c75c12411b9d93fda0031eded498627961952931d9 +f86eaa3bbc056603cf1256815207882f01b1a87e71111603c4c3de070ce90282 +f872168a7a5e75719c8194cdd59470e1966c26bcebfc2d103e85c9ddfba27ccb +f880d6122c62b5e1cc290151da99ac193f607bb9c375453dc39aa47ddb82d523 +f881cda39660c642486db7320c228e2b7f5c942a88fecf0c1477eeefe448fbc5 +f88896499c2ab2ba5e638ac80e31131bb1babebf0fa20d76db2db7959b98f21d +f891e7d5fe190be22307783b3c54c2ae407d49a0884931d05f03b8ed1da1d4d6 +f8943a7cc02f0c8eb2930d44148f6bcadabc2ae829eea51862722f59fce25681 +f89b34c585b5a2788413ee88531d6acfed2ef7ed6f611758446862938341a35e +f8ac4f00d0420acd49cb22d5d2d5aca8d0647aab604a67d97f51d85e1a9540fa +f8bb62d63b902688cc2c845009be5cba51e8cb5f3099c8fe1ed7d133971ab185 +f8cd56b02638831219e2a70af7832947f7be61bae3209dd4620448d42af94af8 +f8d29dcc7f01646b87d05c48df522f6ca5b7eb0c677f1a27edd7b74947c5464a +f8d428d71dc81f9f509a004ff64bd0875ec0d3353a5093828f7bf68affcfe335 +f8d80b52ed0a2ddb8346cf3db334bafc5773c3c38ee48ffde8a9b7ad8762c72b +f8da3c63b218ba9ca3ee12da86fa80bab9099604d67ba82d3c4041863dd747dd +f8de9bfaae6ba0faae778468d9ff0f8d2ecec933e914fbb25216fb274e696b82 +f8e205db38a23bd3560893a106a368e068805fbf624abd6aa5abbaf9b03ff51b +f8f62db70eedd64b50c31264165dbd0cedbeafe8db9f6aa2df6a90f3a65990ef +f8f86785e23c7d74f0ac9565d76c9bc2ce5337f1a4c0620ac8f8607926e760a4 +f8fc7027474c1bdedb00d21b9e3e55279b968b1904c6e3918c184baada3cb2e9 +f905b25a1297085ca96f169f7121d4f5e7f80f82927dae766d7b91424c68b46b +f90784acf335acacfc441a9fca445c3e5a9379836c9b2573cd85cab5f90b2d8a +f90f8e7e55704040bf55055f322b929e6eb30978ce509609a3a610237622ac0a +f914c8321d6c94cd51ac3d213834196824e68d1362e741c2b2ff8b9335ff9c3b +f91739871f2140847a54e3945683232623b0fe2823542fd46b1647e8aa246819 +f926aeefd5a0cb342efc9cd729da520bbe0c357fc50f65393e655ebf5d6ba1ba +f9272f201d3cb9458d10c4d5a03a70a0b30509b3126dbb91f93a7c4b043a7fd1 +f93b76b276f8f18da5ad9f2e4eff4458870a86970f187ac247e1da0536312426 +f93b85235c1a57712e502c0b6f1e399c51dd534ce49df52efe2b0564e40a795a +f93c5b024da1a4a1b8843df74c75a39b38ccefc9324ecfb88778f69e5704d451 +f93dc6121641c60395ba83cbe114726860cca73739bbba5c5f2ce23e16c257b0 +f93ec2c88e541eabfc7500cb2a4468ed933f579e14625dbbc8664a1852e5c855 +f941063cbd735c4c397be7adeaf96aa58fa366f38101d14be18b267dcb3636f1 +f94929e43e37d37cf0a0d0d6e8ace9e4482658595306e7425ef096a673080e3b +f94f282dcd091a9a814d4ca4ccdc7e253fdc3aad1cd283dc921b4b005a8992b5 +f950800e908bb7e9d4580a2d3faa4949145c76cc2b73ce78ba2a5efdb030a1aa +f9521a443e08e4401346410625c83af3d853407fa39471505bc2262a85437180 +f958c617310f3d3654fc3755693cb34e2ac18f86d7fd3c58d94d5a54b17999c1 +f95bb46d36d1a535b81b74dc94d8b93ebff48f08127571524c5700d5d1c433a0 +f95eebc64a3ebd4f2a114dcb8d0353f1a8c6c04f169832d671c04acdbb56ebe1 +f95f23561c4fba63d61a3f26e8258a8b0f1b1bc63bfd4a4fbf340d4e7f19ab75 +f960bad7b9e755ddeab184a5f5aca421b2736cce7b7f2aba685715269bd7202a +f9627b10f4527bd30839f823743fe17f91d5b031735be0b1b076257b56c146b1 +f9649ce6cd1a02f70e80d78875fb6dd9b51910ac4eb12d498904cf1b63d2f7bc +f968235cf091b32ded752ae4322d5065a1913953aefb926adb06db2576aaf114 +f9690f7789ff6b4300ff489aab650b212dfd8735b28144b40317c2ed9f40b850 +f97da04dc6d9a319b14303758f22b227e0adaae9995661f18485fab1f12ba009 +f9a3fb4ce1973c8e046741a6dc064ff17cb128ee12f484593d15bde22518c94e +f9a7754f5f1a08bfe58e81cb27ca76a35bf1e603af4a2a8e8ed5cc80d4bdf817 +f9b4263aa509fb741476d78e673a1bc4d62d110cf09076830b46763b5776a972 +f9bbb981ad84017598a57bf27a0538bc4e25e1086acebd8de6f8fda37c260db5 +f9c3b44b6d68fc140720d52632848c8835a7f28bd4cb1221a5b59caad31d8e03 +f9cc05dbe17c2a540faa6f8bd8da73b5b35154cd655a02c576448cbda513558a +f9cc4c41cc6443991e89faece38f266cf0e55d16da8bdbd82c9720259425642b +f9d068214de0f189ab3c314b325514e814468fdc3f81f714929fe2561cdc3636 +f9db7446c2e2ba1ddf85638a2da69e51c5f9bc771317e9b3d865bc01796062fc +f9dd81cee59e7f22085bce8d06e75cdc6377c07d6cbb907d497f9c110938bb1c +f9eaa46c535c492ca185df074d0a37a3a09ed17efd159b347a0b6adc48df1d8f +f9eb345c7c377bd1adcd1f686abe69f721cc7b7073b4efda392c273b10362bba +f9efb407237ccd5b5b21a6e5c35f90414b6e8ea63c112e7e8f6430f7a35e4f8d +f9f83cf2ed9da021a15dbd5532a0b3c0410bda9d12a8d634cda5f900a0d27cf0 +f9f85048d9053a8dc610e300ffe123aea05fdb9a9c7d076af194dbf897275354 +f9fa611d27cbbb71df1e38beca4386c8e3f13488f53dc221ee0c96726d38cef2 +fa02dbc14ab3030c6162b37df132064ce3764d06491c092301e4919d2a81673f +fa15d9783f1f36c70e0394060638ed252f966bc3936f9f41e354ca14f87941de +fa1d96d603af9d4b2a6765801d6121cffb1a0ba8f666e3d102cb57006ce2a16f +fa231960860fb417b1b313d9977a41312482fc22ff2d722ea49e814f50774cdd +fa2521bb22b0d99a7eaaf262f83ab1b14f708ab40cfdc6f728b252546ecf161e +fa2665d9b180ea65ef2e7957def0254dcbd47a3901a43cc37fdae2562b966c5f +fa3c1921d20acb54fdb61c63c9a0180999ccd71e0bb38f4d07a5d40fd90bb802 +fa48c4d0efd796d5d45e13e11235706fe90d79936a1d3ec2b3b4eb85e8141a35 +fa4b407c6a06920011b7be348e28019a0bde8c24a0ffb461624d6bd255efe7f8 +fa514248afd309cc9dad89fbfc1e1ec12cd52a8d59e177435be3f8ff75a87b38 +fa5398527d67b5727a075156f65ac189c2cb25f1d8c7270c51d7cc78ef5a5722 +fa58dda6bd1e27ab928bb66cdc2e1c0a30311283d2b7cb0b455d2b95f704925c +fa6f56248a8253d739b03a9c17d1b9bb6bb53fa3dcce8b5a9a9f8a56df11c561 +fa7b9133f526d39be41324c65990b7c8285869d5a82b516298ac6cf2040ad866 +fa863b16961ab9575e8d2f2b985ba43c7b6e73b6f0f349e4858d0e70be2a3f3b +fa87a2c3d29f5f4c1607c8126e6f1646afe276f543b5ada61bf798fb02af394f +fa8fe0246ac6da2e342fcce3eb79d099412164cc3a2beb2fb231406debf3cc0c +fa90c0c043b27ac2359475f12fb1efceda6c2abf2b3c48e49bdf1fc09908790e +fa91e3eb2a73c2c325cc1ee415e9e54b35674552ce123b62f7936d295d2720d7 +faa5d9c76bab751e33745703280fd5ca1f13d578e99fe7e3d882cb47909b630f +faae3913831eaeab0ac09f2cda51890f6aa28e860d6f2fa8911638b4d05fd316 +fabc492f7e8a9c12d3a7a6b793c9567b44cadadeb499a5cced6d19534dfdc209 +fad3e060886ecf68bdf5868b0135b796b263ff883264461ec21faedb2fe0aa8a +fae418e9b8c1847767e0cb5318fc92d48967d0832a3bc736f5e1827211f540ea +fae79dde2b21ad8a96c0ebe585e1bc1832f6775c5c320b692a53003da141ced8 +faea26e337ac0d46aacecebb607d63e6a78c716be0057f1f2b82f84e83c454ce +faf649cc09b9c048a5ea0f07d4263b8d18fc9758c8a013e279f0e267401ef75d +fb019c07e9c7ca2bba0c9d33f4647fb393b688cdb91790eb28c81a712f800758 +fb04a3aa9e6851bf9af2b4fb8f2cbe9ae620dc5642fad2e90e63987df2af3cda +fb05fa2925727f63f10d6d55b4be452802d575f4d215c67d8368fd52c699d6f2 +fb0b497c168aeabb3749156db67c644743796362d40c95b98dc62978bfa45841 +fb131cf6a69f4e00cbea1a8d4eec1058dcc13c027f2bda5f08daa91e28566d7a +fb1bd9d85401d58abd23c47fe461ad0ac5098fb3dd1a3403a61e4061483bbb87 +fb248fb81ba250bc285b494276fccc264649177ac6ae7fb8a4990dff9176557b +fb26c2531c3deea5f203f584b8c0ec5aeffe4267f355d35434d719a2b9e95ef0 +fb2c0b67b37d07b57c33464833c8ca278f1afad545a922979e9e2209c98d543c +fb3bd7276c539627a5a186a18d5b165af16da5396ba20c673ea6f9bc0be6b2b7 +fb3e62a510b095eb00e69c4eb4f77286553db0eb4e26cf441497e3d1a0e47aeb +fb4868d8ad8e6b3b57bff4f215ee77d8c291228cc2b5b943a2158a088ca4f42d +fb51a6af920e7e57a2f59adfc5f44df27059e36aa673daaa5a1641f1cbdbca7d +fb5e1615d77591d36997e9c2fbb53a1bbe4e21b38fbfcb7c11b8c47233c0bd23 +fb65fce047b666317a2b42794288541665af8f36f603c7595c5943167648fd3e +fb6fe065d7c7a0dabc34ff9077db6725a6f6111446670391b5f4f99c0b0456d9 +fb74d3e66032f969da541522041412f2f78b26263467fc8752a7a5656bd11f80 +fb7ba21470a3d42ff46b3e3c1141a641dee7d45a7721fafc3c996d8b93f474d0 +fb83df3d48197a1f7d532aed222855eb1b2b00ac7f58fb2c23ee952e6b16427a +fb860f89466ffe742029e66f07b433bc6a2dbe3179f7ad9f918d4e36b8dedbec +fb8768b36637f98504faa4fc66d937d882719b6b5cb3f0fb43a1a41955717d26 +fb89cd8059513dc04102344a42ad3a76d4437fc8e3c9865de7e22d95b8937191 +fb90207fd88de379f79a836302b6f11334b58d8fa25e978fccee85073ab321fa +fb91b5d36e022e276c124d6e8ac394ac1dd6c666b3cb64147875926c351a13f9 +fb977ccef0160648cc5d79efba2d4a9c9ff7da8ca3446e9982317e83ea445203 +fb9dc6e56ef97a72d0ebf26b30f2f22b69f9b3af2d8fccc84f33a1e71b961b07 +fb9ed7beacdfa438709692e7185960f98aec296f8dc03a133b20a0628803cb69 +fbaebcb1996316aa17cdeef460fc853d0c79ffd3f1a23cc55c3c9d99c72ac69e +fbaf6b14eacab601dc563d5bd4fea95af360d8fbc4a53ad05ebe326902ebbe86 +fbc7b29300af140d16ad753b3170a3af613a02b05daaebea68612db94939d666 +fbcb794d3e2721b3e1bfadd97a19daa9bf3eeb0edbab37381764ab6468c2cd25 +fbe4b7cc33d5a45139d62c5f269652f553e28d66d377b2c3399b4ccbd12d1e11 +fbe73152c47766a79b2970f43cff060261585c395a36ba21c7a0309c3b7e9498 +fbebf5a994ea0975f1bdf6d6e5d6496e729b0a76967a52c60d22f3a962c15c61 +fbf8402c85c8d7fb45c0b66f5ebb321395beb32c676cb7656b5fab7636966370 +fbf9efc94331f6c996526ad4e7e6f14da20f89360ce3d013864f4385068faa40 +fbfb18a0ee34ee75a4e32933b607ae99faaa5949ad6306b6bac6ebd06765e9a8 +fc07c7ed7943d6ec479e9af81da25b9612a16cf8583b266bb1c294567a3382da +fc0cdfc5f03e78e35b928b04b65b8caec2529508dc9fc602661c9714e4a22dff +fc158b8731151de71e85e0e3670314c7f0a81fda23e7dbf509485158252f8653 +fc1965491f6694ee6bf38d44bf53d713c83a54747de2798e0631608beec9b0c0 +fc19e8df8833a97eb2624c95d9c22aee5f9daf80ca795b8bfd3a0e59cf5b5a14 +fc21f4218cbabd067ad690eca84e1502fc6dec087f51f90b09c9a594d4ee8625 +fc2cee74814e58993d9e80e933d9ebe9a54c9cc9791f7810b0858b073077bb6d +fc44d43577618f26ffe4f1717296957a424c9922d58a50578705b4aba705881c +fc4c82c16e315d1f53255314e43345e20e6e7b15a36730e29563049cf1904bac +fc4cf199a339c51ed9cfdac57797c0f66989cc386336d7fdc3c4664743fbc7bc +fc53fe6edb5bce16c6fc278112081fa938806c1cffd4021150e248c56bb799a2 +fc5dc904a89387aff15f0eb4dc6c99bea1f9c3a2ff64c12ff9d19ade270631bb +fc6281783c80da8fde94a3ba20e519ce94d3a71a290d2860cef7c0f9b8ad4dd4 +fc6fbe2fd509fd4998d5feb3d3d7a2ecbc3ed974929d1719566fb5c9a4895ab3 +fc78c63678da4d99afb63a16a714bf03d17a165d91d50760c4ff9afdc51a3343 +fc7e88c730888ab06ef665b0ac48a920f9e065e081bae88ad9d69d502d7d4fb2 +fc895e9d80055191dd511f6f44dcc57caf6d7a856523d413165862d79d205552 +fc8bd407f1d9fd3a2a75e8bdb672eb3cce1daf18bc4004341b6917f58eb752f6 +fc9204e1548e9def5c4b99dedee75f2769e92353dc30588c2324edb19cc76e16 +fca113bf8258b1499d5d40719cbf4b374739e4355f68bc2cf31bf9cbfee6cd89 +fca9d8a8a011a33b77280df9384e63df2e1b736a6ae769af6206e2076c53380e +fcb01ec83e183fe90c1b628773bec0c8cf23528571a4c5f3bbdd9c640dc5141f +fcbe1a5c36b2ed53110df6819fef6702bfa9a93c2f278001cc7cc6b14a26d3be +fccfdc3ea245adeac43098f9e8ce22b6937ee0233ed03bc31b9f3ac6c42ebde5 +fcda6a99f6e9f4f531b3351cecfb9cda678a07357b31ae57449c8276c1db0237 +fcdd7fbf928a5d88259fd9247909cccc7f017c06a5a5162a50212f69c57f22f7 +fce039f9497e4c6ee9634fd541399bce37826c180efe097dea45ebb8b32309c1 +fce54dcb036c0fd8990eb1b4660d5514ed008b71169ce4eab800b4b5bf1885ab +fce7c5ed6101de757c9b656deafbc97c66028937e526ff3b24d24a380c025632 +fcea912992cd312107f82f395b5f0a9b41890883aeecb7080242d06762be625e +fcf5e21ef4fe4c3f54856f1ff6105a4230a27c5b1ff389fe189881c3fa399151 +fd0712c3a4c1d336a4d372f212b2c901d165978aef415b2e812af46f2244f22d +fd1792a36ed915206ab1b55bfa402ad9fde61826ec74f809821572d883497c72 +fd20648f26e90e2bdc19e0cb8cc6201db1a877a5670376c1ee5756f33a268abc +fd301d1ca2326237474942948e470f97e0d7c91f720c31a15983d1fa4ec331ba +fd30e7d11f1a71e535d1891c27c05060f34b952e3c6dff711959d0fac315d825 +fd39d6a54c124f1356b219702e3841e72b1808c68efa798ebd5109095a1a2e5b +fd4d804bc2a3597a3ac64d5242bdb3bf870dc5eec2e94ef0513a340257d162f9 +fd524b4bac5a91fc9ab13c0b03466b52d4142433328e70456a46a39e5a53d8b7 +fd6507282131af41e0edbf58f941752d8803cce30508cfaaf9d003b091516cf7 +fd66021c1d2a2b88a83faa4711310fc60cc3d79a603a7430f4fa4dd5ee65a573 +fd6c84706e40530cc3f5cea1b0ac602d008be0b605ae54de5072936342927bc7 +fd713df6f7cba1d17a56d272fd817d44fe1bb8972a9728a3c81e5c86a095e391 +fd731681652240b74659e78c081eaddd4ae2cdcd7d7f76203fad74f14c63b825 +fd73c88411e41b0606c9e2fe0b6824b5fa90d17d165ac9aa28351c9c548af642 +fd75cf21ae2169fd7e04c32d539669f4c58dde907517cd0bedb2ae47fd850072 +fd7fb042d93dfd76b77bd113ff6948029a3b7959943d9cdbe9926b1969e7bf68 +fd80001356c6e8f5b66ab587843089092f3c295116302dc34418b132e6108340 +fd84cee9f00fa0e04e70d6da05137c02637d4820d1fd356b71c483ba2c75e885 +fd8db338459fde7474d1bea1e6c5c1a99bf3c91ceda50006a99286f9138a1c2f +fd935ec4ab965c154ba32a72563e0e889f7d91c9211e225d5f235cd816bd9027 +fd9675cb975f6f1e24289eca205402e737f6c76a9ce85f2f478336efb0ccca7d +fd9dd1fe2a6242e2c0203902b796abdf6813432bfcbb9523ea4d3bd0e04e6dce +fda3bb787118f549e3b661c2371533c66f760b9a5b15609efafa5a4bf7de9522 +fdb1ca7680960312e2c4665d59b0f6aac999325ddc2f1c795e700e838974558c +fdb71c35141c34b75e963b8206ac0258e022442dab8341436027971a360aa56d +fdbb84d62f8ef7a469b421c377d25283a5d68586c6f55f025cc629e0346b0bdc +fdbc4349074b4d6290aabdc08ca0bfbdeac55f78dddb047b2bf7d611ac84dded +fdbe890313309ca10f0f096c305a0f75b251fd726e99b7102152733e130e173d +fdca6600e968a669862900fb411903c609d97ba8868388ece1c8cc65bc844b8a +fdcc5f15ffd892f48511d9235d14bb5e06fb98d1b56f0271b2cb27c1e7ae7834 +fdcebfd2c7860564c7ac8015ab344a3d269978b0f9f88980be49650614f61a03 +fdced30e241210a4ac0ebdd1141c5ddc5ab2872a8db9ca8f20b26271940b5357 +fdd829c2129a94db71cc722c30b4864eacf6422d469fd2b0f616c914de86c28c +fdde3fa577a4dd64117b9a00b4e3822b52319d9b502141a3b4a73d232b47c924 +fde38bb02a528adbb55e691e7061ae3de17d86601510508e843277ccab8d05fa +fdf118e06c89f5115870493a7ff16bed46c0379841efc2ab169c02d18e843abb +fdf437b5b68289afc6a2aa8d11fa2cb7f46616514f296be055a85bf6102a7c2d +fe01a1845be03eea687caf37bf7eb9c2e3f56e688330d7ad40c514c5da04f7ff +fe0ddc9f1511445d5a2a1f67dd6a9e38366388a44fb49cb8838f424a65094309 +fe0f97cdf5bf23412338221b5e04648b957cd09e23a9c9c39903fd4eb6e4a750 +fe13121c1f6d5fec94d40d90ff2330833cdb49cd46a2d56273b1ede60d8bab8c +fe1e863ba73bb018e52dab20ddb7f1746c562892dcdcd1d3c4ec73f32021519b +fe22ca177ae8ab2eb6cbdc92cd59160e12c2d0ba9ec0e778dedac4da9785c996 +fe2f4225477134aeb60ed431b068a8c038c2c8e6f4b9800a9d37af060a5d117c +fe356756e3df9e3e1fe19490c7bd43c8584eff7e3fedda722c84196228a04b76 +fe380193776787c71aa799cc2856fbd0d34c73109a8fec64e4db0dde499b6052 +fe430485b2cb91f7f42669a47dfcbb13f61c53be14869cc5c5cca15c175363d4 +fe43f056c091898645d60e475de70d111f8ca733bb6c56ec70aafcbada232327 +fe50fe213f020e9a36f53990ebdfb3717159bef100b742875f3a1f5e18a28216 +fe53316323f7fda27551910df635316db275a137b426a9ed3c44722b9a3cb981 +fe6b634bf0075856f40fb1bd3e55c622d5835ba3d9437f83a5b6fabcc0878b1f +fe70e9523692057162585585afb726769c89a1b2533ec23f073b33f06553d96c +fe7204d27b92bdcc0bd2091dac904e86753544fd8966c33a5a99deab51d20c21 +fe7372a8ba6acd6ac4849e8d8ac5848a7d2e068bc6a1c7b609363f0764bf9559 +fe76538e8a45988cf7cc00a314d0fa39ea6404a37fcd4be2e987e55e646ebaeb +fe7c46c700b8b41ef3f1065ded7af1354415153e46bb4d3d3bf9ae386f69b098 +fe803773bad05fc8dd49bdb23bc4a51a4d0dfe865cb25247d04f920370329685 +fe83a5f65f38725fd6d92cdd2f1a9b7137c23f60ac0dbc1a5565c6bb98dd4a1e +fe8e12c1ba23064a78fefe21d1104161afe9f8303d99be56796226400b181ee2 +fe975c79428d644569fa0a514e65b9c42a5081d77c82ae5295369d89fbaa2fbc +fe9855b6b886273aa76c4184070b6fbed0a666bb79ae4ed5936de573e53aa1d5 +feaa379aa98cee8916f9e8beec2f2f40b01b041f615972229a92e245844377ed +feaa5257e12b1baf3c2ef611d53761f8ca956a528ef02cbf6ac4e40c9e0da0c2 +fead49bd2db2d86a70d8c125a9decc6554dc71a3309f81803f3bf9a3212a10e6 +feb7e61b5e84cc65bf15afdb8c9cdedff9beb3edf575fcdf81e691668a96e0ad +febae1ae5ad42572a2111c6903eecbeeecd1efd331546efb8ca5363e0eaad52d +fecb838d2c1fb5c9a076233d9c996dea42d3f74fade0cde2c2f5ac93f015373d +fed50b028fd82a613564abfa95e811f922fb94cf15208976efc3e39449df1355 +fedef8f1a87c8aa8007c95decdfc47e89525e6a523836ef6d2a91f7f8c3803bd +fee0d8604987f375f982353dcf382b1c5bea85ed02c2909861e1c0e9219d24ca +fee99edac0b595aa9d225646193bb4d4c7f08a187325163f7019da3bf82cdf5d +feeb68da57d6f7072750e5e3b9eab2de287c0a774d48e7e782b59f60f3077795 +fef8f2961d06c98b60cf43a97f86e7a00015acba07c9ac7323ed9c71dcc4c618 +ff1728808947af8b912fc29341632763c7f7c76e2cab717a08cfdf69b987b457 +ff216d99c3da6153c92650574c5c2536714427feb5129cd47c337665aa6e865b +ff25eb85bc7992c6b084082a66b077777be0b4db2e0b0c24fcc9622e78b27604 +ff3ce936f67444ecefa7f9738d041c6e2c240c11feceda0e78eb4da2e9064f51 +ff3e9797b0a74c34ab342afa67467a47abb70972050322f817ca75d98d1ce480 +ff5bfbb55535ec6567689039f75e85c375a83c9a242153e557506a51aa15b705 +ff5dc732102b0b889ced0422b760b3b9fb5263cbb76e5d1fab398a6001b505ca +ff704f919ca3c924ea981bba06fffac56d6fcb3a67323877320004cd4e6b0a14 +ff7b4095488574a6c17f4ef5ffd34e6e6860e32de02d93c3cbb9e5ffee986d75 +ff879c611f6594576032bf36dbaae7d89d5cc1069320ba9cd7bd724b6a6963c4 +ff8b6f47aca21b3861a6f52b737df710ea71e37d7c9c4a68f448ae2bab50f34e +ff930ef507a1e17166e669cc6eed813b7ef4840290d74c94decbe8e42984c0ff +ff9e3b671f9b3b0f158d005999be258d07c49edea03c9b5759013a7f82ff1ba8 +ffa54d64739b1b2abaf3d1489e0fcce10d39478cba4381e1f7a28363fcb79452 +ffaa8704235a2293fa16d49bdc1605156ca304d95a87e7472101cd98577d76c6 +ffab4e408f33e4a265bfb40f18b1f0f0d674db6ac1fd5d6105b8f50a7010ae87 +ffb282d6fa4352a269da0b1bb3e9b7ba1dbcdbcde5fdda9a855f85d3c8a85089 +ffb6f20d288513a0c7aaf1e0a68c4d3deb614e146d22d1a1524867b8cc25cde3 +ffbbbec6f56de422a9a683c73c3adad73a906b1aa57b61d3af2563b2e9b12f4d +ffc64c46ffadb41c4c1f69b704dc9343fb7a73c2015430137dbafd0d6f863855 +ffc9701af58947d292651a3f0c082391941d73e65046880f45c59cd0e4cbf98f +ffce3d71c545484edb9a1156512390aa54e16efff45e0616737c64e4b351d2fb +ffe720fee9d3d016d8f30e2755654b9b62b1b61969f626d8df47608ba523e2f2 +fff0120b04c7a7f0dfc4fb404a2f480cfa70b1ce7fd852a4e7e4fae28811c84c +fffa34d343bd6cee927abee100f61d0a27b8cf32b3e3a6a0834ba2d7d4129c5f +f56599f4353c6f5d4d01cf9a9c2548cc2a70d3684c127962515b681692ab2b3e diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 0ecb48591..3118e6ad7 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -122,6 +122,8 @@ PODS: - Flutter - MTBBarcodeScanner (5.0.11) - OrderedSet (5.0.0) + - package_info (0.0.1): + - Flutter - package_info_plus (0.4.5): - Flutter - path_provider_foundation (0.0.1): @@ -143,8 +145,6 @@ PODS: - SwiftProtobuf (1.22.0) - SwiftyGif (5.4.4) - Toast (4.0.0) - - tor (0.0.1): - - Flutter - uni_links (0.0.1): - Flutter - UnstoppableDomainsResolution (4.0.0): @@ -175,13 +175,13 @@ DEPENDENCIES: - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - in_app_review (from `.symlinks/plugins/in_app_review/ios`) - local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`) + - package_info (from `.symlinks/plugins/package_info/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - - tor (from `.symlinks/plugins/tor/ios`) - uni_links (from `.symlinks/plugins/uni_links/ios`) - UnstoppableDomainsResolution (~> 4.0.0) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) @@ -236,6 +236,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/in_app_review/ios" local_auth_ios: :path: ".symlinks/plugins/local_auth_ios/ios" + package_info: + :path: ".symlinks/plugins/package_info/ios" package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" path_provider_foundation: @@ -248,8 +250,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/share_plus/ios" shared_preferences_foundation: :path: ".symlinks/plugins/shared_preferences_foundation/darwin" - tor: - :path: ".symlinks/plugins/tor/ios" uni_links: :path: ".symlinks/plugins/uni_links/ios" url_launcher_ios: @@ -282,6 +282,7 @@ SPEC CHECKSUMS: local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605 MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c + package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 @@ -293,7 +294,6 @@ SPEC CHECKSUMS: SwiftProtobuf: 40bd808372cb8706108f22d28f8ab4a6b9bc6989 SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 - tor: 662a9f5b980b5c86decb8ba611de9bcd4c8286eb uni_links: d97da20c7701486ba192624d99bffaaffcfc298a UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841 url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b diff --git a/lib/di.dart b/lib/di.dart index f3a03f03b..c98b98bc8 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -374,7 +374,8 @@ Future setup({ settingsStore: settingsStore, yatStore: getIt.get(), ordersStore: getIt.get(), - anonpayTransactionsStore: getIt.get())); + anonpayTransactionsStore: getIt.get(), + keyService: getIt.get())); getIt.registerFactory( () => AuthService( @@ -792,8 +793,8 @@ Future setup({ getIt.registerFactory( () => RobinhoodBuyProvider(wallet: getIt.get().wallet!)); - getIt.registerFactory( - () => DFXBuyProvider(wallet: getIt.get().wallet!)); + getIt + .registerFactory(() => DFXBuyProvider(wallet: getIt.get().wallet!)); getIt.registerFactory(() => OnRamperBuyProvider( settingsStore: getIt.get().settingsStore, diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index 98b24f783..356c69c00 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -7,6 +7,7 @@ import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sideba import 'package:cake_wallet/src/screens/dashboard/pages/market_place_page.dart'; import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/bottom_sheet_listener.dart'; import 'package:cake_wallet/src/widgets/gradient_background.dart'; +import 'package:cake_wallet/src/widgets/vulnerable_seeds_popup.dart'; import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/version_comparator.dart'; @@ -60,7 +61,8 @@ class DashboardPage extends StatelessWidget { ); if (DeviceInfo.instance.isDesktop) { - if (responsiveLayoutUtil.screenWidth > ResponsiveLayoutUtilBase.kDesktopMaxDashBoardWidthConstraint) { + if (responsiveLayoutUtil.screenWidth > + ResponsiveLayoutUtilBase.kDesktopMaxDashBoardWidthConstraint) { return getIt.get(); } else { return dashboardPageView; @@ -295,6 +297,8 @@ class _DashboardPageView extends BasePage { _showReleaseNotesPopup(context); + _showVulnerableSeedsPopup(context); + var needToPresentYat = false; var isInactive = false; @@ -354,4 +358,22 @@ class _DashboardPageView extends BasePage { sharedPrefs.setInt(PreferencesKey.lastSeenAppVersion, currentAppVersion); } } + + void _showVulnerableSeedsPopup(BuildContext context) async { + final List affectedWalletNames = await dashboardViewModel.checkAffectedWallets(); + + if (affectedWalletNames.isNotEmpty) { + Future.delayed( + Duration(seconds: 1), + () { + showPopUp( + context: context, + builder: (BuildContext context) { + return VulnerableSeedsPopup(affectedWalletNames); + }, + ); + }, + ); + } + } } diff --git a/lib/src/screens/dashboard/desktop_dashboard_page.dart b/lib/src/screens/dashboard/desktop_dashboard_page.dart index 216ea152d..b25d0774b 100644 --- a/lib/src/screens/dashboard/desktop_dashboard_page.dart +++ b/lib/src/screens/dashboard/desktop_dashboard_page.dart @@ -3,6 +3,7 @@ import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/release_notes/release_notes_screen.dart'; import 'package:cake_wallet/src/screens/yat_emoji_id.dart'; +import 'package:cake_wallet/src/widgets/vulnerable_seeds_popup.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/utils/version_comparator.dart'; import 'package:flutter/material.dart'; @@ -110,5 +111,25 @@ class DesktopDashboardPage extends StatelessWidget { } else if (isNewInstall!) { sharedPrefs.setInt(PreferencesKey.lastSeenAppVersion, currentAppVersion); } + + _showVulnerableSeedsPopup(context); + } + + void _showVulnerableSeedsPopup(BuildContext context) async { + final List affectedWalletNames = await dashboardViewModel.checkAffectedWallets(); + + if (affectedWalletNames.isNotEmpty) { + Future.delayed( + Duration(seconds: 1), + () { + showPopUp( + context: context, + builder: (BuildContext context) { + return VulnerableSeedsPopup(affectedWalletNames); + }, + ); + }, + ); + } } } diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart index 5f32bf06f..283d2171d 100644 --- a/lib/src/screens/dashboard/pages/balance_page.dart +++ b/lib/src/screens/dashboard/pages/balance_page.dart @@ -54,6 +54,24 @@ class BalancePage extends StatelessWidget { Theme.of(context).extension()!.pageTitleTextColor, height: 1, ), + unselectedLabelStyle: TextStyle( + fontSize: 18, + fontFamily: 'Lato', + fontWeight: FontWeight.w600, + color: + Theme.of(context).extension()!.pageTitleTextColor, + height: 1, + ), + labelColor: + Theme.of(context).extension()!.pageTitleTextColor, + dividerColor: + Theme.of(context).extension()!.pageTitleTextColor, + indicatorColor: + Theme.of(context).extension()!.pageTitleTextColor, + unselectedLabelColor: Theme.of(context) + .extension()! + .pageTitleTextColor + .withOpacity(0.5), tabs: [ Tab(text: 'My Crypto'), Tab(text: 'My NFTs'), diff --git a/lib/src/widgets/vulnerable_seeds_popup.dart b/lib/src/widgets/vulnerable_seeds_popup.dart new file mode 100644 index 000000000..1fcf474ee --- /dev/null +++ b/lib/src/widgets/vulnerable_seeds_popup.dart @@ -0,0 +1,91 @@ +import 'package:cake_wallet/src/widgets/alert_background.dart'; +import 'package:cake_wallet/src/widgets/alert_close_button.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:flutter/material.dart'; + +class VulnerableSeedsPopup extends StatelessWidget { + final List affectedWalletNames; + + const VulnerableSeedsPopup(this.affectedWalletNames, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Stack( + alignment: Alignment.center, + children: [ + AlertBackground( + child: AlertDialog( + insetPadding: EdgeInsets.only(left: 16, right: 16, bottom: 48), + elevation: 0.0, + contentPadding: EdgeInsets.zero, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(30))), + content: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30.0), + gradient: LinearGradient(colors: [ + Theme.of(context).extension()!.firstGradientBackgroundColor, + Theme.of(context) + .extension()! + .secondGradientBackgroundColor, + ], begin: Alignment.centerLeft, end: Alignment.centerRight)), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24.0), + child: Stack( + children: [ + SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.only(top: 16.0), + child: Container( + alignment: Alignment.bottomCenter, + child: DefaultTextStyle( + style: TextStyle( + decoration: TextDecoration.none, + fontSize: 24.0, + fontWeight: FontWeight.bold, + fontFamily: 'Lato', + color: Theme.of(context).extension()!.textColor, + ), + child: Text("Emergency Notice"), + ), + ), + ), + ), + SingleChildScrollView( + child: Padding( + padding: EdgeInsets.only(top: 48, bottom: 16), + child: Container( + width: double.maxFinite, + child: Column( + children: [ + ConstrainedBox( + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context).size.height * 0.7, + ), + child: Text( + "Your Bitcoin wallet(s) below use a legacy seed format that is vulnerable, which MAY result in you losing money from these wallet(s) if no action is taken.\nWe recommend that you IMMEDIATELY create wallet(s) in Cake Wallet and immediately transfer the funds to these wallet(s).\nVulnerable wallet name(s):\n\n[${affectedWalletNames.join(", ")}]\n\nFor assistance, please use the in-app support or email support@cakewallet.com", + style: TextStyle( + decoration: TextDecoration.none, + fontSize: 16.0, + fontFamily: 'Lato', + color: Theme.of(context) + .extension()! + .textColor, + ), + ), + ) + ], + ), + ), + ), + ), + ], + ), + ), + ), + ), + ), + AlertCloseButton(bottom: 30) + ], + ); + } +} diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 84ba54202..19b5ad544 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -1,3 +1,6 @@ +import 'dart:convert'; + +import 'package:cake_wallet/core/key_service.dart'; import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/balance_display_mode.dart'; import 'package:cake_wallet/entities/buy_provider_types.dart'; @@ -24,12 +27,19 @@ import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart'; import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart'; import 'package:cake_wallet/view_model/settings/sync_mode.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; +import 'package:cryptography/cryptography.dart'; import 'package:cw_core/balance.dart'; +import 'package:cw_core/cake_hive.dart'; +import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/sync_status.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/transaction_info.dart'; +import 'package:cw_core/utils/file.dart'; import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; +import 'package:eth_sig_util/util/utils.dart'; +import 'package:flutter/services.dart'; import 'package:mobx/mobx.dart'; part 'dashboard_view_model.g.dart'; @@ -46,7 +56,8 @@ abstract class DashboardViewModelBase with Store { required this.settingsStore, required this.yatStore, required this.ordersStore, - required this.anonpayTransactionsStore}) + required this.anonpayTransactionsStore, + required this.keyService}) : hasSellAction = false, hasBuyAction = false, hasExchangeAction = false, @@ -262,6 +273,8 @@ abstract class DashboardViewModelBase with Store { bool get hasRescan => wallet.type == WalletType.monero || wallet.type == WalletType.haven; + final KeyService keyService; + BalanceViewModel balanceViewModel; AppStore appStore; @@ -283,12 +296,12 @@ abstract class DashboardViewModelBase with Store { Map> filterItems; BuyProviderType get defaultBuyProvider => - settingsStore.defaultBuyProviders[wallet.type] ?? - BuyProviderType.AskEachTime; + settingsStore.defaultBuyProviders[wallet.type] ?? BuyProviderType.AskEachTime; bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled; - List get availableProviders => BuyProviderType.getAvailableProviders(wallet.type); + List get availableProviders => + BuyProviderType.getAvailableProviders(wallet.type); bool get shouldShowYatPopup => settingsStore.shouldShowYatPopup; @@ -433,4 +446,32 @@ abstract class DashboardViewModelBase with Store { @action void setSyncAll(bool value) => settingsStore.currentSyncAll = value; + + Future> checkAffectedWallets() async { + // await load file + final vulnerableSeedsString = await rootBundle.loadString('assets/text/cakewallet_weak_bitcoin_seeds_hashed_sorted_version1.txt'); + final vulnerableSeeds = vulnerableSeedsString.split("\n"); + + final walletInfoSource = await CakeHive.openBox(WalletInfo.boxName); + + List affectedWallets = []; + for (var walletInfo in walletInfoSource.values) { + if (walletInfo.type == WalletType.bitcoin) { + final password = await keyService.getWalletPassword(walletName: walletInfo.name); + final path = await pathForWallet(name: walletInfo.name, type: walletInfo.type); + final jsonSource = await read(path: path, password: password); + final data = json.decode(jsonSource) as Map; + final mnemonic = data['mnemonic'] as String; + + final hash = await Cryptography.instance.sha256().hash(utf8.encode(mnemonic)); + final seedSha = bytesToHex(hash.bytes); + + if (vulnerableSeeds.contains(seedSha)) { + affectedWallets.add(walletInfo.name); + } + } + } + + return affectedWallets; + } } diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 63a29221b..a07807864 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.8.0" -MONERO_COM_BUILD_NUMBER=69 +MONERO_COM_VERSION="1.9.0" +MONERO_COM_BUILD_NUMBER=71 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.11.0" -CAKEWALLET_BUILD_NUMBER=184 +CAKEWALLET_VERSION="4.12.0" +CAKEWALLET_BUILD_NUMBER=187 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index a831396f1..4f3707ac2 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.8.0" -MONERO_COM_BUILD_NUMBER=67 +MONERO_COM_VERSION="1.9.0" +MONERO_COM_BUILD_NUMBER=69 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.11.0" -CAKEWALLET_BUILD_NUMBER=202 +CAKEWALLET_VERSION="4.12.0" +CAKEWALLET_BUILD_NUMBER=205 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index f6fa8b5e8..6901249de 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -15,8 +15,8 @@ if [ -n "$1" ]; then fi CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.4.0" -CAKEWALLET_BUILD_NUMBER=45 +CAKEWALLET_VERSION="1.5.0" +CAKEWALLET_BUILD_NUMBER=47 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From 1eaebcba83f6484cca25a1bab6bf6397de90ad40 Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 20 Dec 2023 14:25:30 +0200 Subject: [PATCH 081/241] [skip ci]Revert "minor fixes" --- lib/src/screens/seed/warning_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/screens/seed/warning_page.dart b/lib/src/screens/seed/warning_page.dart index 5df55ad5e..18b9b6248 100644 --- a/lib/src/screens/seed/warning_page.dart +++ b/lib/src/screens/seed/warning_page.dart @@ -72,7 +72,7 @@ class WarningPage extends BasePage { ? Navigator.of(context) .popAndPushNamed(Routes.seed, arguments: true) : Navigator.of(context) - .pushNamed(Routes.setup_2faPage), + .popAndPushNamed(Routes.setup_2faPage), text: isPreSeedPage ? S.of(context).pre_seed_button_text : S.of(context).understand, From c8856f5ca1df4d2111f50a08544778adfbccda37 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Fri, 22 Dec 2023 23:31:06 +0200 Subject: [PATCH 082/241] Generic fixes (#1243) * handle currency names with appended network * Fix BCH sending issue for p2sh addresses * Update app versions [skip ci] --- assets/text/Release_Notes.txt | 6 +---- .../lib/src/bitcoin_cash_wallet.dart | 22 ++++++++++++++++++- cw_bitcoin_cash/pubspec.yaml | 1 + cw_core/lib/crypto_currency.dart | 2 +- lib/core/address_validator.dart | 2 +- macos/Podfile.lock | 7 +----- scripts/android/app_env.sh | 4 ++-- scripts/ios/app_env.sh | 4 ++-- scripts/macos/app_env.sh | 4 ++-- 9 files changed, 32 insertions(+), 20 deletions(-) diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 87d1e1747..515a0333e 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,6 +1,2 @@ -Add Polygon (Matic) wallet -Polyseed enhancements -New on-ramp provider DFX -Usability enhancements -Bitcoin enhancements +Support multiple address types for Bitcoin Cash Bug fixes \ No newline at end of file diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index fa41de767..c23220423 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:bitbox/bitbox.dart' as bitbox; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; @@ -210,9 +211,28 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { txb.addInput(input.hash, input.vout); }); + final String bchPrefix = "bitcoincash:"; + outputs.forEach((item) { final outputAmount = hasMultiDestination ? item.formattedCryptoAmount : amount; - final outputAddress = item.isParsedAddress ? item.extractedAddress! : item.address; + String outputAddress = item.isParsedAddress ? item.extractedAddress! : item.address; + + if (!outputAddress.startsWith(bchPrefix)) { + outputAddress = "$bchPrefix$outputAddress"; + } + + bool isP2sh = outputAddress.startsWith("p", bchPrefix.length); + + if (isP2sh) { + final p2sh = P2shAddress.fromAddress( + address: outputAddress, + network: BitcoinCashNetwork.mainnet, + ); + + txb.addOutput(Uint8List.fromList(p2sh.toScriptPubKey().toBytes()), outputAmount!); + return; + } + txb.addOutput(outputAddress, outputAmount!); }); diff --git a/cw_bitcoin_cash/pubspec.yaml b/cw_bitcoin_cash/pubspec.yaml index eb1f057d8..49a5efb15 100644 --- a/cw_bitcoin_cash/pubspec.yaml +++ b/cw_bitcoin_cash/pubspec.yaml @@ -29,6 +29,7 @@ dependencies: git: url: https://github.com/cake-tech/bitbox-flutter.git ref: master + bitcoin_base: ^3.0.1 diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index 35d42f6d2..0f7f25d9b 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -245,7 +245,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen } static CryptoCurrency fromFullName(String name) { - if (CryptoCurrency._fullNameCurrencyMap[name.toLowerCase()] == null) { + if (CryptoCurrency._fullNameCurrencyMap[name.split("(").first.trim().toLowerCase()] == null) { final s = 'Unexpected token: $name for CryptoCurrency fromFullName'; throw ArgumentError.value(name, 'Fullname', s); } diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 558d14f6d..2ae9e3297 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -92,7 +92,7 @@ class AddressValidator extends TextValidator { case CryptoCurrency.eos: return '[0-9a-zA-Z]'; case CryptoCurrency.bch: - return '^(?!bitcoincash:)[0-9a-zA-Z]*\$|^(?!bitcoincash:)q[0-9a-zA-Z]{41}\$|^(?!bitcoincash:)q[0-9a-zA-Z]{42}\$|^bitcoincash:q[0-9a-zA-Z]{41}\$|^bitcoincash:q[0-9a-zA-Z]{42}\$'; + return '^(?!bitcoincash:)[0-9a-zA-Z]*\$|^(?!bitcoincash:)q|p[0-9a-zA-Z]{41}\$|^(?!bitcoincash:)q|p[0-9a-zA-Z]{42}\$|^bitcoincash:q|p[0-9a-zA-Z]{41}\$|^bitcoincash:q|p[0-9a-zA-Z]{42}\$'; case CryptoCurrency.bnb: return '[0-9a-zA-Z]'; case CryptoCurrency.ltc: diff --git a/macos/Podfile.lock b/macos/Podfile.lock index c1659f4cc..329732075 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -41,7 +41,6 @@ PODS: - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS - - tor (0.0.1) - url_launcher_macos (0.0.1): - FlutterMacOS - wakelock_plus (0.0.1): @@ -60,7 +59,6 @@ DEPENDENCIES: - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`) - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - - tor (from `Flutter/ephemeral/.symlinks/plugins/tor/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`) @@ -93,8 +91,6 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos shared_preferences_foundation: :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin - tor: - :path: Flutter/ephemeral/.symlinks/plugins/tor/macos url_launcher_macos: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos wakelock_plus: @@ -102,7 +98,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308 - cw_monero: f8b7f104508efba2591548e76b5c058d05cba3f0 + cw_monero: ec03de55a19c4a2b174ea687e0f4202edc716fa4 device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225 flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea @@ -114,7 +110,6 @@ SPEC CHECKSUMS: ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4 shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 - tor: 2138c48428e696b83eacdda404de6d5574932e26 url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269 diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index a07807864..5feae289e 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -22,8 +22,8 @@ MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.12.0" -CAKEWALLET_BUILD_NUMBER=187 +CAKEWALLET_VERSION="4.12.1" +CAKEWALLET_BUILD_NUMBER=188 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 4f3707ac2..ee59e837c 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -18,8 +18,8 @@ MONERO_COM_BUILD_NUMBER=69 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.12.0" -CAKEWALLET_BUILD_NUMBER=205 +CAKEWALLET_VERSION="4.12.1" +CAKEWALLET_BUILD_NUMBER=206 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 6901249de..a37d67a82 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -15,8 +15,8 @@ if [ -n "$1" ]; then fi CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.5.0" -CAKEWALLET_BUILD_NUMBER=47 +CAKEWALLET_VERSION="1.5.1" +CAKEWALLET_BUILD_NUMBER=48 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From 92914a85329df467789b7af6f894edba1fbd7bf8 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Thu, 28 Dec 2023 02:37:36 +0100 Subject: [PATCH 083/241] fix: Fix walletconnect connecting only with the first wallet (#1247) --- .../wallet_connect/evm_chain_service.dart | 8 +-- .../wallet_connect_key_service.dart | 72 ++++++------------- .../wallet_connect/web3wallet_service.dart | 5 +- lib/di.dart | 2 +- lib/entities/load_current_wallet.dart | 2 +- lib/store/app_store.dart | 13 ++-- lib/view_model/wallet_creation_vm.dart | 2 +- .../wallet_list/wallet_list_view_model.dart | 2 +- 8 files changed, 40 insertions(+), 66 deletions(-) diff --git a/lib/core/wallet_connect/evm_chain_service.dart b/lib/core/wallet_connect/evm_chain_service.dart index 836d1a7c8..81b934e08 100644 --- a/lib/core/wallet_connect/evm_chain_service.dart +++ b/lib/core/wallet_connect/evm_chain_service.dart @@ -138,7 +138,7 @@ class EvmChainServiceImpl implements ChainService { try { // Load the private key final List keys = wcKeyService - .getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type)); + .getKeysForChain(appStore.wallet!); final Credentials credentials = EthPrivateKey.fromHex(keys[0].privateKey); @@ -177,7 +177,7 @@ class EvmChainServiceImpl implements ChainService { try { // Load the private key final List keys = wcKeyService - .getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type)); + .getKeysForChain(appStore.wallet!); final EthPrivateKey credentials = EthPrivateKey.fromHex(keys[0].privateKey); @@ -215,7 +215,7 @@ class EvmChainServiceImpl implements ChainService { // Load the private key final List keys = wcKeyService - .getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type)); + .getKeysForChain(appStore.wallet!); final Credentials credentials = EthPrivateKey.fromHex(keys[0].privateKey); @@ -275,7 +275,7 @@ class EvmChainServiceImpl implements ChainService { } final List keys = wcKeyService - .getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type)); + .getKeysForChain(appStore.wallet!); return EthSigUtil.signTypedData( privateKey: keys[0].privateKey, diff --git a/lib/core/wallet_connect/wallet_connect_key_service.dart b/lib/core/wallet_connect/wallet_connect_key_service.dart index bb0c9d14c..33d721073 100644 --- a/lib/core/wallet_connect/wallet_connect_key_service.dart +++ b/lib/core/wallet_connect/wallet_connect_key_service.dart @@ -1,48 +1,22 @@ import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart'; import 'package:cake_wallet/polygon/polygon.dart'; -import 'package:cw_core/balance.dart'; -import 'package:cw_core/transaction_history.dart'; -import 'package:cw_core/transaction_info.dart'; +import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; abstract class WalletConnectKeyService { /// Returns a list of all the keys. - List getKeys(); - - /// Returns a list of all the chain ids. - List getChains(); + List getKeys(WalletBase wallet); /// Returns a list of all the keys for a given chain id. /// If the chain is not found, returns an empty list. /// - [chain]: The chain to get the keys for. - List getKeysForChain(String chain); + List getKeysForChain(WalletBase wallet); - /// Returns a list of all the accounts in namespace:chainId:address format. - List getAllAccounts(); } class KeyServiceImpl implements WalletConnectKeyService { - KeyServiceImpl(this.wallet) - : _keys = [ - ChainKeyModel( - chains: [ - 'eip155:1', - 'eip155:5', - 'eip155:137', - 'eip155:42161', - 'eip155:80001', - ], - privateKey: _getPrivateKeyForWallet(wallet), - publicKey: _getPublicKeyForWallet(wallet), - ), - ]; - - late final WalletBase, TransactionInfo> wallet; - - late final List _keys; - static String _getPrivateKeyForWallet(WalletBase wallet) { switch (wallet.type) { case WalletType.ethereum: @@ -64,31 +38,31 @@ class KeyServiceImpl implements WalletConnectKeyService { return ''; } } + @override - List getChains() { - final List chainIds = []; - for (final ChainKeyModel key in _keys) { - chainIds.addAll(key.chains); - } - return chainIds; + List getKeys(WalletBase wallet) { + final keys = [ + ChainKeyModel( + chains: [ + 'eip155:1', + 'eip155:5', + 'eip155:137', + 'eip155:42161', + 'eip155:80001', + ], + privateKey: _getPrivateKeyForWallet(wallet), + publicKey: _getPublicKeyForWallet(wallet), + ), + ]; + return keys; } @override - List getKeys() => _keys; + List getKeysForChain(WalletBase wallet) { + final chain = getChainNameSpaceAndIdBasedOnWalletType(wallet.type); - @override - List getKeysForChain(String chain) { - return _keys.where((e) => e.chains.contains(chain)).toList(); - } + final keys = getKeys(wallet); - @override - List getAllAccounts() { - final List accounts = []; - for (final ChainKeyModel key in _keys) { - for (final String chain in key.chains) { - accounts.add('$chain:${key.publicKey}'); - } - } - return accounts; + return keys.where((e) => e.chains.contains(chain)).toList(); } } diff --git a/lib/core/wallet_connect/web3wallet_service.dart b/lib/core/wallet_connect/web3wallet_service.dart index 7a1dac6cc..ee560a0e0 100644 --- a/lib/core/wallet_connect/web3wallet_service.dart +++ b/lib/core/wallet_connect/web3wallet_service.dart @@ -68,7 +68,7 @@ abstract class Web3WalletServiceBase with Store { ); // Setup our accounts - List chainKeys = walletKeyService.getKeys(); + List chainKeys = walletKeyService.getKeys(appStore.wallet!); for (final chainKey in chainKeys) { for (final chainId in chainKey.chains) { _web3Wallet.registerAccount( @@ -136,6 +136,7 @@ abstract class Web3WalletServiceBase with Store { _web3Wallet.onAuthRequest.unsubscribe(_onAuthRequest); _web3Wallet.core.pairing.onPairingDelete.unsubscribe(_onPairingDelete); _web3Wallet.core.pairing.onPairingExpire.unsubscribe(_onPairingDelete); + isInitialized = false; } Web3Wallet getWeb3Wallet() { @@ -236,7 +237,7 @@ abstract class Web3WalletServiceBase with Store { Future _onAuthRequest(AuthRequest? args) async { if (args != null) { final chaindIdNamespace = getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type); - List chainKeys = walletKeyService.getKeysForChain(chaindIdNamespace); + List chainKeys = walletKeyService.getKeysForChain(appStore.wallet!); // Create the message to be signed final String iss = 'did:pkh:$chaindIdNamespace:${chainKeys.first.publicKey}'; final Widget modalWidget = Web3RequestModal( diff --git a/lib/di.dart b/lib/di.dart index c98b98bc8..03b7bfec8 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -474,7 +474,7 @@ Future setup({ final appStore = getIt.get(); - getIt.registerLazySingleton(() => KeyServiceImpl(appStore.wallet!)); + getIt.registerLazySingleton(() => KeyServiceImpl()); getIt.registerLazySingleton(() { final Web3WalletService web3WalletService = Web3WalletService( diff --git a/lib/entities/load_current_wallet.dart b/lib/entities/load_current_wallet.dart index d758b6697..595bc2233 100644 --- a/lib/entities/load_current_wallet.dart +++ b/lib/entities/load_current_wallet.dart @@ -22,7 +22,7 @@ Future loadCurrentWallet() async { final type = deserializeFromInt(typeRaw); final walletLoadingService = getIt.get(); final wallet = await walletLoadingService.load(type, name); - appStore.changeCurrentWallet(wallet); + await appStore.changeCurrentWallet(wallet); getIt.get().registerSyncTask(); } diff --git a/lib/store/app_store.dart b/lib/store/app_store.dart index 46ac2cf1a..a5a2b95e0 100644 --- a/lib/store/app_store.dart +++ b/lib/store/app_store.dart @@ -26,8 +26,7 @@ abstract class AppStoreBase with Store { AuthenticationStore authenticationStore; @observable - WalletBase, TransactionInfo>? - wallet; + WalletBase, TransactionInfo>? wallet; WalletListStore walletList; @@ -36,16 +35,16 @@ abstract class AppStoreBase with Store { NodeListStore nodeListStore; @action - void changeCurrentWallet( - WalletBase, - TransactionInfo> - wallet) { + Future changeCurrentWallet( + WalletBase, TransactionInfo> wallet) async { this.wallet?.close(); this.wallet = wallet; this.wallet!.setExceptionHandler(ExceptionHandler.onError); if (isEVMCompatibleChain(wallet.type)) { - getIt.get().init(); + await getIt.get().onDispose(); + getIt.get().create(); + await getIt.get().init(); } } } diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index aa1efe4d3..45306905c 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -74,7 +74,7 @@ abstract class WalletCreationVMBase with Store { : await process(credentials); walletInfo.address = wallet.walletAddresses.address; await _walletInfoSource.add(walletInfo); - _appStore.changeCurrentWallet(wallet); + await _appStore.changeCurrentWallet(wallet); getIt.get().registerSyncTask(); _appStore.authenticationStore.allowed(); state = ExecutedSuccessfullyState(); 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 3df6491bb..78211bb3e 100644 --- a/lib/view_model/wallet_list/wallet_list_view_model.dart +++ b/lib/view_model/wallet_list/wallet_list_view_model.dart @@ -45,7 +45,7 @@ abstract class WalletListViewModelBase with Store { @action Future loadWallet(WalletListItem walletItem) async { final wallet = await _walletLoadingService.load(walletItem.type, walletItem.name); - _appStore.changeCurrentWallet(wallet); + await _appStore.changeCurrentWallet(wallet); } WalletListOrderType? get orderType => _appStore.settingsStore.walletListOrder; From 914565eb724bbda6a6cc9c8ba166f90761115f67 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 28 Dec 2023 21:20:59 +0200 Subject: [PATCH 084/241] CW-539-DFX-off-ramp-sell-provider (#1229) * buy_provider_types refactoring * refactor MoonPay and sell option flow * dfx sell flow * add default sell provider flow * localization * Update other_settings_page.dart * [skip ci] update localization * [skip ci] providers fixes * [skip ci] ui fixes * refactor sell and buy flow * handle dfx availability by country * PR fixes --- assets/images/moonpay_dark.png | Bin 0 -> 23214 bytes assets/images/moonpay_light.png | Bin 0 -> 20800 bytes cw_haven/pubspec.lock | 9 -- lib/buy/buy_exception.dart | 8 +- lib/buy/buy_provider.dart | 32 +++-- lib/buy/dfx/dfx_buy_provider.dart | 64 +++++++--- lib/buy/moonpay/moonpay_buy_provider.dart | 117 ++++++++++++----- lib/buy/onramper/onramper_buy_provider.dart | 54 +++++--- lib/buy/robinhood/robinhood_buy_provider.dart | 57 +++++---- lib/buy/wyre/wyre_buy_provider.dart | 51 +++++--- lib/di.dart | 10 +- lib/entities/buy_provider_types.dart | 119 +++++++++++++----- lib/entities/main_actions.dart | 115 +++++------------ lib/router.dart | 6 +- lib/routes.dart | 2 +- lib/src/screens/buy/buy_options_page.dart | 108 ++++++---------- .../screens/buy/widgets/buy_list_item.dart | 7 +- .../screens/settings/other_settings_page.dart | 12 +- lib/store/settings_store.dart | 56 ++++++--- lib/view_model/buy/buy_view_model.dart | 3 +- .../dashboard/dashboard_view_model.dart | 35 ++++-- lib/view_model/order_details_view_model.dart | 39 +++--- .../settings/other_settings_view_model.dart | 37 +++++- 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_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_yo.arb | 2 + res/values/strings_zh.arb | 2 + 49 files changed, 623 insertions(+), 370 deletions(-) create mode 100644 assets/images/moonpay_dark.png create mode 100644 assets/images/moonpay_light.png diff --git a/assets/images/moonpay_dark.png b/assets/images/moonpay_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..872e322e2a5f8ab6a639f5949dff97ffcd325e00 GIT binary patch literal 23214 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 literal 0 HcmV?d00001 diff --git a/assets/images/moonpay_light.png b/assets/images/moonpay_light.png new file mode 100644 index 0000000000000000000000000000000000000000..c76ae6e74ec7e578874528b4c670ca4829be5647 GIT binary patch literal 20800 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 '${description.title}: $text'; + String toString() => '$title: $content'; } \ No newline at end of file diff --git a/lib/buy/buy_provider.dart b/lib/buy/buy_provider.dart index 10a13ed94..93f4e8105 100644 --- a/lib/buy/buy_provider.dart +++ b/lib/buy/buy_provider.dart @@ -1,27 +1,35 @@ import 'package:cake_wallet/buy/buy_amount.dart'; -import 'package:cake_wallet/buy/buy_provider_description.dart'; import 'package:cake_wallet/buy/order.dart'; import 'package:cw_core/wallet_base.dart'; -import 'package:cw_core/wallet_type.dart'; +import 'package:flutter/material.dart'; abstract class BuyProvider { - BuyProvider({required this.wallet, required this.isTestEnvironment}); + BuyProvider({ + required this.wallet, + required this.isTestEnvironment, + }); final WalletBase wallet; final bool isTestEnvironment; String get title; - BuyProviderDescription get description; - String get trackUrl; - WalletType get walletType => wallet.type; - String get walletAddress => wallet.walletAddresses.address; - String get walletId => wallet.id; + String get buyOptionDescription; + + String get sellOptionDescription; + + String get lightIcon; + + String get darkIcon; @override String toString() => title; - Future requestUrl(String amount, String sourceCurrency); - Future findOrderById(String id); - Future calculateAmount(String amount, String sourceCurrency); -} \ No newline at end of file + Future launchProvider(BuildContext context, bool? isBuyAction); + + Future requestUrl(String amount, String sourceCurrency) => throw UnimplementedError(); + + Future findOrderById(String id) => throw UnimplementedError(); + + Future calculateAmount(String amount, String sourceCurrency) => throw UnimplementedError(); +} diff --git a/lib/buy/dfx/dfx_buy_provider.dart b/lib/buy/dfx/dfx_buy_provider.dart index d5cf50d10..18ac081ea 100644 --- a/lib/buy/dfx/dfx_buy_provider.dart +++ b/lib/buy/dfx/dfx_buy_provider.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:cake_wallet/buy/buy_provider.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; @@ -11,10 +12,9 @@ import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:url_launcher/url_launcher.dart'; -class DFXBuyProvider { - DFXBuyProvider({required WalletBase wallet}) : this._wallet = wallet; - - final WalletBase _wallet; +class DFXBuyProvider extends BuyProvider { + DFXBuyProvider({required WalletBase wallet, bool isTestEnvironment = false}) + : super(wallet: wallet, isTestEnvironment: isTestEnvironment); static const _baseUrl = 'api.dfx.swiss'; static const _authPath = '/v1/auth/signMessage'; @@ -22,8 +22,23 @@ class DFXBuyProvider { static const _signInPath = '/v1/auth/signIn'; static const walletName = 'CakeWallet'; + @override + String get title => 'DFX Connect'; + + @override + String get buyOptionDescription => S.current.dfx_option_description; + + @override + String get sellOptionDescription => S.current.dfx_option_description; + + @override + String get lightIcon => 'assets/images/dfx_light.png'; + + @override + String get darkIcon => 'assets/images/dfx_dark.png'; + String get assetOut { - switch (_wallet.type) { + switch (wallet.type) { case WalletType.bitcoin: return 'BTC'; case WalletType.bitcoinCash: @@ -35,12 +50,12 @@ class DFXBuyProvider { case WalletType.ethereum: return 'ETH'; default: - throw Exception("WalletType is not available for DFX ${_wallet.type}"); + throw Exception("WalletType is not available for DFX ${wallet.type}"); } } String get blockchain { - switch (_wallet.type) { + switch (wallet.type) { case WalletType.bitcoin: case WalletType.bitcoinCash: case WalletType.litecoin: @@ -50,12 +65,12 @@ class DFXBuyProvider { case WalletType.ethereum: return 'Ethereum'; default: - throw Exception("WalletType is not available for DFX ${_wallet.type}"); + throw Exception("WalletType is not available for DFX ${wallet.type}"); } } Future getSignMessage() async { - final walletAddress = _wallet.walletAddresses.address; + final walletAddress = wallet.walletAddresses.address; final uri = Uri.https(_baseUrl, _authPath, {'address': walletAddress}); var response = await http.get(uri, headers: {'accept': 'application/json'}); @@ -71,7 +86,7 @@ class DFXBuyProvider { Future signUp() async { final signMessage = getSignature(await getSignMessage()); - final walletAddress = _wallet.walletAddresses.address; + final walletAddress = wallet.walletAddresses.address; final requestBody = jsonEncode({ 'wallet': walletName, @@ -86,6 +101,10 @@ class DFXBuyProvider { if (response.statusCode == 201) { final responseBody = jsonDecode(response.body); return responseBody['accessToken'] as String; + } else if (response.statusCode == 403) { + final responseBody = jsonDecode(response.body); + final message = responseBody['message'] ?? 'Service unavailable in your country'; + throw Exception(message); } else { throw Exception( 'Failed to sign up. Status: ${response.statusCode} ${response.body}'); @@ -94,7 +113,7 @@ class DFXBuyProvider { Future signIn() async { final signMessage = getSignature(await getSignMessage()); - final walletAddress = _wallet.walletAddresses.address; + final walletAddress = wallet.walletAddresses.address; final requestBody = jsonEncode({ 'address': walletAddress, @@ -108,6 +127,10 @@ class DFXBuyProvider { if (response.statusCode == 201) { final responseBody = jsonDecode(response.body); return responseBody['accessToken'] as String; + } else if (response.statusCode == 403) { + final responseBody = jsonDecode(response.body); + final message = responseBody['message'] ?? 'Service unavailable in your country'; + throw Exception(message); } else { throw Exception( 'Failed to sign in. Status: ${response.statusCode} ${response.body}'); @@ -115,24 +138,25 @@ class DFXBuyProvider { } String getSignature(String message) { - switch (_wallet.type) { + switch (wallet.type) { case WalletType.ethereum: - return _wallet.signMessage(message); + return wallet.signMessage(message); case WalletType.monero: case WalletType.litecoin: case WalletType.bitcoin: case WalletType.bitcoinCash: - return _wallet.signMessage(message, - address: _wallet.walletAddresses.address); + return wallet.signMessage(message, + address: wallet.walletAddresses.address); default: - throw Exception("WalletType is not available for DFX ${_wallet.type}"); + throw Exception("WalletType is not available for DFX ${wallet.type}"); } } - Future launchProvider(BuildContext context) async { + Future launchProvider(BuildContext context, bool? isBuyAction) async { try { final assetOut = this.assetOut; final blockchain = this.blockchain; + final actionType = isBuyAction == true ? '/buy' : '/sell'; String accessToken; @@ -146,7 +170,7 @@ class DFXBuyProvider { } } - final uri = Uri.https('services.dfx.swiss', '/buy', { + final uri = Uri.https('services.dfx.swiss', actionType, { 'session': accessToken, 'lang': 'en', 'asset-out': assetOut, @@ -156,8 +180,8 @@ class DFXBuyProvider { if (await canLaunchUrl(uri)) { if (DeviceInfo.instance.isMobile) { - Navigator.of(context).pushNamed(Routes.webViewPage, - arguments: [S.of(context).buy, uri]); + Navigator.of(context) + .pushNamed(Routes.webViewPage, arguments: ["DFX Connect", uri]); } else { await launchUrl(uri, mode: LaunchMode.externalApplication); } diff --git a/lib/buy/moonpay/moonpay_buy_provider.dart b/lib/buy/moonpay/moonpay_buy_provider.dart index 0736edeb7..0831e1313 100644 --- a/lib/buy/moonpay/moonpay_buy_provider.dart +++ b/lib/buy/moonpay/moonpay_buy_provider.dart @@ -1,9 +1,14 @@ import 'dart:convert'; import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/themes/theme_base.dart'; +import 'package:cake_wallet/utils/device_info.dart'; import 'package:crypto/crypto.dart'; import 'package:cake_wallet/buy/buy_exception.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:flutter/material.dart'; import 'package:http/http.dart'; import 'package:cake_wallet/buy/buy_amount.dart'; import 'package:cake_wallet/buy/buy_provider.dart'; @@ -14,33 +19,41 @@ import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/exchange/trade_state.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cw_core/crypto_currency.dart'; +import 'package:url_launcher/url_launcher.dart'; class MoonPaySellProvider { - MoonPaySellProvider({this.isTest = false}) - : baseUrl = isTest ? _baseTestUrl : _baseProductUrl; + MoonPaySellProvider({required SettingsStore settingsStore, + required WalletBase wallet, this.isTest = false}) + : baseUrl = isTest ? _baseTestUrl : _baseProductUrl, + this._settingsStore = settingsStore, + this._wallet = wallet; + + final SettingsStore _settingsStore; + final WalletBase _wallet; static const _baseTestUrl = 'sell-sandbox.moonpay.com'; static const _baseProductUrl = 'sell.moonpay.com'; + static String themeToMoonPayTheme(ThemeBase theme) { switch (theme.type) { case ThemeType.bright: - return 'light'; case ThemeType.light: return 'light'; case ThemeType.dark: return 'dark'; } } - static String get _apiKey => secrets.moonPayApiKey; - static String get _secretKey => secrets.moonPaySecretKey; + + static String get _apiKey => secrets.moonPayApiKey; + static String get _secretKey => secrets.moonPaySecretKey; final bool isTest; final String baseUrl; - Future requestUrl( - {required CryptoCurrency currency, - required String refundWalletAddress, - required SettingsStore settingsStore}) async { - + Future requestUrl({ + required CryptoCurrency currency, + required String refundWalletAddress, + required SettingsStore settingsStore, + }) async { final customParams = { 'theme': themeToMoonPayTheme(settingsStore.currentTheme), 'language': settingsStore.languageCode, @@ -50,11 +63,15 @@ class MoonPaySellProvider { }; final originalUri = Uri.https( - baseUrl, '', { + baseUrl, + '', + { 'apiKey': _apiKey, 'defaultBaseCurrencyCode': currency.toString().toLowerCase(), - 'refundWalletAddress': refundWalletAddress - }..addAll(customParams)); + 'refundWalletAddress': refundWalletAddress, + }..addAll(customParams), + ); + final messageBytes = utf8.encode('?${originalUri.query}'); final key = utf8.encode(_secretKey); final hmac = Hmac(sha256, key); @@ -70,6 +87,38 @@ class MoonPaySellProvider { final signedUri = originalUri.replace(queryParameters: query); return signedUri; } + + Future launchProvider(BuildContext context) async { + try { + final uri = await requestUrl( + currency: _wallet.currency, + refundWalletAddress: _wallet.walletAddresses.address, + settingsStore: _settingsStore, + ); + + if (await canLaunchUrl(uri)) { + if (DeviceInfo.instance.isMobile) { + Navigator.of(context).pushNamed(Routes.webViewPage, arguments: ['MoonPay', uri]); + } else { + await launchUrl(uri, mode: LaunchMode.externalApplication); + } + } else { + throw Exception('Could not launch URL'); + } + } catch (e) { + await showDialog( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: 'MoonPay', + alertContent: 'The MoonPay service is currently unavailable: $e', + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop(), + ); + }, + ); + } + } } class MoonPayBuyProvider extends BuyProvider { @@ -88,20 +137,24 @@ class MoonPayBuyProvider extends BuyProvider { static const _secretKey = secrets.moonPaySecretKey; @override - String get title => 'MoonPay'; + String get title => 'Moon Pay'; @override - BuyProviderDescription get description => BuyProviderDescription.moonPay; + String get buyOptionDescription => ''; + @override + String get lightIcon => 'assets/images/moonpay_light.png'; + + @override + String get darkIcon => 'assets/images/moonpay_dark.png'; + String get currencyCode => - walletTypeToCryptoCurrency(walletType).title.toLowerCase(); + walletTypeToCryptoCurrency(wallet.type).title.toLowerCase(); - @override String get trackUrl => baseUrl + '/transaction_receipt?transactionId='; String baseUrl; - @override Future requestUrl(String amount, String sourceCurrency) async { final enabledPaymentMethods = 'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay' @@ -109,7 +162,7 @@ class MoonPayBuyProvider extends BuyProvider { final suffix = '?apiKey=' + _apiKey + '¤cyCode=' + currencyCode + '&enabledPaymentMethods=' + enabledPaymentMethods + - '&walletAddress=' + walletAddress + + '&walletAddress=' + wallet.walletAddresses.address + '&baseCurrencyCode=' + sourceCurrency.toLowerCase() + '&baseCurrencyAmount=' + amount + '&lockAmount=true' + '&showAllCurrencies=false' + '&showWalletAddressForm=false'; @@ -127,7 +180,6 @@ class MoonPayBuyProvider extends BuyProvider { return isTestEnvironment ? originalUrl : urlWithSignature; } - @override Future calculateAmount(String amount, String sourceCurrency) async { final url = _apiUrl + _currenciesSuffix + '/$currencyCode' + _quoteSuffix + '/?apiKey=' + _apiKey + @@ -138,8 +190,8 @@ class MoonPayBuyProvider extends BuyProvider { if (response.statusCode != 200) { throw BuyException( - description: description, - text: 'Quote is not found!'); + title: buyOptionDescription, + content: 'Quote is not found!'); } final responseJSON = json.decode(response.body) as Map; @@ -153,7 +205,6 @@ class MoonPayBuyProvider extends BuyProvider { minAmount: minSourceAmount); } - @override Future findOrderById(String id) async { final url = _apiUrl + _transactionsSuffix + '/$id' + '?apiKey=' + _apiKey; @@ -162,8 +213,8 @@ class MoonPayBuyProvider extends BuyProvider { if (response.statusCode != 200) { throw BuyException( - description: description, - text: 'Transaction $id is not found!'); + title: buyOptionDescription, + content: 'Transaction $id is not found!'); } final responseJSON = json.decode(response.body) as Map; @@ -175,13 +226,13 @@ class MoonPayBuyProvider extends BuyProvider { return Order( id: id, - provider: description, + provider: BuyProviderDescription.moonPay, transferId: id, state: state, createdAt: createdAt, amount: amount.toString(), - receiveAddress: walletAddress, - walletId: walletId + receiveAddress: wallet.walletAddresses.address, + walletId: wallet.id ); } @@ -201,4 +252,14 @@ class MoonPayBuyProvider extends BuyProvider { return isBuyEnable; } + + @override + // TODO: implement sellOptionDescription + String get sellOptionDescription => throw UnimplementedError(); + + @override + Future launchProvider(BuildContext context, bool? isBuyAction) { + // TODO: implement launchProvider + throw UnimplementedError(); + } } \ No newline at end of file diff --git a/lib/buy/onramper/onramper_buy_provider.dart b/lib/buy/onramper/onramper_buy_provider.dart index 872fcebf5..e38d95df3 100644 --- a/lib/buy/onramper/onramper_buy_provider.dart +++ b/lib/buy/onramper/onramper_buy_provider.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/.secrets.g.dart' as secrets; +import 'package:cake_wallet/buy/buy_provider.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/store/settings_store.dart'; @@ -9,20 +10,34 @@ import 'package:cw_core/wallet_base.dart'; import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; -class OnRamperBuyProvider { - OnRamperBuyProvider({required SettingsStore settingsStore, required WalletBase wallet}) - : this._settingsStore = settingsStore, - this._wallet = wallet; - - final SettingsStore _settingsStore; - final WalletBase _wallet; +class OnRamperBuyProvider extends BuyProvider { + OnRamperBuyProvider(this._settingsStore, + {required WalletBase wallet, bool isTestEnvironment = false}) + : super(wallet: wallet, isTestEnvironment: isTestEnvironment); static const _baseUrl = 'buy.onramper.com'; + final SettingsStore _settingsStore; + + @override + String get title => 'Onramper'; + + @override + String get buyOptionDescription => S.current.onramper_option_description; + + @override + String get sellOptionDescription => S.current.onramper_option_description; + + @override + String get lightIcon => 'assets/images/onramper_light.png'; + + @override + String get darkIcon => 'assets/images/onramper_dark.png'; + String get _apiKey => secrets.onramperApiKey; String get _normalizeCryptoCurrency { - switch (_wallet.currency) { + switch (wallet.currency) { case CryptoCurrency.ltc: return "LTC_LITECOIN"; case CryptoCurrency.xmr: @@ -32,7 +47,7 @@ class OnRamperBuyProvider { case CryptoCurrency.nano: return "XNO_NANO"; default: - return _wallet.currency.title; + return wallet.currency.title; } } @@ -40,7 +55,7 @@ class OnRamperBuyProvider { return color.value.toRadixString(16).replaceAll(RegExp(r'^ff'), ""); } - Uri requestUrl(BuildContext context) { + Uri requestOnramperUrl(BuildContext context) { String primaryColor, secondaryColor, primaryTextColor, @@ -50,9 +65,10 @@ class OnRamperBuyProvider { primaryColor = getColorStr(Theme.of(context).primaryColor); secondaryColor = getColorStr(Theme.of(context).colorScheme.background); - primaryTextColor = getColorStr(Theme.of(context).extension()!.titleColor); - secondaryTextColor = - getColorStr(Theme.of(context).extension()!.secondaryTextColor); + primaryTextColor = + getColorStr(Theme.of(context).extension()!.titleColor); + secondaryTextColor = getColorStr( + Theme.of(context).extension()!.secondaryTextColor); containerColor = getColorStr(Theme.of(context).colorScheme.background); cardColor = getColorStr(Theme.of(context).cardColor); @@ -60,12 +76,13 @@ class OnRamperBuyProvider { cardColor = getColorStr(Colors.white); } - final networkName = _wallet.currency.fullName?.toUpperCase().replaceAll(" ", ""); + final networkName = + wallet.currency.fullName?.toUpperCase().replaceAll(" ", ""); return Uri.https(_baseUrl, '', { 'apiKey': _apiKey, 'defaultCrypto': _normalizeCryptoCurrency, - 'networkWallets': '${networkName}:${_wallet.walletAddresses.address}', + 'networkWallets': '${networkName}:${wallet.walletAddresses.address}', 'supportSell': "false", 'supportSwap': "false", 'primaryColor': primaryColor, @@ -77,10 +94,11 @@ class OnRamperBuyProvider { }); } - Future launchProvider(BuildContext context) async { - final uri = requestUrl(context); + Future launchProvider(BuildContext context, bool? isBuyAction) async { + final uri = requestOnramperUrl(context); if (DeviceInfo.instance.isMobile) { - Navigator.of(context).pushNamed(Routes.webViewPage, arguments: [S.of(context).buy, uri]); + Navigator.of(context) + .pushNamed(Routes.webViewPage, arguments: [S.of(context).buy, uri]); } else { await launchUrl(uri); } diff --git a/lib/buy/robinhood/robinhood_buy_provider.dart b/lib/buy/robinhood/robinhood_buy_provider.dart index ade0bf99f..ff6c6a8cf 100644 --- a/lib/buy/robinhood/robinhood_buy_provider.dart +++ b/lib/buy/robinhood/robinhood_buy_provider.dart @@ -1,6 +1,10 @@ import 'dart:convert'; import 'package:cake_wallet/.secrets.g.dart' as secrets; +import 'package:cake_wallet/buy/buy_amount.dart'; +import 'package:cake_wallet/buy/buy_provider.dart'; +import 'package:cake_wallet/buy/buy_provider_description.dart'; +import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; @@ -10,40 +14,48 @@ import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:url_launcher/url_launcher.dart'; -class RobinhoodBuyProvider { - RobinhoodBuyProvider({required WalletBase wallet}) : this._wallet = wallet; - - final WalletBase _wallet; +class RobinhoodBuyProvider extends BuyProvider{ + RobinhoodBuyProvider({required WalletBase wallet, bool isTestEnvironment = false}) + : super(wallet: wallet, isTestEnvironment: isTestEnvironment); static const _baseUrl = 'applink.robinhood.com'; static const _cIdBaseUrl = 'exchange-helper.cakewallet.com'; + + @override + String get title => 'Robinhood Connect'; + + @override + String get buyOptionDescription => S.current.robinhood_option_description; + + @override + String get sellOptionDescription => S.current.robinhood_option_description; + + @override + String get lightIcon => 'assets/images/robinhood_light.png'; + + @override + String get darkIcon => 'assets/images/robinhood_dark.png'; + String get _applicationId => secrets.robinhoodApplicationId; String get _apiSecret => secrets.robinhoodCIdApiSecret; - bool get isAvailable => [ - WalletType.bitcoin, - WalletType.bitcoinCash, - WalletType.litecoin, - WalletType.ethereum - ].contains(_wallet.type); - String getSignature(String message) { - switch (_wallet.type) { + switch (wallet.type) { case WalletType.ethereum: - return _wallet.signMessage(message); + return wallet.signMessage(message); case WalletType.litecoin: case WalletType.bitcoin: case WalletType.bitcoinCash: - return _wallet.signMessage(message, address: _wallet.walletAddresses.address); + return wallet.signMessage(message, address: wallet.walletAddresses.address); default: - throw Exception("WalletType is not available for Robinhood ${_wallet.type}"); + throw Exception("WalletType is not available for Robinhood ${wallet.type}"); } } Future getConnectId() async { - final walletAddress = _wallet.walletAddresses.address; + final walletAddress = wallet.walletAddresses.address; final valid_until = (DateTime.now().millisecondsSinceEpoch / 1000).round() + 10; final message = "$_apiSecret:${valid_until}"; @@ -64,22 +76,22 @@ class RobinhoodBuyProvider { } } - Future requestUrl() async { + Future requestProviderUrl() async { final connectId = await getConnectId(); - final networkName = _wallet.currency.fullName?.toUpperCase().replaceAll(" ", "_"); + final networkName = wallet.currency.fullName?.toUpperCase().replaceAll(" ", "_"); return Uri.https(_baseUrl, '/u/connect', { 'applicationId': _applicationId, 'connectId': connectId, - 'walletAddress': _wallet.walletAddresses.address, - 'userIdentifier': _wallet.walletAddresses.address, + 'walletAddress': wallet.walletAddresses.address, + 'userIdentifier': wallet.walletAddresses.address, 'supportedNetworks': networkName }); } - Future launchProvider(BuildContext context) async { + Future launchProvider(BuildContext context, bool? isBuyAction) async { try { - final uri = await requestUrl(); + final uri = await requestProviderUrl(); await launchUrl(uri, mode: LaunchMode.externalApplication); } catch (_) { await showPopUp( @@ -93,4 +105,5 @@ class RobinhoodBuyProvider { }); } } + } diff --git a/lib/buy/wyre/wyre_buy_provider.dart b/lib/buy/wyre/wyre_buy_provider.dart index 652c92f58..80e48fd4f 100644 --- a/lib/buy/wyre/wyre_buy_provider.dart +++ b/lib/buy/wyre/wyre_buy_provider.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'package:cake_wallet/buy/buy_exception.dart'; +import 'package:flutter/src/widgets/framework.dart'; import 'package:http/http.dart'; import 'package:cake_wallet/buy/buy_amount.dart'; import 'package:cake_wallet/buy/buy_provider.dart'; @@ -35,16 +36,20 @@ class WyreBuyProvider extends BuyProvider { String get title => 'Wyre'; @override - BuyProviderDescription get description => BuyProviderDescription.wyre; + String get buyOptionDescription => ''; @override + String get lightIcon => 'assets/images/robinhood_light.png'; + + @override + String get darkIcon => 'assets/images/robinhood_dark.png'; + String get trackUrl => isTestEnvironment ? _trackTestUrl : _trackProductUrl; String baseApiUrl; - @override Future requestUrl(String amount, String sourceCurrency) async { final timestamp = DateTime.now().millisecondsSinceEpoch.toString(); final url = baseApiUrl + _ordersSuffix + _reserveSuffix + @@ -53,8 +58,8 @@ class WyreBuyProvider extends BuyProvider { final body = { 'amount': amount, 'sourceCurrency': sourceCurrency, - 'destCurrency': walletTypeToCryptoCurrency(walletType).title, - 'dest': walletTypeToString(walletType).toLowerCase() + ':' + walletAddress, + 'destCurrency': walletTypeToCryptoCurrency(wallet.type).title, + 'dest': walletTypeToString(wallet.type).toLowerCase() + ':' + wallet.walletAddresses.address, 'referrerAccountId': _accountId, 'lockFields': ['amount', 'sourceCurrency', 'destCurrency', 'dest'] }; @@ -68,8 +73,8 @@ class WyreBuyProvider extends BuyProvider { if (response.statusCode != 200) { throw BuyException( - description: description, - text: 'Url $url is not found!'); + title: buyOptionDescription, + content: 'Url $url is not found!'); } final responseJSON = json.decode(response.body) as Map; @@ -77,14 +82,13 @@ class WyreBuyProvider extends BuyProvider { return urlFromResponse; } - @override Future calculateAmount(String amount, String sourceCurrency) async { final quoteUrl = _baseProductApiUrl + _ordersSuffix + _quoteSuffix; final body = { 'amount': amount, 'sourceCurrency': sourceCurrency, - 'destCurrency': walletTypeToCryptoCurrency(walletType).title, - 'dest': walletTypeToString(walletType).toLowerCase() + ':' + walletAddress, + 'destCurrency': walletTypeToCryptoCurrency(wallet.type).title, + 'dest': walletTypeToString(wallet.type).toLowerCase() + ':' + wallet.walletAddresses.address, 'accountId': _accountId, 'country': _countryCode }; @@ -99,8 +103,8 @@ class WyreBuyProvider extends BuyProvider { if (response.statusCode != 200) { throw BuyException( - description: description, - text: 'Quote is not found!'); + title: buyOptionDescription, + content: 'Quote is not found!'); } final responseJSON = json.decode(response.body) as Map; @@ -111,7 +115,6 @@ class WyreBuyProvider extends BuyProvider { return BuyAmount(sourceAmount: sourceAmount, destAmount: destAmount, achSourceAmount: achAmount); } - @override Future findOrderById(String id) async { final orderUrl = baseApiUrl + _ordersSuffix + '/$id'; final orderUri = Uri.parse(orderUrl); @@ -119,8 +122,8 @@ class WyreBuyProvider extends BuyProvider { if (orderResponse.statusCode != 200) { throw BuyException( - description: description, - text: 'Order $id is not found!'); + title: buyOptionDescription, + content: 'Order $id is not found!'); } final orderResponseJSON = @@ -141,8 +144,8 @@ class WyreBuyProvider extends BuyProvider { if (transferResponse.statusCode != 200) { throw BuyException( - description: description, - text: 'Transfer $transferId is not found!'); + title: buyOptionDescription, + content: 'Transfer $transferId is not found!'); } final transferResponseJSON = @@ -151,15 +154,25 @@ class WyreBuyProvider extends BuyProvider { return Order( id: id, - provider: description, + provider: BuyProviderDescription.wyre, transferId: transferId, from: from, to: to, state: state, createdAt: createdAt, amount: amount.toString(), - receiveAddress: walletAddress, - walletId: walletId + receiveAddress: wallet.walletAddresses.address, + walletId: wallet.id ); } + + @override + Future launchProvider(BuildContext context, bool? isBuyAction) { + // TODO: implement launchProvider + throw UnimplementedError(); + } + + @override + // TODO: implement sellOptionDescription + String get sellOptionDescription => throw UnimplementedError(); } \ No newline at end of file diff --git a/lib/di.dart b/lib/di.dart index 03b7bfec8..1a0dc5788 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/anonpay/anonpay_api.dart'; import 'package:cake_wallet/anonpay/anonpay_info_base.dart'; import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart'; +import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart'; import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/buy/payfura/payfura_buy_provider.dart'; @@ -796,8 +797,12 @@ Future setup({ getIt .registerFactory(() => DFXBuyProvider(wallet: getIt.get().wallet!)); + getIt.registerFactory(() => MoonPaySellProvider( + settingsStore: getIt.get().settingsStore, + wallet: getIt.get().wallet!)); + getIt.registerFactory(() => OnRamperBuyProvider( - settingsStore: getIt.get().settingsStore, + getIt.get().settingsStore, wallet: getIt.get().wallet!, )); @@ -941,7 +946,8 @@ Future setup({ getIt.registerFactory(() => BuyAmountViewModel()); - getIt.registerFactory(() => BuyOptionsPage(getIt.get())); + getIt.registerFactoryParam( + (isBuyOption, _) => BuySellOptionsPage(getIt.get(), isBuyOption)); getIt.registerFactory(() { final wallet = getIt.get().wallet; diff --git a/lib/entities/buy_provider_types.dart b/lib/entities/buy_provider_types.dart index 1faf2b281..1913d1b25 100644 --- a/lib/entities/buy_provider_types.dart +++ b/lib/entities/buy_provider_types.dart @@ -1,57 +1,112 @@ -import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/buy/buy_provider.dart'; +import 'package:cake_wallet/buy/dfx/dfx_buy_provider.dart'; +import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; +import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart'; +import 'package:cake_wallet/di.dart'; import 'package:cw_core/wallet_type.dart'; enum BuyProviderType { - AskEachTime, - Robinhood, - Onramper, - DFX; + askEachTime, + robinhood, + dfx, + onramper, +} - @override - String toString() { +extension BuyProviderTypeName on BuyProviderType { + String get name { switch (this) { - case BuyProviderType.AskEachTime: - return S.current.ask_each_time; - case BuyProviderType.Robinhood: - return "Robinhood"; - case BuyProviderType.Onramper: - return "Onramper"; - case BuyProviderType.DFX: - return "DFX"; + case BuyProviderType.askEachTime: + return 'Ask each time'; + case BuyProviderType.robinhood: + return 'Robinhood Connect'; + case BuyProviderType.dfx: + return 'DFX Connect'; + case BuyProviderType.onramper: + return 'Onramper'; + default: + return this.toString().split('.').last; } } - static List getAvailableProviders(WalletType walletType) { + String get id { + switch (this) { + case BuyProviderType.askEachTime: + return 'ask_each_time_provider'; + case BuyProviderType.robinhood: + return 'robinhood_connect_provider'; + case BuyProviderType.dfx: + return 'dfx_connect_provider'; + case BuyProviderType.onramper: + return 'onramper_provider'; + default: + return this.toString().split('.').last.replaceAll('.', '_') + .toLowerCase() + '_provider'; + } + } +} + +class BuyProviderHelper { + static List getAvailableBuyProviderTypes( + WalletType walletType) { switch (walletType) { case WalletType.nano: case WalletType.banano: - return [ - BuyProviderType.AskEachTime, - BuyProviderType.Onramper - ]; + return [BuyProviderType.askEachTime, BuyProviderType.onramper]; case WalletType.monero: return [ - BuyProviderType.AskEachTime, - BuyProviderType.Onramper, - BuyProviderType.DFX + BuyProviderType.askEachTime, + BuyProviderType.onramper, + BuyProviderType.dfx ]; case WalletType.bitcoin: case WalletType.ethereum: return [ - BuyProviderType.AskEachTime, - BuyProviderType.Onramper, - BuyProviderType.DFX, - BuyProviderType.Robinhood + BuyProviderType.askEachTime, + BuyProviderType.onramper, + BuyProviderType.dfx, + BuyProviderType.robinhood ]; case WalletType.litecoin: case WalletType.bitcoinCash: - return [ - BuyProviderType.AskEachTime, - BuyProviderType.Onramper, - BuyProviderType.Robinhood - ]; + return [ + BuyProviderType.askEachTime, + BuyProviderType.onramper, + BuyProviderType.robinhood + ]; default: return []; } } + + static List getAvailableSellProviderTypes( + WalletType walletType) { + switch (walletType) { + case WalletType.nano: + case WalletType.banano: + return [BuyProviderType.askEachTime]; + case WalletType.monero: + return [BuyProviderType.askEachTime, BuyProviderType.dfx]; + case WalletType.bitcoin: + case WalletType.ethereum: + return [BuyProviderType.askEachTime, BuyProviderType.dfx]; + case WalletType.litecoin: + case WalletType.bitcoinCash: + return [BuyProviderType.askEachTime]; + default: + return []; + } + } + + static BuyProvider? getProviderByType(BuyProviderType type) { + switch (type) { + case BuyProviderType.robinhood: + return getIt.get(); + case BuyProviderType.dfx: + return getIt.get(); + case BuyProviderType.onramper: + return getIt.get(); + case BuyProviderType.askEachTime: + return null; + } + } } diff --git a/lib/entities/main_actions.dart b/lib/entities/main_actions.dart index 4c629e768..0e4e05ae0 100644 --- a/lib/entities/main_actions.dart +++ b/lib/entities/main_actions.dart @@ -1,18 +1,9 @@ -import 'package:cake_wallet/buy/dfx/dfx_buy_provider.dart'; -import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart'; -import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; -import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart'; -import 'package:cake_wallet/di.dart'; -import 'package:cake_wallet/entities/buy_provider_types.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; -import 'package:url_launcher/url_launcher.dart'; class MainActions { final String Function(BuildContext context) name; @@ -46,53 +37,22 @@ class MainActions { canShow: (viewModel) => viewModel.hasBuyAction, onTap: (BuildContext context, DashboardViewModel viewModel) async { if (!viewModel.isEnabledBuyAction) { - await _showErrorDialog(context, S.of(context).unsupported_asset); + await _showErrorDialog( + context, S.of(context).buy, S.of(context).unsupported_asset); return; } final defaultBuyProvider = viewModel.defaultBuyProvider; try { - await _launchProviderByType(context, defaultBuyProvider); + defaultBuyProvider != null + ? await defaultBuyProvider.launchProvider(context, true) + : await Navigator.of(context).pushNamed(Routes.buySellPage, arguments: true); } catch (e) { - await _showErrorDialog(context, e.toString()); + await _showErrorDialog(context, defaultBuyProvider.toString(), e.toString()); } }, ); - static Future _launchProviderByType(BuildContext context, BuyProviderType providerType) async { - switch (providerType) { - case BuyProviderType.AskEachTime: - Navigator.pushNamed(context, Routes.buy); - break; - case BuyProviderType.Onramper: - await getIt.get().launchProvider(context); - break; - case BuyProviderType.Robinhood: - await getIt.get().launchProvider(context); - break; - case BuyProviderType.DFX: - await getIt.get().launchProvider(context); - break; - default: - throw UnsupportedError('Unsupported buy provider type'); - } - } - - - static Future _showErrorDialog(BuildContext context, String errorMessage) async { - await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: S.of(context).buy, - alertContent: errorMessage, - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop(), - ); - }, - ); - } - static MainActions receiveAction = MainActions._( name: (context) => S.of(context).receive, image: 'assets/images/received.png', @@ -127,42 +87,35 @@ class MainActions { isEnabled: (viewModel) => viewModel.isEnabledSellAction, canShow: (viewModel) => viewModel.hasSellAction, onTap: (BuildContext context, DashboardViewModel viewModel) async { - final walletType = viewModel.type; + if (!viewModel.isEnabledSellAction) { + await _showErrorDialog( + context, S.of(context).sell, S.of(context).unsupported_asset); + return; + } - switch (walletType) { - case WalletType.bitcoin: - case WalletType.litecoin: - case WalletType.ethereum: - case WalletType.polygon: - case WalletType.bitcoinCash: - if (viewModel.isEnabledSellAction) { - final moonPaySellProvider = MoonPaySellProvider(); - final uri = await moonPaySellProvider.requestUrl( - currency: viewModel.wallet.currency, - refundWalletAddress: viewModel.wallet.walletAddresses.address, - settingsStore: viewModel.settingsStore, - ); - if (DeviceInfo.instance.isMobile) { - Navigator.of(context).pushNamed(Routes.webViewPage, - arguments: [S.of(context).sell, uri]); - } else { - await launchUrl(uri); - } - } - - break; - default: - await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: S.of(context).sell, - alertContent: S.of(context).unsupported_asset, - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop()); - }, - ); + final defaultSellProvider = viewModel.defaultSellProvider; + try { + defaultSellProvider != null + ? await defaultSellProvider.launchProvider(context, false) + : await Navigator.of(context).pushNamed(Routes.buySellPage, arguments: false); + } catch (e) { + await _showErrorDialog(context, defaultSellProvider.toString(), e.toString()); } }, ); -} + + static Future _showErrorDialog( + BuildContext context, String title, String errorMessage) async { + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: title, + alertContent: errorMessage, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop(), + ); + }, + ); + } +} \ No newline at end of file diff --git a/lib/router.dart b/lib/router.dart index 11eeb582b..f9ab17d37 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -390,8 +390,10 @@ Route createRoute(RouteSettings settings) { return MaterialPageRoute( builder: (_) => getIt.get(param1: settings.arguments as Order)); - case Routes.buy: - return MaterialPageRoute(builder: (_) => getIt.get()); + case Routes.buySellPage: + final args = settings.arguments as bool; + return MaterialPageRoute( + builder: (_) => getIt.get(param1: args)); case Routes.buyWebView: final args = settings.arguments as List; diff --git a/lib/routes.dart b/lib/routes.dart index 60801297a..59d4acbc9 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -55,7 +55,7 @@ class Routes { static const supportLiveChat = '/support/live_chat'; static const supportOtherLinks = '/support/other'; static const orderDetails = '/order_details'; - static const buy = '/buy'; + static const buySellPage = '/buy_sell_page'; static const buyWebView = '/buy_web_view'; static const unspentCoinsList = '/unspent_coins_list'; static const unspentCoinsDetails = '/unspent_coins_details'; diff --git a/lib/src/screens/buy/buy_options_page.dart b/lib/src/screens/buy/buy_options_page.dart index 62dfc4ec4..6ce8fe9f2 100644 --- a/lib/src/screens/buy/buy_options_page.dart +++ b/lib/src/screens/buy/buy_options_page.dart @@ -1,7 +1,4 @@ -import 'package:cake_wallet/buy/dfx/dfx_buy_provider.dart'; -import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; -import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart'; -import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/buy/buy_provider.dart'; import 'package:cake_wallet/entities/buy_provider_types.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; @@ -11,19 +8,14 @@ import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:flutter/material.dart'; -class BuyOptionsPage extends BasePage { - BuyOptionsPage(this.dashboardViewModel); +class BuySellOptionsPage extends BasePage { + BuySellOptionsPage(this.dashboardViewModel, this.isBuyAction); final DashboardViewModel dashboardViewModel; - final iconDarkRobinhood = 'assets/images/robinhood_dark.png'; - final iconLightRobinhood = 'assets/images/robinhood_light.png'; - final iconDarkOnramper = 'assets/images/onramper_dark.png'; - final iconLightOnramper = 'assets/images/onramper_light.png'; - final iconDarkDFX = 'assets/images/dfx_dark.png'; - final iconLightDFX = 'assets/images/dfx_light.png'; + final bool isBuyAction; @override - String get title => S.current.buy; + String get title => isBuyAction ? S.current.buy : S.current.sell; @override AppBarStyle get appBarStyle => AppBarStyle.regular; @@ -32,17 +24,9 @@ class BuyOptionsPage extends BasePage { Widget body(BuildContext context) { final isLightMode = Theme.of(context).extension()?.useDarkImage ?? false; - final iconRobinhood = Image.asset( - isLightMode ? iconLightRobinhood : iconDarkRobinhood, - height: 40, - width: 40); - final iconOnramper = Image.asset( - isLightMode ? iconLightOnramper : iconDarkOnramper, - height: 40, - width: 40); - final iconDFX = Image.asset(isLightMode ? iconLightDFX : iconDarkDFX, - height: 40, width: 40); - final availableProviders = dashboardViewModel.availableProviders; + final availableProviders = isBuyAction + ? dashboardViewModel.availableBuyProviders + : dashboardViewModel.availableSellProviders; return Container( child: Center( @@ -50,57 +34,43 @@ class BuyOptionsPage extends BasePage { constraints: BoxConstraints(maxWidth: 330), child: Column( children: [ - if (availableProviders.contains(BuyProviderType.Onramper)) - Padding( + ...availableProviders.map((provider) { + final icon = Image.asset( + isLightMode ? provider.lightIcon : provider.darkIcon, + height: 40, + width: 40, + ); + + return Padding( padding: EdgeInsets.only(top: 24), child: OptionTile( - image: iconOnramper, - title: "Onramper", - description: S.of(context).onramper_option_description, - onPressed: () async => await getIt - .get() - .launchProvider(context), + image: icon, + title: provider.toString(), + description: isBuyAction + ? provider.buyOptionDescription + : provider.sellOptionDescription, + onPressed: () => + provider.launchProvider(context, isBuyAction), ), - ), - if (availableProviders.contains(BuyProviderType.Robinhood)) - Padding( - padding: EdgeInsets.only(top: 24), - child: OptionTile( - image: iconRobinhood, - title: "Robinhood Connect", - description: S.of(context).robinhood_option_description, - onPressed: () async => await getIt - .get() - .launchProvider(context), - ), - ), - if (availableProviders.contains(BuyProviderType.DFX)) - Padding( - padding: EdgeInsets.only(top: 24), - child: OptionTile( - image: iconDFX, - title: "DFX Connect", - description: S.of(context).dfx_option_description, - onPressed: () async => await getIt - .get() - .launchProvider(context), - ), - ), + ); + }).toList(), Spacer(), - Padding( - padding: EdgeInsets.fromLTRB(24, 24, 24, 32), - child: Text( - S.of(context).select_buy_provider_notice, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.normal, - color: Theme.of(context) - .extension()! - .detailsTitlesColor, + Padding( + padding: EdgeInsets.fromLTRB(24, 24, 24, 32), + child: Text( + isBuyAction + ? S.of(context).select_buy_provider_notice + : S.of(context).select_sell_provider_notice, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + color: Theme.of(context) + .extension()! + .detailsTitlesColor, + ), ), ), - ), ], ), ), diff --git a/lib/src/screens/buy/widgets/buy_list_item.dart b/lib/src/screens/buy/widgets/buy_list_item.dart index fc8fea81d..d8adddfdc 100644 --- a/lib/src/screens/buy/widgets/buy_list_item.dart +++ b/lib/src/screens/buy/widgets/buy_list_item.dart @@ -29,11 +29,10 @@ class BuyListItem extends StatelessWidget { @override Widget build(BuildContext context) { - final isSelected = selectedProvider?.description == provider.description; + final isSelected = selectedProvider?.buyOptionDescription == provider.buyOptionDescription; final iconColor = isSelected ? Colors.white : Colors.black; - final providerIcon = getBuyProviderIcon(provider.description, - iconColor: iconColor)!; + final providerIcon = Image.asset('assets/images/wyre-icon.png', width: 36, height: 36); final backgroundColor = isSelected ? Palette.greyBlueCraiola @@ -76,7 +75,7 @@ class BuyListItem extends StatelessWidget { padding: EdgeInsets.only(right: 10), child: providerIcon), Text( - provider.description.title, + provider.title, style: TextStyle( color: secondaryTextColor, fontSize: 20, diff --git a/lib/src/screens/settings/other_settings_page.dart b/lib/src/screens/settings/other_settings_page.dart index cc92641f3..c58523185 100644 --- a/lib/src/screens/settings/other_settings_page.dart +++ b/lib/src/screens/settings/other_settings_page.dart @@ -43,10 +43,18 @@ class OtherSettingsPage extends BasePage { if(_otherSettingsViewModel.isEnabledBuyAction) SettingsPickerCell( title: S.current.default_buy_provider, - items: _otherSettingsViewModel.availableBuyProviders, + items: _otherSettingsViewModel.availableBuyProvidersTypes, displayItem: _otherSettingsViewModel.getBuyProviderType, selectedItem: _otherSettingsViewModel.buyProviderType, - onItemSelected: _otherSettingsViewModel.onBuyProviderTypeSelected, + onItemSelected: _otherSettingsViewModel.onBuyProviderTypeSelected + ), + if(_otherSettingsViewModel.isEnabledSellAction) + SettingsPickerCell( + title: S.current.default_sell_provider, + items: _otherSettingsViewModel.availableSellProvidersTypes, + displayItem: _otherSettingsViewModel.getSellProviderType, + selectedItem: _otherSettingsViewModel.sellProviderType, + onItemSelected: _otherSettingsViewModel.onSellProviderTypeSelected, ), SettingsCellWithArrow( title: S.current.settings_terms_and_conditions, diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 95254e557..20f310c83 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; +import 'package:cake_wallet/buy/buy_provider.dart'; import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/buy_provider_types.dart'; import 'package:cake_wallet/entities/cake_2fa_preset_options.dart'; @@ -147,7 +148,9 @@ abstract class SettingsStoreBase with Store { initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings, currentSyncMode = initialSyncMode, currentSyncAll = initialSyncAll, - priority = ObservableMap() { + priority = ObservableMap(), + defaultBuyProviders = ObservableMap(), + defaultSellProviders = ObservableMap() { //this.nodes = ObservableMap.of(nodes); if (initialMoneroTransactionPriority != null) { @@ -181,9 +184,25 @@ abstract class SettingsStoreBase with Store { initializeTrocadorProviderStates(); WalletType.values.forEach((walletType) { - final key = 'defaultBuyProvider_${walletType.toString()}'; - final providerIndex = sharedPreferences.getInt(key); - defaultBuyProviders[walletType] = providerIndex != null ? BuyProviderType.values[providerIndex] : BuyProviderType.AskEachTime; + final key = 'buyProvider_${walletType.toString()}'; + final providerId = sharedPreferences.getString(key); + if (providerId != null) { + defaultBuyProviders[walletType] = BuyProviderType.values + .firstWhere((provider) => provider.id == providerId, orElse: () => BuyProviderType.askEachTime); + } else { + defaultBuyProviders[walletType] = BuyProviderType.askEachTime; + } + }); + + WalletType.values.forEach((walletType) { + final key = 'sellProvider_${walletType.toString()}'; + final providerId = sharedPreferences.getString(key); + if (providerId != null) { + defaultSellProviders[walletType] = BuyProviderType.values + .firstWhere((provider) => provider.id == providerId, orElse: () => BuyProviderType.askEachTime); + } else { + defaultSellProviders[walletType] = BuyProviderType.askEachTime; + } }); reaction( @@ -196,6 +215,20 @@ abstract class SettingsStoreBase with Store { (bool shouldShowYatPopup) => sharedPreferences.setBool(PreferencesKey.shouldShowYatPopup, shouldShowYatPopup)); + defaultBuyProviders.observe((change) { + final String key = 'buyProvider_${change.key.toString()}'; + if (change.newValue != null) { + sharedPreferences.setString(key, change.newValue!.id); + } + }); + + defaultSellProviders.observe((change) { + final String key = 'sellProvider_${change.key.toString()}'; + if (change.newValue != null) { + sharedPreferences.setString(key, change.newValue!.id); + } + }); + priority.observe((change) { final String? key; switch (change.key) { @@ -251,16 +284,6 @@ abstract class SettingsStoreBase with Store { (bool disableSell) => sharedPreferences.setBool(PreferencesKey.disableSellKey, disableSell)); - reaction( - (_) => defaultBuyProviders.asObservable(), - (ObservableMap providers) { - providers.forEach((walletType, provider) { - final key = 'defaultBuyProvider_${walletType.toString()}'; - sharedPreferences.setInt(key, provider.index); - }); - } - ); - reaction( (_) => walletListOrder, (WalletListOrderType walletListOrder) => @@ -594,7 +617,10 @@ abstract class SettingsStoreBase with Store { ObservableMap trocadorProviderStates = ObservableMap(); @observable - ObservableMap defaultBuyProviders = ObservableMap(); + ObservableMap defaultBuyProviders; + + @observable + ObservableMap defaultSellProviders; @observable SortBalanceBy sortBalanceBy; diff --git a/lib/view_model/buy/buy_view_model.dart b/lib/view_model/buy/buy_view_model.dart index 080caa3ad..c0e22dae2 100644 --- a/lib/view_model/buy/buy_view_model.dart +++ b/lib/view_model/buy/buy_view_model.dart @@ -61,8 +61,7 @@ abstract class BuyViewModelBase with Store { String _url = ''; try { - _url = await selectedProvider - !.requestUrl(doubleAmount.toString(), fiatCurrency.title); + _url = await selectedProvider!.requestUrl(doubleAmount.toString(), fiatCurrency.title); } catch (e) { print(e.toString()); } diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 19b5ad544..f4c66b432 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:cake_wallet/buy/buy_provider.dart'; import 'package:cake_wallet/core/key_service.dart'; import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/balance_display_mode.dart'; @@ -41,6 +42,7 @@ import 'package:cw_core/wallet_type.dart'; import 'package:eth_sig_util/util/utils.dart'; import 'package:flutter/services.dart'; import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/entities/buy_provider_types.dart'; part 'dashboard_view_model.g.dart'; @@ -295,13 +297,31 @@ abstract class DashboardViewModelBase with Store { Map> filterItems; - BuyProviderType get defaultBuyProvider => - settingsStore.defaultBuyProviders[wallet.type] ?? BuyProviderType.AskEachTime; + BuyProvider? get defaultBuyProvider => BuyProviderHelper.getProviderByType( + settingsStore.defaultBuyProviders[wallet.type] ?? BuyProviderType.askEachTime); + + BuyProvider? get defaultSellProvider => BuyProviderHelper.getProviderByType( + settingsStore.defaultSellProviders[wallet.type] ?? BuyProviderType.askEachTime); bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled; - List get availableProviders => - BuyProviderType.getAvailableProviders(wallet.type); + List get availableBuyProviders { + final providerTypes = BuyProviderHelper.getAvailableBuyProviderTypes(wallet.type); + return providerTypes + .map((type) => BuyProviderHelper.getProviderByType(type)) + .where((provider) => provider != null) + .cast() + .toList(); + } + + List get availableSellProviders { + final providerTypes = BuyProviderHelper.getAvailableSellProviderTypes(wallet.type); + return providerTypes + .map((type) => BuyProviderHelper.getProviderByType(type)) + .where((provider) => provider != null) + .cast() + .toList(); + } bool get shouldShowYatPopup => settingsStore.shouldShowYatPopup; @@ -315,16 +335,15 @@ abstract class DashboardViewModelBase with Store { bool hasExchangeAction; @computed - bool get isEnabledBuyAction => !settingsStore.disableBuy && wallet.type != WalletType.haven; + bool get isEnabledBuyAction => + !settingsStore.disableBuy && availableBuyProviders.isNotEmpty; @observable bool hasBuyAction; @computed bool get isEnabledSellAction => - !settingsStore.disableSell && - wallet.type != WalletType.haven && - wallet.type != WalletType.monero; + !settingsStore.disableSell && availableSellProviders.isNotEmpty; @observable bool hasSellAction; diff --git a/lib/view_model/order_details_view_model.dart b/lib/view_model/order_details_view_model.dart index 0047ed7b2..4ac848ecf 100644 --- a/lib/view_model/order_details_view_model.dart +++ b/lib/view_model/order_details_view_model.dart @@ -50,8 +50,10 @@ abstract class OrderDetailsViewModelBase with Store { @action Future _updateOrder() async { try { - if (_provider != null) { - final updatedOrder = await _provider!.findOrderById(order.id); + if (_provider != null && (_provider is MoonPayBuyProvider || _provider is WyreBuyProvider)) { + final updatedOrder = _provider is MoonPayBuyProvider + ? await (_provider as MoonPayBuyProvider).findOrderById(order.id) + : await (_provider as WyreBuyProvider).findOrderById(order.id); updatedOrder.from = order.from; updatedOrder.to = order.to; updatedOrder.receiveAddress = order.receiveAddress; @@ -87,19 +89,26 @@ abstract class OrderDetailsViewModelBase with Store { value: order.provider.title) ); - if (_provider?.trackUrl.isNotEmpty ?? false) { - final buildURL = _provider!.trackUrl + '${order.transferId}'; - items.add( - TrackTradeListItem( - title: 'Track', - value: buildURL, - onTap: () { - try { - launch(buildURL); - } catch (e) {} - } - ) - ); + if (_provider != null && (_provider is MoonPayBuyProvider || _provider is WyreBuyProvider)) { + + final trackUrl = _provider is MoonPayBuyProvider + ? (_provider as MoonPayBuyProvider).trackUrl + : (_provider as WyreBuyProvider).trackUrl; + + if (trackUrl.isNotEmpty ?? false) { + final buildURL = trackUrl + '${order.transferId}'; + items.add( + TrackTradeListItem( + title: 'Track', + value: buildURL, + onTap: () { + try { + launch(buildURL); + } catch (e) {} + } + ) + ); + } } items.add( diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart index 4e712dae1..60ed550ef 100644 --- a/lib/view_model/settings/other_settings_view_model.dart +++ b/lib/view_model/settings/other_settings_view_model.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/entities/buy_provider_types.dart'; import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/transaction_history.dart'; @@ -59,12 +60,24 @@ abstract class OtherSettingsViewModelBase with Store { bool get isEnabledBuyAction => !_settingsStore.disableBuy && _wallet.type != WalletType.haven; - List get availableBuyProviders => - BuyProviderType.getAvailableProviders(walletType); + @computed + bool get isEnabledSellAction => + !_settingsStore.disableSell && _wallet.type != WalletType.haven; + + List get availableBuyProvidersTypes { + return BuyProviderHelper.getAvailableBuyProviderTypes(walletType); + } + + List get availableSellProvidersTypes => + BuyProviderHelper.getAvailableSellProviderTypes(walletType); BuyProviderType get buyProviderType => _settingsStore.defaultBuyProviders[walletType] ?? - BuyProviderType.AskEachTime; + BuyProviderType.askEachTime; + + BuyProviderType get sellProviderType => + _settingsStore.defaultSellProviders[walletType] ?? + BuyProviderType.askEachTime; String getDisplayPriority(dynamic priority) { final _priority = priority as TransactionPriority; @@ -81,13 +94,27 @@ abstract class OtherSettingsViewModelBase with Store { String getBuyProviderType(dynamic buyProviderType) { final _buyProviderType = buyProviderType as BuyProviderType; + return _buyProviderType == BuyProviderType.askEachTime + ? S.current.ask_each_time + : _buyProviderType.name; + } - return _buyProviderType.toString(); + String getSellProviderType(dynamic sellProviderType) { + final _sellProviderType = sellProviderType as BuyProviderType; + return _sellProviderType == BuyProviderType.askEachTime + ? S.current.ask_each_time + : _sellProviderType.name; } void onDisplayPrioritySelected(TransactionPriority priority) => _settingsStore.priority[_wallet.type] = priority; - void onBuyProviderTypeSelected(BuyProviderType buyProviderType) => + @action + BuyProviderType onBuyProviderTypeSelected(BuyProviderType buyProviderType) => _settingsStore.defaultBuyProviders[walletType] = buyProviderType; + + @action + BuyProviderType onSellProviderTypeSelected( + BuyProviderType sellProviderType) => + _settingsStore.defaultSellProviders[walletType] = sellProviderType; } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 251afa409..ba2f7731b 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -754,6 +754,8 @@ "dfx_option_description": "ﺎﺑﻭﺭﻭﺃ ﻲﻓ ﺕﺎﻛﺮﺸﻟﺍﻭ ﺔﺋﺰﺠﺘﻟﺍ ءﻼﻤﻌﻟ .ﻲﻓﺎﺿﺇ KYC ﻥﻭﺪﺑ ﻭﺭﻮﻳ 990 ﻰﻟﺇ ﻞﺼﻳ ﺎﻣ .ﻱﺮﺴﻳﻮﺴﻟﺍ", "polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ", "wallet_seed_legacy": "بذرة محفظة قديمة", + "default_sell_provider": " ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ", + "select_sell_provider_notice": ".ﻖﻴﺒﻄﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻚﺑ ﺹﺎﺨﻟﺍ ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ ﻦﻴﻴﻌﺗ ﻖﻳﺮﻃ ﻦﻋ ﺔﺷﺎﺸﻟﺍ ﻩﺬﻫ ﻲﻄﺨﺗ", "custom_drag": "مخصص (عقد وسحب)", "switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index ae83da481..d53df2d0e 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -750,6 +750,8 @@ "dfx_option_description": "Купете крипто с EUR и CHF. До 990 € без допълнителен KYC. За клиенти на дребно и корпоративни клиенти в Европа", "polygonscan_history": "История на PolygonScan", "wallet_seed_legacy": "Наследено портфейл семе", + "default_sell_provider": "Доставчик за продажба по подразбиране", + "select_sell_provider_notice": "Изберете доставчик на продажба по-горе. Можете да пропуснете този екран, като зададете своя доставчик на продажба по подразбиране в настройките на приложението.", "custom_drag": "Персонализиране (задръжте и плъзнете)", "switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)" } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index da22f9f6b..4d29f32a0 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -750,6 +750,8 @@ "dfx_option_description": "Nakupujte kryptoměny za EUR a CHF. Až 990 € bez dalších KYC. Pro maloobchodní a firemní zákazníky v Evropě", "polygonscan_history": "Historie PolygonScan", "wallet_seed_legacy": "Starší semeno peněženky", + "default_sell_provider": "Výchozí poskytovatel prodeje", + "select_sell_provider_notice": "Výše vyberte poskytovatele prodeje. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele prodeje v nastavení aplikace.", "custom_drag": "Custom (Hold and Drag)", "switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)" } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 69b7e47d2..e8f03a23b 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -758,6 +758,8 @@ "dfx_option_description": "Krypto mit EUR und CHF kaufen. Bis zu 990€ ohne zusätzliches KYC. Für Privat- und Firmenkunden in Europa", "polygonscan_history": "PolygonScan-Verlauf", "wallet_seed_legacy": "Legacy Wallet Seed", + "default_sell_provider": "Standard-Verkaufsanbieter", + "select_sell_provider_notice": "Wählen Sie oben einen Verkaufsanbieter aus. Sie können diesen Bildschirm überspringen, indem Sie in den App-Einstellungen Ihren Standard-Verkaufsanbieter festlegen.", "custom_drag": "Custom (Hold and Drag)", "switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)" } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index e1a7fdebc..3f7cbdad2 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -759,6 +759,8 @@ "dfx_option_description": "Buy crypto with EUR & CHF. Up to 990€ without additional KYC. For retail and corporate customers in Europe", "polygonscan_history": "PolygonScan history", "wallet_seed_legacy": "Legacy wallet seed", + "default_sell_provider": "Default Sell Provider", + "select_sell_provider_notice": "Select a sell provider above. You can skip this screen by setting your default sell provider in app settings.", "custom_drag": "Custom (Hold and Drag)", "switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)" } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 21de24163..09bbe985e 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -758,6 +758,8 @@ "dfx_option_description": "Compre criptomonedas con EUR y CHF. Hasta 990€ sin KYC adicional. Para clientes minoristas y corporativos en Europa", "polygonscan_history": "Historial de PolygonScan", "wallet_seed_legacy": "Semilla de billetera heredada", + "default_sell_provider": "Proveedor de venta predeterminado", + "select_sell_provider_notice": "Seleccione un proveedor de venta arriba. Puede omitir esta pantalla configurando su proveedor de venta predeterminado en la configuración de la aplicación.", "custom_drag": "Custom (mantenía y arrastre)", "switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)" } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 2d3895351..7af139a8f 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -758,6 +758,8 @@ "dfx_option_description": "Achetez des crypto-monnaies avec EUR et CHF. Jusqu'à 990€ sans KYC supplémentaire. Pour les clients particuliers et entreprises en Europe", "polygonscan_history": "Historique de PolygonScan", "wallet_seed_legacy": "Graine de portefeuille hérité", + "default_sell_provider": "Fournisseur de vente par défaut", + "select_sell_provider_notice": "Sélectionnez un fournisseur de vente ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur de vente par défaut dans les paramètres de l'application.", "custom_drag": "Custom (maintenir et traîner)", "switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)" } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 69e118f49..ec820f01f 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -736,6 +736,8 @@ "dfx_option_description": "Sayi crypto tare da EUR & CHF. Har zuwa € 990 ba tare da ƙarin KYC ba. Don 'yan kasuwa da abokan ciniki na kamfanoni a Turai", "polygonscan_history": "PolygonScan tarihin kowane zamani", "wallet_seed_legacy": "Tallarin walat walat", + "default_sell_provider": "Tsohuwar Mai Bayar Siyarwa", + "select_sell_provider_notice": "Zaɓi mai bada siyarwa a sama. Kuna iya tsallake wannan allon ta saita mai bada siyar da ku a cikin saitunan app.", "custom_drag": "Al'ada (riƙe da ja)", "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)" } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 5774203db..da83e8cc7 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -758,6 +758,8 @@ "dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। अतिरिक्त केवाईसी के बिना 990€ तक। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए", "polygonscan_history": "पॉलीगॉनस्कैन इतिहास", "wallet_seed_legacy": "विरासत बटुए बीज", + "default_sell_provider": "डिफ़ॉल्ट विक्रय प्रदाता", + "select_sell_provider_notice": "ऊपर एक विक्रय प्रदाता का चयन करें। आप ऐप सेटिंग में अपना डिफ़ॉल्ट विक्रय प्रदाता सेट करके इस स्क्रीन को छोड़ सकते हैं।", "custom_drag": "कस्टम (पकड़ और खींचें)", "switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 5fde4d6de..71b767bdc 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -756,6 +756,8 @@ "dfx_option_description": "Kupujte kripto s EUR i CHF. Do 990 € bez dodatnog KYC-a. Za maloprodajne i poslovne korisnike u Europi", "polygonscan_history": "Povijest PolygonScan", "wallet_seed_legacy": "Sjeme naslijeđenog novčanika", + "default_sell_provider": "Zadani dobavljač prodaje", + "select_sell_provider_notice": "Gore odaberite pružatelja usluga prodaje. Ovaj zaslon možete preskočiti postavljanjem zadanog pružatelja usluga prodaje u postavkama aplikacije.", "custom_drag": "Prilagođeni (držite i povucite)", "switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)" } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 208569b31..2398eccd1 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -746,6 +746,8 @@ "dfx_option_description": "Beli kripto dengan EUR & CHF. Hingga 990€ tanpa KYC tambahan. Untuk pelanggan ritel dan korporat di Eropa", "polygonscan_history": "Sejarah PolygonScan", "wallet_seed_legacy": "Biji dompet warisan", + "default_sell_provider": "Penyedia Penjualan Default", + "select_sell_provider_notice": "Pilih penyedia jual di atas. Anda dapat melewati layar ini dengan mengatur penyedia penjualan default Anda di pengaturan aplikasi.", "custom_drag": "Khusus (tahan dan seret)", "switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)" } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 51beaf576..e8b07c25f 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -758,6 +758,8 @@ "dfx_option_description": "Acquista criptovalute con EUR e CHF. Fino a 990€ senza KYC aggiuntivi. Per clienti al dettaglio e aziendali in Europa", "polygonscan_history": "Cronologia PolygonScan", "wallet_seed_legacy": "Seme di portafoglio legacy", + "default_sell_provider": "Fornitore di vendita predefinito", + "select_sell_provider_notice": "Seleziona un fornitore di vendita sopra. Puoi saltare questa schermata impostando il tuo fornitore di vendita predefinito nelle impostazioni dell'app.", "custom_drag": "Custom (Hold and Drag)", "switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)" } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index ca197adae..94d43cbfb 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -758,6 +758,8 @@ "dfx_option_description": "EUR と CHF で暗号通貨を購入します。追加のKYCなしで最大990ユーロ。ヨーロッパの小売および法人顧客向け", "polygonscan_history": "ポリゴンスキャン履歴", "wallet_seed_legacy": "レガシーウォレットシード", + "default_sell_provider": "デフォルトの販売プロバイダー", + "select_sell_provider_notice": "上記の販売プロバイダーを選択してください。アプリ設定でデフォルトの販売プロバイダーを設定することで、この画面をスキップできます。", "custom_drag": "カスタム(ホールドとドラッグ)", "switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index c657dad7e..ca727c046 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -756,6 +756,8 @@ "dfx_option_description": "EUR 및 CHF로 암호화폐를 구매하세요. 추가 KYC 없이 최대 990€. 유럽의 소매 및 기업 고객용", "polygonscan_history": "다각형 스캔 기록", "wallet_seed_legacy": "레거시 지갑 시드", + "default_sell_provider": "기본 판매 공급자", + "select_sell_provider_notice": "위에서 판매 공급자를 선택하세요. 앱 설정에서 기본 판매 공급자를 설정하면 이 화면을 건너뛸 수 있습니다.", "custom_drag": "사용자 정의 (홀드 앤 드래그)", "switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)" } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 690f59ccc..bd09bf740 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -756,6 +756,8 @@ "dfx_option_description": "EUR & CHF ဖြင့် crypto ကိုဝယ်ပါ။ အပို KYC မပါဘဲ 990€ အထိ။ ဥရောပရှိ လက်လီရောင်းချသူများနှင့် ကော်ပိုရိတ်ဖောက်သည်များအတွက်", "polygonscan_history": "PolygonScan မှတ်တမ်း", "wallet_seed_legacy": "အမွေအနှစ်ပိုက်ဆံအိတ်မျိုးစေ့", + "default_sell_provider": "ပုံသေရောင်းချပေးသူ", + "select_sell_provider_notice": "အထက်ဖော်ပြပါ အရောင်းဝန်ဆောင်မှုပေးသူကို ရွေးပါ။ အက်ပ်ဆက်တင်များတွင် သင်၏မူလရောင်းချပေးသူကို သတ်မှတ်ခြင်းဖြင့် ဤစခရင်ကို ကျော်နိုင်သည်။", "custom_drag": "စိတ်ကြိုက် (Drag)", "switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 426341bc4..8b8e1875e 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -758,6 +758,8 @@ "dfx_option_description": "Koop crypto met EUR & CHF. Tot 990€ zonder extra KYC. Voor particuliere en zakelijke klanten in Europa", "polygonscan_history": "PolygonScan-geschiedenis", "wallet_seed_legacy": "Legacy portemonnee zaad", + "default_sell_provider": "Standaard verkoopaanbieder", + "select_sell_provider_notice": "Selecteer hierboven een verkoopaanbieder. U kunt dit scherm overslaan door uw standaardverkoopprovider in te stellen in de app-instellingen.", "custom_drag": "Custom (vasthouden en slepen)", "switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)" } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 5b6581bad..03d669904 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -758,6 +758,8 @@ "dfx_option_description": "Kupuj kryptowaluty za EUR i CHF. Do 990 € bez dodatkowego KYC. Dla klientów detalicznych i korporacyjnych w Europie", "polygonscan_history": "Historia PolygonScan", "wallet_seed_legacy": "Dziedziczne ziarno portfela", + "default_sell_provider": "Domyślny dostawca sprzedaży", + "select_sell_provider_notice": "Wybierz dostawcę sprzedaży powyżej. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę sprzedaży w ustawieniach aplikacji.", "custom_drag": "Niestandardowe (trzymaj i przeciągnij)", "switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)" } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 5df592837..8cc55ee08 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -757,6 +757,8 @@ "dfx_option_description": "Compre criptografia com EUR e CHF. Até 990€ sem KYC adicional. Para clientes de varejo e corporativos na Europa", "polygonscan_history": "História do PolygonScan", "wallet_seed_legacy": "Semente de carteira herdada", + "default_sell_provider": "Provedor de venda padrão", + "select_sell_provider_notice": "Selecione um fornecedor de venda acima. Você pode pular esta tela definindo seu provedor de venda padrão nas configurações do aplicativo.", "custom_drag": "Personalizado (segure e arraste)", "switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)" } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index e6d149596..bfc6b7b10 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -758,6 +758,8 @@ "dfx_option_description": "Покупайте криптовалюту за EUR и CHF. До 990€ без дополнительного KYC. Для розничных и корпоративных клиентов в Европе", "polygonscan_history": "История PolygonScan", "wallet_seed_legacy": "Наследие семя кошелька", + "default_sell_provider": "Поставщик продаж по умолчанию", + "select_sell_provider_notice": "Выберите поставщика услуг продажи выше. Вы можете пропустить этот экран, установив поставщика услуг продаж по умолчанию в настройках приложения.", "custom_drag": "Пользователь (удерживайте и перетаскивайте)", "switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon)." } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index b445562da..d3142a534 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -756,6 +756,8 @@ "dfx_option_description": "ซื้อ crypto ด้วย EUR และ CHF สูงถึง 990€ โดยไม่มี KYC เพิ่มเติม สำหรับลูกค้ารายย่อยและลูกค้าองค์กรในยุโรป", "polygonscan_history": "ประวัติ PolygonScan", "wallet_seed_legacy": "เมล็ดกระเป๋าเงินมรดก", + "default_sell_provider": "ผู้ให้บริการการขายเริ่มต้น", + "select_sell_provider_notice": "เลือกผู้ให้บริการการขายด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการการขายเริ่มต้นในการตั้งค่าแอป", "custom_drag": "กำหนดเอง (ค้างและลาก)", "switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 5b9af5243..dcae1d6ed 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -752,6 +752,8 @@ "dfx_option_description": "Bumili ng crypto gamit ang EUR at CHF. Hanggang 990€ nang walang karagdagang KYC. Para sa retail at corporate na mga customer sa Europe", "polygonscan_history": "Kasaysayan ng PolygonScan", "wallet_seed_legacy": "Legacy wallet seed", + "default_sell_provider": "Default na Sell Provider", + "select_sell_provider_notice": "Pumili ng provider ng nagbebenta sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na sell provider sa mga setting ng app.", "custom_drag": "Pasadyang (hawakan at i -drag)", "switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)" } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 948415da9..a2722856a 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -756,6 +756,8 @@ "dfx_option_description": "EUR ve CHF ile kripto satın alın. Ek KYC olmadan 990 €'ya kadar. Avrupa'daki perakende ve kurumsal müşteriler için", "polygonscan_history": "PolygonScan geçmişi", "wallet_seed_legacy": "Eski cüzdan tohumu", + "default_sell_provider": "Varsayılan Satış Sağlayıcısı", + "select_sell_provider_notice": "Yukarıdan bir satış sağlayıcısı seçin. Uygulama ayarlarında varsayılan satış sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.", "custom_drag": "Özel (Bekle ve Sürükle)", "switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)" } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index f01afeaad..1a37f6550 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -758,6 +758,8 @@ "seed_language_chinese_traditional": "Китайський (традиційний)", "polygonscan_history": "Історія PolygonScan", "wallet_seed_legacy": "Спадець насіння гаманця", + "default_sell_provider": "Постачальник продажу за замовчуванням", + "select_sell_provider_notice": "Виберіть вище постачальника послуг продажу. Ви можете пропустити цей екран, встановивши постачальника послуг продажу за умовчанням у налаштуваннях програми.", "custom_drag": "На замовлення (утримуйте та перетягується)", "switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)" } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index c8d46bc44..af030e0e7 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -750,6 +750,8 @@ "dfx_option_description": "EUR ﺭﻭﺍ CHF ﯽﻓﺎﺿﺍ ۔ﮟﯾﺪﯾﺮﺧ ﻮﭩﭘﺮﮐ ﮫﺗﺎﺳ ﮯﮐ KYC ﮯﯿﻟ ﮯﮐ ﻦﯿﻓﺭﺎﺻ ﭧﯾﺭﻮﭘﺭﺎﮐ ﺭﻭﺍ ﮦﺩﺭﻮﺧ ﮟ", "polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ", "wallet_seed_legacy": "میراثی پرس کا بیج", + "default_sell_provider": " ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ", + "select_sell_provider_notice": "۔ﮟﯿﮨ ﮯﺘﮑﺳ ﮌﻮﮭﭼ ﻮﮐ ﻦﯾﺮﮑﺳﺍ ﺱﺍ ﺮﮐ ﮮﺩ ﺐﯿﺗﺮﺗ ﻮﮐ ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ ﮯﻨﭘﺍ ﮟﯿﻣ ﺕﺎﺒ", "custom_drag": "کسٹم (ہولڈ اینڈ ڈریگ)", "switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ " } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 3323429a8..a0dcf33a8 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -752,6 +752,8 @@ "dfx_option_description": "Ra crypto pẹlu EUR & CHF. Titi di 990 € laisi afikun KYC. Fun soobu ati awọn onibara ile-iṣẹ ni Yuroopu", "polygonscan_history": "PolygonScan itan", "wallet_seed_legacy": "Irugbin akole", + "default_sell_provider": "Aiyipada Olupese Tita", + "select_sell_provider_notice": "Yan olupese ti o ta loke. O le foju iboju yii nipa tito olupese iṣẹ tita aiyipada rẹ ni awọn eto app.", "custom_drag": "Aṣa (mu ati fa)", "switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)" } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 148460ffb..b7f216640 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -757,6 +757,8 @@ "dfx_option_description": "用欧元和瑞士法郎购买加密货币。高达 990 欧元,无需额外 KYC。对于欧洲的零售和企业客户", "polygonscan_history": "多边形扫描历史", "wallet_seed_legacy": "旧的钱包种子", + "default_sell_provider": "默认销售提供商", + "select_sell_provider_notice": "选择上面的销售提供商。您可以通过在应用程序设置中设置默认销售提供商来跳过此屏幕。", "custom_drag": "定制(保持和拖动)", "switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)" } From f612516be06f353c92d946d5df709651926cf504 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Sat, 30 Dec 2023 16:28:33 +0100 Subject: [PATCH 085/241] CW-545-Overriding-Erc20-tokens-list (#1249) * fix: Erc20 tokens configs list overriding each other in different ethereum wallets * feat: Add backward compatibility for wallets that already use the previous erc20tokens box --- cw_core/lib/erc20_token.dart | 3 ++- cw_ethereum/lib/ethereum_wallet.dart | 40 ++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/cw_core/lib/erc20_token.dart b/cw_core/lib/erc20_token.dart index 830ce383b..f8c2afc06 100644 --- a/cw_core/lib/erc20_token.dart +++ b/cw_core/lib/erc20_token.dart @@ -61,7 +61,8 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin { static const typeId = ERC20_TOKEN_TYPE_ID; static const boxName = 'Erc20Tokens'; - static const polygonBoxName = ' PolygonErc20Tokens'; + static const ethereumBoxName = 'EthereumErc20Tokens'; + static const polygonBoxName = 'PolygonErc20Tokens'; @override bool operator ==(other) => diff --git a/cw_ethereum/lib/ethereum_wallet.dart b/cw_ethereum/lib/ethereum_wallet.dart index 5c6cc4448..cd4bd84cc 100644 --- a/cw_ethereum/lib/ethereum_wallet.dart +++ b/cw_ethereum/lib/ethereum_wallet.dart @@ -75,6 +75,8 @@ abstract class EthereumWalletBase late final Box erc20TokensBox; + late final Box ethereumErc20TokensBox; + late final EthPrivateKey _ethPrivateKey; EthPrivateKey get ethPrivateKey => _ethPrivateKey; @@ -102,7 +104,8 @@ abstract class EthereumWalletBase Completer _sharedPrefs = Completer(); Future init() async { - erc20TokensBox = await CakeHive.openBox(Erc20Token.boxName); + await movePreviousErc20BoxConfigsToNewBox(); + await walletAddresses.init(); await transactionHistory.init(); _ethPrivateKey = await getPrivateKey( @@ -114,6 +117,33 @@ abstract class EthereumWalletBase await save(); } + /// Majorly for backward compatibility for previous configs that have been set. + Future movePreviousErc20BoxConfigsToNewBox() async { + // Opens a box specific to this wallet + ethereumErc20TokensBox = await CakeHive.openBox( + "${walletInfo.name.replaceAll(" ", "_")}_${Erc20Token.ethereumBoxName}"); + + //Open the previous token configs box + erc20TokensBox = await CakeHive.openBox(Erc20Token.boxName); + + // Check if it's empty, if it is, we stop the flow and return. + if (erc20TokensBox.isEmpty) { + // If it's empty, but the new wallet specific box is also empty, + // we load the initial tokens to the new box. + if (ethereumErc20TokensBox.isEmpty) addInitialTokens(); + return; + } + + final allValues = erc20TokensBox.values.toList(); + + // Clear and delete the old token box + await erc20TokensBox.clear(); + await erc20TokensBox.deleteFromDisk(); + + // Add all the previous tokens with configs to the new box + ethereumErc20TokensBox.addAll(allValues); + } + @override int calculateEstimatedFee(TransactionPriority priority, int? amount) { try { @@ -378,7 +408,7 @@ abstract class EthereumWalletBase } Future _fetchErc20Balances() async { - for (var token in erc20TokensBox.values) { + for (var token in ethereumErc20TokensBox.values) { try { if (token.enabled) { balance[token] = await _client.fetchERC20Balances( @@ -413,7 +443,7 @@ abstract class EthereumWalletBase Future? updateBalance() async => await _updateBalance(); - List get erc20Currencies => erc20TokensBox.values.toList(); + List get erc20Currencies => ethereumErc20TokensBox.values.toList(); Future addErc20Token(Erc20Token token) async { String? iconPath; @@ -433,7 +463,7 @@ abstract class EthereumWalletBase iconPath: iconPath, ); - await erc20TokensBox.put(_token.contractAddress, _token); + await ethereumErc20TokensBox.put(_token.contractAddress, _token); if (_token.enabled) { balance[_token] = await _client.fetchERC20Balances( @@ -463,7 +493,7 @@ abstract class EthereumWalletBase void addInitialTokens() { final initialErc20Tokens = DefaultErc20Tokens().initialErc20Tokens; - initialErc20Tokens.forEach((token) => erc20TokensBox.put(token.contractAddress, token)); + initialErc20Tokens.forEach((token) => ethereumErc20TokensBox.put(token.contractAddress, token)); } @override From 3522561cfcbe420caee880988990af3fb8379973 Mon Sep 17 00:00:00 2001 From: Serhii Date: Sat, 30 Dec 2023 21:55:17 +0200 Subject: [PATCH 086/241] info page refactoring --- lib/di.dart | 9 +- lib/router.dart | 12 ++- lib/routes.dart | 3 +- lib/src/screens/InfoPage.dart | 83 ++++++++++++++++++ .../screens/new_wallet/new_wallet_page.dart | 2 +- lib/src/screens/seed/pre_seed_page.dart | 27 ++++++ lib/src/screens/seed/warning_page.dart | 86 ------------------- .../settings/security_backup_page.dart | 2 +- .../setup_2fa/setup_2fa_info_page.dart | 20 +++++ 9 files changed, 148 insertions(+), 96 deletions(-) create mode 100644 lib/src/screens/InfoPage.dart create mode 100644 lib/src/screens/seed/pre_seed_page.dart delete mode 100644 lib/src/screens/seed/warning_page.dart create mode 100644 lib/src/screens/setup_2fa/setup_2fa_info_page.dart diff --git a/lib/di.dart b/lib/di.dart index 49fafb357..dd1001858 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -50,6 +50,7 @@ import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart'; import 'package:cake_wallet/src/screens/settings/tor_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart'; +import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_info_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart'; @@ -133,7 +134,7 @@ import 'package:cake_wallet/src/screens/rescan/rescan_page.dart'; import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart'; import 'package:cake_wallet/src/screens/restore/restore_options_page.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; -import 'package:cake_wallet/src/screens/seed/warning_page.dart'; +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_template_page.dart'; import 'package:cake_wallet/src/screens/setup_pin_code/setup_pin_code.dart'; @@ -524,6 +525,8 @@ Future setup({ getIt.registerFactory( () => TransactionsPage(dashboardViewModel: getIt.get())); + getIt.registerFactory(() => Setup2FAInfoPage()); + getIt.registerFactory( () => Setup2FAPage(setup2FAViewModel: getIt.get())); @@ -915,9 +918,9 @@ Future setup({ getIt.registerFactoryParam( (param1, isCreate) => NewWalletTypePage(onTypeSelected: param1, isCreate: isCreate ?? true)); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (seedPhraseLength, _) - => WarningPage(seedPhraseLength)); + => PreSeedPage(seedPhraseLength)); getIt.registerFactoryParam((trade, _) => TradeDetailsViewModel( diff --git a/lib/router.dart b/lib/router.dart index 5148e2d16..b7b7c9a8e 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -42,11 +42,12 @@ import 'package:cake_wallet/src/screens/order_details/order_details_page.dart'; import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; -import 'package:cake_wallet/src/screens/seed/warning_page.dart'; +import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart'; import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart'; import 'package:cake_wallet/src/screens/settings/tor_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart'; +import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_info_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart'; @@ -414,10 +415,10 @@ Route createRoute(RouteSettings settings) { case Routes.faq: return MaterialPageRoute(builder: (_) => getIt.get()); - case Routes.warningPage: + case Routes.preSeedPage: return MaterialPageRoute( - builder: (_) => getIt.get( - param1: settings.arguments as int?)); + builder: (_) => getIt.get( + param1: settings.arguments as int)); case Routes.backup: return CupertinoPageRoute( @@ -580,6 +581,9 @@ Route createRoute(RouteSettings settings) { case Routes.modify2FAPage: return MaterialPageRoute(builder: (_) => getIt.get()); + case Routes.setup2faInfoPage: + return MaterialPageRoute(builder: (_) => getIt.get()); + case Routes.homeSettings: return CupertinoPageRoute( builder: (_) => getIt.get(param1: settings.arguments), diff --git a/lib/routes.dart b/lib/routes.dart index 06bf7d5fa..7ad5c70bc 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -47,7 +47,7 @@ class Routes { static const exchangeTemplate = '/exchange_template'; static const restoreWalletType = '/restore_wallet_type'; static const restoreWallet = '/restore_wallet'; - static const warningPage = '/warning_page'; + static const preSeedPage = '/pre_seed_page'; static const backup = '/backup'; static const editBackupPassword = '/edit_backup_passowrd'; static const restoreFromBackup = '/restore_from_backup'; @@ -96,6 +96,7 @@ class Routes { static const setup_2faQRPage = '/setup_2fa_qr_page'; static const totpAuthCodePage = '/totp_auth_code_page'; static const modify2FAPage = '/modify_2fa_page'; + static const setup2faInfoPage = '/setup_2fa_info_page'; static const homeSettings = '/home_settings'; static const editToken = '/edit_token'; static const manageNodes = '/manage_nodes'; diff --git a/lib/src/screens/InfoPage.dart b/lib/src/screens/InfoPage.dart new file mode 100644 index 000000000..5398df22c --- /dev/null +++ b/lib/src/screens/InfoPage.dart @@ -0,0 +1,83 @@ +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/theme_base.dart'; +import 'package:cake_wallet/utils/responsive_layout_util.dart'; +import 'package:flutter/material.dart'; + +abstract class InfoPage extends BasePage { + InfoPage({ + this.imageLightPath = 'assets/images/pre_seed_light.png', + this.imageDarkPath = 'assets/images/pre_seed_dark.png', + }); + + final String imageLightPath; + final String imageDarkPath; + + Image get imageLight => Image.asset(imageLightPath); + Image get imageDark => Image.asset(imageDarkPath); + + bool get onWillPop => true; + String get pageTitle; + String get pageDescription; + String get buttonText; + void Function(BuildContext) get onPressed; + + @override + Widget? leading(BuildContext context) => null; + + @override + String get title => pageTitle; + + @override + Widget body(BuildContext context) { + final image = currentTheme.type == ThemeType.dark ? imageDark : imageLight; + + return WillPopScope( + onWillPop: () async => onWillPop, + child: Container( + alignment: Alignment.center, + padding: EdgeInsets.all(24), + child: ConstrainedBox( + constraints: BoxConstraints( + maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: ConstrainedBox( + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context).size.height * 0.3), + child: AspectRatio(aspectRatio: 1, child: image), + ), + ), + Expanded( + child: Padding( + padding: EdgeInsets.all(10), + child: Text( + pageDescription, + textAlign: TextAlign.center, + style: TextStyle( + height: 1.7, + fontSize: 14, + fontWeight: FontWeight.normal, + color: Theme.of(context) + .extension()! + .secondaryTextColor, + ), + ), + ), + ), + PrimaryButton( + onPressed: () => onPressed(context), + text: buttonText, + color: Theme.of(context).primaryColor, + textColor: Colors.white, + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index 9d37e22eb..499e5feff 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -73,7 +73,7 @@ class _WalletNameFormState extends State { _stateReaction ??= reaction((_) => _walletNewVM.state, (ExecutionState state) async { if (state is ExecutedSuccessfullyState) { Navigator.of(navigatorKey.currentContext!) - .pushNamed(Routes.warningPage, arguments: _walletNewVM.seedPhraseWordsLength); + .pushNamed(Routes.preSeedPage, arguments: _walletNewVM.seedPhraseWordsLength); } if (state is FailureState) { diff --git a/lib/src/screens/seed/pre_seed_page.dart b/lib/src/screens/seed/pre_seed_page.dart new file mode 100644 index 000000000..730dfa5f8 --- /dev/null +++ b/lib/src/screens/seed/pre_seed_page.dart @@ -0,0 +1,27 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/InfoPage.dart'; +import 'package:flutter/cupertino.dart'; + +class PreSeedPage extends InfoPage { + PreSeedPage(this.seedPhraseLength); + + final int seedPhraseLength; + + @override + bool get onWillPop => false; + + @override + String get pageTitle => S.current.pre_seed_title; + + @override + String get pageDescription => + S.current.pre_seed_description(seedPhraseLength.toString()); + + @override + String get buttonText => S.current.pre_seed_button_text; + + @override + void Function(BuildContext) get onPressed => (BuildContext context) => + Navigator.of(context).popAndPushNamed(Routes.seed, arguments: true); +} diff --git a/lib/src/screens/seed/warning_page.dart b/lib/src/screens/seed/warning_page.dart deleted file mode 100644 index 18b9b6248..000000000 --- a/lib/src/screens/seed/warning_page.dart +++ /dev/null @@ -1,86 +0,0 @@ -import 'package:cake_wallet/utils/responsive_layout_util.dart'; -import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; -import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/widgets/primary_button.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/themes/theme_base.dart'; -import 'package:flutter/material.dart'; - -class WarningPage extends BasePage { - WarningPage(this.seedPhraseLength) - : isPreSeedPage = seedPhraseLength != null, - imageLight = Image.asset('assets/images/pre_seed_light.png'), - imageDark = Image.asset('assets/images/pre_seed_dark.png'); - - final Image imageDark; - final Image imageLight; - final int? seedPhraseLength; - final bool isPreSeedPage; - - @override - Widget? leading(BuildContext context) => - isPreSeedPage ? null : super.leading(context); - - @override - String? get title => S.current.pre_seed_title; - - @override - Widget body(BuildContext context) { - final image = currentTheme.type == ThemeType.dark ? imageDark : imageLight; - - return WillPopScope( - onWillPop: () async => !isPreSeedPage, - child: Container( - alignment: Alignment.center, - padding: EdgeInsets.all(24), - child: ConstrainedBox( - constraints: BoxConstraints( - maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: ConstrainedBox( - constraints: BoxConstraints( - maxHeight: MediaQuery.of(context).size.height * 0.3), - child: AspectRatio(aspectRatio: 1, child: image), - ), - ), - Expanded( - child: Padding( - padding: EdgeInsets.all(10), - child: Text( - isPreSeedPage - ? S.of(context).pre_seed_description( - seedPhraseLength.toString()) - : S.of(context).setup_warning_2fa_text, - textAlign: TextAlign.center, - style: TextStyle( - height: 1.7, - fontSize: 14, - fontWeight: FontWeight.normal, - color: Theme.of(context) - .extension()! - .secondaryTextColor)), - ), - ), - PrimaryButton( - onPressed: () => isPreSeedPage - ? Navigator.of(context) - .popAndPushNamed(Routes.seed, arguments: true) - : Navigator.of(context) - .popAndPushNamed(Routes.setup_2faPage), - text: isPreSeedPage - ? S.of(context).pre_seed_button_text - : S.of(context).understand, - color: Theme.of(context).primaryColor, - textColor: Colors.white) - ], - ), - ), - )); - } -} diff --git a/lib/src/screens/settings/security_backup_page.dart b/lib/src/screens/settings/security_backup_page.dart index c6fa939de..56ba049ba 100644 --- a/lib/src/screens/settings/security_backup_page.dart +++ b/lib/src/screens/settings/security_backup_page.dart @@ -108,7 +108,7 @@ class SecurityBackupPage extends BasePage { context, route: _securitySettingsViewModel.useTotp2FA ? Routes.modify2FAPage - : Routes.warningPage, + : Routes.setup2faInfoPage, conditionToDetermineIfToUse2FA: _securitySettingsViewModel .shouldRequireTOTP2FAForAllSecurityAndBackupSettings, ), diff --git a/lib/src/screens/setup_2fa/setup_2fa_info_page.dart b/lib/src/screens/setup_2fa/setup_2fa_info_page.dart new file mode 100644 index 000000000..ff6187665 --- /dev/null +++ b/lib/src/screens/setup_2fa/setup_2fa_info_page.dart @@ -0,0 +1,20 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/InfoPage.dart'; +import 'package:flutter/cupertino.dart'; + +class Setup2FAInfoPage extends InfoPage { + + @override + String get pageTitle => S.current.pre_seed_title; + + @override + String get pageDescription => S.current.setup_warning_2fa_text; + + @override + String get buttonText => S.current.understand; + + @override + void Function(BuildContext) get onPressed => (BuildContext context) => + Navigator.of(context).popAndPushNamed(Routes.setup_2faPage); +} From 133fa2987a48fd1f6ac77dd57c202f64a6d75619 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Mon, 1 Jan 2024 15:05:37 +0200 Subject: [PATCH 087/241] Generic fixes (#1245) * Remove error message if buy action is disabled * Fix wallet list selected wallet issue * Check if the widget is still mounted before showing popup * minor code readability enhancement [skip ci] * Code enhancement [skip ci] * Revert removing ask each time localization * Add Moonpay to sell flow Code Enhancements * remove error popup when sell option is disabled --- cw_ethereum/lib/ethereum_wallet_service.dart | 11 +- cw_polygon/lib/polygon_wallet_service.dart | 6 +- lib/buy/buy_provider.dart | 4 +- lib/buy/dfx/dfx_buy_provider.dart | 6 +- ...uy_provider.dart => moonpay_provider.dart} | 122 ++++++++++-------- lib/buy/onramper/onramper_buy_provider.dart | 5 +- lib/buy/robinhood/robinhood_buy_provider.dart | 12 +- lib/buy/wyre/wyre_buy_provider.dart | 55 +++----- lib/di.dart | 2 +- lib/entities/buy_provider_types.dart | 112 ---------------- lib/entities/main_actions.dart | 4 - lib/entities/provider_types.dart | 108 ++++++++++++++++ lib/src/screens/buy/buy_options_page.dart | 38 +++--- lib/src/screens/buy/buy_webview_page.dart | 2 +- .../screens/buy/widgets/buy_list_item.dart | 2 +- .../exchange_trade/exchange_trade_page.dart | 6 +- .../screens/wallet_list/wallet_list_page.dart | 5 +- lib/store/settings_store.dart | 22 ++-- lib/view_model/buy/buy_view_model.dart | 2 +- .../dashboard/dashboard_view_model.dart | 20 +-- lib/view_model/order_details_view_model.dart | 2 +- .../settings/other_settings_view_model.dart | 36 +++--- .../wallet_list/wallet_list_view_model.dart | 1 + 23 files changed, 270 insertions(+), 313 deletions(-) rename lib/buy/moonpay/{moonpay_buy_provider.dart => moonpay_provider.dart} (73%) delete mode 100644 lib/entities/buy_provider_types.dart create mode 100644 lib/entities/provider_types.dart diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index 8810d6014..0acc90bac 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -20,12 +20,7 @@ class EthereumWalletService extends WalletService create(EthereumNewWalletCredentials credentials) async { - - final strength = (credentials.seedPhraseLength == 12) - ? 128 - : (credentials.seedPhraseLength == 24) - ? 256 - : 128; + final strength = credentials.seedPhraseLength == 24 ? 256 : 128; final mnemonic = bip39.generateMnemonic(strength: strength); final wallet = EthereumWallet( @@ -67,8 +62,8 @@ class EthereumWalletService extends WalletService remove(String wallet) async { File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true); - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(wallet, getType()))!; + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; await walletInfoSource.delete(walletInfo.key); } diff --git a/cw_polygon/lib/polygon_wallet_service.dart b/cw_polygon/lib/polygon_wallet_service.dart index dafe3bab0..43c6269f6 100644 --- a/cw_polygon/lib/polygon_wallet_service.dart +++ b/cw_polygon/lib/polygon_wallet_service.dart @@ -20,11 +20,7 @@ class PolygonWalletService extends WalletService create(PolygonNewWalletCredentials credentials) async { - final strength = (credentials.seedPhraseLength == 12) - ? 128 - : (credentials.seedPhraseLength == 24) - ? 256 - : 128; + final strength = credentials.seedPhraseLength == 24 ? 256 : 128; final mnemonic = bip39.generateMnemonic(strength: strength); final wallet = PolygonWallet( diff --git a/lib/buy/buy_provider.dart b/lib/buy/buy_provider.dart index 93f4e8105..4e4c113f4 100644 --- a/lib/buy/buy_provider.dart +++ b/lib/buy/buy_provider.dart @@ -14,9 +14,7 @@ abstract class BuyProvider { String get title; - String get buyOptionDescription; - - String get sellOptionDescription; + String get providerDescription; String get lightIcon; diff --git a/lib/buy/dfx/dfx_buy_provider.dart b/lib/buy/dfx/dfx_buy_provider.dart index 18ac081ea..f74039caa 100644 --- a/lib/buy/dfx/dfx_buy_provider.dart +++ b/lib/buy/dfx/dfx_buy_provider.dart @@ -26,10 +26,7 @@ class DFXBuyProvider extends BuyProvider { String get title => 'DFX Connect'; @override - String get buyOptionDescription => S.current.dfx_option_description; - - @override - String get sellOptionDescription => S.current.dfx_option_description; + String get providerDescription => S.current.dfx_option_description; @override String get lightIcon => 'assets/images/dfx_light.png'; @@ -152,6 +149,7 @@ class DFXBuyProvider extends BuyProvider { } } + @override Future launchProvider(BuildContext context, bool? isBuyAction) async { try { final assetOut = this.assetOut; diff --git a/lib/buy/moonpay/moonpay_buy_provider.dart b/lib/buy/moonpay/moonpay_provider.dart similarity index 73% rename from lib/buy/moonpay/moonpay_buy_provider.dart rename to lib/buy/moonpay/moonpay_provider.dart index 0831e1313..0ccb73e1c 100644 --- a/lib/buy/moonpay/moonpay_buy_provider.dart +++ b/lib/buy/moonpay/moonpay_provider.dart @@ -21,19 +21,33 @@ import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cw_core/crypto_currency.dart'; import 'package:url_launcher/url_launcher.dart'; -class MoonPaySellProvider { - MoonPaySellProvider({required SettingsStore settingsStore, - required WalletBase wallet, this.isTest = false}) - : baseUrl = isTest ? _baseTestUrl : _baseProductUrl, +class MoonPaySellProvider extends BuyProvider { + MoonPaySellProvider({ + required SettingsStore settingsStore, + required WalletBase wallet, + bool isTestEnvironment = false, + }) : baseUrl = isTestEnvironment ? _baseTestUrl : _baseProductUrl, this._settingsStore = settingsStore, - this._wallet = wallet; + super(wallet: wallet, isTestEnvironment: isTestEnvironment); final SettingsStore _settingsStore; - final WalletBase _wallet; static const _baseTestUrl = 'sell-sandbox.moonpay.com'; static const _baseProductUrl = 'sell.moonpay.com'; + @override + String get providerDescription => + 'MoonPay offers a fast and simple way to buy and sell cryptocurrencies'; + + @override + String get title => 'MoonPay'; + + @override + String get lightIcon => 'assets/images/moonpay_light.png'; + + @override + String get darkIcon => 'assets/images/moonpay_dark.png'; + static String themeToMoonPayTheme(ThemeBase theme) { switch (theme.type) { case ThemeType.bright: @@ -45,11 +59,11 @@ class MoonPaySellProvider { } static String get _apiKey => secrets.moonPayApiKey; + static String get _secretKey => secrets.moonPaySecretKey; - final bool isTest; final String baseUrl; - Future requestUrl({ + Future requestMoonPayUrl({ required CryptoCurrency currency, required String refundWalletAddress, required SettingsStore settingsStore, @@ -78,7 +92,7 @@ class MoonPaySellProvider { final digest = hmac.convert(messageBytes); final signature = base64.encode(digest.bytes); - if (isTest) { + if (isTestEnvironment) { return originalUri; } @@ -88,11 +102,12 @@ class MoonPaySellProvider { return signedUri; } - Future launchProvider(BuildContext context) async { + @override + Future launchProvider(BuildContext context, bool? isBuyAction) async { try { - final uri = await requestUrl( - currency: _wallet.currency, - refundWalletAddress: _wallet.walletAddresses.address, + final uri = await requestMoonPayUrl( + currency: wallet.currency, + refundWalletAddress: wallet.walletAddresses.address, settingsStore: _settingsStore, ); @@ -137,35 +152,43 @@ class MoonPayBuyProvider extends BuyProvider { static const _secretKey = secrets.moonPaySecretKey; @override - String get title => 'Moon Pay'; + String get title => 'MoonPay'; @override - String get buyOptionDescription => ''; + String get providerDescription => + 'MoonPay offers a fast and simple way to buy and sell cryptocurrencies'; @override String get lightIcon => 'assets/images/moonpay_light.png'; @override String get darkIcon => 'assets/images/moonpay_dark.png'; - - String get currencyCode => - walletTypeToCryptoCurrency(wallet.type).title.toLowerCase(); + + String get currencyCode => walletTypeToCryptoCurrency(wallet.type).title.toLowerCase(); String get trackUrl => baseUrl + '/transaction_receipt?transactionId='; String baseUrl; Future requestUrl(String amount, String sourceCurrency) async { - final enabledPaymentMethods = - 'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay' + final enabledPaymentMethods = 'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay' '%2Csepa_bank_transfer%2Cgbp_bank_transfer%2Cgbp_open_banking_payment'; - final suffix = '?apiKey=' + _apiKey + '¤cyCode=' + - currencyCode + '&enabledPaymentMethods=' + enabledPaymentMethods + - '&walletAddress=' + wallet.walletAddresses.address + - '&baseCurrencyCode=' + sourceCurrency.toLowerCase() + - '&baseCurrencyAmount=' + amount + '&lockAmount=true' + - '&showAllCurrencies=false' + '&showWalletAddressForm=false'; + final suffix = '?apiKey=' + + _apiKey + + '¤cyCode=' + + currencyCode + + '&enabledPaymentMethods=' + + enabledPaymentMethods + + '&walletAddress=' + + wallet.walletAddresses.address + + '&baseCurrencyCode=' + + sourceCurrency.toLowerCase() + + '&baseCurrencyAmount=' + + amount + + '&lockAmount=true' + + '&showAllCurrencies=false' + + '&showWalletAddressForm=false'; final originalUrl = baseUrl + suffix; @@ -174,24 +197,27 @@ class MoonPayBuyProvider extends BuyProvider { final hmac = Hmac(sha256, key); final digest = hmac.convert(messageBytes); final signature = base64.encode(digest.bytes); - final urlWithSignature = originalUrl + - '&signature=${Uri.encodeComponent(signature)}'; + final urlWithSignature = originalUrl + '&signature=${Uri.encodeComponent(signature)}'; return isTestEnvironment ? originalUrl : urlWithSignature; } Future calculateAmount(String amount, String sourceCurrency) async { - final url = _apiUrl + _currenciesSuffix + '/$currencyCode' + - _quoteSuffix + '/?apiKey=' + _apiKey + - '&baseCurrencyAmount=' + amount + - '&baseCurrencyCode=' + sourceCurrency.toLowerCase(); + final url = _apiUrl + + _currenciesSuffix + + '/$currencyCode' + + _quoteSuffix + + '/?apiKey=' + + _apiKey + + '&baseCurrencyAmount=' + + amount + + '&baseCurrencyCode=' + + sourceCurrency.toLowerCase(); final uri = Uri.parse(url); final response = await get(uri); if (response.statusCode != 200) { - throw BuyException( - title: buyOptionDescription, - content: 'Quote is not found!'); + throw BuyException(title: providerDescription, content: 'Quote is not found!'); } final responseJSON = json.decode(response.body) as Map; @@ -200,21 +226,16 @@ class MoonPayBuyProvider extends BuyProvider { final minSourceAmount = responseJSON['baseCurrency']['minAmount'] as int; return BuyAmount( - sourceAmount: sourceAmount, - destAmount: destAmount, - minAmount: minSourceAmount); + sourceAmount: sourceAmount, destAmount: destAmount, minAmount: minSourceAmount); } Future findOrderById(String id) async { - final url = _apiUrl + _transactionsSuffix + '/$id' + - '?apiKey=' + _apiKey; + final url = _apiUrl + _transactionsSuffix + '/$id' + '?apiKey=' + _apiKey; final uri = Uri.parse(url); final response = await get(uri); if (response.statusCode != 200) { - throw BuyException( - title: buyOptionDescription, - content: 'Transaction $id is not found!'); + throw BuyException(title: providerDescription, content: 'Transaction $id is not found!'); } final responseJSON = json.decode(response.body) as Map; @@ -232,8 +253,7 @@ class MoonPayBuyProvider extends BuyProvider { createdAt: createdAt, amount: amount.toString(), receiveAddress: wallet.walletAddresses.address, - walletId: wallet.id - ); + walletId: wallet.id); } static Future onEnabled() async { @@ -254,12 +274,6 @@ class MoonPayBuyProvider extends BuyProvider { } @override - // TODO: implement sellOptionDescription - String get sellOptionDescription => throw UnimplementedError(); - - @override - Future launchProvider(BuildContext context, bool? isBuyAction) { - // TODO: implement launchProvider - throw UnimplementedError(); - } -} \ No newline at end of file + Future launchProvider(BuildContext context, bool? isBuyAction) => + throw UnimplementedError(); +} diff --git a/lib/buy/onramper/onramper_buy_provider.dart b/lib/buy/onramper/onramper_buy_provider.dart index e38d95df3..014edb813 100644 --- a/lib/buy/onramper/onramper_buy_provider.dart +++ b/lib/buy/onramper/onramper_buy_provider.dart @@ -23,10 +23,7 @@ class OnRamperBuyProvider extends BuyProvider { String get title => 'Onramper'; @override - String get buyOptionDescription => S.current.onramper_option_description; - - @override - String get sellOptionDescription => S.current.onramper_option_description; + String get providerDescription => S.current.onramper_option_description; @override String get lightIcon => 'assets/images/onramper_light.png'; diff --git a/lib/buy/robinhood/robinhood_buy_provider.dart b/lib/buy/robinhood/robinhood_buy_provider.dart index ff6c6a8cf..47c3ab1ea 100644 --- a/lib/buy/robinhood/robinhood_buy_provider.dart +++ b/lib/buy/robinhood/robinhood_buy_provider.dart @@ -1,10 +1,7 @@ import 'dart:convert'; import 'package:cake_wallet/.secrets.g.dart' as secrets; -import 'package:cake_wallet/buy/buy_amount.dart'; import 'package:cake_wallet/buy/buy_provider.dart'; -import 'package:cake_wallet/buy/buy_provider_description.dart'; -import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; @@ -14,22 +11,18 @@ import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:url_launcher/url_launcher.dart'; -class RobinhoodBuyProvider extends BuyProvider{ +class RobinhoodBuyProvider extends BuyProvider { RobinhoodBuyProvider({required WalletBase wallet, bool isTestEnvironment = false}) : super(wallet: wallet, isTestEnvironment: isTestEnvironment); static const _baseUrl = 'applink.robinhood.com'; static const _cIdBaseUrl = 'exchange-helper.cakewallet.com'; - @override String get title => 'Robinhood Connect'; @override - String get buyOptionDescription => S.current.robinhood_option_description; - - @override - String get sellOptionDescription => S.current.robinhood_option_description; + String get providerDescription => S.current.robinhood_option_description; @override String get lightIcon => 'assets/images/robinhood_light.png'; @@ -105,5 +98,4 @@ class RobinhoodBuyProvider extends BuyProvider{ }); } } - } diff --git a/lib/buy/wyre/wyre_buy_provider.dart b/lib/buy/wyre/wyre_buy_provider.dart index 80e48fd4f..4dd091c33 100644 --- a/lib/buy/wyre/wyre_buy_provider.dart +++ b/lib/buy/wyre/wyre_buy_provider.dart @@ -13,10 +13,8 @@ import 'package:cake_wallet/.secrets.g.dart' as secrets; class WyreBuyProvider extends BuyProvider { WyreBuyProvider({required WalletBase wallet, bool isTestEnvironment = false}) - : baseApiUrl = isTestEnvironment - ? _baseTestApiUrl - : _baseProductApiUrl, - super(wallet: wallet, isTestEnvironment: isTestEnvironment); + : baseApiUrl = isTestEnvironment ? _baseTestApiUrl : _baseProductApiUrl, + super(wallet: wallet, isTestEnvironment: isTestEnvironment); static const _baseTestApiUrl = 'https://api.testwyre.com'; static const _baseProductApiUrl = 'https://api.sendwyre.com'; @@ -36,7 +34,7 @@ class WyreBuyProvider extends BuyProvider { String get title => 'Wyre'; @override - String get buyOptionDescription => ''; + String get providerDescription => ''; @override String get lightIcon => 'assets/images/robinhood_light.png'; @@ -44,16 +42,13 @@ class WyreBuyProvider extends BuyProvider { @override String get darkIcon => 'assets/images/robinhood_dark.png'; - String get trackUrl => isTestEnvironment - ? _trackTestUrl - : _trackProductUrl; + String get trackUrl => isTestEnvironment ? _trackTestUrl : _trackProductUrl; String baseApiUrl; Future requestUrl(String amount, String sourceCurrency) async { final timestamp = DateTime.now().millisecondsSinceEpoch.toString(); - final url = baseApiUrl + _ordersSuffix + _reserveSuffix + - _timeStampSuffix + timestamp; + final url = baseApiUrl + _ordersSuffix + _reserveSuffix + _timeStampSuffix + timestamp; final uri = Uri.parse(url); final body = { 'amount': amount, @@ -72,9 +67,7 @@ class WyreBuyProvider extends BuyProvider { body: json.encode(body)); if (response.statusCode != 200) { - throw BuyException( - title: buyOptionDescription, - content: 'Url $url is not found!'); + throw BuyException(title: providerDescription, content: 'Url $url is not found!'); } final responseJSON = json.decode(response.body) as Map; @@ -102,9 +95,7 @@ class WyreBuyProvider extends BuyProvider { body: json.encode(body)); if (response.statusCode != 200) { - throw BuyException( - title: buyOptionDescription, - content: 'Quote is not found!'); + throw BuyException(title: providerDescription, content: 'Quote is not found!'); } final responseJSON = json.decode(response.body) as Map; @@ -112,7 +103,8 @@ class WyreBuyProvider extends BuyProvider { final destAmount = responseJSON['destAmount'] as double; final achAmount = responseJSON['sourceAmountWithoutFees'] as double; - return BuyAmount(sourceAmount: sourceAmount, destAmount: destAmount, achSourceAmount: achAmount); + return BuyAmount( + sourceAmount: sourceAmount, destAmount: destAmount, achSourceAmount: achAmount); } Future findOrderById(String id) async { @@ -121,35 +113,27 @@ class WyreBuyProvider extends BuyProvider { final orderResponse = await get(orderUri); if (orderResponse.statusCode != 200) { - throw BuyException( - title: buyOptionDescription, - content: 'Order $id is not found!'); + throw BuyException(title: providerDescription, content: 'Order $id is not found!'); } - final orderResponseJSON = - json.decode(orderResponse.body) as Map; + final orderResponseJSON = json.decode(orderResponse.body) as Map; final transferId = orderResponseJSON['transferId'] as String; final from = orderResponseJSON['sourceCurrency'] as String; final to = orderResponseJSON['destCurrency'] as String; final status = orderResponseJSON['status'] as String; final state = TradeState.deserialize(raw: status.toLowerCase()); final createdAtRaw = orderResponseJSON['createdAt'] as int; - final createdAt = - DateTime.fromMillisecondsSinceEpoch(createdAtRaw).toLocal(); + final createdAt = DateTime.fromMillisecondsSinceEpoch(createdAtRaw).toLocal(); - final transferUrl = - baseApiUrl + _transferSuffix + transferId + _trackSuffix; + final transferUrl = baseApiUrl + _transferSuffix + transferId + _trackSuffix; final transferUri = Uri.parse(transferUrl); final transferResponse = await get(transferUri); if (transferResponse.statusCode != 200) { - throw BuyException( - title: buyOptionDescription, - content: 'Transfer $transferId is not found!'); + throw BuyException(title: providerDescription, content: 'Transfer $transferId is not found!'); } - final transferResponseJSON = - json.decode(transferResponse.body) as Map; + final transferResponseJSON = json.decode(transferResponse.body) as Map; final amount = transferResponseJSON['destAmount'] as double; return Order( @@ -162,8 +146,7 @@ class WyreBuyProvider extends BuyProvider { createdAt: createdAt, amount: amount.toString(), receiveAddress: wallet.walletAddresses.address, - walletId: wallet.id - ); + walletId: wallet.id); } @override @@ -171,8 +154,4 @@ class WyreBuyProvider extends BuyProvider { // TODO: implement launchProvider throw UnimplementedError(); } - - @override - // TODO: implement sellOptionDescription - String get sellOptionDescription => throw UnimplementedError(); -} \ No newline at end of file +} diff --git a/lib/di.dart b/lib/di.dart index dd1001858..61a04bf1c 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -1,7 +1,7 @@ import 'package:cake_wallet/anonpay/anonpay_api.dart'; import 'package:cake_wallet/anonpay/anonpay_info_base.dart'; import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart'; -import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart'; +import 'package:cake_wallet/buy/moonpay/moonpay_provider.dart'; import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/buy/payfura/payfura_buy_provider.dart'; diff --git a/lib/entities/buy_provider_types.dart b/lib/entities/buy_provider_types.dart deleted file mode 100644 index 1913d1b25..000000000 --- a/lib/entities/buy_provider_types.dart +++ /dev/null @@ -1,112 +0,0 @@ -import 'package:cake_wallet/buy/buy_provider.dart'; -import 'package:cake_wallet/buy/dfx/dfx_buy_provider.dart'; -import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; -import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart'; -import 'package:cake_wallet/di.dart'; -import 'package:cw_core/wallet_type.dart'; - -enum BuyProviderType { - askEachTime, - robinhood, - dfx, - onramper, -} - -extension BuyProviderTypeName on BuyProviderType { - String get name { - switch (this) { - case BuyProviderType.askEachTime: - return 'Ask each time'; - case BuyProviderType.robinhood: - return 'Robinhood Connect'; - case BuyProviderType.dfx: - return 'DFX Connect'; - case BuyProviderType.onramper: - return 'Onramper'; - default: - return this.toString().split('.').last; - } - } - - String get id { - switch (this) { - case BuyProviderType.askEachTime: - return 'ask_each_time_provider'; - case BuyProviderType.robinhood: - return 'robinhood_connect_provider'; - case BuyProviderType.dfx: - return 'dfx_connect_provider'; - case BuyProviderType.onramper: - return 'onramper_provider'; - default: - return this.toString().split('.').last.replaceAll('.', '_') - .toLowerCase() + '_provider'; - } - } -} - -class BuyProviderHelper { - static List getAvailableBuyProviderTypes( - WalletType walletType) { - switch (walletType) { - case WalletType.nano: - case WalletType.banano: - return [BuyProviderType.askEachTime, BuyProviderType.onramper]; - case WalletType.monero: - return [ - BuyProviderType.askEachTime, - BuyProviderType.onramper, - BuyProviderType.dfx - ]; - case WalletType.bitcoin: - case WalletType.ethereum: - return [ - BuyProviderType.askEachTime, - BuyProviderType.onramper, - BuyProviderType.dfx, - BuyProviderType.robinhood - ]; - case WalletType.litecoin: - case WalletType.bitcoinCash: - return [ - BuyProviderType.askEachTime, - BuyProviderType.onramper, - BuyProviderType.robinhood - ]; - default: - return []; - } - } - - static List getAvailableSellProviderTypes( - WalletType walletType) { - switch (walletType) { - case WalletType.nano: - case WalletType.banano: - return [BuyProviderType.askEachTime]; - case WalletType.monero: - return [BuyProviderType.askEachTime, BuyProviderType.dfx]; - case WalletType.bitcoin: - case WalletType.ethereum: - return [BuyProviderType.askEachTime, BuyProviderType.dfx]; - case WalletType.litecoin: - case WalletType.bitcoinCash: - return [BuyProviderType.askEachTime]; - default: - return []; - } - } - - static BuyProvider? getProviderByType(BuyProviderType type) { - switch (type) { - case BuyProviderType.robinhood: - return getIt.get(); - case BuyProviderType.dfx: - return getIt.get(); - case BuyProviderType.onramper: - return getIt.get(); - case BuyProviderType.askEachTime: - return null; - } - } -} diff --git a/lib/entities/main_actions.dart b/lib/entities/main_actions.dart index 0e4e05ae0..c1dd71cc9 100644 --- a/lib/entities/main_actions.dart +++ b/lib/entities/main_actions.dart @@ -37,8 +37,6 @@ class MainActions { canShow: (viewModel) => viewModel.hasBuyAction, onTap: (BuildContext context, DashboardViewModel viewModel) async { if (!viewModel.isEnabledBuyAction) { - await _showErrorDialog( - context, S.of(context).buy, S.of(context).unsupported_asset); return; } @@ -88,8 +86,6 @@ class MainActions { canShow: (viewModel) => viewModel.hasSellAction, onTap: (BuildContext context, DashboardViewModel viewModel) async { if (!viewModel.isEnabledSellAction) { - await _showErrorDialog( - context, S.of(context).sell, S.of(context).unsupported_asset); return; } diff --git a/lib/entities/provider_types.dart b/lib/entities/provider_types.dart new file mode 100644 index 000000000..4cb9a934f --- /dev/null +++ b/lib/entities/provider_types.dart @@ -0,0 +1,108 @@ +import 'package:cake_wallet/buy/buy_provider.dart'; +import 'package:cake_wallet/buy/dfx/dfx_buy_provider.dart'; +import 'package:cake_wallet/buy/moonpay/moonpay_provider.dart'; +import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; +import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart'; +import 'package:cake_wallet/di.dart'; +import 'package:cw_core/wallet_type.dart'; + +enum ProviderType { + askEachTime, + robinhood, + dfx, + onramper, + moonpaySell, +} + +extension ProviderTypeName on ProviderType { + String get title { + switch (this) { + case ProviderType.askEachTime: + return 'Ask each time'; + case ProviderType.robinhood: + return 'Robinhood Connect'; + case ProviderType.dfx: + return 'DFX Connect'; + case ProviderType.onramper: + return 'Onramper'; + case ProviderType.moonpaySell: + return 'MoonPay'; + } + } + + String get id { + switch (this) { + case ProviderType.askEachTime: + return 'ask_each_time_provider'; + case ProviderType.robinhood: + return 'robinhood_connect_provider'; + case ProviderType.dfx: + return 'dfx_connect_provider'; + case ProviderType.onramper: + return 'onramper_provider'; + case ProviderType.moonpaySell: + return 'moonpay_provider'; + } + } +} + +class ProvidersHelper { + static List getAvailableBuyProviderTypes(WalletType walletType) { + switch (walletType) { + case WalletType.nano: + case WalletType.banano: + return [ProviderType.askEachTime, ProviderType.onramper]; + case WalletType.monero: + return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.dfx]; + case WalletType.bitcoin: + case WalletType.ethereum: + return [ + ProviderType.askEachTime, + ProviderType.onramper, + ProviderType.dfx, + ProviderType.robinhood, + ]; + case WalletType.litecoin: + case WalletType.bitcoinCash: + return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood]; + case WalletType.none: + case WalletType.haven: + case WalletType.polygon: + return []; + } + } + + static List getAvailableSellProviderTypes(WalletType walletType) { + switch (walletType) { + case WalletType.monero: + return [ProviderType.askEachTime, ProviderType.dfx]; + case WalletType.bitcoin: + case WalletType.ethereum: + return [ProviderType.askEachTime, ProviderType.moonpaySell, ProviderType.dfx]; + case WalletType.litecoin: + case WalletType.bitcoinCash: + return [ProviderType.askEachTime, ProviderType.moonpaySell]; + case WalletType.nano: + case WalletType.banano: + case WalletType.none: + case WalletType.haven: + case WalletType.polygon: + return []; + } + } + + static BuyProvider? getProviderByType(ProviderType type) { + switch (type) { + case ProviderType.robinhood: + return getIt.get(); + case ProviderType.dfx: + return getIt.get(); + case ProviderType.onramper: + return getIt.get(); + case ProviderType.askEachTime: + return null; + case ProviderType.moonpaySell: + return getIt.get(); + } + } +} diff --git a/lib/src/screens/buy/buy_options_page.dart b/lib/src/screens/buy/buy_options_page.dart index 6ce8fe9f2..50f041d2e 100644 --- a/lib/src/screens/buy/buy_options_page.dart +++ b/lib/src/screens/buy/buy_options_page.dart @@ -1,5 +1,3 @@ -import 'package:cake_wallet/buy/buy_provider.dart'; -import 'package:cake_wallet/entities/buy_provider_types.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/option_tile.dart'; @@ -22,8 +20,7 @@ class BuySellOptionsPage extends BasePage { @override Widget body(BuildContext context) { - final isLightMode = - Theme.of(context).extension()?.useDarkImage ?? false; + final isLightMode = Theme.of(context).extension()?.useDarkImage ?? false; final availableProviders = isBuyAction ? dashboardViewModel.availableBuyProviders : dashboardViewModel.availableSellProviders; @@ -46,31 +43,26 @@ class BuySellOptionsPage extends BasePage { child: OptionTile( image: icon, title: provider.toString(), - description: isBuyAction - ? provider.buyOptionDescription - : provider.sellOptionDescription, - onPressed: () => - provider.launchProvider(context, isBuyAction), + description: provider.providerDescription, + onPressed: () => provider.launchProvider(context, isBuyAction), ), ); }).toList(), Spacer(), - Padding( - padding: EdgeInsets.fromLTRB(24, 24, 24, 32), - child: Text( - isBuyAction - ? S.of(context).select_buy_provider_notice - : S.of(context).select_sell_provider_notice, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.normal, - color: Theme.of(context) - .extension()! - .detailsTitlesColor, - ), + Padding( + padding: EdgeInsets.fromLTRB(24, 24, 24, 32), + child: Text( + isBuyAction + ? S.of(context).select_buy_provider_notice + : S.of(context).select_sell_provider_notice, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + color: Theme.of(context).extension()!.detailsTitlesColor, ), ), + ), ], ), ), diff --git a/lib/src/screens/buy/buy_webview_page.dart b/lib/src/screens/buy/buy_webview_page.dart index a6ea2ab7b..6f7a39322 100644 --- a/lib/src/screens/buy/buy_webview_page.dart +++ b/lib/src/screens/buy/buy_webview_page.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'dart:io'; import 'package:cake_wallet/buy/buy_provider.dart'; -import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart'; +import 'package:cake_wallet/buy/moonpay/moonpay_provider.dart'; import 'package:cake_wallet/buy/wyre/wyre_buy_provider.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/palette.dart'; diff --git a/lib/src/screens/buy/widgets/buy_list_item.dart b/lib/src/screens/buy/widgets/buy_list_item.dart index d8adddfdc..d8c457ac0 100644 --- a/lib/src/screens/buy/widgets/buy_list_item.dart +++ b/lib/src/screens/buy/widgets/buy_list_item.dart @@ -29,7 +29,7 @@ class BuyListItem extends StatelessWidget { @override Widget build(BuildContext context) { - final isSelected = selectedProvider?.buyOptionDescription == provider.buyOptionDescription; + final isSelected = selectedProvider?.providerDescription == provider.providerDescription; final iconColor = isSelected ? Colors.white : Colors.black; final providerIcon = Image.asset('assets/images/wyre-icon.png', width: 36, height: 36); diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index 23595efdf..e72b0f0a8 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -299,7 +299,8 @@ class ExchangeTradeState extends State { } void transactionStatePopup() { - showPopUp( + if (this.mounted) { + showPopUp( context: context, builder: (BuildContext popupContext) { return Observer(builder: (_) { @@ -344,7 +345,7 @@ class ExchangeTradeState extends State { onPressed: () { Navigator.of(popupContext).pop(); RequestReviewHandler.requestReview(); - }, + }, text: S.of(popupContext).got_it, color: Theme.of(popupContext).primaryColor, textColor: Colors.white)) @@ -391,5 +392,6 @@ class ExchangeTradeState extends State { ); }); }); + } } } diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index 8dcd23d29..717bb0a94 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -1,6 +1,5 @@ import 'package:cake_wallet/entities/wallet_list_order_types.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/filter_list_widget.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/filter_widget.dart'; import 'package:cake_wallet/src/screens/wallet_list/filtered_list.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/core/auth_service.dart'; @@ -335,7 +334,9 @@ class WalletListBodyState extends State { // in desktop platforms the navigation tree is different if (responsiveLayoutUtil.shouldRenderMobileUI) { WidgetsBinding.instance.addPostFrameCallback((_) { - Navigator.of(context).pop(); + if (this.mounted) { + Navigator.of(context).pop(); + } }); } } catch (e) { diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 20f310c83..7bccc4fc5 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -4,7 +4,7 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/buy/buy_provider.dart'; import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; -import 'package:cake_wallet/entities/buy_provider_types.dart'; +import 'package:cake_wallet/entities/provider_types.dart'; import 'package:cake_wallet/entities/cake_2fa_preset_options.dart'; import 'package:cake_wallet/entities/background_tasks.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; @@ -149,8 +149,8 @@ abstract class SettingsStoreBase with Store { currentSyncMode = initialSyncMode, currentSyncAll = initialSyncAll, priority = ObservableMap(), - defaultBuyProviders = ObservableMap(), - defaultSellProviders = ObservableMap() { + defaultBuyProviders = ObservableMap(), + defaultSellProviders = ObservableMap() { //this.nodes = ObservableMap.of(nodes); if (initialMoneroTransactionPriority != null) { @@ -187,10 +187,10 @@ abstract class SettingsStoreBase with Store { final key = 'buyProvider_${walletType.toString()}'; final providerId = sharedPreferences.getString(key); if (providerId != null) { - defaultBuyProviders[walletType] = BuyProviderType.values - .firstWhere((provider) => provider.id == providerId, orElse: () => BuyProviderType.askEachTime); + defaultBuyProviders[walletType] = ProviderType.values + .firstWhere((provider) => provider.id == providerId, orElse: () => ProviderType.askEachTime); } else { - defaultBuyProviders[walletType] = BuyProviderType.askEachTime; + defaultBuyProviders[walletType] = ProviderType.askEachTime; } }); @@ -198,10 +198,10 @@ abstract class SettingsStoreBase with Store { final key = 'sellProvider_${walletType.toString()}'; final providerId = sharedPreferences.getString(key); if (providerId != null) { - defaultSellProviders[walletType] = BuyProviderType.values - .firstWhere((provider) => provider.id == providerId, orElse: () => BuyProviderType.askEachTime); + defaultSellProviders[walletType] = ProviderType.values + .firstWhere((provider) => provider.id == providerId, orElse: () => ProviderType.askEachTime); } else { - defaultSellProviders[walletType] = BuyProviderType.askEachTime; + defaultSellProviders[walletType] = ProviderType.askEachTime; } }); @@ -617,10 +617,10 @@ abstract class SettingsStoreBase with Store { ObservableMap trocadorProviderStates = ObservableMap(); @observable - ObservableMap defaultBuyProviders; + ObservableMap defaultBuyProviders; @observable - ObservableMap defaultSellProviders; + ObservableMap defaultSellProviders; @observable SortBalanceBy sortBalanceBy; diff --git a/lib/view_model/buy/buy_view_model.dart b/lib/view_model/buy/buy_view_model.dart index c0e22dae2..d73396e1b 100644 --- a/lib/view_model/buy/buy_view_model.dart +++ b/lib/view_model/buy/buy_view_model.dart @@ -1,5 +1,5 @@ import 'package:cake_wallet/buy/buy_provider.dart'; -import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart'; +import 'package:cake_wallet/buy/moonpay/moonpay_provider.dart'; import 'package:cake_wallet/buy/wyre/wyre_buy_provider.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index f4c66b432..a794c2262 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -4,7 +4,7 @@ import 'package:cake_wallet/buy/buy_provider.dart'; import 'package:cake_wallet/core/key_service.dart'; import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/balance_display_mode.dart'; -import 'package:cake_wallet/entities/buy_provider_types.dart'; +import 'package:cake_wallet/entities/provider_types.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -42,7 +42,7 @@ import 'package:cw_core/wallet_type.dart'; import 'package:eth_sig_util/util/utils.dart'; import 'package:flutter/services.dart'; import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/entities/buy_provider_types.dart'; +import 'package:cake_wallet/entities/provider_types.dart'; part 'dashboard_view_model.g.dart'; @@ -297,27 +297,27 @@ abstract class DashboardViewModelBase with Store { Map> filterItems; - BuyProvider? get defaultBuyProvider => BuyProviderHelper.getProviderByType( - settingsStore.defaultBuyProviders[wallet.type] ?? BuyProviderType.askEachTime); + BuyProvider? get defaultBuyProvider => ProvidersHelper.getProviderByType( + settingsStore.defaultBuyProviders[wallet.type] ?? ProviderType.askEachTime); - BuyProvider? get defaultSellProvider => BuyProviderHelper.getProviderByType( - settingsStore.defaultSellProviders[wallet.type] ?? BuyProviderType.askEachTime); + BuyProvider? get defaultSellProvider => ProvidersHelper.getProviderByType( + settingsStore.defaultSellProviders[wallet.type] ?? ProviderType.askEachTime); bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled; List get availableBuyProviders { - final providerTypes = BuyProviderHelper.getAvailableBuyProviderTypes(wallet.type); + final providerTypes = ProvidersHelper.getAvailableBuyProviderTypes(wallet.type); return providerTypes - .map((type) => BuyProviderHelper.getProviderByType(type)) + .map((type) => ProvidersHelper.getProviderByType(type)) .where((provider) => provider != null) .cast() .toList(); } List get availableSellProviders { - final providerTypes = BuyProviderHelper.getAvailableSellProviderTypes(wallet.type); + final providerTypes = ProvidersHelper.getAvailableSellProviderTypes(wallet.type); return providerTypes - .map((type) => BuyProviderHelper.getProviderByType(type)) + .map((type) => ProvidersHelper.getProviderByType(type)) .where((provider) => provider != null) .cast() .toList(); diff --git a/lib/view_model/order_details_view_model.dart b/lib/view_model/order_details_view_model.dart index 4ac848ecf..9b00bbb46 100644 --- a/lib/view_model/order_details_view_model.dart +++ b/lib/view_model/order_details_view_model.dart @@ -9,7 +9,7 @@ import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.d import 'package:cake_wallet/src/screens/trade_details/track_trade_list_item.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:cw_core/wallet_base.dart'; -import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart'; +import 'package:cake_wallet/buy/moonpay/moonpay_provider.dart'; import 'package:cake_wallet/buy/wyre/wyre_buy_provider.dart'; part 'order_details_view_model.g.dart'; diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart index 60ed550ef..e44eb8fc7 100644 --- a/lib/view_model/settings/other_settings_view_model.dart +++ b/lib/view_model/settings/other_settings_view_model.dart @@ -1,5 +1,5 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart'; -import 'package:cake_wallet/entities/buy_provider_types.dart'; +import 'package:cake_wallet/entities/provider_types.dart'; import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/store/settings_store.dart'; @@ -64,20 +64,20 @@ abstract class OtherSettingsViewModelBase with Store { bool get isEnabledSellAction => !_settingsStore.disableSell && _wallet.type != WalletType.haven; - List get availableBuyProvidersTypes { - return BuyProviderHelper.getAvailableBuyProviderTypes(walletType); + List get availableBuyProvidersTypes { + return ProvidersHelper.getAvailableBuyProviderTypes(walletType); } - List get availableSellProvidersTypes => - BuyProviderHelper.getAvailableSellProviderTypes(walletType); + List get availableSellProvidersTypes => + ProvidersHelper.getAvailableSellProviderTypes(walletType); - BuyProviderType get buyProviderType => + ProviderType get buyProviderType => _settingsStore.defaultBuyProviders[walletType] ?? - BuyProviderType.askEachTime; + ProviderType.askEachTime; - BuyProviderType get sellProviderType => + ProviderType get sellProviderType => _settingsStore.defaultSellProviders[walletType] ?? - BuyProviderType.askEachTime; + ProviderType.askEachTime; String getDisplayPriority(dynamic priority) { final _priority = priority as TransactionPriority; @@ -93,28 +93,28 @@ abstract class OtherSettingsViewModelBase with Store { } String getBuyProviderType(dynamic buyProviderType) { - final _buyProviderType = buyProviderType as BuyProviderType; - return _buyProviderType == BuyProviderType.askEachTime + final _buyProviderType = buyProviderType as ProviderType; + return _buyProviderType == ProviderType.askEachTime ? S.current.ask_each_time - : _buyProviderType.name; + : _buyProviderType.title; } String getSellProviderType(dynamic sellProviderType) { - final _sellProviderType = sellProviderType as BuyProviderType; - return _sellProviderType == BuyProviderType.askEachTime + final _sellProviderType = sellProviderType as ProviderType; + return _sellProviderType == ProviderType.askEachTime ? S.current.ask_each_time - : _sellProviderType.name; + : _sellProviderType.title; } void onDisplayPrioritySelected(TransactionPriority priority) => _settingsStore.priority[_wallet.type] = priority; @action - BuyProviderType onBuyProviderTypeSelected(BuyProviderType buyProviderType) => + ProviderType onBuyProviderTypeSelected(ProviderType buyProviderType) => _settingsStore.defaultBuyProviders[walletType] = buyProviderType; @action - BuyProviderType onSellProviderTypeSelected( - BuyProviderType sellProviderType) => + ProviderType onSellProviderTypeSelected( + ProviderType sellProviderType) => _settingsStore.defaultSellProviders[walletType] = sellProviderType; } 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 78211bb3e..407b6d3bc 100644 --- a/lib/view_model/wallet_list/wallet_list_view_model.dart +++ b/lib/view_model/wallet_list/wallet_list_view_model.dart @@ -22,6 +22,7 @@ abstract class WalletListViewModelBase with Store { ) : wallets = ObservableList() { setOrderType(_appStore.settingsStore.walletListOrder); reaction((_) => _appStore.wallet, (_) => updateList()); + updateList(); } @observable From 26cde6a1931e147f0bdbbec719a6977b6d821264 Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 8 Jan 2024 16:02:12 +0200 Subject: [PATCH 088/241] Cw 533 add the sell option from on ramper (#1251) * add sell option from onramper * minor fix * fix default sell param --- lib/buy/dfx/dfx_buy_provider.dart | 2 +- lib/buy/onramper/onramper_buy_provider.dart | 11 ++++++----- lib/entities/provider_types.dart | 3 ++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/buy/dfx/dfx_buy_provider.dart b/lib/buy/dfx/dfx_buy_provider.dart index f74039caa..384b7d504 100644 --- a/lib/buy/dfx/dfx_buy_provider.dart +++ b/lib/buy/dfx/dfx_buy_provider.dart @@ -179,7 +179,7 @@ class DFXBuyProvider extends BuyProvider { if (await canLaunchUrl(uri)) { if (DeviceInfo.instance.isMobile) { Navigator.of(context) - .pushNamed(Routes.webViewPage, arguments: ["DFX Connect", uri]); + .pushNamed(Routes.webViewPage, arguments: [title, uri]); } else { await launchUrl(uri, mode: LaunchMode.externalApplication); } diff --git a/lib/buy/onramper/onramper_buy_provider.dart b/lib/buy/onramper/onramper_buy_provider.dart index 014edb813..3819f074d 100644 --- a/lib/buy/onramper/onramper_buy_provider.dart +++ b/lib/buy/onramper/onramper_buy_provider.dart @@ -52,7 +52,7 @@ class OnRamperBuyProvider extends BuyProvider { return color.value.toRadixString(16).replaceAll(RegExp(r'^ff'), ""); } - Uri requestOnramperUrl(BuildContext context) { + Uri requestOnramperUrl(BuildContext context, bool? isBuyAction) { String primaryColor, secondaryColor, primaryTextColor, @@ -79,23 +79,24 @@ class OnRamperBuyProvider extends BuyProvider { return Uri.https(_baseUrl, '', { 'apiKey': _apiKey, 'defaultCrypto': _normalizeCryptoCurrency, + 'sell_defaultCrypto': _normalizeCryptoCurrency, 'networkWallets': '${networkName}:${wallet.walletAddresses.address}', - 'supportSell': "false", 'supportSwap': "false", 'primaryColor': primaryColor, 'secondaryColor': secondaryColor, 'primaryTextColor': primaryTextColor, 'secondaryTextColor': secondaryTextColor, 'containerColor': containerColor, - 'cardColor': cardColor + 'cardColor': cardColor, + 'mode': isBuyAction == true ? 'buy' : 'sell', }); } Future launchProvider(BuildContext context, bool? isBuyAction) async { - final uri = requestOnramperUrl(context); + final uri = requestOnramperUrl(context, isBuyAction); if (DeviceInfo.instance.isMobile) { Navigator.of(context) - .pushNamed(Routes.webViewPage, arguments: [S.of(context).buy, uri]); + .pushNamed(Routes.webViewPage, arguments: [title, uri]); } else { await launchUrl(uri); } diff --git a/lib/entities/provider_types.dart b/lib/entities/provider_types.dart index 4cb9a934f..ced79eae7 100644 --- a/lib/entities/provider_types.dart +++ b/lib/entities/provider_types.dart @@ -78,7 +78,8 @@ class ProvidersHelper { return [ProviderType.askEachTime, ProviderType.dfx]; case WalletType.bitcoin: case WalletType.ethereum: - return [ProviderType.askEachTime, ProviderType.moonpaySell, ProviderType.dfx]; + return [ProviderType.askEachTime, ProviderType.onramper, + ProviderType.moonpaySell, ProviderType.dfx]; case WalletType.litecoin: case WalletType.bitcoinCash: return [ProviderType.askEachTime, ProviderType.moonpaySell]; From 2a1bdf69ef743d72bd57d6dff765b1b0dd5c6a2c Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Mon, 8 Jan 2024 16:03:46 +0200 Subject: [PATCH 089/241] Cw 553 update inappwebview (#1252) * Update inapp webview and update it's deprecated code * Add Turkish Lira Fix android in-app webview * Change FAQ url [skip ci] * Fix available balance display issue --- android/app/build.gradle | 2 +- android/app/src/main/AndroidManifestBase.xml | 4 ++-- cw_bitcoin/lib/electrum_balance.dart | 16 +++++----------- lib/entities/fiat_currency.dart | 6 ++++-- lib/src/screens/buy/buy_webview_page.dart | 9 +++------ lib/src/screens/buy/webview_page.dart | 18 ++++++++---------- .../dashboard/pages/transactions_page.dart | 2 +- .../support_chat/widgets/chatwoot_widget.dart | 14 +++++++------- macos/Flutter/GeneratedPluginRegistrant.swift | 2 ++ pubspec_base.yaml | 2 +- 10 files changed, 34 insertions(+), 41 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index e6b9eb2f8..5e27aeb9e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -37,7 +37,7 @@ if (appPropertiesFile.exists()) { } android { - compileSdkVersion 33 + compileSdkVersion 34 lintOptions { disable 'InvalidPackage' diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index f32482e22..2dceca577 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -71,8 +71,8 @@ android:name="flutterEmbedding" android:value="2" /> - bitcoinAmountToString(amount: confirmed - unconfirmed.abs() - frozen); + String get formattedAvailableBalance => bitcoinAmountToString(amount: confirmed - frozen); @override - String get formattedAdditionalBalance => - bitcoinAmountToString(amount: unconfirmed); + String get formattedAdditionalBalance => bitcoinAmountToString(amount: unconfirmed); @override String get formattedUnAvailableBalance { @@ -41,6 +35,6 @@ class ElectrumBalance extends Balance { return frozenFormatted == '0.0' ? '' : frozenFormatted; } - String toJSON() => json.encode( - {'confirmed': confirmed, 'unconfirmed': unconfirmed, 'frozen': frozen}); + String toJSON() => + json.encode({'confirmed': confirmed, 'unconfirmed': unconfirmed, 'frozen': frozen}); } diff --git a/lib/entities/fiat_currency.dart b/lib/entities/fiat_currency.dart index 8310eb18f..a8e2829d8 100644 --- a/lib/entities/fiat_currency.dart +++ b/lib/entities/fiat_currency.dart @@ -10,7 +10,7 @@ class FiatCurrency extends EnumerableItem with Serializable impl static List get all => _all.values.toList(); static List get currenciesAvailableToBuyWith => - [aud, bgn, brl, cad, chf, clp, cop, czk, dkk, egp, eur, gbp, gtq, hkd, hrk, huf, idr, ils, inr, isk, jpy, krw, mad, mxn, myr, ngn, nok, nzd, php, pkr, pln, ron, sek, sgd, thb, twd, usd, vnd, zar]; + [aud, bgn, brl, cad, chf, clp, cop, czk, dkk, egp, eur, gbp, gtq, hkd, hrk, huf, idr, ils, inr, isk, jpy, krw, mad, mxn, myr, ngn, nok, nzd, php, pkr, pln, ron, sek, sgd, thb, twd, usd, vnd, zar, tur]; static const ars = FiatCurrency(symbol: 'ARS', countryCode: "arg", fullName: "Argentine Peso"); static const aud = FiatCurrency(symbol: 'AUD', countryCode: "aus", fullName: "Australian Dollar"); @@ -60,6 +60,7 @@ class FiatCurrency extends EnumerableItem with Serializable impl static const vef = FiatCurrency(symbol: 'VEF', countryCode: "ven", fullName: "Venezuelan Bolivar Bolívar"); static const vnd = FiatCurrency(symbol: 'VND', countryCode: "vnm", fullName: "Vietnamese Dong đồng"); static const zar = FiatCurrency(symbol: 'ZAR', countryCode: "saf", fullName: "South African Rand"); + static const tur = FiatCurrency(symbol: 'TRY', countryCode: "tur", fullName: "Turkish Lira"); static final _all = { FiatCurrency.ars.raw: FiatCurrency.ars, @@ -109,7 +110,8 @@ class FiatCurrency extends EnumerableItem with Serializable impl FiatCurrency.usd.raw: FiatCurrency.usd, FiatCurrency.vef.raw: FiatCurrency.vef, FiatCurrency.vnd.raw: FiatCurrency.vnd, - FiatCurrency.zar.raw: FiatCurrency.zar + FiatCurrency.zar.raw: FiatCurrency.zar, + FiatCurrency.tur.raw: FiatCurrency.tur, }; static FiatCurrency deserialize({required String raw}) => _all[raw]!; diff --git a/lib/src/screens/buy/buy_webview_page.dart b/lib/src/screens/buy/buy_webview_page.dart index 6f7a39322..829bff3d9 100644 --- a/lib/src/screens/buy/buy_webview_page.dart +++ b/lib/src/screens/buy/buy_webview_page.dart @@ -1,10 +1,7 @@ import 'dart:async'; -import 'dart:io'; -import 'package:cake_wallet/buy/buy_provider.dart'; import 'package:cake_wallet/buy/moonpay/moonpay_provider.dart'; import 'package:cake_wallet/buy/wyre/wyre_buy_provider.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/store/dashboard/orders_store.dart'; import 'package:cake_wallet/view_model/buy/buy_view_model.dart'; @@ -72,10 +69,10 @@ class BuyWebViewPageBodyState extends State { Widget build(BuildContext context) { return InAppWebView( key: _webViewkey, - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions(transparentBackground: true), + initialSettings: InAppWebViewSettings( + transparentBackground: true, ), - initialUrlRequest: URLRequest(url: Uri.tryParse(widget.url ?? '')), + initialUrlRequest: URLRequest(url: WebUri(widget.url ?? '')), onWebViewCreated: (InAppWebViewController controller) => setState(() => _webViewController = controller)); } diff --git a/lib/src/screens/buy/webview_page.dart b/lib/src/screens/buy/webview_page.dart index 205b87c47..97387c29a 100644 --- a/lib/src/screens/buy/webview_page.dart +++ b/lib/src/screens/buy/webview_page.dart @@ -1,5 +1,3 @@ -import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; -import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; @@ -35,21 +33,21 @@ class WebViewPageBodyState extends State { @override Widget build(BuildContext context) { return InAppWebView( - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions(transparentBackground: true), + initialSettings: InAppWebViewSettings( + transparentBackground: true, ), - initialUrlRequest: URLRequest(url: widget.uri), - androidOnPermissionRequest: (_, __, resources) async { + initialUrlRequest: URLRequest(url: WebUri.uri(widget.uri)), + onPermissionRequest: (controller, request) async { bool permissionGranted = await Permission.camera.status == PermissionStatus.granted; if (!permissionGranted) { permissionGranted = await Permission.camera.request().isGranted; } - return PermissionRequestResponse( - resources: resources, + return PermissionResponse( + resources: request.resources, action: permissionGranted - ? PermissionRequestResponseAction.GRANT - : PermissionRequestResponseAction.DENY, + ? PermissionResponseAction.GRANT + : PermissionResponseAction.DENY, ); }, ); diff --git a/lib/src/screens/dashboard/pages/transactions_page.dart b/lib/src/screens/dashboard/pages/transactions_page.dart index 1be8a2a65..c983b1c37 100644 --- a/lib/src/screens/dashboard/pages/transactions_page.dart +++ b/lib/src/screens/dashboard/pages/transactions_page.dart @@ -49,7 +49,7 @@ class TransactionsPage extends StatelessWidget { onTap: () => Navigator.of(context).pushNamed(Routes.webViewPage, arguments: [ '', Uri.parse( - 'https://guides.cakewallet.com/docs/bugs-service-status/why_are_my_funds_not_appearing/') + 'https://guides.cakewallet.com/docs/FAQ/why_are_my_funds_not_appearing/') ]), title: S.of(context).syncing_wallet_alert_title, subTitle: S.of(context).syncing_wallet_alert_content, diff --git a/lib/src/screens/support_chat/widgets/chatwoot_widget.dart b/lib/src/screens/support_chat/widgets/chatwoot_widget.dart index 73403d667..2557761a7 100644 --- a/lib/src/screens/support_chat/widgets/chatwoot_widget.dart +++ b/lib/src/screens/support_chat/widgets/chatwoot_widget.dart @@ -22,17 +22,17 @@ class ChatwootWidgetState extends State { @override Widget build(BuildContext context) => InAppWebView( key: _webViewkey, - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions(transparentBackground: true), - ), - initialUrlRequest: URLRequest(url: Uri.tryParse(widget.supportUrl)), + initialSettings: InAppWebViewSettings( + transparentBackground: true, + ), + initialUrlRequest: URLRequest(url: WebUri(widget.supportUrl)), onWebViewCreated: (InAppWebViewController controller) { controller.addWebMessageListener( WebMessageListener( jsObjectName: 'ReactNativeWebView', - onPostMessage: (String? message, Uri? sourceOrigin, bool isMainFrame, - JavaScriptReplyProxy replyProxy) { - final shortenedMessage = message?.substring(16); + onPostMessage: (WebMessage? message, WebUri? sourceOrigin, bool isMainFrame, + PlatformJavaScriptReplyProxy replyProxy) { + final shortenedMessage = message?.data.toString().substring(16); if (shortenedMessage != null && isJsonString(shortenedMessage)) { final parsedMessage = jsonDecode(shortenedMessage); final eventType = parsedMessage["event"]; diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 68d03b5f8..05996a674 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -9,6 +9,7 @@ import connectivity_plus_macos import cw_monero import device_info_plus import devicelocale +import flutter_inappwebview_macos import flutter_secure_storage_macos import in_app_review import package_info @@ -24,6 +25,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { CwMoneroPlugin.register(with: registry.registrar(forPlugin: "CwMoneroPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin")) + InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin")) FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin")) diff --git a/pubspec_base.yaml b/pubspec_base.yaml index b85171ed0..45f675043 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -43,7 +43,7 @@ dependencies: auto_size_text: ^3.0.0 dotted_border: ^2.0.0+2 smooth_page_indicator: ^1.0.0+2 - flutter_inappwebview: ^5.7.2+3 + flutter_inappwebview: ^6.0.0 flutter_spinkit: ^5.1.0 uni_links: ^0.5.1 lottie: ^1.3.0 From b3c8be4ba847d8ef1fb05799516421e414dd234a Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Mon, 8 Jan 2024 16:05:35 +0200 Subject: [PATCH 090/241] Improve balance card UI (#1259) * Improve balance card UI * Disable normal USDC polygon for ChangeNow * UI enhancements * Add Kaspa Minor UI fix * Add kaspa icon [skip ci] --- assets/images/kaspa_icon.png | Bin 0 -> 6921 bytes cw_core/lib/crypto_currency.dart | 2 + .../provider/changenow_exchange_provider.dart | 3 + .../screens/dashboard/pages/balance_page.dart | 66 ++++++++++++++---- .../exchange_trade/exchange_trade_page.dart | 2 +- lib/src/screens/send/send_page.dart | 2 +- 6 files changed, 60 insertions(+), 15 deletions(-) create mode 100644 assets/images/kaspa_icon.png diff --git a/assets/images/kaspa_icon.png b/assets/images/kaspa_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5201174ef9491aa31531ef37acde91280188e8af GIT binary patch literal 6921 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 with Serializable implemen CryptoCurrency.banano, CryptoCurrency.usdtPoly, CryptoCurrency.usdcEPoly, + CryptoCurrency.kaspa, ]; static const havenCurrencies = [ @@ -206,6 +207,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen static const banano = CryptoCurrency(title: 'BAN', fullName: 'Banano', raw: 86, name: 'banano', iconPath: 'assets/images/nano_icon.png', decimals: 29); static const usdtPoly = CryptoCurrency(title: 'USDT', tag: 'POLY', fullName: 'Tether USD (PoS)', raw: 87, name: 'usdtpoly', iconPath: 'assets/images/usdt_icon.png', decimals: 6); static const usdcEPoly = CryptoCurrency(title: 'USDC.E', tag: 'POLY', fullName: 'USD Coin (PoS)', raw: 88, name: 'usdcepoly', iconPath: 'assets/images/usdc_icon.png', decimals: 6); + static const kaspa = CryptoCurrency(title: 'KAS', fullName: 'Kaspa', raw: 89, name: 'kaspa', iconPath: 'assets/images/kaspa_icon.png', decimals: 8); static final Map _rawCurrencyMap = diff --git a/lib/exchange/provider/changenow_exchange_provider.dart b/lib/exchange/provider/changenow_exchange_provider.dart index 300741a08..c4a96bc5b 100644 --- a/lib/exchange/provider/changenow_exchange_provider.dart +++ b/lib/exchange/provider/changenow_exchange_provider.dart @@ -265,6 +265,9 @@ class ChangeNowExchangeProvider extends ExchangeProvider { } String _normalizeCurrency(CryptoCurrency currency) { + if (currency.title == "USDC" && currency.tag == "POLY") { + throw "Only Bridged USDC (USDC.e) is allowed in ChangeNow"; + } switch (currency) { case CryptoCurrency.zec: return 'zec'; diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart index 283d2171d..6ddd8f6e1 100644 --- a/lib/src/screens/dashboard/pages/balance_page.dart +++ b/lib/src/screens/dashboard/pages/balance_page.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:auto_size_text/auto_size_text.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; @@ -14,6 +16,7 @@ import 'package:cake_wallet/utils/feature_flag.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart'; +import 'package:cw_core/crypto_currency.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -200,7 +203,7 @@ class CryptoBalanceWidget extends StatelessWidget { additionalFiatBalance: balance.fiatAdditionalBalance, frozenBalance: balance.frozenBalance, frozenFiatBalance: balance.fiatFrozenBalance, - currency: balance.formattedAssetTitle, + currency: balance.asset, hasAdditionalBalance: dashboardViewModel.balanceViewModel.hasAdditionalBalance, ); @@ -216,7 +219,7 @@ class CryptoBalanceWidget extends StatelessWidget { } class BalanceRowWidget extends StatelessWidget { - const BalanceRowWidget({ + BalanceRowWidget({ required this.availableBalanceLabel, required this.availableBalance, required this.availableFiatBalance, @@ -238,7 +241,7 @@ class BalanceRowWidget extends StatelessWidget { final String additionalFiatBalance; final String frozenBalance; final String frozenFiatBalance; - final String currency; + final CryptoCurrency currency; final bool hasAdditionalBalance; // void _showBalanceDescription(BuildContext context) { @@ -268,7 +271,7 @@ class BalanceRowWidget extends StatelessWidget { children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, children: [ GestureDetector( behavior: HitTestBehavior.opaque, @@ -325,13 +328,48 @@ class BalanceRowWidget extends StatelessWidget { ], ), ), - Text(currency, - style: TextStyle( - fontSize: 28, - fontFamily: 'Lato', - fontWeight: FontWeight.w800, - color: Theme.of(context).extension()!.assetTitleColor, - height: 1)), + SizedBox( + width: MediaQuery.of(context).size.width * 0.18, + child: Center( + child: Column( + children: [ + currency.iconPath != null + ? Container( + child: Image.asset( + currency.iconPath!, + height: 30.0, + width: 30.0, + ), + ) + : Container( + height: 30.0, + width: 30.0, + child: Center( + child: Text( + currency.title.substring(0, min(currency.title.length, 2)), + style: TextStyle(fontSize: 11), + ), + ), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.grey.shade400, + ), + ), + const SizedBox(height: 10), + Text( + currency.title, + style: TextStyle( + fontSize: 18, + fontFamily: 'Lato', + fontWeight: FontWeight.w800, + color: Theme.of(context).extension()!.assetTitleColor, + height: 1, + ), + ), + ], + ), + ), + ), ], ), if (frozenBalance.isNotEmpty) @@ -374,7 +412,9 @@ class BalanceRowWidget extends StatelessWidget { fontSize: 20, fontFamily: 'Lato', fontWeight: FontWeight.w400, - color: Theme.of(context).extension()!.textColor, + color: Theme.of(context) + .extension()! + .balanceAmountColor, height: 1, ), maxLines: 1, @@ -388,7 +428,7 @@ class BalanceRowWidget extends StatelessWidget { fontSize: 12, fontFamily: 'Lato', fontWeight: FontWeight.w400, - color: Theme.of(context).extension()!.textColor, + color: Theme.of(context).extension()!.textColor, height: 1, ), ), diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index e72b0f0a8..7930c9c82 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -261,7 +261,7 @@ class ExchangeTradeState extends State { fee: S.of(popupContext).send_fee, feeValue: widget.exchangeTradeViewModel.sendViewModel .pendingTransaction!.feeFormatted, - rightButtonText: S.of(popupContext).ok, + rightButtonText: S.of(popupContext).send, leftButtonText: S.of(popupContext).cancel, actionRightButton: () async { Navigator.of(popupContext).pop(); diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index b20b94cba..3746118d8 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -423,7 +423,7 @@ class SendPage extends BasePage { feeValue: sendViewModel.pendingTransaction!.feeFormatted, feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted, outputs: sendViewModel.outputs, - rightButtonText: S.of(_dialogContext).ok, + rightButtonText: S.of(_dialogContext).send, leftButtonText: S.of(_dialogContext).cancel, actionRightButton: () { Navigator.of(_dialogContext).pop(); From cbaa299dda9fe0019034ac93949a76211fea03b8 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Wed, 10 Jan 2024 18:08:25 -0500 Subject: [PATCH 091/241] Update issue templates (#1262) * Update issue templates * Add config.yml --- .github/ISSUE_TEMPLATE/bug-report-🪲-.md | 33 +++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 8 +++++ .../feature-or-enhancement-request-✨.md | 20 +++++++++++ 3 files changed, 61 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug-report-🪲-.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature-or-enhancement-request-✨.md diff --git a/.github/ISSUE_TEMPLATE/bug-report-🪲-.md b/.github/ISSUE_TEMPLATE/bug-report-🪲-.md new file mode 100644 index 000000000..457cb84a4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report-🪲-.md @@ -0,0 +1,33 @@ +--- +name: "Bug Report \U0001FAB2 " +about: 'Report a bug ' +title: '' +labels: Bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Platform:** + - OS: [e.g. iOS 15.1, Android 14] + - Device: [e.g. iPhone 14, Galaxy S21] + - Cake Wallet Version: [e.g. 4.12.1] + + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..d7a1a3ed9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Not sure where to start? + url: https://guides.cakewallet.com + about: Start by reading checking out the guides! + - name: Need help? + url: https://cakewallet.com/#contact + about: Use our live chat or send a support email! \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature-or-enhancement-request-✨.md b/.github/ISSUE_TEMPLATE/feature-or-enhancement-request-✨.md new file mode 100644 index 000000000..20bf2d53f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-or-enhancement-request-✨.md @@ -0,0 +1,20 @@ +--- +name: Feature or Enhancement Request ✨ +about: Suggest an idea for Cake Wallet +title: '' +labels: Enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From 8d973cf919e4f8399c98c3b88be8f7ee9057538b Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Thu, 11 Jan 2024 17:29:51 +0200 Subject: [PATCH 092/241] Finish DFX auth flow with the primary address for Electrum (bitcoin) (#1264) --- cw_bitcoin/lib/electrum_wallet_addresses.dart | 3 ++ cw_core/lib/wallet_addresses.dart | 2 ++ lib/buy/dfx/dfx_buy_provider.dart | 32 ++++++++++--------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index ab99a875c..c9e4f8200 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -62,6 +62,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(receiveAddress) : receiveAddress; } + @override + String get primaryAddress => getAddress(index: 0, hd: mainHd); + @override set address(String addr) => null; diff --git a/cw_core/lib/wallet_addresses.dart b/cw_core/lib/wallet_addresses.dart index 632eb1332..d8c84c80c 100644 --- a/cw_core/lib/wallet_addresses.dart +++ b/cw_core/lib/wallet_addresses.dart @@ -10,6 +10,8 @@ abstract class WalletAddresses { String get address; + String? get primaryAddress => null; + set address(String address); Map addressesMap; diff --git a/lib/buy/dfx/dfx_buy_provider.dart b/lib/buy/dfx/dfx_buy_provider.dart index 384b7d504..78a5277ce 100644 --- a/lib/buy/dfx/dfx_buy_provider.dart +++ b/lib/buy/dfx/dfx_buy_provider.dart @@ -66,8 +66,10 @@ class DFXBuyProvider extends BuyProvider { } } + String get walletAddress => + wallet.walletAddresses.primaryAddress ?? wallet.walletAddresses.address; + Future getSignMessage() async { - final walletAddress = wallet.walletAddresses.address; final uri = Uri.https(_baseUrl, _authPath, {'address': walletAddress}); var response = await http.get(uri, headers: {'accept': 'application/json'}); @@ -83,7 +85,6 @@ class DFXBuyProvider extends BuyProvider { Future signUp() async { final signMessage = getSignature(await getSignMessage()); - final walletAddress = wallet.walletAddresses.address; final requestBody = jsonEncode({ 'wallet': walletName, @@ -92,8 +93,11 @@ class DFXBuyProvider extends BuyProvider { }); final uri = Uri.https(_baseUrl, _signUpPath); - var response = await http.post(uri, - headers: {'Content-Type': 'application/json'}, body: requestBody); + var response = await http.post( + uri, + headers: {'Content-Type': 'application/json'}, + body: requestBody, + ); if (response.statusCode == 201) { final responseBody = jsonDecode(response.body); @@ -103,14 +107,12 @@ class DFXBuyProvider extends BuyProvider { final message = responseBody['message'] ?? 'Service unavailable in your country'; throw Exception(message); } else { - throw Exception( - 'Failed to sign up. Status: ${response.statusCode} ${response.body}'); + throw Exception('Failed to sign up. Status: ${response.statusCode} ${response.body}'); } } Future signIn() async { final signMessage = getSignature(await getSignMessage()); - final walletAddress = wallet.walletAddresses.address; final requestBody = jsonEncode({ 'address': walletAddress, @@ -118,8 +120,11 @@ class DFXBuyProvider extends BuyProvider { }); final uri = Uri.https(_baseUrl, _signInPath); - var response = await http.post(uri, - headers: {'Content-Type': 'application/json'}, body: requestBody); + var response = await http.post( + uri, + headers: {'Content-Type': 'application/json'}, + body: requestBody, + ); if (response.statusCode == 201) { final responseBody = jsonDecode(response.body); @@ -129,8 +134,7 @@ class DFXBuyProvider extends BuyProvider { final message = responseBody['message'] ?? 'Service unavailable in your country'; throw Exception(message); } else { - throw Exception( - 'Failed to sign in. Status: ${response.statusCode} ${response.body}'); + throw Exception('Failed to sign in. Status: ${response.statusCode} ${response.body}'); } } @@ -142,8 +146,7 @@ class DFXBuyProvider extends BuyProvider { case WalletType.litecoin: case WalletType.bitcoin: case WalletType.bitcoinCash: - return wallet.signMessage(message, - address: wallet.walletAddresses.address); + return wallet.signMessage(message, address: walletAddress); default: throw Exception("WalletType is not available for DFX ${wallet.type}"); } @@ -178,8 +181,7 @@ class DFXBuyProvider extends BuyProvider { if (await canLaunchUrl(uri)) { if (DeviceInfo.instance.isMobile) { - Navigator.of(context) - .pushNamed(Routes.webViewPage, arguments: [title, uri]); + Navigator.of(context).pushNamed(Routes.webViewPage, arguments: [title, uri]); } else { await launchUrl(uri, mode: LaunchMode.externalApplication); } From fe2e26f14600b19125a3bce2369fb61a742ceda1 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Thu, 11 Jan 2024 15:00:41 -0800 Subject: [PATCH 093/241] Minor nano fixes + abstract nano utils out into package (#1250) * fixes * refactors * fixes * more fixes * fixes for monero.com * update confirmed balance to receivable balance * fix balance display bug * remove print statements * prevent unnecessary writes * review fixes * forgot to add pubspec changes * fix * fix sync status desyncing on rpc fail * fix * update translations + txDetails fixes * squash balance bug * add source address on tx info * fix --- ...let_android.sh => configure_cake_wallet.sh | 22 +- cw_core/lib/transaction_info.dart | 1 + cw_nano/lib/banano_balance.dart | 9 +- cw_nano/lib/nano_balance.dart | 25 +- cw_nano/lib/nano_client.dart | 11 +- cw_nano/lib/nano_transaction_info.dart | 15 +- cw_nano/lib/nano_util.dart | 193 ---------------- cw_nano/lib/nano_wallet.dart | 98 +++++--- cw_nano/lib/nano_wallet_service.dart | 6 +- cw_nano/lib/pending_nano_transaction.dart | 8 +- cw_nano/pubspec.yaml | 4 + lib/nano/cw_nano.dart | 216 ++---------------- .../dashboard/balance_view_model.dart | 5 + .../dashboard/transaction_list_item.dart | 2 +- .../transaction_details_view_model.dart | 8 +- res/values/strings_ar.arb | 7 +- res/values/strings_bg.arb | 7 +- res/values/strings_cs.arb | 7 +- res/values/strings_de.arb | 7 +- res/values/strings_en.arb | 7 +- res/values/strings_es.arb | 7 +- res/values/strings_fr.arb | 7 +- res/values/strings_ha.arb | 7 +- res/values/strings_hi.arb | 7 +- res/values/strings_hr.arb | 7 +- res/values/strings_id.arb | 7 +- res/values/strings_it.arb | 7 +- res/values/strings_ja.arb | 7 +- res/values/strings_ko.arb | 7 +- res/values/strings_my.arb | 7 +- res/values/strings_nl.arb | 7 +- res/values/strings_pl.arb | 7 +- res/values/strings_pt.arb | 7 +- res/values/strings_ru.arb | 7 +- res/values/strings_th.arb | 7 +- res/values/strings_tl.arb | 7 +- res/values/strings_tr.arb | 7 +- res/values/strings_uk.arb | 7 +- res/values/strings_ur.arb | 7 +- res/values/strings_yo.arb | 7 +- res/values/strings_zh.arb | 7 +- tool/configure.dart | 19 +- 42 files changed, 306 insertions(+), 518 deletions(-) rename configure_cake_wallet_android.sh => configure_cake_wallet.sh (74%) delete mode 100644 cw_nano/lib/nano_util.dart diff --git a/configure_cake_wallet_android.sh b/configure_cake_wallet.sh similarity index 74% rename from configure_cake_wallet_android.sh rename to configure_cake_wallet.sh index da794a35c..df96c70f6 100755 --- a/configure_cake_wallet_android.sh +++ b/configure_cake_wallet.sh @@ -1,4 +1,24 @@ -cd scripts/android +IOS="ios" +ANDROID="android" + +PLATFORMS=($IOS $ANDROID) +PLATFORM=$1 + +if ! [[ " ${PLATFORMS[*]} " =~ " ${PLATFORM} " ]]; then + echo "specify platform: ./configure_cake_wallet.sh ios|android" + exit 1 +fi + +if [ "$PLATFORM" == "$IOS" ]; then + echo "Configuring for iOS" + cd scripts/ios +fi + +if [ "$PLATFORM" == "$ANDROID" ]; then + echo "Configuring for Android" + cd scripts/android +fi + source ./app_env.sh cakewallet ./app_config.sh cd ../.. && flutter pub get diff --git a/cw_core/lib/transaction_info.dart b/cw_core/lib/transaction_info.dart index 38b4b799d..7624b147f 100644 --- a/cw_core/lib/transaction_info.dart +++ b/cw_core/lib/transaction_info.dart @@ -15,6 +15,7 @@ abstract class TransactionInfo extends Object with Keyable { String? feeFormatted(); void changeFiatAmount(String amount); String? to; + String? from; @override dynamic get keyIndex => id; diff --git a/cw_nano/lib/banano_balance.dart b/cw_nano/lib/banano_balance.dart index b85609b60..b904a35cb 100644 --- a/cw_nano/lib/banano_balance.dart +++ b/cw_nano/lib/banano_balance.dart @@ -1,20 +1,19 @@ import 'package:cw_core/balance.dart'; -import 'package:cw_nano/nano_util.dart'; +import 'package:nanoutil/nanoutil.dart'; class BananoBalance extends Balance { final BigInt currentBalance; final BigInt receivableBalance; - BananoBalance({required this.currentBalance, required this.receivableBalance}) : super(0, 0) { - } + BananoBalance({required this.currentBalance, required this.receivableBalance}) : super(0, 0); @override String get formattedAvailableBalance { - return NanoUtil.getRawAsUsableString(currentBalance.toString(), NanoUtil.rawPerBanano); + return NanoAmounts.getRawAsUsableString(currentBalance.toString(), NanoAmounts.rawPerBanano); } @override String get formattedAdditionalBalance { - return NanoUtil.getRawAsUsableString(receivableBalance.toString(), NanoUtil.rawPerBanano); + return NanoAmounts.getRawAsUsableString(receivableBalance.toString(), NanoAmounts.rawPerBanano); } } diff --git a/cw_nano/lib/nano_balance.dart b/cw_nano/lib/nano_balance.dart index dbb39d2a3..8b8c93b33 100644 --- a/cw_nano/lib/nano_balance.dart +++ b/cw_nano/lib/nano_balance.dart @@ -1,34 +1,35 @@ import 'package:cw_core/balance.dart'; -import 'package:cw_nano/nano_util.dart'; +import 'package:nanoutil/nanoutil.dart'; BigInt stringAmountToBigInt(String amount) { - return BigInt.parse(NanoUtil.getAmountAsRaw(amount, NanoUtil.rawPerNano)); + return BigInt.parse(NanoAmounts.getAmountAsRaw(amount, NanoAmounts.rawPerNano)); } class NanoBalance extends Balance { final BigInt currentBalance; final BigInt receivableBalance; - late String formattedCurrentBalance; - late String formattedReceivableBalance; - NanoBalance({required this.currentBalance, required this.receivableBalance}) : super(0, 0) { - this.formattedCurrentBalance = ""; - this.formattedReceivableBalance = ""; - } + NanoBalance({required this.currentBalance, required this.receivableBalance}) : super(0, 0); - NanoBalance.fromString( - {required this.formattedCurrentBalance, required this.formattedReceivableBalance}) + NanoBalance.fromFormattedString( + {required String formattedCurrentBalance, required String formattedReceivableBalance}) : currentBalance = stringAmountToBigInt(formattedCurrentBalance), receivableBalance = stringAmountToBigInt(formattedReceivableBalance), super(0, 0); + NanoBalance.fromRawString( + {required String currentBalance, required String receivableBalance}) + : currentBalance = BigInt.parse(currentBalance), + receivableBalance = BigInt.parse(receivableBalance), + super(0, 0); + @override String get formattedAvailableBalance { - return NanoUtil.getRawAsUsableString(currentBalance.toString(), NanoUtil.rawPerNano); + return NanoAmounts.getRawAsUsableString(currentBalance.toString(), NanoAmounts.rawPerNano); } @override String get formattedAdditionalBalance { - return NanoUtil.getRawAsUsableString(receivableBalance.toString(), NanoUtil.rawPerNano); + return NanoAmounts.getRawAsUsableString(receivableBalance.toString(), NanoAmounts.rawPerNano); } } diff --git a/cw_nano/lib/nano_client.dart b/cw_nano/lib/nano_client.dart index f1d08204a..661fbcab8 100644 --- a/cw_nano/lib/nano_client.dart +++ b/cw_nano/lib/nano_client.dart @@ -4,10 +4,10 @@ import 'dart:convert'; import 'package:cw_core/nano_account_info_response.dart'; import 'package:cw_nano/nano_balance.dart'; import 'package:cw_nano/nano_transaction_model.dart'; -import 'package:cw_nano/nano_util.dart'; import 'package:http/http.dart' as http; import 'package:nanodart/nanodart.dart'; import 'package:cw_core/node.dart'; +import 'package:nanoutil/nanoutil.dart'; import 'package:shared_preferences/shared_preferences.dart'; class NanoClient { @@ -61,6 +61,13 @@ class NanoClient { ), ); final data = await jsonDecode(response.body); + if (response.statusCode != 200 || + data["error"] != null || + data["balance"] == null || + data["receivable"] == null) { + throw Exception( + "Error while trying to get balance! ${data["error"] != null ? data["error"] : ""}"); + } final String currentBalance = data["balance"] as String; final String receivableBalance = data["receivable"] as String; final BigInt cur = BigInt.parse(currentBalance); @@ -203,7 +210,7 @@ class NanoClient { String? previousHash, }) async { // our address: - final String publicAddress = NanoUtil.privateKeyToAddress(privateKey); + final String publicAddress = NanoDerivations.privateKeyToAddress(privateKey); // first get the current account balance: if (balanceAfterTx == null) { diff --git a/cw_nano/lib/nano_transaction_info.dart b/cw_nano/lib/nano_transaction_info.dart index 8958086dd..9195a06ef 100644 --- a/cw_nano/lib/nano_transaction_info.dart +++ b/cw_nano/lib/nano_transaction_info.dart @@ -1,7 +1,7 @@ import 'package:cw_core/format_amount.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_info.dart'; -import 'package:cw_nano/nano_util.dart'; +import 'package:nanoutil/nanoutil.dart'; class NanoTransactionInfo extends TransactionInfo { NanoTransactionInfo({ @@ -13,6 +13,8 @@ class NanoTransactionInfo extends TransactionInfo { required this.confirmed, required this.date, required this.confirmations, + required this.to, + required this.from, }) : this.amount = amountRaw.toInt(); final String id; @@ -24,14 +26,17 @@ class NanoTransactionInfo extends TransactionInfo { final bool confirmed; final int confirmations; final String tokenSymbol; + final String? to; + final String? from; String? _fiatAmount; bool get isPending => !this.confirmed; @override String amountFormatted() { - final String amt = NanoUtil.getRawAsUsableString(amountRaw.toString(), NanoUtil.rawPerNano); - final String acc = NanoUtil.getRawAccuracy(amountRaw.toString(), NanoUtil.rawPerNano); + final String amt = + NanoAmounts.getRawAsUsableString(amountRaw.toString(), NanoAmounts.rawPerNano); + final String acc = NanoAmounts.getRawAccuracy(amountRaw.toString(), NanoAmounts.rawPerNano); return "$acc$amt $tokenSymbol"; } @@ -54,6 +59,8 @@ class NanoTransactionInfo extends TransactionInfo { confirmed: data['confirmed'] as bool, confirmations: data['confirmations'] as int, tokenSymbol: data['tokenSymbol'] as String, + to: data['to'] as String, + from: data['from'] as String, ); } @@ -66,5 +73,7 @@ class NanoTransactionInfo extends TransactionInfo { 'confirmed': confirmed, 'confirmations': confirmations, 'tokenSymbol': tokenSymbol, + 'to': to, + 'from': from, }; } diff --git a/cw_nano/lib/nano_util.dart b/cw_nano/lib/nano_util.dart deleted file mode 100644 index 13d6f5649..000000000 --- a/cw_nano/lib/nano_util.dart +++ /dev/null @@ -1,193 +0,0 @@ -import 'dart:convert'; -import 'dart:typed_data'; - -import 'package:convert/convert.dart'; -import "package:ed25519_hd_key/ed25519_hd_key.dart"; -import 'package:libcrypto/libcrypto.dart'; -import 'package:nanodart/nanodart.dart'; -import 'package:decimal/decimal.dart'; - -class NanoUtil { - // standard: - static String seedToPrivate(String seed, int index) { - return NanoKeys.seedToPrivate(seed, index); - } - - static String seedToAddress(String seed, int index) { - return NanoAccounts.createAccount( - NanoAccountType.NANO, privateKeyToPublic(seedToPrivate(seed, index))); - } - - static String seedToMnemonic(String seed) { - return NanoMnemomics.seedToMnemonic(seed).join(" "); - } - - static Future mnemonicToSeed(String mnemonic) async { - return NanoMnemomics.mnemonicListToSeed(mnemonic.split(' ')); - } - - static String privateKeyToPublic(String privateKey) { - // return NanoHelpers.byteToHex(Ed25519Blake2b.getPubkey(NanoHelpers.hexToBytes(privateKey))!); - return NanoKeys.createPublicKey(privateKey); - } - - static String addressToPublicKey(String publicAddress) { - return NanoAccounts.extractPublicKey(publicAddress); - } - - // universal: - static String privateKeyToAddress(String privateKey) { - return NanoAccounts.createAccount(NanoAccountType.NANO, privateKeyToPublic(privateKey)); - } - - static String publicKeyToAddress(String publicKey) { - return NanoAccounts.createAccount(NanoAccountType.NANO, publicKey); - } - - // standard + hd: - static bool isValidSeed(String seed) { - // Ensure seed is 64 or 128 characters long - if (seed == null || (seed.length != 64 && seed.length != 128)) { - return false; - } - // Ensure seed only contains hex characters, 0-9;A-F - return NanoHelpers.isHexString(seed); - } - - // // hd: - static Future hdMnemonicListToSeed(List words) async { - // if (words.length != 24) { - // throw Exception('Expected a 24-word list, got a ${words.length} list'); - // } - final Uint8List salt = Uint8List.fromList(utf8.encode('mnemonic')); - final Pbkdf2 hasher = Pbkdf2(iterations: 2048); - final String seed = await hasher.sha512(words.join(' '), salt); - return seed; - } - - static Future hdSeedToPrivate(String seed, int index) async { - List seedBytes = hex.decode(seed); - KeyData data = await ED25519_HD_KEY.derivePath("m/44'/165'/$index'", seedBytes); - return hex.encode(data.key); - } - - static Future hdSeedToAddress(String seed, int index) async { - return NanoAccounts.createAccount( - NanoAccountType.NANO, privateKeyToPublic(await hdSeedToPrivate(seed, index))); - } - - static Future uniSeedToAddress(String seed, int index, String type) { - if (type == "standard") { - return Future.value(seedToAddress(seed, index)); - } else if (type == "hd") { - return hdSeedToAddress(seed, index); - } else { - throw Exception('Unknown seed type'); - } - } - - static Future uniSeedToPrivate(String seed, int index, String type) { - if (type == "standard") { - return Future.value(seedToPrivate(seed, index)); - } else if (type == "hd") { - return hdSeedToPrivate(seed, index); - } else { - throw Exception('Unknown seed type'); - } - } - - static bool isValidBip39Seed(String seed) { - // Ensure seed is 128 characters long - if (seed.length != 128) { - return false; - } - // Ensure seed only contains hex characters, 0-9;A-F - return NanoHelpers.isHexString(seed); - } - - // number util: - - static const int maxDecimalDigits = 6; // Max digits after decimal - static BigInt rawPerNano = BigInt.parse("1000000000000000000000000000000"); - static BigInt rawPerNyano = BigInt.parse("1000000000000000000000000"); - static BigInt rawPerBanano = BigInt.parse("100000000000000000000000000000"); - static BigInt rawPerXMR = BigInt.parse("1000000000000"); - static BigInt convertXMRtoNano = BigInt.parse("1000000000000000000"); - // static BigInt convertXMRtoNano = BigInt.parse("1000000000000000000000000000"); - - /// Convert raw to ban and return as BigDecimal - /// - /// @param raw 100000000000000000000000000000 - /// @return Decimal value 1.000000000000000000000000000000 - /// - static Decimal getRawAsDecimal(String? raw, BigInt? rawPerCur) { - rawPerCur ??= rawPerNano; - final Decimal amount = Decimal.parse(raw.toString()); - final Decimal result = (amount / Decimal.parse(rawPerCur.toString())).toDecimal(); - return result; - } - - static String truncateDecimal(Decimal input, {int digits = maxDecimalDigits}) { - Decimal bigger = input.shift(digits); - bigger = bigger.floor(); // chop off the decimal: 1.059 -> 1.05 - bigger = bigger.shift(-digits); - return bigger.toString(); - } - - /// Return raw as a NANO amount. - /// - /// @param raw 100000000000000000000000000000 - /// @returns 1 - /// - static String getRawAsUsableString(String? raw, BigInt rawPerCur) { - final String res = - truncateDecimal(getRawAsDecimal(raw, rawPerCur), digits: maxDecimalDigits + 9); - - if (raw == null || raw == "0" || raw == "00000000000000000000000000000000") { - return "0"; - } - - if (!res.contains(".")) { - return res; - } - - final String numAmount = res.split(".")[0]; - String decAmount = res.split(".")[1]; - - // truncate: - if (decAmount.length > maxDecimalDigits) { - decAmount = decAmount.substring(0, maxDecimalDigits); - // remove trailing zeros: - decAmount = decAmount.replaceAllMapped(RegExp(r'0+$'), (Match match) => ''); - if (decAmount.isEmpty) { - return numAmount; - } - } - - return "$numAmount.$decAmount"; - } - - static String getRawAccuracy(String? raw, BigInt rawPerCur) { - final String rawString = getRawAsUsableString(raw, rawPerCur); - final String rawDecimalString = getRawAsDecimal(raw, rawPerCur).toString(); - - if (raw == null || raw.isEmpty || raw == "0") { - return ""; - } - - if (rawString != rawDecimalString) { - return "~"; - } - return ""; - } - - /// Return readable string amount as raw string - /// @param amount 1.01 - /// @returns 101000000000000000000000000000 - /// - static String getAmountAsRaw(String amount, BigInt rawPerCur) { - final Decimal asDecimal = Decimal.parse(amount); - final Decimal rawDecimal = Decimal.parse(rawPerCur.toString()); - return (asDecimal * rawDecimal).toString(); - } -} diff --git a/cw_nano/lib/nano_wallet.dart b/cw_nano/lib/nano_wallet.dart index b0d98efec..1f6ec36ae 100644 --- a/cw_nano/lib/nano_wallet.dart +++ b/cw_nano/lib/nano_wallet.dart @@ -18,7 +18,6 @@ import 'package:cw_nano/nano_client.dart'; import 'package:cw_nano/nano_transaction_credentials.dart'; import 'package:cw_nano/nano_transaction_history.dart'; import 'package:cw_nano/nano_transaction_info.dart'; -import 'package:cw_nano/nano_util.dart'; import 'package:cw_nano/nano_wallet_keys.dart'; import 'package:cw_nano/pending_nano_transaction.dart'; import 'package:mobx/mobx.dart'; @@ -27,6 +26,7 @@ import 'package:cw_nano/nano_wallet_addresses.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:nanodart/nanodart.dart'; import 'package:bip39/bip39.dart' as bip39; +import 'package:nanoutil/nanoutil.dart'; part 'nano_wallet.g.dart'; @@ -83,6 +83,8 @@ abstract class NanoWalletBase @observable late ObservableMap balance; + static const int POLL_INTERVAL_SECONDS = 10; + // initialize the different forms of private / public key we'll need: Future init() async { if (_derivationType == DerivationType.unknown) { @@ -100,11 +102,21 @@ abstract class NanoWalletBase if (_derivationType == DerivationType.nano) { _hexSeed = bip39.mnemonicToEntropy(_mnemonic).toUpperCase(); } else { - _hexSeed = await NanoUtil.hdMnemonicListToSeed(_mnemonic.split(' ')); + _hexSeed = await NanoDerivations.hdMnemonicListToSeed(_mnemonic.split(' ')); } } - _privateKey = await NanoUtil.uniSeedToPrivate(_hexSeed!, 0, type); - _publicAddress = await NanoUtil.uniSeedToAddress(_hexSeed!, 0, type); + NanoDerivationType derivationType = + type == "standard" ? NanoDerivationType.STANDARD : NanoDerivationType.HD; + _privateKey = await NanoDerivations.universalSeedToPrivate( + _hexSeed!, + index: 0, + type: derivationType, + ); + _publicAddress = await NanoDerivations.universalSeedToAddress( + _hexSeed!, + index: 0, + type: derivationType, + ); this.walletInfo.address = _publicAddress!; await walletAddresses.init(); @@ -125,6 +137,7 @@ abstract class NanoWalletBase @override void close() { _client.stop(); + _receiveTimer?.cancel(); } @action @@ -139,6 +152,7 @@ abstract class NanoWalletBase try { await _updateBalance(); + await updateTransactions(); await _updateRep(); await _receiveAll(); } catch (e) { @@ -173,8 +187,8 @@ abstract class NanoWalletBase if (txOut.sendAll) { amt = balance[currency]?.currentBalance ?? BigInt.zero; } else { - amt = BigInt.tryParse(NanoUtil.getAmountAsRaw( - txOut.cryptoAmount?.replaceAll(',', '.') ?? "0", NanoUtil.rawPerNano)) ?? + amt = BigInt.tryParse(NanoAmounts.getAmountAsRaw( + txOut.cryptoAmount?.replaceAll(',', '.') ?? "0", NanoAmounts.rawPerNano)) ?? BigInt.zero; } @@ -186,9 +200,7 @@ abstract class NanoWalletBase final block = await _client.constructSendBlock( amountRaw: amt.toString(), - destinationAddress: txOut.isParsedAddress - ? txOut.extractedAddress! - : txOut.address, + destinationAddress: txOut.isParsedAddress ? txOut.extractedAddress! : txOut.address, privateKey: _privateKey!, balanceAfterTx: runningBalance, previousHash: previousHash, @@ -236,10 +248,10 @@ abstract class NanoWalletBase } } - Future updateTransactions() async { + Future updateTransactions() async { try { if (_isTransactionUpdating) { - return; + return false; } _isTransactionUpdating = true; @@ -247,8 +259,10 @@ abstract class NanoWalletBase transactionHistory.addMany(transactions); await transactionHistory.save(); _isTransactionUpdating = false; + return true; } catch (_) { _isTransactionUpdating = false; + return false; } } @@ -261,16 +275,17 @@ abstract class NanoWalletBase final Map result = {}; for (var transactionModel in transactions) { + final bool isSend = transactionModel.type == "send"; result[transactionModel.hash] = NanoTransactionInfo( id: transactionModel.hash, amountRaw: transactionModel.amount, height: transactionModel.height, - direction: transactionModel.type == "send" - ? TransactionDirection.outgoing - : TransactionDirection.incoming, + direction: isSend ? TransactionDirection.outgoing : TransactionDirection.incoming, confirmed: transactionModel.confirmed, date: transactionModel.date ?? DateTime.now(), confirmations: transactionModel.confirmed ? 1 : 0, + to: isSend ? transactionModel.account : address, + from: isSend ? address : transactionModel.account, ); } @@ -312,11 +327,10 @@ abstract class NanoWalletBase Future startSync() async { try { syncStatus = AttemptingSyncStatus(); - await _updateBalance(); - await updateTransactions(); + // setup a timer to receive transactions periodically: _receiveTimer?.cancel(); - _receiveTimer = Timer.periodic(const Duration(seconds: 15), (timer) async { + _receiveTimer = Timer.periodic(const Duration(seconds: POLL_INTERVAL_SECONDS), (timer) async { // get our balance: await _updateBalance(); // if we have anything to receive, process it: @@ -325,6 +339,14 @@ abstract class NanoWalletBase } }); + // also run once, immediately: + await _updateBalance(); + bool updateSuccess = await updateTransactions(); + if (!updateSuccess) { + syncStatus = FailedSyncStatus(); + return; + } + syncStatus = SyncedSyncStatus(); } catch (e) { print(e); @@ -353,9 +375,11 @@ abstract class NanoWalletBase final data = json.decode(jsonSource) as Map; final mnemonic = data['mnemonic'] as String; - final balance = NanoBalance.fromString( - formattedCurrentBalance: data['currentBalance'] as String? ?? "0", - formattedReceivableBalance: data['receivableBalance'] as String? ?? "0"); + + final balance = NanoBalance.fromRawString( + currentBalance: data['currentBalance'] as String? ?? "0", + receivableBalance: data['receivableBalance'] as String? ?? "0", + ); DerivationType derivationType = DerivationType.nano; if (data['derivationType'] == "DerivationType.bip39") { @@ -374,12 +398,26 @@ abstract class NanoWalletBase } Future _updateBalance() async { + var oldBalance = balance[currency]; try { balance[currency] = await _client.getBalance(_publicAddress!); } catch (e) { print("Failed to get balance $e"); + // if we don't have a balance, we should at least create one, since it's a late binding + // otherwise, it's better to just leave it as whatever it was before: + if (balance[currency] == null) { + balance[currency] = + NanoBalance(currentBalance: BigInt.zero, receivableBalance: BigInt.zero); + } + } + // don't save unnecessarily: + // trying to save too frequently can cause problems with the file system + // since nano is updated frequently this can be a problem, so we only save if there is a change: + if (oldBalance == null || + balance[currency]!.currentBalance != oldBalance.currentBalance || + balance[currency]!.receivableBalance != oldBalance.receivableBalance) { + await save(); } - await save(); } Future _updateRep() async { @@ -394,11 +432,19 @@ abstract class NanoWalletBase } Future regenerateAddress() async { - final String type = (_derivationType == DerivationType.nano) ? "standard" : "hd"; - _privateKey = - await NanoUtil.uniSeedToPrivate(_hexSeed!, this.walletAddresses.account!.id, type); - _publicAddress = - await NanoUtil.uniSeedToAddress(_hexSeed!, this.walletAddresses.account!.id, type); + final NanoDerivationType type = (_derivationType == DerivationType.nano) + ? NanoDerivationType.STANDARD + : NanoDerivationType.HD; + _privateKey = await NanoDerivations.universalSeedToPrivate( + _hexSeed!, + index: this.walletAddresses.account!.id, + type: type, + ); + _publicAddress = await NanoDerivations.universalSeedToAddress( + _hexSeed!, + index: this.walletAddresses.account!.id, + type: type, + ); this.walletInfo.address = _publicAddress!; this.walletAddresses.address = _publicAddress!; diff --git a/cw_nano/lib/nano_wallet_service.dart b/cw_nano/lib/nano_wallet_service.dart index 2f183d1cc..7a66f8c9f 100644 --- a/cw_nano/lib/nano_wallet_service.dart +++ b/cw_nano/lib/nano_wallet_service.dart @@ -6,12 +6,12 @@ import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cw_nano/nano_mnemonic.dart' as nm; -import 'package:cw_nano/nano_util.dart'; import 'package:cw_nano/nano_wallet.dart'; import 'package:cw_nano/nano_wallet_creation_credentials.dart'; import 'package:hive/hive.dart'; import 'package:bip39/bip39.dart' as bip39; import 'package:nanodart/nanodart.dart'; +import 'package:nanoutil/nanoutil.dart'; class NanoWalletService extends WalletService { @@ -30,7 +30,7 @@ class NanoWalletService extends WalletService updateTransactions(Object wallet) async { + Future updateTransactions(Object wallet) async { return (wallet as NanoWallet).updateTransactions(); } @@ -189,116 +189,10 @@ class CWNano extends Nano { } class CWNanoUtil extends NanoUtil { - // standard: - @override - String seedToPrivate(String seed, int index) { - return ND.NanoKeys.seedToPrivate(seed, index); - } - - @override - String seedToAddress(String seed, int index) { - return ND.NanoAccounts.createAccount( - ND.NanoAccountType.NANO, privateKeyToPublic(seedToPrivate(seed, index))); - } - - @override - String seedToMnemonic(String seed) { - return NanoMnemomics.seedToMnemonic(seed).join(" "); - } - - @override - Future mnemonicToSeed(String mnemonic) async { - return NanoMnemomics.mnemonicListToSeed(mnemonic.split(' ')); - } - - @override - String privateKeyToPublic(String privateKey) { - // return NanoHelpers.byteToHex(Ed25519Blake2b.getPubkey(NanoHelpers.hexToBytes(privateKey))!); - return ND.NanoKeys.createPublicKey(privateKey); - } - - @override - String addressToPublicKey(String publicAddress) { - return ND.NanoAccounts.extractPublicKey(publicAddress); - } - - // universal: - @override - String privateKeyToAddress(String privateKey) { - return ND.NanoAccounts.createAccount(ND.NanoAccountType.NANO, privateKeyToPublic(privateKey)); - } - - @override - String publicKeyToAddress(String publicKey) { - return ND.NanoAccounts.createAccount(ND.NanoAccountType.NANO, publicKey); - } - - // standard + hd: - @override - bool isValidSeed(String seed) { - // Ensure seed is 64 or 128 characters long - if (seed.length != 64 && seed.length != 128) { - return false; - } - // Ensure seed only contains hex characters, 0-9;A-F - return ND.NanoHelpers.isHexString(seed); - } - - // hd: - @override - Future hdMnemonicListToSeed(List words) async { - // if (words.length != 24) { - // throw Exception('Expected a 24-word list, got a ${words.length} list'); - // } - final Uint8List salt = Uint8List.fromList(utf8.encode('mnemonic')); - final Pbkdf2 hasher = Pbkdf2(iterations: 2048); - final String seed = await hasher.sha512(words.join(' '), salt); - return seed; - } - - @override - Future hdSeedToPrivate(String seed, int index) async { - List seedBytes = hex.decode(seed); - KeyData data = await ED25519_HD_KEY.derivePath("m/44'/165'/$index'", seedBytes); - return hex.encode(data.key); - } - - @override - Future hdSeedToAddress(String seed, int index) async { - return ND.NanoAccounts.createAccount( - ND.NanoAccountType.NANO, privateKeyToPublic(await hdSeedToPrivate(seed, index))); - } - - @override - Future uniSeedToAddress(String seed, int index, String type) { - if (type == "standard") { - return Future.value(seedToAddress(seed, index)); - } else if (type == "hd") { - return hdSeedToAddress(seed, index); - } else { - throw Exception('Unknown seed type'); - } - } - - @override - Future uniSeedToPrivate(String seed, int index, String type) { - if (type == "standard") { - return Future.value(seedToPrivate(seed, index)); - } else if (type == "hd") { - return hdSeedToPrivate(seed, index); - } else { - throw Exception('Unknown seed type'); - } - } @override bool isValidBip39Seed(String seed) { - // Ensure seed is 128 characters long - if (seed.length != 128) { - return false; - } - // Ensure seed only contains hex characters, 0-9;A-F - return ND.NanoHelpers.isHexString(seed); + return NanoDerivations.isValidBip39Seed(seed); } // number util: @@ -309,92 +203,20 @@ class CWNanoUtil extends NanoUtil { BigInt rawPerBanano = BigInt.parse("100000000000000000000000000000"); BigInt rawPerXMR = BigInt.parse("1000000000000"); BigInt convertXMRtoNano = BigInt.parse("1000000000000000000"); - // static BigInt convertXMRtoNano = BigInt.parse("1000000000000000000000000000"); - /// Convert raw to ban and return as BigDecimal - /// - /// @param raw 100000000000000000000000000000 - /// @return Decimal value 1.000000000000000000000000000000 - /// - Decimal _getRawAsDecimal(String? raw, BigInt? rawPerCur) { - rawPerCur ??= rawPerNano; - final Decimal amount = Decimal.parse(raw.toString()); - final Decimal result = (amount / Decimal.parse(rawPerCur.toString())).toDecimal(); - return result; - } - - @override - String getRawAsDecimalString(String? raw, BigInt? rawPerCur) { - final Decimal result = _getRawAsDecimal(raw, rawPerCur); - return result.toString(); - } - - @override - String truncateDecimal(Decimal input, {int digits = maxDecimalDigits}) { - Decimal bigger = input.shift(digits); - bigger = bigger.floor(); // chop off the decimal: 1.059 -> 1.05 - bigger = bigger.shift(-digits); - return bigger.toString(); - } - - /// Return raw as a NANO amount. - /// - /// @param raw 100000000000000000000000000000 - /// @returns 1 - /// @override String getRawAsUsableString(String? raw, BigInt rawPerCur) { - final String res = - truncateDecimal(_getRawAsDecimal(raw, rawPerCur), digits: maxDecimalDigits + 9); - - if (raw == null || raw == "0" || raw == "00000000000000000000000000000000") { - return "0"; - } - - if (!res.contains(".")) { - return res; - } - - final String numAmount = res.split(".")[0]; - String decAmount = res.split(".")[1]; - - // truncate: - if (decAmount.length > maxDecimalDigits) { - decAmount = decAmount.substring(0, maxDecimalDigits); - // remove trailing zeros: - decAmount = decAmount.replaceAllMapped(RegExp(r'0+$'), (Match match) => ''); - if (decAmount.isEmpty) { - return numAmount; - } - } - - return "$numAmount.$decAmount"; + return NanoAmounts.getRawAsUsableString(raw, rawPerCur); } @override String getRawAccuracy(String? raw, BigInt rawPerCur) { - final String rawString = getRawAsUsableString(raw, rawPerCur); - final String rawDecimalString = _getRawAsDecimal(raw, rawPerCur).toString(); - - if (raw == null || raw.isEmpty || raw == "0") { - return ""; - } - - if (rawString != rawDecimalString) { - return "~"; - } - return ""; + return NanoAmounts.getRawAccuracy(raw, rawPerCur); } - /// Return readable string amount as raw string - /// @param amount 1.01 - /// @returns 101000000000000000000000000000 - /// @override String getAmountAsRaw(String amount, BigInt rawPerCur) { - final Decimal asDecimal = Decimal.parse(amount); - final Decimal rawDecimal = Decimal.parse(rawPerCur.toString()); - return (asDecimal * rawDecimal).toString(); + return NanoAmounts.getAmountAsRaw(amount, rawPerCur); } @override @@ -411,29 +233,29 @@ class CWNanoUtil extends NanoUtil { if (seedKey != null) { if (seedKey.length == 64) { try { - mnemonic = nanoUtil!.seedToMnemonic(seedKey); + mnemonic = NanoDerivations.standardSeedToMnemonic(seedKey); } catch (e) { print("not a valid 'nano' seed key"); } } if (derivationType == DerivationType.bip39) { - publicAddress = await hdSeedToAddress(seedKey, 0); + publicAddress = await NanoDerivations.hdSeedToAddress(seedKey, index: 0); } else if (derivationType == DerivationType.nano) { - publicAddress = await seedToAddress(seedKey, 0); + publicAddress = await NanoDerivations.standardSeedToAddress(seedKey, index: 0); } } if (derivationType == DerivationType.bip39) { if (mnemonic != null) { - seedKey = await hdMnemonicListToSeed(mnemonic.split(' ')); - publicAddress = await hdSeedToAddress(seedKey, 0); + seedKey = await NanoDerivations.hdMnemonicListToSeed(mnemonic.split(' ')); + publicAddress = await NanoDerivations.hdSeedToAddress(seedKey, index: 0); } } if (derivationType == DerivationType.nano) { if (mnemonic != null) { - seedKey = await mnemonicToSeed(mnemonic); - publicAddress = await seedToAddress(seedKey, 0); + seedKey = await NanoDerivations.standardMnemonicToSeed(mnemonic); + publicAddress = await NanoDerivations.standardSeedToAddress(seedKey, index: 0); } } @@ -461,7 +283,7 @@ class CWNanoUtil extends NanoUtil { return [DerivationType.bip39]; } else if (seedKey?.length == 64) { try { - mnemonic = nanoUtil!.seedToMnemonic(seedKey!); + mnemonic = NanoDerivations.standardSeedToMnemonic(seedKey!); } catch (e) { print("not a valid 'nano' seed key"); } @@ -475,19 +297,19 @@ class CWNanoUtil extends NanoUtil { nanoClient.connect(node); if (mnemonic != null) { - seedKey = await hdMnemonicListToSeed(mnemonic.split(' ')); - publicAddressBip39 = await hdSeedToAddress(seedKey, 0); + seedKey = await NanoDerivations.hdMnemonicListToSeed(mnemonic.split(' ')); + publicAddressBip39 = await NanoDerivations.hdSeedToAddress(seedKey, index: 0); - seedKey = await mnemonicToSeed(mnemonic); - publicAddressStandard = await seedToAddress(seedKey, 0); + seedKey = await NanoDerivations.standardMnemonicToSeed(mnemonic); + publicAddressStandard = await NanoDerivations.standardSeedToAddress(seedKey, index: 0); } else if (seedKey != null) { try { - publicAddressBip39 = await hdSeedToAddress(seedKey, 0); + publicAddressBip39 = await NanoDerivations.hdSeedToAddress(seedKey, index: 0); } catch (e) { return [DerivationType.nano]; } try { - publicAddressStandard = await seedToAddress(seedKey, 0); + publicAddressStandard = await NanoDerivations.standardSeedToAddress(seedKey, index: 0); } catch (e) { return [DerivationType.bip39]; } diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index 5c95ab3ab..e2c0382b0 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -125,6 +125,8 @@ abstract class BalanceViewModelBase with Store { case WalletType.haven: case WalletType.ethereum: case WalletType.polygon: + case WalletType.nano: + case WalletType.banano: return S.current.xmr_available_balance; default: return S.current.confirmed; @@ -139,6 +141,9 @@ abstract class BalanceViewModelBase with Store { case WalletType.ethereum: case WalletType.polygon: return S.current.xmr_full_balance; + case WalletType.nano: + case WalletType.banano: + return S.current.receivable_balance; default: return S.current.unconfirmed; } diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart index bc7f70517..d8c4776b7 100644 --- a/lib/view_model/dashboard/transaction_list_item.dart +++ b/lib/view_model/dashboard/transaction_list_item.dart @@ -101,7 +101,7 @@ class TransactionListItem extends ActionListItem with Keyable { break; case WalletType.nano: amount = calculateFiatAmountRaw( - cryptoAmount: double.parse(nanoUtil!.getRawAsDecimalString( + cryptoAmount: double.parse(nanoUtil!.getRawAsUsableString( nano!.getTransactionAmountRaw(transaction).toString(), nanoUtil!.rawPerNano)), price: price); break; diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index 4e17866cb..f9ff466a7 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -247,11 +247,15 @@ abstract class TransactionDetailsViewModelBase with Store { void _addNanoListItems(TransactionInfo tx, DateFormat dateFormat) { final _items = [ StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.id), + if (showRecipientAddress && tx.to != null) + StandartListItem(title: S.current.transaction_details_recipient_address, value: tx.to!), + if (showRecipientAddress && tx.from != null) + StandartListItem(title: S.current.transaction_details_source_address, value: tx.from!), + StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()), StandartListItem( title: S.current.transaction_details_date, value: dateFormat.format(tx.date)), - StandartListItem(title: S.current.confirmations, value: (tx.confirmations > 0).toString()), + StandartListItem(title: S.current.confirmed_tx, value: (tx.confirmations > 0).toString()), StandartListItem(title: S.current.transaction_details_height, value: '${tx.height}'), - StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()), ]; items.addAll(_items); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 95871b904..18035bce5 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -759,5 +759,8 @@ "default_sell_provider": " ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ", "select_sell_provider_notice": ".ﻖﻴﺒﻄﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻚﺑ ﺹﺎﺨﻟﺍ ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ ﻦﻴﻴﻌﺗ ﻖﻳﺮﻃ ﻦﻋ ﺔﺷﺎﺸﻟﺍ ﻩﺬﻫ ﻲﻄﺨﺗ", "custom_drag": "مخصص (عقد وسحب)", - "switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ" -} + "switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", + "receivable_balance": "التوازن القادم", + "confirmed_tx": "مؤكد", + "transaction_details_source_address": "عنوان المصدر" +} \ No newline at end of file diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 197dbe552..e2c88a45d 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -755,5 +755,8 @@ "default_sell_provider": "Доставчик за продажба по подразбиране", "select_sell_provider_notice": "Изберете доставчик на продажба по-горе. Можете да пропуснете този екран, като зададете своя доставчик на продажба по подразбиране в настройките на приложението.", "custom_drag": "Персонализиране (задръжте и плъзнете)", - "switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)", + "receivable_balance": "Баланс за вземания", + "confirmed_tx": "Потвърдено", + "transaction_details_source_address": "Адрес на източника" +} \ No newline at end of file diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index bed4e3193..7d2e8a86f 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -755,5 +755,8 @@ "default_sell_provider": "Výchozí poskytovatel prodeje", "select_sell_provider_notice": "Výše vyberte poskytovatele prodeje. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele prodeje v nastavení aplikace.", "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)", + "receivable_balance": "Zůstatek pohledávek", + "confirmed_tx": "Potvrzeno", + "transaction_details_source_address": "Zdrojová adresa" +} \ No newline at end of file diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 1d63bffc6..b151cbf6a 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -763,5 +763,8 @@ "default_sell_provider": "Standard-Verkaufsanbieter", "select_sell_provider_notice": "Wählen Sie oben einen Verkaufsanbieter aus. Sie können diesen Bildschirm überspringen, indem Sie in den App-Einstellungen Ihren Standard-Verkaufsanbieter festlegen.", "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)", + "receivable_balance": "Forderungsbilanz", + "confirmed_tx": "Bestätigt", + "transaction_details_source_address": "Quelladresse" +} \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index e6c95270e..c70d1f7c2 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -764,5 +764,8 @@ "default_sell_provider": "Default Sell Provider", "select_sell_provider_notice": "Select a sell provider above. You can skip this screen by setting your default sell provider in app settings.", "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)", + "receivable_balance": "Receivable Balance", + "confirmed_tx": "Confirmed", + "transaction_details_source_address": "Source address" +} \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 6ee0f509c..9655edf60 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -763,5 +763,8 @@ "default_sell_provider": "Proveedor de venta predeterminado", "select_sell_provider_notice": "Seleccione un proveedor de venta arriba. Puede omitir esta pantalla configurando su proveedor de venta predeterminado en la configuración de la aplicación.", "custom_drag": "Custom (mantenía y arrastre)", - "switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)", + "receivable_balance": "Saldo de cuentas por cobrar", + "confirmed_tx": "Confirmado", + "transaction_details_source_address": "Dirección de la fuente" +} \ No newline at end of file diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 862f9ae7d..ea5862e80 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -763,5 +763,8 @@ "default_sell_provider": "Fournisseur de vente par défaut", "select_sell_provider_notice": "Sélectionnez un fournisseur de vente ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur de vente par défaut dans les paramètres de l'application.", "custom_drag": "Custom (maintenir et traîner)", - "switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)", + "receivable_balance": "Solde de créances", + "confirmed_tx": "Confirmé", + "transaction_details_source_address": "Adresse source" +} \ No newline at end of file diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 9456085dc..8b1b58c74 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -745,5 +745,8 @@ "default_sell_provider": "Tsohuwar Mai Bayar Siyarwa", "select_sell_provider_notice": "Zaɓi mai bada siyarwa a sama. Kuna iya tsallake wannan allon ta saita mai bada siyar da ku a cikin saitunan app.", "custom_drag": "Al'ada (riƙe da ja)", - "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)", + "receivable_balance": "Daidaituwa da daidaituwa", + "confirmed_tx": "Tabbatar", + "transaction_details_source_address": "Adireshin Incord" +} \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index f6a7701ee..a4070cb12 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -763,5 +763,8 @@ "default_sell_provider": "डिफ़ॉल्ट विक्रय प्रदाता", "select_sell_provider_notice": "ऊपर एक विक्रय प्रदाता का चयन करें। आप ऐप सेटिंग में अपना डिफ़ॉल्ट विक्रय प्रदाता सेट करके इस स्क्रीन को छोड़ सकते हैं।", "custom_drag": "कस्टम (पकड़ और खींचें)", - "switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)" -} + "switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)", + "receivable_balance": "प्राप्य शेष", + "confirmed_tx": "की पुष्टि", + "transaction_details_source_address": "स्रोत पता" +} \ No newline at end of file diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 3565c89a0..94383e1d2 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -761,5 +761,8 @@ "default_sell_provider": "Zadani dobavljač prodaje", "select_sell_provider_notice": "Gore odaberite pružatelja usluga prodaje. Ovaj zaslon možete preskočiti postavljanjem zadanog pružatelja usluga prodaje u postavkama aplikacije.", "custom_drag": "Prilagođeni (držite i povucite)", - "switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)", + "receivable_balance": "Stanje potraživanja", + "confirmed_tx": "Potvrđen", + "transaction_details_source_address": "Adresa izvora" +} \ No newline at end of file diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 6744f0a38..86997c8aa 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -751,5 +751,8 @@ "default_sell_provider": "Penyedia Penjualan Default", "select_sell_provider_notice": "Pilih penyedia jual di atas. Anda dapat melewati layar ini dengan mengatur penyedia penjualan default Anda di pengaturan aplikasi.", "custom_drag": "Khusus (tahan dan seret)", - "switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)", + "receivable_balance": "Saldo piutang", + "confirmed_tx": "Dikonfirmasi", + "transaction_details_source_address": "Alamat sumber" +} \ No newline at end of file diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index bb909a7e0..257139d54 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -763,5 +763,8 @@ "default_sell_provider": "Fornitore di vendita predefinito", "select_sell_provider_notice": "Seleziona un fornitore di vendita sopra. Puoi saltare questa schermata impostando il tuo fornitore di vendita predefinito nelle impostazioni dell'app.", "custom_drag": "Custom (Hold and Drag)", - "switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)", + "receivable_balance": "Bilanciamento creditizio", + "confirmed_tx": "Confermato", + "transaction_details_source_address": "Indirizzo di partenza" +} \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 2152a3dcc..3c648f1ad 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -763,5 +763,8 @@ "default_sell_provider": "デフォルトの販売プロバイダー", "select_sell_provider_notice": "上記の販売プロバイダーを選択してください。アプリ設定でデフォルトの販売プロバイダーを設定することで、この画面をスキップできます。", "custom_drag": "カスタム(ホールドとドラッグ)", - "switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)" -} + "switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)", + "receivable_balance": "売掛金残高", + "confirmed_tx": "確認済み", + "transaction_details_source_address": "ソースアドレス" +} \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 5ad5482ed..1903ff1db 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -761,5 +761,8 @@ "default_sell_provider": "기본 판매 공급자", "select_sell_provider_notice": "위에서 판매 공급자를 선택하세요. 앱 설정에서 기본 판매 공급자를 설정하면 이 화면을 건너뛸 수 있습니다.", "custom_drag": "사용자 정의 (홀드 앤 드래그)", - "switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)" -} + "switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)", + "receivable_balance": "채권 잔액", + "confirmed_tx": "확인", + "transaction_details_source_address": "소스 주소" +} \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 73f4e5dcd..8933afeff 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -761,5 +761,8 @@ "default_sell_provider": "ပုံသေရောင်းချပေးသူ", "select_sell_provider_notice": "အထက်ဖော်ပြပါ အရောင်းဝန်ဆောင်မှုပေးသူကို ရွေးပါ။ အက်ပ်ဆက်တင်များတွင် သင်၏မူလရောင်းချပေးသူကို သတ်မှတ်ခြင်းဖြင့် ဤစခရင်ကို ကျော်နိုင်သည်။", "custom_drag": "စိတ်ကြိုက် (Drag)", - "switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)" -} + "switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)", + "receivable_balance": "လက်ကျန်ငွေ", + "confirmed_tx": "အတည်ပြုသည်", + "transaction_details_source_address": "အရင်းအမြစ်လိပ်စာ" +} \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 6cf41e0b9..b05e29efd 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -763,5 +763,8 @@ "default_sell_provider": "Standaard verkoopaanbieder", "select_sell_provider_notice": "Selecteer hierboven een verkoopaanbieder. U kunt dit scherm overslaan door uw standaardverkoopprovider in te stellen in de app-instellingen.", "custom_drag": "Custom (vasthouden en slepen)", - "switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)", + "receivable_balance": "Het saldo", + "confirmed_tx": "Bevestigd", + "transaction_details_source_address": "Bron adres" +} \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 9d3fb3f93..a4f63255a 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -763,5 +763,8 @@ "default_sell_provider": "Domyślny dostawca sprzedaży", "select_sell_provider_notice": "Wybierz dostawcę sprzedaży powyżej. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę sprzedaży w ustawieniach aplikacji.", "custom_drag": "Niestandardowe (trzymaj i przeciągnij)", - "switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)", + "receivable_balance": "Saldo należności", + "confirmed_tx": "Potwierdzony", + "transaction_details_source_address": "Adres źródłowy" +} \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 5cf1fd370..f30ea9635 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -762,5 +762,8 @@ "default_sell_provider": "Provedor de venda padrão", "select_sell_provider_notice": "Selecione um fornecedor de venda acima. Você pode pular esta tela definindo seu provedor de venda padrão nas configurações do aplicativo.", "custom_drag": "Personalizado (segure e arraste)", - "switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)", + "receivable_balance": "Saldo a receber", + "confirmed_tx": "Confirmado", + "transaction_details_source_address": "Endereço de Origem" +} \ No newline at end of file diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index c81c0bd82..47c82263b 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -763,5 +763,8 @@ "default_sell_provider": "Поставщик продаж по умолчанию", "select_sell_provider_notice": "Выберите поставщика услуг продажи выше. Вы можете пропустить этот экран, установив поставщика услуг продаж по умолчанию в настройках приложения.", "custom_drag": "Пользователь (удерживайте и перетаскивайте)", - "switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon)." -} + "switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon).", + "receivable_balance": "Баланс дебиторской задолженности", + "confirmed_tx": "Подтвержденный", + "transaction_details_source_address": "Адрес источника" +} \ No newline at end of file diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 0965d3979..a4abe9b14 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -761,5 +761,8 @@ "default_sell_provider": "ผู้ให้บริการการขายเริ่มต้น", "select_sell_provider_notice": "เลือกผู้ให้บริการการขายด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการการขายเริ่มต้นในการตั้งค่าแอป", "custom_drag": "กำหนดเอง (ค้างและลาก)", - "switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)", + "receivable_balance": "ยอดลูกหนี้", + "confirmed_tx": "ซึ่งยืนยันแล้ว", + "transaction_details_source_address": "ที่อยู่แหล่งกำเนิด" +} \ No newline at end of file diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index f9bbb5dea..e2c29c742 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -757,5 +757,8 @@ "default_sell_provider": "Default na Sell Provider", "select_sell_provider_notice": "Pumili ng provider ng nagbebenta sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na sell provider sa mga setting ng app.", "custom_drag": "Pasadyang (hawakan at i -drag)", - "switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)", + "receivable_balance": "Natatanggap na balanse", + "confirmed_tx": "Nakumpirma", + "transaction_details_source_address": "SOURCE ADDRESS" +} \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 6fdb8bb99..91d130d60 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -761,5 +761,8 @@ "default_sell_provider": "Varsayılan Satış Sağlayıcısı", "select_sell_provider_notice": "Yukarıdan bir satış sağlayıcısı seçin. Uygulama ayarlarında varsayılan satış sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.", "custom_drag": "Özel (Bekle ve Sürükle)", - "switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)", + "receivable_balance": "Alacak bakiyesi", + "confirmed_tx": "Onaylanmış", + "transaction_details_source_address": "Kaynak adresi" +} \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 721a3970d..5cb5a6754 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -763,5 +763,8 @@ "default_sell_provider": "Постачальник продажу за замовчуванням", "select_sell_provider_notice": "Виберіть вище постачальника послуг продажу. Ви можете пропустити цей екран, встановивши постачальника послуг продажу за умовчанням у налаштуваннях програми.", "custom_drag": "На замовлення (утримуйте та перетягується)", - "switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)", + "receivable_balance": "Баланс дебіторської заборгованості", + "confirmed_tx": "Підтверджений", + "transaction_details_source_address": "Адреса джерела" +} \ No newline at end of file diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index e4a9f4590..d367d11cb 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -755,5 +755,8 @@ "default_sell_provider": " ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ", "select_sell_provider_notice": "۔ﮟﯿﮨ ﮯﺘﮑﺳ ﮌﻮﮭﭼ ﻮﮐ ﻦﯾﺮﮑﺳﺍ ﺱﺍ ﺮﮐ ﮮﺩ ﺐﯿﺗﺮﺗ ﻮﮐ ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ ﮯﻨﭘﺍ ﮟﯿﻣ ﺕﺎﺒ", "custom_drag": "کسٹم (ہولڈ اینڈ ڈریگ)", - "switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ " -} + "switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ ", + "receivable_balance": "قابل وصول توازن", + "confirmed_tx": "تصدیق", + "transaction_details_source_address": "ماخذ ایڈریس" +} \ No newline at end of file diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 964307e6b..332297b4b 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -757,5 +757,8 @@ "default_sell_provider": "Aiyipada Olupese Tita", "select_sell_provider_notice": "Yan olupese ti o ta loke. O le foju iboju yii nipa tito olupese iṣẹ tita aiyipada rẹ ni awọn eto app.", "custom_drag": "Aṣa (mu ati fa)", - "switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)" -} + "switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)", + "receivable_balance": "Iwontunws.funfun ti o gba", + "confirmed_tx": "Jẹrisi", + "transaction_details_source_address": "Adirẹsi orisun" +} \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 43e8c6ce1..76afa40d1 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -762,5 +762,8 @@ "default_sell_provider": "默认销售提供商", "select_sell_provider_notice": "选择上面的销售提供商。您可以通过在应用程序设置中设置默认销售提供商来跳过此屏幕。", "custom_drag": "定制(保持和拖动)", - "switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)" -} + "switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)", + "receivable_balance": "应收余额", + "confirmed_tx": "确认的", + "transaction_details_source_address": "源地址" +} \ No newline at end of file diff --git a/tool/configure.dart b/tool/configure.dart index 67732faa9..3d1bccb12 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -759,7 +759,7 @@ import 'package:convert/convert.dart'; import "package:ed25519_hd_key/ed25519_hd_key.dart"; import 'package:libcrypto/libcrypto.dart'; import 'package:nanodart/nanodart.dart' as ND; -import 'package:decimal/decimal.dart'; +import 'package:nanoutil/nanoutil.dart'; """; const nanoCwPart = "part 'cw_nano.dart';"; const nanoContent = """ @@ -795,7 +795,7 @@ abstract class Nano { Map getKeys(Object wallet); Object createNanoTransactionCredentials(List outputs); Future changeRep(Object wallet, String address); - Future updateTransactions(Object wallet); + Future updateTransactions(Object wallet); BigInt getTransactionAmountRaw(TransactionInfo transactionInfo); String getRepresentative(Object wallet); } @@ -810,20 +810,6 @@ abstract class NanoAccountList { } abstract class NanoUtil { - String seedToPrivate(String seed, int index); - String seedToAddress(String seed, int index); - String seedToMnemonic(String seed); - Future mnemonicToSeed(String mnemonic); - String privateKeyToPublic(String privateKey); - String addressToPublicKey(String publicAddress); - String privateKeyToAddress(String privateKey); - String publicKeyToAddress(String publicKey); - bool isValidSeed(String seed); - Future hdMnemonicListToSeed(List words); - Future hdSeedToPrivate(String seed, int index); - Future hdSeedToAddress(String seed, int index); - Future uniSeedToAddress(String seed, int index, String type); - Future uniSeedToPrivate(String seed, int index, String type); bool isValidBip39Seed(String seed); static const int maxDecimalDigits = 6; // Max digits after decimal BigInt rawPerNano = BigInt.parse("1000000000000000000000000000000"); @@ -831,7 +817,6 @@ abstract class NanoUtil { BigInt rawPerBanano = BigInt.parse("100000000000000000000000000000"); BigInt rawPerXMR = BigInt.parse("1000000000000"); BigInt convertXMRtoNano = BigInt.parse("1000000000000000000"); - String getRawAsDecimalString(String? raw, BigInt? rawPerCur); String getRawAsUsableString(String? raw, BigInt rawPerCur); String getRawAccuracy(String? raw, BigInt rawPerCur); String getAmountAsRaw(String amount, BigInt rawPerCur); From d8f1cdc7ef06dd1cc70ecf0176902109929345ed Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Tue, 16 Jan 2024 02:02:10 +0200 Subject: [PATCH 094/241] v4.13.0 and v1.10.0 (#1265) * New versions * Minor fix [skip ci] * Minor UI enhancement for balance card * Minor UI enhancement * Add Monero build configs for MacOS [skip ci] * Add rest of Macos Configs [skip ci] * Delete empty file Save and report restore from backup exceptions [skip ci] * Minor fixes --- .gitignore | 9 ++++ .../cakewallet_macos_1024.png | Bin .../cakewallet_macos_128.png | Bin .../cakewallet_macos_16.png | Bin .../cakewallet_macos_256.png | Bin .../cakewallet_macos_32.png | Bin .../cakewallet_macos_512.png | Bin .../cakewallet_macos_64.png | Bin .../monero_macos_icons/monero_macos_1024.png | Bin 0 -> 119964 bytes .../monero_macos_icons/monero_macos_128.png | Bin 0 -> 5835 bytes .../monero_macos_icons/monero_macos_16.png | Bin 0 -> 548 bytes .../monero_macos_icons/monero_macos_256.png | Bin 0 -> 14085 bytes .../monero_macos_icons/monero_macos_32.png | Bin 0 -> 1227 bytes .../monero_macos_icons/monero_macos_512.png | Bin 0 -> 41333 bytes .../monero_macos_icons/monero_macos_64.png | Bin 0 -> 2700 bytes assets/text/Monerocom_Release_Notes.txt | 7 ++- assets/text/Release_Notes.txt | 8 +++- cw_nano/pubspec.lock | 18 +++---- cw_polygon/lib/polygon_wallet.dart | 8 +++- ios/Podfile.lock | 22 ++++----- lib/entities/provider_types.dart | 3 +- .../desktop_wallet_selection_dropdown.dart | 4 +- .../screens/dashboard/pages/balance_page.dart | 10 ++-- .../restore/widgets/backup_file_button.dart | 0 .../restore_from_backup_view_model.dart | 10 +++- macos/Podfile.lock | 14 +++++- ...{AppInfo.xcconfig => AppInfoBase.xcconfig} | 4 +- macos/Runner/InfoBase.plist | 4 +- scripts/android/app_env.sh | 8 ++-- scripts/ios/app_env.sh | 8 ++-- scripts/macos/app_config.sh | 11 ++++- scripts/macos/app_env.sh | 19 ++++++-- scripts/macos/app_icon.sh | 44 ++++++++++++++++++ 33 files changed, 155 insertions(+), 56 deletions(-) rename macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png => assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_1024.png (100%) rename macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png => assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_128.png (100%) rename macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png => assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_16.png (100%) rename macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png => assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_256.png (100%) rename macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png => assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_32.png (100%) rename macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png => assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_512.png (100%) rename macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png => assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_64.png (100%) create mode 100644 assets/images/macos_icons/monero_macos_icons/monero_macos_1024.png create mode 100644 assets/images/macos_icons/monero_macos_icons/monero_macos_128.png create mode 100644 assets/images/macos_icons/monero_macos_icons/monero_macos_16.png create mode 100644 assets/images/macos_icons/monero_macos_icons/monero_macos_256.png create mode 100644 assets/images/macos_icons/monero_macos_icons/monero_macos_32.png create mode 100644 assets/images/macos_icons/monero_macos_icons/monero_macos_512.png create mode 100644 assets/images/macos_icons/monero_macos_icons/monero_macos_64.png delete mode 100644 lib/src/screens/restore/widgets/backup_file_button.dart rename macos/Runner/Configs/{AppInfo.xcconfig => AppInfoBase.xcconfig} (85%) create mode 100755 scripts/macos/app_icon.sh diff --git a/.gitignore b/.gitignore index 0a883dd18..2ffb86d76 100644 --- a/.gitignore +++ b/.gitignore @@ -147,3 +147,12 @@ assets/images/app_logo.png macos/Runner/Info.plist macos/Runner/DebugProfile.entitlements macos/Runner/Release.entitlements + +macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png +macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png +macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png +macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png +macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png +macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png +macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png +macos/Runner/Configs/AppInfo.xcconfig diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_1024.png similarity index 100% rename from macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png rename to assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_1024.png diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_128.png similarity index 100% rename from macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png rename to assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_128.png diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_16.png similarity index 100% rename from macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png rename to assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_16.png diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_256.png similarity index 100% rename from macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png rename to assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_256.png diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_32.png similarity index 100% rename from macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png rename to assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_32.png diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_512.png similarity index 100% rename from macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png rename to assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_512.png diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_64.png similarity index 100% rename from macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png rename to assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_64.png diff --git a/assets/images/macos_icons/monero_macos_icons/monero_macos_1024.png b/assets/images/macos_icons/monero_macos_icons/monero_macos_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..f3f91af9561c5fca133bfe94577600a6348affd0 GIT binary patch literal 119964 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 z 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 ChmHaO literal 0 HcmV?d00001 diff --git a/assets/images/macos_icons/monero_macos_icons/monero_macos_128.png b/assets/images/macos_icons/monero_macos_icons/monero_macos_128.png new file mode 100644 index 0000000000000000000000000000000000000000..48a1906e178f45cd8a72b8bc4fb20c8f60e215fd GIT binary patch literal 5835 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 pDPK=+!bSU*0K5j>ir=;a{0j$<bG;#m{ literal 0 HcmV?d00001 diff --git a/assets/images/macos_icons/monero_macos_icons/monero_macos_512.png b/assets/images/macos_icons/monero_macos_icons/monero_macos_512.png new file mode 100644 index 0000000000000000000000000000000000000000..7072c07e747bfd1e0f32a772a085c2e35005c7a1 GIT binary patch literal 41333 zcmeFY)O{`Giws5t}2g)ayhVC<+8+R!ymQFPXLmyZVickFVb40{P4DkdY=-kB1Yv@KY`1a{jdrHdk{CsxL z+0xdn*rzS=Ex*zEPn~>cq-f{y82BItC?ocZ$fFnvDKFogr zUShx;ML}7)xYt>P2)lCl^M#HUDT1P*)O&YD^4H!>Yv@D4{oQmgT_tX910~bsg zbpurkMT^70Tm3Uv-hzz!XU@D3QE1I=Fd+%pE(L{{6`kn^ZmBK-(|08E!w z4w$G3$U%nx`XVxf*;73uMUhj&R3p=BF<;*kmwz}l?`=L&Pc##L_AV{s_jixBg7_n} z9O(ETK-MX+z8alFqpVabff|bs{9{&f1}7=N{nzE9gge)lLK>hvEBsPdg1pA>XdZf$ z>SUHt?<^Q3BVhU%2>_2$F`Mc#1|35aB}`2e^?uY2KW-K<)dT&m1SIpBUaRhn)I7)B8QCh!BBK^+~u0P6(9?#7%D zidl3Yqr>vZB#VaE?AjzMuqqdf!p>j zz%Y|l>1X2r2CPM;{9i$CJN;Z%LN@Yjt;~fKpSOcQ9$fECM_B?~;Jk8s*1PXsWQJcU zMx8%iOPiSXzi;=W6P1BeBHeu4U!FMTMDIe#`=SuCaKNc^x6i3rwQL%xo7E`&Me*o# zxqHz#+s+vy1yO9fV5Ns(jK|;JYaUA{L?mcw5d4TBqZW=Nvbs z3KKSxMx)F;|KW8|2B+zpd~!{|k;%y5R$P82TFew<35_gzlmpzn(lr@_X&;zdY2p@(?2_m?exJthGdex*Dg5zuGE7<~gn! zQc0)e@123fu$nb&fA%X(VB481vC1GP`YON_qi1XiCdq)oe>_XhWQ;^O4wQt974uPj zK{ClufW$w;7#mt1IFXxte3t%*@oa|C%mOd*SpdY0aQ`{mZ< zxLvZ1_<8@62dW(tZ{%eTT`>7?Dz&I5=Pi&q!wAuDt&^b9q-SGlM`OFg!p%oQdgd1U@geH4z_%o#LRks{u=`E7wM0YakkCbKh z(05L!GoxKLCfJ)bT@!AGmy`a(hah#LwpRwO3Yx{F_vgwa?4QzFDPy# zlp6Uym!fdm`PhPYBD$1R*>xZEO7TWZ!w&IC2sz$k&^sYT;#4fO6bKbVXVG+YSj2tT zJ;WPX-AZ7o?XeeXKoq1zL8ucOl>7Y7!2p4eW8kWdc2b?dMGkBtOg=Xi0_@*dCgw+tMzH~)BJ!KgM} z8utgH5F2LqUc9boWufs;Vt>B@M-Zs&DMsM(H8a@OIqN99o0% zea-^6sXkK=VpYl2uLTF(ekkZUIw;C;>;+y>5to7Z&YB6V_V--5i(oA#le^w=&KtR=ki-A9iFJPD;l5MZJ$dfKZk@KB}2T?yj92+*9YpZ z4&(m@QqT-z`Mpxd`k{(k>J(=B5x<;_( zZn~)X=-qO!Wn|2}3U<#%P%^-y4{GzlVN_!qEfXZ|YLze3EC1D9;t~lETqi?0DF3bC zkH$wo`x}@|Jb;B6bMv44d^<|;uGyEHAFpnZi1htm2)g)X=8H38W`brRkR%==sDJscMDuE2a#jE^)@iV{>Ny*8d|&f^1< z6&n{!l)#(t!-z{?=5U1IhRi#$@Prrj61{|ka-h43sS%Z{LOS_)Czqv z|L}@KkOkFURs{@~KdTry&CLL*oR)ptN`L>?AFJZ}d_q}MPX_J*smJ{MOki#0O!H=I z#Q_^NhWA!)Tcj;)FA@S<)0lJ#$D=pskiaz7{l^h~l~y)Fxx#pX%za^BF+So3o##)i z8_&KDe=sI1^a_{A@FN5y(&mik$&RgB+|CLdjC8iYF?C3!nP7!uY`=k0k`-{`HihzvgMk*yOeVHP<0$t=q!JHnR%Ey}^2lfbok>+<5 z!8cXm@^y-u5XS<#x4<>DmLM^Z5oN)FD?QgRHNI)mvqK_53o8hNECd(>4sCk<=U-<% zUHw&|3+62*>wWE37=#26KYm^b_blG&S08ALt?$>{cXF>od=_YH)sQPXA{a-DdQX{h zfosW_qevp~=cKzM(UK4_$r><{S+w*`T@2vXUHw%no$x&TO(hYC!OR7`V3vq@wmBQ( zcJ9YDBTXa`+w(opivGZvHz-$KH3jKrb1-zv?UJ+DiUMX2#ru1wiPvfgOKeW@?ZZHt=V1v-c7y9Fxo_!eepNM;k;{C_3 zw7o*Zf(Zm$^Ar+V(ui@YDV6o|qN-x>G`DWhAZ;)+jSoIk6hW;KG<9Zc%Ow1br4rRu z*3AquLwvLieyT>9%p#h0QEO4=d%(?NcZ)^VMF0#EDO+1hXKp9P-wXt1_en_YJx)bk z*%i`yHB^;T+P%n5g235jZjt@3#&XRK?g9^1I4%{)QeTs^f%d7^cwZt_7TWKTTf!|8 zBE0UU7>ecwd`&-ygWFnkLxjRg0V2ap(b&1jD z+K5(J-1T(YR*H%=($9>~3iL-*Z^$?g`}bc?WvwIvJPIqiTW@tGJRzo%doUWTiZeb1 zok3irg3x@urq z7={!FWGS#*f$O^(53hc#Fof`;X)F<7iKZ=NqOR@24V= z`+-6fXJbGX$PzLXwg; zq`u@=n!vre8UNL84_9c#uNYyYX~B!XG~jbIxVRDb{N6LvQPpR(L9?SXP}+=xqaaAa z+y5r02=zTx!|V0%?`{@!#v=+in2peGnF2iiks>3=(&vlyY#P?Se?52#v>&G69{ksP zIJv(GKnw^s@Pgoz42Rz*MFMT1)6aWo;>}^DJY*UGIqMxW1%b6 zPpQeDzK=q#%nO+j-Y4I$4NI)8XA&*IC43H!@P-cek|D6WxkueG`7)lvxc14VbBg9N zgNa|PUy(5fhS3}e6S!`|Fk3y3gXyx=6JCxZj+n=t_R}CR%C*O74*?5!wrHy0Wy<$w z+LMSX6xUZ$NU9OV%rf2GLLa`Bt@-2y!SeMLuzG!1FYn(Pj)dNo%fnMULxIry-22|D zzH5y{NI~YvyDOwId{7f1ayvfgTu$Sf3vEqkodDuDtt3r`qAVbUTwBE8p=4>yeT&{# z_a9+M!eiUbKn`I*c!C$~pJW0r58yUg;y;U;b7yW^sap(jk$@sHk=Zy@(?mPq)HM}0 z!sJ?hANCWuX|Vs;dU3I{MY58TYUIO`ba3a(-^-365LhP0mno0a^WR?HN}K{ zCuE?4;046$6xI_t35V*=EO>I;jCOgvbr~NMc+M!HA48w4I;>VTI$&GhR~5ac;q~97 z6ro~)-?$wVk0}e|FDyksD?Jny7JpasO!^`a?C^{R|T=4Z@*R)`Q}(3sFozdusjtK$3j_JKZM zcTUQ;|045cAD5ZS>s(JNjgH@`joCkfs(n66rT>rD#8jb__lz>EMt|P5<=eCFmvpWE zWt*5ruI2*%FvS}q_KuDFrV_9%>GU}+R6=6rSPbM?;r0bpvEz_#Wl8k2<5`>hM$pQC zGB5G^GZ;rir(88F^ZW1ezeQ93EuO&)1H2F`x$umA#uzmF5vOjSFGO=A5% zFczl~%dAUV6@xvMr}|A$-WyB?tSmB3Rw6^h(;>(-t0eiih^R;`W6; z7lId#dCs&kz9NwB%bCaZqXWh@Zy{*tM7oXbuqB@&-E|5U8+zHd!*KQ%r#trQy%Tnu zcg*xh(~&0@TMe0hDVHNpSSLfHYx}VOL|E$=BqWCc>b8N2;_+Xk&K#kmFF&X)e@%lw ziLVV9>RVl@H(m_kH?mFlSE$8(E=0E51I&BT9t*7a7 zFx;Y>TUzLUT9JU%e)%=3FE2B^<`%K4TV&Ky2CjT;hg2eFd~fx4w+^ftM<$v;Pu)TNdLI3!aprJ2eZ8(*yzYyG?S?>U_1p7? z|DL|mAzD-xMb*q-L6~v#5mnvgCCm8SP*!lEOCL<(($*ut+RB?Up?-Fm|JanKff-F8 z7u<9m4ov|6NJ}cBftC|NW9=Ti&=V2UTuXOvjR+0^AEW(uKzt5!pD_R_r*}$VlTT8>h z(0*UEdWGt}^(=I*Gb$kW302kifc7uC^@{RZ|FUXur+xIeye}i@xT%+cVfC-qR>i#M zWtYC_!R1!r>(#t!2%6m<^zgU8${Zyg%T?cPojPyfvq67=*k{2Ge_`0f@9_)(I=6{2 zYF-jJ~UF6Pjp`%*hiBP`lUid3huY6^;J%f=Kv8f{`g1KK)<9afvl?FS7f1 z5xQoTYM({jPeXrqw8xh!Z;SJ;L_1~q?=Ky&$#RKViZ5Qz2N3pG$Q+%-KmfomC$?fm zv{3oJLfIcGg=k~(-}ugfto2U)1G#wHFn(!eG`&BJ(<`N!-oJ-Cf3|+Bn{@7Ay08`W z%pD%MgIR4%U9r-^srJ=x1}}1J*5Y zTTM3y+^DXNY9Nod>n!$ibaZaOFOZ9k8F8ELCUK`d0ahqcW-SHdwVVWh41CF`o_Z*# zl&4JWyw#7&s~?Z+J@<1kDPCR;$s?ZxP0nEoRP7PB4By?<(Ff!*3;J~Y=yow*m^z;N zVf4%10AdVOUt1Hb8|I4rnR6*40y_AW80Gaj^>ouNK+v+K3PrTA+w?~6j#m`zKCqPW z%u_be%%DAa2hO>ea%Rp;zMY#7{a1LcQ?pAI`yCaoD;zhK&Nu%DogIOP*;T;j`)Z3G zyimR~1#K+U zud7`b03E-*!Z)IzV#xVIEbV)iS)oub2(Ee$Rd3X^tEq~i^lvk07agmU|_26xW?m=Qn8&;i=ALzg9mxSsYDNLDtu)PO@ako&paUyulT-Ly)@{$DbV z&Vzqx>WX#6BXuLb>i@SFAn`6*wgvN@UNvO_RNbd&7V#xG)myp&H2cYh=#lV#J}T&) zkhOA@LU3ox@J!J}rUqa`^z_p)J$IzEUp|@%!-MVJ?r(KS{lPm?v>MZ3RHG#}^`$AT z5WaX8zVQ647uI5mX09(68i}FzcE0G%Jfy73YZBy8Ual zuxQ=AUxf`|rb$K*NH0;9)J75i-4R+krhUE&Ry-b9Dh^nZ*M+QQR1&P``)+%5a+kD9 z)z~VboBo0!a9WoR)lqRqYyXzkc}ARXd=WTRuh7sP9%T;h<6TsPX!=wcE z{@~~B+|zG+iZ9xHol*C;BCUcKk^>7Q{U$_>{La1$R7-xHFy!#sSlsu|Pz9FSbvuqq zG&~e@Pz-!EmNVOrmq-FjG3=BA1)dt^u0N?1G+Q$t#Ql3YC9!{=t)I%4w*=vH4$yi_>VYKsO%6z5mZCF^a735O|nHOyGS2|J6s_C5^(#Vo90` zvFDVtX_p=tpSfNScI2)oU$4gr3CXKHybN=wJxpUf{ZvB#*yHdi1n?g2!rI$TuWo!nP@23J$*V4y z&HWG4+Uf@GLgykUIj4-nh8B>$8$8f5bn>nQ>|rB^E2h3#ocdo*3E|*8dj4yL5}$eh zTh}VT)xR333M0@+Y_^Xgzi~AtTx}W)4xnLF4Kr5E`%dEiS*X!LRrF*eDBmUQ^1zGD zWOrW;ys!cqKBbQ2i*t{kW_6KIqqZ=@+=_Q+otqU5!KxC=z(U_{=;YYZFn!Kwh6Tzy z06gy`Y?stzd1|!6{%PT@s6iJAUkd{QeR^io1HaY_dU|U#L}NuwgKJ|kHDIVz^f-17I;Bzg zT{Pyw8Ki*chtupW{tm-ox{v*?H$g_2P7?Z|?b$EqB#o5x+9VD6=nT9c^V6zx({5ky zdqH()b6{)`xUY5f!IJV#wgbA!j=EI2IE|gH3|N3>iaDVAKGOSgqGzNxH)gxA)o&6l zzYduB{RTr^{QyT&e?&H?)WW5N z2-5_Gbo#vqYA+>o@*(gnxK!*9vm(t#*4=Z;R$L-Lj*(Gu6+!ss|<8oPm?OB>srEjcR5N$o#<*TtUWOZaft zx>q9oU;=}UVFNP6&hw0&%?*%4uH=cLs)N#ka~6Etpjr&jOt}I{uI=-#+Vd-@X>=<- z%Bv_k&I*O7CEZ^Paa!NkaP;1nhrVt+CUe%+v-ldLqWC_B)2)`S6+1_Po75b5hX1nm zhfCrnD)twvHT`1gu0O)6zb~!z=7#!7nx5%IYXozJ9x&$5rJGvXzj5%wFDu zHALWLq0w1k7e`dN6ja5(_jBJduxZd!sfRpkiNNtU#-D4Bcg<=L8O-V_+ri0vV`-MX z+4A3PzfSY)XQ5=wkmg)smVGA)@L?roHeGz9T-epwxKWzTfq7jID9E2@*30L#w-C#x zDdBG_x=f`9Kpw?8-ehH6X$0tpgPBF=&x)n33YbzelFZ!2Rx95TJ%>HKeAdLKvUUAqac3ygw@Q#~I} zh8AXXUiNTRpY42DvR7lm8g6?P5hzq4zFAfAu{XdNJ^(o`cP)>|9)91vuJ_t=)D!we zv*Jn6s_^t=3+l8xa7yS{Eh!VyZoTi&WZb{BNHN^PNK`J|L5F4{&b0bqP<;D7pGd@X z-?8v=gVr(VKr_kgjUADzAnv1Fg`WHMW*r!MCnw0R65wwo5yzQMKS{N7Ucvex1jiuo z^k2g2e-_cOfBtW~K9yBTP5S(^*mqZ8tN{ms_{pg4{WsDs#-kvh^*4D?zUQABm%Mrm zSRJw=y1>BVfPp_9v*v0sD$c9EJwho|!I4zycMNoBvr1VHNQPuJ%6gQOT>e%hl)rl& z7TiPb{wEGBH~8uXfeZ1|0XWCHN?GFGW=2zu8@yS~-9zB^={%=>5K^Z!G`~8X#RH2+aWh7DM3#(a`F8Qk`obHKzMX z?l*%Jnc(>qkw_P7;o_wl-P`jll%Eew;Cey*ngEyMix($O4VY8~U7a1%Z)RJPU}{)^ z||StW>e{RnAh%feTL?%x1;L`-ju_howBnA<2pHQshDe~TcV6f z;G0WXRjT$PvMTQMw-F{$^`3lKq*5&cU>(3s37bmspK)SZx9eN=-);NK;lC9frUIMl zMTSAy*%;-Cv{`;74c?1+HbUDY&O%0aO8F~dDsUE5_|?tac4E(Dys)Yb$3${kiG8{1 zrK8x?3-nS^osZ|OC9*ItuCv8Z)|VpcMD7LznFF_72xF`LnFkWPf_I~7RhkT9OJAP; zI)o=@2cPV@6E^(_&Q17aXwQ0HJby~g^o8d-;oLX}<^Fl2r6rmirlIZem5X`e%@YH{ z9f^=j$(v@8i(tN?Ud7Ok2Vc#0^kcIl@_wDb8GSP95xt_O>q=_+)^#2k5i8*q<2cZFTz@E6a=647b^=VWp&NThB@gl3ci* zcH841eyV^2Yk$H!^l#KRcnWDdi-FX`UG5_dNATr0u08)M)AD0#D8@c%_zo|W6sM0t z6{H%LM27Pv&Wt5m=Sd8EW>!$#8>Sk6QxkXT^rOSGpk*%a<@i`jSnS-V0ogqRumlrO zU-FdBH;rzct@S~hqyBKUp=iBhrJPCu^U=lo56L=ijZ`_@Kh5Y*oj~E!36U8Jj5+C> z@-?TSfAu6sj=V8ZXNfN+F(B9Pdc-RBI2vfrZ9Q!X4xF##z zJ#E9Qtw4C^{q zS&3SCk z$9ELdy21)dwQr5OqI~!!d?5OC$%h~KQ}L7Cj_?J6S2pGm?kB#CcquUaL1iveg{wO= zn`n*7vC^_0Cs9(43Bd=3`ifB2>YCJa;5*lrnZ0IrIo*5qUy7)SvbIGn-rFVj_^)bu zI$Rjv^@j#c13#sykbTL*D+^qE!P??SvrfS{-)eomUv?dn;#t%_`uLwc81VH%y zT)`su#Wr zsmc_I=!v-#V3$UhhqNTiy?#>V`kz4=Q4)`is6o8&vp)C=5SoeRKUD}R4}#EiHABmVH6 zK3K+=o@ILnSd!jaL%}K)F8haaOH1<=A*gchN0|-|4?1b*zvEst4^&c&h@K8iLmb4Q z@#=>?1BBNt!G$}Hu(BJCz!h2e9x6O_vB+3-_!z72z4Z@YrLTRr=1xuchs(~QSamV= zoY(}RY%D4ClB9^KdbfRLcloxW0*XTxOMp6fu1Zj@I^D$X*AuiALm-Ro0+9`AGXSXA z2GR~1m3)bjIFHo}FbB^O-J7pniTAyA{Vg+;6Q>G zMhZ$;;leO6S&%Z4DMOY;vv9}~V7l0_Ej0!14i`d}Ul^n)wXYkLkh)POP_L~c__{vv z@@m!a^GJ>m`-qqxDx>22g{grlSuB8;ly#37C;9`+kh`c1B4v#3=gNSh8|Q`flY zm^w!Fy}O?sHru~ewmI_(R*{ulFiJ-C*9*?d8<53xk?W52A*a0mkiGp(P|-l_Fud`T zdNeS{FC6)B7bN6bHbBjQ9syH@w0Rl~XDkRa0!i_t}+5Et5 z!@~J}TGq+wTV$W@Kq_zUR%!C+Tz=7iXEi2@d0$By)uOEV`URiQ`r2Y_2oRJKfvQLV zqWE8Dt0F}b<&ztoB1}umv4vdaVqLT*H|62S2CppfycS!Ho)!>Kzu$S>Pa0XR3!}d< zsT6-$Zi74uslg6>iiPj(jWkct&yw;6N8Z3WP@y0T_0|y$&zxX^M_!G5JEig@l({|H z2BHsMm>)uOF1fHLoKCf0{!2C2VFy`c(ju^vQe{k6? zT<(+Y5%)We61cuve90}L6Dg>}%KvBe;MdhV6at16BOsz;j{{}LXcYIc?`S&^vJpUPg+p_I)wALDb7A=NSBkve6#!YIn!%a& z%M}?mezYJ}sp>*|p3KS8ifSunOPWO$)68S9tE0(oe-fTACU=yD0)D@u)j{lNa%+pZ z9>?J%yFd z*muuGbtDd*laD-1ir?%84)I#umuyYh-qcTx;d`tNtM=YX-9ET3MRONpMEeP=MvYKG z+7y8$e|XErnFE<^+!UGUkaytV5!LV5!;<5@0Z;R!k~aT;U(ULi=8th4Pyc?$`7-8| zMN37w9FlqQrnY*@Z$h)TLk4aSfeKhan{tc(eDulO8jiOFX635qbx|>^#*|N%!X%HZ z-#%F9_BPr0nvTte%!}FBg-ScK^t1<47+!wi@{F4G!tjm-^uBUm{PgE`dbfSiIZ#$5 zjlbXelB)lsGt=SOR7T)|Rwn^^5%-_6yw-uB1e9XNyk#L#NOz!4BS|<*NG;(XP#(B-koCZTI3a#_@9=@W>|BObR+dbR)!4_{mpta1=7U%w zsP;Pn1_Jam3~tCl*cT`(J3#}|B3Y4#b3kB?y=7zElM^v^5myqu9hD>kP40@rf7^Dv-7}fU-FAh&L0FwGWY=>G?%5>$OHopM2-RXp|Vi>M51O*_*Jo zZ8IiMPzLsTByqw>G`0tp0K?BY|ji@Z@(S1(R}@;F82N){{rU-#b* zyK=sAXi8S?u=5e})C1#qpIUakgb$iDlwVuA#o)V_r)K*KfSjHFD2vVMZds{Du&&go zWmnfizyAHE`y|JTewt5;?B9ja^WJZ8FStAN^l$&Q;`;KAXbd0uxH;_@`q_g-#bH~I z3i%(>9C6_pwdrN=&1aJEZgVfMG>Yr)48K;tUd8+@4TsdY;sK82f(7ZK1a5?enk?CuyvW z#Y^lqJrc7qtl>O#hL~Vl;RFMd1O!IsR5RtOw3jw zRoNNQZ}fSxmgD;Kvm>kVV$YSC%4uZ7uvBHpNW2ze8jnPV5Y+JZ-*81eWu7GZXk$<{ zmqJKetSnD=>WK+uz7sk1f#Aj=WQ;S{!-{h%{fL049GKGxdiM~Jd}_PgWF1whLYIX@ z+^gETCw3P2yr6l#`F<)(IqP6|ur;*%T1}&Ggz-}8kLnB@qxFqDw$aF3=ItM+00Ek; z3h-K8{6h5E0Cj@%eLIe+rxi{{Yzd*c#cbNTm|Aw$&X9L0_bP*#0w}K?Y?6lkaJ0Z( zQB=bJfURnHd*$c;g$%OZ8o$@Pmz#E#uJ&efQGc?_0sXo~ ze2k^Gkb)G#*fIR}3=a&V8bn(Di^|ofFMvkUM4dzzaW!zSH`8EGh*CICXvOa>?aLr$1fOd1%`GerCbk z$vFc~$3^u$BA?xFdOF8maNatjF0hXUyK4JEcx1XpJ+MO-o&Yw3irl6?A8Kt(H8))C zKA@fu`wAaPhXkDZ`R6{~2#!JHt>cvp?U(A^ek$RMoqXar`LhurDZp=#99vFNuslX~K7%E?GGTPio!%JCaJx-);krB}rF-HAMVfw#$bAu7SKCQ(_`SRN#P)OpW%F95!R|hrce$@0=fO^} z6$+ZV4B9XH^u4=HRjM3O)%+U7vk@V7X@=Ud{*qLUxmq_9g7uU$mx71w_S|x}$q9nP z0wC+vUvT}8l#>O>e22GI)htsywIXw!pJ21a`Vm~ zWOwMl)m=a3oaB7v6`kU^cZo7kN4I~Dj`ftrz_U5wkP+{S)MJx$Go9-zvdc8H?RNCd z8uT(FQOx5bfqJVTHU8&@V>X@vrnt+!4NaR-_tWvPH3+=z<2i@bZl`sYdht$p5T`Bj zq{dq~G?4jQgs-E+bLJgct4muPQSI-)A9$4f;n@PB=-s_mj*oY^aMMfDEsI4a{mGQv zDD!U|S2QlxVpCoR7&aawyzo87Is5ot%ro@98osBtQ#BCJp;_vlZtnf^Opi*l7ZD_2 zH$|tsz;i{Dg8?A{4kH4Z_PYVJ(`RMaHR*TV#W_gA?*=5DS(sNyv8~TD?n}7t?gXeS z{r2k5>ssUe4#_Zxbd6*H8?lbD{*Wv84Hf~?zsZLg;n36)$^T0ErY|!6O*PlD4H>xa zaZR{EW`9A9EqV*30dpdL)vKT4i&N$HB%S#t7QzK^((7MYN;@jzMj zKe3O};k*K?^xOui;eySX+nW&Bhd@UHfg3u_fR8E!s`-MT!_kPlyIHiS$F+OQKN;>y zqG2_Y(fU(LfX$_Iyah*(y7zI<%clqO?g#!sFu}DmIE)ZjXhJlpNe#2aDaj`=1KS2= zF(6K-fo03c&CYTAo+Rmrw43nFGD+cRN+#-4V@gn-lxbFUWLaHm975tkJr+qWw{y1OJZ^zBi z_~gpG7IRQ_{%VZ24cZb~}m zkX%y*>eUFp04I9|hJY7A>s1si+h;juMJTjJo+H&-Qmib_`O8&9=g&$obnlZ2TUdoS zN9^q}Ra<4c`gebssncA@8%PK`mAzggIh%p1QUkwKh?n^y)1{ zObV_JM%)^ct!r&obQ1r;gZYq3YjOy+ZbgGQ!uSLax~@7Wj2e0p4VX^suXIaKeEJM% zL3uZqp9JI%*%N8Ay-2MSFvd9yJ(?JKLf)P@7{x1`oc#!33 z1MH2I{8g`p4^!d>KR;veXTkCz(6T2p88&W`4PhI;w6K!KOL1kp{&q>h&_D>;pG~X# zN2B`o#3QOUp-lhc=q|~3Q@VgndKEi7FPmx7_-qV*cP^ZF*-)gbbnxrx`#%TeCg5Z^ zAlB|`;pwR3(;L7hnV2?aU~!m;r>{CP5zM7N7cyjcp9x=OXrCIj}ACza@iEMQ@WZJyd9V;z+3)%kKqO=%= zPmrU!al4$t>Y!?MVc5Nk3Cff8P~vZTDFUN?a^*;~r7GBn)W;x`132aDH>}xEXhh2^ z`LX>Nd&#XpMl-tg+YM~Url{<=1l+Fso0hLFHD%mwQ5dI6;f=I%}%8K!I><&L@_DrAgSnUAcgNG9N;E8cF$WDf}#S{Au^ zL*`wrO#P%0cKRw37<*8Jpz&~gZEZ4U==7trj0^KFz=YAGZ@Qu{wUHc$`uUZzWx8sI z96z?F&zI%VpG-8!Al^W57y%lk0R(&a=}C9pE{|er0OSM98DBB;$=IG%%@&^ZtRiNI zavAKO&;0$cY6+e9`fw*T`V#(KwEIMwHht_DcQn$JJx{wg(qfkt_R8#JzEgUwrP;asq5SQkkOqxBoL;`H0#BXL!1`$7~c3;Ws@! z+InemWzR5=CvG8<5+9^F#@(n0YA#KU77$%X3w@-_R$SHP zn?ABtg-Og$Iq4zmn{^{|u*$aTd6MAHe=W?wf3drMHFf}G8iPLurN$q@^}oV;94L;7 z!$FM<9rs_1Q@7v)=`SkCt?{M(uQfJ4n;KZCS z+w;O?G{za6FFjL%@!ERQ3FiUKogDqZ^FaOo+Y3N`OyG~_;=KI$=?CpS2YLTeD(g!X zCxrb|r?0OGK$S$hWE$zdMA;YW+u4cfd-KE0{1N4ZbCKxsSFtcA*&Be4fzp>Ox;CE z89pH{I!P_l@x9-_#diH(h6(DaxVlaKe0dfKqQuGuqJFahe zu~ZZ4-j!g&7UKskFSQY6m4~eY53>4j8s_S~_)EgZ9i~D1zt0;^9Km7u05;!*L2pW8 za{Le48v!Rv*``Y@&j%Rtzl`E-8G%?tO=-X4xyQONedbydVk_y7kJm}ptq<{mjCN-w zo{ta0pU%U#j$ez&j(g}M8&+B^niHjwe<^jsu(qn)yLs}t)da+m}c*Jl|jO zAB~$Q^!2wSxOBDZ^w=qr=ZP`=!WnS*5=phE(xhR5?_Q|sXN0RIW0Wd+zFg8-Sj)z{m|LrAq_F{;^_ttBA1ZpcH_kTyT(00<>i!0O>}&b8|E=t<_%Q+=ih)GL zQXQ=$`(U)>Sl1$}$}Rpj!4RI~-pl$wdmfheq&p(oeW_df_@!zgPxeKItTDzZF9Oz7 zL3#Sqmm=3SdNl2o_@<@b3Pbj?59w&kq5OjW?^BMuxLnJtSE#4gyU)OgFZ@1UU$-Do zY|7y}Hy8T_?El5?;w!&Y)obLb7^c8+lHt*N>E{k+acZxKMfV5Hq(%s!H z-AjYCq;!Y0bax}&-QC^1`~2R|_Yc^exo57Kx#FC2z3JDii_=3OH?b}pBa7Ny@hOft zt00px?>mSblCxP<`Qy#tX7{Tvp7Lx=Tw(*ih$pqRmI1>M&qT__iph^l0y5Py_!ZJ^ z*)@-I`w1@*BU0bZ=`_nmH5DHa&wF%9>>_q*ns6$G6&+jkm(CKK&JHa+!YdC;6lG0l z^bkRqHAry6uKQO57KmJi*nC)*owZ9L^3nm@?sML^9Gt6aOoA`cWCB^iEn)L}gkTKs zBpUCcU|`IXTkfa+#}8Wts`zV48l-ZM!w46JXaTVqQrLKoQ~NmaSP-b#UYXjBK?dUb zGeSy5Rn0pw=1?J+M-O|7`T$$jn4f>%t{vjP(N@L>YfQLYVQM-eP48-MwmhaTk8sZy z3*zV4Xrk+e1h0UFF7=Pqtu9m|FP3@@uD#(Ss!qkU4@5_6`GlSHARZ1XDE2CkaBtbFZb!sRe8en=;%DqjZ>ZZYI@nT$T z5PmU;ILcyI?`C9Dx@Xqrr(wZ$39dA-#=TI{GeAc|HQBMiR| z_M~OHU1_t>jSR%~9hY`XO#ggYr0__1$}6?x$`T^muJt`zm=YO6@F&{$;V6@bKm+0S zu)CMfRlseHQY6KkKUVs=PT&1ED3Uz4lL{fnL-a$CIK>-fr%ah^T1kAcyQMOoT^}wAT{?BQwgS*ha zw^9FEuS?@}1d_Qls)}&1yH#0M|E@FBkvlstDE64VCz3mU6m@b>B zJFn|o=ei-38-(TfJPn2`(nRz;*VnX{w4fMrY6)DpHlqQtu_c$9k>`%2rX9J||6h0_ zCkQ6P2QDYZS#{%0+mb?MXILSPf65>;js|cxKkfeY#lodr1&ly$Zp<4joz; z%h~;au?_XOz~!CvgmfNtIN@Wuw7WmcuCN-W1n1pB-rMtgO{#f$)t$yNFG2}G3u_qt z6Sn?QW7$TzQ-uElj&CC-?0X5~Lsg{WtIu+(?8LQ63Tm&ZGimu+>XM?jMn|T~gBNrI zLp%prNAv@+HPxtmYi?8<3-aFW0#6^a$$yX($(mNY-&eK^7KR`Hj-xk<0V@^$dTwCV zkxrP=O--pDi^~Bu&9cWapprdTkf2~*)c{_i}-~t_Pro{ECAU;ASf`k`C-ws zdFJuVEu+sD+`l~=3JPZ*SYENj0fO_SZpllbZej#$;WPlpP18?y?_sR_QsH>ls_-4| zH=0fBh^VR7esg~?6axwxMJt$GX7#NfxPAd+1bK7y9kz*dpfZ;B%8PtNBOK)?zEs`Llrg^YS;aP*{U4cM4xqd_{!^ z8{+}EHURg|eE*H&T%9g^?A zYH(x&W6fHrfh`%Mjsgz7BW3YkR}N6;oJza3klQ}AQ95;<2G&UHPhX{JHOG5XkA086Y~zvXR}<64jRN*T{B+u@+5`gSB4l8 zv!sPk{JKN~7ycvdksxQh_IJ$Ptjk^mW7|*lW2>s$yu32Jk*xWum4~#DN&zo|>tw-q zPxG-)^U3PW)A(=t?nv2^%f)bjXDWTS3^x0jDH@ZcIvTMd!uv_P|Lj?!&A?G7B2|@^ zc%9L{%a^Db!IRJT@v3yD(~SSA*}H)6szlrCSq-=QQ2+D?r+Yx>Tp&;C8`sZ*EH^IF z5I!eVozKc>US9hSP;!JwyqBY<9_zq?w9cz#*t6Nd)@cs)xvg;_SX|(Q2e+nc~g7Ym1cw(_JrGDg|8pg0VO#w944#@-Hn zg`$6n7DR9W^8AaaDD%O#<*`;4mzIRZvxtd$N%$4^!J)Jhm={yP+&vo31aOqC;&Ss! z3yzrNs;&dJ+EjOa=ss)TYAa85zANamO$4-|OqbCCLF5VKbIQKuI%T!jcODMJTcSU? zZ*IxFi?1rgIfo_MC&5BVjwC#-_L2)!0h~pxyamkmGWi#%7VZ`wZ$?t(^(N|tz*6uIfL1P`lU%Y z;5@39pB0GgH*}8QTw0ikJiMW3A zqCJR=0&(QLp8tDyUHe_U?uj6D|Hy#G10Xt1+nqMQzU9vx5auNa!u zznp$%;DsU-<)PvEBvXxC1$F2emLfs3#J3P`6E;(aRDV5cngxT^xe1iL)9TftXq!%= zLYN3*VEZ5hTot&uYOf93mvFIcMwy8=^e?M7f@;F6MlZBVMImlLu9xjr({7eOPO7HF0OrcLH6xyvwF{RK?if~Z?q$+uX`qs z=BtqjbPUI;;9mHqWl!D?Cw!N})+NO3iJazS6*K$Kvqm2>yj5Ns5<3&W%(BKzY5ZGo z=8bJ=EOs9HbjA!O!v&iDvg;|=d@!3qif?t;ms3R*8r-9$cIDX$=A1p(!7^U=Qvlw^H0=FVE!p~I+#;mbCt*vTa z84(tL;G|ia%p>50+4*+w@2ZLSN&JH4X=fwKUzpk`EB^~N4gNC;?_tr!QRBg}`QHar zk})ihRMF?|Jv-8L`jz4ClcCEk^S1a63T>+5z!;ehw)LU6_E}uW0CV#xO2szHySM?~ zp=ksqNYsn-Yvf{Y&cb^{o#YIQ->V%`2#nGIssMe|qHZYbbatGh`2=&^zqFOFu7?TV zoMrI+jk+BneC{~&u&9!FFn7I5wi7%VbNjtrrY3`6n82Za@kxqMp?tdG;Ocn$NX%vN zkM%35|N4M2EK9V)0911)n&>ydf1ZeArnO7N5`odaJp!w^=xQ)`mW{@wy)6{U#ohw^ zT@5aDbZ6xl5&DERp)h)iZzJ|uA)uxV{j!Lh*R+!wbbENfT~p2rO7|5$F&*DlTiF-S zvwT(bdwpp^b)Q{UywzGq0Si%ITBCD5(rczyF^?W;t*q-XPSeeTl zR$!r3Iq%LAyrqqstdef}&t>K0L2rSqilZAd`Pu?s+fxKVPc0KF zxOz)|O!w=jD0Yp1CRG+RNbOPezM($e@>g~S`y0Z5JjJgUWJL0S7S3R61G9?jeki2& z@d8T@rcdPpqgWn{3^SIGX##xCYOVWq3aJfEBuxbHNpyfpHI|?Rvdi&b1`#9iKUwm` zq$;XUvD32?K0w*?DXR~WQrc5agUP)}Ht@#hKGQ9G>S zb&eO~jQ&qqR0gjxSBuLpp|4OOvk5RFgC1Ou43-EyJc?gSj^EE_PNfnxIVGVlq8%%H zq`9-0zoMg8IGtPyQcr&a8HI6i%paSAZ@0hnFL{jIr&WD?ZE=tSiFs=?tiFg+w#w~x ze+K#TwM$o?wJRfSJPrA)HxzF^WebtLeqoV8AHthR3^ziLP)Y<-#4)$=NhaNkU@vZ2 z%ovUG!bsj{k$hYwgbv$`fGrVd3<6b8xa3kXxXV6Snv-Yu8@jEzqr>R(DU9y(`4z>= zYe+-!&ExK!T~4pdTH9%lT3WFnr^Da);8VfO<|*EQZCxGK>U4pSfygUg2$b4fL060t zwodfFEwVDo@BsHTxU~{2Kwbsi=8sZr_3!hx8%%^N4AVo+q`!1r8LH42ALV|b2QClQT zi9y#W>np#LyGO}L|9#LN$gpz50M#KwgQ|c(xmZ<^?R_i$OQkW5H%!p4_n~Nb&#Ca4 z){tr%<)^vvAz+jSsQ!+CtoPWQ;yQnZsMbaDRC=uyUtLcC=d3y9@!}%#d-^RF1zW)H z<2y~Bcjvn34(D924I$aT3c?$0Gah0B^d4No_bH>R*tNgkyaA2z2DCiAO@p^9`%sWk z2Zh3x$(d+v!hL%I|HIU%CMMh`YZ}lSy-_lHI@*V-CoxX*8{VOCs0?e$XS0~*ss z3#-=_zqQst8E!PYZiB5$?7ZQKcXXhaMe<`|x(|iF6NUvzQI~iX7eBwUEY1;C=1;)iC7YS1~w^@jBnIr)jKwnjD`u9Ib@NJ*gRXg~?)R$dj=V zjs?|pbSANT=W{dn7u4xtt!?LSYA7h|m}ZIvJCFTB9HWBSS|2_NYoDmAT@#|gMb}+n zdEB5HHl-e~|NIc{bC&tke#6kbI$uk)=yR%<)R@`Ay*jQ5%8&w5uSSQ3uZL@wmPv8F z2iWk#pyXKpG(YBPrvD3QDA1%T{CDG1f+lF?s`-MU+IH#FfceZ=Jk4uj$~aky3`u9s z@Di@4CXPgbnhaZUJB%)nKs9d$W1W>YUx_qjM_O4F0-Aol2_t9kC1Q8pw6ZPqk)>Hv z0af6SSMO!=>6xIvfY6`0Jq-S6km10|c^@+Cuyw;*PQCu=?N4zTxIHQDeW!WSVCcR_ z3Q@#!#1wQ&1je!vakHN8-`Y8 z4jR(g^_ZJpzSAjo+I_lE_z85j?Y7j9HQvcJQmYlRw`yABDQnZ>-70^LfXk%7H|;pa<2(?si%$tBw<^7P+CuH?^3W?4(hvVaxoobu zZatq@yf!*qsf+kMeO2aZDGioJlfePC^5K1##MH6qa=6T|HB=rMeObk;{^ysFNT0~e zD2K00{%@I^=GQBXZKZN7Nxm}BG3NE@z&c}V2xI0wQ+{Q}D~EI!*7`($?^YW=KcpZj~cfl^!Tz({eb1s~_Xm!sZAClKke^gqQ#lPbQEx zC31fVQ|i=DegTTFPcREuD-H2>v5s!?Nn$!W+S#yuk*Z?bx^>?V8jb3>R7MubV6-iG zY5oFS;r>dQ$Y-Cm0I%J6U0C}lZ!$(Stjy1*;`gJ|J#rhe z))J*Vp56|hSt%9h^v#t&ue{1$zvBu7o2CGzZu#4xMiq@7L2mqcr2i5<<@`R%cOiy|sbRAN7 zR$VeG7SiACgQK`%kn zYsI$pQm#3J?4~tPt3xi5r*Y^0anFSxn*Stc{LCR2;@tDzNiaeGX()L6JtN~87C+`8 zK5FbvUWo3VG>~e9V;b~~A8aox9lq&9y0+(rZ1cT+101fUMIWK2jE<2Y5xw+lUSI?l zn7CucOF9-)dbM@`#_eHbf}pSCj>$ObFSzAzifz{f5Y*v3TjJg?=JmK%no`ZEDuKZL z%EH}3y{T>g4rN4MiDxA?F=pCR+|>}-C{W9#jwh}dXKID^9vwO)LzpdPtVPcfR&PxBIKNb}M%5qw@b8M#@X zdbwr+WLnWfF!g8ev!0qSsq4$hzUlR84fMy<>Wp@G3o>lQq!gbed_dyia+!No%1HeT zw%hgIpZTYJmP}2^QBeL3M~&+HQiR9ou8(uiH*E*cT+Z|_Fmu(Dd6OLW`)Omi%eCB; zV%q1e;I)Y`D+a!gb6`QDRXhvx-zpbp)gtta`e~)t2ns-^_pM>j^M1$Kj+6byELUH} zMt<+X$>A!GU#Sm+s<>^j0^QriEHA0H`;72DVo1B&7c12gz~y;NTxT^MZqRNlo)a5`bBW#(n$E z6{gM2X6Vy}j{fk5jdw)Ns}oZ12rom#!w}d7Z$8UEhwLTU%N7$5&Z(ze2H)>jEmV3% z7|YCJ`R-uC_FT=Ep5&iuS({VcgQx>IlT-Q~8+-cW#`8#LgtYDa72f3~`+1n>uWtmZ|{Ymwkb3QI9?ZgEp&XIu}D%g3oMKDyz>YH>REpJ z>?A`@{Ow~(+AA}Fg9yZ@SlDT6HxOA-Vk*#WBAu20p(UIt%QiGOC2MtxY^ixUZmST< z@x%6$rh1OlQCUsplOv`YQv=)J0}CRRf$-66Hi>b^d$uSMfos;Y zfxnZKc)pFPfakQZJPs`O|7zgkZL70S!LCB1|E|Ip?_YPu8gGm3tI3(?5i;3ZyOZZv z(mS|aJX7!T$i%_bNIq>Ug@(1NjCFYPB)msH3>jB)EDnZ^(GvtF(hXvZh~F?`0nNv+ zF@lD(r!7LctRm796xxeS|IH_Pmb%v9EGk|>G!3=!tU#RxZ7PHvD!p&8xI#IiixGKSJePFJB<%hpp>n{6c$HZj%WQ%!BcL z)Lh55*va_#ya*trl_5YgVuqSb({^&=`IK&5~iQ44c={`G!8d3L<3k`AyVk ziU^n84?=HH#roPW;kp8EPd=Po$hvs<4meN3gq;AbMx1Bbrbch$-xD?FCzI3vXzf&~ zxK7h#I<5a%uf{nqfY@Rk;)?6krr=Lf5u(XZaRfh90Aop(DeyhX`l_#bu8)40_VZgb zDsypK+!q?w9;?d66Q2$l^nQdw(o)YyURPgu6oGIaiip*nUN6A&b2JO$t{DHS|7#w; zp;P2A?zJdHMqCIVtT&-@Rh1G4e|b4=NiSVSImQ@3x|GV|=y)Y}@VnWzNr8yw&;MSHmeQF3 zo;O0ZgnHdKp!`x7s(`=$!vdT&I&0E5$i@5AHG}%|Gl@pI%=`Cgs!xC zQ#Jt{9e9RPAz3T#H%GR z0wiF}4*bua=+G1h6lN1z0oq(54zjugL**pr=6k+coL{WS3l9sUN?| zI!RZeN9tUz`r|nf^tQg-*S0M=l2jxN5gV@EAcbzs`hVrW{kE5|mA=4}4rPI~tBBZp zkfjQmmsfY5Qz}Fiz-mz58XsOas*dmbw7!_xvcFkM%t6&vE@O!v<1glSN9fYd$PYmw z@g|6d%_;$gcEU3D8;+4b>&&FLADEWm6SZ?@2{KlZn)Omfl#Q2&-uvnD@>(WsiVP*b z8LB%j>{Zo1ce|^LK*X66zyB+BbA`*v*1Obf7zE3QNW*m50)ep`uV06EP_*NfTrulG^N+|s@qp(xel zY3|It*R1bYEX=$&R_`zUQt5zt@07UVhy&1J(#e1@UnfxYB&yRtWwpBD+q3t4(*Fauz~v!@7UV+hLQ7A=1?@= zvmy<&^g@>W>8zVGajQF*ZIRDmzM>5s8x0qOF z5YRFr6bXSXT4M0=GO{R#c%4gog91ESvzd`Lli<_)W!cS`%N+}NxBhr8=dDX6cN<+F&A{V#PYc12X~NDOp8|zq~3QfVkU; z%E#rQwje=ceM3-7sunJzRO{AvQmyZo3`7LD#9MC9g$J1=rgtq;TPc@f?i^eBBLI$u z??oW2I}DgoJ~XV(z^;X=TvyjOjb62kdaM_}q~&Kfl$LtG#loTR5LOyvM?$r_|q?_(#XH#4x`C#Q>+IuOh)X%xYctqfdAl$r$!%+R{NC-lzDg+ z?eK;=lM&{uB30x7Wl8l?+3^4iORgQ3o)|v6-4B?%RB7Io@)1^B*K+{w+!tCT4e;-Ck4;@otVR@m)3-?yi2w;y>bSudhCUXavF@jb`{i}IzC7V#Y#|*W! zUCCUQJLq3{#ZRkF*r6ksA>**hL(ok}Ml_)7or;nZUVRV*ffo2A(+j9#kHL_3V3>-L zKXa;*x=itewmJe@txbqQ8&tjCLV~EOX{p{94OSH(z~w>$a!ewhW~f2SNKh%4Y(d*Z zpT`E&$9=4%caK|LAQnj+Oa1jP*nC$}d^V6um-gU_6rDr3JpLMk=ioXi_kEh=k>Eeg3BJNAbbBgK( z2wmd=tp*=p-3k7&^=wOm8*u=QGY4e0i*tSjds5Qd^+64@3gaCi^(E0GPQEucAA7?& z1c$dvWQe8?RoZRfHblB$*~}((Z7VpX6q(%b+8!t%ZDgos)!4gYwUxh(U|tU?s;jrV zaUv%zY`QNm`w|?;V@b`?fEg-npH?hc=LJ_j3K9)K(iQ7|ZUb(73rwnJ$`KbdzepzV z%r{MLrteWp>$UL8TRnf*q|X|F?v8YX^z`r2G6Y{clAJZPaPHvlXO$Qkl2gLAi~Uku z=P(Q^01r?lCYPhO+1EXkw%WM`bCJNgW|0c^sIChnEkw>YQy=VzOMo-)kCGQY@CU@( ze8qySD6%UC>eS@dta>{f4h}RR4jQB?dp+IML3=dS}KKU}W zz%?~=-YDGLZfgc%YU9vS`$DzQ;Pj=1D++1@OJskY#|hq^e;w+6OvWdwv3T!mnKSoe zUY4MVDPFm*x;(#n_Q$JKk>~hc+TAD4CBvvyC0T)b+2g}4|JOVJ=Jj5WjeD;r_v76@ z^3&JX+t`1v+K=ySPtdf}JPFvO1yb)GL*Fb!JO}8Q)t9ZSwjk?cm;N@BOipns?FT&F z=wDTtIkvQiUSHqsoO*H@or$ESmPEx~pV^Yj>|DAsS8O_+z1G-$rAQxsZA0D@*?(R( z4nbUsTJBjf?>Mrn^2-wwX&-<%G6L20ZHx&lZ9A+_0|Tgqj~_7+aWi+ujVfoUCG3*e zcP2!CTS~FniPb($o*KIf(1suq#I)CQt38?F+iMZ!l-5Kf3EG~i&w}+l;Db0@qJ8)PHD9zAgFe4?t~Gx>U969oaP%f z1Vi&NZ9{ehL;`)xBv?)CYw$IP*j?QdIBxr}2}Ft7r>_Qd91u~Xf_gqKgt(;Q4>F`o zrY~TERI$dc5utDN^;ly< z;-M$7>)?kMSAP?ys(!Mjgj>To1*jwzXD%L&TmP7i>j*t5l)$r3#r!10_==%@NJ>6& z-I8m+8_G6xY%xlg#4-x zF0L2$WX?X!;t!s(pK`}N0T&~vReGqxDcrPf4EL2#_HP^eSE9T z2$dyGl}ZzOLc%UF9R@_=C3fUYQJ-BMwLy_`cw$5njKq9_NqpeP19W`+HQ48Ci*b)Hg#d5o!D8zrIaZU ze~31-)P=vYAN8$bb*TEAfOSQw#?aG=UxIM7ky_RiFo0|3XCAkVrx{-HeOEn~S!)2p zRTQ!mV}Xq??b5X)r12DDM)p_K-PZW?l4Ln}NgHd$ay1c-0JB%et*L;mlr%^2V@n-& zIB|nMq4OSjo36w=+00b-`-Ix`cSpkmDu*@?C1Z$`I4A$9%a?!!!?y^yP26f#Q!z)*bS~s z9Kpah8U5~O;L?md=IQlGy!GOk>H40DaZDyALYho_7ZWVeT488{oZ@N7Xx}2tlPmLI z7aX~SR&5YM%_@!Bp_P^Nsorf=-@yIQA)1s6*n1cxg!N^gq zbLi;xmT!gN&Y!T{mNe%Fr9_?aa!}Z|0{XDcw&B!caq8cZ+cGj;%u&2&E2q?>2W6JN z`KJ3G_w5|ToaKkyO(B2L=*Bl4af>+JqqdRyH7AZvM>6|?r&4Dt41`Zh`v~(lTHqKu zdP3s9QBUT0pDu@--2UcJ7&Qi(kVIT7wd$iCpz5ml>x#s3l%lp(m!6NEO<9fi7kk~m zaV9a;de5Avff$YEVXDdV4)-!b>IXc!uiNcxHv%L@_jR@{K@x+yr_od81XJoahE#%TLLYzXNyy)D6bc)iS z5_U7cG~>U1qcNNoiwb^v2Y!b{AOplr8Ca!UPsH#9a{7)-5k6i3q;T_9vb`t{WnnI( zoE`7f&4}UA=ChmIY9vXunH3}U^2EXqf^W{+=)=A0bDP*AZtl1&@CHslVzH&doHD}Z z`BrDq&#AKJ(+Hr_kYApZTs;{1{4-Ko+#&4qY3b@r1e|tJUi!}bP0=Dy-jDiLiwhM# z@B_f5gIY15ogsJ3Ot!H%TM!`k7{2Q29(nmC~r|y;uA-RlzJcptm;XusH<^ zlav=heeFF$Um|fqQ9m7lh@M)3VPF@cxc868r!5X|>HcsauN@JYE4V78Hghlt*KBBqVpgyS(z@?#*L+)xPl-BI6Vcd!C@S&)1!cTwDe&HadMJJ7%8 zKpGc2iHHzgdnXH$Ev>hY*Ddgr>wjioMZtJJ#`d0xYE8Wys5ZNq)k`cp%tia)C%CQZ z1ECTr+*=DK_neu%`i^a=(&CzA*-?>#At8HG9wgD@jF_nkb{`10eExRfpL*%H7XRvm zBWTu_^si=SfC$S@5F{K0nBBRT)}1cMqnTIJj6L@_@?dEErZknKZ$4LdnY47jV1pay z^T^;Zar(^nw+&ALMg)7$J93*RMR7!kIotwk&C(Xo;I@jqD=vi>(hjpl9e{}`&bHaO z-~ki?-mB}@yl-E(q*|Y@oA`dZ|8MA2vZ9Ok^Pq4F^8s@_c8lbMrZ>s4Y#fpm+}8#- zoQ?b0@(`n7l4ZebaY(obOqc+`y5IWr!`X(vRsj>0JSygA!TZ+Q3t#Oh+Re#Zn&dW1 zNnTa0Vp19o<6w@Ra*G=!6Vl#EGbm$W(~4M>P;HYqV#UJojQ%?4|&89PYMYbq&}}m8r_cw6Z8)A3=t$J7ZG#JDdllU6O#K_i}R=Zi}r(E zX76Kr@~Zn!uG(``c=UsrtmP-2fbmoO{#b9;E>lLDU}x#H24A6URwW&x5&jD`lD2wl zf~xusco<93QL3F9#;$NV@HW3eXy6`@%mEsiIsdWiqHooDSLjQao+nIUCgh2mVvS$P zr%yf4D%_k!<+%!%W{a~96jc2uh*9>_PZU33y+qL3vDDG}O-2wmc_n)WXB z3X?Xj|fhb+(yhBZT;P-=)*p4e1@c{%#JRZC8(ojjl52!rI^W zh1mh4Mri< z^QO0`P@=Hv41Vbek)hak3-Tc|xKnJ3Pb`nv$RH*|`y9^B6VnND64K_#fQ<;ikmSDy zy*@_L%g!)hj(ajqO~gZnN&3xwtq#e(0`)1wmFp**9jwgDQ*_>g1sjMK$g3HmyyY_^ zv%3P5h5x!)eN`lDjXl&*rV2vWVP#!Z4Qt`O>+rSI49&?f zha(JU{}o*(1*iUi4{HtpG%>JW{UV*1`9VxG#9=wa27lV+``jsa^DNs!v;!g7kZ!7V zX*U$7U_;#|V}x~Fvd!a$-eA}%46p-a01JwtB`b2EspRj9W1j&z>j2yF5PH-_2Co-W zcr8oSj_!|g?(kh1{QljcwoU;#?qoG~3Yr3Is-GWSzL@=G&DAIwgk`~}Dmm20>_a8aK!@@2 zOQtV;uk-qhB%Xg6m99R7d}AuoxXPRSov|dAF6}IlosGw|^o-(B8KJ3y{ni{ENQ#Ah%ch%Q|FVCn#N6 zj^xYwfznaAf&U_#;^Zf8Je$5It+SaVx#O`tm;`XfFbEC~=nzk_oH}Je=7`ssCu0(G zJF{drnlapeY^0Wo@jKTk4vI@~P7Z?)*r4P%I zyFV5_3B?Z^@G%;vlSlLm9lwPV`1p_}Kji;`CiQt?FxT5L6WL{j*pj6sA5ATs^Lv@sWt(H-)wD0s9;<%WV%X%% z2BAj)r{SV&G=wE#fkr`tNs?v+m zo>LLI{h)oYG=t`xwZ}Go>-%mbyx%)u?rb%!S3aRkQLd;15QlZF>(edt9W2Wh`q4tKp8kyF9ZYC);}sn!ESkv8i5zpCd^A4b8N z-W5=F4ouL^>SD5oy~a%b$10*!8_^IE*8M38#Z@0R;_D=p zc=fGe>9fd@wppMK!a;>Y1L@b~OE&WoFH`LT(hg$dpo<%CE7@>DPE`i0&2^$rE^+}H z_QoL%8-r?vXK|m-7JiHcf0!CTxqNFK+`pB;Hf_`I3*JIU)VGZa#}jCy{nBP?Tumcm zQH%j5V+J_7ZH*11Oh4q^;}P;q(nAG)mNn>@!B`y#8`<~#(yXE%RF;>#uNGuHtZT~N zf@h}Gy10}tC<&FBm}Y`|U<^Ws8nC&W%FKC^azy#BFH?%B3(_=75KBJ{7p55mjQfvs z%1o8ov?{}gL?H>@9R@v_M)ZfhYNhE<&H=2(Az!$x<1^;8yTr(?i19oHcY(|eYjiv7=%0r~wcolC$X~;e{QN}lj5el(aQYA&G9Nzn zJ}E;!f{nU zIu}$-#(yz=RaQWq>V})++n*ku|I14ngTj}M>hV#vp-IUgahhRd-cqFLb8r$xT^0G` zL#Lk8iUaAtre#GZqiMze#J0w!9_p7Tw#cQ{UXY87Pxtt0FvIZ@Z_wV)N0lBEK~Yv= z@;FRCD~WP?)|h;1V*J4XxzwjSJjpf9d}#Uf8v#5Bc`8|CW{Qj(vD(E9B#_(fa^YgOQWrd2`xZ)S=AnYYurEXw2l?pf^aXO;Q!n(A_=41{tFZHB zpWTsuq3*>k53{1R-@B(*(q?PiokS-Gx)z!F6+$m{reC}W{c{wM%yr-#>ygBMUTA|jz*ZQb5U&%2=e!T{6q z=rrD16sub0YfcE3S&WTtU35NVCFdqu%Zzaz+f^f-8R>uHCO#A9>WqrE7ek7$4k?Dt%j@&E`On1B#TYYxyMZdJMSnO`%?-c2J1JX78mw-4_o~Tx3*yo zDVJ6U0UvmiuD{aCK@UdpI3oUs1)$Nr5uX)ueV%0LOdKW{#VE%CQY_haMwSN^ z2|pdo5yAUKB!0NK)A}#iV);_hpRs;BE1o=)N87=U4c^Tb6P!h465}`?s-`Vt*?prT zd6eu`;~M`D_v3SNh@c$wkCATehnd8d+d;RdWR7IWqKKbkgIN0^th#bVjgUtv6}Gm2 z%}25oK1*d@jE6 zr)Zc2%P}C2(v5uvYJ)@APM?75T{1lZo(~apvTn}3DR|2lo>!VG`m%$C+d=sAXFL8i zy>9%4Y4KQeUw2?lR`%7k?`-#II`X$y7Rzs78V9t`HC9Ed!EOhN2$u753siHLf^R6n zb36|n8xV3Ec_oTACmH0pNeIK}=;J)q(og!q$@uP(aWp*eQcwR-ty3) z$H8D7d!&Q>FD9xlQQW-;;Tyd7`#NA9Si)HzT3vJDAL#5^|J9G}Hs80T>8Fq-dBW-p zxq$g@ux`&?sQPHNxhr#K{h+|Sy&&kg?McD{ypV)PLbjltvtp%auAaFPHZA`WN+N{dbEAsy zbK-#W?v*S%>4)wix^lJEn0&zXd{k}3#Z(ujig~;S^@VVqdK~e`!_1s5${}CZH<*-P z&yBIprf{=1RH<>)8U#Lm(b*4#shtAMNOi{v<#QT&0+j_s4~KSt%XJRAsh`Jcabzxn z;adFX`@Z;9aL}S&kVl?3;~esRaFa%qTpZs0*M(W%LbP${`j~`1V;i3y- z=>x3%=@@GXDo5`?l;EwyJ zquEvN$&JTEZO-*2sxVv@W!%SxEa3J+mF2PK?diy$z7fu8e%|{Acr!u#%s*h6J_1{;b%)d zca*Lm9dgO2qXjo&pJE%+0S6AVgB0;WhCRVk8w1>GaaVj;8>0gGP>H{c%Jk=go0?(G z-Rc>eqZdA<)!)EvUdYC*OSLiHu3ENE#CIs9J@g1|o<>(uuTTBal6|@#iFQ>J)(;rL zBN&(yq#+O}GTw+v1p*xuG85=fYEw%;dI*WEpDbhcpWkqQ9M!%wC0uf?z*}^?#99*| znOaTk&o2l-Ib9K>28}QY3g1YB*F+X-RrI_0J+^skmDf>!i-Azpha;VnVbZ}^L*?N? zf$vSuTl|fqJ$!hkZVkTwsAfJWzlT(-KaZXQuVkQT$3mS(7jb{t{bMMZXbLX5n=X}=vH6Jib>65n}=1u&;R&Bj4t!%cpxSbGfK_Lh+ zGyL)S*z$Cp?LlK55?_+Pk-MVZvfg09HCwrDal=sgFv_BR>%%*thVTG|iOnnuwL8?x zwAb=f{WyNeK>mDv=*l}s9bI2{ck{587XMky)z8wvIZSQ@Q&jNUi(L-;<7czL^L&rv zX>2Y;IVI;pvhww&*nOR#hdIJpIYt-DLwRt~y0nK2w>TE|3f=8~t8kB! z@tT9#>9KrtIaT|Hr;+xL)YljsqBZ7_btmFvz&#mDj#I9-8B(i1A;y*%G^*H6%BI~pXU z+;D~a;dq3E6w!T-t(sX~a*ic4k23id&eovs>B41DU@ss=O6gzX_K<$b=z{Jrysmbp zxDmNOvYHUzp#)T0g~`7~`}@Hh4}Ti8NOPZ`X?i3!Y5uQt?-8jOw$OhaLdH>QND|riYuf+9 z<ur1OQ#Xt;fj6IoT|)dlCc`$=c%yor=V{%I{AL6TBtLCcO`Ec>qjk2T z@3Xb}E~K)1i6X3{3=LI1(EUx!bju1_$Tmk4ObtWw?2!;}Xg!^wbE7WF#?A9~n?u9n z!Z1BAjk~yrNMnQeeiGmN+O>0to^rA+fTknJ{lFg5qMkoAe@R4Fty+(<&?=r4E-Ktbf|Fxn!rXo1(w|F&Lj}GPCc+95 z&!imMaGS?F^~HF%q}l*QR`a&!WbKfXS+n7A`W|!U8vz!53QS6q0ev$*21|!vpX3*J zx$k(cDKwB~&9Bf&LeSH`qt&3+FRYt2$)D8~!w`f2f|F3YB@68?B1$8flfwl#t(<%d z13HQT&F`NrQlor%47J~ zQKwU#=ba117i~%#);eY&sBrby87azN_f2VMjJ20LzL@7K6@+jNa58l`?oFuGOS*H1 z)hg(AubS7I6+k1lpQm>XIBq|syE#eTHd^9#HAT=3;s0EFTFj>qqUWRLyuXWGtM z9ZdOH(>#ce4#~#j$%un}$99KgI8_(54@~(#G-V%?>@}3R@j~5d&g)av47tJu7z#fE z81w`crsF?}Z{Bb;R9klYk2Bp&7nW0E;=O7H$f-{#5j3vF9}8a9W@()cZzJa)n6u1!;9l))O=g!gm{ z$|{qhV6k(h{3>SmJ%kUbQlFdCL~jnYJsHiAuAl;lPCbGw0zp1LHnuj?+DkP4lxOz@ z%OheiVuV9rXJgQ z3KC+93vV?p9?m`(9(h-0K>D>7M!{bebk<7_Do@c$AJ@=rEL*s1?~N^MYI`~^N8R`G zB8;G2sjC-CYeVsJo9Nk3Gqn^+hJ)>%zd3?sW zrC>|BAhz|eiF-kxQ-sJmkum`q^eR#|6otQ?JvqzZ9ABT+j?=?Qf6@b`%q|VK zy^~#d4EuLy&e*pcW4k5H4Y087#khXVo%4MOV34235#Nd9{58a5=Nt-e0gM2|tSZZ% zbMH^Lgy%IS`-ZkW6N@&`2Mod_8(M<+?PPNZ+57EpINhmvx!J#@4!I-aeF>s0r}lU4 z9{%Jqbd#s%^0(1dh)Ck|IshRZrGpkh5!=~$NI(>BYTAmMgV;Rd{@I@s&xnG~zfQ#H z#SKX>KM!XmtvN{~tBkRPoBoHCrGsWd5j5E|D%r!a)m^e}5?%D8ra@-mfWe#hDKYH_ z)^SNp%|Fy3fiCfJK;}!4|De5zI06Jt)=ye`rx_<{Zx`vQp!SsJU4Qzi2uS)Rdt;Hd z62Hp!uQ8nMkxgkk0re1wIDq8h&LW8~x&Et!ZoNqpJz6^v{6v4QU0?bU3iQ%1%LYe4 zt9ypQYn7>mK3NcUZ4vpiUWphS#B&DT9{l#rcCd-x@E(aM7M7UV816|IP+t)&A5^?$ zX>)GYqMR|t_JxS!+25Xz(_$!#P3#cT6}bDC*XaEE^E|{%A;Ylh9Z0(}MWOg=-o~^< zXLmU{e(=)K)r|k4ISa$4`rf+WZaF73G~baqyzb17RZNE{2_-p0+Zm1yEFDQwhZC>t zcSD}&pb4?*sKK+59^v>HcHz2{1vg@-ZAIj~!aLv|Tc=c`l(@oM3x(*)xju^DU)G{m zs&gqrtl0V`!78j1EYS!#inLHAZwQWGlgP+=b`9>7eyY_92*ymO`B5KB3^M1N{_Tcn zcF~8pqx%&=A2UD-4!9X7VTBm-@6#CX^3p3C}r6{ zsW)PlfBg2LsxZ(+8i+`8BYzh=#Wwlb_|OMY`7xcS>QiA13?ri0C~MAjG=Y5-K1ALH z3h$Za>I5-D(W7oKb$ClHpX1*EYIS*W8>g}F^p$WtfR)e7-j&*1S-try5r2LwMO|X2 zTm>ri(@+C+nsH zM!oFU0E_kmhLA;}_@!8?ct$_=h=}z{S5O^# zXX33)12oZR7Oj0!o-`>>BPo`iSuz$V@sg2F!hNJao(jL8Pycnn+C~*~soWmj2DPph?Yq}<@nSMwMz z-pXhGd8_R=y6frBfmvBm(`sm_z#ad_qx-q(8(G}up?8~yPk9C;e* zPFd7h2wcL)^t81B-R=2%tXn&&Mx6vqU0yX1qf zf{=`S`Tebm+CRC-z5e1dS+nO)AaJj2Ct*OFN1ex2KW%3K0WvOJ#f0-2=kENCHir>P zI!;>Q!f$%8T4)&e|lBd%SbP zt$IL^+7_PrSL%&SVyAck&&qSjYW^w))!hr(jB0GCW_QnJHog2cNDu=f+}V2U z>rlupE5M8%419krc)2Ri#{nnrYc;1wkf-!vNT$eZS1MCI`StZ>Qp$zDzcV_E#Hf*w zqQ@=|@)ERJA1TB|uyvZ%Bh=L=S$LUzpb4q`ryeI8nD~vRf#%osWP*1-0Z|JL`x0Qz z{`2W3R$>Qa!rbgEH8S;!F!-De9xh8T#2Mw0mB}7VswK8+8#ccl5y-n)P;v=$~g)cPZSqp>G;s@oE zd~9RQ>yjtg-^_q@6Dg9Q=+`#&o4D9I@C!d6zu8B0rhO$hb<=M z)4IHK7V^ouQlvsN_O}1Nbx^h)0#=cJzj6FYxMpjdknOLLB-PL+GIAqvO6OaNL}6Ge z|9oFU%MIDO7u84avV^u*>wVvZ(JiX0kix*KcFLSqCTAK`h$^1;zEK-J&=|eZT56MF zo&AG?LnLXbvW<~Z#R7R#R%r}h_*INCE?&ZV;{6IEU$9|()1n}BG~oK|rx1|*sCmDV z7K>8~swZmiiUXY64vQGms0?(Sd}Bn{`YUEnje?YGn`bIamwLPGdQpo}!#`?eQ}t)~z!ABvmu6jvtL6{Ov{wK`ySg+HY^yiFIr1#c z(I>U%-ScU&gd9i+wav)-jw|cM&fL-q-Bk(Ww_9hC(c90|Wd7P>_me2fu=>bXBp(g>s%(CzCkv37 z<#e8H9vB)<$=ZmT9Xc`DS?n$Z2Fk2rvUQ|cGD~_j5SI|eP=*)ywCPs{3!UbFmKQvc zwBn8K`Qn^9h7@2oAjZqHM7B^;_7pzTOVu2 zDrcp2n|r=LjuT6*rWWF{kkWqT$C0(>^dT^rpyDL}gb;htS3)5Mi+T}DFD~sZFW2t7NI!pgEM2lWBMdae zjgza$<4tRh?z&5yM^>DfAamT82h*vaipu8@5zxbwBe-~vV0Kq**|DFy+cYWt8?KSTD|+zEV&VW(w6k*nk4%2{%kD(?5XjA-Ts>k&8+iHHhv za+PBk_8XmCfO9zlYaIWU^cZ{lKoI5)Y6s!``j!zd7-QoGlXgaEmc$&Z8`SWOj@7v0 z!E^jcdW1I!7+HmWa$;O>L)1<5&@V2jAanPj4L7BJ9wr~KQN~gC1|r6PJ`E-pDL%E= zoNnnxzM`fjuCh|z^A&)$Ehp2e6@lIPQDj9nlM#7pZ>C}G#5DaF(II+Etw?cqLIF%? z!Q0z)5iscbqlEC~?3Wc5ygknt>#J<}Co&naw!fCNMdqJNU)3YLPH=OxAPpvXnn)Z) z+1om-tWZ6VL&(wBAEKq+KdY>^YZ%K>h;LUIuP(zU z`C(E*u0Jr}Ij;yG=*;S-Pd_qd-j`usIgT@Kw2TosGfWT_pFIbueEuNDd8{sW=9kZQ z*HT+@VzN!i0KdWn>=S=7%3gDYLyWUf%E~G^g=)h0U5G2k-Pc^L>gmr)4DoYRGJ7K@ z0(xiby#^WL9g~wda9OwJ1%PM1*)Wzl;VmO0XFm^|8}`}d+#4H>M<95P{z71oiQ~&u z%JxDam^Zv}Yf1%}I1S-AtEaPDSIB{RN9m!&R|DE0l>H*t-CJ+6!H$vReBjcKAuP?u!TFif!DUUe zlUiDesViIhh|G=tD*~Bl0^~|OFG)JxwK~Y3EST;#%ZY1-VJ4~gfFHJTR+Z}N(m0m)3jLq_dFl4=);-pcNphMZTWReQqdwTIHKl3BeRs&1aKjFr*EjOi zYdy4-i*akLkVBuDIA-mS%c*CRAzO(yDAdJpb2iwamI}p}w_U_TK2L@5SokD`w5UA3 z%$+4rqOr3$Y;j#%v@JSBS+e78@u`%;UF&G45|Cx5Ob2#oSJ<3&G0gBX2sEC@O8TgS z$@{Imdj&|JNC83FWI?U_H?%1a14B5Zxp+isvamJdg`yTUdKfShI1&L+ z+TG@5ah1=wa$9YylD^u0Z>YUDA@Yh>V11{GQ0hl~4SlxXNYv~N(4Ax4Z!~7?dEvsy zQ)U{iE0wZJIsr&P*1S+3zOy2i&rhbV3tFpcqGH`)r zPof2$jT&{aEH#02>9mI@=}rcN-231@9apW#t>r!HIR*z{J~1x;P{BJ!keu3n@+J<* z;YX#6RA+_^n1;?>1~%=*pVGGl<)V9 z3qL}ys`lqLf=`KT#7Tb)JM-ud`XPv`ge{DnlWh8#U7A>%xW@U_t)qxNi~I9~+& z<9wk<#BfQdDWfEGUc43BCc@EPD@3plAe`1~G|Rxt4rl#Vdg{qP(SLS(S879PnJqk9 zBn?MXJeY?oo;#jQXoj>(C_=^!;61TkY&dWm~+Yp%Dn27NreDBNPdoO@NB4Bzz92`mmF6fKmzZH0OwaXN)t%8i#Q z{p-(s8LP%PNc%0^1&0PCZZ4K%Uy^U0o*g%uOlW_OWb1GD<{dbReplEoOI2fc&(l=p^!AvMX%$k(g;RPJ zW@ttrnv&0SV-s0c6Hr!_eXASsM{tj4>{~&BfaGRxc-4w{ADh&Ib0vanwAi( z_s>i2$!q&EzOy~}ZQ(4W?c0j@GDx4qV!z#H#3}c^y@lx=yE&?>`m1(h4vpSC;_P{; z^#~Y5^JPTf(?i2Xix&*-4qEf#2-knhgix<}asBxrjTYGDB#7Pe^7I=-o`D2CHMDM>Xf3F9x>MpjhXSd>~~G+=a_i@$n~HCSk5Z@XFP8JbEC(hnmFtSE(?1Lc{eODn=9rhl9Jq5tQJ{_2v~D5zz0Cp`P{?(Rm2%|FYZvfu_(*t|dF; TImE@Y|IJX}Os`JIHSzxe8$@x- literal 0 HcmV?d00001 diff --git a/assets/images/macos_icons/monero_macos_icons/monero_macos_64.png b/assets/images/macos_icons/monero_macos_icons/monero_macos_64.png new file mode 100644 index 0000000000000000000000000000000000000000..74aa4e2ade5501e71e4dfa2b1356c4ab745bc25c GIT binary patch literal 2700 zcmV;73Ul>|P)PxB&y`cwo*(;cXGj7#72z`dkx4MKXd-AmdQC~fBB4%5&J zml$8j0Terds0jLV3ID^?H1gc$si@x$Ml79#6Hw4ZA3q<27jzCdmT@chi2_}PPPE`i zIc~9{7fUu_1dMB+$X9|=bDkH72f|I!)Hv!X{0~7c6D{UGFmyE$g z$+#SFbZHj;+WM)8#e*3a0lAHIZBGy$i^qX@btie0Zyuke{@X5&Edn^_$m0#Q2XtOw z*Ki{BvN3GzsU%D7U|J^N@#EaN_5{1Ead6r(m@J(X2mIGxMW$HAw?u#l{^ieDpAO)# zYAD(AsS33Cs!6F;JJJNK;aqvPo(*Umh*cxWmQQuShrTK@(~cc!0$laMj-Zal*fEk! z9lI-U_#{O@-d4Jyo53TA2m}FW9tWIsE9hgliaHV3)o#WMLOK*Pjz(FjBjQU3qB&)H+Hvn`JFV z;G3MmOZJyIKe0n#VG~_?IsmVQXGJ1bUW$O*n%FNp0{l5U&W|SOsq+tcP`o3WAVW*$FQGlLKYWws76?+v$p43X6SJWLBbr7dTM~xUGq;?g;STSTQER zX653%rm3jgtXH^$K6<(z*2^An4g|E&gXSNfi5slgw<8;s0Hs!JeQSOEv@C7nM>E_f z4M%>|%JJ*H>|9WXJUh;L9B|M-7Z)RhxE*~NornY!eHfg4(2owu02nd_1g$(%fnPL! zmo@XOmOj>PmBetHDuTXJf-{?9JUy)VYL<;iKw1NB^oL-!ET~g~-as|UF|YjJx>+FJ z;0-)M0;?gZvi?|+i%5V{OLf`(DvZs@&po=|cGlAi)Mna8b3RRlmMe3u*ZQ%@ z7)HQ@M|j%iQ|wACMdLnJpodnIT;un+Ci=rO0a!17k9DCZ&jk4IWwFBL6a*|)g-ur& zd`H}ylF5tql{gRD#fzjjjDXv>2N$0hKySzzndDX;I$o~6W5}DcC!fIbq8$9b_dM&A z#T&#yz*ZOF)aN_chCU6Jh`(b5S7;5%u!=R3{4fIYwz9Xn8UMDdk*900!x&$S=ls!r z-el;G!m#Y~O7iOc`*>dM1$IFeQ>^^*9GoJ?U8!EW(I7zRSEb=m^`%G}E0)b+1bDpc z+0Y|ur$KQz0pfS{PM+`e#m)o~yjb})lMxkq;RNIp_)BL6 zc|yiN8JS@O;5r%%N%s6H3bgo5Lx}L&!N>r^k?I3Hf28dos=?(s*kc}ah7*7lxJau> zwoGs`GQ$W!wN#Y9Qf=}W7yP+nHu!JfFQ`I=)y@5E5Et`rxOhB5Ko?5BmNk->q9E>9P zg#|d}t?PS!{z0C#yNkZjQ|YV`xc?6Vq_;qUQ(1Rrjym{WAUu1_1bDpkbE-q;DuPqZ zB&0gwvJw2ER-W;8H@ldHk+-)JMa#pfgZSM$4qPjLa|sM5_8V7%!tN z4lb>R3{HvD8)&mH1cSqhTnx*)D#@z?OJsl`K>RzLga!L~=DVG&*EoF51cW~Y#yHWM zjyd=l8UJKth8IHH=-<03{6I!o$UN=Dc*sPD^Di(>ZLFC9GYNZhAnk(=)?3_(!G8S23ucQ2XBO&f9qe%4-2{$vN+HUYwz-E!HEqmgvP;Wsry|LUF+`*VW02oO$HAK)p?o$PQxhp~wY zOa><#qj!2Lv2@EG4Kr>64B*K-Sn06=?oHGTAezH&2b`$P!ZS99eTO7NS|pi-5nzB9 z@1)a?`1yP0+TE^mX1z2Oc9mx1Z*BQH62()(u7nd{cqYCq|JS+DiZ05Z4C;_?!(;Ao zz>#rI<>#NwbbJtR&7brw5G%mhtvt8APn+e_^!ZmbD0U*q)vk@qbn##2LK<|sFzm|5 zXmdrj+WPWj _sharedPrefs = Completer(); Future init() async { - polygonErc20TokensBox = await CakeHive.openBox( - "${walletInfo.name.replaceAll(" ", "_")}_${Erc20Token.polygonBoxName}"); + final boxName = "${walletInfo.name.replaceAll(" ", "_")}_ ${Erc20Token.polygonBoxName}"; + if (await CakeHive.boxExists(boxName)) { + polygonErc20TokensBox = await CakeHive.openBox(boxName); + } else { + polygonErc20TokensBox = await CakeHive.openBox(boxName.replaceAll(" ", "")); + } await walletAddresses.init(); await transactionHistory.init(); _polygonPrivateKey = await getPrivateKey( diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 3118e6ad7..2545e90ce 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -102,11 +102,11 @@ PODS: - DKImagePickerController/PhotoGallery - Flutter - Flutter (1.0.0) - - flutter_inappwebview (0.0.1): + - flutter_inappwebview_ios (0.0.1): - Flutter - - flutter_inappwebview/Core (= 0.0.1) + - flutter_inappwebview_ios/Core (= 0.0.1) - OrderedSet (~> 5.0) - - flutter_inappwebview/Core (0.0.1): + - flutter_inappwebview_ios/Core (0.0.1): - Flutter - OrderedSet (~> 5.0) - flutter_mailer (0.0.1): @@ -169,7 +169,7 @@ DEPENDENCIES: - devicelocale (from `.symlinks/plugins/devicelocale/ios`) - file_picker (from `.symlinks/plugins/file_picker/ios`) - Flutter (from `Flutter`) - - flutter_inappwebview (from `.symlinks/plugins/flutter_inappwebview/ios`) + - flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`) - flutter_mailer (from `.symlinks/plugins/flutter_mailer/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) @@ -224,8 +224,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/file_picker/ios" Flutter: :path: Flutter - flutter_inappwebview: - :path: ".symlinks/plugins/flutter_inappwebview/ios" + flutter_inappwebview_ios: + :path: ".symlinks/plugins/flutter_inappwebview_ios/ios" flutter_mailer: :path: ".symlinks/plugins/flutter_mailer/ios" flutter_secure_storage: @@ -274,29 +274,29 @@ SPEC CHECKSUMS: DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 file_picker: 15fd9539e4eb735dc54bae8c0534a7a9511a03de Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 - flutter_inappwebview: 3d32228f1304635e7c028b0d4252937730bbc6cf + flutter_inappwebview_ios: 97215cf7d4677db55df76782dbd2930c5e1c1ea0 flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83 flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0 in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d - local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605 + local_auth_ios: 1ba1475238daa33a6ffa2a29242558437be435ac MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 - path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 + path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 SDWebImage: 2aea163b50bfcb569a2726b6a754c54a4506fcf6 sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986 share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 - shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 + shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 SwiftProtobuf: 40bd808372cb8706108f22d28f8ab4a6b9bc6989 SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 uni_links: d97da20c7701486ba192624d99bffaaffcfc298a UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841 - url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b + url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812 wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47 workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6 diff --git a/lib/entities/provider_types.dart b/lib/entities/provider_types.dart index ced79eae7..a3c203960 100644 --- a/lib/entities/provider_types.dart +++ b/lib/entities/provider_types.dart @@ -74,8 +74,6 @@ class ProvidersHelper { static List getAvailableSellProviderTypes(WalletType walletType) { switch (walletType) { - case WalletType.monero: - return [ProviderType.askEachTime, ProviderType.dfx]; case WalletType.bitcoin: case WalletType.ethereum: return [ProviderType.askEachTime, ProviderType.onramper, @@ -83,6 +81,7 @@ class ProvidersHelper { case WalletType.litecoin: case WalletType.bitcoinCash: return [ProviderType.askEachTime, ProviderType.moonpaySell]; + case WalletType.monero: case WalletType.nano: case WalletType.banano: case WalletType.none: diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart index 59c31aa62..f3dd2427d 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart @@ -123,8 +123,8 @@ class _DesktopWalletSelectionDropDownState extends State Navigator.of(context).pop(false), - actionRightButton: () => Navigator.of(context).pop(true)); + actionLeftButton: () => Navigator.of(dialogContext).pop(false), + actionRightButton: () => Navigator.of(dialogContext).pop(true)); }) ?? false; diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart index 6ddd8f6e1..453adccf5 100644 --- a/lib/src/screens/dashboard/pages/balance_page.dart +++ b/lib/src/screens/dashboard/pages/balance_page.dart @@ -265,7 +265,7 @@ class BalanceRowWidget extends StatelessWidget { color: Theme.of(context).extension()!.syncedBackgroundColor, ), child: Container( - margin: const EdgeInsets.only(top: 16, left: 24, right: 24, bottom: 24), + margin: const EdgeInsets.only(top: 16, left: 24, right: 8, bottom: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -329,7 +329,7 @@ class BalanceRowWidget extends StatelessWidget { ), ), SizedBox( - width: MediaQuery.of(context).size.width * 0.18, + width: min(MediaQuery.of(context).size.width * 0.2, 100), child: Center( child: Column( children: [ @@ -337,8 +337,8 @@ class BalanceRowWidget extends StatelessWidget { ? Container( child: Image.asset( currency.iconPath!, - height: 30.0, - width: 30.0, + height: 40.0, + width: 40.0, ), ) : Container( @@ -359,7 +359,7 @@ class BalanceRowWidget extends StatelessWidget { Text( currency.title, style: TextStyle( - fontSize: 18, + fontSize: 15, fontFamily: 'Lato', fontWeight: FontWeight.w800, color: Theme.of(context).extension()!.assetTitleColor, diff --git a/lib/src/screens/restore/widgets/backup_file_button.dart b/lib/src/screens/restore/widgets/backup_file_button.dart deleted file mode 100644 index e69de29bb..000000000 diff --git a/lib/view_model/restore_from_backup_view_model.dart b/lib/view_model/restore_from_backup_view_model.dart index 403ae3ff1..365afb1fa 100644 --- a/lib/view_model/restore_from_backup_view_model.dart +++ b/lib/view_model/restore_from_backup_view_model.dart @@ -1,5 +1,7 @@ import 'dart:io'; import 'package:cake_wallet/core/execution_state.dart'; +import 'package:cake_wallet/utils/exception_handler.dart'; +import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/main.dart'; @@ -60,11 +62,17 @@ abstract class RestoreFromBackupViewModelBase with Store { }); state = ExecutedSuccessfullyState(); - } catch (e) { + } catch (e, s) { var msg = e.toString(); if (msg.toLowerCase().contains("message authentication code (mac)")) { msg = 'Incorrect backup password'; + } else { + ExceptionHandler.onError(FlutterErrorDetails( + exception: e, + stack: s, + library: this.toString(), + )); } state = FailureState(msg); diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 329732075..c158c737e 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -23,11 +23,15 @@ PODS: - FlutterMacOS - devicelocale (0.0.1): - FlutterMacOS + - flutter_inappwebview_macos (0.0.1): + - FlutterMacOS + - OrderedSet (~> 5.0) - flutter_secure_storage_macos (6.1.1): - FlutterMacOS - FlutterMacOS (1.0.0) - in_app_review (0.2.0): - FlutterMacOS + - OrderedSet (5.0.0) - package_info (0.0.1): - FlutterMacOS - package_info_plus (0.0.1): @@ -51,6 +55,7 @@ DEPENDENCIES: - cw_monero (from `Flutter/ephemeral/.symlinks/plugins/cw_monero/macos`) - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`) + - flutter_inappwebview_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos`) - flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`) @@ -64,6 +69,7 @@ DEPENDENCIES: SPEC REPOS: trunk: + - OrderedSet - ReachabilitySwift EXTERNAL SOURCES: @@ -75,6 +81,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos devicelocale: :path: Flutter/ephemeral/.symlinks/plugins/devicelocale/macos + flutter_inappwebview_macos: + :path: Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos flutter_secure_storage_macos: :path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos FlutterMacOS: @@ -101,15 +109,17 @@ SPEC CHECKSUMS: cw_monero: ec03de55a19c4a2b174ea687e0f4202edc716fa4 device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225 + flutter_inappwebview_macos: 9600c9df9fdb346aaa8933812009f8d94304203d flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0 + OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c package_info: 6eba2fd8d3371dda2d85c8db6fe97488f24b74b2 package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce - path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 + path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4 - shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 + shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269 diff --git a/macos/Runner/Configs/AppInfo.xcconfig b/macos/Runner/Configs/AppInfoBase.xcconfig similarity index 85% rename from macos/Runner/Configs/AppInfo.xcconfig rename to macos/Runner/Configs/AppInfoBase.xcconfig index 84f96bff7..aabf7b387 100644 --- a/macos/Runner/Configs/AppInfo.xcconfig +++ b/macos/Runner/Configs/AppInfoBase.xcconfig @@ -5,10 +5,10 @@ // 'flutter create' template. // The application's name. By default this is also the title of the Flutter window. -PRODUCT_NAME = Cake Wallet +PRODUCT_NAME = ${PRODUCT_NAME} // The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = com.fotolockr.cakewallet +PRODUCT_BUNDLE_IDENTIFIER = ${PRODUCT_BUNDLE_IDENTIFIER} // The copyright displayed in application information PRODUCT_COPYRIGHT = Copyright © 2022 com.fotolockr. All rights reserved. diff --git a/macos/Runner/InfoBase.plist b/macos/Runner/InfoBase.plist index 98d0ea9ee..c849a42c7 100644 --- a/macos/Runner/InfoBase.plist +++ b/macos/Runner/InfoBase.plist @@ -12,8 +12,10 @@ $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 + CFBundleDisplayName + Cake Wallet CFBundleName - $(PRODUCT_NAME) + Cake Wallet CFBundlePackageType APPL CFBundleShortVersionString diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 5feae289e..163f178f3 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.9.0" -MONERO_COM_BUILD_NUMBER=71 +MONERO_COM_VERSION="1.10.0" +MONERO_COM_BUILD_NUMBER=72 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.12.1" -CAKEWALLET_BUILD_NUMBER=188 +CAKEWALLET_VERSION="4.13.0" +CAKEWALLET_BUILD_NUMBER=189 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index ee59e837c..9920b1e54 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.9.0" -MONERO_COM_BUILD_NUMBER=69 +MONERO_COM_VERSION="1.10.0" +MONERO_COM_BUILD_NUMBER=70 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.12.1" -CAKEWALLET_BUILD_NUMBER=206 +CAKEWALLET_VERSION="4.13.0" +CAKEWALLET_BUILD_NUMBER=208 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_config.sh b/scripts/macos/app_config.sh index 2e6a945bf..cda367b9c 100755 --- a/scripts/macos/app_config.sh +++ b/scripts/macos/app_config.sh @@ -1,5 +1,6 @@ #!/bin/bash +MONERO_COM="monero.com" CAKEWALLET="cakewallet" DIR=`pwd` @@ -10,6 +11,8 @@ fi cd ../.. # go to root cp -rf ./macos/Runner/InfoBase.plist ./macos/Runner/Info.plist +/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName ${APP_MACOS_NAME}" ./macos/Runner/Info.plist +/usr/libexec/PlistBuddy -c "Set :CFBundleName ${APP_MACOS_NAME}" ./macos/Runner/Info.plist /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier ${APP_MACOS_BUNDLE_ID}" ./macos/Runner/Info.plist /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${APP_MACOS_VERSION}" ./macos/Runner/Info.plist /usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${APP_MACOS_BUILD_NUMBER}" ./macos/Runner/Info.plist @@ -17,11 +20,16 @@ cp -rf ./macos/Runner/InfoBase.plist ./macos/Runner/Info.plist # Fill entitlements Bundle ID cp -rf ./macos/Runner/DebugProfileBase.entitlements ./macos/Runner/DebugProfile.entitlements cp -rf ./macos/Runner/ReleaseBase.entitlements ./macos/Runner/Release.entitlements +cp -rf ./macos/Runner/Configs/AppInfoBase.xcconfig ./macos/Runner/Configs/AppInfo.xcconfig sed -i '' "s/\${BUNDLE_ID}/${APP_MACOS_BUNDLE_ID}/g" ./macos/Runner/DebugProfile.entitlements sed -i '' "s/\${BUNDLE_ID}/${APP_MACOS_BUNDLE_ID}/g" ./macos/Runner/Release.entitlements +sed -i '' "s/\${PRODUCT_NAME}/${APP_MACOS_NAME}/g" ./macos/Runner/Configs/AppInfo.xcconfig +sed -i '' "s/\${PRODUCT_BUNDLE_IDENTIFIER}/${APP_MACOS_BUNDLE_ID}/g" ./macos/Runner/Configs/AppInfo.xcconfig CONFIG_ARGS="" case $APP_MACOS_TYPE in + $MONERO_COM) + CONFIG_ARGS="--monero";; $CAKEWALLET) CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash";; #--haven esac @@ -31,4 +39,5 @@ flutter pub get flutter pub run tool/generate_pubspec.dart flutter pub get flutter packages pub run tool/configure.dart $CONFIG_ARGS -cd $DIR \ No newline at end of file +cd $DIR +$DIR/app_icon.sh \ No newline at end of file diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index a37d67a82..fa040dfee 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -5,18 +5,24 @@ APP_MACOS_VERSION="" APP_MACOS_BUILD_VERSION="" APP_MACOS_BUNDLE_ID="" +MONERO_COM="monero.com" CAKEWALLET="cakewallet" -TYPES=($CAKEWALLET) -APP_MACOS_TYPE=$CAKEWALLET +TYPES=($MONERO_COM $CAKEWALLET) +APP_MACOS_TYPE=$1 if [ -n "$1" ]; then APP_MACOS_TYPE=$1 fi +MONERO_COM_NAME="Monero.com" +MONERO_COM_VERSION="1.0.0" +MONERO_COM_BUILD_NUMBER=1 +MONERO_COM_BUNDLE_ID="com.cakewallet.monero" + CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.5.1" -CAKEWALLET_BUILD_NUMBER=48 +CAKEWALLET_VERSION="1.6.0" +CAKEWALLET_BUILD_NUMBER=50 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then @@ -25,6 +31,11 @@ if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then fi case $APP_MACOS_TYPE in + $MONERO_COM) + APP_MACOS_NAME=$MONERO_COM_NAME + APP_MACOS_VERSION=$MONERO_COM_VERSION + APP_MACOS_BUILD_NUMBER=$MONERO_COM_BUILD_NUMBER + APP_MACOS_BUNDLE_ID=$MONERO_COM_BUNDLE_ID;; $CAKEWALLET) APP_MACOS_NAME=$CAKEWALLET_NAME APP_MACOS_VERSION=$CAKEWALLET_VERSION diff --git a/scripts/macos/app_icon.sh b/scripts/macos/app_icon.sh new file mode 100755 index 000000000..28ca9c17b --- /dev/null +++ b/scripts/macos/app_icon.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +ICON_16_PATH="" +ICON_32_PATH="" +ICON_64_PATH="" +ICON_128_PATH="" +ICON_256_PATH="" +ICON_1024_PATH="" +DEST_DIR_PATH=`pwd`/../../macos/Runner/Assets.xcassets/AppIcon.appiconset + +case $APP_MACOS_TYPE in + "monero.com") + ICON_16_PATH=`pwd`/../../assets/images/macos_icons/monero_macos_icons/monero_macos_16.png + ICON_32_PATH=`pwd`/../../assets/images/macos_icons/monero_macos_icons/monero_macos_32.png + ICON_64_PATH=`pwd`/../../assets/images/macos_icons/monero_macos_icons/monero_macos_64.png + ICON_128_PATH=`pwd`/../../assets/images/macos_icons/monero_macos_icons/monero_macos_128.png + ICON_256_PATH=`pwd`/../../assets/images/macos_icons/monero_macos_icons/monero_macos_256.png + ICON_512_PATH=`pwd`/../../assets/images/macos_icons/monero_macos_icons/monero_macos_512.png + ICON_1024_PATH=`pwd`/../../assets/images/macos_icons/monero_macos_icons/monero_macos_1024.png;; + "cakewallet") + ICON_16_PATH=`pwd`/../../assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_16.png + ICON_32_PATH=`pwd`/../../assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_32.png + ICON_64_PATH=`pwd`/../../assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_64.png + ICON_128_PATH=`pwd`/../../assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_128.png + ICON_256_PATH=`pwd`/../../assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_256.png + ICON_512_PATH=`pwd`/../../assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_512.png + ICON_1024_PATH=`pwd`/../../assets/images/macos_icons/cakewallet_macos_icons/cakewallet_macos_1024.png;; +esac + +rm $DEST_DIR_PATH/app_icon_16.png +rm $DEST_DIR_PATH/app_icon_32.png +rm $DEST_DIR_PATH/app_icon_64.png +rm $DEST_DIR_PATH/app_icon_128.png +rm $DEST_DIR_PATH/app_icon_256.png +rm $DEST_DIR_PATH/app_icon_512.png +rm $DEST_DIR_PATH/app_icon_1024.png + +ln -s $ICON_16_PATH $DEST_DIR_PATH/app_icon_16.png +ln -s $ICON_32_PATH $DEST_DIR_PATH/app_icon_32.png +ln -s $ICON_64_PATH $DEST_DIR_PATH/app_icon_64.png +ln -s $ICON_128_PATH $DEST_DIR_PATH/app_icon_128.png +ln -s $ICON_256_PATH $DEST_DIR_PATH/app_icon_256.png +ln -s $ICON_512_PATH $DEST_DIR_PATH/app_icon_512.png +ln -s $ICON_1024_PATH $DEST_DIR_PATH/app_icon_1024.png \ No newline at end of file From 1b65adce53f93221f8117364e0f0a88875523d10 Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Thu, 18 Jan 2024 01:38:36 +0200 Subject: [PATCH 095/241] Fix typos (#1266) --- lib/core/wallet_connect/evm_chain_service.dart | 2 +- scripts/macos/build_openssl_common.sh | 2 +- tool/configure.dart | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/core/wallet_connect/evm_chain_service.dart b/lib/core/wallet_connect/evm_chain_service.dart index 81b934e08..74bff7479 100644 --- a/lib/core/wallet_connect/evm_chain_service.dart +++ b/lib/core/wallet_connect/evm_chain_service.dart @@ -253,7 +253,7 @@ class EvmChainServiceImpl implements ChainService { return result; } catch (e) { - log('An error has occured while signing transaction: ${e.toString()}'); + log('An error has occurred while signing transaction: ${e.toString()}'); bottomSheetService.queueBottomSheet( isModalDismissible: true, widget: BottomSheetMessageDisplayWidget( diff --git a/scripts/macos/build_openssl_common.sh b/scripts/macos/build_openssl_common.sh index fd07312fa..27cb1ef8c 100755 --- a/scripts/macos/build_openssl_common.sh +++ b/scripts/macos/build_openssl_common.sh @@ -10,7 +10,7 @@ OPEN_SSL_ARM_DIR_PATH="${EXTERNAL_MACOS_SOURCE_DIR}/${OPEN_SSL_ARM_DIR_NAME}" build_openssl_init_common() { DIR=$1 - # Use 1.1.1s becasue of https://github.com/openssl/openssl/issues/18720 + # Use 1.1.1s because of https://github.com/openssl/openssl/issues/18720 OPENSSL_VERSION="1.1.1s" echo "============================ OpenSSL ============================" diff --git a/tool/configure.dart b/tool/configure.dart index 3d1bccb12..9d99bf49a 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -403,10 +403,10 @@ class AssetRate { } abstract class HavenWalletDetails { - // FIX-ME: it's abstruct class + // FIX-ME: it's abstract class @observable late Account account; - // FIX-ME: it's abstruct class + // FIX-ME: it's abstract class @observable late HavenBalance balance; } From d83054eded301e6e8478bbe1eb5f98aa9ca03a0f Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Tue, 23 Jan 2024 01:53:20 +0200 Subject: [PATCH 096/241] Enable DFX for polygon wallet (#1267) --- lib/buy/dfx/dfx_buy_provider.dart | 5 +++++ lib/entities/provider_types.dart | 14 ++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/buy/dfx/dfx_buy_provider.dart b/lib/buy/dfx/dfx_buy_provider.dart index 78a5277ce..8e2d58d11 100644 --- a/lib/buy/dfx/dfx_buy_provider.dart +++ b/lib/buy/dfx/dfx_buy_provider.dart @@ -46,6 +46,8 @@ class DFXBuyProvider extends BuyProvider { return 'XMR'; case WalletType.ethereum: return 'ETH'; + case WalletType.polygon: + return 'MATIC'; default: throw Exception("WalletType is not available for DFX ${wallet.type}"); } @@ -61,6 +63,8 @@ class DFXBuyProvider extends BuyProvider { return 'Monero'; case WalletType.ethereum: return 'Ethereum'; + case WalletType.polygon: + return 'Polygon'; default: throw Exception("WalletType is not available for DFX ${wallet.type}"); } @@ -141,6 +145,7 @@ class DFXBuyProvider extends BuyProvider { String getSignature(String message) { switch (wallet.type) { case WalletType.ethereum: + case WalletType.polygon: return wallet.signMessage(message); case WalletType.monero: case WalletType.litecoin: diff --git a/lib/entities/provider_types.dart b/lib/entities/provider_types.dart index a3c203960..ed688590c 100644 --- a/lib/entities/provider_types.dart +++ b/lib/entities/provider_types.dart @@ -65,9 +65,10 @@ class ProvidersHelper { case WalletType.litecoin: case WalletType.bitcoinCash: return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood]; + case WalletType.polygon: + return [ProviderType.askEachTime, ProviderType.dfx]; case WalletType.none: case WalletType.haven: - case WalletType.polygon: return []; } } @@ -76,17 +77,22 @@ class ProvidersHelper { switch (walletType) { case WalletType.bitcoin: case WalletType.ethereum: - return [ProviderType.askEachTime, ProviderType.onramper, - ProviderType.moonpaySell, ProviderType.dfx]; + return [ + ProviderType.askEachTime, + ProviderType.onramper, + ProviderType.moonpaySell, + ProviderType.dfx, + ]; case WalletType.litecoin: case WalletType.bitcoinCash: return [ProviderType.askEachTime, ProviderType.moonpaySell]; + case WalletType.polygon: + return [ProviderType.askEachTime, ProviderType.dfx]; case WalletType.monero: case WalletType.nano: case WalletType.banano: case WalletType.none: case WalletType.haven: - case WalletType.polygon: return []; } } From efb41aa6bc71c328eda735a3139415466057c80b Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Tue, 23 Jan 2024 00:58:09 +0100 Subject: [PATCH 097/241] feat: Remove ability to create haven wallets (#1273) --- .../new_wallet/new_wallet_type_page.dart | 18 +++++++++++++++++- res/values/strings_ar.arb | 7 ++++--- res/values/strings_bg.arb | 5 +++-- res/values/strings_cs.arb | 5 +++-- res/values/strings_de.arb | 5 +++-- res/values/strings_en.arb | 5 +++-- res/values/strings_es.arb | 5 +++-- res/values/strings_fr.arb | 5 +++-- res/values/strings_ha.arb | 5 +++-- res/values/strings_hi.arb | 5 +++-- res/values/strings_hr.arb | 5 +++-- res/values/strings_id.arb | 5 +++-- res/values/strings_it.arb | 5 +++-- res/values/strings_ja.arb | 5 +++-- res/values/strings_ko.arb | 5 +++-- res/values/strings_my.arb | 5 +++-- res/values/strings_nl.arb | 5 +++-- res/values/strings_pl.arb | 5 +++-- res/values/strings_pt.arb | 5 +++-- res/values/strings_ru.arb | 5 +++-- res/values/strings_th.arb | 5 +++-- res/values/strings_tl.arb | 5 +++-- res/values/strings_tr.arb | 5 +++-- res/values/strings_uk.arb | 5 +++-- res/values/strings_ur.arb | 5 +++-- res/values/strings_yo.arb | 5 +++-- res/values/strings_zh.arb | 5 +++-- 27 files changed, 96 insertions(+), 54 deletions(-) diff --git a/lib/src/screens/new_wallet/new_wallet_type_page.dart b/lib/src/screens/new_wallet/new_wallet_type_page.dart index 225e5b82d..000310060 100644 --- a/lib/src/screens/new_wallet/new_wallet_type_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_type_page.dart @@ -1,12 +1,14 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart'; +import 'package:cake_wallet/src/screens/setup_2fa/widgets/popup_cancellable_alert.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/search_bar_widget.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/wallet_types.g.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; @@ -70,7 +72,8 @@ class WalletTypeFormState extends State { Widget build(BuildContext context) { return Center( child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), + constraints: + BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), child: Column( children: [ Padding( @@ -128,6 +131,19 @@ class WalletTypeFormState extends State { throw Exception('Wallet Type is not selected yet.'); } + if (selected == WalletType.haven) { + return await showPopUp( + context: context, + builder: (BuildContext context) { + return PopUpCancellableAlertDialog( + contentText: S.of(context).pause_wallet_creation, + actionButtonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop(), + ); + }, + ); + } + widget.onTypeSelected(context, selected!); } } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 18035bce5..8ad9ed45b 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -756,11 +756,12 @@ "dfx_option_description": "ﺎﺑﻭﺭﻭﺃ ﻲﻓ ﺕﺎﻛﺮﺸﻟﺍﻭ ﺔﺋﺰﺠﺘﻟﺍ ءﻼﻤﻌﻟ .ﻲﻓﺎﺿﺇ KYC ﻥﻭﺪﺑ ﻭﺭﻮﻳ 990 ﻰﻟﺇ ﻞﺼﻳ ﺎﻣ .ﻱﺮﺴﻳﻮﺴﻟﺍ", "polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ", "wallet_seed_legacy": "بذرة محفظة قديمة", - "default_sell_provider": " ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ", + "default_sell_provider": "ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ", "select_sell_provider_notice": ".ﻖﻴﺒﻄﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻚﺑ ﺹﺎﺨﻟﺍ ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ ﻦﻴﻴﻌﺗ ﻖﻳﺮﻃ ﻦﻋ ﺔﺷﺎﺸﻟﺍ ﻩﺬﻫ ﻲﻄﺨﺗ", "custom_drag": "مخصص (عقد وسحب)", "switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", "receivable_balance": "التوازن القادم", "confirmed_tx": "مؤكد", - "transaction_details_source_address": "عنوان المصدر" -} \ No newline at end of file + "transaction_details_source_address": "عنوان المصدر", + "pause_wallet_creation": ".ﺎﻴًﻟﺎﺣ ﺎﺘًﻗﺆﻣ ﺔﻔﻗﻮﺘﻣ Haven Wallet ءﺎﺸﻧﺇ ﻰﻠﻋ ﺓﺭﺪﻘﻟﺍ" +} diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index e2c88a45d..6f1c96af5 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -758,5 +758,6 @@ "switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)", "receivable_balance": "Баланс за вземания", "confirmed_tx": "Потвърдено", - "transaction_details_source_address": "Адрес на източника" -} \ No newline at end of file + "transaction_details_source_address": "Адрес на източника", + "pause_wallet_creation": "Възможността за създаване на Haven Wallet в момента е на пауза." +} diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 7d2e8a86f..bb63ea00a 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -758,5 +758,6 @@ "switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)", "receivable_balance": "Zůstatek pohledávek", "confirmed_tx": "Potvrzeno", - "transaction_details_source_address": "Zdrojová adresa" -} \ No newline at end of file + "transaction_details_source_address": "Zdrojová adresa", + "pause_wallet_creation": "Možnost vytvářet Haven Wallet je momentálně pozastavena." +} diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index b151cbf6a..a0795960a 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -766,5 +766,6 @@ "switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)", "receivable_balance": "Forderungsbilanz", "confirmed_tx": "Bestätigt", - "transaction_details_source_address": "Quelladresse" -} \ No newline at end of file + "transaction_details_source_address": "Quelladresse", + "pause_wallet_creation": "Die Möglichkeit, Haven Wallet zu erstellen, ist derzeit pausiert." +} diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index c70d1f7c2..20ec41126 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -767,5 +767,6 @@ "switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)", "receivable_balance": "Receivable Balance", "confirmed_tx": "Confirmed", - "transaction_details_source_address": "Source address" -} \ No newline at end of file + "transaction_details_source_address": "Source address", + "pause_wallet_creation": "Ability to create Haven Wallet is currently paused." +} diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 9655edf60..e3783afe0 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -766,5 +766,6 @@ "switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)", "receivable_balance": "Saldo de cuentas por cobrar", "confirmed_tx": "Confirmado", - "transaction_details_source_address": "Dirección de la fuente" -} \ No newline at end of file + "transaction_details_source_address": "Dirección de la fuente", + "pause_wallet_creation": "La capacidad para crear Haven Wallet está actualmente pausada." +} diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index ea5862e80..5ae616bda 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -766,5 +766,6 @@ "switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)", "receivable_balance": "Solde de créances", "confirmed_tx": "Confirmé", - "transaction_details_source_address": "Adresse source" -} \ No newline at end of file + "transaction_details_source_address": "Adresse source", + "pause_wallet_creation": "La possibilité de créer Haven Wallet est actuellement suspendue." +} diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 8b1b58c74..cdbfeb1b6 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -748,5 +748,6 @@ "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)", "receivable_balance": "Daidaituwa da daidaituwa", "confirmed_tx": "Tabbatar", - "transaction_details_source_address": "Adireshin Incord" -} \ No newline at end of file + "transaction_details_source_address": "Adireshin Incord", + "pause_wallet_creation": "A halin yanzu an dakatar da ikon ƙirƙirar Haven Wallet." +} diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index a4070cb12..22519a1c4 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -766,5 +766,6 @@ "switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)", "receivable_balance": "प्राप्य शेष", "confirmed_tx": "की पुष्टि", - "transaction_details_source_address": "स्रोत पता" -} \ No newline at end of file + "transaction_details_source_address": "स्रोत पता", + "pause_wallet_creation": "हेवन वॉलेट बनाने की क्षमता फिलहाल रुकी हुई है।" +} diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 94383e1d2..c951baed4 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -764,5 +764,6 @@ "switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)", "receivable_balance": "Stanje potraživanja", "confirmed_tx": "Potvrđen", - "transaction_details_source_address": "Adresa izvora" -} \ No newline at end of file + "transaction_details_source_address": "Adresa izvora", + "pause_wallet_creation": "Mogućnost stvaranja novčanika Haven trenutno je pauzirana." +} diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 86997c8aa..d383da478 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -754,5 +754,6 @@ "switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)", "receivable_balance": "Saldo piutang", "confirmed_tx": "Dikonfirmasi", - "transaction_details_source_address": "Alamat sumber" -} \ No newline at end of file + "transaction_details_source_address": "Alamat sumber", + "pause_wallet_creation": "Kemampuan untuk membuat Haven Wallet saat ini dijeda." +} diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 257139d54..29edecaad 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -766,5 +766,6 @@ "switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)", "receivable_balance": "Bilanciamento creditizio", "confirmed_tx": "Confermato", - "transaction_details_source_address": "Indirizzo di partenza" -} \ No newline at end of file + "transaction_details_source_address": "Indirizzo di partenza", + "pause_wallet_creation": "La possibilità di creare Haven Wallet è attualmente sospesa." +} diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 3c648f1ad..d15c79c34 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -766,5 +766,6 @@ "switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)", "receivable_balance": "売掛金残高", "confirmed_tx": "確認済み", - "transaction_details_source_address": "ソースアドレス" -} \ No newline at end of file + "transaction_details_source_address": "ソースアドレス", + "pause_wallet_creation": "Haven Wallet を作成する機能は現在一時停止されています。" +} diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 1903ff1db..2a53ecf77 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -764,5 +764,6 @@ "switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)", "receivable_balance": "채권 잔액", "confirmed_tx": "확인", - "transaction_details_source_address": "소스 주소" -} \ No newline at end of file + "transaction_details_source_address": "소스 주소", + "pause_wallet_creation": "Haven Wallet 생성 기능이 현재 일시 중지되었습니다." +} diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 8933afeff..04986ad5c 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -764,5 +764,6 @@ "switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)", "receivable_balance": "လက်ကျန်ငွေ", "confirmed_tx": "အတည်ပြုသည်", - "transaction_details_source_address": "အရင်းအမြစ်လိပ်စာ" -} \ No newline at end of file + "transaction_details_source_address": "အရင်းအမြစ်လိပ်စာ", + "pause_wallet_creation": "Haven Wallet ဖန်တီးနိုင်မှုကို လောလောဆယ် ခေတ္တရပ်ထားသည်။" +} diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index b05e29efd..6c2ed2691 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -766,5 +766,6 @@ "switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)", "receivable_balance": "Het saldo", "confirmed_tx": "Bevestigd", - "transaction_details_source_address": "Bron adres" -} \ No newline at end of file + "transaction_details_source_address": "Bron adres", + "pause_wallet_creation": "De mogelijkheid om Haven Wallet te maken is momenteel onderbroken." +} diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index a4f63255a..5e37e982a 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -766,5 +766,6 @@ "switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)", "receivable_balance": "Saldo należności", "confirmed_tx": "Potwierdzony", - "transaction_details_source_address": "Adres źródłowy" -} \ No newline at end of file + "transaction_details_source_address": "Adres źródłowy", + "pause_wallet_creation": "Możliwość utworzenia Portfela Haven jest obecnie wstrzymana." +} diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index f30ea9635..66f0dd928 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -765,5 +765,6 @@ "switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)", "receivable_balance": "Saldo a receber", "confirmed_tx": "Confirmado", - "transaction_details_source_address": "Endereço de Origem" -} \ No newline at end of file + "transaction_details_source_address": "Endereço de Origem", + "pause_wallet_creation": "A capacidade de criar a Haven Wallet está atualmente pausada." +} diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 47c82263b..60c7bbc15 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -766,5 +766,6 @@ "switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon).", "receivable_balance": "Баланс дебиторской задолженности", "confirmed_tx": "Подтвержденный", - "transaction_details_source_address": "Адрес источника" -} \ No newline at end of file + "transaction_details_source_address": "Адрес источника", + "pause_wallet_creation": "Возможность создания Haven Wallet в настоящее время приостановлена." +} diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index a4abe9b14..b28964357 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -764,5 +764,6 @@ "switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)", "receivable_balance": "ยอดลูกหนี้", "confirmed_tx": "ซึ่งยืนยันแล้ว", - "transaction_details_source_address": "ที่อยู่แหล่งกำเนิด" -} \ No newline at end of file + "transaction_details_source_address": "ที่อยู่แหล่งกำเนิด", + "pause_wallet_creation": "ขณะนี้ความสามารถในการสร้าง Haven Wallet ถูกหยุดชั่วคราว" +} diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index e2c29c742..d30a25ad5 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -760,5 +760,6 @@ "switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)", "receivable_balance": "Natatanggap na balanse", "confirmed_tx": "Nakumpirma", - "transaction_details_source_address": "SOURCE ADDRESS" -} \ No newline at end of file + "transaction_details_source_address": "SOURCE ADDRESS", + "pause_wallet_creation": "Kasalukuyang naka-pause ang kakayahang gumawa ng Haven Wallet." +} diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 91d130d60..563ca5332 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -764,5 +764,6 @@ "switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)", "receivable_balance": "Alacak bakiyesi", "confirmed_tx": "Onaylanmış", - "transaction_details_source_address": "Kaynak adresi" -} \ No newline at end of file + "transaction_details_source_address": "Kaynak adresi", + "pause_wallet_creation": "Haven Cüzdanı oluşturma yeteneği şu anda duraklatıldı." +} diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 5cb5a6754..9418d6065 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -766,5 +766,6 @@ "switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)", "receivable_balance": "Баланс дебіторської заборгованості", "confirmed_tx": "Підтверджений", - "transaction_details_source_address": "Адреса джерела" -} \ No newline at end of file + "transaction_details_source_address": "Адреса джерела", + "pause_wallet_creation": "Можливість створення гаманця Haven зараз призупинено." +} diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index d367d11cb..61e97d751 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -758,5 +758,6 @@ "switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ ", "receivable_balance": "قابل وصول توازن", "confirmed_tx": "تصدیق", - "transaction_details_source_address": "ماخذ ایڈریس" -} \ No newline at end of file + "transaction_details_source_address": "ماخذ ایڈریس", + "pause_wallet_creation": "Haven Wallet ۔ﮯﮨ ﻑﻮﻗﻮﻣ ﻝﺎﺤﻟﺍ ﯽﻓ ﺖﯿﻠﮨﺍ ﯽﮐ ﮯﻧﺎﻨﺑ" +} diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 332297b4b..dbff620a1 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -760,5 +760,6 @@ "switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)", "receivable_balance": "Iwontunws.funfun ti o gba", "confirmed_tx": "Jẹrisi", - "transaction_details_source_address": "Adirẹsi orisun" -} \ No newline at end of file + "transaction_details_source_address": "Adirẹsi orisun", + "pause_wallet_creation": "Agbara lati ṣẹda Haven Wallet ti wa ni idaduro lọwọlọwọ." +} diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 76afa40d1..249a412c4 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -765,5 +765,6 @@ "switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)", "receivable_balance": "应收余额", "confirmed_tx": "确认的", - "transaction_details_source_address": "源地址" -} \ No newline at end of file + "transaction_details_source_address": "源地址", + "pause_wallet_creation": "创建 Haven 钱包的功能当前已暂停。" +} From d664f0a16fd030ed8dae530df66cf6356d6d3aa7 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Mon, 22 Jan 2024 16:30:16 -0800 Subject: [PATCH 098/241] Cw 540 encrypt shared (#1269) * start writing migration * save * finishing up migration * more fixes * fixes * migration fixes * remove commented code and ensure widget initialization in root.dart * use securekey static functions everywhere applicable --- lib/core/auth_service.dart | 8 +- lib/core/backup_service.dart | 85 +--- lib/di.dart | 24 +- lib/entities/default_settings_migration.dart | 79 ++++ lib/entities/preferences_key.dart | 26 +- lib/entities/secret_store_key.dart | 65 +++ lib/main.dart | 2 +- lib/src/screens/root/root.dart | 14 +- lib/store/settings_store.dart | 427 ++++++++++++------ .../security_settings_view_model.dart | 2 +- .../wallet_list/wallet_list_view_model.dart | 2 +- 11 files changed, 452 insertions(+), 282 deletions(-) diff --git a/lib/core/auth_service.dart b/lib/core/auth_service.dart index c072bf65e..a99aef31d 100644 --- a/lib/core/auth_service.dart +++ b/lib/core/auth_service.dart @@ -72,11 +72,11 @@ class AuthService with Store { void saveLastAuthTime() { int timestamp = DateTime.now().millisecondsSinceEpoch; - sharedPreferences.setInt(PreferencesKey.lastAuthTimeMilliseconds, timestamp); + secureStorage.write(key: SecureKey.lastAuthTimeMilliseconds, value: timestamp.toString()); } - bool requireAuth() { - final timestamp = sharedPreferences.getInt(PreferencesKey.lastAuthTimeMilliseconds); + Future requireAuth() async { + final timestamp = int.tryParse(await secureStorage.read(key: SecureKey.lastAuthTimeMilliseconds) ?? '0'); final duration = _durationToRequireAuth(timestamp ?? 0); final requiredPinInterval = settingsStore.pinTimeOutDuration; @@ -100,7 +100,7 @@ class AuthService with Store { 'Either route or onAuthSuccess param must be passed.'); if (!conditionToDetermineIfToUse2FA) { - if (!requireAuth() && !_alwaysAuthenticateRoutes.contains(route)) { + if (!(await requireAuth()) && !_alwaysAuthenticateRoutes.contains(route)) { if (onAuthSuccess != null) { onAuthSuccess(true); } else { diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 7dd0b50f3..9b5c4c8db 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -213,8 +213,6 @@ class BackupService { final defaultBuyProvider = data[PreferencesKey.defaultBuyProvider] as int?; final currentTransactionPriorityKeyLegacy = data[PreferencesKey.currentTransactionPriorityKeyLegacy] as int?; - final allowBiometricalAuthentication = - data[PreferencesKey.allowBiometricalAuthenticationKey] as bool?; final currentBitcoinElectrumSererId = data[PreferencesKey.currentBitcoinElectrumSererIdKey] as int?; final currentLanguageCode = data[PreferencesKey.currentLanguageCode] as String?; @@ -227,23 +225,6 @@ class BackupService { data[PreferencesKey.currentDefaultSettingsMigrationVersion] as int?; final moneroTransactionPriority = data[PreferencesKey.moneroTransactionPriority] as int?; final bitcoinTransactionPriority = data[PreferencesKey.bitcoinTransactionPriority] as int?; - final selectedCake2FAPreset = data[PreferencesKey.selectedCake2FAPreset] as int?; - final shouldRequireTOTP2FAForAccessingWallet = - data[PreferencesKey.shouldRequireTOTP2FAForAccessingWallet] as bool?; - final shouldRequireTOTP2FAForSendsToContact = - data[PreferencesKey.shouldRequireTOTP2FAForSendsToContact] as bool?; - final shouldRequireTOTP2FAForSendsToNonContact = - data[PreferencesKey.shouldRequireTOTP2FAForSendsToNonContact] as bool?; - final shouldRequireTOTP2FAForSendsToInternalWallets = - data[PreferencesKey.shouldRequireTOTP2FAForSendsToInternalWallets] as bool?; - final shouldRequireTOTP2FAForExchangesToInternalWallets = - data[PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets] as bool?; - final shouldRequireTOTP2FAForAddingContacts = - data[PreferencesKey.shouldRequireTOTP2FAForAddingContacts] as bool?; - final shouldRequireTOTP2FAForCreatingNewWallets = - data[PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets] as bool?; - final shouldRequireTOTP2FAForAllSecurityAndBackupSettings = - data[PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings] as bool?; final sortBalanceTokensBy = data[PreferencesKey.sortBalanceBy] as int?; final pinNativeTokenAtTop = data[PreferencesKey.pinNativeTokenAtTop] as bool?; final useEtherscan = data[PreferencesKey.useEtherscan] as bool?; @@ -294,14 +275,7 @@ class BackupService { if (currentTransactionPriorityKeyLegacy != null) await _sharedPreferences.setInt( PreferencesKey.currentTransactionPriorityKeyLegacy, currentTransactionPriorityKeyLegacy); - - if (DeviceInfo.instance.isDesktop) { - await _sharedPreferences.setBool(PreferencesKey.allowBiometricalAuthenticationKey, false); - } else if (allowBiometricalAuthentication != null) { - await _sharedPreferences.setBool( - PreferencesKey.allowBiometricalAuthenticationKey, allowBiometricalAuthentication); - } - + if (currentBitcoinElectrumSererId != null) await _sharedPreferences.setInt( PreferencesKey.currentBitcoinElectrumSererIdKey, currentBitcoinElectrumSererId); @@ -344,43 +318,6 @@ class BackupService { await _sharedPreferences.setInt( PreferencesKey.bitcoinTransactionPriority, bitcoinTransactionPriority); - if (selectedCake2FAPreset != null) - await _sharedPreferences.setInt(PreferencesKey.selectedCake2FAPreset, selectedCake2FAPreset); - - if (shouldRequireTOTP2FAForAccessingWallet != null) - await _sharedPreferences.setBool(PreferencesKey.shouldRequireTOTP2FAForAccessingWallet, - shouldRequireTOTP2FAForAccessingWallet); - - if (shouldRequireTOTP2FAForSendsToContact != null) - await _sharedPreferences.setBool(PreferencesKey.shouldRequireTOTP2FAForSendsToContact, - shouldRequireTOTP2FAForSendsToContact); - - if (shouldRequireTOTP2FAForSendsToNonContact != null) - await _sharedPreferences.setBool(PreferencesKey.shouldRequireTOTP2FAForSendsToNonContact, - shouldRequireTOTP2FAForSendsToNonContact); - - if (shouldRequireTOTP2FAForSendsToInternalWallets != null) - await _sharedPreferences.setBool(PreferencesKey.shouldRequireTOTP2FAForSendsToInternalWallets, - shouldRequireTOTP2FAForSendsToInternalWallets); - - if (shouldRequireTOTP2FAForExchangesToInternalWallets != null) - await _sharedPreferences.setBool( - PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets, - shouldRequireTOTP2FAForExchangesToInternalWallets); - - if (shouldRequireTOTP2FAForAddingContacts != null) - await _sharedPreferences.setBool(PreferencesKey.shouldRequireTOTP2FAForAddingContacts, - shouldRequireTOTP2FAForAddingContacts); - - if (shouldRequireTOTP2FAForCreatingNewWallets != null) - await _sharedPreferences.setBool(PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets, - shouldRequireTOTP2FAForCreatingNewWallets); - - if (shouldRequireTOTP2FAForAllSecurityAndBackupSettings != null) - await _sharedPreferences.setBool( - PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings, - shouldRequireTOTP2FAForAllSecurityAndBackupSettings); - if (sortBalanceTokensBy != null) await _sharedPreferences.setInt(PreferencesKey.sortBalanceBy, sortBalanceTokensBy); @@ -532,8 +469,6 @@ class BackupService { PreferencesKey.currentPinLength: _sharedPreferences.getInt(PreferencesKey.currentPinLength), PreferencesKey.currentTransactionPriorityKeyLegacy: _sharedPreferences.getInt(PreferencesKey.currentTransactionPriorityKeyLegacy), - PreferencesKey.allowBiometricalAuthenticationKey: - _sharedPreferences.getBool(PreferencesKey.allowBiometricalAuthenticationKey), PreferencesKey.currentBitcoinElectrumSererIdKey: _sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey), PreferencesKey.currentLanguageCode: @@ -550,24 +485,6 @@ class BackupService { _sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority), PreferencesKey.currentFiatApiModeKey: _sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey), - PreferencesKey.selectedCake2FAPreset: - _sharedPreferences.getInt(PreferencesKey.selectedCake2FAPreset), - PreferencesKey.shouldRequireTOTP2FAForAccessingWallet: - _sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForAccessingWallet), - PreferencesKey.shouldRequireTOTP2FAForSendsToContact: - _sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToContact), - PreferencesKey.shouldRequireTOTP2FAForSendsToNonContact: - _sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToNonContact), - PreferencesKey.shouldRequireTOTP2FAForSendsToInternalWallets: - _sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToInternalWallets), - PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets: _sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets), - PreferencesKey.shouldRequireTOTP2FAForAddingContacts: - _sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForAddingContacts), - PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets: - _sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets), - PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings: _sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings), PreferencesKey.sortBalanceBy: _sharedPreferences.getInt(PreferencesKey.sortBalanceBy), PreferencesKey.pinNativeTokenAtTop: _sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop), diff --git a/lib/di.dart b/lib/di.dart index 61a04bf1c..a37c76b34 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -276,6 +276,7 @@ Future setup({ if (!_isSetupFinished) { getIt.registerSingletonAsync(() => SharedPreferences.getInstance()); + getIt.registerSingleton(secureStorage); } if (!_isSetupFinished) { getIt.registerFactory(() => BackgroundTasks()); @@ -302,7 +303,6 @@ Future setup({ getIt.registerFactory>(() => _nodeSource); getIt.registerFactory>(() => _powNodeSource, instanceName: Node.boxName + "pow"); - getIt.registerSingleton(secureStorage); getIt.registerSingleton(AuthenticationStore()); getIt.registerSingleton(WalletListStore()); getIt.registerSingleton(NodeListStoreBase.instance); @@ -344,17 +344,19 @@ Future setup({ walletInfoSource: _walletInfoSource)); getIt.registerFactoryParam( - (type, _) => AdvancedPrivacySettingsViewModel(type, getIt.get())); + (type, _) => AdvancedPrivacySettingsViewModel(type, getIt.get())); getIt.registerFactory(() => WalletLoadingService( getIt.get(), getIt.get(), (WalletType type) => getIt.get(param1: type))); - - getIt.registerFactoryParam((type, _) => - WalletNewVM(getIt.get(), - getIt.get(param1: type), _walletInfoSource, - getIt.get(param1: type),type: type)); + + getIt.registerFactoryParam((type, _) => WalletNewVM( + getIt.get(), + getIt.get(param1: type), + _walletInfoSource, + getIt.get(param1: type), + type: type)); getIt.registerFactoryParam((WalletType type, _) { return WalletRestorationFromQRVM(getIt.get(), @@ -805,8 +807,7 @@ Future setup({ .registerFactory(() => DFXBuyProvider(wallet: getIt.get().wallet!)); getIt.registerFactory(() => MoonPaySellProvider( - settingsStore: getIt.get().settingsStore, - wallet: getIt.get().wallet!)); + settingsStore: getIt.get().settingsStore, wallet: getIt.get().wallet!)); getIt.registerFactory(() => OnRamperBuyProvider( getIt.get().settingsStore, @@ -919,8 +920,7 @@ Future setup({ (param1, isCreate) => NewWalletTypePage(onTypeSelected: param1, isCreate: isCreate ?? true)); getIt.registerFactoryParam( - (seedPhraseLength, _) - => PreSeedPage(seedPhraseLength)); + (seedPhraseLength, _) => PreSeedPage(seedPhraseLength)); getIt.registerFactoryParam((trade, _) => TradeDetailsViewModel( @@ -954,7 +954,7 @@ Future setup({ getIt.registerFactory(() => BuyAmountViewModel()); getIt.registerFactoryParam( - (isBuyOption, _) => BuySellOptionsPage(getIt.get(), isBuyOption)); + (isBuyOption, _) => BuySellOptionsPage(getIt.get(), isBuyOption)); getIt.registerFactory(() { final wallet = getIt.get().wallet; diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 22868ae28..1279beeca 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -185,6 +185,9 @@ Future defaultSettingsMigration( case 25: await rewriteSecureStoragePin(secureStorage: secureStorage); break; + case 26: + await insecureStorageMigration(secureStorage: secureStorage, sharedPreferences: sharedPreferences); + break; default: break; } @@ -378,6 +381,82 @@ Node getMoneroDefaultNode({required Box nodes}) { } } +Future insecureStorageMigration({ + required SharedPreferences sharedPreferences, + required FlutterSecureStorage secureStorage, +}) async { + bool? allowBiometricalAuthentication = + sharedPreferences.getBool(SecureKey.allowBiometricalAuthenticationKey); + bool? useTOTP2FA = sharedPreferences.getBool(SecureKey.useTOTP2FA); + bool? shouldRequireTOTP2FAForAccessingWallet = + sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForAccessingWallet); + bool? shouldRequireTOTP2FAForSendsToContact = + sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForSendsToContact); + bool? shouldRequireTOTP2FAForSendsToNonContact = + sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForSendsToNonContact); + bool? shouldRequireTOTP2FAForSendsToInternalWallets = + sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForSendsToInternalWallets); + bool? shouldRequireTOTP2FAForExchangesToInternalWallets = + sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForExchangesToInternalWallets); + bool? shouldRequireTOTP2FAForExchangesToExternalWallets = + sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForExchangesToExternalWallets); + bool? shouldRequireTOTP2FAForAddingContacts = + sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForAddingContacts); + bool? shouldRequireTOTP2FAForCreatingNewWallets = + sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForCreatingNewWallets); + bool? shouldRequireTOTP2FAForAllSecurityAndBackupSettings = + sharedPreferences.getBool(SecureKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings); + int? selectedCake2FAPreset = sharedPreferences.getInt(SecureKey.selectedCake2FAPreset); + String? totpSecretKey = sharedPreferences.getString(SecureKey.totpSecretKey); + int? pinTimeOutDuration = sharedPreferences.getInt(SecureKey.pinTimeOutDuration); + int? lastAuthTimeMilliseconds = sharedPreferences.getInt(SecureKey.lastAuthTimeMilliseconds); + + try { + await secureStorage.write( + key: SecureKey.allowBiometricalAuthenticationKey, + value: allowBiometricalAuthentication.toString()); + await secureStorage.write(key: SecureKey.useTOTP2FA, value: useTOTP2FA.toString()); + await secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForAccessingWallet, + value: shouldRequireTOTP2FAForAccessingWallet.toString()); + await secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForSendsToContact, + value: shouldRequireTOTP2FAForSendsToContact.toString()); + await secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForSendsToNonContact, + value: shouldRequireTOTP2FAForSendsToNonContact.toString()); + await secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForSendsToInternalWallets, + value: shouldRequireTOTP2FAForSendsToInternalWallets.toString()); + await secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForExchangesToInternalWallets, + value: shouldRequireTOTP2FAForExchangesToInternalWallets.toString()); + await secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForExchangesToExternalWallets, + value: shouldRequireTOTP2FAForExchangesToExternalWallets.toString()); + await secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForAddingContacts, + value: shouldRequireTOTP2FAForAddingContacts.toString()); + await secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForCreatingNewWallets, + value: shouldRequireTOTP2FAForCreatingNewWallets.toString()); + await secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings, + value: shouldRequireTOTP2FAForAllSecurityAndBackupSettings.toString()); + await secureStorage.write( + key: SecureKey.selectedCake2FAPreset, value: selectedCake2FAPreset.toString()); + await secureStorage.write(key: SecureKey.totpSecretKey, value: totpSecretKey.toString()); + await secureStorage.write( + key: SecureKey.pinTimeOutDuration, value: pinTimeOutDuration.toString()); + await secureStorage.write( + key: SecureKey.lastAuthTimeMilliseconds, value: lastAuthTimeMilliseconds.toString()); + } catch (e) { + print("Error migrating shared preferences to secure storage!: $e"); + // this actually shouldn't be that big of a problem since we don't delete the old keys in this update + // and we read and write to the new locations when loading storage, the migration is just for extra safety + } +} + Future rewriteSecureStoragePin({required FlutterSecureStorage secureStorage}) async { // the bug only affects ios/mac: if (!Platform.isIOS && !Platform.isMacOS) { diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 2d5e64817..75e61b5e8 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -23,8 +23,6 @@ class PreferencesKey { static const walletListOrder = 'wallet_list_order'; static const walletListAscending = 'wallet_list_ascending'; static const currentFiatApiModeKey = 'current_fiat_api_mode'; - static const allowBiometricalAuthenticationKey = 'allow_biometrical_authentication'; - static const useTOTP2FA = 'use_totp_2fa'; static const failedTotpTokenTrials = 'failed_token_trials'; static const disableExchangeKey = 'disable_exchange'; static const exchangeStatusKey = 'exchange_status'; @@ -33,6 +31,7 @@ class PreferencesKey { static const displayActionListModeKey = 'display_list_mode'; static const currentPinLength = 'current_pin_length'; static const currentLanguageCode = 'language_code'; + static const currentSeedPhraseLength = 'current_seed_phrase_length'; static const currentDefaultSettingsMigrationVersion = 'current_default_settings_migration_version'; static const moneroTransactionPriority = 'current_fee_priority_monero'; @@ -47,8 +46,6 @@ class PreferencesKey { static const moneroWalletPasswordUpdateV1Base = 'monero_wallet_update_v1'; static const syncModeKey = 'sync_mode'; static const syncAllKey = 'sync_all'; - static const pinTimeOutDuration = 'pin_timeout_duration'; - static const lastAuthTimeMilliseconds = 'last_auth_time_milliseconds'; static const lastPopupDate = 'last_popup_date'; static const lastAppReviewDate = 'last_app_review_date'; static const sortBalanceBy = 'sort_balance_by'; @@ -75,25 +72,4 @@ class PreferencesKey { static const lastSeenAppVersion = 'last_seen_app_version'; static const shouldShowMarketPlaceInDashboard = 'should_show_marketplace_in_dashboard'; static const isNewInstall = 'is_new_install'; - static const shouldRequireTOTP2FAForAccessingWallet = - 'should_require_totp_2fa_for_accessing_wallets'; - static const shouldRequireTOTP2FAForSendsToContact = - 'should_require_totp_2fa_for_sends_to_contact'; - static const shouldRequireTOTP2FAForSendsToNonContact = - 'should_require_totp_2fa_for_sends_to_non_contact'; - static const shouldRequireTOTP2FAForSendsToInternalWallets = - 'should_require_totp_2fa_for_sends_to_internal_wallets'; - static const shouldRequireTOTP2FAForExchangesToInternalWallets = - 'should_require_totp_2fa_for_exchanges_to_internal_wallets'; - static const shouldRequireTOTP2FAForExchangesToExternalWallets = - 'should_require_totp_2fa_for_exchanges_to_external_wallets'; - static const shouldRequireTOTP2FAForAddingContacts = - 'should_require_totp_2fa_for_adding_contacts'; - static const shouldRequireTOTP2FAForCreatingNewWallets = - 'should_require_totp_2fa_for_creating_new_wallets'; - static const shouldRequireTOTP2FAForAllSecurityAndBackupSettings = - 'should_require_totp_2fa_for_all_security_and_backup_settings'; - static const selectedCake2FAPreset = 'selected_cake_2fa_preset'; - static const totpSecretKey = 'totp_secret_key'; - static const currentSeedPhraseLength = 'current_seed_phrase_length'; } diff --git a/lib/entities/secret_store_key.dart b/lib/entities/secret_store_key.dart index 00ec06767..2ee490c74 100644 --- a/lib/entities/secret_store_key.dart +++ b/lib/entities/secret_store_key.dart @@ -1,3 +1,6 @@ +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + enum SecretStoreKey { moneroWalletPassword, pinCodePassword, backupPassword } const moneroWalletPassword = "MONERO_WALLET_PASSWORD"; @@ -35,3 +38,65 @@ String generateStoreKeyFor({ return _key; } + +class SecureKey { + static const allowBiometricalAuthenticationKey = 'allow_biometrical_authentication'; + static const useTOTP2FA = 'use_totp_2fa'; + static const shouldRequireTOTP2FAForAccessingWallet = + 'should_require_totp_2fa_for_accessing_wallets'; + static const shouldRequireTOTP2FAForSendsToContact = + 'should_require_totp_2fa_for_sends_to_contact'; + static const shouldRequireTOTP2FAForSendsToNonContact = + 'should_require_totp_2fa_for_sends_to_non_contact'; + static const shouldRequireTOTP2FAForSendsToInternalWallets = + 'should_require_totp_2fa_for_sends_to_internal_wallets'; + static const shouldRequireTOTP2FAForExchangesToInternalWallets = + 'should_require_totp_2fa_for_exchanges_to_internal_wallets'; + static const shouldRequireTOTP2FAForExchangesToExternalWallets = + 'should_require_totp_2fa_for_exchanges_to_external_wallets'; + static const shouldRequireTOTP2FAForAddingContacts = + 'should_require_totp_2fa_for_adding_contacts'; + static const shouldRequireTOTP2FAForCreatingNewWallets = + 'should_require_totp_2fa_for_creating_new_wallets'; + static const shouldRequireTOTP2FAForAllSecurityAndBackupSettings = + 'should_require_totp_2fa_for_all_security_and_backup_settings'; + static const selectedCake2FAPreset = 'selected_cake_2fa_preset'; + static const totpSecretKey = 'totp_secret_key'; + static const pinTimeOutDuration = 'pin_timeout_duration'; + static const lastAuthTimeMilliseconds = 'last_auth_time_milliseconds'; + + static Future getInt({ + required FlutterSecureStorage secureStorage, + required SharedPreferences sharedPreferences, + required String key, + }) async { + int? value = int.tryParse((await secureStorage.read(key: key) ?? '')); + value ??= sharedPreferences.getInt(key); + return value; + } + + static Future getBool({ + required FlutterSecureStorage secureStorage, + required SharedPreferences sharedPreferences, + required String key, + }) async { + String? value = (await secureStorage.read(key: key) ?? ''); + if (value.toLowerCase() == "true") { + return true; + } else if (value.toLowerCase() == "false") { + return false; + } else { + return sharedPreferences.getBool(key); + } + } + + static Future getString({ + required FlutterSecureStorage secureStorage, + required SharedPreferences sharedPreferences, + required String key, + }) async { + String? value = await secureStorage.read(key: key); + value ??= sharedPreferences.getString(key); + return value; + } +} diff --git a/lib/main.dart b/lib/main.dart index 165db1ddd..306b109a0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -163,7 +163,7 @@ Future initializeAppConfigs() async { transactionDescriptions: transactionDescriptions, secureStorage: secureStorage, anonpayInvoiceInfo: anonpayInvoiceInfo, - initialMigrationVersion: 25); + initialMigrationVersion: 26); } Future initialSetup( diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index 5f7fcd205..b3d503162 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -53,13 +53,17 @@ class RootState extends State with WidgetsBindingObserver { @override void initState() { - _requestAuth = widget.authService.requireAuth(); + WidgetsBinding.instance.addPostFrameCallback((_) async { + bool value = await widget.authService.requireAuth(); + setState(() { + _requestAuth = value; + }); + }); _isInactiveController = StreamController.broadcast(); _isInactive = false; _postFrameCallback = false; WidgetsBinding.instance.addObserver(this); super.initState(); - if (DeviceInfo.instance.isMobile) { initUniLinks(); } @@ -105,8 +109,10 @@ class RootState extends State with WidgetsBindingObserver { break; case AppLifecycleState.resumed: - setState(() { - _requestAuth = widget.authService.requireAuth(); + widget.authService.requireAuth().then((value) { + setState(() { + _requestAuth = value; + }); }); break; default: diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 7bccc4fc5..191eeb43f 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -10,6 +10,7 @@ import 'package:cake_wallet/entities/background_tasks.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; +import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cake_wallet/entities/seed_phrase_length.dart'; import 'package:cake_wallet/entities/seed_type.dart'; import 'package:cake_wallet/entities/sort_balance_types.dart'; @@ -24,6 +25,7 @@ import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/themes/theme_list.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:package_info/package_info.dart'; @@ -44,7 +46,8 @@ class SettingsStore = SettingsStoreBase with _$SettingsStore; abstract class SettingsStoreBase with Store { SettingsStoreBase( - {required BackgroundTasks backgroundTasks, + {required FlutterSecureStorage secureStorage, + required BackgroundTasks backgroundTasks, required SharedPreferences sharedPreferences, required bool initialShouldShowMarketPlaceInDashboard, required FiatCurrency initialFiatCurrency, @@ -109,6 +112,7 @@ abstract class SettingsStoreBase with Store { TransactionPriority? initialBitcoinCashTransactionPriority}) : nodes = ObservableMap.of(nodes), powNodes = ObservableMap.of(powNodes), + _secureStorage = secureStorage, _sharedPreferences = sharedPreferences, _backgroundTasks = backgroundTasks, fiatCurrency = initialFiatCurrency, @@ -187,8 +191,9 @@ abstract class SettingsStoreBase with Store { final key = 'buyProvider_${walletType.toString()}'; final providerId = sharedPreferences.getString(key); if (providerId != null) { - defaultBuyProviders[walletType] = ProviderType.values - .firstWhere((provider) => provider.id == providerId, orElse: () => ProviderType.askEachTime); + defaultBuyProviders[walletType] = ProviderType.values.firstWhere( + (provider) => provider.id == providerId, + orElse: () => ProviderType.askEachTime); } else { defaultBuyProviders[walletType] = ProviderType.askEachTime; } @@ -198,8 +203,9 @@ abstract class SettingsStoreBase with Store { final key = 'sellProvider_${walletType.toString()}'; final providerId = sharedPreferences.getString(key); if (providerId != null) { - defaultSellProviders[walletType] = ProviderType.values - .firstWhere((provider) => provider.id == providerId, orElse: () => ProviderType.askEachTime); + defaultSellProviders[walletType] = ProviderType.values.firstWhere( + (provider) => provider.id == providerId, + orElse: () => ProviderType.askEachTime); } else { defaultSellProviders[walletType] = ProviderType.askEachTime; } @@ -312,74 +318,6 @@ abstract class SettingsStoreBase with Store { reaction((_) => currentTheme, (ThemeBase theme) => sharedPreferences.setInt(PreferencesKey.currentTheme, theme.raw)); - reaction( - (_) => allowBiometricalAuthentication, - (bool biometricalAuthentication) => sharedPreferences.setBool( - PreferencesKey.allowBiometricalAuthenticationKey, biometricalAuthentication)); - - reaction( - (_) => selectedCake2FAPreset, - (Cake2FAPresetsOptions selectedCake2FAPreset) => sharedPreferences.setInt( - PreferencesKey.selectedCake2FAPreset, selectedCake2FAPreset.serialize())); - - reaction( - (_) => shouldRequireTOTP2FAForAccessingWallet, - (bool requireTOTP2FAForAccessingWallet) => sharedPreferences.setBool( - PreferencesKey.shouldRequireTOTP2FAForAccessingWallet, - requireTOTP2FAForAccessingWallet)); - - reaction( - (_) => shouldRequireTOTP2FAForSendsToContact, - (bool requireTOTP2FAForSendsToContact) => sharedPreferences.setBool( - PreferencesKey.shouldRequireTOTP2FAForSendsToContact, requireTOTP2FAForSendsToContact)); - - reaction( - (_) => shouldRequireTOTP2FAForSendsToNonContact, - (bool requireTOTP2FAForSendsToNonContact) => sharedPreferences.setBool( - PreferencesKey.shouldRequireTOTP2FAForSendsToNonContact, - requireTOTP2FAForSendsToNonContact)); - - reaction( - (_) => shouldRequireTOTP2FAForSendsToInternalWallets, - (bool requireTOTP2FAForSendsToInternalWallets) => sharedPreferences.setBool( - PreferencesKey.shouldRequireTOTP2FAForSendsToInternalWallets, - requireTOTP2FAForSendsToInternalWallets)); - - reaction( - (_) => shouldRequireTOTP2FAForExchangesToInternalWallets, - (bool requireTOTP2FAForExchangesToInternalWallets) => sharedPreferences.setBool( - PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets, - requireTOTP2FAForExchangesToInternalWallets)); - - reaction( - (_) => shouldRequireTOTP2FAForExchangesToExternalWallets, - (bool requireTOTP2FAForExchangesToExternalWallets) => sharedPreferences.setBool( - PreferencesKey.shouldRequireTOTP2FAForExchangesToExternalWallets, - requireTOTP2FAForExchangesToExternalWallets)); - - reaction( - (_) => shouldRequireTOTP2FAForAddingContacts, - (bool requireTOTP2FAForAddingContacts) => sharedPreferences.setBool( - PreferencesKey.shouldRequireTOTP2FAForAddingContacts, requireTOTP2FAForAddingContacts)); - - reaction( - (_) => shouldRequireTOTP2FAForCreatingNewWallets, - (bool requireTOTP2FAForCreatingNewWallets) => sharedPreferences.setBool( - PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets, - requireTOTP2FAForCreatingNewWallets)); - - reaction( - (_) => shouldRequireTOTP2FAForAllSecurityAndBackupSettings, - (bool requireTOTP2FAForAllSecurityAndBackupSettings) => sharedPreferences.setBool( - PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings, - requireTOTP2FAForAllSecurityAndBackupSettings)); - - reaction( - (_) => useTOTP2FA, (bool use) => sharedPreferences.setBool(PreferencesKey.useTOTP2FA, use)); - - reaction((_) => totpSecretKey, - (String totpKey) => sharedPreferences.setString(PreferencesKey.totpSecretKey, totpKey)); - reaction( (_) => numberOfFailedTokenTrials, (int failedTokenTrail) => @@ -403,11 +341,6 @@ abstract class SettingsStoreBase with Store { (SeedPhraseLength seedPhraseWordCount) => sharedPreferences.setInt( PreferencesKey.currentSeedPhraseLength, seedPhraseWordCount.value)); - reaction( - (_) => pinTimeOutDuration, - (PinCodeRequiredDuration pinCodeInterval) => - sharedPreferences.setInt(PreferencesKey.pinTimeOutDuration, pinCodeInterval.value)); - reaction( (_) => balanceDisplayMode, (BalanceDisplayMode mode) => sharedPreferences.setInt( @@ -485,6 +418,84 @@ abstract class SettingsStoreBase with Store { reaction((_) => lookupsENS, (bool looksUpENS) => _sharedPreferences.setBool(PreferencesKey.lookupsENS, looksUpENS)); + // secure storage keys: + reaction( + (_) => allowBiometricalAuthentication, + (bool biometricalAuthentication) => secureStorage.write( + key: SecureKey.allowBiometricalAuthenticationKey, + value: biometricalAuthentication.toString())); + + reaction( + (_) => selectedCake2FAPreset, + (Cake2FAPresetsOptions selectedCake2FAPreset) => secureStorage.write( + key: SecureKey.selectedCake2FAPreset, + value: selectedCake2FAPreset.serialize().toString())); + + reaction( + (_) => shouldRequireTOTP2FAForAccessingWallet, + (bool requireTOTP2FAForAccessingWallet) => secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForAccessingWallet, + value: requireTOTP2FAForAccessingWallet.toString())); + + reaction( + (_) => shouldRequireTOTP2FAForSendsToContact, + (bool requireTOTP2FAForSendsToContact) => secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForSendsToContact, + value: requireTOTP2FAForSendsToContact.toString())); + + reaction( + (_) => shouldRequireTOTP2FAForSendsToNonContact, + (bool requireTOTP2FAForSendsToNonContact) => secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForSendsToNonContact, + value: requireTOTP2FAForSendsToNonContact.toString())); + + reaction( + (_) => shouldRequireTOTP2FAForSendsToInternalWallets, + (bool requireTOTP2FAForSendsToInternalWallets) => secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForSendsToInternalWallets, + value: requireTOTP2FAForSendsToInternalWallets.toString())); + + reaction( + (_) => shouldRequireTOTP2FAForExchangesToInternalWallets, + (bool requireTOTP2FAForExchangesToInternalWallets) => secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForExchangesToInternalWallets, + value: requireTOTP2FAForExchangesToInternalWallets.toString())); + + reaction( + (_) => shouldRequireTOTP2FAForExchangesToExternalWallets, + (bool requireTOTP2FAForExchangesToExternalWallets) => secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForExchangesToExternalWallets, + value: requireTOTP2FAForExchangesToExternalWallets.toString())); + + reaction( + (_) => shouldRequireTOTP2FAForAddingContacts, + (bool requireTOTP2FAForAddingContacts) => secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForAddingContacts, + value: requireTOTP2FAForAddingContacts.toString())); + + reaction( + (_) => shouldRequireTOTP2FAForCreatingNewWallets, + (bool requireTOTP2FAForCreatingNewWallets) => secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForCreatingNewWallets, + value: requireTOTP2FAForCreatingNewWallets.toString())); + + reaction( + (_) => shouldRequireTOTP2FAForAllSecurityAndBackupSettings, + (bool requireTOTP2FAForAllSecurityAndBackupSettings) => secureStorage.write( + key: SecureKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings, + value: requireTOTP2FAForAllSecurityAndBackupSettings.toString())); + + reaction((_) => useTOTP2FA, + (bool use) => secureStorage.write(key: SecureKey.useTOTP2FA, value: use.toString())); + + reaction((_) => totpSecretKey, + (String totpKey) => secureStorage.write(key: SecureKey.totpSecretKey, value: totpKey)); + + reaction( + (_) => pinTimeOutDuration, + (PinCodeRequiredDuration pinCodeInterval) => secureStorage.write( + key: SecureKey.pinTimeOutDuration, value: pinCodeInterval.value.toString())); + this.nodes.observe((change) { if (change.newValue != null && change.key != null) { _saveCurrentNode(change.newValue!, change.key!); @@ -668,6 +679,7 @@ abstract class SettingsStoreBase with Store { String deviceName; + final FlutterSecureStorage _secureStorage; final SharedPreferences _sharedPreferences; final BackgroundTasks _backgroundTasks; @@ -710,6 +722,7 @@ abstract class SettingsStoreBase with Store { BalanceDisplayMode initialBalanceDisplayMode = BalanceDisplayMode.availableBalance, ThemeBase? initialTheme}) async { final sharedPreferences = await getIt.getAsync(); + final secureStorage = await getIt.get(); final backgroundTasks = getIt.get(); final currentFiatCurrency = FiatCurrency.deserialize( raw: sharedPreferences.getString(PreferencesKey.currentFiatCurrencyKey)!); @@ -770,36 +783,6 @@ abstract class SettingsStoreBase with Store { final currentFiatApiMode = FiatApiMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey) ?? FiatApiMode.enabled.raw); - final allowBiometricalAuthentication = - sharedPreferences.getBool(PreferencesKey.allowBiometricalAuthenticationKey) ?? false; - final selectedCake2FAPreset = Cake2FAPresetsOptions.deserialize( - raw: sharedPreferences.getInt(PreferencesKey.selectedCake2FAPreset) ?? - Cake2FAPresetsOptions.normal.raw); - final shouldRequireTOTP2FAForAccessingWallet = - sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForAccessingWallet) ?? false; - final shouldRequireTOTP2FAForSendsToContact = - sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToContact) ?? false; - final shouldRequireTOTP2FAForSendsToNonContact = - sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToNonContact) ?? false; - final shouldRequireTOTP2FAForSendsToInternalWallets = - sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToInternalWallets) ?? - false; - final shouldRequireTOTP2FAForExchangesToInternalWallets = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ?? - false; - final shouldRequireTOTP2FAForExchangesToExternalWallets = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToExternalWallets) ?? - false; - final shouldRequireTOTP2FAForAddingContacts = - sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForAddingContacts) ?? false; - final shouldRequireTOTP2FAForCreatingNewWallets = - sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets) ?? - false; - final shouldRequireTOTP2FAForAllSecurityAndBackupSettings = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ?? - false; - final useTOTP2FA = sharedPreferences.getBool(PreferencesKey.useTOTP2FA) ?? false; - final totpSecretKey = sharedPreferences.getString(PreferencesKey.totpSecretKey) ?? ''; final tokenTrialNumber = sharedPreferences.getInt(PreferencesKey.failedTotpTokenTrials) ?? 0; final shouldShowMarketPlaceInDashboard = sharedPreferences.getBool(PreferencesKey.shouldShowMarketPlaceInDashboard) ?? true; @@ -816,18 +799,14 @@ abstract class SettingsStoreBase with Store { actionListDisplayMode.addAll(deserializeActionlistDisplayModes( sharedPreferences.getInt(PreferencesKey.displayActionListModeKey) ?? defaultActionsMode)); var pinLength = sharedPreferences.getInt(PreferencesKey.currentPinLength); - final timeOutDuration = sharedPreferences.getInt(PreferencesKey.pinTimeOutDuration); - final seedPhraseCount = sharedPreferences.getInt(PreferencesKey.currentSeedPhraseLength); - final pinCodeTimeOutDuration = timeOutDuration != null - ? PinCodeRequiredDuration.deserialize(raw: timeOutDuration) - : defaultPinCodeTimeOutDuration; - final seedPhraseWordCount = seedPhraseCount != null - ? SeedPhraseLength.deserialize(raw: seedPhraseCount) - : defaultSeedPhraseLength; final sortBalanceBy = SortBalanceBy.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? 0]; final pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true; + final seedPhraseCount = sharedPreferences.getInt(PreferencesKey.currentSeedPhraseLength); + final seedPhraseWordCount = seedPhraseCount != null + ? SeedPhraseLength.deserialize(raw: seedPhraseCount) + : defaultSeedPhraseLength; final useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true; final usePolygonScan = sharedPreferences.getBool(PreferencesKey.usePolygonScan) ?? true; final defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? ""; @@ -929,7 +908,101 @@ abstract class SettingsStoreBase with Store { }); final savedSyncAll = sharedPreferences.getBool(PreferencesKey.syncAllKey) ?? true; + // migrated to secure: + final timeOutDuration = await SecureKey.getInt( + secureStorage: secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.pinTimeOutDuration, + ); + + final pinCodeTimeOutDuration = timeOutDuration != null + ? PinCodeRequiredDuration.deserialize(raw: timeOutDuration) + : defaultPinCodeTimeOutDuration; + + final allowBiometricalAuthentication = await SecureKey.getBool( + secureStorage: secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.pinTimeOutDuration, + ) ?? + false; + + final selectedCake2FAPreset = Cake2FAPresetsOptions.deserialize( + raw: await SecureKey.getInt( + secureStorage: secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.selectedCake2FAPreset, + ) ?? + Cake2FAPresetsOptions.normal.raw); + + final shouldRequireTOTP2FAForAccessingWallet = await SecureKey.getBool( + secureStorage: secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForAccessingWallet, + ) ?? + false; + final shouldRequireTOTP2FAForSendsToContact = await SecureKey.getBool( + secureStorage: secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForSendsToContact, + ) ?? + false; + final shouldRequireTOTP2FAForSendsToNonContact = await SecureKey.getBool( + secureStorage: secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForSendsToNonContact, + ) ?? + false; + final shouldRequireTOTP2FAForSendsToInternalWallets = await SecureKey.getBool( + secureStorage: secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForSendsToInternalWallets, + ) ?? + false; + final shouldRequireTOTP2FAForExchangesToInternalWallets = await SecureKey.getBool( + secureStorage: secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForExchangesToInternalWallets, + ) ?? + false; + final shouldRequireTOTP2FAForExchangesToExternalWallets = await SecureKey.getBool( + secureStorage: secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForExchangesToExternalWallets, + ) ?? + false; + final shouldRequireTOTP2FAForAddingContacts = await SecureKey.getBool( + secureStorage: secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForAddingContacts, + ) ?? + false; + final shouldRequireTOTP2FAForCreatingNewWallets = await SecureKey.getBool( + secureStorage: secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForCreatingNewWallets, + ) ?? + false; + final shouldRequireTOTP2FAForAllSecurityAndBackupSettings = await SecureKey.getBool( + secureStorage: secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings, + ) ?? + false; + final useTOTP2FA = await SecureKey.getBool( + secureStorage: secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.useTOTP2FA, + ) ?? + false; + final totpSecretKey = await SecureKey.getString( + secureStorage: secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.useTOTP2FA, + ) ?? + ''; + return SettingsStore( + secureStorage: secureStorage, sharedPreferences: sharedPreferences, initialShouldShowMarketPlaceInDashboard: shouldShowMarketPlaceInDashboard, nodes: nodes, @@ -1055,8 +1128,6 @@ abstract class SettingsStoreBase with Store { shouldSaveRecipientAddress = sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey) ?? shouldSaveRecipientAddress; - useTOTP2FA = sharedPreferences.getBool(PreferencesKey.useTOTP2FA) ?? useTOTP2FA; - totpSecretKey = sharedPreferences.getString(PreferencesKey.totpSecretKey) ?? totpSecretKey; numberOfFailedTokenTrials = sharedPreferences.getInt(PreferencesKey.failedTotpTokenTrials) ?? numberOfFailedTokenTrials; isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? isAppSecure; @@ -1065,41 +1136,10 @@ abstract class SettingsStoreBase with Store { walletListOrder = WalletListOrderType.values[sharedPreferences.getInt(PreferencesKey.walletListOrder) ?? 0]; walletListAscending = sharedPreferences.getBool(PreferencesKey.walletListAscending) ?? true; - allowBiometricalAuthentication = - sharedPreferences.getBool(PreferencesKey.allowBiometricalAuthenticationKey) ?? - allowBiometricalAuthentication; - selectedCake2FAPreset = Cake2FAPresetsOptions.deserialize( - raw: sharedPreferences.getInt(PreferencesKey.selectedCake2FAPreset) ?? - Cake2FAPresetsOptions.normal.raw); - shouldRequireTOTP2FAForAccessingWallet = - sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForAccessingWallet) ?? false; - shouldRequireTOTP2FAForSendsToContact = - sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToContact) ?? false; - shouldRequireTOTP2FAForSendsToNonContact = - sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToNonContact) ?? false; - shouldRequireTOTP2FAForSendsToInternalWallets = - sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForSendsToInternalWallets) ?? - false; - shouldRequireTOTP2FAForExchangesToInternalWallets = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToInternalWallets) ?? - false; - shouldRequireTOTP2FAForExchangesToExternalWallets = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForExchangesToExternalWallets) ?? - false; - shouldRequireTOTP2FAForAddingContacts = - sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForAddingContacts) ?? false; - shouldRequireTOTP2FAForCreatingNewWallets = - sharedPreferences.getBool(PreferencesKey.shouldRequireTOTP2FAForCreatingNewWallets) ?? - false; - shouldRequireTOTP2FAForAllSecurityAndBackupSettings = sharedPreferences - .getBool(PreferencesKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings) ?? - false; + shouldShowMarketPlaceInDashboard = sharedPreferences.getBool(PreferencesKey.shouldShowMarketPlaceInDashboard) ?? shouldShowMarketPlaceInDashboard; - selectedCake2FAPreset = Cake2FAPresetsOptions.deserialize( - raw: sharedPreferences.getInt(PreferencesKey.selectedCake2FAPreset) ?? - Cake2FAPresetsOptions.narrow.raw); exchangeStatus = ExchangeApiMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.exchangeStatusKey) ?? ExchangeApiMode.enabled.raw); @@ -1188,6 +1228,93 @@ abstract class SettingsStoreBase with Store { if (nanoNode != null) { nodes[WalletType.nano] = nanoNode; } + + // MIGRATED: + + useTOTP2FA = await SecureKey.getBool( + secureStorage: _secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.useTOTP2FA, + ) ?? + useTOTP2FA; + + totpSecretKey = await SecureKey.getString( + secureStorage: _secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.useTOTP2FA, + ) ?? + totpSecretKey; + + allowBiometricalAuthentication = await SecureKey.getBool( + secureStorage: _secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.allowBiometricalAuthenticationKey, + ) ?? + allowBiometricalAuthentication; + + selectedCake2FAPreset = Cake2FAPresetsOptions.deserialize( + raw: await SecureKey.getInt( + secureStorage: _secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.selectedCake2FAPreset, + ) ?? + Cake2FAPresetsOptions.normal.raw); + + shouldRequireTOTP2FAForAccessingWallet = await SecureKey.getBool( + secureStorage: _secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForAccessingWallet, + ) ?? + false; + shouldRequireTOTP2FAForSendsToContact = await SecureKey.getBool( + secureStorage: _secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForSendsToContact, + ) ?? + false; + + shouldRequireTOTP2FAForSendsToNonContact = await SecureKey.getBool( + secureStorage: _secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForSendsToNonContact, + ) ?? + false; + shouldRequireTOTP2FAForSendsToInternalWallets = await SecureKey.getBool( + secureStorage: _secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForSendsToInternalWallets, + ) ?? + false; + shouldRequireTOTP2FAForExchangesToInternalWallets = await SecureKey.getBool( + secureStorage: _secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForExchangesToInternalWallets, + ) ?? + false; + shouldRequireTOTP2FAForExchangesToExternalWallets = await SecureKey.getBool( + secureStorage: _secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForExchangesToExternalWallets, + ) ?? + false; + shouldRequireTOTP2FAForAddingContacts = await SecureKey.getBool( + secureStorage: _secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForAddingContacts, + ) ?? + false; + shouldRequireTOTP2FAForCreatingNewWallets = await SecureKey.getBool( + secureStorage: _secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForCreatingNewWallets, + ) ?? + false; + shouldRequireTOTP2FAForAllSecurityAndBackupSettings = await SecureKey.getBool( + secureStorage: _secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings, + ) ?? + false; } Future _saveCurrentNode(Node node, WalletType walletType) async { diff --git a/lib/view_model/settings/security_settings_view_model.dart b/lib/view_model/settings/security_settings_view_model.dart index 5ea4dd4ea..965e65af8 100644 --- a/lib/view_model/settings/security_settings_view_model.dart +++ b/lib/view_model/settings/security_settings_view_model.dart @@ -44,5 +44,5 @@ abstract class SecuritySettingsViewModelBase with Store { setPinCodeRequiredDuration(PinCodeRequiredDuration duration) => _settingsStore.pinTimeOutDuration = duration; - bool checkPinCodeRiquired() => _authService.requireAuth(); + Future checkPinCodeRiquired() => _authService.requireAuth(); } 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 407b6d3bc..a7e27cbf6 100644 --- a/lib/view_model/wallet_list/wallet_list_view_model.dart +++ b/lib/view_model/wallet_list/wallet_list_view_model.dart @@ -161,7 +161,7 @@ abstract class WalletListViewModelBase with Store { } } - bool checkIfAuthRequired() { + Future checkIfAuthRequired() async { return _authService.requireAuth(); } } From 9754d676012d2d5195ac0d1f56bc8c7f5f06c373 Mon Sep 17 00:00:00 2001 From: Serhii Date: Tue, 23 Jan 2024 07:15:24 +0200 Subject: [PATCH 099/241] Cw-343-a-list-of-previously-used-addresses (#1248) * add used addresses list * generate new address button * fix wallet type issue * fix addresses button title * update selectButton * show all wallet addresses * add tx amount and balance * fix ui * remove cashAddr format * fix generating new address issue * disable autogenerating * fix cashAddr format * minor fix * add search bar * Update address_cell.dart * fix merge conflict * address labeling feature * review fixes --------- Co-authored-by: Omar Hatem --- cw_bitcoin/lib/bitcoin_address_record.dart | 66 +++++-- cw_bitcoin/lib/bitcoin_wallet.dart | 3 + cw_bitcoin/lib/electrum_wallet.dart | 83 +++++--- cw_bitcoin/lib/electrum_wallet_addresses.dart | 182 ++++++++++-------- cw_bitcoin/lib/litecoin_wallet.dart | 3 + .../lib/src/bitcoin_cash_wallet.dart | 3 + cw_core/lib/amount_converter.dart | 1 + lib/bitcoin/cw_bitcoin.dart | 27 ++- lib/reactions/on_current_wallet_change.dart | 3 +- .../screens/dashboard/pages/address_page.dart | 68 ++----- .../new_wallet/widgets/select_button.dart | 32 +-- lib/src/screens/receive/receive_page.dart | 37 ++-- .../screens/receive/widgets/address_cell.dart | 180 ++++++++++++----- .../screens/receive/widgets/header_tile.dart | 138 +++++++++---- .../screens/receive/widgets/qr_widget.dart | 5 +- .../settings/privacy_settings_view_model.dart | 6 +- ...let_address_edit_or_create_view_model.dart | 20 +- .../wallet_address_list_item.dart | 9 +- .../wallet_address_list_view_model.dart | 104 +++++++--- tool/configure.dart | 24 ++- 20 files changed, 664 insertions(+), 330 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_address_record.dart b/cw_bitcoin/lib/bitcoin_address_record.dart index 392771ab0..f2cd63904 100644 --- a/cw_bitcoin/lib/bitcoin_address_record.dart +++ b/cw_bitcoin/lib/bitcoin_address_record.dart @@ -1,40 +1,70 @@ import 'dart:convert'; +import 'package:bitbox/bitbox.dart' as bitbox; class BitcoinAddressRecord { - BitcoinAddressRecord(this.address, - {required this.index, this.isHidden = false, bool isUsed = false}) - : _isUsed = isUsed; + BitcoinAddressRecord( + this.address, { + required this.index, + this.isHidden = false, + int txCount = 0, + int balance = 0, + String name = '', + bool isUsed = false, + }) : _txCount = txCount, + _balance = balance, + _name = name, + _isUsed = isUsed; factory BitcoinAddressRecord.fromJSON(String jsonSource) { final decoded = json.decode(jsonSource) as Map; - return BitcoinAddressRecord( - decoded['address'] as String, - index: decoded['index'] as int, - isHidden: decoded['isHidden'] as bool? ?? false, - isUsed: decoded['isUsed'] as bool? ?? false); + return BitcoinAddressRecord(decoded['address'] as String, + index: decoded['index'] as int, + isHidden: decoded['isHidden'] as bool? ?? false, + isUsed: decoded['isUsed'] as bool? ?? false, + txCount: decoded['txCount'] as int? ?? 0, + name: decoded['name'] as String? ?? '', + balance: decoded['balance'] as int? ?? 0); } - @override - bool operator ==(Object o) => - o is BitcoinAddressRecord && address == o.address; - final String address; final bool isHidden; final int index; + int _txCount; + int _balance; + String _name; + bool _isUsed; + + int get txCount => _txCount; + + String get name => _name; + + int get balance => _balance; + + set txCount(int value) => _txCount = value; + + set balance(int value) => _balance = value; + bool get isUsed => _isUsed; + void setAsUsed() => _isUsed = true; + void setNewName(String label) => _name = label; + + @override + bool operator ==(Object o) => o is BitcoinAddressRecord && address == o.address; + @override int get hashCode => address.hashCode; - bool _isUsed; + String get cashAddr => bitbox.Address.toCashAddress(address); - void setAsUsed() => _isUsed = true; - - String toJSON() => - json.encode({ + String toJSON() => json.encode({ 'address': address, 'index': index, 'isHidden': isHidden, - 'isUsed': isUsed}); + 'txCount': txCount, + 'name': name, + 'isUsed': isUsed, + 'balance': balance, + }); } diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 2c66d02fe..9cdb78f2d 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -47,6 +47,9 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType) .derivePath("m/0'/1"), networkType: networkType); + autorun((_) { + this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress; + }); } static Future create({ diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 4c5ecc7f2..6be525a1f 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -63,6 +63,7 @@ abstract class ElectrumWalletBase _password = password, _feeRates = [], _isTransactionUpdating = false, + isEnabledAutoGenerateSubaddress = true, unspentCoins = [], _scripthashesUpdateSubject = {}, balance = ObservableMap.of(currency != null @@ -87,6 +88,10 @@ abstract class ElectrumWalletBase final bitcoin.HDWallet hd; final String mnemonic; + @override + @observable + bool isEnabledAutoGenerateSubaddress; + late ElectrumClient electrumClient; Box unspentCoinsInfo; @@ -583,38 +588,66 @@ abstract class ElectrumWalletBase Future> fetchTransactions() async { final addressHashes = {}; final normalizedHistories = >[]; + final newTxCounts = {}; + walletAddresses.addresses.forEach((addressRecord) { final sh = scriptHash(addressRecord.address, networkType: networkType); addressHashes[sh] = addressRecord; + newTxCounts[sh] = 0; }); - final histories = addressHashes.keys.map((scriptHash) => - electrumClient.getHistory(scriptHash).then((history) => {scriptHash: history})); - final historyResults = await Future.wait(histories); - historyResults.forEach((history) { - history.entries.forEach((historyItem) { - if (historyItem.value.isNotEmpty) { - final address = addressHashes[historyItem.key]; - address?.setAsUsed(); - normalizedHistories.addAll(historyItem.value); - } + + try { + final histories = addressHashes.keys.map((scriptHash) => + electrumClient.getHistory(scriptHash).then((history) => {scriptHash: history})); + final historyResults = await Future.wait(histories); + + + + historyResults.forEach((history) { + history.entries.forEach((historyItem) { + if (historyItem.value.isNotEmpty) { + final address = addressHashes[historyItem.key]; + address?.setAsUsed(); + newTxCounts[historyItem.key] = historyItem.value.length; + normalizedHistories.addAll(historyItem.value); + } + }); }); - }); - final historiesWithDetails = await Future.wait(normalizedHistories.map((transaction) { - try { - return fetchTransactionInfo( - hash: transaction['tx_hash'] as String, height: transaction['height'] as int); - } catch (_) { - return Future.value(null); + + for (var sh in addressHashes.keys) { + var balanceData = await electrumClient.getBalance(sh); + var addressRecord = addressHashes[sh]; + if (addressRecord != null) { + addressRecord.balance = balanceData['confirmed'] as int? ?? 0; + } } - })); - return historiesWithDetails - .fold>({}, (acc, tx) { - if (tx == null) { + + + addressHashes.forEach((sh, addressRecord) { + addressRecord.txCount = newTxCounts[sh] ?? 0; + }); + + final historiesWithDetails = await Future.wait(normalizedHistories.map((transaction) { + try { + return fetchTransactionInfo( + hash: transaction['tx_hash'] as String, height: transaction['height'] as int); + } catch (_) { + return Future.value(null); + } + })); + + return historiesWithDetails.fold>( + {}, (acc, tx) { + if (tx == null) { + return acc; + } + acc[tx.id] = acc[tx.id]?.updated(tx) ?? tx; return acc; - } - acc[tx.id] = acc[tx.id]?.updated(tx) ?? tx; - return acc; - }); + }); + } catch (e) { + print(e.toString()); + return {}; + } } Future updateTransactions() async { diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index c9e4f8200..a60a7e8ec 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -1,5 +1,5 @@ -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:bitbox/bitbox.dart' as bitbox; +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/script_hash.dart'; @@ -10,8 +10,7 @@ import 'package:mobx/mobx.dart'; part 'electrum_wallet_addresses.g.dart'; -class ElectrumWalletAddresses = ElectrumWalletAddressesBase - with _$ElectrumWalletAddresses; +class ElectrumWalletAddresses = ElectrumWalletAddressesBase with _$ElectrumWalletAddresses; abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { ElectrumWalletAddressesBase(WalletInfo walletInfo, @@ -22,19 +21,16 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { List? initialAddresses, int initialRegularAddressIndex = 0, int initialChangeAddressIndex = 0}) - : addresses = ObservableList.of( - (initialAddresses ?? []).toSet()), - receiveAddresses = ObservableList.of( - (initialAddresses ?? []) + : addresses = ObservableList.of((initialAddresses ?? []).toSet()), + receiveAddresses = ObservableList.of((initialAddresses ?? []) .where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed) - .toSet()), - changeAddresses = ObservableList.of( - (initialAddresses ?? []) + .toSet()), + changeAddresses = ObservableList.of((initialAddresses ?? []) .where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed) - .toSet()), + .toSet()), currentReceiveAddressIndex = initialRegularAddressIndex, currentChangeAddressIndex = initialChangeAddressIndex, - super(walletInfo); + super(walletInfo); static const defaultReceiveAddressesCount = 22; static const defaultChangeAddressesCount = 17; @@ -42,6 +38,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { static String toCashAddr(String address) => bitbox.Address.toCashAddress(address); + static String toLegacy(String address) => bitbox.Address.toLegacyAddress(address); + final ObservableList addresses; final ObservableList receiveAddresses; final ObservableList changeAddresses; @@ -53,41 +51,67 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @override @computed String get address { - if (receiveAddresses.isEmpty) { - final address = generateNewAddress().address; - return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(address) : address; - } - final receiveAddress = receiveAddresses.first.address; + if (isEnabledAutoGenerateSubaddress) { + if (receiveAddresses.isEmpty) { + final newAddress = generateNewAddress().address; + return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(newAddress) : newAddress; + } + final receiveAddress = receiveAddresses.first.address; - return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(receiveAddress) : receiveAddress; + return walletInfo.type == WalletType.bitcoinCash + ? toCashAddr(receiveAddress) + : receiveAddress; + } else { + final receiveAddress = (receiveAddresses.first.address != addresses.first.address && + previousAddressRecord != null) + ? previousAddressRecord!.address + : addresses.first.address; + + return walletInfo.type == WalletType.bitcoinCash + ? toCashAddr(receiveAddress) + : receiveAddress; + } + } + + @observable + bool isEnabledAutoGenerateSubaddress = true; + + @override + set address(String addr) { + if (addr.startsWith('bitcoincash:')) { + addr = toLegacy(addr); + } + final addressRecord = addresses.firstWhere((addressRecord) => addressRecord.address == addr); + + previousAddressRecord = addressRecord; + receiveAddresses.remove(addressRecord); + receiveAddresses.insert(0, addressRecord); } @override String get primaryAddress => getAddress(index: 0, hd: mainHd); - @override - set address(String addr) => null; - int currentReceiveAddressIndex; int currentChangeAddressIndex; - @computed - int get totalCountOfReceiveAddresses => - addresses.fold(0, (acc, addressRecord) { - if (!addressRecord.isHidden) { - return acc + 1; - } - return acc; - }); + @observable + BitcoinAddressRecord? previousAddressRecord; @computed - int get totalCountOfChangeAddresses => - addresses.fold(0, (acc, addressRecord) { - if (addressRecord.isHidden) { - return acc + 1; - } - return acc; - }); + int get totalCountOfReceiveAddresses => addresses.fold(0, (acc, addressRecord) { + if (!addressRecord.isHidden) { + return acc + 1; + } + return acc; + }); + + @computed + int get totalCountOfChangeAddresses => addresses.fold(0, (acc, addressRecord) { + if (addressRecord.isHidden) { + return acc + 1; + } + return acc; + }); Future discoverAddresses() async { await _discoverAddresses(mainHd, false); @@ -117,11 +141,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { if (changeAddresses.isEmpty) { final newAddresses = await _createNewAddresses(gap, - hd: sideHd, - startIndex: totalCountOfChangeAddresses > 0 - ? totalCountOfChangeAddresses - 1 - : 0, - isHidden: true); + hd: sideHd, + startIndex: totalCountOfChangeAddresses > 0 ? totalCountOfChangeAddresses - 1 : 0, + isHidden: true); _addAddresses(newAddresses); } @@ -135,14 +157,14 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { return address; } - BitcoinAddressRecord generateNewAddress( - {bitcoin.HDWallet? hd, bool isHidden = false}) { - currentReceiveAddressIndex += 1; - // FIX-ME: Check logic for whichi HD should be used here ??? - final address = BitcoinAddressRecord( - getAddress(index: currentReceiveAddressIndex, hd: hd ?? sideHd), - index: currentReceiveAddressIndex, - isHidden: isHidden); + BitcoinAddressRecord generateNewAddress({bitcoin.HDWallet? hd, String? label}) { + final isHidden = hd == sideHd; + + final newAddressIndex = addresses.fold( + 0, (int acc, addressRecord) => isHidden == addressRecord.isHidden ? acc + 1 : acc); + + final address = BitcoinAddressRecord(getAddress(index: newAddressIndex, hd: hd ?? sideHd), + index: newAddressIndex, isHidden: isHidden, name: label ?? ''); addresses.add(address); return address; } @@ -160,20 +182,32 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } } + @action + void updateAddress(String address, String label) { + if (address.startsWith('bitcoincash:')) { + address = toLegacy(address); + } + final addressRecord = addresses.firstWhere((addressRecord) => addressRecord.address == address); + addressRecord.setNewName(label); + final index = addresses.indexOf(addressRecord); + addresses.remove(addressRecord); + addresses.insert(index, addressRecord); + } + @action void updateReceiveAddresses() { receiveAddresses.removeRange(0, receiveAddresses.length); - final newAdresses = addresses - .where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed); - receiveAddresses.addAll(newAdresses); + final newAddresses = + addresses.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed); + receiveAddresses.addAll(newAddresses); } @action void updateChangeAddresses() { changeAddresses.removeRange(0, changeAddresses.length); - final newAdresses = addresses - .where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed); - changeAddresses.addAll(newAdresses); + final newAddresses = + addresses.where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed); + changeAddresses.addAll(newAddresses); } Future _discoverAddresses(bitcoin.HDWallet hd, bool isHidden) async { @@ -181,20 +215,16 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { List addrs; if (addresses.isNotEmpty) { - addrs = addresses - .where((addr) => addr.isHidden == isHidden) - .toList(); + addrs = addresses.where((addr) => addr.isHidden == isHidden).toList(); } else { addrs = await _createNewAddresses( - isHidden - ? defaultChangeAddressesCount - : defaultReceiveAddressesCount, + isHidden ? defaultChangeAddressesCount : defaultReceiveAddressesCount, startIndex: 0, hd: hd, isHidden: isHidden); } - while(hasAddrUse) { + while (hasAddrUse) { final addr = addrs.last.address; hasAddrUse = await _hasAddressUsed(addr); @@ -204,11 +234,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { final start = addrs.length; final count = start + gap; - final batch = await _createNewAddresses( - count, - startIndex: start, - hd: hd, - isHidden: isHidden); + final batch = await _createNewAddresses(count, startIndex: start, hd: hd, isHidden: isHidden); addrs.addAll(batch); } @@ -232,21 +258,15 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { if (countOfReceiveAddresses < defaultReceiveAddressesCount) { final addressesCount = defaultReceiveAddressesCount - countOfReceiveAddresses; - final newAddresses = await _createNewAddresses( - addressesCount, - startIndex: countOfReceiveAddresses, - hd: mainHd, - isHidden: false); + final newAddresses = await _createNewAddresses(addressesCount, + startIndex: countOfReceiveAddresses, hd: mainHd, isHidden: false); addresses.addAll(newAddresses); } if (countOfHiddenAddresses < defaultChangeAddressesCount) { final addressesCount = defaultChangeAddressesCount - countOfHiddenAddresses; - final newAddresses = await _createNewAddresses( - addressesCount, - startIndex: countOfHiddenAddresses, - hd: sideHd, - isHidden: true); + final newAddresses = await _createNewAddresses(addressesCount, + startIndex: countOfHiddenAddresses, hd: sideHd, isHidden: true); addresses.addAll(newAddresses); } } @@ -256,10 +276,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { final list = []; for (var i = startIndex; i < count + startIndex; i++) { - final address = BitcoinAddressRecord( - getAddress(index: i, hd: hd), - index: i, - isHidden: isHidden); + final address = + BitcoinAddressRecord(getAddress(index: i, hd: hd), index: i, isHidden: isHidden); list.add(address); } @@ -278,4 +296,4 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { final transactionHistory = await electrumClient.getHistory(sh); return transactionHistory.isNotEmpty; } -} \ No newline at end of file +} diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 6bf1c5735..222e95acc 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -51,6 +51,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { .fromSeed(seedBytes, network: networkType) .derivePath("m/0'/1"), networkType: networkType,); + autorun((_) { + this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress; + }); } static Future create({ diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index c23220423..1b87e2231 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -57,6 +57,9 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { sideHd: bitcoin.HDWallet.fromSeed(seedBytes) .derivePath("m/44'/145'/0'/1"), networkType: networkType); + autorun((_) { + this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress; + }); } diff --git a/cw_core/lib/amount_converter.dart b/cw_core/lib/amount_converter.dart index 6fd43dd82..249b87bd3 100644 --- a/cw_core/lib/amount_converter.dart +++ b/cw_core/lib/amount_converter.dart @@ -81,6 +81,7 @@ class AmountConverter { return _moneroAmountToString(amount); case CryptoCurrency.btc: case CryptoCurrency.bch: + case CryptoCurrency.ltc: return _bitcoinAmountToString(amount); case CryptoCurrency.xhv: case CryptoCurrency.xag: diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index dd713fd15..b6fb6e62d 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -63,9 +63,17 @@ class CWBitcoin extends Bitcoin { } @override - Future generateNewAddress(Object wallet) async { + Future generateNewAddress(Object wallet, String label) async { final bitcoinWallet = wallet as ElectrumWallet; - await bitcoinWallet.walletAddresses.generateNewAddress(); + await bitcoinWallet.walletAddresses.generateNewAddress(label: label); + await wallet.save(); + } + + @override + Future updateAddress(Object wallet,String address, String label) async { + final bitcoinWallet = wallet as ElectrumWallet; + bitcoinWallet.walletAddresses.updateAddress(address, label); + await wallet.save(); } @override @@ -99,6 +107,21 @@ class CWBitcoin extends Bitcoin { .toList(); } + @override + @computed + List getSubAddresses(Object wallet) { + final electrumWallet = wallet as ElectrumWallet; + return electrumWallet.walletAddresses.addresses + .map((BitcoinAddressRecord addr) => ElectrumSubAddress( + id: addr.index, + name: addr.name, + address: electrumWallet.type == WalletType.bitcoinCash ? addr.cashAddr : addr.address, + txCount: addr.txCount, + balance: addr.balance, + isChange: addr.isHidden)) + .toList(); + } + @override String getAddress(Object wallet) { final bitcoinWallet = wallet as ElectrumWallet; diff --git a/lib/reactions/on_current_wallet_change.dart b/lib/reactions/on_current_wallet_change.dart index 42fbd182e..ade9927ff 100644 --- a/lib/reactions/on_current_wallet_change.dart +++ b/lib/reactions/on_current_wallet_change.dart @@ -68,7 +68,8 @@ void startCurrentWalletChangeReaction( .get() .setInt(PreferencesKey.currentWalletType, serializeToInt(wallet.type)); - if (wallet.type == WalletType.monero) { + if (wallet.type == WalletType.monero || wallet.type == WalletType.bitcoin || + wallet.type == WalletType.litecoin || wallet.type == WalletType.bitcoinCash ) { _setAutoGenerateSubaddressStatus(wallet, settingsStore); } diff --git a/lib/src/screens/dashboard/pages/address_page.dart b/lib/src/screens/dashboard/pages/address_page.dart index ff21d4aad..b4460edc9 100644 --- a/lib/src/screens/dashboard/pages/address_page.dart +++ b/lib/src/screens/dashboard/pages/address_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart'; import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; @@ -15,6 +16,7 @@ import 'package:cake_wallet/utils/share_util.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart'; import 'package:cake_wallet/src/screens/receive/widgets/qr_widget.dart'; @@ -155,63 +157,27 @@ class AddressPage extends BasePage { amountController: _amountController, isLight: dashboardViewModel.settingsStore.currentTheme.type == ThemeType.light))), + SizedBox(height: 16), Observer(builder: (_) { if (addressListViewModel.hasAddressList) { - return GestureDetector( - onTap: () async => dashboardViewModel.isAutoGenerateSubaddressesEnabled + return SelectButton( + text: addressListViewModel.buttonTitle, + onTap: () async => dashboardViewModel.isAutoGenerateSubaddressesEnabled && + (WalletType.monero == addressListViewModel.wallet.type || + WalletType.haven == addressListViewModel.wallet.type) ? await showPopUp( - context: context, builder: (_) => getIt.get()) + context: context, + builder: (_) => getIt.get()) : Navigator.of(context).pushNamed(Routes.receive), - child: Container( - height: 50, - padding: EdgeInsets.only(left: 24, right: 12), - alignment: Alignment.center, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(25)), - border: Border.all( - color: - Theme.of(context).extension()!.cardBorderColor, - width: 1), - color: Theme.of(context) - .extension()! - .syncedBackgroundColor), - child: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Observer( - builder: (_) { - String label = addressListViewModel.hasAccounts - ? S.of(context).accounts_subaddresses - : S.of(context).addresses; - - if (dashboardViewModel.isAutoGenerateSubaddressesEnabled) { - label = addressListViewModel.hasAccounts - ? S.of(context).accounts - : S.of(context).account; - } - return Text( - label, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Theme.of(context) - .extension()! - .textColor), - ); - }, - ), - Icon( - Icons.arrow_forward_ios, - size: 14, - color: Theme.of(context).extension()!.textColor, - ) - ], - ), - ), + textColor: Theme.of(context).extension()!.textColor, + color: Theme.of(context).extension()!.syncedBackgroundColor, + borderColor: Theme.of(context).extension()!.cardBorderColor, + arrowColor: Theme.of(context).extension()!.textColor, + textSize: 14, + height: 50, ); } else if (dashboardViewModel.isAutoGenerateSubaddressesEnabled || - addressListViewModel.showElectrumAddressDisclaimer) { + addressListViewModel.isElectrumWallet) { return Text(S.of(context).electrum_address_disclaimer, textAlign: TextAlign.center, style: TextStyle( diff --git a/lib/src/screens/new_wallet/widgets/select_button.dart b/lib/src/screens/new_wallet/widgets/select_button.dart index e220b281e..d94c9767d 100644 --- a/lib/src/screens/new_wallet/widgets/select_button.dart +++ b/lib/src/screens/new_wallet/widgets/select_button.dart @@ -11,29 +11,37 @@ class SelectButton extends StatelessWidget { this.isSelected = false, this.showTrailingIcon = true, this.height = 60, + this.textSize = 18, + this.color, + this.textColor, + this.arrowColor, + this.borderColor, }); final Image? image; final String text; + final double textSize; final bool isSelected; final VoidCallback onTap; final bool showTrailingIcon; final double height; + final Color? color; + final Color? textColor; + final Color? arrowColor; + final Color? borderColor; @override Widget build(BuildContext context) { - final color = isSelected - ? Colors.green - : Theme.of(context).cardColor; - final textColor = isSelected + final backgroundColor = color ?? (isSelected ? Colors.green : Theme.of(context).cardColor); + final effectiveTextColor = textColor ?? (isSelected ? Theme.of(context).extension()!.restoreWalletButtonTextColor - : Theme.of(context).extension()!.buttonTextColor; - final arrowColor = isSelected + : Theme.of(context).extension()!.buttonTextColor); + final effectiveArrowColor = arrowColor ?? (isSelected ? Theme.of(context).extension()!.restoreWalletButtonTextColor - : Theme.of(context).extension()!.titlesColor; + : Theme.of(context).extension()!.titlesColor); final selectArrowImage = Image.asset('assets/images/select_arrow.png', - color: arrowColor); + color: effectiveArrowColor); return GestureDetector( onTap: onTap, @@ -44,7 +52,9 @@ class SelectButton extends StatelessWidget { alignment: Alignment.center, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(30)), - color: color + color: backgroundColor, + border: borderColor != null ? Border.all(color: borderColor!) : null, + ), child: Row( mainAxisSize: MainAxisSize.max, @@ -63,9 +73,9 @@ class SelectButton extends StatelessWidget { child: Text( text, style: TextStyle( - fontSize: 18, + fontSize: textSize, fontWeight: FontWeight.w500, - color: textColor + color: effectiveTextColor, ), ), ) diff --git a/lib/src/screens/receive/receive_page.dart b/lib/src/screens/receive/receive_page.dart index 87b668e34..75719d123 100644 --- a/lib/src/screens/receive/receive_page.dart +++ b/lib/src/screens/receive/receive_page.dart @@ -49,7 +49,7 @@ class ReceivePage extends BasePage { bool get gradientBackground => true; @override - bool get resizeToAvoidBottomInset => false; + bool get resizeToAvoidBottomInset => true; final FocusNode _cryptoAmountFocus; @@ -99,10 +99,11 @@ class ReceivePage extends BasePage { @override Widget body(BuildContext context) { + final isElectrumWallet = addressListViewModel.isElectrumWallet; return (addressListViewModel.type == WalletType.monero || addressListViewModel.type == WalletType.haven || addressListViewModel.type == WalletType.nano || - addressListViewModel.type == WalletType.banano) + isElectrumWallet) ? KeyboardActions( config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, @@ -140,7 +141,9 @@ class ReceivePage extends BasePage { if (item is WalletAccountListHeader) { cell = HeaderTile( - onTap: () async { + showTrailingButton: true, + walletAddressListViewModel: addressListViewModel, + trailingButtonTap: () async { if (addressListViewModel.type == WalletType.monero || addressListViewModel.type == WalletType.haven) { await showPopUp( @@ -153,7 +156,7 @@ class ReceivePage extends BasePage { } }, title: S.of(context).accounts, - icon: Icon( + trailingIcon: Icon( Icons.arrow_forward_ios, size: 14, color: Theme.of(context).extension()!.iconsColor, @@ -161,16 +164,21 @@ class ReceivePage extends BasePage { } if (item is WalletAddressListHeader) { - cell = HeaderTile( - onTap: () => - Navigator.of(context).pushNamed(Routes.newSubaddress), - title: S.of(context).addresses, - icon: Icon( - Icons.add, - size: 20, - color: Theme.of(context).extension()!.iconsColor, - )); - } + cell = HeaderTile( + title: S.of(context).addresses, + walletAddressListViewModel: addressListViewModel, + showTrailingButton: !addressListViewModel.isAutoGenerateSubaddressEnabled, + showSearchButton: true, + trailingButtonTap: () => + Navigator.of(context).pushNamed(Routes.newSubaddress), + trailingIcon: Icon( + Icons.add, + size: 20, + color: Theme.of(context) + .extension()! + .iconsColor, + )); + } if (item is WalletAddressListItem) { cell = Observer(builder: (_) { @@ -185,6 +193,7 @@ class ReceivePage extends BasePage { return AddressCell.fromItem(item, isCurrent: isCurrent, + hasBalance: addressListViewModel.isElectrumWallet, backgroundColor: backgroundColor, textColor: textColor, onTap: (_) => addressListViewModel.setAddress(item), diff --git a/lib/src/screens/receive/widgets/address_cell.dart b/lib/src/screens/receive/widgets/address_cell.dart index 733612e0b..92c870421 100644 --- a/lib/src/screens/receive/widgets/address_cell.dart +++ b/lib/src/screens/receive/widgets/address_cell.dart @@ -1,7 +1,8 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_slidable/flutter_slidable.dart'; +import 'package:auto_size_text/auto_size_text.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; class AddressCell extends StatelessWidget { AddressCell( @@ -12,13 +13,18 @@ class AddressCell extends StatelessWidget { required this.backgroundColor, required this.textColor, this.onTap, - this.onEdit}); + this.onEdit, + this.txCount, + this.balance, + this.isChange = false, + this.hasBalance = false}); factory AddressCell.fromItem(WalletAddressListItem item, {required bool isCurrent, required Color backgroundColor, required Color textColor, Function(String)? onTap, + bool hasBalance = false, Function()? onEdit}) => AddressCell( address: item.address, @@ -28,7 +34,11 @@ class AddressCell extends StatelessWidget { backgroundColor: backgroundColor, textColor: textColor, onTap: onTap, - onEdit: onEdit); + onEdit: onEdit, + txCount: item.txCount, + balance: item.balance, + isChange: item.isChange, + hasBalance: hasBalance); final String address; final String name; @@ -38,17 +48,22 @@ class AddressCell extends StatelessWidget { final Color textColor; final Function(String)? onTap; final Function()? onEdit; + final int? txCount; + final String? balance; + final bool isChange; + final bool hasBalance; - String get label { - if (name.isEmpty){ - if(address.length<=16){ - return address; - }else{ - return address.substring(0,8)+'...'+ - address.substring(address.length-8,address.length); - } - }else{ - return name; + static const int addressPreviewLength = 8; + + String get formattedAddress { + final formatIfCashAddr = address.replaceAll('bitcoincash:', ''); + + if (formatIfCashAddr.length <= (name.isNotEmpty ? 16 : 43)) { + return formatIfCashAddr; + } else { + return formatIfCashAddr.substring(0, addressPreviewLength) + + '...' + + formatIfCashAddr.substring(formatIfCashAddr.length - addressPreviewLength, formatIfCashAddr.length); } } @@ -59,41 +74,114 @@ class AddressCell extends StatelessWidget { child: Container( width: double.infinity, color: backgroundColor, - padding: EdgeInsets.only(left: 24, right: 24, top: 28, bottom: 28), - child: Text( - label, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 14, - color: textColor, - ), + padding: EdgeInsets.only(left: 24, right: 24, top: 20, bottom: 20), + child: Row( + children: [ + Expanded( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + if (isChange) + Padding( + padding: const EdgeInsets.only(right: 8.0), + child: Container( + height: 20, + padding: EdgeInsets.all(4), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(8.5)), + color: textColor), + alignment: Alignment.center, + child: Text( + S.of(context).unspent_change, + style: TextStyle( + color: backgroundColor, + fontSize: 10, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + if (name.isNotEmpty) + Text( + '$name - ', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + color: textColor, + ), + ), + AutoSizeText( + formattedAddress, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: isChange ? 10 : 14, + color: textColor, + ), + ), + ], + ), + if (hasBalance) + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, + children: [ + Text( + 'Balance: $balance', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: textColor, + ), + ), + Text( + '${S.of(context).transactions.toLowerCase()}: $txCount', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: textColor, + ), + ), + ], + ), + ), + ], + ), + ), + ], ), )); - return Semantics( - label: S.of(context).slidable, - selected: isCurrent, - enabled: !isCurrent, - child: Slidable( - key: Key(address), - startActionPane: _actionPane(context), - endActionPane: _actionPane(context), - child: cell, - ), - ); + return onEdit == null + ? cell + : Semantics( + label: S.of(context).slidable, + selected: isCurrent, + enabled: !isCurrent, + child: Slidable( + key: Key(address), + startActionPane: _actionPane(context), + endActionPane: _actionPane(context), + child: cell, + ), + ); } ActionPane _actionPane(BuildContext context) => ActionPane( - motion: const ScrollMotion(), - extentRatio: 0.3, - children: [ - SlidableAction( - onPressed: (_) => onEdit?.call(), - backgroundColor: Colors.blue, - foregroundColor: Colors.white, - icon: Icons.edit, - label: S.of(context).edit, - ), - ], - ); + motion: const ScrollMotion(), + extentRatio: 0.3, + children: [ + SlidableAction( + onPressed: (_) => onEdit?.call(), + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + icon: Icons.edit, + label: S.of(context).edit, + ), + ], + ); } diff --git a/lib/src/screens/receive/widgets/header_tile.dart b/lib/src/screens/receive/widgets/header_tile.dart index e9c134ea5..faaa9ed07 100644 --- a/lib/src/screens/receive/widgets/header_tile.dart +++ b/lib/src/screens/receive/widgets/header_tile.dart @@ -1,50 +1,114 @@ -import 'package:flutter/material.dart'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; +import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart'; +import 'package:flutter/material.dart'; -class HeaderTile extends StatelessWidget { +class HeaderTile extends StatefulWidget { HeaderTile({ - required this.onTap, required this.title, - required this.icon + required this.walletAddressListViewModel, + this.showSearchButton = false, + this.showTrailingButton = false, + this.trailingButtonTap, + this.trailingIcon, }); - final VoidCallback onTap; final String title; - final Icon icon; + final WalletAddressListViewModel walletAddressListViewModel; + final bool showSearchButton; + final bool showTrailingButton; + final VoidCallback? trailingButtonTap; + final Icon? trailingIcon; + + @override + _HeaderTileState createState() => _HeaderTileState(); +} + +class _HeaderTileState extends State { + bool _isSearchActive = false; @override Widget build(BuildContext context) { - return GestureDetector( - onTap: onTap, - child: Container( - padding: EdgeInsets.only( - left: 24, - right: 24, - top: 24, - bottom: 24 - ), - color: Theme.of(context).extension()!.tilesBackgroundColor, - child: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - title, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - color: Theme.of(context).extension()!.tilesTextColor), - ), - Container( - height: 32, - width: 32, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Theme.of(context).extension()!.iconsBackgroundColor), - child: icon, - ) - ], - ), + final searchIcon = Image.asset("assets/images/search_icon.png", + color: Theme.of(context).extension()!.iconsColor); + + return Container( + padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12), + color: Theme.of(context).extension()!.tilesBackgroundColor, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _isSearchActive + ? Expanded( + child: TextField( + onChanged: (value) => widget.walletAddressListViewModel.updateSearchText(value), + cursorColor: Theme.of(context).extension()!.tilesTextColor, + cursorWidth: 0.5, + decoration: InputDecoration( + hintText: '${S.of(context).search}...', + isDense: true, + contentPadding: EdgeInsets.zero, + hintStyle: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Theme.of(context).extension()!.tilesTextColor), + border: UnderlineInputBorder( + borderSide: BorderSide(color: Theme.of(context).dividerColor), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide(color: Theme.of(context).dividerColor), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide(color: Theme.of(context).dividerColor), + ), + ), + autofocus: true, + ), + ) + : Text( + widget.title, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Theme.of(context).extension()!.tilesTextColor), + ), + Row( + children: [ + if (widget.showSearchButton) + GestureDetector( + onTap: () { + setState(() { + _isSearchActive = !_isSearchActive; + widget.walletAddressListViewModel.updateSearchText(''); + }); + }, + child: Container( + height: 32, + width: 32, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Theme.of(context) + .extension()! + .iconsBackgroundColor), + child: searchIcon, + )), + const SizedBox(width: 8), + if (widget.showTrailingButton) + GestureDetector( + onTap: widget.trailingButtonTap, + child: Container( + height: 32, + width: 32, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: + Theme.of(context).extension()!.iconsBackgroundColor), + child: widget.trailingIcon, + ), + ), + ], + ), + ], ), ); } diff --git a/lib/src/screens/receive/widgets/qr_widget.dart b/lib/src/screens/receive/widgets/qr_widget.dart index bbfd4d5c1..bedb3b526 100644 --- a/lib/src/screens/receive/widgets/qr_widget.dart +++ b/lib/src/screens/receive/widgets/qr_widget.dart @@ -1,3 +1,4 @@ +import 'package:auto_size_text/auto_size_text.dart'; import 'package:cake_wallet/entities/qr_view_data.dart'; import 'package:cake_wallet/themes/extensions/qr_code_theme.dart'; import 'package:cake_wallet/routes.dart'; @@ -6,6 +7,7 @@ import 'package:cake_wallet/src/screens/receive/widgets/currency_input_field.dar import 'package:cake_wallet/utils/brightness_util.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -144,9 +146,10 @@ class QRWidget extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( - child: Text( + child: AutoSizeText( addressListViewModel.address.address, textAlign: TextAlign.center, + maxLines: addressListViewModel.wallet.type == WalletType.monero ? 2 : 1, style: TextStyle( fontSize: 15, fontWeight: FontWeight.w500, diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart index e4dd86b37..65375b3e7 100644 --- a/lib/view_model/settings/privacy_settings_view_model.dart +++ b/lib/view_model/settings/privacy_settings_view_model.dart @@ -38,7 +38,11 @@ abstract class PrivacySettingsViewModelBase with Store { } } - bool get isAutoGenerateSubaddressesVisible => _wallet.type == WalletType.monero; + bool get isAutoGenerateSubaddressesVisible => + _wallet.type == WalletType.monero || + _wallet.type == WalletType.bitcoin || + _wallet.type == WalletType.litecoin || + _wallet.type == WalletType.bitcoinCash; @computed bool get shouldSaveRecipientAddress => _settingsStore.shouldSaveRecipientAddress; diff --git a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart index 9e2aa7187..0b4f969cb 100644 --- a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart @@ -1,6 +1,5 @@ import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart'; import 'package:mobx/mobx.dart'; -import 'package:flutter/foundation.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/monero/monero.dart'; @@ -33,7 +32,7 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store { state = AddressEditOrCreateStateInitial(), label = item?.name ?? '', _item = item, - _wallet = wallet; + _wallet = wallet; @observable AddressEditOrCreateState state; @@ -46,6 +45,10 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store { final WalletAddressListItem? _item; final WalletBase _wallet; + bool get isElectrum => _wallet.type == WalletType.bitcoin || + _wallet.type == WalletType.bitcoinCash || + _wallet.type == WalletType.litecoin; + Future save() async { try { state = AddressIsSaving(); @@ -65,12 +68,7 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store { Future _createNew() async { final wallet = _wallet; - if (wallet.type == WalletType.bitcoin - || wallet.type == WalletType.litecoin - || wallet.type == WalletType.bitcoinCash) { - await bitcoin!.generateNewAddress(wallet); - await wallet.save(); - } + if (isElectrum) await bitcoin!.generateNewAddress(wallet, label); if (wallet.type == WalletType.monero) { await monero @@ -96,10 +94,8 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store { Future _update() async { final wallet = _wallet; - /*if (wallet is BitcoinWallet) { - await wallet.walletAddresses.updateAddress(_item.address as String); - await wallet.save(); - }*/ + if (isElectrum) await bitcoin!.updateAddress(wallet, _item!.address, label); + final index = _item?.id; if (index != null) { if (wallet.type == WalletType.monero) { diff --git a/lib/view_model/wallet_address_list/wallet_address_list_item.dart b/lib/view_model/wallet_address_list/wallet_address_list_item.dart index ba7b93cf9..1152f1404 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_item.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_item.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:cake_wallet/utils/list_item.dart'; class WalletAddressListItem extends ListItem { @@ -6,13 +5,19 @@ class WalletAddressListItem extends ListItem { required this.address, required this.isPrimary, this.id, - this.name}) + this.name, + this.txCount, + this.balance, + this.isChange = false}) : super(); final int? id; final bool isPrimary; final String address; final String? name; + final int? txCount; + final String? balance; + final bool isChange; @override String toString() => name ?? address; diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index ade279124..9270d1d44 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -1,21 +1,25 @@ +import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/core/wallet_change_listener_view_model.dart'; -import 'package:cake_wallet/ethereum/ethereum.dart'; +import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; +import 'package:cake_wallet/ethereum/ethereum.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/haven/haven.dart'; +import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; +import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; -import 'package:cw_core/currency.dart'; -import 'package:intl/intl.dart'; -import 'package:mobx/mobx.dart'; import 'package:cake_wallet/utils/list_item.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_account_list_header.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_header.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart'; +import 'package:cw_core/amount_converter.dart'; +import 'package:cw_core/currency.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:cake_wallet/bitcoin/bitcoin.dart'; -import 'package:cake_wallet/store/app_store.dart'; -import 'package:cake_wallet/monero/monero.dart'; -import 'package:cake_wallet/haven/haven.dart'; +import 'package:intl/intl.dart'; +import 'package:mobx/mobx.dart'; part 'wallet_address_list_view_model.g.dart'; @@ -110,7 +114,8 @@ class EthereumURI extends PaymentURI { class BitcoinCashURI extends PaymentURI { BitcoinCashURI({required String amount, required String address}) - : super(amount: amount, address: address); + : super(amount: amount, address: address); + @override String toString() { var base = address; @@ -121,9 +126,7 @@ class BitcoinCashURI extends PaymentURI { return base; } - } - - +} class NanoURI extends PaymentURI { NanoURI({required String amount, required String address}) @@ -167,6 +170,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo hasAccounts = appStore.wallet!.type == WalletType.monero || appStore.wallet!.type == WalletType.haven, amount = '', + _settingsStore = appStore.settingsStore, super(appStore: appStore) { _init(); } @@ -184,12 +188,28 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo final NumberFormat _cryptoNumberFormat; final FiatConversionStore fiatConversionStore; + final SettingsStore _settingsStore; List get currencies => [walletTypeToCryptoCurrency(wallet.type), ...FiatCurrency.all]; + String get buttonTitle { + if (isElectrumWallet) { + return S.current.addresses; + } + + if (isAutoGenerateSubaddressEnabled) { + return hasAccounts ? S.current.accounts : S.current.account; + } + + return hasAccounts ? S.current.accounts_subaddresses : S.current.addresses; + } + @observable Currency selectedCurrency; + @observable + String searchText = ''; + @computed int get selectedCurrencyIndex => currencies.indexOf(selectedCurrency); @@ -277,14 +297,21 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo addressList.addAll(addressItems); } - if (wallet.type == WalletType.bitcoin) { - final primaryAddress = bitcoin!.getAddress(wallet); - final bitcoinAddresses = bitcoin!.getAddresses(wallet).map((addr) { - final isPrimary = addr == primaryAddress; + if (isElectrumWallet) { + final addressItems = bitcoin!.getSubAddresses(wallet).map((subaddress) { + final isPrimary = subaddress.id == 0; - return WalletAddressListItem(isPrimary: isPrimary, name: null, address: addr); + return WalletAddressListItem( + id: subaddress.id, + isPrimary: isPrimary, + name: subaddress.name, + address: subaddress.address, + txCount: subaddress.txCount, + balance: AmountConverter.amountIntToString( + walletTypeToCryptoCurrency(type), subaddress.balance), + isChange: subaddress.isChange); }); - addressList.addAll(bitcoinAddresses); + addressList.addAll(addressItems); } if (wallet.type == WalletType.ethereum) { @@ -299,6 +326,15 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo addressList.add(WalletAddressListItem(isPrimary: true, name: null, address: primaryAddress)); } + if (searchText.isNotEmpty) { + return ObservableList.of(addressList.where((item) { + if (item is WalletAddressListItem) { + return item.address.toLowerCase().contains(searchText.toLowerCase()); + } + return false; + })); + } + return addressList; } @@ -321,15 +357,23 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo @computed bool get hasAddressList => wallet.type == WalletType.monero || - wallet.type == WalletType.haven;/* || - wallet.type == WalletType.nano || - wallet.type == WalletType.banano;*/// TODO: nano accounts are disabled for now + wallet.type == WalletType.haven || + wallet.type == WalletType.bitcoinCash || + wallet.type == WalletType.bitcoin || + wallet.type == WalletType.litecoin; + + // wallet.type == WalletType.nano || + // wallet.type == WalletType.banano; TODO: nano accounts are disabled for now @computed - bool get showElectrumAddressDisclaimer => + bool get isElectrumWallet => wallet.type == WalletType.bitcoin || - wallet.type == WalletType.litecoin || - wallet.type == WalletType.bitcoinCash; + wallet.type == WalletType.litecoin || + wallet.type == WalletType.bitcoinCash; + + @computed + bool get isAutoGenerateSubaddressEnabled => + _settingsStore.autoGenerateSubaddressStatus != AutoGenerateSubaddressStatus.disabled; List _baseItems; @@ -343,9 +387,12 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo _baseItems = []; if (wallet.type == WalletType.monero || - wallet.type == WalletType.haven /*|| + wallet.type == + WalletType + .haven /*|| wallet.type == WalletType.nano || - wallet.type == WalletType.banano*/) { + wallet.type == WalletType.banano*/ + ) { _baseItems.add(WalletAccountListHeader()); } @@ -367,6 +414,11 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo } } + @action + void updateSearchText(String text) { + searchText = text; + } + void _convertAmountToCrypto() { final cryptoCurrency = walletTypeToCryptoCurrency(wallet.type); try { diff --git a/tool/configure.dart b/tool/configure.dart index 9d99bf49a..ce894d197 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -64,6 +64,7 @@ import 'package:cw_core/output_info.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cake_wallet/view_model/send/output.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart';"""; const bitcoinCWHeaders = """ import 'package:cw_bitcoin/electrum_wallet.dart'; @@ -76,9 +77,27 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_bitcoin/litecoin_wallet_service.dart'; +import 'package:mobx/mobx.dart'; """; const bitcoinCwPart = "part 'cw_bitcoin.dart';"; const bitcoinContent = """ + + class ElectrumSubAddress { + ElectrumSubAddress({ + required this.id, + required this.name, + required this.address, + required this.txCount, + required this.balance, + required this.isChange}); + final int id; + final String name; + final String address; + final int txCount; + final int balance; + final bool isChange; +} + abstract class Bitcoin { TransactionPriority getMediumTransactionPriority(); @@ -92,13 +111,16 @@ abstract class Bitcoin { TransactionPriority deserializeBitcoinTransactionPriority(int raw); TransactionPriority deserializeLitecoinTransactionPriority(int raw); int getFeeRate(Object wallet, TransactionPriority priority); - Future generateNewAddress(Object wallet); + Future generateNewAddress(Object wallet, String label); + Future updateAddress(Object wallet,String address, String label); Object createBitcoinTransactionCredentials(List outputs, {required TransactionPriority priority, int? feeRate}); Object createBitcoinTransactionCredentialsRaw(List outputs, {TransactionPriority? priority, required int feeRate}); List getAddresses(Object wallet); String getAddress(Object wallet); + List getSubAddresses(Object wallet); + String formatterBitcoinAmountToString({required int amount}); double formatterBitcoinAmountToDouble({required int amount}); int formatterStringDoubleToBitcoinAmount(String amount); From aed60a7282db2ac839e759cacf4d77c59575dcb0 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Fri, 26 Jan 2024 23:48:33 +0100 Subject: [PATCH 100/241] fix: Route to dashboard when exchange is done (#1276) --- lib/src/screens/exchange_trade/exchange_trade_page.dart | 7 ++++++- macos/Podfile.lock | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index 7930c9c82..41fc29713 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'dart:ui'; import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; @@ -343,7 +344,11 @@ class ExchangeTradeState extends State { bottom: 24, child: PrimaryButton( onPressed: () { - Navigator.of(popupContext).pop(); + Navigator.pushNamedAndRemoveUntil( + popupContext, + Routes.dashboard, + (route) => false, + ); RequestReviewHandler.requestReview(); }, text: S.of(popupContext).got_it, diff --git a/macos/Podfile.lock b/macos/Podfile.lock index c158c737e..fcbe1d733 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -106,7 +106,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308 - cw_monero: ec03de55a19c4a2b174ea687e0f4202edc716fa4 + cw_monero: f8b7f104508efba2591548e76b5c058d05cba3f0 device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225 flutter_inappwebview_macos: 9600c9df9fdb346aaa8933812009f8d94304203d From 89fdc0f4d111f4fe2295647fa45cbe11041d3596 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Sat, 27 Jan 2024 00:51:21 +0200 Subject: [PATCH 101/241] Generic fixes (#1274) * Display fees currency as wallet currency not the selected one * remove unused code catch balance network issues * pop send screen when send completes successfully * revert change [skip ci] * Enable restoring haven wallets * verify context is mounted before showing snackbar [skip ci] * Update privacy [skip ci] * Add user consent popup to inapp webview permission request --- PRIVACY.md | 8 +-- cw_ethereum/lib/ethereum_client.dart | 10 ++-- lib/di.dart | 4 +- lib/src/screens/buy/webview_page.dart | 29 ++++++++++- .../desktop_wallet_selection_dropdown.dart | 8 ++- .../new_wallet/new_wallet_type_page.dart | 11 ++-- lib/src/screens/send/widgets/send_card.dart | 2 +- lib/store/settings_store.dart | 52 ++++++++++--------- .../security_settings_view_model.dart | 11 +--- .../wallet_list/wallet_list_view_model.dart | 7 --- res/values/strings_ar.arb | 3 +- res/values/strings_bg.arb | 3 +- res/values/strings_cs.arb | 3 +- res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 3 +- res/values/strings_es.arb | 3 +- res/values/strings_fr.arb | 3 +- res/values/strings_ha.arb | 3 +- res/values/strings_hi.arb | 3 +- res/values/strings_hr.arb | 3 +- res/values/strings_id.arb | 3 +- res/values/strings_it.arb | 3 +- res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 3 +- res/values/strings_nl.arb | 3 +- res/values/strings_pl.arb | 3 +- res/values/strings_pt.arb | 3 +- res/values/strings_ru.arb | 3 +- res/values/strings_th.arb | 3 +- res/values/strings_tl.arb | 3 +- res/values/strings_tr.arb | 3 +- res/values/strings_uk.arb | 3 +- res/values/strings_ur.arb | 3 +- res/values/strings_yo.arb | 3 +- res/values/strings_zh.arb | 3 +- 36 files changed, 134 insertions(+), 86 deletions(-) diff --git a/PRIVACY.md b/PRIVACY.md index 88f180c5e..76cfcc4d3 100644 --- a/PRIVACY.md +++ b/PRIVACY.md @@ -1,6 +1,6 @@ Privacy Policy -Last modified: August 9, 2023 +Last modified: January 24, 2024 Introduction ============ @@ -112,12 +112,12 @@ Data Security In any situation, Cake Labs takes no responsibility for interception of personal data by any outside individual, group, corporation, or institution. You should understand this and take any and all appropriate actions to secure your own data. -Links to Other Websites ------------------------ +Other Websites and Third-Party Services +--------------------------------------- The App may contain links to other websites that are not operated by us. If you click on a Third-Party Service link, you will be directed to that third party's site. We strongly advise you to review the Privacy Policy of every site you visit. We have no control over and assume no responsibility for the content, privacy policies or practices of any third-party sites or services. - The App includes several optional Third-Party Services, which may not be available to all users. If you use Third-Party Services, you must agree to their respective Privacy Policies. + The App includes several optional Third-Party Services, which may not be available to all users. If you use Third-Party Services, you must agree to their respective Privacy Policies. When using certain optional features in the app such as buying and selling, you may be asked to provide information to a Third-Party Service. You will need to read and accept the privacy policy for that third party. This Third-Party Service may ask for your name, your photo ID, your social security number or other similar number, mailing address, cryptocurrency address, or other information. They may ask you to take a selfie image. Information shared with a Third-Party Service is subject to their respective Privacy Policies. Changes to Our Privacy Policy ----------------------------- diff --git a/cw_ethereum/lib/ethereum_client.dart b/cw_ethereum/lib/ethereum_client.dart index fccbf778d..1b3e4bb44 100644 --- a/cw_ethereum/lib/ethereum_client.dart +++ b/cw_ethereum/lib/ethereum_client.dart @@ -190,11 +190,15 @@ I/flutter ( 4474): Gas Used: 53000 Future fetchERC20Balances( EthereumAddress userAddress, String contractAddress) async { final erc20 = ERC20(address: EthereumAddress.fromHex(contractAddress), client: _client!); - final balance = await erc20.balanceOf(userAddress); + try { + final balance = await erc20.balanceOf(userAddress); - int exponent = (await erc20.decimals()).toInt(); + int exponent = (await erc20.decimals()).toInt(); - return ERC20Balance(balance, exponent: exponent); + return ERC20Balance(balance, exponent: exponent); + } catch (_) { + return ERC20Balance(BigInt.zero); + } } Future getErc20Token(String contractAddress) async { diff --git a/lib/di.dart b/lib/di.dart index a37c76b34..05019a562 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -612,7 +612,6 @@ Future setup({ _walletInfoSource, getIt.get(), getIt.get(), - getIt.get(), ), ); } else { @@ -623,7 +622,6 @@ Future setup({ _walletInfoSource, getIt.get(), getIt.get(), - getIt.get(), ), ); } @@ -725,7 +723,7 @@ Future setup({ }); getIt.registerFactory(() { - return SecuritySettingsViewModel(getIt.get(), getIt.get()); + return SecuritySettingsViewModel(getIt.get()); }); getIt.registerFactory(() => WalletSeedViewModel(getIt.get().wallet!)); diff --git a/lib/src/screens/buy/webview_page.dart b/lib/src/screens/buy/webview_page.dart index 97387c29a..0af5952c4 100644 --- a/lib/src/screens/buy/webview_page.dart +++ b/lib/src/screens/buy/webview_page.dart @@ -1,4 +1,7 @@ +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:permission_handler/permission_handler.dart'; @@ -14,13 +17,14 @@ class WebViewPage extends BasePage { @override Widget body(BuildContext context) { - return WebViewPageBody(_url); + return WebViewPageBody(_title, _url); } } class WebViewPageBody extends StatefulWidget { - WebViewPageBody(this.uri); + WebViewPageBody(this.title, this.uri); + final String title; final Uri uri; @override @@ -40,6 +44,27 @@ class WebViewPageBodyState extends State { onPermissionRequest: (controller, request) async { bool permissionGranted = await Permission.camera.status == PermissionStatus.granted; if (!permissionGranted) { + final bool userConsent = await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithTwoActions( + alertTitle: S.of(context).privacy, + alertContent: S.of(context).camera_consent(widget.title), + rightButtonText: S.of(context).agree, + leftButtonText: S.of(context).cancel, + actionRightButton: () => Navigator.of(context).pop(true), + actionLeftButton: () => Navigator.of(context).pop(false)); + }) ?? + false; + + /// if user did NOT give the consent then return permission denied + if (!userConsent) { + return PermissionResponse( + resources: request.resources, + action: PermissionResponseAction.DENY, + ); + } + permissionGranted = await Permission.camera.request().isGranted; } diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart index f3dd2427d..a81a3f6e4 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart @@ -166,12 +166,16 @@ class _DesktopWalletSelectionDropDownState extends State WalletTypeForm( - onTypeSelected: onTypeSelected, - walletImage: currentTheme.type == ThemeType.dark ? walletTypeImage : walletTypeLightImage); + onTypeSelected: onTypeSelected, + walletImage: currentTheme.type == ThemeType.dark ? walletTypeImage : walletTypeLightImage, + isCreate: isCreate, + ); } class WalletTypeForm extends StatefulWidget { - WalletTypeForm({required this.onTypeSelected, required this.walletImage}); + WalletTypeForm({required this.onTypeSelected, required this.walletImage, required this.isCreate}); final void Function(BuildContext, WalletType) onTypeSelected; final Image walletImage; + final bool isCreate; @override WalletTypeFormState createState() => WalletTypeFormState(); @@ -131,7 +134,7 @@ class WalletTypeFormState extends State { throw Exception('Wallet Type is not selected yet.'); } - if (selected == WalletType.haven) { + if (selected == WalletType.haven && widget.isCreate) { return await showPopUp( context: context, builder: (BuildContext context) { diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 65069e903..07fb34cb2 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -478,7 +478,7 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin _settingsStore.allowBiometricalAuthentication; @@ -41,8 +36,6 @@ abstract class SecuritySettingsViewModelBase with Store { _settingsStore.allowBiometricalAuthentication = value; @action - setPinCodeRequiredDuration(PinCodeRequiredDuration duration) => + void setPinCodeRequiredDuration(PinCodeRequiredDuration duration) => _settingsStore.pinTimeOutDuration = duration; - - Future checkPinCodeRiquired() => _authService.requireAuth(); } 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 a7e27cbf6..b31133c7d 100644 --- a/lib/view_model/wallet_list/wallet_list_view_model.dart +++ b/lib/view_model/wallet_list/wallet_list_view_model.dart @@ -1,4 +1,3 @@ -import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/core/wallet_loading_service.dart'; import 'package:cake_wallet/entities/wallet_list_order_types.dart'; import 'package:hive/hive.dart'; @@ -18,7 +17,6 @@ abstract class WalletListViewModelBase with Store { this._walletInfoSource, this._appStore, this._walletLoadingService, - this._authService, ) : wallets = ObservableList() { setOrderType(_appStore.settingsStore.walletListOrder); reaction((_) => _appStore.wallet, (_) => updateList()); @@ -39,7 +37,6 @@ abstract class WalletListViewModelBase with Store { final AppStore _appStore; final Box _walletInfoSource; final WalletLoadingService _walletLoadingService; - final AuthService _authService; WalletType get currentWalletType => _appStore.wallet!.type; @@ -160,8 +157,4 @@ abstract class WalletListViewModelBase with Store { break; } } - - Future checkIfAuthRequired() async { - return _authService.requireAuth(); - } } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 8ad9ed45b..8fbcb481c 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -763,5 +763,6 @@ "receivable_balance": "التوازن القادم", "confirmed_tx": "مؤكد", "transaction_details_source_address": "عنوان المصدر", - "pause_wallet_creation": ".ﺎﻴًﻟﺎﺣ ﺎﺘًﻗﺆﻣ ﺔﻔﻗﻮﺘﻣ Haven Wallet ءﺎﺸﻧﺇ ﻰﻠﻋ ﺓﺭﺪﻘﻟﺍ" + "pause_wallet_creation": ".ﺎﻴًﻟﺎﺣ ﺎﺘًﻗﺆﻣ ﺔﻔﻗﻮﺘﻣ Haven Wallet ءﺎﺸﻧﺇ ﻰﻠﻋ ﺓﺭﺪﻘﻟﺍ", + "camera_consent": ".ﻞﻴﺻﺎﻔﺘﻟﺍ ﻰﻠﻋ ﻝﻮﺼﺤﻠﻟ ﻢﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺔﻴﺻﻮﺼﺨﻟﺍ ﺔﺳﺎﻴﺳ ﻦﻣ ﻖﻘﺤﺘﻟﺍ ﻰﺟﺮﻳ .${provider} ﻝﻮﻠ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 6f1c96af5..1707c3f8c 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -759,5 +759,6 @@ "receivable_balance": "Баланс за вземания", "confirmed_tx": "Потвърдено", "transaction_details_source_address": "Адрес на източника", - "pause_wallet_creation": "Възможността за създаване на Haven Wallet в момента е на пауза." + "pause_wallet_creation": "Възможността за създаване на Haven Wallet в момента е на пауза.", + "camera_consent": "Вашият фотоапарат ще бъде използван за заснемане на изображение с цел идентификация от ${provider}. Моля, проверете тяхната политика за поверителност за подробности." } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index bb63ea00a..dfae6717c 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -759,5 +759,6 @@ "receivable_balance": "Zůstatek pohledávek", "confirmed_tx": "Potvrzeno", "transaction_details_source_address": "Zdrojová adresa", - "pause_wallet_creation": "Možnost vytvářet Haven Wallet je momentálně pozastavena." + "pause_wallet_creation": "Možnost vytvářet Haven Wallet je momentálně pozastavena.", + "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 a0795960a..b96861f4d 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -767,5 +767,6 @@ "receivable_balance": "Forderungsbilanz", "confirmed_tx": "Bestätigt", "transaction_details_source_address": "Quelladresse", - "pause_wallet_creation": "Die Möglichkeit, Haven Wallet zu erstellen, ist derzeit pausiert." + "pause_wallet_creation": "Die Möglichkeit, Haven Wallet zu erstellen, ist derzeit pausiert.", + "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 20ec41126..10c130a0c 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -768,5 +768,6 @@ "receivable_balance": "Receivable Balance", "confirmed_tx": "Confirmed", "transaction_details_source_address": "Source address", - "pause_wallet_creation": "Ability to create Haven Wallet is currently paused." + "pause_wallet_creation": "Ability to create Haven Wallet is currently paused.", + "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 e3783afe0..5bec3b0ae 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -767,5 +767,6 @@ "receivable_balance": "Saldo de cuentas por cobrar", "confirmed_tx": "Confirmado", "transaction_details_source_address": "Dirección de la fuente", - "pause_wallet_creation": "La capacidad para crear Haven Wallet está actualmente pausada." + "pause_wallet_creation": "La capacidad para crear Haven Wallet está actualmente pausada.", + "camera_consent": "Su cámara será utilizada para capturar una imagen con fines de identificación por ${provider}. Consulte su Política de privacidad para obtener más detalles." } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 5ae616bda..9ce607b20 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -767,5 +767,6 @@ "receivable_balance": "Solde de créances", "confirmed_tx": "Confirmé", "transaction_details_source_address": "Adresse source", - "pause_wallet_creation": "La possibilité de créer Haven Wallet est actuellement suspendue." + "pause_wallet_creation": "La possibilité de créer Haven Wallet est actuellement suspendue.", + "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 cdbfeb1b6..47426aa8c 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -749,5 +749,6 @@ "receivable_balance": "Daidaituwa da daidaituwa", "confirmed_tx": "Tabbatar", "transaction_details_source_address": "Adireshin Incord", - "pause_wallet_creation": "A halin yanzu an dakatar da ikon ƙirƙirar Haven Wallet." + "pause_wallet_creation": "A halin yanzu an dakatar da ikon ƙirƙirar Haven Wallet.", + "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 22519a1c4..91bf40d60 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -767,5 +767,6 @@ "receivable_balance": "प्राप्य शेष", "confirmed_tx": "की पुष्टि", "transaction_details_source_address": "स्रोत पता", - "pause_wallet_creation": "हेवन वॉलेट बनाने की क्षमता फिलहाल रुकी हुई है।" + "pause_wallet_creation": "हेवन वॉलेट बनाने की क्षमता फिलहाल रुकी हुई है।", + "camera_consent": "आपके कैमरे का उपयोग ${provider} द्वारा पहचान उद्देश्यों के लिए एक छवि कैप्चर करने के लिए किया जाएगा। विवरण के लिए कृपया उनकी गोपनीयता नीति जांचें।" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index c951baed4..b3c49ce78 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -765,5 +765,6 @@ "receivable_balance": "Stanje potraživanja", "confirmed_tx": "Potvrđen", "transaction_details_source_address": "Adresa izvora", - "pause_wallet_creation": "Mogućnost stvaranja novčanika Haven trenutno je pauzirana." + "pause_wallet_creation": "Mogućnost stvaranja novčanika Haven trenutno je pauzirana.", + "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_id.arb b/res/values/strings_id.arb index d383da478..2a8fd06e8 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -755,5 +755,6 @@ "receivable_balance": "Saldo piutang", "confirmed_tx": "Dikonfirmasi", "transaction_details_source_address": "Alamat sumber", - "pause_wallet_creation": "Kemampuan untuk membuat Haven Wallet saat ini dijeda." + "pause_wallet_creation": "Kemampuan untuk membuat Haven Wallet saat ini dijeda.", + "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 29edecaad..01e88d56f 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -767,5 +767,6 @@ "receivable_balance": "Bilanciamento creditizio", "confirmed_tx": "Confermato", "transaction_details_source_address": "Indirizzo di partenza", - "pause_wallet_creation": "La possibilità di creare Haven Wallet è attualmente sospesa." + "pause_wallet_creation": "La possibilità di creare Haven Wallet è attualmente sospesa.", + "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 d15c79c34..07bf5fca8 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -767,5 +767,6 @@ "receivable_balance": "売掛金残高", "confirmed_tx": "確認済み", "transaction_details_source_address": "ソースアドレス", - "pause_wallet_creation": "Haven Wallet を作成する機能は現在一時停止されています。" + "pause_wallet_creation": "Haven Wallet を作成する機能は現在一時停止されています。", + "camera_consent": "あなたのカメラは、${provider}_ までに識別目的で画像を撮影するために使用されます。詳細については、プライバシー ポリシーをご確認ください。" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 2a53ecf77..7ea1ea85d 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -765,5 +765,6 @@ "receivable_balance": "채권 잔액", "confirmed_tx": "확인", "transaction_details_source_address": "소스 주소", - "pause_wallet_creation": "Haven Wallet 생성 기능이 현재 일시 중지되었습니다." + "pause_wallet_creation": "Haven Wallet 생성 기능이 현재 일시 중지되었습니다.", + "camera_consent": "귀하의 카메라는 ${provider}의 식별 목적으로 이미지를 캡처하는 데 사용됩니다. 자세한 내용은 해당 개인정보 보호정책을 확인하세요." } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 04986ad5c..9559d224e 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -765,5 +765,6 @@ "receivable_balance": "လက်ကျန်ငွေ", "confirmed_tx": "အတည်ပြုသည်", "transaction_details_source_address": "အရင်းအမြစ်လိပ်စာ", - "pause_wallet_creation": "Haven Wallet ဖန်တီးနိုင်မှုကို လောလောဆယ် ခေတ္တရပ်ထားသည်။" + "pause_wallet_creation": "Haven Wallet ဖန်တီးနိုင်မှုကို လောလောဆယ် ခေတ္တရပ်ထားသည်။", + "camera_consent": "မှတ်ပုံတင်ခြင်းရည်ရွယ်ချက်များအတွက် ${provider} တွင် သင့်ကင်မရာကို အသုံးပြုပါမည်။ အသေးစိတ်အတွက် ၎င်းတို့၏ ကိုယ်ရေးကိုယ်တာမူဝါဒကို စစ်ဆေးပါ။" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 6c2ed2691..23a635a99 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -767,5 +767,6 @@ "receivable_balance": "Het saldo", "confirmed_tx": "Bevestigd", "transaction_details_source_address": "Bron adres", - "pause_wallet_creation": "De mogelijkheid om Haven Wallet te maken is momenteel onderbroken." + "pause_wallet_creation": "De mogelijkheid om Haven Wallet te maken is momenteel onderbroken.", + "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 5e37e982a..f3e9db35c 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -767,5 +767,6 @@ "receivable_balance": "Saldo należności", "confirmed_tx": "Potwierdzony", "transaction_details_source_address": "Adres źródłowy", - "pause_wallet_creation": "Możliwość utworzenia Portfela Haven jest obecnie wstrzymana." + "pause_wallet_creation": "Możliwość utworzenia Portfela Haven jest obecnie wstrzymana.", + "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 66f0dd928..42c4cec28 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -766,5 +766,6 @@ "receivable_balance": "Saldo a receber", "confirmed_tx": "Confirmado", "transaction_details_source_address": "Endereço de Origem", - "pause_wallet_creation": "A capacidade de criar a Haven Wallet está atualmente pausada." + "pause_wallet_creation": "A capacidade de criar a Haven Wallet está atualmente pausada.", + "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 60c7bbc15..edc6993a0 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -767,5 +767,6 @@ "receivable_balance": "Баланс дебиторской задолженности", "confirmed_tx": "Подтвержденный", "transaction_details_source_address": "Адрес источника", - "pause_wallet_creation": "Возможность создания Haven Wallet в настоящее время приостановлена." + "pause_wallet_creation": "Возможность создания Haven Wallet в настоящее время приостановлена.", + "camera_consent": "Ваша камера будет использоваться для захвата изображения в целях идентификации ${provider}. Пожалуйста, ознакомьтесь с их Политикой конфиденциальности для получения подробной информации." } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index b28964357..80fa3f9c6 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -765,5 +765,6 @@ "receivable_balance": "ยอดลูกหนี้", "confirmed_tx": "ซึ่งยืนยันแล้ว", "transaction_details_source_address": "ที่อยู่แหล่งกำเนิด", - "pause_wallet_creation": "ขณะนี้ความสามารถในการสร้าง Haven Wallet ถูกหยุดชั่วคราว" + "pause_wallet_creation": "ขณะนี้ความสามารถในการสร้าง Haven Wallet ถูกหยุดชั่วคราว", + "camera_consent": "กล้องของคุณจะถูกนำมาใช้เพื่อจับภาพเพื่อวัตถุประสงค์ในการระบุตัวตนภายใน ${provider} โปรดตรวจสอบนโยบายความเป็นส่วนตัวเพื่อดูรายละเอียด" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index d30a25ad5..558f26911 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -761,5 +761,6 @@ "receivable_balance": "Natatanggap na balanse", "confirmed_tx": "Nakumpirma", "transaction_details_source_address": "SOURCE ADDRESS", - "pause_wallet_creation": "Kasalukuyang naka-pause ang kakayahang gumawa ng Haven Wallet." + "pause_wallet_creation": "Kasalukuyang naka-pause ang kakayahang gumawa ng Haven Wallet.", + "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 563ca5332..bbbecaf5c 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -765,5 +765,6 @@ "receivable_balance": "Alacak bakiyesi", "confirmed_tx": "Onaylanmış", "transaction_details_source_address": "Kaynak adresi", - "pause_wallet_creation": "Haven Cüzdanı oluşturma yeteneği şu anda duraklatıldı." + "pause_wallet_creation": "Haven Cüzdanı oluşturma yeteneği şu anda duraklatıldı.", + "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 9418d6065..a1d08b352 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -767,5 +767,6 @@ "receivable_balance": "Баланс дебіторської заборгованості", "confirmed_tx": "Підтверджений", "transaction_details_source_address": "Адреса джерела", - "pause_wallet_creation": "Можливість створення гаманця Haven зараз призупинено." + "pause_wallet_creation": "Можливість створення гаманця Haven зараз призупинено.", + "camera_consent": "Ваша камера використовуватиметься для зйомки зображення з метою ідентифікації ${provider}. Будь ласка, ознайомтеся з їхньою політикою конфіденційності, щоб дізнатися більше." } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 61e97d751..517aa9ded 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -759,5 +759,6 @@ "receivable_balance": "قابل وصول توازن", "confirmed_tx": "تصدیق", "transaction_details_source_address": "ماخذ ایڈریس", - "pause_wallet_creation": "Haven Wallet ۔ﮯﮨ ﻑﻮﻗﻮﻣ ﻝﺎﺤﻟﺍ ﯽﻓ ﺖﯿﻠﮨﺍ ﯽﮐ ﮯﻧﺎﻨﺑ" + "pause_wallet_creation": "Haven Wallet ۔ﮯﮨ ﻑﻮﻗﻮﻣ ﻝﺎﺤﻟﺍ ﯽﻓ ﺖﯿﻠﮨﺍ ﯽﮐ ﮯﻧﺎﻨﺑ", + "camera_consent": "۔ﮟﯿﮭﮑﯾﺩ ﯽﺴﯿﻟﺎﭘ ﯽﺴﯾﻮﯿﺋﺍﺮﭘ ﯽﮐ ﻥﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ﮯﯿﻟ ﮯﮐ ﺕﻼ${provider}ﯿﺼﻔﺗ ۔ﺎﮔ ﮯﺋﺎﺟ ﺎﯿﮐ ﻝﺎﻤﻌﺘﺳﺍ ﮯﯿﻟ" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index dbff620a1..298c73c67 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -761,5 +761,6 @@ "receivable_balance": "Iwontunws.funfun ti o gba", "confirmed_tx": "Jẹrisi", "transaction_details_source_address": "Adirẹsi orisun", - "pause_wallet_creation": "Agbara lati ṣẹda Haven Wallet ti wa ni idaduro lọwọlọwọ." + "pause_wallet_creation": "Agbara lati ṣẹda Haven Wallet ti wa ni idaduro lọwọlọwọ.", + "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 249a412c4..20255e76c 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -766,5 +766,6 @@ "receivable_balance": "应收余额", "confirmed_tx": "确认的", "transaction_details_source_address": "源地址", - "pause_wallet_creation": "创建 Haven 钱包的功能当前已暂停。" + "pause_wallet_creation": "创建 Haven 钱包的功能当前已暂停。", + "camera_consent": "${provider} 将使用您的相机拍摄图像以供识别之用。请查看他们的隐私政策了解详情。" } From fc352a6da3c09d179de41cf967de5258b84a857e Mon Sep 17 00:00:00 2001 From: Serhii Date: Sat, 27 Jan 2024 04:34:38 +0200 Subject: [PATCH 102/241] Cw 428 send to nostr addresses (#1271) * add nostr address resolver * Add Nostr localization --------- Co-authored-by: OmarHatem --- lib/entities/parse_address_from_domain.dart | 28 +++- lib/entities/parsed_address.dart | 27 +++- lib/nostr/nostr_api.dart | 142 ++++++++++++++++++ lib/nostr/nostr_user.dart | 35 +++++ lib/src/screens/exchange/exchange_page.dart | 2 +- .../widgets/extract_address_from_parsed.dart | 5 + lib/view_model/send/output.dart | 2 +- pubspec_base.yaml | 6 + res/values/strings_ar.arb | 6 +- res/values/strings_bg.arb | 6 +- res/values/strings_cs.arb | 6 +- res/values/strings_de.arb | 6 +- res/values/strings_en.arb | 6 +- res/values/strings_es.arb | 6 +- res/values/strings_fr.arb | 6 +- res/values/strings_ha.arb | 6 +- res/values/strings_hi.arb | 6 +- res/values/strings_hr.arb | 6 +- res/values/strings_id.arb | 6 +- res/values/strings_it.arb | 6 +- res/values/strings_ja.arb | 6 +- res/values/strings_ko.arb | 6 +- res/values/strings_my.arb | 6 +- res/values/strings_nl.arb | 6 +- res/values/strings_pl.arb | 6 +- res/values/strings_pt.arb | 6 +- res/values/strings_ru.arb | 6 +- res/values/strings_th.arb | 6 +- res/values/strings_tl.arb | 6 +- res/values/strings_tr.arb | 6 +- res/values/strings_uk.arb | 6 +- res/values/strings_ur.arb | 6 +- res/values/strings_yo.arb | 6 +- res/values/strings_zh.arb | 6 +- 34 files changed, 370 insertions(+), 33 deletions(-) create mode 100644 lib/nostr/nostr_api.dart create mode 100644 lib/nostr/nostr_user.dart diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart index e184f5649..52bcc495b 100644 --- a/lib/entities/parse_address_from_domain.dart +++ b/lib/entities/parse_address_from_domain.dart @@ -6,12 +6,14 @@ import 'package:cake_wallet/entities/parsed_address.dart'; import 'package:cake_wallet/entities/unstoppable_domain_address.dart'; import 'package:cake_wallet/entities/emoji_string_extension.dart'; import 'package:cake_wallet/mastodon/mastodon_api.dart'; +import 'package:cake_wallet/nostr/nostr_api.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/twitter/twitter_api.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/entities/fio_address_provider.dart'; +import 'package:flutter/cupertino.dart'; class AddressResolver { AddressResolver({required this.yatService, required this.wallet, required this.settingsStore}) @@ -58,7 +60,16 @@ class AddressResolver { }); } - Future resolve(String text, String ticker) async { + bool isEmailFormat(String address) { + final RegExp emailRegex = RegExp( + r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', + caseSensitive: false, + ); + return emailRegex.hasMatch(address); + } + + + Future resolve(BuildContext context, String text, String ticker) async { try { if (text.startsWith('@') && !text.substring(1).contains('@')) { if(settingsStore.lookupsTwitter) { @@ -165,6 +176,21 @@ class AddressResolver { } } } + if (isEmailFormat(text)) { + final nostrProfile = await NostrProfileHandler.queryProfile(context, text); + if (nostrProfile?.relays != null) { + final nostrUserData = + await NostrProfileHandler.processRelays(context, nostrProfile!, text); + + if (nostrUserData != null) { + String? addressFromBio = extractAddressByType( + raw: nostrUserData.about, type: CryptoCurrency.fromString(ticker)); + if (addressFromBio != null) { + return ParsedAddress.nostrAddress(address: addressFromBio, name: text); + } + } + } + } } catch (e) { print(e.toString()); } diff --git a/lib/entities/parsed_address.dart b/lib/entities/parsed_address.dart index df20dd9ee..d414a827d 100644 --- a/lib/entities/parsed_address.dart +++ b/lib/entities/parsed_address.dart @@ -2,7 +2,18 @@ import 'package:cake_wallet/entities/openalias_record.dart'; import 'package:cake_wallet/entities/yat_record.dart'; -enum ParseFrom { unstoppableDomains, openAlias, yatRecord, fio, notParsed, twitter, ens, contact, mastodon } +enum ParseFrom { + unstoppableDomains, + openAlias, + yatRecord, + fio, + notParsed, + twitter, + ens, + contact, + mastodon, + nostr +} class ParsedAddress { ParsedAddress({ @@ -11,9 +22,9 @@ class ParsedAddress { this.description = '', this.parseFrom = ParseFrom.notParsed, }); - + factory ParsedAddress.fetchEmojiAddress({ - List? addresses, + List? addresses, required String name, }){ if (addresses?.isEmpty ?? true) { @@ -28,7 +39,7 @@ class ParsedAddress { } factory ParsedAddress.fetchUnstoppableDomainAddress({ - String? address, + String? address, required String name, }){ if (address?.isEmpty ?? true) { @@ -94,6 +105,14 @@ class ParsedAddress { ); } + factory ParsedAddress.nostrAddress({required String address, required String name}) { + return ParsedAddress( + addresses: [address], + name: name, + parseFrom: ParseFrom.nostr, + ); + } + final List addresses; final String name; final String description; diff --git a/lib/nostr/nostr_api.dart b/lib/nostr/nostr_api.dart new file mode 100644 index 000000000..7c0eea5ef --- /dev/null +++ b/lib/nostr/nostr_api.dart @@ -0,0 +1,142 @@ +import 'dart:convert'; + +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/nostr/nostr_user.dart'; +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/src/widgets/picker.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:flutter/material.dart'; +import 'package:nostr_tools/nostr_tools.dart'; + +class NostrProfileHandler { + static final relayToDomainMap = { + 'relay.snort.social': 'snort.social', + }; + + static Nip05 _nip05 = Nip05(); + + static Future queryProfile(BuildContext context, String nip05Address) async { + var profile = await _nip05.queryProfile(nip05Address); + if (profile?.pubkey != null) { + if (profile?.relays?.isNotEmpty == true) { + return profile; + } else { + await _showErrorDialog(context, S.of(context).no_relays, S.of(context).no_relays_message); + } + } + return null; + } + + static Future processRelays( + BuildContext context, ProfilePointer profile, String nip05Address) async { + String userDomain = _extractDomain(nip05Address); + const int metaData = 0; + + for (String relayUrl in profile.relays ?? []) { + final relayDomain = _getDomainFromRelayUrl(relayUrl); + final formattedRelayDomain = relayToDomainMap[relayDomain] ?? relayDomain; + if (formattedRelayDomain == userDomain) { + final userDomainData = await _fetchInfoFromRelay(relayUrl, profile.pubkey, [metaData]); + if (userDomainData != null) { + return userDomainData; + } + } + } + await _showErrorDialog(context, S.of(context).no_relays, S.of(context).no_relay_on_domain); + + String? chosenRelayUrl = await _showRelayChoiceDialog(context, profile.relays ?? []); + if (chosenRelayUrl != null) { + final userData = await _fetchInfoFromRelay(chosenRelayUrl, profile.pubkey, [metaData]); + if (userData != null) { + return userData; + } + } + + return null; + } + + static Future _fetchInfoFromRelay( + String relayUrl, String userPubKey, List kinds) async { + try { + final relay = RelayApi(relayUrl: relayUrl); + final stream = await relay.connect(); + + relay.sub([ + Filter( + kinds: kinds, + authors: [userPubKey], + ) + ]); + + await for (var message in stream) { + if (message.type == 'EVENT') { + final event = message.message as Event; + + final eventContent = json.decode(event.content) as Map; + + final userMetadata = UserMetadata.fromJson(eventContent); + relay.close(); + return userMetadata; + } + } + + relay.close(); + return null; + } catch (e) { + print('[!] Error with relay $relayUrl: $e'); + return null; + } + } + + static Future _showErrorDialog( + BuildContext context, String title, String errorMessage) async { + if (context.mounted) { + await showPopUp( + context: context, + builder: (BuildContext dialogContext) { + return AlertWithOneAction( + alertTitle: title, + alertContent: errorMessage, + buttonText: S.of(dialogContext).ok, + buttonAction: () => Navigator.of(dialogContext).pop(), + ); + }, + ); + } + } + + static String _extractDomain(String nip05Address) { + var parts = nip05Address.split('@'); + return parts.length == 2 ? parts[1] : ''; + } + + static String _getDomainFromRelayUrl(String relayUrl) { + try { + var uri = Uri.parse(relayUrl); + return uri.host; + } catch (e) { + print('Error parsing URL: $e'); + return ''; + } + } + + static Future _showRelayChoiceDialog(BuildContext context, List relays) async { + String? selectedRelay; + + if (context.mounted) { + await showPopUp( + context: context, + builder: (BuildContext dialogContext) { + return Picker( + selectedAtIndex: 0, + title: S.of(dialogContext).choose_relay, + items: relays, + onItemSelected: (String relay) => selectedRelay = relay, + ); + }, + ); + } + + return selectedRelay; + } +} diff --git a/lib/nostr/nostr_user.dart b/lib/nostr/nostr_user.dart new file mode 100644 index 000000000..4b1694a11 --- /dev/null +++ b/lib/nostr/nostr_user.dart @@ -0,0 +1,35 @@ + +class UserMetadata { + final String name; + final String lnurl; + final String email; + final String picture; + final String about; + final String nip05; + final String banner; + final String website; + + UserMetadata({ + required this.name, + required this.lnurl, + required this.email, + required this.picture, + required this.about, + required this.nip05, + required this.banner, + required this.website, + }); + + factory UserMetadata.fromJson(Map json) { + return UserMetadata( + name: json['name'] as String? ?? '', + lnurl: json['lud06'] as String? ?? '', + email: json['lud16'] as String? ?? '', + picture: json['picture'] as String? ?? '', + about: json['about'] as String? ?? '', + nip05: json['nip05'] as String? ?? '', + banner: json['banner'] as String? ?? '', + website: json['website'] as String? ?? '', + ); + } +} \ No newline at end of file diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index b3fbd19a7..94b51301c 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -557,7 +557,7 @@ class ExchangePage extends BasePage { } Future fetchParsedAddress(BuildContext context, String domain, String ticker) async { - final parsedAddress = await getIt.get().resolve(domain, ticker); + final parsedAddress = await getIt.get().resolve(context, domain, ticker); final address = await extractAddressFromParsed(context, parsedAddress); return address; } diff --git a/lib/src/screens/send/widgets/extract_address_from_parsed.dart b/lib/src/screens/send/widgets/extract_address_from_parsed.dart index 73bff23c1..bb09d4ca3 100644 --- a/lib/src/screens/send/widgets/extract_address_from_parsed.dart +++ b/lib/src/screens/send/widgets/extract_address_from_parsed.dart @@ -43,6 +43,11 @@ Future extractAddressFromParsed( content = S.of(context).extracted_address_content('${parsedAddress.name} (Mastodon)'); address = parsedAddress.addresses.first; break; + case ParseFrom.nostr: + title = S.of(context).address_detected; + content = S.of(context).extracted_address_content('${parsedAddress.name} (Nostr NIP-05)'); + address = parsedAddress.addresses.first; + break; case ParseFrom.yatRecord: if (parsedAddress.name.isEmpty) { title = S.of(context).yat_error; diff --git a/lib/view_model/send/output.dart b/lib/view_model/send/output.dart index 73fb535f2..e40000139 100644 --- a/lib/view_model/send/output.dart +++ b/lib/view_model/send/output.dart @@ -262,7 +262,7 @@ abstract class OutputBase with Store { Future fetchParsedAddress(BuildContext context) async { final domain = address; final ticker = cryptoCurrencyHandler().title.toLowerCase(); - parsedAddress = await getIt.get().resolve(domain, ticker); + parsedAddress = await getIt.get().resolve(context, domain, ticker); extractedAddress = await extractAddressFromParsed(context, parsedAddress); note = parsedAddress.description; } diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 45f675043..f38482ec3 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -105,6 +105,7 @@ dependencies: socks5_proxy: ^1.0.4 flutter_svg: ^2.0.9 polyseed: ^0.0.2 + nostr_tools: ^1.0.9 dev_dependencies: flutter_test: @@ -123,6 +124,11 @@ dev_dependencies: url: https://github.com/cake-tech/google-translator.git version: 1.0.0 +dependency_overrides: + bech32: + git: + url: https://github.com/cake-tech/bech32.git + flutter_icons: image_path: "assets/images/app_logo.png" android: true diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 8fbcb481c..f8ff07bd2 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -764,5 +764,9 @@ "confirmed_tx": "مؤكد", "transaction_details_source_address": "عنوان المصدر", "pause_wallet_creation": ".ﺎﻴًﻟﺎﺣ ﺎﺘًﻗﺆﻣ ﺔﻔﻗﻮﺘﻣ Haven Wallet ءﺎﺸﻧﺇ ﻰﻠﻋ ﺓﺭﺪﻘﻟﺍ", - "camera_consent": ".ﻞﻴﺻﺎﻔﺘﻟﺍ ﻰﻠﻋ ﻝﻮﺼﺤﻠﻟ ﻢﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺔﻴﺻﻮﺼﺨﻟﺍ ﺔﺳﺎﻴﺳ ﻦﻣ ﻖﻘﺤﺘﻟﺍ ﻰﺟﺮﻳ .${provider} ﻝﻮﻠ" + "camera_consent": ".ﻞﻴﺻﺎﻔﺘﻟﺍ ﻰﻠﻋ ﻝﻮﺼﺤﻠﻟ ﻢﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺔﻴﺻﻮﺼﺨﻟﺍ ﺔﺳﺎﻴﺳ ﻦﻣ ﻖﻘﺤﺘﻟﺍ ﻰﺟﺮﻳ .${provider} ﻝﻮﻠ", + "no_relays": " ﺕﻼﺣﺮﻤﻟﺍ ﻻ", + "choose_relay": " ﻡﺍﺪﺨﺘﺳﻼﻟ ﻊﺑﺎﺘﺘﻟﺍ ﺭﺎﻴﺘﺧﺍ ءﺎﺟﺮﻟﺍ", + "no_relays_message": ".ﻪﺑ ﺹﺎﺨﻟﺍ Nostr ﻞﺠﺳ ﻰﻟﺇ ﺕﻼﺣﺮﻤﻟﺍ ﺔﻓﺎﺿﻹ ﻢﻠﺘﺴﻤﻟﺍ ﺩﺎﺷﺭﺇ ﻰﺟﺮﻳ .ﺕﻼﺣﺮﻣ ﻱﺃ ﻰﻠﻋ ﻱﻮﺘﺤﻳ ﻻ", + "no_relay_on_domain": ".ﻡﺍﺪﺨﺘﺳﻼﻟ ﻊﺑﺎﺘﺘﻟﺍ ﺭﺎﻴﺘﺧﺍ ءﺎﺟﺮﻟﺍ .ﺡﺎﺘﻣ ﺮﻴﻏ ﻞﻴﺣﺮﺘﻟﺍ ﻥﺃ ﻭﺃ ﻡﺪﺨﺘﺴﻤﻟﺍ ﻝﺎﺠﻤﻟ ﻞﻴﺣﺮﺗ ﺪ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 1707c3f8c..8e6a6c1ee 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -760,5 +760,9 @@ "confirmed_tx": "Потвърдено", "transaction_details_source_address": "Адрес на източника", "pause_wallet_creation": "Възможността за създаване на Haven Wallet в момента е на пауза.", - "camera_consent": "Вашият фотоапарат ще бъде използван за заснемане на изображение с цел идентификация от ${provider}. Моля, проверете тяхната политика за поверителност за подробности." + "camera_consent": "Вашият фотоапарат ще бъде използван за заснемане на изображение с цел идентификация от ${provider}. Моля, проверете тяхната политика за поверителност за подробности.", + "no_relays": "Без релета", + "choose_relay": "Моля, изберете реле, което да използвате", + "no_relays_message": "Намерихме запис Nostr NIP-05 за този потребител, но той не съдържа релета. Моля, инструктирайте получателя да добави релета към своя Nostr запис.", + "no_relay_on_domain": "Няма реле за домейна на потребителя или релето не е налично. Моля, изберете реле, което да използвате." } diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index dfae6717c..a739fa05b 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -760,5 +760,9 @@ "confirmed_tx": "Potvrzeno", "transaction_details_source_address": "Zdrojová adresa", "pause_wallet_creation": "Možnost vytvářet Haven Wallet je momentálně pozastavena.", - "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ů." + "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ů.", + "no_relays": "Žádná relé", + "choose_relay": "Vyberte relé, které chcete použít", + "no_relays_message": "Pro tohoto uživatele jsme našli záznam Nostr NIP-05, který však neobsahuje žádná relé. Požádejte příjemce, aby přidal přenosy do svého záznamu Nostr.", + "no_relay_on_domain": "Pro doménu uživatele neexistuje přenos nebo je přenos nedostupný. Vyberte relé, které chcete použít." } diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index b96861f4d..872b8bec2 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -768,5 +768,9 @@ "confirmed_tx": "Bestätigt", "transaction_details_source_address": "Quelladresse", "pause_wallet_creation": "Die Möglichkeit, Haven Wallet zu erstellen, ist derzeit pausiert.", - "camera_consent": "Mit Ihrer Kamera wird bis zum ${provider} ein Bild zur Identifizierung aufgenommen. Weitere Informationen finden Sie in deren Datenschutzbestimmungen." + "camera_consent": "Mit Ihrer Kamera wird bis zum ${provider} ein Bild zur Identifizierung aufgenommen. Weitere Informationen finden Sie in deren Datenschutzbestimmungen.", + "no_relays": "Keine Relais", + "choose_relay": "Bitte wählen Sie ein zu verwendendes Relais aus", + "no_relays_message": "Wir haben einen Nostr NIP-05-Eintrag für diesen Benutzer gefunden, der jedoch keine Relays enthält. Bitte weisen Sie den Empfänger an, Relays zu seinem Nostr-Datensatz hinzuzufügen.", + "no_relay_on_domain": "Es gibt kein Relay für die Domäne des Benutzers oder das Relay ist nicht verfügbar. Bitte wählen Sie ein zu verwendendes Relais aus." } diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 10c130a0c..3ec496b6c 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -769,5 +769,9 @@ "confirmed_tx": "Confirmed", "transaction_details_source_address": "Source address", "pause_wallet_creation": "Ability to create Haven Wallet is currently paused.", - "camera_consent": "Your camera will be used to capture an image for identification purposes by ${provider}. Please check their Privacy Policy for details." + "camera_consent": "Your camera will be used to capture an image for identification purposes by ${provider}. Please check their Privacy Policy for details.", + "no_relays": "No relays", + "choose_relay": "Please choose a relay to use", + "no_relays_message": "We found a Nostr NIP-05 record for this user, but it does not contain any relays. Please instruct the recipient to add relays to their Nostr record.", + "no_relay_on_domain": "There isn't a relay for user's domain or the relay is unavailable. Please choose a relay to use." } diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 5bec3b0ae..ab97e764d 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -768,5 +768,9 @@ "confirmed_tx": "Confirmado", "transaction_details_source_address": "Dirección de la fuente", "pause_wallet_creation": "La capacidad para crear Haven Wallet está actualmente pausada.", - "camera_consent": "Su cámara será utilizada para capturar una imagen con fines de identificación por ${provider}. Consulte su Política de privacidad para obtener más detalles." + "camera_consent": "Su cámara será utilizada para capturar una imagen con fines de identificación por ${provider}. Consulte su Política de privacidad para obtener más detalles.", + "no_relays": "Sin relevos", + "choose_relay": "Por favor elija un relé para usar", + "no_relays_message": "Encontramos un registro Nostr NIP-05 para este usuario, pero no contiene ningún relé. Indique al destinatario que agregue retransmisiones a su registro Nostr.", + "no_relay_on_domain": "No hay una retransmisión para el dominio del usuario o la retransmisión no está disponible. Elija un relé para usar." } diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 9ce607b20..619c35276 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -768,5 +768,9 @@ "confirmed_tx": "Confirmé", "transaction_details_source_address": "Adresse source", "pause_wallet_creation": "La possibilité de créer Haven Wallet est actuellement suspendue.", - "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." + "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.", + "no_relays": "Pas de relais", + "choose_relay": "Veuillez choisir un relais à utiliser", + "no_relays_message": "Nous avons trouvé un enregistrement Nostr NIP-05 pour cet utilisateur, mais il ne contient aucun relais. Veuillez demander au destinataire d'ajouter des relais à son enregistrement Nostr.", + "no_relay_on_domain": "Il n'existe pas de relais pour le domaine de l'utilisateur ou le relais n'est pas disponible. Veuillez choisir un relais à utiliser." } diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 47426aa8c..dd38a4ec3 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -750,5 +750,9 @@ "confirmed_tx": "Tabbatar", "transaction_details_source_address": "Adireshin Incord", "pause_wallet_creation": "A halin yanzu an dakatar da ikon ƙirƙirar Haven Wallet.", - "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." + "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.", + "no_relays": "Babu relays", + "choose_relay": "Da fatan za a zaɓi gudun ba da sanda don amfani", + "no_relays_message": "Mun sami rikodin Nostr NIP-05 don wannan mai amfani, amma ba ya ƙunshe da kowane relays. Da fatan za a umurci mai karɓa ya ƙara relays zuwa rikodin su na Nostr.", + "no_relay_on_domain": "Babu gudun ba da sanda ga yankin mai amfani ko kuma ba a samu ba. Da fatan za a zaɓi gudun ba da sanda don amfani." } diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 91bf40d60..b37aa7c12 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -768,5 +768,9 @@ "confirmed_tx": "की पुष्टि", "transaction_details_source_address": "स्रोत पता", "pause_wallet_creation": "हेवन वॉलेट बनाने की क्षमता फिलहाल रुकी हुई है।", - "camera_consent": "आपके कैमरे का उपयोग ${provider} द्वारा पहचान उद्देश्यों के लिए एक छवि कैप्चर करने के लिए किया जाएगा। विवरण के लिए कृपया उनकी गोपनीयता नीति जांचें।" + "camera_consent": "आपके कैमरे का उपयोग ${provider} द्वारा पहचान उद्देश्यों के लिए एक छवि कैप्चर करने के लिए किया जाएगा। विवरण के लिए कृपया उनकी गोपनीयता नीति जांचें।", + "no_relays": "कोई रिले नहीं", + "choose_relay": "कृपया उपयोग करने के लिए एक रिले चुनें", + "no_relays_message": "हमें इस उपयोगकर्ता के लिए एक Nostr NIP-05 रिकॉर्ड मिला, लेकिन इसमें कोई रिले नहीं है। कृपया प्राप्तकर्ता को अपने नॉस्ट्र रिकॉर्ड में रिले जोड़ने का निर्देश दें।", + "no_relay_on_domain": "उपयोगकर्ता के डोमेन के लिए कोई रिले नहीं है या रिले अनुपलब्ध है। कृपया उपयोग करने के लिए एक रिले चुनें।" } diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index b3c49ce78..c1ba66bb2 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -766,5 +766,9 @@ "confirmed_tx": "Potvrđen", "transaction_details_source_address": "Adresa izvora", "pause_wallet_creation": "Mogućnost stvaranja novčanika Haven trenutno je pauzirana.", - "camera_consent": "Vaš će fotoaparat koristiti za snimanje slike u svrhu identifikacije od strane ${provider}. Pojedinosti potražite u njihovoj politici privatnosti." + "camera_consent": "Vaš će fotoaparat koristiti za snimanje slike u svrhu identifikacije od strane ${provider}. Pojedinosti potražite u njihovoj politici privatnosti.", + "no_relays": "Nema releja", + "choose_relay": "Odaberite relej za korištenje", + "no_relays_message": "Pronašli smo zapis Nostr NIP-05 za ovog korisnika, ali on ne sadrži nikakve releje. Uputite primatelja da doda releje u svoj Nostr zapis.", + "no_relay_on_domain": "Ne postoji relej za korisničku domenu ili je relej nedostupan. Odaberite relej za korištenje." } diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 2a8fd06e8..b736f3977 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -756,5 +756,9 @@ "confirmed_tx": "Dikonfirmasi", "transaction_details_source_address": "Alamat sumber", "pause_wallet_creation": "Kemampuan untuk membuat Haven Wallet saat ini dijeda.", - "camera_consent": "Kamera Anda akan digunakan untuk mengambil gambar untuk tujuan identifikasi oleh ${provider}. Silakan periksa Kebijakan Privasi mereka untuk detailnya." + "camera_consent": "Kamera Anda akan digunakan untuk mengambil gambar untuk tujuan identifikasi oleh ${provider}. Silakan periksa Kebijakan Privasi mereka untuk detailnya.", + "no_relays": "Tidak ada relay", + "choose_relay": "Silakan pilih relai yang akan digunakan", + "no_relays_message": "Kami menemukan catatan Nostr NIP-05 untuk pengguna ini, tetapi tidak berisi relay apa pun. Harap instruksikan penerima untuk menambahkan relay ke catatan Nostr mereka.", + "no_relay_on_domain": "Tidak ada relai untuk domain pengguna atau relai tidak tersedia. Silakan pilih relai yang akan digunakan." } diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 01e88d56f..adcaa3204 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -768,5 +768,9 @@ "confirmed_tx": "Confermato", "transaction_details_source_address": "Indirizzo di partenza", "pause_wallet_creation": "La possibilità di creare Haven Wallet è attualmente sospesa.", - "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." + "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.", + "no_relays": "Nessun relè", + "choose_relay": "Scegli un relè da utilizzare", + "no_relays_message": "Abbiamo trovato un record Nostr NIP-05 per questo utente, ma non contiene alcun relè. Si prega di indicare al destinatario di aggiungere inoltri al proprio record Nostr.", + "no_relay_on_domain": "Non esiste un inoltro per il dominio dell'utente oppure l'inoltro non è disponibile. Scegli un relè da utilizzare." } diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 07bf5fca8..9dabebc45 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -768,5 +768,9 @@ "confirmed_tx": "確認済み", "transaction_details_source_address": "ソースアドレス", "pause_wallet_creation": "Haven Wallet を作成する機能は現在一時停止されています。", - "camera_consent": "あなたのカメラは、${provider}_ までに識別目的で画像を撮影するために使用されます。詳細については、プライバシー ポリシーをご確認ください。" + "camera_consent": "あなたのカメラは、${provider}_ までに識別目的で画像を撮影するために使用されます。詳細については、プライバシー ポリシーをご確認ください。", + "no_relays": "リレーなし", + "choose_relay": "使用するリレーを選択してください", + "no_relays_message": "このユーザーの Nostr NIP-05 レコードが見つかりましたが、リレーは含まれていません。受信者に Nostr レコードにリレーを追加するよう指示してください。", + "no_relay_on_domain": "ユーザーのドメインのリレーが存在しないか、リレーが使用できません。使用するリレーを選択してください。" } diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 7ea1ea85d..ee41a369b 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -766,5 +766,9 @@ "confirmed_tx": "확인", "transaction_details_source_address": "소스 주소", "pause_wallet_creation": "Haven Wallet 생성 기능이 현재 일시 중지되었습니다.", - "camera_consent": "귀하의 카메라는 ${provider}의 식별 목적으로 이미지를 캡처하는 데 사용됩니다. 자세한 내용은 해당 개인정보 보호정책을 확인하세요." + "camera_consent": "귀하의 카메라는 ${provider}의 식별 목적으로 이미지를 캡처하는 데 사용됩니다. 자세한 내용은 해당 개인정보 보호정책을 확인하세요.", + "no_relays": "릴레이 없음", + "choose_relay": "사용할 릴레이를 선택해주세요", + "no_relays_message": "이 사용자에 대한 Nostr NIP-05 레코드를 찾았지만 릴레이가 포함되어 있지 않습니다. 수신자에게 Nostr 기록에 릴레이를 추가하도록 지시하십시오.", + "no_relay_on_domain": "사용자 도메인에 릴레이가 없거나 릴레이를 사용할 수 없습니다. 사용할 릴레이를 선택해주세요." } diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 9559d224e..199d72660 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -766,5 +766,9 @@ "confirmed_tx": "အတည်ပြုသည်", "transaction_details_source_address": "အရင်းအမြစ်လိပ်စာ", "pause_wallet_creation": "Haven Wallet ဖန်တီးနိုင်မှုကို လောလောဆယ် ခေတ္တရပ်ထားသည်။", - "camera_consent": "မှတ်ပုံတင်ခြင်းရည်ရွယ်ချက်များအတွက် ${provider} တွင် သင့်ကင်မရာကို အသုံးပြုပါမည်။ အသေးစိတ်အတွက် ၎င်းတို့၏ ကိုယ်ရေးကိုယ်တာမူဝါဒကို စစ်ဆေးပါ။" + "camera_consent": "မှတ်ပုံတင်ခြင်းရည်ရွယ်ချက်များအတွက် ${provider} တွင် သင့်ကင်မရာကို အသုံးပြုပါမည်။ အသေးစိတ်အတွက် ၎င်းတို့၏ ကိုယ်ရေးကိုယ်တာမူဝါဒကို စစ်ဆေးပါ။", + "no_relays": "Relay မရှိပါ။", + "choose_relay": "အသုံးပြုရန် relay ကိုရွေးချယ်ပါ။", + "no_relays_message": "ဤအသုံးပြုသူအတွက် Nostr NIP-05 မှတ်တမ်းကို ကျွန်ုပ်တို့တွေ့ရှိသော်လည်း ၎င်းတွင် မည်သည့် relays မှ မပါဝင်ပါ။ ကျေးဇူးပြု၍ လက်ခံသူကို ၎င်းတို့၏ Nostr မှတ်တမ်းတွင် ထပ်လောင်းထည့်ရန် ညွှန်ကြားပါ။", + "no_relay_on_domain": "အသုံးပြုသူ၏ဒိုမိန်းအတွက် ထပ်ဆင့်လွှင့်ခြင်း မရှိပါ သို့မဟုတ် ထပ်ဆင့်လွှင့်ခြင်း မရနိုင်ပါ။ အသုံးပြုရန် relay ကိုရွေးချယ်ပါ။" } diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 23a635a99..9f27236aa 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -768,5 +768,9 @@ "confirmed_tx": "Bevestigd", "transaction_details_source_address": "Bron adres", "pause_wallet_creation": "De mogelijkheid om Haven Wallet te maken is momenteel onderbroken.", - "camera_consent": "Uw camera wordt gebruikt om vóór ${provider} een beeld vast te leggen voor identificatiedoeleinden. Raadpleeg hun privacybeleid voor meer informatie." + "camera_consent": "Uw camera wordt gebruikt om vóór ${provider} een beeld vast te leggen voor identificatiedoeleinden. Raadpleeg hun privacybeleid voor meer informatie.", + "no_relays": "Geen relais", + "choose_relay": "Kies een relais dat u wilt gebruiken", + "no_relays_message": "We hebben een Nostr NIP-05-record voor deze gebruiker gevonden, maar deze bevat geen relays. Instrueer de ontvanger om relays toe te voegen aan zijn Nostr-record.", + "no_relay_on_domain": "Er is geen relay voor het domein van de gebruiker of de relay is niet beschikbaar. Kies een relais dat u wilt gebruiken." } diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index f3e9db35c..c6e4806b1 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -768,5 +768,9 @@ "confirmed_tx": "Potwierdzony", "transaction_details_source_address": "Adres źródłowy", "pause_wallet_creation": "Możliwość utworzenia Portfela Haven jest obecnie wstrzymana.", - "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." + "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.", + "no_relays": "Żadnych przekaźników", + "choose_relay": "Wybierz przekaźnik, którego chcesz użyć", + "no_relays_message": "Znaleźliśmy rekord Nostr NIP-05 dla tego użytkownika, ale nie zawiera on żadnych przekaźników. Poinstruuj odbiorcę, aby dodał przekaźniki do swojego rekordu Nostr.", + "no_relay_on_domain": "Brak przekaźnika dla domeny użytkownika lub przekaźnik jest niedostępny. Wybierz przekaźnik, którego chcesz użyć." } diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 42c4cec28..b9694d223 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -767,5 +767,9 @@ "confirmed_tx": "Confirmado", "transaction_details_source_address": "Endereço de Origem", "pause_wallet_creation": "A capacidade de criar a Haven Wallet está atualmente pausada.", - "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." + "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.", + "no_relays": "Sem relés", + "choose_relay": "Escolha um relé para usar", + "no_relays_message": "Encontramos um registro Nostr NIP-05 para este usuário, mas ele não contém nenhum relé. Instrua o destinatário a adicionar retransmissões ao seu registro Nostr.", + "no_relay_on_domain": "Não há uma retransmissão para o domínio do usuário ou a retransmissão está indisponível. Escolha um relé para usar." } diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index edc6993a0..3e5d2cec2 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -768,5 +768,9 @@ "confirmed_tx": "Подтвержденный", "transaction_details_source_address": "Адрес источника", "pause_wallet_creation": "Возможность создания Haven Wallet в настоящее время приостановлена.", - "camera_consent": "Ваша камера будет использоваться для захвата изображения в целях идентификации ${provider}. Пожалуйста, ознакомьтесь с их Политикой конфиденциальности для получения подробной информации." + "camera_consent": "Ваша камера будет использоваться для захвата изображения в целях идентификации ${provider}. Пожалуйста, ознакомьтесь с их Политикой конфиденциальности для получения подробной информации.", + "no_relays": "Нет реле", + "choose_relay": "Пожалуйста, выберите реле для использования", + "no_relays_message": "Мы нашли запись Nostr NIP-05 для этого пользователя, но она не содержит никаких реле. Попросите получателя добавить реле в свою запись Nostr.", + "no_relay_on_domain": "Для домена пользователя реле не существует или реле недоступно. Пожалуйста, выберите реле для использования." } diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 80fa3f9c6..a9fe67959 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -766,5 +766,9 @@ "confirmed_tx": "ซึ่งยืนยันแล้ว", "transaction_details_source_address": "ที่อยู่แหล่งกำเนิด", "pause_wallet_creation": "ขณะนี้ความสามารถในการสร้าง Haven Wallet ถูกหยุดชั่วคราว", - "camera_consent": "กล้องของคุณจะถูกนำมาใช้เพื่อจับภาพเพื่อวัตถุประสงค์ในการระบุตัวตนภายใน ${provider} โปรดตรวจสอบนโยบายความเป็นส่วนตัวเพื่อดูรายละเอียด" + "camera_consent": "กล้องของคุณจะถูกนำมาใช้เพื่อจับภาพเพื่อวัตถุประสงค์ในการระบุตัวตนภายใน ${provider} โปรดตรวจสอบนโยบายความเป็นส่วนตัวเพื่อดูรายละเอียด", + "no_relays": "ไม่มีรีเลย์", + "choose_relay": "กรุณาเลือกรีเลย์ที่จะใช้", + "no_relays_message": "เราพบบันทึก Nostr NIP-05 สำหรับผู้ใช้รายนี้ แต่ไม่มีรีเลย์ใดๆ โปรดแนะนำให้ผู้รับเพิ่มรีเลย์ลงในบันทึก Nostr ของตน", + "no_relay_on_domain": "ไม่มีการส่งต่อสำหรับโดเมนของผู้ใช้ หรือการส่งต่อไม่พร้อมใช้งาน กรุณาเลือกรีเลย์ที่จะใช้" } diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 558f26911..3d05cc700 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -762,5 +762,9 @@ "confirmed_tx": "Nakumpirma", "transaction_details_source_address": "SOURCE ADDRESS", "pause_wallet_creation": "Kasalukuyang naka-pause ang kakayahang gumawa ng Haven Wallet.", - "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." + "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.", + "no_relays": "Walang mga relay", + "choose_relay": "Mangyaring pumili ng relay na gagamitin", + "no_relays_message": "Nakakita kami ng Nostr NIP-05 record para sa user na ito, ngunit hindi ito naglalaman ng anumang mga relay. Mangyaring atasan ang tatanggap na magdagdag ng mga relay sa kanilang Nostr record.", + "no_relay_on_domain": "Walang relay para sa domain ng user o hindi available ang relay. Mangyaring pumili ng relay na gagamitin." } diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index bbbecaf5c..62243838d 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -766,5 +766,9 @@ "confirmed_tx": "Onaylanmış", "transaction_details_source_address": "Kaynak adresi", "pause_wallet_creation": "Haven Cüzdanı oluşturma yeteneği şu anda duraklatıldı.", - "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." + "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.", + "no_relays": "Röle yok", + "choose_relay": "Lütfen kullanmak için bir röle seçin", + "no_relays_message": "Bu kullanıcı için bir Nostr NIP-05 kaydı bulduk ancak bu kayıt herhangi bir aktarma içermiyor. Lütfen alıcıya Nostr kayıtlarına aktarma eklemesi talimatını verin.", + "no_relay_on_domain": "Kullanıcının alanı için bir geçiş yok veya geçiş kullanılamıyor. Lütfen kullanmak için bir röle seçin." } diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index a1d08b352..def086b2e 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -768,5 +768,9 @@ "confirmed_tx": "Підтверджений", "transaction_details_source_address": "Адреса джерела", "pause_wallet_creation": "Можливість створення гаманця Haven зараз призупинено.", - "camera_consent": "Ваша камера використовуватиметься для зйомки зображення з метою ідентифікації ${provider}. Будь ласка, ознайомтеся з їхньою політикою конфіденційності, щоб дізнатися більше." + "camera_consent": "Ваша камера використовуватиметься для зйомки зображення з метою ідентифікації ${provider}. Будь ласка, ознайомтеся з їхньою політикою конфіденційності, щоб дізнатися більше.", + "no_relays": "Без реле", + "choose_relay": "Будь ласка, виберіть реле для використання", + "no_relays_message": "Ми знайшли запис Nostr NIP-05 для цього користувача, але він не містить жодних реле. Будь ласка, попросіть одержувача додати реле до свого запису Nostr.", + "no_relay_on_domain": "Немає ретранслятора для домену користувача або ретранслятор недоступний. Будь ласка, виберіть реле для використання." } diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 517aa9ded..34b1042ac 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -760,5 +760,9 @@ "confirmed_tx": "تصدیق", "transaction_details_source_address": "ماخذ ایڈریس", "pause_wallet_creation": "Haven Wallet ۔ﮯﮨ ﻑﻮﻗﻮﻣ ﻝﺎﺤﻟﺍ ﯽﻓ ﺖﯿﻠﮨﺍ ﯽﮐ ﮯﻧﺎﻨﺑ", - "camera_consent": "۔ﮟﯿﮭﮑﯾﺩ ﯽﺴﯿﻟﺎﭘ ﯽﺴﯾﻮﯿﺋﺍﺮﭘ ﯽﮐ ﻥﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ﮯﯿﻟ ﮯﮐ ﺕﻼ${provider}ﯿﺼﻔﺗ ۔ﺎﮔ ﮯﺋﺎﺟ ﺎﯿﮐ ﻝﺎﻤﻌﺘﺳﺍ ﮯﯿﻟ" + "camera_consent": "۔ﮟﯿﮭﮑﯾﺩ ﯽﺴﯿﻟﺎﭘ ﯽﺴﯾﻮﯿﺋﺍﺮﭘ ﯽﮐ ﻥﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ﮯﯿﻟ ﮯﮐ ﺕﻼ${provider}ﯿﺼﻔﺗ ۔ﺎﮔ ﮯﺋﺎﺟ ﺎﯿﮐ ﻝﺎﻤﻌﺘﺳﺍ ﮯﯿﻟ", + "no_relays": " ۔ﮟﯿﮩﻧ ﮯﻠﯾﺭ ﯽﺋﻮﮐ", + "choose_relay": " ۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﮯﻠﯾﺭ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ ﻡﺮﮐ ﮦﺍﺮﺑ", + "no_relays_message": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮯﻠﯾﺭ ﮟﯿﻣ ﮈﺭﺎﮑﯾﺭ ﺮﭩﺳﻮﻧ ﮯﻨﭘﺍ ﮦﻭ ﮧﮐ ﮟﯾﺩ ﺖﯾﺍﺪﮨ ﻮﮐ ﮦﺪﻨﻨﮐ ﻝﻮﺻﻭ ﻡﺮﮐ ﮦﺍﺮﺑ ۔", + "no_relay_on_domain": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﮯﻠﯾﺭ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ۔ﮯﮨ ﮟﯿﮩﻧ ﺏﺎﯿﺘﺳﺩ ﮯﻠﯾﺭ ﺎﯾ ﮯﮨ ﮟ" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 298c73c67..12769ec91 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -762,5 +762,9 @@ "confirmed_tx": "Jẹrisi", "transaction_details_source_address": "Adirẹsi orisun", "pause_wallet_creation": "Agbara lati ṣẹda Haven Wallet ti wa ni idaduro lọwọlọwọ.", - "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." + "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.", + "no_relays": "Ko si relays", + "choose_relay": "Jọwọ yan yii lati lo", + "no_relays_message": "A ri igbasilẹ Nostr NIP-05 fun olumulo yii, ṣugbọn ko ni eyikeyi awọn iṣipopada ninu. Jọwọ sọ fun olugba lati ṣafikun awọn isunmọ si igbasilẹ Nostr wọn.", + "no_relay_on_domain": "Ko si iṣipopada fun agbegbe olumulo tabi yiyi ko si. Jọwọ yan yii lati lo." } diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 20255e76c..cdffd8141 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -767,5 +767,9 @@ "confirmed_tx": "确认的", "transaction_details_source_address": "源地址", "pause_wallet_creation": "创建 Haven 钱包的功能当前已暂停。", - "camera_consent": "${provider} 将使用您的相机拍摄图像以供识别之用。请查看他们的隐私政策了解详情。" + "camera_consent": "${provider} 将使用您的相机拍摄图像以供识别之用。请查看他们的隐私政策了解详情。", + "no_relays": "无继电器", + "choose_relay": "请选择要使用的继电器", + "no_relays_message": "我们找到了该用户的 Nostr NIP-05 记录,但它不包含任何中继。请指示收件人将中继添加到他们的 Nostr 记录中。", + "no_relay_on_domain": "用户域没有中继或中继不可用。请选择要使用的继电器。" } From f68987bfb98aee5593321871f6f74427415a63fc Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Sat, 27 Jan 2024 04:08:53 +0100 Subject: [PATCH 103/241] CW-566-Cake2FA-Bypass-Bug (#1275) * fix: TOTP 2FA Bug * fix: key switch error * Fix 2fa preset issue --------- Co-authored-by: OmarHatem --- lib/store/settings_store.dart | 4 ++-- lib/view_model/set_up_2fa_viewmodel.dart | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index e792ee3b0..0ffedec90 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -997,7 +997,7 @@ abstract class SettingsStoreBase with Store { final totpSecretKey = await SecureKey.getString( secureStorage: secureStorage, sharedPreferences: sharedPreferences, - key: SecureKey.useTOTP2FA, + key: SecureKey.totpSecretKey, ) ?? ''; @@ -1243,7 +1243,7 @@ abstract class SettingsStoreBase with Store { totpSecretKey = await SecureKey.getString( secureStorage: _secureStorage, sharedPreferences: sharedPreferences, - key: SecureKey.useTOTP2FA, + key: SecureKey.totpSecretKey, ) ?? totpSecretKey; diff --git a/lib/view_model/set_up_2fa_viewmodel.dart b/lib/view_model/set_up_2fa_viewmodel.dart index 9587e3075..7347b32a8 100644 --- a/lib/view_model/set_up_2fa_viewmodel.dart +++ b/lib/view_model/set_up_2fa_viewmodel.dart @@ -27,7 +27,9 @@ abstract class Setup2FAViewModelBase with Store { unhighlightTabs = false, selected2FASettings = ObservableList(), state = InitialExecutionState() { - selectCakePreset(selectedCake2FAPreset); + if (selectedCake2FAPreset != Cake2FAPresetsOptions.none) { + selectCakePreset(selectedCake2FAPreset); + } reaction((_) => state, _saveLastAuthTime); } From 952503f0d8f77c3d2714bb577a7a2f4061b365ce Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Mon, 29 Jan 2024 22:49:54 +0200 Subject: [PATCH 104/241] New versions (#1277) * New versions * Update macos build number Minor UI fix --- assets/text/Monerocom_Release_Notes.txt | 6 +++--- assets/text/Release_Notes.txt | 10 ++++------ .../screens/receive/widgets/address_cell.dart | 16 +++++++++------- scripts/android/app_env.sh | 8 ++++---- scripts/ios/app_env.sh | 8 ++++---- scripts/macos/app_env.sh | 8 ++++---- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 2715bdeee..2b783ee1e 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,3 +1,3 @@ -On-ramp flow fixes and enhancements -UI enhancements -Generic enhancements and bug fixes \ No newline at end of file +Security and Privacy enhancements +Usability enhancements +Bug fixes \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 90428c2ab..411ed609b 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,6 +1,4 @@ -Add new Off-ramp providers (DFX, OnRamper) -On-ramp flow fixes and enhancements -Ethereum and WalletConnect fixes and improvements -Nano enhancements -UI enhancements -Generic enhancements and bug fixes \ No newline at end of file +List previously used Bitcoin addresses +Security and Privacy enhancements +Usability enhancements +Bug fixes \ No newline at end of file diff --git a/lib/src/screens/receive/widgets/address_cell.dart b/lib/src/screens/receive/widgets/address_cell.dart index 92c870421..a07456284 100644 --- a/lib/src/screens/receive/widgets/address_cell.dart +++ b/lib/src/screens/receive/widgets/address_cell.dart @@ -113,13 +113,15 @@ class AddressCell extends StatelessWidget { color: textColor, ), ), - AutoSizeText( - formattedAddress, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: isChange ? 10 : 14, - color: textColor, + Flexible( + child: AutoSizeText( + formattedAddress, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: isChange ? 10 : 14, + color: textColor, + ), ), ), ], diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 163f178f3..9301b4a89 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.10.0" -MONERO_COM_BUILD_NUMBER=72 +MONERO_COM_VERSION="1.10.1" +MONERO_COM_BUILD_NUMBER=73 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.13.0" -CAKEWALLET_BUILD_NUMBER=189 +CAKEWALLET_VERSION="4.13.1" +CAKEWALLET_BUILD_NUMBER=190 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 9920b1e54..4642fbc64 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.10.0" -MONERO_COM_BUILD_NUMBER=70 +MONERO_COM_VERSION="1.10.1" +MONERO_COM_BUILD_NUMBER=71 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.13.0" -CAKEWALLET_BUILD_NUMBER=208 +CAKEWALLET_VERSION="4.13.1" +CAKEWALLET_BUILD_NUMBER=209 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index fa040dfee..4e9c7a09b 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -16,13 +16,13 @@ if [ -n "$1" ]; then fi MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.0.0" -MONERO_COM_BUILD_NUMBER=1 +MONERO_COM_VERSION="1.0.1" +MONERO_COM_BUILD_NUMBER=3 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.6.0" -CAKEWALLET_BUILD_NUMBER=50 +CAKEWALLET_VERSION="1.6.1" +CAKEWALLET_BUILD_NUMBER=51 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From b92ccb5c0b28d6ea260aca5751738e8a034598f0 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Tue, 30 Jan 2024 19:57:47 +0200 Subject: [PATCH 105/241] Generic fixes (#1282) * New versions * Fix unspent coins issue * Fix white screen issues for some users --- lib/bitcoin/cw_bitcoin.dart | 2 +- lib/entities/default_settings_migration.dart | 7 ++- lib/monero/cw_monero.dart | 2 +- .../exchange_trade/exchange_trade_page.dart | 20 +++---- lib/src/screens/root/root.dart | 10 ++-- lib/store/settings_store.dart | 12 ++++- .../unspent_coins_list_view_model.dart | 54 ++++++++++++------- scripts/android/app_env.sh | 8 +-- scripts/ios/app_env.sh | 8 +-- scripts/macos/app_env.sh | 8 +-- tool/configure.dart | 4 +- 11 files changed, 82 insertions(+), 53 deletions(-) diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index b6fb6e62d..6836cc4dc 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -150,7 +150,7 @@ class CWBitcoin extends Bitcoin { return bitcoinWallet.unspentCoins; } - void updateUnspents(Object wallet) async { + Future updateUnspents(Object wallet) async { final bitcoinWallet = wallet as ElectrumWallet; await bitcoinWallet.updateUnspent(); } diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 1279beeca..68e76d423 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -186,7 +186,10 @@ Future defaultSettingsMigration( await rewriteSecureStoragePin(secureStorage: secureStorage); break; case 26: - await insecureStorageMigration(secureStorage: secureStorage, sharedPreferences: sharedPreferences); + /// commented out as it was a probable cause for some users to have white screen issues + /// maybe due to multiple access on Secure Storage at once + /// or long await time on start of the app + // await insecureStorageMigration(secureStorage: secureStorage, sharedPreferences: sharedPreferences); break; default: break; @@ -507,7 +510,7 @@ Future changeLitecoinCurrentElectrumServerToDefault( Future changeBitcoinCashCurrentNodeToDefault( {required SharedPreferences sharedPreferences, required Box nodes}) async { final server = getBitcoinCashDefaultElectrumServer(nodes: nodes); - final serverId = server?.key as int ?? 0; + final serverId = server?.key as int? ?? 0; await sharedPreferences.setInt(PreferencesKey.currentBitcoinCashNodeIdKey, serverId); } diff --git a/lib/monero/cw_monero.dart b/lib/monero/cw_monero.dart index 947d274a8..959ae92ce 100644 --- a/lib/monero/cw_monero.dart +++ b/lib/monero/cw_monero.dart @@ -331,7 +331,7 @@ class CWMonero extends Monero { } @override - void updateUnspents(Object wallet) async { + Future updateUnspents(Object wallet) async { final moneroWallet = wallet as MoneroWallet; await moneroWallet.updateUnspent(); } diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index 41fc29713..c4dcae32c 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -283,15 +283,17 @@ class ExchangeTradeState extends State { if (state is TransactionCommitted) { WidgetsBinding.instance.addPostFrameCallback((_) { - showPopUp( - context: context, - builder: (BuildContext popupContext) { - return AlertWithOneAction( - alertTitle: S.of(popupContext).sending, - alertContent: S.of(popupContext).transaction_sent, - buttonText: S.of(popupContext).ok, - buttonAction: () => Navigator.of(popupContext).pop()); - }); + if (context.mounted) { + showPopUp( + context: context, + builder: (BuildContext popupContext) { + return AlertWithOneAction( + alertTitle: S.of(popupContext).sending, + alertContent: S.of(popupContext).transaction_sent, + buttonText: S.of(popupContext).ok, + buttonAction: () => Navigator.of(popupContext).pop()); + }); + } }); } }); diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index b3d503162..5704c99ad 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -53,16 +53,16 @@ class RootState extends State with WidgetsBindingObserver { @override void initState() { - WidgetsBinding.instance.addPostFrameCallback((_) async { - bool value = await widget.authService.requireAuth(); - setState(() { - _requestAuth = value; + WidgetsBinding.instance.addObserver(this); + + widget.authService.requireAuth().then((value) { + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() => _requestAuth = value); }); }); _isInactiveController = StreamController.broadcast(); _isInactive = false; _postFrameCallback = false; - WidgetsBinding.instance.addObserver(this); super.initState(); if (DeviceInfo.instance.isMobile) { initUniLinks(); diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 0ffedec90..253adf3ea 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -922,7 +922,7 @@ abstract class SettingsStoreBase with Store { final allowBiometricalAuthentication = await SecureKey.getBool( secureStorage: secureStorage, sharedPreferences: sharedPreferences, - key: SecureKey.pinTimeOutDuration, + key: SecureKey.allowBiometricalAuthenticationKey, ) ?? false; @@ -1247,6 +1247,16 @@ abstract class SettingsStoreBase with Store { ) ?? totpSecretKey; + final timeOutDuration = await SecureKey.getInt( + secureStorage: _secureStorage, + sharedPreferences: sharedPreferences, + key: SecureKey.pinTimeOutDuration, + ); + + pinTimeOutDuration = timeOutDuration != null + ? PinCodeRequiredDuration.deserialize(raw: timeOutDuration) + : defaultPinCodeTimeOutDuration; + allowBiometricalAuthentication = await SecureKey.getBool( secureStorage: _secureStorage, sharedPreferences: sharedPreferences, diff --git a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart index 1815b1689..6380bb07e 100644 --- a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart +++ b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart @@ -16,30 +16,17 @@ abstract class UnspentCoinsListViewModelBase with Store { UnspentCoinsListViewModelBase( {required this.wallet, required Box unspentCoinsInfo}) : _unspentCoinsInfo = unspentCoinsInfo { + _updateUnspentCoinsInfo(); _updateUnspents(); } WalletBase wallet; final Box _unspentCoinsInfo; - @computed - ObservableList get items => ObservableList.of(_getUnspents().map((elem) { - final info = - getUnspentCoinInfo(elem.hash, elem.address, elem.value, elem.vout, elem.keyImage); + final ObservableList _items = ObservableList(); - return UnspentCoinsItem( - address: elem.address, - amount: '${formatAmountToString(elem.value)} ${wallet.currency.title}', - hash: elem.hash, - isFrozen: info.isFrozen, - note: info.note, - isSending: info.isSending, - amountRaw: elem.value, - vout: elem.vout, - keyImage: elem.keyImage, - isChange: elem.isChange, - ); - })); + @computed + ObservableList get items => _items; Future saveUnspentCoinInfo(UnspentCoinsItem item) async { try { @@ -77,9 +64,14 @@ abstract class UnspentCoinsListViewModelBase with Store { } Future _updateUnspents() async { - if (wallet.type == WalletType.monero) return monero!.updateUnspents(wallet); - if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(wallet.type)) - return bitcoin!.updateUnspents(wallet); + if (wallet.type == WalletType.monero) { + await monero!.updateUnspents(wallet); + } + if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(wallet.type)) { + await bitcoin!.updateUnspents(wallet); + } + + _updateUnspentCoinsInfo(); } List _getUnspents() { @@ -88,4 +80,26 @@ abstract class UnspentCoinsListViewModelBase with Store { return bitcoin!.getUnspents(wallet); return List.empty(); } + + @action + void _updateUnspentCoinsInfo() { + _items.clear(); + _items.addAll(_getUnspents().map((elem) { + final info = + getUnspentCoinInfo(elem.hash, elem.address, elem.value, elem.vout, elem.keyImage); + + return UnspentCoinsItem( + address: elem.address, + amount: '${formatAmountToString(elem.value)} ${wallet.currency.title}', + hash: elem.hash, + isFrozen: info.isFrozen, + note: info.note, + isSending: info.isSending, + amountRaw: elem.value, + vout: elem.vout, + keyImage: elem.keyImage, + isChange: elem.isChange, + ); + })); + } } diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 9301b4a89..8de5be02c 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.10.1" -MONERO_COM_BUILD_NUMBER=73 +MONERO_COM_VERSION="1.10.2" +MONERO_COM_BUILD_NUMBER=74 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.13.1" -CAKEWALLET_BUILD_NUMBER=190 +CAKEWALLET_VERSION="4.13.2" +CAKEWALLET_BUILD_NUMBER=191 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 4642fbc64..c7d62a40a 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.10.1" -MONERO_COM_BUILD_NUMBER=71 +MONERO_COM_VERSION="1.10.2" +MONERO_COM_BUILD_NUMBER=72 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.13.1" -CAKEWALLET_BUILD_NUMBER=209 +CAKEWALLET_VERSION="4.13.2" +CAKEWALLET_BUILD_NUMBER=210 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 4e9c7a09b..c2c7493af 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -16,13 +16,13 @@ if [ -n "$1" ]; then fi MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.0.1" -MONERO_COM_BUILD_NUMBER=3 +MONERO_COM_VERSION="1.0.2" +MONERO_COM_BUILD_NUMBER=4 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.6.1" -CAKEWALLET_BUILD_NUMBER=51 +CAKEWALLET_VERSION="1.6.2" +CAKEWALLET_BUILD_NUMBER=52 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then diff --git a/tool/configure.dart b/tool/configure.dart index ce894d197..4421d4f3f 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -127,7 +127,7 @@ abstract class Bitcoin { String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate); List getUnspents(Object wallet); - void updateUnspents(Object wallet); + Future updateUnspents(Object wallet); WalletService createBitcoinWalletService(Box walletInfoSource, Box unspentCoinSource); WalletService createLitecoinWalletService(Box walletInfoSource, Box unspentCoinSource); TransactionPriority getBitcoinTransactionPriorityMedium(); @@ -270,7 +270,7 @@ abstract class Monero { List getMoneroWordList(String language); List getUnspents(Object wallet); - void updateUnspents(Object wallet); + Future updateUnspents(Object wallet); WalletCredentials createMoneroRestoreWalletFromKeysCredentials({ required String name, From 7410daacff6f35e12e079ab45cc1c15d2453c600 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Tue, 30 Jan 2024 19:01:48 +0100 Subject: [PATCH 106/241] CW-551-Refactor-EVM-Chains (#1256) * feat: Create central package for EVM chains * chore: Cleanup pubspec and add core evm dependencies * feat: Replicated core evm chain files, time to start fixing the issues * feat: Setup evm central package to handle all evm chains * feat: Link up Polygon and Ethereum wallets to the centra evm package, fix bugs and issues, and optimze for better performance * feat: Setup and adjust configs to reflect new evm configurations * Remove unneeded file * fix: Changes done while re-reviewing entire structure and refactor * fix: Add evm chain wallet path to imports in configure file * feat: Adjust implementation of parent class, remove unneeded files, remove windows, linux and mac directories, restructure the evm child classes * fix: Make EVMChainWallet a central abstract class and adjust accordingly * fix: Adjust transaction info, restructure EVMWalletChain to be an abstract, adjust external facing interfaces for polygon and ethereum, adjust configuration for ethereum and polygon in configure file * fix: Testing issues * fix: Add localization for nft tile and details page texts and add dashes for null responses * fix: merge conflicts * Minor fixes for building Monero.com --------- Co-authored-by: OmarHatem --- .github/workflows/pr_test_build.yml | 10 +- .gitignore | 3 +- configure_cake_wallet.sh | 3 +- .../lib/default_ethereum_erc20_tokens.dart | 2 +- cw_ethereum/lib/ethereum_client.dart | 260 +------- cw_ethereum/lib/ethereum_exceptions.dart | 11 - cw_ethereum/lib/ethereum_formatter.dart | 25 - .../lib/ethereum_mnemonics_exception.dart | 5 + .../lib/ethereum_transaction_history.dart | 79 +-- .../lib/ethereum_transaction_info.dart | 82 +-- .../lib/ethereum_transaction_priority.dart | 52 -- cw_ethereum/lib/ethereum_wallet.dart | 551 +++-------------- .../ethereum_wallet_creation_credentials.dart | 29 - cw_ethereum/lib/ethereum_wallet_service.dart | 76 +-- cw_ethereum/pubspec.yaml | 39 +- cw_evm/.gitignore | 30 + cw_evm/.metadata | 10 + cw_evm/CHANGELOG.md | 3 + cw_evm/LICENSE | 1 + cw_evm/README.md | 39 ++ cw_evm/analysis_options.yaml | 4 + cw_evm/lib/cw_evm.dart | 7 + cw_evm/lib/evm_chain_client.dart | 251 ++++++++ cw_evm/lib/evm_chain_exceptions.dart | 11 + cw_evm/lib/evm_chain_formatter.dart | 25 + .../lib/evm_chain_mnemonics.dart | 8 +- .../evm_chain_transaction_credentials.dart | 8 +- cw_evm/lib/evm_chain_transaction_history.dart | 88 +++ cw_evm/lib/evm_chain_transaction_info.dart | 77 +++ .../lib/evm_chain_transaction_model.dart | 10 +- .../lib/evm_chain_transaction_priority.dart | 52 ++ cw_evm/lib/evm_chain_wallet.dart | 512 ++++++++++++++++ .../lib/evm_chain_wallet_addresses.dart | 12 +- ...evm_chain_wallet_creation_credentials.dart | 29 + cw_evm/lib/evm_chain_wallet_service.dart | 50 ++ .../lib/evm_erc20_balance.dart | 13 +- {cw_ethereum => cw_evm}/lib/file.dart | 0 .../lib/pending_evm_chain_transaction.dart | 4 +- cw_evm/pubspec.yaml | 45 ++ cw_evm/test/cw_evm_test.dart | 12 + .../lib/pending_polygon_transaction.dart | 19 - cw_polygon/lib/polygon_client.dart | 14 +- cw_polygon/lib/polygon_exceptions.dart | 6 - cw_polygon/lib/polygon_formatter.dart | 25 - .../lib/polygon_transaction_credentials.dart | 18 - .../lib/polygon_transaction_history.dart | 80 +-- cw_polygon/lib/polygon_transaction_info.dart | 44 +- cw_polygon/lib/polygon_transaction_model.dart | 49 -- .../lib/polygon_transaction_priority.dart | 51 -- cw_polygon/lib/polygon_wallet.dart | 564 +++--------------- cw_polygon/lib/polygon_wallet_addresses.dart | 5 - .../polygon_wallet_creation_credentials.dart | 28 - cw_polygon/lib/polygon_wallet_service.dart | 63 +- cw_polygon/pubspec.yaml | 15 +- lib/ethereum/cw_ethereum.dart | 38 +- lib/polygon/cw_polygon.dart | 38 +- .../dashboard/pages/nft_details_page.dart | 14 +- .../dashboard/widgets/nft_tile_widget.dart | 34 +- .../transaction_details_view_model.dart | 6 +- model_generator.sh | 3 +- res/values/strings_ar.arb | 7 +- res/values/strings_bg.arb | 3 + res/values/strings_cs.arb | 3 + res/values/strings_de.arb | 3 + res/values/strings_en.arb | 3 + res/values/strings_es.arb | 3 + res/values/strings_fr.arb | 3 + res/values/strings_ha.arb | 3 + res/values/strings_hi.arb | 3 + res/values/strings_hr.arb | 3 + res/values/strings_id.arb | 3 + res/values/strings_it.arb | 3 + res/values/strings_ja.arb | 3 + res/values/strings_ko.arb | 3 + res/values/strings_my.arb | 3 + res/values/strings_nl.arb | 3 + res/values/strings_pl.arb | 3 + res/values/strings_pt.arb | 3 + res/values/strings_ru.arb | 3 + res/values/strings_th.arb | 3 + res/values/strings_tl.arb | 3 + res/values/strings_tr.arb | 3 + res/values/strings_uk.arb | 3 + res/values/strings_ur.arb | 7 +- res/values/strings_yo.arb | 3 + res/values/strings_zh.arb | 3 + tool/configure.dart | 56 +- tool/generate_secrets_config.dart | 8 +- tool/import_secrets_config.dart | 20 +- tool/utils/secret_key.dart | 4 +- 90 files changed, 1775 insertions(+), 2041 deletions(-) delete mode 100644 cw_ethereum/lib/ethereum_exceptions.dart delete mode 100644 cw_ethereum/lib/ethereum_formatter.dart create mode 100644 cw_ethereum/lib/ethereum_mnemonics_exception.dart delete mode 100644 cw_ethereum/lib/ethereum_transaction_priority.dart delete mode 100644 cw_ethereum/lib/ethereum_wallet_creation_credentials.dart create mode 100644 cw_evm/.gitignore create mode 100644 cw_evm/.metadata create mode 100644 cw_evm/CHANGELOG.md create mode 100644 cw_evm/LICENSE create mode 100644 cw_evm/README.md create mode 100644 cw_evm/analysis_options.yaml create mode 100644 cw_evm/lib/cw_evm.dart create mode 100644 cw_evm/lib/evm_chain_client.dart create mode 100644 cw_evm/lib/evm_chain_exceptions.dart create mode 100644 cw_evm/lib/evm_chain_formatter.dart rename cw_ethereum/lib/ethereum_mnemonics.dart => cw_evm/lib/evm_chain_mnemonics.dart (99%) rename cw_ethereum/lib/ethereum_transaction_credentials.dart => cw_evm/lib/evm_chain_transaction_credentials.dart (60%) create mode 100644 cw_evm/lib/evm_chain_transaction_history.dart create mode 100644 cw_evm/lib/evm_chain_transaction_info.dart rename cw_ethereum/lib/ethereum_transaction_model.dart => cw_evm/lib/evm_chain_transaction_model.dart (81%) create mode 100644 cw_evm/lib/evm_chain_transaction_priority.dart create mode 100644 cw_evm/lib/evm_chain_wallet.dart rename cw_ethereum/lib/ethereum_wallet_addresses.dart => cw_evm/lib/evm_chain_wallet_addresses.dart (63%) create mode 100644 cw_evm/lib/evm_chain_wallet_creation_credentials.dart create mode 100644 cw_evm/lib/evm_chain_wallet_service.dart rename cw_ethereum/lib/erc20_balance.dart => cw_evm/lib/evm_erc20_balance.dart (76%) rename {cw_ethereum => cw_evm}/lib/file.dart (100%) rename cw_ethereum/lib/pending_ethereum_transaction.dart => cw_evm/lib/pending_evm_chain_transaction.dart (91%) create mode 100644 cw_evm/pubspec.yaml create mode 100644 cw_evm/test/cw_evm_test.dart delete mode 100644 cw_polygon/lib/pending_polygon_transaction.dart delete mode 100644 cw_polygon/lib/polygon_exceptions.dart delete mode 100644 cw_polygon/lib/polygon_formatter.dart delete mode 100644 cw_polygon/lib/polygon_transaction_credentials.dart delete mode 100644 cw_polygon/lib/polygon_transaction_model.dart delete mode 100644 cw_polygon/lib/polygon_transaction_priority.dart delete mode 100644 cw_polygon/lib/polygon_wallet_addresses.dart delete mode 100644 cw_polygon/lib/polygon_wallet_creation_credentials.dart diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 88cdc6f6c..6e5f9e171 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -105,21 +105,19 @@ jobs: run: | cd /opt/android/cake_wallet cd cw_core && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. + cd cw_evm && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_monero && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. - cd cw_ethereum && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. - cd cw_polygon && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs - name: Add secrets run: | cd /opt/android/cake_wallet touch lib/.secrets.g.dart - touch cw_ethereum/lib/.secrets.g.dart - touch cw_polygon/lib/.secrets.g.dart + touch cw_evm/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 @@ -146,14 +144,14 @@ jobs: echo "const anonPayReferralCode = '${{ secrets.ANON_PAY_REFERRAL_CODE }}';" >> lib/.secrets.g.dart echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart - echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_ethereum/lib/.secrets.g.dart + echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_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 robinhoodCIdApiSecret = '${{ 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_ethereum/lib/.secrets.g.dart + echo "const polygonScanApiKey = '${{ secrets.POLYGON_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart - name: Rename app run: echo -e "id=com.cakewallet.test\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties diff --git a/.gitignore b/.gitignore index 2ffb86d76..f084f8d0d 100644 --- a/.gitignore +++ b/.gitignore @@ -90,9 +90,10 @@ android/key.properties **/tool/.secrets-prod.json **/tool/.secrets-test.json **/tool/.secrets-config.json +**/tool/.evm-secrets-config.json **/tool/.ethereum-secrets-config.json **/lib/.secrets.g.dart -**/cw_ethereum/lib/.secrets.g.dart +**/cw_evm/lib/.secrets.g.dart vendor/ diff --git a/configure_cake_wallet.sh b/configure_cake_wallet.sh index df96c70f6..a4b6f2654 100755 --- a/configure_cake_wallet.sh +++ b/configure_cake_wallet.sh @@ -24,11 +24,10 @@ source ./app_env.sh cakewallet cd ../.. && flutter pub get flutter packages pub run tool/generate_localization.dart cd cw_core && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_evm && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_monero && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -cd cw_ethereum && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -cd cw_polygon && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs diff --git a/cw_ethereum/lib/default_ethereum_erc20_tokens.dart b/cw_ethereum/lib/default_ethereum_erc20_tokens.dart index a8f82d181..c26ee1efc 100644 --- a/cw_ethereum/lib/default_ethereum_erc20_tokens.dart +++ b/cw_ethereum/lib/default_ethereum_erc20_tokens.dart @@ -1,7 +1,7 @@ import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/erc20_token.dart'; -class DefaultErc20Tokens { +class DefaultEthereumErc20Tokens { final List _defaultTokens = [ Erc20Token( name: "USD Coin", diff --git a/cw_ethereum/lib/ethereum_client.dart b/cw_ethereum/lib/ethereum_client.dart index 1b3e4bb44..929dadf2f 100644 --- a/cw_ethereum/lib/ethereum_client.dart +++ b/cw_ethereum/lib/ethereum_client.dart @@ -1,229 +1,22 @@ -import 'dart:async'; import 'dart:convert'; +import 'dart:developer'; +import 'dart:typed_data'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_ethereum/erc20_balance.dart'; -import 'package:cw_core/erc20_token.dart'; -import 'package:cw_ethereum/ethereum_transaction_model.dart'; -import 'package:cw_ethereum/pending_ethereum_transaction.dart'; -import 'package:flutter/services.dart'; -import 'package:http/http.dart'; +import 'package:cw_evm/evm_chain_client.dart'; +import 'package:cw_evm/.secrets.g.dart' as secrets; +import 'package:cw_evm/evm_chain_transaction_model.dart'; import 'package:web3dart/web3dart.dart'; -import 'package:erc20/erc20.dart'; -import 'package:cw_core/node.dart'; -import 'package:cw_ethereum/ethereum_transaction_priority.dart'; -import 'package:cw_ethereum/.secrets.g.dart' as secrets; - -class EthereumClient { - final httpClient = Client(); - Web3Client? _client; - - bool connect(Node node) { - try { - _client = Web3Client(node.uri.toString(), httpClient); - - return true; - } catch (e) { - return false; - } - } - - void setListeners(EthereumAddress userAddress, Function() onNewTransaction) async { - // _client?.pendingTransactions().listen((transactionHash) async { - // final transaction = await _client!.getTransactionByHash(transactionHash); - // - // if (transaction.from.hex == userAddress || transaction.to?.hex == userAddress) { - // onNewTransaction(); - // } - // }); - } - - Future getBalance(EthereumAddress address) async { - try { - return await _client!.getBalance(address); - } catch (_) { - return EtherAmount.zero(); - } - } - - Future getGasUnitPrice() async { - try { - final gasPrice = await _client!.getGasPrice(); - return gasPrice.getInWei.toInt(); - } catch (_) { - return 0; - } - } - - Future getEstimatedGas() async { - try { - final estimatedGas = await _client!.estimateGas(); - return estimatedGas.toInt(); - } catch (_) { - return 0; - } - } - - Future signTransaction({ - required EthPrivateKey privateKey, - required String toAddress, - required String amount, - required int gas, - required EthereumTransactionPriority priority, - required CryptoCurrency currency, - required int exponent, - String? contractAddress, - }) async { - assert(currency == CryptoCurrency.eth || - currency == CryptoCurrency.maticpoly || - contractAddress != null); - - bool _isEVMCompatibleChain = - currency == CryptoCurrency.eth || currency == CryptoCurrency.maticpoly; - - final price = _client!.getGasPrice(); - - final Transaction transaction = createTransaction( - from: privateKey.address, - to: EthereumAddress.fromHex(toAddress), - maxPriorityFeePerGas: EtherAmount.fromInt(EtherUnit.gwei, priority.tip), - amount: _isEVMCompatibleChain ? EtherAmount.inWei(BigInt.parse(amount)) : EtherAmount.zero(), - ); - - final signedTransaction = - await _client!.signTransaction(privateKey, transaction, chainId: chainId); - - final Function _sendTransaction; - - if (_isEVMCompatibleChain) { - _sendTransaction = () async => await sendTransaction(signedTransaction); - } else { - final erc20 = ERC20( - client: _client!, - address: EthereumAddress.fromHex(contractAddress!), - chainId: chainId, - ); - - _sendTransaction = () async { - await erc20.transfer( - EthereumAddress.fromHex(toAddress), - BigInt.parse(amount), - credentials: privateKey, - transaction: transaction, - ); - }; - } - - return PendingEthereumTransaction( - signedTransaction: signedTransaction, - amount: amount, - fee: BigInt.from(gas) * (await price).getInWei, - sendTransaction: _sendTransaction, - exponent: exponent, - ); - } +class EthereumClient extends EVMChainClient { + @override int get chainId => 1; - Transaction createTransaction({ - required EthereumAddress from, - required EthereumAddress to, - required EtherAmount amount, - EtherAmount? maxPriorityFeePerGas, - }) { - return Transaction( - from: from, - to: to, - maxPriorityFeePerGas: maxPriorityFeePerGas, - value: amount, - ); - } - - Future sendTransaction(Uint8List signedTransaction) async => - await _client!.sendRawTransaction(prepareSignedTransactionForSending(signedTransaction)); - + @override Uint8List prepareSignedTransactionForSending(Uint8List signedTransaction) => prependTransactionType(0x02, signedTransaction); - Future getTransactionDetails(String transactionHash) async { - // Wait for the transaction receipt to become available - TransactionReceipt? receipt; - while (receipt == null) { - receipt = await _client!.getTransactionReceipt(transactionHash); - await Future.delayed(Duration(seconds: 1)); - } - - // Print the receipt information - print('Transaction Hash: ${receipt.transactionHash}'); - print('Block Hash: ${receipt.blockHash}'); - print('Block Number: ${receipt.blockNumber}'); - print('Gas Used: ${receipt.gasUsed}'); - - /* - Transaction Hash: [112, 244, 4, 238, 89, 199, 171, 191, 210, 236, 110, 42, 185, 202, 220, 21, 27, 132, 123, 221, 137, 90, 77, 13, 23, 43, 12, 230, 93, 63, 221, 116] -I/flutter ( 4474): Block Hash: [149, 44, 250, 119, 111, 104, 82, 98, 17, 89, 30, 190, 25, 44, 218, 118, 127, 189, 241, 35, 213, 106, 25, 95, 195, 37, 55, 131, 185, 180, 246, 200] -I/flutter ( 4474): Block Number: 17120242 -I/flutter ( 4474): Gas Used: 21000 - */ - - // Wait for the transaction receipt to become available - TransactionInformation? transactionInformation; - while (transactionInformation == null) { - print("********************************"); - transactionInformation = await _client!.getTransactionByHash(transactionHash); - await Future.delayed(Duration(seconds: 1)); - } - // Print the receipt information - print('Transaction Hash: ${transactionInformation.hash}'); - print('Block Hash: ${transactionInformation.blockHash}'); - print('Block Number: ${transactionInformation.blockNumber}'); - print('Gas Used: ${transactionInformation.gas}'); - - /* - Transaction Hash: 0x70f404ee59c7abbfd2ec6e2ab9cadc151b847bdd895a4d0d172b0ce65d3fdd74 -I/flutter ( 4474): Block Hash: 0x952cfa776f68526211591ebe192cda767fbdf123d56a195fc3253783b9b4f6c8 -I/flutter ( 4474): Block Number: 17120242 -I/flutter ( 4474): Gas Used: 53000 - */ - } - - Future fetchERC20Balances( - EthereumAddress userAddress, String contractAddress) async { - final erc20 = ERC20(address: EthereumAddress.fromHex(contractAddress), client: _client!); - try { - final balance = await erc20.balanceOf(userAddress); - - int exponent = (await erc20.decimals()).toInt(); - - return ERC20Balance(balance, exponent: exponent); - } catch (_) { - return ERC20Balance(BigInt.zero); - } - } - - Future getErc20Token(String contractAddress) async { - try { - final erc20 = ERC20(address: EthereumAddress.fromHex(contractAddress), client: _client!); - final name = await erc20.name(); - final symbol = await erc20.symbol(); - final decimal = await erc20.decimals(); - - return Erc20Token( - name: name, - symbol: symbol, - contractAddress: contractAddress, - decimal: decimal.toInt(), - ); - } catch (e) { - return null; - } - } - - void stop() { - _client?.dispose(); - } - - Future> fetchTransactions(String address, + @override + Future> fetchTransactions(String address, {String? contractAddress}) async { try { final response = await httpClient.get(Uri.https("api.etherscan.io", "/api", { @@ -234,41 +27,18 @@ I/flutter ( 4474): Gas Used: 53000 "apikey": secrets.etherScanApiKey, })); - final _jsonResponse = json.decode(response.body) as Map; + final jsonResponse = json.decode(response.body) as Map; - if (response.statusCode >= 200 && response.statusCode < 300 && _jsonResponse['status'] != 0) { - return (_jsonResponse['result'] as List) - .map((e) => EthereumTransactionModel.fromJson(e as Map)) + if (response.statusCode >= 200 && response.statusCode < 300 && jsonResponse['status'] != 0) { + return (jsonResponse['result'] as List) + .map((e) => EVMChainTransactionModel.fromJson(e as Map, 'ETH')) .toList(); } return []; } catch (e) { - print(e); + log(e.toString()); return []; } } - - Web3Client? getWeb3Client() { - return _client; - } - -// Future _getDecimalPlacesForContract(DeployedContract contract) async { -// final String abi = await rootBundle.loadString("assets/abi_json/erc20_abi.json"); -// final contractAbi = ContractAbi.fromJson(abi, "ERC20"); -// -// final contract = DeployedContract( -// contractAbi, -// EthereumAddress.fromHex(_erc20Currencies[erc20Currency]!), -// ); -// final decimalsFunction = contract.function('decimals'); -// final decimals = await _client!.call( -// contract: contract, -// function: decimalsFunction, -// params: [], -// ); -// -// int exponent = int.parse(decimals.first.toString()); -// return exponent; -// } } diff --git a/cw_ethereum/lib/ethereum_exceptions.dart b/cw_ethereum/lib/ethereum_exceptions.dart deleted file mode 100644 index 518f46275..000000000 --- a/cw_ethereum/lib/ethereum_exceptions.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:cw_core/crypto_currency.dart'; - -class EthereumTransactionCreationException implements Exception { - final String exceptionMessage; - - EthereumTransactionCreationException(CryptoCurrency currency) : - this.exceptionMessage = 'Wrong balance. Not enough ${currency.title} on your balance.'; - - @override - String toString() => exceptionMessage; -} diff --git a/cw_ethereum/lib/ethereum_formatter.dart b/cw_ethereum/lib/ethereum_formatter.dart deleted file mode 100644 index 468c536f8..000000000 --- a/cw_ethereum/lib/ethereum_formatter.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:intl/intl.dart'; - -const ethereumAmountLength = 12; -const ethereumAmountDivider = 1000000000000; -final ethereumAmountFormat = NumberFormat() - ..maximumFractionDigits = ethereumAmountLength - ..minimumFractionDigits = 1; - -class EthereumFormatter { - static int parseEthereumAmount(String amount) { - try { - return (double.parse(amount) * ethereumAmountDivider).round(); - } catch (_) { - return 0; - } - } - - static double parseEthereumAmountToDouble(int amount) { - try { - return amount / ethereumAmountDivider; - } catch (_) { - return 0; - } - } -} diff --git a/cw_ethereum/lib/ethereum_mnemonics_exception.dart b/cw_ethereum/lib/ethereum_mnemonics_exception.dart new file mode 100644 index 000000000..b91a15c94 --- /dev/null +++ b/cw_ethereum/lib/ethereum_mnemonics_exception.dart @@ -0,0 +1,5 @@ +class EthereumMnemonicIsIncorrectException implements Exception { + @override + String toString() => + 'Ethereum mnemonic has incorrect format. Mnemonic should contain 12 or 24 words separated by space.'; +} diff --git a/cw_ethereum/lib/ethereum_transaction_history.dart b/cw_ethereum/lib/ethereum_transaction_history.dart index 4511f4436..f774ae905 100644 --- a/cw_ethereum/lib/ethereum_transaction_history.dart +++ b/cw_ethereum/lib/ethereum_transaction_history.dart @@ -1,77 +1,18 @@ -import 'dart:convert'; import 'dart:core'; -import 'package:cw_core/pathForWallet.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cw_ethereum/file.dart'; -import 'package:mobx/mobx.dart'; -import 'package:cw_core/transaction_history.dart'; import 'package:cw_ethereum/ethereum_transaction_info.dart'; +import 'package:cw_evm/evm_chain_transaction_history.dart'; +import 'package:cw_evm/evm_chain_transaction_info.dart'; -part 'ethereum_transaction_history.g.dart'; - -const transactionsHistoryFileName = 'transactions.json'; - -class EthereumTransactionHistory = EthereumTransactionHistoryBase with _$EthereumTransactionHistory; - -abstract class EthereumTransactionHistoryBase - extends TransactionHistoryBase with Store { - EthereumTransactionHistoryBase({required this.walletInfo, required String password}) - : _password = password { - transactions = ObservableMap(); - } - - final WalletInfo walletInfo; - String _password; - - Future init() async => await _load(); +class EthereumTransactionHistory extends EVMChainTransactionHistory { + EthereumTransactionHistory({ + required super.walletInfo, + required super.password, + }); @override - Future save() async { - try { - final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type); - final path = '$dirPath/$transactionsHistoryFileName'; - final data = json.encode({'transactions': transactions}); - await writeData(path: path, password: _password, data: data); - } catch (e, s) { - print('Error while save ethereum transaction history: ${e.toString()}'); - print(s); - } - } + String getTransactionHistoryFileName() => 'transactions.json'; @override - void addOne(EthereumTransactionInfo transaction) => transactions[transaction.id] = transaction; - - @override - void addMany(Map transactions) => - this.transactions.addAll(transactions); - - Future> _read() async { - final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type); - final path = '$dirPath/$transactionsHistoryFileName'; - final content = await read(path: path, password: _password); - if (content.isEmpty) { - return {}; - } - return json.decode(content) as Map; - } - - Future _load() async { - try { - final content = await _read(); - final txs = content['transactions'] as Map? ?? {}; - - txs.entries.forEach((entry) { - final val = entry.value; - - if (val is Map) { - final tx = EthereumTransactionInfo.fromJson(val); - _update(tx); - } - }); - } catch (e) { - print(e); - } - } - - void _update(EthereumTransactionInfo transaction) => transactions[transaction.id] = transaction; + EVMChainTransactionInfo getTransactionInfo(Map val) => + EthereumTransactionInfo.fromJson(val); } diff --git a/cw_ethereum/lib/ethereum_transaction_info.dart b/cw_ethereum/lib/ethereum_transaction_info.dart index f0deae931..d5d3fea8d 100644 --- a/cw_ethereum/lib/ethereum_transaction_info.dart +++ b/cw_ethereum/lib/ethereum_transaction_info.dart @@ -1,57 +1,21 @@ -import 'dart:math'; - -import 'package:cw_core/format_amount.dart'; import 'package:cw_core/transaction_direction.dart'; -import 'package:cw_core/transaction_info.dart'; +import 'package:cw_evm/evm_chain_transaction_info.dart'; -class EthereumTransactionInfo extends TransactionInfo { +class EthereumTransactionInfo extends EVMChainTransactionInfo { EthereumTransactionInfo({ - required this.id, - required this.height, - required this.ethAmount, - required this.ethFee, - this.tokenSymbol = "ETH", - this.exponent = 18, - required this.direction, - required this.isPending, - required this.date, - required this.confirmations, - required this.to, - }) : this.amount = ethAmount.toInt(), - this.fee = ethFee.toInt(); - - final String id; - final int height; - final int amount; - final BigInt ethAmount; - final int exponent; - final TransactionDirection direction; - final DateTime date; - final bool isPending; - final int fee; - final BigInt ethFee; - final int confirmations; - final String tokenSymbol; - String? _fiatAmount; - final String? to; - - @override - String amountFormatted() { - final amount = formatAmount((ethAmount / BigInt.from(10).pow(exponent)).toString()); - return '${amount.substring(0, min(10, amount.length))} $tokenSymbol'; - } - - @override - String fiatAmount() => _fiatAmount ?? ''; - - @override - void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount); - - @override - String feeFormatted() { - final amount = (ethFee / BigInt.from(10).pow(18)).toString(); - return '${amount.substring(0, min(10, amount.length))} ETH'; - } + required super.id, + required super.height, + required super.ethAmount, + required super.ethFee, + required super.tokenSymbol, + required super.direction, + required super.isPending, + required super.date, + required super.confirmations, + required super.to, + required super.from, + super.exponent, + }); factory EthereumTransactionInfo.fromJson(Map data) { return EthereumTransactionInfo( @@ -66,20 +30,10 @@ class EthereumTransactionInfo extends TransactionInfo { confirmations: data['confirmations'] as int, tokenSymbol: data['tokenSymbol'] as String, to: data['to'], + from: data['from'], ); } - Map toJson() => { - 'id': id, - 'height': height, - 'amount': ethAmount.toString(), - 'exponent': exponent, - 'fee': ethFee.toString(), - 'direction': direction.index, - 'date': date.millisecondsSinceEpoch, - 'isPending': isPending, - 'confirmations': confirmations, - 'tokenSymbol': tokenSymbol, - 'to': to, - }; + @override + String get feeCurrency => 'ETH'; } diff --git a/cw_ethereum/lib/ethereum_transaction_priority.dart b/cw_ethereum/lib/ethereum_transaction_priority.dart deleted file mode 100644 index ff5668397..000000000 --- a/cw_ethereum/lib/ethereum_transaction_priority.dart +++ /dev/null @@ -1,52 +0,0 @@ -import 'package:cw_core/transaction_priority.dart'; - -class EthereumTransactionPriority extends TransactionPriority { - final int tip; - - const EthereumTransactionPriority({required String title, required int raw, required this.tip}) - : super(title: title, raw: raw); - - static const List all = [fast, medium, slow]; - static const EthereumTransactionPriority slow = - EthereumTransactionPriority(title: 'slow', raw: 0, tip: 1); - static const EthereumTransactionPriority medium = - EthereumTransactionPriority(title: 'Medium', raw: 1, tip: 2); - static const EthereumTransactionPriority fast = - EthereumTransactionPriority(title: 'Fast', raw: 2, tip: 4); - - static EthereumTransactionPriority deserialize({required int raw}) { - switch (raw) { - case 0: - return slow; - case 1: - return medium; - case 2: - return fast; - default: - throw Exception('Unexpected token: $raw for EthereumTransactionPriority deserialize'); - } - } - - String get units => 'gas'; - - @override - String toString() { - var label = ''; - - switch (this) { - case EthereumTransactionPriority.slow: - label = 'Slow'; - break; - case EthereumTransactionPriority.medium: - label = 'Medium'; - break; - case EthereumTransactionPriority.fast: - label = 'Fast'; - break; - default: - break; - } - - return label; - } -} diff --git a/cw_ethereum/lib/ethereum_wallet.dart b/cw_ethereum/lib/ethereum_wallet.dart index cd4bd84cc..4604db662 100644 --- a/cw_ethereum/lib/ethereum_wallet.dart +++ b/cw_ethereum/lib/ethereum_wallet.dart @@ -1,126 +1,58 @@ -import 'dart:async'; import 'dart:convert'; -import 'dart:io'; -import 'dart:math'; -import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/cake_hive.dart'; -import 'package:cw_core/node.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/erc20_token.dart'; import 'package:cw_core/pathForWallet.dart'; -import 'package:cw_core/pending_transaction.dart'; -import 'package:cw_core/sync_status.dart'; import 'package:cw_core/transaction_direction.dart'; -import 'package:cw_core/transaction_priority.dart'; -import 'package:cw_core/wallet_addresses.dart'; -import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_ethereum/default_ethereum_erc20_tokens.dart'; -import 'package:cw_ethereum/erc20_balance.dart'; import 'package:cw_ethereum/ethereum_client.dart'; -import 'package:cw_ethereum/ethereum_exceptions.dart'; -import 'package:cw_ethereum/ethereum_formatter.dart'; -import 'package:cw_ethereum/ethereum_transaction_credentials.dart'; import 'package:cw_ethereum/ethereum_transaction_history.dart'; import 'package:cw_ethereum/ethereum_transaction_info.dart'; -import 'package:cw_ethereum/ethereum_transaction_model.dart'; -import 'package:cw_ethereum/ethereum_transaction_priority.dart'; -import 'package:cw_ethereum/ethereum_wallet_addresses.dart'; -import 'package:cw_ethereum/file.dart'; -import 'package:cw_core/erc20_token.dart'; -import 'package:hive/hive.dart'; -import 'package:hex/hex.dart'; -import 'package:mobx/mobx.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:web3dart/crypto.dart'; -import 'package:web3dart/web3dart.dart'; -import 'package:bip39/bip39.dart' as bip39; -import 'package:bip32/bip32.dart' as bip32; +import 'package:cw_evm/evm_chain_transaction_history.dart'; +import 'package:cw_evm/evm_chain_transaction_info.dart'; +import 'package:cw_evm/evm_chain_transaction_model.dart'; +import 'package:cw_evm/evm_chain_wallet.dart'; +import 'package:cw_evm/evm_erc20_balance.dart'; +import 'package:cw_evm/file.dart'; -part 'ethereum_wallet.g.dart'; +class EthereumWallet extends EVMChainWallet { + EthereumWallet({ + required super.client, + required super.password, + required super.walletInfo, + super.mnemonic, + super.initialBalance, + super.privateKey, + }) : super(nativeCurrency: CryptoCurrency.eth); -class EthereumWallet = EthereumWalletBase with _$EthereumWallet; + @override + void addInitialTokens() { + final initialErc20Tokens = DefaultEthereumErc20Tokens().initialErc20Tokens; -abstract class EthereumWalletBase - extends WalletBase - with Store { - EthereumWalletBase({ - required WalletInfo walletInfo, - String? mnemonic, - String? privateKey, - required String password, - ERC20Balance? initialBalance, - }) : syncStatus = NotConnectedSyncStatus(), - _password = password, - _mnemonic = mnemonic, - _hexPrivateKey = privateKey, - _isTransactionUpdating = false, - _client = EthereumClient(), - walletAddresses = EthereumWalletAddresses(walletInfo), - balance = ObservableMap.of( - {CryptoCurrency.eth: initialBalance ?? ERC20Balance(BigInt.zero)}), - super(walletInfo) { - this.walletInfo = walletInfo; - transactionHistory = EthereumTransactionHistory(walletInfo: walletInfo, password: password); - - if (!CakeHive.isAdapterRegistered(Erc20Token.typeId)) { - CakeHive.registerAdapter(Erc20TokenAdapter()); + for (var token in initialErc20Tokens) { + evmChainErc20TokensBox.put(token.contractAddress, token); } - - _sharedPrefs.complete(SharedPreferences.getInstance()); } - final String? _mnemonic; - final String? _hexPrivateKey; - final String _password; - - late final Box erc20TokensBox; - - late final Box ethereumErc20TokensBox; - - late final EthPrivateKey _ethPrivateKey; - - EthPrivateKey get ethPrivateKey => _ethPrivateKey; - - late EthereumClient _client; - - int? _gasPrice; - int? _estimatedGas; - bool _isTransactionUpdating; - - // TODO: remove after integrating our own node and having eth_newPendingTransactionFilter - Timer? _transactionsUpdateTimer; + @override + Future checkIfScanProviderIsEnabled() async { + bool isEtherscanEnabled = (await sharedPrefs.future).getBool("use_etherscan") ?? true; + return isEtherscanEnabled; + } @override - WalletAddresses walletAddresses; - - @override - @observable - SyncStatus syncStatus; - - @override - @observable - late ObservableMap balance; - - Completer _sharedPrefs = Completer(); - - Future init() async { + Future initErc20TokensBox() async { + // This is for ethereum wallets, + // Other wallets would override and initialize their respective boxes with their boxNames. await movePreviousErc20BoxConfigsToNewBox(); - - await walletAddresses.init(); - await transactionHistory.init(); - _ethPrivateKey = await getPrivateKey( - mnemonic: _mnemonic, - privateKey: _hexPrivateKey, - password: _password, - ); - walletAddresses.address = _ethPrivateKey.address.toString(); - await save(); } /// Majorly for backward compatibility for previous configs that have been set. Future movePreviousErc20BoxConfigsToNewBox() async { // Opens a box specific to this wallet - ethereumErc20TokensBox = await CakeHive.openBox( + evmChainErc20TokensBox = await CakeHive.openBox( "${walletInfo.name.replaceAll(" ", "_")}_${Erc20Token.ethereumBoxName}"); //Open the previous token configs box @@ -130,7 +62,7 @@ abstract class EthereumWalletBase if (erc20TokensBox.isEmpty) { // If it's empty, but the new wallet specific box is also empty, // we load the initial tokens to the new box. - if (ethereumErc20TokensBox.isEmpty) addInitialTokens(); + if (evmChainErc20TokensBox.isEmpty) addInitialTokens(); return; } @@ -141,319 +73,37 @@ abstract class EthereumWalletBase await erc20TokensBox.deleteFromDisk(); // Add all the previous tokens with configs to the new box - ethereumErc20TokensBox.addAll(allValues); + evmChainErc20TokensBox.addAll(allValues); } @override - int calculateEstimatedFee(TransactionPriority priority, int? amount) { - try { - if (priority is EthereumTransactionPriority) { - final priorityFee = EtherAmount.fromInt(EtherUnit.gwei, priority.tip).getInWei.toInt(); - return (_gasPrice! + priorityFee) * (_estimatedGas ?? 0); - } - - return 0; - } catch (e) { - return 0; - } - } - - @override - Future changePassword(String password) { - throw UnimplementedError("changePassword"); - } - - @override - void close() { - _client.stop(); - _transactionsUpdateTimer?.cancel(); - } - - @action - @override - Future connectToNode({required Node node}) async { - try { - syncStatus = ConnectingSyncStatus(); - - final isConnected = _client.connect(node); - - if (!isConnected) { - throw Exception("Ethereum Node connection failed"); - } - - _client.setListeners(_ethPrivateKey.address, _onNewTransaction); - - _setTransactionUpdateTimer(); - - syncStatus = ConnectedSyncStatus(); - } catch (e) { - syncStatus = FailedSyncStatus(); - } - } - - @override - Future createTransaction(Object credentials) async { - final _credentials = credentials as EthereumTransactionCredentials; - final outputs = _credentials.outputs; - final hasMultiDestination = outputs.length > 1; - - final CryptoCurrency transactionCurrency = - balance.keys.firstWhere((element) => element.title == _credentials.currency.title); - - final _erc20Balance = balance[transactionCurrency]!; - BigInt totalAmount = BigInt.zero; - int exponent = transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18; - num amountToEthereumMultiplier = pow(10, exponent); - - // so far this can not be made with Ethereum as Ethereum does not support multiple recipients - if (hasMultiDestination) { - if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) { - throw EthereumTransactionCreationException(transactionCurrency); - } - - final totalOriginalAmount = EthereumFormatter.parseEthereumAmountToDouble( - outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0))); - totalAmount = BigInt.from(totalOriginalAmount * amountToEthereumMultiplier); - - if (_erc20Balance.balance < totalAmount) { - throw EthereumTransactionCreationException(transactionCurrency); - } - } else { - final output = outputs.first; - // since the fees are taken from Ethereum - // then no need to subtract the fees from the amount if send all - final BigInt allAmount; - if (transactionCurrency is Erc20Token) { - allAmount = _erc20Balance.balance; - } else { - allAmount = _erc20Balance.balance - - BigInt.from(calculateEstimatedFee(_credentials.priority!, null)); - } - final totalOriginalAmount = - EthereumFormatter.parseEthereumAmountToDouble(output.formattedCryptoAmount ?? 0); - totalAmount = output.sendAll - ? allAmount - : BigInt.from(totalOriginalAmount * amountToEthereumMultiplier); - - if (_erc20Balance.balance < totalAmount) { - throw EthereumTransactionCreationException(transactionCurrency); - } - } - - final pendingEthereumTransaction = await _client.signTransaction( - privateKey: _ethPrivateKey, - toAddress: _credentials.outputs.first.isParsedAddress - ? _credentials.outputs.first.extractedAddress! - : _credentials.outputs.first.address, - amount: totalAmount.toString(), - gas: _estimatedGas!, - priority: _credentials.priority!, - currency: transactionCurrency, - exponent: exponent, - contractAddress: - transactionCurrency is Erc20Token ? transactionCurrency.contractAddress : null, + EVMChainTransactionInfo getTransactionInfo( + EVMChainTransactionModel transactionModel, String address) { + final model = EthereumTransactionInfo( + id: transactionModel.hash, + height: transactionModel.blockNumber, + ethAmount: transactionModel.amount, + direction: transactionModel.from == address + ? TransactionDirection.outgoing + : TransactionDirection.incoming, + isPending: false, + date: transactionModel.date, + confirmations: transactionModel.confirmations, + ethFee: BigInt.from(transactionModel.gasUsed) * transactionModel.gasPrice, + exponent: transactionModel.tokenDecimal ?? 18, + tokenSymbol: transactionModel.tokenSymbol ?? "ETH", + to: transactionModel.to, + from: transactionModel.from, ); - - return pendingEthereumTransaction; - } - - Future _updateTransactions() async { - try { - if (_isTransactionUpdating) { - return; - } - bool isEtherscanEnabled = (await _sharedPrefs.future).getBool("use_etherscan") ?? true; - if (!isEtherscanEnabled) { - return; - } - - _isTransactionUpdating = true; - final transactions = await fetchTransactions(); - transactionHistory.addMany(transactions); - await transactionHistory.save(); - _isTransactionUpdating = false; - } catch (_) { - _isTransactionUpdating = false; - } + return model; } @override - Future> fetchTransactions() async { - final address = _ethPrivateKey.address.hex; - final transactions = await _client.fetchTransactions(address); - - final List>> erc20TokensTransactions = []; - - for (var token in balance.keys) { - if (token is Erc20Token) { - erc20TokensTransactions.add(_client.fetchTransactions( - address, - contractAddress: token.contractAddress, - )); - } - } - - final tokensTransaction = await Future.wait(erc20TokensTransactions); - transactions.addAll(tokensTransaction.expand((element) => element)); - - final Map result = {}; - - for (var transactionModel in transactions) { - if (transactionModel.isError) { - continue; - } - - result[transactionModel.hash] = EthereumTransactionInfo( - id: transactionModel.hash, - height: transactionModel.blockNumber, - ethAmount: transactionModel.amount, - direction: transactionModel.from == address - ? TransactionDirection.outgoing - : TransactionDirection.incoming, - isPending: false, - date: transactionModel.date, - confirmations: transactionModel.confirmations, - ethFee: BigInt.from(transactionModel.gasUsed) * transactionModel.gasPrice, - exponent: transactionModel.tokenDecimal ?? 18, - tokenSymbol: transactionModel.tokenSymbol ?? "ETH", - to: transactionModel.to, - ); - } - - return result; - } + String getTransactionHistoryFileName() => 'transactions.json'; @override - Object get keys => throw UnimplementedError("keys"); - - @override - Future rescan({required int height}) { - throw UnimplementedError("rescan"); - } - - @override - Future save() async { - await walletAddresses.updateAddressesInBox(); - final path = await makePath(); - await write(path: path, password: _password, data: toJSON()); - await transactionHistory.save(); - } - - @override - String? get seed => _mnemonic; - - @override - String get privateKey => HEX.encode(_ethPrivateKey.privateKey); - - @action - @override - Future startSync() async { - try { - syncStatus = AttemptingSyncStatus(); - await _updateBalance(); - await _updateTransactions(); - _gasPrice = await _client.getGasUnitPrice(); - _estimatedGas = await _client.getEstimatedGas(); - - Timer.periodic( - const Duration(minutes: 1), (timer) async => _gasPrice = await _client.getGasUnitPrice()); - Timer.periodic(const Duration(seconds: 10), - (timer) async => _estimatedGas = await _client.getEstimatedGas()); - - syncStatus = SyncedSyncStatus(); - } catch (e) { - syncStatus = FailedSyncStatus(); - } - } - - Future makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); - - String toJSON() => json.encode({ - 'mnemonic': _mnemonic, - 'private_key': privateKey, - 'balance': balance[currency]!.toJSON(), - }); - - static Future open({ - required String name, - required String password, - required WalletInfo walletInfo, - }) async { - final path = await pathForWallet(name: name, type: walletInfo.type); - final jsonSource = await read(path: path, password: password); - final data = json.decode(jsonSource) as Map; - final mnemonic = data['mnemonic'] as String?; - final privateKey = data['private_key'] as String?; - final balance = ERC20Balance.fromJSON(data['balance'] as String) ?? ERC20Balance(BigInt.zero); - - return EthereumWallet( - walletInfo: walletInfo, - password: password, - mnemonic: mnemonic, - privateKey: privateKey, - initialBalance: balance, - ); - } - - Future _updateBalance() async { - balance[currency] = await _fetchEthBalance(); - - await _fetchErc20Balances(); - await save(); - } - - Future _fetchEthBalance() async { - final balance = await _client.getBalance(_ethPrivateKey.address); - return ERC20Balance(balance.getInWei); - } - - Future _fetchErc20Balances() async { - for (var token in ethereumErc20TokensBox.values) { - try { - if (token.enabled) { - balance[token] = await _client.fetchERC20Balances( - _ethPrivateKey.address, - token.contractAddress, - ); - } else { - balance.remove(token); - } - } catch (_) {} - } - } - - Future getPrivateKey( - {String? mnemonic, String? privateKey, required String password}) async { - assert(mnemonic != null || privateKey != null); - - if (privateKey != null) { - return EthPrivateKey.fromHex(privateKey); - } - - final seed = bip39.mnemonicToSeed(mnemonic!); - - final root = bip32.BIP32.fromSeed(seed); - - const _hdPathEthereum = "m/44'/60'/0'/0"; - const index = 0; - final addressAtIndex = root.derivePath("$_hdPathEthereum/$index"); - - return EthPrivateKey.fromHex(HEX.encode(addressAtIndex.privateKey as List)); - } - - Future? updateBalance() async => await _updateBalance(); - - List get erc20Currencies => ethereumErc20TokensBox.values.toList(); - - Future addErc20Token(Erc20Token token) async { - String? iconPath; - try { - iconPath = CryptoCurrency.all - .firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase()) - .iconPath; - } catch (_) {} - - final _token = Erc20Token( + Erc20Token createNewErc20TokenObject(Erc20Token token, String? iconPath) { + return Erc20Token( name: token.name, symbol: token.symbol, contractAddress: token.contractAddress, @@ -462,85 +112,30 @@ abstract class EthereumWalletBase tag: token.tag ?? "ETH", iconPath: iconPath, ); - - await ethereumErc20TokensBox.put(_token.contractAddress, _token); - - if (_token.enabled) { - balance[_token] = await _client.fetchERC20Balances( - _ethPrivateKey.address, - _token.contractAddress, - ); - } else { - balance.remove(_token); - } - } - - Future deleteErc20Token(Erc20Token token) async { - await token.delete(); - - balance.remove(token); - _updateBalance(); - } - - Future getErc20Token(String contractAddress) async => - await _client.getErc20Token(contractAddress); - - void _onNewTransaction() { - _updateBalance(); - _updateTransactions(); - } - - void addInitialTokens() { - final initialErc20Tokens = DefaultErc20Tokens().initialErc20Tokens; - - initialErc20Tokens.forEach((token) => ethereumErc20TokensBox.put(token.contractAddress, token)); } @override - Future renameWalletFiles(String newWalletName) async { - final currentWalletPath = await pathForWallet(name: walletInfo.name, type: type); - final currentWalletFile = File(currentWalletPath); - - final currentDirPath = await pathForWalletDir(name: walletInfo.name, type: type); - final currentTransactionsFile = File('$currentDirPath/$transactionsHistoryFileName'); - - // Copies current wallet files into new wallet name's dir and files - if (currentWalletFile.existsSync()) { - final newWalletPath = await pathForWallet(name: newWalletName, type: type); - await currentWalletFile.copy(newWalletPath); - } - if (currentTransactionsFile.existsSync()) { - final newDirPath = await pathForWalletDir(name: newWalletName, type: type); - await currentTransactionsFile.copy('$newDirPath/$transactionsHistoryFileName'); - } - - // Delete old name's dir and files - await Directory(currentDirPath).delete(recursive: true); + EVMChainTransactionHistory setUpTransactionHistory(WalletInfo walletInfo, String password) { + return EthereumTransactionHistory(walletInfo: walletInfo, password: password); } - void _setTransactionUpdateTimer() { - if (_transactionsUpdateTimer?.isActive ?? false) { - _transactionsUpdateTimer!.cancel(); - } + static Future open( + {required String name, required String password, required WalletInfo walletInfo}) async { + final path = await pathForWallet(name: name, type: walletInfo.type); + final jsonSource = await read(path: path, password: password); + final data = json.decode(jsonSource) as Map; + final mnemonic = data['mnemonic'] as String?; + final privateKey = data['private_key'] as String?; + final balance = EVMChainERC20Balance.fromJSON(data['balance'] as String) ?? + EVMChainERC20Balance(BigInt.zero); - _transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 10), (_) { - _updateTransactions(); - _updateBalance(); - }); + return EthereumWallet( + walletInfo: walletInfo, + password: password, + mnemonic: mnemonic, + privateKey: privateKey, + initialBalance: balance, + client: EthereumClient(), + ); } - - void updateEtherscanUsageState(bool isEnabled) { - if (isEnabled) { - _updateTransactions(); - _setTransactionUpdateTimer(); - } else { - _transactionsUpdateTimer?.cancel(); - } - } - - @override - String signMessage(String message, {String? address}) => - bytesToHex(_ethPrivateKey.signPersonalMessageToUint8List(ascii.encode(message))); - - Web3Client? getWeb3Client() => _client.getWeb3Client(); } diff --git a/cw_ethereum/lib/ethereum_wallet_creation_credentials.dart b/cw_ethereum/lib/ethereum_wallet_creation_credentials.dart deleted file mode 100644 index 6546f2fae..000000000 --- a/cw_ethereum/lib/ethereum_wallet_creation_credentials.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:cw_core/wallet_credentials.dart'; -import 'package:cw_core/wallet_info.dart'; - -class EthereumNewWalletCredentials extends WalletCredentials { - EthereumNewWalletCredentials({required String name, WalletInfo? walletInfo}) - : super(name: name, walletInfo: walletInfo); -} - -class EthereumRestoreWalletFromSeedCredentials extends WalletCredentials { - EthereumRestoreWalletFromSeedCredentials( - {required String name, - required String password, - required this.mnemonic, - WalletInfo? walletInfo}) - : super(name: name, password: password, walletInfo: walletInfo); - - final String mnemonic; -} - -class EthereumRestoreWalletFromPrivateKey extends WalletCredentials { - EthereumRestoreWalletFromPrivateKey( - {required String name, - required String password, - required this.privateKey, - WalletInfo? walletInfo}) - : super(name: name, password: password, walletInfo: walletInfo); - - final String privateKey; -} diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index 0acc90bac..1cd776867 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -1,32 +1,31 @@ -import 'dart:io'; - -import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/wallet_base.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_ethereum/ethereum_mnemonics.dart'; +import 'package:cw_ethereum/ethereum_client.dart'; +import 'package:cw_ethereum/ethereum_mnemonics_exception.dart'; import 'package:cw_ethereum/ethereum_wallet.dart'; -import 'package:cw_ethereum/ethereum_wallet_creation_credentials.dart'; -import 'package:hive/hive.dart'; +import 'package:cw_evm/evm_chain_wallet_creation_credentials.dart'; +import 'package:cw_evm/evm_chain_wallet_service.dart'; import 'package:bip39/bip39.dart' as bip39; -import 'package:collection/collection.dart'; -class EthereumWalletService extends WalletService { - EthereumWalletService(this.walletInfoSource); +class EthereumWalletService extends EVMChainWalletService { + EthereumWalletService(super.walletInfoSource, {required this.client}); - final Box walletInfoSource; + late EthereumClient client; @override - Future create(EthereumNewWalletCredentials credentials) async { + WalletType getType() => WalletType.ethereum; + + @override + Future create(EVMChainNewWalletCredentials credentials) async { final strength = credentials.seedPhraseLength == 24 ? 256 : 128; final mnemonic = bip39.generateMnemonic(strength: strength); + final wallet = EthereumWallet( walletInfo: credentials.walletInfo!, mnemonic: mnemonic, password: credentials.password!, + client: client, ); await wallet.init(); @@ -36,18 +35,11 @@ class EthereumWalletService extends WalletService WalletType.ethereum; - - @override - Future isWalletExit(String name) async => - File(await pathForWallet(name: name, type: getType())).existsSync(); - @override Future openWallet(String name, String password) async { final walletInfo = walletInfoSource.values.firstWhere((info) => info.id == WalletBase.idFor(name, getType())); - final wallet = await EthereumWalletBase.open( + final wallet = await EthereumWallet.open( name: name, password: password, walletInfo: walletInfo, @@ -60,19 +52,28 @@ class EthereumWalletService extends WalletService remove(String wallet) async { - File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true); - final walletInfo = walletInfoSource.values - .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; - await walletInfoSource.delete(walletInfo.key); + Future rename(String currentName, String password, String newName) async { + final currentWalletInfo = walletInfoSource.values + .firstWhere((info) => info.id == WalletBase.idFor(currentName, getType())); + final currentWallet = await EthereumWallet.open( + password: password, name: currentName, walletInfo: currentWalletInfo); + + await currentWallet.renameWalletFiles(newName); + + final newWalletInfo = currentWalletInfo; + newWalletInfo.id = WalletBase.idFor(newName, getType()); + newWalletInfo.name = newName; + + await walletInfoSource.put(currentWalletInfo.key, newWalletInfo); } @override - Future restoreFromKeys(EthereumRestoreWalletFromPrivateKey credentials) async { + Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials) async { final wallet = EthereumWallet( password: credentials.password!, privateKey: credentials.privateKey, walletInfo: credentials.walletInfo!, + client: client, ); await wallet.init(); @@ -84,7 +85,7 @@ class EthereumWalletService extends WalletService restoreFromSeed( - EthereumRestoreWalletFromSeedCredentials credentials) async { + EVMChainRestoreWalletFromSeedCredentials credentials) async { if (!bip39.validateMnemonic(credentials.mnemonic)) { throw EthereumMnemonicIsIncorrectException(); } @@ -93,6 +94,7 @@ class EthereumWalletService extends WalletService rename(String currentName, String password, String newName) async { - final currentWalletInfo = walletInfoSource.values - .firstWhere((info) => info.id == WalletBase.idFor(currentName, getType())); - final currentWallet = await EthereumWalletBase.open( - password: password, name: currentName, walletInfo: currentWalletInfo); - - await currentWallet.renameWalletFiles(newName); - - final newWalletInfo = currentWalletInfo; - newWalletInfo.id = WalletBase.idFor(newName, getType()); - newWalletInfo.name = newName; - - await walletInfoSource.put(currentWalletInfo.key, newWalletInfo); - } } diff --git a/cw_ethereum/pubspec.yaml b/cw_ethereum/pubspec.yaml index 6946a43a1..649ec574b 100644 --- a/cw_ethereum/pubspec.yaml +++ b/cw_ethereum/pubspec.yaml @@ -13,56 +13,23 @@ dependencies: flutter: sdk: flutter web3dart: ^2.7.1 - erc20: ^1.0.1 - mobx: ^2.0.7+4 - bip39: ^1.0.6 - bip32: ^2.0.0 - hex: ^0.2.0 - http: ^1.1.0 - shared_preferences: ^2.0.15 cw_core: path: ../cw_core + cw_evm: + path: ../cw_evm + hive: ^2.2.3 dev_dependencies: flutter_test: sdk: flutter build_runner: ^2.1.11 - mobx_codegen: ^2.0.7 - hive_generator: ^1.1.3 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. flutter: - - # To add assets to your package, add an assets section, like this: # assets: # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg - # - # For details regarding assets in packages, see - # https://flutter.dev/assets-and-images/#from-packages - # - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware - - # To add custom fonts to your package, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: # fonts: # - family: Schyler # fonts: # - asset: fonts/Schyler-Regular.ttf # - asset: fonts/Schyler-Italic.ttf # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts in packages, see - # https://flutter.dev/custom-fonts/#from-packages diff --git a/cw_evm/.gitignore b/cw_evm/.gitignore new file mode 100644 index 000000000..96486fd93 --- /dev/null +++ b/cw_evm/.gitignore @@ -0,0 +1,30 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/cw_evm/.metadata b/cw_evm/.metadata new file mode 100644 index 000000000..fa347fc6a --- /dev/null +++ b/cw_evm/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + channel: stable + +project_type: package diff --git a/cw_evm/CHANGELOG.md b/cw_evm/CHANGELOG.md new file mode 100644 index 000000000..41cc7d819 --- /dev/null +++ b/cw_evm/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/cw_evm/LICENSE b/cw_evm/LICENSE new file mode 100644 index 000000000..ba75c69f7 --- /dev/null +++ b/cw_evm/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/cw_evm/README.md b/cw_evm/README.md new file mode 100644 index 000000000..02fe8ecab --- /dev/null +++ b/cw_evm/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/cw_evm/analysis_options.yaml b/cw_evm/analysis_options.yaml new file mode 100644 index 000000000..a5744c1cf --- /dev/null +++ b/cw_evm/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/cw_evm/lib/cw_evm.dart b/cw_evm/lib/cw_evm.dart new file mode 100644 index 000000000..40f2bcaba --- /dev/null +++ b/cw_evm/lib/cw_evm.dart @@ -0,0 +1,7 @@ +library cw_evm; + +/// A Calculator. +class Calculator { + /// Returns [value] plus 1. + int addOne(int value) => value + 1; +} diff --git a/cw_evm/lib/evm_chain_client.dart b/cw_evm/lib/evm_chain_client.dart new file mode 100644 index 000000000..de5b3874a --- /dev/null +++ b/cw_evm/lib/evm_chain_client.dart @@ -0,0 +1,251 @@ +import 'dart:async'; +import 'dart:developer'; + +import 'package:cw_core/node.dart'; +import 'package:cw_core/erc20_token.dart'; +import 'package:cw_core/crypto_currency.dart'; + +import 'package:cw_evm/evm_erc20_balance.dart'; +import 'package:cw_evm/evm_chain_transaction_model.dart'; +import 'package:cw_evm/pending_evm_chain_transaction.dart'; +import 'package:cw_evm/evm_chain_transaction_priority.dart'; +import 'package:flutter/services.dart'; + +import 'package:http/http.dart'; +import 'package:erc20/erc20.dart'; +import 'package:web3dart/web3dart.dart'; + +abstract class EVMChainClient { + final httpClient = Client(); + Web3Client? _client; + + //! To be overridden by all child classes + + int get chainId; + + Future> fetchTransactions(String address, + {String? contractAddress}); + + Uint8List prepareSignedTransactionForSending(Uint8List signedTransaction); + + //! Common methods across all child classes + + bool connect(Node node) { + try { + _client = Web3Client(node.uri.toString(), httpClient); + + return true; + } catch (e) { + return false; + } + } + + void setListeners(EthereumAddress userAddress, Function() onNewTransaction) async { + // _client?.pendingTransactions().listen((transactionHash) async { + // final transaction = await _client!.getTransactionByHash(transactionHash); + // + // if (transaction.from.hex == userAddress || transaction.to?.hex == userAddress) { + // onNewTransaction(); + // } + // }); + } + + Future getBalance(EthereumAddress address) async { + try { + return await _client!.getBalance(address); + } catch (_) { + return EtherAmount.zero(); + } + } + + Future getGasUnitPrice() async { + try { + final gasPrice = await _client!.getGasPrice(); + return gasPrice.getInWei.toInt(); + } catch (_) { + return 0; + } + } + + Future getEstimatedGas() async { + try { + final estimatedGas = await _client!.estimateGas(); + return estimatedGas.toInt(); + } catch (_) { + return 0; + } + } + + Future signTransaction({ + required EthPrivateKey privateKey, + required String toAddress, + required String amount, + required int gas, + required EVMChainTransactionPriority priority, + required CryptoCurrency currency, + required int exponent, + String? contractAddress, + }) async { + assert(currency == CryptoCurrency.eth || + currency == CryptoCurrency.maticpoly || + contractAddress != null); + + bool isEVMCompatibleChain = + currency == CryptoCurrency.eth || currency == CryptoCurrency.maticpoly; + + final price = _client!.getGasPrice(); + + final Transaction transaction = createTransaction( + from: privateKey.address, + to: EthereumAddress.fromHex(toAddress), + maxPriorityFeePerGas: EtherAmount.fromInt(EtherUnit.gwei, priority.tip), + amount: isEVMCompatibleChain ? EtherAmount.inWei(BigInt.parse(amount)) : EtherAmount.zero(), + ); + + final signedTransaction = + await _client!.signTransaction(privateKey, transaction, chainId: chainId); + + final Function _sendTransaction; + + if (isEVMCompatibleChain) { + _sendTransaction = () async => await sendTransaction(signedTransaction); + } else { + final erc20 = ERC20( + client: _client!, + address: EthereumAddress.fromHex(contractAddress!), + chainId: chainId, + ); + + _sendTransaction = () async { + await erc20.transfer( + EthereumAddress.fromHex(toAddress), + BigInt.parse(amount), + credentials: privateKey, + transaction: transaction, + ); + }; + } + + return PendingEVMChainTransaction( + signedTransaction: signedTransaction, + amount: amount, + fee: BigInt.from(gas) * (await price).getInWei, + sendTransaction: _sendTransaction, + exponent: exponent, + ); + } + + Transaction createTransaction({ + required EthereumAddress from, + required EthereumAddress to, + required EtherAmount amount, + EtherAmount? maxPriorityFeePerGas, + }) { + return Transaction( + from: from, + to: to, + maxPriorityFeePerGas: maxPriorityFeePerGas, + value: amount, + ); + } + + Future sendTransaction(Uint8List signedTransaction) async => + await _client!.sendRawTransaction(prepareSignedTransactionForSending(signedTransaction)); + + Future getTransactionDetails(String transactionHash) async { + // Wait for the transaction receipt to become available + TransactionReceipt? receipt; + while (receipt == null) { + receipt = await _client!.getTransactionReceipt(transactionHash); + await Future.delayed(const Duration(seconds: 1)); + } + + // Print the receipt information + log('Transaction Hash: ${receipt.transactionHash}'); + log('Block Hash: ${receipt.blockHash}'); + log('Block Number: ${receipt.blockNumber}'); + log('Gas Used: ${receipt.gasUsed}'); + + /* + Transaction Hash: [112, 244, 4, 238, 89, 199, 171, 191, 210, 236, 110, 42, 185, 202, 220, 21, 27, 132, 123, 221, 137, 90, 77, 13, 23, 43, 12, 230, 93, 63, 221, 116] + I/flutter ( 4474): Block Hash: [149, 44, 250, 119, 111, 104, 82, 98, 17, 89, 30, 190, 25, 44, 218, 118, 127, 189, 241, 35, 213, 106, 25, 95, 195, 37, 55, 131, 185, 180, 246, 200] + I/flutter ( 4474): Block Number: 17120242 + I/flutter ( 4474): Gas Used: 21000 + */ + + // Wait for the transaction receipt to become available + TransactionInformation? transactionInformation; + while (transactionInformation == null) { + log("********************************"); + transactionInformation = await _client!.getTransactionByHash(transactionHash); + await Future.delayed(const Duration(seconds: 1)); + } + // Print the receipt information + log('Transaction Hash: ${transactionInformation.hash}'); + log('Block Hash: ${transactionInformation.blockHash}'); + log('Block Number: ${transactionInformation.blockNumber}'); + log('Gas Used: ${transactionInformation.gas}'); + + /* + Transaction Hash: 0x70f404ee59c7abbfd2ec6e2ab9cadc151b847bdd895a4d0d172b0ce65d3fdd74 + I/flutter ( 4474): Block Hash: 0x952cfa776f68526211591ebe192cda767fbdf123d56a195fc3253783b9b4f6c8 + I/flutter ( 4474): Block Number: 17120242 + I/flutter ( 4474): Gas Used: 53000 + */ + } + + Future fetchERC20Balances( + EthereumAddress userAddress, String contractAddress) async { + final erc20 = ERC20(address: EthereumAddress.fromHex(contractAddress), client: _client!); + final balance = await erc20.balanceOf(userAddress); + + int exponent = (await erc20.decimals()).toInt(); + + return EVMChainERC20Balance(balance, exponent: exponent); + } + + Future getErc20Token(String contractAddress) async { + try { + final erc20 = ERC20(address: EthereumAddress.fromHex(contractAddress), client: _client!); + final name = await erc20.name(); + final symbol = await erc20.symbol(); + final decimal = await erc20.decimals(); + + return Erc20Token( + name: name, + symbol: symbol, + contractAddress: contractAddress, + decimal: decimal.toInt(), + ); + } catch (e) { + return null; + } + } + + void stop() { + _client?.dispose(); + } + + Web3Client? getWeb3Client() { + return _client; + } + +// Future _getDecimalPlacesForContract(DeployedContract contract) async { +// final String abi = await rootBundle.loadString("assets/abi_json/erc20_abi.json"); +// final contractAbi = ContractAbi.fromJson(abi, "ERC20"); +// +// final contract = DeployedContract( +// contractAbi, +// EthereumAddress.fromHex(_erc20Currencies[erc20Currency]!), +// ); +// final decimalsFunction = contract.function('decimals'); +// final decimals = await _client!.call( +// contract: contract, +// function: decimalsFunction, +// params: [], +// ); +// +// int exponent = int.parse(decimals.first.toString()); +// return exponent; +// } +} diff --git a/cw_evm/lib/evm_chain_exceptions.dart b/cw_evm/lib/evm_chain_exceptions.dart new file mode 100644 index 000000000..1c09ecf6d --- /dev/null +++ b/cw_evm/lib/evm_chain_exceptions.dart @@ -0,0 +1,11 @@ +import 'package:cw_core/crypto_currency.dart'; + +class EVMChainTransactionCreationException implements Exception { + final String exceptionMessage; + + EVMChainTransactionCreationException(CryptoCurrency currency) + : exceptionMessage = 'Wrong balance. Not enough ${currency.title} on your balance.'; + + @override + String toString() => exceptionMessage; +} diff --git a/cw_evm/lib/evm_chain_formatter.dart b/cw_evm/lib/evm_chain_formatter.dart new file mode 100644 index 000000000..cb9b7346c --- /dev/null +++ b/cw_evm/lib/evm_chain_formatter.dart @@ -0,0 +1,25 @@ +import 'package:intl/intl.dart'; + +const evmChainAmountLength = 12; +const evmChainAmountDivider = 1000000000000; +final evmChainAmountFormat = NumberFormat() + ..maximumFractionDigits = evmChainAmountLength + ..minimumFractionDigits = 1; + +class EVMChainFormatter { + static int parseEVMChainAmount(String amount) { + try { + return (double.parse(amount) * evmChainAmountDivider).round(); + } catch (_) { + return 0; + } + } + + static double parseEVMChainAmountToDouble(int amount) { + try { + return amount / evmChainAmountDivider; + } catch (_) { + return 0; + } + } +} diff --git a/cw_ethereum/lib/ethereum_mnemonics.dart b/cw_evm/lib/evm_chain_mnemonics.dart similarity index 99% rename from cw_ethereum/lib/ethereum_mnemonics.dart rename to cw_evm/lib/evm_chain_mnemonics.dart index 8af7b10f3..55fa4c3a8 100644 --- a/cw_ethereum/lib/ethereum_mnemonics.dart +++ b/cw_evm/lib/evm_chain_mnemonics.dart @@ -1,10 +1,4 @@ -class EthereumMnemonicIsIncorrectException implements Exception { - @override - String toString() => - 'Ethereum mnemonic has incorrect format. Mnemonic should contain 12 or 24 words separated by space.'; -} - -class EthereumMnemonics { +class EVMChainMnemonics { static const englishWordlist = [ 'abandon', 'ability', diff --git a/cw_ethereum/lib/ethereum_transaction_credentials.dart b/cw_evm/lib/evm_chain_transaction_credentials.dart similarity index 60% rename from cw_ethereum/lib/ethereum_transaction_credentials.dart rename to cw_evm/lib/evm_chain_transaction_credentials.dart index b015b7141..5b5bdf170 100644 --- a/cw_ethereum/lib/ethereum_transaction_credentials.dart +++ b/cw_evm/lib/evm_chain_transaction_credentials.dart @@ -1,9 +1,9 @@ import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/output_info.dart'; -import 'package:cw_ethereum/ethereum_transaction_priority.dart'; +import 'package:cw_evm/evm_chain_transaction_priority.dart'; -class EthereumTransactionCredentials { - EthereumTransactionCredentials( +class EVMChainTransactionCredentials { + EVMChainTransactionCredentials( this.outputs, { required this.priority, required this.currency, @@ -11,7 +11,7 @@ class EthereumTransactionCredentials { }); final List outputs; - final EthereumTransactionPriority? priority; + final EVMChainTransactionPriority? priority; final int? feeRate; final CryptoCurrency currency; } diff --git a/cw_evm/lib/evm_chain_transaction_history.dart b/cw_evm/lib/evm_chain_transaction_history.dart new file mode 100644 index 000000000..2f5c31e82 --- /dev/null +++ b/cw_evm/lib/evm_chain_transaction_history.dart @@ -0,0 +1,88 @@ +import 'dart:convert'; +import 'dart:core'; +import 'dart:developer'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_evm/evm_chain_transaction_info.dart'; +import 'package:cw_evm/file.dart'; +import 'package:mobx/mobx.dart'; +import 'package:cw_core/transaction_history.dart'; + +part 'evm_chain_transaction_history.g.dart'; + +abstract class EVMChainTransactionHistory = EVMChainTransactionHistoryBase + with _$EVMChainTransactionHistory; + +abstract class EVMChainTransactionHistoryBase + extends TransactionHistoryBase with Store { + EVMChainTransactionHistoryBase({required this.walletInfo, required String password}) + : _password = password { + transactions = ObservableMap(); + } + + String _password; + + final WalletInfo walletInfo; + + //! Method to be overridden by all child classes + + String getTransactionHistoryFileName(); + + EVMChainTransactionInfo getTransactionInfo(Map val); + + //! Common methods across all child classes + + Future init() async => await _load(); + + @override + Future save() async { + final transactionsHistoryFileNameForWallet = getTransactionHistoryFileName(); + try { + final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type); + String path = '$dirPath/$transactionsHistoryFileNameForWallet'; + final data = json.encode({'transactions': transactions}); + await writeData(path: path, password: _password, data: data); + } catch (e, s) { + log('Error while saving ${walletInfo.type.name} transaction history: ${e.toString()}'); + log(s.toString()); + } + } + + @override + void addOne(EVMChainTransactionInfo transaction) => transactions[transaction.id] = transaction; + + @override + void addMany(Map transactions) => + this.transactions.addAll(transactions); + + Future> _read() async { + final transactionsHistoryFileNameForWallet = getTransactionHistoryFileName(); + final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type); + String path = '$dirPath/$transactionsHistoryFileNameForWallet'; + final content = await read(path: path, password: _password); + if (content.isEmpty) { + return {}; + } + return json.decode(content) as Map; + } + + Future _load() async { + try { + final content = await _read(); + final txs = content['transactions'] as Map? ?? {}; + + for (var entry in txs.entries) { + final val = entry.value; + + if (val is Map) { + final tx = getTransactionInfo(val); + _update(tx); + } + } + } catch (e) { + log(e.toString()); + } + } + + void _update(EVMChainTransactionInfo transaction) => transactions[transaction.id] = transaction; +} diff --git a/cw_evm/lib/evm_chain_transaction_info.dart b/cw_evm/lib/evm_chain_transaction_info.dart new file mode 100644 index 000000000..329061db2 --- /dev/null +++ b/cw_evm/lib/evm_chain_transaction_info.dart @@ -0,0 +1,77 @@ +// ignore_for_file: overridden_fields, annotate_overrides + +import 'dart:math'; + +import 'package:cw_core/format_amount.dart'; +import 'package:cw_core/transaction_direction.dart'; +import 'package:cw_core/transaction_info.dart'; + +abstract class EVMChainTransactionInfo extends TransactionInfo { + EVMChainTransactionInfo({ + required this.id, + required this.height, + required this.ethAmount, + required this.ethFee, + required this.tokenSymbol, + this.exponent = 18, + required this.direction, + required this.isPending, + required this.date, + required this.confirmations, + required this.to, + required this.from, + }) : amount = ethAmount.toInt(), + fee = ethFee.toInt(); + + final String id; + final int height; + final int amount; + final BigInt ethAmount; + final int exponent; + final TransactionDirection direction; + final DateTime date; + final bool isPending; + final int fee; + final BigInt ethFee; + final int confirmations; + final String tokenSymbol; + String? _fiatAmount; + final String? to; + final String? from; + + //! Getter to be overridden in child classes + String get feeCurrency; + + @override + String amountFormatted() { + final amount = formatAmount((ethAmount / BigInt.from(10).pow(exponent)).toString()); + return '${amount.substring(0, min(10, amount.length))} $tokenSymbol'; + } + + @override + String fiatAmount() => _fiatAmount ?? ''; + + @override + void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount); + + @override + String feeFormatted() { + final amount = (ethFee / BigInt.from(10).pow(18)).toString(); + return '${amount.substring(0, min(10, amount.length))} $feeCurrency'; + } + + Map toJson() => { + 'id': id, + 'height': height, + 'amount': ethAmount.toString(), + 'exponent': exponent, + 'fee': ethFee.toString(), + 'direction': direction.index, + 'date': date.millisecondsSinceEpoch, + 'isPending': isPending, + 'confirmations': confirmations, + 'tokenSymbol': tokenSymbol, + 'to': to, + 'from': from, + }; +} diff --git a/cw_ethereum/lib/ethereum_transaction_model.dart b/cw_evm/lib/evm_chain_transaction_model.dart similarity index 81% rename from cw_ethereum/lib/ethereum_transaction_model.dart rename to cw_evm/lib/evm_chain_transaction_model.dart index 3b5f724fc..a328a2d6d 100644 --- a/cw_ethereum/lib/ethereum_transaction_model.dart +++ b/cw_evm/lib/evm_chain_transaction_model.dart @@ -1,5 +1,4 @@ -//! Model used for in parsing transactions fetched using etherscan -class EthereumTransactionModel { +class EVMChainTransactionModel { final DateTime date; final String hash; final String from; @@ -14,7 +13,7 @@ class EthereumTransactionModel { final int? tokenDecimal; final bool isError; - EthereumTransactionModel({ + EVMChainTransactionModel({ required this.date, required this.hash, required this.from, @@ -30,7 +29,8 @@ class EthereumTransactionModel { required this.isError, }); - factory EthereumTransactionModel.fromJson(Map json) => EthereumTransactionModel( + factory EVMChainTransactionModel.fromJson(Map json, String defaultSymbol) => + EVMChainTransactionModel( date: DateTime.fromMillisecondsSinceEpoch(int.parse(json["timeStamp"]) * 1000), hash: json["hash"], from: json["from"], @@ -41,7 +41,7 @@ class EthereumTransactionModel { contractAddress: json["contractAddress"], confirmations: int.parse(json["confirmations"]), blockNumber: int.parse(json["blockNumber"]), - tokenSymbol: json["tokenSymbol"] ?? "ETH", + tokenSymbol: json["tokenSymbol"] ?? defaultSymbol, tokenDecimal: int.tryParse(json["tokenDecimal"] ?? ""), isError: json["isError"] == "1", ); diff --git a/cw_evm/lib/evm_chain_transaction_priority.dart b/cw_evm/lib/evm_chain_transaction_priority.dart new file mode 100644 index 000000000..b4ce55490 --- /dev/null +++ b/cw_evm/lib/evm_chain_transaction_priority.dart @@ -0,0 +1,52 @@ +import 'package:cw_core/transaction_priority.dart'; + +class EVMChainTransactionPriority extends TransactionPriority { + final int tip; + + const EVMChainTransactionPriority({required String title, required int raw, required this.tip}) + : super(title: title, raw: raw); + + static const List all = [fast, medium, slow]; + static const EVMChainTransactionPriority slow = + EVMChainTransactionPriority(title: 'slow', raw: 0, tip: 1); + static const EVMChainTransactionPriority medium = + EVMChainTransactionPriority(title: 'Medium', raw: 1, tip: 2); + static const EVMChainTransactionPriority fast = + EVMChainTransactionPriority(title: 'Fast', raw: 2, tip: 4); + + static EVMChainTransactionPriority deserialize({required int raw}) { + switch (raw) { + case 0: + return slow; + case 1: + return medium; + case 2: + return fast; + default: + throw Exception('Unexpected token: $raw for EVMChainTransactionPriority deserialize'); + } + } + + String get units => 'gas'; + + @override + String toString() { + var label = ''; + + switch (this) { + case EVMChainTransactionPriority.slow: + label = 'Slow'; + break; + case EVMChainTransactionPriority.medium: + label = 'Medium'; + break; + case EVMChainTransactionPriority.fast: + label = 'Fast'; + break; + default: + break; + } + + return label; + } +} diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart new file mode 100644 index 000000000..ea19a8557 --- /dev/null +++ b/cw_evm/lib/evm_chain_wallet.dart @@ -0,0 +1,512 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:math'; + +import 'package:bip32/bip32.dart' as bip32; +import 'package:bip39/bip39.dart' as bip39; +import 'package:cw_core/cake_hive.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/erc20_token.dart'; +import 'package:cw_core/node.dart'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/pending_transaction.dart'; +import 'package:cw_core/sync_status.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/wallet_addresses.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:cw_evm/evm_chain_client.dart'; +import 'package:cw_evm/evm_chain_exceptions.dart'; +import 'package:cw_evm/evm_chain_formatter.dart'; +import 'package:cw_evm/evm_chain_transaction_credentials.dart'; +import 'package:cw_evm/evm_chain_transaction_history.dart'; +import 'package:cw_evm/evm_chain_transaction_model.dart'; +import 'package:cw_evm/evm_chain_transaction_priority.dart'; +import 'package:cw_evm/evm_chain_wallet_addresses.dart'; +import 'package:cw_evm/file.dart'; +import 'package:hex/hex.dart'; +import 'package:hive/hive.dart'; +import 'package:mobx/mobx.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:web3dart/crypto.dart'; +import 'package:web3dart/web3dart.dart'; + +import 'evm_chain_transaction_info.dart'; +import 'evm_erc20_balance.dart'; + +part 'evm_chain_wallet.g.dart'; + +abstract class EVMChainWallet = EVMChainWalletBase with _$EVMChainWallet; + +abstract class EVMChainWalletBase + extends WalletBase + with Store { + EVMChainWalletBase({ + required WalletInfo walletInfo, + required EVMChainClient client, + required CryptoCurrency nativeCurrency, + String? mnemonic, + String? privateKey, + required String password, + EVMChainERC20Balance? initialBalance, + }) : syncStatus = const NotConnectedSyncStatus(), + _password = password, + _mnemonic = mnemonic, + _hexPrivateKey = privateKey, + _isTransactionUpdating = false, + _client = client, + walletAddresses = EVMChainWalletAddresses(walletInfo), + balance = ObservableMap.of( + { + // Not sure of this yet, will it work? will it not? + nativeCurrency: initialBalance ?? EVMChainERC20Balance(BigInt.zero), + }, + ), + super(walletInfo) { + this.walletInfo = walletInfo; + transactionHistory = setUpTransactionHistory(walletInfo, password); + + if (!CakeHive.isAdapterRegistered(Erc20Token.typeId)) { + CakeHive.registerAdapter(Erc20TokenAdapter()); + } + + sharedPrefs.complete(SharedPreferences.getInstance()); + } + + final String? _mnemonic; + final String? _hexPrivateKey; + final String _password; + + late final Box erc20TokensBox; + + late final Box evmChainErc20TokensBox; + + late final EthPrivateKey _evmChainPrivateKey; + + EthPrivateKey get evmChainPrivateKey => _evmChainPrivateKey; + + late EVMChainClient _client; + + int? _gasPrice; + int? _estimatedGas; + bool _isTransactionUpdating; + + // TODO: remove after integrating our own node and having eth_newPendingTransactionFilter + Timer? _transactionsUpdateTimer; + + @override + WalletAddresses walletAddresses; + + @override + @observable + SyncStatus syncStatus; + + @override + @observable + late ObservableMap balance; + + Completer sharedPrefs = Completer(); + + //! Methods to be overridden by every child + + void addInitialTokens(); + + // Future open({ + // required String name, + // required String password, + // required WalletInfo walletInfo, + // }); + + Future initErc20TokensBox(); + + String getTransactionHistoryFileName(); + + Future checkIfScanProviderIsEnabled(); + + EVMChainTransactionInfo getTransactionInfo( + EVMChainTransactionModel transactionModel, String address); + + Erc20Token createNewErc20TokenObject(Erc20Token token, String? iconPath); + + EVMChainTransactionHistory setUpTransactionHistory(WalletInfo walletInfo, String password); + + //! Common Methods across child classes + + String idFor(String name, WalletType type) => '${walletTypeToString(type).toLowerCase()}_$name'; + + Future init() async { + await initErc20TokensBox(); + + await walletAddresses.init(); + await transactionHistory.init(); + _evmChainPrivateKey = await getPrivateKey( + mnemonic: _mnemonic, + privateKey: _hexPrivateKey, + password: _password, + ); + walletAddresses.address = _evmChainPrivateKey.address.toString(); + await save(); + } + + @override + int calculateEstimatedFee(TransactionPriority priority, int? amount) { + try { + if (priority is EVMChainTransactionPriority) { + final priorityFee = EtherAmount.fromInt(EtherUnit.gwei, priority.tip).getInWei.toInt(); + return (_gasPrice! + priorityFee) * (_estimatedGas ?? 0); + } + + return 0; + } catch (e) { + return 0; + } + } + + @override + Future changePassword(String password) { + throw UnimplementedError("changePassword"); + } + + @override + void close() { + _client.stop(); + _transactionsUpdateTimer?.cancel(); + } + + @action + @override + Future connectToNode({required Node node}) async { + try { + syncStatus = ConnectingSyncStatus(); + + final isConnected = _client.connect(node); + + if (!isConnected) { + throw Exception("${walletInfo.type.name.toUpperCase()} Node connection failed"); + } + + _client.setListeners(_evmChainPrivateKey.address, _onNewTransaction); + + _setTransactionUpdateTimer(); + + syncStatus = ConnectedSyncStatus(); + } catch (e) { + syncStatus = FailedSyncStatus(); + } + } + + @action + @override + Future startSync() async { + try { + syncStatus = AttemptingSyncStatus(); + await _updateBalance(); + await _updateTransactions(); + _gasPrice = await _client.getGasUnitPrice(); + _estimatedGas = await _client.getEstimatedGas(); + + Timer.periodic( + const Duration(minutes: 1), (timer) async => _gasPrice = await _client.getGasUnitPrice()); + Timer.periodic(const Duration(seconds: 10), + (timer) async => _estimatedGas = await _client.getEstimatedGas()); + + syncStatus = SyncedSyncStatus(); + } catch (e) { + syncStatus = FailedSyncStatus(); + } + } + + @override + Future createTransaction(Object credentials) async { + final _credentials = credentials as EVMChainTransactionCredentials; + final outputs = _credentials.outputs; + final hasMultiDestination = outputs.length > 1; + + final CryptoCurrency transactionCurrency = + balance.keys.firstWhere((element) => element.title == _credentials.currency.title); + + final _erc20Balance = balance[transactionCurrency]!; + BigInt totalAmount = BigInt.zero; + int exponent = transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18; + num amountToEVMChainMultiplier = pow(10, exponent); + + // so far this can not be made with Ethereum as Ethereum does not support multiple recipients + if (hasMultiDestination) { + if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) { + throw EVMChainTransactionCreationException(transactionCurrency); + } + + final totalOriginalAmount = EVMChainFormatter.parseEVMChainAmountToDouble( + outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0))); + totalAmount = BigInt.from(totalOriginalAmount * amountToEVMChainMultiplier); + + if (_erc20Balance.balance < totalAmount) { + throw EVMChainTransactionCreationException(transactionCurrency); + } + } else { + final output = outputs.first; + // since the fees are taken from Ethereum + // then no need to subtract the fees from the amount if send all + final BigInt allAmount; + if (transactionCurrency is Erc20Token) { + allAmount = _erc20Balance.balance; + } else { + allAmount = _erc20Balance.balance - + BigInt.from(calculateEstimatedFee(_credentials.priority!, null)); + } + final totalOriginalAmount = + EVMChainFormatter.parseEVMChainAmountToDouble(output.formattedCryptoAmount ?? 0); + totalAmount = output.sendAll + ? allAmount + : BigInt.from(totalOriginalAmount * amountToEVMChainMultiplier); + + if (_erc20Balance.balance < totalAmount) { + throw EVMChainTransactionCreationException(transactionCurrency); + } + } + + final pendingEVMChainTransaction = await _client.signTransaction( + privateKey: _evmChainPrivateKey, + toAddress: _credentials.outputs.first.isParsedAddress + ? _credentials.outputs.first.extractedAddress! + : _credentials.outputs.first.address, + amount: totalAmount.toString(), + gas: _estimatedGas!, + priority: _credentials.priority!, + currency: transactionCurrency, + exponent: exponent, + contractAddress: + transactionCurrency is Erc20Token ? transactionCurrency.contractAddress : null, + ); + + return pendingEVMChainTransaction; + } + + Future _updateTransactions() async { + try { + if (_isTransactionUpdating) { + return; + } + + final isProviderEnabled = await checkIfScanProviderIsEnabled(); + + if (!isProviderEnabled) { + return; + } + + _isTransactionUpdating = true; + final transactions = await fetchTransactions(); + transactionHistory.addMany(transactions); + await transactionHistory.save(); + _isTransactionUpdating = false; + } catch (_) { + _isTransactionUpdating = false; + } + } + + @override + Future> fetchTransactions() async { + final address = _evmChainPrivateKey.address.hex; + final transactions = await _client.fetchTransactions(address); + + final List>> erc20TokensTransactions = []; + + for (var token in balance.keys) { + if (token is Erc20Token) { + erc20TokensTransactions.add(_client.fetchTransactions( + address, + contractAddress: token.contractAddress, + )); + } + } + + final tokensTransaction = await Future.wait(erc20TokensTransactions); + transactions.addAll(tokensTransaction.expand((element) => element)); + + final Map result = {}; + + for (var transactionModel in transactions) { + if (transactionModel.isError) { + continue; + } + + result[transactionModel.hash] = getTransactionInfo(transactionModel, address); + } + + return result; + } + + @override + Object get keys => throw UnimplementedError("keys"); + + @override + Future rescan({required int height}) { + throw UnimplementedError("rescan"); + } + + @override + Future save() async { + await walletAddresses.updateAddressesInBox(); + final path = await makePath(); + await write(path: path, password: _password, data: toJSON()); + await transactionHistory.save(); + } + + @override + String? get seed => _mnemonic; + + @override + String get privateKey => HEX.encode(_evmChainPrivateKey.privateKey); + + Future makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); + + String toJSON() => json.encode({ + 'mnemonic': _mnemonic, + 'private_key': privateKey, + 'balance': balance[currency]!.toJSON(), + }); + + Future _updateBalance() async { + balance[currency] = await _fetchEVMChainBalance(); + + await _fetchErc20Balances(); + await save(); + } + + Future _fetchEVMChainBalance() async { + final balance = await _client.getBalance(_evmChainPrivateKey.address); + return EVMChainERC20Balance(balance.getInWei); + } + + Future _fetchErc20Balances() async { + for (var token in evmChainErc20TokensBox.values) { + try { + if (token.enabled) { + balance[token] = await _client.fetchERC20Balances( + _evmChainPrivateKey.address, + token.contractAddress, + ); + } else { + balance.remove(token); + } + } catch (_) {} + } + } + + Future getPrivateKey( + {String? mnemonic, String? privateKey, required String password}) async { + assert(mnemonic != null || privateKey != null); + + if (privateKey != null) { + return EthPrivateKey.fromHex(privateKey); + } + + final seed = bip39.mnemonicToSeed(mnemonic!); + + final root = bip32.BIP32.fromSeed(seed); + + const hdPathEVMChain = "m/44'/60'/0'/0"; + const index = 0; + final addressAtIndex = root.derivePath("$hdPathEVMChain/$index"); + + return EthPrivateKey.fromHex(HEX.encode(addressAtIndex.privateKey as List)); + } + + Future? updateBalance() async => await _updateBalance(); + + List get erc20Currencies => evmChainErc20TokensBox.values.toList(); + + Future addErc20Token(Erc20Token token) async { + String? iconPath; + try { + iconPath = CryptoCurrency.all + .firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase()) + .iconPath; + } catch (_) {} + + final newToken = createNewErc20TokenObject(token, iconPath); + + await evmChainErc20TokensBox.put(newToken.contractAddress, newToken); + + if (newToken.enabled) { + balance[newToken] = await _client.fetchERC20Balances( + _evmChainPrivateKey.address, + newToken.contractAddress, + ); + } else { + balance.remove(newToken); + } + } + + Future deleteErc20Token(Erc20Token token) async { + await token.delete(); + + balance.remove(token); + _updateBalance(); + } + + Future getErc20Token(String contractAddress) async => + await _client.getErc20Token(contractAddress); + + void _onNewTransaction() { + _updateBalance(); + _updateTransactions(); + } + + @override + Future renameWalletFiles(String newWalletName) async { + final transactionHistoryFileNameForWallet = getTransactionHistoryFileName(); + + final currentWalletPath = await pathForWallet(name: walletInfo.name, type: type); + final currentWalletFile = File(currentWalletPath); + + final currentDirPath = await pathForWalletDir(name: walletInfo.name, type: type); + final currentTransactionsFile = File('$currentDirPath/$transactionHistoryFileNameForWallet'); + + // Copies current wallet files into new wallet name's dir and files + if (currentWalletFile.existsSync()) { + final newWalletPath = await pathForWallet(name: newWalletName, type: type); + await currentWalletFile.copy(newWalletPath); + } + if (currentTransactionsFile.existsSync()) { + final newDirPath = await pathForWalletDir(name: newWalletName, type: type); + await currentTransactionsFile.copy('$newDirPath/$transactionHistoryFileNameForWallet'); + } + + // Delete old name's dir and files + await Directory(currentDirPath).delete(recursive: true); + } + + void _setTransactionUpdateTimer() { + if (_transactionsUpdateTimer?.isActive ?? false) { + _transactionsUpdateTimer!.cancel(); + } + + _transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 10), (_) { + _updateTransactions(); + _updateBalance(); + }); + } + + /// Scan Providers: + /// + /// EtherScan for Ethereum. + /// + /// PolygonScan for Polygon. + void updateScanProviderUsageState(bool isEnabled) { + if (isEnabled) { + _updateTransactions(); + _setTransactionUpdateTimer(); + } else { + _transactionsUpdateTimer?.cancel(); + } + } + + @override + String signMessage(String message, {String? address}) => + bytesToHex(_evmChainPrivateKey.signPersonalMessageToUint8List(ascii.encode(message))); + + Web3Client? getWeb3Client() => _client.getWeb3Client(); +} diff --git a/cw_ethereum/lib/ethereum_wallet_addresses.dart b/cw_evm/lib/evm_chain_wallet_addresses.dart similarity index 63% rename from cw_ethereum/lib/ethereum_wallet_addresses.dart rename to cw_evm/lib/evm_chain_wallet_addresses.dart index 4a3492e6f..d5d39f21d 100644 --- a/cw_ethereum/lib/ethereum_wallet_addresses.dart +++ b/cw_evm/lib/evm_chain_wallet_addresses.dart @@ -1,13 +1,15 @@ +import 'dart:developer'; + import 'package:cw_core/wallet_addresses.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:mobx/mobx.dart'; -part 'ethereum_wallet_addresses.g.dart'; +part 'evm_chain_wallet_addresses.g.dart'; -class EthereumWalletAddresses = EthereumWalletAddressesBase with _$EthereumWalletAddresses; +class EVMChainWalletAddresses = EVMChainWalletAddressesBase with _$EVMChainWalletAddresses; -abstract class EthereumWalletAddressesBase extends WalletAddresses with Store { - EthereumWalletAddressesBase(WalletInfo walletInfo) +abstract class EVMChainWalletAddressesBase extends WalletAddresses with Store { + EVMChainWalletAddressesBase(WalletInfo walletInfo) : address = '', super(walletInfo); @@ -27,7 +29,7 @@ abstract class EthereumWalletAddressesBase extends WalletAddresses with Store { addressesMap[address] = ''; await saveAddressesInBox(); } catch (e) { - print(e.toString()); + log(e.toString()); } } } diff --git a/cw_evm/lib/evm_chain_wallet_creation_credentials.dart b/cw_evm/lib/evm_chain_wallet_creation_credentials.dart new file mode 100644 index 000000000..7c3271daf --- /dev/null +++ b/cw_evm/lib/evm_chain_wallet_creation_credentials.dart @@ -0,0 +1,29 @@ +import 'package:cw_core/wallet_credentials.dart'; +import 'package:cw_core/wallet_info.dart'; + +class EVMChainNewWalletCredentials extends WalletCredentials { + EVMChainNewWalletCredentials({required String name, WalletInfo? walletInfo}) + : super(name: name, walletInfo: walletInfo); +} + +class EVMChainRestoreWalletFromSeedCredentials extends WalletCredentials { + EVMChainRestoreWalletFromSeedCredentials({ + required String name, + required String password, + required this.mnemonic, + WalletInfo? walletInfo, + }) : super(name: name, password: password, walletInfo: walletInfo); + + final String mnemonic; +} + +class EVMChainRestoreWalletFromPrivateKey extends WalletCredentials { + EVMChainRestoreWalletFromPrivateKey({ + required String name, + required String password, + required this.privateKey, + WalletInfo? walletInfo, + }) : super(name: name, password: password, walletInfo: walletInfo); + + final String privateKey; +} diff --git a/cw_evm/lib/evm_chain_wallet_service.dart b/cw_evm/lib/evm_chain_wallet_service.dart new file mode 100644 index 000000000..988a38684 --- /dev/null +++ b/cw_evm/lib/evm_chain_wallet_service.dart @@ -0,0 +1,50 @@ +import 'dart:io'; + +import 'package:collection/collection.dart'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/wallet_base.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_evm/evm_chain_wallet.dart'; +import 'package:cw_evm/evm_chain_wallet_creation_credentials.dart'; +import 'package:hive/hive.dart'; + +abstract class EVMChainWalletService extends WalletService< + EVMChainNewWalletCredentials, + EVMChainRestoreWalletFromSeedCredentials, + EVMChainRestoreWalletFromPrivateKey> { + EVMChainWalletService(this.walletInfoSource); + + final Box walletInfoSource; + + @override + WalletType getType(); + + @override + Future create(EVMChainNewWalletCredentials credentials); + + @override + Future openWallet(String name, String password); + + @override + Future rename(String currentName, String password, String newName); + + @override + Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials); + + @override + Future restoreFromSeed(EVMChainRestoreWalletFromSeedCredentials credentials); + + @override + Future isWalletExit(String name) async => + File(await pathForWallet(name: name, type: getType())).existsSync(); + + @override + Future remove(String wallet) async { + File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true); + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; + await walletInfoSource.delete(walletInfo.key); + } +} diff --git a/cw_ethereum/lib/erc20_balance.dart b/cw_evm/lib/evm_erc20_balance.dart similarity index 76% rename from cw_ethereum/lib/erc20_balance.dart rename to cw_evm/lib/evm_erc20_balance.dart index 7d11f8e45..1727d7962 100644 --- a/cw_ethereum/lib/erc20_balance.dart +++ b/cw_evm/lib/evm_erc20_balance.dart @@ -3,10 +3,9 @@ import 'dart:math'; import 'package:cw_core/balance.dart'; -class ERC20Balance extends Balance { - ERC20Balance(this.balance, {this.exponent = 18}) - : super(balance.toInt(), - balance.toInt()); +class EVMChainERC20Balance extends Balance { + EVMChainERC20Balance(this.balance, {this.exponent = 18}) + : super(balance.toInt(), balance.toInt()); final BigInt balance; final int exponent; @@ -28,7 +27,7 @@ class ERC20Balance extends Balance { 'exponent': exponent, }); - static ERC20Balance? fromJSON(String? jsonSource) { + static EVMChainERC20Balance? fromJSON(String? jsonSource) { if (jsonSource == null) { return null; } @@ -36,12 +35,12 @@ class ERC20Balance extends Balance { final decoded = json.decode(jsonSource) as Map; try { - return ERC20Balance( + return EVMChainERC20Balance( BigInt.parse(decoded['balanceInWei']), exponent: decoded['exponent'], ); } catch (e) { - return ERC20Balance(BigInt.zero); + return EVMChainERC20Balance(BigInt.zero); } } } diff --git a/cw_ethereum/lib/file.dart b/cw_evm/lib/file.dart similarity index 100% rename from cw_ethereum/lib/file.dart rename to cw_evm/lib/file.dart diff --git a/cw_ethereum/lib/pending_ethereum_transaction.dart b/cw_evm/lib/pending_evm_chain_transaction.dart similarity index 91% rename from cw_ethereum/lib/pending_ethereum_transaction.dart rename to cw_evm/lib/pending_evm_chain_transaction.dart index d47630fd6..8129de728 100644 --- a/cw_ethereum/lib/pending_ethereum_transaction.dart +++ b/cw_evm/lib/pending_evm_chain_transaction.dart @@ -4,14 +4,14 @@ import 'dart:typed_data'; import 'package:cw_core/pending_transaction.dart'; import 'package:web3dart/crypto.dart'; -class PendingEthereumTransaction with PendingTransaction { +class PendingEVMChainTransaction with PendingTransaction { final Function sendTransaction; final Uint8List signedTransaction; final BigInt fee; final String amount; final int exponent; - PendingEthereumTransaction({ + PendingEVMChainTransaction({ required this.sendTransaction, required this.signedTransaction, required this.fee, diff --git a/cw_evm/pubspec.yaml b/cw_evm/pubspec.yaml new file mode 100644 index 000000000..c202cc72a --- /dev/null +++ b/cw_evm/pubspec.yaml @@ -0,0 +1,45 @@ +name: cw_evm +description: A new Flutter package project. +version: 0.0.1 +publish_to: none +author: Cake Wallet +homepage: https://cakewallet.com + +environment: + sdk: '>=3.0.6 <4.0.0' + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + web3dart: ^2.7.1 + erc20: ^1.0.1 + bip39: ^1.0.6 + bip32: ^2.0.0 + hex: ^0.2.0 + http: ^1.1.0 + hive: ^2.2.3 + collection: ^1.17.1 + shared_preferences: ^2.0.15 + cw_core: + path: ../cw_core + +dev_dependencies: + flutter_test: + sdk: flutter + build_runner: ^2.1.11 + mobx_codegen: ^2.0.7 + hive_generator: ^1.1.3 + flutter_lints: ^2.0.0 + +flutter: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic diff --git a/cw_evm/test/cw_evm_test.dart b/cw_evm/test/cw_evm_test.dart new file mode 100644 index 000000000..6a4dea276 --- /dev/null +++ b/cw_evm/test/cw_evm_test.dart @@ -0,0 +1,12 @@ +import 'package:flutter_test/flutter_test.dart'; + +import 'package:cw_evm/cw_evm.dart'; + +void main() { + test('adds one to input values', () { + final calculator = Calculator(); + expect(calculator.addOne(2), 3); + expect(calculator.addOne(-7), -6); + expect(calculator.addOne(0), 1); + }); +} diff --git a/cw_polygon/lib/pending_polygon_transaction.dart b/cw_polygon/lib/pending_polygon_transaction.dart deleted file mode 100644 index 50f1f0638..000000000 --- a/cw_polygon/lib/pending_polygon_transaction.dart +++ /dev/null @@ -1,19 +0,0 @@ -import 'dart:typed_data'; - -import 'package:cw_ethereum/pending_ethereum_transaction.dart'; - -class PendingPolygonTransaction extends PendingEthereumTransaction { - PendingPolygonTransaction({ - required Function sendTransaction, - required Uint8List signedTransaction, - required BigInt fee, - required String amount, - required int exponent, - }) : super( - amount: amount, - sendTransaction: sendTransaction, - signedTransaction: signedTransaction, - fee: fee, - exponent: exponent, - ); -} diff --git a/cw_polygon/lib/polygon_client.dart b/cw_polygon/lib/polygon_client.dart index 876f4c60d..055b42f87 100644 --- a/cw_polygon/lib/polygon_client.dart +++ b/cw_polygon/lib/polygon_client.dart @@ -1,12 +1,12 @@ import 'dart:convert'; -import 'package:cw_ethereum/ethereum_client.dart'; -import 'package:cw_polygon/polygon_transaction_model.dart'; -import 'package:cw_ethereum/.secrets.g.dart' as secrets; +import 'package:cw_evm/evm_chain_client.dart'; +import 'package:cw_evm/.secrets.g.dart' as secrets; +import 'package:cw_evm/evm_chain_transaction_model.dart'; import 'package:flutter/foundation.dart'; import 'package:web3dart/web3dart.dart'; -class PolygonClient extends EthereumClient { +class PolygonClient extends EVMChainClient { @override Transaction createTransaction({ required EthereumAddress from, @@ -28,7 +28,7 @@ class PolygonClient extends EthereumClient { int get chainId => 137; @override - Future> fetchTransactions(String address, + Future> fetchTransactions(String address, {String? contractAddress}) async { try { final response = await httpClient.get(Uri.https("api.polygonscan.com", "/api", { @@ -43,7 +43,9 @@ class PolygonClient extends EthereumClient { if (response.statusCode >= 200 && response.statusCode < 300 && jsonResponse['status'] != 0) { return (jsonResponse['result'] as List) - .map((e) => PolygonTransactionModel.fromJson(e as Map)) + .map( + (e) => EVMChainTransactionModel.fromJson(e as Map, 'MATIC'), + ) .toList(); } diff --git a/cw_polygon/lib/polygon_exceptions.dart b/cw_polygon/lib/polygon_exceptions.dart deleted file mode 100644 index 2d08106b6..000000000 --- a/cw_polygon/lib/polygon_exceptions.dart +++ /dev/null @@ -1,6 +0,0 @@ -import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_ethereum/ethereum_exceptions.dart'; - -class PolygonTransactionCreationException extends EthereumTransactionCreationException { - PolygonTransactionCreationException(CryptoCurrency currency) : super(currency); -} diff --git a/cw_polygon/lib/polygon_formatter.dart b/cw_polygon/lib/polygon_formatter.dart deleted file mode 100644 index f016db7ab..000000000 --- a/cw_polygon/lib/polygon_formatter.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:intl/intl.dart'; - -const polygonAmountLength = 12; -const polygonAmountDivider = 1000000000000; -final polygonAmountFormat = NumberFormat() - ..maximumFractionDigits = polygonAmountLength - ..minimumFractionDigits = 1; - -class PolygonFormatter { - static int parsePolygonAmount(String amount) { - try { - return (double.parse(amount) * polygonAmountDivider).round(); - } catch (_) { - return 0; - } - } - - static double parsePolygonAmountToDouble(int amount) { - try { - return amount / polygonAmountDivider; - } catch (_) { - return 0; - } - } -} diff --git a/cw_polygon/lib/polygon_transaction_credentials.dart b/cw_polygon/lib/polygon_transaction_credentials.dart deleted file mode 100644 index 6611e15da..000000000 --- a/cw_polygon/lib/polygon_transaction_credentials.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/output_info.dart'; -import 'package:cw_ethereum/ethereum_transaction_credentials.dart'; -import 'package:cw_polygon/polygon_transaction_priority.dart'; - -class PolygonTransactionCredentials extends EthereumTransactionCredentials { - PolygonTransactionCredentials( - List outputs, { - required PolygonTransactionPriority? priority, - required CryptoCurrency currency, - final int? feeRate, - }) : super( - outputs, - currency: currency, - priority: priority, - feeRate: feeRate, - ); -} diff --git a/cw_polygon/lib/polygon_transaction_history.dart b/cw_polygon/lib/polygon_transaction_history.dart index a06b8be4a..8674882cd 100644 --- a/cw_polygon/lib/polygon_transaction_history.dart +++ b/cw_polygon/lib/polygon_transaction_history.dart @@ -1,77 +1,19 @@ -import 'dart:convert'; import 'dart:core'; -import 'package:cw_core/pathForWallet.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cw_ethereum/file.dart'; + +import 'package:cw_evm/evm_chain_transaction_history.dart'; +import 'package:cw_evm/evm_chain_transaction_info.dart'; import 'package:cw_polygon/polygon_transaction_info.dart'; -import 'package:mobx/mobx.dart'; -import 'package:cw_core/transaction_history.dart'; -part 'polygon_transaction_history.g.dart'; - -const transactionsHistoryFileName = 'polygon_transactions.json'; - -class PolygonTransactionHistory = PolygonTransactionHistoryBase with _$PolygonTransactionHistory; - -abstract class PolygonTransactionHistoryBase extends TransactionHistoryBase - with Store { - PolygonTransactionHistoryBase({required this.walletInfo, required String password}) - : _password = password { - transactions = ObservableMap(); - } - - final WalletInfo walletInfo; - String _password; - - Future init() async => await _load(); +class PolygonTransactionHistory extends EVMChainTransactionHistory { + PolygonTransactionHistory({ + required super.walletInfo, + required super.password, + }); @override - Future save() async { - try { - final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type); - final path = '$dirPath/$transactionsHistoryFileName'; - final data = json.encode({'transactions': transactions}); - await writeData(path: path, password: _password, data: data); - } catch (e, s) { - print('Error while saving polygon transaction history: ${e.toString()}'); - print(s); - } - } + String getTransactionHistoryFileName() => 'polygon_transactions.json'; @override - void addOne(PolygonTransactionInfo transaction) => transactions[transaction.id] = transaction; - - @override - void addMany(Map transactions) => - this.transactions.addAll(transactions); - - Future> _read() async { - final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type); - final path = '$dirPath/$transactionsHistoryFileName'; - final content = await read(path: path, password: _password); - if (content.isEmpty) { - return {}; - } - return json.decode(content) as Map; - } - - Future _load() async { - try { - final content = await _read(); - final txs = content['transactions'] as Map? ?? {}; - - txs.entries.forEach((entry) { - final val = entry.value; - - if (val is Map) { - final tx = PolygonTransactionInfo.fromJson(val); - _update(tx); - } - }); - } catch (e) { - print(e); - } - } - - void _update(PolygonTransactionInfo transaction) => transactions[transaction.id] = transaction; + EVMChainTransactionInfo getTransactionInfo(Map val) => + PolygonTransactionInfo.fromJson(val); } diff --git a/cw_polygon/lib/polygon_transaction_info.dart b/cw_polygon/lib/polygon_transaction_info.dart index f1976a601..1fbe1c5d4 100644 --- a/cw_polygon/lib/polygon_transaction_info.dart +++ b/cw_polygon/lib/polygon_transaction_info.dart @@ -1,32 +1,21 @@ import 'package:cw_core/transaction_direction.dart'; -import 'package:cw_ethereum/ethereum_transaction_info.dart'; +import 'package:cw_evm/evm_chain_transaction_info.dart'; -class PolygonTransactionInfo extends EthereumTransactionInfo { +class PolygonTransactionInfo extends EVMChainTransactionInfo { PolygonTransactionInfo({ - required String id, - required int height, - required BigInt ethAmount, - int exponent = 18, - required TransactionDirection direction, - required DateTime date, - required bool isPending, - required BigInt ethFee, - required int confirmations, - String tokenSymbol = "MATIC", - required String? to, - }) : super( - confirmations: confirmations, - id: id, - height: height, - ethAmount: ethAmount, - exponent: exponent, - direction: direction, - date: date, - isPending: isPending, - ethFee: ethFee, - to: to, - tokenSymbol: tokenSymbol, - ); + required super.id, + required super.height, + required super.ethAmount, + required super.ethFee, + required super.tokenSymbol, + required super.direction, + required super.isPending, + required super.date, + required super.confirmations, + required super.to, + required super.from, + super.exponent, + }); factory PolygonTransactionInfo.fromJson(Map data) { return PolygonTransactionInfo( @@ -41,9 +30,10 @@ class PolygonTransactionInfo extends EthereumTransactionInfo { confirmations: data['confirmations'] as int, tokenSymbol: data['tokenSymbol'] as String, to: data['to'], + from: data['from'], ); } @override - String feeFormatted() => '${(ethFee / BigInt.from(10).pow(18)).toString()} MATIC'; + String get feeCurrency => 'MATIC'; } diff --git a/cw_polygon/lib/polygon_transaction_model.dart b/cw_polygon/lib/polygon_transaction_model.dart deleted file mode 100644 index 704d674e5..000000000 --- a/cw_polygon/lib/polygon_transaction_model.dart +++ /dev/null @@ -1,49 +0,0 @@ -import 'package:cw_ethereum/ethereum_transaction_model.dart'; - -class PolygonTransactionModel extends EthereumTransactionModel { - PolygonTransactionModel({ - required DateTime date, - required String hash, - required String from, - required String to, - required BigInt amount, - required int gasUsed, - required BigInt gasPrice, - required String contractAddress, - required int confirmations, - required int blockNumber, - required String? tokenSymbol, - required int? tokenDecimal, - required bool isError, - }) : super( - amount: amount, - date: date, - hash: hash, - from: from, - to: to, - gasPrice: gasPrice, - gasUsed: gasUsed, - confirmations: confirmations, - contractAddress: contractAddress, - blockNumber: blockNumber, - tokenDecimal: tokenDecimal, - tokenSymbol: tokenSymbol, - isError: isError, - ); - - factory PolygonTransactionModel.fromJson(Map json) => PolygonTransactionModel( - date: DateTime.fromMillisecondsSinceEpoch(int.parse(json["timeStamp"]) * 1000), - hash: json["hash"], - from: json["from"], - to: json["to"], - amount: BigInt.parse(json["value"]), - gasUsed: int.parse(json["gasUsed"]), - gasPrice: BigInt.parse(json["gasPrice"]), - contractAddress: json["contractAddress"], - confirmations: int.parse(json["confirmations"]), - blockNumber: int.parse(json["blockNumber"]), - tokenSymbol: json["tokenSymbol"] ?? "MATIC", - tokenDecimal: int.tryParse(json["tokenDecimal"] ?? ""), - isError: json["isError"] == "1", - ); -} diff --git a/cw_polygon/lib/polygon_transaction_priority.dart b/cw_polygon/lib/polygon_transaction_priority.dart deleted file mode 100644 index dba1dab55..000000000 --- a/cw_polygon/lib/polygon_transaction_priority.dart +++ /dev/null @@ -1,51 +0,0 @@ -import 'package:cw_ethereum/ethereum_transaction_priority.dart'; - -class PolygonTransactionPriority extends EthereumTransactionPriority { - const PolygonTransactionPriority({required String title, required int raw, required int tip}) - : super(title: title, raw: raw, tip: tip); - - static const List all = [fast, medium, slow]; - static const PolygonTransactionPriority slow = - PolygonTransactionPriority(title: 'slow', raw: 0, tip: 1); - static const PolygonTransactionPriority medium = - PolygonTransactionPriority(title: 'Medium', raw: 1, tip: 2); - static const PolygonTransactionPriority fast = - PolygonTransactionPriority(title: 'Fast', raw: 2, tip: 4); - - static PolygonTransactionPriority deserialize({required int raw}) { - switch (raw) { - case 0: - return slow; - case 1: - return medium; - case 2: - return fast; - default: - throw Exception('Unexpected token: $raw for PolygonTransactionPriority deserialize'); - } - } - - @override - String get units => 'gas'; - - @override - String toString() { - var label = ''; - - switch (this) { - case PolygonTransactionPriority.slow: - label = 'Slow'; - break; - case PolygonTransactionPriority.medium: - label = 'Medium'; - break; - case PolygonTransactionPriority.fast: - label = 'Fast'; - break; - default: - break; - } - - return label; - } -} diff --git a/cw_polygon/lib/polygon_wallet.dart b/cw_polygon/lib/polygon_wallet.dart index 13ee13f01..60c7ad2ff 100644 --- a/cw_polygon/lib/polygon_wallet.dart +++ b/cw_polygon/lib/polygon_wallet.dart @@ -1,366 +1,109 @@ -import 'dart:async'; import 'dart:convert'; -import 'dart:io'; -import 'dart:math'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/cake_hive.dart'; -import 'package:cw_core/node.dart'; -import 'package:cw_core/pathForWallet.dart'; -import 'package:cw_core/pending_transaction.dart'; -import 'package:cw_core/sync_status.dart'; -import 'package:cw_core/transaction_direction.dart'; -import 'package:cw_core/transaction_priority.dart'; -import 'package:cw_core/wallet_addresses.dart'; -import 'package:cw_core/wallet_base.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cw_ethereum/erc20_balance.dart'; -import 'package:cw_ethereum/ethereum_formatter.dart'; -import 'package:cw_ethereum/file.dart'; import 'package:cw_core/erc20_token.dart'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/transaction_direction.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_evm/evm_chain_transaction_history.dart'; +import 'package:cw_evm/evm_chain_transaction_info.dart'; +import 'package:cw_evm/evm_chain_transaction_model.dart'; +import 'package:cw_evm/evm_chain_wallet.dart'; +import 'package:cw_evm/evm_erc20_balance.dart'; +import 'package:cw_evm/file.dart'; import 'package:cw_polygon/default_polygon_erc20_tokens.dart'; -import 'package:cw_polygon/polygon_client.dart'; -import 'package:cw_polygon/polygon_exceptions.dart'; -import 'package:cw_polygon/polygon_formatter.dart'; -import 'package:cw_polygon/polygon_transaction_credentials.dart'; -import 'package:cw_polygon/polygon_transaction_history.dart'; import 'package:cw_polygon/polygon_transaction_info.dart'; -import 'package:cw_polygon/polygon_transaction_model.dart'; -import 'package:cw_polygon/polygon_transaction_priority.dart'; -import 'package:cw_polygon/polygon_wallet_addresses.dart'; -import 'package:hive/hive.dart'; -import 'package:hex/hex.dart'; -import 'package:mobx/mobx.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:web3dart/crypto.dart'; -import 'package:web3dart/web3dart.dart'; -import 'package:bip39/bip39.dart' as bip39; -import 'package:bip32/bip32.dart' as bip32; +import 'package:cw_polygon/polygon_client.dart'; +import 'package:cw_polygon/polygon_transaction_history.dart'; -part 'polygon_wallet.g.dart'; - -class PolygonWallet = PolygonWalletBase with _$PolygonWallet; - -abstract class PolygonWalletBase - extends WalletBase with Store { - PolygonWalletBase({ - required WalletInfo walletInfo, - String? mnemonic, - String? privateKey, - required String password, - ERC20Balance? initialBalance, - }) : syncStatus = const NotConnectedSyncStatus(), - _password = password, - _mnemonic = mnemonic, - _hexPrivateKey = privateKey, - _isTransactionUpdating = false, - _client = PolygonClient(), - walletAddresses = PolygonWalletAddresses(walletInfo), - balance = ObservableMap.of( - {CryptoCurrency.maticpoly: initialBalance ?? ERC20Balance(BigInt.zero)}), - super(walletInfo) { - this.walletInfo = walletInfo; - transactionHistory = PolygonTransactionHistory(walletInfo: walletInfo, password: password); - - if (!CakeHive.isAdapterRegistered(Erc20Token.typeId)) { - CakeHive.registerAdapter(Erc20TokenAdapter()); - } - - _sharedPrefs.complete(SharedPreferences.getInstance()); - } - - final String? _mnemonic; - final String? _hexPrivateKey; - final String _password; - - late final Box polygonErc20TokensBox; - - late final EthPrivateKey _polygonPrivateKey; - - late final PolygonClient _client; - - EthPrivateKey get polygonPrivateKey => _polygonPrivateKey; - - int? _gasPrice; - int? _estimatedGas; - bool _isTransactionUpdating; - - // TODO: remove after integrating our own node and having eth_newPendingTransactionFilter - Timer? _transactionsUpdateTimer; +class PolygonWallet extends EVMChainWallet { + PolygonWallet({ + required super.walletInfo, + required super.password, + super.mnemonic, + super.initialBalance, + super.privateKey, + required super.client, + }) : super(nativeCurrency: CryptoCurrency.maticpoly); @override - WalletAddresses walletAddresses; - - @override - @observable - SyncStatus syncStatus; - - @override - @observable - late ObservableMap balance; - - final Completer _sharedPrefs = Completer(); - - Future init() async { + Future initErc20TokensBox() async { final boxName = "${walletInfo.name.replaceAll(" ", "_")}_ ${Erc20Token.polygonBoxName}"; if (await CakeHive.boxExists(boxName)) { - polygonErc20TokensBox = await CakeHive.openBox(boxName); + evmChainErc20TokensBox = await CakeHive.openBox(boxName); } else { - polygonErc20TokensBox = await CakeHive.openBox(boxName.replaceAll(" ", "")); + evmChainErc20TokensBox = await CakeHive.openBox(boxName.replaceAll(" ", "")); } - await walletAddresses.init(); - await transactionHistory.init(); - _polygonPrivateKey = await getPrivateKey( - mnemonic: _mnemonic, - privateKey: _hexPrivateKey, - password: _password, + } + + @override + void addInitialTokens() { + final initialErc20Tokens = DefaultPolygonErc20Tokens().initialPolygonErc20Tokens; + + for (var token in initialErc20Tokens) { + evmChainErc20TokensBox.put(token.contractAddress, token); + } + } + + @override + Future checkIfScanProviderIsEnabled() async { + bool isPolygonScanEnabled = (await sharedPrefs.future).getBool("use_polygonscan") ?? true; + return isPolygonScanEnabled; + } + + @override + String getTransactionHistoryFileName() => 'polygon_transactions.json'; + + @override + Erc20Token createNewErc20TokenObject(Erc20Token token, String? iconPath) { + return Erc20Token( + name: token.name, + symbol: token.symbol, + contractAddress: token.contractAddress, + decimal: token.decimal, + enabled: token.enabled, + tag: token.tag ?? "MATIC", + iconPath: iconPath, ); - walletAddresses.address = _polygonPrivateKey.address.toString(); - await save(); } @override - int calculateEstimatedFee(TransactionPriority priority, int? amount) { - try { - if (priority is PolygonTransactionPriority) { - final priorityFee = EtherAmount.fromInt(EtherUnit.gwei, priority.tip).getInWei.toInt(); - return (_gasPrice! + priorityFee) * (_estimatedGas ?? 0); - } - - return 0; - } catch (e) { - return 0; - } - } - - @override - Future changePassword(String password) { - throw UnimplementedError("changePassword"); - } - - @override - void close() { - _client.stop(); - _transactionsUpdateTimer?.cancel(); - } - - @action - @override - Future connectToNode({required Node node}) async { - try { - syncStatus = ConnectingSyncStatus(); - - final isConnected = _client.connect(node); - - if (!isConnected) { - throw Exception("Polygon Node connection failed"); - } - - _client.setListeners(_polygonPrivateKey.address, _onNewTransaction); - - _setTransactionUpdateTimer(); - - syncStatus = ConnectedSyncStatus(); - } catch (e) { - syncStatus = FailedSyncStatus(); - } - } - - @override - Future createTransaction(Object credentials) async { - final credentials0 = credentials as PolygonTransactionCredentials; - final outputs = credentials0.outputs; - final hasMultiDestination = outputs.length > 1; - - final CryptoCurrency transactionCurrency = - balance.keys.firstWhere((element) => element.title == credentials0.currency.title); - - final erc20Balance = balance[transactionCurrency]!; - BigInt totalAmount = BigInt.zero; - int exponent = transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18; - num amountToPolygonMultiplier = pow(10, exponent); - - // so far this can not be made with Polygon as Polygon does not support multiple recipients - if (hasMultiDestination) { - if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) { - throw PolygonTransactionCreationException(transactionCurrency); - } - - final totalOriginalAmount = PolygonFormatter.parsePolygonAmountToDouble( - outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0))); - totalAmount = BigInt.from(totalOriginalAmount * amountToPolygonMultiplier); - - if (erc20Balance.balance < totalAmount) { - throw PolygonTransactionCreationException(transactionCurrency); - } - } else { - final output = outputs.first; - // since the fees are taken from Ethereum - // then no need to subtract the fees from the amount if send all - final BigInt allAmount; - if (transactionCurrency is Erc20Token) { - allAmount = erc20Balance.balance; - } else { - allAmount = - erc20Balance.balance - BigInt.from(calculateEstimatedFee(credentials0.priority!, null)); - } - final totalOriginalAmount = - EthereumFormatter.parseEthereumAmountToDouble(output.formattedCryptoAmount ?? 0); - totalAmount = - output.sendAll ? allAmount : BigInt.from(totalOriginalAmount * amountToPolygonMultiplier); - - if (erc20Balance.balance < totalAmount) { - throw PolygonTransactionCreationException(transactionCurrency); - } - } - - final pendingPolygonTransaction = await _client.signTransaction( - privateKey: _polygonPrivateKey, - toAddress: credentials0.outputs.first.isParsedAddress - ? credentials0.outputs.first.extractedAddress! - : credentials0.outputs.first.address, - amount: totalAmount.toString(), - gas: _estimatedGas!, - priority: credentials0.priority!, - currency: transactionCurrency, - exponent: exponent, - contractAddress: - transactionCurrency is Erc20Token ? transactionCurrency.contractAddress : null, + EVMChainTransactionInfo getTransactionInfo( + EVMChainTransactionModel transactionModel, String address) { + final model = PolygonTransactionInfo( + id: transactionModel.hash, + height: transactionModel.blockNumber, + ethAmount: transactionModel.amount, + direction: transactionModel.from == address + ? TransactionDirection.outgoing + : TransactionDirection.incoming, + isPending: false, + date: transactionModel.date, + confirmations: transactionModel.confirmations, + ethFee: BigInt.from(transactionModel.gasUsed) * transactionModel.gasPrice, + exponent: transactionModel.tokenDecimal ?? 18, + tokenSymbol: transactionModel.tokenSymbol ?? "MATIC", + to: transactionModel.to, + from: transactionModel.from, ); - - return pendingPolygonTransaction; - } - - Future _updateTransactions() async { - try { - if (_isTransactionUpdating) { - return; - } - bool isPolygonScanEnabled = (await _sharedPrefs.future).getBool("use_polygonscan") ?? true; - if (!isPolygonScanEnabled) { - return; - } - - _isTransactionUpdating = true; - final transactions = await fetchTransactions(); - transactionHistory.addMany(transactions); - await transactionHistory.save(); - _isTransactionUpdating = false; - } catch (_) { - _isTransactionUpdating = false; - } + return model; } @override - Future> fetchTransactions() async { - final address = _polygonPrivateKey.address.hex; - final transactions = await _client.fetchTransactions(address); - - final List>> polygonErc20TokensTransactions = []; - - for (var token in balance.keys) { - if (token is Erc20Token) { - polygonErc20TokensTransactions.add( - _client.fetchTransactions( - address, - contractAddress: token.contractAddress, - ), - ); - } - } - - final tokensTransaction = await Future.wait(polygonErc20TokensTransactions); - transactions.addAll(tokensTransaction.expand((element) => element)); - - final Map result = {}; - - for (var transactionModel in transactions) { - if (transactionModel.isError) { - continue; - } - - result[transactionModel.hash] = PolygonTransactionInfo( - id: transactionModel.hash, - height: transactionModel.blockNumber, - ethAmount: transactionModel.amount, - direction: transactionModel.from == address - ? TransactionDirection.outgoing - : TransactionDirection.incoming, - isPending: false, - date: transactionModel.date, - confirmations: transactionModel.confirmations, - ethFee: BigInt.from(transactionModel.gasUsed) * transactionModel.gasPrice, - exponent: transactionModel.tokenDecimal ?? 18, - tokenSymbol: transactionModel.tokenSymbol ?? "MATIC", - to: transactionModel.to, - ); - } - - return result; + EVMChainTransactionHistory setUpTransactionHistory(WalletInfo walletInfo, String password) { + return PolygonTransactionHistory(walletInfo: walletInfo, password: password); } - @override - Object get keys => throw UnimplementedError("keys"); - - @override - Future rescan({required int height}) { - throw UnimplementedError("rescan"); - } - - @override - Future save() async { - await walletAddresses.updateAddressesInBox(); - final path = await makePath(); - await write(path: path, password: _password, data: toJSON()); - await transactionHistory.save(); - } - - @override - String? get seed => _mnemonic; - - @override - String get privateKey => HEX.encode(_polygonPrivateKey.privateKey); - - @action - @override - Future startSync() async { - try { - syncStatus = AttemptingSyncStatus(); - await _updateBalance(); - await _updateTransactions(); - _gasPrice = await _client.getGasUnitPrice(); - _estimatedGas = await _client.getEstimatedGas(); - - Timer.periodic( - const Duration(minutes: 1), (timer) async => _gasPrice = await _client.getGasUnitPrice()); - Timer.periodic(const Duration(seconds: 10), - (timer) async => _estimatedGas = await _client.getEstimatedGas()); - - syncStatus = SyncedSyncStatus(); - } catch (e) { - syncStatus = FailedSyncStatus(); - } - } - - Future makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); - - String toJSON() => json.encode({ - 'mnemonic': _mnemonic, - 'private_key': privateKey, - 'balance': balance[currency]!.toJSON(), - }); - - static Future open({ - required String name, - required String password, - required WalletInfo walletInfo, - }) async { + static Future open( + {required String name, required String password, required WalletInfo walletInfo}) async { final path = await pathForWallet(name: name, type: walletInfo.type); final jsonSource = await read(path: path, password: password); final data = json.decode(jsonSource) as Map; final mnemonic = data['mnemonic'] as String?; final privateKey = data['private_key'] as String?; - final balance = ERC20Balance.fromJSON(data['balance'] as String) ?? ERC20Balance(BigInt.zero); + final balance = EVMChainERC20Balance.fromJSON(data['balance'] as String) ?? + EVMChainERC20Balance(BigInt.zero); return PolygonWallet( walletInfo: walletInfo, @@ -368,158 +111,7 @@ abstract class PolygonWalletBase mnemonic: mnemonic, privateKey: privateKey, initialBalance: balance, + client: PolygonClient(), ); } - - Future _updateBalance() async { - balance[currency] = await _fetchMaticBalance(); - - await _fetchErc20Balances(); - await save(); - } - - Future _fetchMaticBalance() async { - final balance = await _client.getBalance(_polygonPrivateKey.address); - return ERC20Balance(balance.getInWei); - } - - Future _fetchErc20Balances() async { - for (var token in polygonErc20TokensBox.values) { - try { - if (token.enabled) { - balance[token] = await _client.fetchERC20Balances( - _polygonPrivateKey.address, - token.contractAddress, - ); - } else { - balance.remove(token); - } - } catch (_) {} - } - } - - Future getPrivateKey( - {String? mnemonic, String? privateKey, required String password}) async { - assert(mnemonic != null || privateKey != null); - - if (privateKey != null) { - return EthPrivateKey.fromHex(privateKey); - } - - final seed = bip39.mnemonicToSeed(mnemonic!); - - final root = bip32.BIP32.fromSeed(seed); - - const hdPathPolygon = "m/44'/60'/0'/0"; - const index = 0; - final addressAtIndex = root.derivePath("$hdPathPolygon/$index"); - - return EthPrivateKey.fromHex(HEX.encode(addressAtIndex.privateKey as List)); - } - - @override - Future? updateBalance() async => await _updateBalance(); - - List get erc20Currencies => polygonErc20TokensBox.values.toList(); - - Future addErc20Token(Erc20Token token) async { - String? iconPath; - try { - iconPath = CryptoCurrency.all - .firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase()) - .iconPath; - } catch (_) {} - - final token0 = Erc20Token( - name: token.name, - symbol: token.symbol, - contractAddress: token.contractAddress, - decimal: token.decimal, - enabled: token.enabled, - tag: token.tag ?? "POLY", - iconPath: iconPath, - ); - - await polygonErc20TokensBox.put(token0.contractAddress, token0); - - if (token0.enabled) { - balance[token0] = await _client.fetchERC20Balances( - _polygonPrivateKey.address, - token0.contractAddress, - ); - } else { - balance.remove(token0); - } - } - - Future deleteErc20Token(Erc20Token token) async { - await token.delete(); - - balance.remove(token); - _updateBalance(); - } - - Future getErc20Token(String contractAddress) async => - await _client.getErc20Token(contractAddress); - - void _onNewTransaction() { - _updateBalance(); - _updateTransactions(); - } - - void addInitialTokens() { - final initialErc20Tokens = DefaultPolygonErc20Tokens().initialPolygonErc20Tokens; - - for (var token in initialErc20Tokens) { - polygonErc20TokensBox.put(token.contractAddress, token); - } - } - - @override - Future renameWalletFiles(String newWalletName) async { - final currentWalletPath = await pathForWallet(name: walletInfo.name, type: type); - final currentWalletFile = File(currentWalletPath); - - final currentDirPath = await pathForWalletDir(name: walletInfo.name, type: type); - final currentTransactionsFile = File('$currentDirPath/$transactionsHistoryFileName'); - - // Copies current wallet files into new wallet name's dir and files - if (currentWalletFile.existsSync()) { - final newWalletPath = await pathForWallet(name: newWalletName, type: type); - await currentWalletFile.copy(newWalletPath); - } - if (currentTransactionsFile.existsSync()) { - final newDirPath = await pathForWalletDir(name: newWalletName, type: type); - await currentTransactionsFile.copy('$newDirPath/$transactionsHistoryFileName'); - } - - // Delete old name's dir and files - await Directory(currentDirPath).delete(recursive: true); - } - - void _setTransactionUpdateTimer() { - if (_transactionsUpdateTimer?.isActive ?? false) { - _transactionsUpdateTimer!.cancel(); - } - - _transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 10), (_) { - _updateTransactions(); - _updateBalance(); - }); - } - - void updatePolygonScanUsageState(bool isEnabled) { - if (isEnabled) { - _updateTransactions(); - _setTransactionUpdateTimer(); - } else { - _transactionsUpdateTimer?.cancel(); - } - } - - @override - String signMessage(String message, {String? address}) => - bytesToHex(_polygonPrivateKey.signPersonalMessageToUint8List(ascii.encode(message))); - - Web3Client? getWeb3Client() => _client.getWeb3Client(); } diff --git a/cw_polygon/lib/polygon_wallet_addresses.dart b/cw_polygon/lib/polygon_wallet_addresses.dart deleted file mode 100644 index 0a6a407c7..000000000 --- a/cw_polygon/lib/polygon_wallet_addresses.dart +++ /dev/null @@ -1,5 +0,0 @@ -import 'package:cw_ethereum/ethereum_wallet_addresses.dart'; - -class PolygonWalletAddresses extends EthereumWalletAddresses { - PolygonWalletAddresses(super.walletInfo); -} diff --git a/cw_polygon/lib/polygon_wallet_creation_credentials.dart b/cw_polygon/lib/polygon_wallet_creation_credentials.dart deleted file mode 100644 index 74c7c5ed7..000000000 --- a/cw_polygon/lib/polygon_wallet_creation_credentials.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:cw_core/wallet_credentials.dart'; -import 'package:cw_core/wallet_info.dart'; -class PolygonNewWalletCredentials extends WalletCredentials { - PolygonNewWalletCredentials({required String name, WalletInfo? walletInfo}) - : super(name: name, walletInfo: walletInfo); -} - -class PolygonRestoreWalletFromSeedCredentials extends WalletCredentials { - PolygonRestoreWalletFromSeedCredentials( - {required String name, - required String password, - required this.mnemonic, - WalletInfo? walletInfo}) - : super(name: name, password: password, walletInfo: walletInfo); - - final String mnemonic; -} - -class PolygonRestoreWalletFromPrivateKey extends WalletCredentials { - PolygonRestoreWalletFromPrivateKey( - {required String name, - required String password, - required this.privateKey, - WalletInfo? walletInfo}) - : super(name: name, password: password, walletInfo: walletInfo); - - final String privateKey; -} diff --git a/cw_polygon/lib/polygon_wallet_service.dart b/cw_polygon/lib/polygon_wallet_service.dart index 43c6269f6..451dc7288 100644 --- a/cw_polygon/lib/polygon_wallet_service.dart +++ b/cw_polygon/lib/polygon_wallet_service.dart @@ -1,32 +1,34 @@ -import 'dart:io'; - -import 'package:cw_core/pathForWallet.dart'; -import 'package:cw_core/wallet_base.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_ethereum/ethereum_mnemonics.dart'; -import 'package:cw_polygon/polygon_wallet.dart'; import 'package:bip39/bip39.dart' as bip39; -import 'package:hive/hive.dart'; -import 'polygon_wallet_creation_credentials.dart'; -import 'package:collection/collection.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:cw_evm/evm_chain_wallet_creation_credentials.dart'; +import 'package:cw_evm/evm_chain_wallet_service.dart'; +import 'package:cw_polygon/polygon_client.dart'; +import 'package:cw_polygon/polygon_mnemonics_exception.dart'; +import 'package:cw_polygon/polygon_wallet.dart'; -class PolygonWalletService extends WalletService { - PolygonWalletService(this.walletInfoSource); +class PolygonWalletService extends EVMChainWalletService { + PolygonWalletService( + super.walletInfoSource, { + required this.client, + }); - final Box walletInfoSource; + late PolygonClient client; @override - Future create(PolygonNewWalletCredentials credentials) async { + WalletType getType() => WalletType.polygon; + + @override + Future create(EVMChainNewWalletCredentials credentials) async { final strength = credentials.seedPhraseLength == 24 ? 256 : 128; final mnemonic = bip39.generateMnemonic(strength: strength); + final wallet = PolygonWallet( walletInfo: credentials.walletInfo!, mnemonic: mnemonic, password: credentials.password!, + client: client, ); await wallet.init(); @@ -36,18 +38,11 @@ class PolygonWalletService extends WalletService WalletType.polygon; - - @override - Future isWalletExit(String name) async => - File(await pathForWallet(name: name, type: getType())).existsSync(); - @override Future openWallet(String name, String password) async { final walletInfo = walletInfoSource.values.firstWhere((info) => info.id == WalletBase.idFor(name, getType())); - final wallet = await PolygonWalletBase.open( + final wallet = await PolygonWallet.open( name: name, password: password, walletInfo: walletInfo, @@ -60,19 +55,13 @@ class PolygonWalletService extends WalletService remove(String wallet) async { - File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true); - final walletInfo = walletInfoSource.values - .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; - await walletInfoSource.delete(walletInfo.key); - } + Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials) async { - @override - Future restoreFromKeys(PolygonRestoreWalletFromPrivateKey credentials) async { final wallet = PolygonWallet( password: credentials.password!, privateKey: credentials.privateKey, walletInfo: credentials.walletInfo!, + client: client, ); await wallet.init(); @@ -83,15 +72,17 @@ class PolygonWalletService extends WalletService restoreFromSeed(PolygonRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed( + EVMChainRestoreWalletFromSeedCredentials credentials) async { if (!bip39.validateMnemonic(credentials.mnemonic)) { - throw EthereumMnemonicIsIncorrectException(); + throw PolygonMnemonicIsIncorrectException(); } final wallet = PolygonWallet( password: credentials.password!, mnemonic: credentials.mnemonic, walletInfo: credentials.walletInfo!, + client: client, ); await wallet.init(); @@ -105,7 +96,7 @@ class PolygonWalletService extends WalletService rename(String currentName, String password, String newName) async { final currentWalletInfo = walletInfoSource.values .firstWhere((info) => info.id == WalletBase.idFor(currentName, getType())); - final currentWallet = await PolygonWalletBase.open( + final currentWallet = await PolygonWallet.open( password: password, name: currentName, walletInfo: currentWalletInfo); await currentWallet.renameWalletFiles(newName); diff --git a/cw_polygon/pubspec.yaml b/cw_polygon/pubspec.yaml index e99e6dbbb..505838d7c 100644 --- a/cw_polygon/pubspec.yaml +++ b/cw_polygon/pubspec.yaml @@ -16,15 +16,12 @@ dependencies: path: ../cw_core cw_ethereum: path: ../cw_ethereum - mobx: ^2.0.7+4 - intl: ^0.18.0 - bip39: ^1.0.6 - hive: ^2.2.3 - collection: ^1.17.1 + cw_evm: + path: ../cw_evm web3dart: ^2.7.1 - bip32: ^2.0.0 - hex: ^0.2.0 - shared_preferences: ^2.0.15 + hive: ^2.2.3 + bip39: ^1.0.6 + collection: ^1.17.1 dev_dependencies: @@ -32,8 +29,6 @@ dev_dependencies: sdk: flutter flutter_lints: ^2.0.0 build_runner: ^2.1.11 - mobx_codegen: ^2.0.7 - hive_generator: ^1.1.3 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/lib/ethereum/cw_ethereum.dart b/lib/ethereum/cw_ethereum.dart index abafc2f26..d7c174e1a 100644 --- a/lib/ethereum/cw_ethereum.dart +++ b/lib/ethereum/cw_ethereum.dart @@ -2,17 +2,17 @@ part of 'ethereum.dart'; class CWEthereum extends Ethereum { @override - List getEthereumWordList(String language) => EthereumMnemonics.englishWordlist; + List getEthereumWordList(String language) => EVMChainMnemonics.englishWordlist; WalletService createEthereumWalletService(Box walletInfoSource) => - EthereumWalletService(walletInfoSource); + EthereumWalletService(walletInfoSource, client: EthereumClient()); @override WalletCredentials createEthereumNewWalletCredentials({ required String name, WalletInfo? walletInfo, }) => - EthereumNewWalletCredentials(name: name, walletInfo: walletInfo); + EVMChainNewWalletCredentials(name: name, walletInfo: walletInfo); @override WalletCredentials createEthereumRestoreWalletFromSeedCredentials({ @@ -20,7 +20,7 @@ class CWEthereum extends Ethereum { required String mnemonic, required String password, }) => - EthereumRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic); + EVMChainRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic); @override WalletCredentials createEthereumRestoreWalletFromPrivateKey({ @@ -28,37 +28,37 @@ class CWEthereum extends Ethereum { required String privateKey, required String password, }) => - EthereumRestoreWalletFromPrivateKey(name: name, password: password, privateKey: privateKey); + EVMChainRestoreWalletFromPrivateKey(name: name, password: password, privateKey: privateKey); @override String getAddress(WalletBase wallet) => (wallet as EthereumWallet).walletAddresses.address; @override String getPrivateKey(WalletBase wallet) { - final privateKeyHolder = (wallet as EthereumWallet).ethPrivateKey; + final privateKeyHolder = (wallet as EthereumWallet).evmChainPrivateKey; String stringKey = bytesToHex(privateKeyHolder.privateKey); return stringKey; } @override String getPublicKey(WalletBase wallet) { - final privateKeyInUnitInt = (wallet as EthereumWallet).ethPrivateKey; + final privateKeyInUnitInt = (wallet as EthereumWallet).evmChainPrivateKey; final publicKey = privateKeyInUnitInt.address.hex; return publicKey; } @override - TransactionPriority getDefaultTransactionPriority() => EthereumTransactionPriority.medium; + TransactionPriority getDefaultTransactionPriority() => EVMChainTransactionPriority.medium; @override - TransactionPriority getEthereumTransactionPrioritySlow() => EthereumTransactionPriority.slow; + TransactionPriority getEthereumTransactionPrioritySlow() => EVMChainTransactionPriority.slow; @override - List getTransactionPriorities() => EthereumTransactionPriority.all; + List getTransactionPriorities() => EVMChainTransactionPriority.all; @override TransactionPriority deserializeEthereumTransactionPriority(int raw) => - EthereumTransactionPriority.deserialize(raw: raw); + EVMChainTransactionPriority.deserialize(raw: raw); Object createEthereumTransactionCredentials( List outputs, { @@ -66,7 +66,7 @@ class CWEthereum extends Ethereum { required CryptoCurrency currency, int? feeRate, }) => - EthereumTransactionCredentials( + EVMChainTransactionCredentials( outputs .map((out) => OutputInfo( fiatAmount: out.fiatAmount, @@ -78,7 +78,7 @@ class CWEthereum extends Ethereum { isParsedAddress: out.isParsedAddress, formattedCryptoAmount: out.formattedCryptoAmount)) .toList(), - priority: priority as EthereumTransactionPriority, + priority: priority as EVMChainTransactionPriority, currency: currency, feeRate: feeRate, ); @@ -89,15 +89,15 @@ class CWEthereum extends Ethereum { required CryptoCurrency currency, required int feeRate, }) => - EthereumTransactionCredentials( + EVMChainTransactionCredentials( outputs, - priority: priority as EthereumTransactionPriority?, + priority: priority as EVMChainTransactionPriority?, currency: currency, feeRate: feeRate, ); @override - int formatterEthereumParseAmount(String amount) => EthereumFormatter.parseEthereumAmount(amount); + int formatterEthereumParseAmount(String amount) => EVMChainFormatter.parseEVMChainAmount(amount); @override double formatterEthereumAmountToDouble( @@ -105,7 +105,7 @@ class CWEthereum extends Ethereum { assert(transaction != null || amount != null); if (transaction != null) { - transaction as EthereumTransactionInfo; + transaction as EVMChainTransactionInfo; return transaction.ethAmount / BigInt.from(10).pow(transaction.exponent); } else { return (amount!) / BigInt.from(10).pow(exponent); @@ -134,7 +134,7 @@ class CWEthereum extends Ethereum { @override CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) { - transaction as EthereumTransactionInfo; + transaction as EVMChainTransactionInfo; if (transaction.tokenSymbol == CryptoCurrency.eth.title) { return CryptoCurrency.eth; } @@ -146,7 +146,7 @@ class CWEthereum extends Ethereum { @override void updateEtherscanUsageState(WalletBase wallet, bool isEnabled) { - (wallet as EthereumWallet).updateEtherscanUsageState(isEnabled); + (wallet as EthereumWallet).updateScanProviderUsageState(isEnabled); } @override diff --git a/lib/polygon/cw_polygon.dart b/lib/polygon/cw_polygon.dart index 066b29d43..6e5fbe2c6 100644 --- a/lib/polygon/cw_polygon.dart +++ b/lib/polygon/cw_polygon.dart @@ -2,17 +2,17 @@ part of 'polygon.dart'; class CWPolygon extends Polygon { @override - List getPolygonWordList(String language) => EthereumMnemonics.englishWordlist; + List getPolygonWordList(String language) => EVMChainMnemonics.englishWordlist; WalletService createPolygonWalletService(Box walletInfoSource) => - PolygonWalletService(walletInfoSource); + PolygonWalletService(walletInfoSource, client: PolygonClient()); @override WalletCredentials createPolygonNewWalletCredentials({ required String name, WalletInfo? walletInfo, }) => - PolygonNewWalletCredentials(name: name, walletInfo: walletInfo); + EVMChainNewWalletCredentials(name: name, walletInfo: walletInfo); @override WalletCredentials createPolygonRestoreWalletFromSeedCredentials({ @@ -20,7 +20,7 @@ class CWPolygon extends Polygon { required String mnemonic, required String password, }) => - PolygonRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic); + EVMChainRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic); @override WalletCredentials createPolygonRestoreWalletFromPrivateKey({ @@ -28,37 +28,37 @@ class CWPolygon extends Polygon { required String privateKey, required String password, }) => - PolygonRestoreWalletFromPrivateKey(name: name, password: password, privateKey: privateKey); + EVMChainRestoreWalletFromPrivateKey(name: name, password: password, privateKey: privateKey); @override String getAddress(WalletBase wallet) => (wallet as PolygonWallet).walletAddresses.address; @override String getPrivateKey(WalletBase wallet) { - final privateKeyHolder = (wallet as PolygonWallet).polygonPrivateKey; + final privateKeyHolder = (wallet as PolygonWallet).evmChainPrivateKey; String stringKey = bytesToHex(privateKeyHolder.privateKey); return stringKey; } @override String getPublicKey(WalletBase wallet) { - final privateKeyInUnitInt = (wallet as PolygonWallet).polygonPrivateKey; + final privateKeyInUnitInt = (wallet as PolygonWallet).evmChainPrivateKey; final publicKey = privateKeyInUnitInt.address.hex; return publicKey; } @override - TransactionPriority getDefaultTransactionPriority() => PolygonTransactionPriority.medium; + TransactionPriority getDefaultTransactionPriority() => EVMChainTransactionPriority.medium; @override - TransactionPriority getPolygonTransactionPrioritySlow() => PolygonTransactionPriority.slow; + TransactionPriority getPolygonTransactionPrioritySlow() => EVMChainTransactionPriority.slow; @override - List getTransactionPriorities() => PolygonTransactionPriority.all; + List getTransactionPriorities() => EVMChainTransactionPriority.all; @override TransactionPriority deserializePolygonTransactionPriority(int raw) => - PolygonTransactionPriority.deserialize(raw: raw); + EVMChainTransactionPriority.deserialize(raw: raw); Object createPolygonTransactionCredentials( List outputs, { @@ -66,7 +66,7 @@ class CWPolygon extends Polygon { required CryptoCurrency currency, int? feeRate, }) => - PolygonTransactionCredentials( + EVMChainTransactionCredentials( outputs .map((out) => OutputInfo( fiatAmount: out.fiatAmount, @@ -78,7 +78,7 @@ class CWPolygon extends Polygon { isParsedAddress: out.isParsedAddress, formattedCryptoAmount: out.formattedCryptoAmount)) .toList(), - priority: priority as PolygonTransactionPriority, + priority: priority as EVMChainTransactionPriority, currency: currency, feeRate: feeRate, ); @@ -89,15 +89,15 @@ class CWPolygon extends Polygon { required CryptoCurrency currency, required int feeRate, }) => - PolygonTransactionCredentials( + EVMChainTransactionCredentials( outputs, - priority: priority as PolygonTransactionPriority?, + priority: priority as EVMChainTransactionPriority?, currency: currency, feeRate: feeRate, ); @override - int formatterPolygonParseAmount(String amount) => PolygonFormatter.parsePolygonAmount(amount); + int formatterPolygonParseAmount(String amount) => EVMChainFormatter.parseEVMChainAmount(amount); @override double formatterPolygonAmountToDouble( @@ -105,7 +105,7 @@ class CWPolygon extends Polygon { assert(transaction != null || amount != null); if (transaction != null) { - transaction as PolygonTransactionInfo; + transaction as EVMChainTransactionInfo; return transaction.ethAmount / BigInt.from(10).pow(transaction.exponent); } else { return (amount!) / BigInt.from(10).pow(exponent); @@ -134,7 +134,7 @@ class CWPolygon extends Polygon { @override CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) { - transaction as PolygonTransactionInfo; + transaction as EVMChainTransactionInfo; if (transaction.tokenSymbol == CryptoCurrency.maticpoly.title) { return CryptoCurrency.maticpoly; } @@ -146,7 +146,7 @@ class CWPolygon extends Polygon { @override void updatePolygonScanUsageState(WalletBase wallet, bool isEnabled) { - (wallet as PolygonWallet).updatePolygonScanUsageState(isEnabled); + (wallet as PolygonWallet).updateScanProviderUsageState(isEnabled); } @override diff --git a/lib/src/screens/dashboard/pages/nft_details_page.dart b/lib/src/screens/dashboard/pages/nft_details_page.dart index 4bddb550b..bb642fd4b 100644 --- a/lib/src/screens/dashboard/pages/nft_details_page.dart +++ b/lib/src/screens/dashboard/pages/nft_details_page.dart @@ -101,26 +101,26 @@ class NFTDetailsPage extends BasePage { SizedBox(height: 16), _NFTSingleInfoTile( infoType: S.current.name, - infoValue: nftAsset.normalizedMetadata?.name ?? '', + infoValue: nftAsset.normalizedMetadata?.name ?? '---', ), if (nftAsset.normalizedMetadata?.description != null) ...[ SizedBox(height: 16), _NFTSingleInfoTile( - infoType: 'Description', - infoValue: nftAsset.normalizedMetadata?.description ?? '', + infoType: S.current.description, + infoValue: nftAsset.normalizedMetadata?.description ?? '---', ), ], SizedBox(height: 16), _NFTSingleInfoTile( - infoType: 'Contract Name', - infoValue: nftAsset.name ?? '', + infoType: S.current.contractName, + infoValue: nftAsset.name ?? '---', ), SizedBox(height: 8), _NFTSingleInfoTile( - infoType: 'Contract Symbol', - infoValue: nftAsset.symbol ?? '', + infoType: S.current.contractSymbol, + infoValue: nftAsset.symbol ?? '---', ), ], ), diff --git a/lib/src/screens/dashboard/widgets/nft_tile_widget.dart b/lib/src/screens/dashboard/widgets/nft_tile_widget.dart index 0be027f44..e7391b970 100644 --- a/lib/src/screens/dashboard/widgets/nft_tile_widget.dart +++ b/lib/src/screens/dashboard/widgets/nft_tile_widget.dart @@ -13,22 +13,15 @@ class NFTTileWidget extends StatelessWidget { @override Widget build(BuildContext context) { return InkWell( - onTap: () => Navigator.pushNamed(context, Routes.nftDetailsPage, - arguments: nftAsset), + onTap: () => Navigator.pushNamed(context, Routes.nftDetailsPage, arguments: nftAsset), child: Container( width: double.infinity, margin: const EdgeInsets.only(left: 16, right: 16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(30.0), border: Border.all( - color: Theme.of(context) - .extension()! - .cardBorderColor, - width: 1, - ), - color: Theme.of(context) - .extension()! - .syncedBackgroundColor, + color: Theme.of(context).extension()!.cardBorderColor, width: 1), + color: Theme.of(context).extension()!.syncedBackgroundColor, ), child: Row( children: [ @@ -40,14 +33,10 @@ class NFTTileWidget extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(16.0), border: Border.all( - color: Theme.of(context) - .extension()! - .cardBorderColor, + color: Theme.of(context).extension()!.cardBorderColor, width: 1, ), - color: Theme.of(context) - .extension()! - .syncedBackgroundColor, + color: Theme.of(context).extension()!.syncedBackgroundColor, ), child: NFTImageWidget( imageUrl: nftAsset.normalizedMetadata?.imageUrl, @@ -59,27 +48,23 @@ class NFTTileWidget extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - '${nftAsset.name ?? ''} - ${nftAsset.symbol ?? ''}', + '${nftAsset.name ?? '---'} - ${nftAsset.symbol ?? '---'}', style: TextStyle( fontSize: 12, fontFamily: 'Lato', fontWeight: FontWeight.w400, - color: Theme.of(context) - .extension()! - .labelTextColor, + color: Theme.of(context).extension()!.labelTextColor, height: 1, ), ), SizedBox(height: 8), Text( - nftAsset.normalizedMetadata?.name ?? nftAsset.name ?? "", + nftAsset.normalizedMetadata?.name ?? nftAsset.name ?? "---", style: TextStyle( fontSize: 20, fontFamily: 'Lato', fontWeight: FontWeight.w900, - color: Theme.of(context) - .extension()! - .assetTitleColor, + color: Theme.of(context).extension()!.assetTitleColor, height: 1, ), ), @@ -92,4 +77,3 @@ class NFTTileWidget extends StatelessWidget { ); } } - diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index f9ff466a7..a3bf281ca 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -239,6 +239,8 @@ abstract class TransactionDetailsViewModelBase with Store { StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!), if (showRecipientAddress && tx.to != null) StandartListItem(title: S.current.transaction_details_recipient_address, value: tx.to!), + if (tx.direction == TransactionDirection.incoming && tx.from != null) + StandartListItem(title: S.current.transaction_details_source_address, value: tx.from!), ]; items.addAll(_items); @@ -271,8 +273,10 @@ abstract class TransactionDetailsViewModelBase with Store { StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()), if (tx.feeFormatted()?.isNotEmpty ?? false) StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!), - if (showRecipientAddress && tx.to != null) + if (showRecipientAddress && tx.to != null && tx.direction == TransactionDirection.outgoing) StandartListItem(title: S.current.transaction_details_recipient_address, value: tx.to!), + if (tx.direction == TransactionDirection.incoming && tx.from != null) + StandartListItem(title: S.current.transaction_details_source_address, value: tx.from!), ]; items.addAll(_items); diff --git a/model_generator.sh b/model_generator.sh index 32d863aeb..e7231f19a 100755 --- a/model_generator.sh +++ b/model_generator.sh @@ -1,9 +1,8 @@ cd cw_core && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_evm && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_monero && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -cd cw_ethereum && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -cd cw_polygon && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs \ No newline at end of file diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index f8ff07bd2..7ee08460d 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -764,9 +764,12 @@ "confirmed_tx": "مؤكد", "transaction_details_source_address": "عنوان المصدر", "pause_wallet_creation": ".ﺎﻴًﻟﺎﺣ ﺎﺘًﻗﺆﻣ ﺔﻔﻗﻮﺘﻣ Haven Wallet ءﺎﺸﻧﺇ ﻰﻠﻋ ﺓﺭﺪﻘﻟﺍ", + "contractName": "ﺪﻘﻌﻟﺍ ﻢﺳﺍ", + "contractSymbol": "ﺪﻘﻌﻟﺍ ﺰﻣﺭ", + "description": "ﻒﺻﻭ", "camera_consent": ".ﻞﻴﺻﺎﻔﺘﻟﺍ ﻰﻠﻋ ﻝﻮﺼﺤﻠﻟ ﻢﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺔﻴﺻﻮﺼﺨﻟﺍ ﺔﺳﺎﻴﺳ ﻦﻣ ﻖﻘﺤﺘﻟﺍ ﻰﺟﺮﻳ .${provider} ﻝﻮﻠ", - "no_relays": " ﺕﻼﺣﺮﻤﻟﺍ ﻻ", - "choose_relay": " ﻡﺍﺪﺨﺘﺳﻼﻟ ﻊﺑﺎﺘﺘﻟﺍ ﺭﺎﻴﺘﺧﺍ ءﺎﺟﺮﻟﺍ", + "no_relays": "ﺕﻼﺣﺮﻤﻟﺍ ﻻ", + "choose_relay": "ﻡﺍﺪﺨﺘﺳﻼﻟ ﻊﺑﺎﺘﺘﻟﺍ ﺭﺎﻴﺘﺧﺍ ءﺎﺟﺮﻟﺍ", "no_relays_message": ".ﻪﺑ ﺹﺎﺨﻟﺍ Nostr ﻞﺠﺳ ﻰﻟﺇ ﺕﻼﺣﺮﻤﻟﺍ ﺔﻓﺎﺿﻹ ﻢﻠﺘﺴﻤﻟﺍ ﺩﺎﺷﺭﺇ ﻰﺟﺮﻳ .ﺕﻼﺣﺮﻣ ﻱﺃ ﻰﻠﻋ ﻱﻮﺘﺤﻳ ﻻ", "no_relay_on_domain": ".ﻡﺍﺪﺨﺘﺳﻼﻟ ﻊﺑﺎﺘﺘﻟﺍ ﺭﺎﻴﺘﺧﺍ ءﺎﺟﺮﻟﺍ .ﺡﺎﺘﻣ ﺮﻴﻏ ﻞﻴﺣﺮﺘﻟﺍ ﻥﺃ ﻭﺃ ﻡﺪﺨﺘﺴﻤﻟﺍ ﻝﺎﺠﻤﻟ ﻞﻴﺣﺮﺗ ﺪ" } diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 8e6a6c1ee..58c27d5e8 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -760,6 +760,9 @@ "confirmed_tx": "Потвърдено", "transaction_details_source_address": "Адрес на източника", "pause_wallet_creation": "Възможността за създаване на Haven Wallet в момента е на пауза.", + "contractName": "Име на договора", + "contractSymbol": "Договор Символ", + "description": "Описание", "camera_consent": "Вашият фотоапарат ще бъде използван за заснемане на изображение с цел идентификация от ${provider}. Моля, проверете тяхната политика за поверителност за подробности.", "no_relays": "Без релета", "choose_relay": "Моля, изберете реле, което да използвате", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index a739fa05b..92874e315 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -760,6 +760,9 @@ "confirmed_tx": "Potvrzeno", "transaction_details_source_address": "Zdrojová adresa", "pause_wallet_creation": "Možnost vytvářet Haven Wallet je momentálně pozastavena.", + "contractName": "Název smlouvy", + "contractSymbol": "Symbol smlouvy", + "description": "Popis", "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ů.", "no_relays": "Žádná relé", "choose_relay": "Vyberte relé, které chcete použít", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 872b8bec2..9aca5ba28 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -768,6 +768,9 @@ "confirmed_tx": "Bestätigt", "transaction_details_source_address": "Quelladresse", "pause_wallet_creation": "Die Möglichkeit, Haven Wallet zu erstellen, ist derzeit pausiert.", + "contractName": "Vertragsname", + "contractSymbol": "Vertragssymbol", + "description": "Beschreibung", "camera_consent": "Mit Ihrer Kamera wird bis zum ${provider} ein Bild zur Identifizierung aufgenommen. Weitere Informationen finden Sie in deren Datenschutzbestimmungen.", "no_relays": "Keine Relais", "choose_relay": "Bitte wählen Sie ein zu verwendendes Relais aus", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 3ec496b6c..d54b7baa4 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -769,6 +769,9 @@ "confirmed_tx": "Confirmed", "transaction_details_source_address": "Source address", "pause_wallet_creation": "Ability to create Haven Wallet is currently paused.", + "contractName": "Contract Name", + "contractSymbol": "Contract Symbol", + "description": "Description", "camera_consent": "Your camera will be used to capture an image for identification purposes by ${provider}. Please check their Privacy Policy for details.", "no_relays": "No relays", "choose_relay": "Please choose a relay to use", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index ab97e764d..5f9a8e53b 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -768,6 +768,9 @@ "confirmed_tx": "Confirmado", "transaction_details_source_address": "Dirección de la fuente", "pause_wallet_creation": "La capacidad para crear Haven Wallet está actualmente pausada.", + "contractName": "Nombre del contrato", + "contractSymbol": "Símbolo de contrato", + "description": "Descripción", "camera_consent": "Su cámara será utilizada para capturar una imagen con fines de identificación por ${provider}. Consulte su Política de privacidad para obtener más detalles.", "no_relays": "Sin relevos", "choose_relay": "Por favor elija un relé para usar", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 619c35276..523253bf4 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -768,6 +768,9 @@ "confirmed_tx": "Confirmé", "transaction_details_source_address": "Adresse source", "pause_wallet_creation": "La possibilité de créer Haven Wallet est actuellement suspendue.", + "contractName": "Nom du contrat", + "contractSymbol": "Symbole du contrat", + "description": "Description", "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.", "no_relays": "Pas de relais", "choose_relay": "Veuillez choisir un relais à utiliser", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index dd38a4ec3..2f2343434 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -750,6 +750,9 @@ "confirmed_tx": "Tabbatar", "transaction_details_source_address": "Adireshin Incord", "pause_wallet_creation": "A halin yanzu an dakatar da ikon ƙirƙirar Haven Wallet.", + "contractName": "Sunan Kwangila", + "contractSymbol": "Alamar Kwangila", + "description": "Bayani", "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.", "no_relays": "Babu relays", "choose_relay": "Da fatan za a zaɓi gudun ba da sanda don amfani", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index b37aa7c12..a3950b44e 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -768,6 +768,9 @@ "confirmed_tx": "की पुष्टि", "transaction_details_source_address": "स्रोत पता", "pause_wallet_creation": "हेवन वॉलेट बनाने की क्षमता फिलहाल रुकी हुई है।", + "contractName": "अनुबंध का नाम", + "contractSymbol": "अनुबंध चिह्न", + "description": "विवरण", "camera_consent": "आपके कैमरे का उपयोग ${provider} द्वारा पहचान उद्देश्यों के लिए एक छवि कैप्चर करने के लिए किया जाएगा। विवरण के लिए कृपया उनकी गोपनीयता नीति जांचें।", "no_relays": "कोई रिले नहीं", "choose_relay": "कृपया उपयोग करने के लिए एक रिले चुनें", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index c1ba66bb2..8e3365c96 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -766,6 +766,9 @@ "confirmed_tx": "Potvrđen", "transaction_details_source_address": "Adresa izvora", "pause_wallet_creation": "Mogućnost stvaranja novčanika Haven trenutno je pauzirana.", + "contractName": "Naziv ugovora", + "contractSymbol": "Simbol ugovora", + "description": "Opis", "camera_consent": "Vaš će fotoaparat koristiti za snimanje slike u svrhu identifikacije od strane ${provider}. Pojedinosti potražite u njihovoj politici privatnosti.", "no_relays": "Nema releja", "choose_relay": "Odaberite relej za korištenje", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index b736f3977..27bfc4c7b 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -756,6 +756,9 @@ "confirmed_tx": "Dikonfirmasi", "transaction_details_source_address": "Alamat sumber", "pause_wallet_creation": "Kemampuan untuk membuat Haven Wallet saat ini dijeda.", + "contractName": "Nama Kontrak", + "contractSymbol": "Simbol Kontrak", + "description": "Keterangan", "camera_consent": "Kamera Anda akan digunakan untuk mengambil gambar untuk tujuan identifikasi oleh ${provider}. Silakan periksa Kebijakan Privasi mereka untuk detailnya.", "no_relays": "Tidak ada relay", "choose_relay": "Silakan pilih relai yang akan digunakan", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index adcaa3204..a29ac5c93 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -768,6 +768,9 @@ "confirmed_tx": "Confermato", "transaction_details_source_address": "Indirizzo di partenza", "pause_wallet_creation": "La possibilità di creare Haven Wallet è attualmente sospesa.", + "contractName": "Nome del contratto", + "contractSymbol": "Simbolo del contratto", + "description": "Descrizione", "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.", "no_relays": "Nessun relè", "choose_relay": "Scegli un relè da utilizzare", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 9dabebc45..df317392f 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -768,6 +768,9 @@ "confirmed_tx": "確認済み", "transaction_details_source_address": "ソースアドレス", "pause_wallet_creation": "Haven Wallet を作成する機能は現在一時停止されています。", + "contractName": "契約名", + "contractSymbol": "契約記号", + "description": "説明", "camera_consent": "あなたのカメラは、${provider}_ までに識別目的で画像を撮影するために使用されます。詳細については、プライバシー ポリシーをご確認ください。", "no_relays": "リレーなし", "choose_relay": "使用するリレーを選択してください", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index ee41a369b..5c3affbc5 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -766,6 +766,9 @@ "confirmed_tx": "확인", "transaction_details_source_address": "소스 주소", "pause_wallet_creation": "Haven Wallet 생성 기능이 현재 일시 중지되었습니다.", + "contractName": "계약명", + "contractSymbol": "계약 기호", + "description": "설명", "camera_consent": "귀하의 카메라는 ${provider}의 식별 목적으로 이미지를 캡처하는 데 사용됩니다. 자세한 내용은 해당 개인정보 보호정책을 확인하세요.", "no_relays": "릴레이 없음", "choose_relay": "사용할 릴레이를 선택해주세요", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 199d72660..27c9bdeeb 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -766,6 +766,9 @@ "confirmed_tx": "အတည်ပြုသည်", "transaction_details_source_address": "အရင်းအမြစ်လိပ်စာ", "pause_wallet_creation": "Haven Wallet ဖန်တီးနိုင်မှုကို လောလောဆယ် ခေတ္တရပ်ထားသည်။", + "contractName": "စာချုပ်အမည်", + "contractSymbol": "စာချုပ်သင်္ကေတ", + "description": "ဖော်ပြချက်", "camera_consent": "မှတ်ပုံတင်ခြင်းရည်ရွယ်ချက်များအတွက် ${provider} တွင် သင့်ကင်မရာကို အသုံးပြုပါမည်။ အသေးစိတ်အတွက် ၎င်းတို့၏ ကိုယ်ရေးကိုယ်တာမူဝါဒကို စစ်ဆေးပါ။", "no_relays": "Relay မရှိပါ။", "choose_relay": "အသုံးပြုရန် relay ကိုရွေးချယ်ပါ။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 9f27236aa..51f25e64a 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -768,6 +768,9 @@ "confirmed_tx": "Bevestigd", "transaction_details_source_address": "Bron adres", "pause_wallet_creation": "De mogelijkheid om Haven Wallet te maken is momenteel onderbroken.", + "contractName": "Contractnaam", + "contractSymbol": "Contractsymbool", + "description": "Beschrijving", "camera_consent": "Uw camera wordt gebruikt om vóór ${provider} een beeld vast te leggen voor identificatiedoeleinden. Raadpleeg hun privacybeleid voor meer informatie.", "no_relays": "Geen relais", "choose_relay": "Kies een relais dat u wilt gebruiken", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index c6e4806b1..4363ef5ae 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -768,6 +768,9 @@ "confirmed_tx": "Potwierdzony", "transaction_details_source_address": "Adres źródłowy", "pause_wallet_creation": "Możliwość utworzenia Portfela Haven jest obecnie wstrzymana.", + "contractName": "Nazwa umowy", + "contractSymbol": "Symbol kontraktu", + "description": "Opis", "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.", "no_relays": "Żadnych przekaźników", "choose_relay": "Wybierz przekaźnik, którego chcesz użyć", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index b9694d223..7cfd261eb 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -767,6 +767,9 @@ "confirmed_tx": "Confirmado", "transaction_details_source_address": "Endereço de Origem", "pause_wallet_creation": "A capacidade de criar a Haven Wallet está atualmente pausada.", + "contractName": "Nome do contrato", + "contractSymbol": "Símbolo do Contrato", + "description": "Descrição", "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.", "no_relays": "Sem relés", "choose_relay": "Escolha um relé para usar", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 3e5d2cec2..a4c34f5c5 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -768,6 +768,9 @@ "confirmed_tx": "Подтвержденный", "transaction_details_source_address": "Адрес источника", "pause_wallet_creation": "Возможность создания Haven Wallet в настоящее время приостановлена.", + "contractName": "Название контракта", + "contractSymbol": "Символ контракта", + "description": "Описание", "camera_consent": "Ваша камера будет использоваться для захвата изображения в целях идентификации ${provider}. Пожалуйста, ознакомьтесь с их Политикой конфиденциальности для получения подробной информации.", "no_relays": "Нет реле", "choose_relay": "Пожалуйста, выберите реле для использования", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index a9fe67959..603d04067 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -766,6 +766,9 @@ "confirmed_tx": "ซึ่งยืนยันแล้ว", "transaction_details_source_address": "ที่อยู่แหล่งกำเนิด", "pause_wallet_creation": "ขณะนี้ความสามารถในการสร้าง Haven Wallet ถูกหยุดชั่วคราว", + "contractName": "ชื่อสัญญา", + "contractSymbol": "สัญลักษณ์สัญญา", + "description": "คำอธิบาย", "camera_consent": "กล้องของคุณจะถูกนำมาใช้เพื่อจับภาพเพื่อวัตถุประสงค์ในการระบุตัวตนภายใน ${provider} โปรดตรวจสอบนโยบายความเป็นส่วนตัวเพื่อดูรายละเอียด", "no_relays": "ไม่มีรีเลย์", "choose_relay": "กรุณาเลือกรีเลย์ที่จะใช้", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 3d05cc700..a8ec4df3e 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -762,6 +762,9 @@ "confirmed_tx": "Nakumpirma", "transaction_details_source_address": "SOURCE ADDRESS", "pause_wallet_creation": "Kasalukuyang naka-pause ang kakayahang gumawa ng Haven Wallet.", + "contractName": "Pangalan ng Kontrata", + "contractSymbol": "Simbolo ng Kontrata", + "description": "Paglalarawan", "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.", "no_relays": "Walang mga relay", "choose_relay": "Mangyaring pumili ng relay na gagamitin", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 62243838d..337a85ff8 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -766,6 +766,9 @@ "confirmed_tx": "Onaylanmış", "transaction_details_source_address": "Kaynak adresi", "pause_wallet_creation": "Haven Cüzdanı oluşturma yeteneği şu anda duraklatıldı.", + "contractName": "Sözleşme Adı", + "contractSymbol": "Sözleşme Sembolü", + "description": "Tanım", "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.", "no_relays": "Röle yok", "choose_relay": "Lütfen kullanmak için bir röle seçin", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index def086b2e..7cc41ab43 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -768,6 +768,9 @@ "confirmed_tx": "Підтверджений", "transaction_details_source_address": "Адреса джерела", "pause_wallet_creation": "Можливість створення гаманця Haven зараз призупинено.", + "contractName": "Назва контракту", + "contractSymbol": "Контракт символ", + "description": "опис", "camera_consent": "Ваша камера використовуватиметься для зйомки зображення з метою ідентифікації ${provider}. Будь ласка, ознайомтеся з їхньою політикою конфіденційності, щоб дізнатися більше.", "no_relays": "Без реле", "choose_relay": "Будь ласка, виберіть реле для використання", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 34b1042ac..11fc67c4e 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -760,9 +760,12 @@ "confirmed_tx": "تصدیق", "transaction_details_source_address": "ماخذ ایڈریس", "pause_wallet_creation": "Haven Wallet ۔ﮯﮨ ﻑﻮﻗﻮﻣ ﻝﺎﺤﻟﺍ ﯽﻓ ﺖﯿﻠﮨﺍ ﯽﮐ ﮯﻧﺎﻨﺑ", + "contractName": "ﻡﺎﻧ ﺎﮐ ﮦﺪﮨﺎﻌﻣ", + "contractSymbol": "ﺖﻣﻼﻋ ﯽﮐ ﮦﺪﮨﺎﻌﻣ", + "description": "ﻞﯿﺼﻔﺗ", "camera_consent": "۔ﮟﯿﮭﮑﯾﺩ ﯽﺴﯿﻟﺎﭘ ﯽﺴﯾﻮﯿﺋﺍﺮﭘ ﯽﮐ ﻥﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ﮯﯿﻟ ﮯﮐ ﺕﻼ${provider}ﯿﺼﻔﺗ ۔ﺎﮔ ﮯﺋﺎﺟ ﺎﯿﮐ ﻝﺎﻤﻌﺘﺳﺍ ﮯﯿﻟ", - "no_relays": " ۔ﮟﯿﮩﻧ ﮯﻠﯾﺭ ﯽﺋﻮﮐ", - "choose_relay": " ۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﮯﻠﯾﺭ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ ﻡﺮﮐ ﮦﺍﺮﺑ", + "no_relays": "۔ﮟﯿﮩﻧ ﮯﻠﯾﺭ ﯽﺋﻮﮐ", + "choose_relay": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﮯﻠﯾﺭ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ ﻡﺮﮐ ﮦﺍﺮﺑ", "no_relays_message": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮯﻠﯾﺭ ﮟﯿﻣ ﮈﺭﺎﮑﯾﺭ ﺮﭩﺳﻮﻧ ﮯﻨﭘﺍ ﮦﻭ ﮧﮐ ﮟﯾﺩ ﺖﯾﺍﺪﮨ ﻮﮐ ﮦﺪﻨﻨﮐ ﻝﻮﺻﻭ ﻡﺮﮐ ﮦﺍﺮﺑ ۔", "no_relay_on_domain": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﮯﻠﯾﺭ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ۔ﮯﮨ ﮟﯿﮩﻧ ﺏﺎﯿﺘﺳﺩ ﮯﻠﯾﺭ ﺎﯾ ﮯﮨ ﮟ" } diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 12769ec91..142d9f5bf 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -762,6 +762,9 @@ "confirmed_tx": "Jẹrisi", "transaction_details_source_address": "Adirẹsi orisun", "pause_wallet_creation": "Agbara lati ṣẹda Haven Wallet ti wa ni idaduro lọwọlọwọ.", + "contractName": "Orukọ adehun", + "contractSymbol": "Aami adehun", + "description": "Apejuwe", "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.", "no_relays": "Ko si relays", "choose_relay": "Jọwọ yan yii lati lo", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index cdffd8141..92904034b 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -767,6 +767,9 @@ "confirmed_tx": "确认的", "transaction_details_source_address": "源地址", "pause_wallet_creation": "创建 Haven 钱包的功能当前已暂停。", + "contractName": "合约名称", + "contractSymbol": "合约符号", + "description": "描述", "camera_consent": "${provider} 将使用您的相机拍摄图像以供识别之用。请查看他们的隐私政策了解详情。", "no_relays": "无继电器", "choose_relay": "请选择要使用的继电器", diff --git a/tool/configure.dart b/tool/configure.dart index 4421d4f3f..8297d8a39 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -525,19 +525,24 @@ import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; + +"""; + const ethereumCWHeaders = """ +import 'package:cw_evm/evm_chain_formatter.dart'; +import 'package:cw_evm/evm_chain_mnemonics.dart'; +import 'package:cw_evm/evm_chain_transaction_credentials.dart'; +import 'package:cw_evm/evm_chain_transaction_info.dart'; +import 'package:cw_evm/evm_chain_transaction_priority.dart'; +import 'package:cw_evm/evm_chain_wallet_creation_credentials.dart'; + +import 'package:cw_ethereum/ethereum_client.dart'; +import 'package:cw_ethereum/ethereum_wallet.dart'; +import 'package:cw_ethereum/ethereum_wallet_service.dart'; + import 'package:eth_sig_util/util/utils.dart'; import 'package:hive/hive.dart'; import 'package:web3dart/web3dart.dart'; -"""; - const ethereumCWHeaders = """ -import 'package:cw_ethereum/ethereum_formatter.dart'; -import 'package:cw_ethereum/ethereum_mnemonics.dart'; -import 'package:cw_ethereum/ethereum_transaction_credentials.dart'; -import 'package:cw_ethereum/ethereum_transaction_info.dart'; -import 'package:cw_ethereum/ethereum_wallet.dart'; -import 'package:cw_ethereum/ethereum_wallet_creation_credentials.dart'; -import 'package:cw_ethereum/ethereum_wallet_service.dart'; -import 'package:cw_ethereum/ethereum_transaction_priority.dart'; + """; const ethereumCwPart = "part 'cw_ethereum.dart';"; const ethereumContent = """ @@ -612,19 +617,24 @@ import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; -import 'package:eth_sig_util/util/utils.dart'; -import 'package:hive/hive.dart'; -import 'package:web3dart/web3dart.dart'; + """; const polygonCWHeaders = """ -import 'package:cw_polygon/polygon_formatter.dart'; -import 'package:cw_polygon/polygon_transaction_credentials.dart'; -import 'package:cw_polygon/polygon_transaction_info.dart'; +import 'package:cw_evm/evm_chain_formatter.dart'; +import 'package:cw_evm/evm_chain_mnemonics.dart'; +import 'package:cw_evm/evm_chain_transaction_info.dart'; +import 'package:cw_evm/evm_chain_transaction_priority.dart'; +import 'package:cw_evm/evm_chain_transaction_credentials.dart'; +import 'package:cw_evm/evm_chain_wallet_creation_credentials.dart'; + +import 'package:cw_polygon/polygon_client.dart'; import 'package:cw_polygon/polygon_wallet.dart'; -import 'package:cw_polygon/polygon_wallet_creation_credentials.dart'; import 'package:cw_polygon/polygon_wallet_service.dart'; -import 'package:cw_polygon/polygon_transaction_priority.dart'; -import 'package:cw_ethereum/ethereum_mnemonics.dart'; + +import 'package:hive/hive.dart'; +import 'package:web3dart/web3dart.dart'; +import 'package:eth_sig_util/util/utils.dart'; + """; const polygonCwPart = "part 'cw_polygon.dart';"; const polygonContent = """ @@ -924,6 +934,10 @@ Future generatePubspec( cw_polygon: path: ./cw_polygon """; + const cwEVM = """ + cw_evm: + path: ./cw_evm + """; final inputFile = File(pubspecOutputPath); final inputText = await inputFile.readAsString(); final inputLines = inputText.split('\n'); @@ -964,6 +978,10 @@ Future generatePubspec( output += '\n$cwHaven'; } + if (hasEthereum || hasPolygon) { + output += '\n$cwEVM'; + } + final outputLines = output.split('\n'); inputLines.insertAll(dependenciesIndex + 1, outputLines); final outputContent = inputLines.join('\n'); diff --git a/tool/generate_secrets_config.dart b/tool/generate_secrets_config.dart index 1d533b0b1..58e7b8839 100644 --- a/tool/generate_secrets_config.dart +++ b/tool/generate_secrets_config.dart @@ -4,7 +4,7 @@ import 'utils/secret_key.dart'; import 'utils/utils.dart'; const configPath = 'tool/.secrets-config.json'; -const ethereumConfigPath = 'tool/.ethereum-secrets-config.json'; +const evmChainsConfigPath = 'tool/.evm-secrets-config.json'; Future main(List args) async => generateSecretsConfig(args); @@ -17,7 +17,7 @@ Future generateSecretsConfig(List args) async { }); final configFile = File(configPath); - final ethereumConfigFile = File(ethereumConfigPath); + final evmChainsConfigFile = File(evmChainsConfigPath); final secrets = {}; secrets.addAll(extraInfo); @@ -49,7 +49,7 @@ Future generateSecretsConfig(List args) async { await configFile.writeAsString(secretsJson); secrets.clear(); - SecretKey.ethereumSecrets.forEach((sec) { + SecretKey.evmChainsSecrets.forEach((sec) { if (secrets[sec.name] != null) { return; } @@ -59,5 +59,5 @@ Future generateSecretsConfig(List args) async { secretsJson = JsonEncoder.withIndent(' ').convert(secrets); - await ethereumConfigFile.writeAsString(secretsJson); + await evmChainsConfigFile.writeAsString(secretsJson); } diff --git a/tool/import_secrets_config.dart b/tool/import_secrets_config.dart index 5987b9005..83e345f78 100644 --- a/tool/import_secrets_config.dart +++ b/tool/import_secrets_config.dart @@ -5,8 +5,8 @@ import 'utils/utils.dart'; const configPath = 'tool/.secrets-config.json'; const outputPath = 'lib/.secrets.g.dart'; -const ethereumConfigPath = 'tool/.ethereum-secrets-config.json'; -const ethereumOutputPath = 'cw_ethereum/lib/.secrets.g.dart'; +const evmChainsConfigPath = 'tool/.evm-secrets-config.json'; +const evmChainsOutputPath = 'cw_evm/lib/.secrets.g.dart'; Future main(List args) async => importSecretsConfig(); @@ -15,11 +15,11 @@ Future importSecretsConfig() async { final input = json.decode(File(configPath).readAsStringSync()) as Map; final output = input.keys.fold('', (String acc, String val) => acc + generateConst(val, input)); - final ethereumOutputFile = File(ethereumOutputPath); - final ethereumInput = - json.decode(File(ethereumConfigPath).readAsStringSync()) as Map; - final ethereumOutput = ethereumInput.keys - .fold('', (String acc, String val) => acc + generateConst(val, ethereumInput)); + final evmChainsOutputFile = File(evmChainsOutputPath); + final evmChainsInput = + json.decode(File(evmChainsConfigPath).readAsStringSync()) as Map; + final evmChainsOutput = evmChainsInput.keys + .fold('', (String acc, String val) => acc + generateConst(val, evmChainsInput)); if (outputFile.existsSync()) { await outputFile.delete(); @@ -27,9 +27,9 @@ Future importSecretsConfig() async { await outputFile.writeAsString(output); - if (ethereumOutputFile.existsSync()) { - await ethereumOutputFile.delete(); + if (evmChainsOutputFile.existsSync()) { + await evmChainsOutputFile.delete(); } - await ethereumOutputFile.writeAsString(ethereumOutput); + await evmChainsOutputFile.writeAsString(evmChainsOutput); } diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index e6f625426..f991c43cf 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -36,10 +36,10 @@ class SecretKey { SecretKey('robinhoodApplicationId', () => ''), SecretKey('robinhoodCIdApiSecret', () => ''), SecretKey('walletConnectProjectId', () => ''), - SecretKey('moralisApiKey', () => '') + SecretKey('moralisApiKey', () => ''), ]; - static final ethereumSecrets = [ + static final evmChainsSecrets = [ SecretKey('etherScanApiKey', () => ''), SecretKey('polygonScanApiKey', () => ''), ]; From a3790b1e290c1f8f5a1b94e0358b2c8acf42865d Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Wed, 31 Jan 2024 16:05:03 +0200 Subject: [PATCH 107/241] Add missing packages pub get, to model generator [skip ci] (#1286) --- .github/workflows/pr_test_build.yml | 2 ++ configure_cake_wallet.sh | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 6e5f9e171..88dd2c1eb 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -111,6 +111,8 @@ jobs: cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. + cd cw_ethereum && flutter pub get && cd .. + cd cw_polygon && flutter pub get && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs - name: Add secrets diff --git a/configure_cake_wallet.sh b/configure_cake_wallet.sh index a4b6f2654..5009cd9e3 100755 --- a/configure_cake_wallet.sh +++ b/configure_cake_wallet.sh @@ -30,4 +30,6 @@ cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_ethereum && flutter pub get && cd .. +cd cw_polygon && flutter pub get && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs From 39a73b2058f92d2367390a1a2e549ccf9155a7e8 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Sat, 3 Feb 2024 03:16:04 +0200 Subject: [PATCH 108/241] Update model_generator.sh --- model_generator.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/model_generator.sh b/model_generator.sh index e7231f19a..a2b016bb0 100755 --- a/model_generator.sh +++ b/model_generator.sh @@ -5,4 +5,6 @@ cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -flutter packages pub run build_runner build --delete-conflicting-outputs \ No newline at end of file +cd cw_ethereum && flutter pub get && cd .. +cd cw_polygon && flutter pub get && cd .. +flutter packages pub run build_runner build --delete-conflicting-outputs From 3945a3d7b43a14646c3459fe0daacfc127487d3d Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Tue, 6 Feb 2024 12:12:51 -0800 Subject: [PATCH 109/241] Cw 577 translation fixes (#1290) * pt.1 * alphabetize * alphabetize translation files * revert trailing comma addition * fix translations --- res/values/strings_ar.arb | 1483 +++++++++---------- res/values/strings_bg.arb | 1475 +++++++++---------- res/values/strings_cs.arb | 1475 +++++++++---------- res/values/strings_de.arb | 1495 +++++++++---------- res/values/strings_en.arb | 1497 +++++++++---------- res/values/strings_es.arb | 1495 +++++++++---------- res/values/strings_fr.arb | 1495 +++++++++---------- res/values/strings_ha.arb | 1459 +++++++++---------- res/values/strings_hi.arb | 1495 +++++++++---------- res/values/strings_hr.arb | 1497 +++++++++---------- res/values/strings_id.arb | 1467 +++++++++---------- res/values/strings_it.arb | 1491 +++++++++---------- res/values/strings_ja.arb | 1491 +++++++++---------- res/values/strings_ko.arb | 1493 +++++++++---------- res/values/strings_my.arb | 1487 +++++++++---------- res/values/strings_nl.arb | 1491 +++++++++---------- res/values/strings_pl.arb | 1491 +++++++++---------- res/values/strings_pt.arb | 1489 +++++++++---------- res/values/strings_ru.arb | 1491 +++++++++---------- res/values/strings_th.arb | 1487 +++++++++---------- res/values/strings_tl.arb | 1501 ++++++++++---------- res/values/strings_tr.arb | 1487 +++++++++---------- res/values/strings_uk.arb | 1491 +++++++++---------- res/values/strings_ur.arb | 1475 +++++++++---------- res/values/strings_yo.arb | 1485 +++++++++---------- res/values/strings_zh.arb | 1495 +++++++++---------- tool/append_translation.dart | 10 + tool/utils/translation/arb_file_utils.dart | 26 +- 28 files changed, 19385 insertions(+), 19329 deletions(-) diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 7ee08460d..6ccc3f9bf 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -1,775 +1,776 @@ { - "welcome": "مرحبا بك في", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "محفظة رائعة ل Monero, Bitcoin, Ethereum, Litecoin و Haven", - "please_make_selection": "يرجى الأختيار لإنشاء أو استعادة محفظتك.", - "create_new": "إنشاء محفظة جديدة", - "restore_wallet": "استعادة محفظة", - "monero_com": "Monero.com بواسطة Cake Wallet", - "monero_com_wallet_text": "محفظة رائعة ل Monero", - "haven_app": "Haven بواسطة Cake Wallet", - "haven_app_wallet_text": "محفظة رائعة ل Haven", - "accounts": "حسابتي", - "edit": "تعديل", + "about_cake_pay": "يتيح لك Cake Pay شراء بطاقات هدايا بأصول افتراضية بسهولة ، ويمكن إنفاقها على الفور لدى أكثر من 150,000 تاجر في الولايات المتحدة.", "account": "حساب", + "accounts": "حسابتي", + "accounts_subaddresses": "الحسابات والعناوين الفرعية", + "activate": "تفعيل", + "active": "نشيط", + "active_cards": "البطاقات النشطة", + "activeConnectionsPrompt": "ﺎﻨﻫ ﺔﻄﺸﻨﻟﺍ ﺕﻻﺎﺼﺗﻻﺍ ﺮﻬﻈﺘﺳ", "add": "إضافة", + "add_contact": "ﻝﺎﺼﺗﺍ ﺔﻬﺟ ﺔﻓﺎﺿﺇ", + "add_custom_node": "إضافة عقدة مخصصة جديدة", + "add_custom_redemption": "إضافة استرداد مخصص", + "add_fund_to_card": "أضف أموالاً مدفوعة مسبقًا إلى البطاقات (حتى ${value})", + "add_new_node": "أضافة عقدة جديدة", + "add_new_word": "أضف كلمة جديدة", + "add_receiver": "أضف مستقبل آخر (اختياري)", + "add_secret_code": " ﺔﻗﺩﺎﺼﻤﻟﺍ ﻖﻴﺒﻄﺗ ﻰﻟﺇ ﻱﺮﺴﻟﺍ ﺰﻣﺮﻟﺍ ﺍﺬﻫ ﻒﺿﺃ ﻭﺃ", + "add_tip": "أضف بقشيش", + "add_token_disclaimer_check": "لقد قمت بتأكيد عنوان ومعلومات عقد الرمز المميز باستخدام مصدر حسن السمعة. يمكن أن تؤدي إضافة معلومات خبيثة أو غير صحيحة إلى خسارة الأموال.", + "add_token_warning": "لا تقم بتحرير أو إضافة رموز وفقًا لتعليمات المحتالين.\nقم دائمًا بتأكيد عناوين الرموز مع مصادر حسنة السمعة!", + "add_value": "إضافة قيمة", + "address": " ﻥﺍﻮﻨﻋ", "address_book": "دليل العناوين", - "contact": "تواصل", - "please_select": "الرجاء الأختيار:", - "cancel": "إلغاء", - "ok": "حسناً", - "contact_name": "اسم جهة الاتصال", - "reset": "إعادة", - "save": "حفظ", + "address_book_menu": "دليل العناوين", + "address_detected": "تم ايجاد العنوان", + "address_from_domain": "هذا العنوان من ${domain} من Unstoppable Domains", + "address_from_yat": "هذا العنوان من ${emoji} على Yat", + "address_label": "تسمية عنوان", "address_remove_contact": "ازالة جهة الاتصال", "address_remove_content": "هل أنت متأكد من رغبتك في إزالة جهة الاتصال المحددة؟", - "authenticated": "تم المصادقة", - "authentication": "المصادقة", - "failed_authentication": "${state_error} فشل المصادقة.", - "wallet_menu": "قائمة", - "Blocks_remaining": "بلوك متبقي ${status}", - "please_try_to_connect_to_another_node": "الرجاء محاولة الاتصال بعقدة أخرى", - "xmr_hidden": "مختفي", - "xmr_available_balance": "الرصيد المتوفر", - "xmr_full_balance": "الرصيد الكامل", - "send": "إرسال", - "receive": "استلام", - "transactions": "المعاملات", - "incoming": "الواردة", - "outgoing": "الصادره", - "transactions_by_date": "المعاملات حسب التاريخ", - "trades": "عمليات التداول", - "filter_by": "تصفية حسب", - "today": "اليوم", - "yesterday": "الامس", - "received": "استلام", - "sent": "تم الأرسال", - "pending": " (في الإنتظار)", - "rescan": "إعادة الفحص", - "reconnect": "أعد الاتصال", - "wallets": "المحافظ", - "show_seed": "عرض السييد", - "show_keys": "اظهار السييد / المفاتيح", - "address_book_menu": "دليل العناوين", - "reconnection": "إعادة الاتصال", - "reconnect_alert_text": "هل أنت متأكد من رغبتك في إعادة الاتصال؟", - "exchange": "تبادل", - "clear": "مسح", - "refund_address": "عنوان إعادة المال", - "change_exchange_provider": "تغيير مزود الصرف", - "you_will_send": "تحويل من", - "you_will_get": "حول الى", - "amount_is_guaranteed": "مبلغ الاستلام مضمون", - "amount_is_estimate": "المبلغ المستلم هو تقدير", - "powered_by": "بدعم من ${title}", - "error": "خطأ", - "estimated": "مُقدَّر", - "min_value": "الحد الأدنى: ${value} ${currency}", - "max_value": "الحد الأقصى: ${value} ${currency}", - "change_currency": "تغيير العملة", - "overwrite_amount": "تغير المبلغ", - "qr_payment_amount": "يحتوي هذا ال QR على مبلغ الدفع. هل تريد تغير المبلغ فوق القيمة الحالية؟", - "copy_id": "نسخ معرف العملية", - "exchange_result_write_down_trade_id": "يرجى نسخ أو كتابة معرّف العملية للمتابعة.", - "trade_id": "معرف عملية التبادل:", - "copied_to_clipboard": "نسخ إلى الحافظة", - "saved_the_trade_id": "لقد تم حفظ معرف العملية", - "fetching": "جار الجلب", - "id": "رقم المعرف:", - "amount": "مقدار:", - "payment_id": "معرف الدفع:", - "status": "الحالة:", - "offer_expires_in": "ينتهي العرض في:", - "trade_is_powered_by": "عملية التبادل مدعومة من ${provider}", - "copy_address": "نسخ العنوان", - "exchange_result_confirm": "بالضغط على تأكيد ، سترسل ${fetchingLabel} ${from} من محفظتك المسماة ${walletName} إلى العنوان الموضح أدناه. أو يمكنك الإرسال من محفظتك الخارجية إلى العنوان أدناه / QR.\n\nيرجى الضغط على تأكيد للمتابعة أو الرجوع لتغيير المبالغ.", - "exchange_result_description": "يجب عليك إرسال ما لا يقل عن ${fetchingLabel} ${from} إلى العنوان المعروض في الصفحة التالية. إذا أرسلت مبلغًا أقل من ${fetchingLabel} ${from} فقد لا يتم تحويله وقد لا يتم رده.", - "exchange_result_write_down_ID": "* يرجى نسخ أو كتابة معرف هويتك الأعلى لحفظة.", - "confirm": "تأكيد", - "confirm_sending": "تأكيد الإرسال", - "commit_transaction_amount_fee": "تنفيذ الصفقة\nالمبلغ: ${amount}\nالرسوم: ${fee}", - "sending": "يتم الإرسال", - "transaction_sent": "تم إرسال المعاملة!", - "expired": "منتهي الصلاحية", - "time": "${minutes}د ${seconds}س", - "send_xmr": "أرسل XMR", - "exchange_new_template": "قالب جديد", - "faq": "الأسئلة الشائعة", - "enter_your_pin": "أدخل كود الرقم السري", - "loading_your_wallet": "يتم تحميل محفظتك", - "new_wallet": "إنشاء محفظة جديدة", - "wallet_name": "اسم المحفظة", - "continue_text": "التالي", - "choose_wallet_currency": "الرجاء اختيار عملة المحفظة:", - "node_new": "عقدة جديدة", - "node_address": "عنوان العقدة", - "node_port": "منفذ العقدة", - "login": "تسجيل الدخول", - "password": "كلمة المرور", - "nodes": "العقد", - "node_reset_settings_title": "اعادة الضبط", - "nodes_list_reset_to_default_message": "هل أنت متأكد أنك تريد إعادة تعيين الإعدادات إلى الافتراضي؟", - "change_current_node": "هل أنت متأكد من تغيير العقدة الحالية إلى ${node}؟", - "change": "تغير", - "remove_node": "إزالة العقدة", - "remove_node_message": "هل أنت متأكد أنك تريد إزالة العقدة المحددة؟", - "remove": "إزالة", - "delete": "حذف", - "add_new_node": "أضافة عقدة جديدة", - "change_current_node_title": "تغيير العقدة الحالية", - "node_test": "تجربة", - "node_connection_successful": "تم الاتصال بنجاح", - "node_connection_failed": "فشل الاتصال", - "new_node_testing": "تجربة العقدة الجديدة", - "use": "التبديل إلى", - "digit_pin": "-رقم PIN", - "share_address": "شارك العنوان", - "receive_amount": "المقدار", - "subaddresses": "العناوين الفرعية", "addresses": "عناوين", - "scan_qr_code_to_get_address": "امسح ال QR للحصول على العنوان", - "qr_fullscreen": "انقر لفتح ال QR بملء الشاشة", - "rename": "إعادة تسمية", - "choose_account": "اختر حساب", - "create_new_account": "انشاء حساب جديد", - "accounts_subaddresses": "الحسابات والعناوين الفرعية", - "restore_restore_wallet": "استعادة محفظة", - "restore_title_from_seed_keys": "استعادة من السييد / المفاتيح", - "restore_description_from_seed_keys": "استرجع محفظتك من السييد / المفاتيح التي قمت بحفظها في مكان آمن", - "restore_next": "التالي", - "restore_title_from_backup": "استعادة من النسخة الاحتياطية", - "restore_description_from_backup": "يمكنك استعادة تطبيق Cake Wallet بالكامل من ملف النسخ الاحتياطي", - "restore_seed_keys_restore": "استعادة السييد / المفاتيح", - "restore_title_from_seed": "استعادة من السييد", - "restore_description_from_seed": "قم باستعادة محفظتك من الرمز المكون من 25 كلمة أو 13 كلمة", - "restore_title_from_keys": "استعادة من المفاتيح", - "restore_description_from_keys": "قم باستعادة محفظتك من ضغطات المفاتيح المولدة المحفوظة من مفاتيحك الخاصة", - "restore_wallet_name": "اسم المحفظة", - "restore_address": "العنوان", - "restore_view_key_private": "مفتاح العرض (خاص)", - "restore_spend_key_private": "مفتاح الإنفاق (خاص)", - "restore_recover": "استعادة", - "restore_wallet_restore_description": "وصف استعادة المحفظة", - "restore_new_seed": "سييد جديدة", - "restore_active_seed": "السييد النشطة", - "restore_bitcoin_description_from_seed": "قم باستعادة محفظتك من كود مكون من 24 كلمة", - "restore_bitcoin_description_from_keys": "قم باستعادة محفظتك من سلسلة WIF التي تم إنشاؤها من مفاتيحك الخاصة", - "restore_bitcoin_title_from_keys": "استعادة من WIF", - "restore_from_date_or_blockheight": "الرجاء إدخال تاريخ قبل إنشاء هذه المحفظة ببضعة أيام. أو إذا كنت تعرف ارتفاع البلوك، فيرجى إدخاله بدلاً من ذلك", - "seed_reminder": "يرجى تدوينها في حالة فقد هاتفك أو مسحه", - "seed_title": "سييد", - "seed_share": "شارك السييد", - "copy": "نسخ", - "seed_language": "لغة البذور", - "seed_choose": "اختر لغة السييد", - "seed_language_next": "التالي", - "seed_language_english": "إنجليزي", - "seed_language_chinese": "صينى", - "seed_language_dutch": "هولندي", - "seed_language_german": "ألمانية", - "seed_language_japanese": "اليابانية", - "seed_language_portuguese": "البرتغالية", - "seed_language_russian": "الروسية", - "seed_language_spanish": "الأسبانية", - "seed_language_french": "فرنسي", - "seed_language_italian": "إيطالي", - "send_title": "إرسال", - "send_your_wallet": "محفظتك", - "send_address": "عنوان ${cryptoCurrency}", - "send_payment_id": "معرف عملية الدفع (اختياري)", + "advanced_settings": "إعدادات متقدمة", + "aggressive": "عنيف", + "agree": "موافق", + "agree_and_continue": "الموافقة ومتابعة", + "agree_to": "من خلال إنشاء حساب فإنك توافق على", "all": "الكل", - "send_error_minimum_value": "الحد الأدنى لقيمة المبلغ هو 0.01", - "send_error_currency": "العملة يجب أن تحتوي على أرقام فقط", - "send_estimated_fee": "الرسوم المقدرة:", - "send_priority": "حاليًا ، تم تحديد الرسوم بأولوية ${transactionPriority}.\nيمكن تعديل أولوية المعاملة في الإعدادات", - "send_creating_transaction": " يتم إنشاء المعاملة", - "send_templates": "القوالب", - "send_new": "جديد", - "send_amount": "مقدار:", - "send_fee": "الرسوم:", - "send_name": "الأسم", - "got_it": "فهمتك", - "send_sending": "يتم الإرسال...", - "send_success": "تم إرسال ${crypto} الخاص بك بنجاح", - "settings_title": "إعدادات", - "settings_nodes": "العقد", - "settings_current_node": "العقدة الحالية", - "settings_wallets": "المحافظ", - "settings_display_balance": "عرض الرصيد", - "settings_currency": "العملة", - "settings_fee_priority": "رسوم الأولوية", - "settings_save_recipient_address": "حفظ عنوان المستلم", - "settings_personal": "شخصي", - "settings_change_pin": "تغيير PIN", - "settings_change_language": "تغيير اللغة", - "settings_allow_biometrical_authentication": "السماح بالمصادقة البيومترية", - "settings_dark_mode": "الوضع الداكن", - "settings_transactions": "المبادلات", - "settings_trades": "الصفقات", - "settings_display_on_dashboard_list": "عرض في قائمة لوحة المعلومات", - "settings_all": "الكل", - "settings_only_trades": "الصفقات فقط", - "settings_only_transactions": "المعاملات فقط", - "settings_none": "لا شيء", - "settings_support": "الدعم", - "settings_terms_and_conditions": "الأحكام والشروط", - "pin_is_incorrect": "رقم ال PIN غير صحيح", - "setup_pin": "تعيين PIN", - "enter_your_pin_again": "أدخل PIN الخاص بك مرة أخرى", - "setup_successful": "تم إعداد PIN الخاص بك بنجاح!", - "wallet_keys": "سييد المحفظة / المفاتيح", - "wallet_seed": "سييد المحفظة", - "private_key": "مفتاح خاص", - "public_key": "مفتاح عمومي", - "view_key_private": "مفتاح العرض (خاص)", - "view_key_public": "مفتاح العرض (عام)", - "spend_key_private": "مفتاح الإنفاق (خاص)", - "spend_key_public": "مفتاح الإنفاق (عام)", - "copied_key_to_clipboard": "تم نسخ ${key} إلى الحافظة", - "new_subaddress_title": "عنوان جديد", - "new_subaddress_label_name": "تسمية", - "new_subaddress_create": "إنشاء", - "address_label": "تسمية عنوان", - "subaddress_title": "قائمة العناوين الفرعية", - "trade_details_title": "تفاصيل الصفقة", - "trade_details_id": "معرف (ID)", - "trade_details_state": "الحالة", - "trade_details_fetching": "جار الجلب", - "trade_details_provider": "مزود", - "trade_details_created_at": "أنشئت في", - "trade_details_pair": "زوج", - "trade_details_copied": "تم نسخ ${title} إلى الحافظة", - "trade_history_title": "تاريخ الصفقه", - "transaction_details_title": "تفاصيل المعاملة", - "transaction_details_transaction_id": "رقم المعاملة", - "transaction_details_date": "تاريخ", - "transaction_details_height": "ارتفاع", - "transaction_details_amount": "مقدار", - "transaction_details_fee": "رسوم", - "transaction_details_copied": "تم نسخ ${title} إلى الحافظة", - "transaction_details_recipient_address": "عناوين المستلم", - "wallet_list_title": "محفظة Monero", - "wallet_list_create_new_wallet": "إنشاء محفظة جديدة", - "wallet_list_edit_wallet": "تحرير المحفظة", - "wallet_list_wallet_name": "اسم المحفظة", - "wallet_list_restore_wallet": "استعادة المحفظة", - "wallet_list_load_wallet": "تحميل المحفظة", - "wallet_list_loading_wallet": "جار تحميل محفظة ${wallet_name}", - "wallet_list_failed_to_load": "فشل تحميل محفظة ${wallet_name}. ${error}", - "wallet_list_removing_wallet": "يتم إزالة محفظة ${wallet_name}", - "wallet_list_failed_to_remove": "فشلت إزالة محفظة ${wallet_name}. ${error}", - "widgets_address": "عنوان", - "widgets_restore_from_blockheight": "استعادة من ارتفاع البلوك", - "widgets_restore_from_date": "استعادة من التاريخ", - "widgets_or": "أو", - "widgets_seed": "سييد", - "router_no_route": "لم يتم تحديد مسار لـ ${name}", - "error_text_account_name": "يجب أن يحتوي اسم الحساب على أحرف وأرقام فقط\nويجب أن يتراوح بين حرف واحد و 15 حرفًا", - "error_text_contact_name": "لا يمكن أن يحتوي اسم جهة الاتصال على الرموز ` , ' \"\nويجب أن يتراوح بين حرف و 32 حرفًا", - "error_text_address": "يجب أن يتوافق عنوان المحفظة مع نوع\nالعملة المشفرة", - "error_text_node_address": "الرجاء إدخال عنوان IPv4", - "error_text_node_port": "منفذ العقدة يمكن أن يحتوي فقط على أرقام بين 0 و 65535", - "error_text_node_proxy_address": "الرجاء إدخال <عنوان IPv4>: ، على سبيل المثال 127.0.0.1:9050", - "error_text_payment_id": "يمكن أن يحتوي معرّف الدفع فقط من 16 إلى 64 حرفًا hex", - "error_text_xmr": "لا يمكن أن تتجاوز قيمة XMR الرصيد المتاح.\nيجب أن يكون عدد الكسور أقل من أو يساوي 12", - "error_text_fiat": "لا يمكن أن تتجاوز قيمة المبلغ الرصيد المتاح.\nيجب أن يكون عدد الكسور أقل أو يساوي 2", - "error_text_subaddress_name": "لا يمكن أن يحتوي اسم العنوان الفرعي على رموز ` , ' \"\nويجب أن يتراوح طولها بين حرف واحد و 20 حرفًا", - "error_text_amount": "يجب أن يحتوي المبلغ على أرقام فقط", - "error_text_wallet_name": "يمكن أن يحتوي اسم المحفظة على أحرف وأرقام ورموز _ - فقط\nويجب أن يتراوح طولها بين حرف واحد و 33 حرفًا", - "error_text_keys": "يمكن أن تحتوي مفاتيح المحفظة على 64 حرفًا hex", - "error_text_crypto_currency": "عدد الكسور\nيجب أن تكون أقل من أو تساوي 12", - "error_text_minimal_limit": "لم يتم إنشاء الصفقة لـ ${provider}. المبلغ أقل من الحد الأدنى: ${min} ${currency}", - "error_text_maximum_limit": "لم يتم إنشاء الصفقة لـ ${provider}. المبلغ أكبر من الحد الأقصى: ${max} ${currency}", - "error_text_limits_loading_failed": "لم يتم إنشاء الصفقة لـ ${provider}. فشل تحميل الحدود", - "error_text_template": "لا يمكن أن يحتوي اسم القالب وعنوانه على رموز ` , \"\nويجب أن يتراوح طولها بين 1 و 106 حرفًا", + "all_trades": "جميع عمليات التداول", + "all_transactions": "كل التحركات المالية", + "alphabetical": "مرتب حسب الحروف الأبجدية", + "already_have_account": "لديك حساب؟", + "always": "دائماً", + "amount": "مقدار:", + "amount_is_estimate": "المبلغ المستلم هو تقدير", + "amount_is_guaranteed": "مبلغ الاستلام مضمون", + "and": "و", + "anonpay_description": "توليد ${type}. يمكن للمستلم ${method} بأي عملة مشفرة مدعومة ، وستتلقى أموالاً في هذه", + "apk_update": "تحديث APK", + "approve": "ﺪﻤﺘﻌﻳ", + "arrive_in_this_address": "سيصل ${currency} ${tag}إلى هذا العنوان", + "ascending": "تصاعدي", + "ask_each_time": "اسأل في كل مرة", "auth_store_ban_timeout": "مهلة_الحظر", "auth_store_banned_for": "محظور ل", "auth_store_banned_minutes": " دقيقة", "auth_store_incorrect_password": "PIN خطأ", - "wallet_store_monero_wallet": "محفظة Monero", - "wallet_restoration_store_incorrect_seed_length": "طول السييد غير صحيح", - "full_balance": "الرصيد الكامل", - "available_balance": "الرصيد المتوفر", - "hidden_balance": "الميزان الخفي", - "sync_status_syncronizing": "يتم المزامنة", - "sync_status_syncronized": "متزامن", - "sync_status_not_connected": "غير متصل", - "sync_status_starting_sync": "بدء المزامنة", - "sync_status_failed_connect": "انقطع الاتصال", - "sync_status_connecting": "يتم التوصيل", - "sync_status_connected": "متصل", - "sync_status_attempting_sync": "جاري محاولة المزامنة", - "transaction_priority_slow": "بطيء", - "transaction_priority_regular": "عادي", - "transaction_priority_medium": "متوسط", - "transaction_priority_fast": "سريع", - "transaction_priority_fastest": "أسرع", - "trade_for_not_created": "لم يتم إنشاء التداول للعنصر ${title}.", - "trade_not_created": "التداول لم ينشأ", - "trade_id_not_found": "تداول ${tradeId} من ${title} غير موجود.", - "trade_not_found": "التداول غير موجودة.", - "trade_state_pending": "قيد الانتظار", - "trade_state_confirming": "جاري التأكيد", - "trade_state_trading": "يتم التداول", - "trade_state_traded": "تم التداول بنجاح", - "trade_state_complete": "اكتمل", - "trade_state_to_be_created": "ليتم انشائه", - "trade_state_unpaid": "غير مدفوعة", - "trade_state_underpaid": "أجر أقل من اللازم", - "trade_state_paid_unconfirmed": "دفع غير مؤكد", - "trade_state_paid": "مدفوع", - "trade_state_btc_sent": "تم أرسل Btc", - "trade_state_timeout": "نفذ الوقت", - "trade_state_created": "تم الأنشاء", - "trade_state_finished": "تم", - "change_language": "تغيير اللغة", - "change_language_to": "هل تريد تغيير اللغة إلى ${language}؟", - "paste": "لصق", - "restore_from_seed_placeholder": "الرجاء إدخال أو لصق السييد الخاصة بك هنا", - "add_new_word": "أضف كلمة جديدة", - "incorrect_seed": "النص الذي تم إدخاله غير صالح.", - "biometric_auth_reason": "امسح بصمة إصبعك للمصادقة", - "version": "الإصدار ${currentVersion}", - "extracted_address_content": "سوف ترسل الأموال إلى\n${recipient_name}", - "card_address": "العنوان:", - "buy": "اشتري", - "sell": "بيع", - "placeholder_transactions": "سيتم عرض معاملاتك هنا", - "placeholder_contacts": "سيتم عرض جهات الاتصال الخاصة بك هنا", - "template": "قالب", - "confirm_delete_template": "سيؤدي هذا الإجراء إلى حذف هذا القالب. هل ترغب في الاستمرار؟", - "confirm_delete_wallet": "سيؤدي هذا الإجراء إلى حذف هذه المحفظة. هل ترغب في الاستمرار؟", - "change_wallet_alert_title": "تغيير المحفظة الحالية", - "change_wallet_alert_content": "هل تريد تغيير المحفظة الحالية إلى ${wallet_name}؟", - "creating_new_wallet": "يتم إنشاء محفظة جديدة", - "creating_new_wallet_error": "خطأ: ${description}", - "seed_alert_title": "انتباه", - "seed_alert_content": "السييد هي الطريقة الوحيدة لاسترداد محفظتك. هل كتبتها؟", - "seed_alert_back": "العودة إلى الوراء", - "seed_alert_yes": "نعم، فعلت ذلك", - "exchange_sync_alert_content": "يرجى الانتظار حتى تتم مزامنة محفظتك", - "pre_seed_title": "مهم", - "pre_seed_description": "في الصفحة التالية ستشاهد سلسلة من الكلمات ${words}. هذه هي سييد الفريدة والخاصة بك وهي الطريقة الوحيدة لاسترداد محفظتك في حالة فقدها أو عطلها. تقع على عاتقك مسؤولية تدوينها وتخزينها في مكان آمن خارج تطبيق Cake Wallet.", - "pre_seed_button_text": "انا أفهم. أرني سييد الخاص بي", - "xmr_to_error": "خطأ XMR.TO", - "xmr_to_error_description": "مبلغ غير صحيح. الحد الأقصى 8 أرقام بعد الفاصلة العشرية", - "provider_error": "خطأ ${provider}", - "use_ssl": "استخدم SSL", - "trusted": "موثوق به", - "color_theme": "سمة اللون", - "light_theme": "فاتح", - "bright_theme": "مشرق", - "dark_theme": "داكن", - "enter_your_note": "أدخل ملاحظتك ...", - "note_optional": "ملاحظة (اختياري)", - "note_tap_to_change": "ملاحظة (انقر للتغيير)", - "view_in_block_explorer": "عرض في Block Explorer", - "view_transaction_on": "عرض العملية على", - "transaction_key": "مفتاح العملية", - "confirmations": "التأكيدات", - "recipient_address": "عنوان المستلم", - "extra_id": "معرف إضافي:", - "destination_tag": "علامة الوجهة:", - "memo": "مذكرة:", - "backup": "نسخ الاحتياطي", - "change_password": "تغيير كلمة المرور", - "backup_password": "كلمة مرور النسخ الاحتياطي", - "write_down_backup_password": "يرجى كتابة كلمة المرور الاحتياطية الخاصة بك ، والتي يتم استخدامها لاستيراد ملفات النسخ الاحتياطي الخاصة بك.", - "export_backup": "تصدير نسخة احتياطية", - "save_backup_password": "يرجى التأكد من حفظ كلمة المرور الاحتياطية. لن تتمكن من استيراد ملفات النسخ الاحتياطي بدونها.", - "backup_file": "ملف النسخ الاحتياطي", - "edit_backup_password": "تعديل كلمة مرور النسخ الاحتياطي", - "save_backup_password_alert": "حفظ كلمة المرور الاحتياطية", - "change_backup_password_alert": "لن تكون ملفات النسخ الاحتياطي السابقة متاحة للاستيراد بكلمة مرور نسخ احتياطي جديدة. سيتم استخدام كلمة مرور النسخ الاحتياطي الجديدة لملفات النسخ الاحتياطي الجديدة فقط. هل أنت متأكد أنك تريد تغيير كلمة المرور الاحتياطية؟", - "enter_backup_password": "أدخل كلمة المرور الاحتياطية هنا", - "select_backup_file": "حدد ملف النسخ الاحتياطي", - "import": "ﺩﺭﻮﺘﺴﻳ", - "please_select_backup_file": "الرجاء تحديد ملف النسخ الاحتياطي وإدخال كلمة مرور النسخ الاحتياطي.", - "fixed_rate": "السعر الثابت", - "fixed_rate_alert": "ستتمكن من إدخال مبلغ الاستلام عند تشغيل وضع السعر الثابت. هل تريد التبديل إلى وضع السعر الثابت؟", - "xlm_extra_info": "من فضلك لا تنس تحديد معرّف المذكرة أثناء إرسال معاملة XLM للتبادل", - "xrp_extra_info": "من فضلك لا تنس تحديد علامة الوجهة أثناء إرسال معاملة XRP للتبادل", - "exchange_incorrect_current_wallet_for_xmr": "إذا كنت ترغب في استبدال XMR من رصيد Cake Wallet Monero ، فيرجى التبديل إلى محفظة Monero أولاً.", - "confirmed": "رصيد مؤكد", - "unconfirmed": "رصيد غير مؤكد", - "displayable": "قابل للعرض", - "submit_request": "تقديم طلب", - "buy_alert_content": ".ﺎﻬﻴﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻭﺃ Monero ﻭﺃ Litecoin ﻭﺃ Ethereum ﻭﺃ Bitcoin ﺔﻈﻔﺤﻣ ءﺎﺸﻧﺇ ﻰﺟﺮﻳ .", - "sell_alert_content": ".ﺎﻬﻴﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻭﺃ Litecoin ﻭﺃ Ethereum ﻭﺃ Bitcoin ﺔﻈﻔﺤﻣ ءﺎﺸﻧﺇ ﻰﺟﺮﻳ .Litecoin ﻭ", - "outdated_electrum_wallet_description": "محافظ Bitcoin الجديدة التي تم إنشاؤها في Cake الآن سييد مكونة من 24 كلمة. من الضروري أن تقوم بإنشاء محفظة Bitcoin جديدة وتحويل جميع أموالك إلى المحفظة الجديدة المكونة من 24 كلمة ، والتوقف عن استخدام محافظ سييد مكونة من 12 كلمة. يرجى القيام بذلك على الفور لتأمين أموالك.", - "understand": "لقد فهمت", - "apk_update": "تحديث APK", - "buy_bitcoin": "شراء Bitcoin", - "buy_with": "اشتر بواسطة", - "moonpay_alert_text": "يجب أن تكون قيمة المبلغ أكبر من أو تساوي ${minAmount} ${fiatCurrency}", - "outdated_electrum_wallet_receive_warning": "إذا كانت هذه المحفظة تحتوي على سييد مكونة من 12 كلمة وتم إنشاؤها في Cake ، فلا تقم بإيداع Bitcoin في هذه المحفظة. قد يتم فقد أي BTC تم تحويله إلى هذه المحفظة. قم بإنشاء محفظة جديدة مكونة من 24 كلمة (انقر فوق القائمة في الجزء العلوي الأيمن ، وحدد محافظ ، واختر إنشاء محفظة جديدة ، ثم حدد Bitcoin) وقم على الفور بنقل BTC الخاص بك هناك. محافظ BTC الجديدة (24 كلمة) من Cake آمنة", - "do_not_show_me": "لا ترني هذا مجددا", - "unspent_coins_title": "العملات الغير المنفقة", - "unspent_coins_details_title": "تفاصيل العملات الغير المنفقة", - "freeze": "تجميد", - "frozen": "مجمدة", - "coin_control": "التحكم في العملة (اختياري)", - "address_detected": "تم ايجاد العنوان", - "address_from_domain": "هذا العنوان من ${domain} من Unstoppable Domains", - "add_receiver": "أضف مستقبل آخر (اختياري)", - "manage_yats": "إدارة Yats", - "yat_alert_title": "أرسل واستقبل العملات المشفرة بسهولة أكبر مع Yat", - "yat_alert_content": "يمكن لمستخدمي Cake Wallet الآن إرسال واستلام جميع عملاتهم المفضلة باستخدام اسم مستخدم فريد من نوعه قائم على الرموز التعبيرية.", - "get_your_yat": "احصل على Yat", - "connect_an_existing_yat": "توصيل Yat الحالي", - "connect_yats": "توصيل Yats", - "yat_address": "عنوان Yat", - "yat": "Yat", - "address_from_yat": "هذا العنوان من ${emoji} على Yat", - "yat_error": "خطأ Yat", - "yat_error_content": "لا توجد عناوين مرتبطة بهذا Yat. جرب يات آخر", - "choose_address": "\n\nالرجاء اختيار عنوان:", - "yat_popup_title": "يمكن تحويل عنوان محفظتك إلى رموز تعبيرية.", - "yat_popup_content": "يمكنك الآن إرسال واستلام العملات المشفرة في Cake Wallet باستخدام Yat - اسم مستخدم قصير يعتمد على الرموز التعبيرية. إدارة Yats في أي وقت على شاشة الإعدادات", - "second_intro_title": "عنوان تعبيري ايموجي واحد يحكمهم جميعا!", - "second_intro_content": "Yat الخاص بك هو عنوان تعبيري فريد يحل محل جميع العناوين السداسية العشرية الطويلة لجميع عملاتك.", - "third_intro_title": "يتماشي Yat بلطف مع الآخرين", - "third_intro_content": "يعيش Yats خارج Cake Wallet أيضًا. يمكن استبدال أي عنوان محفظة على وجه الأرض بـ Yat!", - "learn_more": "اعرف المزيد", - "search": "بحث", - "search_language": "ابحث عن لغة", - "search_currency": "ابحث عن عملة", - "new_template": "قالب جديد", - "electrum_address_disclaimer": "نقوم بإنشاء عناوين جديدة في كل مرة تستخدم فيها عنوانًا ، لكن العناوين السابقة تستمر في العمل", - "wallet_name_exists": "توجد بالفعل محفظة بهذا الاسم. الرجاء اختيار اسم مختلف أو إعادة تسمية المحفظة الأخرى أولاً.", - "market_place": "منصة التجارة", - "cake_pay_title": "بطاقات هدايا Cake Pay", - "cake_pay_subtitle": "شراء بطاقات هدايا مخفضة السعر (الولايات المتحدة فقط)", - "cake_pay_web_cards_title": "بطاقات Cake Pay Web", - "cake_pay_web_cards_subtitle": "اشتري بطاقات مدفوعة مسبقا وبطاقات هدايا في جميع أنحاء العالم", - "about_cake_pay": "يتيح لك Cake Pay شراء بطاقات هدايا بأصول افتراضية بسهولة ، ويمكن إنفاقها على الفور لدى أكثر من 150,000 تاجر في الولايات المتحدة.", - "cake_pay_account_note": "قم بالتسجيل باستخدام عنوان بريد إلكتروني فقط لمشاهدة البطاقات وشرائها. حتى أن بعضها متوفر بسعر مخفض!", - "already_have_account": "لديك حساب؟", - "create_account": "إنشاء حساب", - "privacy_policy": "سياسة الخصوصية", - "welcome_to_cakepay": "مرحبا بكم في Cake Pay!", - "sign_up": "اشتراك", - "forgot_password": "هل نسيت كلمة السر", - "reset_password": "إعادة تعيين كلمة المرور", - "gift_cards": "بطاقات الهدايا", - "setup_your_debit_card": "قم بإعداد بطاقة ائتمان الخاصة بك", - "no_id_required": "لا ID مطلوب. اشحن وانفق في أي مكان", - "how_to_use_card": "كيفية استخدام هذه البطاقة", - "purchase_gift_card": "شراء بطاقة هدايا", - "verification": "تَحَقّق", - "fill_code": "يرجى ملء رمز التحقق المرسل إلى بريدك الإلكتروني", - "didnt_get_code": "لم تحصل على رمز؟", - "resend_code": "الرجاء إعادة إرسالها", - "debit_card": "بطاقة ائتمان", - "cakepay_prepaid_card": "بطاقة ائتمان CakePay مسبقة الدفع", - "no_id_needed": "لا حاجة لID!", - "frequently_asked_questions": "الأسئلة الشائعة", - "debit_card_terms": "يخضع تخزين واستخدام رقم بطاقة الدفع الخاصة بك (وبيانات الاعتماد المقابلة لرقم بطاقة الدفع الخاصة بك) في هذه المحفظة الرقمية لشروط وأحكام اتفاقية حامل البطاقة المعمول بها مع جهة إصدار بطاقة الدفع ، كما هو معمول به من وقت لآخر.", - "please_reference_document": "يرجى الرجوع إلى الوثائق أدناه لمزيد من المعلومات.", - "cardholder_agreement": "اتفاقية حامل البطاقة", - "e_sign_consent": "الموافقة على التوقيع الإلكتروني", - "agree_and_continue": "الموافقة ومتابعة", - "email_address": "عنوان البريد الالكترونى", - "agree_to": "من خلال إنشاء حساب فإنك توافق على", - "and": "و", - "enter_code": "ادخل الرمز", - "congratulations": "تهانينا!", - "you_now_have_debit_card": "لديك الآن بطاقة ائتمان", - "min_amount": "الحد الأدنى: ${value}", - "max_amount": "الحد الأقصى: ${value}", - "enter_amount": "أدخل المبلغ", - "billing_address_info": "إذا طُلب منك عنوان إرسال فواتير ، فأدخل عنوان الشحن الخاص بك", - "order_physical_card": "طلب البطاقة المادية", - "add_value": "إضافة قيمة", - "activate": "تفعيل", - "get_a": "احصل على", - "digital_and_physical_card": " بطاقة ائتمان رقمية ومادية مسبقة الدفع", - "get_card_note": " يمكنك إعادة تحميلها بالعملات الرقمية. لا توجد معلومات إضافية مطلوبة!", - "signup_for_card_accept_terms": "قم بالتسجيل للحصول على البطاقة وقبول الشروط.", - "add_fund_to_card": "أضف أموالاً مدفوعة مسبقًا إلى البطاقات (حتى ${value})", - "use_card_info_two": "يتم تحويل الأموال إلى الدولار الأمريكي عند الاحتفاظ بها في الحساب المدفوع مسبقًا ، وليس بالعملات الرقمية.", - "use_card_info_three": "استخدم البطاقة الرقمية عبر الإنترنت أو مع طرق الدفع غير التلامسية.", - "optionally_order_card": "اختياريا اطلب بطاقة فعلية (مادية).", - "hide_details": "أخف التفاصيل", - "show_details": "اظهر التفاصيل", - "upto": "حتى ${value}", - "discount": "وفر ${value}٪", - "gift_card_amount": "مبلغ بطاقة الهدايا", - "bill_amount": "مبلغ الفاتورة", - "you_pay": "انت تدفع", - "tip": "بقشيش:", - "custom": "مخصصة", - "by_cake_pay": "عن طريق Cake Pay", - "expires": "تنتهي", - "mm": "MM", - "yy": "YY", - "online": "متصل", - "offline": "غير متصل على الانترنت", - "gift_card_number": "رقم بطاقة الهدية", - "pin_number": "الرقم السري", - "total_saving": "إجمالي المدخرات", - "last_30_days": "آخر 30 يومًا", - "avg_savings": "متوسط مدخرات", - "view_all": "مشاهدة الكل", - "active_cards": "البطاقات النشطة", - "delete_account": "حذف الحساب", - "cards": "البطاقات", - "active": "نشيط", - "redeemed": "استردت", - "gift_card_balance_note": "ستظهر هنا بطاقات الهدايا ذات الرصيد المتبقي", - "gift_card_redeemed_note": "ستظهر هنا بطاقات الهدايا التي استردت قيمتها", - "logout": "تسجيل خروج", - "add_tip": "أضف بقشيش", - "percentageOf": "من ${amount}", - "is_percentage": "يكون", - "search_category": "فئة البحث", - "mark_as_redeemed": "وضع علامة كمسترد", - "more_options": "المزيد من الخيارات", - "awaiting_payment_confirmation": "في انتظار تأكيد الدفع", - "transaction_sent_notice": "إذا لم تستمر الشاشة بعد دقيقة واحدة ، فتحقق من مستكشف البلوك والبريد الإلكتروني.", - "agree": "موافق", - "in_store": "في المتجر", - "generating_gift_card": "يتم توليد بطاقة هدية", - "payment_was_received": "تم استلام الدفع الخاص بك.", - "proceed_after_one_minute": "إذا لم تستمر الشاشة بعد دقيقة واحدة ، فتحقق من بريدك الإلكتروني.", - "order_id": "رقم التعريف الخاص بالطلب", - "gift_card_is_generated": "تم إنشاء بطاقة الهدايا", - "open_gift_card": "افتح بطاقة الهدية", - "contact_support": "اتصل بالدعم", - "gift_cards_unavailable": "تتوفر بطاقات الهدايا للشراء فقط باستخدام Monero و Bitcoin و Litecoin في الوقت الحالي", - "introducing_cake_pay": "نقدم لكم Cake Pay!", - "cake_pay_learn_more": "شراء واسترداد بطاقات الهدايا على الفور في التطبيق!\nاسحب من اليسار إلى اليمين لمعرفة المزيد.", + "authenticated": "تم المصادقة", + "authentication": "المصادقة", + "auto_generate_subaddresses": "تلقائي توليد subddresses", "automatic": "تلقائي", - "fixed_pair_not_supported": "هذا الزوج الثابت غير مدعوم في التبادلات المحددة", - "variable_pair_not_supported": "هذا الزوج المتغير غير مدعوم في التبادلات المحددة", - "none_of_selected_providers_can_exchange": "لا يمكن لأي من مقدمي الخدمة المختارين إجراء هذا التبادل", - "choose_one": "اختر واحدة", - "choose_from_available_options": "اختر من بين الخيارات المتاحة:", - "custom_redeem_amount": "مبلغ الاسترداد مخصص", - "add_custom_redemption": "إضافة استرداد مخصص", - "remaining": "متبقي", - "delete_wallet": "حذف المحفظة", - "delete_wallet_confirm_message": "هل أنت متأكد أنك تريد حذف محفظة ${wallet_name}؟", - "low_fee": "رسوم منخفضة", - "low_fee_alert": "أنت تستخدم حاليًا أولوية منخفضة لرسوم الشبكة. قد يتسبب هذا في فترات انتظار طويلة ، أو أسعار مختلفة ، أو إلغاء صفقات. نوصي بتحديد رسوم أعلى لتجربة أفضل.", - "ignor": "تجاهل", - "use_suggested": "استخدام المقترح", - "do_not_share_warning_text": "لا تشارك هذه مع أي شخص آخر ، بما في ذلك الدعم.\n\nيمكن أن تتم سرقة أموالك!", - "help": "مساعده", - "all_transactions": "كل التحركات المالية", - "all_trades": "جميع عمليات التداول", - "connection_sync": "الاتصال والمزامنة", - "security_and_backup": "الأمان والنسخ الاحتياطي", - "create_backup": "انشئ نسخة احتياطية", - "privacy_settings": "إعدادات الخصوصية", - "privacy": "خصوصية", - "display_settings": "اعدادات العرض", - "other_settings": "اعدادات اخرى", - "require_pin_after": "طلب PIN بعد", - "always": "دائماً", - "minutes_to_pin_code": "${minutes} دقيقة", - "disable_exchange": "تعطيل التبادل", - "advanced_settings": "إعدادات متقدمة", - "settings_can_be_changed_later": "يمكن تغيير هذه الإعدادات لاحقًا في إعدادات التطبيق", - "add_custom_node": "إضافة عقدة مخصصة جديدة", - "disable_fiat": "تعطيل fiat", - "fiat_api": "Fiat API", - "disabled": "معطلة", - "enabled": "ممكنة", - "tor_only": "Tor فقط", - "unmatched_currencies": "عملة محفظتك الحالية لا تتطابق مع عملة QR الممسوحة ضوئيًا", - "orbot_running_alert": "يرجى التأكد من تشغيل Orbot قبل الاتصال بهذه العقدة.", - "bitcoin_payments_require_1_confirmation": "تتطلب مدفوعات Bitcoin تأكيدًا واحدًا ، والذي قد يستغرق 20 دقيقة أو أكثر. شكرا لصبرك! سيتم إرسال بريد إلكتروني إليك عند تأكيد الدفع.", - "send_to_this_address": "أرسل ${currency} ${tag}إلى هذا العنوان", - "arrive_in_this_address": "سيصل ${currency} ${tag}إلى هذا العنوان", - "do_not_send": "لا ترسل", - "error_dialog_content": "عفوًا ، لقد حصلنا على بعض الخطأ.\n\nيرجى إرسال تقرير التعطل إلى فريق الدعم لدينا لتحسين التطبيق.", - "scan_qr_code": "امسح رمز QR ضوئيًا", - "cold_or_recover_wallet": "أضف محفظة باردة أو استعد محفظة ورقية", - "please_wait": "انتظر من فضلك", - "sweeping_wallet": "كنس المحفظة", - "sweeping_wallet_alert": "لن يستغرق هذا وقتًا طويلاً. لا تترك هذه الشاشة وإلا فقد يتم فقد أموال سويبت", - "decimal_places_error": "عدد كبير جدًا من المنازل العشرية", - "edit_node": "تحرير العقدة", - "invoice_details": "تفاصيل الفاتورة", - "donation_link_details": "تفاصيل رابط التبرع", - "anonpay_description": "توليد ${type}. يمكن للمستلم ${method} بأي عملة مشفرة مدعومة ، وستتلقى أموالاً في هذه", - "create_invoice": "إنشاء فاتورة", - "create_donation_link": "إنشاء رابط التبرع", - "optional_email_hint": "البريد الإلكتروني إخطار المدفوع لأمره الاختياري", - "optional_description": "وصف اختياري", - "optional_name": "اسم المستلم الاختياري", - "clearnet_link": "رابط Clearnet", - "onion_link": "رابط البصل", - "settings": "إعدادات", - "sell_monero_com_alert_content": "بيع Monero غير مدعوم حتى الآن", - "error_text_input_below_minimum_limit": " المبلغ أقل من الحد الأدنى", - "error_text_input_above_maximum_limit": "المبلغ أكبر من الحد الأقصى", - "show_market_place": "إظهار السوق", - "prevent_screenshots": "منع لقطات الشاشة وتسجيل الشاشة", - "profile": "حساب تعريفي", - "close": "يغلق", - "modify_2fa": "تعديل 2 عامل المصادقة", - "disable_cake_2fa": "تعطيل 2 عامل المصادقة", - "question_to_disable_2fa": "هل أنت متأكد أنك تريد تعطيل Cake 2FA؟ لن تكون هناك حاجة إلى رمز 2FA للوصول إلى المحفظة ووظائف معينة.", - "disable": "إبطال", - "setup_2fa": "تعيين 2 عامل المصادقة", - "verify_with_2fa": "تحقق مع Cake 2FA", - "totp_code": "كود TOTP", - "please_fill_totp": "يرجى ملء الرمز المكون من 8 أرقام الموجود على جهازك الآخر", - "totp_2fa_success": "نجاح! تم تمكين Cake 2FA لهذه المحفظة. تذكر حفظ بذرة ذاكري في حالة فقد الوصول إلى المحفظة.", - "totp_verification_success": "تم التحقق بنجاح!", - "totp_2fa_failure": "شفرة خاطئة. يرجى تجربة رمز مختلف أو إنشاء مفتاح سري جديد. استخدم تطبيق 2FA متوافقًا يدعم الرموز المكونة من 8 أرقام و SHA512.", - "enter_totp_code": "الرجاء إدخال رمز TOTP.", - "add_secret_code": " ﺔﻗﺩﺎﺼﻤﻟﺍ ﻖﻴﺒﻄﺗ ﻰﻟﺇ ﻱﺮﺴﻟﺍ ﺰﻣﺮﻟﺍ ﺍﺬﻫ ﻒﺿﺃ ﻭﺃ", - "totp_secret_code": "كود TOTP السري", - "setup_2fa_text": " .ﻲﻧﺎﺜﻟﺍ ﺔﻗﺩﺎﺼﻤﻟﺍ ﻞﻣﺎﻌﻛ TOTP ﻡﺍﺪﺨﺘﺳﺎﺑ Cake 2FA ﻞﻤﻌﻳ", - "setup_totp_recommended": " TOTP ﺩﺍﺪﻋﺇ", - "disable_buy": "تعطيل إجراء الشراء", - "disable_sell": "قم بتعطيل إجراء البيع", - "cake_2fa_preset": " كعكة 2FA مسبقا", - "narrow": "ضيق", - "normal": "طبيعي", - "aggressive": "عنيف", - "require_for_assessing_wallet": "تتطلب الوصول إلى المحفظة", - "require_for_sends_to_non_contacts": "تتطلب لارسال لغير جهات الاتصال", - "require_for_sends_to_contacts": "تتطلب لارسال جهات الاتصال", - "require_for_sends_to_internal_wallets": "تتطلب عمليات الإرسال إلى المحافظ الداخلية", - "require_for_exchanges_to_internal_wallets": "تتطلب عمليات التبادل إلى المحافظ الداخلية", - "require_for_adding_contacts": "تتطلب إضافة جهات اتصال", - "require_for_creating_new_wallets": "تتطلب إنشاء محافظ جديدة", - "require_for_all_security_and_backup_settings": "مطلوب لجميع إعدادات الأمان والنسخ الاحتياطي", + "available_balance": "الرصيد المتوفر", "available_balance_description": "الرصيد المتاح هو الرصيد الذي يمكنك إنفاقه أو تحويله إلى محفظة أخرى. يتم تجميد الرصيد المتاح للمعاملات الصادرة والمعاملات الواردة غير المؤكدة.", - "syncing_wallet_alert_title": "محفظتك تتم مزامنتها", - "syncing_wallet_alert_content": "قد لا يكتمل رصيدك وقائمة المعاملات الخاصة بك حتى تظهر عبارة “SYNCHRONIZED“ في الأعلى. انقر / اضغط لمعرفة المزيد.", - "home_screen_settings": "إعدادات الشاشة الرئيسية", - "sort_by": "ترتيب حسب", - "search_add_token": "بحث / إضافة رمز", - "edit_token": "تحرير الرمز المميز", - "warning": "تحذير", - "add_token_warning": "لا تقم بتحرير أو إضافة رموز وفقًا لتعليمات المحتالين.\nقم دائمًا بتأكيد عناوين الرموز مع مصادر حسنة السمعة!", - "add_token_disclaimer_check": "لقد قمت بتأكيد عنوان ومعلومات عقد الرمز المميز باستخدام مصدر حسن السمعة. يمكن أن تؤدي إضافة معلومات خبيثة أو غير صحيحة إلى خسارة الأموال.", - "token_contract_address": "عنوان عقد الرمز", - "token_name": "اسم الرمز ، على سبيل المثال: Tether", - "token_symbol": "رمز العملة ، على سبيل المثال: USDT", - "token_decimal": "رمز عشري", - "field_required": "هذه الخانة مطلوبه", - "pin_at_top": "تثبيت ${token} في الأعلى", - "invalid_input": "مدخل غير صالح", - "fiat_balance": "الرصيد فيات", - "gross_balance": "إجمالي الرصيد", - "alphabetical": "مرتب حسب الحروف الأبجدية", - "generate_name": "توليد الاسم", + "avg_savings": "متوسط مدخرات", + "awaitDAppProcessing": ".ﺔﺠﻟﺎﻌﻤﻟﺍ ﻦﻣ dApp ﻲﻬﺘﻨﻳ ﻰﺘﺣ ﺭﺎﻈﺘﻧﻻﺍ ﻰﺟﺮﻳ", + "awaiting_payment_confirmation": "في انتظار تأكيد الدفع", + "backup": "نسخ الاحتياطي", + "backup_file": "ملف النسخ الاحتياطي", + "backup_password": "كلمة مرور النسخ الاحتياطي", "balance_page": "صفحة التوازن", - "share": "يشارك", - "slidable": "قابل للانزلاق", - "monero_dark_theme": "موضوع مونيرو الظلام", + "bill_amount": "مبلغ الفاتورة", + "billing_address_info": "إذا طُلب منك عنوان إرسال فواتير ، فأدخل عنوان الشحن الخاص بك", + "biometric_auth_reason": "امسح بصمة إصبعك للمصادقة", "bitcoin_dark_theme": "موضوع البيتكوين الظلام", "bitcoin_light_theme": "موضوع البيتكوين الخفيفة", - "high_contrast_theme": "موضوع عالي التباين", - "matrix_green_dark_theme": "موضوع ماتريكس الأخضر الداكن", - "monero_light_theme": " ضوء مونيرو", - "etherscan_history": "Etherscan تاريخ", - "template_name": "اسم القالب", + "bitcoin_payments_require_1_confirmation": "تتطلب مدفوعات Bitcoin تأكيدًا واحدًا ، والذي قد يستغرق 20 دقيقة أو أكثر. شكرا لصبرك! سيتم إرسال بريد إلكتروني إليك عند تأكيد الدفع.", + "Blocks_remaining": "بلوك متبقي ${status}", + "bright_theme": "مشرق", + "buy": "اشتري", + "buy_alert_content": ".ﺎﻬﻴﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻭﺃ Monero ﻭﺃ Litecoin ﻭﺃ Ethereum ﻭﺃ Bitcoin ﺔﻈﻔﺤﻣ ءﺎﺸﻧﺇ ﻰﺟﺮﻳ .", + "buy_bitcoin": "شراء Bitcoin", + "buy_provider_unavailable": "مزود حاليا غير متوفر.", + "buy_with": "اشتر بواسطة", + "by_cake_pay": "عن طريق Cake Pay", + "cake_2fa_preset": " كعكة 2FA مسبقا", + "cake_pay_account_note": "قم بالتسجيل باستخدام عنوان بريد إلكتروني فقط لمشاهدة البطاقات وشرائها. حتى أن بعضها متوفر بسعر مخفض!", + "cake_pay_learn_more": "شراء واسترداد بطاقات الهدايا على الفور في التطبيق!\nاسحب من اليسار إلى اليمين لمعرفة المزيد.", + "cake_pay_subtitle": "شراء بطاقات هدايا مخفضة السعر (الولايات المتحدة فقط)", + "cake_pay_title": "بطاقات هدايا Cake Pay", + "cake_pay_web_cards_subtitle": "اشتري بطاقات مدفوعة مسبقا وبطاقات هدايا في جميع أنحاء العالم", + "cake_pay_web_cards_title": "بطاقات Cake Pay Web", + "cake_wallet": "Cake Wallet", + "cakepay_prepaid_card": "بطاقة ائتمان CakePay مسبقة الدفع", + "camera_consent": ".ﻞﻴﺻﺎﻔﺘﻟﺍ ﻰﻠﻋ ﻝﻮﺼﺤﻠﻟ ﻢﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺔﻴﺻﻮﺼﺨﻟﺍ ﺔﺳﺎﻴﺳ ﻦﻣ ﻖﻘﺤﺘﻟﺍ ﻰﺟﺮﻳ .${provider} ﻝﻮﻠ", + "camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ", + "cancel": "إلغاء", + "card_address": "العنوان:", + "cardholder_agreement": "اتفاقية حامل البطاقة", + "cards": "البطاقات", + "chains": "ﻞﺳﻼﺴﻟﺍ", + "change": "تغير", + "change_backup_password_alert": "لن تكون ملفات النسخ الاحتياطي السابقة متاحة للاستيراد بكلمة مرور نسخ احتياطي جديدة. سيتم استخدام كلمة مرور النسخ الاحتياطي الجديدة لملفات النسخ الاحتياطي الجديدة فقط. هل أنت متأكد أنك تريد تغيير كلمة المرور الاحتياطية؟", + "change_currency": "تغيير العملة", + "change_current_node": "هل أنت متأكد من تغيير العقدة الحالية إلى ${node}؟", + "change_current_node_title": "تغيير العقدة الحالية", + "change_exchange_provider": "تغيير مزود الصرف", + "change_language": "تغيير اللغة", + "change_language_to": "هل تريد تغيير اللغة إلى ${language}؟", + "change_password": "تغيير كلمة المرور", "change_rep": "ﺏﻭﺪﻨﻣ ﺮﻴﻴﻐﺗ", "change_rep_message": "؟ﻦﻴﻠﺜﻤﻤﻟﺍ ﺮﻴﻴﻐﺗ ﺪﻳﺮﺗ ﻚﻧﺃ ﺪﻛﺄﺘﻣ ﺖﻧﺃ ﻞﻫ", - "manage_nodes": "ﺪﻘﻌﻟﺍ ﺓﺭﺍﺩﺇ", - "unsupported_asset": ".ﻡﻮﻋﺪﻣ ﻞﺻﺃ ﻉﻮﻧ ﻦﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻭﺃ ءﺎﺸﻧﺇ ﻰﺟﺮﻳ .ﻞﺻﻷﺍ ﺍﺬﻬﻟ ءﺍﺮﺟﻹﺍ ﺍﺬﻫ ﻢﻋﺪﻧ ﻻ ﻦﺤﻧ", - "manage_pow_nodes": "PoW ﻁﺎﻘﻧ ﺓﺭﺍﺩﺇ", - "support_title_live_chat": "الدعم المباشر", - "support_description_live_chat": "حرة وسريعة! ممثلو الدعم المدربين متاحون للمساعدة", - "support_title_guides": "أدلة محفظة كعكة", - "support_description_guides": "توثيق ودعم القضايا المشتركة", - "support_title_other_links": "روابط دعم أخرى", - "support_description_other_links": "انضم إلى مجتمعاتنا أو تصل إلينا شركائنا من خلال أساليب أخرى", + "change_rep_successful": "تم تغيير ممثل بنجاح", + "change_wallet_alert_content": "هل تريد تغيير المحفظة الحالية إلى ${wallet_name}؟", + "change_wallet_alert_title": "تغيير المحفظة الحالية", + "choose_account": "اختر حساب", + "choose_address": "\n\nالرجاء اختيار عنوان:", "choose_derivation": "اختر اشتقاق المحفظة", - "new_first_wallet_text": "حافظ بسهولة على أمان العملة المشفرة", - "select_destination": ".ﻲﻃﺎﻴﺘﺣﻻﺍ ﺦﺴﻨﻟﺍ ﻒﻠﻣ ﺔﻬﺟﻭ ﺪﻳﺪﺤﺗ ءﺎﺟﺮﻟﺍ", - "auto_generate_subaddresses": "تلقائي توليد subddresses", - "save_to_downloads": "ﺕﻼﻳﺰﻨﺘﻟﺍ ﻲﻓ ﻆﻔﺣ", - "select_buy_provider_notice": "حدد مزود شراء أعلاه. يمكنك تخطي هذه الشاشة عن طريق تعيين مزود شراء الافتراضي في إعدادات التطبيق.", - "onramper_option_description": "شراء بسرعة التشفير مع العديد من طرق الدفع. متوفر في معظم البلدان. ينتشر وتختلف الرسوم.", + "choose_from_available_options": "اختر من بين الخيارات المتاحة:", + "choose_one": "اختر واحدة", + "choose_relay": "ﻡﺍﺪﺨﺘﺳﻼﻟ ﻊﺑﺎﺘﺘﻟﺍ ﺭﺎﻴﺘﺧﺍ ءﺎﺟﺮﻟﺍ", + "choose_wallet_currency": "الرجاء اختيار عملة المحفظة:", + "clear": "مسح", + "clearnet_link": "رابط Clearnet", + "close": "يغلق", + "coin_control": "التحكم في العملة (اختياري)", + "cold_or_recover_wallet": "أضف محفظة باردة أو استعد محفظة ورقية", + "color_theme": "سمة اللون", + "commit_transaction_amount_fee": "تنفيذ الصفقة\nالمبلغ: ${amount}\nالرسوم: ${fee}", + "confirm": "تأكيد", + "confirm_delete_template": "سيؤدي هذا الإجراء إلى حذف هذا القالب. هل ترغب في الاستمرار؟", + "confirm_delete_wallet": "سيؤدي هذا الإجراء إلى حذف هذه المحفظة. هل ترغب في الاستمرار؟", + "confirm_sending": "تأكيد الإرسال", + "confirmations": "التأكيدات", + "confirmed": "رصيد مؤكد", + "confirmed_tx": "مؤكد", + "congratulations": "تهانينا!", + "connect_an_existing_yat": "توصيل Yat الحالي", + "connect_yats": "توصيل Yats", + "connection_sync": "الاتصال والمزامنة", + "connectWalletPrompt": "ﺕﻼﻣﺎﻌﻤﻟﺍ ءﺍﺮﺟﻹ WalletConnect ﻊﻣ ﻚﺘﻈﻔﺤﻣ ﻞﻴﺻﻮﺘﺑ ﻢﻗ", + "contact": "تواصل", + "contact_name": "اسم جهة الاتصال", + "contact_support": "اتصل بالدعم", + "continue_text": "التالي", + "contractName": "ﺪﻘﻌﻟﺍ ﻢﺳﺍ", + "contractSymbol": "ﺪﻘﻌﻟﺍ ﺰﻣﺭ", + "copied_key_to_clipboard": "تم نسخ ${key} إلى الحافظة", + "copied_to_clipboard": "نسخ إلى الحافظة", + "copy": "نسخ", + "copy_address": "نسخ العنوان", + "copy_id": "نسخ معرف العملية", + "copyWalletConnectLink": "ﺎﻨﻫ ﻪﻘﺼﻟﺍﻭ dApp ﻦﻣ WalletConnect ﻂﺑﺍﺭ ﺦﺴﻧﺍ", + "create_account": "إنشاء حساب", + "create_backup": "انشئ نسخة احتياطية", + "create_donation_link": "إنشاء رابط التبرع", + "create_invoice": "إنشاء فاتورة", + "create_new": "إنشاء محفظة جديدة", + "create_new_account": "انشاء حساب جديد", + "creating_new_wallet": "يتم إنشاء محفظة جديدة", + "creating_new_wallet_error": "خطأ: ${description}", + "creation_date": "تاريخ الإنشاء", + "custom": "مخصصة", + "custom_drag": "مخصص (عقد وسحب)", + "custom_redeem_amount": "مبلغ الاسترداد مخصص", + "dark_theme": "داكن", + "debit_card": "بطاقة ائتمان", + "debit_card_terms": "يخضع تخزين واستخدام رقم بطاقة الدفع الخاصة بك (وبيانات الاعتماد المقابلة لرقم بطاقة الدفع الخاصة بك) في هذه المحفظة الرقمية لشروط وأحكام اتفاقية حامل البطاقة المعمول بها مع جهة إصدار بطاقة الدفع ، كما هو معمول به من وقت لآخر.", + "decimal_places_error": "عدد كبير جدًا من المنازل العشرية", "default_buy_provider": "مزود شراء الافتراضي", - "ask_each_time": "اسأل في كل مرة", - "buy_provider_unavailable": "مزود حاليا غير متوفر.", - "signTransaction": " ﺔﻠﻣﺎﻌﻤﻟﺍ ﻊﻴﻗﻮﺗ", + "default_sell_provider": "ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ", + "delete": "حذف", + "delete_account": "حذف الحساب", + "delete_wallet": "حذف المحفظة", + "delete_wallet_confirm_message": "هل أنت متأكد أنك تريد حذف محفظة ${wallet_name}؟", + "deleteConnectionConfirmationPrompt": "ـﺑ ﻝﺎﺼﺗﻻﺍ ﻑﺬﺣ ﺪﻳﺮﺗ ﻚﻧﺃ ﺪﻛﺄﺘﻣ ﺖﻧﺃ ﻞﻫ", + "descending": "النزول", + "description": "ﻒﺻﻭ", + "destination_tag": "علامة الوجهة:", + "dfx_option_description": "ﺎﺑﻭﺭﻭﺃ ﻲﻓ ﺕﺎﻛﺮﺸﻟﺍﻭ ﺔﺋﺰﺠﺘﻟﺍ ءﻼﻤﻌﻟ .ﻲﻓﺎﺿﺇ KYC ﻥﻭﺪﺑ ﻭﺭﻮﻳ 990 ﻰﻟﺇ ﻞﺼﻳ ﺎﻣ .ﻱﺮﺴﻳﻮﺴﻟﺍ", + "didnt_get_code": "لم تحصل على رمز؟", + "digit_pin": "-رقم PIN", + "digital_and_physical_card": " بطاقة ائتمان رقمية ومادية مسبقة الدفع", + "disable": "إبطال", + "disable_buy": "تعطيل إجراء الشراء", + "disable_cake_2fa": "تعطيل 2 عامل المصادقة", + "disable_exchange": "تعطيل التبادل", + "disable_fiat": "تعطيل fiat", + "disable_sell": "قم بتعطيل إجراء البيع", + "disabled": "معطلة", + "discount": "وفر ${value}٪", + "display_settings": "اعدادات العرض", + "displayable": "قابل للعرض", + "do_not_have_enough_gas_asset": "ليس لديك ما يكفي من ${currency} لإجراء معاملة وفقًا لشروط شبكة blockchain الحالية. أنت بحاجة إلى المزيد من ${currency} لدفع رسوم شبكة blockchain، حتى لو كنت ترسل أصلًا مختلفًا.", + "do_not_send": "لا ترسل", + "do_not_share_warning_text": "لا تشارك هذه مع أي شخص آخر ، بما في ذلك الدعم.\n\nيمكن أن تتم سرقة أموالك!", + "do_not_show_me": "لا ترني هذا مجددا", + "domain_looks_up": "ﻝﺎﺠﻤﻟﺍ ﺚﺤﺑ ﺕﺎﻴﻠﻤﻋ", + "donation_link_details": "تفاصيل رابط التبرع", + "e_sign_consent": "الموافقة على التوقيع الإلكتروني", + "edit": "تعديل", + "edit_backup_password": "تعديل كلمة مرور النسخ الاحتياطي", + "edit_node": "تحرير العقدة", + "edit_token": "تحرير الرمز المميز", + "electrum_address_disclaimer": "نقوم بإنشاء عناوين جديدة في كل مرة تستخدم فيها عنوانًا ، لكن العناوين السابقة تستمر في العمل", + "email_address": "عنوان البريد الالكترونى", + "enabled": "ممكنة", + "enter_amount": "أدخل المبلغ", + "enter_backup_password": "أدخل كلمة المرور الاحتياطية هنا", + "enter_code": "ادخل الرمز", + "enter_seed_phrase": "أدخل عبارة البذور الخاصة بك", + "enter_totp_code": "الرجاء إدخال رمز TOTP.", + "enter_your_note": "أدخل ملاحظتك ...", + "enter_your_pin": "أدخل كود الرقم السري", + "enter_your_pin_again": "أدخل PIN الخاص بك مرة أخرى", + "enterTokenID": "ﺰﻴﻤﻤﻟﺍ ﺰﻣﺮﻟﺍ ﻑﺮﻌﻣ ﻞﺧﺩﺃ", + "enterWalletConnectURI": "WalletConnect ـﻟ URI ﻞﺧﺩﺃ", + "error": "خطأ", + "error_dialog_content": "عفوًا ، لقد حصلنا على بعض الخطأ.\n\nيرجى إرسال تقرير التعطل إلى فريق الدعم لدينا لتحسين التطبيق.", + "error_text_account_name": "يجب أن يحتوي اسم الحساب على أحرف وأرقام فقط\nويجب أن يتراوح بين حرف واحد و 15 حرفًا", + "error_text_address": "يجب أن يتوافق عنوان المحفظة مع نوع\nالعملة المشفرة", + "error_text_amount": "يجب أن يحتوي المبلغ على أرقام فقط", + "error_text_contact_name": "لا يمكن أن يحتوي اسم جهة الاتصال على الرموز ` , ' \"\nويجب أن يتراوح بين حرف و 32 حرفًا", + "error_text_crypto_currency": "عدد الكسور\nيجب أن تكون أقل من أو تساوي 12", + "error_text_fiat": "لا يمكن أن تتجاوز قيمة المبلغ الرصيد المتاح.\nيجب أن يكون عدد الكسور أقل أو يساوي 2", + "error_text_input_above_maximum_limit": "المبلغ أكبر من الحد الأقصى", + "error_text_input_below_minimum_limit": " المبلغ أقل من الحد الأدنى", + "error_text_keys": "يمكن أن تحتوي مفاتيح المحفظة على 64 حرفًا hex", + "error_text_limits_loading_failed": "لم يتم إنشاء الصفقة لـ ${provider}. فشل تحميل الحدود", + "error_text_maximum_limit": "لم يتم إنشاء الصفقة لـ ${provider}. المبلغ أكبر من الحد الأقصى: ${max} ${currency}", + "error_text_minimal_limit": "لم يتم إنشاء الصفقة لـ ${provider}. المبلغ أقل من الحد الأدنى: ${min} ${currency}", + "error_text_node_address": "الرجاء إدخال عنوان IPv4", + "error_text_node_port": "منفذ العقدة يمكن أن يحتوي فقط على أرقام بين 0 و 65535", + "error_text_node_proxy_address": "الرجاء إدخال <عنوان IPv4>: ، على سبيل المثال 127.0.0.1:9050", + "error_text_payment_id": "يمكن أن يحتوي معرّف الدفع فقط من 16 إلى 64 حرفًا hex", + "error_text_subaddress_name": "لا يمكن أن يحتوي اسم العنوان الفرعي على رموز ` , ' \"\nويجب أن يتراوح طولها بين حرف واحد و 20 حرفًا", + "error_text_template": "لا يمكن أن يحتوي اسم القالب وعنوانه على رموز ` , \"\nويجب أن يتراوح طولها بين 1 و 106 حرفًا", + "error_text_wallet_name": "يمكن أن يحتوي اسم المحفظة على أحرف وأرقام ورموز _ - فقط\nويجب أن يتراوح طولها بين حرف واحد و 33 حرفًا", + "error_text_xmr": "لا يمكن أن تتجاوز قيمة XMR الرصيد المتاح.\nيجب أن يكون عدد الكسور أقل من أو يساوي 12", "errorGettingCredentials": "ﺩﺎﻤﺘﻋﻻﺍ ﺕﺎﻧﺎﻴﺑ ﻰﻠﻋ ﻝﻮﺼﺤﻟﺍ ءﺎﻨﺛﺃ ﺄﻄﺧ ﺙﺪﺣ :ﻞﺸﻓ", "errorSigningTransaction": "ﺔﻠﻣﺎﻌﻤﻟﺍ ﻊﻴﻗﻮﺗ ءﺎﻨﺛﺃ ﺄﻄﺧ ﺙﺪﺣ", - "pairingInvalidEvent": "ﺢﻟﺎﺻ ﺮﻴﻏ ﺙﺪﺣ ﻥﺍﺮﻗﺇ", - "chains": "ﻞﺳﻼﺴﻟﺍ", - "methods": " ﻕﺮﻃُ", - "events": "ﺙﺍﺪﺣﻷﺍ", - "reject": "ﺾﻓﺮﻳ", - "approve": "ﺪﻤﺘﻌﻳ", - "expiresOn": "ﻲﻓ ﻪﺘﻴﺣﻼﺻ ﻲﻬﺘﻨﺗ", - "walletConnect": "WalletConnect", - "nullURIError": "ﻍﺭﺎﻓ (URI) ﻢﻈﺘﻨﻤﻟﺍ ﺩﺭﺍﻮﻤﻟﺍ ﻑﺮﻌﻣ", - "connectWalletPrompt": "ﺕﻼﻣﺎﻌﻤﻟﺍ ءﺍﺮﺟﻹ WalletConnect ﻊﻣ ﻚﺘﻈﻔﺤﻣ ﻞﻴﺻﻮﺘﺑ ﻢﻗ", - "newConnection": "ﺪﻳﺪﺟ ﻝﺎﺼﺗﺍ", - "activeConnectionsPrompt": "ﺎﻨﻫ ﺔﻄﺸﻨﻟﺍ ﺕﻻﺎﺼﺗﻻﺍ ﺮﻬﻈﺘﺳ", - "deleteConnectionConfirmationPrompt": "ـﺑ ﻝﺎﺼﺗﻻﺍ ﻑﺬﺣ ﺪﻳﺮﺗ ﻚﻧﺃ ﺪﻛﺄﺘﻣ ﺖﻧﺃ ﻞﻫ", + "estimated": "مُقدَّر", + "etherscan_history": "Etherscan تاريخ", "event": "ﺙﺪﺣ", - "successful": "ﺢﺟﺎﻧ", - "wouoldLikeToConnect": "ﻝﺎﺼﺗﻻﺍ ﻲﻓ ﺐﻏﺮﺗ", - "message": "ﺔﻟﺎﺳﺭ", - "do_not_have_enough_gas_asset": "ليس لديك ما يكفي من ${currency} لإجراء معاملة وفقًا لشروط شبكة blockchain الحالية. أنت بحاجة إلى المزيد من ${currency} لدفع رسوم شبكة blockchain، حتى لو كنت ترسل أصلًا مختلفًا.", - "totp_auth_url": "TOTP ﺔﻗﺩﺎﺼﻤﻟ URL ﻥﺍﻮﻨﻋ", - "awaitDAppProcessing": ".ﺔﺠﻟﺎﻌﻤﻟﺍ ﻦﻣ dApp ﻲﻬﺘﻨﻳ ﻰﺘﺣ ﺭﺎﻈﺘﻧﻻﺍ ﻰﺟﺮﻳ", - "copyWalletConnectLink": "ﺎﻨﻫ ﻪﻘﺼﻟﺍﻭ dApp ﻦﻣ WalletConnect ﻂﺑﺍﺭ ﺦﺴﻧﺍ", - "enterWalletConnectURI": "WalletConnect ـﻟ URI ﻞﺧﺩﺃ", - "seed_key": "مفتاح البذور", - "enter_seed_phrase": "أدخل عبارة البذور الخاصة بك", - "change_rep_successful": "تم تغيير ممثل بنجاح", - "add_contact": "ﻝﺎﺼﺗﺍ ﺔﻬﺟ ﺔﻓﺎﺿﺇ", + "events": "ﺙﺍﺪﺣﻷﺍ", + "exchange": "تبادل", + "exchange_incorrect_current_wallet_for_xmr": "إذا كنت ترغب في استبدال XMR من رصيد Cake Wallet Monero ، فيرجى التبديل إلى محفظة Monero أولاً.", + "exchange_new_template": "قالب جديد", "exchange_provider_unsupported": "${providerName} لم يعد مدعومًا!", - "domain_looks_up": "ﻝﺎﺠﻤﻟﺍ ﺚﺤﺑ ﺕﺎﻴﻠﻤﻋ", - "require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ", - "camera_permission_is_required": ".ﺍﺮﻴﻣﺎﻜﻟﺍ ﻥﺫﺇ ﺏﻮﻠﻄﻣ", - "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", - "order_by": "ترتيب حسب", - "creation_date": "تاريخ الإنشاء", + "exchange_result_confirm": "بالضغط على تأكيد ، سترسل ${fetchingLabel} ${from} من محفظتك المسماة ${walletName} إلى العنوان الموضح أدناه. أو يمكنك الإرسال من محفظتك الخارجية إلى العنوان أدناه / QR.\n\nيرجى الضغط على تأكيد للمتابعة أو الرجوع لتغيير المبالغ.", + "exchange_result_description": "يجب عليك إرسال ما لا يقل عن ${fetchingLabel} ${from} إلى العنوان المعروض في الصفحة التالية. إذا أرسلت مبلغًا أقل من ${fetchingLabel} ${from} فقد لا يتم تحويله وقد لا يتم رده.", + "exchange_result_write_down_ID": "* يرجى نسخ أو كتابة معرف هويتك الأعلى لحفظة.", + "exchange_result_write_down_trade_id": "يرجى نسخ أو كتابة معرّف العملية للمتابعة.", + "exchange_sync_alert_content": "يرجى الانتظار حتى تتم مزامنة محفظتك", + "expired": "منتهي الصلاحية", + "expires": "تنتهي", + "expiresOn": "ﻲﻓ ﻪﺘﻴﺣﻼﺻ ﻲﻬﺘﻨﺗ", + "export_backup": "تصدير نسخة احتياطية", + "extra_id": "معرف إضافي:", + "extracted_address_content": "سوف ترسل الأموال إلى\n${recipient_name}", + "failed_authentication": "${state_error} فشل المصادقة.", + "faq": "الأسئلة الشائعة", + "fetching": "جار الجلب", + "fiat_api": "Fiat API", + "fiat_balance": "الرصيد فيات", + "field_required": "هذه الخانة مطلوبه", + "fill_code": "يرجى ملء رمز التحقق المرسل إلى بريدك الإلكتروني", + "filter_by": "تصفية حسب", + "first_wallet_text": "محفظة رائعة ل Monero, Bitcoin, Ethereum, Litecoin و Haven", + "fixed_pair_not_supported": "هذا الزوج الثابت غير مدعوم في التبادلات المحددة", + "fixed_rate": "السعر الثابت", + "fixed_rate_alert": "ستتمكن من إدخال مبلغ الاستلام عند تشغيل وضع السعر الثابت. هل تريد التبديل إلى وضع السعر الثابت؟", + "forgot_password": "هل نسيت كلمة السر", + "freeze": "تجميد", + "frequently_asked_questions": "الأسئلة الشائعة", + "frozen": "مجمدة", + "full_balance": "الرصيد الكامل", + "generate_name": "توليد الاسم", + "generating_gift_card": "يتم توليد بطاقة هدية", + "get_a": "احصل على", + "get_card_note": " يمكنك إعادة تحميلها بالعملات الرقمية. لا توجد معلومات إضافية مطلوبة!", + "get_your_yat": "احصل على Yat", + "gift_card_amount": "مبلغ بطاقة الهدايا", + "gift_card_balance_note": "ستظهر هنا بطاقات الهدايا ذات الرصيد المتبقي", + "gift_card_is_generated": "تم إنشاء بطاقة الهدايا", + "gift_card_number": "رقم بطاقة الهدية", + "gift_card_redeemed_note": "ستظهر هنا بطاقات الهدايا التي استردت قيمتها", + "gift_cards": "بطاقات الهدايا", + "gift_cards_unavailable": "تتوفر بطاقات الهدايا للشراء فقط باستخدام Monero و Bitcoin و Litecoin في الوقت الحالي", + "got_it": "فهمتك", + "gross_balance": "إجمالي الرصيد", "group_by_type": "مجموعة حسب النوع", - "importNFTs": "NFTs ﺩﺍﺮﻴﺘﺳﺍ", - "noNFTYet": "ﻥﻵﺍ ﻰﺘﺣ NFTs ﺪﺟﻮﻳ ﻻ", - "address": " ﻥﺍﻮﻨﻋ", - "enterTokenID": "ﺰﻴﻤﻤﻟﺍ ﺰﻣﺮﻟﺍ ﻑﺮﻌﻣ ﻞﺧﺩﺃ", - "tokenID": "ﻒﻳﺮﻌﺗ ﺔﻗﺎﻄﺑ", - "name": "ﻢﺳﺍ", - "symbol": "ﺰﻣﺭ", - "seed_phrase_length": "ﺭﻭﺬﺒﻟﺍ ﺓﺭﺎﺒﻌﻟﺍ ﻝﻮﻃ", - "unavailable_balance": "ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ", - "unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ", - "unspent_change": "يتغير", - "setup_warning_2fa_text": ".ﺩﺭﺎﺒﻟﺍ ﻦﻳﺰﺨﺘﻟﺍ ﻞﺜﻣ ﺔﻨﻣﺁ ﺖﺴﻴﻟ ﺎﻬﻧﺇ .ﺔﻈﻔﺤﻤﻟﺍ ﻲﻓ ﺔﻨﻴﻌﻣ ﺕﺍءﺍﺮﺟﻹ ﺔﻴﻧﺎﺛ ﺔﻗﺩﺎﺼﻣ ﺔﺑﺎﺜ", - "scan_qr_on_device": " ﺮﺧﺁ ﺯﺎﻬﺟ ﻰﻠﻋ ﺎﻴًﺋﻮﺿ ﺍﺬﻫ ﺔﻌﻳﺮﺴﻟﺍ ﺔﺑﺎﺠﺘﺳﻻﺍ ﺰﻣﺭ ﺢﺴﻤﺑ ﻢﻗ", + "haven_app": "Haven بواسطة Cake Wallet", + "haven_app_wallet_text": "محفظة رائعة ل Haven", + "help": "مساعده", + "hidden_balance": "الميزان الخفي", + "hide_details": "أخف التفاصيل", + "high_contrast_theme": "موضوع عالي التباين", + "home_screen_settings": "إعدادات الشاشة الرئيسية", "how_to_use": " ﻞﻤﻌﺘﺴﺗ ﻒﻴﻛ", + "how_to_use_card": "كيفية استخدام هذه البطاقة", + "id": "رقم المعرف:", + "ignor": "تجاهل", + "import": "ﺩﺭﻮﺘﺴﻳ", + "importNFTs": "NFTs ﺩﺍﺮﻴﺘﺳﺍ", + "in_store": "في المتجر", + "incoming": "الواردة", + "incorrect_seed": "النص الذي تم إدخاله غير صالح.", + "introducing_cake_pay": "نقدم لكم Cake Pay!", + "invalid_input": "مدخل غير صالح", + "invoice_details": "تفاصيل الفاتورة", + "is_percentage": "يكون", + "last_30_days": "آخر 30 يومًا", + "learn_more": "اعرف المزيد", + "light_theme": "فاتح", + "loading_your_wallet": "يتم تحميل محفظتك", + "login": "تسجيل الدخول", + "logout": "تسجيل خروج", + "low_fee": "رسوم منخفضة", + "low_fee_alert": "أنت تستخدم حاليًا أولوية منخفضة لرسوم الشبكة. قد يتسبب هذا في فترات انتظار طويلة ، أو أسعار مختلفة ، أو إلغاء صفقات. نوصي بتحديد رسوم أعلى لتجربة أفضل.", + "manage_nodes": "ﺪﻘﻌﻟﺍ ﺓﺭﺍﺩﺇ", + "manage_pow_nodes": "PoW ﻁﺎﻘﻧ ﺓﺭﺍﺩﺇ", + "manage_yats": "إدارة Yats", + "mark_as_redeemed": "وضع علامة كمسترد", + "market_place": "منصة التجارة", + "matrix_green_dark_theme": "موضوع ماتريكس الأخضر الداكن", + "max_amount": "الحد الأقصى: ${value}", + "max_value": "الحد الأقصى: ${value} ${currency}", + "memo": "مذكرة:", + "message": "ﺔﻟﺎﺳﺭ", + "methods": " ﻕﺮﻃُ", + "min_amount": "الحد الأدنى: ${value}", + "min_value": "الحد الأدنى: ${value} ${currency}", + "minutes_to_pin_code": "${minutes} دقيقة", + "mm": "MM", + "modify_2fa": "تعديل 2 عامل المصادقة", + "monero_com": "Monero.com بواسطة Cake Wallet", + "monero_com_wallet_text": "محفظة رائعة ل Monero", + "monero_dark_theme": "موضوع مونيرو الظلام", + "monero_light_theme": " ضوء مونيرو", + "moonpay_alert_text": "يجب أن تكون قيمة المبلغ أكبر من أو تساوي ${minAmount} ${fiatCurrency}", + "more_options": "المزيد من الخيارات", + "name": "ﻢﺳﺍ", + "narrow": "ضيق", + "new_first_wallet_text": "حافظ بسهولة على أمان العملة المشفرة", + "new_node_testing": "تجربة العقدة الجديدة", + "new_subaddress_create": "إنشاء", + "new_subaddress_label_name": "تسمية", + "new_subaddress_title": "عنوان جديد", + "new_template": "قالب جديد", + "new_wallet": "إنشاء محفظة جديدة", + "newConnection": "ﺪﻳﺪﺟ ﻝﺎﺼﺗﺍ", + "no_id_needed": "لا حاجة لID!", + "no_id_required": "لا ID مطلوب. اشحن وانفق في أي مكان", + "no_relay_on_domain": ".ﻡﺍﺪﺨﺘﺳﻼﻟ ﻊﺑﺎﺘﺘﻟﺍ ﺭﺎﻴﺘﺧﺍ ءﺎﺟﺮﻟﺍ .ﺡﺎﺘﻣ ﺮﻴﻏ ﻞﻴﺣﺮﺘﻟﺍ ﻥﺃ ﻭﺃ ﻡﺪﺨﺘﺴﻤﻟﺍ ﻝﺎﺠﻤﻟ ﻞﻴﺣﺮﺗ ﺪ", + "no_relays": "ﺕﻼﺣﺮﻤﻟﺍ ﻻ", + "no_relays_message": ".ﻪﺑ ﺹﺎﺨﻟﺍ Nostr ﻞﺠﺳ ﻰﻟﺇ ﺕﻼﺣﺮﻤﻟﺍ ﺔﻓﺎﺿﻹ ﻢﻠﺘﺴﻤﻟﺍ ﺩﺎﺷﺭﺇ ﻰﺟﺮﻳ .ﺕﻼﺣﺮﻣ ﻱﺃ ﻰﻠﻋ ﻱﻮﺘﺤﻳ ﻻ", + "node_address": "عنوان العقدة", + "node_connection_failed": "فشل الاتصال", + "node_connection_successful": "تم الاتصال بنجاح", + "node_new": "عقدة جديدة", + "node_port": "منفذ العقدة", + "node_reset_settings_title": "اعادة الضبط", + "node_test": "تجربة", + "nodes": "العقد", + "nodes_list_reset_to_default_message": "هل أنت متأكد أنك تريد إعادة تعيين الإعدادات إلى الافتراضي؟", + "none_of_selected_providers_can_exchange": "لا يمكن لأي من مقدمي الخدمة المختارين إجراء هذا التبادل", + "noNFTYet": "ﻥﻵﺍ ﻰﺘﺣ NFTs ﺪﺟﻮﻳ ﻻ", + "normal": "طبيعي", + "note_optional": "ملاحظة (اختياري)", + "note_tap_to_change": "ملاحظة (انقر للتغيير)", + "nullURIError": "ﻍﺭﺎﻓ (URI) ﻢﻈﺘﻨﻤﻟﺍ ﺩﺭﺍﻮﻤﻟﺍ ﻑﺮﻌﻣ", + "offer_expires_in": "ينتهي العرض في:", + "offline": "غير متصل على الانترنت", + "ok": "حسناً", + "onion_link": "رابط البصل", + "online": "متصل", + "onramper_option_description": "شراء بسرعة التشفير مع العديد من طرق الدفع. متوفر في معظم البلدان. ينتشر وتختلف الرسوم.", + "open_gift_card": "افتح بطاقة الهدية", + "optional_description": "وصف اختياري", + "optional_email_hint": "البريد الإلكتروني إخطار المدفوع لأمره الاختياري", + "optional_name": "اسم المستلم الاختياري", + "optionally_order_card": "اختياريا اطلب بطاقة فعلية (مادية).", + "orbot_running_alert": "يرجى التأكد من تشغيل Orbot قبل الاتصال بهذه العقدة.", + "order_by": "ترتيب حسب", + "order_id": "رقم التعريف الخاص بالطلب", + "order_physical_card": "طلب البطاقة المادية", + "other_settings": "اعدادات اخرى", + "outdated_electrum_wallet_description": "محافظ Bitcoin الجديدة التي تم إنشاؤها في Cake الآن سييد مكونة من 24 كلمة. من الضروري أن تقوم بإنشاء محفظة Bitcoin جديدة وتحويل جميع أموالك إلى المحفظة الجديدة المكونة من 24 كلمة ، والتوقف عن استخدام محافظ سييد مكونة من 12 كلمة. يرجى القيام بذلك على الفور لتأمين أموالك.", + "outdated_electrum_wallet_receive_warning": "إذا كانت هذه المحفظة تحتوي على سييد مكونة من 12 كلمة وتم إنشاؤها في Cake ، فلا تقم بإيداع Bitcoin في هذه المحفظة. قد يتم فقد أي BTC تم تحويله إلى هذه المحفظة. قم بإنشاء محفظة جديدة مكونة من 24 كلمة (انقر فوق القائمة في الجزء العلوي الأيمن ، وحدد محافظ ، واختر إنشاء محفظة جديدة ، ثم حدد Bitcoin) وقم على الفور بنقل BTC الخاص بك هناك. محافظ BTC الجديدة (24 كلمة) من Cake آمنة", + "outgoing": "الصادره", + "overwrite_amount": "تغير المبلغ", + "pairingInvalidEvent": "ﺢﻟﺎﺻ ﺮﻴﻏ ﺙﺪﺣ ﻥﺍﺮﻗﺇ", + "password": "كلمة المرور", + "paste": "لصق", + "pause_wallet_creation": ".ﺎﻴًﻟﺎﺣ ﺎﺘًﻗﺆﻣ ﺔﻔﻗﻮﺘﻣ Haven Wallet ءﺎﺸﻧﺇ ﻰﻠﻋ ﺓﺭﺪﻘﻟﺍ", + "payment_id": "معرف الدفع:", + "payment_was_received": "تم استلام الدفع الخاص بك.", + "pending": " (في الإنتظار)", + "percentageOf": "من ${amount}", + "pin_at_top": "تثبيت ${token} في الأعلى", + "pin_is_incorrect": "رقم ال PIN غير صحيح", + "pin_number": "الرقم السري", + "placeholder_contacts": "سيتم عرض جهات الاتصال الخاصة بك هنا", + "placeholder_transactions": "سيتم عرض معاملاتك هنا", + "please_fill_totp": "يرجى ملء الرمز المكون من 8 أرقام الموجود على جهازك الآخر", + "please_make_selection": "يرجى الأختيار لإنشاء أو استعادة محفظتك.", + "please_reference_document": "يرجى الرجوع إلى الوثائق أدناه لمزيد من المعلومات.", + "please_select": "الرجاء الأختيار:", + "please_select_backup_file": "الرجاء تحديد ملف النسخ الاحتياطي وإدخال كلمة مرور النسخ الاحتياطي.", + "please_try_to_connect_to_another_node": "الرجاء محاولة الاتصال بعقدة أخرى", + "please_wait": "انتظر من فضلك", + "polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ", + "powered_by": "بدعم من ${title}", + "pre_seed_button_text": "انا أفهم. أرني سييد الخاص بي", + "pre_seed_description": "في الصفحة التالية ستشاهد سلسلة من الكلمات ${words}. هذه هي سييد الفريدة والخاصة بك وهي الطريقة الوحيدة لاسترداد محفظتك في حالة فقدها أو عطلها. تقع على عاتقك مسؤولية تدوينها وتخزينها في مكان آمن خارج تطبيق Cake Wallet.", + "pre_seed_title": "مهم", + "prevent_screenshots": "منع لقطات الشاشة وتسجيل الشاشة", + "privacy": "خصوصية", + "privacy_policy": "سياسة الخصوصية", + "privacy_settings": "إعدادات الخصوصية", + "private_key": "مفتاح خاص", + "proceed_after_one_minute": "إذا لم تستمر الشاشة بعد دقيقة واحدة ، فتحقق من بريدك الإلكتروني.", + "profile": "حساب تعريفي", + "provider_error": "خطأ ${provider}", + "public_key": "مفتاح عمومي", + "purchase_gift_card": "شراء بطاقة هدايا", + "qr_fullscreen": "انقر لفتح ال QR بملء الشاشة", + "qr_payment_amount": "يحتوي هذا ال QR على مبلغ الدفع. هل تريد تغير المبلغ فوق القيمة الحالية؟", + "question_to_disable_2fa": "هل أنت متأكد أنك تريد تعطيل Cake 2FA؟ لن تكون هناك حاجة إلى رمز 2FA للوصول إلى المحفظة ووظائف معينة.", + "receivable_balance": "التوازن القادم", + "receive": "استلام", + "receive_amount": "المقدار", + "received": "استلام", + "recipient_address": "عنوان المستلم", + "reconnect": "أعد الاتصال", + "reconnect_alert_text": "هل أنت متأكد من رغبتك في إعادة الاتصال؟", + "reconnection": "إعادة الاتصال", + "redeemed": "استردت", + "refund_address": "عنوان إعادة المال", + "reject": "ﺾﻓﺮﻳ", + "remaining": "متبقي", + "remove": "إزالة", + "remove_node": "إزالة العقدة", + "remove_node_message": "هل أنت متأكد أنك تريد إزالة العقدة المحددة؟", + "rename": "إعادة تسمية", + "require_for_adding_contacts": "تتطلب إضافة جهات اتصال", + "require_for_all_security_and_backup_settings": "مطلوب لجميع إعدادات الأمان والنسخ الاحتياطي", + "require_for_assessing_wallet": "تتطلب الوصول إلى المحفظة", + "require_for_creating_new_wallets": "تتطلب إنشاء محافظ جديدة", + "require_for_exchanges_to_external_wallets": "ﺔﻴﺟﺭﺎﺧ ﻆﻓﺎﺤﻣ ﻰﻟﺇ ﺕﻻﺩﺎﺒﺘﻟﺍ ﺐﻠﻄﺘﺗ", + "require_for_exchanges_to_internal_wallets": "تتطلب عمليات التبادل إلى المحافظ الداخلية", + "require_for_sends_to_contacts": "تتطلب لارسال جهات الاتصال", + "require_for_sends_to_internal_wallets": "تتطلب عمليات الإرسال إلى المحافظ الداخلية", + "require_for_sends_to_non_contacts": "تتطلب لارسال لغير جهات الاتصال", + "require_pin_after": "طلب PIN بعد", + "rescan": "إعادة الفحص", + "resend_code": "الرجاء إعادة إرسالها", + "reset": "إعادة", + "reset_password": "إعادة تعيين كلمة المرور", + "restore_active_seed": "السييد النشطة", + "restore_address": "العنوان", + "restore_bitcoin_description_from_keys": "قم باستعادة محفظتك من سلسلة WIF التي تم إنشاؤها من مفاتيحك الخاصة", + "restore_bitcoin_description_from_seed": "قم باستعادة محفظتك من كود مكون من 24 كلمة", + "restore_bitcoin_title_from_keys": "استعادة من WIF", + "restore_description_from_backup": "يمكنك استعادة تطبيق Cake Wallet بالكامل من ملف النسخ الاحتياطي", + "restore_description_from_keys": "قم باستعادة محفظتك من ضغطات المفاتيح المولدة المحفوظة من مفاتيحك الخاصة", + "restore_description_from_seed": "قم باستعادة محفظتك من الرمز المكون من 25 كلمة أو 13 كلمة", + "restore_description_from_seed_keys": "استرجع محفظتك من السييد / المفاتيح التي قمت بحفظها في مكان آمن", + "restore_from_date_or_blockheight": "الرجاء إدخال تاريخ قبل إنشاء هذه المحفظة ببضعة أيام. أو إذا كنت تعرف ارتفاع البلوك، فيرجى إدخاله بدلاً من ذلك", + "restore_from_seed_placeholder": "الرجاء إدخال أو لصق السييد الخاصة بك هنا", + "restore_new_seed": "سييد جديدة", + "restore_next": "التالي", + "restore_recover": "استعادة", + "restore_restore_wallet": "استعادة محفظة", + "restore_seed_keys_restore": "استعادة السييد / المفاتيح", + "restore_spend_key_private": "مفتاح الإنفاق (خاص)", + "restore_title_from_backup": "استعادة من النسخة الاحتياطية", + "restore_title_from_keys": "استعادة من المفاتيح", + "restore_title_from_seed": "استعادة من السييد", + "restore_title_from_seed_keys": "استعادة من السييد / المفاتيح", + "restore_view_key_private": "مفتاح العرض (خاص)", + "restore_wallet": "استعادة محفظة", + "restore_wallet_name": "اسم المحفظة", + "restore_wallet_restore_description": "وصف استعادة المحفظة", + "router_no_route": "لم يتم تحديد مسار لـ ${name}", + "save": "حفظ", + "save_backup_password": "يرجى التأكد من حفظ كلمة المرور الاحتياطية. لن تتمكن من استيراد ملفات النسخ الاحتياطي بدونها.", + "save_backup_password_alert": "حفظ كلمة المرور الاحتياطية", + "save_to_downloads": "ﺕﻼﻳﺰﻨﺘﻟﺍ ﻲﻓ ﻆﻔﺣ", + "saved_the_trade_id": "لقد تم حفظ معرف العملية", + "scan_qr_code": "امسح رمز QR ضوئيًا", + "scan_qr_code_to_get_address": "امسح ال QR للحصول على العنوان", + "scan_qr_on_device": " ﺮﺧﺁ ﺯﺎﻬﺟ ﻰﻠﻋ ﺎﻴًﺋﻮﺿ ﺍﺬﻫ ﺔﻌﻳﺮﺴﻟﺍ ﺔﺑﺎﺠﺘﺳﻻﺍ ﺰﻣﺭ ﺢﺴﻤﺑ ﻢﻗ", + "search": "بحث", + "search_add_token": "بحث / إضافة رمز", + "search_category": "فئة البحث", + "search_currency": "ابحث عن عملة", + "search_language": "ابحث عن لغة", + "second_intro_content": "Yat الخاص بك هو عنوان تعبيري فريد يحل محل جميع العناوين السداسية العشرية الطويلة لجميع عملاتك.", + "second_intro_title": "عنوان تعبيري ايموجي واحد يحكمهم جميعا!", + "security_and_backup": "الأمان والنسخ الاحتياطي", + "seed_alert_back": "العودة إلى الوراء", + "seed_alert_content": "السييد هي الطريقة الوحيدة لاسترداد محفظتك. هل كتبتها؟", + "seed_alert_title": "انتباه", + "seed_alert_yes": "نعم، فعلت ذلك", + "seed_choose": "اختر لغة السييد", "seed_hex_form": "بذور المحفظة (شكل عرافة)", - "tor_connection": "ﺭﻮﺗ ﻝﺎﺼﺗﺍ", + "seed_key": "مفتاح البذور", + "seed_language": "لغة البذور", + "seed_language_chinese": "صينى", + "seed_language_chinese_traditional": "تقاليد صينية)", + "seed_language_czech": "التشيكية", + "seed_language_dutch": "هولندي", + "seed_language_english": "إنجليزي", + "seed_language_french": "فرنسي", + "seed_language_german": "ألمانية", + "seed_language_italian": "إيطالي", + "seed_language_japanese": "اليابانية", + "seed_language_korean": "الكورية", + "seed_language_next": "التالي", + "seed_language_portuguese": "البرتغالية", + "seed_language_russian": "الروسية", + "seed_language_spanish": "الأسبانية", + "seed_phrase_length": "ﺭﻭﺬﺒﻟﺍ ﺓﺭﺎﺒﻌﻟﺍ ﻝﻮﻃ", + "seed_reminder": "يرجى تدوينها في حالة فقد هاتفك أو مسحه", + "seed_share": "شارك السييد", + "seed_title": "سييد", "seedtype": "البذور", "seedtype_legacy": "إرث (25 كلمة)", "seedtype_polyseed": "بوليسيد (16 كلمة)", - "seed_language_czech": "التشيكية", - "seed_language_korean": "الكورية", - "seed_language_chinese_traditional": "تقاليد صينية)", - "ascending": "تصاعدي", - "descending": "النزول", - "dfx_option_description": "ﺎﺑﻭﺭﻭﺃ ﻲﻓ ﺕﺎﻛﺮﺸﻟﺍﻭ ﺔﺋﺰﺠﺘﻟﺍ ءﻼﻤﻌﻟ .ﻲﻓﺎﺿﺇ KYC ﻥﻭﺪﺑ ﻭﺭﻮﻳ 990 ﻰﻟﺇ ﻞﺼﻳ ﺎﻣ .ﻱﺮﺴﻳﻮﺴﻟﺍ", - "polygonscan_history": "ﻥﺎﻜﺴﻧﻮﺠﻴﻟﻮﺑ ﺦﻳﺭﺎﺗ", - "wallet_seed_legacy": "بذرة محفظة قديمة", - "default_sell_provider": "ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ", + "select_backup_file": "حدد ملف النسخ الاحتياطي", + "select_buy_provider_notice": "حدد مزود شراء أعلاه. يمكنك تخطي هذه الشاشة عن طريق تعيين مزود شراء الافتراضي في إعدادات التطبيق.", + "select_destination": ".ﻲﻃﺎﻴﺘﺣﻻﺍ ﺦﺴﻨﻟﺍ ﻒﻠﻣ ﺔﻬﺟﻭ ﺪﻳﺪﺤﺗ ءﺎﺟﺮﻟﺍ", "select_sell_provider_notice": ".ﻖﻴﺒﻄﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻚﺑ ﺹﺎﺨﻟﺍ ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ ﻦﻴﻴﻌﺗ ﻖﻳﺮﻃ ﻦﻋ ﺔﺷﺎﺸﻟﺍ ﻩﺬﻫ ﻲﻄﺨﺗ", - "custom_drag": "مخصص (عقد وسحب)", + "sell": "بيع", + "sell_alert_content": ".ﺎﻬﻴﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻭﺃ Litecoin ﻭﺃ Ethereum ﻭﺃ Bitcoin ﺔﻈﻔﺤﻣ ءﺎﺸﻧﺇ ﻰﺟﺮﻳ .Litecoin ﻭ", + "sell_monero_com_alert_content": "بيع Monero غير مدعوم حتى الآن", + "send": "إرسال", + "send_address": "عنوان ${cryptoCurrency}", + "send_amount": "مقدار:", + "send_creating_transaction": " يتم إنشاء المعاملة", + "send_error_currency": "العملة يجب أن تحتوي على أرقام فقط", + "send_error_minimum_value": "الحد الأدنى لقيمة المبلغ هو 0.01", + "send_estimated_fee": "الرسوم المقدرة:", + "send_fee": "الرسوم:", + "send_name": "الأسم", + "send_new": "جديد", + "send_payment_id": "معرف عملية الدفع (اختياري)", + "send_priority": "حاليًا ، تم تحديد الرسوم بأولوية ${transactionPriority}.\nيمكن تعديل أولوية المعاملة في الإعدادات", + "send_sending": "يتم الإرسال...", + "send_success": "تم إرسال ${crypto} الخاص بك بنجاح", + "send_templates": "القوالب", + "send_title": "إرسال", + "send_to_this_address": "أرسل ${currency} ${tag}إلى هذا العنوان", + "send_xmr": "أرسل XMR", + "send_your_wallet": "محفظتك", + "sending": "يتم الإرسال", + "sent": "تم الأرسال", + "settings": "إعدادات", + "settings_all": "الكل", + "settings_allow_biometrical_authentication": "السماح بالمصادقة البيومترية", + "settings_can_be_changed_later": "يمكن تغيير هذه الإعدادات لاحقًا في إعدادات التطبيق", + "settings_change_language": "تغيير اللغة", + "settings_change_pin": "تغيير PIN", + "settings_currency": "العملة", + "settings_current_node": "العقدة الحالية", + "settings_dark_mode": "الوضع الداكن", + "settings_display_balance": "عرض الرصيد", + "settings_display_on_dashboard_list": "عرض في قائمة لوحة المعلومات", + "settings_fee_priority": "رسوم الأولوية", + "settings_nodes": "العقد", + "settings_none": "لا شيء", + "settings_only_trades": "الصفقات فقط", + "settings_only_transactions": "المعاملات فقط", + "settings_personal": "شخصي", + "settings_save_recipient_address": "حفظ عنوان المستلم", + "settings_support": "الدعم", + "settings_terms_and_conditions": "الأحكام والشروط", + "settings_title": "إعدادات", + "settings_trades": "الصفقات", + "settings_transactions": "المبادلات", + "settings_wallets": "المحافظ", + "setup_2fa": "تعيين 2 عامل المصادقة", + "setup_2fa_text": " .ﻲﻧﺎﺜﻟﺍ ﺔﻗﺩﺎﺼﻤﻟﺍ ﻞﻣﺎﻌﻛ TOTP ﻡﺍﺪﺨﺘﺳﺎﺑ Cake 2FA ﻞﻤﻌﻳ", + "setup_pin": "تعيين PIN", + "setup_successful": "تم إعداد PIN الخاص بك بنجاح!", + "setup_totp_recommended": " TOTP ﺩﺍﺪﻋﺇ", + "setup_warning_2fa_text": ".ﺩﺭﺎﺒﻟﺍ ﻦﻳﺰﺨﺘﻟﺍ ﻞﺜﻣ ﺔﻨﻣﺁ ﺖﺴﻴﻟ ﺎﻬﻧﺇ .ﺔﻈﻔﺤﻤﻟﺍ ﻲﻓ ﺔﻨﻴﻌﻣ ﺕﺍءﺍﺮﺟﻹ ﺔﻴﻧﺎﺛ ﺔﻗﺩﺎﺼﻣ ﺔﺑﺎﺜ", + "setup_your_debit_card": "قم بإعداد بطاقة ائتمان الخاصة بك", + "share": "يشارك", + "share_address": "شارك العنوان", + "show_details": "اظهر التفاصيل", + "show_keys": "اظهار السييد / المفاتيح", + "show_market_place": "إظهار السوق", + "show_seed": "عرض السييد", + "sign_up": "اشتراك", + "signTransaction": " ﺔﻠﻣﺎﻌﻤﻟﺍ ﻊﻴﻗﻮﺗ", + "signup_for_card_accept_terms": "قم بالتسجيل للحصول على البطاقة وقبول الشروط.", + "slidable": "قابل للانزلاق", + "sort_by": "ترتيب حسب", + "spend_key_private": "مفتاح الإنفاق (خاص)", + "spend_key_public": "مفتاح الإنفاق (عام)", + "status": "الحالة:", + "subaddress_title": "قائمة العناوين الفرعية", + "subaddresses": "العناوين الفرعية", + "submit_request": "تقديم طلب", + "successful": "ﺢﺟﺎﻧ", + "support_description_guides": "توثيق ودعم القضايا المشتركة", + "support_description_live_chat": "حرة وسريعة! ممثلو الدعم المدربين متاحون للمساعدة", + "support_description_other_links": "انضم إلى مجتمعاتنا أو تصل إلينا شركائنا من خلال أساليب أخرى", + "support_title_guides": "أدلة محفظة كعكة", + "support_title_live_chat": "الدعم المباشر", + "support_title_other_links": "روابط دعم أخرى", + "sweeping_wallet": "كنس المحفظة", + "sweeping_wallet_alert": "لن يستغرق هذا وقتًا طويلاً. لا تترك هذه الشاشة وإلا فقد يتم فقد أموال سويبت", + "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", "switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", - "receivable_balance": "التوازن القادم", - "confirmed_tx": "مؤكد", + "symbol": "ﺰﻣﺭ", + "sync_status_attempting_sync": "جاري محاولة المزامنة", + "sync_status_connected": "متصل", + "sync_status_connecting": "يتم التوصيل", + "sync_status_failed_connect": "انقطع الاتصال", + "sync_status_not_connected": "غير متصل", + "sync_status_starting_sync": "بدء المزامنة", + "sync_status_syncronized": "متزامن", + "sync_status_syncronizing": "يتم المزامنة", + "syncing_wallet_alert_content": "قد لا يكتمل رصيدك وقائمة المعاملات الخاصة بك حتى تظهر عبارة “SYNCHRONIZED“ في الأعلى. انقر / اضغط لمعرفة المزيد.", + "syncing_wallet_alert_title": "محفظتك تتم مزامنتها", + "template": "قالب", + "template_name": "اسم القالب", + "third_intro_content": "يعيش Yats خارج Cake Wallet أيضًا. يمكن استبدال أي عنوان محفظة على وجه الأرض بـ Yat!", + "third_intro_title": "يتماشي Yat بلطف مع الآخرين", + "time": "${minutes}د ${seconds}س", + "tip": "بقشيش:", + "today": "اليوم", + "token_contract_address": "عنوان عقد الرمز", + "token_decimal": "رمز عشري", + "token_name": "اسم الرمز ، على سبيل المثال: Tether", + "token_symbol": "رمز العملة ، على سبيل المثال: USDT", + "tokenID": "ﻒﻳﺮﻌﺗ ﺔﻗﺎﻄﺑ", + "tor_connection": "ﺭﻮﺗ ﻝﺎﺼﺗﺍ", + "tor_only": "Tor فقط", + "total_saving": "إجمالي المدخرات", + "totp_2fa_failure": "شفرة خاطئة. يرجى تجربة رمز مختلف أو إنشاء مفتاح سري جديد. استخدم تطبيق 2FA متوافقًا يدعم الرموز المكونة من 8 أرقام و SHA512.", + "totp_2fa_success": "نجاح! تم تمكين Cake 2FA لهذه المحفظة. تذكر حفظ بذرة ذاكري في حالة فقد الوصول إلى المحفظة.", + "totp_auth_url": "TOTP ﺔﻗﺩﺎﺼﻤﻟ URL ﻥﺍﻮﻨﻋ", + "totp_code": "كود TOTP", + "totp_secret_code": "كود TOTP السري", + "totp_verification_success": "تم التحقق بنجاح!", + "trade_details_copied": "تم نسخ ${title} إلى الحافظة", + "trade_details_created_at": "أنشئت في", + "trade_details_fetching": "جار الجلب", + "trade_details_id": "معرف (ID)", + "trade_details_pair": "زوج", + "trade_details_provider": "مزود", + "trade_details_state": "الحالة", + "trade_details_title": "تفاصيل الصفقة", + "trade_for_not_created": "لم يتم إنشاء التداول للعنصر ${title}.", + "trade_history_title": "تاريخ الصفقه", + "trade_id": "معرف عملية التبادل:", + "trade_id_not_found": "تداول ${tradeId} من ${title} غير موجود.", + "trade_is_powered_by": "عملية التبادل مدعومة من ${provider}", + "trade_not_created": "التداول لم ينشأ", + "trade_not_found": "التداول غير موجودة.", + "trade_state_btc_sent": "تم أرسل Btc", + "trade_state_complete": "اكتمل", + "trade_state_confirming": "جاري التأكيد", + "trade_state_created": "تم الأنشاء", + "trade_state_finished": "تم", + "trade_state_paid": "مدفوع", + "trade_state_paid_unconfirmed": "دفع غير مؤكد", + "trade_state_pending": "قيد الانتظار", + "trade_state_timeout": "نفذ الوقت", + "trade_state_to_be_created": "ليتم انشائه", + "trade_state_traded": "تم التداول بنجاح", + "trade_state_trading": "يتم التداول", + "trade_state_underpaid": "أجر أقل من اللازم", + "trade_state_unpaid": "غير مدفوعة", + "trades": "عمليات التداول", + "transaction_details_amount": "مقدار", + "transaction_details_copied": "تم نسخ ${title} إلى الحافظة", + "transaction_details_date": "تاريخ", + "transaction_details_fee": "رسوم", + "transaction_details_height": "ارتفاع", + "transaction_details_recipient_address": "عناوين المستلم", "transaction_details_source_address": "عنوان المصدر", - "pause_wallet_creation": ".ﺎﻴًﻟﺎﺣ ﺎﺘًﻗﺆﻣ ﺔﻔﻗﻮﺘﻣ Haven Wallet ءﺎﺸﻧﺇ ﻰﻠﻋ ﺓﺭﺪﻘﻟﺍ", - "contractName": "ﺪﻘﻌﻟﺍ ﻢﺳﺍ", - "contractSymbol": "ﺪﻘﻌﻟﺍ ﺰﻣﺭ", - "description": "ﻒﺻﻭ", - "camera_consent": ".ﻞﻴﺻﺎﻔﺘﻟﺍ ﻰﻠﻋ ﻝﻮﺼﺤﻠﻟ ﻢﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺔﻴﺻﻮﺼﺨﻟﺍ ﺔﺳﺎﻴﺳ ﻦﻣ ﻖﻘﺤﺘﻟﺍ ﻰﺟﺮﻳ .${provider} ﻝﻮﻠ", - "no_relays": "ﺕﻼﺣﺮﻤﻟﺍ ﻻ", - "choose_relay": "ﻡﺍﺪﺨﺘﺳﻼﻟ ﻊﺑﺎﺘﺘﻟﺍ ﺭﺎﻴﺘﺧﺍ ءﺎﺟﺮﻟﺍ", - "no_relays_message": ".ﻪﺑ ﺹﺎﺨﻟﺍ Nostr ﻞﺠﺳ ﻰﻟﺇ ﺕﻼﺣﺮﻤﻟﺍ ﺔﻓﺎﺿﻹ ﻢﻠﺘﺴﻤﻟﺍ ﺩﺎﺷﺭﺇ ﻰﺟﺮﻳ .ﺕﻼﺣﺮﻣ ﻱﺃ ﻰﻠﻋ ﻱﻮﺘﺤﻳ ﻻ", - "no_relay_on_domain": ".ﻡﺍﺪﺨﺘﺳﻼﻟ ﻊﺑﺎﺘﺘﻟﺍ ﺭﺎﻴﺘﺧﺍ ءﺎﺟﺮﻟﺍ .ﺡﺎﺘﻣ ﺮﻴﻏ ﻞﻴﺣﺮﺘﻟﺍ ﻥﺃ ﻭﺃ ﻡﺪﺨﺘﺴﻤﻟﺍ ﻝﺎﺠﻤﻟ ﻞﻴﺣﺮﺗ ﺪ" -} + "transaction_details_title": "تفاصيل المعاملة", + "transaction_details_transaction_id": "رقم المعاملة", + "transaction_key": "مفتاح العملية", + "transaction_priority_fast": "سريع", + "transaction_priority_fastest": "أسرع", + "transaction_priority_medium": "متوسط", + "transaction_priority_regular": "عادي", + "transaction_priority_slow": "بطيء", + "transaction_sent": "تم إرسال المعاملة!", + "transaction_sent_notice": "إذا لم تستمر الشاشة بعد دقيقة واحدة ، فتحقق من مستكشف البلوك والبريد الإلكتروني.", + "transactions": "المعاملات", + "transactions_by_date": "المعاملات حسب التاريخ", + "trusted": "موثوق به", + "unavailable_balance": "ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ", + "unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ", + "unconfirmed": "رصيد غير مؤكد", + "understand": "لقد فهمت", + "unmatched_currencies": "عملة محفظتك الحالية لا تتطابق مع عملة QR الممسوحة ضوئيًا", + "unspent_change": "يتغير", + "unspent_coins_details_title": "تفاصيل العملات الغير المنفقة", + "unspent_coins_title": "العملات الغير المنفقة", + "unsupported_asset": ".ﻡﻮﻋﺪﻣ ﻞﺻﺃ ﻉﻮﻧ ﻦﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻭﺃ ءﺎﺸﻧﺇ ﻰﺟﺮﻳ .ﻞﺻﻷﺍ ﺍﺬﻬﻟ ءﺍﺮﺟﻹﺍ ﺍﺬﻫ ﻢﻋﺪﻧ ﻻ ﻦﺤﻧ", + "upto": "حتى ${value}", + "use": "التبديل إلى", + "use_card_info_three": "استخدم البطاقة الرقمية عبر الإنترنت أو مع طرق الدفع غير التلامسية.", + "use_card_info_two": "يتم تحويل الأموال إلى الدولار الأمريكي عند الاحتفاظ بها في الحساب المدفوع مسبقًا ، وليس بالعملات الرقمية.", + "use_ssl": "استخدم SSL", + "use_suggested": "استخدام المقترح", + "variable_pair_not_supported": "هذا الزوج المتغير غير مدعوم في التبادلات المحددة", + "verification": "تَحَقّق", + "verify_with_2fa": "تحقق مع Cake 2FA", + "version": "الإصدار ${currentVersion}", + "view_all": "مشاهدة الكل", + "view_in_block_explorer": "عرض في Block Explorer", + "view_key_private": "مفتاح العرض (خاص)", + "view_key_public": "مفتاح العرض (عام)", + "view_transaction_on": "عرض العملية على", + "wallet_keys": "سييد المحفظة / المفاتيح", + "wallet_list_create_new_wallet": "إنشاء محفظة جديدة", + "wallet_list_edit_wallet": "تحرير المحفظة", + "wallet_list_failed_to_load": "فشل تحميل محفظة ${wallet_name}. ${error}", + "wallet_list_failed_to_remove": "فشلت إزالة محفظة ${wallet_name}. ${error}", + "wallet_list_load_wallet": "تحميل المحفظة", + "wallet_list_loading_wallet": "جار تحميل محفظة ${wallet_name}", + "wallet_list_removing_wallet": "يتم إزالة محفظة ${wallet_name}", + "wallet_list_restore_wallet": "استعادة المحفظة", + "wallet_list_title": "محفظة Monero", + "wallet_list_wallet_name": "اسم المحفظة", + "wallet_menu": "قائمة", + "wallet_name": "اسم المحفظة", + "wallet_name_exists": "توجد بالفعل محفظة بهذا الاسم. الرجاء اختيار اسم مختلف أو إعادة تسمية المحفظة الأخرى أولاً.", + "wallet_restoration_store_incorrect_seed_length": "طول السييد غير صحيح", + "wallet_seed": "سييد المحفظة", + "wallet_seed_legacy": "بذرة محفظة قديمة", + "wallet_store_monero_wallet": "محفظة Monero", + "walletConnect": "WalletConnect", + "wallets": "المحافظ", + "warning": "تحذير", + "welcome": "مرحبا بك في", + "welcome_to_cakepay": "مرحبا بكم في Cake Pay!", + "widgets_address": "عنوان", + "widgets_or": "أو", + "widgets_restore_from_blockheight": "استعادة من ارتفاع البلوك", + "widgets_restore_from_date": "استعادة من التاريخ", + "widgets_seed": "سييد", + "wouoldLikeToConnect": "ﻝﺎﺼﺗﻻﺍ ﻲﻓ ﺐﻏﺮﺗ", + "write_down_backup_password": "يرجى كتابة كلمة المرور الاحتياطية الخاصة بك ، والتي يتم استخدامها لاستيراد ملفات النسخ الاحتياطي الخاصة بك.", + "xlm_extra_info": "من فضلك لا تنس تحديد معرّف المذكرة أثناء إرسال معاملة XLM للتبادل", + "xmr_available_balance": "الرصيد المتوفر", + "xmr_full_balance": "الرصيد الكامل", + "xmr_hidden": "مختفي", + "xmr_to_error": "خطأ XMR.TO", + "xmr_to_error_description": "مبلغ غير صحيح. الحد الأقصى 8 أرقام بعد الفاصلة العشرية", + "xrp_extra_info": "من فضلك لا تنس تحديد علامة الوجهة أثناء إرسال معاملة XRP للتبادل", + "yat": "Yat", + "yat_address": "عنوان Yat", + "yat_alert_content": "يمكن لمستخدمي Cake Wallet الآن إرسال واستلام جميع عملاتهم المفضلة باستخدام اسم مستخدم فريد من نوعه قائم على الرموز التعبيرية.", + "yat_alert_title": "أرسل واستقبل العملات المشفرة بسهولة أكبر مع Yat", + "yat_error": "خطأ Yat", + "yat_error_content": "لا توجد عناوين مرتبطة بهذا Yat. جرب يات آخر", + "yat_popup_content": "يمكنك الآن إرسال واستلام العملات المشفرة في Cake Wallet باستخدام Yat - اسم مستخدم قصير يعتمد على الرموز التعبيرية. إدارة Yats في أي وقت على شاشة الإعدادات", + "yat_popup_title": "يمكن تحويل عنوان محفظتك إلى رموز تعبيرية.", + "yesterday": "الامس", + "you_now_have_debit_card": "لديك الآن بطاقة ائتمان", + "you_pay": "انت تدفع", + "you_will_get": "حول الى", + "you_will_send": "تحويل من", + "yy": "YY", + "zzzz": "ززز" +} \ No newline at end of file diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 58c27d5e8..783f83d55 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -1,771 +1,772 @@ { - "welcome": "Добре дошли в", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Невероятен портфейл за Monero, Bitcoin, Ethereum, Litecoin и Haven", - "please_make_selection": "Моля, изберете отдолу за създаване или възстановяване на портфейл.", - "create_new": "Създаване на нов портфейл", - "restore_wallet": "Възстановяване на портфейл", - "monero_com": "Monero.com от Cake Wallet", - "monero_com_wallet_text": "Невероятен портфейл за Monero", - "haven_app": "Haven от Cake Wallet", - "haven_app_wallet_text": "Невероятен портфейл за Haven", - "accounts": "Профили", - "edit": "Промени", + "about_cake_pay": "Cake Pay Ви позволява лесно да купувате предплатени карти, които веднага могат да се използват с над 150,000 търговци на територията на САЩ.", "account": "Профил", + "accounts": "Профили", + "accounts_subaddresses": "Профили и подадреси", + "activate": "Активиране", + "active": "Активиране", + "active_cards": "Активни карти", + "activeConnectionsPrompt": "Тук ще се появят активни връзки", "add": "Добави", + "add_contact": "Добави контакт", + "add_custom_node": "Добавяне на нов персонализиран Node", + "add_custom_redemption": "Добавете персонализиран Redemption", + "add_fund_to_card": "Добавете предплатени средства в картите (до ${value})", + "add_new_node": "Добави нов node", + "add_new_word": "Добавяне на нова дума", + "add_receiver": "Добавяне на друг получател (не е задължително)", + "add_secret_code": "Или добавете този таен код към приложение за удостоверяване", + "add_tip": "Add Tip", + "add_token_disclaimer_check": "Потвърдих адреса и информацията за токен договора, използвайки надежден източник. Добавянето на злонамерена или неправилна информация може да доведе до загуба на средства.", + "add_token_warning": "Не редактирайте и не добавяйте токени според инструкциите на измамниците.\nВинаги потвърждавайте адресите на токени с надеждни източници!", + "add_value": "Добавяне на стойност", + "address": "Адрес", "address_book": "Адресна книга", - "contact": "Контакт", - "please_select": "Моля, изберете:", - "cancel": "Откажи", - "ok": "Ок", - "contact_name": "Име на контакт", - "reset": "Нулиране", - "save": "Запази", + "address_book_menu": "Адресна книга", + "address_detected": "Открит е адрес", + "address_from_domain": "Този адрес е от ${domain} на Unstoppable Domains", + "address_from_yat": "Този адрес е от ${emoji} в Yat", + "address_label": "Адресен label", "address_remove_contact": "Премахни контакт", "address_remove_content": "Сигурни ли сте, че искате да премахнете избрания контакт?", - "authenticated": "Удостоверено", - "authentication": "Удостоверяване", - "failed_authentication": "Неуспешно удостоверяване. ${state_error}", - "wallet_menu": "Меню", - "Blocks_remaining": "${status} оставащи блока", - "please_try_to_connect_to_another_node": "Моля, опитайте се да се свържете към друг node.", - "xmr_hidden": "Скрит", - "xmr_available_balance": "Наличен баланс", - "xmr_full_balance": "Пълен баланс", - "send": "Изпрати", - "receive": "Получи", - "transactions": "Транзакции", - "incoming": "Входящи", - "outgoing": "Изходящи", - "transactions_by_date": "Транзакции по дата", - "trades": "Trades", - "filter_by": "Филтрирай по", - "today": "Днес", - "yesterday": "Вчера", - "received": "Получени", - "sent": "Изпратени", - "pending": " (чакащи)", - "rescan": "Сканирай отново", - "reconnect": "Reconnect", - "wallets": "Портфейли", - "show_seed": "Покажи seed", - "show_keys": "Покажи seed/keys", - "address_book_menu": "Адресна книга", - "reconnection": "Свързване отново", - "reconnect_alert_text": "Сигурни ли сте, че искате да се свържете отново?", - "exchange": "Exchange", - "clear": "Изчисти", - "refund_address": "Refund address", - "change_exchange_provider": "Промяна на Exchange Provider", - "you_will_send": "Обръщане от", - "you_will_get": "Обръщане в", - "amount_is_guaranteed": "Сумата за получаване е гарантирана", - "amount_is_estimate": "Сумата за получаване е ", - "powered_by": "Powered by ${title}", - "error": "Грешка", - "estimated": "Изчислено", - "min_value": "Мин: ${value} ${currency}", - "max_value": "Макс: ${value} ${currency}", - "change_currency": "Смени валута", - "overwrite_amount": "Промени сума", - "qr_payment_amount": "Този QR код съдържа сума за плащане. Искате ли да промените стойността?", - "copy_id": "Копиране на ID", - "exchange_result_write_down_trade_id": "Моля, запишете trade ID-то, за да продължите.", - "trade_id": "Trade ID:", - "copied_to_clipboard": "Копирано", - "saved_the_trade_id": "Запазих trade ID-то", - "fetching": "Обработване", - "id": "ID: ", - "amount": "Сума: ", - "payment_id": "Payment ID: ", - "status": "Статус: ", - "offer_expires_in": "Предложението изтича след: ", - "trade_is_powered_by": "This trade is powered by ${provider}", - "copy_address": "Copy Address", - "exchange_result_confirm": "By pressing confirm, you will be sending ${fetchingLabel} ${from} from your wallet called ${walletName} to the address shown below. Or you can send from your external wallet to the below address/QR code.\n\nPlease press confirm to continue or go back to change the amounts.", - "exchange_result_description": "You must send a minimum of ${fetchingLabel} ${from} to the address shown on the next page. If you send an amount lower than ${fetchingLabel} ${from} it may not get converted and it may not be refunded.", - "exchange_result_write_down_ID": "*Please copy or write down your ID shown above.", - "confirm": "Потвърждаване", - "confirm_sending": "Потвърждаване на изпращането", - "commit_transaction_amount_fee": "Изпълняване на транзакция\nСума: ${amount}\nТакса: ${fee}", - "sending": "Изпращане", - "transaction_sent": "Сумата е изпратена!", - "expired": "Изтекло", - "time": "${minutes} мин ${seconds} сек", - "send_xmr": "Изпращане на XMR", - "exchange_new_template": "Нов шаблон", - "faq": "FAQ", - "enter_your_pin": "Въведете PIN", - "loading_your_wallet": "Зареждане на портфейл", - "new_wallet": "Нов портфейл", - "wallet_name": "Име на портфейл", - "continue_text": "Напред", - "choose_wallet_currency": "Изберете валута за портфейла:", - "node_new": "Нов Node", - "node_address": "Нов адрес", - "node_port": "Node порт", - "login": "Влизане", - "password": "Парола", - "nodes": "Nodes", - "node_reset_settings_title": "Възстановяване на настройки", - "nodes_list_reset_to_default_message": "Сигурни ли сте, че искате да възстановите фабричните настройки?", - "change_current_node": "Сигурни ли сте, че искате да промените сегашния node на ${node}?", - "change": "Промени", - "remove_node": "Премахни node", - "remove_node_message": "Сигурни ли сте, че искате да премахнете избрания node?", - "remove": "Премахни", - "delete": "Изтрий", - "add_new_node": "Добави нов node", - "change_current_node_title": "Промени сегашния node", - "node_test": "Тест", - "node_connection_successful": "Връзката бе установена успешно", - "node_connection_failed": "Връзката не можа да бъде установена", - "new_node_testing": "Тестване на нов node", - "use": "Смяна на ", - "digit_pin": "-цифрен PIN", - "share_address": "Сподели адрес", - "receive_amount": "Сума", - "subaddresses": "Подадреси", "addresses": "Адреси", - "scan_qr_code": "Сканирайте QR кода, за да получите адреса", - "qr_fullscreen": "Натиснете, за да отворите QR кода на цял екран", - "rename": "Промяна на името", - "choose_account": "Избиране на профил", - "create_new_account": "Създаване на нов профил", - "accounts_subaddresses": "Профили и подадреси", - "restore_restore_wallet": "Възстановяване на портфейл", - "restore_title_from_seed_keys": "Възстановяване от seed/keys", - "restore_description_from_seed_keys": "Възстановете своя портфейл от seed/keys, които сте съхранили на сигурно място", - "restore_next": "Next", - "restore_title_from_backup": "Възстановяване от резервно копие", - "restore_description_from_backup": "Можете да възстановите цялото приложение Cake Wallet от своя резервен файл", - "restore_seed_keys_restore": "Възстановяне от Seed/Keys", - "restore_title_from_seed": "Възстановяване от seed", - "restore_description_from_seed": "Възстановяване на портфейл от кода от 13 или 25 думи", - "restore_title_from_keys": "Възстановяване от keys", - "restore_description_from_keys": "Възстановяване на портфейл от генерираните от Вашите тайни ключове клавиши", - "restore_wallet_name": "Име на портфейл", - "restore_address": "Адреси", - "restore_view_key_private": "View key (таен)", - "restore_spend_key_private": "Spend key (публичен)", - "restore_recover": "Възстановяване", - "restore_wallet_restore_description": "Описание на възстановяване на портфейл", - "restore_new_seed": "Нов seed", - "restore_active_seed": "Активиране на seed", - "restore_bitcoin_description_from_seed": "Възстановяване на портфейл чрез код от 24 думи", - "restore_bitcoin_description_from_keys": "Възстановяване на портфейл чрез WIF, изведен от Вашите private keys", - "restore_bitcoin_title_from_keys": "Възстановяване от WIF", - "restore_from_date_or_blockheight": "Моля, въведете дата няколко дни преди създаването на този портфейл. Ако знаете blockheight-а, въведето него вместо това", - "seed_reminder": "Моля, запишете го в случай на загуба на устройството.", - "seed_title": "Seed", - "seed_share": "Споделяне на seed", - "copy": "Копиране", - "seed_language": "Език на семената", - "seed_choose": "Изберете език на seed-а", - "seed_language_next": "Следващ", - "seed_language_english": "Английски", - "seed_language_chinese": "Китайски", - "seed_language_dutch": "Нидерландски", - "seed_language_german": "Немски", - "seed_language_japanese": "Японски", - "seed_language_portuguese": "Португалски", - "seed_language_russian": "Руски", - "seed_language_spanish": "Испански", - "seed_language_french": "Френски", - "seed_language_italian": "Италиански", - "send_title": "Изпращане", - "send_your_wallet": "Вашият портфейл", - "send_address": "${cryptoCurrency} адрес", - "send_payment_id": "Payment ID (не е задължително)", + "advanced_settings": "Разширени настройки", + "aggressive": "Прекалено усърден", + "agree": "Съгласен/а съм", + "agree_and_continue": "Съгласяване и продължаване", + "agree_to": "Чрез създаването на акаунт вие се съгласявате с ", "all": "ALL", - "send_error_minimum_value": "Минималната сума е 0.01", - "send_error_currency": "Валутата може да съдържа само числа", - "send_estimated_fee": "Изчислена такса:", - "send_priority": "В момента таксата е на ${transactionPriority} приоритетност.\nПриоритетността на транзакцията може да бъде променена в настройките", - "send_creating_transaction": "Създаване на транзакция", - "send_templates": "Шаблони", - "send_new": "Ново", - "send_amount": "Сума:", - "send_fee": "Такса:", - "send_name": "Име", - "got_it": "Готово", - "send_sending": "Изпращане...", - "send_success": "Вашите ${crypto} бяха успешно изпратени", - "settings_title": "Настройки", - "settings_nodes": "Nodes", - "settings_current_node": "Сегашен node", - "settings_wallets": "Портфейли", - "settings_display_balance": "Показване на баланс", - "settings_currency": "Валута", - "settings_fee_priority": "Таксова приоритетност", - "settings_save_recipient_address": "Запазване адрес на получател", - "settings_personal": "Лични", - "settings_change_pin": "Промяна на PIN", - "settings_change_language": "Промяна на езика", - "settings_allow_biometrical_authentication": "Позволяване на биометрично удостоверяване.", - "settings_dark_mode": "Тъмен режим", - "settings_transactions": "Транзакции", - "settings_trades": "Сделки", - "settings_display_on_dashboard_list": "Показване на таблото", - "settings_all": "Всичко", - "settings_only_trades": "Само сделки", - "settings_only_transactions": "Само транзакции", - "settings_none": "Липсва", - "settings_support": "Поддръжка", - "settings_terms_and_conditions": "Условия", - "pin_is_incorrect": "Грешен PIN", - "setup_pin": "Настройване на PIN", - "enter_your_pin_again": "Въведете своя PIN отново", - "setup_successful": "Вашият PIN бе успешно настроен!", - "wallet_keys": "Seed/keys на портфейла", - "wallet_seed": "Seed на портфейла", - "private_key": "Таен ключ", - "public_key": "Публичен ключ", - "view_key_private": "View key (таен)", - "view_key_public": "View key (публичен)", - "spend_key_private": "Spend key (таен)", - "spend_key_public": "Spend key (публичен)", - "copied_key_to_clipboard": "Копиран ключ: ${key}", - "new_subaddress_title": "Нов адрес", - "new_subaddress_label_name": "Име на Label", - "new_subaddress_create": "Създаване", - "address_label": "Адресен label", - "subaddress_title": "Лист от подадреси", - "trade_details_title": "Подробности на сделката", - "trade_details_id": "ID", - "trade_details_state": "Статус", - "trade_details_fetching": "Обработка", - "trade_details_provider": "Provider", - "trade_details_created_at": "Създадено", - "trade_details_pair": "Pair", - "trade_details_copied": "${title} копирано", - "trade_history_title": "История на сделките", - "transaction_details_title": "Подробности на транзакцията", - "transaction_details_transaction_id": "Transaction ID", - "transaction_details_date": "Дата", - "transaction_details_height": "Height", - "transaction_details_amount": "Сума", - "transaction_details_fee": "Такса", - "transaction_details_copied": "${title} копирано", - "transaction_details_recipient_address": "Адрес на получател", - "wallet_list_title": "Monero портфейл", - "wallet_list_create_new_wallet": "Създаване на нов портфейл", - "wallet_list_edit_wallet": "Редактиране на портфейла", - "wallet_list_wallet_name": "Име на портфейла", - "wallet_list_restore_wallet": "Възстановяване на портфейл", - "wallet_list_load_wallet": "Зареждане на портфейл", - "wallet_list_loading_wallet": "Зареждане на портфейл ${wallet_name}", - "wallet_list_failed_to_load": "Грешка при зареждането на портфейл ${wallet_name}. ${error}", - "wallet_list_removing_wallet": "Премахване на портфейл ${wallet_name}", - "wallet_list_failed_to_remove": "Грешка при премахването на портфейл${wallet_name}. ${error}", - "widgets_address": "Адрес", - "widgets_restore_from_blockheight": "Възстановяване от blockheight", - "widgets_restore_from_date": "Възстановяване от дата", - "widgets_or": "или", - "widgets_seed": "Seed", - "router_no_route": "Няма дефиниран път за ${name}", - "error_text_account_name": "Името на профила може да съдържа само букви и числа \nи трябва да е между 1 и 15 символа", - "error_text_contact_name": "Името на контакта не може да съдържа символите ` , ' \" \nи и трябва да е между 1 и 32 символа", - "error_text_address": "Адресът на портфейла трябва да отговаря \n на вида криптовалута", - "error_text_node_address": "Моля, въведете iPv4 адрес", - "error_text_node_port": "Node port-ът е цяло число между 0 и 65535", - "error_text_node_proxy_address": "Моля, въведете :<порт>, например 127.0.0.1:9050", - "error_text_payment_id": "Payment ID-то може да съдържа само между 16 и 64 шестнайсетични символа", - "error_text_xmr": "XMR сумата не може да надхвърля наличния баланс.\nБроят на цифрите след десетичната запетая може да бъде най-много 12", - "error_text_fiat": "Сумата не може да надвишава наличния баланс.\nThe number of fraction digits must be less or equal to 2", - "error_text_subaddress_name": "Името на подадреса не може да съдържат символите ` , ' \" \n и трябва да е между 1 и 20 символа", - "error_text_amount": "Сумата може да съдържа само числа", - "error_text_wallet_name": "Името на портфейла може да съдържа само букви, цифри, и символите _ и - \n и трябва да е между 1 и 33 символа", - "error_text_keys": "Ключовете за портфейл може да съдържат само 64 шестнайсетични символа", - "error_text_crypto_currency": "Броят на цифрите след десетичната запетая\nможе да бъде най-много 12", - "error_text_minimal_limit": "Сделка за ${provider} не беше създадена. Сумата е по-малко от минималната: ${min} ${currency}", - "error_text_maximum_limit": "Сделка за ${provider} не беше създадена. Сумата надвишава максималната: ${max} ${currency}", - "error_text_limits_loading_failed": "Сделка за ${provider} не беше създадена. Неуспешно зареждане на лимити", - "error_text_template": "Имената на шаблони и адреси не могат да съдържат ` , ' \" \nи трябва да са между 1 и 106 символа.", + "all_trades": "Всички сделкки", + "all_transactions": "Всички транзакции", + "alphabetical": "Азбучен ред", + "already_have_account": "Вече имате профил?", + "always": "Винаги", + "amount": "Сума: ", + "amount_is_estimate": "Сумата за получаване е ", + "amount_is_guaranteed": "Сумата за получаване е гарантирана", + "and": "и", + "anonpay_description": "Генерирайте ${type}. Получателят може да ${method} с всяка поддържана криптовалута и вие ще получите средства в този портфейл.", + "apk_update": "APK ъпдейт", + "approve": "Одобряване", + "arrive_in_this_address": "${currency} ${tag}ще отидат на този адрес", + "ascending": "Възходящ", + "ask_each_time": "Питайте всеки път", "auth_store_ban_timeout": "ban_timeout", "auth_store_banned_for": "Забрана за ", "auth_store_banned_minutes": " минути", "auth_store_incorrect_password": "Грешен PIN", - "wallet_store_monero_wallet": "Monero портфейл", - "wallet_restoration_store_incorrect_seed_length": "Грешна дължина на seed-а", - "full_balance": "Пълен баланс", - "available_balance": "Наличен баланс", - "hidden_balance": "Скрит баланс", - "sync_status_syncronizing": "СИНХРОНИЗИРАНЕ", - "sync_status_syncronized": "СИНХРОНИЗИРАНО", - "sync_status_not_connected": "НЯМА ВРЪЗКА", - "sync_status_starting_sync": "ЗАПОЧВАНЕ НА СИНХРОНИЗАЦИЯ", - "sync_status_failed_connect": "НЕУСПЕШНО СВЪРЗВАНЕ", - "sync_status_connecting": "СВЪРЗВАНЕ", - "sync_status_connected": "СВЪРЗВАНЕ", - "sync_status_attempting_sync": "ОПИТ ЗА СИНХРОНИЗАЦИЯ", - "transaction_priority_slow": "Бавно", - "transaction_priority_regular": "Обичайно", - "transaction_priority_medium": "Средно", - "transaction_priority_fast": "Бързо", - "transaction_priority_fastest": "Най-бързо", - "trade_for_not_created": "Сделка за ${title} не бе създадена.", - "trade_not_created": "Сделка не бе създадена.", - "trade_id_not_found": "Сделка ${tradeId} на ${title} не бе намерена.", - "trade_not_found": "Сделката не бе намерена.", - "trade_state_pending": "Изчаква се", - "trade_state_confirming": "Потвърждава се", - "trade_state_trading": "Trading", - "trade_state_traded": "Traded", - "trade_state_complete": "Завършено", - "trade_state_to_be_created": "Изчаква създаване", - "trade_state_unpaid": "Неплатено", - "trade_state_underpaid": "Недостатъчно плащане", - "trade_state_paid_unconfirmed": "Непотвърдено плащане", - "trade_state_paid": "Платено", - "trade_state_btc_sent": "Btc изпратен", - "trade_state_timeout": "Време за изчакване", - "trade_state_created": "Създадено", - "trade_state_finished": "Завършено", - "change_language": "Смяна на езика", - "change_language_to": "Смяна на езика на ${language}?", - "paste": "Поставяне", - "restore_from_seed_placeholder": "Моля, въведете своя seed тук", - "add_new_word": "Добавяне на нова дума", - "incorrect_seed": "Въведеният текст е невалиден.", - "biometric_auth_reason": "Сканирайте своя пръстов отпечатък", - "version": "Версия ${currentVersion}", - "extracted_address_content": "Ще изпратите средства на \n${recipient_name}", - "card_address": "Адрес:", - "buy": "Купуване", - "sell": "Продаване", - "placeholder_transactions": "Вашите транзакции ще се покажат тук", - "placeholder_contacts": "Вашите контакти ще се покажат тук", - "template": "Шаблон", - "confirm_delete_template": "Този шаблон ще бъде изтрит. Искате ли да продължите?", - "confirm_delete_wallet": "Този портфейл ще бъде изтрит. Искате ли да продължите?", - "change_wallet_alert_title": "Смяна на сегашния портфейл", - "change_wallet_alert_content": "Искате ли да смените сегашния портфейл на ${wallet_name}?", - "creating_new_wallet": "Създаване на нов портфейл", - "creating_new_wallet_error": "Грешка: ${description}", - "seed_alert_title": "Внимание", - "seed_alert_content": "Seed-ът е единственият начин да възстановите портфейла си. Записахте ли го?", - "seed_alert_back": "Назад", - "seed_alert_yes": "Да", - "exchange_sync_alert_content": "Моля, изчакайте синхронизирането на Вашия портфейл", - "pre_seed_title": "ВАЖНО", - "pre_seed_description": "На следващата страница ще видите поредица от ${words} думи. Това е вашият таен личен seed и е единственият начин да възстановите портфейла си. Отговорността за съхранението му на сигурно място извън приложението на Cake Wallet е изцяло ВАША.", - "pre_seed_button_text": "Разбирам. Покажи seed", - "xmr_to_error": "XMR.TO грешка", - "xmr_to_error_description": "Невалидна сума - най-много 8 цифри след десетичната запетая", - "provider_error": "Грешка на ${provider} ", - "use_ssl": "Използване на SSL", - "trusted": "Надежден", - "color_theme": "Цвят", - "light_theme": "Светло", - "bright_theme": "Ярко", - "dark_theme": "Тъмно", - "enter_your_note": "Въвеждане на бележка…", - "note_optional": "Бележка (не е задължително)", - "note_tap_to_change": "Бележка (натиснете за промяна)", - "view_in_block_explorer": "Вижте в Block Explorer", - "view_transaction_on": "Вижте транзакция на ", - "transaction_key": "Transaction Key", - "confirmations": "потвърждения", - "recipient_address": "Адрес на получател", - "extra_id": "Допълнително ID:", - "destination_tag": "Destination tag:", - "memo": "Мемо:", - "backup": "Резервно копие", - "change_password": "Смяна на парола", - "backup_password": "Парола за възстановяване", - "write_down_backup_password": "Моля, запишете своята парола за възстановяване. Тя се използва за импортиране на резервни копия на Вашите файлове.", - "export_backup": "Експортиране на резервно копие", - "save_backup_password": "Моля, запишете своята парола за възстановяване. Импортирането на резервни копия не е възможно без нея.", - "backup_file": "Резервно копие", - "edit_backup_password": "Промяна на паролата за възстановяване", - "save_backup_password_alert": "Запазване на паролата за възстановяване", - "change_backup_password_alert": "Предишните резервни копия не могат да бъдат импортирани с новата парола. Те ще се използва само за нови такива. Are you sure that you want to change backup password?", - "enter_backup_password": "Въведете парола за възстановяване", - "select_backup_file": "Избор на резервно копие", - "import": "Импортиране", - "please_select_backup_file": "Моля, изберете резервно копие и въведете парола за възстановяване.", - "fixed_rate": "Постоянен обменен курс", - "fixed_rate_alert": "Ще можете да въведете сумата за получаване, когато е избранен постоянен обменен курс. Искате ли да изберете постоянен обменен курс?", - "xlm_extra_info": "Не забравяйте да дадете Memo ID-то, докато изпращате XLM транзакцията за обмена", - "xrp_extra_info": "Не забравяйте да дадете Destination Tag-а, когато изпращате XRP транзакцията за обмена", - "exchange_incorrect_current_wallet_for_xmr": "Ако искате да обмените XMR от своя Cake Wallet Monero баланс, първо изберете своя Monero портфейл.", - "confirmed": "Потвърден баланс", - "unconfirmed": "Непотвърден баланс", - "displayable": "Възможност за показване", - "submit_request": "изпращане на заявка", - "buy_alert_content": "В момента поддържаме само закупуването на Bitcoin, Ethereum, Litecoin и Monero. Моля, създайте или превключете към своя портфейл Bitcoin, Ethereum, Litecoin или Monero.", - "sell_alert_content": "В момента поддържаме само продажбата на Bitcoin, Ethereum и Litecoin. Моля, създайте или превключете към своя портфейл Bitcoin, Ethereum или Litecoin.", - "outdated_electrum_wallet_description": "Нови Bitcoin портфейли, създадени в Cake, сега имат seed от 24 думи. Трябва да създадете нов Bitcoin адрес и да прехвърлите всичките си средства в него и веднага да спрете използването на стари портфейли. Моля, напревете това незабавно, за да подсигурите средствата си.", - "understand": "Разбирам", - "apk_update": "APK ъпдейт", - "buy_bitcoin": "Купуване на Bitcoin", - "buy_with": "Купуване чрез", - "moonpay_alert_text": "Сумата трябва да бъде най-малко ${minAmount} ${fiatCurrency}", - "outdated_electrum_wallet_receive_warning": "Ако този адрес има seed от 12 думи и е създаден чрез Cake, НЕ добавяйте Bitcoin в него. Всякакъв Bitcoin, изпратен на този адрес, може да бъде загубен завинаги. Създайте нов портфейл от 24 думи (натиснете менюто горе, вдясно, изберете Портфейли, изберете Създаване на нов портфейл, след това изберете Bitcoin) и НЕЗАБАВНО преместете своя Bitcoin там. Нови (такива с 24 думи) Bitcoin портфейли от Cake са надеждни", - "do_not_show_me": "Не показвай повече това", - "unspent_coins_title": "Неизползвани монети", - "unspent_coins_details_title": "Подробности за неизползваните монети", - "freeze": "Замразяване", - "frozen": "Замразени", - "coin_control": "Управление на монетите (не е задължително)", - "address_detected": "Открит е адрес", - "address_from_domain": "Този адрес е от ${domain} на Unstoppable Domains", - "add_receiver": "Добавяне на друг получател (не е задължително)", - "manage_yats": "Управление на Yats", - "yat_alert_title": "Търгувайте с крипто много по-лесно чрез Yat", - "yat_alert_content": "Потребителите на Cake Wallet вече могат да изпращат и получават любимите си валути чрез неповторимо потребителско име от емоджита.", - "get_your_yat": "Получете своя Yat", - "connect_an_existing_yat": "Добавете съществуващ Yat", - "connect_yats": "Добавете Yats", - "yat_address": "Yat Адрес", - "yat": "Yat", - "address_from_yat": "Този адрес е от ${emoji} в Yat", - "yat_error": "Yat грешка", - "yat_error_content": "Няма адреси, свързани с този Yat. Опитайте с друг Yat", - "choose_address": "\n\nМоля, изберете адреса:", - "yat_popup_title": "Адресът на вашия портфейл може да съдържа емоджита.", - "yat_popup_content": "Вече можете да изпращате и да получавате крипто в Cake Wallet с вашия Yat - кратко потребителско име във формата на емоджи. Управлявайте своите Yats по всяко време в настройките", - "second_intro_title": "Един емоджи адрес, обединяващ всички останали.", - "second_intro_content": "Вашият Yat е уникален адрес във формата на емоджи, който играе ролята на всички Ваши дълги шестнайсетични портфейли за всяка валута.", - "third_intro_title": "Yat добре се сработва с други", - "third_intro_content": "Yats също живее извън Cake Wallet. Всеки адрес на портфейл може да бъде заменен с Yat!", - "learn_more": "Научете още", - "search": "Търсене", - "search_language": "Търсене на език", - "search_currency": "Търсене на валута", - "new_template": "Нов шаблон", - "electrum_address_disclaimer": "Нови адреси се генерират всеки път, когато използвате този, но и предишните продължават да работят", - "wallet_name_exists": "Вече има портфейл с това име. Моля, изберете друго име или преименувайте другия портфейл.", - "market_place": "Магазин", - "cake_pay_title": "Cake Pay Gift Карти", - "cake_pay_subtitle": "Купете гифткарти на намалени цени (само за САЩ)", - "cake_pay_web_cards_title": "Cake Pay Онлайн Карти", - "cake_pay_web_cards_subtitle": "Купете световно признати предплатени и гифт карти", - "about_cake_pay": "Cake Pay Ви позволява лесно да купувате предплатени карти, които веднага могат да се използват с над 150,000 търговци на територията на САЩ.", - "cake_pay_account_note": "Регистрайте се само с един имейл, за да виждате и купувате карти. За някои има дори и отстъпка!", - "already_have_account": "Вече имате профил?", - "create_account": "Създаване на профил", - "privacy_policy": "Политика за поверителността", - "welcome_to_cakepay": "Добре дошли в Cake Pay!", - "sign_up": "Регистрация", - "forgot_password": "Забравена парола", - "reset_password": "Нулиране на парола", - "gift_cards": "Gift Карти", - "setup_your_debit_card": "Настройте своята дебитна карта", - "no_id_required": "Без нужда от документ за самоличност. Използвайте навсякъде", - "how_to_use_card": "Как се ползва тази карта", - "purchase_gift_card": "Купуване на Gift Card", - "verification": "Потвърждаване", - "fill_code": "Моля, въведето кода за потвърждаване, изпратен на Вашия имейл", - "didnt_get_code": "Не получихте код?", - "resend_code": "Повторно изпращане", - "debit_card": "Дебитна карта", - "cakepay_prepaid_card": "CakePay предплатена дебитна карта", - "no_id_needed": "Без нужда от документ за самоличност!", - "frequently_asked_questions": "Често задавани въпроси", - "debit_card_terms": "Съхранението и използването на данните от вашата платежна карта в този дигитален портфейл подлежат на условията на съответното съгласие за картодържец от издателя на картата.", - "please_reference_document": "Моля, вижте документите по-долу за повече информация.", - "cardholder_agreement": "Съгласие за картодържец", - "e_sign_consent": "E-Sign съгласие", - "agree_and_continue": "Съгласяване и продължаване", - "email_address": "Имейл адрес", - "agree_to": "Чрез създаването на акаунт вие се съгласявате с ", - "and": "и", - "enter_code": "Въведете код", - "congratulations": "Поздравления!", - "you_now_have_debit_card": "Вече имате дебитна карта", - "min_amount": "Мин: ${value}", - "max_amount": "Макс: ${value}", - "enter_amount": "Въведете сума", - "billing_address_info": "Ако Ви попитат за билинг адрес, въведето своя адрес за доставка", - "order_physical_card": "Поръчка на физическа карта", - "add_value": "Добавяне на стойност", - "activate": "Активиране", - "get_a": "Вземете ", - "digital_and_physical_card": " дигитална или физическа предплатена дебитна карта", - "get_card_note": ", която можете да заредите с дигитална валута. Без нужда от допълнителна информация!", - "signup_for_card_accept_terms": "Регистрайте се за картата и приемете условията.", - "add_fund_to_card": "Добавете предплатени средства в картите (до ${value})", - "use_card_info_two": "Средствата се обръщат в USD, когато биват запазени в предплатената карта, а не в дигитална валута.", - "use_card_info_three": "Използвайте дигиталната карта онлайн или чрез безконтактен метод на плащане.", - "optionally_order_card": "По желание поръчайте и физическа карта.", - "hide_details": "Скриване на подробностите", - "show_details": "Показване на подробностите", - "upto": "до ${value}", - "discount": "Спестете ${value}%", - "gift_card_amount": "Сума в Gift Card", - "bill_amount": "Искана сума", - "you_pay": "Вие плащате", - "tip": "Tip:", - "custom": "персонализирано", - "by_cake_pay": "от Cake Pay", - "expires": "Изтича", - "mm": "мм", - "yy": "гг", - "online": "Онлайн", - "offline": "Офлайн", - "gift_card_number": "Номер на Gift Card", - "pin_number": "PIN код", - "total_saving": "Общо спестявания", - "last_30_days": "Последните 30 дни", - "avg_savings": "Средни спестявания", - "view_all": "Виж всички", - "active_cards": "Активни карти", - "delete_account": "Изтриване на акаунт", - "cards": "Карти", - "active": "Активиране", - "redeemed": "Използвани", - "gift_card_balance_note": "Гифткарти с наличен баланс ще се покажат тук", - "gift_card_redeemed_note": "Използваните гифткарти ще се покажат тук", - "logout": "Logout", - "add_tip": "Add Tip", - "percentageOf": "от ${amount}", - "is_percentage": "е", - "search_category": "Търсене в категория", - "mark_as_redeemed": "Отбележи като използван", - "more_options": "Още настройки", - "awaiting_payment_confirmation": "Чака се потвърждение на плащането", - "transaction_sent_notice": "Ако процесът продължи повече от 1 минута, проверете някой block explorer и своя имейл.", - "agree": "Съгласен/а съм", - "in_store": "In Store", - "generating_gift_card": "Създаване на Gift Card", - "payment_was_received": "Плащането бе получено.", - "proceed_after_one_minute": "Ако процесът продължи повече от 1 минута, проверете своя имейл.", - "order_id": "ID на поръчка", - "gift_card_is_generated": "Gift Card бе създадена", - "open_gift_card": "Отвори Gift Card", - "contact_support": "Свържи се с отдел поддръжка", - "gift_cards_unavailable": "В момента гифткарти могат да бъдат закупени само с Monero, Bitcoin и Litecoin", - "introducing_cake_pay": "Запознайте се с Cake Pay!", - "cake_pay_learn_more": "Купете и използвайте гифткарти директно в приложението!\nПлъзнете отляво надясно, за да научите още.", - "automatic": "Автоматично", - "fixed_pair_not_supported": "Този fixed pair не се поддържа от избраната борса", - "variable_pair_not_supported": "Този variable pair не се поддържа от избраната борса", - "none_of_selected_providers_can_exchange": "Нито един от избраните provider-ъри не може да направи този превод", - "choose_one": "Изберете едно", - "choose_from_available_options": "Изберете от следните опции:", - "custom_redeem_amount": "Персонализирана сума за използване", - "add_custom_redemption": "Добавете персонализиран Redemption", - "remaining": "оставащи", - "delete_wallet": "Изтриване на портфейл", - "delete_wallet_confirm_message": "Сигурни ли сте, че искате да изтриете протфейла ${wallet_name}?", - "low_fee": "Ниска такса", - "low_fee_alert": "Използвате ниска приоритетност в мрежата. Това може да доведе до дълго чакане, различни обменни курсове или отказани сделки. Препоръчваме използването на по-висока такса.", - "ignor": "Игнориране", - "use_suggested": "Използване на предложеното", - "do_not_share_warning_text": "Не споделяйте това с никого, дори и отдел поддръжка.\n\nПарите Ви могат и ще бъдат откраднати!", - "help": "Помощ", - "all_transactions": "Всички транзакции", - "all_trades": "Всички сделкки", - "connection_sync": "Свързване и синхронизиране", - "security_and_backup": "Сигурност и резервни копия", - "create_backup": "Създаване на резервно копие", - "privacy_settings": "Настройки за поверителност", - "privacy": "Поверителност", - "display_settings": "Настройки на екрана", - "other_settings": "Други настройки", - "require_pin_after": "Въведете PIN след", - "always": "Винаги", - "minutes_to_pin_code": "${minute} минути", - "disable_exchange": "Деактивиране на борса", - "advanced_settings": "Разширени настройки", - "settings_can_be_changed_later": "Тези настройки могат да бъдат променени по-късно от приложението", - "add_custom_node": "Добавяне на нов персонализиран Node", - "disable_fiat": "Деактивиране на fiat", - "fiat_api": "Fiat API", - "disabled": "Деактивирано", - "enabled": "Активирано", - "tor_only": "Само чрез Tor", - "unmatched_currencies": "Валутата на този портфейл не съвпада с тази от сканирания QR код", - "orbot_running_alert": "Моля, включете Orbot преди да свържете към този node.", - "contact_list_contacts": "Контакти", - "contact_list_wallets": "Моите портфейли", - "bitcoin_payments_require_1_confirmation": "Плащанията с Bitcoin изискват потвърждение, което може да отнеме 20 минути или повече. Благодарим за търпението! Ще получите имейл, когато плащането е потвърдено.", - "send_to_this_address": "Send ${currency} ${tag}to this address", - "arrive_in_this_address": "${currency} ${tag}ще отидат на този адрес", - "do_not_send": "Не изпращай", - "error_dialog_content": "Получихме грешка.\n\nМоля, изпратете доклада до нашия отдел поддръжка, за да подобрим приложението.", - "decimal_places_error": "Твърде много знаци след десетичната запетая", - "edit_node": "Редактиране на възел", - "invoice_details": "IДанни за фактура", - "donation_link_details": "Подробности за връзката за дарение", - "anonpay_description": "Генерирайте ${type}. Получателят може да ${method} с всяка поддържана криптовалута и вие ще получите средства в този портфейл.", - "create_invoice": "Създайте фактура", - "create_donation_link": "Създайте връзка за дарение", - "optional_email_hint": "Незадължителен имейл за уведомяване на получателя", - "optional_description": "Описание по избор", - "optional_name": "Незадължително име на получател", - "clearnet_link": "Clearnet връзка", - "onion_link": "Лукова връзка", - "sell_monero_com_alert_content": "Продажбата на Monero все още не се поддържа", - "error_text_input_below_minimum_limit": "Сумата е по-малко от минималната", - "error_text_input_above_maximum_limit": "Сумата надвишава максималната", - "show_market_place": "Покажи пазар", - "prevent_screenshots": "Предотвратете екранни снимки и запис на екрана", - "profile": "Профил", - "close": "затвори", - "modify_2fa": "Модифициране на тортата 2FA", - "disable_cake_2fa": "Деактивирайте Cake 2FA", - "question_to_disable_2fa": "Сигурни ли сте, че искате да деактивирате Cake 2FA? Вече няма да е необходим 2FA код за достъп до портфейла и определени функции.", - "disable": "Деактивиране", - "setup_2fa": "Настройка на Cake 2FA", - "verify_with_2fa": "Проверете с Cake 2FA", - "totp_code": "TOTP код", - "please_fill_totp": "Моля, попълнете 8-цифрения код на другото ви устройство", - "totp_2fa_success": "Успех! Cake 2FA е активиран за този портфейл. Не забравяйте да запазите мнемоничното начало, в случай че загубите достъп до портфейла.", - "totp_verification_success": "Проверката е успешна!", - "totp_2fa_failure": "Грешен код. Моля, опитайте с различен код или генерирайте нов таен ключ. Използвайте съвместимо 2FA приложение, което поддържа 8-цифрени кодове и SHA512.", - "enter_totp_code": "Моля, въведете TOTP кода.", - "add_secret_code": "Или добавете този таен код към приложение за удостоверяване", - "totp_secret_code": "TOTP таен код", - "setup_2fa_text": "Cake 2FA работи с помощта на TOTP като втори фактор за удостоверяване.\n\nTOTP на Cake 2FA изисква SHA-512 и поддръжка на 8 цифри; това осигурява повишена сигурност. Повече информация и поддържани приложения можете да намерите в ръководството.", - "setup_totp_recommended": "Настройка на TOTP", - "disable_buy": "Деактивирайте действието за покупка", - "disable_sell": "Деактивирайте действието за продажба", + "authenticated": "Удостоверено", + "authentication": "Удостоверяване", "auto_generate_subaddresses": "Автоматично генериране на подадреси", - "cake_2fa_preset": "Торта 2FA Preset", - "narrow": "Тесен", - "normal": "нормално", - "aggressive": "Прекалено усърден", - "require_for_assessing_wallet": "Изискване за достъп до портфейла", - "require_for_sends_to_non_contacts": "Изискване за изпращане до лица без контакт", - "require_for_sends_to_contacts": "Изискване за изпращане до контакти", - "require_for_sends_to_internal_wallets": "Изискване за изпращане до вътрешни портфейли", - "require_for_exchanges_to_internal_wallets": "Изискване за обмен към вътрешни портфейли", - "require_for_adding_contacts": "Изисква се за добавяне на контакти", - "require_for_creating_new_wallets": "Изискване за създаване на нови портфейли", - "require_for_all_security_and_backup_settings": "Изисква се за всички настройки за сигурност и архивиране", + "automatic": "Автоматично", + "available_balance": "Наличен баланс", "available_balance_description": "Това е балансът, който можете да използвате за покупка на криптовалути. Това не включва замразените средства.", - "syncing_wallet_alert_title": "Вашият портфейл се синхронизира", - "syncing_wallet_alert_content": "Списъкът ви с баланс и транзакции може да не е пълен, докато в горната част не пише „СИНХРОНИЗИРАН“. Кликнете/докоснете, за да научите повече.", - "home_screen_settings": "Настройки на началния екран", - "sort_by": "Сортирай по", - "search_add_token": "Търсене/Добавяне на токен", - "edit_token": "Редактиране на токена", - "warning": "Внимание", - "add_token_warning": "Не редактирайте и не добавяйте токени според инструкциите на измамниците.\nВинаги потвърждавайте адресите на токени с надеждни източници!", - "add_token_disclaimer_check": "Потвърдих адреса и информацията за токен договора, използвайки надежден източник. Добавянето на злонамерена или неправилна информация може да доведе до загуба на средства.", - "token_contract_address": "Адрес на токен договор", - "token_name": "Име на токена, напр.: Tether", - "token_symbol": "Символ на токена, напр.: USDT", - "token_decimal": "Токен десетичен", - "field_required": "Това поле е задължително", - "pin_at_top": "закачете ${token} отгоре", - "invalid_input": "Невалиден вход", - "fiat_balance": "Фиат Баланс", - "gross_balance": "Брутен баланс", - "alphabetical": "Азбучен ред", - "generate_name": "Генериране на име", + "avg_savings": "Средни спестявания", + "awaitDAppProcessing": "Моля, изчакайте dApp да завърши обработката.", + "awaiting_payment_confirmation": "Чака се потвърждение на плащането", + "backup": "Резервно копие", + "backup_file": "Резервно копие", + "backup_password": "Парола за възстановяване", "balance_page": "Страница за баланс", - "share": "Дял", - "slidable": "Плъзгащ се", - "monero_dark_theme": "Тъмна тема Monero", + "bill_amount": "Искана сума", + "billing_address_info": "Ако Ви попитат за билинг адрес, въведето своя адрес за доставка", + "biometric_auth_reason": "Сканирайте своя пръстов отпечатък", "bitcoin_dark_theme": "Тъмна тема за биткойн", "bitcoin_light_theme": "Лека биткойн тема", - "high_contrast_theme": "Тема с висок контраст", - "matrix_green_dark_theme": "Зелена тъмна тема Matrix", - "monero_light_theme": "Лека тема Monero", - "etherscan_history": "История на Etherscan", - "template_name": "Име на шаблон", + "bitcoin_payments_require_1_confirmation": "Плащанията с Bitcoin изискват потвърждение, което може да отнеме 20 минути или повече. Благодарим за търпението! Ще получите имейл, когато плащането е потвърдено.", + "Blocks_remaining": "${status} оставащи блока", + "bright_theme": "Ярко", + "buy": "Купуване", + "buy_alert_content": "В момента поддържаме само закупуването на Bitcoin, Ethereum, Litecoin и Monero. Моля, създайте или превключете към своя портфейл Bitcoin, Ethereum, Litecoin или Monero.", + "buy_bitcoin": "Купуване на Bitcoin", + "buy_provider_unavailable": "Понастоящем доставчик не е наличен.", + "buy_with": "Купуване чрез", + "by_cake_pay": "от Cake Pay", + "cake_2fa_preset": "Торта 2FA Preset", + "cake_pay_account_note": "Регистрайте се само с един имейл, за да виждате и купувате карти. За някои има дори и отстъпка!", + "cake_pay_learn_more": "Купете и използвайте гифткарти директно в приложението!\nПлъзнете отляво надясно, за да научите още.", + "cake_pay_subtitle": "Купете гифткарти на намалени цени (само за САЩ)", + "cake_pay_title": "Cake Pay Gift Карти", + "cake_pay_web_cards_subtitle": "Купете световно признати предплатени и гифт карти", + "cake_pay_web_cards_title": "Cake Pay Онлайн Карти", + "cake_wallet": "Cake Wallet", + "cakepay_prepaid_card": "CakePay предплатена дебитна карта", + "camera_consent": "Вашият фотоапарат ще бъде използван за заснемане на изображение с цел идентификация от ${provider}. Моля, проверете тяхната политика за поверителност за подробности.", + "camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.", + "cancel": "Откажи", + "card_address": "Адрес:", + "cardholder_agreement": "Съгласие за картодържец", + "cards": "Карти", + "chains": "Вериги", + "change": "Промени", + "change_backup_password_alert": "Предишните резервни копия не могат да бъдат импортирани с новата парола. Те ще се използва само за нови такива. Are you sure that you want to change backup password?", + "change_currency": "Смени валута", + "change_current_node": "Сигурни ли сте, че искате да промените сегашния node на ${node}?", + "change_current_node_title": "Промени сегашния node", + "change_exchange_provider": "Промяна на Exchange Provider", + "change_language": "Смяна на езика", + "change_language_to": "Смяна на езика на ${language}?", + "change_password": "Смяна на парола", "change_rep": "Смяна на представител", "change_rep_message": "Сигурни ли сте, че искате да смените представителите?", - "manage_nodes": "Управление на възли", - "unsupported_asset": "Не поддържаме това действие за този актив. Моля, създайте или преминете към портфейл от поддържан тип актив.", - "manage_pow_nodes": "Управление на PoW възли", - "support_title_live_chat": "Подкрепа на живо", - "support_description_live_chat": "Безплатно и бързо! Обучени представители на подкрепата са на разположение за подпомагане", - "support_title_guides": "Ръководства за портфейл за торта", - "support_description_guides": "Документация и подкрепа за общи проблеми", - "support_title_other_links": "Други връзки за поддръжка", - "support_description_other_links": "Присъединете се към нашите общности или се свържете с нас нашите партньори чрез други методи", + "change_rep_successful": "Успешно промени представител", + "change_wallet_alert_content": "Искате ли да смените сегашния портфейл на ${wallet_name}?", + "change_wallet_alert_title": "Смяна на сегашния портфейл", + "choose_account": "Избиране на профил", + "choose_address": "\n\nМоля, изберете адреса:", "choose_derivation": "Изберете производно на портфейла", - "new_first_wallet_text": "Лесно пазете криптовалутата си в безопасност", - "select_destination": "Моля, изберете дестинация за архивния файл.", - "save_to_downloads": "Запазване в Изтегляния", - "select_buy_provider_notice": "Изберете доставчик на покупка по -горе. Можете да пропуснете този екран, като зададете вашия доставчик по подразбиране по подразбиране в настройките на приложението.", - "onramper_option_description": "Бързо купувайте криптовалута с много методи за плащане. Предлага се в повечето страни. Разпространенията и таксите варират.", + "choose_from_available_options": "Изберете от следните опции:", + "choose_one": "Изберете едно", + "choose_relay": "Моля, изберете реле, което да използвате", + "choose_wallet_currency": "Изберете валута за портфейла:", + "clear": "Изчисти", + "clearnet_link": "Clearnet връзка", + "close": "затвори", + "coin_control": "Управление на монетите (не е задължително)", + "color_theme": "Цвят", + "commit_transaction_amount_fee": "Изпълняване на транзакция\nСума: ${amount}\nТакса: ${fee}", + "confirm": "Потвърждаване", + "confirm_delete_template": "Този шаблон ще бъде изтрит. Искате ли да продължите?", + "confirm_delete_wallet": "Този портфейл ще бъде изтрит. Искате ли да продължите?", + "confirm_sending": "Потвърждаване на изпращането", + "confirmations": "потвърждения", + "confirmed": "Потвърден баланс", + "confirmed_tx": "Потвърдено", + "congratulations": "Поздравления!", + "connect_an_existing_yat": "Добавете съществуващ Yat", + "connect_yats": "Добавете Yats", + "connection_sync": "Свързване и синхронизиране", + "connectWalletPrompt": "Свържете портфейла си с WalletConnect, за да извършвате транзакции", + "contact": "Контакт", + "contact_list_contacts": "Контакти", + "contact_list_wallets": "Моите портфейли", + "contact_name": "Име на контакт", + "contact_support": "Свържи се с отдел поддръжка", + "continue_text": "Напред", + "contractName": "Име на договора", + "contractSymbol": "Договор Символ", + "copied_key_to_clipboard": "Копиран ключ: ${key}", + "copied_to_clipboard": "Копирано", + "copy": "Копиране", + "copy_address": "Copy Address", + "copy_id": "Копиране на ID", + "copyWalletConnectLink": "Копирайте връзката WalletConnect от dApp и я поставете тук", + "create_account": "Създаване на профил", + "create_backup": "Създаване на резервно копие", + "create_donation_link": "Създайте връзка за дарение", + "create_invoice": "Създайте фактура", + "create_new": "Създаване на нов портфейл", + "create_new_account": "Създаване на нов профил", + "creating_new_wallet": "Създаване на нов портфейл", + "creating_new_wallet_error": "Грешка: ${description}", + "creation_date": "Дата на създаване", + "custom": "персонализирано", + "custom_drag": "Персонализиране (задръжте и плъзнете)", + "custom_redeem_amount": "Персонализирана сума за използване", + "dark_theme": "Тъмно", + "debit_card": "Дебитна карта", + "debit_card_terms": "Съхранението и използването на данните от вашата платежна карта в този дигитален портфейл подлежат на условията на съответното съгласие за картодържец от издателя на картата.", + "decimal_places_error": "Твърде много знаци след десетичната запетая", "default_buy_provider": "Доставчик по подразбиране купува", - "ask_each_time": "Питайте всеки път", - "buy_provider_unavailable": "Понастоящем доставчик не е наличен.", - "signTransaction": "Подпишете транзакция", + "default_sell_provider": "Доставчик за продажба по подразбиране", + "delete": "Изтрий", + "delete_account": "Изтриване на акаунт", + "delete_wallet": "Изтриване на портфейл", + "delete_wallet_confirm_message": "Сигурни ли сте, че искате да изтриете протфейла ${wallet_name}?", + "deleteConnectionConfirmationPrompt": "Сигурни ли сте, че искате да изтриете връзката към", + "descending": "Низходящ", + "description": "Описание", + "destination_tag": "Destination tag:", + "dfx_option_description": "Купете крипто с EUR и CHF. До 990 € без допълнителен KYC. За клиенти на дребно и корпоративни клиенти в Европа", + "didnt_get_code": "Не получихте код?", + "digit_pin": "-цифрен PIN", + "digital_and_physical_card": " дигитална или физическа предплатена дебитна карта", + "disable": "Деактивиране", + "disable_buy": "Деактивирайте действието за покупка", + "disable_cake_2fa": "Деактивирайте Cake 2FA", + "disable_exchange": "Деактивиране на борса", + "disable_fiat": "Деактивиране на fiat", + "disable_sell": "Деактивирайте действието за продажба", + "disabled": "Деактивирано", + "discount": "Спестете ${value}%", + "display_settings": "Настройки на екрана", + "displayable": "Възможност за показване", + "do_not_have_enough_gas_asset": "Нямате достатъчно ${currency}, за да извършите транзакция с текущите условия на блокчейн мрежата. Имате нужда от повече ${currency}, за да платите таксите за блокчейн мрежа, дори ако изпращате различен актив.", + "do_not_send": "Не изпращай", + "do_not_share_warning_text": "Не споделяйте това с никого, дори и отдел поддръжка.\n\nПарите Ви могат и ще бъдат откраднати!", + "do_not_show_me": "Не показвай повече това", + "domain_looks_up": "Търсене на домейни", + "donation_link_details": "Подробности за връзката за дарение", + "e_sign_consent": "E-Sign съгласие", + "edit": "Промени", + "edit_backup_password": "Промяна на паролата за възстановяване", + "edit_node": "Редактиране на възел", + "edit_token": "Редактиране на токена", + "electrum_address_disclaimer": "Нови адреси се генерират всеки път, когато използвате този, но и предишните продължават да работят", + "email_address": "Имейл адрес", + "enabled": "Активирано", + "enter_amount": "Въведете сума", + "enter_backup_password": "Въведете парола за възстановяване", + "enter_code": "Въведете код", + "enter_seed_phrase": "Въведете вашата фраза за семена", + "enter_totp_code": "Моля, въведете TOTP кода.", + "enter_your_note": "Въвеждане на бележка…", + "enter_your_pin": "Въведете PIN", + "enter_your_pin_again": "Въведете своя PIN отново", + "enterTokenID": "Въведете идентификатора на токена", + "enterWalletConnectURI": "Въведете URI на WalletConnect", + "error": "Грешка", + "error_dialog_content": "Получихме грешка.\n\nМоля, изпратете доклада до нашия отдел поддръжка, за да подобрим приложението.", + "error_text_account_name": "Името на профила може да съдържа само букви и числа \nи трябва да е между 1 и 15 символа", + "error_text_address": "Адресът на портфейла трябва да отговаря \n на вида криптовалута", + "error_text_amount": "Сумата може да съдържа само числа", + "error_text_contact_name": "Името на контакта не може да съдържа символите ` , ' \" \nи и трябва да е между 1 и 32 символа", + "error_text_crypto_currency": "Броят на цифрите след десетичната запетая\nможе да бъде най-много 12", + "error_text_fiat": "Сумата не може да надвишава наличния баланс.\nThe number of fraction digits must be less or equal to 2", + "error_text_input_above_maximum_limit": "Сумата надвишава максималната", + "error_text_input_below_minimum_limit": "Сумата е по-малко от минималната", + "error_text_keys": "Ключовете за портфейл може да съдържат само 64 шестнайсетични символа", + "error_text_limits_loading_failed": "Сделка за ${provider} не беше създадена. Неуспешно зареждане на лимити", + "error_text_maximum_limit": "Сделка за ${provider} не беше създадена. Сумата надвишава максималната: ${max} ${currency}", + "error_text_minimal_limit": "Сделка за ${provider} не беше създадена. Сумата е по-малко от минималната: ${min} ${currency}", + "error_text_node_address": "Моля, въведете iPv4 адрес", + "error_text_node_port": "Node port-ът е цяло число между 0 и 65535", + "error_text_node_proxy_address": "Моля, въведете :<порт>, например 127.0.0.1:9050", + "error_text_payment_id": "Payment ID-то може да съдържа само между 16 и 64 шестнайсетични символа", + "error_text_subaddress_name": "Името на подадреса не може да съдържат символите ` , ' \" \n и трябва да е между 1 и 20 символа", + "error_text_template": "Имената на шаблони и адреси не могат да съдържат ` , ' \" \nи трябва да са между 1 и 106 символа.", + "error_text_wallet_name": "Името на портфейла може да съдържа само букви, цифри, и символите _ и - \n и трябва да е между 1 и 33 символа", + "error_text_xmr": "XMR сумата не може да надхвърля наличния баланс.\nБроят на цифрите след десетичната запетая може да бъде най-много 12", "errorGettingCredentials": "Неуспешно: Грешка при получаване на идентификационни данни", "errorSigningTransaction": "Възникна грешка при подписване на транзакция", - "pairingInvalidEvent": "Невалидно събитие при сдвояване", - "chains": "Вериги", - "methods": "Методи", - "events": "събития", - "reject": "Отхвърляне", - "approve": "Одобряване", - "expiresOn": "Изтича на", - "walletConnect": "WalletConnect", - "nullURIError": "URI е нула", - "connectWalletPrompt": "Свържете портфейла си с WalletConnect, за да извършвате транзакции", - "newConnection": "Нова връзка", - "activeConnectionsPrompt": "Тук ще се появят активни връзки", - "deleteConnectionConfirmationPrompt": "Сигурни ли сте, че искате да изтриете връзката към", + "estimated": "Изчислено", + "etherscan_history": "История на Etherscan", "event": "Събитие", - "successful": "Успешен", - "wouoldLikeToConnect": "иска да се свърже", - "message": "Съобщение", - "do_not_have_enough_gas_asset": "Нямате достатъчно ${currency}, за да извършите транзакция с текущите условия на блокчейн мрежата. Имате нужда от повече ${currency}, за да платите таксите за блокчейн мрежа, дори ако изпращате различен актив.", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Моля, изчакайте dApp да завърши обработката.", - "copyWalletConnectLink": "Копирайте връзката WalletConnect от dApp и я поставете тук", - "enterWalletConnectURI": "Въведете URI на WalletConnect", - "seed_key": "Ключ за семена", - "enter_seed_phrase": "Въведете вашата фраза за семена", - "change_rep_successful": "Успешно промени представител", - "add_contact": "Добави контакт", + "events": "събития", + "exchange": "Exchange", + "exchange_incorrect_current_wallet_for_xmr": "Ако искате да обмените XMR от своя Cake Wallet Monero баланс, първо изберете своя Monero портфейл.", + "exchange_new_template": "Нов шаблон", "exchange_provider_unsupported": "${providerName} вече не се поддържа!", - "domain_looks_up": "Търсене на домейни", - "require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли", - "camera_permission_is_required": "Изисква се разрешение за камерата.\nМоля, активирайте го от настройките на приложението.", - "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново", - "order_by": "Подредени по", - "creation_date": "Дата на създаване", + "exchange_result_confirm": "By pressing confirm, you will be sending ${fetchingLabel} ${from} from your wallet called ${walletName} to the address shown below. Or you can send from your external wallet to the below address/QR code.\n\nPlease press confirm to continue or go back to change the amounts.", + "exchange_result_description": "You must send a minimum of ${fetchingLabel} ${from} to the address shown on the next page. If you send an amount lower than ${fetchingLabel} ${from} it may not get converted and it may not be refunded.", + "exchange_result_write_down_ID": "*Please copy or write down your ID shown above.", + "exchange_result_write_down_trade_id": "Моля, запишете trade ID-то, за да продължите.", + "exchange_sync_alert_content": "Моля, изчакайте синхронизирането на Вашия портфейл", + "expired": "Изтекло", + "expires": "Изтича", + "expiresOn": "Изтича на", + "export_backup": "Експортиране на резервно копие", + "extra_id": "Допълнително ID:", + "extracted_address_content": "Ще изпратите средства на \n${recipient_name}", + "failed_authentication": "Неуспешно удостоверяване. ${state_error}", + "faq": "FAQ", + "fetching": "Обработване", + "fiat_api": "Fiat API", + "fiat_balance": "Фиат Баланс", + "field_required": "Това поле е задължително", + "fill_code": "Моля, въведето кода за потвърждаване, изпратен на Вашия имейл", + "filter_by": "Филтрирай по", + "first_wallet_text": "Невероятен портфейл за Monero, Bitcoin, Ethereum, Litecoin и Haven", + "fixed_pair_not_supported": "Този fixed pair не се поддържа от избраната борса", + "fixed_rate": "Постоянен обменен курс", + "fixed_rate_alert": "Ще можете да въведете сумата за получаване, когато е избранен постоянен обменен курс. Искате ли да изберете постоянен обменен курс?", + "forgot_password": "Забравена парола", + "freeze": "Замразяване", + "frequently_asked_questions": "Често задавани въпроси", + "frozen": "Замразени", + "full_balance": "Пълен баланс", + "generate_name": "Генериране на име", + "generating_gift_card": "Създаване на Gift Card", + "get_a": "Вземете ", + "get_card_note": ", която можете да заредите с дигитална валута. Без нужда от допълнителна информация!", + "get_your_yat": "Получете своя Yat", + "gift_card_amount": "Сума в Gift Card", + "gift_card_balance_note": "Гифткарти с наличен баланс ще се покажат тук", + "gift_card_is_generated": "Gift Card бе създадена", + "gift_card_number": "Номер на Gift Card", + "gift_card_redeemed_note": "Използваните гифткарти ще се покажат тук", + "gift_cards": "Gift Карти", + "gift_cards_unavailable": "В момента гифткарти могат да бъдат закупени само с Monero, Bitcoin и Litecoin", + "got_it": "Готово", + "gross_balance": "Брутен баланс", "group_by_type": "Група по вид", - "importNFTs": "Импортирайте NFT", - "noNFTYet": "Все още няма NFT", - "address": "Адрес", - "enterTokenID": "Въведете идентификатора на токена", - "tokenID": "документ за самоличност", - "name": "Име", - "symbol": "Символ", - "seed_phrase_length": "Дължина на началната фраза", - "unavailable_balance": "Неналично салдо", - "unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.", - "unspent_change": "Промяна", - "tor_connection": "Tor връзка", - "setup_warning_2fa_text": "Cake 2FA е второ удостоверяване за определени действия в портфейла. НЕ е толкова сигурно, колкото хладилното съхранение.\n\nАко загубите достъп до вашето 2FA приложение или TOTP ключове, ЩЕ загубите достъп до този портфейл. Ще трябва да възстановите портфейла си от мнемоничното семе.\n\nПоддръжката на Cake няма да може да ви помогне, ако загубите достъп до вашите 2FA или мнемонични семена.\nПреди да използвате Cake 2FA, препоръчваме да прочетете ръководството.", - "scan_qr_on_device": "Сканирайте този QR код на друго устройство", + "haven_app": "Haven от Cake Wallet", + "haven_app_wallet_text": "Невероятен портфейл за Haven", + "help": "Помощ", + "hidden_balance": "Скрит баланс", + "hide_details": "Скриване на подробностите", + "high_contrast_theme": "Тема с висок контраст", + "home_screen_settings": "Настройки на началния екран", "how_to_use": "Как да използвам", + "how_to_use_card": "Как се ползва тази карта", + "id": "ID: ", + "ignor": "Игнориране", + "import": "Импортиране", + "importNFTs": "Импортирайте NFT", + "in_store": "In Store", + "incoming": "Входящи", + "incorrect_seed": "Въведеният текст е невалиден.", + "introducing_cake_pay": "Запознайте се с Cake Pay!", + "invalid_input": "Невалиден вход", + "invoice_details": "IДанни за фактура", + "is_percentage": "е", + "last_30_days": "Последните 30 дни", + "learn_more": "Научете още", + "light_theme": "Светло", + "loading_your_wallet": "Зареждане на портфейл", + "login": "Влизане", + "logout": "Logout", + "low_fee": "Ниска такса", + "low_fee_alert": "Използвате ниска приоритетност в мрежата. Това може да доведе до дълго чакане, различни обменни курсове или отказани сделки. Препоръчваме използването на по-висока такса.", + "manage_nodes": "Управление на възли", + "manage_pow_nodes": "Управление на PoW възли", + "manage_yats": "Управление на Yats", + "mark_as_redeemed": "Отбележи като използван", + "market_place": "Магазин", + "matrix_green_dark_theme": "Зелена тъмна тема Matrix", + "max_amount": "Макс: ${value}", + "max_value": "Макс: ${value} ${currency}", + "memo": "Мемо:", + "message": "Съобщение", + "methods": "Методи", + "min_amount": "Мин: ${value}", + "min_value": "Мин: ${value} ${currency}", + "minutes_to_pin_code": "${minute} минути", + "mm": "мм", + "modify_2fa": "Модифициране на тортата 2FA", + "monero_com": "Monero.com от Cake Wallet", + "monero_com_wallet_text": "Невероятен портфейл за Monero", + "monero_dark_theme": "Тъмна тема Monero", + "monero_light_theme": "Лека тема Monero", + "moonpay_alert_text": "Сумата трябва да бъде най-малко ${minAmount} ${fiatCurrency}", + "more_options": "Още настройки", + "name": "Име", + "narrow": "Тесен", + "new_first_wallet_text": "Лесно пазете криптовалутата си в безопасност", + "new_node_testing": "Тестване на нов node", + "new_subaddress_create": "Създаване", + "new_subaddress_label_name": "Име на Label", + "new_subaddress_title": "Нов адрес", + "new_template": "Нов шаблон", + "new_wallet": "Нов портфейл", + "newConnection": "Нова връзка", + "no_id_needed": "Без нужда от документ за самоличност!", + "no_id_required": "Без нужда от документ за самоличност. Използвайте навсякъде", + "no_relay_on_domain": "Няма реле за домейна на потребителя или релето не е налично. Моля, изберете реле, което да използвате.", + "no_relays": "Без релета", + "no_relays_message": "Намерихме запис Nostr NIP-05 за този потребител, но той не съдържа релета. Моля, инструктирайте получателя да добави релета към своя Nostr запис.", + "node_address": "Нов адрес", + "node_connection_failed": "Връзката не можа да бъде установена", + "node_connection_successful": "Връзката бе установена успешно", + "node_new": "Нов Node", + "node_port": "Node порт", + "node_reset_settings_title": "Възстановяване на настройки", + "node_test": "Тест", + "nodes": "Nodes", + "nodes_list_reset_to_default_message": "Сигурни ли сте, че искате да възстановите фабричните настройки?", + "none_of_selected_providers_can_exchange": "Нито един от избраните provider-ъри не може да направи този превод", + "noNFTYet": "Все още няма NFT", + "normal": "нормално", + "note_optional": "Бележка (не е задължително)", + "note_tap_to_change": "Бележка (натиснете за промяна)", + "nullURIError": "URI е нула", + "offer_expires_in": "Предложението изтича след: ", + "offline": "Офлайн", + "ok": "Ок", + "onion_link": "Лукова връзка", + "online": "Онлайн", + "onramper_option_description": "Бързо купувайте криптовалута с много методи за плащане. Предлага се в повечето страни. Разпространенията и таксите варират.", + "open_gift_card": "Отвори Gift Card", + "optional_description": "Описание по избор", + "optional_email_hint": "Незадължителен имейл за уведомяване на получателя", + "optional_name": "Незадължително име на получател", + "optionally_order_card": "По желание поръчайте и физическа карта.", + "orbot_running_alert": "Моля, включете Orbot преди да свържете към този node.", + "order_by": "Подредени по", + "order_id": "ID на поръчка", + "order_physical_card": "Поръчка на физическа карта", + "other_settings": "Други настройки", + "outdated_electrum_wallet_description": "Нови Bitcoin портфейли, създадени в Cake, сега имат seed от 24 думи. Трябва да създадете нов Bitcoin адрес и да прехвърлите всичките си средства в него и веднага да спрете използването на стари портфейли. Моля, напревете това незабавно, за да подсигурите средствата си.", + "outdated_electrum_wallet_receive_warning": "Ако този адрес има seed от 12 думи и е създаден чрез Cake, НЕ добавяйте Bitcoin в него. Всякакъв Bitcoin, изпратен на този адрес, може да бъде загубен завинаги. Създайте нов портфейл от 24 думи (натиснете менюто горе, вдясно, изберете Портфейли, изберете Създаване на нов портфейл, след това изберете Bitcoin) и НЕЗАБАВНО преместете своя Bitcoin там. Нови (такива с 24 думи) Bitcoin портфейли от Cake са надеждни", + "outgoing": "Изходящи", + "overwrite_amount": "Промени сума", + "pairingInvalidEvent": "Невалидно събитие при сдвояване", + "password": "Парола", + "paste": "Поставяне", + "pause_wallet_creation": "Възможността за създаване на Haven Wallet в момента е на пауза.", + "payment_id": "Payment ID: ", + "payment_was_received": "Плащането бе получено.", + "pending": " (чакащи)", + "percentageOf": "от ${amount}", + "pin_at_top": "закачете ${token} отгоре", + "pin_is_incorrect": "Грешен PIN", + "pin_number": "PIN код", + "placeholder_contacts": "Вашите контакти ще се покажат тук", + "placeholder_transactions": "Вашите транзакции ще се покажат тук", + "please_fill_totp": "Моля, попълнете 8-цифрения код на другото ви устройство", + "please_make_selection": "Моля, изберете отдолу за създаване или възстановяване на портфейл.", + "please_reference_document": "Моля, вижте документите по-долу за повече информация.", + "please_select": "Моля, изберете:", + "please_select_backup_file": "Моля, изберете резервно копие и въведете парола за възстановяване.", + "please_try_to_connect_to_another_node": "Моля, опитайте се да се свържете към друг node.", + "polygonscan_history": "История на PolygonScan", + "powered_by": "Powered by ${title}", + "pre_seed_button_text": "Разбирам. Покажи seed", + "pre_seed_description": "На следващата страница ще видите поредица от ${words} думи. Това е вашият таен личен seed и е единственият начин да възстановите портфейла си. Отговорността за съхранението му на сигурно място извън приложението на Cake Wallet е изцяло ВАША.", + "pre_seed_title": "ВАЖНО", + "prevent_screenshots": "Предотвратете екранни снимки и запис на екрана", + "privacy": "Поверителност", + "privacy_policy": "Политика за поверителността", + "privacy_settings": "Настройки за поверителност", + "private_key": "Таен ключ", + "proceed_after_one_minute": "Ако процесът продължи повече от 1 минута, проверете своя имейл.", + "profile": "Профил", + "provider_error": "Грешка на ${provider} ", + "public_key": "Публичен ключ", + "purchase_gift_card": "Купуване на Gift Card", + "qr_fullscreen": "Натиснете, за да отворите QR кода на цял екран", + "qr_payment_amount": "Този QR код съдържа сума за плащане. Искате ли да промените стойността?", + "question_to_disable_2fa": "Сигурни ли сте, че искате да деактивирате Cake 2FA? Вече няма да е необходим 2FA код за достъп до портфейла и определени функции.", + "receivable_balance": "Баланс за вземания", + "receive": "Получи", + "receive_amount": "Сума", + "received": "Получени", + "recipient_address": "Адрес на получател", + "reconnect": "Reconnect", + "reconnect_alert_text": "Сигурни ли сте, че искате да се свържете отново?", + "reconnection": "Свързване отново", + "redeemed": "Използвани", + "refund_address": "Refund address", + "reject": "Отхвърляне", + "remaining": "оставащи", + "remove": "Премахни", + "remove_node": "Премахни node", + "remove_node_message": "Сигурни ли сте, че искате да премахнете избрания node?", + "rename": "Промяна на името", + "require_for_adding_contacts": "Изисква се за добавяне на контакти", + "require_for_all_security_and_backup_settings": "Изисква се за всички настройки за сигурност и архивиране", + "require_for_assessing_wallet": "Изискване за достъп до портфейла", + "require_for_creating_new_wallets": "Изискване за създаване на нови портфейли", + "require_for_exchanges_to_external_wallets": "Изискване за обмен към външни портфейли", + "require_for_exchanges_to_internal_wallets": "Изискване за обмен към вътрешни портфейли", + "require_for_sends_to_contacts": "Изискване за изпращане до контакти", + "require_for_sends_to_internal_wallets": "Изискване за изпращане до вътрешни портфейли", + "require_for_sends_to_non_contacts": "Изискване за изпращане до лица без контакт", + "require_pin_after": "Въведете PIN след", + "rescan": "Сканирай отново", + "resend_code": "Повторно изпращане", + "reset": "Нулиране", + "reset_password": "Нулиране на парола", + "restore_active_seed": "Активиране на seed", + "restore_address": "Адреси", + "restore_bitcoin_description_from_keys": "Възстановяване на портфейл чрез WIF, изведен от Вашите private keys", + "restore_bitcoin_description_from_seed": "Възстановяване на портфейл чрез код от 24 думи", + "restore_bitcoin_title_from_keys": "Възстановяване от WIF", + "restore_description_from_backup": "Можете да възстановите цялото приложение Cake Wallet от своя резервен файл", + "restore_description_from_keys": "Възстановяване на портфейл от генерираните от Вашите тайни ключове клавиши", + "restore_description_from_seed": "Възстановяване на портфейл от кода от 13 или 25 думи", + "restore_description_from_seed_keys": "Възстановете своя портфейл от seed/keys, които сте съхранили на сигурно място", + "restore_from_date_or_blockheight": "Моля, въведете дата няколко дни преди създаването на този портфейл. Ако знаете blockheight-а, въведето него вместо това", + "restore_from_seed_placeholder": "Моля, въведете своя seed тук", + "restore_new_seed": "Нов seed", + "restore_next": "Next", + "restore_recover": "Възстановяване", + "restore_restore_wallet": "Възстановяване на портфейл", + "restore_seed_keys_restore": "Възстановяне от Seed/Keys", + "restore_spend_key_private": "Spend key (публичен)", + "restore_title_from_backup": "Възстановяване от резервно копие", + "restore_title_from_keys": "Възстановяване от keys", + "restore_title_from_seed": "Възстановяване от seed", + "restore_title_from_seed_keys": "Възстановяване от seed/keys", + "restore_view_key_private": "View key (таен)", + "restore_wallet": "Възстановяване на портфейл", + "restore_wallet_name": "Име на портфейл", + "restore_wallet_restore_description": "Описание на възстановяване на портфейл", + "router_no_route": "Няма дефиниран път за ${name}", + "save": "Запази", + "save_backup_password": "Моля, запишете своята парола за възстановяване. Импортирането на резервни копия не е възможно без нея.", + "save_backup_password_alert": "Запазване на паролата за възстановяване", + "save_to_downloads": "Запазване в Изтегляния", + "saved_the_trade_id": "Запазих trade ID-то", + "scan_qr_code": "Сканирайте QR кода, за да получите адреса", + "scan_qr_on_device": "Сканирайте този QR код на друго устройство", + "search": "Търсене", + "search_add_token": "Търсене/Добавяне на токен", + "search_category": "Търсене в категория", + "search_currency": "Търсене на валута", + "search_language": "Търсене на език", + "second_intro_content": "Вашият Yat е уникален адрес във формата на емоджи, който играе ролята на всички Ваши дълги шестнайсетични портфейли за всяка валута.", + "second_intro_title": "Един емоджи адрес, обединяващ всички останали.", + "security_and_backup": "Сигурност и резервни копия", + "seed_alert_back": "Назад", + "seed_alert_content": "Seed-ът е единственият начин да възстановите портфейла си. Записахте ли го?", + "seed_alert_title": "Внимание", + "seed_alert_yes": "Да", + "seed_choose": "Изберете език на seed-а", "seed_hex_form": "Семена от портфейл (шестнадесетична форма)", + "seed_key": "Ключ за семена", + "seed_language": "Език на семената", + "seed_language_chinese": "Китайски", + "seed_language_chinese_traditional": "Традиционен китайски)", + "seed_language_czech": "Чех", + "seed_language_dutch": "Нидерландски", + "seed_language_english": "Английски", + "seed_language_french": "Френски", + "seed_language_german": "Немски", + "seed_language_italian": "Италиански", + "seed_language_japanese": "Японски", + "seed_language_korean": "Корейски", + "seed_language_next": "Следващ", + "seed_language_portuguese": "Португалски", + "seed_language_russian": "Руски", + "seed_language_spanish": "Испански", + "seed_phrase_length": "Дължина на началната фраза", + "seed_reminder": "Моля, запишете го в случай на загуба на устройството.", + "seed_share": "Споделяне на seed", + "seed_title": "Seed", "seedtype": "Семенна тип", "seedtype_legacy": "Наследство (25 думи)", "seedtype_polyseed": "Поли семе (16 думи)", - "seed_language_czech": "Чех", - "seed_language_korean": "Корейски", - "seed_language_chinese_traditional": "Традиционен китайски)", - "ascending": "Възходящ", - "descending": "Низходящ", - "dfx_option_description": "Купете крипто с EUR и CHF. До 990 € без допълнителен KYC. За клиенти на дребно и корпоративни клиенти в Европа", - "polygonscan_history": "История на PolygonScan", - "wallet_seed_legacy": "Наследено портфейл семе", - "default_sell_provider": "Доставчик за продажба по подразбиране", + "select_backup_file": "Избор на резервно копие", + "select_buy_provider_notice": "Изберете доставчик на покупка по -горе. Можете да пропуснете този екран, като зададете вашия доставчик по подразбиране по подразбиране в настройките на приложението.", + "select_destination": "Моля, изберете дестинация за архивния файл.", "select_sell_provider_notice": "Изберете доставчик на продажба по-горе. Можете да пропуснете този екран, като зададете своя доставчик на продажба по подразбиране в настройките на приложението.", - "custom_drag": "Персонализиране (задръжте и плъзнете)", + "sell": "Продаване", + "sell_alert_content": "В момента поддържаме само продажбата на Bitcoin, Ethereum и Litecoin. Моля, създайте или превключете към своя портфейл Bitcoin, Ethereum или Litecoin.", + "sell_monero_com_alert_content": "Продажбата на Monero все още не се поддържа", + "send": "Изпрати", + "send_address": "${cryptoCurrency} адрес", + "send_amount": "Сума:", + "send_creating_transaction": "Създаване на транзакция", + "send_error_currency": "Валутата може да съдържа само числа", + "send_error_minimum_value": "Минималната сума е 0.01", + "send_estimated_fee": "Изчислена такса:", + "send_fee": "Такса:", + "send_name": "Име", + "send_new": "Ново", + "send_payment_id": "Payment ID (не е задължително)", + "send_priority": "В момента таксата е на ${transactionPriority} приоритетност.\nПриоритетността на транзакцията може да бъде променена в настройките", + "send_sending": "Изпращане...", + "send_success": "Вашите ${crypto} бяха успешно изпратени", + "send_templates": "Шаблони", + "send_title": "Изпращане", + "send_to_this_address": "Send ${currency} ${tag}to this address", + "send_xmr": "Изпращане на XMR", + "send_your_wallet": "Вашият портфейл", + "sending": "Изпращане", + "sent": "Изпратени", + "settings_all": "Всичко", + "settings_allow_biometrical_authentication": "Позволяване на биометрично удостоверяване.", + "settings_can_be_changed_later": "Тези настройки могат да бъдат променени по-късно от приложението", + "settings_change_language": "Промяна на езика", + "settings_change_pin": "Промяна на PIN", + "settings_currency": "Валута", + "settings_current_node": "Сегашен node", + "settings_dark_mode": "Тъмен режим", + "settings_display_balance": "Показване на баланс", + "settings_display_on_dashboard_list": "Показване на таблото", + "settings_fee_priority": "Таксова приоритетност", + "settings_nodes": "Nodes", + "settings_none": "Липсва", + "settings_only_trades": "Само сделки", + "settings_only_transactions": "Само транзакции", + "settings_personal": "Лични", + "settings_save_recipient_address": "Запазване адрес на получател", + "settings_support": "Поддръжка", + "settings_terms_and_conditions": "Условия", + "settings_title": "Настройки", + "settings_trades": "Сделки", + "settings_transactions": "Транзакции", + "settings_wallets": "Портфейли", + "setup_2fa": "Настройка на Cake 2FA", + "setup_2fa_text": "Cake 2FA работи с помощта на TOTP като втори фактор за удостоверяване.\n\nTOTP на Cake 2FA изисква SHA-512 и поддръжка на 8 цифри; това осигурява повишена сигурност. Повече информация и поддържани приложения можете да намерите в ръководството.", + "setup_pin": "Настройване на PIN", + "setup_successful": "Вашият PIN бе успешно настроен!", + "setup_totp_recommended": "Настройка на TOTP", + "setup_warning_2fa_text": "Cake 2FA е второ удостоверяване за определени действия в портфейла. НЕ е толкова сигурно, колкото хладилното съхранение.\n\nАко загубите достъп до вашето 2FA приложение или TOTP ключове, ЩЕ загубите достъп до този портфейл. Ще трябва да възстановите портфейла си от мнемоничното семе.\n\nПоддръжката на Cake няма да може да ви помогне, ако загубите достъп до вашите 2FA или мнемонични семена.\nПреди да използвате Cake 2FA, препоръчваме да прочетете ръководството.", + "setup_your_debit_card": "Настройте своята дебитна карта", + "share": "Дял", + "share_address": "Сподели адрес", + "show_details": "Показване на подробностите", + "show_keys": "Покажи seed/keys", + "show_market_place": "Покажи пазар", + "show_seed": "Покажи seed", + "sign_up": "Регистрация", + "signTransaction": "Подпишете транзакция", + "signup_for_card_accept_terms": "Регистрайте се за картата и приемете условията.", + "slidable": "Плъзгащ се", + "sort_by": "Сортирай по", + "spend_key_private": "Spend key (таен)", + "spend_key_public": "Spend key (публичен)", + "status": "Статус: ", + "subaddress_title": "Лист от подадреси", + "subaddresses": "Подадреси", + "submit_request": "изпращане на заявка", + "successful": "Успешен", + "support_description_guides": "Документация и подкрепа за общи проблеми", + "support_description_live_chat": "Безплатно и бързо! Обучени представители на подкрепата са на разположение за подпомагане", + "support_description_other_links": "Присъединете се към нашите общности или се свържете с нас нашите партньори чрез други методи", + "support_title_guides": "Ръководства за портфейл за торта", + "support_title_live_chat": "Подкрепа на живо", + "support_title_other_links": "Други връзки за поддръжка", + "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново", "switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)", - "receivable_balance": "Баланс за вземания", - "confirmed_tx": "Потвърдено", + "symbol": "Символ", + "sync_status_attempting_sync": "ОПИТ ЗА СИНХРОНИЗАЦИЯ", + "sync_status_connected": "СВЪРЗВАНЕ", + "sync_status_connecting": "СВЪРЗВАНЕ", + "sync_status_failed_connect": "НЕУСПЕШНО СВЪРЗВАНЕ", + "sync_status_not_connected": "НЯМА ВРЪЗКА", + "sync_status_starting_sync": "ЗАПОЧВАНЕ НА СИНХРОНИЗАЦИЯ", + "sync_status_syncronized": "СИНХРОНИЗИРАНО", + "sync_status_syncronizing": "СИНХРОНИЗИРАНЕ", + "syncing_wallet_alert_content": "Списъкът ви с баланс и транзакции може да не е пълен, докато в горната част не пише „СИНХРОНИЗИРАН“. Кликнете/докоснете, за да научите повече.", + "syncing_wallet_alert_title": "Вашият портфейл се синхронизира", + "template": "Шаблон", + "template_name": "Име на шаблон", + "third_intro_content": "Yats също живее извън Cake Wallet. Всеки адрес на портфейл може да бъде заменен с Yat!", + "third_intro_title": "Yat добре се сработва с други", + "time": "${minutes} мин ${seconds} сек", + "tip": "Tip:", + "today": "Днес", + "token_contract_address": "Адрес на токен договор", + "token_decimal": "Токен десетичен", + "token_name": "Име на токена, напр.: Tether", + "token_symbol": "Символ на токена, напр.: USDT", + "tokenID": "документ за самоличност", + "tor_connection": "Tor връзка", + "tor_only": "Само чрез Tor", + "total_saving": "Общо спестявания", + "totp_2fa_failure": "Грешен код. Моля, опитайте с различен код или генерирайте нов таен ключ. Използвайте съвместимо 2FA приложение, което поддържа 8-цифрени кодове и SHA512.", + "totp_2fa_success": "Успех! Cake 2FA е активиран за този портфейл. Не забравяйте да запазите мнемоничното начало, в случай че загубите достъп до портфейла.", + "totp_auth_url": "TOTP AUTH URL", + "totp_code": "TOTP код", + "totp_secret_code": "TOTP таен код", + "totp_verification_success": "Проверката е успешна!", + "trade_details_copied": "${title} копирано", + "trade_details_created_at": "Създадено", + "trade_details_fetching": "Обработка", + "trade_details_id": "ID", + "trade_details_pair": "Pair", + "trade_details_provider": "Provider", + "trade_details_state": "Статус", + "trade_details_title": "Подробности на сделката", + "trade_for_not_created": "Сделка за ${title} не бе създадена.", + "trade_history_title": "История на сделките", + "trade_id": "Trade ID:", + "trade_id_not_found": "Сделка ${tradeId} на ${title} не бе намерена.", + "trade_is_powered_by": "This trade is powered by ${provider}", + "trade_not_created": "Сделка не бе създадена.", + "trade_not_found": "Сделката не бе намерена.", + "trade_state_btc_sent": "Btc изпратен", + "trade_state_complete": "Завършено", + "trade_state_confirming": "Потвърждава се", + "trade_state_created": "Създадено", + "trade_state_finished": "Завършено", + "trade_state_paid": "Платено", + "trade_state_paid_unconfirmed": "Непотвърдено плащане", + "trade_state_pending": "Изчаква се", + "trade_state_timeout": "Време за изчакване", + "trade_state_to_be_created": "Изчаква създаване", + "trade_state_traded": "Traded", + "trade_state_trading": "Trading", + "trade_state_underpaid": "Недостатъчно плащане", + "trade_state_unpaid": "Неплатено", + "trades": "Trades", + "transaction_details_amount": "Сума", + "transaction_details_copied": "${title} копирано", + "transaction_details_date": "Дата", + "transaction_details_fee": "Такса", + "transaction_details_height": "Height", + "transaction_details_recipient_address": "Адрес на получател", "transaction_details_source_address": "Адрес на източника", - "pause_wallet_creation": "Възможността за създаване на Haven Wallet в момента е на пауза.", - "contractName": "Име на договора", - "contractSymbol": "Договор Символ", - "description": "Описание", - "camera_consent": "Вашият фотоапарат ще бъде използван за заснемане на изображение с цел идентификация от ${provider}. Моля, проверете тяхната политика за поверителност за подробности.", - "no_relays": "Без релета", - "choose_relay": "Моля, изберете реле, което да използвате", - "no_relays_message": "Намерихме запис Nostr NIP-05 за този потребител, но той не съдържа релета. Моля, инструктирайте получателя да добави релета към своя Nostr запис.", - "no_relay_on_domain": "Няма реле за домейна на потребителя или релето не е налично. Моля, изберете реле, което да използвате." -} + "transaction_details_title": "Подробности на транзакцията", + "transaction_details_transaction_id": "Transaction ID", + "transaction_key": "Transaction Key", + "transaction_priority_fast": "Бързо", + "transaction_priority_fastest": "Най-бързо", + "transaction_priority_medium": "Средно", + "transaction_priority_regular": "Обичайно", + "transaction_priority_slow": "Бавно", + "transaction_sent": "Сумата е изпратена!", + "transaction_sent_notice": "Ако процесът продължи повече от 1 минута, проверете някой block explorer и своя имейл.", + "transactions": "Транзакции", + "transactions_by_date": "Транзакции по дата", + "trusted": "Надежден", + "unavailable_balance": "Неналично салдо", + "unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.", + "unconfirmed": "Непотвърден баланс", + "understand": "Разбирам", + "unmatched_currencies": "Валутата на този портфейл не съвпада с тази от сканирания QR код", + "unspent_change": "Промяна", + "unspent_coins_details_title": "Подробности за неизползваните монети", + "unspent_coins_title": "Неизползвани монети", + "unsupported_asset": "Не поддържаме това действие за този актив. Моля, създайте или преминете към портфейл от поддържан тип актив.", + "upto": "до ${value}", + "use": "Смяна на ", + "use_card_info_three": "Използвайте дигиталната карта онлайн или чрез безконтактен метод на плащане.", + "use_card_info_two": "Средствата се обръщат в USD, когато биват запазени в предплатената карта, а не в дигитална валута.", + "use_ssl": "Използване на SSL", + "use_suggested": "Използване на предложеното", + "variable_pair_not_supported": "Този variable pair не се поддържа от избраната борса", + "verification": "Потвърждаване", + "verify_with_2fa": "Проверете с Cake 2FA", + "version": "Версия ${currentVersion}", + "view_all": "Виж всички", + "view_in_block_explorer": "Вижте в Block Explorer", + "view_key_private": "View key (таен)", + "view_key_public": "View key (публичен)", + "view_transaction_on": "Вижте транзакция на ", + "wallet_keys": "Seed/keys на портфейла", + "wallet_list_create_new_wallet": "Създаване на нов портфейл", + "wallet_list_edit_wallet": "Редактиране на портфейла", + "wallet_list_failed_to_load": "Грешка при зареждането на портфейл ${wallet_name}. ${error}", + "wallet_list_failed_to_remove": "Грешка при премахването на портфейл${wallet_name}. ${error}", + "wallet_list_load_wallet": "Зареждане на портфейл", + "wallet_list_loading_wallet": "Зареждане на портфейл ${wallet_name}", + "wallet_list_removing_wallet": "Премахване на портфейл ${wallet_name}", + "wallet_list_restore_wallet": "Възстановяване на портфейл", + "wallet_list_title": "Monero портфейл", + "wallet_list_wallet_name": "Име на портфейла", + "wallet_menu": "Меню", + "wallet_name": "Име на портфейл", + "wallet_name_exists": "Вече има портфейл с това име. Моля, изберете друго име или преименувайте другия портфейл.", + "wallet_restoration_store_incorrect_seed_length": "Грешна дължина на seed-а", + "wallet_seed": "Seed на портфейла", + "wallet_seed_legacy": "Наследено портфейл семе", + "wallet_store_monero_wallet": "Monero портфейл", + "walletConnect": "WalletConnect", + "wallets": "Портфейли", + "warning": "Внимание", + "welcome": "Добре дошли в", + "welcome_to_cakepay": "Добре дошли в Cake Pay!", + "widgets_address": "Адрес", + "widgets_or": "или", + "widgets_restore_from_blockheight": "Възстановяване от blockheight", + "widgets_restore_from_date": "Възстановяване от дата", + "widgets_seed": "Seed", + "wouoldLikeToConnect": "иска да се свърже", + "write_down_backup_password": "Моля, запишете своята парола за възстановяване. Тя се използва за импортиране на резервни копия на Вашите файлове.", + "xlm_extra_info": "Не забравяйте да дадете Memo ID-то, докато изпращате XLM транзакцията за обмена", + "xmr_available_balance": "Наличен баланс", + "xmr_full_balance": "Пълен баланс", + "xmr_hidden": "Скрит", + "xmr_to_error": "XMR.TO грешка", + "xmr_to_error_description": "Невалидна сума - най-много 8 цифри след десетичната запетая", + "xrp_extra_info": "Не забравяйте да дадете Destination Tag-а, когато изпращате XRP транзакцията за обмена", + "yat": "Yat", + "yat_address": "Yat Адрес", + "yat_alert_content": "Потребителите на Cake Wallet вече могат да изпращат и получават любимите си валути чрез неповторимо потребителско име от емоджита.", + "yat_alert_title": "Търгувайте с крипто много по-лесно чрез Yat", + "yat_error": "Yat грешка", + "yat_error_content": "Няма адреси, свързани с този Yat. Опитайте с друг Yat", + "yat_popup_content": "Вече можете да изпращате и да получавате крипто в Cake Wallet с вашия Yat - кратко потребителско име във формата на емоджи. Управлявайте своите Yats по всяко време в настройките", + "yat_popup_title": "Адресът на вашия портфейл може да съдържа емоджита.", + "yesterday": "Вчера", + "you_now_have_debit_card": "Вече имате дебитна карта", + "you_pay": "Вие плащате", + "you_will_get": "Обръщане в", + "you_will_send": "Обръщане от", + "yy": "гг", + "zzzz": "zzzz" +} \ No newline at end of file diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 92874e315..3f38bd277 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -1,771 +1,772 @@ { - "welcome": "Vítejte v", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Úžasná peněženka pro Monero, Bitcoin, Ethereum, Litecoin a Haven", - "please_make_selection": "Prosím vyberte si níže, jestli chcete vytvořit, nebo obnovit peněženku.", - "create_new": "Vytvořit novou peněženku", - "restore_wallet": "Obnovit peněženku", - "monero_com": "Monero.com od Cake Wallet", - "monero_com_wallet_text": "Úžasná peněženka pro Monero", - "haven_app": "Haven od Cake Wallet", - "haven_app_wallet_text": "Úžasná peněženka pro Haven", - "accounts": "Účty", - "edit": "Upravit", + "about_cake_pay": "Cake Pay umožňuje jednoduše nakupovat dárkové karty pomocí virtuálních prostředků, které lze okamžitě uplatnit u více než 150 000 obchodníků ve Spojených státech.", "account": "Účet", + "accounts": "Účty", + "accounts_subaddresses": "Účty a subadresy", + "activate": "Aktivovat", + "active": "Aktivní", + "active_cards": "Aktivní karty", + "activeConnectionsPrompt": "Zde se zobrazí aktivní připojení", "add": "Přidat", + "add_contact": "Přidat kontakt", + "add_custom_node": "Přidat vlastní uzel", + "add_custom_redemption": "Přidat vlastní uplatnění", + "add_fund_to_card": "Všechny předplacené prostředky na kartě (až ${value})", + "add_new_node": "Přidat nový uzel", + "add_new_word": "Přidat nové slovo", + "add_receiver": "Přidat dalšího příjemce (nepovinné)", + "add_secret_code": "Nebo přidejte tento tajný kód do ověřovací aplikace", + "add_tip": "Přidat spropitné", + "add_token_disclaimer_check": "Potvrdil jsem adresu a informace smlouvy o tokenu pomocí důvěryhodného zdroje. Přidání škodlivých nebo nesprávných informací může vést ke ztrátě finančních prostředků.", + "add_token_warning": "Neupravujte ani nepřidávejte tokeny podle pokynů podvodníků.\nVždy potvrďte adresy tokenů s renomovanými zdroji!", + "add_value": "Přidat hodnotu", + "address": "Adresa", "address_book": "Adresář", - "contact": "Kontakt", - "please_select": "Zvolte si:", - "cancel": "Zrušit", - "ok": "OK", - "contact_name": "Jméno kontaktu", - "reset": "Vymazat", - "save": "Uložit", + "address_book_menu": "Adresář", + "address_detected": "Adresa detekována", + "address_from_domain": "Tato adresa je z ${domain} na Unstoppable Domains", + "address_from_yat": "Tato adresa je z ${emoji} na Yatu", + "address_label": "Popisek adresy", "address_remove_contact": "Smazat kontakt", "address_remove_content": "Opravdu chcete smazat označený kontakt?", - "authenticated": "Ověřeno", - "authentication": "Ověřování", - "failed_authentication": "Ověřování selhalo. ${state_error}", - "wallet_menu": "Menu", - "Blocks_remaining": "Zbývá ${status} bloků", - "please_try_to_connect_to_another_node": "Zkuste se prosím připojit k jinému uzlu", - "xmr_hidden": "Skryto", - "xmr_available_balance": "Zůstatek (dostupný)", - "xmr_full_balance": "Zůstatek (celkový)", - "send": "Poslat", - "receive": "Přijmout", - "transactions": "Transakce", - "incoming": "Příchozí", - "outgoing": "Odchozí", - "transactions_by_date": "Transakce podle data", - "trades": "Obchody", - "filter_by": "Filtrovat podle", - "today": "Dnes", - "yesterday": "Včera", - "received": "Přijato", - "sent": "Odesláno", - "pending": " (čeká)", - "rescan": "Znovu prohledat", - "reconnect": "Znovu připojit", - "wallets": "Peněženky", - "show_seed": "Zobrazit seed", - "show_keys": "Zobrazit seed/klíče", - "address_book_menu": "Adresář", - "reconnection": "Znovu připojit", - "reconnect_alert_text": "Opravdu se chcete znovu připojit?", - "exchange": "Směnit", - "clear": "Smazat", - "refund_address": "Adresa pro vrácení", - "change_exchange_provider": "Změnit směnárnu", - "you_will_send": "Směnit z", - "you_will_get": "Směnit na", - "amount_is_guaranteed": "Částka, kterou dostanete, je konečná", - "amount_is_estimate": "Částka, kterou dostanete, je jen odhad.", - "powered_by": "Zajišťuje ${title}", - "error": "Chyba", - "estimated": "Odhadováno", - "min_value": "Min: ${value} ${currency}", - "max_value": "Max: ${value} ${currency}", - "change_currency": "Změnit měnu", - "overwrite_amount": "Přepsat částku", - "qr_payment_amount": "Tento QR kód obsahuje i částku. Chcete přepsat současnou hodnotu?", - "copy_id": "Kopírovat ID", - "exchange_result_write_down_trade_id": "Prosím zkopírujte si, nebo zapište si ID transakce (trade ID) pro pokračování.", - "trade_id": "ID transakce (trade ID):", - "copied_to_clipboard": "Zkopírováno do schránky", - "saved_the_trade_id": "Uložil jsem si ID transakce (trade ID)", - "fetching": "Načítá se", - "id": "ID: ", - "amount": "Částka: ", - "payment_id": "ID platby: ", - "status": "Status: ", - "offer_expires_in": "Nabídka vyprší: ", - "trade_is_powered_by": "Tento obchod zajišťuje ${provider}", - "copy_address": "Zkopírovat adresu", - "exchange_result_confirm": "Po stisknutí Potvrdit odešlete ${fetchingLabel} ${from} ze své peněženky s názvem ${walletName} na adresu uvedenou níže. Nebo můžete prostředky poslat ze své externí peněženky na níže uvedenou adresu/QR kód.\n\nProsím stiskněte Potvrdit pro pokračování, nebo se vraťte zpět pro změnu částky.", - "exchange_result_description": "Musíte poslat minimálně ${fetchingLabel} ${from} na adresu uvedenou na následující stránce. Pokud pošlete nižší částku než ${fetchingLabel} ${from} nemusí dojít ke směně, ani k jejímu vrácení.", - "exchange_result_write_down_ID": "*Prosím zkopírujte si, nebo zapište si výše uvedené ID.", - "confirm": "Potvrdit", - "confirm_sending": "Potvrdit odeslání", - "commit_transaction_amount_fee": "Odeslat transakci\nČástka: ${amount}\nPoplatek: ${fee}", - "sending": "Odesílání", - "transaction_sent": "Transakce odeslána!", - "expired": "Vypršelo", - "time": "${minutes}m ${seconds}s", - "send_xmr": "Odeslat XMR", - "exchange_new_template": "Nová šablona", - "faq": "FAQ", - "enter_your_pin": "Zadejte svůj PIN", - "loading_your_wallet": "Načítám peněženku", - "new_wallet": "Nová peněženka", - "wallet_name": "Název peněženky", - "continue_text": "Pokračovat", - "choose_wallet_currency": "Prosím zvolte si měnu pro peněženku:", - "node_new": "Nový uzel", - "node_address": "Adresa uzlu", - "node_port": "Port uzlu", - "login": "Login", - "password": "Heslo", - "nodes": "Uzly", - "node_reset_settings_title": "Zrušit nastavení", - "nodes_list_reset_to_default_message": "Opravdu chcete zrušit nastavení a vrátit výchozí hodnotu?", - "change_current_node": "Opravdu chcete změnit současný uzel na ${node}?", - "change": "Změnit", - "remove_node": "Odstranit uzel", - "remove_node_message": "Opravdu chcete odstranit označený uzel?", - "remove": "Odstranit", - "delete": "Smazat", - "add_new_node": "Přidat nový uzel", - "change_current_node_title": "Změnit současný uzel", - "node_test": "Otestovat", - "node_connection_successful": "Připojení bylo úspěšné", - "node_connection_failed": "Připojení selhalo", - "new_node_testing": "Testování nového uzlu", - "use": "Přepnout na ", - "digit_pin": "-číselný PIN", - "share_address": "Sdílet adresu", - "receive_amount": "Částka", - "subaddresses": "Subadresy", "addresses": "Adresy", - "scan_qr_code": "Naskenujte QR kód pro získání adresy", - "qr_fullscreen": "Poklepáním otevřete QR kód na celé obrazovce", - "rename": "Přejmenovat", - "choose_account": "Zvolte částku", - "create_new_account": "Vytvořit nový účet", - "accounts_subaddresses": "Účty a subadresy", - "restore_restore_wallet": "Obnovit peněženku", - "restore_title_from_seed_keys": "Obnovit ze seedu/klíčů", - "restore_description_from_seed_keys": "Obnovte svou peněženku ze seedu/klíčů, které jste si uložili na bezpečném místě", - "restore_next": "Další", - "restore_title_from_backup": "Obnovit ze zálohy", - "restore_description_from_backup": "Můžete obnovit celou Cake Wallet aplikaci ze souboru se zálohou", - "restore_seed_keys_restore": "Obnovit ze seedu/klíčů", - "restore_title_from_seed": "Obnovit ze seedu", - "restore_description_from_seed": "Obnovte svou peněženku pomocí kombinace 25, nebo 13 slov", - "restore_title_from_keys": "Obnovit z klíčů", - "restore_description_from_keys": "Obnovte svou peněženku pomocí generovaných stisků kláves uložených z vašich soukromých klíčů", - "restore_wallet_name": "Jméno peněženky", - "restore_address": "Adresa", - "restore_view_key_private": "Klíč pro zobrazení (soukromý)", - "restore_spend_key_private": "Klíč pro platby (soukromý)", - "restore_recover": "Obnovit", - "restore_wallet_restore_description": "Popis obnovení peněženky", - "restore_new_seed": "Nový seed", - "restore_active_seed": "Aktivní seed", - "restore_bitcoin_description_from_seed": "Obnovte svou peněženku pomocí kombinace 24 slov", - "restore_bitcoin_description_from_keys": "Obnovte svou peněženku pomocí vygenerovaného WIF řetězce z vašich soukromých klíčů", - "restore_bitcoin_title_from_keys": "Obnovit z WIF", - "restore_from_date_or_blockheight": "Prosím zadejte datum z doby několik dnů před tím, než jste si zakládali tuto peněženku. Nebo místo toho zadejte výšku bloku, pokud ji znáte.", - "seed_reminder": "Prosím zapište si toto pro případ ztráty, nebo poškození telefonu", - "seed_title": "Seed", - "seed_share": "Sdílet seed", - "copy": "Kopírovat", - "seed_language": "Jazyk semen", - "seed_choose": "Zvolte si jazyk seedu", - "seed_language_next": "Další", - "seed_language_english": "Angličtina", - "seed_language_chinese": "Čínština", - "seed_language_dutch": "Nizozemština", - "seed_language_german": "Němčina", - "seed_language_japanese": "Japonština", - "seed_language_portuguese": "Portugalština", - "seed_language_russian": "Ruština", - "seed_language_spanish": "Španělština", - "seed_language_french": "Francouzština", - "seed_language_italian": "Italština", - "send_title": "Poslat", - "send_your_wallet": "Vaše peněženka", - "send_address": "${cryptoCurrency} adresa", - "send_payment_id": "ID platby (nepovinné)", + "advanced_settings": "Pokročilé nastavení", + "aggressive": "Agresivní", + "agree": "Souhlasím", + "agree_and_continue": "Souhlasím & pokračovat", + "agree_to": "Vytvořením účtu souhlasíte s ", "all": "VŠE", - "send_error_minimum_value": "Minimální částka je 0,01", - "send_error_currency": "Měna může obsahovat pouze čísla", - "send_estimated_fee": "Odhadovaný poplatek:", - "send_priority": "Momentálně je poplatek nastaven na prioritu: ${transactionPriority}.\nPriorita transakce může být upravena v nastavení.", - "send_creating_transaction": "Vytváření transakce", - "send_templates": "Šablony", - "send_new": "Nová", - "send_amount": "Částka:", - "send_fee": "Poplatek:", - "send_name": "Název", - "got_it": "Rozumím", - "send_sending": "Odesílání...", - "send_success": "Vaše ${crypto} bylo úspěšně odesláno", - "settings_title": "Nastavení", - "settings_nodes": "Uzly", - "settings_current_node": "Aktuální uzel", - "settings_wallets": "Peněženky", - "settings_display_balance": "Zobrazovat zůstatek", - "settings_currency": "Měna", - "settings_fee_priority": "Priorita (poplatky)", - "settings_save_recipient_address": "Ukládat adresu příjemce", - "settings_personal": "Osobní", - "settings_change_pin": "Změnit PIN", - "settings_change_language": "Změnit jazyk", - "settings_allow_biometrical_authentication": "Povolit biometrické ověření", - "settings_dark_mode": "Tmavý režim", - "settings_transactions": "Transakce", - "settings_trades": "Obchody", - "settings_display_on_dashboard_list": "Zobrazit na seznamu na dashboardu", - "settings_all": "VŠE", - "settings_only_trades": "Pouze obchody", - "settings_only_transactions": "Pouze transakce", - "settings_none": "Žádný", - "settings_support": "Podpora", - "settings_terms_and_conditions": "Obchodní podmínky", - "pin_is_incorrect": "PIN není správný", - "setup_pin": "Nastavit PIN", - "enter_your_pin_again": "Zadejte znovu svůj PIN", - "setup_successful": "Váš PIN byl úspěšně nastaven!", - "wallet_keys": "Seed/klíče peněženky", - "wallet_seed": "Seed peněženky", - "private_key": "Soukromý klíč", - "public_key": "Veřejný klíč", - "view_key_private": "Klíč pro zobrazení (soukromý)", - "view_key_public": "Klíč pro zobrazení (veřejný)", - "spend_key_private": "Klíč pro platby (soukromý)", - "spend_key_public": "Klíč pro platby (veřejný)", - "copied_key_to_clipboard": "Zkopírován ${key} do schránky", - "new_subaddress_title": "Nová adresa", - "new_subaddress_label_name": "Popisek", - "new_subaddress_create": "Vytvořit", - "address_label": "Popisek adresy", - "subaddress_title": "Seznam subadres", - "trade_details_title": "Podrobnosti k obchodu", - "trade_details_id": "ID", - "trade_details_state": "Stav", - "trade_details_fetching": "Získávám", - "trade_details_provider": "Poskytovatel", - "trade_details_created_at": "Vytvořeno v", - "trade_details_pair": "Pár", - "trade_details_copied": "${title} zkopírováno do schránky", - "trade_history_title": "Historie obchodů", - "transaction_details_title": "Podrobnosti o transakci", - "transaction_details_transaction_id": "ID transakce", - "transaction_details_date": "Datum", - "transaction_details_height": "Výška", - "transaction_details_amount": "Částka", - "transaction_details_fee": "Poplatek", - "transaction_details_copied": "${title} zkopírováno do schránky", - "transaction_details_recipient_address": "Adresa příjemce", - "wallet_list_title": "Monero Wallet", - "wallet_list_create_new_wallet": "Vytvořit novou peněženku", - "wallet_list_edit_wallet": "Upravit peněženku", - "wallet_list_wallet_name": "Název peněženky", - "wallet_list_restore_wallet": "Obnovit peněženku", - "wallet_list_load_wallet": "Načíst peněženku", - "wallet_list_loading_wallet": "Načítám ${wallet_name} peněženku", - "wallet_list_failed_to_load": "Chyba při načítání ${wallet_name} peněženky. ${error}", - "wallet_list_removing_wallet": "Odstraňuji ${wallet_name} peněženku", - "wallet_list_failed_to_remove": "Chyba při odstraňování ${wallet_name} peněženky. ${error}", - "widgets_address": "Adresa", - "widgets_restore_from_blockheight": "Obnovit z výšky bloku", - "widgets_restore_from_date": "Obnovit z data", - "widgets_or": "nebo", - "widgets_seed": "Seed", - "router_no_route": "Pro ${name} není definována žádná cesta", - "error_text_account_name": "Název účtu může obsahovat jen písmena a čísla\na musí mít délku 1 až 15 znaků", - "error_text_contact_name": "Jméno kontaktu nemůže obsahovat symboly ` , ' \" \na musí mít délku 1 až 32 znaků", - "error_text_address": "Adresa peněženky musí odpovídat typu\nkryptoměny", - "error_text_node_address": "prosím zadejte IPv4 adresu", - "error_text_node_port": "Port uzlu musí být číslo mezi 0 a 65535", - "error_text_node_proxy_address": "Zadejte prosím :, například 127.0.0.1:9050", - "error_text_payment_id": "ID platby se musí skládat z 16 až 64 hexadecimálních znaků", - "error_text_xmr": "Hodnota XMR nemůže překročit dostupný zůstatek.\nPočet desetinných míst musí být menší, nebo roven 12", - "error_text_fiat": "Částka nemůže překročit dostupný zůstatek.\nPočet desetinných míst musí být menší, nebo roven 2", - "error_text_subaddress_name": "Subadresa nemůže obsahovat symboly ` , ' \" \na musí mít délku 1 až 20 znaků", - "error_text_amount": "Částka může obsahovat pouze čísla", - "error_text_wallet_name": "Jméno peněženky může obsahovat pouze písmena, čísla, symbol _ \na musí mít délku 1 až 33 znaků", - "error_text_keys": "Klíče peněženky musí obsahovat 64 hexadecimálních znaků", - "error_text_crypto_currency": "Počet desetinných míst\nmusí být menší, nebo roven 12", - "error_text_minimal_limit": "Obchod pro ${provider} nebyl vytvořen. Částka je menší než minimální hodnota: ${min} ${currency}", - "error_text_maximum_limit": "Obchod pro ${provider} nebyl vytvořen. Částka je větší než maximální hodnota: ${max} ${currency}", - "error_text_limits_loading_failed": "Obchod pro ${provider} nebyl vytvořen. Selhalo načítání limitů", - "error_text_template": "Jméno šablony a adresa nemohou obsahovat symboly ` , ' \" \na musí mít délku 1 až 106 znaků", + "all_trades": "Všechny obchody", + "all_transactions": "Všechny transakce", + "alphabetical": "Abecední", + "already_have_account": "Máte už účet?", + "always": "Vždy", + "amount": "Částka: ", + "amount_is_estimate": "Částka, kterou dostanete, je jen odhad.", + "amount_is_guaranteed": "Částka, kterou dostanete, je konečná", + "and": "a", + "anonpay_description": "Vygenerujte ${type}. Příjemce může ${method} s jakoukoli podporovanou kryptoměnou a vy obdržíte prostředky v této peněžence.", + "apk_update": "aktualizace APK", + "approve": "Schvalovat", + "arrive_in_this_address": "${currency} ${tag}přijde na tuto adresu", + "ascending": "Vzestupné", + "ask_each_time": "Zeptejte se pokaždé", "auth_store_ban_timeout": "ban_timeout", "auth_store_banned_for": "Zablokován na ", "auth_store_banned_minutes": " minut", "auth_store_incorrect_password": "Nesprávný PIN", - "wallet_store_monero_wallet": "Monero Wallet", - "wallet_restoration_store_incorrect_seed_length": "Nesprávná délka seedu", - "full_balance": "Celkový zůstatek", - "available_balance": "Dostupný zůstatek", - "hidden_balance": "Skrytý zůstatek", - "sync_status_syncronizing": "SYNCHRONIZUJI", - "sync_status_syncronized": "SYNCHRONIZOVÁNO", - "sync_status_not_connected": "NEPŘIPOJENO", - "sync_status_starting_sync": "SPOUŠTĚNÍ SYNCHRONIZACE", - "sync_status_failed_connect": "ODPOJENO", - "sync_status_connecting": "PŘIPOJOVÁNÍ", - "sync_status_connected": "PŘIPOJENO", - "sync_status_attempting_sync": "ZAHAJUJI SYNCHR.", - "transaction_priority_slow": "Pomalá", - "transaction_priority_regular": "Běžná", - "transaction_priority_medium": "Střední", - "transaction_priority_fast": "Rychlá", - "transaction_priority_fastest": "Nejrychlejší", - "trade_for_not_created": "Obchod pro ${title} nebyl vytvořen.", - "trade_not_created": "Obchod nebyl vytvořen", - "trade_id_not_found": "Obchod ${tradeId} z ${title} nenalezen.", - "trade_not_found": "Obchod nenalezen.", - "trade_state_pending": "Čekající", - "trade_state_confirming": "Ověřování", - "trade_state_trading": "Obchoduji", - "trade_state_traded": "Zobchodováno", - "trade_state_complete": "Kompletní", - "trade_state_to_be_created": "Bude vytvořen", - "trade_state_unpaid": "Nezaplaceno", - "trade_state_underpaid": "Zaplaceno méně", - "trade_state_paid_unconfirmed": "Nepotvrzeně zaplaceno", - "trade_state_paid": "Zaplaceno", - "trade_state_btc_sent": "BTC odesláno", - "trade_state_timeout": "Vypršel časový limit", - "trade_state_created": "Vytvořeno", - "trade_state_finished": "Hotovo", - "change_language": "Změnit jazyk", - "change_language_to": "Změnit jazyk na ${language}?", - "paste": "Vložit", - "restore_from_seed_placeholder": "Prosím zadejte, nebo vložte ze schránky svůj seed.", - "add_new_word": "Přidat nové slovo", - "incorrect_seed": "Zadaný text není správný.", - "biometric_auth_reason": "Naskenujte otisk prstu pro ověření", - "version": "Verze ${currentVersion}", - "extracted_address_content": "Prostředky budete posílat na\n${recipient_name}", - "card_address": "Adresa:", - "buy": "Koupit", - "sell": "Prodat", - "placeholder_transactions": "Vaše transakce budou zobrazeny zde", - "placeholder_contacts": "Vaše kontakty budou zobrazeny zde", - "template": "Šablona", - "confirm_delete_template": "Tato akce smaže tuto šablonu. Přejete si pokračovat?", - "confirm_delete_wallet": "Tato akce smaže tuto peněženku. Přejete si pokračovat?", - "change_wallet_alert_title": "Přepnout peněženku", - "change_wallet_alert_content": "Opravdu chcete změnit aktivní peněženku na ${wallet_name}?", - "creating_new_wallet": "Vytvářím novou peněženku", - "creating_new_wallet_error": "Chyba: ${description}", - "seed_alert_title": "Pozor", - "seed_alert_content": "Tento seed představuje jedinou možnost, jak obnovit peněženku. Zapsali jste si ho?", - "seed_alert_back": "Zpět", - "seed_alert_yes": "Ano", - "exchange_sync_alert_content": "Prosím počkejte, dokud nebude vaše peněženka synchronizována", - "pre_seed_title": "DŮLEŽITÉ", - "pre_seed_description": "Na následující stránce uvidíte sérii ${words} slov. Je to váš tzv. seed a je to JEDINÁ možnost, jak můžete později obnovit svou peněženku v případě ztráty nebo poruchy. Je VAŠÍ zodpovědností zapsat si ho a uložit si ho na bezpečném místě mimo aplikaci Cake Wallet.", - "pre_seed_button_text": "Rozumím. Ukaž mi můj seed.", - "xmr_to_error": "XMR.TO chyba", - "xmr_to_error_description": "Neplatná částka. Maximálně lze použít 8 desetinných míst", - "provider_error": "${provider} chyba", - "use_ssl": "Použít SSL", - "trusted": "Důvěřovat", - "color_theme": "Barevný motiv", - "light_theme": "Světlý", - "bright_theme": "Jasný", - "dark_theme": "Tmavý", - "enter_your_note": "Zadejte poznámku…", - "note_optional": "Poznámka (nepovinné)", - "note_tap_to_change": "Poznámka (poklepáním upravit)", - "view_in_block_explorer": "Zobrazit v Block Exploreru", - "view_transaction_on": "Zobrazit transakci na ", - "transaction_key": "Klíč transakce", - "confirmations": "Potvrzení", - "recipient_address": "Adresa příjemce", - "extra_id": "Extra ID:", - "destination_tag": "Destination Tag:", - "memo": "Memo:", - "backup": "Záloha", - "change_password": "Změnit heslo", - "backup_password": "Heslo pro zálohy", - "write_down_backup_password": "Prosím zapište si své heslo pro zálohy, které se používá pro import vašich souborů se zálohami.", - "export_backup": "Exportovat zálohu", - "save_backup_password": "Prosím ujistěte se, že máte uschováno heslo pro zálohy. Bez něj nebudete moci naimportovat soubory se zálohami.", - "backup_file": "Soubor se zálohou", - "edit_backup_password": "Upravit heslo pro zálohy", - "save_backup_password_alert": "Uložit heslo pro zálohy", - "change_backup_password_alert": "Vaše předchozí soubory se zálohami nebude možné naimportovat s novým heslem. Nové heslo bude použito pouze pro nové zálohy. Opravdu chcete změnit heslo pro zálohy?", - "enter_backup_password": "Zde zadejte své heslo pro zálohy", - "select_backup_file": "Vybrat soubor se zálohou", - "import": "Import", - "please_select_backup_file": "Prosím vyberte soubor se zálohou a zadejte heslo pro zálohy.", - "fixed_rate": "Pevný kurz", - "fixed_rate_alert": "Když je zvolený pevný kurz, můžete zadat konkrétní částku, kterou chcete dostat. Chcete se přepnout do režimu s pevným kurzem?", - "xlm_extra_info": "Prosím nezapomeňte zadat Memo ID, když posíláte XLM transakce ke směně", - "xrp_extra_info": "Prosím nezapomeňte zadat Destination Tag, když posíláte XRP transakce ke směně", - "exchange_incorrect_current_wallet_for_xmr": "Pokud chcete směnit XMR z Monero částky v Cake Wallet, prosím přepněte se nejprve do své Monero peněženky.", - "confirmed": "Potvrzený zůstatek", - "unconfirmed": "Nepotvrzený zůstatek", - "displayable": "Zobrazitelné", - "submit_request": "odeslat požadavek", - "buy_alert_content": "V současné době podporujeme pouze nákup bitcoinů, etherea, litecoinů a monero. Vytvořte nebo přepněte na svou peněženku bitcoinů, etherea, litecoinů nebo monero.", - "sell_alert_content": "V současné době podporujeme pouze prodej bitcoinů, etherea a litecoinů. Vytvořte nebo přepněte na svou bitcoinovou, ethereum nebo litecoinovou peněženku.", - "outdated_electrum_wallet_description": "Nové Bitcoinové peněženky vytvořené v Cake mají nyní seed se 24 slovy. Je třeba si vytvořit novou Bitcoinovou peněženku se 24 slovy, převést na ni všechny prostředky a přestat používat seed se 12 slovy. Prosím udělejte to hned pro zabezpečení svých prostředků.", - "understand": "Rozumím", - "apk_update": "aktualizace APK", - "buy_bitcoin": "Nakoupit Bitcoin", - "buy_with": "Nakoupit pomocí", - "moonpay_alert_text": "Částka musí být větší nebo rovna ${minAmount} ${fiatCurrency}", - "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é", - "do_not_show_me": "Příště nezobrazovat", - "unspent_coins_title": "Neutracené mince", - "unspent_coins_details_title": "Podrobnosti o neutracených mincích", - "freeze": "Zmrazit", - "frozen": "Zmraženo", - "coin_control": "Volba mincí (nepovinné)", - "address_detected": "Adresa detekována", - "address_from_domain": "Tato adresa je z ${domain} na Unstoppable Domains", - "add_receiver": "Přidat dalšího příjemce (nepovinné)", - "manage_yats": "Spravovat Yaty", - "yat_alert_title": "Posílejte a přijímejte crypto jednodušeji s Yat", - "yat_alert_content": "Uživatelé Cake Wallet mohou nyní posílat a přijímat všechny své oblíbené měny pomocí něco jako uživatelského jména tvořeného emoji.", - "get_your_yat": "Získat Yat", - "connect_an_existing_yat": "Připojit existující Yat", - "connect_yats": "Připojit Yaty", - "yat_address": "Yat adresa", - "yat": "Yat", - "address_from_yat": "Tato adresa je z ${emoji} na Yatu", - "yat_error": "Yat chyba", - "yat_error_content": "Žádná adresa není spojena s tímto Yatem. Zkuste jiný Yat", - "choose_address": "\n\nProsím vyberte adresu:", - "yat_popup_title": "Adresa Vaší peněženky může být emojifikována.", - "yat_popup_content": "Nyní můžete posílat a přijímat crypto v Cake Wallet se svým Yatem - krátkým uživatelským jménem složeným z emoji. Spravujte kdykoliv Yaty na stránce s nastavením", - "second_intro_title": "Jedna emoji adresa vládne všem", - "second_intro_content": "Váš Yat je jediná unikátní emoji adresa, která nahrazuje všechny Vaše dlouhé hexadecimální adresy pro všechny Vaše měny.", - "third_intro_title": "Yat dobře spolupracuje s ostatními", - "third_intro_content": "Yat existuje i mimo Cake Wallet. Jakákoliv adresa peněženky na světě může být nahrazena Yatem!", - "learn_more": "Zjistit více", - "search": "Hledat", - "search_language": "Hledat jazyk", - "search_currency": "Hledat měnu", - "new_template": "Nová šablona", - "electrum_address_disclaimer": "Po každém použití je generována nová adresa, ale předchozí adresy také stále fungují", - "wallet_name_exists": "Peněženka s tímto názvem už existuje. Prosím zvolte si jiný název, nebo nejprve přejmenujte nejprve druhou peněženku.", - "market_place": "Obchod", - "cake_pay_title": "Cake Pay dárkové karty", - "cake_pay_subtitle": "Kupte si zlevněné dárkové karty (pouze USA)", - "cake_pay_web_cards_title": "Cake Pay webové karty", - "cake_pay_web_cards_subtitle": "Kupte si celosvětové předplacené a dárkové karty", - "about_cake_pay": "Cake Pay umožňuje jednoduše nakupovat dárkové karty pomocí virtuálních prostředků, které lze okamžitě uplatnit u více než 150 000 obchodníků ve Spojených státech.", - "cake_pay_account_note": "Přihlaste se svou e-mailovou adresou pro zobrazení a nákup karet. Některé jsou dostupné ve slevě!", - "already_have_account": "Máte už účet?", - "create_account": "Vytvořit účet", - "privacy_policy": "Zásady ochrany soukromí", - "welcome_to_cakepay": "Vítejte v Cake Pay!", - "sign_up": "Registrovat se", - "forgot_password": "Zapomenuté heslo", - "reset_password": "Resetovat heslo", - "gift_cards": "Dárkové karty", - "setup_your_debit_card": "Nastavit debetní kartu", - "no_id_required": "Žádní ID není potřeba. Dobijte si a utrácejte kdekoliv", - "how_to_use_card": "Jak použít tuto kartu", - "purchase_gift_card": "Objednat dárkovou kartu", - "verification": "Ověření", - "fill_code": "Prosím vyplňte ověřovací kód zaslaný na Váš e-mail", - "didnt_get_code": "Nepřišel Vám kód?", - "resend_code": "Prosím poslat znovu", - "debit_card": "Debetní karta", - "cakepay_prepaid_card": "CakePay předplacená debetní karta", - "no_id_needed": "Žádné ID není potřeba!", - "frequently_asked_questions": "Často kladené otázky", - "debit_card_terms": "Uložení a použití vašeho čísla platební karty (a přihlašovací údaje k vašemu číslu karty) v této digitální peněžence se řídí Obchodními podmínkami smlouvy příslušného držitele karty s vydavatelem karty (v jejich nejaktuálnější verzi).", - "please_reference_document": "Více informací naleznete v dokumentu níže.", - "cardholder_agreement": "Smlouva držitele karty", - "e_sign_consent": "E-Sign souhlas", - "agree_and_continue": "Souhlasím & pokračovat", - "email_address": "E-mailová adresa", - "agree_to": "Vytvořením účtu souhlasíte s ", - "and": "a", - "enter_code": "Zadejte kód", - "congratulations": "Gratulujeme!", - "you_now_have_debit_card": "Nyní máte debetní kartu", - "min_amount": "Min: ${value}", - "max_amount": "Max: ${value}", - "enter_amount": "Zadejte částku", - "billing_address_info": "Při dotazu na fakturační adresu, zadejte svou doručovací adresu", - "order_physical_card": "Objednat fyzickou kartu", - "add_value": "Přidat hodnotu", - "activate": "Aktivovat", - "get_a": "Získejte ", - "digital_and_physical_card": " digitální a fyzické předplacené debetní karty,", - "get_card_note": " které můžete nabít digitální měnou. Žádné další informace nejsou vyžadovány!", - "signup_for_card_accept_terms": "Zaregistrujte se pro kartu a souhlaste s podmínkami.", - "add_fund_to_card": "Všechny předplacené prostředky na kartě (až ${value})", - "use_card_info_two": "Prostředky jsou převedeny na USD, když jsou drženy na předplaceném účtu, nikoliv na digitální měnu.", - "use_card_info_three": "Použijte tuto digitální kartu online nebo bezkontaktními platebními metodami.", - "optionally_order_card": "Volitelně objednat fyzickou kartu.", - "hide_details": "Skrýt detaily", - "show_details": "Zobrazit detaily", - "upto": "až ${value}", - "discount": "Ušetříte ${value}%", - "gift_card_amount": "Hodnota dárkové karty", - "bill_amount": "Účtovaná částka", - "you_pay": "Zaplatíte", - "tip": "Spropitné:", - "custom": "vlastní", - "by_cake_pay": "od Cake Pay", - "expires": "Vyprší", - "mm": "MM", - "yy": "YY", - "online": "Online", - "offline": "Offline", - "gift_card_number": "Číslo dárkové karty", - "pin_number": "Číslo PIN", - "total_saving": "Celkem ušetřeno", - "last_30_days": "Posledních 30 dnů", - "avg_savings": "Prům. ušetřeno", - "view_all": "Zobrazit vše", - "active_cards": "Aktivní karty", - "delete_account": "Smazat účet", - "cards": "Karty", - "active": "Aktivní", - "redeemed": "Uplatněné", - "gift_card_balance_note": "Dárkové karty se zbývající částkou se zobrazí zde", - "gift_card_redeemed_note": "Dárkové karty, které jste uplatnili, se zobrazí zde", - "logout": "Odhlásit", - "add_tip": "Přidat spropitné", - "percentageOf": "z ${amount}", - "is_percentage": "je", - "search_category": "Hledat kategorii", - "mark_as_redeemed": "Označit jako uplatněný", - "more_options": "Více možností", - "awaiting_payment_confirmation": "Čeká se na potvrzení platby", - "transaction_sent_notice": "Pokud proces nepokročí během 1 minuty, zkontrolujte block explorer a svůj e-mail.", - "agree": "Souhlasím", - "in_store": "V obchodě", - "generating_gift_card": "Generuji dárkovou kartu", - "payment_was_received": "Vaše platba byla přijata.", - "proceed_after_one_minute": "Pokud proces nepokročí během 1 minuty, zkontrolujte svůj e-mail.", - "order_id": "ID objednávky", - "gift_card_is_generated": "Generuje se dárková karta", - "open_gift_card": "Otevřít dárkovou kartu", - "contact_support": "Kontaktovat podporu", - "gift_cards_unavailable": "Dárkové karty jsou v tuto chvíli dostupné pro zakoupení pouze pomocí Monera, Bitcoinu a Litecoinu.", - "introducing_cake_pay": "Představujeme Cake Pay!", - "cake_pay_learn_more": "Okamžitý nákup a uplatnění dárkových karet v aplikaci!\nPřejeďte prstem zleva doprava pro další informace.", - "automatic": "Automatický", - "fixed_pair_not_supported": "Tento pár s pevným kurzem není ve zvolené směnárně podporován", - "variable_pair_not_supported": "Tento pár s tržním kurzem není ve zvolené směnárně podporován", - "none_of_selected_providers_can_exchange": "Žádný ze zvolených poskytovatelů nemůže provést tuto směnu", - "choose_one": "Zvolte si", - "choose_from_available_options": "Zvolte si z dostupných možností:", - "custom_redeem_amount": "Vlastní částka pro uplatnění", - "add_custom_redemption": "Přidat vlastní uplatnění", - "remaining": "zbývá", - "delete_wallet": "Smazat peněženku", - "delete_wallet_confirm_message": "Opravdu chcete smazat ${wallet_name} peněženku?", - "low_fee": "Nízký poplatek", - "low_fee_alert": "Momentálně máte nastavené nízké poplatky pro transakce. To může způsobovat dlouhé čekání, změnu směnného kurzu, nebo zrušení směny. Doporučujeme nastavit vyšší poplatek.", - "ignor": "Ignorovat", - "use_suggested": "Použít doporučený", - "do_not_share_warning_text": "Toto nesdílejte s nikým jiným, ani s podporou.\n\nJinak mohou být Vaše prostředky ukradeny!", - "help": "pomoc", - "all_transactions": "Všechny transakce", - "all_trades": "Všechny obchody", - "connection_sync": "Připojení a synch.", - "security_and_backup": "Bezpečnost a zálohy", - "create_backup": "Vytvořit zálohu", - "privacy_settings": "Nastavení soukromí", - "privacy": "Soukromí", - "display_settings": "Nastavení zobrazení", - "other_settings": "Další nastavení", - "require_pin_after": "Vyžadovat PIN po", - "always": "Vždy", - "minutes_to_pin_code": "${minute} minutách", - "disable_exchange": "Zakázat směnárny", - "advanced_settings": "Pokročilé nastavení", - "settings_can_be_changed_later": "Tato nastavení mohou být změněna později v nastavení v této aplikaci", - "add_custom_node": "Přidat vlastní uzel", - "disable_fiat": "Zakázat fiat", - "fiat_api": "Fiat API", - "disabled": "Zakázáno", - "enabled": "Povoleno", - "tor_only": "Pouze Tor", - "unmatched_currencies": "Měna vaší současné peněženky neodpovídá té v naskenovaném QR kódu", - "orbot_running_alert": "Prosím ujistěte se, že je Orbot spuštěný, před tím, než se připojíte k tomuto uzlu.", - "contact_list_contacts": "Kontakty", - "contact_list_wallets": "Moje peněženky", - "bitcoin_payments_require_1_confirmation": "U plateb Bitcoinem je vyžadováno alespoň 1 potvrzení, což může trvat 20 minut i déle. Děkujeme za vaši trpělivost! Až bude platba potvrzena, budete informováni e-mailem.", - "send_to_this_address": "Poslat ${currency} ${tag}na tuto adresu", - "arrive_in_this_address": "${currency} ${tag}přijde na tuto adresu", - "do_not_send": "Neodesílat", - "error_dialog_content": "Nastala chyba.\n\nProsím odešlete zprávu o chybě naší podpoře, aby mohli zajistit opravu.", - "decimal_places_error": "Příliš mnoho desetinných míst", - "edit_node": "Upravit uzel", - "invoice_details": "detaily faktury", - "donation_link_details": "Podrobnosti odkazu na darování", - "anonpay_description": "Vygenerujte ${type}. Příjemce může ${method} s jakoukoli podporovanou kryptoměnou a vy obdržíte prostředky v této peněžence.", - "create_invoice": "Vytvořit fakturu", - "create_donation_link": "Vytvořit odkaz na darování", - "optional_email_hint": "Volitelný e-mail s upozorněním na příjemce platby", - "optional_description": "Volitelný popis", - "optional_name": "Volitelné jméno příjemce", - "clearnet_link": "Odkaz na Clearnet", - "onion_link": "Cibulový odkaz", - "sell_monero_com_alert_content": "Prodej Monero zatím není podporován", - "error_text_input_below_minimum_limit": "Částka je menší než minimální hodnota", - "error_text_input_above_maximum_limit": "Částka je větší než maximální hodnota", - "show_market_place": "Zobrazit trh", - "prevent_screenshots": "Zabránit vytváření snímků obrazovky a nahrávání obrazovky", - "profile": "Profil", - "close": "zavřít", - "modify_2fa": "Upravte Cake 2FA", - "disable_cake_2fa": "Zakázat Cake 2FA", - "question_to_disable_2fa": "Opravdu chcete deaktivovat Cake 2FA? Pro přístup k peněžence a některým funkcím již nebude potřeba kód 2FA.", - "disable": "Zakázat", - "setup_2fa": "Nastavení Cake 2FA", - "verify_with_2fa": "Ověřte pomocí Cake 2FA", - "totp_code": "Kód TOTP", - "please_fill_totp": "Vyplňte prosím 8místný kód na vašem druhém zařízení", - "totp_2fa_success": "Úspěch! Pro tuto peněženku povolen Cake 2FA. Nezapomeňte si uložit mnemotechnický klíč pro případ, že ztratíte přístup k peněžence.", - "totp_verification_success": "Ověření proběhlo úspěšně!", - "totp_2fa_failure": "Nesprávný kód. Zkuste prosím jiný kód nebo vygenerujte nový tajný klíč. Použijte kompatibilní aplikaci 2FA, která podporuje 8místné kódy a SHA512.", - "enter_totp_code": "Zadejte kód TOTP.", - "add_secret_code": "Nebo přidejte tento tajný kód do ověřovací aplikace", - "totp_secret_code": "Tajný kód TOTP", - "setup_2fa_text": "Cake 2FA pracuje s použitím TOTP jako druhého autentizačního faktoru.\n\nTOTP Cake 2FA vyžaduje SHA-512 a podporu 8 číslic; to poskytuje zvýšenou bezpečnost. Další informace a podporované aplikace naleznete v průvodci.", - "setup_totp_recommended": "Nastavení TOTP", - "disable_buy": "Zakázat akci nákupu", - "disable_sell": "Zakázat akci prodeje", + "authenticated": "Ověřeno", + "authentication": "Ověřování", "auto_generate_subaddresses": "Automaticky generovat podadresy", - "cake_2fa_preset": "Předvolba Cake 2FA", - "narrow": "Úzký", - "normal": "Normální", - "aggressive": "Agresivní", - "require_for_assessing_wallet": "Vyžadovat pro přístup k peněžence", - "require_for_sends_to_non_contacts": "Vyžadovat pro odesílání nekontaktním osobám", - "require_for_sends_to_contacts": "Vyžadovat pro odeslání kontaktům", - "require_for_sends_to_internal_wallets": "Vyžadovat pro odesílání do interních peněženek", - "require_for_exchanges_to_internal_wallets": "Vyžadovat pro výměny do interních peněženek", - "require_for_adding_contacts": "Vyžadovat pro přidání kontaktů", - "require_for_creating_new_wallets": "Vyžadovat pro vytváření nových peněženek", - "require_for_all_security_and_backup_settings": "Vyžadovat všechna nastavení zabezpečení a zálohování", + "automatic": "Automatický", + "available_balance": "Dostupný zůstatek", "available_balance_description": "Dostupná částka je částka, kterou můžete okamžitě utratit. Zmrazená částka je částka, která ještě není k dispozici, protože ještě nebyla potvrzena síťovým protokolem.", - "syncing_wallet_alert_title": "Vaše peněženka se synchronizuje", - "syncing_wallet_alert_content": "Váš seznam zůstatků a transakcí nemusí být úplný, dokud nebude nahoře uvedeno „SYNCHRONIZOVANÉ“. Kliknutím/klepnutím se dozvíte více.", - "home_screen_settings": "Nastavení domovské obrazovky", - "sort_by": "Seřazeno podle", - "search_add_token": "Hledat / Přidat token", - "edit_token": "Upravit token", - "warning": "Varování", - "add_token_warning": "Neupravujte ani nepřidávejte tokeny podle pokynů podvodníků.\nVždy potvrďte adresy tokenů s renomovanými zdroji!", - "add_token_disclaimer_check": "Potvrdil jsem adresu a informace smlouvy o tokenu pomocí důvěryhodného zdroje. Přidání škodlivých nebo nesprávných informací může vést ke ztrátě finančních prostředků.", - "token_contract_address": "Adresa tokenové smlouvy", - "token_name": "Název tokenu např.: Tether", - "token_symbol": "Symbol tokenu, např.: USDT", - "token_decimal": "Token v desítkové soustavě", - "field_required": "Toto pole je povinné", - "pin_at_top": "špendlík ${token} nahoře", - "invalid_input": "Neplatný vstup", - "fiat_balance": "Fiat Balance", - "gross_balance": "Hrubý zůstatek", - "alphabetical": "Abecední", - "generate_name": "Generovat jméno", + "avg_savings": "Prům. ušetřeno", + "awaitDAppProcessing": "Počkejte, až dApp dokončí zpracování.", + "awaiting_payment_confirmation": "Čeká se na potvrzení platby", + "backup": "Záloha", + "backup_file": "Soubor se zálohou", + "backup_password": "Heslo pro zálohy", "balance_page": "Stránka zůstatku", - "share": "Podíl", - "slidable": "Posuvné", - "monero_dark_theme": "Tmavé téma Monero", + "bill_amount": "Účtovaná částka", + "billing_address_info": "Při dotazu na fakturační adresu, zadejte svou doručovací adresu", + "biometric_auth_reason": "Naskenujte otisk prstu pro ověření", "bitcoin_dark_theme": "Tmavé téma bitcoinů", "bitcoin_light_theme": "Světlé téma bitcoinů", - "high_contrast_theme": "Téma s vysokým kontrastem", - "matrix_green_dark_theme": "Tmavé téma Matrix Green", - "monero_light_theme": "Světlé téma Monero", - "manage_nodes": "Spravovat uzly", - "etherscan_history": "Historie Etherscanu", - "template_name": "Název šablony", + "bitcoin_payments_require_1_confirmation": "U plateb Bitcoinem je vyžadováno alespoň 1 potvrzení, což může trvat 20 minut i déle. Děkujeme za vaši trpělivost! Až bude platba potvrzena, budete informováni e-mailem.", + "Blocks_remaining": "Zbývá ${status} bloků", + "bright_theme": "Jasný", + "buy": "Koupit", + "buy_alert_content": "V současné době podporujeme pouze nákup bitcoinů, etherea, litecoinů a monero. Vytvořte nebo přepněte na svou peněženku bitcoinů, etherea, litecoinů nebo monero.", + "buy_bitcoin": "Nakoupit Bitcoin", + "buy_provider_unavailable": "Poskytovatel aktuálně nedostupný.", + "buy_with": "Nakoupit pomocí", + "by_cake_pay": "od Cake Pay", + "cake_2fa_preset": "Předvolba Cake 2FA", + "cake_pay_account_note": "Přihlaste se svou e-mailovou adresou pro zobrazení a nákup karet. Některé jsou dostupné ve slevě!", + "cake_pay_learn_more": "Okamžitý nákup a uplatnění dárkových karet v aplikaci!\nPřejeďte prstem zleva doprava pro další informace.", + "cake_pay_subtitle": "Kupte si zlevněné dárkové karty (pouze USA)", + "cake_pay_title": "Cake Pay 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_wallet": "Cake Wallet", + "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ů.", + "camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.", + "cancel": "Zrušit", + "card_address": "Adresa:", + "cardholder_agreement": "Smlouva držitele karty", + "cards": "Karty", + "chains": "Řetězy", + "change": "Změnit", + "change_backup_password_alert": "Vaše předchozí soubory se zálohami nebude možné naimportovat s novým heslem. Nové heslo bude použito pouze pro nové zálohy. Opravdu chcete změnit heslo pro zálohy?", + "change_currency": "Změnit měnu", + "change_current_node": "Opravdu chcete změnit současný uzel na ${node}?", + "change_current_node_title": "Změnit současný uzel", + "change_exchange_provider": "Změnit směnárnu", + "change_language": "Změnit jazyk", + "change_language_to": "Změnit jazyk na ${language}?", + "change_password": "Změnit heslo", "change_rep": "Změna zástupce", "change_rep_message": "Jste si jisti, že chcete změnit zástupce?", - "unsupported_asset": "Tuto akci u tohoto díla nepodporujeme. Vytvořte nebo přepněte na peněženku podporovaného typu aktiv.", - "manage_pow_nodes": "Správa uzlů PoW", - "support_title_live_chat": "Živá podpora", - "support_description_live_chat": "Zdarma a rychle! K dispozici jsou zástupci vyškolených podpůrných podpory", - "support_title_guides": "Průvodce peněženkami dortu", - "support_description_guides": "Dokumentace a podpora běžných otázek", - "support_title_other_links": "Další odkazy na podporu", - "support_description_other_links": "Připojte se k našim komunitám nebo se k nám oslovte další metody", + "change_rep_successful": "Úspěšně změnil zástupce", + "change_wallet_alert_content": "Opravdu chcete změnit aktivní peněženku na ${wallet_name}?", + "change_wallet_alert_title": "Přepnout peněženku", + "choose_account": "Zvolte částku", + "choose_address": "\n\nProsím vyberte adresu:", "choose_derivation": "Vyberte derivaci peněženky", - "new_first_wallet_text": "Snadno udržujte svou kryptoměnu v bezpečí", - "select_destination": "Vyberte cíl pro záložní soubor.", - "save_to_downloads": "Uložit do Stažených souborů", - "select_buy_provider_notice": "Vyberte výše uvedeného poskytovatele nákupu. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele nákupu v nastavení aplikace.", - "onramper_option_description": "Rychle si koupte krypto s mnoha metodami plateb. K dispozici ve většině zemí. Rozpětí a poplatky se liší.", + "choose_from_available_options": "Zvolte si z dostupných možností:", + "choose_one": "Zvolte si", + "choose_relay": "Vyberte relé, které chcete použít", + "choose_wallet_currency": "Prosím zvolte si měnu pro peněženku:", + "clear": "Smazat", + "clearnet_link": "Odkaz na Clearnet", + "close": "zavřít", + "coin_control": "Volba mincí (nepovinné)", + "color_theme": "Barevný motiv", + "commit_transaction_amount_fee": "Odeslat transakci\nČástka: ${amount}\nPoplatek: ${fee}", + "confirm": "Potvrdit", + "confirm_delete_template": "Tato akce smaže tuto šablonu. Přejete si pokračovat?", + "confirm_delete_wallet": "Tato akce smaže tuto peněženku. Přejete si pokračovat?", + "confirm_sending": "Potvrdit odeslání", + "confirmations": "Potvrzení", + "confirmed": "Potvrzený zůstatek", + "confirmed_tx": "Potvrzeno", + "congratulations": "Gratulujeme!", + "connect_an_existing_yat": "Připojit existující Yat", + "connect_yats": "Připojit Yaty", + "connection_sync": "Připojení a synch.", + "connectWalletPrompt": "Propojte svou peněženku s WalletConnect a provádějte transakce", + "contact": "Kontakt", + "contact_list_contacts": "Kontakty", + "contact_list_wallets": "Moje peněženky", + "contact_name": "Jméno kontaktu", + "contact_support": "Kontaktovat podporu", + "continue_text": "Pokračovat", + "contractName": "Název smlouvy", + "contractSymbol": "Symbol smlouvy", + "copied_key_to_clipboard": "Zkopírován ${key} do schránky", + "copied_to_clipboard": "Zkopírováno do schránky", + "copy": "Kopírovat", + "copy_address": "Zkopírovat adresu", + "copy_id": "Kopírovat ID", + "copyWalletConnectLink": "Zkopírujte odkaz WalletConnect z dApp a vložte jej sem", + "create_account": "Vytvořit účet", + "create_backup": "Vytvořit zálohu", + "create_donation_link": "Vytvořit odkaz na darování", + "create_invoice": "Vytvořit fakturu", + "create_new": "Vytvořit novou peněženku", + "create_new_account": "Vytvořit nový účet", + "creating_new_wallet": "Vytvářím novou peněženku", + "creating_new_wallet_error": "Chyba: ${description}", + "creation_date": "Datum vzniku", + "custom": "vlastní", + "custom_drag": "Custom (Hold and Drag)", + "custom_redeem_amount": "Vlastní částka pro uplatnění", + "dark_theme": "Tmavý", + "debit_card": "Debetní karta", + "debit_card_terms": "Uložení a použití vašeho čísla platební karty (a přihlašovací údaje k vašemu číslu karty) v této digitální peněžence se řídí Obchodními podmínkami smlouvy příslušného držitele karty s vydavatelem karty (v jejich nejaktuálnější verzi).", + "decimal_places_error": "Příliš mnoho desetinných míst", "default_buy_provider": "Výchozí poskytovatel nákupu", - "ask_each_time": "Zeptejte se pokaždé", - "buy_provider_unavailable": "Poskytovatel aktuálně nedostupný.", - "signTransaction": "Podepsat transakci", + "default_sell_provider": "Výchozí poskytovatel prodeje", + "delete": "Smazat", + "delete_account": "Smazat účet", + "delete_wallet": "Smazat peněženku", + "delete_wallet_confirm_message": "Opravdu chcete smazat ${wallet_name} peněženku?", + "deleteConnectionConfirmationPrompt": "Jste si jisti, že chcete smazat připojení k?", + "descending": "Klesající", + "description": "Popis", + "destination_tag": "Destination Tag:", + "dfx_option_description": "Nakupujte kryptoměny za EUR a CHF. Až 990 € bez dalších KYC. Pro maloobchodní a firemní zákazníky v Evropě", + "didnt_get_code": "Nepřišel Vám kód?", + "digit_pin": "-číselný PIN", + "digital_and_physical_card": " digitální a fyzické předplacené debetní karty,", + "disable": "Zakázat", + "disable_buy": "Zakázat akci nákupu", + "disable_cake_2fa": "Zakázat Cake 2FA", + "disable_exchange": "Zakázat směnárny", + "disable_fiat": "Zakázat fiat", + "disable_sell": "Zakázat akci prodeje", + "disabled": "Zakázáno", + "discount": "Ušetříte ${value}%", + "display_settings": "Nastavení zobrazení", + "displayable": "Zobrazitelné", + "do_not_have_enough_gas_asset": "Nemáte dostatek ${currency} k provedení transakce s aktuálními podmínkami blockchainové sítě. K placení poplatků za blockchainovou síť potřebujete více ${currency}, i když posíláte jiné aktivum.", + "do_not_send": "Neodesílat", + "do_not_share_warning_text": "Toto nesdílejte s nikým jiným, ani s podporou.\n\nJinak mohou být Vaše prostředky ukradeny!", + "do_not_show_me": "Příště nezobrazovat", + "domain_looks_up": "Vyhledávání domén", + "donation_link_details": "Podrobnosti odkazu na darování", + "e_sign_consent": "E-Sign souhlas", + "edit": "Upravit", + "edit_backup_password": "Upravit heslo pro zálohy", + "edit_node": "Upravit uzel", + "edit_token": "Upravit token", + "electrum_address_disclaimer": "Po každém použití je generována nová adresa, ale předchozí adresy také stále fungují", + "email_address": "E-mailová adresa", + "enabled": "Povoleno", + "enter_amount": "Zadejte částku", + "enter_backup_password": "Zde zadejte své heslo pro zálohy", + "enter_code": "Zadejte kód", + "enter_seed_phrase": "Zadejte svou frázi semen", + "enter_totp_code": "Zadejte kód TOTP.", + "enter_your_note": "Zadejte poznámku…", + "enter_your_pin": "Zadejte svůj PIN", + "enter_your_pin_again": "Zadejte znovu svůj PIN", + "enterTokenID": "Zadejte ID tokenu", + "enterWalletConnectURI": "Zadejte identifikátor URI WalletConnect", + "error": "Chyba", + "error_dialog_content": "Nastala chyba.\n\nProsím odešlete zprávu o chybě naší podpoře, aby mohli zajistit opravu.", + "error_text_account_name": "Název účtu může obsahovat jen písmena a čísla\na musí mít délku 1 až 15 znaků", + "error_text_address": "Adresa peněženky musí odpovídat typu\nkryptoměny", + "error_text_amount": "Částka může obsahovat pouze čísla", + "error_text_contact_name": "Jméno kontaktu nemůže obsahovat symboly ` , ' \" \na musí mít délku 1 až 32 znaků", + "error_text_crypto_currency": "Počet desetinných míst\nmusí být menší, nebo roven 12", + "error_text_fiat": "Částka nemůže překročit dostupný zůstatek.\nPočet desetinných míst musí být menší, nebo roven 2", + "error_text_input_above_maximum_limit": "Částka je větší než maximální hodnota", + "error_text_input_below_minimum_limit": "Částka je menší než minimální hodnota", + "error_text_keys": "Klíče peněženky musí obsahovat 64 hexadecimálních znaků", + "error_text_limits_loading_failed": "Obchod pro ${provider} nebyl vytvořen. Selhalo načítání limitů", + "error_text_maximum_limit": "Obchod pro ${provider} nebyl vytvořen. Částka je větší než maximální hodnota: ${max} ${currency}", + "error_text_minimal_limit": "Obchod pro ${provider} nebyl vytvořen. Částka je menší než minimální hodnota: ${min} ${currency}", + "error_text_node_address": "prosím zadejte IPv4 adresu", + "error_text_node_port": "Port uzlu musí být číslo mezi 0 a 65535", + "error_text_node_proxy_address": "Zadejte prosím :, například 127.0.0.1:9050", + "error_text_payment_id": "ID platby se musí skládat z 16 až 64 hexadecimálních znaků", + "error_text_subaddress_name": "Subadresa nemůže obsahovat symboly ` , ' \" \na musí mít délku 1 až 20 znaků", + "error_text_template": "Jméno šablony a adresa nemohou obsahovat symboly ` , ' \" \na musí mít délku 1 až 106 znaků", + "error_text_wallet_name": "Jméno peněženky může obsahovat pouze písmena, čísla, symbol _ \na musí mít délku 1 až 33 znaků", + "error_text_xmr": "Hodnota XMR nemůže překročit dostupný zůstatek.\nPočet desetinných míst musí být menší, nebo roven 12", "errorGettingCredentials": "Selhalo: Chyba při získávání přihlašovacích údajů", "errorSigningTransaction": "Při podepisování transakce došlo k chybě", - "pairingInvalidEvent": "Neplatná událost párování", - "chains": "Řetězy", - "methods": "Metody", - "events": "Události", - "reject": "Odmítnout", - "approve": "Schvalovat", - "expiresOn": "Vyprší dne", - "walletConnect": "WalletConnect", - "nullURIError": "URI je nulové", - "connectWalletPrompt": "Propojte svou peněženku s WalletConnect a provádějte transakce", - "newConnection": "Nové připojení", - "activeConnectionsPrompt": "Zde se zobrazí aktivní připojení", - "deleteConnectionConfirmationPrompt": "Jste si jisti, že chcete smazat připojení k?", + "estimated": "Odhadováno", + "etherscan_history": "Historie Etherscanu", "event": "událost", - "successful": "Úspěšný", - "wouoldLikeToConnect": "by se chtělo připojit", - "message": "Zpráva", - "do_not_have_enough_gas_asset": "Nemáte dostatek ${currency} k provedení transakce s aktuálními podmínkami blockchainové sítě. K placení poplatků za blockchainovou síť potřebujete více ${currency}, i když posíláte jiné aktivum.", - "totp_auth_url": "URL AUTH TOTP", - "awaitDAppProcessing": "Počkejte, až dApp dokončí zpracování.", - "copyWalletConnectLink": "Zkopírujte odkaz WalletConnect z dApp a vložte jej sem", - "enterWalletConnectURI": "Zadejte identifikátor URI WalletConnect", - "seed_key": "Klíč semen", - "enter_seed_phrase": "Zadejte svou frázi semen", - "change_rep_successful": "Úspěšně změnil zástupce", - "add_contact": "Přidat kontakt", + "events": "Události", + "exchange": "Směnit", + "exchange_incorrect_current_wallet_for_xmr": "Pokud chcete směnit XMR z Monero částky v Cake Wallet, prosím přepněte se nejprve do své Monero peněženky.", + "exchange_new_template": "Nová šablona", "exchange_provider_unsupported": "${providerName} již není podporováno!", - "domain_looks_up": "Vyhledávání domén", - "require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek", - "camera_permission_is_required": "Vyžaduje se povolení fotoaparátu.\nPovolte jej v nastavení aplikace.", - "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu", - "order_by": "Seřadit podle", - "creation_date": "Datum vzniku", + "exchange_result_confirm": "Po stisknutí Potvrdit odešlete ${fetchingLabel} ${from} ze své peněženky s názvem ${walletName} na adresu uvedenou níže. Nebo můžete prostředky poslat ze své externí peněženky na níže uvedenou adresu/QR kód.\n\nProsím stiskněte Potvrdit pro pokračování, nebo se vraťte zpět pro změnu částky.", + "exchange_result_description": "Musíte poslat minimálně ${fetchingLabel} ${from} na adresu uvedenou na následující stránce. Pokud pošlete nižší částku než ${fetchingLabel} ${from} nemusí dojít ke směně, ani k jejímu vrácení.", + "exchange_result_write_down_ID": "*Prosím zkopírujte si, nebo zapište si výše uvedené ID.", + "exchange_result_write_down_trade_id": "Prosím zkopírujte si, nebo zapište si ID transakce (trade ID) pro pokračování.", + "exchange_sync_alert_content": "Prosím počkejte, dokud nebude vaše peněženka synchronizována", + "expired": "Vypršelo", + "expires": "Vyprší", + "expiresOn": "Vyprší dne", + "export_backup": "Exportovat zálohu", + "extra_id": "Extra ID:", + "extracted_address_content": "Prostředky budete posílat na\n${recipient_name}", + "failed_authentication": "Ověřování selhalo. ${state_error}", + "faq": "FAQ", + "fetching": "Načítá se", + "fiat_api": "Fiat API", + "fiat_balance": "Fiat Balance", + "field_required": "Toto pole je povinné", + "fill_code": "Prosím vyplňte ověřovací kód zaslaný na Váš e-mail", + "filter_by": "Filtrovat podle", + "first_wallet_text": "Úžasná peněženka pro Monero, Bitcoin, Ethereum, Litecoin a Haven", + "fixed_pair_not_supported": "Tento pár s pevným kurzem není ve zvolené směnárně podporován", + "fixed_rate": "Pevný kurz", + "fixed_rate_alert": "Když je zvolený pevný kurz, můžete zadat konkrétní částku, kterou chcete dostat. Chcete se přepnout do režimu s pevným kurzem?", + "forgot_password": "Zapomenuté heslo", + "freeze": "Zmrazit", + "frequently_asked_questions": "Často kladené otázky", + "frozen": "Zmraženo", + "full_balance": "Celkový zůstatek", + "generate_name": "Generovat jméno", + "generating_gift_card": "Generuji dárkovou kartu", + "get_a": "Získejte ", + "get_card_note": " které můžete nabít digitální měnou. Žádné další informace nejsou vyžadovány!", + "get_your_yat": "Získat Yat", + "gift_card_amount": "Hodnota dárkové karty", + "gift_card_balance_note": "Dárkové karty se zbývající částkou se zobrazí zde", + "gift_card_is_generated": "Generuje se dárková karta", + "gift_card_number": "Číslo dárkové karty", + "gift_card_redeemed_note": "Dárkové karty, které jste uplatnili, se zobrazí zde", + "gift_cards": "Dárkové karty", + "gift_cards_unavailable": "Dárkové karty jsou v tuto chvíli dostupné pro zakoupení pouze pomocí Monera, Bitcoinu a Litecoinu.", + "got_it": "Rozumím", + "gross_balance": "Hrubý zůstatek", "group_by_type": "Skupina podle typu", - "importNFTs": "Importujte NFT", - "noNFTYet": "Zatím žádné NFT", - "address": "Adresa", - "enterTokenID": "Zadejte ID tokenu", - "tokenID": "ID", - "name": "název", - "symbol": "Symbol", - "seed_phrase_length": "Délka fráze semene", - "unavailable_balance": "Nedostupný zůstatek", - "unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.", - "unspent_change": "Změna", - "tor_connection": "Připojení Tor", - "setup_warning_2fa_text": "Budete muset obnovit svou peněženku z mnemotechnického semínka.\n\nPodpora dortů vám nebude schopna pomoci, pokud ztratíte přístup ke svým 2FA nebo mnemotechnickým semenům.\nCake 2FA je druhá autentizace pro určité akce v peněžence. Před použitím Cake 2FA doporučujeme přečíst si průvodce.NENÍ tak bezpečný jako skladování v chladu.\n\nPokud ztratíte přístup ke své aplikaci 2FA nebo klíčům TOTP, ztratíte přístup k této peněžence. ", - "scan_qr_on_device": "Naskenujte tento QR kód na jiném zařízení", + "haven_app": "Haven od Cake Wallet", + "haven_app_wallet_text": "Úžasná peněženka pro Haven", + "help": "pomoc", + "hidden_balance": "Skrytý zůstatek", + "hide_details": "Skrýt detaily", + "high_contrast_theme": "Téma s vysokým kontrastem", + "home_screen_settings": "Nastavení domovské obrazovky", "how_to_use": "Jak používat", + "how_to_use_card": "Jak použít tuto kartu", + "id": "ID: ", + "ignor": "Ignorovat", + "import": "Import", + "importNFTs": "Importujte NFT", + "in_store": "V obchodě", + "incoming": "Příchozí", + "incorrect_seed": "Zadaný text není správný.", + "introducing_cake_pay": "Představujeme Cake Pay!", + "invalid_input": "Neplatný vstup", + "invoice_details": "detaily faktury", + "is_percentage": "je", + "last_30_days": "Posledních 30 dnů", + "learn_more": "Zjistit více", + "light_theme": "Světlý", + "loading_your_wallet": "Načítám peněženku", + "login": "Login", + "logout": "Odhlásit", + "low_fee": "Nízký poplatek", + "low_fee_alert": "Momentálně máte nastavené nízké poplatky pro transakce. To může způsobovat dlouhé čekání, změnu směnného kurzu, nebo zrušení směny. Doporučujeme nastavit vyšší poplatek.", + "manage_nodes": "Spravovat uzly", + "manage_pow_nodes": "Správa uzlů PoW", + "manage_yats": "Spravovat Yaty", + "mark_as_redeemed": "Označit jako uplatněný", + "market_place": "Obchod", + "matrix_green_dark_theme": "Tmavé téma Matrix Green", + "max_amount": "Max: ${value}", + "max_value": "Max: ${value} ${currency}", + "memo": "Memo:", + "message": "Zpráva", + "methods": "Metody", + "min_amount": "Min: ${value}", + "min_value": "Min: ${value} ${currency}", + "minutes_to_pin_code": "${minute} minutách", + "mm": "MM", + "modify_2fa": "Upravte Cake 2FA", + "monero_com": "Monero.com od Cake Wallet", + "monero_com_wallet_text": "Úžasná peněženka pro Monero", + "monero_dark_theme": "Tmavé téma Monero", + "monero_light_theme": "Světlé téma Monero", + "moonpay_alert_text": "Částka musí být větší nebo rovna ${minAmount} ${fiatCurrency}", + "more_options": "Více možností", + "name": "název", + "narrow": "Úzký", + "new_first_wallet_text": "Snadno udržujte svou kryptoměnu v bezpečí", + "new_node_testing": "Testování nového uzlu", + "new_subaddress_create": "Vytvořit", + "new_subaddress_label_name": "Popisek", + "new_subaddress_title": "Nová adresa", + "new_template": "Nová šablona", + "new_wallet": "Nová peněženka", + "newConnection": "Nové připojení", + "no_id_needed": "Žádné ID není potřeba!", + "no_id_required": "Žádní ID není potřeba. Dobijte si a utrácejte kdekoliv", + "no_relay_on_domain": "Pro doménu uživatele neexistuje přenos nebo je přenos nedostupný. Vyberte relé, které chcete použít.", + "no_relays": "Žádná relé", + "no_relays_message": "Pro tohoto uživatele jsme našli záznam Nostr NIP-05, který však neobsahuje žádná relé. Požádejte příjemce, aby přidal přenosy do svého záznamu Nostr.", + "node_address": "Adresa uzlu", + "node_connection_failed": "Připojení selhalo", + "node_connection_successful": "Připojení bylo úspěšné", + "node_new": "Nový uzel", + "node_port": "Port uzlu", + "node_reset_settings_title": "Zrušit nastavení", + "node_test": "Otestovat", + "nodes": "Uzly", + "nodes_list_reset_to_default_message": "Opravdu chcete zrušit nastavení a vrátit výchozí hodnotu?", + "none_of_selected_providers_can_exchange": "Žádný ze zvolených poskytovatelů nemůže provést tuto směnu", + "noNFTYet": "Zatím žádné NFT", + "normal": "Normální", + "note_optional": "Poznámka (nepovinné)", + "note_tap_to_change": "Poznámka (poklepáním upravit)", + "nullURIError": "URI je nulové", + "offer_expires_in": "Nabídka vyprší: ", + "offline": "Offline", + "ok": "OK", + "onion_link": "Cibulový odkaz", + "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", + "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", + "optionally_order_card": "Volitelně objednat fyzickou kartu.", + "orbot_running_alert": "Prosím ujistěte se, že je Orbot spuštěný, před tím, než se připojíte k tomuto uzlu.", + "order_by": "Seřadit podle", + "order_id": "ID objednávky", + "order_physical_card": "Objednat fyzickou kartu", + "other_settings": "Další nastavení", + "outdated_electrum_wallet_description": "Nové Bitcoinové peněženky vytvořené v Cake mají nyní seed se 24 slovy. Je třeba si vytvořit novou Bitcoinovou peněženku se 24 slovy, převést na ni všechny prostředky a přestat používat seed se 12 slovy. Prosím udělejte to hned pro zabezpečení svých prostředků.", + "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í", + "overwrite_amount": "Přepsat částku", + "pairingInvalidEvent": "Neplatná událost párování", + "password": "Heslo", + "paste": "Vložit", + "pause_wallet_creation": "Možnost vytvářet Haven Wallet je momentálně pozastavena.", + "payment_id": "ID platby: ", + "payment_was_received": "Vaše platba byla přijata.", + "pending": " (čeká)", + "percentageOf": "z ${amount}", + "pin_at_top": "špendlík ${token} nahoře", + "pin_is_incorrect": "PIN není správný", + "pin_number": "Číslo PIN", + "placeholder_contacts": "Vaše kontakty budou zobrazeny zde", + "placeholder_transactions": "Vaše transakce budou zobrazeny zde", + "please_fill_totp": "Vyplňte prosím 8místný kód na vašem druhém zařízení", + "please_make_selection": "Prosím vyberte si níže, jestli chcete vytvořit, nebo obnovit peněženku.", + "please_reference_document": "Více informací naleznete v dokumentu níže.", + "please_select": "Zvolte si:", + "please_select_backup_file": "Prosím vyberte soubor se zálohou a zadejte heslo pro zálohy.", + "please_try_to_connect_to_another_node": "Zkuste se prosím připojit k jinému uzlu", + "polygonscan_history": "Historie PolygonScan", + "powered_by": "Zajišťuje ${title}", + "pre_seed_button_text": "Rozumím. Ukaž mi můj seed.", + "pre_seed_description": "Na následující stránce uvidíte sérii ${words} slov. Je to váš tzv. seed a je to JEDINÁ možnost, jak můžete později obnovit svou peněženku v případě ztráty nebo poruchy. Je VAŠÍ zodpovědností zapsat si ho a uložit si ho na bezpečném místě mimo aplikaci Cake Wallet.", + "pre_seed_title": "DŮLEŽITÉ", + "prevent_screenshots": "Zabránit vytváření snímků obrazovky a nahrávání obrazovky", + "privacy": "Soukromí", + "privacy_policy": "Zásady ochrany soukromí", + "privacy_settings": "Nastavení soukromí", + "private_key": "Soukromý klíč", + "proceed_after_one_minute": "Pokud proces nepokročí během 1 minuty, zkontrolujte svůj e-mail.", + "profile": "Profil", + "provider_error": "${provider} chyba", + "public_key": "Veřejný klíč", + "purchase_gift_card": "Objednat dárkovou kartu", + "qr_fullscreen": "Poklepáním otevřete QR kód na celé obrazovce", + "qr_payment_amount": "Tento QR kód obsahuje i částku. Chcete přepsat současnou hodnotu?", + "question_to_disable_2fa": "Opravdu chcete deaktivovat Cake 2FA? Pro přístup k peněžence a některým funkcím již nebude potřeba kód 2FA.", + "receivable_balance": "Zůstatek pohledávek", + "receive": "Přijmout", + "receive_amount": "Částka", + "received": "Přijato", + "recipient_address": "Adresa příjemce", + "reconnect": "Znovu připojit", + "reconnect_alert_text": "Opravdu se chcete znovu připojit?", + "reconnection": "Znovu připojit", + "redeemed": "Uplatněné", + "refund_address": "Adresa pro vrácení", + "reject": "Odmítnout", + "remaining": "zbývá", + "remove": "Odstranit", + "remove_node": "Odstranit uzel", + "remove_node_message": "Opravdu chcete odstranit označený uzel?", + "rename": "Přejmenovat", + "require_for_adding_contacts": "Vyžadovat pro přidání kontaktů", + "require_for_all_security_and_backup_settings": "Vyžadovat všechna nastavení zabezpečení a zálohování", + "require_for_assessing_wallet": "Vyžadovat pro přístup k peněžence", + "require_for_creating_new_wallets": "Vyžadovat pro vytváření nových peněženek", + "require_for_exchanges_to_external_wallets": "Vyžadovat pro výměny do externích peněženek", + "require_for_exchanges_to_internal_wallets": "Vyžadovat pro výměny do interních peněženek", + "require_for_sends_to_contacts": "Vyžadovat pro odeslání kontaktům", + "require_for_sends_to_internal_wallets": "Vyžadovat pro odesílání do interních peněženek", + "require_for_sends_to_non_contacts": "Vyžadovat pro odesílání nekontaktním osobám", + "require_pin_after": "Vyžadovat PIN po", + "rescan": "Znovu prohledat", + "resend_code": "Prosím poslat znovu", + "reset": "Vymazat", + "reset_password": "Resetovat heslo", + "restore_active_seed": "Aktivní seed", + "restore_address": "Adresa", + "restore_bitcoin_description_from_keys": "Obnovte svou peněženku pomocí vygenerovaného WIF řetězce z vašich soukromých klíčů", + "restore_bitcoin_description_from_seed": "Obnovte svou peněženku pomocí kombinace 24 slov", + "restore_bitcoin_title_from_keys": "Obnovit z WIF", + "restore_description_from_backup": "Můžete obnovit celou Cake Wallet aplikaci ze souboru se zálohou", + "restore_description_from_keys": "Obnovte svou peněženku pomocí generovaných stisků kláves uložených z vašich soukromých klíčů", + "restore_description_from_seed": "Obnovte svou peněženku pomocí kombinace 25, nebo 13 slov", + "restore_description_from_seed_keys": "Obnovte svou peněženku ze seedu/klíčů, které jste si uložili na bezpečném místě", + "restore_from_date_or_blockheight": "Prosím zadejte datum z doby několik dnů před tím, než jste si zakládali tuto peněženku. Nebo místo toho zadejte výšku bloku, pokud ji znáte.", + "restore_from_seed_placeholder": "Prosím zadejte, nebo vložte ze schránky svůj seed.", + "restore_new_seed": "Nový seed", + "restore_next": "Další", + "restore_recover": "Obnovit", + "restore_restore_wallet": "Obnovit peněženku", + "restore_seed_keys_restore": "Obnovit ze seedu/klíčů", + "restore_spend_key_private": "Klíč pro platby (soukromý)", + "restore_title_from_backup": "Obnovit ze zálohy", + "restore_title_from_keys": "Obnovit z klíčů", + "restore_title_from_seed": "Obnovit ze seedu", + "restore_title_from_seed_keys": "Obnovit ze seedu/klíčů", + "restore_view_key_private": "Klíč pro zobrazení (soukromý)", + "restore_wallet": "Obnovit peněženku", + "restore_wallet_name": "Jméno peněženky", + "restore_wallet_restore_description": "Popis obnovení peněženky", + "router_no_route": "Pro ${name} není definována žádná cesta", + "save": "Uložit", + "save_backup_password": "Prosím ujistěte se, že máte uschováno heslo pro zálohy. Bez něj nebudete moci naimportovat soubory se zálohami.", + "save_backup_password_alert": "Uložit heslo pro zálohy", + "save_to_downloads": "Uložit do Stažených souborů", + "saved_the_trade_id": "Uložil jsem si ID transakce (trade ID)", + "scan_qr_code": "Naskenujte QR kód pro získání adresy", + "scan_qr_on_device": "Naskenujte tento QR kód na jiném zařízení", + "search": "Hledat", + "search_add_token": "Hledat / Přidat token", + "search_category": "Hledat kategorii", + "search_currency": "Hledat měnu", + "search_language": "Hledat jazyk", + "second_intro_content": "Váš Yat je jediná unikátní emoji adresa, která nahrazuje všechny Vaše dlouhé hexadecimální adresy pro všechny Vaše měny.", + "second_intro_title": "Jedna emoji adresa vládne všem", + "security_and_backup": "Bezpečnost a zálohy", + "seed_alert_back": "Zpět", + "seed_alert_content": "Tento seed představuje jedinou možnost, jak obnovit peněženku. Zapsali jste si ho?", + "seed_alert_title": "Pozor", + "seed_alert_yes": "Ano", + "seed_choose": "Zvolte si jazyk seedu", "seed_hex_form": "Semeno peněženky (hex formulář)", + "seed_key": "Klíč semen", + "seed_language": "Jazyk semen", + "seed_language_chinese": "Čínština", + "seed_language_chinese_traditional": "Číňan (tradiční)", + "seed_language_czech": "čeština", + "seed_language_dutch": "Nizozemština", + "seed_language_english": "Angličtina", + "seed_language_french": "Francouzština", + "seed_language_german": "Němčina", + "seed_language_italian": "Italština", + "seed_language_japanese": "Japonština", + "seed_language_korean": "korejština", + "seed_language_next": "Další", + "seed_language_portuguese": "Portugalština", + "seed_language_russian": "Ruština", + "seed_language_spanish": "Španělština", + "seed_phrase_length": "Délka fráze semene", + "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", "seedtype": "SeedType", "seedtype_legacy": "Legacy (25 slov)", "seedtype_polyseed": "Polyseed (16 slov)", - "seed_language_czech": "čeština", - "seed_language_korean": "korejština", - "seed_language_chinese_traditional": "Číňan (tradiční)", - "ascending": "Vzestupné", - "descending": "Klesající", - "dfx_option_description": "Nakupujte kryptoměny za EUR a CHF. Až 990 € bez dalších KYC. Pro maloobchodní a firemní zákazníky v Evropě", - "polygonscan_history": "Historie PolygonScan", - "wallet_seed_legacy": "Starší semeno peněženky", - "default_sell_provider": "Výchozí poskytovatel prodeje", + "select_backup_file": "Vybrat soubor se zálohou", + "select_buy_provider_notice": "Vyberte výše uvedeného poskytovatele nákupu. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele nákupu v nastavení aplikace.", + "select_destination": "Vyberte cíl pro záložní soubor.", "select_sell_provider_notice": "Výše vyberte poskytovatele prodeje. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele prodeje v nastavení aplikace.", - "custom_drag": "Custom (Hold and Drag)", + "sell": "Prodat", + "sell_alert_content": "V současné době podporujeme pouze prodej bitcoinů, etherea a litecoinů. Vytvořte nebo přepněte na svou bitcoinovou, ethereum nebo litecoinovou peněženku.", + "sell_monero_com_alert_content": "Prodej Monero zatím není podporován", + "send": "Poslat", + "send_address": "${cryptoCurrency} adresa", + "send_amount": "Částka:", + "send_creating_transaction": "Vytváření transakce", + "send_error_currency": "Měna může obsahovat pouze čísla", + "send_error_minimum_value": "Minimální částka je 0,01", + "send_estimated_fee": "Odhadovaný poplatek:", + "send_fee": "Poplatek:", + "send_name": "Název", + "send_new": "Nová", + "send_payment_id": "ID platby (nepovinné)", + "send_priority": "Momentálně je poplatek nastaven na prioritu: ${transactionPriority}.\nPriorita transakce může být upravena v nastavení.", + "send_sending": "Odesílání...", + "send_success": "Vaše ${crypto} bylo úspěšně odesláno", + "send_templates": "Šablony", + "send_title": "Poslat", + "send_to_this_address": "Poslat ${currency} ${tag}na tuto adresu", + "send_xmr": "Odeslat XMR", + "send_your_wallet": "Vaše peněženka", + "sending": "Odesílání", + "sent": "Odesláno", + "settings_all": "VŠE", + "settings_allow_biometrical_authentication": "Povolit biometrické ověření", + "settings_can_be_changed_later": "Tato nastavení mohou být změněna později v nastavení v této aplikaci", + "settings_change_language": "Změnit jazyk", + "settings_change_pin": "Změnit PIN", + "settings_currency": "Měna", + "settings_current_node": "Aktuální uzel", + "settings_dark_mode": "Tmavý režim", + "settings_display_balance": "Zobrazovat zůstatek", + "settings_display_on_dashboard_list": "Zobrazit na seznamu na dashboardu", + "settings_fee_priority": "Priorita (poplatky)", + "settings_nodes": "Uzly", + "settings_none": "Žádný", + "settings_only_trades": "Pouze obchody", + "settings_only_transactions": "Pouze transakce", + "settings_personal": "Osobní", + "settings_save_recipient_address": "Ukládat adresu příjemce", + "settings_support": "Podpora", + "settings_terms_and_conditions": "Obchodní podmínky", + "settings_title": "Nastavení", + "settings_trades": "Obchody", + "settings_transactions": "Transakce", + "settings_wallets": "Peněženky", + "setup_2fa": "Nastavení Cake 2FA", + "setup_2fa_text": "Cake 2FA pracuje s použitím TOTP jako druhého autentizačního faktoru.\n\nTOTP Cake 2FA vyžaduje SHA-512 a podporu 8 číslic; to poskytuje zvýšenou bezpečnost. Další informace a podporované aplikace naleznete v průvodci.", + "setup_pin": "Nastavit PIN", + "setup_successful": "Váš PIN byl úspěšně nastaven!", + "setup_totp_recommended": "Nastavení TOTP", + "setup_warning_2fa_text": "Budete muset obnovit svou peněženku z mnemotechnického semínka.\n\nPodpora dortů vám nebude schopna pomoci, pokud ztratíte přístup ke svým 2FA nebo mnemotechnickým semenům.\nCake 2FA je druhá autentizace pro určité akce v peněžence. Před použitím Cake 2FA doporučujeme přečíst si průvodce.NENÍ tak bezpečný jako skladování v chladu.\n\nPokud ztratíte přístup ke své aplikaci 2FA nebo klíčům TOTP, ztratíte přístup k této peněžence. ", + "setup_your_debit_card": "Nastavit debetní kartu", + "share": "Podíl", + "share_address": "Sdílet adresu", + "show_details": "Zobrazit detaily", + "show_keys": "Zobrazit seed/klíče", + "show_market_place": "Zobrazit trh", + "show_seed": "Zobrazit seed", + "sign_up": "Registrovat se", + "signTransaction": "Podepsat transakci", + "signup_for_card_accept_terms": "Zaregistrujte se pro kartu a souhlaste s podmínkami.", + "slidable": "Posuvné", + "sort_by": "Seřazeno podle", + "spend_key_private": "Klíč pro platby (soukromý)", + "spend_key_public": "Klíč pro platby (veřejný)", + "status": "Status: ", + "subaddress_title": "Seznam subadres", + "subaddresses": "Subadresy", + "submit_request": "odeslat požadavek", + "successful": "Úspěšný", + "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_live_chat": "Živá podpora", + "support_title_other_links": "Další odkazy na podporu", + "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu", "switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)", - "receivable_balance": "Zůstatek pohledávek", - "confirmed_tx": "Potvrzeno", + "symbol": "Symbol", + "sync_status_attempting_sync": "ZAHAJUJI SYNCHR.", + "sync_status_connected": "PŘIPOJENO", + "sync_status_connecting": "PŘIPOJOVÁNÍ", + "sync_status_failed_connect": "ODPOJENO", + "sync_status_not_connected": "NEPŘIPOJENO", + "sync_status_starting_sync": "SPOUŠTĚNÍ SYNCHRONIZACE", + "sync_status_syncronized": "SYNCHRONIZOVÁNO", + "sync_status_syncronizing": "SYNCHRONIZUJI", + "syncing_wallet_alert_content": "Váš seznam zůstatků a transakcí nemusí být úplný, dokud nebude nahoře uvedeno „SYNCHRONIZOVANÉ“. Kliknutím/klepnutím se dozvíte více.", + "syncing_wallet_alert_title": "Vaše peněženka se synchronizuje", + "template": "Šablona", + "template_name": "Název šablony", + "third_intro_content": "Yat existuje i mimo Cake Wallet. Jakákoliv adresa peněženky na světě může být nahrazena Yatem!", + "third_intro_title": "Yat dobře spolupracuje s ostatními", + "time": "${minutes}m ${seconds}s", + "tip": "Spropitné:", + "today": "Dnes", + "token_contract_address": "Adresa tokenové smlouvy", + "token_decimal": "Token v desítkové soustavě", + "token_name": "Název tokenu např.: Tether", + "token_symbol": "Symbol tokenu, např.: USDT", + "tokenID": "ID", + "tor_connection": "Připojení Tor", + "tor_only": "Pouze Tor", + "total_saving": "Celkem ušetřeno", + "totp_2fa_failure": "Nesprávný kód. Zkuste prosím jiný kód nebo vygenerujte nový tajný klíč. Použijte kompatibilní aplikaci 2FA, která podporuje 8místné kódy a SHA512.", + "totp_2fa_success": "Úspěch! Pro tuto peněženku povolen Cake 2FA. Nezapomeňte si uložit mnemotechnický klíč pro případ, že ztratíte přístup k peněžence.", + "totp_auth_url": "URL AUTH TOTP", + "totp_code": "Kód TOTP", + "totp_secret_code": "Tajný kód TOTP", + "totp_verification_success": "Ověření proběhlo úspěšně!", + "trade_details_copied": "${title} zkopírováno do schránky", + "trade_details_created_at": "Vytvořeno v", + "trade_details_fetching": "Získávám", + "trade_details_id": "ID", + "trade_details_pair": "Pár", + "trade_details_provider": "Poskytovatel", + "trade_details_state": "Stav", + "trade_details_title": "Podrobnosti k obchodu", + "trade_for_not_created": "Obchod pro ${title} nebyl vytvořen.", + "trade_history_title": "Historie obchodů", + "trade_id": "ID transakce (trade ID):", + "trade_id_not_found": "Obchod ${tradeId} z ${title} nenalezen.", + "trade_is_powered_by": "Tento obchod zajišťuje ${provider}", + "trade_not_created": "Obchod nebyl vytvořen", + "trade_not_found": "Obchod nenalezen.", + "trade_state_btc_sent": "BTC odesláno", + "trade_state_complete": "Kompletní", + "trade_state_confirming": "Ověřování", + "trade_state_created": "Vytvořeno", + "trade_state_finished": "Hotovo", + "trade_state_paid": "Zaplaceno", + "trade_state_paid_unconfirmed": "Nepotvrzeně zaplaceno", + "trade_state_pending": "Čekající", + "trade_state_timeout": "Vypršel časový limit", + "trade_state_to_be_created": "Bude vytvořen", + "trade_state_traded": "Zobchodováno", + "trade_state_trading": "Obchoduji", + "trade_state_underpaid": "Zaplaceno méně", + "trade_state_unpaid": "Nezaplaceno", + "trades": "Obchody", + "transaction_details_amount": "Částka", + "transaction_details_copied": "${title} zkopírováno do schránky", + "transaction_details_date": "Datum", + "transaction_details_fee": "Poplatek", + "transaction_details_height": "Výška", + "transaction_details_recipient_address": "Adresa příjemce", "transaction_details_source_address": "Zdrojová adresa", - "pause_wallet_creation": "Možnost vytvářet Haven Wallet je momentálně pozastavena.", - "contractName": "Název smlouvy", - "contractSymbol": "Symbol smlouvy", - "description": "Popis", - "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ů.", - "no_relays": "Žádná relé", - "choose_relay": "Vyberte relé, které chcete použít", - "no_relays_message": "Pro tohoto uživatele jsme našli záznam Nostr NIP-05, který však neobsahuje žádná relé. Požádejte příjemce, aby přidal přenosy do svého záznamu Nostr.", - "no_relay_on_domain": "Pro doménu uživatele neexistuje přenos nebo je přenos nedostupný. Vyberte relé, které chcete použít." -} + "transaction_details_title": "Podrobnosti o transakci", + "transaction_details_transaction_id": "ID transakce", + "transaction_key": "Klíč transakce", + "transaction_priority_fast": "Rychlá", + "transaction_priority_fastest": "Nejrychlejší", + "transaction_priority_medium": "Střední", + "transaction_priority_regular": "Běžná", + "transaction_priority_slow": "Pomalá", + "transaction_sent": "Transakce odeslána!", + "transaction_sent_notice": "Pokud proces nepokročí během 1 minuty, zkontrolujte block explorer a svůj e-mail.", + "transactions": "Transakce", + "transactions_by_date": "Transakce podle data", + "trusted": "Důvěřovat", + "unavailable_balance": "Nedostupný zůstatek", + "unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.", + "unconfirmed": "Nepotvrzený zůstatek", + "understand": "Rozumím", + "unmatched_currencies": "Měna vaší současné peněženky neodpovídá té v naskenovaném QR kódu", + "unspent_change": "Změna", + "unspent_coins_details_title": "Podrobnosti o neutracených mincích", + "unspent_coins_title": "Neutracené mince", + "unsupported_asset": "Tuto akci u tohoto díla nepodporujeme. Vytvořte nebo přepněte na peněženku podporovaného typu aktiv.", + "upto": "až ${value}", + "use": "Přepnout na ", + "use_card_info_three": "Použijte tuto digitální kartu online nebo bezkontaktními platebními metodami.", + "use_card_info_two": "Prostředky jsou převedeny na USD, když jsou drženy na předplaceném účtu, nikoliv na digitální měnu.", + "use_ssl": "Použít SSL", + "use_suggested": "Použít doporučený", + "variable_pair_not_supported": "Tento pár s tržním kurzem není ve zvolené směnárně podporován", + "verification": "Ověření", + "verify_with_2fa": "Ověřte pomocí Cake 2FA", + "version": "Verze ${currentVersion}", + "view_all": "Zobrazit vše", + "view_in_block_explorer": "Zobrazit v Block Exploreru", + "view_key_private": "Klíč pro zobrazení (soukromý)", + "view_key_public": "Klíč pro zobrazení (veřejný)", + "view_transaction_on": "Zobrazit transakci na ", + "wallet_keys": "Seed/klíče peněženky", + "wallet_list_create_new_wallet": "Vytvořit novou peněženku", + "wallet_list_edit_wallet": "Upravit peněženku", + "wallet_list_failed_to_load": "Chyba při načítání ${wallet_name} peněženky. ${error}", + "wallet_list_failed_to_remove": "Chyba při odstraňování ${wallet_name} peněženky. ${error}", + "wallet_list_load_wallet": "Načíst peněženku", + "wallet_list_loading_wallet": "Načítám ${wallet_name} peněženku", + "wallet_list_removing_wallet": "Odstraňuji ${wallet_name} peněženku", + "wallet_list_restore_wallet": "Obnovit peněženku", + "wallet_list_title": "Monero Wallet", + "wallet_list_wallet_name": "Název peněženky", + "wallet_menu": "Menu", + "wallet_name": "Název peněženky", + "wallet_name_exists": "Peněženka s tímto názvem už existuje. Prosím zvolte si jiný název, nebo nejprve přejmenujte nejprve druhou peněženku.", + "wallet_restoration_store_incorrect_seed_length": "Nesprávná délka seedu", + "wallet_seed": "Seed peněženky", + "wallet_seed_legacy": "Starší semeno peněženky", + "wallet_store_monero_wallet": "Monero Wallet", + "walletConnect": "WalletConnect", + "wallets": "Peněženky", + "warning": "Varování", + "welcome": "Vítejte v", + "welcome_to_cakepay": "Vítejte v Cake Pay!", + "widgets_address": "Adresa", + "widgets_or": "nebo", + "widgets_restore_from_blockheight": "Obnovit z výšky bloku", + "widgets_restore_from_date": "Obnovit z data", + "widgets_seed": "Seed", + "wouoldLikeToConnect": "by se chtělo připojit", + "write_down_backup_password": "Prosím zapište si své heslo pro zálohy, které se používá pro import vašich souborů se zálohami.", + "xlm_extra_info": "Prosím nezapomeňte zadat Memo ID, když posíláte XLM transakce ke směně", + "xmr_available_balance": "Zůstatek (dostupný)", + "xmr_full_balance": "Zůstatek (celkový)", + "xmr_hidden": "Skryto", + "xmr_to_error": "XMR.TO chyba", + "xmr_to_error_description": "Neplatná částka. Maximálně lze použít 8 desetinných míst", + "xrp_extra_info": "Prosím nezapomeňte zadat Destination Tag, když posíláte XRP transakce ke směně", + "yat": "Yat", + "yat_address": "Yat adresa", + "yat_alert_content": "Uživatelé Cake Wallet mohou nyní posílat a přijímat všechny své oblíbené měny pomocí něco jako uživatelského jména tvořeného emoji.", + "yat_alert_title": "Posílejte a přijímejte crypto jednodušeji s Yat", + "yat_error": "Yat chyba", + "yat_error_content": "Žádná adresa není spojena s tímto Yatem. Zkuste jiný Yat", + "yat_popup_content": "Nyní můžete posílat a přijímat crypto v Cake Wallet se svým Yatem - krátkým uživatelským jménem složeným z emoji. Spravujte kdykoliv Yaty na stránce s nastavením", + "yat_popup_title": "Adresa Vaší peněženky může být emojifikována.", + "yesterday": "Včera", + "you_now_have_debit_card": "Nyní máte debetní kartu", + "you_pay": "Zaplatíte", + "you_will_get": "Směnit na", + "you_will_send": "Směnit z", + "yy": "YY", + "zzzz": "Zzzz" +} \ No newline at end of file diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 9aca5ba28..8369cc5b7 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -1,779 +1,780 @@ { - "welcome": "Willkommen bei", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Eine großartige Wallet für Monero, Bitcoin, Ethereum, Litecoin, und Haven", - "please_make_selection": "Bitte treffen Sie unten eine Auswahl zum Erstellen oder Wiederherstellen Ihrer Wallet.", - "create_new": "Neue Wallet erstellen", - "restore_wallet": "Wallet wiederherstellen", - "monero_com": "Monero.com von Cake Wallet", - "monero_com_wallet_text": "Eine großartige Wallet für Monero", - "haven_app": "Haven von Cake Wallet", - "haven_app_wallet_text": "Eine großartige Wallet für Haven", - "accounts": "Konten", - "edit": "Bearbeiten", + "about_cake_pay": "Mit Cake Pay können Sie ganz einfach Geschenkkarten mit virtuellen Vermögenswerten kaufen, die Sie sofort bei über 150.000 Händlern in den Vereinigten Staaten ausgeben können.", "account": "Konto", + "accounts": "Konten", + "accounts_subaddresses": "Konten und Unteradressen", + "activate": "aktivieren", + "active": "Aktiv", + "active_cards": "Aktive Karten", + "activeConnectionsPrompt": "Hier werden aktive Verbindungen angezeigt", "add": "Hinzufügen", + "add_contact": "Kontakt hinzufügen", + "add_custom_node": "Neuen benutzerdefinierten Knoten hinzufügen", + "add_custom_redemption": "Benutzerdefinierte Einlösung hinzufügen", + "add_fund_to_card": "Prepaid-Guthaben zu den Karten hinzufügen (bis zu ${value})", + "add_new_node": "Neuen Knoten hinzufügen", + "add_new_word": "Neues Wort hinzufügen", + "add_receiver": "Fügen Sie einen weiteren Empfänger hinzu (optional)", + "add_secret_code": "Oder fügen Sie diesen Geheimcode einer Authentifizierungs-App hinzu", + "add_tip": "Tipp hinzufügen", + "add_token_disclaimer_check": "Ich habe die Adresse und Informationen zum Token-Vertrag anhand einer seriösen Quelle bestätigt. Das Hinzufügen böswilliger oder falscher Informationen kann zu einem Verlust von Geldern führen.", + "add_token_warning": "Bearbeiten oder fügen Sie Token nicht gemäß den Anweisungen von Betrügern hinzu.\nBestätigen Sie Token-Adressen immer mit seriösen Quellen!", + "add_value": "Wert hinzufügen", + "address": "Adresse", "address_book": "Adressbuch", - "contact": "Kontakt", - "please_select": "Bitte auswählen:", - "cancel": "Abbrechen", - "ok": "OK", - "contact_name": "Name des Kontakts", - "reset": "Zurücksetzen", - "save": "Speichern", + "address_book_menu": "Adressbuch", + "address_detected": "Adresse erkannt", + "address_from_domain": "Diese Adresse ist von ${domain} auf Unstoppable Domains", + "address_from_yat": "Diese Adresse ist von ${emoji} auf Yat", + "address_label": "Address label", "address_remove_contact": "Kontakt entfernen", "address_remove_content": "Sind Sie sicher, dass Sie den ausgewählten Kontakt entfernen möchten?", - "authenticated": "Authentifiziert", - "authentication": "Authentifizierung", - "failed_authentication": "Authentifizierung fehlgeschlagen. ${state_error}", - "wallet_menu": "Wallet-Menü", - "Blocks_remaining": "${status} verbleibende Blöcke", - "please_try_to_connect_to_another_node": "Bitte versuchen Sie, sich mit einem anderen Knoten zu verbinden", - "xmr_hidden": "Versteckt", - "xmr_available_balance": "Verfügbares Guthaben", - "xmr_full_balance": "Gesamtguthaben", - "send": "Senden", - "receive": "Empfangen", - "transactions": "Transaktionen", - "incoming": "Eingehend", - "outgoing": "Ausgehend", - "transactions_by_date": "Transaktionen nach Datum", - "trades": "Börsen", - "filter_by": "Filtern nach", - "today": "Heute", - "yesterday": "Gestern", - "received": "Empfangen", - "sent": "Versendet", - "pending": " (ausstehend)", - "rescan": "Erneut scannen", - "reconnect": "Erneut verbinden", - "wallets": "Wallets", - "show_seed": "Seed zeigen", - "show_keys": "Seed/Schlüssel anzeigen", - "address_book_menu": "Adressbuch", - "reconnection": "Neu verbinden", - "reconnect_alert_text": "Sind Sie sicher, dass Sie sich neu verbinden möchten?", - "exchange": "Umwechseln", - "clear": "Zurücksetzen", - "refund_address": "Rückerstattungsadresse", - "change_exchange_provider": "Exchange-Anbieter ändern", - "you_will_send": "Konvertieren von", - "you_will_get": "Konvertieren zu", - "amount_is_guaranteed": "Der Empfangsbetrag ist garantiert", - "amount_is_estimate": "Der empfangene Betrag ist eine Schätzung", - "powered_by": "Ermöglicht durch ${title}", - "error": "Fehler", - "estimated": "Geschätzt", - "min_value": "Min: ${value} ${currency}", - "max_value": "Max: ${value} ${currency}", - "change_currency": "Währung ändern", - "overwrite_amount": "Overwrite amount", - "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", - "copy_id": "ID kopieren", - "exchange_result_write_down_trade_id": "Bitte kopieren oder notieren Sie die Handels-ID, um fortzufahren.", - "trade_id": "Handels-ID:", - "copied_to_clipboard": "In die Zwischenablage kopiert", - "saved_the_trade_id": "Ich habe die Handels-ID gespeichert", - "fetching": "Frage ab", - "id": "ID: ", - "amount": "Betrag: ", - "payment_id": "Zahlungs-ID: ", - "status": "Status: ", - "offer_expires_in": "Angebot läuft ab in: ", - "trade_is_powered_by": "Dieser Handel wird angeboten von ${provider}", - "copy_address": "Adresse kopieren", - "exchange_result_confirm": "Durch Drücken von \"Bestätigen\" wird ${fetchingLabel} ${from} von Ihrer Wallet namens ${walletName} an die unten angegebene Adresse gesendet. Alternativ können Sie von einer externen Wallet an die unten angegebene Adresse / QR-Code senden.\n\nBitte bestätigen Sie, um fortzufahren, oder gehen Sie zurück, um die Beträge zu ändern.", - "exchange_result_description": "Sie müssen mindestens ${fetchingLabel} ${from} an die auf der nächsten Seite angegebene Adresse senden. Wenn Sie einen Betrag unter ${fetchingLabel} ${from} senden, wird dieser möglicherweise nicht konvertiert und möglicherweise nicht erstattet.", - "exchange_result_write_down_ID": "*Bitte kopieren oder notieren Sie sich die oben gezeigte ID.", - "confirm": "Bestätigen", - "confirm_sending": "Senden bestätigen", - "commit_transaction_amount_fee": "Transaktion absenden\nBetrag: ${amount}\nGebühr: ${fee}", - "sending": "Senden", - "transaction_sent": "Transaktion gesendet!", - "expired": "Abgelaufen", - "time": "${minutes}m ${seconds}s", - "send_xmr": "XMR senden", - "exchange_new_template": "Neue Vorlage", - "faq": "Häufig gestellte Fragen", - "enter_your_pin": "PIN eingeben", - "loading_your_wallet": "Wallet wird geladen", - "new_wallet": "Neue Wallet", - "wallet_name": "Walletname", - "continue_text": "Weiter", - "choose_wallet_currency": "Bitte wählen Sie die Währung der Wallet:", - "node_new": "Neuer Knoten", - "node_address": "Knotenadresse", - "node_port": "Knotenport", - "login": "Einloggen", - "password": "Passwort", - "nodes": "Knoten", - "node_reset_settings_title": "Einstellungen zurücksetzen", - "nodes_list_reset_to_default_message": "Möchten Sie wirklich die Standardeinstellungen wiederherstellen?", - "change_current_node": "Möchten Sie den aktuellen Knoten wirklich zu ${node}? ändern?", - "change": "Ändern", - "remove_node": "Knoten entfernen", - "remove_node_message": "Möchten Sie den ausgewählten Knoten wirklich entfernen?", - "remove": "Entfernen", - "delete": "Löschen", - "add_new_node": "Neuen Knoten hinzufügen", - "change_current_node_title": "Aktuellen Knoten ändern", - "node_test": "Test", - "node_connection_successful": "Die Verbindung war erfolgreich", - "node_connection_failed": "Verbindung fehlgeschlagen", - "new_node_testing": "Neuen Knoten testen", - "use": "Wechsel zu ", - "digit_pin": "-stellige PIN", - "share_address": "Adresse teilen ", - "receive_amount": "Betrag", - "subaddresses": "Unteradressen", "addresses": "Adressen", - "scan_qr_code_to_get_address": "Scannen Sie den QR-Code, um die Adresse zu erhalten", - "qr_fullscreen": "Tippen Sie hier, um den QR-Code im Vollbildmodus zu öffnen", - "rename": "Umbenennen", - "choose_account": "Konto auswählen", - "create_new_account": "Neues Konto erstellen", - "accounts_subaddresses": "Konten und Unteradressen", - "restore_restore_wallet": "Wallet wiederherstellen", - "restore_title_from_seed_keys": "Aus Seed/Schlüssel wiederherstellen", - "restore_description_from_seed_keys": "Stellen Sie Ihr Wallet aus Seed/Schlüsseln wieder her, die Sie sicher aufbewahrt haben", - "restore_next": "Weiter", - "restore_title_from_backup": "Aus einer Sicherungsdatei wiederherstellen", - "restore_description_from_backup": "Sie können die gesamte Cake Wallet-App aus Ihrer Sicherungsdatei wiederherstellen", - "restore_seed_keys_restore": "Seed/Schlüssel wiederherstellen", - "restore_title_from_seed": "Aus Seed wiederherstellen", - "restore_description_from_seed": "Stellen Sie Ihre Wallet aus den 25 Wörtern oder dem 13-Wort-Kombinationscode wieder her", - "restore_title_from_keys": "Aus Schlüsseln wiederherstellen", - "restore_description_from_keys": "Stellen Sie Ihr Wallet aus generierten Tastenanschlägen her, die von Ihren privaten Schlüsseln gespeichert wurden", - "restore_wallet_name": "Walletname", - "restore_address": "Adresse", - "restore_view_key_private": "View Key (geheim)", - "restore_spend_key_private": "Spend Key (geheim)", - "restore_recover": "Wiederherstellen", - "restore_wallet_restore_description": "Beschreibung zur Wallet-Wiederherstellung", - "restore_new_seed": "Neuer Seed", - "restore_active_seed": "Aktiver Seed", - "restore_bitcoin_description_from_seed": "Stellen Sie Ihre Wallet aus dem 24-Wort-Kombinationscode wieder her", - "restore_bitcoin_description_from_keys": "Stellen Sie Ihre Wallet aus der generierten WIF-Zeichenfolge aus Ihren privaten Schlüsseln wieder her", - "restore_bitcoin_title_from_keys": "Aus WIF wiederherstellen", - "restore_from_date_or_blockheight": "Bitte geben Sie ein Datum ein, das einige Tage vor dem Erstellen dieser Wallet liegt. Oder wenn Sie die Blockhöhe kennen, geben Sie stattdessen diese ein", - "seed_reminder": "Bitte notieren Sie diese für den Fall, dass Sie Ihr Telefon verlieren oder es kaputtgeht", - "seed_title": "Seed", - "seed_share": "Seed teilen", - "copy": "Kopieren", - "seed_language": "Seed-Sprache", - "seed_choose": "Seed-Sprache auswählen", - "seed_language_next": "Weiter", - "seed_language_english": "Englisch", - "seed_language_chinese": "Chinesisch", - "seed_language_dutch": "Niederländisch", - "seed_language_german": "Deutsch", - "seed_language_japanese": "Japanisch", - "seed_language_portuguese": "Portugiesisch", - "seed_language_russian": "Russisch", - "seed_language_spanish": "Spanisch", - "seed_language_french": "Französisch", - "seed_language_italian": "Italiana/Italiano", - "send_title": "Senden", - "send_your_wallet": "Ihre Wallet", - "send_address": "${cryptoCurrency}-Adresse", - "send_payment_id": "Zahlungs-ID (optional)", + "advanced_settings": "Erweiterte Einstellungen", + "aggressive": "Übereifrig", + "agree": "stimme zu", + "agree_and_continue": "Zustimmen & fortfahren", + "agree_to": "Indem Sie ein Konto erstellen, stimmen Sie den ", "all": "ALLES", - "send_error_minimum_value": "Der Mindestbetrag ist 0,01", - "send_error_currency": "Die Währung darf nur Zahlen enthalten", - "send_estimated_fee": "Geschätzte Gebühr:", - "send_priority": "Derzeit ist ${transactionPriority} als Gebührenpriorität eingestellt.\nDie Transaktionspriorität kann in den Einstellungen angepasst werden", - "send_creating_transaction": "Erstelle Transaktion", - "send_templates": "Vorlagen", - "send_new": "Neu", - "send_amount": "Betrag:", - "send_fee": "Gebühr:", - "send_name": "Name", - "got_it": "Verstanden", - "send_sending": "Senden...", - "send_success": "Ihr ${crypto} wurde erfolgreich versendet", - "settings_title": "Einstellungen", - "settings_nodes": "Knoten", - "settings_current_node": "Aktueller Knoten", - "settings_wallets": "Wallets", - "settings_display_balance": "Kontostand anzeigen", - "settings_currency": "Währung", - "settings_fee_priority": "Gebührenpriorität", - "settings_save_recipient_address": "Empfängeradresse speichern", - "settings_personal": "Persönlich", - "settings_change_pin": "PIN ändern", - "settings_change_language": "Sprache ändern", - "settings_allow_biometrical_authentication": "Biometrische Authentifizierung zulassen", - "settings_dark_mode": "Dunkler Modus", - "settings_transactions": "Transaktionen", - "settings_trades": "Handel", - "settings_display_on_dashboard_list": "Anzeige in der Dashboard-Liste", - "settings_all": "ALLE", - "settings_only_trades": "Nur Handel", - "settings_only_transactions": "Nur Transaktionen", - "settings_none": "Keiner", - "settings_support": "Hilfe", - "settings_terms_and_conditions": "Geschäftsbedingungen", - "pin_is_incorrect": "PIN ist falsch", - "setup_pin": "PIN einrichten", - "enter_your_pin_again": "Geben Sie Ihre PIN erneut ein", - "setup_successful": "Ihre PIN wurde erfolgreich eingerichtet!", - "wallet_keys": "Wallet-Seed/-Schlüssel", - "wallet_seed": "Wallet-Seed", - "private_key": "Privater Schlüssel", - "public_key": "Öffentlicher Schlüssel", - "view_key_private": "View Key (geheim)", - "view_key_public": "View Key (öffentlich)", - "spend_key_private": "Spend Key (geheim)", - "spend_key_public": "Spend Key (öffentlich)", - "copied_key_to_clipboard": "${key} in Zwischenablage kopiert", - "new_subaddress_title": "Neue Adresse", - "new_subaddress_label_name": "Bezeichnung", - "new_subaddress_create": "Erstellen", - "address_label": "Address label", - "subaddress_title": "Unteradressenliste", - "trade_details_title": "Handelsdetails", - "trade_details_id": "ID", - "trade_details_state": "Status", - "trade_details_fetching": "Wird ermittelt", - "trade_details_provider": "Anbieter", - "trade_details_created_at": "Erzeugt am", - "trade_details_pair": "Paar", - "trade_details_copied": "${title} in die Zwischenablage kopiert", - "trade_history_title": "Handelsverlauf", - "transaction_details_title": "Transaktionsdetails", - "transaction_details_transaction_id": "Transaktions-ID", - "transaction_details_date": "Datum", - "transaction_details_height": "Höhe", - "transaction_details_amount": "Betrag", - "transaction_details_fee": "Gebühr", - "transaction_details_copied": "${title} in die Zwischenablage kopiert", - "transaction_details_recipient_address": "Empfängeradressen", - "wallet_list_title": "Monero-Wallet", - "wallet_list_create_new_wallet": "Neue Wallet erstellen", - "wallet_list_edit_wallet": "Wallet bearbeiten", - "wallet_list_wallet_name": "Wallet namen", - "wallet_list_restore_wallet": "Wallet wiederherstellen", - "wallet_list_load_wallet": "Wallet laden", - "wallet_list_loading_wallet": "Wallet ${wallet_name} wird geladen", - "wallet_list_failed_to_load": "Laden der Wallet ${wallet_name} fehlgeschlagen. ${error}", - "wallet_list_removing_wallet": "Wallet ${wallet_name} wird entfernt", - "wallet_list_failed_to_remove": "Fehler beim Entfernen der Wallet ${wallet_name}. ${error}", - "widgets_address": "Adresse", - "widgets_restore_from_blockheight": "Ab Blockhöhe wiederherstellen", - "widgets_restore_from_date": "Ab Datum wiederherstellen", - "widgets_or": "oder", - "widgets_seed": "Seed", - "router_no_route": "Keine Route definiert für ${name}", - "error_text_account_name": "Der Kontoname darf nur Buchstaben und Zahlen enthalten\nund muss zwischen 1 und 15 Zeichen lang sein", - "error_text_contact_name": "Kontaktname darf nicht die Zeichen ` , ' \" enthalten\nund muss zwischen 1 und 32 Zeichen lang sein", - "error_text_address": "Die Walletadresse muss dem Typ der Kryptowährung\nentsprechen", - "error_text_node_address": "Bitte geben Sie eine iPv4-Adresse ein", - "error_text_node_port": "Der Knotenport darf nur Nummern zwischen 0 und 65535 enthalten", - "error_text_node_proxy_address": "Bitte geben Sie : ein, zum Beispiel 127.0.0.1:9050", - "error_text_payment_id": "Die Zahlungs-ID darf nur 16 bis 64 hexadezimale Zeichen enthalten", - "error_text_xmr": "Der XMR-Wert darf das verfügbare Guthaben nicht überschreiten.\nDie Anzahl der Nachkommastellen muss kleiner oder gleich 12 sein", - "error_text_fiat": "Der Wert des Betrags darf den verfügbaren Kontostand nicht überschreiten.\nDie Anzahl der Nachkommastellen muss kleiner oder gleich 2 sein", - "error_text_subaddress_name": "Der Name der Unteradresse darf nicht die Zeichen ` , ' \" enthalten\nund muss zwischen 1 und 20 Zeichen lang sein", - "error_text_amount": "Betrag darf nur Zahlen enthalten", - "error_text_wallet_name": "Der Wallet-Name darf nur Buchstaben, Zahlen und _- Symbole enthalten\nund muss zwischen 1 und 33 Zeichen lang sein", - "error_text_keys": "Walletschlüssel können nur 64 hexadezimale Zeichen enthalten", - "error_text_crypto_currency": "Die Anzahl der Nachkommastellen\nmuss kleiner oder gleich 12 sein.", - "error_text_minimal_limit": "Handel für ${provider} wird nicht erstellt. Menge ist unter dem Minimum: ${min} ${currency}", - "error_text_maximum_limit": "Handel für ${provider} wird nicht erstellt. Menge ist über dem Maximum: ${max} ${currency}", - "error_text_limits_loading_failed": "Handel für ${provider} wird nicht erstellt. Das Laden der Limits ist fehlgeschlagen", - "error_text_template": "Vorlagenname und Adresse dürfen nicht die Zeichen ` , ' \" enthalten\nund müssen zwischen 1 und 106 Zeichen lang sein", + "all_trades": "Alle Trades", + "all_transactions": "Alle Transaktionen", + "alphabetical": "Alphabetisch", + "already_have_account": "Sie haben bereits ein Konto?", + "always": "immer", + "amount": "Betrag: ", + "amount_is_estimate": "Der empfangene Betrag ist eine Schätzung", + "amount_is_guaranteed": "Der Empfangsbetrag ist garantiert", + "anonpay_description": "Generieren Sie ${type}. Der Empfänger kann ${method} mit jeder unterstützten Kryptowährung verwenden, und Sie erhalten Geld in dieser Wallet.", + "apk_update": "APK-Update", + "approve": "Genehmigen", + "arrive_in_this_address": "${currency} ${tag}wird an dieser Adresse ankommen", + "ascending": "Aufsteigend", + "ask_each_time": "Jedes Mal fragen", "auth_store_ban_timeout": "ban_timeout", "auth_store_banned_for": "Gebannt für ", "auth_store_banned_minutes": " Minuten", "auth_store_incorrect_password": "Falsche PIN", - "wallet_store_monero_wallet": "Monero-Wallet", - "wallet_restoration_store_incorrect_seed_length": "Falsche Seed-Länge", - "full_balance": "Gesamtguthaben", - "available_balance": "Verfügbares Guthaben", - "hidden_balance": "Verstecktes Guthaben", - "sync_status_syncronizing": "SYNCHRONISIERE", - "sync_status_syncronized": "SYNCHRONISIERT", - "sync_status_not_connected": "NICHT VERBUNDEN", - "sync_status_starting_sync": "STARTE SYNCHRONISIERUNG", - "sync_status_failed_connect": "GETRENNT", - "sync_status_connecting": "VERBINDEN", - "sync_status_connected": "VERBUNDEN", - "sync_status_attempting_sync": "SYNC VERSUCHEN", - "transaction_priority_slow": "Langsam", - "transaction_priority_regular": "Normal", - "transaction_priority_medium": "Mittel", - "transaction_priority_fast": "Schnell", - "transaction_priority_fastest": "Am schnellsten", - "trade_for_not_created": "Handel für ${title} wird nicht erstellt.", - "trade_not_created": "Handel nicht erstellt", - "trade_id_not_found": "Handel ${tradeId} von ${title} nicht gefunden.", - "trade_not_found": "Handel nicht gefunden.", - "trade_state_pending": "Steht aus", - "trade_state_confirming": "Bestätigung", - "trade_state_trading": "Handel", - "trade_state_traded": "Gehandelt", - "trade_state_complete": "Abgeschlossen", - "trade_state_to_be_created": "Noch nicht erstellt", - "trade_state_unpaid": "Unbezahlt", - "trade_state_underpaid": "Unterbezahlt", - "trade_state_paid_unconfirmed": "Unbestätigt bezahlt", - "trade_state_paid": "Bezahlt", - "trade_state_btc_sent": "Btc gesendet", - "trade_state_timeout": "Timeout", - "trade_state_created": "Erstellt", - "trade_state_finished": "Fertig", - "change_language": "Sprache ändern", - "change_language_to": "Sprache zu ${language} ändern?", - "paste": "Einfügen", - "restore_from_seed_placeholder": "Seed bitte hier eingeben oder einfügen", - "add_new_word": "Neues Wort hinzufügen", - "incorrect_seed": "Der eingegebene Text ist ungültig.", - "biometric_auth_reason": "Scannen Sie Ihren Fingerabdruck zur Authentifizierung", - "version": "Version ${currentVersion}", - "extracted_address_content": "Sie senden Geld an\n${recipient_name}", - "card_address": "Adresse:", - "buy": "Kaufen", - "sell": "Verkaufen", - "placeholder_transactions": "Ihre Transaktionen werden hier angezeigt", - "placeholder_contacts": "Ihre Kontakte werden hier angezeigt", - "template": "Vorlage", - "confirm_delete_template": "Diese Aktion löscht diese Vorlage. Möchten Sie fortfahren?", - "confirm_delete_wallet": "Diese Aktion löscht diese Wallet. Möchten Sie fortfahren?", - "change_wallet_alert_title": "Aktuelle Wallet ändern", - "change_wallet_alert_content": "Möchten Sie die aktuelle Wallet zu ${wallet_name} ändern?", - "creating_new_wallet": "Neue Wallet erstellen", - "creating_new_wallet_error": "Fehler: ${description}", - "seed_alert_title": "Achtung", - "seed_alert_content": "Der Seed ist der einzige Weg, Ihre Wallet wiederherzustellen. Haben Sie ihn aufgeschrieben?", - "seed_alert_back": "Zurückgehen", - "seed_alert_yes": "Ja, habe ich", - "exchange_sync_alert_content": "Bitte warten Sie, bis Ihre Wallet synchronisiert ist", - "pre_seed_title": "WICHTIG", - "pre_seed_description": "Auf der nächsten Seite sehen Sie eine Reihe von ${words} Wörtern. Dies ist Ihr einzigartiger und privater Seed und der EINZIGE Weg, um Ihre Wallet im Falle eines Verlusts oder einer Fehlfunktion wiederherzustellen. Es liegt in IHRER Verantwortung, ihn aufzuschreiben und an einem sicheren Ort außerhalb der Cake Wallet-App aufzubewahren.", - "pre_seed_button_text": "Verstanden. Zeig mir meinen Seed", - "xmr_to_error": "XMR.TO-Fehler", - "xmr_to_error_description": "Ungültiger Betrag. Höchstgrenze 8 Stellen nach dem Dezimalpunkt", - "provider_error": "${provider}-Fehler", - "use_ssl": "SSL verwenden", - "trusted": "Vertrauenswürdige", - "color_theme": "Farbthema", - "light_theme": "Hell", - "bright_theme": "Strahlend hell", - "dark_theme": "Dunkel", - "enter_your_note": "Geben Sie Ihre Bemerkung ein…", - "note_optional": "Bemerkung (optional)", - "note_tap_to_change": "Bemerkung (zum Ändern tippen)", - "view_in_block_explorer": "In Block Explorer anzeigen", - "view_transaction_on": "Anzeigen der Transaktion auf ", - "transaction_key": "Transaktionsschlüssel", - "confirmations": "Bestätigungen", - "recipient_address": "Empfängeradresse", - "extra_id": "Extra ID:", - "destination_tag": "Ziel-Tag:", - "memo": "Memo:", - "backup": "Sicherung", - "change_password": "Passwort ändern", - "backup_password": "Passwort sichern", - "write_down_backup_password": "Bitte notieren Sie sich Ihr Sicherungskennwort, das für den Import Ihrer Sicherungsdateien gebraucht wird.", - "export_backup": "Sicherung exportieren", - "save_backup_password": "Bitte stellen Sie sicher, dass Sie Ihr Sicherungskennwort gespeichert haben. Ohne dieses können Sie Ihre Sicherungsdateien nicht importieren.", - "backup_file": "Sicherungsdatei", - "edit_backup_password": "Sicherungskennwort bearbeiten", - "save_backup_password_alert": "Sicherungskennwort speichern", - "change_backup_password_alert": "Ihre vorherigen Sicherungsdateien können nicht mit einem neuen Sicherungskennwort importiert werden. Das neue Sicherungskennwort wird nur für neue Sicherungsdateien verwendet. Sind Sie sicher, dass Sie das Sicherungskennwort ändern möchten?", - "enter_backup_password": "Sicherungskennwort hier eingeben", - "select_backup_file": "Sicherungsdatei auswählen", - "import": "Importieren", - "please_select_backup_file": "Bitte wählen Sie die Sicherungsdatei und geben Sie das Sicherungskennwort ein.", - "fixed_rate": "Feste Rate", - "fixed_rate_alert": "Sie können den Empfangsbetrag eingeben, wenn der Festratenmodus aktiviert ist. Möchten Sie in den Festratenmodus wechseln?", - "xlm_extra_info": "Bitte vergessen Sie nicht, die Memo-ID anzugeben, während Sie die XLM-Transaktion für den Austausch senden", - "xrp_extra_info": "Bitte vergessen Sie nicht, das Ziel-Tag anzugeben, während Sie die XRP-Transaktion für den Austausch senden", - "exchange_incorrect_current_wallet_for_xmr": "Wenn Sie XMR von Ihrem Cake Wallet Monero-Guthaben umtauschen möchten, wechseln Sie bitte zuerst zu Ihrer Monero-Wallet.", - "confirmed": "Bestätigter Saldo", - "unconfirmed": "Unbestätigter Saldo", - "displayable": "Anzeigebar", - "submit_request": "Eine Anfrage stellen", - "buy_alert_content": "Derzeit unterstützen wir nur den Kauf von Bitcoin, Ethereum, Litecoin und Monero. Bitte erstellen Sie Ihr Bitcoin-, Ethereum-, Litecoin- oder Monero-Wallet oder wechseln Sie zu diesem.", - "sell_alert_content": "Wir unterstützen derzeit nur den Verkauf von Bitcoin, Ethereum und Litecoin. Bitte erstellen Sie Ihr Bitcoin-, Ethereum- oder Litecoin-Wallet oder wechseln Sie zu diesem.", - "outdated_electrum_wallet_description": "Neue Bitcoin-Wallets, die in Cake erstellt wurden, haben jetzt einen 24-Wort-Seed. Sie müssen eine neue Bitcoin-Wallet erstellen, Ihr gesamtes Geld in die neue 24-Wort-Wallet überweisen und keine Wallet mit einem 12-Wort-Seed mehr verwenden. Bitte tun Sie dies sofort, um Ihr Geld zu sichern.", - "understand": "Ich verstehe", - "apk_update": "APK-Update", - "buy_bitcoin": "Bitcoin kaufen", - "buy_with": "Kaufen mit", - "moonpay_alert_text": "Der Wert des Betrags muss größer oder gleich ${minAmount} ${fiatCurrency} sein", - "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", - "do_not_show_me": "Zeig mir das nicht noch einmal", - "unspent_coins_title": "Nicht ausgegebene Coins", - "unspent_coins_details_title": "Details zu nicht ausgegebenen Coins", - "freeze": "Einfrieren", - "frozen": "Gefroren", - "coin_control": "Coin Control (optional)", - "address_detected": "Adresse erkannt", - "address_from_domain": "Diese Adresse ist von ${domain} auf Unstoppable Domains", - "add_receiver": "Fügen Sie einen weiteren Empfänger hinzu (optional)", - "manage_yats": "Yats verwalten", - "yat_alert_title": "Senden und Empfangen von Krypto leichter mit Yat", - "yat_alert_content": "Cake Wallet-Benutzer können jetzt alle ihre Lieblingswährungen mit einem einzigartigen Emoji-basierten Benutzernamen senden und empfangen.", - "get_your_yat": "Holen Sie sich Ihre Yat", - "connect_an_existing_yat": "Verbinden Sie ein vorhandenes Yat", - "connect_yats": "Yats verbinden", - "yat_address": "Yat-Adresse", - "yat": "Yat", - "address_from_yat": "Diese Adresse ist von ${emoji} auf Yat", - "yat_error": "Yat-Fehler", - "yat_error_content": "Keine Adressen mit diesem Yat verknüpft. Versuchen Sie es mit einem anderen Yat", - "choose_address": "\n\nBitte wählen Sie die Adresse:", - "yat_popup_title": "Ihre Wallet-Adresse kann emojifiziert werden.", - "yat_popup_content": "Sie können jetzt Krypto in Cake Wallet mit Ihrem Yat senden und empfangen - einem kurzen, Emoji-basierten Benutzernamen. Verwalten Sie Yats jederzeit auf dem Einstellungsbildschirm", - "second_intro_title": "Eine Emoji-Adresse, um sie alle zu beherrschen", - "second_intro_content": "Ihr Yat ist eine einzige eindeutige Emoji-Adresse, die alle Ihre langen hexadezimalen Adressen für alle Ihre Währungen ersetzt.", - "third_intro_title": "Yat spielt gut mit anderen", - "third_intro_content": "Yats leben auch außerhalb von Cake Wallet. Jede Wallet-Adresse auf der Welt kann durch ein Yat ersetzt werden!", - "learn_more": "Erfahren Sie mehr", - "search": "Suche", - "search_language": "Sprache suchen", - "search_currency": "Währung suchen", - "new_template": "neue Vorlage", - "electrum_address_disclaimer": "Wir generieren jedes Mal neue Adressen, wenn Sie eine verwenden, aber vorherige Adressen funktionieren weiterhin", - "wallet_name_exists": "Wallet mit diesem Namen existiert bereits", - "market_place": "Marktplatz", - "cake_pay_title": "Cake Pay-Geschenkkarten", - "cake_pay_subtitle": "Kaufen Sie ermäßigte Geschenkkarten (nur USA)", - "cake_pay_web_cards_title": "Cake Pay-Webkarten", - "cake_pay_web_cards_subtitle": "Kaufen Sie weltweit Prepaid-Karten und Geschenkkarten", - "about_cake_pay": "Mit Cake Pay können Sie ganz einfach Geschenkkarten mit virtuellen Vermögenswerten kaufen, die Sie sofort bei über 150.000 Händlern in den Vereinigten Staaten ausgeben können.", - "cake_pay_account_note": "Melden Sie sich nur mit einer E-Mail-Adresse an, um Karten anzuzeigen und zu kaufen. Einige sind sogar mit Rabatt erhältlich!", - "already_have_account": "Sie haben bereits ein Konto?", - "create_account": "Konto erstellen", - "privacy_policy": "Datenschutzrichtlinie", - "welcome_to_cakepay": "Willkommen bei Cake Pay!", - "sign_up": "Anmelden", - "forgot_password": "Passwort vergessen", - "reset_password": "Passwort zurücksetzen", - "gift_cards": "Geschenkkarten", - "setup_your_debit_card": "Richten Sie Ihre Debitkarte ein", - "no_id_required": "Keine ID erforderlich. Upgraden und überall ausgeben", - "how_to_use_card": "Wie man diese Karte benutzt", - "purchase_gift_card": "Geschenkkarte kaufen", - "verification": "Verifizierung", - "fill_code": "Geben Sie den Bestätigungscode ein, den Sie per E-Mail erhalten haben", - "didnt_get_code": "Kein Code?", - "resend_code": "Bitte erneut senden", - "debit_card": "Debitkarte", - "cakepay_prepaid_card": "CakePay-Prepaid-Debitkarte", - "no_id_needed": "Keine ID erforderlich!", - "frequently_asked_questions": "Häufig gestellte Fragen", - "debit_card_terms": "Die Speicherung und Nutzung Ihrer Zahlungskartennummer (und Ihrer Zahlungskartennummer entsprechenden Anmeldeinformationen) in dieser digitalen Geldbörse unterliegt den Allgemeinen Geschäftsbedingungen des geltenden Karteninhabervertrags mit dem Zahlungskartenaussteller, gültig ab von Zeit zu Zeit.", - "Please_reference_document": "Weitere Informationen finden Sie in den Dokumenten unten.", - "cardholder_agreement": "Karteninhabervertrag", - "e_sign_consent": "E-Sign-Zustimmung", - "agree_and_continue": "Zustimmen & fortfahren", - "email_address": "E-Mail-Adresse", - "agree_to": "Indem Sie ein Konto erstellen, stimmen Sie den ", - "und": "und", - "enter_code": "Code eingeben", - "congratulations": "Glückwunsch!", - "you_now_have_debit_card": "Sie haben jetzt eine Debitkarte", - "min_amount": "Min: ${value}", - "max_amount": "Max: ${value}", - "enter_amount": "Betrag eingeben", - "billing_address_info": "Wenn Sie nach einer Rechnungsadresse gefragt werden, geben Sie bitte Ihre Lieferadresse an", - "order_physical_card": "Physische Karte bestellen", - "add_value": "Wert hinzufügen", - "activate": "aktivieren", - "get_a": "Hole ein", - "digital_and_physical_card": "digitale und physische Prepaid-Debitkarte", - "get_card_note": " die Sie mit digitaler Währung aufladen können. Keine zusätzlichen Informationen erforderlich!", - "signup_for_card_accept_terms": "Melden Sie sich für die Karte an und akzeptieren Sie die Bedingungen.", - "add_fund_to_card": "Prepaid-Guthaben zu den Karten hinzufügen (bis zu ${value})", - "use_card_info_two": "Guthaben werden auf dem Prepaid-Konto in USD umgerechnet, nicht in digitale Währung.", - "use_card_info_three": "Verwenden Sie die digitale Karte online oder mit kontaktlosen Zahlungsmethoden.", - "optionally_order_card": "Optional eine physische Karte bestellen.", - "hide_details": "Details ausblenden", - "show_details": "Details anzeigen", - "upto": "bis zu ${value}", - "discount": "${value} % sparen", - "gift_card_amount": "Gutscheinbetrag", - "bill_amount": "Rechnungsbetrag", - "you_pay": "Sie bezahlen", - "tip": "Hinweis:", - "custom": "benutzerdefiniert", - "by_cake_pay": "von Cake Pay", - "expires": "Läuft ab", - "mm": "MM", - "yy": "YY", - "online": "online", - "offline": "offline", - "gift_card_number": "Geschenkkartennummer", - "pin_number": "PIN-Nummer", - "total_saving": "Gesamteinsparungen", - "last_30_days": "Letzte 30 Tage", - "avg_savings": "Durchschn. Einsparungen", - "view_all": "Alle anzeigen", - "active_cards": "Aktive Karten", - "delete_account": "Konto löschen", - "cards": "Karten", - "active": "Aktiv", - "redeemed": "Versilbert", - "gift_card_balance_note": "Geschenkkarten mit Restguthaben erscheinen hier", - "gift_card_redeemed_note": "Gutscheine, die Sie eingelöst haben, werden hier angezeigt", - "logout": "Abmelden", - "add_tip": "Tipp hinzufügen", - "percentageOf": "von ${amount}", - "is_percentage": "ist", - "search_category": "Suchkategorie", - "mark_as_redeemed": "Als eingelöst markieren", - "more_options": "Weitere Optionen", - "waiting_payment_confirmation": "Warte auf Zahlungsbestätigung", - "transaction_sent_notice": "Wenn der Bildschirm nach 1 Minute nicht weitergeht, überprüfen Sie einen Block-Explorer und Ihre E-Mail.", - "agree": "stimme zu", - "in_store": "Im Geschäft", - "generating_gift_card": "Geschenkkarte wird erstellt", - "payment_was_received": "Ihre Zahlung ist eingegangen.", - "proceed_after_one_minute": "Wenn der Bildschirm nach 1 Minute nicht weitergeht, überprüfen Sie bitte Ihre E-Mail.", - "order_id": "Bestell-ID", - "gift_card_is_generated": "Geschenkkarte wird generiert", - "open_gift_card": "Geschenkkarte öffnen", - "contact_support": "Support kontaktieren", - "gift_cards_unavailable": "Geschenkkarten können derzeit nur über Monero, Bitcoin und Litecoin erworben werden", - "background_sync_mode": "Hintergrundsynchronisierungsmodus", - "sync_all_wallets": "Alle Wallets synchronisieren", - "introducing_cake_pay": "Einführung von Cake Pay!", - "cake_pay_learn_more": "Kaufen und lösen Sie Geschenkkarten sofort in der App ein!\nWischen Sie von links nach rechts, um mehr zu erfahren.", + "authenticated": "Authentifiziert", + "authentication": "Authentifizierung", + "auto_generate_subaddresses": "Unteradressen automatisch generieren", "automatic": "Automatisch", - "fixed_pair_not_supported": "Dieses feste Paar wird von den ausgewählten Vermittlungsstellen nicht unterstützt", - "variable_pair_not_supported": "Dieses Variablenpaar wird von den ausgewählten Börsen nicht unterstützt", - "none_of_selected_providers_can_exchange": "Keiner der ausgewählten Anbieter kann diesen Austausch vornehmen", - "choose_one": "Wähle ein", - "choose_from_available_options": "Wähle aus verfügbaren Optionen:", - "custom_redeem_amount": "Benutzerdefinierter Einlösungsbetrag", - "add_custom_redemption": "Benutzerdefinierte Einlösung hinzufügen", - "remaining": "Rest", - "delete_wallet": "Wallet löschen", - "delete_wallet_confirm_message": "Sind Sie sicher, dass Sie das ${wallet_name} Wallet löschen möchten?", - "low_fee": "Niedrige Gebühr", - "low_fee_alert": "Sie verwenden derzeit eine niedrige Netzwerkgebührenpriorität. Dies kann zu langen Wartezeiten, unterschiedlichen Kursen oder stornierten Trades führen. Wir empfehlen, für ein besseres Erlebnis eine höhere Gebühr festzulegen.", - "ignor": "Ignorieren", - "use_suggested": "Vorgeschlagen verwenden", - "do_not_share_warning_text": "Teilen Sie diese nicht mit anderen, einschließlich Support.\n\nIhr Geld kann und wird gestohlen werden!", - "help": "hilfe", - "all_transactions": "Alle Transaktionen", - "all_trades": "Alle Trades", - "connection_sync": "Verbindung und Synchronisierung", - "security_and_backup": "Sicherheit und Datensicherung", - "create_backup": "Backup erstellen", - "privacy_settings": "Datenschutzeinstellungen", - "privacy": "Datenschutz", - "display_settings": "Anzeigeeinstellungen", - "other_settings": "Andere Einstellungen", - "require_pin_after": "PIN anfordern nach", - "always": "immer", - "minutes_to_pin_code": "${minute} Minuten", - "disable_exchange": "Exchange deaktivieren", - "advanced_settings": "Erweiterte Einstellungen", - "settings_can_be_changed_later": "Diese Einstellungen können später in den App-Einstellungen geändert werden", - "add_custom_node": "Neuen benutzerdefinierten Knoten hinzufügen", - "disable_fiat": "Fiat deaktivieren", - "fiat_api": "Fiat API", - "disabled": "Deaktiviert", - "enabled": "Ermöglicht", - "tor_only": "Nur Tor", - "unmatched_currencies": "Die Währung Ihres aktuellen Wallets stimmt nicht mit der des gescannten QR überein", - "orbot_running_alert": "Bitte stellen Sie sicher, dass Orbot läuft, bevor Sie sich mit diesem Knoten verbinden.", - "contact_list_contacts": "Kontakte", - "contact_list_wallets": "Meine Wallets", - "bitcoin_payments_require_1_confirmation": "Bitcoin-Zahlungen erfordern 1 Bestätigung, was 20 Minuten oder länger dauern kann. Danke für Ihre Geduld! Sie erhalten eine E-Mail, wenn die Zahlung bestätigt ist.", - "send_to_this_address": "Senden Sie ${currency} ${tag}an diese Adresse", - "arrive_in_this_address": "${currency} ${tag}wird an dieser Adresse ankommen", - "do_not_send": "Nicht senden", - "error_dialog_content": "Hoppla, wir haben einen Fehler.\n\nBitte senden Sie den Absturzbericht an unser Support-Team, um die Anwendung zu verbessern.", - "scan_qr_code": "QR-Code scannen", - "cold_or_recover_wallet": "Fügen Sie eine Cold Wallet hinzu oder stellen Sie eine Paper Wallet wieder her", - "please_wait": "Warten Sie mal", - "sweeping_wallet": "Wallet leeren", - "sweeping_wallet_alert": "Das sollte nicht lange dauern. VERLASSEN SIE DIESEN BILDSCHIRM NICHT, ANDERNFALLS KÖNNEN DIE GELDER VERLOREN GEHEN", - "decimal_places_error": "Zu viele Nachkommastellen", - "edit_node": "Knoten bearbeiten", - "invoice_details": "Rechnungs-Details", - "donation_link_details": "Details zum Spendenlink", - "anonpay_description": "Generieren Sie ${type}. Der Empfänger kann ${method} mit jeder unterstützten Kryptowährung verwenden, und Sie erhalten Geld in dieser Wallet.", - "create_invoice": "Rechnung erstellen", - "create_donation_link": "Spendenlink erstellen", - "optional_email_hint": "Optionale Benachrichtigungs-E-Mail für den Zahlungsempfänger", - "optional_description": "Optionale Beschreibung", - "optional_name": "Optionaler Empfängername", - "clearnet_link": "Clearnet-Link", - "onion_link": "Zwiebel-Link", - "settings": "Einstellungen", - "sell_monero_com_alert_content": "Der Verkauf von Monero wird noch nicht unterstützt", - "error_text_input_below_minimum_limit": "Menge ist unter dem Minimum", - "error_text_input_above_maximum_limit": "Menge ist über dem Maximum", - "show_market_place": "Marktplatz anzeigen", - "prevent_screenshots": "Verhindern Sie Screenshots und Bildschirmaufzeichnungen", - "profile": "Profil", - "close": "Schließen", - "modify_2fa": "Cake 2FA ändern", - "disable_cake_2fa": "Cake 2FA deaktivieren", - "question_to_disable_2fa": "Sind Sie sicher, dass Sie Cake 2FA deaktivieren möchten? Für den Zugriff auf die Wallet und bestimmte Funktionen wird kein 2FA-Code mehr benötigt.", - "disable": "Deaktivieren", - "setup_2fa": "Setup-Cake 2FA", - "verify_with_2fa": "Verifizieren Sie mit Cake 2FA", - "totp_code": "TOTP-Code", - "please_fill_totp": "Bitte geben Sie den 8-stelligen Code ein, der auf Ihrem anderen Gerät vorhanden ist", - "totp_2fa_success": "Erfolg! Cake 2FA für dieses Wallet aktiviert. Denken Sie daran, Ihren mnemonischen Seed zu speichern, falls Sie den Zugriff auf die Wallet verlieren.", - "totp_verification_success": "Verifizierung erfolgreich!", - "totp_2fa_failure": "Falscher Code. Bitte versuchen Sie es mit einem anderen Code oder generieren Sie einen neuen geheimen Schlüssel. Verwenden Sie eine kompatible 2FA-App, die 8-stellige Codes und SHA512 unterstützt.", - "enter_totp_code": "Bitte geben Sie den TOTP-Code ein.", - "add_secret_code": "Oder fügen Sie diesen Geheimcode einer Authentifizierungs-App hinzu", - "totp_secret_code": "TOTP-Geheimcode", - "setup_2fa_text": "Cake 2FA verwendet TOTP als zweiten Authentifizierungsfaktor.\n\nDas TOTP von Cake 2FA erfordert SHA-512 und 8-stellige Unterstützung; Dies sorgt für erhöhte Sicherheit. Weitere Informationen und unterstützte Apps finden Sie im Leitfaden.", - "setup_totp_recommended": "TOTP einrichten", - "disable_buy": "Kaufaktion deaktivieren", - "disable_sell": "Verkaufsaktion deaktivieren", - "cake_2fa_preset": "Kuchen 2FA-Voreinstellung", - "monero_dark_theme": "Dunkles Monero-Thema", + "available_balance": "Verfügbares Guthaben", + "available_balance_description": "Verfügbarer Saldo ist der Betrag, den Sie sofort ausgeben können. Dieser Betrag kann sich ändern, wenn Sie eine Transaktion senden oder empfangen.", + "avg_savings": "Durchschn. Einsparungen", + "awaitDAppProcessing": "Bitte warten Sie, bis die dApp die Verarbeitung abgeschlossen hat.", + "background_sync_mode": "Hintergrundsynchronisierungsmodus", + "backup": "Sicherung", + "backup_file": "Sicherungsdatei", + "backup_password": "Passwort sichern", + "balance_page": "Balance-Seite", + "bill_amount": "Rechnungsbetrag", + "billing_address_info": "Wenn Sie nach einer Rechnungsadresse gefragt werden, geben Sie bitte Ihre Lieferadresse an", + "biometric_auth_reason": "Scannen Sie Ihren Fingerabdruck zur Authentifizierung", "bitcoin_dark_theme": "Dunkles Bitcoin-Thema", "bitcoin_light_theme": "Bitcoin Light-Thema", - "high_contrast_theme": "Kontrastreiches Thema", - "matrix_green_dark_theme": "Matrix Green Dark Theme", - "monero_light_theme": "Monero Light-Thema", - "auto_generate_subaddresses": "Unteradressen automatisch generieren", - "narrow": "Eng", - "normal": "Normal", - "aggressive": "Übereifrig", - "require_for_assessing_wallet": "Für den Zugriff auf die Wallet erforderlich", - "require_for_sends_to_non_contacts": "Erforderlich für Versendungen an Nichtkontakte", - "require_for_sends_to_contacts": "Erforderlich für Versendungen an Kontakte", - "require_for_sends_to_internal_wallets": "Erforderlich für Sendungen an interne Wallets", - "require_for_exchanges_to_internal_wallets": "Erforderlich für den Umtausch in interne Wallets", - "require_for_adding_contacts": "Erforderlich zum Hinzufügen von Kontakten", - "require_for_creating_new_wallets": "Erforderlich zum Erstellen neuer Wallets", - "require_for_all_security_and_backup_settings": "Für alle Sicherheits- und Sicherungseinstellungen erforderlich", - "available_balance_description": "Verfügbarer Saldo ist der Betrag, den Sie sofort ausgeben können. Dieser Betrag kann sich ändern, wenn Sie eine Transaktion senden oder empfangen.", - "syncing_wallet_alert_title": "Ihr Wallet wird synchronisiert", - "syncing_wallet_alert_content": "Ihr Kontostand und Ihre Transaktionsliste sind möglicherweise erst vollständig, wenn oben „SYNCHRONISIERT“ steht. Klicken/tippen Sie, um mehr zu erfahren.", - "home_screen_settings": "Einstellungen für den Startbildschirm", - "sort_by": "Sortiere nach", - "search_add_token": "Token suchen / hinzufügen", - "edit_token": "Token bearbeiten", - "warning": "Warnung", - "add_token_warning": "Bearbeiten oder fügen Sie Token nicht gemäß den Anweisungen von Betrügern hinzu.\nBestätigen Sie Token-Adressen immer mit seriösen Quellen!", - "add_token_disclaimer_check": "Ich habe die Adresse und Informationen zum Token-Vertrag anhand einer seriösen Quelle bestätigt. Das Hinzufügen böswilliger oder falscher Informationen kann zu einem Verlust von Geldern führen.", - "token_contract_address": "Token-Vertragsadresse", - "token_name": "Token-Name, z. B.: Tether", - "token_symbol": "Token-Symbol, z. B.: USDT", - "token_decimal": "Token-Dezimalzahl", - "field_required": "Dieses Feld ist erforderlich", - "pin_at_top": "Stecken Sie ${token} oben fest", - "invalid_input": "Ungültige Eingabe", - "fiat_balance": "Fiat Balance", - "gross_balance": "Bruttosaldo", - "alphabetical": "Alphabetisch", - "generate_name": "Namen generieren", - "balance_page": "Balance-Seite", - "share": "Teilen", - "slidable": "Verschiebbar", - "manage_nodes": "Knoten verwalten", - "etherscan_history": "Etherscan-Geschichte", - "template_name": "Vorlagenname", + "bitcoin_payments_require_1_confirmation": "Bitcoin-Zahlungen erfordern 1 Bestätigung, was 20 Minuten oder länger dauern kann. Danke für Ihre Geduld! Sie erhalten eine E-Mail, wenn die Zahlung bestätigt ist.", + "Blocks_remaining": "${status} verbleibende Blöcke", + "bright_theme": "Strahlend hell", + "buy": "Kaufen", + "buy_alert_content": "Derzeit unterstützen wir nur den Kauf von Bitcoin, Ethereum, Litecoin und Monero. Bitte erstellen Sie Ihr Bitcoin-, Ethereum-, Litecoin- oder Monero-Wallet oder wechseln Sie zu diesem.", + "buy_bitcoin": "Bitcoin kaufen", + "buy_provider_unavailable": "Anbieter derzeit nicht verfügbar.", + "buy_with": "Kaufen mit", + "by_cake_pay": "von Cake Pay", + "cake_2fa_preset": "Kuchen 2FA-Voreinstellung", + "cake_pay_account_note": "Melden Sie sich nur mit einer E-Mail-Adresse an, um Karten anzuzeigen und zu kaufen. Einige sind sogar mit Rabatt erhältlich!", + "cake_pay_learn_more": "Kaufen und lösen Sie Geschenkkarten sofort in der App ein!\nWischen Sie von links nach rechts, um mehr zu erfahren.", + "cake_pay_subtitle": "Kaufen Sie ermäßigte Geschenkkarten (nur USA)", + "cake_pay_title": "Cake Pay-Geschenkkarten", + "cake_pay_web_cards_subtitle": "Kaufen Sie weltweit Prepaid-Karten und Geschenkkarten", + "cake_pay_web_cards_title": "Cake Pay-Webkarten", + "cake_wallet": "Cake Wallet", + "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.", + "camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.", + "cancel": "Abbrechen", + "card_address": "Adresse:", + "cardholder_agreement": "Karteninhabervertrag", + "cards": "Karten", + "chains": "Ketten", + "change": "Ändern", + "change_backup_password_alert": "Ihre vorherigen Sicherungsdateien können nicht mit einem neuen Sicherungskennwort importiert werden. Das neue Sicherungskennwort wird nur für neue Sicherungsdateien verwendet. Sind Sie sicher, dass Sie das Sicherungskennwort ändern möchten?", + "change_currency": "Währung ändern", + "change_current_node": "Möchten Sie den aktuellen Knoten wirklich zu ${node}? ändern?", + "change_current_node_title": "Aktuellen Knoten ändern", + "change_exchange_provider": "Exchange-Anbieter ändern", + "change_language": "Sprache ändern", + "change_language_to": "Sprache zu ${language} ändern?", + "change_password": "Passwort ändern", "change_rep": "Change-Beauftragter", "change_rep_message": "Sind Sie sicher, dass Sie den Vertreter wechseln möchten?", - "unsupported_asset": "Wir unterstützen diese Aktion für dieses Asset nicht. Bitte erstellen Sie eine Wallet eines unterstützten Asset-Typs oder wechseln Sie zu einer Wallet.", - "manage_pow_nodes": "PoW-Knoten verwalten", - "support_title_live_chat": "Live Support", - "support_description_live_chat": "Kostenlos und schnell! Ausgebildete Mitarbeiter stehen zur Unterstützung bereit, um zu helfen", - "support_title_guides": "Cake Wallet Guides", - "support_description_guides": "Dokumentation und Hilfe für bekannte Probleme", - "support_title_other_links": "Andere Support-Links", - "support_description_other_links": "Treten Sie unseren Communities bei oder erreichen Sie uns oder unsere Partner über andere Methoden", + "change_rep_successful": "Vertreter erfolgreich gerändert", + "change_wallet_alert_content": "Möchten Sie die aktuelle Wallet zu ${wallet_name} ändern?", + "change_wallet_alert_title": "Aktuelle Wallet ändern", + "choose_account": "Konto auswählen", + "choose_address": "\n\nBitte wählen Sie die Adresse:", "choose_derivation": "Wählen Sie Brieftaschenableitung", - "new_first_wallet_text": "Bewahren Sie Ihre Kryptowährung einfach sicher auf", - "select_destination": "Bitte wählen Sie das Ziel für die Sicherungsdatei aus.", - "save_to_downloads": "Unter „Downloads“ speichern", - "select_buy_provider_notice": "Wählen Sie oben einen Anbieter kaufen. Sie können diese Seite überspringen, indem Sie Ihren Standard-Kaufanbieter in den App-Einstellungen festlegen.", - "onramper_option_description": "Kaufen Sie schnell Krypto mit vielen Zahlungsmethoden. In den meisten Ländern erhältlich. Spreads und Gebühren variieren.", + "choose_from_available_options": "Wähle aus verfügbaren Optionen:", + "choose_one": "Wähle ein", + "choose_relay": "Bitte wählen Sie ein zu verwendendes Relais aus", + "choose_wallet_currency": "Bitte wählen Sie die Währung der Wallet:", + "clear": "Zurücksetzen", + "clearnet_link": "Clearnet-Link", + "close": "Schließen", + "coin_control": "Coin Control (optional)", + "cold_or_recover_wallet": "Fügen Sie eine Cold Wallet hinzu oder stellen Sie eine Paper Wallet wieder her", + "color_theme": "Farbthema", + "commit_transaction_amount_fee": "Transaktion absenden\nBetrag: ${amount}\nGebühr: ${fee}", + "confirm": "Bestätigen", + "confirm_delete_template": "Diese Aktion löscht diese Vorlage. Möchten Sie fortfahren?", + "confirm_delete_wallet": "Diese Aktion löscht diese Wallet. Möchten Sie fortfahren?", + "confirm_sending": "Senden bestätigen", + "confirmations": "Bestätigungen", + "confirmed": "Bestätigter Saldo", + "confirmed_tx": "Bestätigt", + "congratulations": "Glückwunsch!", + "connect_an_existing_yat": "Verbinden Sie ein vorhandenes Yat", + "connect_yats": "Yats verbinden", + "connection_sync": "Verbindung und Synchronisierung", + "connectWalletPrompt": "Verbinden Sie Ihr Wallet mit WalletConnect, um Transaktionen durchzuführen", + "contact": "Kontakt", + "contact_list_contacts": "Kontakte", + "contact_list_wallets": "Meine Wallets", + "contact_name": "Name des Kontakts", + "contact_support": "Support kontaktieren", + "continue_text": "Weiter", + "contractName": "Vertragsname", + "contractSymbol": "Vertragssymbol", + "copied_key_to_clipboard": "${key} in Zwischenablage kopiert", + "copied_to_clipboard": "In die Zwischenablage kopiert", + "copy": "Kopieren", + "copy_address": "Adresse kopieren", + "copy_id": "ID kopieren", + "copyWalletConnectLink": "Kopieren Sie den WalletConnect-Link von dApp und fügen Sie ihn hier ein", + "create_account": "Konto erstellen", + "create_backup": "Backup erstellen", + "create_donation_link": "Spendenlink erstellen", + "create_invoice": "Rechnung erstellen", + "create_new": "Neue Wallet erstellen", + "create_new_account": "Neues Konto erstellen", + "creating_new_wallet": "Neue Wallet erstellen", + "creating_new_wallet_error": "Fehler: ${description}", + "creation_date": "Erstellungsdatum", + "custom": "benutzerdefiniert", + "custom_drag": "Custom (Hold and Drag)", + "custom_redeem_amount": "Benutzerdefinierter Einlösungsbetrag", + "dark_theme": "Dunkel", + "debit_card": "Debitkarte", + "debit_card_terms": "Die Speicherung und Nutzung Ihrer Zahlungskartennummer (und Ihrer Zahlungskartennummer entsprechenden Anmeldeinformationen) in dieser digitalen Geldbörse unterliegt den Allgemeinen Geschäftsbedingungen des geltenden Karteninhabervertrags mit dem Zahlungskartenaussteller, gültig ab von Zeit zu Zeit.", + "decimal_places_error": "Zu viele Nachkommastellen", "default_buy_provider": "Standard-Kaufanbieter", - "ask_each_time": "Jedes Mal fragen", - "buy_provider_unavailable": "Anbieter derzeit nicht verfügbar.", - "signTransaction": "Transaktion unterzeichnen", + "default_sell_provider": "Standard-Verkaufsanbieter", + "delete": "Löschen", + "delete_account": "Konto löschen", + "delete_wallet": "Wallet löschen", + "delete_wallet_confirm_message": "Sind Sie sicher, dass Sie das ${wallet_name} Wallet löschen möchten?", + "deleteConnectionConfirmationPrompt": "Sind Sie sicher, dass Sie die Verbindung zu löschen möchten?", + "descending": "Absteigend", + "description": "Beschreibung", + "destination_tag": "Ziel-Tag:", + "dfx_option_description": "Krypto mit EUR und CHF kaufen. Bis zu 990€ ohne zusätzliches KYC. Für Privat- und Firmenkunden in Europa", + "didnt_get_code": "Kein Code?", + "digit_pin": "-stellige PIN", + "digital_and_physical_card": "digitale und physische Prepaid-Debitkarte", + "disable": "Deaktivieren", + "disable_buy": "Kaufaktion deaktivieren", + "disable_cake_2fa": "Cake 2FA deaktivieren", + "disable_exchange": "Exchange deaktivieren", + "disable_fiat": "Fiat deaktivieren", + "disable_sell": "Verkaufsaktion deaktivieren", + "disabled": "Deaktiviert", + "discount": "${value} % sparen", + "display_settings": "Anzeigeeinstellungen", + "displayable": "Anzeigebar", + "do_not_have_enough_gas_asset": "Sie verfügen nicht über genügend ${currency}, um eine Transaktion unter den aktuellen Bedingungen des Blockchain-Netzwerks durchzuführen. Sie benötigen mehr ${currency}, um die Gebühren für das Blockchain-Netzwerk zu bezahlen, auch wenn Sie einen anderen Vermögenswert senden.", + "do_not_send": "Nicht senden", + "do_not_share_warning_text": "Teilen Sie diese nicht mit anderen, einschließlich Support.\n\nIhr Geld kann und wird gestohlen werden!", + "do_not_show_me": "Zeig mir das nicht noch einmal", + "domain_looks_up": "Domain-Suchen", + "donation_link_details": "Details zum Spendenlink", + "e_sign_consent": "E-Sign-Zustimmung", + "edit": "Bearbeiten", + "edit_backup_password": "Sicherungskennwort bearbeiten", + "edit_node": "Knoten bearbeiten", + "edit_token": "Token bearbeiten", + "electrum_address_disclaimer": "Wir generieren jedes Mal neue Adressen, wenn Sie eine verwenden, aber vorherige Adressen funktionieren weiterhin", + "email_address": "E-Mail-Adresse", + "enabled": "Ermöglicht", + "enter_amount": "Betrag eingeben", + "enter_backup_password": "Sicherungskennwort hier eingeben", + "enter_code": "Code eingeben", + "enter_seed_phrase": "Geben Sie Ihre Seed-Phrase ein", + "enter_totp_code": "Bitte geben Sie den TOTP-Code ein.", + "enter_your_note": "Geben Sie Ihre Bemerkung ein…", + "enter_your_pin": "PIN eingeben", + "enter_your_pin_again": "Geben Sie Ihre PIN erneut ein", + "enterTokenID": "Geben Sie die Token-ID ein", + "enterWalletConnectURI": "Geben Sie den WalletConnect-URI ein", + "error": "Fehler", + "error_dialog_content": "Hoppla, wir haben einen Fehler.\n\nBitte senden Sie den Absturzbericht an unser Support-Team, um die Anwendung zu verbessern.", + "error_text_account_name": "Der Kontoname darf nur Buchstaben und Zahlen enthalten\nund muss zwischen 1 und 15 Zeichen lang sein", + "error_text_address": "Die Walletadresse muss dem Typ der Kryptowährung\nentsprechen", + "error_text_amount": "Betrag darf nur Zahlen enthalten", + "error_text_contact_name": "Kontaktname darf nicht die Zeichen ` , ' \" enthalten\nund muss zwischen 1 und 32 Zeichen lang sein", + "error_text_crypto_currency": "Die Anzahl der Nachkommastellen\nmuss kleiner oder gleich 12 sein.", + "error_text_fiat": "Der Wert des Betrags darf den verfügbaren Kontostand nicht überschreiten.\nDie Anzahl der Nachkommastellen muss kleiner oder gleich 2 sein", + "error_text_input_above_maximum_limit": "Menge ist über dem Maximum", + "error_text_input_below_minimum_limit": "Menge ist unter dem Minimum", + "error_text_keys": "Walletschlüssel können nur 64 hexadezimale Zeichen enthalten", + "error_text_limits_loading_failed": "Handel für ${provider} wird nicht erstellt. Das Laden der Limits ist fehlgeschlagen", + "error_text_maximum_limit": "Handel für ${provider} wird nicht erstellt. Menge ist über dem Maximum: ${max} ${currency}", + "error_text_minimal_limit": "Handel für ${provider} wird nicht erstellt. Menge ist unter dem Minimum: ${min} ${currency}", + "error_text_node_address": "Bitte geben Sie eine iPv4-Adresse ein", + "error_text_node_port": "Der Knotenport darf nur Nummern zwischen 0 und 65535 enthalten", + "error_text_node_proxy_address": "Bitte geben Sie : ein, zum Beispiel 127.0.0.1:9050", + "error_text_payment_id": "Die Zahlungs-ID darf nur 16 bis 64 hexadezimale Zeichen enthalten", + "error_text_subaddress_name": "Der Name der Unteradresse darf nicht die Zeichen ` , ' \" enthalten\nund muss zwischen 1 und 20 Zeichen lang sein", + "error_text_template": "Vorlagenname und Adresse dürfen nicht die Zeichen ` , ' \" enthalten\nund müssen zwischen 1 und 106 Zeichen lang sein", + "error_text_wallet_name": "Der Wallet-Name darf nur Buchstaben, Zahlen und _- Symbole enthalten\nund muss zwischen 1 und 33 Zeichen lang sein", + "error_text_xmr": "Der XMR-Wert darf das verfügbare Guthaben nicht überschreiten.\nDie Anzahl der Nachkommastellen muss kleiner oder gleich 12 sein", "errorGettingCredentials": "Fehlgeschlagen: Fehler beim Abrufen der Anmeldeinformationen", "errorSigningTransaction": "Beim Signieren der Transaktion ist ein Fehler aufgetreten", - "pairingInvalidEvent": "Paarung ungültiges Ereignis", - "chains": "Ketten", - "methods": "Methoden", - "events": "Veranstaltungen", - "reject": "Ablehnen", - "approve": "Genehmigen", - "expiresOn": "Läuft aus am", - "walletConnect": "WalletConnect", - "nullURIError": "URI ist null", - "connectWalletPrompt": "Verbinden Sie Ihr Wallet mit WalletConnect, um Transaktionen durchzuführen", - "newConnection": "Neue Verbindung", - "activeConnectionsPrompt": "Hier werden aktive Verbindungen angezeigt", - "deleteConnectionConfirmationPrompt": "Sind Sie sicher, dass Sie die Verbindung zu löschen möchten?", + "estimated": "Geschätzt", + "etherscan_history": "Etherscan-Geschichte", "event": "Ereignis", - "successful": "Erfolgreich", - "wouoldLikeToConnect": "möchte mich gerne vernetzen", - "message": "Nachricht", - "do_not_have_enough_gas_asset": "Sie verfügen nicht über genügend ${currency}, um eine Transaktion unter den aktuellen Bedingungen des Blockchain-Netzwerks durchzuführen. Sie benötigen mehr ${currency}, um die Gebühren für das Blockchain-Netzwerk zu bezahlen, auch wenn Sie einen anderen Vermögenswert senden.", - "totp_auth_url": "TOTP-Auth-URL", - "awaitDAppProcessing": "Bitte warten Sie, bis die dApp die Verarbeitung abgeschlossen hat.", - "copyWalletConnectLink": "Kopieren Sie den WalletConnect-Link von dApp und fügen Sie ihn hier ein", - "enterWalletConnectURI": "Geben Sie den WalletConnect-URI ein", - "seed_key": "Seed-Schlüssel", - "enter_seed_phrase": "Geben Sie Ihre Seed-Phrase ein", - "change_rep_successful": "Vertreter erfolgreich gerändert", - "add_contact": "Kontakt hinzufügen", + "events": "Veranstaltungen", + "exchange": "Umwechseln", + "exchange_incorrect_current_wallet_for_xmr": "Wenn Sie XMR von Ihrem Cake Wallet Monero-Guthaben umtauschen möchten, wechseln Sie bitte zuerst zu Ihrer Monero-Wallet.", + "exchange_new_template": "Neue Vorlage", "exchange_provider_unsupported": "${providerName} wird nicht mehr unterstützt!", - "domain_looks_up": "Domain-Suchen", - "require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets", - "camera_permission_is_required": "Eine Kameraerlaubnis ist erforderlich.\nBitte aktivieren Sie es in den App-Einstellungen.", - "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut", - "order_by": "Sortieren nach", - "creation_date": "Erstellungsdatum", + "exchange_result_confirm": "Durch Drücken von \"Bestätigen\" wird ${fetchingLabel} ${from} von Ihrer Wallet namens ${walletName} an die unten angegebene Adresse gesendet. Alternativ können Sie von einer externen Wallet an die unten angegebene Adresse / QR-Code senden.\n\nBitte bestätigen Sie, um fortzufahren, oder gehen Sie zurück, um die Beträge zu ändern.", + "exchange_result_description": "Sie müssen mindestens ${fetchingLabel} ${from} an die auf der nächsten Seite angegebene Adresse senden. Wenn Sie einen Betrag unter ${fetchingLabel} ${from} senden, wird dieser möglicherweise nicht konvertiert und möglicherweise nicht erstattet.", + "exchange_result_write_down_ID": "*Bitte kopieren oder notieren Sie sich die oben gezeigte ID.", + "exchange_result_write_down_trade_id": "Bitte kopieren oder notieren Sie die Handels-ID, um fortzufahren.", + "exchange_sync_alert_content": "Bitte warten Sie, bis Ihre Wallet synchronisiert ist", + "expired": "Abgelaufen", + "expires": "Läuft ab", + "expiresOn": "Läuft aus am", + "export_backup": "Sicherung exportieren", + "extra_id": "Extra ID:", + "extracted_address_content": "Sie senden Geld an\n${recipient_name}", + "failed_authentication": "Authentifizierung fehlgeschlagen. ${state_error}", + "faq": "Häufig gestellte Fragen", + "fetching": "Frage ab", + "fiat_api": "Fiat API", + "fiat_balance": "Fiat Balance", + "field_required": "Dieses Feld ist erforderlich", + "fill_code": "Geben Sie den Bestätigungscode ein, den Sie per E-Mail erhalten haben", + "filter_by": "Filtern nach", + "first_wallet_text": "Eine großartige Wallet für Monero, Bitcoin, Ethereum, Litecoin, und Haven", + "fixed_pair_not_supported": "Dieses feste Paar wird von den ausgewählten Vermittlungsstellen nicht unterstützt", + "fixed_rate": "Feste Rate", + "fixed_rate_alert": "Sie können den Empfangsbetrag eingeben, wenn der Festratenmodus aktiviert ist. Möchten Sie in den Festratenmodus wechseln?", + "forgot_password": "Passwort vergessen", + "freeze": "Einfrieren", + "frequently_asked_questions": "Häufig gestellte Fragen", + "frozen": "Gefroren", + "full_balance": "Gesamtguthaben", + "generate_name": "Namen generieren", + "generating_gift_card": "Geschenkkarte wird erstellt", + "get_a": "Hole ein", + "get_card_note": " die Sie mit digitaler Währung aufladen können. Keine zusätzlichen Informationen erforderlich!", + "get_your_yat": "Holen Sie sich Ihre Yat", + "gift_card_amount": "Gutscheinbetrag", + "gift_card_balance_note": "Geschenkkarten mit Restguthaben erscheinen hier", + "gift_card_is_generated": "Geschenkkarte wird generiert", + "gift_card_number": "Geschenkkartennummer", + "gift_card_redeemed_note": "Gutscheine, die Sie eingelöst haben, werden hier angezeigt", + "gift_cards": "Geschenkkarten", + "gift_cards_unavailable": "Geschenkkarten können derzeit nur über Monero, Bitcoin und Litecoin erworben werden", + "got_it": "Verstanden", + "gross_balance": "Bruttosaldo", "group_by_type": "Gruppe nach Typ", - "importNFTs": "NFTs importieren", - "noNFTYet": "Noch keine NFTs", - "address": "Adresse", - "enterTokenID": "Geben Sie die Token-ID ein", - "tokenID": "AUSWEIS", - "name": "Name", - "symbol": "Symbol", - "seed_phrase_length": "Länge der Seed-Phrase", - "unavailable_balance": "Nicht verfügbares Guthaben", - "unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.", - "unspent_change": "Wechselgeld", - "tor_connection": "Tor-Verbindung", - "setup_warning_2fa_text": "Sie müssen Ihr Wallet aus dem mnemonischen Seed wiederherstellen.\n\nDer Cake-Support kann Ihnen nicht weiterhelfen, wenn Sie den Zugriff auf Ihre 2FA- oder Mnemonik-Seeds verlieren.\nCake 2FA ist eine zweite Authentifizierung für bestimmte Aktionen im Wallet. Bevor Sie Cake 2FA verwenden, empfehlen wir Ihnen, die Anleitung durchzulesen.Es ist NICHT so sicher wie eine Kühllagerung.\n\nWenn Sie den Zugriff auf Ihre 2FA-App oder Ihre TOTP-Schlüssel verlieren, verlieren Sie auch den Zugriff auf dieses Wallet. ", - "scan_qr_on_device": "Scannen Sie diesen QR-Code auf einem anderen Gerät", + "haven_app": "Haven von Cake Wallet", + "haven_app_wallet_text": "Eine großartige Wallet für Haven", + "help": "hilfe", + "hidden_balance": "Verstecktes Guthaben", + "hide_details": "Details ausblenden", + "high_contrast_theme": "Kontrastreiches Thema", + "home_screen_settings": "Einstellungen für den Startbildschirm", "how_to_use": "Wie benutzt man", + "how_to_use_card": "Wie man diese Karte benutzt", + "id": "ID: ", + "ignor": "Ignorieren", + "import": "Importieren", + "importNFTs": "NFTs importieren", + "in_store": "Im Geschäft", + "incoming": "Eingehend", + "incorrect_seed": "Der eingegebene Text ist ungültig.", + "introducing_cake_pay": "Einführung von Cake Pay!", + "invalid_input": "Ungültige Eingabe", + "invoice_details": "Rechnungs-Details", + "is_percentage": "ist", + "last_30_days": "Letzte 30 Tage", + "learn_more": "Erfahren Sie mehr", + "light_theme": "Hell", + "loading_your_wallet": "Wallet wird geladen", + "login": "Einloggen", + "logout": "Abmelden", + "low_fee": "Niedrige Gebühr", + "low_fee_alert": "Sie verwenden derzeit eine niedrige Netzwerkgebührenpriorität. Dies kann zu langen Wartezeiten, unterschiedlichen Kursen oder stornierten Trades führen. Wir empfehlen, für ein besseres Erlebnis eine höhere Gebühr festzulegen.", + "manage_nodes": "Knoten verwalten", + "manage_pow_nodes": "PoW-Knoten verwalten", + "manage_yats": "Yats verwalten", + "mark_as_redeemed": "Als eingelöst markieren", + "market_place": "Marktplatz", + "matrix_green_dark_theme": "Matrix Green Dark Theme", + "max_amount": "Max: ${value}", + "max_value": "Max: ${value} ${currency}", + "memo": "Memo:", + "message": "Nachricht", + "methods": "Methoden", + "min_amount": "Min: ${value}", + "min_value": "Min: ${value} ${currency}", + "minutes_to_pin_code": "${minute} Minuten", + "mm": "MM", + "modify_2fa": "Cake 2FA ändern", + "monero_com": "Monero.com von Cake Wallet", + "monero_com_wallet_text": "Eine großartige Wallet für Monero", + "monero_dark_theme": "Dunkles Monero-Thema", + "monero_light_theme": "Monero Light-Thema", + "moonpay_alert_text": "Der Wert des Betrags muss größer oder gleich ${minAmount} ${fiatCurrency} sein", + "more_options": "Weitere Optionen", + "name": "Name", + "narrow": "Eng", + "new_first_wallet_text": "Bewahren Sie Ihre Kryptowährung einfach sicher auf", + "new_node_testing": "Neuen Knoten testen", + "new_subaddress_create": "Erstellen", + "new_subaddress_label_name": "Bezeichnung", + "new_subaddress_title": "Neue Adresse", + "new_template": "neue Vorlage", + "new_wallet": "Neue Wallet", + "newConnection": "Neue Verbindung", + "no_id_needed": "Keine ID erforderlich!", + "no_id_required": "Keine ID erforderlich. Upgraden und überall ausgeben", + "no_relay_on_domain": "Es gibt kein Relay für die Domäne des Benutzers oder das Relay ist nicht verfügbar. Bitte wählen Sie ein zu verwendendes Relais aus.", + "no_relays": "Keine Relais", + "no_relays_message": "Wir haben einen Nostr NIP-05-Eintrag für diesen Benutzer gefunden, der jedoch keine Relays enthält. Bitte weisen Sie den Empfänger an, Relays zu seinem Nostr-Datensatz hinzuzufügen.", + "node_address": "Knotenadresse", + "node_connection_failed": "Verbindung fehlgeschlagen", + "node_connection_successful": "Die Verbindung war erfolgreich", + "node_new": "Neuer Knoten", + "node_port": "Knotenport", + "node_reset_settings_title": "Einstellungen zurücksetzen", + "node_test": "Test", + "nodes": "Knoten", + "nodes_list_reset_to_default_message": "Möchten Sie wirklich die Standardeinstellungen wiederherstellen?", + "none_of_selected_providers_can_exchange": "Keiner der ausgewählten Anbieter kann diesen Austausch vornehmen", + "noNFTYet": "Noch keine NFTs", + "normal": "Normal", + "note_optional": "Bemerkung (optional)", + "note_tap_to_change": "Bemerkung (zum Ändern tippen)", + "nullURIError": "URI ist null", + "offer_expires_in": "Angebot läuft ab in: ", + "offline": "offline", + "ok": "OK", + "onion_link": "Zwiebel-Link", + "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", + "optional_description": "Optionale Beschreibung", + "optional_email_hint": "Optionale Benachrichtigungs-E-Mail für den Zahlungsempfänger", + "optional_name": "Optionaler Empfängername", + "optionally_order_card": "Optional eine physische Karte bestellen.", + "orbot_running_alert": "Bitte stellen Sie sicher, dass Orbot läuft, bevor Sie sich mit diesem Knoten verbinden.", + "order_by": "Sortieren nach", + "order_id": "Bestell-ID", + "order_physical_card": "Physische Karte bestellen", + "other_settings": "Andere Einstellungen", + "outdated_electrum_wallet_description": "Neue Bitcoin-Wallets, die in Cake erstellt wurden, haben jetzt einen 24-Wort-Seed. Sie müssen eine neue Bitcoin-Wallet erstellen, Ihr gesamtes Geld in die neue 24-Wort-Wallet überweisen und keine Wallet mit einem 12-Wort-Seed mehr verwenden. Bitte tun Sie dies sofort, um Ihr Geld zu sichern.", + "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", + "overwrite_amount": "Overwrite amount", + "pairingInvalidEvent": "Paarung ungültiges Ereignis", + "password": "Passwort", + "paste": "Einfügen", + "pause_wallet_creation": "Die Möglichkeit, Haven Wallet zu erstellen, ist derzeit pausiert.", + "payment_id": "Zahlungs-ID: ", + "payment_was_received": "Ihre Zahlung ist eingegangen.", + "pending": " (ausstehend)", + "percentageOf": "von ${amount}", + "pin_at_top": "Stecken Sie ${token} oben fest", + "pin_is_incorrect": "PIN ist falsch", + "pin_number": "PIN-Nummer", + "placeholder_contacts": "Ihre Kontakte werden hier angezeigt", + "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_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", + "please_wait": "Warten Sie mal", + "polygonscan_history": "PolygonScan-Verlauf", + "powered_by": "Ermöglicht durch ${title}", + "pre_seed_button_text": "Verstanden. Zeig mir meinen Seed", + "pre_seed_description": "Auf der nächsten Seite sehen Sie eine Reihe von ${words} Wörtern. Dies ist Ihr einzigartiger und privater Seed und der EINZIGE Weg, um Ihre Wallet im Falle eines Verlusts oder einer Fehlfunktion wiederherzustellen. Es liegt in IHRER Verantwortung, ihn aufzuschreiben und an einem sicheren Ort außerhalb der Cake Wallet-App aufzubewahren.", + "pre_seed_title": "WICHTIG", + "prevent_screenshots": "Verhindern Sie Screenshots und Bildschirmaufzeichnungen", + "privacy": "Datenschutz", + "privacy_policy": "Datenschutzrichtlinie", + "privacy_settings": "Datenschutzeinstellungen", + "private_key": "Privater Schlüssel", + "proceed_after_one_minute": "Wenn der Bildschirm nach 1 Minute nicht weitergeht, überprüfen Sie bitte Ihre E-Mail.", + "profile": "Profil", + "provider_error": "${provider}-Fehler", + "public_key": "Öffentlicher Schlüssel", + "purchase_gift_card": "Geschenkkarte kaufen", + "qr_fullscreen": "Tippen Sie hier, um den QR-Code im Vollbildmodus zu öffnen", + "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", + "question_to_disable_2fa": "Sind Sie sicher, dass Sie Cake 2FA deaktivieren möchten? Für den Zugriff auf die Wallet und bestimmte Funktionen wird kein 2FA-Code mehr benötigt.", + "receivable_balance": "Forderungsbilanz", + "receive": "Empfangen", + "receive_amount": "Betrag", + "received": "Empfangen", + "recipient_address": "Empfängeradresse", + "reconnect": "Erneut verbinden", + "reconnect_alert_text": "Sind Sie sicher, dass Sie sich neu verbinden möchten?", + "reconnection": "Neu verbinden", + "redeemed": "Versilbert", + "refund_address": "Rückerstattungsadresse", + "reject": "Ablehnen", + "remaining": "Rest", + "remove": "Entfernen", + "remove_node": "Knoten entfernen", + "remove_node_message": "Möchten Sie den ausgewählten Knoten wirklich entfernen?", + "rename": "Umbenennen", + "require_for_adding_contacts": "Erforderlich zum Hinzufügen von Kontakten", + "require_for_all_security_and_backup_settings": "Für alle Sicherheits- und Sicherungseinstellungen erforderlich", + "require_for_assessing_wallet": "Für den Zugriff auf die Wallet erforderlich", + "require_for_creating_new_wallets": "Erforderlich zum Erstellen neuer Wallets", + "require_for_exchanges_to_external_wallets": "Erforderlich für den Umtausch in externe Wallets", + "require_for_exchanges_to_internal_wallets": "Erforderlich für den Umtausch in interne Wallets", + "require_for_sends_to_contacts": "Erforderlich für Versendungen an Kontakte", + "require_for_sends_to_internal_wallets": "Erforderlich für Sendungen an interne Wallets", + "require_for_sends_to_non_contacts": "Erforderlich für Versendungen an Nichtkontakte", + "require_pin_after": "PIN anfordern nach", + "rescan": "Erneut scannen", + "resend_code": "Bitte erneut senden", + "reset": "Zurücksetzen", + "reset_password": "Passwort zurücksetzen", + "restore_active_seed": "Aktiver Seed", + "restore_address": "Adresse", + "restore_bitcoin_description_from_keys": "Stellen Sie Ihre Wallet aus der generierten WIF-Zeichenfolge aus Ihren privaten Schlüsseln wieder her", + "restore_bitcoin_description_from_seed": "Stellen Sie Ihre Wallet aus dem 24-Wort-Kombinationscode wieder her", + "restore_bitcoin_title_from_keys": "Aus WIF wiederherstellen", + "restore_description_from_backup": "Sie können die gesamte Cake Wallet-App aus Ihrer Sicherungsdatei wiederherstellen", + "restore_description_from_keys": "Stellen Sie Ihr Wallet aus generierten Tastenanschlägen her, die von Ihren privaten Schlüsseln gespeichert wurden", + "restore_description_from_seed": "Stellen Sie Ihre Wallet aus den 25 Wörtern oder dem 13-Wort-Kombinationscode wieder her", + "restore_description_from_seed_keys": "Stellen Sie Ihr Wallet aus Seed/Schlüsseln wieder her, die Sie sicher aufbewahrt haben", + "restore_from_date_or_blockheight": "Bitte geben Sie ein Datum ein, das einige Tage vor dem Erstellen dieser Wallet liegt. Oder wenn Sie die Blockhöhe kennen, geben Sie stattdessen diese ein", + "restore_from_seed_placeholder": "Seed bitte hier eingeben oder einfügen", + "restore_new_seed": "Neuer Seed", + "restore_next": "Weiter", + "restore_recover": "Wiederherstellen", + "restore_restore_wallet": "Wallet wiederherstellen", + "restore_seed_keys_restore": "Seed/Schlüssel wiederherstellen", + "restore_spend_key_private": "Spend Key (geheim)", + "restore_title_from_backup": "Aus einer Sicherungsdatei wiederherstellen", + "restore_title_from_keys": "Aus Schlüsseln wiederherstellen", + "restore_title_from_seed": "Aus Seed wiederherstellen", + "restore_title_from_seed_keys": "Aus Seed/Schlüssel wiederherstellen", + "restore_view_key_private": "View Key (geheim)", + "restore_wallet": "Wallet wiederherstellen", + "restore_wallet_name": "Walletname", + "restore_wallet_restore_description": "Beschreibung zur Wallet-Wiederherstellung", + "router_no_route": "Keine Route definiert für ${name}", + "save": "Speichern", + "save_backup_password": "Bitte stellen Sie sicher, dass Sie Ihr Sicherungskennwort gespeichert haben. Ohne dieses können Sie Ihre Sicherungsdateien nicht importieren.", + "save_backup_password_alert": "Sicherungskennwort speichern", + "save_to_downloads": "Unter „Downloads“ speichern", + "saved_the_trade_id": "Ich habe die Handels-ID gespeichert", + "scan_qr_code": "QR-Code scannen", + "scan_qr_code_to_get_address": "Scannen Sie den QR-Code, um die Adresse zu erhalten", + "scan_qr_on_device": "Scannen Sie diesen QR-Code auf einem anderen Gerät", + "search": "Suche", + "search_add_token": "Token suchen / hinzufügen", + "search_category": "Suchkategorie", + "search_currency": "Währung suchen", + "search_language": "Sprache suchen", + "second_intro_content": "Ihr Yat ist eine einzige eindeutige Emoji-Adresse, die alle Ihre langen hexadezimalen Adressen für alle Ihre Währungen ersetzt.", + "second_intro_title": "Eine Emoji-Adresse, um sie alle zu beherrschen", + "security_and_backup": "Sicherheit und Datensicherung", + "seed_alert_back": "Zurückgehen", + "seed_alert_content": "Der Seed ist der einzige Weg, Ihre Wallet wiederherzustellen. Haben Sie ihn aufgeschrieben?", + "seed_alert_title": "Achtung", + "seed_alert_yes": "Ja, habe ich", + "seed_choose": "Seed-Sprache auswählen", "seed_hex_form": "Brieftaschensamen (Sechskantform)", + "seed_key": "Seed-Schlüssel", + "seed_language": "Seed-Sprache", + "seed_language_chinese": "Chinesisch", + "seed_language_chinese_traditional": "Chinesisch (Traditionell)", + "seed_language_czech": "Tschechisch", + "seed_language_dutch": "Niederländisch", + "seed_language_english": "Englisch", + "seed_language_french": "Französisch", + "seed_language_german": "Deutsch", + "seed_language_italian": "Italiana/Italiano", + "seed_language_japanese": "Japanisch", + "seed_language_korean": "Koreanisch", + "seed_language_next": "Weiter", + "seed_language_portuguese": "Portugiesisch", + "seed_language_russian": "Russisch", + "seed_language_spanish": "Spanisch", + "seed_phrase_length": "Länge der Seed-Phrase", + "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", "seedtype": "Seedtyp", "seedtype_legacy": "Veraltet (25 Wörter)", "seedtype_polyseed": "Polyseed (16 Wörter)", - "seed_language_czech": "Tschechisch", - "seed_language_korean": "Koreanisch", - "seed_language_chinese_traditional": "Chinesisch (Traditionell)", - "ascending": "Aufsteigend", - "descending": "Absteigend", - "dfx_option_description": "Krypto mit EUR und CHF kaufen. Bis zu 990€ ohne zusätzliches KYC. Für Privat- und Firmenkunden in Europa", - "polygonscan_history": "PolygonScan-Verlauf", - "wallet_seed_legacy": "Legacy Wallet Seed", - "default_sell_provider": "Standard-Verkaufsanbieter", + "select_backup_file": "Sicherungsdatei auswählen", + "select_buy_provider_notice": "Wählen Sie oben einen Anbieter kaufen. Sie können diese Seite überspringen, indem Sie Ihren Standard-Kaufanbieter in den App-Einstellungen festlegen.", + "select_destination": "Bitte wählen Sie das Ziel für die Sicherungsdatei aus.", "select_sell_provider_notice": "Wählen Sie oben einen Verkaufsanbieter aus. Sie können diesen Bildschirm überspringen, indem Sie in den App-Einstellungen Ihren Standard-Verkaufsanbieter festlegen.", - "custom_drag": "Custom (Hold and Drag)", + "sell": "Verkaufen", + "sell_alert_content": "Wir unterstützen derzeit nur den Verkauf von Bitcoin, Ethereum und Litecoin. Bitte erstellen Sie Ihr Bitcoin-, Ethereum- oder Litecoin-Wallet oder wechseln Sie zu diesem.", + "sell_monero_com_alert_content": "Der Verkauf von Monero wird noch nicht unterstützt", + "send": "Senden", + "send_address": "${cryptoCurrency}-Adresse", + "send_amount": "Betrag:", + "send_creating_transaction": "Erstelle Transaktion", + "send_error_currency": "Die Währung darf nur Zahlen enthalten", + "send_error_minimum_value": "Der Mindestbetrag ist 0,01", + "send_estimated_fee": "Geschätzte Gebühr:", + "send_fee": "Gebühr:", + "send_name": "Name", + "send_new": "Neu", + "send_payment_id": "Zahlungs-ID (optional)", + "send_priority": "Derzeit ist ${transactionPriority} als Gebührenpriorität eingestellt.\nDie Transaktionspriorität kann in den Einstellungen angepasst werden", + "send_sending": "Senden...", + "send_success": "Ihr ${crypto} wurde erfolgreich versendet", + "send_templates": "Vorlagen", + "send_title": "Senden", + "send_to_this_address": "Senden Sie ${currency} ${tag}an diese Adresse", + "send_xmr": "XMR senden", + "send_your_wallet": "Ihre Wallet", + "sending": "Senden", + "sent": "Versendet", + "settings": "Einstellungen", + "settings_all": "ALLE", + "settings_allow_biometrical_authentication": "Biometrische Authentifizierung zulassen", + "settings_can_be_changed_later": "Diese Einstellungen können später in den App-Einstellungen geändert werden", + "settings_change_language": "Sprache ändern", + "settings_change_pin": "PIN ändern", + "settings_currency": "Währung", + "settings_current_node": "Aktueller Knoten", + "settings_dark_mode": "Dunkler Modus", + "settings_display_balance": "Kontostand anzeigen", + "settings_display_on_dashboard_list": "Anzeige in der Dashboard-Liste", + "settings_fee_priority": "Gebührenpriorität", + "settings_nodes": "Knoten", + "settings_none": "Keiner", + "settings_only_trades": "Nur Handel", + "settings_only_transactions": "Nur Transaktionen", + "settings_personal": "Persönlich", + "settings_save_recipient_address": "Empfängeradresse speichern", + "settings_support": "Hilfe", + "settings_terms_and_conditions": "Geschäftsbedingungen", + "settings_title": "Einstellungen", + "settings_trades": "Handel", + "settings_transactions": "Transaktionen", + "settings_wallets": "Wallets", + "setup_2fa": "Setup-Cake 2FA", + "setup_2fa_text": "Cake 2FA verwendet TOTP als zweiten Authentifizierungsfaktor.\n\nDas TOTP von Cake 2FA erfordert SHA-512 und 8-stellige Unterstützung; Dies sorgt für erhöhte Sicherheit. Weitere Informationen und unterstützte Apps finden Sie im Leitfaden.", + "setup_pin": "PIN einrichten", + "setup_successful": "Ihre PIN wurde erfolgreich eingerichtet!", + "setup_totp_recommended": "TOTP einrichten", + "setup_warning_2fa_text": "Sie müssen Ihr Wallet aus dem mnemonischen Seed wiederherstellen.\n\nDer Cake-Support kann Ihnen nicht weiterhelfen, wenn Sie den Zugriff auf Ihre 2FA- oder Mnemonik-Seeds verlieren.\nCake 2FA ist eine zweite Authentifizierung für bestimmte Aktionen im Wallet. Bevor Sie Cake 2FA verwenden, empfehlen wir Ihnen, die Anleitung durchzulesen.Es ist NICHT so sicher wie eine Kühllagerung.\n\nWenn Sie den Zugriff auf Ihre 2FA-App oder Ihre TOTP-Schlüssel verlieren, verlieren Sie auch den Zugriff auf dieses Wallet. ", + "setup_your_debit_card": "Richten Sie Ihre Debitkarte ein", + "share": "Teilen", + "share_address": "Adresse teilen ", + "show_details": "Details anzeigen", + "show_keys": "Seed/Schlüssel anzeigen", + "show_market_place": "Marktplatz anzeigen", + "show_seed": "Seed zeigen", + "sign_up": "Anmelden", + "signTransaction": "Transaktion unterzeichnen", + "signup_for_card_accept_terms": "Melden Sie sich für die Karte an und akzeptieren Sie die Bedingungen.", + "slidable": "Verschiebbar", + "sort_by": "Sortiere nach", + "spend_key_private": "Spend Key (geheim)", + "spend_key_public": "Spend Key (öffentlich)", + "status": "Status: ", + "subaddress_title": "Unteradressenliste", + "subaddresses": "Unteradressen", + "submit_request": "Eine Anfrage stellen", + "successful": "Erfolgreich", + "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_live_chat": "Live Support", + "support_title_other_links": "Andere Support-Links", + "sweeping_wallet": "Wallet leeren", + "sweeping_wallet_alert": "Das sollte nicht lange dauern. VERLASSEN SIE DIESEN BILDSCHIRM NICHT, ANDERNFALLS KÖNNEN DIE GELDER VERLOREN GEHEN", + "switchToETHWallet": "Bitte wechseln Sie zu einem Ethereum-Wallet und versuchen Sie es erneut", "switchToEVMCompatibleWallet": "Bitte wechseln Sie zu einem EVM-kompatiblen Wallet und versuchen Sie es erneut (Ethereum, Polygon)", - "receivable_balance": "Forderungsbilanz", - "confirmed_tx": "Bestätigt", + "symbol": "Symbol", + "sync_all_wallets": "Alle Wallets synchronisieren", + "sync_status_attempting_sync": "SYNC VERSUCHEN", + "sync_status_connected": "VERBUNDEN", + "sync_status_connecting": "VERBINDEN", + "sync_status_failed_connect": "GETRENNT", + "sync_status_not_connected": "NICHT VERBUNDEN", + "sync_status_starting_sync": "STARTE SYNCHRONISIERUNG", + "sync_status_syncronized": "SYNCHRONISIERT", + "sync_status_syncronizing": "SYNCHRONISIERE", + "syncing_wallet_alert_content": "Ihr Kontostand und Ihre Transaktionsliste sind möglicherweise erst vollständig, wenn oben „SYNCHRONISIERT“ steht. Klicken/tippen Sie, um mehr zu erfahren.", + "syncing_wallet_alert_title": "Ihr Wallet wird synchronisiert", + "template": "Vorlage", + "template_name": "Vorlagenname", + "third_intro_content": "Yats leben auch außerhalb von Cake Wallet. Jede Wallet-Adresse auf der Welt kann durch ein Yat ersetzt werden!", + "third_intro_title": "Yat spielt gut mit anderen", + "time": "${minutes}m ${seconds}s", + "tip": "Hinweis:", + "today": "Heute", + "token_contract_address": "Token-Vertragsadresse", + "token_decimal": "Token-Dezimalzahl", + "token_name": "Token-Name, z. B.: Tether", + "token_symbol": "Token-Symbol, z. B.: USDT", + "tokenID": "AUSWEIS", + "tor_connection": "Tor-Verbindung", + "tor_only": "Nur Tor", + "total_saving": "Gesamteinsparungen", + "totp_2fa_failure": "Falscher Code. Bitte versuchen Sie es mit einem anderen Code oder generieren Sie einen neuen geheimen Schlüssel. Verwenden Sie eine kompatible 2FA-App, die 8-stellige Codes und SHA512 unterstützt.", + "totp_2fa_success": "Erfolg! Cake 2FA für dieses Wallet aktiviert. Denken Sie daran, Ihren mnemonischen Seed zu speichern, falls Sie den Zugriff auf die Wallet verlieren.", + "totp_auth_url": "TOTP-Auth-URL", + "totp_code": "TOTP-Code", + "totp_secret_code": "TOTP-Geheimcode", + "totp_verification_success": "Verifizierung erfolgreich!", + "trade_details_copied": "${title} in die Zwischenablage kopiert", + "trade_details_created_at": "Erzeugt am", + "trade_details_fetching": "Wird ermittelt", + "trade_details_id": "ID", + "trade_details_pair": "Paar", + "trade_details_provider": "Anbieter", + "trade_details_state": "Status", + "trade_details_title": "Handelsdetails", + "trade_for_not_created": "Handel für ${title} wird nicht erstellt.", + "trade_history_title": "Handelsverlauf", + "trade_id": "Handels-ID:", + "trade_id_not_found": "Handel ${tradeId} von ${title} nicht gefunden.", + "trade_is_powered_by": "Dieser Handel wird angeboten von ${provider}", + "trade_not_created": "Handel nicht erstellt", + "trade_not_found": "Handel nicht gefunden.", + "trade_state_btc_sent": "Btc gesendet", + "trade_state_complete": "Abgeschlossen", + "trade_state_confirming": "Bestätigung", + "trade_state_created": "Erstellt", + "trade_state_finished": "Fertig", + "trade_state_paid": "Bezahlt", + "trade_state_paid_unconfirmed": "Unbestätigt bezahlt", + "trade_state_pending": "Steht aus", + "trade_state_timeout": "Timeout", + "trade_state_to_be_created": "Noch nicht erstellt", + "trade_state_traded": "Gehandelt", + "trade_state_trading": "Handel", + "trade_state_underpaid": "Unterbezahlt", + "trade_state_unpaid": "Unbezahlt", + "trades": "Börsen", + "transaction_details_amount": "Betrag", + "transaction_details_copied": "${title} in die Zwischenablage kopiert", + "transaction_details_date": "Datum", + "transaction_details_fee": "Gebühr", + "transaction_details_height": "Höhe", + "transaction_details_recipient_address": "Empfängeradressen", "transaction_details_source_address": "Quelladresse", - "pause_wallet_creation": "Die Möglichkeit, Haven Wallet zu erstellen, ist derzeit pausiert.", - "contractName": "Vertragsname", - "contractSymbol": "Vertragssymbol", - "description": "Beschreibung", - "camera_consent": "Mit Ihrer Kamera wird bis zum ${provider} ein Bild zur Identifizierung aufgenommen. Weitere Informationen finden Sie in deren Datenschutzbestimmungen.", - "no_relays": "Keine Relais", - "choose_relay": "Bitte wählen Sie ein zu verwendendes Relais aus", - "no_relays_message": "Wir haben einen Nostr NIP-05-Eintrag für diesen Benutzer gefunden, der jedoch keine Relays enthält. Bitte weisen Sie den Empfänger an, Relays zu seinem Nostr-Datensatz hinzuzufügen.", - "no_relay_on_domain": "Es gibt kein Relay für die Domäne des Benutzers oder das Relay ist nicht verfügbar. Bitte wählen Sie ein zu verwendendes Relais aus." -} + "transaction_details_title": "Transaktionsdetails", + "transaction_details_transaction_id": "Transaktions-ID", + "transaction_key": "Transaktionsschlüssel", + "transaction_priority_fast": "Schnell", + "transaction_priority_fastest": "Am schnellsten", + "transaction_priority_medium": "Mittel", + "transaction_priority_regular": "Normal", + "transaction_priority_slow": "Langsam", + "transaction_sent": "Transaktion gesendet!", + "transaction_sent_notice": "Wenn der Bildschirm nach 1 Minute nicht weitergeht, überprüfen Sie einen Block-Explorer und Ihre E-Mail.", + "transactions": "Transaktionen", + "transactions_by_date": "Transaktionen nach Datum", + "trusted": "Vertrauenswürdige", + "unavailable_balance": "Nicht verfügbares Guthaben", + "unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.", + "unconfirmed": "Unbestätigter Saldo", + "und": "und", + "understand": "Ich verstehe", + "unmatched_currencies": "Die Währung Ihres aktuellen Wallets stimmt nicht mit der des gescannten QR überein", + "unspent_change": "Wechselgeld", + "unspent_coins_details_title": "Details zu nicht ausgegebenen Coins", + "unspent_coins_title": "Nicht ausgegebene Coins", + "unsupported_asset": "Wir unterstützen diese Aktion für dieses Asset nicht. Bitte erstellen Sie eine Wallet eines unterstützten Asset-Typs oder wechseln Sie zu einer Wallet.", + "upto": "bis zu ${value}", + "use": "Wechsel zu ", + "use_card_info_three": "Verwenden Sie die digitale Karte online oder mit kontaktlosen Zahlungsmethoden.", + "use_card_info_two": "Guthaben werden auf dem Prepaid-Konto in USD umgerechnet, nicht in digitale Währung.", + "use_ssl": "SSL verwenden", + "use_suggested": "Vorgeschlagen verwenden", + "variable_pair_not_supported": "Dieses Variablenpaar wird von den ausgewählten Börsen nicht unterstützt", + "verification": "Verifizierung", + "verify_with_2fa": "Verifizieren Sie mit Cake 2FA", + "version": "Version ${currentVersion}", + "view_all": "Alle anzeigen", + "view_in_block_explorer": "In Block Explorer anzeigen", + "view_key_private": "View Key (geheim)", + "view_key_public": "View Key (öffentlich)", + "view_transaction_on": "Anzeigen der Transaktion auf ", + "waiting_payment_confirmation": "Warte auf Zahlungsbestätigung", + "wallet_keys": "Wallet-Seed/-Schlüssel", + "wallet_list_create_new_wallet": "Neue Wallet erstellen", + "wallet_list_edit_wallet": "Wallet bearbeiten", + "wallet_list_failed_to_load": "Laden der Wallet ${wallet_name} fehlgeschlagen. ${error}", + "wallet_list_failed_to_remove": "Fehler beim Entfernen der Wallet ${wallet_name}. ${error}", + "wallet_list_load_wallet": "Wallet laden", + "wallet_list_loading_wallet": "Wallet ${wallet_name} wird geladen", + "wallet_list_removing_wallet": "Wallet ${wallet_name} wird entfernt", + "wallet_list_restore_wallet": "Wallet wiederherstellen", + "wallet_list_title": "Monero-Wallet", + "wallet_list_wallet_name": "Wallet namen", + "wallet_menu": "Wallet-Menü", + "wallet_name": "Walletname", + "wallet_name_exists": "Wallet mit diesem Namen existiert bereits", + "wallet_restoration_store_incorrect_seed_length": "Falsche Seed-Länge", + "wallet_seed": "Wallet-Seed", + "wallet_seed_legacy": "Legacy Wallet Seed", + "wallet_store_monero_wallet": "Monero-Wallet", + "walletConnect": "WalletConnect", + "wallets": "Wallets", + "warning": "Warnung", + "welcome": "Willkommen bei", + "welcome_to_cakepay": "Willkommen bei Cake Pay!", + "widgets_address": "Adresse", + "widgets_or": "oder", + "widgets_restore_from_blockheight": "Ab Blockhöhe wiederherstellen", + "widgets_restore_from_date": "Ab Datum wiederherstellen", + "widgets_seed": "Seed", + "wouoldLikeToConnect": "möchte mich gerne vernetzen", + "write_down_backup_password": "Bitte notieren Sie sich Ihr Sicherungskennwort, das für den Import Ihrer Sicherungsdateien gebraucht wird.", + "xlm_extra_info": "Bitte vergessen Sie nicht, die Memo-ID anzugeben, während Sie die XLM-Transaktion für den Austausch senden", + "xmr_available_balance": "Verfügbares Guthaben", + "xmr_full_balance": "Gesamtguthaben", + "xmr_hidden": "Versteckt", + "xmr_to_error": "XMR.TO-Fehler", + "xmr_to_error_description": "Ungültiger Betrag. Höchstgrenze 8 Stellen nach dem Dezimalpunkt", + "xrp_extra_info": "Bitte vergessen Sie nicht, das Ziel-Tag anzugeben, während Sie die XRP-Transaktion für den Austausch senden", + "yat": "Yat", + "yat_address": "Yat-Adresse", + "yat_alert_content": "Cake Wallet-Benutzer können jetzt alle ihre Lieblingswährungen mit einem einzigartigen Emoji-basierten Benutzernamen senden und empfangen.", + "yat_alert_title": "Senden und Empfangen von Krypto leichter mit Yat", + "yat_error": "Yat-Fehler", + "yat_error_content": "Keine Adressen mit diesem Yat verknüpft. Versuchen Sie es mit einem anderen Yat", + "yat_popup_content": "Sie können jetzt Krypto in Cake Wallet mit Ihrem Yat senden und empfangen - einem kurzen, Emoji-basierten Benutzernamen. Verwalten Sie Yats jederzeit auf dem Einstellungsbildschirm", + "yat_popup_title": "Ihre Wallet-Adresse kann emojifiziert werden.", + "yesterday": "Gestern", + "you_now_have_debit_card": "Sie haben jetzt eine Debitkarte", + "you_pay": "Sie bezahlen", + "you_will_get": "Konvertieren zu", + "you_will_send": "Konvertieren von", + "yy": "YY", + "zzzz": "Zzzz" +} \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index d54b7baa4..c596cde10 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -1,780 +1,781 @@ { - "welcome": "Welcome to", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Awesome wallet for Monero, Bitcoin, Ethereum, Litecoin, and Haven", - "please_make_selection": "Please make a selection below to create or recover your wallet.", - "create_new": "Create New Wallet", - "restore_wallet": "Restore Wallet", - "monero_com": "Monero.com by Cake Wallet", - "monero_com_wallet_text": "Awesome wallet for Monero", - "haven_app": "Haven by Cake Wallet", - "haven_app_wallet_text": "Awesome wallet for Haven", - "accounts": "Accounts", - "edit": "Edit", + "about_cake_pay": "Cake Pay allows you to easily buy gift cards with virtual assets, spendable instantly at over 150,000 merchants in the United States.", "account": "Account", + "accounts": "Accounts", + "accounts_subaddresses": "Accounts and subaddresses", + "activate": "Activate", + "active": "Active", + "active_cards": "Active cards", + "activeConnectionsPrompt": "Active connections will appear here", "add": "Add", + "add_contact": "Add contact", + "add_custom_node": "Add New Custom Node", + "add_custom_redemption": "Add Custom Redemption", + "add_fund_to_card": "Add prepaid funds to the cards (up to ${value})", + "add_new_node": "Add new node", + "add_new_word": "Add new word", + "add_receiver": "Add another receiver (optional)", + "add_secret_code": "Or, add this secret code to an authenticator app", + "add_tip": "Add Tip", + "add_token_disclaimer_check": "I have confirmed the token contract address and information using a reputable source. Adding malicious or incorrect information can result in a loss of funds.", + "add_token_warning": "Do not edit or add tokens as instructed by scammers.\nAlways confirm token addresses with reputable sources!", + "add_value": "Add value", + "address": "Address", "address_book": "Address Book", - "contact": "Contact", - "please_select": "Please select:", - "cancel": "Cancel", - "ok": "OK", - "contact_name": "Contact Name", - "reset": "Reset", - "save": "Save", + "address_book_menu": "Address book", + "address_detected": "Address detected", + "address_from_domain": "This address is from ${domain} on Unstoppable Domains", + "address_from_yat": "This address is from ${emoji} on Yat", + "address_label": "Address label", "address_remove_contact": "Remove contact", "address_remove_content": "Are you sure that you want to remove selected contact?", - "authenticated": "Authenticated", - "authentication": "Authentication", - "failed_authentication": "Failed authentication. ${state_error}", - "wallet_menu": "Menu", - "Blocks_remaining": "${status} Blocks Remaining", - "please_try_to_connect_to_another_node": "Please try to connect to another node", - "xmr_hidden": "Hidden", - "xmr_available_balance": "Available Balance", - "xmr_full_balance": "Full Balance", - "send": "Send", - "receive": "Receive", - "transactions": "Transactions", - "incoming": "Incoming", - "outgoing": "Outgoing", - "transactions_by_date": "Transactions by date", - "trades": "Trades", - "filter_by": "Filter by", - "today": "Today", - "yesterday": "Yesterday", - "received": "Received", - "sent": "Sent", - "pending": " (pending)", - "rescan": "Rescan", - "reconnect": "Reconnect", - "wallets": "Wallets", - "show_seed": "Show seed", - "show_keys": "Show seed/keys", - "address_book_menu": "Address book", - "reconnection": "Reconnection", - "reconnect_alert_text": "Are you sure you want to reconnect?", - "exchange": "Exchange", - "clear": "Clear", - "refund_address": "Refund address", - "change_exchange_provider": "Change Exchange Provider", - "you_will_send": "Convert from", - "you_will_get": "Convert to", - "amount_is_guaranteed": "The receive amount is guaranteed", - "amount_is_estimate": "The receive amount is an estimate", - "powered_by": "Powered by ${title}", - "error": "Error", - "estimated": "Estimated", - "min_value": "Min: ${value} ${currency}", - "max_value": "Max: ${value} ${currency}", - "change_currency": "Change Currency", - "overwrite_amount": "Overwrite amount", - "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", - "copy_id": "Copy ID", - "exchange_result_write_down_trade_id": "Please copy or write down the trade ID to continue.", - "trade_id": "Trade ID:", - "copied_to_clipboard": "Copied to Clipboard", - "saved_the_trade_id": "I've saved the trade ID", - "fetching": "Fetching", - "id": "ID: ", - "amount": "Amount: ", - "payment_id": "Payment ID: ", - "status": "Status: ", - "offer_expires_in": "Offer expires in: ", - "trade_is_powered_by": "This trade is powered by ${provider}", - "copy_address": "Copy Address", - "exchange_result_confirm": "By pressing confirm, you will be sending ${fetchingLabel} ${from} from your wallet called ${walletName} to the address shown below. Or you can send from your external wallet to the below address/QR code.\n\nPlease press confirm to continue or go back to change the amounts.", - "exchange_result_description": "You must send a minimum of ${fetchingLabel} ${from} to the address shown on the next page. If you send an amount lower than ${fetchingLabel} ${from} it may not get converted and it may not be refunded.", - "exchange_result_write_down_ID": "*Please copy or write down your ID shown above.", - "confirm": "Confirm", - "confirm_sending": "Confirm sending", - "commit_transaction_amount_fee": "Commit transaction\nAmount: ${amount}\nFee: ${fee}", - "sending": "Sending", - "transaction_sent": "Transaction sent!", - "expired": "Expired", - "time": "${minutes}m ${seconds}s", - "send_xmr": "Send XMR", - "exchange_new_template": "New template", - "faq": "FAQ", - "enter_your_pin": "Enter your PIN", - "loading_your_wallet": "Loading your wallet", - "new_wallet": "New Wallet", - "wallet_name": "Wallet name", - "continue_text": "Continue", - "choose_wallet_currency": "Please choose wallet currency:", - "node_new": "New Node", - "node_address": "Node Address", - "node_port": "Node port", - "login": "Login", - "password": "Password", - "nodes": "Nodes", - "node_reset_settings_title": "Reset settings", - "nodes_list_reset_to_default_message": "Are you sure that you want to reset settings to default?", - "change_current_node": "Are you sure to change current node to ${node}?", - "change": "Change", - "remove_node": "Remove node", - "remove_node_message": "Are you sure that you want to remove selected node?", - "remove": "Remove", - "delete": "Delete", - "add_new_node": "Add new node", - "change_current_node_title": "Change current node", - "node_test": "Test", - "node_connection_successful": "Connection was successful", - "node_connection_failed": "Connection was failed", - "new_node_testing": "New node testing", - "use": "Switch to ", - "digit_pin": "-digit PIN", - "share_address": "Share address", - "receive_amount": "Amount", - "subaddresses": "Subaddresses", "addresses": "Addresses", - "scan_qr_code_to_get_address": "Scan the QR code to get the address", - "qr_fullscreen": "Tap to open full screen QR code", - "rename": "Rename", - "choose_account": "Choose account", - "create_new_account": "Create new account", - "accounts_subaddresses": "Accounts and subaddresses", - "restore_restore_wallet": "Restore Wallet", - "restore_title_from_seed_keys": "Restore from seed/keys", - "restore_description_from_seed_keys": "Get back your wallet from seed/keys that you've saved to secure place", - "restore_next": "Next", - "restore_title_from_backup": "Restore from backup", - "restore_description_from_backup": "You can restore the whole Cake Wallet app from your back-up file", - "restore_seed_keys_restore": "Seed/Keys Restore", - "restore_title_from_seed": "Restore from seed", - "restore_description_from_seed": "Restore your wallet from either the 25 word or 13 word combination code", - "restore_title_from_keys": "Restore from keys", - "restore_description_from_keys": "Restore your wallet from generated keystrokes saved from your private keys", - "restore_wallet_name": "Wallet name", - "restore_address": "Address", - "restore_view_key_private": "View key (private)", - "restore_spend_key_private": "Spend key (private)", - "restore_recover": "Restore", - "restore_wallet_restore_description": "Wallet restore description", - "restore_new_seed": "New seed", - "restore_active_seed": "Active seed", - "restore_bitcoin_description_from_seed": "Restore your wallet from 24 word combination code", - "restore_bitcoin_description_from_keys": "Restore your wallet from generated WIF string from your private keys", - "restore_bitcoin_title_from_keys": "Restore from WIF", - "restore_from_date_or_blockheight": "Please enter a date a few days before you created this wallet. Or if you know the blockheight, please enter it instead", - "seed_reminder": "Please write these down in case you lose or wipe your phone", - "seed_title": "Seed", - "seed_share": "Share seed", - "copy": "Copy", - "seed_language": "Seed language", - "seed_choose": "Choose seed language", - "seed_language_next": "Next", - "seed_language_english": "English", - "seed_language_chinese": "Chinese", - "seed_language_dutch": "Dutch", - "seed_language_german": "German", - "seed_language_japanese": "Japanese", - "seed_language_portuguese": "Portuguese", - "seed_language_russian": "Russian", - "seed_language_spanish": "Spanish", - "seed_language_french": "French", - "seed_language_italian": "Italian", - "send_title": "Send", - "send_your_wallet": "Your wallet", - "send_address": "${cryptoCurrency} address", - "send_payment_id": "Payment ID (optional)", + "advanced_settings": "Advanced Settings", + "aggressive": "Aggressive", + "agree": "Agree", + "agree_and_continue": "Agree & Continue", + "agree_to": "By creating account you agree to the ", "all": "ALL", - "send_error_minimum_value": "Minimum value of amount is 0.01", - "send_error_currency": "Currency can only contain numbers", - "send_estimated_fee": "Estimated fee:", - "send_priority": "Currently the fee is set at ${transactionPriority} priority.\nTransaction priority can be adjusted in the settings", - "send_creating_transaction": "Creating transaction", - "send_templates": "Templates", - "send_new": "New", - "send_amount": "Amount:", - "send_fee": "Fee:", - "send_name": "Name", - "got_it": "Got it", - "send_sending": "Sending...", - "send_success": "Your ${crypto} was successfully sent", - "settings_title": "Settings", - "settings_nodes": "Nodes", - "settings_current_node": "Current node", - "settings_wallets": "Wallets", - "settings_display_balance": "Display balance", - "settings_currency": "Currency", - "settings_fee_priority": "Fee priority", - "settings_save_recipient_address": "Save recipient address", - "settings_personal": "Personal", - "settings_change_pin": "Change PIN", - "settings_change_language": "Change language", - "settings_allow_biometrical_authentication": "Allow biometrical authentication", - "settings_dark_mode": "Dark mode", - "settings_transactions": "Transactions", - "settings_trades": "Trades", - "settings_display_on_dashboard_list": "Display on dashboard list", - "settings_all": "ALL", - "settings_only_trades": "Only trades", - "settings_only_transactions": "Only transactions", - "settings_none": "None", - "settings_support": "Support", - "settings_terms_and_conditions": "Terms and Conditions", - "pin_is_incorrect": "PIN is incorrect", - "setup_pin": "Setup PIN", - "enter_your_pin_again": "Enter your pin again", - "setup_successful": "Your PIN has been set up successfully!", - "wallet_keys": "Wallet seed/keys", - "wallet_seed": "Wallet seed", - "private_key": "Private key", - "public_key": "Public key", - "view_key_private": "View key (private)", - "view_key_public": "View key (public)", - "spend_key_private": "Spend key (private)", - "spend_key_public": "Spend key (public)", - "copied_key_to_clipboard": "Copied ${key} to Clipboard", - "new_subaddress_title": "New address", - "new_subaddress_label_name": "Label name", - "new_subaddress_create": "Create", - "address_label": "Address label", - "subaddress_title": "Subaddress list", - "trade_details_title": "Trade Details", - "trade_details_id": "ID", - "trade_details_state": "Status", - "trade_details_fetching": "Fetching", - "trade_details_provider": "Provider", - "trade_details_created_at": "Created at", - "trade_details_pair": "Pair", - "trade_details_copied": "${title} copied to Clipboard", - "trade_history_title": "Trade history", - "transaction_details_title": "Transaction Details", - "transaction_details_transaction_id": "Transaction ID", - "transaction_details_date": "Date", - "transaction_details_height": "Height", - "transaction_details_amount": "Amount", - "transaction_details_fee": "Fee", - "transaction_details_copied": "${title} copied to Clipboard", - "transaction_details_recipient_address": "Recipient addresses", - "wallet_list_title": "Monero Wallet", - "wallet_list_create_new_wallet": "Create New Wallet", - "wallet_list_edit_wallet": "Edit wallet", - "wallet_list_wallet_name": "Wallet name", - "wallet_list_restore_wallet": "Restore Wallet", - "wallet_list_load_wallet": "Load wallet", - "wallet_list_loading_wallet": "Loading ${wallet_name} wallet", - "wallet_list_failed_to_load": "Failed to load ${wallet_name} wallet. ${error}", - "wallet_list_removing_wallet": "Removing ${wallet_name} wallet", - "wallet_list_failed_to_remove": "Failed to remove ${wallet_name} wallet. ${error}", - "widgets_address": "Address", - "widgets_restore_from_blockheight": "Restore from blockheight", - "widgets_restore_from_date": "Restore from date", - "widgets_or": "or", - "widgets_seed": "Seed", - "router_no_route": "No route defined for ${name}", - "error_text_account_name": "Account name can only contain letters, numbers\nand must be between 1 and 15 characters long", - "error_text_contact_name": "Contact name can't contain ` , ' \" symbols\nand must be between 1 and 32 characters long", - "error_text_address": "Wallet address must correspond to the type\nof cryptocurrency", - "error_text_node_address": "Please enter a iPv4 address", - "error_text_node_port": "Node port can only contain numbers between 0 and 65535", - "error_text_node_proxy_address": "Please enter :, for example 127.0.0.1:9050", - "error_text_payment_id": "Payment ID can only contain from 16 to 64 chars in hex", - "error_text_xmr": "XMR value can't exceed available balance.\nThe number of fraction digits must be less or equal to 12", - "error_text_fiat": "Value of amount can't exceed available balance.\nThe number of fraction digits must be less or equal to 2", - "error_text_subaddress_name": "Subaddress name can't contain ` , ' \" symbols\nand must be between 1 and 20 characters long", - "error_text_amount": "Amount can only contain numbers", - "error_text_wallet_name": "Wallet name can only contain letters, numbers, _ - symbols \nand must be between 1 and 33 characters long", - "error_text_keys": "Wallet keys can only contain 64 chars in hex", - "error_text_crypto_currency": "The number of fraction digits\nmust be less or equal to 12", - "error_text_minimal_limit": "Trade for ${provider} is not created. Amount is less then minimal: ${min} ${currency}", - "error_text_maximum_limit": "Trade for ${provider} is not created. Amount is more then maximum: ${max} ${currency}", - "error_text_limits_loading_failed": "Trade for ${provider} is not created. Limits loading failed", - "error_text_template": "Template name and address can't contain ` , ' \" symbols\nand must be between 1 and 106 characters long", + "all_trades": "All trades", + "all_transactions": "All transactions", + "alphabetical": "Alphabetical", + "already_have_account": "Already have an account?", + "always": "Always", + "amount": "Amount: ", + "amount_is_estimate": "The receive amount is an estimate", + "amount_is_guaranteed": "The receive amount is guaranteed", + "and": "and", + "anonpay_description": "Generate ${type}. The recipient can ${method} with any supported cryptocurrency, and you will receive funds in this wallet.", + "apk_update": "APK update", + "approve": "Approve", + "arrive_in_this_address": "${currency} ${tag}will arrive in this address", + "ascending": "Ascending", + "ask_each_time": "Ask each time", "auth_store_ban_timeout": "ban_timeout", "auth_store_banned_for": "Banned for ", "auth_store_banned_minutes": " minutes", "auth_store_incorrect_password": "Wrong PIN", - "wallet_store_monero_wallet": "Monero Wallet", - "wallet_restoration_store_incorrect_seed_length": "Incorrect seed length", - "full_balance": "Full Balance", - "available_balance": "Available Balance", - "hidden_balance": "Hidden Balance", - "sync_status_syncronizing": "SYNCHRONIZING", - "sync_status_syncronized": "SYNCHRONIZED", - "sync_status_not_connected": "NOT CONNECTED", - "sync_status_starting_sync": "STARTING SYNC", - "sync_status_failed_connect": "DISCONNECTED", - "sync_status_connecting": "CONNECTING", - "sync_status_connected": "CONNECTED", - "sync_status_attempting_sync": "ATTEMPTING SYNC", - "transaction_priority_slow": "Slow", - "transaction_priority_regular": "Regular", - "transaction_priority_medium": "Medium", - "transaction_priority_fast": "Fast", - "transaction_priority_fastest": "Fastest", - "trade_for_not_created": "Trade for ${title} is not created.", - "trade_not_created": "Trade not created", - "trade_id_not_found": "Trade ${tradeId} of ${title} not found.", - "trade_not_found": "Trade not found.", - "trade_state_pending": "Pending", - "trade_state_confirming": "Confirming", - "trade_state_trading": "Trading", - "trade_state_traded": "Traded", - "trade_state_complete": "Complete", - "trade_state_to_be_created": "To be created", - "trade_state_unpaid": "Unpaid", - "trade_state_underpaid": "Underpaid", - "trade_state_paid_unconfirmed": "Paid unconfirmed", - "trade_state_paid": "Paid", - "trade_state_btc_sent": "Btc sent", - "trade_state_timeout": "Timeout", - "trade_state_created": "Created", - "trade_state_finished": "Finished", - "change_language": "Change language", - "change_language_to": "Change language to ${language}?", - "paste": "Paste", - "restore_from_seed_placeholder": "Please enter or paste your seed here", - "add_new_word": "Add new word", - "incorrect_seed": "The text entered is not valid.", - "biometric_auth_reason": "Scan your fingerprint to authenticate", - "version": "Version ${currentVersion}", - "extracted_address_content": "You will be sending funds to\n${recipient_name}", - "card_address": "Address:", - "buy": "Buy", - "sell": "Sell", - "placeholder_transactions": "Your transactions will be displayed here", - "placeholder_contacts": "Your contacts will be displayed here", - "template": "Template", - "confirm_delete_template": "This action will delete this template. Do you wish to continue?", - "confirm_delete_wallet": "This action will delete this wallet. Do you wish to continue?", - "change_wallet_alert_title": "Change current wallet", - "change_wallet_alert_content": "Do you want to change current wallet to ${wallet_name}?", - "creating_new_wallet": "Creating new wallet", - "creating_new_wallet_error": "Error: ${description}", - "seed_alert_title": "Attention", - "seed_alert_content": "The seed is the only way to recover your wallet. Have you written it down?", - "seed_alert_back": "Go back", - "seed_alert_yes": "Yes, I have", - "exchange_sync_alert_content": "Please wait until your wallet is synchronized", - "pre_seed_title": "IMPORTANT", - "pre_seed_description": "On the next page you will see a series of ${words} words. This is your unique and private seed and it is the ONLY way to recover your wallet in case of loss or malfunction. It is YOUR responsibility to write it down and store it in a safe place outside of the Cake Wallet app.", - "pre_seed_button_text": "I understand. Show me my seed", - "xmr_to_error": "XMR.TO error", - "xmr_to_error_description": "Invalid amount. Maximum limit 8 digits after the decimal point", - "provider_error": "${provider} error", - "use_ssl": "Use SSL", - "trusted": "Trusted", - "color_theme": "Color theme", - "light_theme": "Light", - "bright_theme": "Bright", - "dark_theme": "Dark", - "enter_your_note": "Enter your note…", - "note_optional": "Note (optional)", - "note_tap_to_change": "Note (tap to change)", - "view_in_block_explorer": "View in Block Explorer", - "view_transaction_on": "View Transaction on ", - "transaction_key": "Transaction Key", - "confirmations": "Confirmations", - "recipient_address": "Recipient address", - "extra_id": "Extra ID:", - "destination_tag": "Destination tag:", - "memo": "Memo:", - "backup": "Backup", - "change_password": "Change password", - "backup_password": "Backup password", - "write_down_backup_password": "Please write down your backup password, which is used for the import of your backup files.", - "export_backup": "Export backup", - "save_backup_password": "Please make sure that you have saved your backup password. You will not be able to import your backup files without it.", - "backup_file": "Backup file", - "edit_backup_password": "Edit Backup Password", - "save_backup_password_alert": "Save backup password", - "change_backup_password_alert": "Your previous backup files will be not available to import with new backup password. New backup password will be used only for new backup files. Are you sure that you want to change backup password?", - "enter_backup_password": "Enter backup password here", - "select_backup_file": "Select backup file", - "import": "Import", - "please_select_backup_file": "Please select backup file and enter backup password.", - "fixed_rate": "Fixed rate", - "fixed_rate_alert": "You will be able to enter receive amount when fixed rate mode is checked. Do you want to switch to fixed rate mode?", - "xlm_extra_info": "Please don’t forget to specify the Memo ID while sending the XLM transaction for the exchange", - "xrp_extra_info": "Please don’t forget to specify the Destination Tag while sending the XRP transaction for the exchange", - "exchange_incorrect_current_wallet_for_xmr": "If you want to exchange XMR from your Cake Wallet Monero balance, please switch to your Monero wallet first.", - "confirmed": "Confirmed Balance", - "unconfirmed": "Unconfirmed Balance", - "displayable": "Displayable", - "submit_request": "submit a request", - "buy_alert_content": "Currently we only support the purchase of Bitcoin, Ethereum, Litecoin, and Monero. Please create or switch to your Bitcoin, Ethereum, Litecoin, or Monero wallet.", - "sell_alert_content": "We currently only support the sale of Bitcoin, Ethereum and Litecoin. Please create or switch to your Bitcoin, Ethereum or Litecoin wallet.", - "outdated_electrum_wallet_description": "New Bitcoin wallets created in Cake now have a 24-word seed. It is mandatory that you create a new Bitcoin wallet and transfer all of your funds to the new 24-word wallet, and stop using wallets with a 12-word seed. Please do this immediately to secure your funds.", - "understand": "I understand", - "apk_update": "APK update", - "buy_bitcoin": "Buy Bitcoin", - "buy_with": "Buy with", - "moonpay_alert_text": "Value of the amount must be more or equal to ${minAmount} ${fiatCurrency}", - "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", - "do_not_show_me": "Do not show me this again", - "unspent_coins_title": "Unspent coins", - "unspent_coins_details_title": "Unspent coins details", - "freeze": "Freeze", - "frozen": "Frozen", - "coin_control": "Coin control (optional)", - "address_detected": "Address detected", - "address_from_domain": "This address is from ${domain} on Unstoppable Domains", - "add_receiver": "Add another receiver (optional)", - "manage_yats": "Manage Yats", - "yat_alert_title": "Send and receive crypto more easily with Yat", - "yat_alert_content": "Cake Wallet users can now send and receive all their favorite currencies with a one-of-a-kind emoji-based username.", - "get_your_yat": "Get your Yat", - "connect_an_existing_yat": "Connect an existing Yat", - "connect_yats": "Connect Yats", - "yat_address": "Yat Address", - "yat": "Yat", - "address_from_yat": "This address is from ${emoji} on Yat", - "yat_error": "Yat error", - "yat_error_content": "No addresses linked with this Yat. Try another Yat", - "choose_address": "\n\nPlease choose the address:", - "yat_popup_title": "Your wallet address can be emojified.", - "yat_popup_content": "You can now send and receive crypto in Cake Wallet with your Yat - a short, emoji-based username. Manage Yats at any time on the settings screen", - "second_intro_title": "One emoji address to rule them all", - "second_intro_content": "Your Yat is a single unique emoji address that replaces all of your long hexadecimal addresses for all of your currencies.", - "third_intro_title": "Yat plays nicely with others", - "third_intro_content": "Yats live outside of Cake Wallet, too. Any wallet address on earth can be replaced with a Yat!", - "learn_more": "Learn More", - "search": "Search", - "search_language": "Search language", - "search_currency": "Search currency", - "new_template": "New Template", - "electrum_address_disclaimer": "We generate new addresses each time you use one, but previous addresses continue to work", - "wallet_name_exists": "A wallet with that name already exists. Please choose a different name or rename the other wallet first.", - "market_place": "Marketplace", - "cake_pay_title": "Cake Pay Gift Cards", - "cake_pay_subtitle": "Buy discounted gift cards (USA only)", - "cake_pay_web_cards_title": "Cake Pay Web Cards", - "cake_pay_web_cards_subtitle": "Buy worldwide prepaid cards and gift cards", - "about_cake_pay": "Cake Pay allows you to easily buy gift cards with virtual assets, spendable instantly at over 150,000 merchants in the United States.", - "cake_pay_account_note": "Sign up with just an email address to see and purchase cards. Some are even available at a discount!", - "already_have_account": "Already have an account?", - "create_account": "Create Account", - "privacy_policy": "Privacy Policy", - "welcome_to_cakepay": "Welcome to Cake Pay!", - "sign_up": "Sign Up", - "forgot_password": "Forgot Password", - "reset_password": "Reset Password", - "gift_cards": "Gift Cards", - "setup_your_debit_card": "Set up your debit card", - "no_id_required": "No ID required. Top up and spend anywhere", - "how_to_use_card": "How to use this card", - "purchase_gift_card": "Purchase Gift Card", - "verification": "Verification", - "fill_code": "Please fill in the verification code provided to your email", - "didnt_get_code": "Didn't get code?", - "resend_code": "Please resend it", - "debit_card": "Debit Card", - "cakepay_prepaid_card": "CakePay Prepaid Debit Card", - "no_id_needed": "No ID needed!", - "frequently_asked_questions": "Frequently asked questions", - "debit_card_terms": "The storage and usage of your payment card number (and credentials corresponding to your payment card number) in this digital wallet are subject to the Terms and Conditions of the applicable cardholder agreement with the payment card issuer, as in effect from time to time.", - "please_reference_document": "Please reference the documents below for more information.", - "cardholder_agreement": "Cardholder Agreement", - "e_sign_consent": "E-Sign Consent", - "agree_and_continue": "Agree & Continue", - "email_address": "Email Address", - "agree_to": "By creating account you agree to the ", - "and": "and", - "enter_code": "Enter code", - "congratulations": "Congratulations!", - "you_now_have_debit_card": "You now have a debit card", - "min_amount": "Min: ${value}", - "max_amount": "Max: ${value}", - "enter_amount": "Enter Amount", - "billing_address_info": "If asked for a billing address, provide your shipping address", - "order_physical_card": "Order Physical Card", - "add_value": "Add value", - "activate": "Activate", - "get_a": "Get a ", - "digital_and_physical_card": " digital and physical prepaid debit card", - "get_card_note": " that you can reload with digital currencies. No additional information needed!", - "signup_for_card_accept_terms": "Sign up for the card and accept the terms.", - "add_fund_to_card": "Add prepaid funds to the cards (up to ${value})", - "use_card_info_two": "Funds are converted to USD when they're held in the prepaid account, not in digital currencies.", - "use_card_info_three": "Use the digital card online or with contactless payment methods.", - "optionally_order_card": "Optionally order a physical card.", - "hide_details": "Hide Details", - "show_details": "Show Details", - "upto": "up to ${value}", - "discount": "Save ${value}%", - "gift_card_amount": "Gift Card Amount", - "bill_amount": "Bill Amount", - "you_pay": "You Pay", - "tip": "Tip:", - "custom": "Custom", - "by_cake_pay": "by Cake Pay", - "expires": "Expires", - "mm": "MM", - "yy": "YY", - "online": "Online", - "offline": "Offline", - "gift_card_number": "Gift card number", - "pin_number": "PIN number", - "total_saving": "Total Savings", - "last_30_days": "Last 30 days", - "avg_savings": "Avg. Savings", - "view_all": "View all", - "active_cards": "Active cards", - "delete_account": "Delete Account", - "cards": "Cards", - "active": "Active", - "redeemed": "Redeemed", - "gift_card_balance_note": "Gift cards with a balance remaining will appear here", - "gift_card_redeemed_note": "Gift cards you’ve redeemed will appear here", - "logout": "Logout", - "add_tip": "Add Tip", - "percentageOf": "of ${amount}", - "is_percentage": "is", - "search_category": "Search category", - "mark_as_redeemed": "Mark As Redeemed", - "more_options": "More Options", - "awaiting_payment_confirmation": "Awaiting Payment Confirmation", - "transaction_sent_notice": "If the screen doesn’t proceed after 1 minute, check a block explorer and your email.", - "agree": "Agree", - "in_store": "In Store", - "generating_gift_card": "Generating Gift Card", - "payment_was_received": "Your payment was received.", - "proceed_after_one_minute": "If the screen doesn’t proceed after 1 minute, check your email.", - "order_id": "Order ID", - "gift_card_is_generated": "Gift Card is generated", - "open_gift_card": "Open Gift Card", - "contact_support": "Contact Support", - "gift_cards_unavailable": "Gift cards are available for purchase only with Monero, Bitcoin, and Litecoin at this time", - "background_sync_mode": "Background sync mode", - "sync_all_wallets": "Sync all wallets", - "introducing_cake_pay": "Introducing Cake Pay!", - "cake_pay_learn_more": "Instantly purchase and redeem gift cards in the app!\nSwipe left to right to learn more.", - "automatic": "Automatic", - "fixed_pair_not_supported": "This fixed pair is not supported with the selected exchanges", - "variable_pair_not_supported": "This variable pair is not supported with the selected exchanges", - "none_of_selected_providers_can_exchange": "None of the selected providers can make this exchange", - "choose_one": "Choose one", - "choose_from_available_options": "Choose from the available options:", - "custom_redeem_amount": "Custom Redeem Amount", - "add_custom_redemption": "Add Custom Redemption", - "remaining": "remaining", - "delete_wallet": "Delete wallet", - "delete_wallet_confirm_message": "Are you sure that you want to delete ${wallet_name} wallet?", - "low_fee": "Low fee", - "low_fee_alert": "You currently are using a low network fee priority. This could cause long waits, different rates, or canceled trades. We recommend setting a higher fee for a better experience.", - "ignor": "Ignore", - "use_suggested": "Use Suggested", - "do_not_share_warning_text": "Do not share these with anyone else, including support.\n\nYour funds can and will be stolen!", - "help": "help", - "all_transactions": "All transactions", - "all_trades": "All trades", - "connection_sync": "Connection and sync", - "security_and_backup": "Security and backup", - "create_backup": "Create backup", - "privacy_settings": "Privacy settings", - "privacy": "Privacy", - "display_settings": "Display settings", - "other_settings": "Other settings", + "authenticated": "Authenticated", + "authentication": "Authentication", "auto_generate_subaddresses": "Auto generate subaddresses", - "require_pin_after": "Require PIN after", - "always": "Always", - "minutes_to_pin_code": "${minute} minutes", - "disable_exchange": "Disable exchange", - "advanced_settings": "Advanced Settings", - "settings_can_be_changed_later": "These settings can be changed later in the app settings", - "add_custom_node": "Add New Custom Node", - "disable_fiat": "Disable fiat", - "fiat_api": "Fiat API", - "disabled": "Disabled", - "enabled": "Enabled", - "tor_only": "Tor only", - "unmatched_currencies": "Your current wallet's currency does not match that of the scanned QR", - "orbot_running_alert": "Please make sure Orbot is running prior to connecting to this node.", - "contact_list_contacts": "Contacts", - "contact_list_wallets": "My Wallets", - "bitcoin_payments_require_1_confirmation": "Bitcoin payments require 1 confirmation, which can take 20 minutes or longer. Thanks for your patience! You will be emailed when the payment is confirmed.", - "send_to_this_address": "Send ${currency} ${tag}to this address", - "arrive_in_this_address": "${currency} ${tag}will arrive in this address", - "do_not_send": "Don't send", - "error_dialog_content": "Oops, we got some error.\n\nPlease send the crash report to our support team to make the application better.", - "scan_qr_code": "Scan QR code", - "cold_or_recover_wallet": "Add a cold wallet or recover a paper wallet", - "please_wait": "Please wait", - "sweeping_wallet": "Sweeping wallet", - "sweeping_wallet_alert": "This shouldn’t take long. DO NOT LEAVE THIS SCREEN OR THE SWEPT FUNDS MAY BE LOST.", - "invoice_details": "Invoice details", - "donation_link_details": "Donation link details", - "anonpay_description": "Generate ${type}. The recipient can ${method} with any supported cryptocurrency, and you will receive funds in this wallet.", - "create_invoice": "Create invoice", - "create_donation_link": "Create donation link", - "optional_email_hint": "Optional payee notification email", - "optional_description": "Optional description", - "optional_name": "Optional recipient name", - "clearnet_link": "Clearnet link", - "onion_link": "Onion link", - "decimal_places_error": "Too many decimal places", - "edit_node": "Edit Node", - "settings": "Settings", - "sell_monero_com_alert_content": "Selling Monero is not supported yet", - "error_text_input_below_minimum_limit": "Amount is less than the minimum", - "error_text_input_above_maximum_limit": "Amount is more than the maximum", - "show_market_place": "Show Marketplace", - "prevent_screenshots": "Prevent screenshots and screen recording", - "profile": "Profile", - "close": "Close", - "modify_2fa": "Modify Cake 2FA", - "disable_cake_2fa": "Disable Cake 2FA", - "question_to_disable_2fa": "Are you sure that you want to disable Cake 2FA? A 2FA code will no longer be needed to access the wallet and certain functions.", - "disable": "Disable", - "setup_2fa": "Setup Cake 2FA", - "verify_with_2fa": "Verify with Cake 2FA", - "totp_code": "TOTP Code", - "please_fill_totp": "Please fill in the 8-digit code present on your other device", - "totp_2fa_success": "Success! Cake 2FA enabled for this wallet. Remember to save your mnemonic seed in case you lose wallet access.", - "totp_verification_success": "Verification Successful!", - "totp_2fa_failure": "Incorrect code. Please try a different code or generate a new secret key. Use a compatible 2FA app that supports 8-digit codes and SHA512.", - "enter_totp_code": "Please enter the TOTP Code.", - "scan_qr_on_device": "Scan this QR code on another device", - "add_secret_code": "Or, add this secret code to an authenticator app", - "totp_secret_code": "TOTP Secret Code", - "setup_2fa_text": "Cake 2FA works using TOTP as the second authentication factor.\n\nCake 2FA's TOTP requires SHA-512 and 8 digit support; this provides increased security. More information and supported apps can be found in the guide.", - "setup_warning_2fa_text": "Cake 2FA is a second authentication for certain actions in the wallet. It is NOT as secure as cold storage.\n\nIf you lose access to your 2FA app or TOTP keys, you WILL lose access to this wallet. You will need to restore your wallet from the mnemonic seed.\n\nCake support will be unable to assist you if you lose access to your 2FA or mnemonic seeds.\nBefore using Cake 2FA, we recommend reading through the guide.", - "setup_totp_recommended": "Setup TOTP", - "disable_buy": "Disable buy action", - "disable_sell": "Disable sell action", - "cake_2fa_preset": "Cake 2FA Preset", - "monero_dark_theme": "Monero Dark Theme", + "automatic": "Automatic", + "available_balance": "Available Balance", + "available_balance_description": "The “Available Balance” or “Confirmed Balance” are funds that can be spent immediately. If funds appear in the lower balance but not the top balance, then you must wait a few minutes for the incoming funds to get more network confirmations. After they get more confirmations, they will be spendable.", + "avg_savings": "Avg. Savings", + "awaitDAppProcessing": "Kindly wait for the dApp to finish processing.", + "awaiting_payment_confirmation": "Awaiting Payment Confirmation", + "background_sync_mode": "Background sync mode", + "backup": "Backup", + "backup_file": "Backup file", + "backup_password": "Backup password", + "balance_page": "Balance Page", + "bill_amount": "Bill Amount", + "billing_address_info": "If asked for a billing address, provide your shipping address", + "biometric_auth_reason": "Scan your fingerprint to authenticate", "bitcoin_dark_theme": "Bitcoin Dark Theme", "bitcoin_light_theme": "Bitcoin Light Theme", - "high_contrast_theme": "High Contrast Theme", - "matrix_green_dark_theme": "Matrix Green Dark Theme", - "monero_light_theme": "Monero Light Theme", - "narrow": "Narrow", - "normal": "Normal", - "aggressive": "Aggressive", - "require_for_assessing_wallet": "Require for accessing wallet", - "require_for_sends_to_non_contacts": "Require for sends to non-contacts", - "require_for_sends_to_contacts": "Require for sends to contacts", - "require_for_sends_to_internal_wallets": "Require for sends to internal wallets", - "require_for_exchanges_to_internal_wallets": "Require for exchanges to internal wallets", - "require_for_adding_contacts": "Require for adding contacts", - "require_for_creating_new_wallets": "Require for creating new wallets", - "require_for_all_security_and_backup_settings": "Require for all security and backup settings", - "available_balance_description": "The “Available Balance” or “Confirmed Balance” are funds that can be spent immediately. If funds appear in the lower balance but not the top balance, then you must wait a few minutes for the incoming funds to get more network confirmations. After they get more confirmations, they will be spendable.", - "syncing_wallet_alert_title": "Your wallet is syncing", - "syncing_wallet_alert_content": "Your balance and transaction list may not be complete until it says “SYNCHRONIZED” at the top. Click/tap to learn more.", - "home_screen_settings": "Home screen settings", - "sort_by": "Sort by", - "search_add_token": "Search / Add token", - "edit_token": "Edit token", - "warning": "Warning", - "add_token_warning": "Do not edit or add tokens as instructed by scammers.\nAlways confirm token addresses with reputable sources!", - "add_token_disclaimer_check": "I have confirmed the token contract address and information using a reputable source. Adding malicious or incorrect information can result in a loss of funds.", - "token_contract_address": "Token contract address", - "token_name": "Token name eg: Tether", - "token_symbol": "Token symbol eg: USDT", - "token_decimal": "Token decimal", - "field_required": "This field is required", - "pin_at_top": "Pin ${token} at top", - "invalid_input": "Invalid input", - "fiat_balance": "Fiat Balance", - "gross_balance": "Gross Balance", - "alphabetical": "Alphabetical", - "generate_name": "Generate Name", - "balance_page": "Balance Page", - "share": "Share", - "slidable": "Slidable", - "manage_nodes": "Manage nodes", - "etherscan_history": "Etherscan history", - "template_name": "Template Name", + "bitcoin_payments_require_1_confirmation": "Bitcoin payments require 1 confirmation, which can take 20 minutes or longer. Thanks for your patience! You will be emailed when the payment is confirmed.", + "Blocks_remaining": "${status} Blocks Remaining", + "bright_theme": "Bright", + "buy": "Buy", + "buy_alert_content": "Currently we only support the purchase of Bitcoin, Ethereum, Litecoin, and Monero. Please create or switch to your Bitcoin, Ethereum, Litecoin, or Monero wallet.", + "buy_bitcoin": "Buy Bitcoin", + "buy_provider_unavailable": "Provider currently unavailable.", + "buy_with": "Buy with", + "by_cake_pay": "by Cake Pay", + "cake_2fa_preset": "Cake 2FA Preset", + "cake_pay_account_note": "Sign up with just an email address to see and purchase cards. Some are even available at a discount!", + "cake_pay_learn_more": "Instantly purchase and redeem gift cards in the app!\nSwipe left to right to learn more.", + "cake_pay_subtitle": "Buy discounted gift cards (USA only)", + "cake_pay_title": "Cake Pay Gift Cards", + "cake_pay_web_cards_subtitle": "Buy worldwide prepaid cards and gift cards", + "cake_pay_web_cards_title": "Cake Pay Web Cards", + "cake_wallet": "Cake Wallet", + "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.", + "camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.", + "cancel": "Cancel", + "card_address": "Address:", + "cardholder_agreement": "Cardholder Agreement", + "cards": "Cards", + "chains": "Chains", + "change": "Change", + "change_backup_password_alert": "Your previous backup files will be not available to import with new backup password. New backup password will be used only for new backup files. Are you sure that you want to change backup password?", + "change_currency": "Change Currency", + "change_current_node": "Are you sure to change current node to ${node}?", + "change_current_node_title": "Change current node", + "change_exchange_provider": "Change Exchange Provider", + "change_language": "Change language", + "change_language_to": "Change language to ${language}?", + "change_password": "Change password", "change_rep": "Change Representative", "change_rep_message": "Are you sure that you want to change representatives?", - "unsupported_asset": "We don't support this action for this asset. Please create or switch to a wallet of a supported asset type.", - "manage_pow_nodes": "Manage PoW nodes", - "support_title_live_chat": "Live support", - "support_description_live_chat": "Free and fast! Trained support representatives are available to assist", - "support_title_guides": "Cake Wallet guides", - "support_description_guides": "Documentation and support for common issues", - "support_title_other_links": "Other support links", - "support_description_other_links": "Join our communities or reach us or our partners through other methods", + "change_rep_successful": "Successfully changed representative", + "change_wallet_alert_content": "Do you want to change current wallet to ${wallet_name}?", + "change_wallet_alert_title": "Change current wallet", + "choose_account": "Choose account", + "choose_address": "\n\nPlease choose the address:", "choose_derivation": "Choose Wallet Derivation", - "new_first_wallet_text": "Keep your crypto safe, piece of cake", - "select_destination": "Please select destination for the backup file.", - "save_to_downloads": "Save to Downloads", - "select_buy_provider_notice": "Select a buy provider above. You can skip this screen by setting your default buy provider in app settings.", - "onramper_option_description": "Quickly buy crypto with many payment methods. Available in most countries. Spreads and fees vary.", + "choose_from_available_options": "Choose from the available options:", + "choose_one": "Choose one", + "choose_relay": "Please choose a relay to use", + "choose_wallet_currency": "Please choose wallet currency:", + "clear": "Clear", + "clearnet_link": "Clearnet link", + "close": "Close", + "coin_control": "Coin control (optional)", + "cold_or_recover_wallet": "Add a cold wallet or recover a paper wallet", + "color_theme": "Color theme", + "commit_transaction_amount_fee": "Commit transaction\nAmount: ${amount}\nFee: ${fee}", + "confirm": "Confirm", + "confirm_delete_template": "This action will delete this template. Do you wish to continue?", + "confirm_delete_wallet": "This action will delete this wallet. Do you wish to continue?", + "confirm_sending": "Confirm sending", + "confirmations": "Confirmations", + "confirmed": "Confirmed Balance", + "confirmed_tx": "Confirmed", + "congratulations": "Congratulations!", + "connect_an_existing_yat": "Connect an existing Yat", + "connect_yats": "Connect Yats", + "connection_sync": "Connection and sync", + "connectWalletPrompt": "Connect your wallet with WalletConnect to make transactions", + "contact": "Contact", + "contact_list_contacts": "Contacts", + "contact_list_wallets": "My Wallets", + "contact_name": "Contact Name", + "contact_support": "Contact Support", + "continue_text": "Continue", + "contractName": "Contract Name", + "contractSymbol": "Contract Symbol", + "copied_key_to_clipboard": "Copied ${key} to Clipboard", + "copied_to_clipboard": "Copied to Clipboard", + "copy": "Copy", + "copy_address": "Copy Address", + "copy_id": "Copy ID", + "copyWalletConnectLink": "Copy the WalletConnect link from dApp and paste here", + "create_account": "Create Account", + "create_backup": "Create backup", + "create_donation_link": "Create donation link", + "create_invoice": "Create invoice", + "create_new": "Create New Wallet", + "create_new_account": "Create new account", + "creating_new_wallet": "Creating new wallet", + "creating_new_wallet_error": "Error: ${description}", + "creation_date": "Creation Date", + "custom": "Custom", + "custom_drag": "Custom (Hold and Drag)", + "custom_redeem_amount": "Custom Redeem Amount", + "dark_theme": "Dark", + "debit_card": "Debit Card", + "debit_card_terms": "The storage and usage of your payment card number (and credentials corresponding to your payment card number) in this digital wallet are subject to the Terms and Conditions of the applicable cardholder agreement with the payment card issuer, as in effect from time to time.", + "decimal_places_error": "Too many decimal places", "default_buy_provider": "Default Buy Provider", - "ask_each_time": "Ask each time", - "robinhood_option_description": "Buy and transfer instantly using your debit card, bank account, or Robinhood balance. USA only.", - "buy_provider_unavailable": "Provider currently unavailable.", - "signTransaction": "Sign Transaction", + "default_sell_provider": "Default Sell Provider", + "delete": "Delete", + "delete_account": "Delete Account", + "delete_wallet": "Delete wallet", + "delete_wallet_confirm_message": "Are you sure that you want to delete ${wallet_name} wallet?", + "deleteConnectionConfirmationPrompt": "Are you sure that you want to delete the connection to", + "descending": "Descending", + "description": "Description", + "destination_tag": "Destination tag:", + "dfx_option_description": "Buy crypto with EUR & CHF. Up to 990€ without additional KYC. For retail and corporate customers in Europe", + "didnt_get_code": "Didn't get code?", + "digit_pin": "-digit PIN", + "digital_and_physical_card": " digital and physical prepaid debit card", + "disable": "Disable", + "disable_buy": "Disable buy action", + "disable_cake_2fa": "Disable Cake 2FA", + "disable_exchange": "Disable exchange", + "disable_fiat": "Disable fiat", + "disable_sell": "Disable sell action", + "disabled": "Disabled", + "discount": "Save ${value}%", + "display_settings": "Display settings", + "displayable": "Displayable", + "do_not_have_enough_gas_asset": "You do not have enough ${currency} to make a transaction with the current blockchain network conditions. You need more ${currency} to pay blockchain network fees, even if you are sending a different asset.", + "do_not_send": "Don't send", + "do_not_share_warning_text": "Do not share these with anyone else, including support.\n\nYour funds can and will be stolen!", + "do_not_show_me": "Do not show me this again", + "domain_looks_up": "Domain lookups", + "donation_link_details": "Donation link details", + "e_sign_consent": "E-Sign Consent", + "edit": "Edit", + "edit_backup_password": "Edit Backup Password", + "edit_node": "Edit Node", + "edit_token": "Edit token", + "electrum_address_disclaimer": "We generate new addresses each time you use one, but previous addresses continue to work", + "email_address": "Email Address", + "enabled": "Enabled", + "enter_amount": "Enter Amount", + "enter_backup_password": "Enter backup password here", + "enter_code": "Enter code", + "enter_seed_phrase": "Enter your seed phrase", + "enter_totp_code": "Please enter the TOTP Code.", + "enter_your_note": "Enter your note…", + "enter_your_pin": "Enter your PIN", + "enter_your_pin_again": "Enter your pin again", + "enterTokenID": "Enter the token ID", + "enterWalletConnectURI": "Enter WalletConnect URI", + "error": "Error", + "error_dialog_content": "Oops, we got some error.\n\nPlease send the crash report to our support team to make the application better.", + "error_text_account_name": "Account name can only contain letters, numbers\nand must be between 1 and 15 characters long", + "error_text_address": "Wallet address must correspond to the type\nof cryptocurrency", + "error_text_amount": "Amount can only contain numbers", + "error_text_contact_name": "Contact name can't contain ` , ' \" symbols\nand must be between 1 and 32 characters long", + "error_text_crypto_currency": "The number of fraction digits\nmust be less or equal to 12", + "error_text_fiat": "Value of amount can't exceed available balance.\nThe number of fraction digits must be less or equal to 2", + "error_text_input_above_maximum_limit": "Amount is more than the maximum", + "error_text_input_below_minimum_limit": "Amount is less than the minimum", + "error_text_keys": "Wallet keys can only contain 64 chars in hex", + "error_text_limits_loading_failed": "Trade for ${provider} is not created. Limits loading failed", + "error_text_maximum_limit": "Trade for ${provider} is not created. Amount is more then maximum: ${max} ${currency}", + "error_text_minimal_limit": "Trade for ${provider} is not created. Amount is less then minimal: ${min} ${currency}", + "error_text_node_address": "Please enter a iPv4 address", + "error_text_node_port": "Node port can only contain numbers between 0 and 65535", + "error_text_node_proxy_address": "Please enter :, for example 127.0.0.1:9050", + "error_text_payment_id": "Payment ID can only contain from 16 to 64 chars in hex", + "error_text_subaddress_name": "Subaddress name can't contain ` , ' \" symbols\nand must be between 1 and 20 characters long", + "error_text_template": "Template name and address can't contain ` , ' \" symbols\nand must be between 1 and 106 characters long", + "error_text_wallet_name": "Wallet name can only contain letters, numbers, _ - symbols \nand must be between 1 and 33 characters long", + "error_text_xmr": "XMR value can't exceed available balance.\nThe number of fraction digits must be less or equal to 12", "errorGettingCredentials": "Failed: Error while getting credentials", "errorSigningTransaction": "An error has occured while signing transaction", - "pairingInvalidEvent": "Pairing Invalid Event", - "chains": "Chains", - "methods": "Methods", - "events": "Events", - "reject": "Reject", - "approve": "Approve", - "expiresOn": "Expires on", - "walletConnect": "WalletConnect", - "nullURIError": "URI is null", - "connectWalletPrompt": "Connect your wallet with WalletConnect to make transactions", - "newConnection": "New Connection", - "activeConnectionsPrompt": "Active connections will appear here", - "deleteConnectionConfirmationPrompt": "Are you sure that you want to delete the connection to", + "estimated": "Estimated", + "etherscan_history": "Etherscan history", "event": "Event", - "successful": "Successful", - "wouoldLikeToConnect": "would like to connect", - "message": "Message", - "do_not_have_enough_gas_asset": "You do not have enough ${currency} to make a transaction with the current blockchain network conditions. You need more ${currency} to pay blockchain network fees, even if you are sending a different asset.", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Kindly wait for the dApp to finish processing.", - "copyWalletConnectLink": "Copy the WalletConnect link from dApp and paste here", - "enterWalletConnectURI": "Enter WalletConnect URI", - "seed_key": "Seed key", - "enter_seed_phrase": "Enter your seed phrase", - "change_rep_successful": "Successfully changed representative", - "add_contact": "Add contact", + "events": "Events", + "exchange": "Exchange", + "exchange_incorrect_current_wallet_for_xmr": "If you want to exchange XMR from your Cake Wallet Monero balance, please switch to your Monero wallet first.", + "exchange_new_template": "New template", "exchange_provider_unsupported": "${providerName} is no longer supported!", - "domain_looks_up": "Domain lookups", - "require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets", - "camera_permission_is_required": "Camera permission is required. \nPlease enable it from app settings.", - "switchToETHWallet": "Please switch to an Ethereum wallet and try again", - "order_by": "Order by", - "creation_date": "Creation Date", + "exchange_result_confirm": "By pressing confirm, you will be sending ${fetchingLabel} ${from} from your wallet called ${walletName} to the address shown below. Or you can send from your external wallet to the below address/QR code.\n\nPlease press confirm to continue or go back to change the amounts.", + "exchange_result_description": "You must send a minimum of ${fetchingLabel} ${from} to the address shown on the next page. If you send an amount lower than ${fetchingLabel} ${from} it may not get converted and it may not be refunded.", + "exchange_result_write_down_ID": "*Please copy or write down your ID shown above.", + "exchange_result_write_down_trade_id": "Please copy or write down the trade ID to continue.", + "exchange_sync_alert_content": "Please wait until your wallet is synchronized", + "expired": "Expired", + "expires": "Expires", + "expiresOn": "Expires on", + "export_backup": "Export backup", + "extra_id": "Extra ID:", + "extracted_address_content": "You will be sending funds to\n${recipient_name}", + "failed_authentication": "Failed authentication. ${state_error}", + "faq": "FAQ", + "fetching": "Fetching", + "fiat_api": "Fiat API", + "fiat_balance": "Fiat Balance", + "field_required": "This field is required", + "fill_code": "Please fill in the verification code provided to your email", + "filter_by": "Filter by", + "first_wallet_text": "Awesome wallet for Monero, Bitcoin, Ethereum, Litecoin, and Haven", + "fixed_pair_not_supported": "This fixed pair is not supported with the selected exchanges", + "fixed_rate": "Fixed rate", + "fixed_rate_alert": "You will be able to enter receive amount when fixed rate mode is checked. Do you want to switch to fixed rate mode?", + "forgot_password": "Forgot Password", + "freeze": "Freeze", + "frequently_asked_questions": "Frequently asked questions", + "frozen": "Frozen", + "full_balance": "Full Balance", + "generate_name": "Generate Name", + "generating_gift_card": "Generating Gift Card", + "get_a": "Get a ", + "get_card_note": " that you can reload with digital currencies. No additional information needed!", + "get_your_yat": "Get your Yat", + "gift_card_amount": "Gift Card Amount", + "gift_card_balance_note": "Gift cards with a balance remaining will appear here", + "gift_card_is_generated": "Gift Card is generated", + "gift_card_number": "Gift card number", + "gift_card_redeemed_note": "Gift cards you’ve redeemed will appear here", + "gift_cards": "Gift Cards", + "gift_cards_unavailable": "Gift cards are available for purchase only with Monero, Bitcoin, and Litecoin at this time", + "got_it": "Got it", + "gross_balance": "Gross Balance", "group_by_type": "Group by type", - "importNFTs": "Import NFTs", - "noNFTYet": "No NFTs yet", - "address": "Address", - "enterTokenID": "Enter the token ID", - "tokenID": "ID", - "name": "Name", - "symbol": "Symbol", - "seed_phrase_length": "Seed phrase length", - "unavailable_balance": "Unavailable balance", - "unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.", - "unspent_change": "Change", - "tor_connection": "Tor connection", + "haven_app": "Haven by Cake Wallet", + "haven_app_wallet_text": "Awesome wallet for Haven", + "help": "help", + "hidden_balance": "Hidden Balance", + "hide_details": "Hide Details", + "high_contrast_theme": "High Contrast Theme", + "home_screen_settings": "Home screen settings", "how_to_use": "How to use", + "how_to_use_card": "How to use this card", + "id": "ID: ", + "ignor": "Ignore", + "import": "Import", + "importNFTs": "Import NFTs", + "in_store": "In Store", + "incoming": "Incoming", + "incorrect_seed": "The text entered is not valid.", + "introducing_cake_pay": "Introducing Cake Pay!", + "invalid_input": "Invalid input", + "invoice_details": "Invoice details", + "is_percentage": "is", + "last_30_days": "Last 30 days", + "learn_more": "Learn More", + "light_theme": "Light", + "loading_your_wallet": "Loading your wallet", + "login": "Login", + "logout": "Logout", + "low_fee": "Low fee", + "low_fee_alert": "You currently are using a low network fee priority. This could cause long waits, different rates, or canceled trades. We recommend setting a higher fee for a better experience.", + "manage_nodes": "Manage nodes", + "manage_pow_nodes": "Manage PoW nodes", + "manage_yats": "Manage Yats", + "mark_as_redeemed": "Mark As Redeemed", + "market_place": "Marketplace", + "matrix_green_dark_theme": "Matrix Green Dark Theme", + "max_amount": "Max: ${value}", + "max_value": "Max: ${value} ${currency}", + "memo": "Memo:", + "message": "Message", + "methods": "Methods", + "min_amount": "Min: ${value}", + "min_value": "Min: ${value} ${currency}", + "minutes_to_pin_code": "${minute} minutes", + "mm": "MM", + "modify_2fa": "Modify Cake 2FA", + "monero_com": "Monero.com by Cake Wallet", + "monero_com_wallet_text": "Awesome wallet for Monero", + "monero_dark_theme": "Monero Dark Theme", + "monero_light_theme": "Monero Light Theme", + "moonpay_alert_text": "Value of the amount must be more or equal to ${minAmount} ${fiatCurrency}", + "more_options": "More Options", + "name": "Name", + "narrow": "Narrow", + "new_first_wallet_text": "Keep your crypto safe, piece of cake", + "new_node_testing": "New node testing", + "new_subaddress_create": "Create", + "new_subaddress_label_name": "Label name", + "new_subaddress_title": "New address", + "new_template": "New Template", + "new_wallet": "New Wallet", + "newConnection": "New Connection", + "no_id_needed": "No ID needed!", + "no_id_required": "No ID required. Top up and spend anywhere", + "no_relay_on_domain": "There isn't a relay for user's domain or the relay is unavailable. Please choose a relay to use.", + "no_relays": "No relays", + "no_relays_message": "We found a Nostr NIP-05 record for this user, but it does not contain any relays. Please instruct the recipient to add relays to their Nostr record.", + "node_address": "Node Address", + "node_connection_failed": "Connection was failed", + "node_connection_successful": "Connection was successful", + "node_new": "New Node", + "node_port": "Node port", + "node_reset_settings_title": "Reset settings", + "node_test": "Test", + "nodes": "Nodes", + "nodes_list_reset_to_default_message": "Are you sure that you want to reset settings to default?", + "none_of_selected_providers_can_exchange": "None of the selected providers can make this exchange", + "noNFTYet": "No NFTs yet", + "normal": "Normal", + "note_optional": "Note (optional)", + "note_tap_to_change": "Note (tap to change)", + "nullURIError": "URI is null", + "offer_expires_in": "Offer expires in: ", + "offline": "Offline", + "ok": "OK", + "onion_link": "Onion link", + "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", + "optional_description": "Optional description", + "optional_email_hint": "Optional payee notification email", + "optional_name": "Optional recipient name", + "optionally_order_card": "Optionally order a physical card.", + "orbot_running_alert": "Please make sure Orbot is running prior to connecting to this node.", + "order_by": "Order by", + "order_id": "Order ID", + "order_physical_card": "Order Physical Card", + "other_settings": "Other settings", + "outdated_electrum_wallet_description": "New Bitcoin wallets created in Cake now have a 24-word seed. It is mandatory that you create a new Bitcoin wallet and transfer all of your funds to the new 24-word wallet, and stop using wallets with a 12-word seed. Please do this immediately to secure your funds.", + "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", + "overwrite_amount": "Overwrite amount", + "pairingInvalidEvent": "Pairing Invalid Event", + "password": "Password", + "paste": "Paste", + "pause_wallet_creation": "Ability to create Haven Wallet is currently paused.", + "payment_id": "Payment ID: ", + "payment_was_received": "Your payment was received.", + "pending": " (pending)", + "percentageOf": "of ${amount}", + "pin_at_top": "Pin ${token} at top", + "pin_is_incorrect": "PIN is incorrect", + "pin_number": "PIN number", + "placeholder_contacts": "Your contacts will be displayed here", + "placeholder_transactions": "Your transactions will be displayed here", + "please_fill_totp": "Please fill in the 8-digit code present on your other device", + "please_make_selection": "Please make a selection below to create or recover your wallet.", + "please_reference_document": "Please reference the documents below for more information.", + "please_select": "Please select:", + "please_select_backup_file": "Please select backup file and enter backup password.", + "please_try_to_connect_to_another_node": "Please try to connect to another node", + "please_wait": "Please wait", + "polygonscan_history": "PolygonScan history", + "powered_by": "Powered by ${title}", + "pre_seed_button_text": "I understand. Show me my seed", + "pre_seed_description": "On the next page you will see a series of ${words} words. This is your unique and private seed and it is the ONLY way to recover your wallet in case of loss or malfunction. It is YOUR responsibility to write it down and store it in a safe place outside of the Cake Wallet app.", + "pre_seed_title": "IMPORTANT", + "prevent_screenshots": "Prevent screenshots and screen recording", + "privacy": "Privacy", + "privacy_policy": "Privacy Policy", + "privacy_settings": "Privacy settings", + "private_key": "Private key", + "proceed_after_one_minute": "If the screen doesn’t proceed after 1 minute, check your email.", + "profile": "Profile", + "provider_error": "${provider} error", + "public_key": "Public key", + "purchase_gift_card": "Purchase Gift Card", + "qr_fullscreen": "Tap to open full screen QR code", + "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", + "question_to_disable_2fa": "Are you sure that you want to disable Cake 2FA? A 2FA code will no longer be needed to access the wallet and certain functions.", + "receivable_balance": "Receivable Balance", + "receive": "Receive", + "receive_amount": "Amount", + "received": "Received", + "recipient_address": "Recipient address", + "reconnect": "Reconnect", + "reconnect_alert_text": "Are you sure you want to reconnect?", + "reconnection": "Reconnection", + "redeemed": "Redeemed", + "refund_address": "Refund address", + "reject": "Reject", + "remaining": "remaining", + "remove": "Remove", + "remove_node": "Remove node", + "remove_node_message": "Are you sure that you want to remove selected node?", + "rename": "Rename", + "require_for_adding_contacts": "Require for adding contacts", + "require_for_all_security_and_backup_settings": "Require for all security and backup settings", + "require_for_assessing_wallet": "Require for accessing wallet", + "require_for_creating_new_wallets": "Require for creating new wallets", + "require_for_exchanges_to_external_wallets": "Require for exchanges to external wallets", + "require_for_exchanges_to_internal_wallets": "Require for exchanges to internal wallets", + "require_for_sends_to_contacts": "Require for sends to contacts", + "require_for_sends_to_internal_wallets": "Require for sends to internal wallets", + "require_for_sends_to_non_contacts": "Require for sends to non-contacts", + "require_pin_after": "Require PIN after", + "rescan": "Rescan", + "resend_code": "Please resend it", + "reset": "Reset", + "reset_password": "Reset Password", + "restore_active_seed": "Active seed", + "restore_address": "Address", + "restore_bitcoin_description_from_keys": "Restore your wallet from generated WIF string from your private keys", + "restore_bitcoin_description_from_seed": "Restore your wallet from 24 word combination code", + "restore_bitcoin_title_from_keys": "Restore from WIF", + "restore_description_from_backup": "You can restore the whole Cake Wallet app from your back-up file", + "restore_description_from_keys": "Restore your wallet from generated keystrokes saved from your private keys", + "restore_description_from_seed": "Restore your wallet from either the 25 word or 13 word combination code", + "restore_description_from_seed_keys": "Get back your wallet from seed/keys that you've saved to secure place", + "restore_from_date_or_blockheight": "Please enter a date a few days before you created this wallet. Or if you know the blockheight, please enter it instead", + "restore_from_seed_placeholder": "Please enter or paste your seed here", + "restore_new_seed": "New seed", + "restore_next": "Next", + "restore_recover": "Restore", + "restore_restore_wallet": "Restore Wallet", + "restore_seed_keys_restore": "Seed/Keys Restore", + "restore_spend_key_private": "Spend key (private)", + "restore_title_from_backup": "Restore from backup", + "restore_title_from_keys": "Restore from keys", + "restore_title_from_seed": "Restore from seed", + "restore_title_from_seed_keys": "Restore from seed/keys", + "restore_view_key_private": "View key (private)", + "restore_wallet": "Restore Wallet", + "restore_wallet_name": "Wallet name", + "restore_wallet_restore_description": "Wallet restore description", + "robinhood_option_description": "Buy and transfer instantly using your debit card, bank account, or Robinhood balance. USA only.", + "router_no_route": "No route defined for ${name}", + "save": "Save", + "save_backup_password": "Please make sure that you have saved your backup password. You will not be able to import your backup files without it.", + "save_backup_password_alert": "Save backup password", + "save_to_downloads": "Save to Downloads", + "saved_the_trade_id": "I've saved the trade ID", + "scan_qr_code": "Scan QR code", + "scan_qr_code_to_get_address": "Scan the QR code to get the address", + "scan_qr_on_device": "Scan this QR code on another device", + "search": "Search", + "search_add_token": "Search / Add token", + "search_category": "Search category", + "search_currency": "Search currency", + "search_language": "Search language", + "second_intro_content": "Your Yat is a single unique emoji address that replaces all of your long hexadecimal addresses for all of your currencies.", + "second_intro_title": "One emoji address to rule them all", + "security_and_backup": "Security and backup", + "seed_alert_back": "Go back", + "seed_alert_content": "The seed is the only way to recover your wallet. Have you written it down?", + "seed_alert_title": "Attention", + "seed_alert_yes": "Yes, I have", + "seed_choose": "Choose seed language", "seed_hex_form": "Wallet seed (hex form)", + "seed_key": "Seed key", + "seed_language": "Seed language", + "seed_language_chinese": "Chinese", + "seed_language_chinese_traditional": "Chinese (Traditional)", + "seed_language_czech": "Czech", + "seed_language_dutch": "Dutch", + "seed_language_english": "English", + "seed_language_french": "French", + "seed_language_german": "German", + "seed_language_italian": "Italian", + "seed_language_japanese": "Japanese", + "seed_language_korean": "Korean", + "seed_language_next": "Next", + "seed_language_portuguese": "Portuguese", + "seed_language_russian": "Russian", + "seed_language_spanish": "Spanish", + "seed_phrase_length": "Seed phrase length", + "seed_reminder": "Please write these down in case you lose or wipe your phone", + "seed_share": "Share seed", + "seed_title": "Seed", "seedtype": "Seedtype", "seedtype_legacy": "Legacy (25 words)", "seedtype_polyseed": "Polyseed (16 words)", - "seed_language_czech": "Czech", - "seed_language_korean": "Korean", - "seed_language_chinese_traditional": "Chinese (Traditional)", - "ascending": "Ascending", - "descending": "Descending", - "dfx_option_description": "Buy crypto with EUR & CHF. Up to 990€ without additional KYC. For retail and corporate customers in Europe", - "polygonscan_history": "PolygonScan history", - "wallet_seed_legacy": "Legacy wallet seed", - "default_sell_provider": "Default Sell Provider", + "select_backup_file": "Select backup file", + "select_buy_provider_notice": "Select a buy provider above. You can skip this screen by setting your default buy provider in app settings.", + "select_destination": "Please select destination for the backup file.", "select_sell_provider_notice": "Select a sell provider above. You can skip this screen by setting your default sell provider in app settings.", - "custom_drag": "Custom (Hold and Drag)", + "sell": "Sell", + "sell_alert_content": "We currently only support the sale of Bitcoin, Ethereum and Litecoin. Please create or switch to your Bitcoin, Ethereum or Litecoin wallet.", + "sell_monero_com_alert_content": "Selling Monero is not supported yet", + "send": "Send", + "send_address": "${cryptoCurrency} address", + "send_amount": "Amount:", + "send_creating_transaction": "Creating transaction", + "send_error_currency": "Currency can only contain numbers", + "send_error_minimum_value": "Minimum value of amount is 0.01", + "send_estimated_fee": "Estimated fee:", + "send_fee": "Fee:", + "send_name": "Name", + "send_new": "New", + "send_payment_id": "Payment ID (optional)", + "send_priority": "Currently the fee is set at ${transactionPriority} priority.\nTransaction priority can be adjusted in the settings", + "send_sending": "Sending...", + "send_success": "Your ${crypto} was successfully sent", + "send_templates": "Templates", + "send_title": "Send", + "send_to_this_address": "Send ${currency} ${tag}to this address", + "send_xmr": "Send XMR", + "send_your_wallet": "Your wallet", + "sending": "Sending", + "sent": "Sent", + "settings": "Settings", + "settings_all": "ALL", + "settings_allow_biometrical_authentication": "Allow biometrical authentication", + "settings_can_be_changed_later": "These settings can be changed later in the app settings", + "settings_change_language": "Change language", + "settings_change_pin": "Change PIN", + "settings_currency": "Currency", + "settings_current_node": "Current node", + "settings_dark_mode": "Dark mode", + "settings_display_balance": "Display balance", + "settings_display_on_dashboard_list": "Display on dashboard list", + "settings_fee_priority": "Fee priority", + "settings_nodes": "Nodes", + "settings_none": "None", + "settings_only_trades": "Only trades", + "settings_only_transactions": "Only transactions", + "settings_personal": "Personal", + "settings_save_recipient_address": "Save recipient address", + "settings_support": "Support", + "settings_terms_and_conditions": "Terms and Conditions", + "settings_title": "Settings", + "settings_trades": "Trades", + "settings_transactions": "Transactions", + "settings_wallets": "Wallets", + "setup_2fa": "Setup Cake 2FA", + "setup_2fa_text": "Cake 2FA works using TOTP as the second authentication factor.\n\nCake 2FA's TOTP requires SHA-512 and 8 digit support; this provides increased security. More information and supported apps can be found in the guide.", + "setup_pin": "Setup PIN", + "setup_successful": "Your PIN has been set up successfully!", + "setup_totp_recommended": "Setup TOTP", + "setup_warning_2fa_text": "Cake 2FA is a second authentication for certain actions in the wallet. It is NOT as secure as cold storage.\n\nIf you lose access to your 2FA app or TOTP keys, you WILL lose access to this wallet. You will need to restore your wallet from the mnemonic seed.\n\nCake support will be unable to assist you if you lose access to your 2FA or mnemonic seeds.\nBefore using Cake 2FA, we recommend reading through the guide.", + "setup_your_debit_card": "Set up your debit card", + "share": "Share", + "share_address": "Share address", + "show_details": "Show Details", + "show_keys": "Show seed/keys", + "show_market_place": "Show Marketplace", + "show_seed": "Show seed", + "sign_up": "Sign Up", + "signTransaction": "Sign Transaction", + "signup_for_card_accept_terms": "Sign up for the card and accept the terms.", + "slidable": "Slidable", + "sort_by": "Sort by", + "spend_key_private": "Spend key (private)", + "spend_key_public": "Spend key (public)", + "status": "Status: ", + "subaddress_title": "Subaddress list", + "subaddresses": "Subaddresses", + "submit_request": "submit a request", + "successful": "Successful", + "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_live_chat": "Live support", + "support_title_other_links": "Other support links", + "sweeping_wallet": "Sweeping wallet", + "sweeping_wallet_alert": "This shouldn’t take long. DO NOT LEAVE THIS SCREEN OR THE SWEPT FUNDS MAY BE LOST.", + "switchToETHWallet": "Please switch to an Ethereum wallet and try again", "switchToEVMCompatibleWallet": "Please switch to an EVM compatible wallet and try again (Ethereum, Polygon)", - "receivable_balance": "Receivable Balance", - "confirmed_tx": "Confirmed", + "symbol": "Symbol", + "sync_all_wallets": "Sync all wallets", + "sync_status_attempting_sync": "ATTEMPTING SYNC", + "sync_status_connected": "CONNECTED", + "sync_status_connecting": "CONNECTING", + "sync_status_failed_connect": "DISCONNECTED", + "sync_status_not_connected": "NOT CONNECTED", + "sync_status_starting_sync": "STARTING SYNC", + "sync_status_syncronized": "SYNCHRONIZED", + "sync_status_syncronizing": "SYNCHRONIZING", + "syncing_wallet_alert_content": "Your balance and transaction list may not be complete until it says “SYNCHRONIZED” at the top. Click/tap to learn more.", + "syncing_wallet_alert_title": "Your wallet is syncing", + "template": "Template", + "template_name": "Template Name", + "third_intro_content": "Yats live outside of Cake Wallet, too. Any wallet address on earth can be replaced with a Yat!", + "third_intro_title": "Yat plays nicely with others", + "time": "${minutes}m ${seconds}s", + "tip": "Tip:", + "today": "Today", + "token_contract_address": "Token contract address", + "token_decimal": "Token decimal", + "token_name": "Token name eg: Tether", + "token_symbol": "Token symbol eg: USDT", + "tokenID": "ID", + "tor_connection": "Tor connection", + "tor_only": "Tor only", + "total_saving": "Total Savings", + "totp_2fa_failure": "Incorrect code. Please try a different code or generate a new secret key. Use a compatible 2FA app that supports 8-digit codes and SHA512.", + "totp_2fa_success": "Success! Cake 2FA enabled for this wallet. Remember to save your mnemonic seed in case you lose wallet access.", + "totp_auth_url": "TOTP AUTH URL", + "totp_code": "TOTP Code", + "totp_secret_code": "TOTP Secret Code", + "totp_verification_success": "Verification Successful!", + "trade_details_copied": "${title} copied to Clipboard", + "trade_details_created_at": "Created at", + "trade_details_fetching": "Fetching", + "trade_details_id": "ID", + "trade_details_pair": "Pair", + "trade_details_provider": "Provider", + "trade_details_state": "Status", + "trade_details_title": "Trade Details", + "trade_for_not_created": "Trade for ${title} is not created.", + "trade_history_title": "Trade history", + "trade_id": "Trade ID:", + "trade_id_not_found": "Trade ${tradeId} of ${title} not found.", + "trade_is_powered_by": "This trade is powered by ${provider}", + "trade_not_created": "Trade not created", + "trade_not_found": "Trade not found.", + "trade_state_btc_sent": "Btc sent", + "trade_state_complete": "Complete", + "trade_state_confirming": "Confirming", + "trade_state_created": "Created", + "trade_state_finished": "Finished", + "trade_state_paid": "Paid", + "trade_state_paid_unconfirmed": "Paid unconfirmed", + "trade_state_pending": "Pending", + "trade_state_timeout": "Timeout", + "trade_state_to_be_created": "To be created", + "trade_state_traded": "Traded", + "trade_state_trading": "Trading", + "trade_state_underpaid": "Underpaid", + "trade_state_unpaid": "Unpaid", + "trades": "Trades", + "transaction_details_amount": "Amount", + "transaction_details_copied": "${title} copied to Clipboard", + "transaction_details_date": "Date", + "transaction_details_fee": "Fee", + "transaction_details_height": "Height", + "transaction_details_recipient_address": "Recipient addresses", "transaction_details_source_address": "Source address", - "pause_wallet_creation": "Ability to create Haven Wallet is currently paused.", - "contractName": "Contract Name", - "contractSymbol": "Contract Symbol", - "description": "Description", - "camera_consent": "Your camera will be used to capture an image for identification purposes by ${provider}. Please check their Privacy Policy for details.", - "no_relays": "No relays", - "choose_relay": "Please choose a relay to use", - "no_relays_message": "We found a Nostr NIP-05 record for this user, but it does not contain any relays. Please instruct the recipient to add relays to their Nostr record.", - "no_relay_on_domain": "There isn't a relay for user's domain or the relay is unavailable. Please choose a relay to use." -} + "transaction_details_title": "Transaction Details", + "transaction_details_transaction_id": "Transaction ID", + "transaction_key": "Transaction Key", + "transaction_priority_fast": "Fast", + "transaction_priority_fastest": "Fastest", + "transaction_priority_medium": "Medium", + "transaction_priority_regular": "Regular", + "transaction_priority_slow": "Slow", + "transaction_sent": "Transaction sent!", + "transaction_sent_notice": "If the screen doesn’t proceed after 1 minute, check a block explorer and your email.", + "transactions": "Transactions", + "transactions_by_date": "Transactions by date", + "trusted": "Trusted", + "unavailable_balance": "Unavailable balance", + "unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.", + "unconfirmed": "Unconfirmed Balance", + "understand": "I understand", + "unmatched_currencies": "Your current wallet's currency does not match that of the scanned QR", + "unspent_change": "Change", + "unspent_coins_details_title": "Unspent coins details", + "unspent_coins_title": "Unspent coins", + "unsupported_asset": "We don't support this action for this asset. Please create or switch to a wallet of a supported asset type.", + "upto": "up to ${value}", + "use": "Switch to ", + "use_card_info_three": "Use the digital card online or with contactless payment methods.", + "use_card_info_two": "Funds are converted to USD when they're held in the prepaid account, not in digital currencies.", + "use_ssl": "Use SSL", + "use_suggested": "Use Suggested", + "variable_pair_not_supported": "This variable pair is not supported with the selected exchanges", + "verification": "Verification", + "verify_with_2fa": "Verify with Cake 2FA", + "version": "Version ${currentVersion}", + "view_all": "View all", + "view_in_block_explorer": "View in Block Explorer", + "view_key_private": "View key (private)", + "view_key_public": "View key (public)", + "view_transaction_on": "View Transaction on ", + "wallet_keys": "Wallet seed/keys", + "wallet_list_create_new_wallet": "Create New Wallet", + "wallet_list_edit_wallet": "Edit wallet", + "wallet_list_failed_to_load": "Failed to load ${wallet_name} wallet. ${error}", + "wallet_list_failed_to_remove": "Failed to remove ${wallet_name} wallet. ${error}", + "wallet_list_load_wallet": "Load wallet", + "wallet_list_loading_wallet": "Loading ${wallet_name} wallet", + "wallet_list_removing_wallet": "Removing ${wallet_name} wallet", + "wallet_list_restore_wallet": "Restore Wallet", + "wallet_list_title": "Monero Wallet", + "wallet_list_wallet_name": "Wallet name", + "wallet_menu": "Menu", + "wallet_name": "Wallet name", + "wallet_name_exists": "A wallet with that name already exists. Please choose a different name or rename the other wallet first.", + "wallet_restoration_store_incorrect_seed_length": "Incorrect seed length", + "wallet_seed": "Wallet seed", + "wallet_seed_legacy": "Legacy wallet seed", + "wallet_store_monero_wallet": "Monero Wallet", + "walletConnect": "WalletConnect", + "wallets": "Wallets", + "warning": "Warning", + "welcome": "Welcome to", + "welcome_to_cakepay": "Welcome to Cake Pay!", + "widgets_address": "Address", + "widgets_or": "or", + "widgets_restore_from_blockheight": "Restore from blockheight", + "widgets_restore_from_date": "Restore from date", + "widgets_seed": "Seed", + "wouoldLikeToConnect": "would like to connect", + "write_down_backup_password": "Please write down your backup password, which is used for the import of your backup files.", + "xlm_extra_info": "Please don’t forget to specify the Memo ID while sending the XLM transaction for the exchange", + "xmr_available_balance": "Available Balance", + "xmr_full_balance": "Full Balance", + "xmr_hidden": "Hidden", + "xmr_to_error": "XMR.TO error", + "xmr_to_error_description": "Invalid amount. Maximum limit 8 digits after the decimal point", + "xrp_extra_info": "Please don’t forget to specify the Destination Tag while sending the XRP transaction for the exchange", + "yat": "Yat", + "yat_address": "Yat Address", + "yat_alert_content": "Cake Wallet users can now send and receive all their favorite currencies with a one-of-a-kind emoji-based username.", + "yat_alert_title": "Send and receive crypto more easily with Yat", + "yat_error": "Yat error", + "yat_error_content": "No addresses linked with this Yat. Try another Yat", + "yat_popup_content": "You can now send and receive crypto in Cake Wallet with your Yat - a short, emoji-based username. Manage Yats at any time on the settings screen", + "yat_popup_title": "Your wallet address can be emojified.", + "yesterday": "Yesterday", + "you_now_have_debit_card": "You now have a debit card", + "you_pay": "You Pay", + "you_will_get": "Convert to", + "you_will_send": "Convert from", + "yy": "YY", + "zzzz": "zzzz" +} \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 5f9a8e53b..4f54e0f87 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -1,779 +1,780 @@ { - "welcome": "Bienvenido", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Impresionante billetera para Monero, Bitcoin, Ethereum, Litecoin, y Haven", - "please_make_selection": "Seleccione a continuación para crear o recuperar su billetera.", - "create_new": "Crear nueva billetera", - "restore_wallet": "Restaurar billetera", - "monero_com": "Monero.com by Cake Wallet", - "monero_com_wallet_text": "Awesome wallet for Monero", - "haven_app": "Haven by Cake Wallet", - "haven_app_wallet_text": "Awesome wallet for Haven", - "accounts": "Cuentas", - "edit": "Editar", + "about_cake_pay": "Cake Pay le permite comprar fácilmente tarjetas de regalo con activos virtuales, gastables instantáneamente en más de 150 000 comerciantes en los Estados Unidos.", "account": "Cuenta", + "accounts": "Cuentas", + "accounts_subaddresses": "Cuentas y subdirecciones", + "activate": "Activar", + "active": "Activo", + "active_cards": "Tarjetas activas", + "activeConnectionsPrompt": "Las conexiones activas aparecerán aquí", "add": "Añadir", + "add_contact": "Agregar contacto", + "add_custom_node": "Agregar nuevo nodo personalizado", + "add_custom_redemption": "Agregar redención personalizada", + "add_fund_to_card": "Agregar fondos prepagos a las tarjetas (hasta ${value})", + "add_new_node": "Agregar nuevo nodo", + "add_new_word": "Agregar palabra nueva", + "add_receiver": "Agregar otro receptor (opcional)", + "add_secret_code": "O agregue este código secreto a una aplicación de autenticación", + "add_tip": "Agregar sugerencia", + "add_token_disclaimer_check": "He confirmado la dirección del contrato del token y la información utilizando una fuente confiable. Agregar información maliciosa o incorrecta puede resultar en una pérdida de fondos.", + "add_token_warning": "No edite ni agregue tokens según las instrucciones de los estafadores.\n¡Confirme siempre las direcciones de los tokens con fuentes acreditadas!", + "add_value": "Añadir valor", + "address": "DIRECCIÓN", "address_book": "Libreta de direcciones", - "contact": "Contacto", - "please_select": "Por favor seleccione:", - "cancel": "Cancelar", - "ok": "OK", - "contact_name": "Nombre de contacto", - "reset": "Reiniciar", - "save": "Salvar", + "address_book_menu": "Libreta de direcciones", + "address_detected": "Dirección detectada", + "address_from_domain": "Esta dirección es de ${domain} en Unstoppable Domains", + "address_from_yat": "Esta dirección es de ${emoji} en Yat", + "address_label": "Address label", "address_remove_contact": "Remover contacto", "address_remove_content": "¿Estás seguro de que quieres eliminar el contacto seleccionado?", - "authenticated": "Autenticados", - "authentication": "Autenticación", - "failed_authentication": "Autenticación fallida. ${state_error}", - "wallet_menu": "Menú de billetera", - "Blocks_remaining": "${status} Bloques restantes", - "please_try_to_connect_to_another_node": "Intenta conectarte a otro nodo", - "xmr_hidden": "Oculto", - "xmr_available_balance": "Saldo disponible", - "xmr_full_balance": "Balance total", - "send": "Enviar", - "receive": "Recibir", - "transactions": "Actas", - "incoming": "Entrante", - "outgoing": "Saliente", - "transactions_by_date": "Transacciones por fecha", - "trades": "Cambios", - "filter_by": "Filtrado por", - "today": "Hoy", - "yesterday": "Ayer", - "received": "Recibido", - "sent": "Expedido", - "pending": " (pendiente)", - "rescan": "Reescanear", - "reconnect": "Volver a conectar", - "wallets": "Carteras", - "show_seed": "Mostrar semilla", - "show_keys": "Mostrar semilla/claves", - "address_book_menu": "Libreta de direcciones", - "reconnection": "Reconexión", - "reconnect_alert_text": "¿Estás seguro de reconectar?", - "exchange": "Intercambiar", - "clear": "Claro", - "refund_address": "Dirección de reembolso", - "change_exchange_provider": "Cambiar proveedor de intercambio", - "you_will_send": "Convertir de", - "you_will_get": "Convertir a", - "amount_is_guaranteed": "La cantidad recibida está garantizada", - "amount_is_estimate": "El monto recibido es un estimado", - "powered_by": "Energizado por ${title}", - "error": "Error", - "estimated": "Estimado", - "min_value": "Min: ${value} ${currency}", - "max_value": "Max: ${value} ${currency}", - "change_currency": "Cambiar moneda", - "overwrite_amount": "Overwrite amount", - "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", - "copy_id": "Copiar ID", - "exchange_result_write_down_trade_id": "Por favor, copia o escribe el ID.", - "trade_id": "Comercial ID:", - "copied_to_clipboard": "Copiado al portapapeles", - "saved_the_trade_id": "He salvado comercial ID", - "fetching": "Cargando", - "id": "ID: ", - "amount": "Cantidad: ", - "payment_id": "ID de pago: ", - "status": "Estado: ", - "offer_expires_in": "Oferta expira en: ", - "trade_is_powered_by": "Este comercio es impulsado por ${provider}", - "copy_address": "Copiar dirección ", - "exchange_result_confirm": "Al presionar confirmar, enviará ${fetchingLabel} ${from} desde su billetera llamada ${walletName} a la dirección que se muestra a continuación. O puede enviar desde su billetera externa a la siguiente dirección / código QR anterior.\n\nPresione confirmar para continuar o regrese para cambiar los montos.", - "exchange_result_description": "Debe enviar un mínimo de ${fetchingLabel} ${from} a la dirección que se muestra en la página siguiente. Si envía una cantidad inferior a ${fetchingLabel} ${from}, es posible que no se convierta y no se reembolse.", - "exchange_result_write_down_ID": "*Copie o escriba su identificación que se muestra arriba.", - "confirm": "Confirmar", - "confirm_sending": "Confirmar envío", - "commit_transaction_amount_fee": "Confirmar transacción\nCantidad: ${amount}\nCuota: ${fee}", - "sending": "Enviando", - "transaction_sent": "Transacción enviada!", - "expired": "Muerto", - "time": "${minutes}m ${seconds}s", - "send_xmr": "Enviar XMR", - "exchange_new_template": "Nueva plantilla", - "faq": "FAQ", - "enter_your_pin": "Introduce tu PIN", - "loading_your_wallet": "Cargando tu billetera", - "new_wallet": "Nueva billetera", - "wallet_name": "Nombre de la billetera", - "continue_text": "Continuar", - "choose_wallet_currency": "Por favor, elija la moneda de la billetera:", - "node_new": "Nuevo nodo", - "node_address": "Dirección de nodo", - "node_port": "Puerto de nodo", - "login": "Iniciar sesión", - "password": "Contraseña", - "nodes": "Nodos", - "node_reset_settings_title": "Reiniciar ajustes", - "nodes_list_reset_to_default_message": "¿Está seguro de que desea restablecer la configuración predeterminada?", - "change_current_node": "¿Está seguro de cambiar el nodo actual a ${node}?", - "change": "Cambio", - "remove_node": "Eliminar nodo", - "remove_node_message": "¿Está seguro de que desea eliminar el nodo seleccionado?", - "remove": "Retirar", - "delete": "Borrar", - "add_new_node": "Agregar nuevo nodo", - "change_current_node_title": "Cambiar el nodo actual", - "node_test": "Prueba", - "node_connection_successful": "La conexión fue exitosa", - "node_connection_failed": "La conexión falló", - "new_node_testing": "Prueba de nuevos nodos", - "use": "Utilizar a ", - "digit_pin": "-dígito PIN", - "share_address": "Compartir dirección", - "receive_amount": "Cantidad", - "subaddresses": "Subdirecciones", "addresses": "Direcciones", - "scan_qr_code_to_get_address": "Escanee el código QR para obtener la dirección", - "qr_fullscreen": "Toque para abrir el código QR en pantalla completa", - "rename": "Rebautizar", - "choose_account": "Elegir cuenta", - "create_new_account": "Crear una nueva cuenta", - "accounts_subaddresses": "Cuentas y subdirecciones", - "restore_restore_wallet": "Recuperar Cartera", - "restore_title_from_seed_keys": "Restaurar desde semilla/claves", - "restore_description_from_seed_keys": "Recupere su billetera de las semillas/claves que ha guardado en un lugar seguro", - "restore_next": "Próximo", - "restore_title_from_backup": "Restaurar desde un archivo de respaldo", - "restore_description_from_backup": "Puede restaurar toda la aplicación Cake Wallet desde ysu archivo de respaldo", - "restore_seed_keys_restore": "Restauración de semillas / llaves", - "restore_title_from_seed": "De la semilla", - "restore_description_from_seed": "Restaure su billetera desde el código de combinación de 25 palabras i de 13 palabras", - "restore_title_from_keys": "De las claves", - "restore_description_from_keys": "Restaure su billetera de las pulsaciones de teclas generadas guardadas de sus claves privadas", - "restore_wallet_name": "Nombre de la billetera", - "restore_address": "Dirección", - "restore_view_key_private": "View clave (privado)", - "restore_spend_key_private": "Spend clave (privado)", - "restore_recover": "Recuperar", - "restore_wallet_restore_description": "Restaurar billetera", - "restore_new_seed": "Nueva semilla", - "restore_active_seed": "Semilla activa", - "restore_bitcoin_description_from_seed": "Restaure su billetera a partir del código de combinación de 24 palabras", - "restore_bitcoin_description_from_keys": "Restaure su billetera a partir de una cadena WIF generada a partir de sus claves privadas", - "restore_bitcoin_title_from_keys": "Restaurar desde WIF", - "restore_from_date_or_blockheight": "Ingrese una fecha unos días antes de crear esta billetera. O si conoce la altura del bloque, ingréselo en su lugar", - "seed_reminder": "Anótelos en caso de que pierda o borre su teléfono", - "seed_title": "Semilla", - "seed_share": "Compartir semillas", - "copy": "Dupdo", - "seed_language": "Lenguaje de semillas", - "seed_choose": "Elige el idioma semilla", - "seed_language_next": "Próximo", - "seed_language_english": "Inglés", - "seed_language_chinese": "Chino", - "seed_language_dutch": "Holandés", - "seed_language_german": "Alemán", - "seed_language_japanese": "Japonés", - "seed_language_portuguese": "Portugués", - "seed_language_russian": "Ruso", - "seed_language_spanish": "Español", - "seed_language_french": "Francesa/Francés", - "seed_language_italian": "Italiana/Italiano", - "send_title": "Enviar", - "send_your_wallet": "Tu billetera", - "send_address": "Dirección de ${cryptoCurrency}", - "send_payment_id": "ID de pago (opcional)", + "advanced_settings": "Ajustes avanzados", + "aggressive": "Demasiado entusiasta", + "agree": "De acuerdo", + "agree_and_continue": "Aceptar y continuar", + "agree_to": "Al crear una cuenta, aceptas ", "all": "TODOS", - "send_error_minimum_value": "El valor mínimo de la cantidad es 0.01", - "send_error_currency": "La moneda solo puede contener números", - "send_estimated_fee": "Tarifa estimada:", - "send_priority": "Actualmente la tarifa se establece en ${transactionPriority} prioridad.\nLa prioridad de la transacción se puede ajustar en la configuración", - "send_creating_transaction": "Creando transacción", - "send_templates": "Plantillas", - "send_new": "Nuevo", - "send_amount": "Cantidad:", - "send_fee": "Cuota:", - "send_name": "Nombre", - "got_it": "Entendido", - "send_sending": "Enviando...", - "send_success": "Su ${crypto} fue enviado con éxito", - "settings_title": "Configuraciones", - "settings_nodes": "Nodos", - "settings_current_node": "Nodo actual", - "settings_wallets": "Carteras", - "settings_display_balance": "Mostrar saldo", - "settings_currency": "Moneda", - "settings_fee_priority": "Prioridad de tasa", - "settings_save_recipient_address": "Guardar dirección del destinatario", - "settings_personal": "Personal", - "settings_change_pin": "Cambiar PIN", - "settings_change_language": "Cambiar idioma", - "settings_allow_biometrical_authentication": "Permitir autenticación biométrica", - "settings_dark_mode": "Modo oscuro", - "settings_transactions": "Transacciones", - "settings_trades": "Comercia", - "settings_display_on_dashboard_list": "Mostrar en la lista del tablero", - "settings_all": "TODOS", - "settings_only_trades": "Solo comercia", - "settings_only_transactions": "Solo transacciones", - "settings_none": "Ninguno", - "settings_support": "Apoyo", - "settings_terms_and_conditions": "Términos y Condiciones", - "pin_is_incorrect": "PIN es incorrecto", - "setup_pin": "PIN de configuración", - "enter_your_pin_again": "Ingrese su PIN nuevamente", - "setup_successful": "Su PIN se ha configurado correctamente!", - "wallet_keys": "Billetera semilla/claves", - "wallet_seed": "Semilla de billetera", - "private_key": "Clave privada", - "public_key": "Clave pública", - "view_key_private": "View clave (privado)", - "view_key_public": "View clave (público)", - "spend_key_private": "Spend clave (privado)", - "spend_key_public": "Spend clave (público)", - "copied_key_to_clipboard": "Copiado ${key} al portapapeles", - "new_subaddress_title": "Nueva direccion", - "new_subaddress_label_name": "Nombre de etiqueta", - "new_subaddress_create": "Crear", - "address_label": "Address label", - "subaddress_title": "Lista de subdirecciones", - "trade_details_title": "Detalles comerciales", - "trade_details_id": "ID", - "trade_details_state": "Estado", - "trade_details_fetching": "Cargando", - "trade_details_provider": "Proveedor", - "trade_details_created_at": "Creado en", - "trade_details_pair": "Par", - "trade_details_copied": "${title} Copiado al portapapeles", - "trade_history_title": "Historia del comercio", - "transaction_details_title": "Detalles de la transacción", - "transaction_details_transaction_id": "ID de transacción", - "transaction_details_date": "Fecha", - "transaction_details_height": "Altura", - "transaction_details_amount": "Cantidad", - "transaction_details_fee": "Cuota", - "transaction_details_copied": "${title} Copiado al portapapeles", - "transaction_details_recipient_address": "Direcciones de destinatarios", - "wallet_list_title": "Monedero Monero", - "wallet_list_create_new_wallet": "Crear nueva billetera", - "wallet_list_edit_wallet": "Editar billetera", - "wallet_list_wallet_name": "Nombre de la billetera", - "wallet_list_restore_wallet": "Restaurar billetera", - "wallet_list_load_wallet": "Billetera de carga", - "wallet_list_loading_wallet": "Billetera ${wallet_name} de carga", - "wallet_list_failed_to_load": "No se pudo cargar ${wallet_name} la billetera. ${error}", - "wallet_list_removing_wallet": "Retirar ${wallet_name} billetera", - "wallet_list_failed_to_remove": "Error al elimina ${wallet_name} billetera. ${error}", - "widgets_address": "Dirección", - "widgets_restore_from_blockheight": "Restaurar desde blockheight", - "widgets_restore_from_date": "Restaurar desde fecha", - "widgets_or": "o", - "widgets_seed": "Semilla", - "router_no_route": "No hay ruta definida para ${name}", - "error_text_account_name": "El nombre de la cuenta solo puede contener letras, números \ny debe tener entre 1 y 15 caracteres de longitud", - "error_text_contact_name": "El nombre del contacto no puede contener símbolos `, '\" \ny debe tener entre 1 y 32 caracteres de longitud", - "error_text_address": "La dirección de la billetera debe corresponder al tipo \nde criptomoneda", - "error_text_node_address": "Por favor, introduzca una dirección iPv4", - "error_text_node_port": "El puerto de nodo solo puede contener números entre 0 y 65535", - "error_text_node_proxy_address": "Ingrese :, por ejemplo 127.0.0.1:9050", - "error_text_payment_id": "La ID de pago solo puede contener de 16 a 64 caracteres en hexadecimal", - "error_text_xmr": "El valor XMR no puede exceder el saldo disponible.\nTEl número de dígitos de fracción debe ser menor o igual a 12", - "error_text_fiat": "El valor de la cantidad no puede exceder el saldo disponible.\nEl número de dígitos de fracción debe ser menor o igual a 2", - "error_text_subaddress_name": "El nombre de la subdirección no puede contener símbolos `, '\" \ny debe tener entre 1 y 20 caracteres de longitud", - "error_text_amount": "La cantidad solo puede contener números", - "error_text_wallet_name": "El nombre de la billetera solo puede contener letras, números , _ - símbolos\ny debe tener entre 1 y 33 caracteres de longitud", - "error_text_keys": "Las llaves de billetera solo pueden contener 64 caracteres en hexadecimal", - "error_text_crypto_currency": "El número de dígitos fraccionarios \ndebe ser menor o igual a 12", - "error_text_minimal_limit": "El comercio por ${provider} no se crea. La cantidad es menos que mínima: ${min} ${currency}", - "error_text_maximum_limit": "El comercio por ${provider} no se crea. La cantidad es más que el máximo: ${max} ${currency}", - "error_text_limits_loading_failed": "El comercio por ${provider} no se crea. Límites de carga fallidos", - "error_text_template": "El nombre y la dirección de la plantilla no pueden contener símbolos ` , '\" \ny debe tener entre 1 y 106 caracteres de longitud", + "all_trades": "Todos los oficios", + "all_transactions": "Todas las transacciones", + "alphabetical": "Alfabético", + "already_have_account": "¿Ya tienes una cuenta?", + "always": "siempre", + "amount": "Cantidad: ", + "amount_is_estimate": "El monto recibido es un estimado", + "amount_is_guaranteed": "La cantidad recibida está garantizada", + "and": "y", + "anonpay_description": "Genera ${type}. El destinatario puede ${method} con cualquier criptomoneda admitida, y recibirá fondos en esta billetera.", + "apk_update": "Actualización de APK", + "approve": "Aprobar", + "arrive_in_this_address": "${currency} ${tag}llegará a esta dirección", + "ascending": "Ascendente", + "ask_each_time": "Pregunta cada vez", "auth_store_ban_timeout": "prohibición de tiempo de espera", "auth_store_banned_for": "Prohibido para ", "auth_store_banned_minutes": " minutos", "auth_store_incorrect_password": "Contraseña PIN", - "wallet_store_monero_wallet": "Monedero Monero", - "wallet_restoration_store_incorrect_seed_length": "Longitud de semilla incorrecta", - "full_balance": "Balance completo", - "available_balance": "Balance disponible", - "hidden_balance": "Balance oculto", - "sync_status_syncronizing": "SINCRONIZANDO", - "sync_status_syncronized": "SINCRONIZADO", - "sync_status_not_connected": "NO CONECTADO", - "sync_status_starting_sync": "EMPEZANDO A SINCRONIZAR", - "sync_status_failed_connect": "DESCONECTADO", - "sync_status_connecting": "CONECTANDO", - "sync_status_connected": "CONECTADO", - "sync_status_attempting_sync": "INTENTAR SINCRONIZAR", - "transaction_priority_slow": "Lento", - "transaction_priority_regular": "Regular", - "transaction_priority_medium": "Medio", - "transaction_priority_fast": "Rápido", - "transaction_priority_fastest": "Lo más rápido", - "trade_for_not_created": "Comercio por ${title} no se crea.", - "trade_not_created": "Comercio no se crea", - "trade_id_not_found": "Comercio ${tradeId} de ${title} no encontrado.", - "trade_not_found": "Comercio no encontrado.", - "trade_state_pending": "Pendiente", - "trade_state_confirming": "Confirmando", - "trade_state_trading": "Comercio", - "trade_state_traded": "Negociado", - "trade_state_complete": "Completar", - "trade_state_to_be_created": "Ser creado", - "trade_state_unpaid": "No pagado", - "trade_state_underpaid": "Poco pagado", - "trade_state_paid_unconfirmed": "Pagado sin confirmar", - "trade_state_paid": "Pagado", - "trade_state_btc_sent": "Btc expedido", - "trade_state_timeout": "Se acabó el tiempo", - "trade_state_created": "Creado", - "trade_state_finished": "Terminado", - "change_language": "Cambiar idioma", - "change_language_to": "Cambiar el idioma a ${language}?", - "paste": "Pegar", - "restore_from_seed_placeholder": "Ingrese o pegue su frase de código aquí", - "add_new_word": "Agregar palabra nueva", - "incorrect_seed": "El texto ingresado no es válido.", - "biometric_auth_reason": "Escanee su huella digital para autenticar", - "version": "Versión ${currentVersion}", - "extracted_address_content": "Enviará fondos a\n${recipient_name}", - "card_address": "Dirección:", - "buy": "Comprar", - "sell": "Vender", - "placeholder_transactions": "Sus transacciones se mostrarán aquí", - "placeholder_contacts": "Tus contactos se mostrarán aquí", - "template": "Plantilla", - "confirm_delete_template": "Esta acción eliminará esta plantilla. ¿Desea continuar?", - "confirm_delete_wallet": "Esta acción eliminará esta billetera. ¿Desea continuar?", - "change_wallet_alert_title": "Cambiar billetera actual", - "change_wallet_alert_content": "¿Quieres cambiar la billetera actual a ${wallet_name}?", - "creating_new_wallet": "Creando nueva billetera", - "creating_new_wallet_error": "Error: ${description}", - "seed_alert_title": "Atención", - "seed_alert_content": "La semilla es la única forma de recuperar su billetera. ¿Lo has escrito?", - "seed_alert_back": "Regresa", - "seed_alert_yes": "Sí tengo", - "exchange_sync_alert_content": "Espere hasta que su billetera esté sincronizada", - "pre_seed_title": "IMPORTANTE", - "pre_seed_description": "En la página siguiente verá una serie de ${words} palabras. Esta es su semilla única y privada y es la ÚNICA forma de recuperar su billetera en caso de pérdida o mal funcionamiento. Es SU responsabilidad escribirlo y guardarlo en un lugar seguro fuera de la aplicación Cake Wallet.", - "pre_seed_button_text": "Entiendo. Muéstrame mi semilla", - "xmr_to_error": "Error de XMR.TO", - "xmr_to_error_description": "Monto invalido. Límite máximo de 8 dígitos después del punto decimal", - "provider_error": "${provider} error", - "use_ssl": "Utilice SSL", - "trusted": "de confianza", - "color_theme": "Tema de color", - "light_theme": "Ligera", - "bright_theme": "Brillante", - "dark_theme": "Oscura", - "enter_your_note": "Ingresa tu nota…", - "note_optional": "Nota (opcional)", - "note_tap_to_change": "Nota (toque para cambiar)", - "view_in_block_explorer": "View in Block Explorer", - "view_transaction_on": "View Transaction on ", - "transaction_key": "Clave de transacción", - "confirmations": "Confirmaciones", - "recipient_address": "Dirección del receptor", - "extra_id": "ID adicional:", - "destination_tag": "Etiqueta de destino:", - "memo": "Memorándum:", - "backup": "Apoyo", - "change_password": "Cambia la contraseña", - "backup_password": "Contraseña de respaldo", - "write_down_backup_password": "Escriba su contraseña de respaldo, que se utiliza para la importación de sus archivos de respaldo.", - "export_backup": "Exportar copia de seguridad", - "save_backup_password": "Asegúrese de haber guardado su contraseña de respaldo. No podrá importar sus archivos de respaldo sin él.", - "backup_file": "Archivo de respaldo", - "edit_backup_password": "Editar contraseña de respaldo", - "save_backup_password_alert": "Guardar contraseña de respaldo", - "change_backup_password_alert": "Sus archivos de respaldo anteriores no estarán disponibles para importar con la nueva contraseña de respaldo. La nueva contraseña de respaldo se utilizará solo para los nuevos archivos de respaldo. ¿Está seguro de que desea cambiar la contraseña de respaldo?", - "enter_backup_password": "Ingrese la contraseña de respaldo aquí", - "select_backup_file": "Seleccionar archivo de respaldo", - "import": "Importar", - "please_select_backup_file": "Seleccione el archivo de respaldo e ingrese la contraseña de respaldo.", - "fixed_rate": "Tipo de interés fijo", - "fixed_rate_alert": "Podrá ingresar la cantidad recibida cuando el modo de tarifa fija esté marcado. ¿Quieres cambiar al modo de tarifa fija?", - "xlm_extra_info": "No olvide especificar el ID de nota al enviar la transacción XLM para el intercambio", - "xrp_extra_info": "No olvide especificar la etiqueta de destino al enviar la transacción XRP para el intercambio", - "exchange_incorrect_current_wallet_for_xmr": "Si desea intercambiar XMR de su saldo de Cake Wallet Monero, primero cambie a su billetera Monero.", - "confirmed": "Saldo confirmado", - "unconfirmed": "Saldo no confirmado", - "displayable": "Visualizable", - "submit_request": "presentar una solicitud", - "buy_alert_content": "Actualmente solo admitimos la compra de Bitcoin, Ethereum, Litecoin y Monero. Cree o cambie a su billetera Bitcoin, Ethereum, Litecoin o Monero.", - "sell_alert_content": "Actualmente solo admitimos la venta de Bitcoin, Ethereum y Litecoin. Cree o cambie a su billetera Bitcoin, Ethereum o Litecoin.", - "outdated_electrum_wallet_description": "Las nuevas carteras de Bitcoin creadas en Cake ahora tienen una semilla de 24 palabras. Es obligatorio que cree una nueva billetera de Bitcoin y transfiera todos sus fondos a la nueva billetera de 24 palabras, y deje de usar billeteras con una semilla de 12 palabras. Haga esto de inmediato para asegurar sus fondos.", - "understand": "Entiendo", - "apk_update": "Actualización de APK", - "buy_bitcoin": "Comprar Bitcoin", - "buy_with": "Compra con", - "moonpay_alert_text": "El valor de la cantidad debe ser mayor o igual a ${minAmount} ${fiatCurrency}", - "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", - "do_not_show_me": "no me muestres esto otra vez", - "unspent_coins_title": "Monedas no gastadas", - "unspent_coins_details_title": "Detalles de monedas no gastadas", - "freeze": "Congelar", - "frozen": "Congelada", - "coin_control": "Control de monedas (opcional)", - "address_detected": "Dirección detectada", - "address_from_domain": "Esta dirección es de ${domain} en Unstoppable Domains", - "add_receiver": "Agregar otro receptor (opcional)", - "manage_yats": "Administrar Yats", - "yat_alert_title": "Envíe y reciba criptomonedas más fácilmente con Yat", - "yat_alert_content": "Los usuarios de Cake Wallet ahora pueden enviar y recibir todas sus monedas favoritas con un nombre de usuario único basado en emoji.", - "get_your_yat": "Obtén tu Yat", - "connect_an_existing_yat": "Conectar un Yat existente", - "yat_address": "Dirección de Yat", - "yat": "Yat", - "connect_yats": "Conectar Yats", - "address_from_yat": "Esta dirección es de ${emoji} en Yat", - "yat_error": "Error de Yat", - "yat_error_content": "No hay direcciones vinculadas con este Yat. Prueba con otro Yat", - "choose_address": "\n\nPor favor elija la dirección:", - "yat_popup_title": "La dirección de su billetera se puede emojificar.", - "yat_popup_content": "Ahora puede enviar y recibir criptografía en Cake Wallet con su Yat, un nombre de usuario corto basado en emoji. Administre Yats en cualquier momento en la pantalla de configuración", - "second_intro_title": "Una dirección de emoji para gobernarlos a todos", - "second_intro_content": "Tu Yat es una única dirección emoji única que reemplaza todas tus direcciones hexadecimales largas para todas tus monedas.", - "third_intro_title": "Yat juega muy bien con otras", - "third_intro_content": "Los Yats también viven fuera de Cake Wallet. Cualquier dirección de billetera en la tierra se puede reemplazar con un Yat!", - "learn_more": "Aprende más", - "search": "Búsqueda", - "search_language": "Idioma de búsqueda", - "search_currency": "Moneda de búsqueda", - "new_template": "Nueva plantilla", - "electrum_address_disclaimer": "Generamos nuevas direcciones cada vez que usa una, pero las direcciones anteriores siguen funcionando", - "wallet_name_exists": "Wallet con ese nombre ya ha existido", - "market_place": "Mercado", - "cake_pay_title": "Tarjetas de regalo Cake Pay", - "cake_pay_subtitle": "Compre tarjetas de regalo con descuento (solo EE. UU.)", - "cake_pay_web_cards_title": "Tarjetas Web Cake Pay", - "cake_pay_web_cards_subtitle": "Compre tarjetas de prepago y tarjetas de regalo en todo el mundo", - "about_cake_pay": "Cake Pay le permite comprar fácilmente tarjetas de regalo con activos virtuales, gastables instantáneamente en más de 150 000 comerciantes en los Estados Unidos.", - "cake_pay_account_note": "Regístrese con solo una dirección de correo electrónico para ver y comprar tarjetas. ¡Algunas incluso están disponibles con descuento!", - "already_have_account": "¿Ya tienes una cuenta?", - "create_account": "Crear Cuenta", - "privacy_policy": "Política de privacidad", - "welcome_to_cakepay": "¡Bienvenido a Cake Pay!", - "sign_up": "Registrarse", - "forgot_password": "Olvidé mi contraseña", - "reset_password": "Restablecer contraseña", - "gift_cards": "Tarjetas de regalo", - "setup_your_debit_card": "Configura tu tarjeta de débito", - "no_id_required": "No se requiere identificación. Recargue y gaste en cualquier lugar", - "how_to_use_card": "Cómo usar esta tarjeta", - "purchase_gift_card": "Comprar tarjeta de regalo", - "verification": "Verificación", - "fill_code": "Por favor complete el código de verificación proporcionado a su correo electrónico", - "didnt_get_code": "¿No recibiste el código?", - "resend_code": "Por favor reenvíalo", - "debit_card": "Tarjeta de Débito", - "cakepay_prepaid_card": "Tarjeta de Débito Prepago CakePay", - "no_id_needed": "¡No se necesita identificación!", - "frequently_asked_questions": "Preguntas frecuentes", - "debit_card_terms": "El almacenamiento y el uso de su número de tarjeta de pago (y las credenciales correspondientes a su número de tarjeta de pago) en esta billetera digital están sujetos a los Términos y condiciones del acuerdo del titular de la tarjeta aplicable con el emisor de la tarjeta de pago, en vigor desde tiempo al tiempo.", - "please_reference_document": "Consulte los documentos a continuación para obtener más información.", - "cardholder_agreement": "Acuerdo del titular de la tarjeta", - "e_sign_consent": "Consentimiento de firma electrónica", - "agree_and_continue": "Aceptar y continuar", - "email_address": "Dirección de correo electrónico", - "agree_to": "Al crear una cuenta, aceptas ", - "and": "y", - "enter_code": "Ingresar código", - "congratulations": "Felicidades!", - "you_now_have_debit_card": "Ahora tiene una tarjeta de débito", - "min_amount": "Mínimo: ${value}", - "max_amount": "Máx: ${value}", - "enter_amount": "Ingrese la cantidad", - "billing_address_info": "Si se le solicita una dirección de facturación, proporcione su dirección de envío", - "order_physical_card": "Pedir tarjeta física", - "add_value": "Añadir valor", - "activate": "Activar", - "get_a": "Obtener un", - "digital_and_physical_card": " tarjeta de débito prepago digital y física", - "get_card_note": " que puedes recargar con monedas digitales. ¡No se necesita información adicional!", - "signup_for_card_accept_terms": "Regístrese para obtener la tarjeta y acepte los términos.", - "add_fund_to_card": "Agregar fondos prepagos a las tarjetas (hasta ${value})", - "use_card_info_two": "Los fondos se convierten a USD cuando se mantienen en la cuenta prepaga, no en monedas digitales.", - "use_card_info_three": "Utilice la tarjeta digital en línea o con métodos de pago sin contacto.", - "optionally_order_card": "Opcionalmente pide una tarjeta física.", - "hide_details": "Ocultar detalles", - "show_details": "Mostrar detalles", - "upto": "hasta ${value}", - "discount": "Ahorra ${value}%", - "gift_card_amount": "Cantidad de la tarjeta de regalo", - "bill_amount": "Importe de la factura", - "you_pay": "Tú pagas", - "tip": "Consejo:", - "personalizado": "personalizado", - "by_cake_pay": "por Cake Pay", - "expires": "Caduca", - "mm": "mm", - "yy": "YY", - "online": "En línea", - "offline": "fuera de línea", - "gift_card_number": "Número de tarjeta de regalo", - "pin_number": "Número PIN", - "total_saving": "Ahorro Total", - "last_30_days": "Últimos 30 días", - "avg_savings": "Ahorro promedio", - "view_all": "Ver todo", - "active_cards": "Tarjetas activas", - "delete_account": "Eliminar cuenta", - "cards": "Cartas", - "active": "Activo", - "redeemed": "Redimido", - "gift_card_balance_note": "Las tarjetas de regalo con saldo restante aparecerán aquí", - "gift_card_redeemed_note": "Las tarjetas de regalo que hayas canjeado aparecerán aquí", - "logout": "Cerrar sesión", - "add_tip": "Agregar sugerencia", - "percentageOf": "de ${amount}", - "is_percentage": "es", - "search_category": "Categoría de búsqueda", - "mark_as_redeemed": "Marcar como canjeado", - "more_options": "Más Opciones", - "awaiting_payment_confirmation": "Esperando confirmación de pago", - "transaction_sent_notice": "Si la pantalla no continúa después de 1 minuto, revisa un explorador de bloques y tu correo electrónico.", - "agree": "De acuerdo", - "in_store": "En la tienda", - "generating_gift_card": "Generando tarjeta de regalo", - "payment_was_received": "Su pago fue recibido.", - "proceed_after_one_minute": "Si la pantalla no continúa después de 1 minuto, revisa tu correo electrónico.", - "order_id": "Identificación del pedido", - "gift_card_is_generated": "Se genera la tarjeta de regalo", - "open_gift_card": "Abrir tarjeta de regalo", - "contact_support": "Contactar con Soporte", - "gift_cards_unavailable": "Las tarjetas de regalo están disponibles para comprar solo a través de Monero, Bitcoin y Litecoin en este momento", - "background_sync_mode": "Modo de sincronización en segundo plano", - "sync_all_wallets": "Sincronizar todas las billeteras", - "introducing_cake_pay": "¡Presentamos Cake Pay!", - "cake_pay_learn_more": "¡Compre y canjee tarjetas de regalo al instante en la aplicación!\nDeslice el dedo de izquierda a derecha para obtener más información.", + "authenticated": "Autenticados", + "authentication": "Autenticación", + "auto_generate_subaddresses": "Generar subdirecciones automáticamente", "automatic": "Automático", - "fixed_pair_not_supported": "Este par fijo no es compatible con los intercambios seleccionados", - "variable_pair_not_supported": "Este par de variables no es compatible con los intercambios seleccionados", - "none_of_selected_providers_can_exchange": "Ninguno de los proveedores seleccionados puede realizar este intercambio", - "choose_one": "Elige uno", - "choose_from_available_options": "Elija entre las opciones disponibles:", - "custom_redeem_amount": "Cantidad de canje personalizada", - "add_custom_redemption": "Agregar redención personalizada", - "remaining": "restante", - "delete_wallet": "Eliminar billetera", - "delete_wallet_confirm_message": "¿Está seguro de que desea eliminar la billetera ${wallet_name}?", - "low_fee": "Tarifa baja", - "low_fee_alert": "Actualmente está utilizando una prioridad de tarifa de red baja. Esto podría causar largas esperas, tarifas diferentes o transacciones canceladas. Recomendamos establecer una tarifa más alta para una mejor experiencia.", - "ignor": "Pasar por alto", - "use_suggested": "Usar sugerido", - "do_not_share_warning_text": "No comparta estos con nadie más, incluido el soporte.\n\n¡Sus fondos pueden ser y serán robados!", - "help": "ayuda", - "all_transactions": "Todas las transacciones", - "all_trades": "Todos los oficios", - "connection_sync": "Conexión y sincronización", - "security_and_backup": "Seguridad y respaldo", - "create_backup": "Crear copia de seguridad", - "privacy_settings": "Configuración de privacidad", - "privacy": "Privacidad", - "display_settings": "Configuración de pantalla", - "other_settings": "Otras configuraciones", - "require_pin_after": "Requerir PIN después de", - "always": "siempre", - "minutes_to_pin_code": "${minute} minutos", - "disable_exchange": "Deshabilitar intercambio", - "advanced_settings": "Ajustes avanzados", - "settings_can_be_changed_later": "Estas configuraciones se pueden cambiar más tarde en la configuración de la aplicación", - "add_custom_node": "Agregar nuevo nodo personalizado", - "disable_fiat": "Deshabilitar fiat", - "fiat_api": "Fiat API", - "disabled": "Desactivado", - "enabled": "Activado", - "tor_only": "solo Tor", - "unmatched_currencies": "La moneda de su billetera actual no coincide con la del QR escaneado", - "orbot_running_alert": "Asegúrese de que Orbot se esté ejecutando antes de conectarse a este nodo.", - "contact_list_contacts": "Contactos", - "contact_list_wallets": "Mis billeteras", - "bitcoin_payments_require_1_confirmation": "Los pagos de Bitcoin requieren 1 confirmación, que puede demorar 20 minutos o más. ¡Gracias por su paciencia! Se le enviará un correo electrónico cuando se confirme el pago.", - "send_to_this_address": "Enviar ${currency} ${tag}a esta dirección", - "arrive_in_this_address": "${currency} ${tag}llegará a esta dirección", - "do_not_send": "no enviar", - "error_dialog_content": "Vaya, tenemos un error.\n\nEnvíe el informe de bloqueo a nuestro equipo de soporte para mejorar la aplicación.", - "scan_qr_code": "Escanear código QR", - "cold_or_recover_wallet": "Agregue una billetera fría o recupere una billetera de papel", - "please_wait": "Espere por favor", - "sweeping_wallet": "Billetera de barrido", - "sweeping_wallet_alert": "Esto no debería llevar mucho tiempo. NO DEJES ESTA PANTALLA O SE PUEDEN PERDER LOS FONDOS BARRIDOS", - "decimal_places_error": "Demasiados lugares decimales", - "edit_node": "Editar nodo", - "invoice_details": "Detalles de la factura", - "donation_link_details": "Detalles del enlace de donación", - "anonpay_description": "Genera ${type}. El destinatario puede ${method} con cualquier criptomoneda admitida, y recibirá fondos en esta billetera.", - "create_invoice": "Crear factura", - "create_donation_link": "Crear enlace de donación", - "optional_email_hint": "Correo electrónico de notificación del beneficiario opcional", - "optional_description": "Descripción opcional", - "optional_name": "Nombre del destinatario opcional", - "clearnet_link": "enlace Clearnet", - "onion_link": "Enlace de cebolla", - "settings": "Configuraciones", - "sell_monero_com_alert_content": "Aún no se admite la venta de Monero", - "error_text_input_below_minimum_limit": "La cantidad es menos que mínima", - "error_text_input_above_maximum_limit": "La cantidad es más que el máximo", - "show_market_place": "Mostrar mercado", - "prevent_screenshots": "Evitar capturas de pantalla y grabación de pantalla", - "profile": "Perfil", - "close": "Cerca", - "modify_2fa": "Modificar torta 2FA", - "disable_cake_2fa": "Desactivar pastel 2FA", - "question_to_disable_2fa": "¿Está seguro de que desea deshabilitar Cake 2FA? Ya no se necesitará un código 2FA para acceder a la billetera y a ciertas funciones.", - "disable": "Desactivar", - "setup_2fa": "Configurar pastel 2FA", - "verify_with_2fa": "Verificar con Cake 2FA", - "totp_code": "Código TOTP", - "please_fill_totp": "Complete el código de 8 dígitos presente en su otro dispositivo", - "totp_2fa_success": "¡Éxito! Cake 2FA habilitado para esta billetera. Recuerde guardar su semilla mnemotécnica en caso de que pierda el acceso a la billetera.", - "totp_verification_success": "¡Verificación exitosa!", - "totp_2fa_failure": "Código incorrecto. Intente con un código diferente o genere una nueva clave secreta. Use una aplicación 2FA compatible que admita códigos de 8 dígitos y SHA512.", - "enter_totp_code": "Ingrese el código TOTP.", - "add_secret_code": "O agregue este código secreto a una aplicación de autenticación", - "totp_secret_code": "Código secreto TOTP", - "setup_2fa_text": "Cake 2FA funciona utilizando TOTP como segundo factor de autenticación.\n\nEl TOTP de Cake 2FA requiere SHA-512 y soporte de 8 dígitos; esto proporciona una mayor seguridad. Puede encontrar más información y aplicaciones compatibles en la guía.", - "setup_totp_recommended": "Configurar TOTP", - "disable_buy": "Desactivar acción de compra", - "disable_sell": "Desactivar acción de venta", - "cake_2fa_preset": "Pastel 2FA preestablecido", - "monero_dark_theme": "Tema oscuro de Monero", + "available_balance": "Balance disponible", + "available_balance_description": "Su saldo disponible es la cantidad de fondos que puede gastar. Los fondos que se muestran aquí se pueden gastar inmediatamente.", + "avg_savings": "Ahorro promedio", + "awaitDAppProcessing": "Espere a que la dApp termine de procesarse.", + "awaiting_payment_confirmation": "Esperando confirmación de pago", + "background_sync_mode": "Modo de sincronización en segundo plano", + "backup": "Apoyo", + "backup_file": "Archivo de respaldo", + "backup_password": "Contraseña de respaldo", + "balance_page": "Página de saldo", + "bill_amount": "Importe de la factura", + "billing_address_info": "Si se le solicita una dirección de facturación, proporcione su dirección de envío", + "biometric_auth_reason": "Escanee su huella digital para autenticar", "bitcoin_dark_theme": "Tema oscuro de Bitcoin", "bitcoin_light_theme": "Tema de la luz de Bitcoin", - "high_contrast_theme": "Tema de alto contraste", - "matrix_green_dark_theme": "Matrix verde oscuro tema", - "monero_light_theme": "Tema ligero de Monero", - "auto_generate_subaddresses": "Generar subdirecciones automáticamente", - "narrow": "Angosto", - "normal": "Normal", - "aggressive": "Demasiado entusiasta", - "require_for_assessing_wallet": "Requerido para acceder a la billetera", - "require_for_sends_to_non_contacts": "Requerido para envíos a no contactos", - "require_for_sends_to_contacts": "Requerir para envíos a contactos", - "require_for_sends_to_internal_wallets": "Requerido para envíos a billeteras internas", - "require_for_exchanges_to_internal_wallets": "Requerido para intercambios a billeteras internas", - "require_for_adding_contacts": "Requerido para agregar contactos", - "require_for_creating_new_wallets": "Requerido para crear nuevas billeteras", - "require_for_all_security_and_backup_settings": "Requerido para todas las configuraciones de seguridad y copia de seguridad", - "available_balance_description": "Su saldo disponible es la cantidad de fondos que puede gastar. Los fondos que se muestran aquí se pueden gastar inmediatamente.", - "syncing_wallet_alert_title": "Tu billetera se está sincronizando", - "syncing_wallet_alert_content": "Es posible que su lista de saldo y transacciones no esté completa hasta que diga \"SINCRONIZADO\" en la parte superior. Haga clic/toque para obtener más información.", - "home_screen_settings": "Configuración de la pantalla de inicio", - "sort_by": "Ordenar por", - "search_add_token": "Buscar/Agregar token", - "edit_token": "Editar token", - "warning": "Advertencia", - "add_token_warning": "No edite ni agregue tokens según las instrucciones de los estafadores.\n¡Confirme siempre las direcciones de los tokens con fuentes acreditadas!", - "add_token_disclaimer_check": "He confirmado la dirección del contrato del token y la información utilizando una fuente confiable. Agregar información maliciosa o incorrecta puede resultar en una pérdida de fondos.", - "token_contract_address": "Dirección de contrato de token", - "token_name": "Nombre del token, por ejemplo: Tether", - "token_symbol": "Símbolo de token, por ejemplo: USDT", - "token_decimal": "Token decimal", - "field_required": "Este campo es obligatorio", - "pin_at_top": "pin ${token} en la parte superior", - "invalid_input": "Entrada inválida", - "fiat_balance": "Equilibrio Fiat", - "gross_balance": "Saldo bruto", - "alphabetical": "Alfabético", - "generate_name": "Generar nombre", - "balance_page": "Página de saldo", - "share": "Compartir", - "slidable": "deslizable", - "manage_nodes": "Administrar nodos", - "etherscan_history": "historia de etherscan", - "template_name": "Nombre de la plantilla", + "bitcoin_payments_require_1_confirmation": "Los pagos de Bitcoin requieren 1 confirmación, que puede demorar 20 minutos o más. ¡Gracias por su paciencia! Se le enviará un correo electrónico cuando se confirme el pago.", + "Blocks_remaining": "${status} Bloques restantes", + "bright_theme": "Brillante", + "buy": "Comprar", + "buy_alert_content": "Actualmente solo admitimos la compra de Bitcoin, Ethereum, Litecoin y Monero. Cree o cambie a su billetera Bitcoin, Ethereum, Litecoin o Monero.", + "buy_bitcoin": "Comprar Bitcoin", + "buy_provider_unavailable": "Proveedor actualmente no disponible.", + "buy_with": "Compra con", + "by_cake_pay": "por Cake Pay", + "cake_2fa_preset": "Pastel 2FA preestablecido", + "cake_pay_account_note": "Regístrese con solo una dirección de correo electrónico para ver y comprar tarjetas. ¡Algunas incluso están disponibles con descuento!", + "cake_pay_learn_more": "¡Compre y canjee tarjetas de regalo al instante en la aplicación!\nDeslice el dedo de izquierda a derecha para obtener más información.", + "cake_pay_subtitle": "Compre tarjetas de regalo con descuento (solo EE. UU.)", + "cake_pay_title": "Tarjetas de regalo Cake Pay", + "cake_pay_web_cards_subtitle": "Compre tarjetas de prepago y tarjetas de regalo en todo el mundo", + "cake_pay_web_cards_title": "Tarjetas Web Cake Pay", + "cake_wallet": "Cake Wallet", + "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}. Consulte su Política de privacidad para obtener más detalles.", + "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.", + "cancel": "Cancelar", + "card_address": "Dirección:", + "cardholder_agreement": "Acuerdo del titular de la tarjeta", + "cards": "Cartas", + "chains": "Cadenas", + "change": "Cambio", + "change_backup_password_alert": "Sus archivos de respaldo anteriores no estarán disponibles para importar con la nueva contraseña de respaldo. La nueva contraseña de respaldo se utilizará solo para los nuevos archivos de respaldo. ¿Está seguro de que desea cambiar la contraseña de respaldo?", + "change_currency": "Cambiar moneda", + "change_current_node": "¿Está seguro de cambiar el nodo actual a ${node}?", + "change_current_node_title": "Cambiar el nodo actual", + "change_exchange_provider": "Cambiar proveedor de intercambio", + "change_language": "Cambiar idioma", + "change_language_to": "Cambiar el idioma a ${language}?", + "change_password": "Cambia la contraseña", "change_rep": "Representante de cambio", "change_rep_message": "¿Estás seguro de que quieres cambiar de representante?", - "unsupported_asset": "No admitimos esta acción para este activo. Cree o cambie a una billetera de un tipo de activo admitido.", - "manage_pow_nodes": "Administrar nodos PoW", - "support_title_live_chat": "Soporte vital", - "support_description_live_chat": "¡GRATIS y RÁPIDO! Los representantes de apoyo capacitado están disponibles para ayudar", - "support_title_guides": "Guías de billetera para pastel", - "support_description_guides": "Documentación y apoyo para problemas comunes", - "support_title_other_links": "Otros enlaces de soporte", - "support_description_other_links": "Únase a nuestras comunidades o comuníquese con nosotros nuestros socios a través de otros métodos", + "change_rep_successful": "Representante cambiado con éxito", + "change_wallet_alert_content": "¿Quieres cambiar la billetera actual a ${wallet_name}?", + "change_wallet_alert_title": "Cambiar billetera actual", + "choose_account": "Elegir cuenta", + "choose_address": "\n\nPor favor elija la dirección:", "choose_derivation": "Elija la derivación de la billetera", - "new_first_wallet_text": "Mantenga fácilmente su criptomoneda segura", - "select_destination": "Seleccione el destino del archivo de copia de seguridad.", - "save_to_downloads": "Guardar en Descargas", - "select_buy_provider_notice": "Seleccione un proveedor de compra arriba. Puede omitir esta pantalla configurando su proveedor de compra predeterminado en la configuración de la aplicación.", - "onramper_option_description": "Compre 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.", + "choose_from_available_options": "Elija entre las opciones disponibles:", + "choose_one": "Elige uno", + "choose_relay": "Por favor elija un relé para usar", + "choose_wallet_currency": "Por favor, elija la moneda de la billetera:", + "clear": "Claro", + "clearnet_link": "enlace Clearnet", + "close": "Cerca", + "coin_control": "Control de monedas (opcional)", + "cold_or_recover_wallet": "Agregue una billetera fría o recupere una billetera de papel", + "color_theme": "Tema de color", + "commit_transaction_amount_fee": "Confirmar transacción\nCantidad: ${amount}\nCuota: ${fee}", + "confirm": "Confirmar", + "confirm_delete_template": "Esta acción eliminará esta plantilla. ¿Desea continuar?", + "confirm_delete_wallet": "Esta acción eliminará esta billetera. ¿Desea continuar?", + "confirm_sending": "Confirmar envío", + "confirmations": "Confirmaciones", + "confirmed": "Saldo confirmado", + "confirmed_tx": "Confirmado", + "congratulations": "Felicidades!", + "connect_an_existing_yat": "Conectar un Yat existente", + "connect_yats": "Conectar Yats", + "connection_sync": "Conexión y sincronización", + "connectWalletPrompt": "Conecte su billetera con WalletConnect para realizar transacciones", + "contact": "Contacto", + "contact_list_contacts": "Contactos", + "contact_list_wallets": "Mis billeteras", + "contact_name": "Nombre de contacto", + "contact_support": "Contactar con Soporte", + "continue_text": "Continuar", + "contractName": "Nombre del contrato", + "contractSymbol": "Símbolo de contrato", + "copied_key_to_clipboard": "Copiado ${key} al portapapeles", + "copied_to_clipboard": "Copiado al portapapeles", + "copy": "Dupdo", + "copy_address": "Copiar dirección ", + "copy_id": "Copiar ID", + "copyWalletConnectLink": "Copie el enlace de WalletConnect de dApp y péguelo aquí", + "create_account": "Crear Cuenta", + "create_backup": "Crear copia de seguridad", + "create_donation_link": "Crear enlace de donación", + "create_invoice": "Crear factura", + "create_new": "Crear nueva billetera", + "create_new_account": "Crear una nueva cuenta", + "creating_new_wallet": "Creando nueva billetera", + "creating_new_wallet_error": "Error: ${description}", + "creation_date": "Fecha de creación", + "custom_drag": "Custom (mantenía y arrastre)", + "custom_redeem_amount": "Cantidad de canje personalizada", + "dark_theme": "Oscura", + "debit_card": "Tarjeta de Débito", + "debit_card_terms": "El almacenamiento y el uso de su número de tarjeta de pago (y las credenciales correspondientes a su número de tarjeta de pago) en esta billetera digital están sujetos a los Términos y condiciones del acuerdo del titular de la tarjeta aplicable con el emisor de la tarjeta de pago, en vigor desde tiempo al tiempo.", + "decimal_places_error": "Demasiados lugares decimales", "default_buy_provider": "Proveedor de compra predeterminado", - "ask_each_time": "Pregunta cada vez", - "buy_provider_unavailable": "Proveedor actualmente no disponible.", - "signTransaction": "Firmar transacción", + "default_sell_provider": "Proveedor de venta predeterminado", + "delete": "Borrar", + "delete_account": "Eliminar cuenta", + "delete_wallet": "Eliminar billetera", + "delete_wallet_confirm_message": "¿Está seguro de que desea eliminar la billetera ${wallet_name}?", + "deleteConnectionConfirmationPrompt": "¿Está seguro de que desea eliminar la conexión a", + "descending": "Descendente", + "description": "Descripción", + "destination_tag": "Etiqueta de destino:", + "dfx_option_description": "Compre criptomonedas con EUR y CHF. Hasta 990€ sin KYC adicional. Para clientes minoristas y corporativos en Europa", + "didnt_get_code": "¿No recibiste el código?", + "digit_pin": "-dígito PIN", + "digital_and_physical_card": " tarjeta de débito prepago digital y física", + "disable": "Desactivar", + "disable_buy": "Desactivar acción de compra", + "disable_cake_2fa": "Desactivar pastel 2FA", + "disable_exchange": "Deshabilitar intercambio", + "disable_fiat": "Deshabilitar fiat", + "disable_sell": "Desactivar acción de venta", + "disabled": "Desactivado", + "discount": "Ahorra ${value}%", + "display_settings": "Configuración de pantalla", + "displayable": "Visualizable", + "do_not_have_enough_gas_asset": "No tienes suficiente ${currency} para realizar una transacción con las condiciones actuales de la red blockchain. Necesita más ${currency} para pagar las tarifas de la red blockchain, incluso si envía un activo diferente.", + "do_not_send": "no enviar", + "do_not_share_warning_text": "No comparta estos con nadie más, incluido el soporte.\n\n¡Sus fondos pueden ser y serán robados!", + "do_not_show_me": "no me muestres esto otra vez", + "domain_looks_up": "Búsquedas de dominio", + "donation_link_details": "Detalles del enlace de donación", + "e_sign_consent": "Consentimiento de firma electrónica", + "edit": "Editar", + "edit_backup_password": "Editar contraseña de respaldo", + "edit_node": "Editar nodo", + "edit_token": "Editar token", + "electrum_address_disclaimer": "Generamos nuevas direcciones cada vez que usa una, pero las direcciones anteriores siguen funcionando", + "email_address": "Dirección de correo electrónico", + "enabled": "Activado", + "enter_amount": "Ingrese la cantidad", + "enter_backup_password": "Ingrese la contraseña de respaldo aquí", + "enter_code": "Ingresar código", + "enter_seed_phrase": "Ingrese su frase de semillas", + "enter_totp_code": "Ingrese el código TOTP.", + "enter_your_note": "Ingresa tu nota…", + "enter_your_pin": "Introduce tu PIN", + "enter_your_pin_again": "Ingrese su PIN nuevamente", + "enterTokenID": "Ingrese el ID del token", + "enterWalletConnectURI": "Ingrese el URI de WalletConnect", + "error": "Error", + "error_dialog_content": "Vaya, tenemos un error.\n\nEnvíe el informe de bloqueo a nuestro equipo de soporte para mejorar la aplicación.", + "error_text_account_name": "El nombre de la cuenta solo puede contener letras, números \ny debe tener entre 1 y 15 caracteres de longitud", + "error_text_address": "La dirección de la billetera debe corresponder al tipo \nde criptomoneda", + "error_text_amount": "La cantidad solo puede contener números", + "error_text_contact_name": "El nombre del contacto no puede contener símbolos `, '\" \ny debe tener entre 1 y 32 caracteres de longitud", + "error_text_crypto_currency": "El número de dígitos fraccionarios \ndebe ser menor o igual a 12", + "error_text_fiat": "El valor de la cantidad no puede exceder el saldo disponible.\nEl número de dígitos de fracción debe ser menor o igual a 2", + "error_text_input_above_maximum_limit": "La cantidad es más que el máximo", + "error_text_input_below_minimum_limit": "La cantidad es menos que mínima", + "error_text_keys": "Las llaves de billetera solo pueden contener 64 caracteres en hexadecimal", + "error_text_limits_loading_failed": "El comercio por ${provider} no se crea. Límites de carga fallidos", + "error_text_maximum_limit": "El comercio por ${provider} no se crea. La cantidad es más que el máximo: ${max} ${currency}", + "error_text_minimal_limit": "El comercio por ${provider} no se crea. La cantidad es menos que mínima: ${min} ${currency}", + "error_text_node_address": "Por favor, introduzca una dirección iPv4", + "error_text_node_port": "El puerto de nodo solo puede contener números entre 0 y 65535", + "error_text_node_proxy_address": "Ingrese :, por ejemplo 127.0.0.1:9050", + "error_text_payment_id": "La ID de pago solo puede contener de 16 a 64 caracteres en hexadecimal", + "error_text_subaddress_name": "El nombre de la subdirección no puede contener símbolos `, '\" \ny debe tener entre 1 y 20 caracteres de longitud", + "error_text_template": "El nombre y la dirección de la plantilla no pueden contener símbolos ` , '\" \ny debe tener entre 1 y 106 caracteres de longitud", + "error_text_wallet_name": "El nombre de la billetera solo puede contener letras, números , _ - símbolos\ny debe tener entre 1 y 33 caracteres de longitud", + "error_text_xmr": "El valor XMR no puede exceder el saldo disponible.\nTEl número de dígitos de fracción debe ser menor o igual a 12", "errorGettingCredentials": "Error: error al obtener las credenciales", "errorSigningTransaction": "Se ha producido un error al firmar la transacción.", - "pairingInvalidEvent": "Evento de emparejamiento no válido", - "chains": "Cadenas", - "methods": "Métodos", - "events": "Eventos", - "reject": "Rechazar", - "approve": "Aprobar", - "expiresOn": "Expira el", - "walletConnect": "MonederoConectar", - "nullURIError": "URI es nula", - "connectWalletPrompt": "Conecte su billetera con WalletConnect para realizar transacciones", - "newConnection": "Nueva conexión", - "activeConnectionsPrompt": "Las conexiones activas aparecerán aquí", - "deleteConnectionConfirmationPrompt": "¿Está seguro de que desea eliminar la conexión a", + "estimated": "Estimado", + "etherscan_history": "historia de etherscan", "event": "Evento", - "successful": "Exitoso", - "wouoldLikeToConnect": "quisiera conectar", - "message": "Mensaje", - "do_not_have_enough_gas_asset": "No tienes suficiente ${currency} para realizar una transacción con las condiciones actuales de la red blockchain. Necesita más ${currency} para pagar las tarifas de la red blockchain, incluso si envía un activo diferente.", - "totp_auth_url": "URL de autenticación TOTP", - "awaitDAppProcessing": "Espere a que la dApp termine de procesarse.", - "copyWalletConnectLink": "Copie el enlace de WalletConnect de dApp y péguelo aquí", - "enterWalletConnectURI": "Ingrese el URI de WalletConnect", - "seed_key": "Llave de semilla", - "enter_seed_phrase": "Ingrese su frase de semillas", - "change_rep_successful": "Representante cambiado con éxito", - "add_contact": "Agregar contacto", + "events": "Eventos", + "exchange": "Intercambiar", + "exchange_incorrect_current_wallet_for_xmr": "Si desea intercambiar XMR de su saldo de Cake Wallet Monero, primero cambie a su billetera Monero.", + "exchange_new_template": "Nueva plantilla", "exchange_provider_unsupported": "¡${providerName} ya no es compatible!", - "domain_looks_up": "Búsquedas de dominio", - "require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas", - "camera_permission_is_required": "Se requiere permiso de la cámara.\nHabilítelo desde la configuración de la aplicación.", - "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente.", - "order_by": "Ordenar", - "creation_date": "Fecha de creación", + "exchange_result_confirm": "Al presionar confirmar, enviará ${fetchingLabel} ${from} desde su billetera llamada ${walletName} a la dirección que se muestra a continuación. O puede enviar desde su billetera externa a la siguiente dirección / código QR anterior.\n\nPresione confirmar para continuar o regrese para cambiar los montos.", + "exchange_result_description": "Debe enviar un mínimo de ${fetchingLabel} ${from} a la dirección que se muestra en la página siguiente. Si envía una cantidad inferior a ${fetchingLabel} ${from}, es posible que no se convierta y no se reembolse.", + "exchange_result_write_down_ID": "*Copie o escriba su identificación que se muestra arriba.", + "exchange_result_write_down_trade_id": "Por favor, copia o escribe el ID.", + "exchange_sync_alert_content": "Espere hasta que su billetera esté sincronizada", + "expired": "Muerto", + "expires": "Caduca", + "expiresOn": "Expira el", + "export_backup": "Exportar copia de seguridad", + "extra_id": "ID adicional:", + "extracted_address_content": "Enviará fondos a\n${recipient_name}", + "failed_authentication": "Autenticación fallida. ${state_error}", + "faq": "FAQ", + "fetching": "Cargando", + "fiat_api": "Fiat API", + "fiat_balance": "Equilibrio Fiat", + "field_required": "Este campo es obligatorio", + "fill_code": "Por favor complete el código de verificación proporcionado a su correo electrónico", + "filter_by": "Filtrado por", + "first_wallet_text": "Impresionante billetera para Monero, Bitcoin, Ethereum, Litecoin, y Haven", + "fixed_pair_not_supported": "Este par fijo no es compatible con los intercambios seleccionados", + "fixed_rate": "Tipo de interés fijo", + "fixed_rate_alert": "Podrá ingresar la cantidad recibida cuando el modo de tarifa fija esté marcado. ¿Quieres cambiar al modo de tarifa fija?", + "forgot_password": "Olvidé mi contraseña", + "freeze": "Congelar", + "frequently_asked_questions": "Preguntas frecuentes", + "frozen": "Congelada", + "full_balance": "Balance completo", + "generate_name": "Generar nombre", + "generating_gift_card": "Generando tarjeta de regalo", + "get_a": "Obtener un", + "get_card_note": " que puedes recargar con monedas digitales. ¡No se necesita información adicional!", + "get_your_yat": "Obtén tu Yat", + "gift_card_amount": "Cantidad de la tarjeta de regalo", + "gift_card_balance_note": "Las tarjetas de regalo con saldo restante aparecerán aquí", + "gift_card_is_generated": "Se genera la tarjeta de regalo", + "gift_card_number": "Número de tarjeta de regalo", + "gift_card_redeemed_note": "Las tarjetas de regalo que hayas canjeado aparecerán aquí", + "gift_cards": "Tarjetas de regalo", + "gift_cards_unavailable": "Las tarjetas de regalo están disponibles para comprar solo a través de Monero, Bitcoin y Litecoin en este momento", + "got_it": "Entendido", + "gross_balance": "Saldo bruto", "group_by_type": "Grupo por tipo", - "importNFTs": "Importar NFT", - "noNFTYet": "Aún no hay NFT", - "address": "DIRECCIÓN", - "enterTokenID": "Ingrese el ID del token", - "tokenID": "IDENTIFICACIÓN", - "name": "Nombre", - "symbol": "Símbolo", - "seed_phrase_length": "Longitud de la frase inicial", - "unavailable_balance": "Saldo no disponible", - "unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.", - "unspent_change": "Cambiar", - "tor_connection": "conexión tor", - "setup_warning_2fa_text": "Deberá restaurar su billetera a partir de la semilla mnemotécnica.\n\nEl soporte de Cake no podrá ayudarlo si pierde el acceso a su 2FA o a sus semillas mnemotécnicas.\nCake 2FA es una segunda autenticación para ciertas acciones en la billetera. Antes de usar Cake 2FA, recomendamos leer la guía.NO es tan seguro como el almacenamiento en frío.\n\nSi pierde el acceso a su aplicación 2FA o a sus claves TOTP, perderá el acceso a esta billetera. ", - "scan_qr_on_device": "Escanea este código QR en otro dispositivo", + "haven_app": "Haven by Cake Wallet", + "haven_app_wallet_text": "Awesome wallet for Haven", + "help": "ayuda", + "hidden_balance": "Balance oculto", + "hide_details": "Ocultar detalles", + "high_contrast_theme": "Tema de alto contraste", + "home_screen_settings": "Configuración de la pantalla de inicio", "how_to_use": "Cómo utilizar", + "how_to_use_card": "Cómo usar esta tarjeta", + "id": "ID: ", + "ignor": "Pasar por alto", + "import": "Importar", + "importNFTs": "Importar NFT", + "in_store": "En la tienda", + "incoming": "Entrante", + "incorrect_seed": "El texto ingresado no es válido.", + "introducing_cake_pay": "¡Presentamos Cake Pay!", + "invalid_input": "Entrada inválida", + "invoice_details": "Detalles de la factura", + "is_percentage": "es", + "last_30_days": "Últimos 30 días", + "learn_more": "Aprende más", + "light_theme": "Ligera", + "loading_your_wallet": "Cargando tu billetera", + "login": "Iniciar sesión", + "logout": "Cerrar sesión", + "low_fee": "Tarifa baja", + "low_fee_alert": "Actualmente está utilizando una prioridad de tarifa de red baja. Esto podría causar largas esperas, tarifas diferentes o transacciones canceladas. Recomendamos establecer una tarifa más alta para una mejor experiencia.", + "manage_nodes": "Administrar nodos", + "manage_pow_nodes": "Administrar nodos PoW", + "manage_yats": "Administrar Yats", + "mark_as_redeemed": "Marcar como canjeado", + "market_place": "Mercado", + "matrix_green_dark_theme": "Matrix verde oscuro tema", + "max_amount": "Máx: ${value}", + "max_value": "Max: ${value} ${currency}", + "memo": "Memorándum:", + "message": "Mensaje", + "methods": "Métodos", + "min_amount": "Mínimo: ${value}", + "min_value": "Min: ${value} ${currency}", + "minutes_to_pin_code": "${minute} minutos", + "mm": "mm", + "modify_2fa": "Modificar torta 2FA", + "monero_com": "Monero.com by Cake Wallet", + "monero_com_wallet_text": "Awesome wallet for Monero", + "monero_dark_theme": "Tema oscuro de Monero", + "monero_light_theme": "Tema ligero de Monero", + "moonpay_alert_text": "El valor de la cantidad debe ser mayor o igual a ${minAmount} ${fiatCurrency}", + "more_options": "Más Opciones", + "name": "Nombre", + "narrow": "Angosto", + "new_first_wallet_text": "Mantenga fácilmente su criptomoneda segura", + "new_node_testing": "Prueba de nuevos nodos", + "new_subaddress_create": "Crear", + "new_subaddress_label_name": "Nombre de etiqueta", + "new_subaddress_title": "Nueva direccion", + "new_template": "Nueva plantilla", + "new_wallet": "Nueva billetera", + "newConnection": "Nueva conexión", + "no_id_needed": "¡No se necesita identificación!", + "no_id_required": "No se requiere identificación. Recargue y gaste en cualquier lugar", + "no_relay_on_domain": "No hay una retransmisión para el dominio del usuario o la retransmisión no está disponible. Elija un relé para usar.", + "no_relays": "Sin relevos", + "no_relays_message": "Encontramos un registro Nostr NIP-05 para este usuario, pero no contiene ningún relé. Indique al destinatario que agregue retransmisiones a su registro Nostr.", + "node_address": "Dirección de nodo", + "node_connection_failed": "La conexión falló", + "node_connection_successful": "La conexión fue exitosa", + "node_new": "Nuevo nodo", + "node_port": "Puerto de nodo", + "node_reset_settings_title": "Reiniciar ajustes", + "node_test": "Prueba", + "nodes": "Nodos", + "nodes_list_reset_to_default_message": "¿Está seguro de que desea restablecer la configuración predeterminada?", + "none_of_selected_providers_can_exchange": "Ninguno de los proveedores seleccionados puede realizar este intercambio", + "noNFTYet": "Aún no hay NFT", + "normal": "Normal", + "note_optional": "Nota (opcional)", + "note_tap_to_change": "Nota (toque para cambiar)", + "nullURIError": "URI es nula", + "offer_expires_in": "Oferta expira en: ", + "offline": "fuera de línea", + "ok": "OK", + "onion_link": "Enlace de cebolla", + "online": "En línea", + "onramper_option_description": "Compre 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", + "optional_description": "Descripción opcional", + "optional_email_hint": "Correo electrónico de notificación del beneficiario opcional", + "optional_name": "Nombre del destinatario opcional", + "optionally_order_card": "Opcionalmente pide una tarjeta física.", + "orbot_running_alert": "Asegúrese de que Orbot se esté ejecutando antes de conectarse a este nodo.", + "order_by": "Ordenar", + "order_id": "Identificación del pedido", + "order_physical_card": "Pedir tarjeta física", + "other_settings": "Otras configuraciones", + "outdated_electrum_wallet_description": "Las nuevas carteras de Bitcoin creadas en Cake ahora tienen una semilla de 24 palabras. Es obligatorio que cree una nueva billetera de Bitcoin y transfiera todos sus fondos a la nueva billetera de 24 palabras, y deje de usar billeteras con una semilla de 12 palabras. Haga esto de inmediato para asegurar sus fondos.", + "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", + "overwrite_amount": "Overwrite amount", + "pairingInvalidEvent": "Evento de emparejamiento no válido", + "password": "Contraseña", + "paste": "Pegar", + "pause_wallet_creation": "La capacidad para crear Haven Wallet está actualmente pausada.", + "payment_id": "ID de pago: ", + "payment_was_received": "Su pago fue recibido.", + "pending": " (pendiente)", + "percentageOf": "de ${amount}", + "personalizado": "personalizado", + "pin_at_top": "pin ${token} en la parte superior", + "pin_is_incorrect": "PIN es incorrecto", + "pin_number": "Número PIN", + "placeholder_contacts": "Tus contactos se mostrarán aquí", + "placeholder_transactions": "Sus transacciones se mostrarán aquí", + "please_fill_totp": "Complete el código de 8 dígitos presente en su otro dispositivo", + "please_make_selection": "Seleccione a continuación para crear o recuperar su billetera.", + "please_reference_document": "Consulte los documentos a continuación para obtener más información.", + "please_select": "Por favor seleccione:", + "please_select_backup_file": "Seleccione el archivo de respaldo e ingrese la contraseña de respaldo.", + "please_try_to_connect_to_another_node": "Intenta conectarte a otro nodo", + "please_wait": "Espere por favor", + "polygonscan_history": "Historial de PolygonScan", + "powered_by": "Energizado por ${title}", + "pre_seed_button_text": "Entiendo. Muéstrame mi semilla", + "pre_seed_description": "En la página siguiente verá una serie de ${words} palabras. Esta es su semilla única y privada y es la ÚNICA forma de recuperar su billetera en caso de pérdida o mal funcionamiento. Es SU responsabilidad escribirlo y guardarlo en un lugar seguro fuera de la aplicación Cake Wallet.", + "pre_seed_title": "IMPORTANTE", + "prevent_screenshots": "Evitar capturas de pantalla y grabación de pantalla", + "privacy": "Privacidad", + "privacy_policy": "Política de privacidad", + "privacy_settings": "Configuración de privacidad", + "private_key": "Clave privada", + "proceed_after_one_minute": "Si la pantalla no continúa después de 1 minuto, revisa tu correo electrónico.", + "profile": "Perfil", + "provider_error": "${provider} error", + "public_key": "Clave pública", + "purchase_gift_card": "Comprar tarjeta de regalo", + "qr_fullscreen": "Toque para abrir el código QR en pantalla completa", + "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", + "question_to_disable_2fa": "¿Está seguro de que desea deshabilitar Cake 2FA? Ya no se necesitará un código 2FA para acceder a la billetera y a ciertas funciones.", + "receivable_balance": "Saldo de cuentas por cobrar", + "receive": "Recibir", + "receive_amount": "Cantidad", + "received": "Recibido", + "recipient_address": "Dirección del receptor", + "reconnect": "Volver a conectar", + "reconnect_alert_text": "¿Estás seguro de reconectar?", + "reconnection": "Reconexión", + "redeemed": "Redimido", + "refund_address": "Dirección de reembolso", + "reject": "Rechazar", + "remaining": "restante", + "remove": "Retirar", + "remove_node": "Eliminar nodo", + "remove_node_message": "¿Está seguro de que desea eliminar el nodo seleccionado?", + "rename": "Rebautizar", + "require_for_adding_contacts": "Requerido para agregar contactos", + "require_for_all_security_and_backup_settings": "Requerido para todas las configuraciones de seguridad y copia de seguridad", + "require_for_assessing_wallet": "Requerido para acceder a la billetera", + "require_for_creating_new_wallets": "Requerido para crear nuevas billeteras", + "require_for_exchanges_to_external_wallets": "Requerido para intercambios a billeteras externas", + "require_for_exchanges_to_internal_wallets": "Requerido para intercambios a billeteras internas", + "require_for_sends_to_contacts": "Requerir para envíos a contactos", + "require_for_sends_to_internal_wallets": "Requerido para envíos a billeteras internas", + "require_for_sends_to_non_contacts": "Requerido para envíos a no contactos", + "require_pin_after": "Requerir PIN después de", + "rescan": "Reescanear", + "resend_code": "Por favor reenvíalo", + "reset": "Reiniciar", + "reset_password": "Restablecer contraseña", + "restore_active_seed": "Semilla activa", + "restore_address": "Dirección", + "restore_bitcoin_description_from_keys": "Restaure su billetera a partir de una cadena WIF generada a partir de sus claves privadas", + "restore_bitcoin_description_from_seed": "Restaure su billetera a partir del código de combinación de 24 palabras", + "restore_bitcoin_title_from_keys": "Restaurar desde WIF", + "restore_description_from_backup": "Puede restaurar toda la aplicación Cake Wallet desde ysu archivo de respaldo", + "restore_description_from_keys": "Restaure su billetera de las pulsaciones de teclas generadas guardadas de sus claves privadas", + "restore_description_from_seed": "Restaure su billetera desde el código de combinación de 25 palabras i de 13 palabras", + "restore_description_from_seed_keys": "Recupere su billetera de las semillas/claves que ha guardado en un lugar seguro", + "restore_from_date_or_blockheight": "Ingrese una fecha unos días antes de crear esta billetera. O si conoce la altura del bloque, ingréselo en su lugar", + "restore_from_seed_placeholder": "Ingrese o pegue su frase de código aquí", + "restore_new_seed": "Nueva semilla", + "restore_next": "Próximo", + "restore_recover": "Recuperar", + "restore_restore_wallet": "Recuperar Cartera", + "restore_seed_keys_restore": "Restauración de semillas / llaves", + "restore_spend_key_private": "Spend clave (privado)", + "restore_title_from_backup": "Restaurar desde un archivo de respaldo", + "restore_title_from_keys": "De las claves", + "restore_title_from_seed": "De la semilla", + "restore_title_from_seed_keys": "Restaurar desde semilla/claves", + "restore_view_key_private": "View clave (privado)", + "restore_wallet": "Restaurar billetera", + "restore_wallet_name": "Nombre de la billetera", + "restore_wallet_restore_description": "Restaurar billetera", + "router_no_route": "No hay ruta definida para ${name}", + "save": "Salvar", + "save_backup_password": "Asegúrese de haber guardado su contraseña de respaldo. No podrá importar sus archivos de respaldo sin él.", + "save_backup_password_alert": "Guardar contraseña de respaldo", + "save_to_downloads": "Guardar en Descargas", + "saved_the_trade_id": "He salvado comercial ID", + "scan_qr_code": "Escanear código QR", + "scan_qr_code_to_get_address": "Escanee el código QR para obtener la dirección", + "scan_qr_on_device": "Escanea este código QR en otro dispositivo", + "search": "Búsqueda", + "search_add_token": "Buscar/Agregar token", + "search_category": "Categoría de búsqueda", + "search_currency": "Moneda de búsqueda", + "search_language": "Idioma de búsqueda", + "second_intro_content": "Tu Yat es una única dirección emoji única que reemplaza todas tus direcciones hexadecimales largas para todas tus monedas.", + "second_intro_title": "Una dirección de emoji para gobernarlos a todos", + "security_and_backup": "Seguridad y respaldo", + "seed_alert_back": "Regresa", + "seed_alert_content": "La semilla es la única forma de recuperar su billetera. ¿Lo has escrito?", + "seed_alert_title": "Atención", + "seed_alert_yes": "Sí tengo", + "seed_choose": "Elige el idioma semilla", "seed_hex_form": "Semilla de billetera (forma hexadecimal)", + "seed_key": "Llave de semilla", + "seed_language": "Lenguaje de semillas", + "seed_language_chinese": "Chino", + "seed_language_chinese_traditional": "Chino (tradicional)", + "seed_language_czech": "checo", + "seed_language_dutch": "Holandés", + "seed_language_english": "Inglés", + "seed_language_french": "Francesa/Francés", + "seed_language_german": "Alemán", + "seed_language_italian": "Italiana/Italiano", + "seed_language_japanese": "Japonés", + "seed_language_korean": "coreano", + "seed_language_next": "Próximo", + "seed_language_portuguese": "Portugués", + "seed_language_russian": "Ruso", + "seed_language_spanish": "Español", + "seed_phrase_length": "Longitud de la frase inicial", + "seed_reminder": "Anótelos en caso de que pierda o borre su teléfono", + "seed_share": "Compartir semillas", + "seed_title": "Semilla", "seedtype": "Type de semillas", "seedtype_legacy": "Legado (25 palabras)", "seedtype_polyseed": "Polieta (16 palabras)", - "seed_language_czech": "checo", - "seed_language_korean": "coreano", - "ascending": "Ascendente", - "descending": "Descendente", - "dfx_option_description": "Compre criptomonedas con EUR y CHF. Hasta 990€ sin KYC adicional. Para clientes minoristas y corporativos en Europa", - "seed_language_chinese_traditional": "Chino (tradicional)", - "polygonscan_history": "Historial de PolygonScan", - "wallet_seed_legacy": "Semilla de billetera heredada", - "default_sell_provider": "Proveedor de venta predeterminado", + "select_backup_file": "Seleccionar archivo de respaldo", + "select_buy_provider_notice": "Seleccione un proveedor de compra arriba. Puede omitir esta pantalla configurando su proveedor de compra predeterminado en la configuración de la aplicación.", + "select_destination": "Seleccione el destino del archivo de copia de seguridad.", "select_sell_provider_notice": "Seleccione un proveedor de venta arriba. Puede omitir esta pantalla configurando su proveedor de venta predeterminado en la configuración de la aplicación.", - "custom_drag": "Custom (mantenía y arrastre)", + "sell": "Vender", + "sell_alert_content": "Actualmente solo admitimos la venta de Bitcoin, Ethereum y Litecoin. Cree o cambie a su billetera Bitcoin, Ethereum o Litecoin.", + "sell_monero_com_alert_content": "Aún no se admite la venta de Monero", + "send": "Enviar", + "send_address": "Dirección de ${cryptoCurrency}", + "send_amount": "Cantidad:", + "send_creating_transaction": "Creando transacción", + "send_error_currency": "La moneda solo puede contener números", + "send_error_minimum_value": "El valor mínimo de la cantidad es 0.01", + "send_estimated_fee": "Tarifa estimada:", + "send_fee": "Cuota:", + "send_name": "Nombre", + "send_new": "Nuevo", + "send_payment_id": "ID de pago (opcional)", + "send_priority": "Actualmente la tarifa se establece en ${transactionPriority} prioridad.\nLa prioridad de la transacción se puede ajustar en la configuración", + "send_sending": "Enviando...", + "send_success": "Su ${crypto} fue enviado con éxito", + "send_templates": "Plantillas", + "send_title": "Enviar", + "send_to_this_address": "Enviar ${currency} ${tag}a esta dirección", + "send_xmr": "Enviar XMR", + "send_your_wallet": "Tu billetera", + "sending": "Enviando", + "sent": "Expedido", + "settings": "Configuraciones", + "settings_all": "TODOS", + "settings_allow_biometrical_authentication": "Permitir autenticación biométrica", + "settings_can_be_changed_later": "Estas configuraciones se pueden cambiar más tarde en la configuración de la aplicación", + "settings_change_language": "Cambiar idioma", + "settings_change_pin": "Cambiar PIN", + "settings_currency": "Moneda", + "settings_current_node": "Nodo actual", + "settings_dark_mode": "Modo oscuro", + "settings_display_balance": "Mostrar saldo", + "settings_display_on_dashboard_list": "Mostrar en la lista del tablero", + "settings_fee_priority": "Prioridad de tasa", + "settings_nodes": "Nodos", + "settings_none": "Ninguno", + "settings_only_trades": "Solo comercia", + "settings_only_transactions": "Solo transacciones", + "settings_personal": "Personal", + "settings_save_recipient_address": "Guardar dirección del destinatario", + "settings_support": "Apoyo", + "settings_terms_and_conditions": "Términos y Condiciones", + "settings_title": "Configuraciones", + "settings_trades": "Comercia", + "settings_transactions": "Transacciones", + "settings_wallets": "Carteras", + "setup_2fa": "Configurar pastel 2FA", + "setup_2fa_text": "Cake 2FA funciona utilizando TOTP como segundo factor de autenticación.\n\nEl TOTP de Cake 2FA requiere SHA-512 y soporte de 8 dígitos; esto proporciona una mayor seguridad. Puede encontrar más información y aplicaciones compatibles en la guía.", + "setup_pin": "PIN de configuración", + "setup_successful": "Su PIN se ha configurado correctamente!", + "setup_totp_recommended": "Configurar TOTP", + "setup_warning_2fa_text": "Deberá restaurar su billetera a partir de la semilla mnemotécnica.\n\nEl soporte de Cake no podrá ayudarlo si pierde el acceso a su 2FA o a sus semillas mnemotécnicas.\nCake 2FA es una segunda autenticación para ciertas acciones en la billetera. Antes de usar Cake 2FA, recomendamos leer la guía.NO es tan seguro como el almacenamiento en frío.\n\nSi pierde el acceso a su aplicación 2FA o a sus claves TOTP, perderá el acceso a esta billetera. ", + "setup_your_debit_card": "Configura tu tarjeta de débito", + "share": "Compartir", + "share_address": "Compartir dirección", + "show_details": "Mostrar detalles", + "show_keys": "Mostrar semilla/claves", + "show_market_place": "Mostrar mercado", + "show_seed": "Mostrar semilla", + "sign_up": "Registrarse", + "signTransaction": "Firmar transacción", + "signup_for_card_accept_terms": "Regístrese para obtener la tarjeta y acepte los términos.", + "slidable": "deslizable", + "sort_by": "Ordenar por", + "spend_key_private": "Spend clave (privado)", + "spend_key_public": "Spend clave (público)", + "status": "Estado: ", + "subaddress_title": "Lista de subdirecciones", + "subaddresses": "Subdirecciones", + "submit_request": "presentar una solicitud", + "successful": "Exitoso", + "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": "Únase a nuestras comunidades o comuníquese con nosotros nuestros socios a través de otros métodos", + "support_title_guides": "Guías de billetera para pastel", + "support_title_live_chat": "Soporte vital", + "support_title_other_links": "Otros enlaces de soporte", + "sweeping_wallet": "Billetera de barrido", + "sweeping_wallet_alert": "Esto no debería llevar mucho tiempo. NO DEJES ESTA PANTALLA O SE PUEDEN PERDER LOS FONDOS BARRIDOS", + "switchToETHWallet": "Cambie a una billetera Ethereum e inténtelo nuevamente.", "switchToEVMCompatibleWallet": "Cambie a una billetera compatible con EVM e inténtelo nuevamente (Ethereum, Polygon)", - "receivable_balance": "Saldo de cuentas por cobrar", - "confirmed_tx": "Confirmado", + "symbol": "Símbolo", + "sync_all_wallets": "Sincronizar todas las billeteras", + "sync_status_attempting_sync": "INTENTAR SINCRONIZAR", + "sync_status_connected": "CONECTADO", + "sync_status_connecting": "CONECTANDO", + "sync_status_failed_connect": "DESCONECTADO", + "sync_status_not_connected": "NO CONECTADO", + "sync_status_starting_sync": "EMPEZANDO A SINCRONIZAR", + "sync_status_syncronized": "SINCRONIZADO", + "sync_status_syncronizing": "SINCRONIZANDO", + "syncing_wallet_alert_content": "Es posible que su lista de saldo y transacciones no esté completa hasta que diga \"SINCRONIZADO\" en la parte superior. Haga clic/toque para obtener más información.", + "syncing_wallet_alert_title": "Tu billetera se está sincronizando", + "template": "Plantilla", + "template_name": "Nombre de la plantilla", + "third_intro_content": "Los Yats también viven fuera de Cake Wallet. Cualquier dirección de billetera en la tierra se puede reemplazar con un Yat!", + "third_intro_title": "Yat juega muy bien con otras", + "time": "${minutes}m ${seconds}s", + "tip": "Consejo:", + "today": "Hoy", + "token_contract_address": "Dirección de contrato de token", + "token_decimal": "Token decimal", + "token_name": "Nombre del token, por ejemplo: Tether", + "token_symbol": "Símbolo de token, por ejemplo: USDT", + "tokenID": "IDENTIFICACIÓN", + "tor_connection": "conexión tor", + "tor_only": "solo Tor", + "total_saving": "Ahorro Total", + "totp_2fa_failure": "Código incorrecto. Intente con un código diferente o genere una nueva clave secreta. Use una aplicación 2FA compatible que admita códigos de 8 dígitos y SHA512.", + "totp_2fa_success": "¡Éxito! Cake 2FA habilitado para esta billetera. Recuerde guardar su semilla mnemotécnica en caso de que pierda el acceso a la billetera.", + "totp_auth_url": "URL de autenticación TOTP", + "totp_code": "Código TOTP", + "totp_secret_code": "Código secreto TOTP", + "totp_verification_success": "¡Verificación exitosa!", + "trade_details_copied": "${title} Copiado al portapapeles", + "trade_details_created_at": "Creado en", + "trade_details_fetching": "Cargando", + "trade_details_id": "ID", + "trade_details_pair": "Par", + "trade_details_provider": "Proveedor", + "trade_details_state": "Estado", + "trade_details_title": "Detalles comerciales", + "trade_for_not_created": "Comercio por ${title} no se crea.", + "trade_history_title": "Historia del comercio", + "trade_id": "Comercial ID:", + "trade_id_not_found": "Comercio ${tradeId} de ${title} no encontrado.", + "trade_is_powered_by": "Este comercio es impulsado por ${provider}", + "trade_not_created": "Comercio no se crea", + "trade_not_found": "Comercio no encontrado.", + "trade_state_btc_sent": "Btc expedido", + "trade_state_complete": "Completar", + "trade_state_confirming": "Confirmando", + "trade_state_created": "Creado", + "trade_state_finished": "Terminado", + "trade_state_paid": "Pagado", + "trade_state_paid_unconfirmed": "Pagado sin confirmar", + "trade_state_pending": "Pendiente", + "trade_state_timeout": "Se acabó el tiempo", + "trade_state_to_be_created": "Ser creado", + "trade_state_traded": "Negociado", + "trade_state_trading": "Comercio", + "trade_state_underpaid": "Poco pagado", + "trade_state_unpaid": "No pagado", + "trades": "Cambios", + "transaction_details_amount": "Cantidad", + "transaction_details_copied": "${title} Copiado al portapapeles", + "transaction_details_date": "Fecha", + "transaction_details_fee": "Cuota", + "transaction_details_height": "Altura", + "transaction_details_recipient_address": "Direcciones de destinatarios", "transaction_details_source_address": "Dirección de la fuente", - "pause_wallet_creation": "La capacidad para crear Haven Wallet está actualmente pausada.", - "contractName": "Nombre del contrato", - "contractSymbol": "Símbolo de contrato", - "description": "Descripción", - "camera_consent": "Su cámara será utilizada para capturar una imagen con fines de identificación por ${provider}. Consulte su Política de privacidad para obtener más detalles.", - "no_relays": "Sin relevos", - "choose_relay": "Por favor elija un relé para usar", - "no_relays_message": "Encontramos un registro Nostr NIP-05 para este usuario, pero no contiene ningún relé. Indique al destinatario que agregue retransmisiones a su registro Nostr.", - "no_relay_on_domain": "No hay una retransmisión para el dominio del usuario o la retransmisión no está disponible. Elija un relé para usar." -} + "transaction_details_title": "Detalles de la transacción", + "transaction_details_transaction_id": "ID de transacción", + "transaction_key": "Clave de transacción", + "transaction_priority_fast": "Rápido", + "transaction_priority_fastest": "Lo más rápido", + "transaction_priority_medium": "Medio", + "transaction_priority_regular": "Regular", + "transaction_priority_slow": "Lento", + "transaction_sent": "Transacción enviada!", + "transaction_sent_notice": "Si la pantalla no continúa después de 1 minuto, revisa un explorador de bloques y tu correo electrónico.", + "transactions": "Actas", + "transactions_by_date": "Transacciones por fecha", + "trusted": "de confianza", + "unavailable_balance": "Saldo no disponible", + "unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.", + "unconfirmed": "Saldo no confirmado", + "understand": "Entiendo", + "unmatched_currencies": "La moneda de su billetera actual no coincide con la del QR escaneado", + "unspent_change": "Cambiar", + "unspent_coins_details_title": "Detalles de monedas no gastadas", + "unspent_coins_title": "Monedas no gastadas", + "unsupported_asset": "No admitimos esta acción para este activo. Cree o cambie a una billetera de un tipo de activo admitido.", + "upto": "hasta ${value}", + "use": "Utilizar a ", + "use_card_info_three": "Utilice la tarjeta digital en línea o con métodos de pago sin contacto.", + "use_card_info_two": "Los fondos se convierten a USD cuando se mantienen en la cuenta prepaga, no en monedas digitales.", + "use_ssl": "Utilice SSL", + "use_suggested": "Usar sugerido", + "variable_pair_not_supported": "Este par de variables no es compatible con los intercambios seleccionados", + "verification": "Verificación", + "verify_with_2fa": "Verificar con Cake 2FA", + "version": "Versión ${currentVersion}", + "view_all": "Ver todo", + "view_in_block_explorer": "View in Block Explorer", + "view_key_private": "View clave (privado)", + "view_key_public": "View clave (público)", + "view_transaction_on": "View Transaction on ", + "wallet_keys": "Billetera semilla/claves", + "wallet_list_create_new_wallet": "Crear nueva billetera", + "wallet_list_edit_wallet": "Editar billetera", + "wallet_list_failed_to_load": "No se pudo cargar ${wallet_name} la billetera. ${error}", + "wallet_list_failed_to_remove": "Error al elimina ${wallet_name} billetera. ${error}", + "wallet_list_load_wallet": "Billetera de carga", + "wallet_list_loading_wallet": "Billetera ${wallet_name} de carga", + "wallet_list_removing_wallet": "Retirar ${wallet_name} billetera", + "wallet_list_restore_wallet": "Restaurar billetera", + "wallet_list_title": "Monedero Monero", + "wallet_list_wallet_name": "Nombre de la billetera", + "wallet_menu": "Menú de billetera", + "wallet_name": "Nombre de la billetera", + "wallet_name_exists": "Wallet con ese nombre ya ha existido", + "wallet_restoration_store_incorrect_seed_length": "Longitud de semilla incorrecta", + "wallet_seed": "Semilla de billetera", + "wallet_seed_legacy": "Semilla de billetera heredada", + "wallet_store_monero_wallet": "Monedero Monero", + "walletConnect": "MonederoConectar", + "wallets": "Carteras", + "warning": "Advertencia", + "welcome": "Bienvenido", + "welcome_to_cakepay": "¡Bienvenido a Cake Pay!", + "widgets_address": "Dirección", + "widgets_or": "o", + "widgets_restore_from_blockheight": "Restaurar desde blockheight", + "widgets_restore_from_date": "Restaurar desde fecha", + "widgets_seed": "Semilla", + "wouoldLikeToConnect": "quisiera conectar", + "write_down_backup_password": "Escriba su contraseña de respaldo, que se utiliza para la importación de sus archivos de respaldo.", + "xlm_extra_info": "No olvide especificar el ID de nota al enviar la transacción XLM para el intercambio", + "xmr_available_balance": "Saldo disponible", + "xmr_full_balance": "Balance total", + "xmr_hidden": "Oculto", + "xmr_to_error": "Error de XMR.TO", + "xmr_to_error_description": "Monto invalido. Límite máximo de 8 dígitos después del punto decimal", + "xrp_extra_info": "No olvide especificar la etiqueta de destino al enviar la transacción XRP para el intercambio", + "yat": "Yat", + "yat_address": "Dirección de Yat", + "yat_alert_content": "Los usuarios de Cake Wallet ahora pueden enviar y recibir todas sus monedas favoritas con un nombre de usuario único basado en emoji.", + "yat_alert_title": "Envíe y reciba criptomonedas más fácilmente con Yat", + "yat_error": "Error de Yat", + "yat_error_content": "No hay direcciones vinculadas con este Yat. Prueba con otro Yat", + "yat_popup_content": "Ahora puede enviar y recibir criptografía en Cake Wallet con su Yat, un nombre de usuario corto basado en emoji. Administre Yats en cualquier momento en la pantalla de configuración", + "yat_popup_title": "La dirección de su billetera se puede emojificar.", + "yesterday": "Ayer", + "you_now_have_debit_card": "Ahora tiene una tarjeta de débito", + "you_pay": "Tú pagas", + "you_will_get": "Convertir a", + "you_will_send": "Convertir de", + "yy": "YY", + "zzzz": "zzzz" +} \ No newline at end of file diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 523253bf4..fc72c06db 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -1,779 +1,780 @@ { - "welcome": "Bienvenue sur", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Super portefeuille (wallet) pour Monero, Bitcoin, Ethereum, Litecoin et Haven", - "please_make_selection": "Merci de faire un choix ci-dessous pour créer ou restaurer votre portefeuille (wallet).", - "create_new": "Créer un Nouveau Portefeuille (Wallet)", - "restore_wallet": "Restaurer un Portefeuille (Wallet)", - "monero_com": "Monero.com par Cake Wallet", - "monero_com_wallet_text": "Super portefeuille (wallet) pour Monero", - "haven_app": "Haven par Cake Wallet", - "haven_app_wallet_text": "Super portefeuille (wallet) pour Haven", - "accounts": "Comptes", - "edit": "Modifier", + "about_cake_pay": "Cake Pay vous permet d'acheter facilement des cartes-cadeaux avec des actifs virtuels, utilisables instantanément chez plus de 150 000 marchands aux États-Unis.", "account": "Compte", + "accounts": "Comptes", + "accounts_subaddresses": "Comptes et sous-adresses", + "activate": "Activer", + "active": "Actives", + "active_cards": "Cartes actives", + "activeConnectionsPrompt": "Les connexions actives apparaîtront ici", "add": "Ajouter", + "add_contact": "Ajouter le contact", + "add_custom_node": "Ajouter un nouveau nœud personnalisé", + "add_custom_redemption": "Ajouter un remboursement personnalisé", + "add_fund_to_card": "Ajouter des fonds prépayés aux cartes (jusqu'à ${value})", + "add_new_node": "Ajouter un nouveau nœud", + "add_new_word": "Ajouter un nouveau mot", + "add_receiver": "Ajouter un autre bénéficiaire (optionnel)", + "add_secret_code": "Ou ajoutez ce code secret à une application d'authentification", + "add_tip": "Ajouter un pourboire", + "add_token_disclaimer_check": "J'ai confirmé l'adresse et les informations du contrat de token en utilisant une source fiable. L'ajout d'informations malveillantes ou incorrectes peut entraîner une perte de fonds.", + "add_token_warning": "Ne modifiez pas ou n'ajoutez pas de tokens comme pourraient vous le suggérer des escrocs.\nConfirmez toujours les adresses de token auprès de sources fiables !", + "add_value": "Ajouter une valeur", + "address": "Adresse", "address_book": "Carnet d'Adresses", - "contact": "Contact", - "please_select": "Merci de sélectionner :", - "cancel": "Annuler", - "ok": "OK", - "contact_name": "Nom de Contact", - "reset": "Réinitialiser", - "save": "Sauvegarder", + "address_book_menu": "Carnet d'Adresses", + "address_detected": "Adresse détectée", + "address_from_domain": "Cette adresse est issue de ${domain} sur Unstoppable Domains", + "address_from_yat": "Cette adresse est issue de ${emoji} sur Yat", + "address_label": "Nom de l'adresse", "address_remove_contact": "Supprimer le contact", "address_remove_content": "Êtes vous certain de vouloir supprimer le contact sélectionné ?", - "authenticated": "Authentifié", - "authentication": "Authentification", - "failed_authentication": "Échec d'authentification. ${state_error}", - "wallet_menu": "Menu", - "Blocks_remaining": "Blocs Restants : ${status}", - "please_try_to_connect_to_another_node": "Merci d'essayer la connexion vers un autre nœud", - "xmr_hidden": "Caché", - "xmr_available_balance": "Solde Disponible", - "xmr_full_balance": "Solde Total", - "send": "Envoyer", - "receive": "Recevoir", - "transactions": "Transactions", - "incoming": "Entrantes", - "outgoing": "Sortantes", - "transactions_by_date": "Transactions par date", - "trades": "Échanges", - "filter_by": "Filtrer par", - "today": "Aujourd'hui", - "yesterday": "Hier", - "received": "Reçus", - "sent": "Envoyés", - "pending": " (en attente)", - "rescan": "Analyser la blockchain", - "reconnect": "Reconnecter", - "wallets": "Portefeuilles (Wallets)", - "show_seed": "Visualiser la phrase secrète (seed)", - "show_keys": "Visualiser la phrase secrète (seed) et les clefs", - "address_book_menu": "Carnet d'Adresses", - "reconnection": "Reconnexion", - "reconnect_alert_text": "Êtes vous certain de vouloir vous reconnecter ?", - "exchange": "Échanger", - "clear": "Effacer", - "refund_address": "Adresse de Remboursement", - "change_exchange_provider": "Changer de Plateforme d'Échange", - "you_will_send": "Convertir depuis", - "you_will_get": "Convertir vers", - "amount_is_guaranteed": "Le montant reçu est garanti", - "amount_is_estimate": "Le montant reçu est estimé", - "powered_by": "Proposé par ${title}", - "error": "Erreur", - "estimated": "Estimé", - "min_value": "Min: ${value} ${currency}", - "max_value": "Max: ${value} ${currency}", - "change_currency": "Changer de Devise", - "overwrite_amount": "Remplacer le montant", - "qr_payment_amount": "Ce QR code contient un montant de paiement. Voulez-vous remplacer la valeur actuelle ?", - "copy_id": "Copier l'ID", - "exchange_result_write_down_trade_id": "Merci de copier ou d'écrire l'ID d'échange pour continuer.", - "trade_id": "ID d'échange :", - "copied_to_clipboard": "Copié vers le Presse-Papier", - "saved_the_trade_id": "J'ai sauvegardé l'ID d'échange", - "fetching": "Récupération", - "id": "ID : ", - "amount": "Montant : ", - "payment_id": "ID de Paiement : ", - "status": "Statut : ", - "offer_expires_in": "L'Offre expire dans : ", - "trade_is_powered_by": "Cet échange est proposé par ${provider}", - "copy_address": "Copier l'Adresse", - "exchange_result_confirm": "En pressant confirmer, vous enverrez ${fetchingLabel} ${from} depuis votre portefeuille (wallet) nommé ${walletName} vers l'adresse ci-dessous. Vous pouvez aussi envoyer depuis votre portefeuille externe vers l'adresse/QR code ci-dessous.\n\nMerci d'appuyer sur confirmer pour continuer ou retournez en arrière pour modifier les montants.", - "exchange_result_description": "Vous devez envoyer un minimum de ${fetchingLabel} ${from} à l'adresse indiquée page suivante. Si vous envoyez un montant inférieur à ${fetchingLabel} ${from} il pourrait ne pas être converti et ne pas être remboursé.", - "exchange_result_write_down_ID": "*Merci de copier ou écrire votre ID présenté ci-dessus.", - "confirm": "Confirmer", - "confirm_sending": "Confirmer l'envoi", - "commit_transaction_amount_fee": "Valider la transaction\nMontant : ${amount}\nFrais : ${fee}", - "sending": "Envoi", - "transaction_sent": "Transaction émise !", - "expired": "Expirée", - "time": "${minutes}m ${seconds}s", - "send_xmr": "Envoyer XMR", - "exchange_new_template": "Nouveau modèle d'échange", - "faq": "FAQ", - "enter_your_pin": "Entrez votre code PIN", - "loading_your_wallet": "Chargement de votre portefeuille (wallet)", - "new_wallet": "Nouveau Portefeuille (Wallet)", - "wallet_name": "Nom du Portefeuille (Wallet)", - "continue_text": "Continuer", - "choose_wallet_currency": "Merci de choisir la devise du portefeuille (wallet) :", - "node_new": "Nouveau Nœud", - "node_address": "Adresse du Nœud", - "node_port": "Port du Nœud", - "login": "Utilisateur", - "password": "Mot de passe", - "nodes": "Nœuds", - "node_reset_settings_title": "Réinitialisation des réglages", - "nodes_list_reset_to_default_message": "Êtes vous certain de vouloir revenir aux réglages par défaut ?", - "change_current_node": "Êtes vous certain de vouloir changer le nœud actuel pour ${node} ?", - "change": "Changer", - "remove_node": "Supprimer le nœud", - "remove_node_message": "Êtes vous certain de vouloir supprimer le nœud sélectionné ?", - "remove": "Supprimer", - "delete": "Effacer", - "add_new_node": "Ajouter un nouveau nœud", - "change_current_node_title": "Changer le nœud actuel", - "node_test": "Tester", - "node_connection_successful": "Connexion établie avec succès", - "node_connection_failed": "La connexion a échoué", - "new_node_testing": "Test du nouveau nœud", - "use": "Changer vers code PIN à ", - "digit_pin": " chiffres", - "share_address": "Partager l'adresse", - "receive_amount": "Montant", - "subaddresses": "Sous-adresses", "addresses": "Adresses", - "scan_qr_code_to_get_address": "Scannez le QR code pour obtenir l'adresse", - "qr_fullscreen": "Appuyez pour ouvrir le QR code en mode plein écran", - "rename": "Renommer", - "choose_account": "Choisir le compte", - "create_new_account": "Créer un nouveau compte", - "accounts_subaddresses": "Comptes et sous-adresses", - "restore_restore_wallet": "Restaurer le Portefeuille (Wallet)", - "restore_title_from_seed_keys": "Restaurer depuis une phrase secrète (seed) ou des clefs", - "restore_description_from_seed_keys": "Restaurez votre portefeuille (wallet) depuis une phrase secrète (seed) ou des clefs que vous avez stockées en lieu sûr", - "restore_next": "Suivant", - "restore_title_from_backup": "Restaurer depuis une sauvegarde", - "restore_description_from_backup": "Vous pouvez restaurer l'intégralité de l'application Cake Wallet depuis un fichier de sauvegarde", - "restore_seed_keys_restore": "Restaurer depuis Phrase secrète (seed)/Clefs", - "restore_title_from_seed": "Restaurer depuis une phrase secrète (seed)", - "restore_description_from_seed": "Restaurer votre portefeuille (wallet) depuis une phrase secrète (seed) de 25 ou 13 mots", - "restore_title_from_keys": "Restaurer depuis des clefs", - "restore_description_from_keys": "Restaurer votre portefeuille (wallet) d'après les séquences de touches générées d'après vos clefs privées", - "restore_wallet_name": "Nom du portefeuille (wallet)", - "restore_address": "Adresse", - "restore_view_key_private": "Clef d'audit (view key) (privée)", - "restore_spend_key_private": "Clef de dépense (spend key) (privée)", - "restore_recover": "Restaurer", - "restore_wallet_restore_description": "Description de la restauration de portefeuille (wallet)", - "restore_new_seed": "Nouvelle phrase secrète (seed)", - "restore_active_seed": "Phrase secrète (seed) active", - "restore_bitcoin_description_from_seed": "Restaurer votre portefeuille (wallet) à l'aide d'une phrase secrète (seed) de 24 mots", - "restore_bitcoin_description_from_keys": "Restaurer votre portefeuille (wallet) d'après la chaîne WIF générée d'après vos clefs privées", - "restore_bitcoin_title_from_keys": "Restaurer depuis la chaîne WIF", - "restore_from_date_or_blockheight": "Merci d'entrer une date antérieure de quelques jours à la date de création de votre portefeuille (wallet). Ou si vous connaissez la hauteur de bloc, merci de la spécifier plutôt qu'une date", - "seed_reminder": "Merci d'écrire votre phrase secrète (seed) au cas où vous perdriez ou effaceriez votre téléphone", - "seed_title": "Phrase secrète (seed)", - "seed_share": "Partager la phrase secrète (seed)", - "copy": "Copier", - "seed_language": "Langage de la phrase secrète", - "seed_choose": "Choisissez la langue de la phrase secrète (seed)", - "seed_language_next": "Suivant", - "seed_language_english": "Anglais", - "seed_language_chinese": "Chinois", - "seed_language_dutch": "Néerlandais", - "seed_language_german": "Allemand", - "seed_language_japanese": "Japonais", - "seed_language_portuguese": "Portugais", - "seed_language_russian": "Russe", - "seed_language_spanish": "Espagnol", - "seed_language_french": "Français", - "seed_language_italian": "Italien", - "send_title": "Envoyer", - "send_your_wallet": "Votre portefeuille (wallet)", - "send_address": "adresse ${cryptoCurrency}", - "send_payment_id": "ID de paiement (optionnel)", + "advanced_settings": "Réglages avancés", + "aggressive": "Agressif", + "agree": "d'accord", + "agree_and_continue": "Accepter et continuer", + "agree_to": "En créant un compte, vous acceptez les ", "all": "TOUT", - "send_error_minimum_value": "La valeur minimale du montant est 0.01", - "send_error_currency": "La monnaie ne peut contenir que des nombres", - "send_estimated_fee": "Estimation des frais :", - "send_priority": "Actuellement les frais sont positionnés à la priorité ${transactionPriority}.\nLa priorité de la transaction peut être modifiée dans les réglages", - "send_creating_transaction": "Création de la transaction", - "send_templates": "Modèles d'envois", - "send_new": "Nouveau", - "send_amount": "Montant :", - "send_fee": "Frais :", - "send_name": "Nom", - "got_it": "Compris", - "send_sending": "Envoi...", - "send_success": "Vos ${crypto} ont été envoyés avec succès", - "settings_title": "Réglages", - "settings_nodes": "Nœuds", - "settings_current_node": "Nœud actuel", - "settings_wallets": "Portefeuilles (Wallets)", - "settings_display_balance": "Affichage du solde", - "settings_currency": "Devise", - "settings_fee_priority": "Priorité des frais", - "settings_save_recipient_address": "Sauvegarder l'adresse du bénéficiaire", - "settings_personal": "Personnel", - "settings_change_pin": "Modifier le code PIN", - "settings_change_language": "Modifier la langue", - "settings_allow_biometrical_authentication": "Autoriser l'authentification biométrique", - "settings_dark_mode": "Mode sombre", - "settings_transactions": "Transactions", - "settings_trades": "Échanges", - "settings_display_on_dashboard_list": "Afficher sur la liste des tableaux de bord", - "settings_all": "TOUT", - "settings_only_trades": "Seulement les échanges", - "settings_only_transactions": "Seulement les transactions", - "settings_none": "Rien", - "settings_support": "Support", - "settings_terms_and_conditions": "Termes et Conditions", - "pin_is_incorrect": "Le code PIN est incorrect", - "setup_pin": "Configurer le code PIN", - "enter_your_pin_again": "Entrez à nouveau votre code PIN", - "setup_successful": "Votre code PIN a été configuré avec succès !", - "wallet_keys": "Phrase secrète (seed)/Clefs du portefeuille (wallet)", - "wallet_seed": "Phrase secrète (seed) du portefeuille (wallet)", - "private_key": "Clef privée", - "public_key": "Clef publique", - "view_key_private": "Clef d'audit (view key) (privée)", - "view_key_public": "Clef d'audit (view key) (publique)", - "spend_key_private": "Clef de dépense (spend key) (privée)", - "spend_key_public": "Clef de dépense (spend key) (publique)", - "copied_key_to_clipboard": "${key} copiée vers le presse-papier", - "new_subaddress_title": "Nouvelle adresse", - "new_subaddress_label_name": "Nom", - "new_subaddress_create": "Créer", - "address_label": "Nom de l'adresse", - "subaddress_title": "Liste des sous-adresses", - "trade_details_title": "Détails de l'échange", - "trade_details_id": "ID", - "trade_details_state": "Statut", - "trade_details_fetching": "Récupération", - "trade_details_provider": "Fournisseur", - "trade_details_created_at": "Créé le", - "trade_details_pair": "Paire", - "trade_details_copied": "${title} copié vers le presse-papier", - "trade_history_title": "Historique des échanges", - "transaction_details_title": "Détails de transaction", - "transaction_details_transaction_id": "ID de transaction", - "transaction_details_date": "Date", - "transaction_details_height": "Hauteur", - "transaction_details_amount": "Montant", - "transaction_details_fee": "Frais", - "transaction_details_copied": "${title} copié vers le presse-papier", - "transaction_details_recipient_address": "Adresse du bénéficiaire", - "wallet_list_title": "Portefeuille (Wallet) Monero", - "wallet_list_create_new_wallet": "Créer un Nouveau Portefeuille (Wallet)", - "wallet_list_edit_wallet": "Modifier le portefeuille", - "wallet_list_wallet_name": "Nom du portefeuille", - "wallet_list_restore_wallet": "Restaurer un Portefeuille (Wallet)", - "wallet_list_load_wallet": "Charger un Portefeuille (Wallet)", - "wallet_list_loading_wallet": "Chargement du portefeuille (wallet) ${wallet_name}", - "wallet_list_failed_to_load": "Échec de chargement du portefeuille (wallet) ${wallet_name}. ${error}", - "wallet_list_removing_wallet": "Suppression du portefeuille (wallet) ${wallet_name}", - "wallet_list_failed_to_remove": "Échec de la suppression du portefeuille (wallet) ${wallet_name}. ${error}", - "widgets_address": "Adresse", - "widgets_restore_from_blockheight": "Restaurer depuis une hauteur de bloc", - "widgets_restore_from_date": "Restaurer depuis une date", - "widgets_or": "ou", - "widgets_seed": "Phrase secrète (seed)", - "router_no_route": "Aucune route définie pour ${name}", - "error_text_account_name": "Le nom de compte ne peut contenir que des lettres et des chiffres\net sa longueur doit être comprise entre 1 et 15 caractères", - "error_text_contact_name": "Un nom de contact ne peut pas contenir les symboles ` , ' \"\net doit faire entre 1 et 32 caractères", - "error_text_address": "L'adresse du portefeuille (wallet) doit correspondre au type de\ncryptomonnaie", - "error_text_node_address": "Merci d'entrer une adresse IPv4", - "error_text_node_port": "Le port d'un nœud doit être un nombre compris entre 0 et 65535", - "error_text_node_proxy_address": "Veuillez saisir :, par exemple 127.0.0.1:9050", - "error_text_payment_id": "Un ID de paiement ne peut être constitué que de 16 à 64 caractères hexadécimaux", - "error_text_xmr": "La valeur de XMR dépasse le solde disponible.\nLa partie décimale doit comporter au plus 12 chiffres", - "error_text_fiat": "La valeur du montant ne peut dépasser le solde disponible.\nLa partie décimale doit comporter au plus 2 chiffres", - "error_text_subaddress_name": "Le nom de sous-adresse ne peut contenir les symboles ` , ' \"\net sa longueur doit être comprise entre 1 et 20 caractères", - "error_text_amount": "Le montant ne peut comporter que des nombres", - "error_text_wallet_name": "Le nom du portefeuille (wallet) ne peut contenir que des lettres et des chiffres\net sa longueur doit être comprise entre 1 et 15 caractères", - "error_text_keys": "Les clefs du portefeuille (wallet) ne peuvent être constituées que de 64 caractères hexadécimaux", - "error_text_crypto_currency": "La partie décimale\ndoit comporter au plus 12 chiffres", - "error_text_minimal_limit": "Échange pour ${provider} non créé. Le montant est inférieur au minimum : ${min} ${currency}", - "error_text_maximum_limit": "Échange pour ${provider} non créé. Le montant est supérieur au maximum : ${max} ${currency}", - "error_text_limits_loading_failed": "Échange pour ${provider} non créé. Échec de chargement des limites", - "error_text_template": "Le nom du modèle et l'adresse ne peuvent pas contenir les symboles ` , ' \"\net leur longueur doit être comprise entre 1 et 106 caractères", + "all_trades": "Tous échanges", + "all_transactions": "Toutes transactions", + "alphabetical": "Alphabétique", + "already_have_account": "Vous avez déjà un compte ?", + "always": "toujours", + "amount": "Montant : ", + "amount_is_estimate": "Le montant reçu est estimé", + "amount_is_guaranteed": "Le montant reçu est garanti", + "and": "et", + "anonpay_description": "Générez ${type}. Le destinataire peut ${method} avec n'importe quelle crypto-monnaie prise en charge, et vous recevrez des fonds dans ce portefeuille (wallet).", + "apk_update": "Mise à jour d'APK", + "approve": "Approuver", + "arrive_in_this_address": "${currency} ${tag}arrivera à cette adresse", + "ascending": "Ascendant", + "ask_each_time": "Demander à chaque fois", "auth_store_ban_timeout": "délai de bannisement", "auth_store_banned_for": "Banni pour ", "auth_store_banned_minutes": " minutes", "auth_store_incorrect_password": "Mauvais code PIN", - "wallet_store_monero_wallet": "Portefeuille (Wallet) Monero", - "wallet_restoration_store_incorrect_seed_length": "Longueur de phrase secrète (seed) incorrecte", - "full_balance": "Solde Complet", - "available_balance": "Solde Disponible", - "hidden_balance": "Solde Caché", - "sync_status_syncronizing": "SYNCHRONISATION EN COURS", - "sync_status_syncronized": "SYNCHRONISÉ", - "sync_status_not_connected": "NON CONNECTÉ", - "sync_status_starting_sync": "DÉBUT DE SYNCHRO", - "sync_status_failed_connect": "DÉCONNECTÉ", - "sync_status_connecting": "CONNEXION EN COURS", - "sync_status_connected": "CONNECTÉ", - "sync_status_attempting_sync": "TENTATIVE DE SYNCHRONISATION", - "transaction_priority_slow": "Lent", - "transaction_priority_regular": "Normal", - "transaction_priority_medium": "Moyen", - "transaction_priority_fast": "Rapide", - "transaction_priority_fastest": "Le plus rapide", - "trade_for_not_created": "L'échange pour ${title} n'est pas créé.", - "trade_not_created": "Échange non créé", - "trade_id_not_found": "Échange ${tradeId} de ${title} introuvable.", - "trade_not_found": "Échange introuvable.", - "trade_state_pending": "En cours", - "trade_state_confirming": "En cours de confirmation", - "trade_state_trading": "Échange en cours", - "trade_state_traded": "Échange terminé", - "trade_state_complete": "Finalisé", - "trade_state_to_be_created": "À créer", - "trade_state_unpaid": "Non payé", - "trade_state_underpaid": "Sous payé", - "trade_state_paid_unconfirmed": "Payé mais non confirmé", - "trade_state_paid": "Payé", - "trade_state_btc_sent": "Btc envoyés", - "trade_state_timeout": "Délai dépassé", - "trade_state_created": "Créé", - "trade_state_finished": "Terminé", - "change_language": "Changer de langue", - "change_language_to": "Changer la langue vers ${language} ?", - "paste": "Coller", - "restore_from_seed_placeholder": "Merci d'entrer ou de coller votre phrase secrète (seed) ici", - "add_new_word": "Ajouter un nouveau mot", - "incorrect_seed": "Le texte entré est invalide.", - "biometric_auth_reason": "Scannez votre empreinte digitale pour vous authentifier", - "version": "Version ${currentVersion}", - "extracted_address_content": "Vous allez envoyer des fonds à\n${recipient_name}", - "card_address": "Adresse :", - "buy": "Acheter", - "sell": "Vendre", - "placeholder_transactions": "Vos transactions apparaîtront ici", - "placeholder_contacts": "Vos contacts apparaîtront ici", - "template": "Modèle", - "confirm_delete_template": "Cette action va supprimer ce modèle. Souhaitez-vous continuer ?", - "confirm_delete_wallet": "Cette action va supprimer ce portefeuille (wallet). Souhaitez-vous contnuer ?", - "change_wallet_alert_title": "Changer le portefeuille (wallet) actuel", - "change_wallet_alert_content": "Souhaitez-vous changer le portefeuille (wallet) actuel vers ${wallet_name} ?", - "creating_new_wallet": "Création d'un nouveau portefeuille (wallet)", - "creating_new_wallet_error": "Erreur : ${description}", - "seed_alert_title": "Attention", - "seed_alert_content": "La phrase secrète (seed) est la seule façon de restaurer votre portefeuille (wallet). L'avez-vous correctement écrite ?", - "seed_alert_back": "Retour", - "seed_alert_yes": "Oui, je suis sûr", - "exchange_sync_alert_content": "Merci d'attendre que votre portefeuille (wallet) soit synchronisé", - "pre_seed_title": "IMPORTANT", - "pre_seed_description": "Sur la page suivante vous allez voir une série de ${words} mots. Ils constituent votre phrase secrète (seed) unique et privée et sont le SEUL moyen de restaurer votre portefeuille (wallet) en cas de perte ou de dysfonctionnement. Il est de VOTRE responsabilité d'écrire cette série de mots et de la stocker dans un lieu sûr en dehors de l'application Cake Wallet.", - "pre_seed_button_text": "J'ai compris. Montrez moi ma phrase secrète (seed)", - "xmr_to_error": "Erreur XMR.TO", - "xmr_to_error_description": "Montant invalide. La partie décimale doit contenir au plus 8 chiffres", - "provider_error": "Erreur de ${provider}", - "use_ssl": "Utiliser SSL", - "trusted": "de confiance", - "color_theme": "Thème", - "light_theme": "Clair", - "bright_theme": "Vif", - "dark_theme": "Sombre", - "enter_your_note": "Entrez votre note…", - "note_optional": "Note (optionnelle)", - "note_tap_to_change": "Note (appuyez pour changer)", - "view_in_block_explorer": "Voir dans l'Explorateur de Blocs", - "view_transaction_on": "Voir la Transaction sur ", - "transaction_key": "Clef de Transaction", - "confirmations": "Confirmations", - "recipient_address": "Adresse bénéficiaire", - "extra_id": "ID supplémentaire :", - "destination_tag": "Tag de destination :", - "memo": "Mémo :", - "backup": "Sauvegarde", - "change_password": "Changer le mot de passe", - "backup_password": "Mot de passe de sauvegarde", - "write_down_backup_password": "Merci d'écrire votre mot de passe de sauvegarde, vous en aurez besoin lors de la relecture de vos fichiers de sauvegarde.", - "export_backup": "Exporter la sauvegarde", - "save_backup_password": "Merci de vous assurer d'avoir bien sauvegardé votre mot de passe de sauvegarde. Vous ne pourrez pas restaurer vos fichiers de sauvegarde sans ce dernier.", - "backup_file": "Fichier de sauvegarde", - "edit_backup_password": "Modifier le Mot de Passe de Sauvegarde", - "save_backup_password_alert": "Enregistrer le mot de passe de sauvegarde", - "change_backup_password_alert": "Vos fichiers de sauvegarde précédents ne pourront pas être importés avec le nouveau mot de passe de sauvegarde. Le nouveau mot de passe ne sera utilisé que pour les nouveaux fichiers de sauvegarde. Êtes vous certain de vouloir modifier le mot de passe de sauvegarde ?", - "enter_backup_password": "Entrez le mot de passe de sauvegarde ici", - "select_backup_file": "Sélectionnez le fichier de sauvegarde", - "import": "Importer", - "please_select_backup_file": "Merci de sélectionner le fichier de sauvegarde et de rentrer le mot de passe associé.", - "fixed_rate": "Taux fixe", - "fixed_rate_alert": "Vous aurez la possibilité de rentrer le montant reçu lorsque le mode taux fixe est sélectionné. Souhaitez vous basculer en mode taux fixe ?", - "xlm_extra_info": "Merci de ne pas oublier de spécifier l'ID de mémo lors de l'envoi de la transaction XLM de l'échange", - "xrp_extra_info": "Merci de ne pas oublier de spécifier le tag de destination lors de l'envoi de la transaction XRP de l'échange", - "exchange_incorrect_current_wallet_for_xmr": "Si vous souhaitez échanger des XMR du solde Monero de votre Cake Wallet, merci de sélectionner votre portefeuille (wallet) Monero au préalable.", - "confirmed": "Solde confirmé", - "unconfirmed": "Solde non confirmé", - "displayable": "Visible", - "submit_request": "soumettre une requête", - "buy_alert_content": "Actuellement, nous ne prenons en charge que l'achat de Bitcoin, Ethereum, Litecoin et Monero. Veuillez créer ou basculer vers votre portefeuille Bitcoin, Ethereum, Litecoin ou Monero.", - "sell_alert_content": "Nous ne prenons actuellement en charge que la vente de Bitcoin, Ethereum et Litecoin. Veuillez créer ou basculer vers votre portefeuille Bitcoin, Ethereum ou Litecoin.", - "outdated_electrum_wallet_description": "Les nouveaux portefeuilles (wallets) Bitcoin créés dans Cake ont dorénavant une phrase secrète (seed) de 24 mots. Il est impératif que vous créiez un nouveau portefeuille Bitcoin, que vous y transfériez tous vos fonds puis que vous cessiez d'utiliser le portefeuille avec une phrase secrète de 12 mots. Merci de faire cela immédiatement pour assurer la sécurité de vos avoirs.", - "understand": "J'ai compris", - "apk_update": "Mise à jour d'APK", - "buy_bitcoin": "Acheter du Bitcoin", - "buy_with": "Acheter avec", - "moonpay_alert_text": "Le montant doit être au moins égal à ${minAmount} ${fiatCurrency}", - "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", - "do_not_show_me": "Ne plus me montrer ceci à l'avenir", - "unspent_coins_title": "Pièces (coins) non dépensées", - "unspent_coins_details_title": "Détails des pièces (coins) non dépensées", - "freeze": "Geler", - "frozen": "Gelées", - "coin_control": "Contrôle optionnel des pièces (coins)", - "address_detected": "Adresse détectée", - "address_from_domain": "Cette adresse est issue de ${domain} sur Unstoppable Domains", - "add_receiver": "Ajouter un autre bénéficiaire (optionnel)", - "manage_yats": "Gérer les Yats", - "yat_alert_title": "Envoyez et recevez des cryptos plus facilement avec Yat", - "yat_alert_content": "Les utilisateurs de Cake Wallet peuvent maintenant envoyer et recevoir leurs monnaies favorites avec un utilisateur unique en son genre basé sur les emojis.", - "get_your_yat": "Obtenir votre Yat", - "connect_an_existing_yat": "Connecter un Yat existant", - "connect_yats": "Connecter Yats", - "yat_address": "Adresse Yat", - "yat": "Yat", - "address_from_yat": "Cette adresse est issue de ${emoji} sur Yat", - "yat_error": "Erreur Yat", - "yat_error_content": "Aucune adresse associée à ce Yat. Essayez un autre Yat", - "choose_address": "\n\nMerci de choisir l'adresse :", - "yat_popup_title": "L'adresse de votre portefeuille (wallet) peut être emojifiée.", - "yat_popup_content": "Vous pouvez à présent envoyer et recevoir des cryptos dans Cake Wallet à l'aide de votre Yat - un nom d'utilisateur court à base d'emoji. Gérér les Yats à tout moment depuis l'écran de paramétrage", - "second_intro_title": "Une adresse emoji pour les gouverner toutes", - "second_intro_content": "Votre Yat est une seule et unique adresse emoji qui remplace toutes vos longues adresses hexadécimales pour toutes vos cryptomonnaies.", - "third_intro_title": "Yat est universel", - "third_intro_content": "Les Yats existent aussi en dehors de Cake Wallet. Toute adresse sur terre peut être remplacée par un Yat !", - "learn_more": "En savoir plus", - "search": "Chercher", - "search_language": "Rechercher une langue", - "search_currency": "Rechercher une devise", - "new_template": "Nouveau Modèle", - "electrum_address_disclaimer": "Nous générons de nouvelles adresses à chaque fois que vous en utilisez une, mais les adresses précédentes continuent à fonctionner", - "wallet_name_exists": "Un portefeuille (wallet) portant ce nom existe déjà", - "market_place": "Place de marché", - "cake_pay_title": "Cartes cadeaux Cake Pay", - "cake_pay_subtitle": "Achetez des cartes-cadeaux à prix réduit (États-Unis uniquement)", - "cake_pay_web_cards_title": "Cartes Web Cake Pay", - "cake_pay_web_cards_subtitle": "Achetez des cartes prépayées et des cartes-cadeaux dans le monde entier", - "about_cake_pay": "Cake Pay vous permet d'acheter facilement des cartes-cadeaux avec des actifs virtuels, utilisables instantanément chez plus de 150 000 marchands aux États-Unis.", - "cake_pay_account_note": "Inscrivez-vous avec juste une adresse e-mail pour voir et acheter des cartes. Certaines sont même disponibles à prix réduit !", - "already_have_account": "Vous avez déjà un compte ?", - "create_account": "Créer un compte", - "privacy_policy": "Politique de confidentialité", - "welcome_to_cakepay": "Bienvenue sur Cake Pay !", - "sign_up": "S'inscrire", - "forgot_password": "Mot de passe oublié", - "reset_password": "Réinitialiser le mot de passe", - "setup_your_debit_card": "Configurer votre carte de débit", - "no_id_required": "Aucune pièce d'identité requise. Rechargez et dépensez n'importe où", - "how_to_use_card": "Comment utiliser cette carte", - "purchase_gift_card": "Acheter une carte-cadeau", - "verification": "Vérification", - "fill_code": "Veuillez remplir le code de vérification fourni sur votre e-mail", - "didnt_get_code": "Vous n'avez pas reçu le code ?", - "resend_code": "Veuillez le renvoyer", - "debit_card": "Carte de débit", - "cakepay_prepaid_card": "Carte de débit prépayée Cake Pay", - "no_id_needed": "Aucune pièce d'identité nécessaire !", - "frequently_asked_questions": "Foire aux questions", - "debit_card_terms": "Le stockage et l'utilisation de votre numéro de carte de paiement (et des informations d'identification correspondant à votre numéro de carte de paiement) dans ce portefeuille (wallet) numérique peuvent être soumis aux conditions générales de l'accord du titulaire de carte parfois en vigueur avec l'émetteur de la carte de paiement.", - "please_reference_document": "Veuillez vous référer aux documents ci-dessous pour plus d'informations.", - "cardholder_agreement": "Contrat de titulaire de carte", - "e_sign_consent": "Consentement de signature électronique", - "agree_and_continue": "Accepter et continuer", - "email_address": "Adresse e-mail", - "agree_to": "En créant un compte, vous acceptez les ", - "and": "et", - "enter_code": "Entrez le code", - "congratulations": "Félicitations !", - "you_now_have_debit_card": "Vous avez maintenant une carte de débit", - "min_amount": "Min : ${value}", - "max_amount": "Max : ${value}", - "enter_amount": "Entrez le montant", - "billing_address_info": "Si une adresse de facturation vous est demandée, indiquez votre adresse de livraison", - "order_physical_card": "Commander une carte physique", - "add_value": "Ajouter une valeur", - "activate": "Activer", - "get_a": "Obtenir un ", - "digital_and_physical_card": "carte de débit prépayée numérique et physique", - "get_card_note": " que vous pouvez recharger avec des devises numériques. Aucune information supplémentaire n'est nécessaire !", - "signup_for_card_accept_terms": "Inscrivez-vous pour la carte et acceptez les conditions.", - "add_fund_to_card": "Ajouter des fonds prépayés aux cartes (jusqu'à ${value})", - "use_card_info_two": "Les fonds sont convertis en USD lorsqu'ils sont détenus sur le compte prépayé, et non en devises numériques.", - "use_card_info_three": "Utilisez la carte numérique en ligne ou avec des méthodes de paiement sans contact.", - "optionally_order_card": "Commander éventuellement une carte physique.", - "hide_details": "Masquer les détails", - "show_details": "Afficher les détails", - "upto": "jusqu'à ${value}", - "discount": "Économisez ${value}%", - "gift_card_amount": "Montant de la carte-cadeau", - "bill_amount": "Montant de la facture", - "you_pay": "Vous payez", - "tip": "Pourboire :", - "custom": "personnalisé", - "by_cake_pay": "par Cake Pay", - "expires": "Expire", - "mm": "MM", - "yy": "AA", - "online": "En ligne", - "offline": "Hors ligne", - "gift_card_number": "Numéro de carte cadeau", - "pin_number": "Numéro PIN", - "total_saving": "Économies totales", - "last_30_days": "30 derniers jours", - "avg_savings": "Économies moy.", - "view_all": "Voir tout", - "active_cards": "Cartes actives", - "delete_account": "Supprimer le compte", - "cards": "Cartes", - "active": "Actives", - "redeemed": "Converties", - "gift_card_balance_note": "Les cartes-cadeaux avec un solde restant apparaîtront ici", - "gift_card_redeemed_note": "Les cartes-cadeaux que vous avez utilisées apparaîtront ici", - "logout": "Déconnexion", - "add_tip": "Ajouter un pourboire", - "percentageOf": "sur ${amount}", - "is_percentage": "est", - "search_category": "Catégorie de recherche", - "mark_as_redeemed": "Marquer comme convertie", - "more_options": "Plus d'options", - "awaiting_payment_confirmation": "En attente de confirmation de paiement", - "transaction_sent_notice": "Si l'écran ne continue pas après 1 minute, vérifiez un explorateur de blocs et votre e-mail.", - "agree": "d'accord", - "in_store": "En magasin", - "generating_gift_card": "Génération d'une carte-cadeau", - "payment_was_received": "Votre paiement a été reçu.", - "proceed_after_one_minute": "Si l'écran ne s'affiche pas après 1 minute, vérifiez vos e-mails.", - "order_id": "Numéro de commande", - "gift_card_is_generated": "La carte-cadeau est générée", - "open_gift_card": "Ouvrir la carte-cadeau", - "contact_support": "Contacter l'assistance", - "gift_cards_unavailable": "Les cartes-cadeaux ne sont disponibles à l'achat que via Monero, Bitcoin et Litecoin pour le moment", - "background_sync_mode": "Mode de synchronisation en arrière-plan", - "sync_all_wallets": "Synchroniser tous les portefeuilles", - "gift_cards": "Cartes-Cadeaux", - "introducing_cake_pay": "Présentation de Cake Pay !", - "cake_pay_learn_more": "Achetez et utilisez instantanément des cartes-cadeaux dans l'application !\nBalayer de gauche à droite pour en savoir plus.", + "authenticated": "Authentifié", + "authentication": "Authentification", + "auto_generate_subaddresses": "Générer automatiquement des sous-adresses", "automatic": "Automatique", - "fixed_pair_not_supported": "Cette paire fixe n'est pas prise en charge avec les échanges sélectionnés", - "variable_pair_not_supported": "Cette paire variable n'est pas prise en charge avec les échanges sélectionnés", - "none_of_selected_providers_can_exchange": "Aucun des prestataires sélectionnés ne peut effectuer cet échange", - "choose_one": "Choisissez-en un", - "choose_from_available_options": "Choisissez parmi les options disponibles :", - "custom_redeem_amount": "Montant d'échange personnalisé", - "add_custom_redemption": "Ajouter un remboursement personnalisé", - "remaining": "restant", - "delete_wallet": "Supprimer le portefeuille (wallet)", - "delete_wallet_confirm_message": "Êtes-vous sûr de vouloir supprimer le portefeuille (wallet) ${wallet_name}?", - "low_fee": "Frais modiques", - "low_fee_alert": "Vous utilisez actuellement une priorité de frais de réseau peu élevés. Cela pourrait entraîner de longues attentes, des taux différents ou des transactions annulées. Nous vous recommandons de fixer des frais plus élevés pour une meilleure expérience.", - "ignor": "Ignorer", - "use_suggested": "Suivre la suggestion", - "do_not_share_warning_text": "Ne les partagez avec personne, y compris avec l'assistance.\n\nVos fonds seraient inmanquablement volés !", - "help": "aide", - "all_transactions": "Toutes transactions", - "all_trades": "Tous échanges", - "connection_sync": "Connexion et synchronisation", - "security_and_backup": "Sécurité et sauvegarde", - "create_backup": "Créer une sauvegarde", - "privacy_settings": "Paramètres de confidentialité", - "privacy": "Confidentialité", - "display_settings": "Paramètres d'affichage", - "other_settings": "Autres paramètres", - "require_pin_after": "Code PIN requis après", - "always": "toujours", - "minutes_to_pin_code": "${minute} minutes", - "disable_exchange": "Désactiver l'échange", - "advanced_settings": "Réglages avancés", - "settings_can_be_changed_later": "Ces paramètres peuvent être modifiés ultérieurement dans les paramètres de l'application", - "add_custom_node": "Ajouter un nouveau nœud personnalisé", - "disable_fiat": "Désactiver les montants en fiat", - "fiat_api": "Fiat API", - "disabled": "Désactivé", - "enabled": "Activé", - "tor_only": "Tor uniquement", - "unmatched_currencies": "La devise de votre portefeuille (wallet) actuel ne correspond pas à celle du QR code scanné", - "orbot_running_alert": "Veuillez vous assurer qu'Orbot est en cours d'exécution avant de vous connecter à ce nœud.", - "contact_list_contacts": "Contacts", - "contact_list_wallets": "Mes portefeuilles (wallets)", - "bitcoin_payments_require_1_confirmation": "Les paiements Bitcoin nécessitent 1 confirmation, ce qui peut prendre 20 minutes ou plus. Merci pour votre patience ! Vous serez averti par e-mail lorsque le paiement sera confirmé.", - "send_to_this_address": "Envoyer ${currency} ${tag}à cette adresse", - "arrive_in_this_address": "${currency} ${tag}arrivera à cette adresse", - "do_not_send": "Ne pas envoyer", - "error_dialog_content": "Oups, nous avons rencontré une erreur.\n\nMerci d'envoyer le rapport d'erreur à notre équipe d'assistance afin de nous permettre d'améliorer l'application.", - "scan_qr_code": "Scannez le QR code", - "cold_or_recover_wallet": "Ajoutez un portefeuille froid (cold wallet) ou récupérez un portefeuille papier (paper wallet)", - "please_wait": "Merci de patienter", - "sweeping_wallet": "Portefeuille (wallet) de consolidation", - "sweeping_wallet_alert": "Cette opération ne devrait pas prendre longtemps. NE QUITTEZ PAS CET ÉCRAN OU LES FONDS CONSOLIDÉS POURRAIENT ÊTRE PERDUS", - "decimal_places_error": "Trop de décimales", - "edit_node": "Modifier le nœud", - "invoice_details": "Détails de la facture", - "donation_link_details": "Détails du lien de don", - "anonpay_description": "Générez ${type}. Le destinataire peut ${method} avec n'importe quelle crypto-monnaie prise en charge, et vous recevrez des fonds dans ce portefeuille (wallet).", - "create_invoice": "Créer une facture", - "create_donation_link": "Créer un lien de don", - "optional_email_hint": "E-mail de notification du bénéficiaire facultatif", - "optional_description": "Descriptif facultatif", - "optional_name": "Nom du destinataire facultatif", - "clearnet_link": "Lien Clearnet", - "settings": "Paramètres", - "onion_link": "Lien .onion", - "sell_monero_com_alert_content": "La vente de Monero n'est pas encore prise en charge", - "error_text_input_below_minimum_limit": "Le montant est inférieur au minimum", - "error_text_input_above_maximum_limit": "Le montant est supérieur au maximum", - "show_market_place": "Afficher la place de marché", - "prevent_screenshots": "Empêcher les captures d'écran et l'enregistrement d'écran", - "profile": "Profil", - "close": "Fermer", - "modify_2fa": "Modifier les paramètres Cake 2FA", - "disable_cake_2fa": "Désactiver Cake 2FA", - "question_to_disable_2fa": "Êtes-vous sûr de vouloir désactiver Cake 2FA ? Un code 2FA ne sera plus nécessaire pour accéder au portefeuille (wallet) et à certaines fonctions.", - "disable": "Désactiver", - "setup_2fa": "Paramétrer Cake 2FA", - "verify_with_2fa": "Vérifier avec Cake 2FA", - "totp_code": "Code TOTP", - "please_fill_totp": "Veuillez renseigner le code à 8 chiffres affiché sur votre autre appareil", - "totp_2fa_success": "Succès! Cake 2FA est activé pour ce portefeuille. N'oubliez pas de sauvegarder votre phrase secrète (seed) au cas où vous perdriez l'accès au portefeuille (wallet).", - "totp_verification_success": "Vérification réussie !", - "totp_2fa_failure": "Code incorrect. Veuillez essayer un code différent ou générer un nouveau secret TOTP. Utilisez une application 2FA compatible qui prend en charge les codes à 8 chiffres et SHA512.", - "enter_totp_code": "Veuillez entrer le code TOTP.", - "add_secret_code": "Ou ajoutez ce code secret à une application d'authentification", - "totp_secret_code": "Secret TOTP", - "setup_2fa_text": "Cake 2FA fonctionne en utilisant TOTP comme deuxième facteur d'authentification.\n\nLe TOTP de Cake 2FA nécessite la prise en charge de SHA-512 et de 8 chiffres ; cela offre une sécurité accrue. Plus d’informations et les applications prises en charge peuvent être trouvées dans le guide.", - "setup_totp_recommended": "Configurer TOTP", - "disable_buy": "Désactiver l'action d'achat", - "disable_sell": "Désactiver l'action de vente", - "cake_2fa_preset": "Cake 2FA prédéfini", - "monero_dark_theme": "Thème sombre Monero", + "available_balance": "Solde Disponible", + "available_balance_description": "Le solde disponible est le montant que vous pouvez dépenser immédiatement. Il est calculé en soustrayant le solde gelé du solde total.", + "avg_savings": "Économies moy.", + "awaitDAppProcessing": "Veuillez attendre que l'application décentralisée (dApp) termine le traitement.", + "awaiting_payment_confirmation": "En attente de confirmation de paiement", + "background_sync_mode": "Mode de synchronisation en arrière-plan", + "backup": "Sauvegarde", + "backup_file": "Fichier de sauvegarde", + "backup_password": "Mot de passe de sauvegarde", + "balance_page": "Page Solde", + "bill_amount": "Montant de la facture", + "billing_address_info": "Si une adresse de facturation vous est demandée, indiquez votre adresse de livraison", + "biometric_auth_reason": "Scannez votre empreinte digitale pour vous authentifier", "bitcoin_dark_theme": "Thème sombre Bitcoin", "bitcoin_light_theme": "Thème léger Bitcoin", - "high_contrast_theme": "Thème à contraste élevé", - "matrix_green_dark_theme": "Thème Matrix Green Dark", - "monero_light_theme": "Thème de lumière Monero", - "auto_generate_subaddresses": "Générer automatiquement des sous-adresses", - "narrow": "Étroit", - "normal": "Normal", - "aggressive": "Agressif", - "require_for_assessing_wallet": "Nécessaire pour accéder au portefeuille", - "require_for_sends_to_non_contacts": "Exiger pour les envois hors contacts", - "require_for_sends_to_contacts": "Exiger pour les envois aux contacts", - "require_for_sends_to_internal_wallets": "Exiger pour les envois vers des portefeuilles (wallets) internes", - "require_for_exchanges_to_internal_wallets": "Exiger pour les échanges vers des portefeuilles (wallets) internes", - "require_for_adding_contacts": "Requis pour ajouter des contacts", - "require_for_creating_new_wallets": "Nécessaire pour créer de nouveaux portefeuilles (wallets)", - "require_for_all_security_and_backup_settings": "Exiger pour tous les paramètres de sécurité et de sauvegarde", - "available_balance_description": "Le solde disponible est le montant que vous pouvez dépenser immédiatement. Il est calculé en soustrayant le solde gelé du solde total.", - "syncing_wallet_alert_title": "Votre portefeuille (wallet) est en cours de synchronisation", - "syncing_wallet_alert_content": "Votre solde et votre liste de transactions peuvent ne pas être à jour tant que la mention « SYNCHRONISÉ » n'apparaît en haut de l'écran. Cliquez/appuyez pour en savoir plus.", - "home_screen_settings": "Paramètres de l'écran d'accueil", - "sort_by": "Trier par", - "search_add_token": "Rechercher / Ajouter un token", - "edit_token": "Modifier le token", - "warning": "Avertissement", - "add_token_warning": "Ne modifiez pas ou n'ajoutez pas de tokens comme pourraient vous le suggérer des escrocs.\nConfirmez toujours les adresses de token auprès de sources fiables !", - "add_token_disclaimer_check": "J'ai confirmé l'adresse et les informations du contrat de token en utilisant une source fiable. L'ajout d'informations malveillantes ou incorrectes peut entraîner une perte de fonds.", - "token_contract_address": "Adresse du contrat de token", - "token_name": "Nom du token, par exemple : Tether", - "token_symbol": "Symbole de token, par exemple : USDT", - "token_decimal": "Décimales de token", - "field_required": "Ce champ est obligatoire", - "pin_at_top": "épingler ${token} en haut", - "invalid_input": "Entrée invalide", - "fiat_balance": "Solde fiat", - "gross_balance": "Solde brut", - "alphabetical": "Alphabétique", - "generate_name": "Générer un nom", - "balance_page": "Page Solde", - "share": "Partager", - "slidable": "Glissable", - "manage_nodes": "Gérer les nœuds", - "etherscan_history": "Historique d'Etherscan", - "template_name": "Nom du modèle", + "bitcoin_payments_require_1_confirmation": "Les paiements Bitcoin nécessitent 1 confirmation, ce qui peut prendre 20 minutes ou plus. Merci pour votre patience ! Vous serez averti par e-mail lorsque le paiement sera confirmé.", + "Blocks_remaining": "Blocs Restants : ${status}", + "bright_theme": "Vif", + "buy": "Acheter", + "buy_alert_content": "Actuellement, nous ne prenons en charge que l'achat de Bitcoin, Ethereum, Litecoin et Monero. Veuillez créer ou basculer vers votre portefeuille Bitcoin, Ethereum, Litecoin ou Monero.", + "buy_bitcoin": "Acheter du Bitcoin", + "buy_provider_unavailable": "Fournisseur actuellement indisponible.", + "buy_with": "Acheter avec", + "by_cake_pay": "par Cake Pay", + "cake_2fa_preset": "Cake 2FA prédéfini", + "cake_pay_account_note": "Inscrivez-vous avec juste une adresse e-mail pour voir et acheter des cartes. Certaines sont même disponibles à prix réduit !", + "cake_pay_learn_more": "Achetez et utilisez instantanément des cartes-cadeaux dans l'application !\nBalayer de gauche à droite pour en savoir plus.", + "cake_pay_subtitle": "Achetez des cartes-cadeaux à prix réduit (États-Unis uniquement)", + "cake_pay_title": "Cartes cadeaux Cake Pay", + "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_wallet": "Cake Wallet", + "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.", + "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", + "cancel": "Annuler", + "card_address": "Adresse :", + "cardholder_agreement": "Contrat de titulaire de carte", + "cards": "Cartes", + "chains": "Chaînes", + "change": "Changer", + "change_backup_password_alert": "Vos fichiers de sauvegarde précédents ne pourront pas être importés avec le nouveau mot de passe de sauvegarde. Le nouveau mot de passe ne sera utilisé que pour les nouveaux fichiers de sauvegarde. Êtes vous certain de vouloir modifier le mot de passe de sauvegarde ?", + "change_currency": "Changer de Devise", + "change_current_node": "Êtes vous certain de vouloir changer le nœud actuel pour ${node} ?", + "change_current_node_title": "Changer le nœud actuel", + "change_exchange_provider": "Changer de Plateforme d'Échange", + "change_language": "Changer de langue", + "change_language_to": "Changer la langue vers ${language} ?", + "change_password": "Changer le mot de passe", "change_rep": "Changer de représentant", "change_rep_message": "Êtes-vous sûr de vouloir changer de représentant ?", - "unsupported_asset": "Nous ne prenons pas en charge cette action pour cet élément. Veuillez créer ou passer à un portefeuille d'un type d'actif pris en charge.", - "manage_pow_nodes": "Gérer les nœuds PoW", - "support_title_live_chat": "Support en direct", - "support_description_live_chat": "GRATUIT ET RAPIDE ! Des représentants de soutien formé sont disponibles pour aider", - "support_title_guides": "Guides de Cake Wallet", - "support_description_guides": "Documentation et support pour les problèmes communs", - "support_title_other_links": "Autres liens d'assistance", - "support_description_other_links": "Rejoignez nos communautés ou contactez-nous ou nos partenaires à travers d'autres méthodes", + "change_rep_successful": "Représentant changé avec succès", + "change_wallet_alert_content": "Souhaitez-vous changer le portefeuille (wallet) actuel vers ${wallet_name} ?", + "change_wallet_alert_title": "Changer le portefeuille (wallet) actuel", + "choose_account": "Choisir le compte", + "choose_address": "\n\nMerci de choisir l'adresse :", "choose_derivation": "Choisissez le chemin de dérivation du portefeuille", - "new_first_wallet_text": "Gardez facilement votre crypto-monnaie en sécurité", - "select_destination": "Veuillez sélectionner la destination du fichier de sauvegarde.", - "save_to_downloads": "Enregistrer dans les téléchargements", - "select_buy_provider_notice": "Sélectionnez un fournisseur d'achat ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur d'achat par défaut dans les paramètres de l'application.", - "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.", + "choose_from_available_options": "Choisissez parmi les options disponibles :", + "choose_one": "Choisissez-en un", + "choose_relay": "Veuillez choisir un relais à utiliser", + "choose_wallet_currency": "Merci de choisir la devise du portefeuille (wallet) :", + "clear": "Effacer", + "clearnet_link": "Lien Clearnet", + "close": "Fermer", + "coin_control": "Contrôle optionnel des pièces (coins)", + "cold_or_recover_wallet": "Ajoutez un portefeuille froid (cold wallet) ou récupérez un portefeuille papier (paper wallet)", + "color_theme": "Thème", + "commit_transaction_amount_fee": "Valider la transaction\nMontant : ${amount}\nFrais : ${fee}", + "confirm": "Confirmer", + "confirm_delete_template": "Cette action va supprimer ce modèle. Souhaitez-vous continuer ?", + "confirm_delete_wallet": "Cette action va supprimer ce portefeuille (wallet). Souhaitez-vous contnuer ?", + "confirm_sending": "Confirmer l'envoi", + "confirmations": "Confirmations", + "confirmed": "Solde confirmé", + "confirmed_tx": "Confirmé", + "congratulations": "Félicitations !", + "connect_an_existing_yat": "Connecter un Yat existant", + "connect_yats": "Connecter Yats", + "connection_sync": "Connexion et synchronisation", + "connectWalletPrompt": "Connectez votre portefeuille (wallet) avec WalletConnect pour effectuer des transactions", + "contact": "Contact", + "contact_list_contacts": "Contacts", + "contact_list_wallets": "Mes portefeuilles (wallets)", + "contact_name": "Nom de Contact", + "contact_support": "Contacter l'assistance", + "continue_text": "Continuer", + "contractName": "Nom du contrat", + "contractSymbol": "Symbole du contrat", + "copied_key_to_clipboard": "${key} copiée vers le presse-papier", + "copied_to_clipboard": "Copié vers le Presse-Papier", + "copy": "Copier", + "copy_address": "Copier l'Adresse", + "copy_id": "Copier l'ID", + "copyWalletConnectLink": "Copiez le lien WalletConnect depuis l'application décentralisée (dApp) et collez-le ici", + "create_account": "Créer un compte", + "create_backup": "Créer une sauvegarde", + "create_donation_link": "Créer un lien de don", + "create_invoice": "Créer une facture", + "create_new": "Créer un Nouveau Portefeuille (Wallet)", + "create_new_account": "Créer un nouveau compte", + "creating_new_wallet": "Création d'un nouveau portefeuille (wallet)", + "creating_new_wallet_error": "Erreur : ${description}", + "creation_date": "Date de création", + "custom": "personnalisé", + "custom_drag": "Custom (maintenir et traîner)", + "custom_redeem_amount": "Montant d'échange personnalisé", + "dark_theme": "Sombre", + "debit_card": "Carte de débit", + "debit_card_terms": "Le stockage et l'utilisation de votre numéro de carte de paiement (et des informations d'identification correspondant à votre numéro de carte de paiement) dans ce portefeuille (wallet) numérique peuvent être soumis aux conditions générales de l'accord du titulaire de carte parfois en vigueur avec l'émetteur de la carte de paiement.", + "decimal_places_error": "Trop de décimales", "default_buy_provider": "Fournisseur d'achat par défaut", - "ask_each_time": "Demander à chaque fois", - "buy_provider_unavailable": "Fournisseur actuellement indisponible.", - "signTransaction": "Signer une transaction", + "default_sell_provider": "Fournisseur de vente par défaut", + "delete": "Effacer", + "delete_account": "Supprimer le compte", + "delete_wallet": "Supprimer le portefeuille (wallet)", + "delete_wallet_confirm_message": "Êtes-vous sûr de vouloir supprimer le portefeuille (wallet) ${wallet_name}?", + "deleteConnectionConfirmationPrompt": "Êtes-vous sûr de vouloir supprimer la connexion à", + "descending": "Descendant", + "description": "Description", + "destination_tag": "Tag de destination :", + "dfx_option_description": "Achetez des crypto-monnaies avec EUR et CHF. Jusqu'à 990€ sans KYC supplémentaire. Pour les clients particuliers et entreprises en Europe", + "didnt_get_code": "Vous n'avez pas reçu le code ?", + "digit_pin": " chiffres", + "digital_and_physical_card": "carte de débit prépayée numérique et physique", + "disable": "Désactiver", + "disable_buy": "Désactiver l'action d'achat", + "disable_cake_2fa": "Désactiver Cake 2FA", + "disable_exchange": "Désactiver l'échange", + "disable_fiat": "Désactiver les montants en fiat", + "disable_sell": "Désactiver l'action de vente", + "disabled": "Désactivé", + "discount": "Économisez ${value}%", + "display_settings": "Paramètres d'affichage", + "displayable": "Visible", + "do_not_have_enough_gas_asset": "Vous n'avez pas assez de ${currency} pour effectuer une transaction avec les conditions actuelles du réseau blockchain. Vous avez besoin de plus de ${currency} pour payer les frais du réseau blockchain, même si vous envoyez un actif différent.", + "do_not_send": "Ne pas envoyer", + "do_not_share_warning_text": "Ne les partagez avec personne, y compris avec l'assistance.\n\nVos fonds seraient inmanquablement volés !", + "do_not_show_me": "Ne plus me montrer ceci à l'avenir", + "domain_looks_up": "Résolution de nom", + "donation_link_details": "Détails du lien de don", + "e_sign_consent": "Consentement de signature électronique", + "edit": "Modifier", + "edit_backup_password": "Modifier le Mot de Passe de Sauvegarde", + "edit_node": "Modifier le nœud", + "edit_token": "Modifier le token", + "electrum_address_disclaimer": "Nous générons de nouvelles adresses à chaque fois que vous en utilisez une, mais les adresses précédentes continuent à fonctionner", + "email_address": "Adresse e-mail", + "enabled": "Activé", + "enter_amount": "Entrez le montant", + "enter_backup_password": "Entrez le mot de passe de sauvegarde ici", + "enter_code": "Entrez le code", + "enter_seed_phrase": "Entrez votre phrase secrète (seed)", + "enter_totp_code": "Veuillez entrer le code TOTP.", + "enter_your_note": "Entrez votre note…", + "enter_your_pin": "Entrez votre code PIN", + "enter_your_pin_again": "Entrez à nouveau votre code PIN", + "enterTokenID": "Entrez l'ID du jeton", + "enterWalletConnectURI": "Saisissez l'URI de WalletConnect.", + "error": "Erreur", + "error_dialog_content": "Oups, nous avons rencontré une erreur.\n\nMerci d'envoyer le rapport d'erreur à notre équipe d'assistance afin de nous permettre d'améliorer l'application.", + "error_text_account_name": "Le nom de compte ne peut contenir que des lettres et des chiffres\net sa longueur doit être comprise entre 1 et 15 caractères", + "error_text_address": "L'adresse du portefeuille (wallet) doit correspondre au type de\ncryptomonnaie", + "error_text_amount": "Le montant ne peut comporter que des nombres", + "error_text_contact_name": "Un nom de contact ne peut pas contenir les symboles ` , ' \"\net doit faire entre 1 et 32 caractères", + "error_text_crypto_currency": "La partie décimale\ndoit comporter au plus 12 chiffres", + "error_text_fiat": "La valeur du montant ne peut dépasser le solde disponible.\nLa partie décimale doit comporter au plus 2 chiffres", + "error_text_input_above_maximum_limit": "Le montant est supérieur au maximum", + "error_text_input_below_minimum_limit": "Le montant est inférieur au minimum", + "error_text_keys": "Les clefs du portefeuille (wallet) ne peuvent être constituées que de 64 caractères hexadécimaux", + "error_text_limits_loading_failed": "Échange pour ${provider} non créé. Échec de chargement des limites", + "error_text_maximum_limit": "Échange pour ${provider} non créé. Le montant est supérieur au maximum : ${max} ${currency}", + "error_text_minimal_limit": "Échange pour ${provider} non créé. Le montant est inférieur au minimum : ${min} ${currency}", + "error_text_node_address": "Merci d'entrer une adresse IPv4", + "error_text_node_port": "Le port d'un nœud doit être un nombre compris entre 0 et 65535", + "error_text_node_proxy_address": "Veuillez saisir :, par exemple 127.0.0.1:9050", + "error_text_payment_id": "Un ID de paiement ne peut être constitué que de 16 à 64 caractères hexadécimaux", + "error_text_subaddress_name": "Le nom de sous-adresse ne peut contenir les symboles ` , ' \"\net sa longueur doit être comprise entre 1 et 20 caractères", + "error_text_template": "Le nom du modèle et l'adresse ne peuvent pas contenir les symboles ` , ' \"\net leur longueur doit être comprise entre 1 et 106 caractères", + "error_text_wallet_name": "Le nom du portefeuille (wallet) ne peut contenir que des lettres et des chiffres\net sa longueur doit être comprise entre 1 et 15 caractères", + "error_text_xmr": "La valeur de XMR dépasse le solde disponible.\nLa partie décimale doit comporter au plus 12 chiffres", "errorGettingCredentials": "Échec : erreur lors de l'obtention des informations d'identification", "errorSigningTransaction": "Une erreur s'est produite lors de la signature de la transaction", - "pairingInvalidEvent": "Événement de couplage non valide", - "chains": "Chaînes", - "methods": "Méthodes", - "events": "Événements", - "reject": "Rejeter", - "approve": "Approuver", - "expiresOn": "Expire le", - "walletConnect": "WalletConnect", - "nullURIError": "L'URI est nul", - "connectWalletPrompt": "Connectez votre portefeuille (wallet) avec WalletConnect pour effectuer des transactions", - "newConnection": "Nouvelle connexion", - "activeConnectionsPrompt": "Les connexions actives apparaîtront ici", - "deleteConnectionConfirmationPrompt": "Êtes-vous sûr de vouloir supprimer la connexion à", + "estimated": "Estimé", + "etherscan_history": "Historique d'Etherscan", "event": "Événement", - "successful": "Réussi", - "wouoldLikeToConnect": "je voudrais me connecter", - "message": "Message", - "do_not_have_enough_gas_asset": "Vous n'avez pas assez de ${currency} pour effectuer une transaction avec les conditions actuelles du réseau blockchain. Vous avez besoin de plus de ${currency} pour payer les frais du réseau blockchain, même si vous envoyez un actif différent.", - "totp_auth_url": "URL D'AUTORISATION TOTP", - "awaitDAppProcessing": "Veuillez attendre que l'application décentralisée (dApp) termine le traitement.", - "copyWalletConnectLink": "Copiez le lien WalletConnect depuis l'application décentralisée (dApp) et collez-le ici", - "enterWalletConnectURI": "Saisissez l'URI de WalletConnect.", - "seed_key": "Clé secrète (seed key)", - "enter_seed_phrase": "Entrez votre phrase secrète (seed)", - "change_rep_successful": "Représentant changé avec succès", - "add_contact": "Ajouter le contact", + "events": "Événements", + "exchange": "Échanger", + "exchange_incorrect_current_wallet_for_xmr": "Si vous souhaitez échanger des XMR du solde Monero de votre Cake Wallet, merci de sélectionner votre portefeuille (wallet) Monero au préalable.", + "exchange_new_template": "Nouveau modèle d'échange", "exchange_provider_unsupported": "${providerName} n'est plus pris en charge !", - "domain_looks_up": "Résolution de nom", - "require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes", - "camera_permission_is_required": "L'autorisation de la caméra est requise.\nVeuillez l'activer à partir des paramètres de l'application.", - "importNFTs": "Importer des NFT", - "noNFTYet": "Pas encore de NFT", - "address": "Adresse", - "enterTokenID": "Entrez l'ID du jeton", - "tokenID": "IDENTIFIANT", - "name": "Nom", - "symbol": "Symbole", - "seed_phrase_length": "Longueur de la phrase de départ", - "unavailable_balance": "Solde indisponible", - "unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.", - "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", - "unspent_change": "Changement", - "order_by": "Commandé par", - "creation_date": "Date de création", + "exchange_result_confirm": "En pressant confirmer, vous enverrez ${fetchingLabel} ${from} depuis votre portefeuille (wallet) nommé ${walletName} vers l'adresse ci-dessous. Vous pouvez aussi envoyer depuis votre portefeuille externe vers l'adresse/QR code ci-dessous.\n\nMerci d'appuyer sur confirmer pour continuer ou retournez en arrière pour modifier les montants.", + "exchange_result_description": "Vous devez envoyer un minimum de ${fetchingLabel} ${from} à l'adresse indiquée page suivante. Si vous envoyez un montant inférieur à ${fetchingLabel} ${from} il pourrait ne pas être converti et ne pas être remboursé.", + "exchange_result_write_down_ID": "*Merci de copier ou écrire votre ID présenté ci-dessus.", + "exchange_result_write_down_trade_id": "Merci de copier ou d'écrire l'ID d'échange pour continuer.", + "exchange_sync_alert_content": "Merci d'attendre que votre portefeuille (wallet) soit synchronisé", + "expired": "Expirée", + "expires": "Expire", + "expiresOn": "Expire le", + "export_backup": "Exporter la sauvegarde", + "extra_id": "ID supplémentaire :", + "extracted_address_content": "Vous allez envoyer des fonds à\n${recipient_name}", + "failed_authentication": "Échec d'authentification. ${state_error}", + "faq": "FAQ", + "fetching": "Récupération", + "fiat_api": "Fiat API", + "fiat_balance": "Solde fiat", + "field_required": "Ce champ est obligatoire", + "fill_code": "Veuillez remplir le code de vérification fourni sur votre e-mail", + "filter_by": "Filtrer par", + "first_wallet_text": "Super portefeuille (wallet) pour Monero, Bitcoin, Ethereum, Litecoin et Haven", + "fixed_pair_not_supported": "Cette paire fixe n'est pas prise en charge avec les échanges sélectionnés", + "fixed_rate": "Taux fixe", + "fixed_rate_alert": "Vous aurez la possibilité de rentrer le montant reçu lorsque le mode taux fixe est sélectionné. Souhaitez vous basculer en mode taux fixe ?", + "forgot_password": "Mot de passe oublié", + "freeze": "Geler", + "frequently_asked_questions": "Foire aux questions", + "frozen": "Gelées", + "full_balance": "Solde Complet", + "generate_name": "Générer un nom", + "generating_gift_card": "Génération d'une carte-cadeau", + "get_a": "Obtenir un ", + "get_card_note": " que vous pouvez recharger avec des devises numériques. Aucune information supplémentaire n'est nécessaire !", + "get_your_yat": "Obtenir votre Yat", + "gift_card_amount": "Montant de la carte-cadeau", + "gift_card_balance_note": "Les cartes-cadeaux avec un solde restant apparaîtront ici", + "gift_card_is_generated": "La carte-cadeau est générée", + "gift_card_number": "Numéro de carte cadeau", + "gift_card_redeemed_note": "Les cartes-cadeaux que vous avez utilisées apparaîtront ici", + "gift_cards": "Cartes-Cadeaux", + "gift_cards_unavailable": "Les cartes-cadeaux ne sont disponibles à l'achat que via Monero, Bitcoin et Litecoin pour le moment", + "got_it": "Compris", + "gross_balance": "Solde brut", "group_by_type": "Groupe par type", - "tor_connection": "Connexion Tor", - "setup_warning_2fa_text": "Vous devrez restaurer votre portefeuille à partir de la graine mnémonique.\n\nLe support Cake ne pourra pas vous aider si vous perdez l'accès à vos graines 2FA ou mnémoniques.\nCake 2FA est une seconde authentification pour certaines actions dans le portefeuille. Avant d'utiliser Cake 2FA, nous vous recommandons de lire le guide.Ce n’est PAS aussi sécurisé que l’entreposage frigorifique.\n\nSi vous perdez l'accès à votre application 2FA ou à vos clés TOTP, vous perdrez l'accès à ce portefeuille. ", - "scan_qr_on_device": "Scannez ce code QR sur un autre appareil", + "haven_app": "Haven par Cake Wallet", + "haven_app_wallet_text": "Super portefeuille (wallet) pour Haven", + "help": "aide", + "hidden_balance": "Solde Caché", + "hide_details": "Masquer les détails", + "high_contrast_theme": "Thème à contraste élevé", + "home_screen_settings": "Paramètres de l'écran d'accueil", "how_to_use": "Comment utiliser", + "how_to_use_card": "Comment utiliser cette carte", + "id": "ID : ", + "ignor": "Ignorer", + "import": "Importer", + "importNFTs": "Importer des NFT", + "in_store": "En magasin", + "incoming": "Entrantes", + "incorrect_seed": "Le texte entré est invalide.", + "introducing_cake_pay": "Présentation de Cake Pay !", + "invalid_input": "Entrée invalide", + "invoice_details": "Détails de la facture", + "is_percentage": "est", + "last_30_days": "30 derniers jours", + "learn_more": "En savoir plus", + "light_theme": "Clair", + "loading_your_wallet": "Chargement de votre portefeuille (wallet)", + "login": "Utilisateur", + "logout": "Déconnexion", + "low_fee": "Frais modiques", + "low_fee_alert": "Vous utilisez actuellement une priorité de frais de réseau peu élevés. Cela pourrait entraîner de longues attentes, des taux différents ou des transactions annulées. Nous vous recommandons de fixer des frais plus élevés pour une meilleure expérience.", + "manage_nodes": "Gérer les nœuds", + "manage_pow_nodes": "Gérer les nœuds PoW", + "manage_yats": "Gérer les Yats", + "mark_as_redeemed": "Marquer comme convertie", + "market_place": "Place de marché", + "matrix_green_dark_theme": "Thème Matrix Green Dark", + "max_amount": "Max : ${value}", + "max_value": "Max: ${value} ${currency}", + "memo": "Mémo :", + "message": "Message", + "methods": "Méthodes", + "min_amount": "Min : ${value}", + "min_value": "Min: ${value} ${currency}", + "minutes_to_pin_code": "${minute} minutes", + "mm": "MM", + "modify_2fa": "Modifier les paramètres Cake 2FA", + "monero_com": "Monero.com par Cake Wallet", + "monero_com_wallet_text": "Super portefeuille (wallet) pour Monero", + "monero_dark_theme": "Thème sombre Monero", + "monero_light_theme": "Thème de lumière Monero", + "moonpay_alert_text": "Le montant doit être au moins égal à ${minAmount} ${fiatCurrency}", + "more_options": "Plus d'options", + "name": "Nom", + "narrow": "Étroit", + "new_first_wallet_text": "Gardez facilement votre crypto-monnaie en sécurité", + "new_node_testing": "Test du nouveau nœud", + "new_subaddress_create": "Créer", + "new_subaddress_label_name": "Nom", + "new_subaddress_title": "Nouvelle adresse", + "new_template": "Nouveau Modèle", + "new_wallet": "Nouveau Portefeuille (Wallet)", + "newConnection": "Nouvelle connexion", + "no_id_needed": "Aucune pièce d'identité nécessaire !", + "no_id_required": "Aucune pièce d'identité requise. Rechargez et dépensez n'importe où", + "no_relay_on_domain": "Il n'existe pas de relais pour le domaine de l'utilisateur ou le relais n'est pas disponible. Veuillez choisir un relais à utiliser.", + "no_relays": "Pas de relais", + "no_relays_message": "Nous avons trouvé un enregistrement Nostr NIP-05 pour cet utilisateur, mais il ne contient aucun relais. Veuillez demander au destinataire d'ajouter des relais à son enregistrement Nostr.", + "node_address": "Adresse du Nœud", + "node_connection_failed": "La connexion a échoué", + "node_connection_successful": "Connexion établie avec succès", + "node_new": "Nouveau Nœud", + "node_port": "Port du Nœud", + "node_reset_settings_title": "Réinitialisation des réglages", + "node_test": "Tester", + "nodes": "Nœuds", + "nodes_list_reset_to_default_message": "Êtes vous certain de vouloir revenir aux réglages par défaut ?", + "none_of_selected_providers_can_exchange": "Aucun des prestataires sélectionnés ne peut effectuer cet échange", + "noNFTYet": "Pas encore de NFT", + "normal": "Normal", + "note_optional": "Note (optionnelle)", + "note_tap_to_change": "Note (appuyez pour changer)", + "nullURIError": "L'URI est nul", + "offer_expires_in": "L'Offre expire dans : ", + "offline": "Hors ligne", + "ok": "OK", + "onion_link": "Lien .onion", + "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", + "optional_description": "Descriptif facultatif", + "optional_email_hint": "E-mail de notification du bénéficiaire facultatif", + "optional_name": "Nom du destinataire facultatif", + "optionally_order_card": "Commander éventuellement une carte physique.", + "orbot_running_alert": "Veuillez vous assurer qu'Orbot est en cours d'exécution avant de vous connecter à ce nœud.", + "order_by": "Commandé par", + "order_id": "Numéro de commande", + "order_physical_card": "Commander une carte physique", + "other_settings": "Autres paramètres", + "outdated_electrum_wallet_description": "Les nouveaux portefeuilles (wallets) Bitcoin créés dans Cake ont dorénavant une phrase secrète (seed) de 24 mots. Il est impératif que vous créiez un nouveau portefeuille Bitcoin, que vous y transfériez tous vos fonds puis que vous cessiez d'utiliser le portefeuille avec une phrase secrète de 12 mots. Merci de faire cela immédiatement pour assurer la sécurité de vos avoirs.", + "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", + "overwrite_amount": "Remplacer le montant", + "pairingInvalidEvent": "Événement de couplage non valide", + "password": "Mot de passe", + "paste": "Coller", + "pause_wallet_creation": "La possibilité de créer Haven Wallet est actuellement suspendue.", + "payment_id": "ID de Paiement : ", + "payment_was_received": "Votre paiement a été reçu.", + "pending": " (en attente)", + "percentageOf": "sur ${amount}", + "pin_at_top": "épingler ${token} en haut", + "pin_is_incorrect": "Le code PIN est incorrect", + "pin_number": "Numéro PIN", + "placeholder_contacts": "Vos contacts apparaîtront ici", + "placeholder_transactions": "Vos transactions apparaîtront ici", + "please_fill_totp": "Veuillez renseigner le code à 8 chiffres affiché sur votre autre appareil", + "please_make_selection": "Merci de faire un choix ci-dessous pour créer ou restaurer votre portefeuille (wallet).", + "please_reference_document": "Veuillez vous référer aux documents ci-dessous pour plus d'informations.", + "please_select": "Merci de sélectionner :", + "please_select_backup_file": "Merci de sélectionner le fichier de sauvegarde et de rentrer le mot de passe associé.", + "please_try_to_connect_to_another_node": "Merci d'essayer la connexion vers un autre nœud", + "please_wait": "Merci de patienter", + "polygonscan_history": "Historique de PolygonScan", + "powered_by": "Proposé par ${title}", + "pre_seed_button_text": "J'ai compris. Montrez moi ma phrase secrète (seed)", + "pre_seed_description": "Sur la page suivante vous allez voir une série de ${words} mots. Ils constituent votre phrase secrète (seed) unique et privée et sont le SEUL moyen de restaurer votre portefeuille (wallet) en cas de perte ou de dysfonctionnement. Il est de VOTRE responsabilité d'écrire cette série de mots et de la stocker dans un lieu sûr en dehors de l'application Cake Wallet.", + "pre_seed_title": "IMPORTANT", + "prevent_screenshots": "Empêcher les captures d'écran et l'enregistrement d'écran", + "privacy": "Confidentialité", + "privacy_policy": "Politique de confidentialité", + "privacy_settings": "Paramètres de confidentialité", + "private_key": "Clef privée", + "proceed_after_one_minute": "Si l'écran ne s'affiche pas après 1 minute, vérifiez vos e-mails.", + "profile": "Profil", + "provider_error": "Erreur de ${provider}", + "public_key": "Clef publique", + "purchase_gift_card": "Acheter une carte-cadeau", + "qr_fullscreen": "Appuyez pour ouvrir le QR code en mode plein écran", + "qr_payment_amount": "Ce QR code contient un montant de paiement. Voulez-vous remplacer la valeur actuelle ?", + "question_to_disable_2fa": "Êtes-vous sûr de vouloir désactiver Cake 2FA ? Un code 2FA ne sera plus nécessaire pour accéder au portefeuille (wallet) et à certaines fonctions.", + "receivable_balance": "Solde de créances", + "receive": "Recevoir", + "receive_amount": "Montant", + "received": "Reçus", + "recipient_address": "Adresse bénéficiaire", + "reconnect": "Reconnecter", + "reconnect_alert_text": "Êtes vous certain de vouloir vous reconnecter ?", + "reconnection": "Reconnexion", + "redeemed": "Converties", + "refund_address": "Adresse de Remboursement", + "reject": "Rejeter", + "remaining": "restant", + "remove": "Supprimer", + "remove_node": "Supprimer le nœud", + "remove_node_message": "Êtes vous certain de vouloir supprimer le nœud sélectionné ?", + "rename": "Renommer", + "require_for_adding_contacts": "Requis pour ajouter des contacts", + "require_for_all_security_and_backup_settings": "Exiger pour tous les paramètres de sécurité et de sauvegarde", + "require_for_assessing_wallet": "Nécessaire pour accéder au portefeuille", + "require_for_creating_new_wallets": "Nécessaire pour créer de nouveaux portefeuilles (wallets)", + "require_for_exchanges_to_external_wallets": "Exiger pour les échanges vers des portefeuilles externes", + "require_for_exchanges_to_internal_wallets": "Exiger pour les échanges vers des portefeuilles (wallets) internes", + "require_for_sends_to_contacts": "Exiger pour les envois aux contacts", + "require_for_sends_to_internal_wallets": "Exiger pour les envois vers des portefeuilles (wallets) internes", + "require_for_sends_to_non_contacts": "Exiger pour les envois hors contacts", + "require_pin_after": "Code PIN requis après", + "rescan": "Analyser la blockchain", + "resend_code": "Veuillez le renvoyer", + "reset": "Réinitialiser", + "reset_password": "Réinitialiser le mot de passe", + "restore_active_seed": "Phrase secrète (seed) active", + "restore_address": "Adresse", + "restore_bitcoin_description_from_keys": "Restaurer votre portefeuille (wallet) d'après la chaîne WIF générée d'après vos clefs privées", + "restore_bitcoin_description_from_seed": "Restaurer votre portefeuille (wallet) à l'aide d'une phrase secrète (seed) de 24 mots", + "restore_bitcoin_title_from_keys": "Restaurer depuis la chaîne WIF", + "restore_description_from_backup": "Vous pouvez restaurer l'intégralité de l'application Cake Wallet depuis un fichier de sauvegarde", + "restore_description_from_keys": "Restaurer votre portefeuille (wallet) d'après les séquences de touches générées d'après vos clefs privées", + "restore_description_from_seed": "Restaurer votre portefeuille (wallet) depuis une phrase secrète (seed) de 25 ou 13 mots", + "restore_description_from_seed_keys": "Restaurez votre portefeuille (wallet) depuis une phrase secrète (seed) ou des clefs que vous avez stockées en lieu sûr", + "restore_from_date_or_blockheight": "Merci d'entrer une date antérieure de quelques jours à la date de création de votre portefeuille (wallet). Ou si vous connaissez la hauteur de bloc, merci de la spécifier plutôt qu'une date", + "restore_from_seed_placeholder": "Merci d'entrer ou de coller votre phrase secrète (seed) ici", + "restore_new_seed": "Nouvelle phrase secrète (seed)", + "restore_next": "Suivant", + "restore_recover": "Restaurer", + "restore_restore_wallet": "Restaurer le Portefeuille (Wallet)", + "restore_seed_keys_restore": "Restaurer depuis Phrase secrète (seed)/Clefs", + "restore_spend_key_private": "Clef de dépense (spend key) (privée)", + "restore_title_from_backup": "Restaurer depuis une sauvegarde", + "restore_title_from_keys": "Restaurer depuis des clefs", + "restore_title_from_seed": "Restaurer depuis une phrase secrète (seed)", + "restore_title_from_seed_keys": "Restaurer depuis une phrase secrète (seed) ou des clefs", + "restore_view_key_private": "Clef d'audit (view key) (privée)", + "restore_wallet": "Restaurer un Portefeuille (Wallet)", + "restore_wallet_name": "Nom du portefeuille (wallet)", + "restore_wallet_restore_description": "Description de la restauration de portefeuille (wallet)", + "router_no_route": "Aucune route définie pour ${name}", + "save": "Sauvegarder", + "save_backup_password": "Merci de vous assurer d'avoir bien sauvegardé votre mot de passe de sauvegarde. Vous ne pourrez pas restaurer vos fichiers de sauvegarde sans ce dernier.", + "save_backup_password_alert": "Enregistrer le mot de passe de sauvegarde", + "save_to_downloads": "Enregistrer dans les téléchargements", + "saved_the_trade_id": "J'ai sauvegardé l'ID d'échange", + "scan_qr_code": "Scannez le QR code", + "scan_qr_code_to_get_address": "Scannez le QR code pour obtenir l'adresse", + "scan_qr_on_device": "Scannez ce code QR sur un autre appareil", + "search": "Chercher", + "search_add_token": "Rechercher / Ajouter un token", + "search_category": "Catégorie de recherche", + "search_currency": "Rechercher une devise", + "search_language": "Rechercher une langue", + "second_intro_content": "Votre Yat est une seule et unique adresse emoji qui remplace toutes vos longues adresses hexadécimales pour toutes vos cryptomonnaies.", + "second_intro_title": "Une adresse emoji pour les gouverner toutes", + "security_and_backup": "Sécurité et sauvegarde", + "seed_alert_back": "Retour", + "seed_alert_content": "La phrase secrète (seed) est la seule façon de restaurer votre portefeuille (wallet). L'avez-vous correctement écrite ?", + "seed_alert_title": "Attention", + "seed_alert_yes": "Oui, je suis sûr", + "seed_choose": "Choisissez la langue de la phrase secrète (seed)", "seed_hex_form": "Graine du portefeuille (forme hexagonale)", + "seed_key": "Clé secrète (seed key)", + "seed_language": "Langage de la phrase secrète", + "seed_language_chinese": "Chinois", + "seed_language_chinese_traditional": "Chinois (Traditionnel)", + "seed_language_czech": "tchèque", + "seed_language_dutch": "Néerlandais", + "seed_language_english": "Anglais", + "seed_language_french": "Français", + "seed_language_german": "Allemand", + "seed_language_italian": "Italien", + "seed_language_japanese": "Japonais", + "seed_language_korean": "coréen", + "seed_language_next": "Suivant", + "seed_language_portuguese": "Portugais", + "seed_language_russian": "Russe", + "seed_language_spanish": "Espagnol", + "seed_phrase_length": "Longueur de la phrase de départ", + "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)", "seedtype": "Type de type graine", "seedtype_legacy": "Héritage (25 mots)", "seedtype_polyseed": "Polyseed (16 mots)", - "seed_language_czech": "tchèque", - "seed_language_korean": "coréen", - "seed_language_chinese_traditional": "Chinois (Traditionnel)", - "ascending": "Ascendant", - "descending": "Descendant", - "dfx_option_description": "Achetez des crypto-monnaies avec EUR et CHF. Jusqu'à 990€ sans KYC supplémentaire. Pour les clients particuliers et entreprises en Europe", - "polygonscan_history": "Historique de PolygonScan", - "wallet_seed_legacy": "Graine de portefeuille hérité", - "default_sell_provider": "Fournisseur de vente par défaut", + "select_backup_file": "Sélectionnez le fichier de sauvegarde", + "select_buy_provider_notice": "Sélectionnez un fournisseur d'achat ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur d'achat par défaut dans les paramètres de l'application.", + "select_destination": "Veuillez sélectionner la destination du fichier de sauvegarde.", "select_sell_provider_notice": "Sélectionnez un fournisseur de vente ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur de vente par défaut dans les paramètres de l'application.", - "custom_drag": "Custom (maintenir et traîner)", + "sell": "Vendre", + "sell_alert_content": "Nous ne prenons actuellement en charge que la vente de Bitcoin, Ethereum et Litecoin. Veuillez créer ou basculer vers votre portefeuille Bitcoin, Ethereum ou Litecoin.", + "sell_monero_com_alert_content": "La vente de Monero n'est pas encore prise en charge", + "send": "Envoyer", + "send_address": "adresse ${cryptoCurrency}", + "send_amount": "Montant :", + "send_creating_transaction": "Création de la transaction", + "send_error_currency": "La monnaie ne peut contenir que des nombres", + "send_error_minimum_value": "La valeur minimale du montant est 0.01", + "send_estimated_fee": "Estimation des frais :", + "send_fee": "Frais :", + "send_name": "Nom", + "send_new": "Nouveau", + "send_payment_id": "ID de paiement (optionnel)", + "send_priority": "Actuellement les frais sont positionnés à la priorité ${transactionPriority}.\nLa priorité de la transaction peut être modifiée dans les réglages", + "send_sending": "Envoi...", + "send_success": "Vos ${crypto} ont été envoyés avec succès", + "send_templates": "Modèles d'envois", + "send_title": "Envoyer", + "send_to_this_address": "Envoyer ${currency} ${tag}à cette adresse", + "send_xmr": "Envoyer XMR", + "send_your_wallet": "Votre portefeuille (wallet)", + "sending": "Envoi", + "sent": "Envoyés", + "settings": "Paramètres", + "settings_all": "TOUT", + "settings_allow_biometrical_authentication": "Autoriser l'authentification biométrique", + "settings_can_be_changed_later": "Ces paramètres peuvent être modifiés ultérieurement dans les paramètres de l'application", + "settings_change_language": "Modifier la langue", + "settings_change_pin": "Modifier le code PIN", + "settings_currency": "Devise", + "settings_current_node": "Nœud actuel", + "settings_dark_mode": "Mode sombre", + "settings_display_balance": "Affichage du solde", + "settings_display_on_dashboard_list": "Afficher sur la liste des tableaux de bord", + "settings_fee_priority": "Priorité des frais", + "settings_nodes": "Nœuds", + "settings_none": "Rien", + "settings_only_trades": "Seulement les échanges", + "settings_only_transactions": "Seulement les transactions", + "settings_personal": "Personnel", + "settings_save_recipient_address": "Sauvegarder l'adresse du bénéficiaire", + "settings_support": "Support", + "settings_terms_and_conditions": "Termes et Conditions", + "settings_title": "Réglages", + "settings_trades": "Échanges", + "settings_transactions": "Transactions", + "settings_wallets": "Portefeuilles (Wallets)", + "setup_2fa": "Paramétrer Cake 2FA", + "setup_2fa_text": "Cake 2FA fonctionne en utilisant TOTP comme deuxième facteur d'authentification.\n\nLe TOTP de Cake 2FA nécessite la prise en charge de SHA-512 et de 8 chiffres ; cela offre une sécurité accrue. Plus d’informations et les applications prises en charge peuvent être trouvées dans le guide.", + "setup_pin": "Configurer le code PIN", + "setup_successful": "Votre code PIN a été configuré avec succès !", + "setup_totp_recommended": "Configurer TOTP", + "setup_warning_2fa_text": "Vous devrez restaurer votre portefeuille à partir de la graine mnémonique.\n\nLe support Cake ne pourra pas vous aider si vous perdez l'accès à vos graines 2FA ou mnémoniques.\nCake 2FA est une seconde authentification pour certaines actions dans le portefeuille. Avant d'utiliser Cake 2FA, nous vous recommandons de lire le guide.Ce n’est PAS aussi sécurisé que l’entreposage frigorifique.\n\nSi vous perdez l'accès à votre application 2FA ou à vos clés TOTP, vous perdrez l'accès à ce portefeuille. ", + "setup_your_debit_card": "Configurer votre carte de débit", + "share": "Partager", + "share_address": "Partager l'adresse", + "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é", + "show_seed": "Visualiser la phrase secrète (seed)", + "sign_up": "S'inscrire", + "signTransaction": "Signer une transaction", + "signup_for_card_accept_terms": "Inscrivez-vous pour la carte et acceptez les conditions.", + "slidable": "Glissable", + "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)", + "status": "Statut : ", + "subaddress_title": "Liste des sous-adresses", + "subaddresses": "Sous-adresses", + "submit_request": "soumettre une requête", + "successful": "Réussi", + "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_live_chat": "Support en direct", + "support_title_other_links": "Autres liens d'assistance", + "sweeping_wallet": "Portefeuille (wallet) de consolidation", + "sweeping_wallet_alert": "Cette opération ne devrait pas prendre longtemps. NE QUITTEZ PAS CET ÉCRAN OU LES FONDS CONSOLIDÉS POURRAIENT ÊTRE PERDUS", + "switchToETHWallet": "Veuillez passer à un portefeuille (wallet) Ethereum et réessayer", "switchToEVMCompatibleWallet": "Veuillez passer à un portefeuille compatible EVM et réessayer (Ethereum, Polygon)", - "receivable_balance": "Solde de créances", - "confirmed_tx": "Confirmé", + "symbol": "Symbole", + "sync_all_wallets": "Synchroniser tous les portefeuilles", + "sync_status_attempting_sync": "TENTATIVE DE SYNCHRONISATION", + "sync_status_connected": "CONNECTÉ", + "sync_status_connecting": "CONNEXION EN COURS", + "sync_status_failed_connect": "DÉCONNECTÉ", + "sync_status_not_connected": "NON CONNECTÉ", + "sync_status_starting_sync": "DÉBUT DE SYNCHRO", + "sync_status_syncronized": "SYNCHRONISÉ", + "sync_status_syncronizing": "SYNCHRONISATION EN COURS", + "syncing_wallet_alert_content": "Votre solde et votre liste de transactions peuvent ne pas être à jour tant que la mention « SYNCHRONISÉ » n'apparaît en haut de l'écran. Cliquez/appuyez pour en savoir plus.", + "syncing_wallet_alert_title": "Votre portefeuille (wallet) est en cours de synchronisation", + "template": "Modèle", + "template_name": "Nom du modèle", + "third_intro_content": "Les Yats existent aussi en dehors de Cake Wallet. Toute adresse sur terre peut être remplacée par un Yat !", + "third_intro_title": "Yat est universel", + "time": "${minutes}m ${seconds}s", + "tip": "Pourboire :", + "today": "Aujourd'hui", + "token_contract_address": "Adresse du contrat de token", + "token_decimal": "Décimales de token", + "token_name": "Nom du token, par exemple : Tether", + "token_symbol": "Symbole de token, par exemple : USDT", + "tokenID": "IDENTIFIANT", + "tor_connection": "Connexion Tor", + "tor_only": "Tor uniquement", + "total_saving": "Économies totales", + "totp_2fa_failure": "Code incorrect. Veuillez essayer un code différent ou générer un nouveau secret TOTP. Utilisez une application 2FA compatible qui prend en charge les codes à 8 chiffres et SHA512.", + "totp_2fa_success": "Succès! Cake 2FA est activé pour ce portefeuille. N'oubliez pas de sauvegarder votre phrase secrète (seed) au cas où vous perdriez l'accès au portefeuille (wallet).", + "totp_auth_url": "URL D'AUTORISATION TOTP", + "totp_code": "Code TOTP", + "totp_secret_code": "Secret TOTP", + "totp_verification_success": "Vérification réussie !", + "trade_details_copied": "${title} copié vers le presse-papier", + "trade_details_created_at": "Créé le", + "trade_details_fetching": "Récupération", + "trade_details_id": "ID", + "trade_details_pair": "Paire", + "trade_details_provider": "Fournisseur", + "trade_details_state": "Statut", + "trade_details_title": "Détails de l'échange", + "trade_for_not_created": "L'échange pour ${title} n'est pas créé.", + "trade_history_title": "Historique des échanges", + "trade_id": "ID d'échange :", + "trade_id_not_found": "Échange ${tradeId} de ${title} introuvable.", + "trade_is_powered_by": "Cet échange est proposé par ${provider}", + "trade_not_created": "Échange non créé", + "trade_not_found": "Échange introuvable.", + "trade_state_btc_sent": "Btc envoyés", + "trade_state_complete": "Finalisé", + "trade_state_confirming": "En cours de confirmation", + "trade_state_created": "Créé", + "trade_state_finished": "Terminé", + "trade_state_paid": "Payé", + "trade_state_paid_unconfirmed": "Payé mais non confirmé", + "trade_state_pending": "En cours", + "trade_state_timeout": "Délai dépassé", + "trade_state_to_be_created": "À créer", + "trade_state_traded": "Échange terminé", + "trade_state_trading": "Échange en cours", + "trade_state_underpaid": "Sous payé", + "trade_state_unpaid": "Non payé", + "trades": "Échanges", + "transaction_details_amount": "Montant", + "transaction_details_copied": "${title} copié vers le presse-papier", + "transaction_details_date": "Date", + "transaction_details_fee": "Frais", + "transaction_details_height": "Hauteur", + "transaction_details_recipient_address": "Adresse du bénéficiaire", "transaction_details_source_address": "Adresse source", - "pause_wallet_creation": "La possibilité de créer Haven Wallet est actuellement suspendue.", - "contractName": "Nom du contrat", - "contractSymbol": "Symbole du contrat", - "description": "Description", - "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.", - "no_relays": "Pas de relais", - "choose_relay": "Veuillez choisir un relais à utiliser", - "no_relays_message": "Nous avons trouvé un enregistrement Nostr NIP-05 pour cet utilisateur, mais il ne contient aucun relais. Veuillez demander au destinataire d'ajouter des relais à son enregistrement Nostr.", - "no_relay_on_domain": "Il n'existe pas de relais pour le domaine de l'utilisateur ou le relais n'est pas disponible. Veuillez choisir un relais à utiliser." -} + "transaction_details_title": "Détails de transaction", + "transaction_details_transaction_id": "ID de transaction", + "transaction_key": "Clef de Transaction", + "transaction_priority_fast": "Rapide", + "transaction_priority_fastest": "Le plus rapide", + "transaction_priority_medium": "Moyen", + "transaction_priority_regular": "Normal", + "transaction_priority_slow": "Lent", + "transaction_sent": "Transaction émise !", + "transaction_sent_notice": "Si l'écran ne continue pas après 1 minute, vérifiez un explorateur de blocs et votre e-mail.", + "transactions": "Transactions", + "transactions_by_date": "Transactions par date", + "trusted": "de confiance", + "unavailable_balance": "Solde indisponible", + "unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.", + "unconfirmed": "Solde non confirmé", + "understand": "J'ai compris", + "unmatched_currencies": "La devise de votre portefeuille (wallet) actuel ne correspond pas à celle du QR code scanné", + "unspent_change": "Changement", + "unspent_coins_details_title": "Détails des pièces (coins) non dépensées", + "unspent_coins_title": "Pièces (coins) non dépensées", + "unsupported_asset": "Nous ne prenons pas en charge cette action pour cet élément. Veuillez créer ou passer à un portefeuille d'un type d'actif pris en charge.", + "upto": "jusqu'à ${value}", + "use": "Changer vers code PIN à ", + "use_card_info_three": "Utilisez la carte numérique en ligne ou avec des méthodes de paiement sans contact.", + "use_card_info_two": "Les fonds sont convertis en USD lorsqu'ils sont détenus sur le compte prépayé, et non en devises numériques.", + "use_ssl": "Utiliser SSL", + "use_suggested": "Suivre la suggestion", + "variable_pair_not_supported": "Cette paire variable n'est pas prise en charge avec les échanges sélectionnés", + "verification": "Vérification", + "verify_with_2fa": "Vérifier avec Cake 2FA", + "version": "Version ${currentVersion}", + "view_all": "Voir tout", + "view_in_block_explorer": "Voir dans l'Explorateur de Blocs", + "view_key_private": "Clef d'audit (view key) (privée)", + "view_key_public": "Clef d'audit (view key) (publique)", + "view_transaction_on": "Voir la Transaction sur ", + "wallet_keys": "Phrase secrète (seed)/Clefs du portefeuille (wallet)", + "wallet_list_create_new_wallet": "Créer un Nouveau Portefeuille (Wallet)", + "wallet_list_edit_wallet": "Modifier le portefeuille", + "wallet_list_failed_to_load": "Échec de chargement du portefeuille (wallet) ${wallet_name}. ${error}", + "wallet_list_failed_to_remove": "Échec de la suppression du portefeuille (wallet) ${wallet_name}. ${error}", + "wallet_list_load_wallet": "Charger un Portefeuille (Wallet)", + "wallet_list_loading_wallet": "Chargement du portefeuille (wallet) ${wallet_name}", + "wallet_list_removing_wallet": "Suppression du portefeuille (wallet) ${wallet_name}", + "wallet_list_restore_wallet": "Restaurer un Portefeuille (Wallet)", + "wallet_list_title": "Portefeuille (Wallet) Monero", + "wallet_list_wallet_name": "Nom du portefeuille", + "wallet_menu": "Menu", + "wallet_name": "Nom du Portefeuille (Wallet)", + "wallet_name_exists": "Un portefeuille (wallet) portant ce nom existe déjà", + "wallet_restoration_store_incorrect_seed_length": "Longueur de phrase secrète (seed) incorrecte", + "wallet_seed": "Phrase secrète (seed) du portefeuille (wallet)", + "wallet_seed_legacy": "Graine de portefeuille hérité", + "wallet_store_monero_wallet": "Portefeuille (Wallet) Monero", + "walletConnect": "WalletConnect", + "wallets": "Portefeuilles (Wallets)", + "warning": "Avertissement", + "welcome": "Bienvenue sur", + "welcome_to_cakepay": "Bienvenue sur Cake Pay !", + "widgets_address": "Adresse", + "widgets_or": "ou", + "widgets_restore_from_blockheight": "Restaurer depuis une hauteur de bloc", + "widgets_restore_from_date": "Restaurer depuis une date", + "widgets_seed": "Phrase secrète (seed)", + "wouoldLikeToConnect": "je voudrais me connecter", + "write_down_backup_password": "Merci d'écrire votre mot de passe de sauvegarde, vous en aurez besoin lors de la relecture de vos fichiers de sauvegarde.", + "xlm_extra_info": "Merci de ne pas oublier de spécifier l'ID de mémo lors de l'envoi de la transaction XLM de l'échange", + "xmr_available_balance": "Solde Disponible", + "xmr_full_balance": "Solde Total", + "xmr_hidden": "Caché", + "xmr_to_error": "Erreur XMR.TO", + "xmr_to_error_description": "Montant invalide. La partie décimale doit contenir au plus 8 chiffres", + "xrp_extra_info": "Merci de ne pas oublier de spécifier le tag de destination lors de l'envoi de la transaction XRP de l'échange", + "yat": "Yat", + "yat_address": "Adresse Yat", + "yat_alert_content": "Les utilisateurs de Cake Wallet peuvent maintenant envoyer et recevoir leurs monnaies favorites avec un utilisateur unique en son genre basé sur les emojis.", + "yat_alert_title": "Envoyez et recevez des cryptos plus facilement avec Yat", + "yat_error": "Erreur Yat", + "yat_error_content": "Aucune adresse associée à ce Yat. Essayez un autre Yat", + "yat_popup_content": "Vous pouvez à présent envoyer et recevoir des cryptos dans Cake Wallet à l'aide de votre Yat - un nom d'utilisateur court à base d'emoji. Gérér les Yats à tout moment depuis l'écran de paramétrage", + "yat_popup_title": "L'adresse de votre portefeuille (wallet) peut être emojifiée.", + "yesterday": "Hier", + "you_now_have_debit_card": "Vous avez maintenant une carte de débit", + "you_pay": "Vous payez", + "you_will_get": "Convertir vers", + "you_will_send": "Convertir depuis", + "yy": "AA", + "zzzz": "zzzz" +} \ No newline at end of file diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 2f2343434..748c134c6 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -1,761 +1,762 @@ { - "welcome": "Barka da zuwa", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Aikace-aikacen e-wallet ga Monero, Bitcoin, Ethereum, Litecoin, da kuma Haven", - "please_make_selection": "Don Allah zaɓi ƙasa don ƙirƙira ko dawo da kwalinku.", - "create_new": "Ƙirƙira Sabon Kwalinku", - "restore_wallet": "Dawo da Kwalinku", - "monero_com": "Monero.com ta Cake Wallet", - "monero_com_wallet_text": "Aikace-aikacen e-wallet ga Monero", - "haven_app": "Haven da Cake Wallet", - "haven_app_wallet_text": "Aikace-aikacen e-wallet ga Haven", - "accounts": "Lissafi", - "edit": "Gyara", + "about_cake_pay": "Biyan Cake yana ba ku damar sauƙin siyan katunan kyauta tare da kadarorin kama-da-wane, wanda za'a iya kashewa nan take a sama da yan kasuwa 150,000 a Amurka.", "account": "Asusu", + "accounts": "Lissafi", + "accounts_subaddresses": "Accounts da subaddresses", + "activate": "Kunna", + "active": "Mai aiki", + "active_cards": "Katunan aiki", + "activeConnectionsPrompt": "Haɗin kai mai aiki zai bayyana a nan", "add": "Ƙara", + "add_contact": "Ƙara lamba", + "add_custom_node": "Ƙara Sabon Kulli na Custom", + "add_custom_redemption": "Ƙara Ceto na Musamman", + "add_fund_to_card": "Ƙara kuɗin da aka riga aka biya a katunan (har zuwa ${value})", + "add_new_node": "Ƙara sabon node", + "add_new_word": "Ƙara kalma sabuwa", + "add_receiver": "Ƙara wani mai karɓa (na zaɓi)", + "add_secret_code": "Ko, ƙara wannan lambar sirrin zuwa ƙa'idar mai tabbatarwa", + "add_tip": "Ƙara Tukwici", + "add_token_disclaimer_check": "Na tabbatar da adireshin kwangilar alamar da bayanin ta amfani da ingantaccen tushe. Ƙara bayanan ƙeta ko kuskure na iya haifar da asarar kuɗi.", + "add_token_warning": "Kar a gyara ko ƙara alamu kamar yadda masu zamba suka umarta.\nKoyaushe tabbatar da adiresoshin alamar tare da sanannun tushe!", + "add_value": "Ƙara ƙima", + "address": "Adireshi", "address_book": "Littafin adireshi", - "contact": "Tuntuɓar", - "please_select": "Don Allah zaɓi:", - "cancel": "Soke", - "ok": "OK", - "contact_name": "Sunan Tuntuɓi", - "reset": "Sake saiti", - "save": "Ajiye", + "address_book_menu": "Littafin adireshi", + "address_detected": "An gano adireshin", + "address_from_domain": "Wannan adireshin ya fito daga ${domain} akan Unstoppable Domain", + "address_from_yat": "Wannan adireshin daga ${emoji} ne akan Yat", + "address_label": "Labari adireshi", "address_remove_contact": "Cire lamba", "address_remove_content": "Kuna tabbatar kuna so ku cire wannan Contact?", - "authenticated": "Ingantacce", - "authentication": "Tabbatarwa", - "failed_authentication": "Binne wajen shiga. ${state_error}", - "wallet_menu": "Menu", - "Blocks_remaining": "${status} Katanga ya rage", - "please_try_to_connect_to_another_node": "Don Allah yi ƙoƙarin haɗa da wani node", - "xmr_hidden": "Boye", - "xmr_available_balance": "Akwai Ma'auni", - "xmr_full_balance": "Cikakken Ma'auni", - "send": "Aika", - "receive": "Samu", - "transactions": "Ma'amaloli", - "incoming": "Mai shigowa", - "outgoing": "Mai fita", - "transactions_by_date": "Ma'amaloli ta kwanan wata", - "trades": "Cinikai", - "filter_by": "Tace ta", - "today": "Yau", - "yesterday": "Jiya", - "received": "Samu", - "sent": "Aika", - "pending": "(pending)", - "rescan": "Rescan", - "reconnect": "Sake haɗawa", - "wallets": "Wallets", - "show_seed": "Nuna iri", - "show_keys": "Nuna iri/maɓallai", - "address_book_menu": "Littafin adireshi", - "reconnection": "Sake haɗawa", - "reconnect_alert_text": "Shin kun tabbata kuna son sake haɗawa?", - "exchange": "Exchange", - "clear": "Share", - "refund_address": "Adireshin maidowa", - "change_exchange_provider": "Canza Mai Bayar da Musanya", - "you_will_send": "Maida daga", - "you_will_get": "Maida zuwa", - "amount_is_guaranteed": "Adadin da aka karɓa yana da garanti", - "amount_is_estimate": "Adadin da aka karɓa shine kimantawa", - "powered_by": "An ƙarfafa shi ta ${title}", - "error": "Kuskure", - "estimated": "Kiyasta", - "min_value": "Min: ${value} ${currency}", - "max_value": "Max: ${value} ${currency}", - "change_currency": "Canja Kuɗi", - "overwrite_amount": "Rubuta adadin", - "qr_payment_amount": "Wannan QR code yana da adadin kuɗi. Kuna so ku overwrite wannan adadi?", - "copy_id": "Kwafi ID", - "exchange_result_write_down_trade_id": "Da fatan za a kwafa ko rubuta ID ɗin ciniki don ci gaba.", - "trade_id": "ID na kasuwanci:", - "copied_to_clipboard": "An kwafi zuwa Clipboard", - "saved_the_trade_id": "Na ajiye ID na ciniki", - "fetching": "Daukewa", - "id": "ID:", - "amount": "Adadi:", - "payment_id": "ID na biyan kuɗi:", - "status": "Matsayi:", - "offer_expires_in": "tayin zai ƙare a:", - "trade_is_powered_by": "Ana yin wannan ciniki ta hanyar ${provider}", - "copy_address": "Kwafi Adireshin", - "exchange_result_confirm": "Ta danna tabbatarwa, zaku aika ${fetchingLabel} ${from} daga walat ɗin ku mai suna ${walletName} zuwa address dake kasa. Ko zaka iya aika daga kwalinku na external zuwa address/QR code dake kasa.\n\nDon Allah shigar da confirm don ci gaba ko dawo ka canja adadinku.", - "exchange_result_description": "Dole ne ku aika mafi ƙarancin ${fetchingLabel} ${from} zuwa adireshin da aka nuna akan shafi na gaba. Idan ka aika adadi kasa da ${fetchingLabel} ${from} bazai yi converting ba kuma ba zai koma ba.", - "exchange_result_write_down_ID": "*Don Allah kwafi ko rubuta ID dake nuna sama.", - "confirm": "Tabbatar", - "confirm_sending": "Tabbatar da aikawa", - "commit_transaction_amount_fee": "Aikata ciniki\nAdadi: ${amount}\nKuda: ${fee}", - "sending": "Aika", - "transaction_sent": "An aika ciniki!", - "expired": "Karewa", - "time": "${minutes}m ${seconds}s", - "send_xmr": "Aika XMR", - "exchange_new_template": "Sabon template", - "faq": "FAQ", - "enter_your_pin": "Shigar da PIN", - "loading_your_wallet": "Ana loda walat ɗin ku", - "new_wallet": "Sabuwar Wallet", - "wallet_name": "Sunan walat", - "continue_text": "Ci gaba", - "choose_wallet_currency": "Da fatan za a zaɓi kuɗin walat:", - "node_new": "Sabon Node", - "node_address": "Address Node", - "node_port": "Node tashar jiragen ruwa", - "login": "Shiga", - "password": "Kalmar wucewa", - "nodes": "Nodes", - "node_reset_settings_title": "Sake saitunan", - "nodes_list_reset_to_default_message": "Kuna tabbatar kuna so ku sake saitunan zuwa default?", - "change_current_node": "Kuna tabbatar kuna so ku canja node yanzu zuwa ${node}?", - "change": "Canja", - "remove_node": "Cire node", - "remove_node_message": "Kuna tabbatar kuna so ku cire wannan node?", - "remove": "Cire", - "delete": "Share", - "add_new_node": "Ƙara sabon node", - "change_current_node_title": "Canja node yanzu", - "node_test": "Gwaji", - "node_connection_successful": "Haɗin ya yi nasara", - "node_connection_failed": "Haɗin ya gaza", - "new_node_testing": "Sabbin gwajin kumburi", - "use": "Canja zuwa", - "digit_pin": "-lambar PIN", - "share_address": "Raba adireshin", - "receive_amount": "Adadi", - "subaddresses": "Subaddresses", "addresses": "Addresses", - "scan_qr_code": "Gani QR kodin", - "qr_fullscreen": "Matsa don buɗe lambar QR na cikakken allo", - "rename": "Sake suna", - "choose_account": "Zaɓi asusu", - "create_new_account": "Ƙirƙiri sabon asusu", - "accounts_subaddresses": "Accounts da subaddresses", - "restore_restore_wallet": "Maida Wallet", - "restore_title_from_seed_keys": "Dawo da iri/maɓallai", - "restore_description_from_seed_keys": "Maido da walat ɗin ku daga iri/maɓallan da kuka adana don amintaccen wuri", - "restore_next": "Na gaba", - "restore_title_from_backup": "Dawo daga madadin", - "restore_description_from_backup": "Kuna iya dawo da duk aikace-aikacen Wallet ɗin Cake daga fayil ɗin ajiyar ku", - "restore_seed_keys_restore": "Mayar da iri/Maɓallai", - "restore_title_from_seed": "Maidowa daga iri", - "restore_description_from_seed": "Dawo da kwalinku daga 25 ko 13 lambar haɗin kalma", - "restore_title_from_keys": "Dawo daga maɓallai", - "restore_description_from_keys": "Maido da walat ɗin ku daga maɓallan maɓalli da aka ƙera da aka ajiye daga maɓallan ku na sirri", - "restore_wallet_name": "Sunan kwalinku", - "restore_address": "Address", - "restore_view_key_private": "Maɓallin Duba (key kalmar sirri)", - "restore_spend_key_private": "Maɓallin kashewa (key kalmar sirri)", - "restore_recover": "Maida", - "restore_wallet_restore_description": "Bayanin dawo da walat", - "restore_new_seed": "Sabon iri", - "restore_active_seed": "iri mai aiki", - "restore_bitcoin_description_from_seed": "Dawo da kwalinku daga 24 lambar haɗin kalma", - "restore_bitcoin_description_from_keys": "Dawo da kwalinku daga WIF string dake generate daga maɓallan sirri", - "restore_bitcoin_title_from_keys": "Dawo daga WIF", - "restore_from_date_or_blockheight": "Don Allah shigar da wata kwanan a kafin ku ƙirƙirar wannan kwalinku. Ko idan kun san blockheight, don Allah shigar da shi", - "seed_reminder": "Don Allah rubuta wadannan in case ka manta ko ka sake kwallon wayarka", - "seed_title": "iri", - "seed_share": "Raba iri", - "copy": "Kwafi", - "seed_language": "Harshen Magani", - "seed_choose": "Zaɓi harshen seed", - "seed_language_next": "Na gaba", - "seed_language_english": "Ingilishi", - "seed_language_chinese": "Sinanci", - "seed_language_dutch": "Dutch", - "seed_language_german": "Jamus", - "seed_language_japanese": "Jafananci", - "seed_language_portuguese": "Fotigal", - "seed_language_russian": "Rashanci", - "seed_language_spanish": "Spanish", - "seed_language_french": "Faransanci", - "seed_language_italian": "Italiyanci", - "send_title": "Aika", - "send_your_wallet": "Walat ɗin ku", - "send_address": "${cryptoCurrency} address", - "send_payment_id": "ID na biyan kuɗi (optional)", + "advanced_settings": "Saitunan ci gaba", + "aggressive": "Mai tsananin kishi", + "agree": "Yarda", + "agree_and_continue": "Amincewa & Ci gaba", + "agree_to": "Ta hanyar ƙirƙirar asusu kun yarda da", "all": "DUK", - "send_error_minimum_value": "Mafi ƙarancin ƙimar adadin shine 0.01", - "send_error_currency": "Kudi zai iya ƙunsar lambobi kawai", - "send_estimated_fee": "Ƙimar kuɗi:", - "send_priority": "Yanzu haka fee yana set a ${transactionPriority} fifiko.\nAna iya daidaita fifikon ciniki a cikin saitunan", - "send_creating_transaction": "Ƙirƙirar ciniki", - "send_templates": "Samfura", - "send_new": "Sabon", - "send_amount": "Adadi:", - "send_fee": "Kudin:", - "send_name": "Sunan", - "got_it": "Gama", - "send_sending": "Aika...", - "send_success": "${crypto} kwalinku ya aika da nasara", - "settings_title": "Saitunan", - "settings_nodes": "Nodes", - "settings_current_node": "Node yanzu", - "settings_wallets": "Wallets", - "settings_display_balance": "Nuna ma'auni", - "settings_currency": "Kudi", - "settings_fee_priority": "fifikon kuɗi", - "settings_save_recipient_address": "Ajiye adireshin mai karɓa", - "settings_personal": "Na sirri", - "settings_change_pin": "Canja PIN", - "settings_change_language": "Canja yaren", - "settings_allow_biometrical_authentication": "Bada izinin tantance sawun yatsa", - "settings_dark_mode": "Launi mai duhu", - "settings_transactions": "Ma'amaloli", - "settings_trades": "Cinikai", - "settings_display_on_dashboard_list": "Nuna a kan tebur na bayanan", - "settings_all": "DUK", - "settings_only_trades": "Kawai kasuwancin", - "settings_only_transactions": "Kawai ayyuka", - "settings_none": "Babu", - "settings_support": "Taimako", - "settings_terms_and_conditions": "Sharuɗɗa da Ka'idoji", - "pin_is_incorrect": "PIN ba daidai ba ne", - "setup_pin": "Saita PIN", - "enter_your_pin_again": "Shigar da PIN ɗinku na sake", - "setup_successful": "An saita PIN ɗinku da nasara!", - "wallet_keys": "Iri/maɓalli na walat", - "wallet_seed": "kalmar sirri na walat", - "private_key": "Keɓaɓɓen maɓalli", - "public_key": "Maɓallin jama'a", - "view_key_private": "Duba maɓallin (maɓallin kalmar sirri)", - "view_key_public": "Maɓallin Duba (maɓallin jama'a)", - "spend_key_private": "makullin biya (maɓallin kalmar sirri)", - "spend_key_public": "makullin biya (maɓallin jama'a)", - "copied_key_to_clipboard": "An kwafa ${key} a cikin kwafin", - "new_subaddress_title": "Adireshin sabuwa", - "new_subaddress_label_name": "Lakabin suna", - "new_subaddress_create": "Ƙirƙiri", - "address_label": "Labari adireshi", - "subaddress_title": "Jagorar subaddress", - "trade_details_title": "Bayanai game da kasuwancin", - "trade_details_id": "ID", - "trade_details_state": "Matsayi", - "trade_details_fetching": "Daukewa", - "trade_details_provider": "Mai bayarwa", - "trade_details_created_at": "An ƙirƙira a", - "trade_details_pair": "miji da matarsa", - "trade_details_copied": "${title} an kwafa zuwa cikin kwafin", - "trade_history_title": "Tarihin kasuwancin", - "transaction_details_title": "Bayanai game da aikace-aikacen", - "transaction_details_transaction_id": "ID na kasuwanci", - "transaction_details_date": "Kwanan wata", - "transaction_details_height": "tsawo", - "transaction_details_amount": "Adadin", - "transaction_details_fee": "Kudin", - "transaction_details_copied": "${title} an kwafa zuwa cikin kwafin", - "transaction_details_recipient_address": "Adireshin masu amfani", - "wallet_list_title": "Monero walat", - "wallet_list_create_new_wallet": "Ƙirƙiri Sabon Wallet", - "wallet_list_edit_wallet": "Gyara walat", - "wallet_list_wallet_name": "Sunan walat", - "wallet_list_restore_wallet": "Maida Wallet", - "wallet_list_load_wallet": "Ana loda wallet na Monero", - "wallet_list_loading_wallet": "Ana loda ${wallet_name} walat", - "wallet_list_failed_to_load": "An kasa loda ${wallet_name} walat. ${error}", - "wallet_list_removing_wallet": "Cirewa ${wallet_name} walat", - "wallet_list_failed_to_remove": "Ba a iya cirewa ${wallet_name} walat. ${error}", - "widgets_address": "Adireshin", - "widgets_restore_from_blockheight": "Sake dawo da daga blockheight", - "widgets_restore_from_date": "Sake dawo da daga kwanan wata", - "widgets_or": "ko", - "widgets_seed": "iri", - "router_no_route": "Babu wata hanya da aka bayyana don ${name}", - "error_text_account_name": "Sunan ajiya zai iya ɗauka ne kawai da haruffa, lambobi\nkuma ya zama tsakanin 1 zuwa 15 haruffa", - "error_text_contact_name": "Sunan kira ba zai iya ɗaukar ` , ' \" haruffa\nkuma ya zama tsakanin 1 zuwa 32 haruffa", - "error_text_address": "Adireshin hujja ya kamata ya dace da irin\nna cryptocurrency", - "error_text_node_address": "Da fatan a shigar da iPv4 adireshin", - "error_text_node_port": "Node tashar jiragen ruwa zai iya ƙunsar lambobi tsakanin 0 zuwa 65535 kawai", - "error_text_node_proxy_address": "Da fatan za a shigar da :, misali 127.0.0.1:9050", - "error_text_payment_id": "ID na biyan kudi kawai zai iya ɗaukar daga 16 zuwa 64 haruffa a cikin hex", - "error_text_xmr": "XMR adadin ba zai iya wuce available balance.\nAdadin haruffan gaba zai kamata ya zama ko ƙasa daga na 12", - "error_text_fiat": "Adadin kudin ba zai iya wuce available balance.\nAdadin haruffan gaba zai kamata ya zama ko ƙasa daga na 2", - "error_text_subaddress_name": "Sunan subaddress ba zai iya ɗaukar `, ', \" haruffa\nkuma ya zama tsakanin 1 zuwa 20 haruffa", - "error_text_amount": "Adadin biya zai iya ƙunsar lambobi kawai", - "error_text_wallet_name": "Sunan hujja kawai zai iya ɗauka ne haruffa, lambobi, _ - haruffa\nkuma ya zama tsakanin 1 zuwa 33 haruffa", - "error_text_keys": "Ƙunci na hujja kawai zai iya ɗaukar 64 haruffa a cikin hex", - "error_text_crypto_currency": "Adadin haruffan gaba\n zai kamata ya zama ko ƙasa daga na 12", - "error_text_minimal_limit": "Kasuwanci ga ${provider} ba a yi ba. Adadin shine ƙasa fiye da ƙananan: ${min} ${currency}", - "error_text_maximum_limit": "Kasuwanci ga ${provider} ba a yi ba. Adadin shine fiye da ƙimanin: ${max} ${currency}", - "error_text_limits_loading_failed": "Kasuwanci ga ${provider} ba a yi ba. An kasa saukewa masanan", - "error_text_template": "Sunan na tushe da adireshin ba zai iya ɗaukar ` , ' \" haruffa\nkuma ya zama tsakanin 1 zuwa 106 haruffa", + "all_trades": "Duk ciniki", + "all_transactions": "Dukan Ma'amaloli", + "alphabetical": "Harafi", + "already_have_account": "Kuna da asusu?", + "always": "Koyaushe", + "amount": "Adadi:", + "amount_is_estimate": "Adadin da aka karɓa shine kimantawa", + "amount_is_guaranteed": "Adadin da aka karɓa yana da garanti", + "and": "kuma", + "anonpay_description": "Ƙirƙirar ${type}. Maƙiyantun mai nasara zai iya ${method} da duk abubuwan da ke samun lambar waya, kuma zaku samu kuɗin dama a wannan kashi.", + "apk_update": "apk sabunta", + "approve": "Amincewa", + "arrive_in_this_address": "${currency} ${tag} zai je wurin wannan adireshi", + "ascending": "Hau", + "ask_each_time": "Tambaya kowane lokaci", "auth_store_ban_timeout": "ban_timeout", "auth_store_banned_for": "An haramta don", "auth_store_banned_minutes": "da minti", "auth_store_incorrect_password": "PIN na gaskiya", - "wallet_store_monero_wallet": "Monero walat", - "wallet_restoration_store_incorrect_seed_length": "kalmar sirrin iri ba daidai ba", - "full_balance": "DUKAN KUDI", - "available_balance": "KUDI", - "hidden_balance": "BOYE KUDI", - "sync_status_syncronizing": "KWAFI", - "sync_status_syncronized": "KYAU", - "sync_status_not_connected": "BABU INTERNET", - "sync_status_starting_sync": "KWAFI", - "sync_status_failed_connect": "BABU INTERNET", - "sync_status_connecting": "HADA", - "sync_status_connected": "HANNU", - "sync_status_attempting_sync": "KWAFI", - "transaction_priority_slow": "SAURI DA SAURI", - "transaction_priority_regular": "SAURI NORMAL", - "transaction_priority_medium": "SAURI DA DADI", - "transaction_priority_fast": "sauri", - "transaction_priority_fastest": "mafi sauri", - "trade_for_not_created": "Ba a ƙirƙira ciniki don ${title} ba.", - "trade_not_created": "Ba a ƙirƙira ciniki ba", - "trade_id_not_found": "Ba a samo cinikin ${tradeId} na ${title} ba.", - "trade_not_found": "Ba a sami ciniki ba.", - "trade_state_pending": "Jira", - "trade_state_confirming": "Tabbatar", - "trade_state_trading": "Ciniki", - "trade_state_traded": "Ciniki", - "trade_state_complete": "Cikakkun", - "trade_state_to_be_created": "za a halicci", - "trade_state_unpaid": "ba a biya ba", - "trade_state_underpaid": "ba a biya gaba ɗaya ba", - "trade_state_paid_unconfirmed": "an biya amma ba a tabbatar ba", - "trade_state_paid": "an biya", - "trade_state_btc_sent": "Btc an aika", - "trade_state_timeout": "lokacin da ya ƙare", - "trade_state_created": "an halicci", - "trade_state_finished": "an kammala", - "change_language": "canja harshen", - "change_language_to": "canja harshen zuwa ${language}?", - "paste": "Manna", - "restore_from_seed_placeholder": "Da fatan za a shigar da ko manna maɓallin ku a nan", - "add_new_word": "Ƙara kalma sabuwa", - "incorrect_seed": "rubutun da aka shigar ba shi da inganci.", - "biometric_auth_reason": "Duba hoton yatsa don tantancewa", - "version": "Sigar ${currentVersion}", - "openalias_alert_title": "An gano adireshin", - "openalias_alert_content": "Zaka aika kuɗi zuwa \n${recipient_name}", - "card_address": "Adireshin:", - "buy": "Sayi", - "sell": "sayar", - "placeholder_transactions": "Za a nuna ma'amalolin ku anan", - "placeholder_contacts": "Za a nuna lambobin sadarwar ku anan", - "template": "Samfura", - "confirm_delete_template": "Wannan aikin zai share wannan samfuri. Kuna so ku ci gaba?", - "confirm_delete_wallet": "Wannan aikin zai share wannan walat. Kuna so ku ci gaba?", - "change_wallet_alert_title": "Canja walat yanzu", - "change_wallet_alert_content": "Kana so ka canja walat yanzu zuwa ${wallet_name}?", - "creating_new_wallet": "Haliccin walat sabuwa", - "creating_new_wallet_error": "Kuskure: ${description}", - "seed_alert_title": "Hankali", - "seed_alert_content": "Irin ita ce kawai hanya don dawo da walat ɗin ku. Kun rubuta shi?", - "seed_alert_back": "juya baya", - "seed_alert_yes": "E, Na yi", - "exchange_sync_alert_content": "Da fatan za a jira har sai an daidaita walat ɗin ku", - "pre_seed_title": "MUHIMMANCI", - "pre_seed_description": "A kan shafin nan za ku ga wata ƙungiya na ${words} kalmomi. Wannan shine tsarin daban-daban ku kuma na sirri kuma shine hanya ɗaya kadai don mai da purse dinku a cikin yanayin rasa ko rashin aiki. Yana da damar da kuke a cikin tabbatar da kuyi rubuta shi kuma kuyi ajiye shi a wuri na aminci wanda ya wuce wurin app na Cake Wallet.", - "pre_seed_button_text": "Ina fahimta. Nuna mini seed din nawa", - "xmr_to_error": "XMR.TO kuskure", - "xmr_to_error_description": "Adadin ba shi da inganci. Maksimum ɗaura 8 digiri bayan decimal point", - "provider_error": "${provider} kuskure", - "use_ssl": "Yi amfani da SSL", - "trusted": "Amintacce", - "color_theme": "Jigon launi", - "light_theme": "Haske", - "bright_theme": "Mai haske", - "dark_theme": "Duhu", - "enter_your_note": "Shigar da bayanin kula…", - "note_optional": "Bayani (optional)", - "note_tap_to_change": "Bayani (tap don canja)", - "view_in_block_explorer": "Dubo a cikin Block Explorer", - "view_transaction_on": "Dubo aikace-aikacen akan", - "transaction_key": "Aikace-aikacen key", - "confirmations": "Tabbatar", - "recipient_address": "Adireshin mai karɓa", - "extra_id": "Karin ID:", - "destination_tag": "Tambarin makoma:", - "memo": "Memo:", - "backup": "Ajiyayyen", - "change_password": "Canza kalmar shiga", - "backup_password": "Ajiyayyen kalmar sirri", - "write_down_backup_password": "Da fatan za a rubuta kalmar sirrin ajiyar ku, wacce ake amfani da ita don shigo da fayilolin ajiyar ku.", - "export_backup": "Ajiyayyen fitarwa", - "save_backup_password": "Da fatan za a tabbatar cewa kun adana kalmar sirrin ajiyar ku. Ba za ku iya shigo da fayilolin ajiyar ku ba tare da shi ba.", - "backup_file": "Ajiyayyen fayil", - "edit_backup_password": "Shirya Kalmar wucewa ta Ajiyayyen", - "save_backup_password_alert": "Ajiye kalmar sirri ta ajiya", - "change_backup_password_alert": "Fayilolin madadin ku na baya ba za su kasance don shigo da sabon kalmar sirri ta madadin ba. Sabuwar kalmar sirri ta ajiya za a yi amfani da ita kawai don sabbin fayilolin madadin. Shin kun tabbata cewa kuna son canza kalmar wucewa?", - "enter_backup_password": "Shigar da kalmar wucewa ta madadin nan", - "select_backup_file": "Zaɓi fayil ɗin madadin", - "import": "Shigo da", - "please_select_backup_file": "Da fatan za a zaɓi fayil ɗin madadin kuma shigar da kalmar wucewa ta madadin.", - "fixed_rate": "Kafaffen ƙima", - "fixed_rate_alert": "Za ku iya shigar da adadin karɓa lokacin da aka duba ƙayyadadden zaɓin ƙimar kuɗi. Kuna so ku canza zuwa ƙayyadadden yanayin ƙimar kuɗi?", - "xlm_extra_info": "Don Allah kar a manta da saka Memo ID yayin aika ma'amalar XLM don musayar", - "xrp_extra_info": "Don Allah kar a manta da saka alamar Ƙaddamarwa yayin aika ma'amalar XRP don musayar", - "exchange_incorrect_current_wallet_for_xmr": "Idan kana son musanya XMR daga ma'aunin Cake Wallet Monero, da fatan za a fara canza wallet ɗin Monero ɗin ku.", - "confirmed": "An tabbatar", - "unconfirmed": "Ba a tabbatar ba", - "displayable": "Ana iya nunawa", - "submit_request": "gabatar da bukata", - "buy_alert_content": "A halin yanzu muna tallafawa kawai siyan Bitcoin, Ethereum, Litecoin, da Monero. Da fatan za a ƙirƙiri ko canza zuwa Bitcoin, Ethereum, Litecoin, ko Monero walat.", - "sell_alert_content": "A halin yanzu muna tallafawa kawai siyar da Bitcoin, Ethereum da Litecoin. Da fatan za a ƙirƙiri ko canza zuwa walat ɗin ku na Bitcoin, Ethereum ko Litecoin.", - "outdated_electrum_wallet_description": "Sabbin walat ɗin Bitcoin da aka kirkira a cikin Cake yanzu suna da nau'in kalma 24. Ya zama dole ka ƙirƙiri sabon walat ɗin Bitcoin kuma canza duk kuɗin ku zuwa sabon walat ɗin kalmomi 24, kuma ku daina amfani da walat tare da iri mai kalma 12. Da fatan za a yi haka nan take don samun kuɗin ku.", - "understand": "na gane", - "apk_update": "apk sabunta", - "buy_bitcoin": "Sayi Bitcoin", - "buy_with": "Saya da", - "moonpay_alert_text": "Darajar adadin dole ne ya zama fiye ko daidai da ${minAmount} ${fiatCurrency}", - "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", - "do_not_show_me": "Kar ka sake nuna min wannan", - "unspent_coins_title": "Tsabar da ba a kashe ba", - "unspent_coins_details_title": "Bayanan tsabar kudi da ba a kashe ba", - "freeze": "Daskare", - "frozen": "Daskararre", - "coin_control": "Sarrafa tsabar kuɗi (na zaɓi)", - "address_detected": "An gano adireshin", - "address_from_domain": "Wannan adireshin ya fito daga ${domain} akan Unstoppable Domain", - "add_receiver": "Ƙara wani mai karɓa (na zaɓi)", - "manage_yats": "Sarrafa Yats", - "yat_alert_title": "Aika da karɓar crypto cikin sauƙi tare da Yat", - "yat_alert_content": "Masu amfani da Wallet ɗin Cake yanzu za su iya aikawa da karɓar duk kuɗin da suka fi so tare da sunan mai amfani na tushen emoji iri ɗaya.", - "get_your_yat": "Samun Yat ka", - "connect_an_existing_yat": "Haɗa Yat da ke akwai", - "connect_yats": "Haɗa Yats", - "yat_address": "Yat Address", - "yat": "Yat", - "address_from_yat": "Wannan adireshin daga ${emoji} ne akan Yat", - "yat_error": "Kuskure", - "yat_error_content": "Babu adireshi da ke da alaƙa da wannan Yat. Gwada wani Yat", - "choose_address": "\n\n Da fatan za a zaɓi adireshin:", - "yat_popup_title": "Adireshin jakar ku na iya zama emojifid.", - "yat_popup_content": "Yanzu zaku iya aikawa da karɓar crypto a cikin Cake Wallet tare da Yat - gajere, sunan mai amfani na tushen emoji. Sarrafa Yats a kowane lokaci akan allon saiti", - "second_intro_title": "Adireshin emoji ɗaya don sarrafa su duka", - "second_intro_content": "Your Yat adireshi ne na musamman na Emoji guda ɗaya wanda ke maye gurbin duk dogayen adiresoshin ku na hexadecimal na duk kudaden ku.", - "third_intro_title": "Yat yana wasa da kyau tare da wasu", - "third_intro_content": "Yats suna zaune a wajen Kek Wallet, kuma. Ana iya maye gurbin kowane adireshin walat a duniya da Yat!", - "learn_more": "Ƙara Koyi", - "search": "Bincika", - "search_language": "Bincika harshe", - "search_currency": "Neman kudin waje", - "new_template": "Sabon Samfura", - "electrum_address_disclaimer": "Muna samar da sababbin adireshi duk lokacin da kuka yi amfani da ɗaya, amma adiresoshin da suka gabata suna ci gaba da aiki", - "wallet_name_exists": "Wallet mai wannan sunan ya riga ya wanzu. Da fatan za a zaɓi wani suna daban ko sake suna ɗayan walat tukuna.", - "market_place": "Kasuwa", - "cake_pay_title": "Cake Pay Gift Cards", - "cake_pay_subtitle": "Sayi katunan kyauta masu rahusa (Amurka kawai)", - "cake_pay_web_cards_title": "Cake Pay Web Cards", - "cake_pay_web_cards_subtitle": "Sayi katunan da aka riga aka biya na duniya da katunan kyauta", - "about_cake_pay": "Biyan Cake yana ba ku damar sauƙin siyan katunan kyauta tare da kadarorin kama-da-wane, wanda za'a iya kashewa nan take a sama da yan kasuwa 150,000 a Amurka.", - "cake_pay_account_note": "Yi rajista tare da adireshin imel kawai don gani da siyan katunan. Wasu ma suna samuwa a rangwame!", - "already_have_account": "Kuna da asusu?", - "create_account": "Kirkira ajiya", - "privacy_policy": "takardar kebantawa", - "welcome_to_cakepay": "Barka da zuwa Cake Pay!", - "sign_up": "Shiga", - "forgot_password": "Manta Kalmar wucewa", - "reset_password": "Sake saita kalmar wucewa", - "gift_cards": "Katunan Kyauta", - "setup_your_debit_card": "Saita katin zare kudi", - "no_id_required": "Babu ID da ake buƙata. Yi da kuma ciyar a ko'ina", - "how_to_use_card": "Yadda ake amfani da wannan kati", - "purchase_gift_card": "Katin Kyautar Sayi", - "verification": "tabbatar", - "fill_code": "Da fatan za a cika lambar tabbatarwa da aka bayar zuwa imel ɗin ku", - "didnt_get_code": "Ba a samun code?", - "resend_code": "Da fatan za a sake aika shi", - "debit_card": "Katin Zare kudi", - "cakepay_prepaid_card": "Katin zare kudi na CakePay", - "no_id_needed": "Babu ID da ake buƙata!", - "frequently_asked_questions": "Tambayoyin da ake yawan yi", - "debit_card_terms": "Adana da amfani da lambar katin kuɗin ku (da takaddun shaida masu dacewa da lambar katin kuɗin ku) a cikin wannan walat ɗin dijital suna ƙarƙashin Sharuɗɗa da Sharuɗɗa na yarjejeniya mai amfani da katin tare da mai fitar da katin biyan kuɗi, kamar yadda yake aiki daga lokaci zuwa lokaci.", - "please_reference_document": "Da fatan za a nemi takaddun da ke ƙasa don ƙarin bayani.", - "cardholder_agreement": "Yarjejeniyar mai katin", - "e_sign_consent": "Izinin Alamar E-Sign", - "agree_and_continue": "Amincewa & Ci gaba", - "email_address": "Adireshin i-mel", - "agree_to": "Ta hanyar ƙirƙirar asusu kun yarda da", - "and": "kuma", - "enter_code": "Shigar da lamba", - "congratulations": "Taya murna!", - "you_now_have_debit_card": "Yanzu kana da katin zare kudi", - "min_amount": "Min: ${value}", - "max_amount": "Max: ${value}", - "enter_amount": "Shigar da Adadi", - "billing_address_info": "Idan an nemi adireshin biyan kuɗi, samar da adireshin jigilar kaya", - "order_physical_card": "Yi Oda Katin Jiki", - "add_value": "Ƙara ƙima", - "activate": "Kunna", - "get_a": "Samu a", - "digital_and_physical_card": "katin zare kudi na dijital da na zahiri", - "get_card_note": "cewa zaku iya sake lodawa tare da kudaden dijital. Babu ƙarin bayani da ake buƙata!", - "signup_for_card_accept_terms": "Yi rajista don katin kuma karɓi sharuɗɗan.", - "add_fund_to_card": "Ƙara kuɗin da aka riga aka biya a katunan (har zuwa ${value})", - "use_card_info_two": "Ana canza kuɗi zuwa dalar Amurka lokacin da ake riƙe su a cikin asusun da aka riga aka biya, ba cikin agogon dijital ba.", - "use_card_info_three": "Yi amfani da katin dijital akan layi ko tare da hanyoyin biyan kuɗi mara lamba.", - "optionally_order_card": "Zaɓin yin odar katin zahiri.", - "hide_details": "Ɓoye cikakkun bayanai", - "show_details": "Nuna Cikakkun bayanai", - "upto": "har zuwa ${value}", - "discount": "Ajiye ${value}%", - "gift_card_amount": "Adadin Katin Kyauta", - "bill_amount": "Adadin Bill", - "you_pay": "Ka Bayar", - "tip": "Tukwici:", - "custom": "al'ada", - "by_cake_pay": "da Cake Pay", - "expires": "Ya ƙare", - "mm": "MM", - "yy": "YY", - "online": "Kan layi", - "offline": "Offline", - "gift_card_number": "Lambar katin kyauta", - "pin_number": "Lambar PIN", - "total_saving": "Jimlar Adana", - "last_30_days": "Kwanaki 30 na ƙarshe", - "avg_savings": "Matsakaici Adana", - "view_all": "Duba duka", - "active_cards": "Katunan aiki", - "delete_account": "Share Account", - "cards": "Katuna", - "active": "Mai aiki", - "redeemed": "An fanshi", - "gift_card_balance_note": "Katunan kyauta tare da ragowar ma'auni zasu bayyana anan", - "gift_card_redeemed_note": "Katunan kyauta da kuka fanshi zasu bayyana anan", - "logout": "Fita", - "add_tip": "Ƙara Tukwici", - "percentageOf": "na ${amount}", - "is_percentage": "shine", - "search_category": "Nemo nau'in", - "mark_as_redeemed": "Yi Alama Kamar An Fansa", - "more_options": "Ƙarin Zaɓuɓɓuka", - "awaiting_payment_confirmation": "Ana jiran Tabbacin Biyan Kuɗi", - "transaction_sent_notice": "Idan allon bai ci gaba ba bayan minti 1, duba mai binciken toshewa da imel ɗin ku.", - "agree": "Yarda", - "in_store": "A cikin Store", - "generating_gift_card": "Samar da Katin Kyauta", - "payment_was_received": "An karɓi kuɗin ku.", - "proceed_after_one_minute": "Idan allon bai ci gaba ba bayan minti 1, duba imel ɗin ku.", - "order_id": "Oda ID", - "gift_card_is_generated": "An samar da Katin Kyauta", - "open_gift_card": "Bude Katin Kyauta", - "contact_support": "Tuntuɓi Support", - "gift_cards_unavailable": "Ana samun katunan kyauta don siye kawai tare da Monero, Bitcoin, da Litecoin a wannan lokacin", - "introducing_cake_pay": "Gabatar da Cake Pay!", - "cake_pay_learn_more": "Nan take siya ku kwaso katunan kyaututtuka a cikin app!\nTake hagu zuwa dama don ƙarin koyo.", + "authenticated": "Ingantacce", + "authentication": "Tabbatarwa", + "auto_generate_subaddresses": "Saɓaƙa subaddresses ta kai tsaye", "automatic": "Na atomatik", - "fixed_pair_not_supported": "Wannan kafaffen guda biyu ba shi da tallafi tare da zaɓaɓɓun musayar", - "variable_pair_not_supported": "Ba a samun goyan bayan wannan m biyu tare da zaɓaɓɓun musayar", - "none_of_selected_providers_can_exchange": "Babu ɗaya daga cikin zaɓaɓɓun masu samarwa da zai iya yin wannan musayar", - "choose_one": "Zaɓi ɗaya", - "choose_from_available_options": "Zaɓi daga zaɓuɓɓukan da ake da su:", - "custom_redeem_amount": "Adadin Fansa na Musamman", - "add_custom_redemption": "Ƙara Ceto na Musamman", - "remaining": "saura", - "delete_wallet": "Share walat", - "delete_wallet_confirm_message": "Shin kun tabbata cewa kuna son share jakar ${wallet_name}?", - "low_fee": "maras tsada", - "low_fee_alert": "A halin yanzu kuna amfani da ƙarancin fifikon kuɗin hanyar sadarwa. Wannan na iya haifar da dogon jira, farashi daban-daban, ko soke kasuwancin. Muna ba da shawarar saita farashi mafi girma don ƙwarewa mafi kyau.", - "ignor": "Yi watsi da shi", - "use_suggested": "Amfani da Shawarwari", - "do_not_share_warning_text": "Kada ku raba waɗannan ga kowa, gami da tallafi.\n\nZa a iya sace kuɗin ku kuma za a sace!", - "help": "taimako", - "all_transactions": "Dukan Ma'amaloli", - "all_trades": "Duk ciniki", - "connection_sync": "Haɗi da daidaitawa", - "security_and_backup": "Tsaro da madadin", - "create_backup": "Ƙirƙiri madadin", - "privacy_settings": "Saitunan sirri", - "privacy": "Keɓantawa", - "display_settings": "Nuni saituna", - "other_settings": "Sauran saituna", - "require_pin_after": "Bukatar PIN bayan", - "always": "Koyaushe", - "minutes_to_pin_code": "${minute} minti", - "disable_exchange": "Kashe musanya", - "advanced_settings": "Saitunan ci gaba", - "settings_can_be_changed_later": "Ana iya canza waɗannan saitunan daga baya a cikin saitunan app", - "add_custom_node": "Ƙara Sabon Kulli na Custom", - "disable_fiat": "Dakatar da fiat", - "fiat_api": "API ɗin Fiat", - "disabled": "tsaya", - "enabled": "An kunna", - "tor_only": "Tor kawai", - "unmatched_currencies": "Nau'in walat ɗin ku na yanzu bai dace da na lambar QR da aka bincika ba", - "contact_list_contacts": "Lambobin sadarwa", - "contact_list_wallets": "Wallets dina", - "bitcoin_payments_require_1_confirmation": "Akwatin Bitcoin na buɗe 1 sambumbu, da yake za ta samu mintuna 20 ko yawa. Ina kira ga sabuwar lafiya! Zaka sanarwa ta email lokacin da aka samu akwatin samun lambar waya.", - "send_to_this_address": "Aiko ${currency} ${tag} zuwa adireshin wannan", - "arrive_in_this_address": "${currency} ${tag} zai je wurin wannan adireshi", - "do_not_send": "Kada ka aika", - "error_dialog_content": "Ai, yanzu muka ga alamar kuskure. \n\nDa fatan, aika rahoton kuskuren da muka kira zuwa gasar tsarinmu don gaskiyar shirya.", - "cold_or_recover_wallet": "Samun kashi na baya ko samun kashi na kasa", - "please_wait": "Don Allah a rufe", - "sweeping_wallet": "Kashi na kasa", - "sweeping_wallet_alert": "Wannan ba zai samu lokacin mai tsaski. KADA KA SAMU KUNGIYARAN KUHON, ZAMAN DADIN BANKUNCI ZAI HAŘA", - "invoice_details": "Bayanin wadannan", - "donation_link_details": "Bayanin hanyar sadaka", - "anonpay_description": "Ƙirƙirar ${type}. Maƙiyantun mai nasara zai iya ${method} da duk abubuwan da ke samun lambar waya, kuma zaku samu kuɗin dama a wannan kashi.", - "create_invoice": "Sanya bayanin wadannan", - "create_donation_link": "Sanya hanyar sadaka", - "optional_email_hint": "Email na kayan taimako ga wadanda basu ba da maki", - "optional_description": "Bayanin zai iya ba da maki", - "optional_name": "Sunan mawallin zai iya ba da maki", - "clearnet_link": "Lambar makomar kwayoyi", - "onion_link": "Lambar onion", - "decimal_places_error": "Wadannan suna da tsawon harsuna", - "edit_node": "Shirya Node", - "settings": "Saiti", - "sell_monero_com_alert_content": "Selling Monero bai sami ƙarshen mai bukatar samun ba", - "error_text_input_below_minimum_limit": "Kudin ba a kamai", - "error_text_input_above_maximum_limit": "Kudin da ya kamata", - "show_market_place": "Nuna dan kasuwa", - "prevent_screenshots": "Fada lambobi da jarrabobi na kayan lambobi", - "disable_buy": "Kashe alama", - "disable_sell": "Kashe karbuwa", - "cake_2fa_preset": "Cake 2FA saiti", - "monero_dark_theme": "Monero Dark Jigo", + "available_balance": "KUDI", + "available_balance_description": "Ma'auni mai samuwa” ko ”,Tabbataccen Ma'auni”, kudade ne da za a iya kashewa nan da nan. Idan kudade sun bayyana a cikin ƙananan ma'auni amma ba babban ma'auni ba, to dole ne ku jira 'yan mintoci kaɗan don kudaden shiga don samun ƙarin tabbaci na hanyar sadarwa. Bayan sun sami ƙarin tabbaci, za a kashe su.", + "avg_savings": "Matsakaici Adana", + "awaitDAppProcessing": "Da fatan za a jira dApp ya gama aiki.", + "awaiting_payment_confirmation": "Ana jiran Tabbacin Biyan Kuɗi", + "backup": "Ajiyayyen", + "backup_file": "Ajiyayyen fayil", + "backup_password": "Ajiyayyen kalmar sirri", + "balance_page": "Ma'auni Page", + "bill_amount": "Adadin Bill", + "billing_address_info": "Idan an nemi adireshin biyan kuɗi, samar da adireshin jigilar kaya", + "biometric_auth_reason": "Duba hoton yatsa don tantancewa", "bitcoin_dark_theme": "Bitcoin Dark Jigo", "bitcoin_light_theme": "Jigon Hasken Bitcoin", - "high_contrast_theme": "Babban Jigon Kwatance", - "matrix_green_dark_theme": "Matrix Green Dark Jigo", - "monero_light_theme": "Jigon Hasken Monero", - "auto_generate_subaddresses": "Saɓaƙa subaddresses ta kai tsaye", - "narrow": "kunkuntar", - "normal": "Na al'ada", - "aggressive": "Mai tsananin kishi", - "require_for_assessing_wallet": "Bukatar samun damar walat", - "require_for_sends_to_non_contacts": "Bukatar aika zuwa waɗanda ba lambobin sadarwa ba", - "require_for_sends_to_contacts": "Bukatar aika zuwa lambobin sadarwa", - "require_for_sends_to_internal_wallets": "Bukatar aika zuwa wallet na ciki", - "require_for_exchanges_to_internal_wallets": "Bukatar musanya zuwa wallet na ciki", - "require_for_adding_contacts": "Bukatar ƙara lambobin sadarwa", - "require_for_creating_new_wallets": "Bukatar ƙirƙirar sabbin wallet", - "require_for_all_security_and_backup_settings": "Bukatar duk tsaro da saitunan wariyar ajiya", - "available_balance_description": "Ma'auni mai samuwa” ko ”,Tabbataccen Ma'auni”, kudade ne da za a iya kashewa nan da nan. Idan kudade sun bayyana a cikin ƙananan ma'auni amma ba babban ma'auni ba, to dole ne ku jira 'yan mintoci kaɗan don kudaden shiga don samun ƙarin tabbaci na hanyar sadarwa. Bayan sun sami ƙarin tabbaci, za a kashe su.", - "syncing_wallet_alert_title": "Walat ɗin ku yana aiki tare", - "syncing_wallet_alert_content": "Ma'aunin ku da lissafin ma'amala bazai cika ba har sai an ce \"SYNCHRONIZED\" a saman. Danna/matsa don ƙarin koyo.", - "home_screen_settings": "Saitunan allo na gida", - "sort_by": "Kasa", - "search_add_token": "Bincika / Ƙara alama", - "edit_token": "Gyara alamar", - "warning": "Gargadi", - "add_token_warning": "Kar a gyara ko ƙara alamu kamar yadda masu zamba suka umarta.\nKoyaushe tabbatar da adiresoshin alamar tare da sanannun tushe!", - "add_token_disclaimer_check": "Na tabbatar da adireshin kwangilar alamar da bayanin ta amfani da ingantaccen tushe. Ƙara bayanan ƙeta ko kuskure na iya haifar da asarar kuɗi.", - "token_contract_address": "Adireshin kwangilar Token", - "token_name": "Alamar sunan misali: Tether", - "token_symbol": "Alamar alama misali: USDT", - "token_decimal": "Alamar ƙima", - "field_required": "wannan fillin ana bukatansa", - "pin_at_top": "pin ${token} a sama", - "invalid_input": "Shigar da ba daidai ba", - "fiat_balance": "Fiat Balance", - "gross_balance": "Babban Ma'auni", - "alphabetical": "Harafi", - "generate_name": "Ƙirƙirar Suna", - "balance_page": "Ma'auni Page", - "share": "Raba", - "slidable": "Mai iya zamewa", - "etherscan_history": "Etherscan tarihin kowane zamani", - "template_name": "Sunan Samfura", + "bitcoin_payments_require_1_confirmation": "Akwatin Bitcoin na buɗe 1 sambumbu, da yake za ta samu mintuna 20 ko yawa. Ina kira ga sabuwar lafiya! Zaka sanarwa ta email lokacin da aka samu akwatin samun lambar waya.", + "Blocks_remaining": "${status} Katanga ya rage", + "bright_theme": "Mai haske", + "buy": "Sayi", + "buy_alert_content": "A halin yanzu muna tallafawa kawai siyan Bitcoin, Ethereum, Litecoin, da Monero. Da fatan za a ƙirƙiri ko canza zuwa Bitcoin, Ethereum, Litecoin, ko Monero walat.", + "buy_bitcoin": "Sayi Bitcoin", + "buy_provider_unavailable": "Mai ba da kyauta a halin yanzu babu.", + "buy_with": "Saya da", + "by_cake_pay": "da Cake Pay", + "cake_2fa_preset": "Cake 2FA saiti", + "cake_pay_account_note": "Yi rajista tare da adireshin imel kawai don gani da siyan katunan. Wasu ma suna samuwa a rangwame!", + "cake_pay_learn_more": "Nan take siya ku kwaso katunan kyaututtuka a cikin app!\nTake hagu zuwa dama don ƙarin koyo.", + "cake_pay_subtitle": "Sayi katunan kyauta masu rahusa (Amurka kawai)", + "cake_pay_title": "Cake Pay Gift Cards", + "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_wallet": "Cake Wallet", + "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.", + "camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.", + "cancel": "Soke", + "card_address": "Adireshin:", + "cardholder_agreement": "Yarjejeniyar mai katin", + "cards": "Katuna", + "chains": "Sarkoki", + "change": "Canja", + "change_backup_password_alert": "Fayilolin madadin ku na baya ba za su kasance don shigo da sabon kalmar sirri ta madadin ba. Sabuwar kalmar sirri ta ajiya za a yi amfani da ita kawai don sabbin fayilolin madadin. Shin kun tabbata cewa kuna son canza kalmar wucewa?", + "change_currency": "Canja Kuɗi", + "change_current_node": "Kuna tabbatar kuna so ku canja node yanzu zuwa ${node}?", + "change_current_node_title": "Canja node yanzu", + "change_exchange_provider": "Canza Mai Bayar da Musanya", + "change_language": "canja harshen", + "change_language_to": "canja harshen zuwa ${language}?", + "change_password": "Canza kalmar shiga", "change_rep": "Canza Wakili", "change_rep_message": "Shin kun tabbata kuna son canza wakilai?", - "manage_nodes": "Sarrafa nodes", - "unsupported_asset": "Ba mu goyi bayan wannan aikin don wannan kadara. Da fatan za a ƙirƙira ko canza zuwa walat na nau'in kadara mai tallafi.", - "manage_pow_nodes": "Sarrafa PoW Nodes", - "support_title_live_chat": "Tallafi na Live", - "support_description_live_chat": "Kyauta da sauri! An horar da wakilan tallafi na tallafi don taimakawa", - "support_title_guides": "Jagorar Cake", - "support_description_guides": "Tallafi da tallafi don batutuwa na yau da kullun", - "support_title_other_links": "Sauran hanyoyin tallafi", - "support_description_other_links": "Kasance tare da al'ummominmu ko kuma ka kai mu abokanmu ta hanyar wasu hanyoyi", + "change_rep_successful": "An samu nasarar canzawa wakilin", + "change_wallet_alert_content": "Kana so ka canja walat yanzu zuwa ${wallet_name}?", + "change_wallet_alert_title": "Canja walat yanzu", + "choose_account": "Zaɓi asusu", + "choose_address": "\n\n Da fatan za a zaɓi adireshin:", "choose_derivation": "Zaɓi walatawa", - "new_first_wallet_text": "A sauƙaƙe kiyaye kuzarin ku", - "select_destination": "Da fatan za a zaɓi wurin da za a yi wa madadin fayil ɗin.", - "save_to_downloads": "Ajiye zuwa Zazzagewa", - "select_buy_provider_notice": "Zaɓi mai ba da kyauta a sama. Zaka iya tsallake wannan allon ta hanyar saita mai ba da isasshen busasshen mai ba da isasshen busasshiyar saiti.", - "onramper_option_description": "Da sauri sayi Crypto tare da hanyoyin biyan kuɗi da yawa. Akwai a yawancin ƙasashe. Yaduwa da kudade sun bambanta.", + "choose_from_available_options": "Zaɓi daga zaɓuɓɓukan da ake da su:", + "choose_one": "Zaɓi ɗaya", + "choose_relay": "Da fatan za a zaɓi gudun ba da sanda don amfani", + "choose_wallet_currency": "Da fatan za a zaɓi kuɗin walat:", + "clear": "Share", + "clearnet_link": "Lambar makomar kwayoyi", + "coin_control": "Sarrafa tsabar kuɗi (na zaɓi)", + "cold_or_recover_wallet": "Samun kashi na baya ko samun kashi na kasa", + "color_theme": "Jigon launi", + "commit_transaction_amount_fee": "Aikata ciniki\nAdadi: ${amount}\nKuda: ${fee}", + "confirm": "Tabbatar", + "confirm_delete_template": "Wannan aikin zai share wannan samfuri. Kuna so ku ci gaba?", + "confirm_delete_wallet": "Wannan aikin zai share wannan walat. Kuna so ku ci gaba?", + "confirm_sending": "Tabbatar da aikawa", + "confirmations": "Tabbatar", + "confirmed": "An tabbatar", + "confirmed_tx": "Tabbatar", + "congratulations": "Taya murna!", + "connect_an_existing_yat": "Haɗa Yat da ke akwai", + "connect_yats": "Haɗa Yats", + "connection_sync": "Haɗi da daidaitawa", + "connectWalletPrompt": "Haɗa walat ɗin ku tare da WalletConnect don yin ma'amala", + "contact": "Tuntuɓar", + "contact_list_contacts": "Lambobin sadarwa", + "contact_list_wallets": "Wallets dina", + "contact_name": "Sunan Tuntuɓi", + "contact_support": "Tuntuɓi Support", + "continue_text": "Ci gaba", + "contractName": "Sunan Kwangila", + "contractSymbol": "Alamar Kwangila", + "copied_key_to_clipboard": "An kwafa ${key} a cikin kwafin", + "copied_to_clipboard": "An kwafi zuwa Clipboard", + "copy": "Kwafi", + "copy_address": "Kwafi Adireshin", + "copy_id": "Kwafi ID", + "copyWalletConnectLink": "Kwafi hanyar haɗin WalletConnect daga dApp kuma liƙa a nan", + "create_account": "Kirkira ajiya", + "create_backup": "Ƙirƙiri madadin", + "create_donation_link": "Sanya hanyar sadaka", + "create_invoice": "Sanya bayanin wadannan", + "create_new": "Ƙirƙira Sabon Kwalinku", + "create_new_account": "Ƙirƙiri sabon asusu", + "creating_new_wallet": "Haliccin walat sabuwa", + "creating_new_wallet_error": "Kuskure: ${description}", + "creation_date": "Ranar halitta", + "custom": "al'ada", + "custom_drag": "Al'ada (riƙe da ja)", + "custom_redeem_amount": "Adadin Fansa na Musamman", + "dark_theme": "Duhu", + "debit_card": "Katin Zare kudi", + "debit_card_terms": "Adana da amfani da lambar katin kuɗin ku (da takaddun shaida masu dacewa da lambar katin kuɗin ku) a cikin wannan walat ɗin dijital suna ƙarƙashin Sharuɗɗa da Sharuɗɗa na yarjejeniya mai amfani da katin tare da mai fitar da katin biyan kuɗi, kamar yadda yake aiki daga lokaci zuwa lokaci.", + "decimal_places_error": "Wadannan suna da tsawon harsuna", "default_buy_provider": "Tsohuwar Siyarwa", - "ask_each_time": "Tambaya kowane lokaci", - "buy_provider_unavailable": "Mai ba da kyauta a halin yanzu babu.", - "signTransaction": "Sa hannu Ma'amala", + "default_sell_provider": "Tsohuwar Mai Bayar Siyarwa", + "delete": "Share", + "delete_account": "Share Account", + "delete_wallet": "Share walat", + "delete_wallet_confirm_message": "Shin kun tabbata cewa kuna son share jakar ${wallet_name}?", + "deleteConnectionConfirmationPrompt": "Shin kun tabbata cewa kuna son share haɗin zuwa", + "descending": "Saukowa", + "description": "Bayani", + "destination_tag": "Tambarin makoma:", + "dfx_option_description": "Sayi crypto tare da EUR & CHF. Har zuwa € 990 ba tare da ƙarin KYC ba. Don 'yan kasuwa da abokan ciniki na kamfanoni a Turai", + "didnt_get_code": "Ba a samun code?", + "digit_pin": "-lambar PIN", + "digital_and_physical_card": "katin zare kudi na dijital da na zahiri", + "disable_buy": "Kashe alama", + "disable_exchange": "Kashe musanya", + "disable_fiat": "Dakatar da fiat", + "disable_sell": "Kashe karbuwa", + "disabled": "tsaya", + "discount": "Ajiye ${value}%", + "display_settings": "Nuni saituna", + "displayable": "Ana iya nunawa", + "do_not_have_enough_gas_asset": "Ba ku da isassun ${currency} don yin ma'amala tare da yanayin cibiyar sadarwar blockchain na yanzu. Kuna buƙatar ƙarin ${currency} don biyan kuɗaɗen cibiyar sadarwar blockchain, koda kuwa kuna aika wata kadara daban.", + "do_not_send": "Kada ka aika", + "do_not_share_warning_text": "Kada ku raba waɗannan ga kowa, gami da tallafi.\n\nZa a iya sace kuɗin ku kuma za a sace!", + "do_not_show_me": "Kar ka sake nuna min wannan", + "domain_looks_up": "Binciken yanki", + "donation_link_details": "Bayanin hanyar sadaka", + "e_sign_consent": "Izinin Alamar E-Sign", + "edit": "Gyara", + "edit_backup_password": "Shirya Kalmar wucewa ta Ajiyayyen", + "edit_node": "Shirya Node", + "edit_token": "Gyara alamar", + "electrum_address_disclaimer": "Muna samar da sababbin adireshi duk lokacin da kuka yi amfani da ɗaya, amma adiresoshin da suka gabata suna ci gaba da aiki", + "email_address": "Adireshin i-mel", + "enabled": "An kunna", + "enter_amount": "Shigar da Adadi", + "enter_backup_password": "Shigar da kalmar wucewa ta madadin nan", + "enter_code": "Shigar da lamba", + "enter_seed_phrase": "Shigar da Sert Sentarku", + "enter_your_note": "Shigar da bayanin kula…", + "enter_your_pin": "Shigar da PIN", + "enter_your_pin_again": "Shigar da PIN ɗinku na sake", + "enterTokenID": "Shigar da alamar alama", + "enterWalletConnectURI": "Shigar da WalletConnect URI", + "error": "Kuskure", + "error_dialog_content": "Ai, yanzu muka ga alamar kuskure. \n\nDa fatan, aika rahoton kuskuren da muka kira zuwa gasar tsarinmu don gaskiyar shirya.", + "error_text_account_name": "Sunan ajiya zai iya ɗauka ne kawai da haruffa, lambobi\nkuma ya zama tsakanin 1 zuwa 15 haruffa", + "error_text_address": "Adireshin hujja ya kamata ya dace da irin\nna cryptocurrency", + "error_text_amount": "Adadin biya zai iya ƙunsar lambobi kawai", + "error_text_contact_name": "Sunan kira ba zai iya ɗaukar ` , ' \" haruffa\nkuma ya zama tsakanin 1 zuwa 32 haruffa", + "error_text_crypto_currency": "Adadin haruffan gaba\n zai kamata ya zama ko ƙasa daga na 12", + "error_text_fiat": "Adadin kudin ba zai iya wuce available balance.\nAdadin haruffan gaba zai kamata ya zama ko ƙasa daga na 2", + "error_text_input_above_maximum_limit": "Kudin da ya kamata", + "error_text_input_below_minimum_limit": "Kudin ba a kamai", + "error_text_keys": "Ƙunci na hujja kawai zai iya ɗaukar 64 haruffa a cikin hex", + "error_text_limits_loading_failed": "Kasuwanci ga ${provider} ba a yi ba. An kasa saukewa masanan", + "error_text_maximum_limit": "Kasuwanci ga ${provider} ba a yi ba. Adadin shine fiye da ƙimanin: ${max} ${currency}", + "error_text_minimal_limit": "Kasuwanci ga ${provider} ba a yi ba. Adadin shine ƙasa fiye da ƙananan: ${min} ${currency}", + "error_text_node_address": "Da fatan a shigar da iPv4 adireshin", + "error_text_node_port": "Node tashar jiragen ruwa zai iya ƙunsar lambobi tsakanin 0 zuwa 65535 kawai", + "error_text_node_proxy_address": "Da fatan za a shigar da :, misali 127.0.0.1:9050", + "error_text_payment_id": "ID na biyan kudi kawai zai iya ɗaukar daga 16 zuwa 64 haruffa a cikin hex", + "error_text_subaddress_name": "Sunan subaddress ba zai iya ɗaukar `, ', \" haruffa\nkuma ya zama tsakanin 1 zuwa 20 haruffa", + "error_text_template": "Sunan na tushe da adireshin ba zai iya ɗaukar ` , ' \" haruffa\nkuma ya zama tsakanin 1 zuwa 106 haruffa", + "error_text_wallet_name": "Sunan hujja kawai zai iya ɗauka ne haruffa, lambobi, _ - haruffa\nkuma ya zama tsakanin 1 zuwa 33 haruffa", + "error_text_xmr": "XMR adadin ba zai iya wuce available balance.\nAdadin haruffan gaba zai kamata ya zama ko ƙasa daga na 12", "errorGettingCredentials": "Ba a yi nasara ba: Kuskure yayin samun takaddun shaida", "errorSigningTransaction": "An sami kuskure yayin sanya hannu kan ciniki", - "pairingInvalidEvent": "Haɗa Lamarin mara inganci", - "chains": "Sarkoki", - "methods": "Hanyoyin", - "events": "Abubuwan da suka faru", - "reject": "Ƙi", - "approve": "Amincewa", - "expiresOn": "Yana ƙarewa", - "walletConnect": "WalletConnect", - "nullURIError": "URI banza ne", - "connectWalletPrompt": "Haɗa walat ɗin ku tare da WalletConnect don yin ma'amala", - "newConnection": "Sabuwar Haɗi", - "activeConnectionsPrompt": "Haɗin kai mai aiki zai bayyana a nan", - "deleteConnectionConfirmationPrompt": "Shin kun tabbata cewa kuna son share haɗin zuwa", + "estimated": "Kiyasta", + "etherscan_history": "Etherscan tarihin kowane zamani", "event": "Lamarin", - "successful": "Nasara", - "wouoldLikeToConnect": "ina son haɗi", - "message": "Sako", - "do_not_have_enough_gas_asset": "Ba ku da isassun ${currency} don yin ma'amala tare da yanayin cibiyar sadarwar blockchain na yanzu. Kuna buƙatar ƙarin ${currency} don biyan kuɗaɗen cibiyar sadarwar blockchain, koda kuwa kuna aika wata kadara daban.", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Da fatan za a jira dApp ya gama aiki.", - "copyWalletConnectLink": "Kwafi hanyar haɗin WalletConnect daga dApp kuma liƙa a nan", - "enterWalletConnectURI": "Shigar da WalletConnect URI", - "seed_key": "Maɓallin iri", - "enter_seed_phrase": "Shigar da Sert Sentarku", - "change_rep_successful": "An samu nasarar canzawa wakilin", - "add_contact": "Ƙara lamba", + "events": "Abubuwan da suka faru", + "exchange": "Exchange", + "exchange_incorrect_current_wallet_for_xmr": "Idan kana son musanya XMR daga ma'aunin Cake Wallet Monero, da fatan za a fara canza wallet ɗin Monero ɗin ku.", + "exchange_new_template": "Sabon template", "exchange_provider_unsupported": "${providerName}", - "domain_looks_up": "Binciken yanki", - "require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje", - "camera_permission_is_required": "Ana buƙatar izinin kyamara.\nDa fatan za a kunna shi daga saitunan app.", - "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa", - "order_by": "Oda ta", - "creation_date": "Ranar halitta", + "exchange_result_confirm": "Ta danna tabbatarwa, zaku aika ${fetchingLabel} ${from} daga walat ɗin ku mai suna ${walletName} zuwa address dake kasa. Ko zaka iya aika daga kwalinku na external zuwa address/QR code dake kasa.\n\nDon Allah shigar da confirm don ci gaba ko dawo ka canja adadinku.", + "exchange_result_description": "Dole ne ku aika mafi ƙarancin ${fetchingLabel} ${from} zuwa adireshin da aka nuna akan shafi na gaba. Idan ka aika adadi kasa da ${fetchingLabel} ${from} bazai yi converting ba kuma ba zai koma ba.", + "exchange_result_write_down_ID": "*Don Allah kwafi ko rubuta ID dake nuna sama.", + "exchange_result_write_down_trade_id": "Da fatan za a kwafa ko rubuta ID ɗin ciniki don ci gaba.", + "exchange_sync_alert_content": "Da fatan za a jira har sai an daidaita walat ɗin ku", + "expired": "Karewa", + "expires": "Ya ƙare", + "expiresOn": "Yana ƙarewa", + "export_backup": "Ajiyayyen fitarwa", + "extra_id": "Karin ID:", + "failed_authentication": "Binne wajen shiga. ${state_error}", + "faq": "FAQ", + "fetching": "Daukewa", + "fiat_api": "API ɗin Fiat", + "fiat_balance": "Fiat Balance", + "field_required": "wannan fillin ana bukatansa", + "fill_code": "Da fatan za a cika lambar tabbatarwa da aka bayar zuwa imel ɗin ku", + "filter_by": "Tace ta", + "first_wallet_text": "Aikace-aikacen e-wallet ga Monero, Bitcoin, Ethereum, Litecoin, da kuma Haven", + "fixed_pair_not_supported": "Wannan kafaffen guda biyu ba shi da tallafi tare da zaɓaɓɓun musayar", + "fixed_rate": "Kafaffen ƙima", + "fixed_rate_alert": "Za ku iya shigar da adadin karɓa lokacin da aka duba ƙayyadadden zaɓin ƙimar kuɗi. Kuna so ku canza zuwa ƙayyadadden yanayin ƙimar kuɗi?", + "forgot_password": "Manta Kalmar wucewa", + "freeze": "Daskare", + "frequently_asked_questions": "Tambayoyin da ake yawan yi", + "frozen": "Daskararre", + "full_balance": "DUKAN KUDI", + "generate_name": "Ƙirƙirar Suna", + "generating_gift_card": "Samar da Katin Kyauta", + "get_a": "Samu a", + "get_card_note": "cewa zaku iya sake lodawa tare da kudaden dijital. Babu ƙarin bayani da ake buƙata!", + "get_your_yat": "Samun Yat ka", + "gift_card_amount": "Adadin Katin Kyauta", + "gift_card_balance_note": "Katunan kyauta tare da ragowar ma'auni zasu bayyana anan", + "gift_card_is_generated": "An samar da Katin Kyauta", + "gift_card_number": "Lambar katin kyauta", + "gift_card_redeemed_note": "Katunan kyauta da kuka fanshi zasu bayyana anan", + "gift_cards": "Katunan Kyauta", + "gift_cards_unavailable": "Ana samun katunan kyauta don siye kawai tare da Monero, Bitcoin, da Litecoin a wannan lokacin", + "got_it": "Gama", + "gross_balance": "Babban Ma'auni", "group_by_type": "Rukuni ta nau'in", - "importNFTs": "Shigo da NFTs", - "noNFTYet": "Babu NFTs tukuna", - "address": "Adireshi", - "enterTokenID": "Shigar da alamar alama", - "tokenID": "ID", - "name": "Suna", - "symbol": "Alama", - "seed_phrase_length": "Tsawon jimlar iri", - "unavailable_balance": "Ma'aunin da ba ya samuwa", - "unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.", - "unspent_change": "Canza", - "tor_connection": "Tor haɗin gwiwa", - "setup_2fa_text": "Cake 2FA yana aiki ta amfani da TOTP azaman ƙimar tabbatarwa ta biyu.\n\nCake 2FA's TOTP yana buƙatar tallafin lambobi SHA-512 da 8; wannan yana ba da ƙarin tsaro. Ana iya samun ƙarin bayani da ƙa'idodi masu goyan baya a cikin jagorar.", - "setup_warning_2fa_text": "Kuna buƙatar dawo da walat ɗin ku daga zuriyar mnemonic.\n\nTallafin kek ba zai iya taimaka muku ba idan kun rasa damar yin amfani da 2FA ko tsaba na mnemonic.\nCake 2FA tabbaci ne na biyu don wasu ayyuka a cikin walat. Kafin amfani da Cake 2FA, muna ba da shawarar karanta ta cikin jagorar.BA shi da tsaro kamar ajiyar sanyi.\n\nIdan ka rasa damar yin amfani da app ɗinka na 2FA ko maɓallan TOTP, ZA KA rasa damar shiga wannan wallet ɗin. ", - "add_secret_code": "Ko, ƙara wannan lambar sirrin zuwa ƙa'idar mai tabbatarwa", - "scan_qr_on_device": "Duba wannan lambar QR akan wata na'ura", + "haven_app": "Haven da Cake Wallet", + "haven_app_wallet_text": "Aikace-aikacen e-wallet ga Haven", + "help": "taimako", + "hidden_balance": "BOYE KUDI", + "hide_details": "Ɓoye cikakkun bayanai", + "high_contrast_theme": "Babban Jigon Kwatance", + "home_screen_settings": "Saitunan allo na gida", "how_to_use": "Yadda ake amfani da shi", + "how_to_use_card": "Yadda ake amfani da wannan kati", + "id": "ID:", + "ignor": "Yi watsi da shi", + "import": "Shigo da", + "importNFTs": "Shigo da NFTs", + "in_store": "A cikin Store", + "incoming": "Mai shigowa", + "incorrect_seed": "rubutun da aka shigar ba shi da inganci.", + "introducing_cake_pay": "Gabatar da Cake Pay!", + "invalid_input": "Shigar da ba daidai ba", + "invoice_details": "Bayanin wadannan", + "is_percentage": "shine", + "last_30_days": "Kwanaki 30 na ƙarshe", + "learn_more": "Ƙara Koyi", + "light_theme": "Haske", + "loading_your_wallet": "Ana loda walat ɗin ku", + "login": "Shiga", + "logout": "Fita", + "low_fee": "maras tsada", + "low_fee_alert": "A halin yanzu kuna amfani da ƙarancin fifikon kuɗin hanyar sadarwa. Wannan na iya haifar da dogon jira, farashi daban-daban, ko soke kasuwancin. Muna ba da shawarar saita farashi mafi girma don ƙwarewa mafi kyau.", + "manage_nodes": "Sarrafa nodes", + "manage_pow_nodes": "Sarrafa PoW Nodes", + "manage_yats": "Sarrafa Yats", + "mark_as_redeemed": "Yi Alama Kamar An Fansa", + "market_place": "Kasuwa", + "matrix_green_dark_theme": "Matrix Green Dark Jigo", + "max_amount": "Max: ${value}", + "max_value": "Max: ${value} ${currency}", + "memo": "Memo:", + "message": "Sako", + "methods": "Hanyoyin", + "min_amount": "Min: ${value}", + "min_value": "Min: ${value} ${currency}", + "minutes_to_pin_code": "${minute} minti", + "mm": "MM", + "monero_com": "Monero.com ta Cake Wallet", + "monero_com_wallet_text": "Aikace-aikacen e-wallet ga Monero", + "monero_dark_theme": "Monero Dark Jigo", + "monero_light_theme": "Jigon Hasken Monero", + "moonpay_alert_text": "Darajar adadin dole ne ya zama fiye ko daidai da ${minAmount} ${fiatCurrency}", + "more_options": "Ƙarin Zaɓuɓɓuka", + "name": "Suna", + "narrow": "kunkuntar", + "new_first_wallet_text": "A sauƙaƙe kiyaye kuzarin ku", + "new_node_testing": "Sabbin gwajin kumburi", + "new_subaddress_create": "Ƙirƙiri", + "new_subaddress_label_name": "Lakabin suna", + "new_subaddress_title": "Adireshin sabuwa", + "new_template": "Sabon Samfura", + "new_wallet": "Sabuwar Wallet", + "newConnection": "Sabuwar Haɗi", + "no_id_needed": "Babu ID da ake buƙata!", + "no_id_required": "Babu ID da ake buƙata. Yi da kuma ciyar a ko'ina", + "no_relay_on_domain": "Babu gudun ba da sanda ga yankin mai amfani ko kuma ba a samu ba. Da fatan za a zaɓi gudun ba da sanda don amfani.", + "no_relays": "Babu relays", + "no_relays_message": "Mun sami rikodin Nostr NIP-05 don wannan mai amfani, amma ba ya ƙunshe da kowane relays. Da fatan za a umurci mai karɓa ya ƙara relays zuwa rikodin su na Nostr.", + "node_address": "Address Node", + "node_connection_failed": "Haɗin ya gaza", + "node_connection_successful": "Haɗin ya yi nasara", + "node_new": "Sabon Node", + "node_port": "Node tashar jiragen ruwa", + "node_reset_settings_title": "Sake saitunan", + "node_test": "Gwaji", + "nodes": "Nodes", + "nodes_list_reset_to_default_message": "Kuna tabbatar kuna so ku sake saitunan zuwa default?", + "none_of_selected_providers_can_exchange": "Babu ɗaya daga cikin zaɓaɓɓun masu samarwa da zai iya yin wannan musayar", + "noNFTYet": "Babu NFTs tukuna", + "normal": "Na al'ada", + "note_optional": "Bayani (optional)", + "note_tap_to_change": "Bayani (tap don canja)", + "nullURIError": "URI banza ne", + "offer_expires_in": "tayin zai ƙare a:", + "offline": "Offline", + "ok": "OK", + "onion_link": "Lambar onion", + "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", + "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", + "optional_email_hint": "Email na kayan taimako ga wadanda basu ba da maki", + "optional_name": "Sunan mawallin zai iya ba da maki", + "optionally_order_card": "Zaɓin yin odar katin zahiri.", + "order_by": "Oda ta", + "order_id": "Oda ID", + "order_physical_card": "Yi Oda Katin Jiki", + "other_settings": "Sauran saituna", + "outdated_electrum_wallet_description": "Sabbin walat ɗin Bitcoin da aka kirkira a cikin Cake yanzu suna da nau'in kalma 24. Ya zama dole ka ƙirƙiri sabon walat ɗin Bitcoin kuma canza duk kuɗin ku zuwa sabon walat ɗin kalmomi 24, kuma ku daina amfani da walat tare da iri mai kalma 12. Da fatan za a yi haka nan take don samun kuɗin ku.", + "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", + "overwrite_amount": "Rubuta adadin", + "pairingInvalidEvent": "Haɗa Lamarin mara inganci", + "password": "Kalmar wucewa", + "paste": "Manna", + "pause_wallet_creation": "A halin yanzu an dakatar da ikon ƙirƙirar Haven Wallet.", + "payment_id": "ID na biyan kuɗi:", + "payment_was_received": "An karɓi kuɗin ku.", + "pending": "(pending)", + "percentageOf": "na ${amount}", + "pin_at_top": "pin ${token} a sama", + "pin_is_incorrect": "PIN ba daidai ba ne", + "pin_number": "Lambar PIN", + "placeholder_contacts": "Za a nuna lambobin sadarwar ku anan", + "placeholder_transactions": "Za a nuna ma'amalolin ku anan", + "please_make_selection": "Don Allah zaɓi ƙasa don ƙirƙira ko dawo da kwalinku.", + "please_reference_document": "Da fatan za a nemi takaddun da ke ƙasa don ƙarin bayani.", + "please_select": "Don Allah zaɓi:", + "please_select_backup_file": "Da fatan za a zaɓi fayil ɗin madadin kuma shigar da kalmar wucewa ta madadin.", + "please_try_to_connect_to_another_node": "Don Allah yi ƙoƙarin haɗa da wani node", + "please_wait": "Don Allah a rufe", + "polygonscan_history": "PolygonScan tarihin kowane zamani", + "powered_by": "An ƙarfafa shi ta ${title}", + "pre_seed_button_text": "Ina fahimta. Nuna mini seed din nawa", + "pre_seed_description": "A kan shafin nan za ku ga wata ƙungiya na ${words} kalmomi. Wannan shine tsarin daban-daban ku kuma na sirri kuma shine hanya ɗaya kadai don mai da purse dinku a cikin yanayin rasa ko rashin aiki. Yana da damar da kuke a cikin tabbatar da kuyi rubuta shi kuma kuyi ajiye shi a wuri na aminci wanda ya wuce wurin app na Cake Wallet.", + "pre_seed_title": "MUHIMMANCI", + "prevent_screenshots": "Fada lambobi da jarrabobi na kayan lambobi", + "privacy": "Keɓantawa", + "privacy_policy": "takardar kebantawa", + "privacy_settings": "Saitunan sirri", + "private_key": "Keɓaɓɓen maɓalli", + "proceed_after_one_minute": "Idan allon bai ci gaba ba bayan minti 1, duba imel ɗin ku.", + "provider_error": "${provider} kuskure", + "public_key": "Maɓallin jama'a", + "purchase_gift_card": "Katin Kyautar Sayi", + "qr_fullscreen": "Matsa don buɗe lambar QR na cikakken allo", + "qr_payment_amount": "Wannan QR code yana da adadin kuɗi. Kuna so ku overwrite wannan adadi?", + "receivable_balance": "Daidaituwa da daidaituwa", + "receive": "Samu", + "receive_amount": "Adadi", + "received": "Samu", + "recipient_address": "Adireshin mai karɓa", + "reconnect": "Sake haɗawa", + "reconnect_alert_text": "Shin kun tabbata kuna son sake haɗawa?", + "reconnection": "Sake haɗawa", + "redeemed": "An fanshi", + "refund_address": "Adireshin maidowa", + "reject": "Ƙi", + "remaining": "saura", + "remove": "Cire", + "remove_node": "Cire node", + "remove_node_message": "Kuna tabbatar kuna so ku cire wannan node?", + "rename": "Sake suna", + "require_for_adding_contacts": "Bukatar ƙara lambobin sadarwa", + "require_for_all_security_and_backup_settings": "Bukatar duk tsaro da saitunan wariyar ajiya", + "require_for_assessing_wallet": "Bukatar samun damar walat", + "require_for_creating_new_wallets": "Bukatar ƙirƙirar sabbin wallet", + "require_for_exchanges_to_external_wallets": "Bukatar musanya zuwa wallet na waje", + "require_for_exchanges_to_internal_wallets": "Bukatar musanya zuwa wallet na ciki", + "require_for_sends_to_contacts": "Bukatar aika zuwa lambobin sadarwa", + "require_for_sends_to_internal_wallets": "Bukatar aika zuwa wallet na ciki", + "require_for_sends_to_non_contacts": "Bukatar aika zuwa waɗanda ba lambobin sadarwa ba", + "require_pin_after": "Bukatar PIN bayan", + "rescan": "Rescan", + "resend_code": "Da fatan za a sake aika shi", + "reset": "Sake saiti", + "reset_password": "Sake saita kalmar wucewa", + "restore_active_seed": "iri mai aiki", + "restore_address": "Address", + "restore_bitcoin_description_from_keys": "Dawo da kwalinku daga WIF string dake generate daga maɓallan sirri", + "restore_bitcoin_description_from_seed": "Dawo da kwalinku daga 24 lambar haɗin kalma", + "restore_bitcoin_title_from_keys": "Dawo daga WIF", + "restore_description_from_backup": "Kuna iya dawo da duk aikace-aikacen Wallet ɗin Cake daga fayil ɗin ajiyar ku", + "restore_description_from_keys": "Maido da walat ɗin ku daga maɓallan maɓalli da aka ƙera da aka ajiye daga maɓallan ku na sirri", + "restore_description_from_seed": "Dawo da kwalinku daga 25 ko 13 lambar haɗin kalma", + "restore_description_from_seed_keys": "Maido da walat ɗin ku daga iri/maɓallan da kuka adana don amintaccen wuri", + "restore_from_date_or_blockheight": "Don Allah shigar da wata kwanan a kafin ku ƙirƙirar wannan kwalinku. Ko idan kun san blockheight, don Allah shigar da shi", + "restore_from_seed_placeholder": "Da fatan za a shigar da ko manna maɓallin ku a nan", + "restore_new_seed": "Sabon iri", + "restore_next": "Na gaba", + "restore_recover": "Maida", + "restore_restore_wallet": "Maida Wallet", + "restore_seed_keys_restore": "Mayar da iri/Maɓallai", + "restore_spend_key_private": "Maɓallin kashewa (key kalmar sirri)", + "restore_title_from_backup": "Dawo daga madadin", + "restore_title_from_keys": "Dawo daga maɓallai", + "restore_title_from_seed": "Maidowa daga iri", + "restore_title_from_seed_keys": "Dawo da iri/maɓallai", + "restore_view_key_private": "Maɓallin Duba (key kalmar sirri)", + "restore_wallet": "Dawo da Kwalinku", + "restore_wallet_name": "Sunan kwalinku", + "restore_wallet_restore_description": "Bayanin dawo da walat", + "router_no_route": "Babu wata hanya da aka bayyana don ${name}", + "save": "Ajiye", + "save_backup_password": "Da fatan za a tabbatar cewa kun adana kalmar sirrin ajiyar ku. Ba za ku iya shigo da fayilolin ajiyar ku ba tare da shi ba.", + "save_backup_password_alert": "Ajiye kalmar sirri ta ajiya", + "save_to_downloads": "Ajiye zuwa Zazzagewa", + "saved_the_trade_id": "Na ajiye ID na ciniki", + "scan_qr_code": "Gani QR kodin", + "scan_qr_on_device": "Duba wannan lambar QR akan wata na'ura", + "search": "Bincika", + "search_add_token": "Bincika / Ƙara alama", + "search_category": "Nemo nau'in", + "search_currency": "Neman kudin waje", + "search_language": "Bincika harshe", + "second_intro_content": "Your Yat adireshi ne na musamman na Emoji guda ɗaya wanda ke maye gurbin duk dogayen adiresoshin ku na hexadecimal na duk kudaden ku.", + "second_intro_title": "Adireshin emoji ɗaya don sarrafa su duka", + "security_and_backup": "Tsaro da madadin", + "seed_alert_back": "juya baya", + "seed_alert_content": "Irin ita ce kawai hanya don dawo da walat ɗin ku. Kun rubuta shi?", + "seed_alert_title": "Hankali", + "seed_alert_yes": "E, Na yi", + "seed_choose": "Zaɓi harshen seed", "seed_hex_form": "Gany Sero (form form)", + "seed_key": "Maɓallin iri", + "seed_language": "Harshen Magani", + "seed_language_chinese": "Sinanci", + "seed_language_chinese_traditional": "Sinanci (na gargajiya)", + "seed_language_czech": "Czech", + "seed_language_dutch": "Dutch", + "seed_language_english": "Ingilishi", + "seed_language_french": "Faransanci", + "seed_language_german": "Jamus", + "seed_language_italian": "Italiyanci", + "seed_language_japanese": "Jafananci", + "seed_language_korean": "Yaren Koriya", + "seed_language_next": "Na gaba", + "seed_language_portuguese": "Fotigal", + "seed_language_russian": "Rashanci", + "seed_language_spanish": "Spanish", + "seed_phrase_length": "Tsawon jimlar iri", + "seed_reminder": "Don Allah rubuta wadannan in case ka manta ko ka sake kwallon wayarka", + "seed_share": "Raba iri", + "seed_title": "iri", "seedtype": "Seedtype", "seedtype_legacy": "Legacy (25 kalmomi)", "seedtype_polyseed": "Polyseed (16 kalmomi)", - "seed_language_czech": "Czech", - "seed_language_korean": "Yaren Koriya", - "seed_language_chinese_traditional": "Sinanci (na gargajiya)", - "ascending": "Hau", - "descending": "Saukowa", - "dfx_option_description": "Sayi crypto tare da EUR & CHF. Har zuwa € 990 ba tare da ƙarin KYC ba. Don 'yan kasuwa da abokan ciniki na kamfanoni a Turai", - "polygonscan_history": "PolygonScan tarihin kowane zamani", - "wallet_seed_legacy": "Tallarin walat walat", - "setup_totp_recommended": "Saita TOTP", - "default_sell_provider": "Tsohuwar Mai Bayar Siyarwa", + "select_backup_file": "Zaɓi fayil ɗin madadin", + "select_buy_provider_notice": "Zaɓi mai ba da kyauta a sama. Zaka iya tsallake wannan allon ta hanyar saita mai ba da isasshen busasshen mai ba da isasshen busasshiyar saiti.", + "select_destination": "Da fatan za a zaɓi wurin da za a yi wa madadin fayil ɗin.", "select_sell_provider_notice": "Zaɓi mai bada siyarwa a sama. Kuna iya tsallake wannan allon ta saita mai bada siyar da ku a cikin saitunan app.", - "custom_drag": "Al'ada (riƙe da ja)", + "sell": "sayar", + "sell_alert_content": "A halin yanzu muna tallafawa kawai siyar da Bitcoin, Ethereum da Litecoin. Da fatan za a ƙirƙiri ko canza zuwa walat ɗin ku na Bitcoin, Ethereum ko Litecoin.", + "sell_monero_com_alert_content": "Selling Monero bai sami ƙarshen mai bukatar samun ba", + "send": "Aika", + "send_address": "${cryptoCurrency} address", + "send_amount": "Adadi:", + "send_creating_transaction": "Ƙirƙirar ciniki", + "send_error_currency": "Kudi zai iya ƙunsar lambobi kawai", + "send_error_minimum_value": "Mafi ƙarancin ƙimar adadin shine 0.01", + "send_estimated_fee": "Ƙimar kuɗi:", + "send_fee": "Kudin:", + "send_name": "Sunan", + "send_new": "Sabon", + "send_payment_id": "ID na biyan kuɗi (optional)", + "send_priority": "Yanzu haka fee yana set a ${transactionPriority} fifiko.\nAna iya daidaita fifikon ciniki a cikin saitunan", + "send_sending": "Aika...", + "send_success": "${crypto} kwalinku ya aika da nasara", + "send_templates": "Samfura", + "send_title": "Aika", + "send_to_this_address": "Aiko ${currency} ${tag} zuwa adireshin wannan", + "send_xmr": "Aika XMR", + "send_your_wallet": "Walat ɗin ku", + "sending": "Aika", + "sent": "Aika", + "settings": "Saiti", + "settings_all": "DUK", + "settings_allow_biometrical_authentication": "Bada izinin tantance sawun yatsa", + "settings_can_be_changed_later": "Ana iya canza waɗannan saitunan daga baya a cikin saitunan app", + "settings_change_language": "Canja yaren", + "settings_change_pin": "Canja PIN", + "settings_currency": "Kudi", + "settings_current_node": "Node yanzu", + "settings_dark_mode": "Launi mai duhu", + "settings_display_balance": "Nuna ma'auni", + "settings_display_on_dashboard_list": "Nuna a kan tebur na bayanan", + "settings_fee_priority": "fifikon kuɗi", + "settings_nodes": "Nodes", + "settings_none": "Babu", + "settings_only_trades": "Kawai kasuwancin", + "settings_only_transactions": "Kawai ayyuka", + "settings_personal": "Na sirri", + "settings_save_recipient_address": "Ajiye adireshin mai karɓa", + "settings_support": "Taimako", + "settings_terms_and_conditions": "Sharuɗɗa da Ka'idoji", + "settings_title": "Saitunan", + "settings_trades": "Cinikai", + "settings_transactions": "Ma'amaloli", + "settings_wallets": "Wallets", + "setup_2fa_text": "Cake 2FA yana aiki ta amfani da TOTP azaman ƙimar tabbatarwa ta biyu.\n\nCake 2FA's TOTP yana buƙatar tallafin lambobi SHA-512 da 8; wannan yana ba da ƙarin tsaro. Ana iya samun ƙarin bayani da ƙa'idodi masu goyan baya a cikin jagorar.", + "setup_pin": "Saita PIN", + "setup_successful": "An saita PIN ɗinku da nasara!", + "setup_totp_recommended": "Saita TOTP", + "setup_warning_2fa_text": "Kuna buƙatar dawo da walat ɗin ku daga zuriyar mnemonic.\n\nTallafin kek ba zai iya taimaka muku ba idan kun rasa damar yin amfani da 2FA ko tsaba na mnemonic.\nCake 2FA tabbaci ne na biyu don wasu ayyuka a cikin walat. Kafin amfani da Cake 2FA, muna ba da shawarar karanta ta cikin jagorar.BA shi da tsaro kamar ajiyar sanyi.\n\nIdan ka rasa damar yin amfani da app ɗinka na 2FA ko maɓallan TOTP, ZA KA rasa damar shiga wannan wallet ɗin. ", + "setup_your_debit_card": "Saita katin zare kudi", + "share": "Raba", + "share_address": "Raba adireshin", + "show_details": "Nuna Cikakkun bayanai", + "show_keys": "Nuna iri/maɓallai", + "show_market_place": "Nuna dan kasuwa", + "show_seed": "Nuna iri", + "sign_up": "Shiga", + "signTransaction": "Sa hannu Ma'amala", + "signup_for_card_accept_terms": "Yi rajista don katin kuma karɓi sharuɗɗan.", + "slidable": "Mai iya zamewa", + "sort_by": "Kasa", + "spend_key_private": "makullin biya (maɓallin kalmar sirri)", + "spend_key_public": "makullin biya (maɓallin jama'a)", + "status": "Matsayi:", + "subaddress_title": "Jagorar subaddress", + "subaddresses": "Subaddresses", + "submit_request": "gabatar da bukata", + "successful": "Nasara", + "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_live_chat": "Tallafi na Live", + "support_title_other_links": "Sauran hanyoyin tallafi", + "sweeping_wallet": "Kashi na kasa", + "sweeping_wallet_alert": "Wannan ba zai samu lokacin mai tsaski. KADA KA SAMU KUNGIYARAN KUHON, ZAMAN DADIN BANKUNCI ZAI HAŘA", + "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa", "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)", - "receivable_balance": "Daidaituwa da daidaituwa", - "confirmed_tx": "Tabbatar", + "symbol": "Alama", + "sync_status_attempting_sync": "KWAFI", + "sync_status_connected": "HANNU", + "sync_status_connecting": "HADA", + "sync_status_failed_connect": "BABU INTERNET", + "sync_status_not_connected": "BABU INTERNET", + "sync_status_starting_sync": "KWAFI", + "sync_status_syncronized": "KYAU", + "sync_status_syncronizing": "KWAFI", + "syncing_wallet_alert_content": "Ma'aunin ku da lissafin ma'amala bazai cika ba har sai an ce \"SYNCHRONIZED\" a saman. Danna/matsa don ƙarin koyo.", + "syncing_wallet_alert_title": "Walat ɗin ku yana aiki tare", + "template": "Samfura", + "template_name": "Sunan Samfura", + "third_intro_content": "Yats suna zaune a wajen Kek Wallet, kuma. Ana iya maye gurbin kowane adireshin walat a duniya da Yat!", + "third_intro_title": "Yat yana wasa da kyau tare da wasu", + "time": "${minutes}m ${seconds}s", + "tip": "Tukwici:", + "today": "Yau", + "token_contract_address": "Adireshin kwangilar Token", + "token_decimal": "Alamar ƙima", + "token_name": "Alamar sunan misali: Tether", + "token_symbol": "Alamar alama misali: USDT", + "tokenID": "ID", + "tor_connection": "Tor haɗin gwiwa", + "tor_only": "Tor kawai", + "total_saving": "Jimlar Adana", + "totp_auth_url": "TOTP AUTH URL", + "trade_details_copied": "${title} an kwafa zuwa cikin kwafin", + "trade_details_created_at": "An ƙirƙira a", + "trade_details_fetching": "Daukewa", + "trade_details_id": "ID", + "trade_details_pair": "miji da matarsa", + "trade_details_provider": "Mai bayarwa", + "trade_details_state": "Matsayi", + "trade_details_title": "Bayanai game da kasuwancin", + "trade_for_not_created": "Ba a ƙirƙira ciniki don ${title} ba.", + "trade_history_title": "Tarihin kasuwancin", + "trade_id": "ID na kasuwanci:", + "trade_id_not_found": "Ba a samo cinikin ${tradeId} na ${title} ba.", + "trade_is_powered_by": "Ana yin wannan ciniki ta hanyar ${provider}", + "trade_not_created": "Ba a ƙirƙira ciniki ba", + "trade_not_found": "Ba a sami ciniki ba.", + "trade_state_btc_sent": "Btc an aika", + "trade_state_complete": "Cikakkun", + "trade_state_confirming": "Tabbatar", + "trade_state_created": "an halicci", + "trade_state_finished": "an kammala", + "trade_state_paid": "an biya", + "trade_state_paid_unconfirmed": "an biya amma ba a tabbatar ba", + "trade_state_pending": "Jira", + "trade_state_timeout": "lokacin da ya ƙare", + "trade_state_to_be_created": "za a halicci", + "trade_state_traded": "Ciniki", + "trade_state_trading": "Ciniki", + "trade_state_underpaid": "ba a biya gaba ɗaya ba", + "trade_state_unpaid": "ba a biya ba", + "trades": "Cinikai", + "transaction_details_amount": "Adadin", + "transaction_details_copied": "${title} an kwafa zuwa cikin kwafin", + "transaction_details_date": "Kwanan wata", + "transaction_details_fee": "Kudin", + "transaction_details_height": "tsawo", + "transaction_details_recipient_address": "Adireshin masu amfani", "transaction_details_source_address": "Adireshin Incord", - "pause_wallet_creation": "A halin yanzu an dakatar da ikon ƙirƙirar Haven Wallet.", - "contractName": "Sunan Kwangila", - "contractSymbol": "Alamar Kwangila", - "description": "Bayani", - "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.", - "no_relays": "Babu relays", - "choose_relay": "Da fatan za a zaɓi gudun ba da sanda don amfani", - "no_relays_message": "Mun sami rikodin Nostr NIP-05 don wannan mai amfani, amma ba ya ƙunshe da kowane relays. Da fatan za a umurci mai karɓa ya ƙara relays zuwa rikodin su na Nostr.", - "no_relay_on_domain": "Babu gudun ba da sanda ga yankin mai amfani ko kuma ba a samu ba. Da fatan za a zaɓi gudun ba da sanda don amfani." -} + "transaction_details_title": "Bayanai game da aikace-aikacen", + "transaction_details_transaction_id": "ID na kasuwanci", + "transaction_key": "Aikace-aikacen key", + "transaction_priority_fast": "sauri", + "transaction_priority_fastest": "mafi sauri", + "transaction_priority_medium": "SAURI DA DADI", + "transaction_priority_regular": "SAURI NORMAL", + "transaction_priority_slow": "SAURI DA SAURI", + "transaction_sent": "An aika ciniki!", + "transaction_sent_notice": "Idan allon bai ci gaba ba bayan minti 1, duba mai binciken toshewa da imel ɗin ku.", + "transactions": "Ma'amaloli", + "transactions_by_date": "Ma'amaloli ta kwanan wata", + "trusted": "Amintacce", + "unavailable_balance": "Ma'aunin da ba ya samuwa", + "unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.", + "unconfirmed": "Ba a tabbatar ba", + "understand": "na gane", + "unmatched_currencies": "Nau'in walat ɗin ku na yanzu bai dace da na lambar QR da aka bincika ba", + "unspent_change": "Canza", + "unspent_coins_details_title": "Bayanan tsabar kudi da ba a kashe ba", + "unspent_coins_title": "Tsabar da ba a kashe ba", + "unsupported_asset": "Ba mu goyi bayan wannan aikin don wannan kadara. Da fatan za a ƙirƙira ko canza zuwa walat na nau'in kadara mai tallafi.", + "upto": "har zuwa ${value}", + "use": "Canja zuwa", + "use_card_info_three": "Yi amfani da katin dijital akan layi ko tare da hanyoyin biyan kuɗi mara lamba.", + "use_card_info_two": "Ana canza kuɗi zuwa dalar Amurka lokacin da ake riƙe su a cikin asusun da aka riga aka biya, ba cikin agogon dijital ba.", + "use_ssl": "Yi amfani da SSL", + "use_suggested": "Amfani da Shawarwari", + "variable_pair_not_supported": "Ba a samun goyan bayan wannan m biyu tare da zaɓaɓɓun musayar", + "verification": "tabbatar", + "version": "Sigar ${currentVersion}", + "view_all": "Duba duka", + "view_in_block_explorer": "Dubo a cikin Block Explorer", + "view_key_private": "Duba maɓallin (maɓallin kalmar sirri)", + "view_key_public": "Maɓallin Duba (maɓallin jama'a)", + "view_transaction_on": "Dubo aikace-aikacen akan", + "wallet_keys": "Iri/maɓalli na walat", + "wallet_list_create_new_wallet": "Ƙirƙiri Sabon Wallet", + "wallet_list_edit_wallet": "Gyara walat", + "wallet_list_failed_to_load": "An kasa loda ${wallet_name} walat. ${error}", + "wallet_list_failed_to_remove": "Ba a iya cirewa ${wallet_name} walat. ${error}", + "wallet_list_load_wallet": "Ana loda wallet na Monero", + "wallet_list_loading_wallet": "Ana loda ${wallet_name} walat", + "wallet_list_removing_wallet": "Cirewa ${wallet_name} walat", + "wallet_list_restore_wallet": "Maida Wallet", + "wallet_list_title": "Monero walat", + "wallet_list_wallet_name": "Sunan walat", + "wallet_menu": "Menu", + "wallet_name": "Sunan walat", + "wallet_name_exists": "Wallet mai wannan sunan ya riga ya wanzu. Da fatan za a zaɓi wani suna daban ko sake suna ɗayan walat tukuna.", + "wallet_restoration_store_incorrect_seed_length": "kalmar sirrin iri ba daidai ba", + "wallet_seed": "kalmar sirri na walat", + "wallet_seed_legacy": "Tallarin walat walat", + "wallet_store_monero_wallet": "Monero walat", + "walletConnect": "WalletConnect", + "wallets": "Wallets", + "warning": "Gargadi", + "welcome": "Barka da zuwa", + "welcome_to_cakepay": "Barka da zuwa Cake Pay!", + "widgets_address": "Adireshin", + "widgets_or": "ko", + "widgets_restore_from_blockheight": "Sake dawo da daga blockheight", + "widgets_restore_from_date": "Sake dawo da daga kwanan wata", + "widgets_seed": "iri", + "wouoldLikeToConnect": "ina son haɗi", + "write_down_backup_password": "Da fatan za a rubuta kalmar sirrin ajiyar ku, wacce ake amfani da ita don shigo da fayilolin ajiyar ku.", + "xlm_extra_info": "Don Allah kar a manta da saka Memo ID yayin aika ma'amalar XLM don musayar", + "xmr_available_balance": "Akwai Ma'auni", + "xmr_full_balance": "Cikakken Ma'auni", + "xmr_hidden": "Boye", + "xmr_to_error": "XMR.TO kuskure", + "xmr_to_error_description": "Adadin ba shi da inganci. Maksimum ɗaura 8 digiri bayan decimal point", + "xrp_extra_info": "Don Allah kar a manta da saka alamar Ƙaddamarwa yayin aika ma'amalar XRP don musayar", + "yat": "Yat", + "yat_address": "Yat Address", + "yat_alert_content": "Masu amfani da Wallet ɗin Cake yanzu za su iya aikawa da karɓar duk kuɗin da suka fi so tare da sunan mai amfani na tushen emoji iri ɗaya.", + "yat_alert_title": "Aika da karɓar crypto cikin sauƙi tare da Yat", + "yat_error": "Kuskure", + "yat_error_content": "Babu adireshi da ke da alaƙa da wannan Yat. Gwada wani Yat", + "yat_popup_content": "Yanzu zaku iya aikawa da karɓar crypto a cikin Cake Wallet tare da Yat - gajere, sunan mai amfani na tushen emoji. Sarrafa Yats a kowane lokaci akan allon saiti", + "yat_popup_title": "Adireshin jakar ku na iya zama emojifid.", + "yesterday": "Jiya", + "you_now_have_debit_card": "Yanzu kana da katin zare kudi", + "you_pay": "Ka Bayar", + "you_will_get": "Maida zuwa", + "you_will_send": "Maida daga", + "yy": "YY", + "zzzz": "zzzz" +} \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index a3950b44e..53347a69a 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -1,779 +1,780 @@ { - "welcome": "स्वागत हे सेवा मेरे", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Monero, Bitcoin, Ethereum, Litecoin, और Haven के लिए बहुत बढ़िया बटुआ", - "please_make_selection": "कृपया नीचे चयन करें अपना बटुआ बनाएं या पुनर्प्राप्त करें.", - "create_new": "नया बटुआ बनाएँ", - "restore_wallet": "वॉलेट को पुनर्स्थापित करें", - "monero_com": "Monero.com by Cake Wallet", - "monero_com_wallet_text": "Awesome wallet for Monero", - "haven_app": "Haven by Cake Wallet", - "haven_app_wallet_text": "Awesome wallet for Haven", - "accounts": "हिसाब किताब", - "edit": "संपादित करें", + "about_cake_pay": "केक पे आपको वर्चुअल संपत्ति के साथ आसानी से उपहार कार्ड खरीदने की अनुमति देता है, जिसे संयुक्त राज्य में 150,000 से अधिक व्यापारियों पर तुरंत खर्च किया जा सकता है।", "account": "लेखा", + "accounts": "हिसाब किताब", + "accounts_subaddresses": "लेखा और उपदेस", + "activate": "सक्रिय करें", + "active": "सक्रिय", + "active_cards": "सक्रिय कार्ड", + "activeConnectionsPrompt": "सक्रिय कनेक्शन यहां दिखाई देंगे", "add": "जोड़ना", + "add_contact": "संपर्क जोड़ें", + "add_custom_node": "नया कस्टम नोड जोड़ें", + "add_custom_redemption": "कस्टम रिडेम्पशन जोड़ें", + "add_fund_to_card": "कार्ड में प्रीपेड धनराशि जोड़ें (${value} तक)", + "add_new_node": "नया नोड जोड़ें", + "add_new_word": "नया शब्द जोड़ें", + "add_receiver": "एक और रिसीवर जोड़ें (वैकल्पिक)", + "add_secret_code": "या, इस गुप्त कोड को प्रमाणक ऐप में जोड़ें", + "add_tip": "टिप जोड़ें", + "add_token_disclaimer_check": "मैंने एक प्रतिष्ठित स्रोत का उपयोग करके टोकन अनुबंध पते और जानकारी की पुष्टि की है। दुर्भावनापूर्ण या गलत जानकारी जोड़ने से धन की हानि हो सकती है।", + "add_token_warning": "स्कैमर्स के निर्देशानुसार टोकन संपादित या जोड़ें न करें।\nहमेशा प्रतिष्ठित स्रोतों से टोकन पते की पुष्टि करें!", + "add_value": "मूल्य जोड़ें", + "address": "पता", "address_book": "पता पुस्तिका", - "contact": "संपर्क करें", - "please_select": "कृपया चुने:", - "cancel": "रद्द करना", - "ok": "ठीक है", - "contact_name": "संपर्क नाम", - "reset": "रीसेट", - "save": "बचाना", + "address_book_menu": "पता पुस्तिका", + "address_detected": "पता लग गया", + "address_from_domain": "यह पता ${domain} से है Unstoppable Domains", + "address_from_yat": "यह पता ${emoji} से है Yat", + "address_label": "Address label", "address_remove_contact": "संपर्क हटाये", "address_remove_content": "क्या आप वाकई चयनित संपर्क को हटाना चाहते हैं?", - "authenticated": "प्रमाणीकृत", - "authentication": "प्रमाणीकरण", - "failed_authentication": "प्रमाणीकरण विफल. ${state_error}", - "wallet_menu": "बटुआ मेनू", - "Blocks_remaining": "${status} शेष रहते हैं", - "please_try_to_connect_to_another_node": "कृपया दूसरे नोड से कनेक्ट करने का प्रयास करें", - "xmr_hidden": "छिपा हुआ", - "xmr_available_balance": "उपलब्ध शेष राशि", - "xmr_full_balance": "पूरा संतुलन", - "send": "संदेश", - "receive": "प्राप्त करना", - "transactions": "लेन-देन", - "incoming": "आने वाली", - "outgoing": "निवर्तमान", - "transactions_by_date": "तारीख से लेन-देन", - "trades": "ट्रेडों", - "filter_by": "के द्वारा छनित", - "today": "आज", - "yesterday": "बिता कल", - "received": "प्राप्त किया", - "sent": "भेज दिया", - "pending": " (अपूर्ण)", - "rescan": "पुन: स्कैन", - "reconnect": "रिकनेक्ट", - "wallets": "पर्स", - "show_seed": "बीज दिखाओ", - "show_keys": "बीज / कुंजियाँ दिखाएँ", - "address_book_menu": "पता पुस्तिका", - "reconnection": "पुनर्संयोजन", - "reconnect_alert_text": "क्या आप पुन: कनेक्ट होना सुनिश्चित करते हैं?", - "exchange": "अदला बदली", - "clear": "स्पष्ट", - "refund_address": "वापसी का पता", - "change_exchange_provider": "एक्सचेंज प्रदाता बदलें", - "you_will_send": "से रूपांतरित करें", - "you_will_get": "में बदलें", - "amount_is_guaranteed": "प्राप्त राशि की गारंटी है", - "amount_is_estimate": "प्राप्त राशि एक अनुमान है", - "powered_by": "द्वारा संचालित ${title}", - "error": "त्रुटि", - "estimated": "अनुमानित", - "min_value": "मिन: ${value} ${currency}", - "max_value": "मैक्स: ${value} ${currency}", - "change_currency": "मुद्रा परिवर्तन करें", - "overwrite_amount": "Overwrite amount", - "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", - "copy_id": "प्रतिलिपि ID", - "exchange_result_write_down_trade_id": "जारी रखने के लिए कृपया ट्रेड ID की प्रतिलिपि बनाएँ या लिखें.", - "trade_id": "व्यापार ID:", - "copied_to_clipboard": "क्लिपबोर्ड पर नकल", - "saved_the_trade_id": "मैंने व्यापार बचा लिया है ID", - "fetching": "ला रहा है", - "id": "ID: ", - "amount": "रकम: ", - "payment_id": "भुगतान ID: ", - "status": "स्थिति: ", - "offer_expires_in": "में ऑफर समाप्त हो रहा है: ", - "trade_is_powered_by": "यह व्यापार द्वारा संचालित है ${provider}", - "copy_address": "पता कॉपी करें", - "exchange_result_confirm": "पुष्टि दबाकर, आप भेज रहे होंगे ${fetchingLabel} ${from} अपने बटुए से ${walletName} नीचे दिखाए गए पते पर। या आप अपने बाहरी वॉलेट से नीचे के पते पर भेज सकते हैं / क्यूआर कोड पर भेज सकते हैं।\n\nकृपया जारी रखने या राशि बदलने के लिए वापस जाने के लिए पुष्टि करें दबाएं.", - "exchange_result_description": "आपको अगले पृष्ठ पर दिखाए गए पते पर न्यूनतम ${fetchingLabel} ${from} भेजना होगा। यदि आप ${fetchingLabel} ${from} से कम राशि भेजते हैं तो यह परिवर्तित नहीं हो सकती है और इसे वापस नहीं किया जा सकता है।", - "exchange_result_write_down_ID": "*कृपया ऊपर दिखाए गए अपने ID को कॉपी या लिख लें.", - "confirm": "की पुष्टि करें", - "confirm_sending": "भेजने की पुष्टि करें", - "commit_transaction_amount_fee": "लेन-देन करें\nरकम: ${amount}\nशुल्क: ${fee}", - "sending": "भेजना", - "transaction_sent": "भेजा गया लेन-देन", - "expired": "समय सीमा समाप्त", - "time": "${minutes}m ${seconds}s", - "send_xmr": "संदेश XMR", - "exchange_new_template": "नया टेम्पलेट", - "faq": "FAQ", - "enter_your_pin": "अपना पिन दर्ज करो", - "loading_your_wallet": "अपना बटुआ लोड कर रहा है", - "new_wallet": "नया बटुआ", - "wallet_name": "बटुए का नाम", - "continue_text": "जारी रहना", - "choose_wallet_currency": "कृपया बटुआ मुद्रा चुनें:", - "node_new": "नया नोड", - "node_address": "नोड पता", - "node_port": "नोड पोर्ट", - "login": "लॉग इन करें", - "password": "पारण शब्द", - "nodes": "नोड्स", - "node_reset_settings_title": "सेटिंग्स को दुबारा करें", - "nodes_list_reset_to_default_message": "क्या आप वाकई सेटिंग को डिफ़ॉल्ट पर रीसेट करना चाहते हैं?", - "change_current_node": "क्या आप वर्तमान नोड को बदलना सुनिश्चित करते हैं ${node}?", - "change": "परिवर्तन", - "remove_node": "नोड निकालें", - "remove_node_message": "क्या आप वाकई चयनित नोड को निकालना चाहते हैं?", - "remove": "हटाना", - "delete": "हटाएं", - "add_new_node": "नया नोड जोड़ें", - "change_current_node_title": "वर्तमान नोड बदलें", - "node_test": "परीक्षा", - "node_connection_successful": "कनेक्शन सफल रहा", - "node_connection_failed": "कनेक्शन विफल रहा", - "new_node_testing": "नई नोड परीक्षण", - "use": "उपयोग ", - "digit_pin": "-अंक पिन", - "share_address": "पता साझा करें", - "receive_amount": "रकम", - "subaddresses": "उप पते", "addresses": "पतों", - "scan_qr_code_to_get_address": "पता प्राप्त करने के लिए QR कोड स्कैन करें", - "qr_fullscreen": "फ़ुल स्क्रीन क्यूआर कोड खोलने के लिए टैप करें", - "rename": "नाम बदलें", - "choose_account": "खाता चुनें", - "create_new_account": "नया खाता बनाएँ", - "accounts_subaddresses": "लेखा और उपदेस", - "restore_restore_wallet": "वॉलेट को पुनर्स्थापित करें", - "restore_title_from_seed_keys": "बीज / कुंजियों से पुनर्स्थापित करें", - "restore_description_from_seed_keys": "अपने बटुए को बीज से वापस लें/वे कुंजियाँ जिन्हें आपने सुरक्षित स्थान पर सहेजा है", - "restore_next": "आगामी", - "restore_title_from_backup": "बैक-अप फ़ाइल से पुनर्स्थापित करें", - "restore_description_from_backup": "आप से पूरे केक वॉलेट एप्लिकेशन को पुनर्स्थापित कर सकते हैं आपकी बैक-अप फ़ाइल", - "restore_seed_keys_restore": "बीज / कुंजी पुनर्स्थापित करें", - "restore_title_from_seed": "बीज से पुनर्स्थापित करें", - "restore_description_from_seed": "या तो 25 शब्द से अपने वॉलेट को पुनर्स्थापित करें या 13 शब्द संयोजन कोड", - "restore_title_from_keys": "कुंजी से पुनर्स्थापित करें", - "restore_description_from_keys": "अपने वॉलेट को जेनरेट से पुनर्स्थापित करें आपकी निजी कुंजी से कीस्ट्रोक्स सहेजे गए", - "restore_wallet_name": "बटुए का नाम", - "restore_address": "पता", - "restore_view_key_private": "कुंजी देखें (निजी)", - "restore_spend_key_private": "कुंजी खर्च करें (निजीe)", - "restore_recover": "वसूली", - "restore_wallet_restore_description": "बटुआ विवरण पुनर्स्थापित करें", - "restore_new_seed": "नया बीज", - "restore_active_seed": "सक्रिय बीज", - "restore_bitcoin_description_from_seed": "24 शब्द संयोजन कोड से अपने वॉलेट को पुनर्स्थापित करें", - "restore_bitcoin_description_from_keys": "अपने निजी कुंजी से उत्पन्न WIF स्ट्रिंग से अपने वॉलेट को पुनर्स्थापित करें", - "restore_bitcoin_title_from_keys": "WIF से पुनर्स्थापित करें", - "restore_from_date_or_blockheight": "कृपया इस वॉलेट को बनाने से कुछ दिन पहले एक तारीख दर्ज करें। या यदि आप ब्लॉकचेट जानते हैं, तो कृपया इसके बजाय इसे दर्ज करें", - "seed_reminder": "यदि आप अपना फोन खो देते हैं या मिटा देते हैं तो कृपया इन्हें लिख लें", - "seed_title": "बीज", - "seed_share": "बीज साझा करें", - "copy": "प्रतिलिपि", - "seed_language": "बीज", - "seed_choose": "बीज भाषा चुनें", - "seed_language_next": "आगामी", - "seed_language_english": "अंग्रेज़ी", - "seed_language_chinese": "चीनी", - "seed_language_dutch": "डच", - "seed_language_german": "जर्मन", - "seed_language_japanese": "जापानी", - "seed_language_portuguese": "पुर्तगाली", - "seed_language_russian": "रूसी", - "seed_language_spanish": "स्पेनिश", - "seed_language_french": "फ्रेंच", - "seed_language_italian": "इतालवी", - "send_title": "संदेश", - "send_your_wallet": "आपका बटुआ", - "send_address": "${cryptoCurrency} पता", - "send_payment_id": "भुगतान ID (ऐच्छिक)", + "advanced_settings": "एडवांस सेटिंग", + "aggressive": "ज्यादा", + "agree": "सहमत", + "agree_and_continue": "सहमत और जारी रखें", + "agree_to": "खाता बनाकर आप इससे सहमत होते हैं ", "all": "सब", - "send_error_minimum_value": "राशि का न्यूनतम मूल्य 0.01 है", - "send_error_currency": "मुद्रा में केवल संख्याएँ हो सकती हैं", - "send_estimated_fee": "अनुमानित शुल्क:", - "send_priority": "वर्तमान में शुल्क निर्धारित है ${transactionPriority} प्राथमिकता.\nलेन-देन की प्राथमिकता को सेटिंग्स में समायोजित किया जा सकता है", - "send_creating_transaction": "लेन-देन बनाना", - "send_templates": "टेम्पलेट्स", - "send_new": "नया", - "send_amount": "रकम:", - "send_fee": "शुल्क:", - "send_name": "नाम", - "got_it": "समझ गया", - "send_sending": "भेजना...", - "send_success": "आपका ${crypto} सफलतापूर्वक भेजा गया", - "settings_title": "सेटिंग्स", - "settings_nodes": "नोड्स", - "settings_current_node": "वर्तमान नोड", - "settings_wallets": "पर्स", - "settings_display_balance": "प्रदर्शन संतुलन", - "settings_currency": "मुद्रा", - "settings_fee_priority": "शुल्क प्राथमिकता", - "settings_save_recipient_address": "प्राप्तकर्ता का पता सहेजें", - "settings_personal": "निजी", - "settings_change_pin": "पिन बदलें", - "settings_change_language": "भाषा बदलो", - "settings_allow_biometrical_authentication": "बायोमेट्रिक प्रमाणीकरण की अनुमति दें", - "settings_dark_mode": "डार्क मोड", - "settings_transactions": "लेन-देन", - "settings_trades": "ट्रेडों", - "settings_display_on_dashboard_list": "डैशबोर्ड सूची पर प्रदर्शित करें", - "settings_all": "सब", - "settings_only_trades": "केवल ट्रेड करता है", - "settings_only_transactions": "केवल लेन-देन", - "settings_none": "कोई नहीं", - "settings_support": "समर्थन", - "settings_terms_and_conditions": "नियम और शर्तें", - "pin_is_incorrect": "पिन गलत है", - "setup_pin": "पिन सेट करें", - "enter_your_pin_again": "फिर से अपना पिन डालें", - "setup_successful": "आपका पिन सफलतापूर्वक सेट हो गया है", - "wallet_keys": "बटुआ बीज / चाबियाँ", - "wallet_seed": "बटुआ का बीज", - "private_key": "निजी चाबी", - "public_key": "सार्वजनिक कुंजी", - "view_key_private": "कुंजी देखें(निजी)", - "view_key_public": "कुंजी देखें (जनता)", - "spend_key_private": "खर्च करना (निजी)", - "spend_key_public": "खर्च करना (जनता)", - "copied_key_to_clipboard": "की नकल की ${key} क्लिपबोर्ड पर", - "new_subaddress_title": "नया पता", - "new_subaddress_label_name": "लेबल का नाम", - "new_subaddress_create": "सर्जन करना", - "address_label": "Address label", - "subaddress_title": "उपखंड सूची", - "trade_details_title": "व्यापार विवरण", - "trade_details_id": "आईडी", - "trade_details_state": "दर्जा", - "trade_details_fetching": "ला रहा है", - "trade_details_provider": "प्रदाता", - "trade_details_created_at": "पर बनाया गया", - "trade_details_pair": "जोड़ा", - "trade_details_copied": "${title} क्लिपबोर्ड पर नकल", - "trade_history_title": "व्यापार का इतिहास", - "transaction_details_title": "लेनदेन का विवरण", - "transaction_details_transaction_id": "लेनदेन आईडी", - "transaction_details_date": "तारीख", - "transaction_details_height": "ऊंचाई", - "transaction_details_amount": "रकम", - "transaction_details_fee": "शुल्क", - "transaction_details_copied": "${title} क्लिपबोर्ड पर नकल", - "transaction_details_recipient_address": "प्राप्तकर्ता के पते", - "wallet_list_title": "Monero बटुआ", - "wallet_list_create_new_wallet": "नया बटुआ बनाएँ", - "wallet_list_edit_wallet": "बटुआ संपादित करें", - "wallet_list_wallet_name": "बटुआ नाम", - "wallet_list_restore_wallet": "वॉलेट को पुनर्स्थापित करें", - "wallet_list_load_wallet": "वॉलेट लोड करें", - "wallet_list_loading_wallet": "लोड हो रहा है ${wallet_name} बटुआ", - "wallet_list_failed_to_load": "लोड करने में विफल ${wallet_name} बटुआ. ${error}", - "wallet_list_removing_wallet": "निकाला जा रहा है ${wallet_name} बटुआ", - "wallet_list_failed_to_remove": "निकालने में विफल ${wallet_name} बटुआ. ${error}", - "widgets_address": "पता", - "widgets_restore_from_blockheight": "ब्लॉकचेन से पुनर्स्थापित करें", - "widgets_restore_from_date": "दिनांक से पुनर्स्थापित करें", - "widgets_or": "या", - "widgets_seed": "बीज", - "router_no_route": "के लिए कोई मार्ग निर्धारित नहीं है ${name}", - "error_text_account_name": "खाता नाम में केवल अक्षर, संख्याएं हो सकती हैं\nऔर 1 और 15 वर्णों के बीच लंबा होना चाहिए", - "error_text_contact_name": "संपर्क नाम शामिल नहीं हो सकता ` , ' \" प्रतीकों\nऔर 1 और 32 वर्णों के बीच लंबा होना चाहिए", - "error_text_address": "वॉलेट पता प्रकार के अनुरूप होना चाहिए\nक्रिप्टोकरेंसी का", - "error_text_node_address": "कृपया एक IPv4 पता दर्ज करें", - "error_text_node_port": "नोड पोर्ट में केवल 0 और 65535 के बीच संख्याएँ हो सकती हैं", - "error_text_node_proxy_address": "कृपया दर्ज करें: <पोर्ट>, उदाहरण के लिए 127.0.0.1:9050", - "error_text_payment_id": "पेमेंट आईडी केवल हेक्स में 16 से 64 चार्ट तक हो सकती है", - "error_text_xmr": "एक्सएमआर मूल्य उपलब्ध शेष राशि से अधिक नहीं हो सकता.\nअंश अंकों की संख्या 12 से कम या इसके बराबर होनी चाहिए", - "error_text_fiat": "राशि का मूल्य उपलब्ध शेष राशि से अधिक नहीं हो सकता.\nअंश अंकों की संख्या कम या 2 के बराबर होनी चाहिए", - "error_text_subaddress_name": "सबड्रेस नाम नहीं हो सकता` , ' \" प्रतीकों\nऔर 1 और 20 वर्णों के बीच लंबा होना चाहिए", - "error_text_amount": "राशि में केवल संख्याएँ हो सकती हैं", - "error_text_wallet_name": "वॉलेट नाम में केवल अक्षर, संख्याएं, _ - प्रतीक हो सकते हैं\nऔर 1 और 33 वर्णों के बीच लंबा होना चाहिए", - "error_text_keys": "वॉलेट कीज़ में हेक्स में केवल 64 वर्ण हो सकते हैं", - "error_text_crypto_currency": "अंश अंकों की संख्या\n12 से कम या इसके बराबर होना चाहिए", - "error_text_minimal_limit": "व्यापार ${provider} के लिए नहीं बनाया गया है। राशि कम है तो न्यूनतम: ${min} ${currency}", - "error_text_maximum_limit": "व्यापार ${provider} के लिए नहीं बनाया गया है। राशि अधिक है तो अधिकतम: ${max} ${currency}", - "error_text_limits_loading_failed": "व्यापार ${provider} के लिए नहीं बनाया गया है। लोडिंग की सीमाएं विफल रहीं", - "error_text_template": "टेम्प्लेट का नाम और पता नहीं हो सकता ` , ' \" प्रतीकों\nऔर 1 और 106 वर्णों के बीच लंबा होना चाहिए", + "all_trades": "सभी व्यापार", + "all_transactions": "सभी लेन - देन", + "alphabetical": "वर्णमाला", + "always": "हमेशा", + "amount": "रकम: ", + "amount_is_estimate": "प्राप्त राशि एक अनुमान है", + "amount_is_guaranteed": "प्राप्त राशि की गारंटी है", + "and": "और", + "anonpay_description": "${type} उत्पन्न करें। प्राप्तकर्ता किसी भी समर्थित क्रिप्टोकरेंसी के साथ ${method} कर सकता है, और आपको इस वॉलेट में धन प्राप्त होगा।", + "apk_update": "APK अद्यतन", + "approve": "मंज़ूरी देना", + "arrive_in_this_address": "${currency} ${tag}इस पते पर पहुंचेंगे", + "ascending": "आरोही", + "ask_each_time": "हर बार पूछें", "auth_store_ban_timeout": "समय की पाबंदी", "auth_store_banned_for": "के लिए प्रतिबंधित है ", "auth_store_banned_minutes": " मिनट", "auth_store_incorrect_password": "गलत पिन", - "wallet_store_monero_wallet": "मोनरो वॉलेट", - "wallet_restoration_store_incorrect_seed_length": "गलत बीज की लंबाई", - "full_balance": "पूर्ण संतुलन", - "available_balance": "उपलब्ध शेष राशि", - "hidden_balance": "छिपा हुआ संतुलन", - "sync_status_syncronizing": "सिंक्रनाइज़ करने", - "sync_status_syncronized": "सिंक्रनाइज़", - "sync_status_not_connected": "जुड़े नहीं हैं", - "sync_status_starting_sync": "सिताज़ा करना", - "sync_status_failed_connect": "डिस्कनेक्ट किया गया", - "sync_status_connecting": "कनेक्ट", - "sync_status_connected": "जुड़े हुए", - "sync_status_attempting_sync": "सिंक करने का प्रयास", - "transaction_priority_slow": "धीरे", - "transaction_priority_regular": "नियमित", - "transaction_priority_medium": "मध्यम", - "transaction_priority_fast": "उपवास", - "transaction_priority_fastest": "सबसे तेजी से", - "trade_for_not_created": "के लिए व्यापार ${title} निर्मित नहीं है.", - "trade_not_created": "व्यापार नहीं बनाया गया", - "trade_id_not_found": "व्यापार ${tradeId} of ${title} नहीं मिला.", - "trade_not_found": "व्यापार नहीं मिला", - "trade_state_pending": "विचाराधीन", - "trade_state_confirming": "पुष्टि", - "trade_state_trading": "व्यापार", - "trade_state_traded": "ट्रेडेड", - "trade_state_complete": "पूर्ण", - "trade_state_to_be_created": "बनाए जाने के लिए", - "trade_state_unpaid": "अवैतनिक", - "trade_state_underpaid": "के तहत भुगतान किया", - "trade_state_paid_unconfirmed": "अपुष्ट भुगतान किया", - "trade_state_paid": "भुगतान किया है", - "trade_state_btc_sent": "भेज दिया", - "trade_state_timeout": "समय समाप्त", - "trade_state_created": "बनाया था", - "trade_state_finished": "ख़त्म होना", - "change_language": "भाषा बदलो", - "change_language_to": "को भाषा बदलें ${language}?", - "paste": "पेस्ट करें", - "restore_from_seed_placeholder": "कृपया अपना कोड वाक्यांश यहां दर्ज करें या पेस्ट करें", - "add_new_word": "नया शब्द जोड़ें", - "incorrect_seed": "दर्ज किया गया पाठ मान्य नहीं है।", - "biometric_auth_reason": "प्रमाणित करने के लिए अपने फ़िंगरप्रिंट को स्कैन करें", - "version": "संस्करण ${currentVersion}", - "extracted_address_content": "आपको धनराशि भेजी जाएगी\n${recipient_name}", - "card_address": "पता:", - "buy": "खरीदें", - "sell": "बेचना", - "placeholder_transactions": "आपके लेनदेन यहां प्रदर्शित होंगे", - "placeholder_contacts": "आपके संपर्क यहां प्रदर्शित होंगे", - "template": "खाका", - "confirm_delete_template": "यह क्रिया इस टेम्पलेट को हटा देगी। क्या आप जारी रखना चाहते हैं?", - "confirm_delete_wallet": "यह क्रिया इस वॉलेट को हटा देगी। क्या आप जारी रखना चाहते हैं?", - "change_wallet_alert_title": "वर्तमान बटुआ बदलें", - "change_wallet_alert_content": "क्या आप करंट वॉलेट को बदलना चाहते हैं ${wallet_name}?", - "creating_new_wallet": "नया बटुआ बनाना", - "creating_new_wallet_error": "त्रुटि: ${description}", - "seed_alert_title": "ध्यान", - "seed_alert_content": "बीज आपके बटुए को पुनर्प्राप्त करने का एकमात्र तरीका है। क्या आपने इसे लिखा है?", - "seed_alert_back": "वापस जाओ", - "seed_alert_yes": "हाँ मेरे पास है", - "exchange_sync_alert_content": "कृपया प्रतीक्षा करें जब तक आपका बटुआ सिंक्रनाइज़ नहीं किया जाता है", - "pre_seed_title": "महत्वपूर्ण", - "pre_seed_description": "अगले पेज पर आपको ${words} शब्दों की एक श्रृंखला दिखाई देगी। यह आपका अद्वितीय और निजी बीज है और नुकसान या खराबी के मामले में अपने बटुए को पुनर्प्राप्त करने का एकमात्र तरीका है। यह आपकी जिम्मेदारी है कि इसे नीचे लिखें और इसे Cake Wallet ऐप के बाहर सुरक्षित स्थान पर संग्रहीत करें।", - "pre_seed_button_text": "मै समझता हुँ। मुझे अपना बीज दिखाओ", - "xmr_to_error": "XMR.TO त्रुटि", - "xmr_to_error_description": "अवैध राशि। दशमलव बिंदु के बाद अधिकतम सीमा 8 अंक", - "provider_error": "${provider} त्रुटि", - "use_ssl": "उपयोग SSL", - "trusted": "भरोसा", - "color_theme": "रंग विषय", - "light_theme": "रोशनी", - "bright_theme": "उज्ज्वल", - "dark_theme": "अंधेरा", - "enter_your_note": "अपना नोट दर्ज करें ...", - "note_optional": "नोट (वैकल्पिक)", - "note_tap_to_change": "नोट (टैप टू चेंज)", - "view_in_block_explorer": "View in Block Explorer", - "view_transaction_on": "View Transaction on ", - "transaction_key": "लेन-देन की", - "confirmations": "पुष्टिकरण", - "recipient_address": "प्राप्तकर्ता का पता", - "extra_id": "अतिरिक्त आईडी:", - "destination_tag": "गंतव्य टैग:", - "memo": "ज्ञापन:", - "backup": "बैकअप", - "change_password": "पासवर्ड बदलें", - "backup_password": "बैकअप पासवर्ड", - "write_down_backup_password": "कृपया अपना बैकअप पासवर्ड लिखें, जिसका उपयोग आपकी बैकअप फ़ाइलों के आयात के लिए किया जाता है।", - "export_backup": "निर्यात बैकअप", - "save_backup_password": "कृपया सुनिश्चित करें कि आपने अपना बैकअप पासवर्ड सहेज लिया है। आप इसके बिना अपनी बैकअप फ़ाइलों को आयात नहीं कर पाएंगे।", - "backup_file": "बैकअपफ़ाइल", - "edit_backup_password": "बैकअप पासवर्ड संपादित करें", - "save_backup_password_alert": "बैकअप पासवर्ड सेव करें", - "change_backup_password_alert": "आपकी पिछली बैकअप फाइलें नए बैकअप पासवर्ड के साथ आयात करने के लिए उपलब्ध नहीं होंगी। नए बैकअप पासवर्ड का उपयोग केवल नई बैकअप फ़ाइलों के लिए किया जाएगा। क्या आप वाकई बैकअप पासवर्ड बदलना चाहते हैं?", - "enter_backup_password": "यहां बैकअप पासवर्ड डालें", - "select_backup_file": "बैकअप फ़ाइल का चयन करें", - "import": "आयात", - "please_select_backup_file": "कृपया बैकअप फ़ाइल चुनें और बैकअप पासवर्ड डालें।", - "fixed_rate": "निर्धारित दर", - "fixed_rate_alert": "फिक्स्ड रेट मोड की जांच करने पर आप प्राप्त राशि दर्ज कर पाएंगे। क्या आप निश्चित दर मोड पर स्विच करना चाहते हैं?", - "xlm_extra_info": "एक्सचेंज के लिए XLM ट्रांजेक्शन भेजते समय मेमो आईडी निर्दिष्ट करना न भूलें", - "xrp_extra_info": "एक्सचेंज के लिए एक्सआरपी लेनदेन भेजते समय कृपया गंतव्य टैग निर्दिष्ट करना न भूलें", - "exchange_incorrect_current_wallet_for_xmr": "यदि आप अपने केक वॉलेट मोनेरो बैलेंस से एक्सएमआर का आदान-प्रदान करना चाहते हैं, तो कृपया अपने मोनेरो वॉलेट में जाएं।", - "confirmed": "पुष्टि की गई शेष राशिी", - "unconfirmed": "अपुष्ट शेष राशि", - "displayable": "प्रदर्शन योग्य", - "submit_request": "एक अनुरोध सबमिट करें", - "buy_alert_content": "वर्तमान में हम केवल बिटकॉइन, एथेरियम, लाइटकॉइन और मोनेरो की खरीद का समर्थन करते हैं। कृपया अपना बिटकॉइन, एथेरियम, लाइटकॉइन, या मोनेरो वॉलेट बनाएं या उस पर स्विच करें।", - "sell_alert_content": "हम वर्तमान में केवल बिटकॉइन, एथेरियम और लाइटकॉइन की बिक्री का समर्थन करते हैं। कृपया अपना बिटकॉइन, एथेरियम या लाइटकॉइन वॉलेट बनाएं या उसमें स्विच करें।", - "outdated_electrum_wallet_description": "केक में बनाए गए नए बिटकॉइन वॉलेट में अब 24-शब्द का बीज है। यह अनिवार्य है कि आप एक नया बिटकॉइन वॉलेट बनाएं और अपने सभी फंड को नए 24-शब्द वाले वॉलेट में स्थानांतरित करें, और 12-शब्द बीज वाले वॉलेट का उपयोग करना बंद करें। कृपया अपने धन को सुरक्षित करने के लिए इसे तुरंत करें।", - "understand": "मुझे समझ", - "apk_update": "APK अद्यतन", - "buy_bitcoin": "बिटकॉइन खरीदें", - "buy_with": "के साथ खरीदें", - "moonpay_alert_text": "राशि का मूल्य अधिक है या करने के लिए बराबर होना चाहिए ${minAmount} ${fiatCurrency}", - "outdated_electrum_wallet_receive_warning": "अगर इस वॉलेट में 12 शब्दों का बीज है और इसे केक में बनाया गया है, तो इस वॉलेट में बिटकॉइन जमा न करें। इस वॉलेट में स्थानांतरित किया गया कोई भी बीटीसी खो सकता है। एक नया 24-शब्द वॉलेट बनाएं (ऊपर दाईं ओर स्थित मेनू पर टैप करें, वॉलेट चुनें, नया वॉलेट बनाएं चुनें, फिर बिटकॉइन चुनें) और तुरंत अपना बीटीसी वहां ले जाएं। केक से नए (24-शब्द) बीटीसी वॉलेट सुरक्षित हैं", - "do_not_show_me": "मुझे यह फिर न दिखाएं", - "unspent_coins_title": "खर्च न किए गए सिक्के", - "unspent_coins_details_title": "अव्ययित सिक्कों का विवरण", - "freeze": "फ्रीज", - "frozen": "जमा हुआ", - "coin_control": "सिक्का नियंत्रण (वैकल्पिक)", - "address_detected": "पता लग गया", - "address_from_domain": "यह पता ${domain} से है Unstoppable Domains", - "add_receiver": "एक और रिसीवर जोड़ें (वैकल्पिक)", - "manage_yats": "Yats प्रबंधित करें", - "yat_alert_title": "के साथ अधिक आसानी से क्रिप्टो भेजें और प्राप्त करें Yat", - "yat_alert_content": "Cake Wallet उपयोगकर्ता अब अपनी सभी पसंदीदा मुद्राओं को एक-एक तरह के इमोजी-आधारित उपयोगकर्ता नाम के साथ भेज और प्राप्त कर सकते हैं।", - "get_your_yat": "अपना प्राप्त करें Yat", - "connect_an_existing_yat": "मौजूदा Yat कनेक्ट करें", - "yat_address": "Yat पता", - "yat": "Yat", - "connect_yats": "कनेक्ट Yats", - "address_from_yat": "यह पता ${emoji} से है Yat", - "yat_error": "Yat त्रुटि", - "yat_error_content": "इसके साथ कोई पता लिंक नहीं है Yat. कोई दूसरा आज़माएं Yat", - "choose_address": "\n\nकृपया पता चुनें:", - "yat_popup_title": "आपका वॉलेट पता इमोजी किया जा सकता है।", - "yat_popup_content": "अब आप क्रिप्टो भेज और प्राप्त कर सकते हैं Cake Wallet अपने Yat के साथ - एक छोटा, इमोजी-आधारित उपयोगकर्ता नाम। सेटिंग स्क्रीन पर किसी भी समय Yats को प्रबंधित करें", - "second_intro_title": "उन सभी पर राज करने के लिए एक इमोजी पता", - "second_intro_content": "आपका Yat एक अद्वितीय इमोजी पता है जो आपकी सभी मुद्राओं के लिए आपके सभी लंबे हेक्साडेसिमल पतों को बदल देता है।", - "third_intro_title": "Yat दूसरों के साथ अच्छा खेलता है", - "third_intro_content": "Yats Cake Wallet के बाहर भी रहता है। धरती पर किसी भी वॉलेट पते को Yat से बदला जा सकता है!", - "learn_more": "और अधिक जानें", - "search": "खोज", - "search_language": "भाषा खोजें", - "search_currency": "मुद्रा खोजें", - "new_template": "नया टेम्पलेट", - "electrum_address_disclaimer": "हर बार जब आप एक का उपयोग करते हैं तो हम नए पते उत्पन्न करते हैं, लेकिन पिछले पते काम करना जारी रखते हैं", - "wallet_name_exists": "उस नाम वाला वॉलेट पहले से मौजूद है", - "market_place": "मार्केटप्लेस", - "cake_pay_title": "केक पे गिफ्ट कार्ड्स", - "cake_pay_subtitle": "रियायती उपहार कार्ड खरीदें (केवल यूएसए)", - "cake_pay_web_cards_title": "केक भुगतान वेब कार्ड", - "cake_pay_web_cards_subtitle": "दुनिया भर में प्रीपेड कार्ड और गिफ्ट कार्ड खरीदें", - "about_cake_pay": "केक पे आपको वर्चुअल संपत्ति के साथ आसानी से उपहार कार्ड खरीदने की अनुमति देता है, जिसे संयुक्त राज्य में 150,000 से अधिक व्यापारियों पर तुरंत खर्च किया जा सकता है।", - "cake_pay_account_note": "कार्ड देखने और खरीदने के लिए केवल एक ईमेल पते के साथ साइन अप करें। कुछ छूट पर भी उपलब्ध हैं!", - "ready_have_account": "क्या आपके पास पहले से ही एक खाता है?", - "create_account": "खाता बनाएं", - "privacy_policy": "गोपनीयता नीति", - "welcome_to_cakepay": "केकपे में आपका स्वागत है!", - "sign_up": "साइन अप करें", - "forgot_password": "पासवर्ड भूल गए", - "reset_password": "पासवर्ड रीसेट करें", - "gift_cards": "उपहार कार्ड", - "setup_your_debit_card": "अपना डेबिट कार्ड सेट करें", - "no_id_required": "कोई आईडी आवश्यक नहीं है। टॉप अप करें और कहीं भी खर्च करें", - "how_to_use_card": "इस कार्ड का उपयोग कैसे करें", - "purchase_gift_card": "गिफ्ट कार्ड खरीदें", - "verification": "सत्यापन", - "fill_code": "कृपया अपने ईमेल पर प्रदान किया गया सत्यापन कोड भरें", - "didnt_get_code": "कोड नहीं मिला?", - "resend_code": "कृपया इसे फिर से भेजें", - "debit_card": "डेबिट कार्ड", - "cakepay_prepaid_card": "केकपे प्रीपेड डेबिट कार्ड", - "no_id_needed": "कोई आईडी नहीं चाहिए!", - "frequently_asked_questions": "अक्सर पूछे जाने वाले प्रश्न", - "debit_card_terms": "इस डिजिटल वॉलेट में आपके भुगतान कार्ड नंबर (और आपके भुगतान कार्ड नंबर से संबंधित क्रेडेंशियल) का भंडारण और उपयोग भुगतान कार्ड जारीकर्ता के साथ लागू कार्डधारक समझौते के नियमों और शर्तों के अधीन है, जैसा कि प्रभावी है समय - समय पर।", - "please_reference_document": "कृपया अधिक जानकारी के लिए नीचे दिए गए दस्तावेज़ देखें।", - "cardholder_agreement": "कार्डधारक अनुबंध", - "e_sign_consent": "ई-साइन सहमति", - "agree_and_continue": "सहमत और जारी रखें", - "email_address": "ईमेल पता", - "agree_to": "खाता बनाकर आप इससे सहमत होते हैं ", - "and": "और", - "enter_code": "कोड दर्ज करें", - "congratulations": "बधाई!", - "you_now_have_debit_card": "अब आपके पास डेबिट कार्ड है", - "min_amount": "न्यूनतम: ${value}", - "max_amount": "अधिकतम: ${value}", - "enter_amount": "राशि दर्ज करें", - "billing_address_info": "यदि बिलिंग पता मांगा जाए, तो अपना शिपिंग पता प्रदान करें", - "order_physical_card": "फिजिकल कार्ड ऑर्डर करें", - "add_value": "मूल्य जोड़ें", - "activate": "सक्रिय करें", - "get_a": "एक प्राप्त करें", - "digital_and_physical_card": "डिजिटल और भौतिक प्रीपेड डेबिट कार्ड", - "get_card_note": " कि आप डिजिटल मुद्राओं के साथ पुनः लोड कर सकते हैं। कोई अतिरिक्त जानकारी की आवश्यकता नहीं है!", - "signup_for_card_accept_terms": "कार्ड के लिए साइन अप करें और शर्तें स्वीकार करें।", - "add_fund_to_card": "कार्ड में प्रीपेड धनराशि जोड़ें (${value} तक)", - "use_card_info_two": "डिजिटल मुद्राओं में नहीं, प्रीपेड खाते में रखे जाने पर निधियों को यूएसडी में बदल दिया जाता है।", - "use_card_info_three": "डिजिटल कार्ड का ऑनलाइन या संपर्क रहित भुगतान विधियों के साथ उपयोग करें।", - "optionally_order_card": "वैकल्पिक रूप से एक भौतिक कार्ड ऑर्डर करें।", - "hide_details": "विवरण छुपाएं", - "show_details": "विवरण दिखाएं", - "upto": "${value} तक", - "discount": "${value}% बचाएं", - "gift_card_amount": "गिफ्ट कार्ड राशि", - "bill_amount": "बिल राशि", - "you_pay": "आप भुगतान करते हैं", - "tip": "टिप:", - "custom": "कस्टम", - "by_cake_pay": "केकपे द्वारा", - "expires": "समाप्त हो जाता है", - "mm": "एमएम", - "yy": "वाईवाई", - "online": "ऑनलाइन", - "offline": "ऑफ़लाइन", - "gift_card_number": "गिफ्ट कार्ड नंबर", - "pin_number": "पिन नंबर", - "total_saving": "कुल बचत", - "last_30_days": "पिछले 30 दिन", - "avg_savings": "औसत बचत", - "view_all": "सभी देखें", - "active_cards": "सक्रिय कार्ड", - "delete_account": "खाता हटाएं", - "cards": "कार्ड", - "active": "सक्रिय", - "redeemed": "रिडीम किया गया", - "gift_card_balance_note": "गिफ्ट कार्ड शेष राशि के साथ यहां दिखाई देंगे", - "gift_card_redeemed_note": "आपके द्वारा भुनाए गए उपहार कार्ड यहां दिखाई देंगे", - "logout": "लॉगआउट", - "add_tip": "टिप जोड़ें", - "percentageOf": "${amount} का", - "is_percentage": "है", - "search_category": "खोज श्रेणी", - "mark_as_redeemed": "रिडीम किए गए के रूप में चिह्नित करें", - "more_options": "और विकल्प", - "awaiting_payment_confirmation": "भुगतान की पुष्टि की प्रतीक्षा में", - "transaction_sent_notice": "अगर 1 मिनट के बाद भी स्क्रीन आगे नहीं बढ़ती है, तो ब्लॉक एक्सप्लोरर और अपना ईमेल देखें।", - "agree": "सहमत", - "in_store": "स्टोर में", - "generating_gift_card": "गिफ्ट कार्ड जनरेट कर रहा है", - "Payment_was_received": "आपका भुगतान प्राप्त हो गया था।", - "proceed_after_one_minute": "यदि 1 मिनट के बाद भी स्क्रीन आगे नहीं बढ़ती है, तो अपना ईमेल देखें।", - "order_id": "ऑर्डर आईडी", - "gift_card_is_generated": "गिफ्ट कार्ड जनरेट हुआ", - "open_gift_card": "गिफ्ट कार्ड खोलें", - "contact_support": "सहायता से संपर्क करें", - "gift_cards_unavailable": "उपहार कार्ड इस समय केवल मोनेरो, बिटकॉइन और लिटकोइन के माध्यम से खरीदने के लिए उपलब्ध हैं", - "background_sync_mode": "बैकग्राउंड सिंक मोड", - "sync_all_wallets": "सभी वॉलेट सिंक करें", - "introducing_cake_pay": "परिचय Cake Pay!", - "cake_pay_learn_more": "ऐप में उपहार कार्ड तुरंत खरीदें और रिडीम करें!\nअधिक जानने के लिए बाएं से दाएं स्वाइप करें।", + "authenticated": "प्रमाणीकृत", + "authentication": "प्रमाणीकरण", + "auto_generate_subaddresses": "स्वचालित रूप से उप-पते उत्पन्न करें", "automatic": "स्वचालित", - "fixed_pair_not_supported": "यह निश्चित जोड़ी चयनित एक्सचेंजों के साथ समर्थित नहीं है", - "variable_pair_not_supported": "यह परिवर्तनीय जोड़ी चयनित एक्सचेंजों के साथ समर्थित नहीं है", - "none_of_selected_providers_can_exchange": "चयनित प्रदाताओं में से कोई भी इस एक्सचेंज को नहीं बना सकता", - "choose_one": "एक का चयन", - "choose_from_available_options": "उपलब्ध विकल्पों में से चुनें:", - "custom_redeem_amount": "कस्टम रिडीम राशि", - "add_custom_redemption": "कस्टम रिडेम्पशन जोड़ें", - "remaining": "शेष", - "delete_wallet": "वॉलेट हटाएं", - "delete_wallet_confirm_message": "क्या आप वाकई ${wallet_name} वॉलेट हटाना चाहते हैं?", - "low_fee": "कम शुल्क", - "low_fee_alert": "आप वर्तमान में कम नेटवर्क शुल्क प्राथमिकता का उपयोग कर रहे हैं। यह लंबे इंतजार, अलग-अलग दरों या रद्द किए गए ट्रेडों का कारण बन सकता है। हम बेहतर अनुभव के लिए अधिक शुल्क निर्धारित करने की सलाह देते हैं।", - "ignor": "नज़रअंदाज़ करना", - "use_suggested": "सुझाए गए का प्रयोग करें", - "do_not_share_warning_text": "समर्थन सहित, इन्हें किसी और के साथ साझा न करें।\n\nआपके धन की चोरी हो सकती है और होगी!", - "help": "मदद करना", - "all_transactions": "सभी लेन - देन", - "all_trades": "सभी व्यापार", - "connection_sync": "कनेक्शन और सिंक", - "security_and_backup": "सुरक्षा और बैकअप", - "create_backup": "बैकअप बनाएँ", - "privacy_settings": "गोपनीयता सेटिंग्स", - "privacy": "गोपनीयता", - "display_settings": "प्रदर्शन सेटिंग्स", - "other_settings": "अन्य सेटिंग्स", - "require_pin_after": "इसके बाद पिन आवश्यक है", - "always": "हमेशा", - "minutes_to_pin_code": "${minute} मिनट", - "disable_exchange": "एक्सचेंज अक्षम करें", - "advanced_settings": "एडवांस सेटिंग", - "settings_can_be_changed_later": "इन सेटिंग्स को बाद में ऐप सेटिंग में बदला जा सकता है", - "add_custom_node": "नया कस्टम नोड जोड़ें", - "disable_fiat": "िएट को अक्षम करें", - "fiat_api": "फिएट पैसे API", - "disabled": "अक्षम", - "enabled": "सक्रिय", - "tor_only": "Tor केवल", - "unmatched_currencies": "आपके वर्तमान वॉलेट की मुद्रा स्कैन किए गए क्यूआर से मेल नहीं खाती", - "orbot_running_alert": "कृपया सुनिश्चित करें कि इस नोड से कनेक्ट करने से पहले Orbot चल रहा है।", - "contact_list_contacts": "संपर्क", - "contact_list_wallets": "मेरा बटुआ", - "bitcoin_payments_require_1_confirmation": "बिटकॉइन भुगतान के लिए 1 पुष्टिकरण की आवश्यकता होती है, जिसमें 20 मिनट या अधिक समय लग सकता है। आपके धैर्य के लिए धन्यवाद! भुगतान की पुष्टि होने पर आपको ईमेल किया जाएगा।", - "send_to_this_address": "इस पते पर ${currency} ${tag}भेजें", - "arrive_in_this_address": "${currency} ${tag}इस पते पर पहुंचेंगे", - "do_not_send": "मत भेजो", - "error_dialog_content": "ओह, हमसे कुछ गड़बड़ी हुई है.\n\nएप्लिकेशन को बेहतर बनाने के लिए कृपया क्रैश रिपोर्ट हमारी सहायता टीम को भेजें।", - "scan_qr_code": "स्कैन क्यू आर कोड", - "cold_or_recover_wallet": "कोल्ड वॉलेट जोड़ें या पेपर वॉलेट पुनर्प्राप्त करें", - "please_wait": "कृपया प्रतीक्षा करें", - "sweeping_wallet": "स्वीपिंग वॉलेट", - "sweeping_wallet_alert": "इसमें अधिक समय नहीं लगना चाहिए। इस स्क्रीन को न छोड़ें या स्वैप्ट फंड खो सकते हैं", - "decimal_places_error": "बहुत अधिक दशमलव स्थान", - "edit_node": "नोड संपादित करें", - "invoice_details": "चालान विवरण", - "donation_link_details": "दान लिंक विवरण", - "anonpay_description": "${type} उत्पन्न करें। प्राप्तकर्ता किसी भी समर्थित क्रिप्टोकरेंसी के साथ ${method} कर सकता है, और आपको इस वॉलेट में धन प्राप्त होगा।", - "create_invoice": "इनवॉयस बनाएँ", - "create_donation_link": "दान लिंक बनाएं", - "optional_email_hint": "वैकल्पिक प्राप्तकर्ता सूचना ईमेल", - "optional_description": "वैकल्पिक विवरण", - "optional_name": "वैकल्पिक प्राप्तकर्ता नाम", - "clearnet_link": "क्लियरनेट लिंक", - "onion_link": "प्याज का लिंक", - "settings": "समायोजन", - "sell_monero_com_alert_content": "मोनेरो बेचना अभी तक समर्थित नहीं है", - "error_text_input_below_minimum_limit": "राशि न्यूनतम से कम है", - "error_text_input_above_maximum_limit": "राशि अधिकतम से अधिक है", - "show_market_place": "बाज़ार दिखाएँ", - "prevent_screenshots": "स्क्रीनशॉट और स्क्रीन रिकॉर्डिंग रोकें", - "profile": "प्रोफ़ाइल", - "close": "बंद करना", - "modify_2fa": "केक 2FA संशोधित करें", - "disable_cake_2fa": "केक 2FA अक्षम करें", - "question_to_disable_2fa": "क्या आप सुनिश्चित हैं कि आप Cake 2FA को अक्षम करना चाहते हैं? वॉलेट और कुछ कार्यों तक पहुँचने के लिए अब 2FA कोड की आवश्यकता नहीं होगी।", - "disable": "अक्षम करना", - "setup_2fa": "सेटअप केक 2FA", - "verify_with_2fa": "केक 2FA के साथ सत्यापित करें", - "totp_code": "टीओटीपी कोड", - "please_fill_totp": "कृपया अपने दूसरे डिवाइस पर मौजूद 8 अंकों का कोड भरें", - "totp_2fa_success": "सफलता! इस वॉलेट के लिए Cake 2FA सक्षम है। यदि आप वॉलेट एक्सेस खो देते हैं तो अपने स्मरक बीज को सहेजना याद रखें।", - "totp_verification_success": "सत्यापन सफल!", - "totp_2fa_failure": "गलत कोड़। कृपया एक अलग कोड का प्रयास करें या एक नई गुप्त कुंजी उत्पन्न करें। 8-अंकीय कोड और SHA512 का समर्थन करने वाले संगत 2FA ऐप का उपयोग करें।", - "enter_totp_code": "कृपया TOTP कोड दर्ज करें।", - "add_secret_code": "या, इस गुप्त कोड को प्रमाणक ऐप में जोड़ें", - "totp_secret_code": "टीओटीपी गुप्त कोड", - "setup_2fa_text": "केक 2FA दूसरे प्रमाणीकरण कारक के रूप में TOTP का उपयोग करके काम करता है।\n\nकेक 2FA के TOTP को SHA-512 और 8 अंकों के समर्थन की आवश्यकता है; इससे अधिक सुरक्षा मिलती है. अधिक जानकारी और समर्थित ऐप्स गाइड में पाए जा सकते हैं।", - "setup_totp_recommended": "सेटअप टीओटीपी", - "disable_buy": "खरीद कार्रवाई अक्षम करें", - "disable_sell": "बेचने की कार्रवाई अक्षम करें", - "cake_2fa_preset": "केक 2एफए प्रीसेट", - "monero_dark_theme": "मोनेरो डार्क थीम", + "available_balance": "उपलब्ध शेष राशि", + "available_balance_description": "उपलब्ध शेष या ”पुष्टिकृत शेष”, वे धनराशि हैं जिन्हें तुरंत खर्च किया जा सकता है। यदि फंड निचले बैलेंस में दिखाई देते हैं, लेकिन शीर्ष बैलेंस में नहीं, तो आपको आने वाले फंड के लिए अधिक नेटवर्क पुष्टिकरण प्राप्त करने के लिए कुछ मिनट इंतजार करना होगा। अधिक पुष्टि मिलने के बाद, वे खर्च करने योग्य हो जाएंगे।", + "avg_savings": "औसत बचत", + "awaitDAppProcessing": "कृपया डीएपी की प्रोसेसिंग पूरी होने तक प्रतीक्षा करें।", + "awaiting_payment_confirmation": "भुगतान की पुष्टि की प्रतीक्षा में", + "background_sync_mode": "बैकग्राउंड सिंक मोड", + "backup": "बैकअप", + "backup_file": "बैकअपफ़ाइल", + "backup_password": "बैकअप पासवर्ड", + "balance_page": "बैलेंस पेज", + "bill_amount": "बिल राशि", + "billing_address_info": "यदि बिलिंग पता मांगा जाए, तो अपना शिपिंग पता प्रदान करें", + "biometric_auth_reason": "प्रमाणित करने के लिए अपने फ़िंगरप्रिंट को स्कैन करें", "bitcoin_dark_theme": "बिटकॉइन डार्क थीम", "bitcoin_light_theme": "बिटकॉइन लाइट थीम", - "high_contrast_theme": "उच्च कंट्रास्ट थीम", - "matrix_green_dark_theme": "मैट्रिक्स ग्रीन डार्क थीम", - "monero_light_theme": "मोनेरो लाइट थीम", - "auto_generate_subaddresses": "स्वचालित रूप से उप-पते उत्पन्न करें", - "narrow": "सँकरा", - "normal": "सामान्य", - "aggressive": "ज्यादा", - "require_for_assessing_wallet": "वॉलेट तक पहुँचने के लिए आवश्यकता है", - "require_for_sends_to_non_contacts": "गैर-संपर्कों को भेजने की आवश्यकता", - "require_for_sends_to_contacts": "संपर्कों को भेजने के लिए आवश्यक है", - "require_for_sends_to_internal_wallets": "आंतरिक वॉलेट में भेजने की आवश्यकता है", - "require_for_exchanges_to_internal_wallets": "आंतरिक वॉलेट में आदान-प्रदान की आवश्यकता है", - "require_for_adding_contacts": "संपर्क जोड़ने के लिए आवश्यकता है", - "require_for_creating_new_wallets": "नए वॉलेट बनाने की आवश्यकता है", - "require_for_all_security_and_backup_settings": "सभी सुरक्षा और बैकअप सेटिंग्स की आवश्यकता है", - "available_balance_description": "उपलब्ध शेष या ”पुष्टिकृत शेष”, वे धनराशि हैं जिन्हें तुरंत खर्च किया जा सकता है। यदि फंड निचले बैलेंस में दिखाई देते हैं, लेकिन शीर्ष बैलेंस में नहीं, तो आपको आने वाले फंड के लिए अधिक नेटवर्क पुष्टिकरण प्राप्त करने के लिए कुछ मिनट इंतजार करना होगा। अधिक पुष्टि मिलने के बाद, वे खर्च करने योग्य हो जाएंगे।", - "syncing_wallet_alert_title": "आपका वॉलेट सिंक हो रहा है", - "syncing_wallet_alert_content": "आपकी शेष राशि और लेनदेन सूची तब तक पूरी नहीं हो सकती जब तक कि शीर्ष पर \"सिंक्रनाइज़्ड\" न लिखा हो। अधिक जानने के लिए क्लिक/टैप करें।", - "home_screen_settings": "होम स्क्रीन सेटिंग्स", - "sort_by": "इसके अनुसार क्रमबद्ध करें", - "search_add_token": "खोजें/टोकन जोड़ें", - "edit_token": "टोकन संपादित करें", - "warning": "चेतावनी", - "add_token_warning": "स्कैमर्स के निर्देशानुसार टोकन संपादित या जोड़ें न करें।\nहमेशा प्रतिष्ठित स्रोतों से टोकन पते की पुष्टि करें!", - "add_token_disclaimer_check": "मैंने एक प्रतिष्ठित स्रोत का उपयोग करके टोकन अनुबंध पते और जानकारी की पुष्टि की है। दुर्भावनापूर्ण या गलत जानकारी जोड़ने से धन की हानि हो सकती है।", - "token_contract_address": "टोकन अनुबंध पता", - "token_name": "टोकन नाम जैसे: टीथर", - "token_symbol": "टोकन प्रतीक जैसे: यूएसडीटी", - "token_decimal": "सांकेतिक दशमलव", - "field_required": "यह फ़ील्ड आवश्यक है", - "pin_at_top": "शीर्ष पर ${token} पिन करें", - "invalid_input": "अमान्य निवेश", - "fiat_balance": "फिएट बैलेंस", - "gross_balance": "सकल संतुलन", - "alphabetical": "वर्णमाला", - "generate_name": "नाम जनरेट करें", - "balance_page": "बैलेंस पेज", - "share": "शेयर करना", - "slidable": "फिसलने लायक", - "manage_nodes": "नोड्स प्रबंधित करें", - "etherscan_history": "इथरस्कैन इतिहास", - "template_name": "टेम्पलेट नाम", + "bitcoin_payments_require_1_confirmation": "बिटकॉइन भुगतान के लिए 1 पुष्टिकरण की आवश्यकता होती है, जिसमें 20 मिनट या अधिक समय लग सकता है। आपके धैर्य के लिए धन्यवाद! भुगतान की पुष्टि होने पर आपको ईमेल किया जाएगा।", + "Blocks_remaining": "${status} शेष रहते हैं", + "bright_theme": "उज्ज्वल", + "buy": "खरीदें", + "buy_alert_content": "वर्तमान में हम केवल बिटकॉइन, एथेरियम, लाइटकॉइन और मोनेरो की खरीद का समर्थन करते हैं। कृपया अपना बिटकॉइन, एथेरियम, लाइटकॉइन, या मोनेरो वॉलेट बनाएं या उस पर स्विच करें।", + "buy_bitcoin": "बिटकॉइन खरीदें", + "buy_provider_unavailable": "वर्तमान में प्रदाता अनुपलब्ध है।", + "buy_with": "के साथ खरीदें", + "by_cake_pay": "केकपे द्वारा", + "cake_2fa_preset": "केक 2एफए प्रीसेट", + "cake_pay_account_note": "कार्ड देखने और खरीदने के लिए केवल एक ईमेल पते के साथ साइन अप करें। कुछ छूट पर भी उपलब्ध हैं!", + "cake_pay_learn_more": "ऐप में उपहार कार्ड तुरंत खरीदें और रिडीम करें!\nअधिक जानने के लिए बाएं से दाएं स्वाइप करें।", + "cake_pay_subtitle": "रियायती उपहार कार्ड खरीदें (केवल यूएसए)", + "cake_pay_title": "केक पे गिफ्ट कार्ड्स", + "cake_pay_web_cards_subtitle": "दुनिया भर में प्रीपेड कार्ड और गिफ्ट कार्ड खरीदें", + "cake_pay_web_cards_title": "केक भुगतान वेब कार्ड", + "cake_wallet": "Cake Wallet", + "cakepay_prepaid_card": "केकपे प्रीपेड डेबिट कार्ड", + "camera_consent": "आपके कैमरे का उपयोग ${provider} द्वारा पहचान उद्देश्यों के लिए एक छवि कैप्चर करने के लिए किया जाएगा। विवरण के लिए कृपया उनकी गोपनीयता नीति जांचें।", + "camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।", + "cancel": "रद्द करना", + "card_address": "पता:", + "cardholder_agreement": "कार्डधारक अनुबंध", + "cards": "कार्ड", + "chains": "चेन", + "change": "परिवर्तन", + "change_backup_password_alert": "आपकी पिछली बैकअप फाइलें नए बैकअप पासवर्ड के साथ आयात करने के लिए उपलब्ध नहीं होंगी। नए बैकअप पासवर्ड का उपयोग केवल नई बैकअप फ़ाइलों के लिए किया जाएगा। क्या आप वाकई बैकअप पासवर्ड बदलना चाहते हैं?", + "change_currency": "मुद्रा परिवर्तन करें", + "change_current_node": "क्या आप वर्तमान नोड को बदलना सुनिश्चित करते हैं ${node}?", + "change_current_node_title": "वर्तमान नोड बदलें", + "change_exchange_provider": "एक्सचेंज प्रदाता बदलें", + "change_language": "भाषा बदलो", + "change_language_to": "को भाषा बदलें ${language}?", + "change_password": "पासवर्ड बदलें", "change_rep": "प्रतिनिधि बदलें", "change_rep_message": "क्या आप वाकई प्रतिनिधियों को बदलना चाहते हैं?", - "unsupported_asset": "हम इस संपत्ति के लिए इस कार्रवाई का समर्थन नहीं करते हैं. कृपया समर्थित परिसंपत्ति प्रकार का वॉलेट बनाएं या उस पर स्विच करें।", - "manage_pow_nodes": "PoW नोड्स प्रबंधित करें", - "support_title_live_chat": "लाइव सहायता", - "support_description_live_chat": "मुक्त और तेजी से! प्रशिक्षित सहायता प्रतिनिधि सहायता के लिए उपलब्ध हैं", - "support_title_guides": "केक वॉलेट गाइड", - "support_description_guides": "सामान्य मुद्दों के लिए प्रलेखन और समर्थन", - "support_title_other_links": "अन्य समर्थन लिंक", - "support_description_other_links": "हमारे समुदायों में शामिल हों या अन्य तरीकों के माध्यम से हमारे साथी तक पहुंचें", + "change_rep_successful": "सफलतापूर्वक बदलकर प्रतिनिधि", + "change_wallet_alert_content": "क्या आप करंट वॉलेट को बदलना चाहते हैं ${wallet_name}?", + "change_wallet_alert_title": "वर्तमान बटुआ बदलें", + "choose_account": "खाता चुनें", + "choose_address": "\n\nकृपया पता चुनें:", "choose_derivation": "वॉलेट व्युत्पत्ति चुनें", - "new_first_wallet_text": "आसानी से अपनी क्रिप्टोक्यूरेंसी को सुरक्षित रखें", - "select_destination": "कृपया बैकअप फ़ाइल के लिए गंतव्य का चयन करें।", - "save_to_downloads": "डाउनलोड में सहेजें", - "select_buy_provider_notice": "ऊपर एक खरीद प्रदाता का चयन करें। आप इस स्क्रीन को ऐप सेटिंग्स में अपना डिफ़ॉल्ट बाय प्रदाता सेट करके छोड़ सकते हैं।", - "onramper_option_description": "जल्दी से कई भुगतान विधियों के साथ क्रिप्टो खरीदें। अधिकांश देशों में उपलब्ध है। फैलता है और फीस अलग -अलग होती है।", + "choose_from_available_options": "उपलब्ध विकल्पों में से चुनें:", + "choose_one": "एक का चयन", + "choose_relay": "कृपया उपयोग करने के लिए एक रिले चुनें", + "choose_wallet_currency": "कृपया बटुआ मुद्रा चुनें:", + "clear": "स्पष्ट", + "clearnet_link": "क्लियरनेट लिंक", + "close": "बंद करना", + "coin_control": "सिक्का नियंत्रण (वैकल्पिक)", + "cold_or_recover_wallet": "कोल्ड वॉलेट जोड़ें या पेपर वॉलेट पुनर्प्राप्त करें", + "color_theme": "रंग विषय", + "commit_transaction_amount_fee": "लेन-देन करें\nरकम: ${amount}\nशुल्क: ${fee}", + "confirm": "की पुष्टि करें", + "confirm_delete_template": "यह क्रिया इस टेम्पलेट को हटा देगी। क्या आप जारी रखना चाहते हैं?", + "confirm_delete_wallet": "यह क्रिया इस वॉलेट को हटा देगी। क्या आप जारी रखना चाहते हैं?", + "confirm_sending": "भेजने की पुष्टि करें", + "confirmations": "पुष्टिकरण", + "confirmed": "पुष्टि की गई शेष राशिी", + "confirmed_tx": "की पुष्टि", + "congratulations": "बधाई!", + "connect_an_existing_yat": "मौजूदा Yat कनेक्ट करें", + "connect_yats": "कनेक्ट Yats", + "connection_sync": "कनेक्शन और सिंक", + "connectWalletPrompt": "लेन-देन करने के लिए अपने वॉलेट को वॉलेटकनेक्ट से कनेक्ट करें", + "contact": "संपर्क करें", + "contact_list_contacts": "संपर्क", + "contact_list_wallets": "मेरा बटुआ", + "contact_name": "संपर्क नाम", + "contact_support": "सहायता से संपर्क करें", + "continue_text": "जारी रहना", + "contractName": "अनुबंध का नाम", + "contractSymbol": "अनुबंध चिह्न", + "copied_key_to_clipboard": "की नकल की ${key} क्लिपबोर्ड पर", + "copied_to_clipboard": "क्लिपबोर्ड पर नकल", + "copy": "प्रतिलिपि", + "copy_address": "पता कॉपी करें", + "copy_id": "प्रतिलिपि ID", + "copyWalletConnectLink": "dApp से वॉलेटकनेक्ट लिंक को कॉपी करें और यहां पेस्ट करें", + "create_account": "खाता बनाएं", + "create_backup": "बैकअप बनाएँ", + "create_donation_link": "दान लिंक बनाएं", + "create_invoice": "इनवॉयस बनाएँ", + "create_new": "नया बटुआ बनाएँ", + "create_new_account": "नया खाता बनाएँ", + "creating_new_wallet": "नया बटुआ बनाना", + "creating_new_wallet_error": "त्रुटि: ${description}", + "creation_date": "निर्माण तिथि", + "custom": "कस्टम", + "custom_drag": "कस्टम (पकड़ और खींचें)", + "custom_redeem_amount": "कस्टम रिडीम राशि", + "dark_theme": "अंधेरा", + "debit_card": "डेबिट कार्ड", + "debit_card_terms": "इस डिजिटल वॉलेट में आपके भुगतान कार्ड नंबर (और आपके भुगतान कार्ड नंबर से संबंधित क्रेडेंशियल) का भंडारण और उपयोग भुगतान कार्ड जारीकर्ता के साथ लागू कार्डधारक समझौते के नियमों और शर्तों के अधीन है, जैसा कि प्रभावी है समय - समय पर।", + "decimal_places_error": "बहुत अधिक दशमलव स्थान", "default_buy_provider": "डिफ़ॉल्ट खरीद प्रदाता", - "ask_each_time": "हर बार पूछें", - "buy_provider_unavailable": "वर्तमान में प्रदाता अनुपलब्ध है।", - "signTransaction": "लेन-देन पर हस्ताक्षर करें", + "default_sell_provider": "डिफ़ॉल्ट विक्रय प्रदाता", + "delete": "हटाएं", + "delete_account": "खाता हटाएं", + "delete_wallet": "वॉलेट हटाएं", + "delete_wallet_confirm_message": "क्या आप वाकई ${wallet_name} वॉलेट हटाना चाहते हैं?", + "deleteConnectionConfirmationPrompt": "क्या आप वाकई कनेक्शन हटाना चाहते हैं?", + "descending": "अवरोही", + "description": "विवरण", + "destination_tag": "गंतव्य टैग:", + "dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। अतिरिक्त केवाईसी के बिना 990€ तक। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए", + "didnt_get_code": "कोड नहीं मिला?", + "digit_pin": "-अंक पिन", + "digital_and_physical_card": "डिजिटल और भौतिक प्रीपेड डेबिट कार्ड", + "disable": "अक्षम करना", + "disable_buy": "खरीद कार्रवाई अक्षम करें", + "disable_cake_2fa": "केक 2FA अक्षम करें", + "disable_exchange": "एक्सचेंज अक्षम करें", + "disable_fiat": "िएट को अक्षम करें", + "disable_sell": "बेचने की कार्रवाई अक्षम करें", + "disabled": "अक्षम", + "discount": "${value}% बचाएं", + "display_settings": "प्रदर्शन सेटिंग्स", + "displayable": "प्रदर्शन योग्य", + "do_not_have_enough_gas_asset": "वर्तमान ब्लॉकचेन नेटवर्क स्थितियों में लेनदेन करने के लिए आपके पास पर्याप्त ${currency} नहीं है। ब्लॉकचेन नेटवर्क शुल्क का भुगतान करने के लिए आपको अधिक ${currency} की आवश्यकता है, भले ही आप एक अलग संपत्ति भेज रहे हों।", + "do_not_send": "मत भेजो", + "do_not_share_warning_text": "समर्थन सहित, इन्हें किसी और के साथ साझा न करें।\n\nआपके धन की चोरी हो सकती है और होगी!", + "do_not_show_me": "मुझे यह फिर न दिखाएं", + "domain_looks_up": "डोमेन लुकअप", + "donation_link_details": "दान लिंक विवरण", + "e_sign_consent": "ई-साइन सहमति", + "edit": "संपादित करें", + "edit_backup_password": "बैकअप पासवर्ड संपादित करें", + "edit_node": "नोड संपादित करें", + "edit_token": "टोकन संपादित करें", + "electrum_address_disclaimer": "हर बार जब आप एक का उपयोग करते हैं तो हम नए पते उत्पन्न करते हैं, लेकिन पिछले पते काम करना जारी रखते हैं", + "email_address": "ईमेल पता", + "enabled": "सक्रिय", + "enter_amount": "राशि दर्ज करें", + "enter_backup_password": "यहां बैकअप पासवर्ड डालें", + "enter_code": "कोड दर्ज करें", + "enter_seed_phrase": "अपना बीज वाक्यांश दर्ज करें", + "enter_totp_code": "कृपया TOTP कोड दर्ज करें।", + "enter_your_note": "अपना नोट दर्ज करें ...", + "enter_your_pin": "अपना पिन दर्ज करो", + "enter_your_pin_again": "फिर से अपना पिन डालें", + "enterTokenID": "टोकन आईडी दर्ज करें", + "enterWalletConnectURI": "वॉलेटकनेक्ट यूआरआई दर्ज करें", + "error": "त्रुटि", + "error_dialog_content": "ओह, हमसे कुछ गड़बड़ी हुई है.\n\nएप्लिकेशन को बेहतर बनाने के लिए कृपया क्रैश रिपोर्ट हमारी सहायता टीम को भेजें।", + "error_text_account_name": "खाता नाम में केवल अक्षर, संख्याएं हो सकती हैं\nऔर 1 और 15 वर्णों के बीच लंबा होना चाहिए", + "error_text_address": "वॉलेट पता प्रकार के अनुरूप होना चाहिए\nक्रिप्टोकरेंसी का", + "error_text_amount": "राशि में केवल संख्याएँ हो सकती हैं", + "error_text_contact_name": "संपर्क नाम शामिल नहीं हो सकता ` , ' \" प्रतीकों\nऔर 1 और 32 वर्णों के बीच लंबा होना चाहिए", + "error_text_crypto_currency": "अंश अंकों की संख्या\n12 से कम या इसके बराबर होना चाहिए", + "error_text_fiat": "राशि का मूल्य उपलब्ध शेष राशि से अधिक नहीं हो सकता.\nअंश अंकों की संख्या कम या 2 के बराबर होनी चाहिए", + "error_text_input_above_maximum_limit": "राशि अधिकतम से अधिक है", + "error_text_input_below_minimum_limit": "राशि न्यूनतम से कम है", + "error_text_keys": "वॉलेट कीज़ में हेक्स में केवल 64 वर्ण हो सकते हैं", + "error_text_limits_loading_failed": "व्यापार ${provider} के लिए नहीं बनाया गया है। लोडिंग की सीमाएं विफल रहीं", + "error_text_maximum_limit": "व्यापार ${provider} के लिए नहीं बनाया गया है। राशि अधिक है तो अधिकतम: ${max} ${currency}", + "error_text_minimal_limit": "व्यापार ${provider} के लिए नहीं बनाया गया है। राशि कम है तो न्यूनतम: ${min} ${currency}", + "error_text_node_address": "कृपया एक IPv4 पता दर्ज करें", + "error_text_node_port": "नोड पोर्ट में केवल 0 और 65535 के बीच संख्याएँ हो सकती हैं", + "error_text_node_proxy_address": "कृपया दर्ज करें: <पोर्ट>, उदाहरण के लिए 127.0.0.1:9050", + "error_text_payment_id": "पेमेंट आईडी केवल हेक्स में 16 से 64 चार्ट तक हो सकती है", + "error_text_subaddress_name": "सबड्रेस नाम नहीं हो सकता` , ' \" प्रतीकों\nऔर 1 और 20 वर्णों के बीच लंबा होना चाहिए", + "error_text_template": "टेम्प्लेट का नाम और पता नहीं हो सकता ` , ' \" प्रतीकों\nऔर 1 और 106 वर्णों के बीच लंबा होना चाहिए", + "error_text_wallet_name": "वॉलेट नाम में केवल अक्षर, संख्याएं, _ - प्रतीक हो सकते हैं\nऔर 1 और 33 वर्णों के बीच लंबा होना चाहिए", + "error_text_xmr": "एक्सएमआर मूल्य उपलब्ध शेष राशि से अधिक नहीं हो सकता.\nअंश अंकों की संख्या 12 से कम या इसके बराबर होनी चाहिए", "errorGettingCredentials": "विफल: क्रेडेंशियल प्राप्त करते समय त्रुटि", "errorSigningTransaction": "लेन-देन पर हस्ताक्षर करते समय एक त्रुटि उत्पन्न हुई है", - "pairingInvalidEvent": "अमान्य ईवेंट युग्मित करना", - "chains": "चेन", - "methods": "तरीकों", - "events": "आयोजन", - "reject": "अस्वीकार करना", - "approve": "मंज़ूरी देना", - "expiresOn": "पर समय सीमा समाप्त", - "walletConnect": "वॉलेटकनेक्ट", - "nullURIError": "यूआरआई शून्य है", - "connectWalletPrompt": "लेन-देन करने के लिए अपने वॉलेट को वॉलेटकनेक्ट से कनेक्ट करें", - "newConnection": "नया कनेक्शन", - "activeConnectionsPrompt": "सक्रिय कनेक्शन यहां दिखाई देंगे", - "deleteConnectionConfirmationPrompt": "क्या आप वाकई कनेक्शन हटाना चाहते हैं?", + "estimated": "अनुमानित", + "etherscan_history": "इथरस्कैन इतिहास", "event": "आयोजन", - "successful": "सफल", - "wouoldLikeToConnect": "जुड़ना चाहेंगे", - "message": "संदेश", - "do_not_have_enough_gas_asset": "वर्तमान ब्लॉकचेन नेटवर्क स्थितियों में लेनदेन करने के लिए आपके पास पर्याप्त ${currency} नहीं है। ब्लॉकचेन नेटवर्क शुल्क का भुगतान करने के लिए आपको अधिक ${currency} की आवश्यकता है, भले ही आप एक अलग संपत्ति भेज रहे हों।", - "totp_auth_url": "TOTP प्रामाणिक यूआरएल", - "awaitDAppProcessing": "कृपया डीएपी की प्रोसेसिंग पूरी होने तक प्रतीक्षा करें।", - "copyWalletConnectLink": "dApp से वॉलेटकनेक्ट लिंक को कॉपी करें और यहां पेस्ट करें", - "enterWalletConnectURI": "वॉलेटकनेक्ट यूआरआई दर्ज करें", - "seed_key": "बीज कुंजी", - "enter_seed_phrase": "अपना बीज वाक्यांश दर्ज करें", - "change_rep_successful": "सफलतापूर्वक बदलकर प्रतिनिधि", - "add_contact": "संपर्क जोड़ें", + "events": "आयोजन", + "exchange": "अदला बदली", + "exchange_incorrect_current_wallet_for_xmr": "यदि आप अपने केक वॉलेट मोनेरो बैलेंस से एक्सएमआर का आदान-प्रदान करना चाहते हैं, तो कृपया अपने मोनेरो वॉलेट में जाएं।", + "exchange_new_template": "नया टेम्पलेट", "exchange_provider_unsupported": "${providerName} अब समर्थित नहीं है!", - "domain_looks_up": "डोमेन लुकअप", - "require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है", - "camera_permission_is_required": "कैमरे की अनुमति आवश्यक है.\nकृपया इसे ऐप सेटिंग से सक्षम करें।", - "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें", - "order_by": "द्वारा आदेश", - "creation_date": "निर्माण तिथि", + "exchange_result_confirm": "पुष्टि दबाकर, आप भेज रहे होंगे ${fetchingLabel} ${from} अपने बटुए से ${walletName} नीचे दिखाए गए पते पर। या आप अपने बाहरी वॉलेट से नीचे के पते पर भेज सकते हैं / क्यूआर कोड पर भेज सकते हैं।\n\nकृपया जारी रखने या राशि बदलने के लिए वापस जाने के लिए पुष्टि करें दबाएं.", + "exchange_result_description": "आपको अगले पृष्ठ पर दिखाए गए पते पर न्यूनतम ${fetchingLabel} ${from} भेजना होगा। यदि आप ${fetchingLabel} ${from} से कम राशि भेजते हैं तो यह परिवर्तित नहीं हो सकती है और इसे वापस नहीं किया जा सकता है।", + "exchange_result_write_down_ID": "*कृपया ऊपर दिखाए गए अपने ID को कॉपी या लिख लें.", + "exchange_result_write_down_trade_id": "जारी रखने के लिए कृपया ट्रेड ID की प्रतिलिपि बनाएँ या लिखें.", + "exchange_sync_alert_content": "कृपया प्रतीक्षा करें जब तक आपका बटुआ सिंक्रनाइज़ नहीं किया जाता है", + "expired": "समय सीमा समाप्त", + "expires": "समाप्त हो जाता है", + "expiresOn": "पर समय सीमा समाप्त", + "export_backup": "निर्यात बैकअप", + "extra_id": "अतिरिक्त आईडी:", + "extracted_address_content": "आपको धनराशि भेजी जाएगी\n${recipient_name}", + "failed_authentication": "प्रमाणीकरण विफल. ${state_error}", + "faq": "FAQ", + "fetching": "ला रहा है", + "fiat_api": "फिएट पैसे API", + "fiat_balance": "फिएट बैलेंस", + "field_required": "यह फ़ील्ड आवश्यक है", + "fill_code": "कृपया अपने ईमेल पर प्रदान किया गया सत्यापन कोड भरें", + "filter_by": "के द्वारा छनित", + "first_wallet_text": "Monero, Bitcoin, Ethereum, Litecoin, और Haven के लिए बहुत बढ़िया बटुआ", + "fixed_pair_not_supported": "यह निश्चित जोड़ी चयनित एक्सचेंजों के साथ समर्थित नहीं है", + "fixed_rate": "निर्धारित दर", + "fixed_rate_alert": "फिक्स्ड रेट मोड की जांच करने पर आप प्राप्त राशि दर्ज कर पाएंगे। क्या आप निश्चित दर मोड पर स्विच करना चाहते हैं?", + "forgot_password": "पासवर्ड भूल गए", + "freeze": "फ्रीज", + "frequently_asked_questions": "अक्सर पूछे जाने वाले प्रश्न", + "frozen": "जमा हुआ", + "full_balance": "पूर्ण संतुलन", + "generate_name": "नाम जनरेट करें", + "generating_gift_card": "गिफ्ट कार्ड जनरेट कर रहा है", + "get_a": "एक प्राप्त करें", + "get_card_note": " कि आप डिजिटल मुद्राओं के साथ पुनः लोड कर सकते हैं। कोई अतिरिक्त जानकारी की आवश्यकता नहीं है!", + "get_your_yat": "अपना प्राप्त करें Yat", + "gift_card_amount": "गिफ्ट कार्ड राशि", + "gift_card_balance_note": "गिफ्ट कार्ड शेष राशि के साथ यहां दिखाई देंगे", + "gift_card_is_generated": "गिफ्ट कार्ड जनरेट हुआ", + "gift_card_number": "गिफ्ट कार्ड नंबर", + "gift_card_redeemed_note": "आपके द्वारा भुनाए गए उपहार कार्ड यहां दिखाई देंगे", + "gift_cards": "उपहार कार्ड", + "gift_cards_unavailable": "उपहार कार्ड इस समय केवल मोनेरो, बिटकॉइन और लिटकोइन के माध्यम से खरीदने के लिए उपलब्ध हैं", + "got_it": "समझ गया", + "gross_balance": "सकल संतुलन", "group_by_type": "प्रकार द्वारा समूह", - "importNFTs": "एनएफटी आयात करें", - "noNFTYet": "अभी तक कोई एनएफटी नहीं", - "address": "पता", - "enterTokenID": "टोकन आईडी दर्ज करें", - "tokenID": "पहचान", - "name": "नाम", - "symbol": "प्रतीक", - "seed_phrase_length": "बीज वाक्यांश की लंबाई", - "unavailable_balance": "अनुपलब्ध शेष", - "unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।", - "unspent_change": "परिवर्तन", - "tor_connection": "टोर कनेक्शन", - "setup_warning_2fa_text": "केक 2एफए वॉलेट में कुछ कार्यों के लिए दूसरा प्रमाणीकरण है। यह कोल्ड स्टोरेज जितना सुरक्षित नहीं है।\n\nयदि आप अपने 2एफए ऐप या टीओटीपी कुंजियों तक पहुंच खो देते हैं, तो आप इस वॉलेट तक पहुंच खो देंगे। आपको अपने बटुए को स्मरक बीज से पुनर्स्थापित करने की आवश्यकता होगी।\n\nयदि आप अपने 2एफए या निमोनिक बीजों तक पहुंच खो देते हैं तो केक समर्थन आपकी सहायता करने में असमर्थ होगा।\nकेक 2एफए का उपयोग करने से पहले, हम गाइड को पढ़ने की सलाह देते हैं।", - "scan_qr_on_device": "इस QR कोड को किसी अन्य डिवाइस पर स्कैन करें", + "haven_app": "Haven by Cake Wallet", + "haven_app_wallet_text": "Awesome wallet for Haven", + "help": "मदद करना", + "hidden_balance": "छिपा हुआ संतुलन", + "hide_details": "विवरण छुपाएं", + "high_contrast_theme": "उच्च कंट्रास्ट थीम", + "home_screen_settings": "होम स्क्रीन सेटिंग्स", "how_to_use": "का उपयोग कैसे करें", + "how_to_use_card": "इस कार्ड का उपयोग कैसे करें", + "id": "ID: ", + "ignor": "नज़रअंदाज़ करना", + "import": "आयात", + "importNFTs": "एनएफटी आयात करें", + "in_store": "स्टोर में", + "incoming": "आने वाली", + "incorrect_seed": "दर्ज किया गया पाठ मान्य नहीं है।", + "introducing_cake_pay": "परिचय Cake Pay!", + "invalid_input": "अमान्य निवेश", + "invoice_details": "चालान विवरण", + "is_percentage": "है", + "last_30_days": "पिछले 30 दिन", + "learn_more": "और अधिक जानें", + "light_theme": "रोशनी", + "loading_your_wallet": "अपना बटुआ लोड कर रहा है", + "login": "लॉग इन करें", + "logout": "लॉगआउट", + "low_fee": "कम शुल्क", + "low_fee_alert": "आप वर्तमान में कम नेटवर्क शुल्क प्राथमिकता का उपयोग कर रहे हैं। यह लंबे इंतजार, अलग-अलग दरों या रद्द किए गए ट्रेडों का कारण बन सकता है। हम बेहतर अनुभव के लिए अधिक शुल्क निर्धारित करने की सलाह देते हैं।", + "manage_nodes": "नोड्स प्रबंधित करें", + "manage_pow_nodes": "PoW नोड्स प्रबंधित करें", + "manage_yats": "Yats प्रबंधित करें", + "mark_as_redeemed": "रिडीम किए गए के रूप में चिह्नित करें", + "market_place": "मार्केटप्लेस", + "matrix_green_dark_theme": "मैट्रिक्स ग्रीन डार्क थीम", + "max_amount": "अधिकतम: ${value}", + "max_value": "मैक्स: ${value} ${currency}", + "memo": "ज्ञापन:", + "message": "संदेश", + "methods": "तरीकों", + "min_amount": "न्यूनतम: ${value}", + "min_value": "मिन: ${value} ${currency}", + "minutes_to_pin_code": "${minute} मिनट", + "mm": "एमएम", + "modify_2fa": "केक 2FA संशोधित करें", + "monero_com": "Monero.com by Cake Wallet", + "monero_com_wallet_text": "Awesome wallet for Monero", + "monero_dark_theme": "मोनेरो डार्क थीम", + "monero_light_theme": "मोनेरो लाइट थीम", + "moonpay_alert_text": "राशि का मूल्य अधिक है या करने के लिए बराबर होना चाहिए ${minAmount} ${fiatCurrency}", + "more_options": "और विकल्प", + "name": "नाम", + "narrow": "सँकरा", + "new_first_wallet_text": "आसानी से अपनी क्रिप्टोक्यूरेंसी को सुरक्षित रखें", + "new_node_testing": "नई नोड परीक्षण", + "new_subaddress_create": "सर्जन करना", + "new_subaddress_label_name": "लेबल का नाम", + "new_subaddress_title": "नया पता", + "new_template": "नया टेम्पलेट", + "new_wallet": "नया बटुआ", + "newConnection": "नया कनेक्शन", + "no_id_needed": "कोई आईडी नहीं चाहिए!", + "no_id_required": "कोई आईडी आवश्यक नहीं है। टॉप अप करें और कहीं भी खर्च करें", + "no_relay_on_domain": "उपयोगकर्ता के डोमेन के लिए कोई रिले नहीं है या रिले अनुपलब्ध है। कृपया उपयोग करने के लिए एक रिले चुनें।", + "no_relays": "कोई रिले नहीं", + "no_relays_message": "हमें इस उपयोगकर्ता के लिए एक Nostr NIP-05 रिकॉर्ड मिला, लेकिन इसमें कोई रिले नहीं है। कृपया प्राप्तकर्ता को अपने नॉस्ट्र रिकॉर्ड में रिले जोड़ने का निर्देश दें।", + "node_address": "नोड पता", + "node_connection_failed": "कनेक्शन विफल रहा", + "node_connection_successful": "कनेक्शन सफल रहा", + "node_new": "नया नोड", + "node_port": "नोड पोर्ट", + "node_reset_settings_title": "सेटिंग्स को दुबारा करें", + "node_test": "परीक्षा", + "nodes": "नोड्स", + "nodes_list_reset_to_default_message": "क्या आप वाकई सेटिंग को डिफ़ॉल्ट पर रीसेट करना चाहते हैं?", + "none_of_selected_providers_can_exchange": "चयनित प्रदाताओं में से कोई भी इस एक्सचेंज को नहीं बना सकता", + "noNFTYet": "अभी तक कोई एनएफटी नहीं", + "normal": "सामान्य", + "note_optional": "नोट (वैकल्पिक)", + "note_tap_to_change": "नोट (टैप टू चेंज)", + "nullURIError": "यूआरआई शून्य है", + "offer_expires_in": "में ऑफर समाप्त हो रहा है: ", + "offline": "ऑफ़लाइन", + "ok": "ठीक है", + "onion_link": "प्याज का लिंक", + "online": "ऑनलाइन", + "onramper_option_description": "जल्दी से कई भुगतान विधियों के साथ क्रिप्टो खरीदें। अधिकांश देशों में उपलब्ध है। फैलता है और फीस अलग -अलग होती है।", + "open_gift_card": "गिफ्ट कार्ड खोलें", + "optional_description": "वैकल्पिक विवरण", + "optional_email_hint": "वैकल्पिक प्राप्तकर्ता सूचना ईमेल", + "optional_name": "वैकल्पिक प्राप्तकर्ता नाम", + "optionally_order_card": "वैकल्पिक रूप से एक भौतिक कार्ड ऑर्डर करें।", + "orbot_running_alert": "कृपया सुनिश्चित करें कि इस नोड से कनेक्ट करने से पहले Orbot चल रहा है।", + "order_by": "द्वारा आदेश", + "order_id": "ऑर्डर आईडी", + "order_physical_card": "फिजिकल कार्ड ऑर्डर करें", + "other_settings": "अन्य सेटिंग्स", + "outdated_electrum_wallet_description": "केक में बनाए गए नए बिटकॉइन वॉलेट में अब 24-शब्द का बीज है। यह अनिवार्य है कि आप एक नया बिटकॉइन वॉलेट बनाएं और अपने सभी फंड को नए 24-शब्द वाले वॉलेट में स्थानांतरित करें, और 12-शब्द बीज वाले वॉलेट का उपयोग करना बंद करें। कृपया अपने धन को सुरक्षित करने के लिए इसे तुरंत करें।", + "outdated_electrum_wallet_receive_warning": "अगर इस वॉलेट में 12 शब्दों का बीज है और इसे केक में बनाया गया है, तो इस वॉलेट में बिटकॉइन जमा न करें। इस वॉलेट में स्थानांतरित किया गया कोई भी बीटीसी खो सकता है। एक नया 24-शब्द वॉलेट बनाएं (ऊपर दाईं ओर स्थित मेनू पर टैप करें, वॉलेट चुनें, नया वॉलेट बनाएं चुनें, फिर बिटकॉइन चुनें) और तुरंत अपना बीटीसी वहां ले जाएं। केक से नए (24-शब्द) बीटीसी वॉलेट सुरक्षित हैं", + "outgoing": "निवर्तमान", + "overwrite_amount": "Overwrite amount", + "pairingInvalidEvent": "अमान्य ईवेंट युग्मित करना", + "password": "पारण शब्द", + "paste": "पेस्ट करें", + "pause_wallet_creation": "हेवन वॉलेट बनाने की क्षमता फिलहाल रुकी हुई है।", + "payment_id": "भुगतान ID: ", + "Payment_was_received": "आपका भुगतान प्राप्त हो गया था।", + "pending": " (अपूर्ण)", + "percentageOf": "${amount} का", + "pin_at_top": "शीर्ष पर ${token} पिन करें", + "pin_is_incorrect": "पिन गलत है", + "pin_number": "पिन नंबर", + "placeholder_contacts": "आपके संपर्क यहां प्रदर्शित होंगे", + "placeholder_transactions": "आपके लेनदेन यहां प्रदर्शित होंगे", + "please_fill_totp": "कृपया अपने दूसरे डिवाइस पर मौजूद 8 अंकों का कोड भरें", + "please_make_selection": "कृपया नीचे चयन करें अपना बटुआ बनाएं या पुनर्प्राप्त करें.", + "please_reference_document": "कृपया अधिक जानकारी के लिए नीचे दिए गए दस्तावेज़ देखें।", + "please_select": "कृपया चुने:", + "please_select_backup_file": "कृपया बैकअप फ़ाइल चुनें और बैकअप पासवर्ड डालें।", + "please_try_to_connect_to_another_node": "कृपया दूसरे नोड से कनेक्ट करने का प्रयास करें", + "please_wait": "कृपया प्रतीक्षा करें", + "polygonscan_history": "पॉलीगॉनस्कैन इतिहास", + "powered_by": "द्वारा संचालित ${title}", + "pre_seed_button_text": "मै समझता हुँ। मुझे अपना बीज दिखाओ", + "pre_seed_description": "अगले पेज पर आपको ${words} शब्दों की एक श्रृंखला दिखाई देगी। यह आपका अद्वितीय और निजी बीज है और नुकसान या खराबी के मामले में अपने बटुए को पुनर्प्राप्त करने का एकमात्र तरीका है। यह आपकी जिम्मेदारी है कि इसे नीचे लिखें और इसे Cake Wallet ऐप के बाहर सुरक्षित स्थान पर संग्रहीत करें।", + "pre_seed_title": "महत्वपूर्ण", + "prevent_screenshots": "स्क्रीनशॉट और स्क्रीन रिकॉर्डिंग रोकें", + "privacy": "गोपनीयता", + "privacy_policy": "गोपनीयता नीति", + "privacy_settings": "गोपनीयता सेटिंग्स", + "private_key": "निजी चाबी", + "proceed_after_one_minute": "यदि 1 मिनट के बाद भी स्क्रीन आगे नहीं बढ़ती है, तो अपना ईमेल देखें।", + "profile": "प्रोफ़ाइल", + "provider_error": "${provider} त्रुटि", + "public_key": "सार्वजनिक कुंजी", + "purchase_gift_card": "गिफ्ट कार्ड खरीदें", + "qr_fullscreen": "फ़ुल स्क्रीन क्यूआर कोड खोलने के लिए टैप करें", + "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", + "question_to_disable_2fa": "क्या आप सुनिश्चित हैं कि आप Cake 2FA को अक्षम करना चाहते हैं? वॉलेट और कुछ कार्यों तक पहुँचने के लिए अब 2FA कोड की आवश्यकता नहीं होगी।", + "ready_have_account": "क्या आपके पास पहले से ही एक खाता है?", + "receivable_balance": "प्राप्य शेष", + "receive": "प्राप्त करना", + "receive_amount": "रकम", + "received": "प्राप्त किया", + "recipient_address": "प्राप्तकर्ता का पता", + "reconnect": "रिकनेक्ट", + "reconnect_alert_text": "क्या आप पुन: कनेक्ट होना सुनिश्चित करते हैं?", + "reconnection": "पुनर्संयोजन", + "redeemed": "रिडीम किया गया", + "refund_address": "वापसी का पता", + "reject": "अस्वीकार करना", + "remaining": "शेष", + "remove": "हटाना", + "remove_node": "नोड निकालें", + "remove_node_message": "क्या आप वाकई चयनित नोड को निकालना चाहते हैं?", + "rename": "नाम बदलें", + "require_for_adding_contacts": "संपर्क जोड़ने के लिए आवश्यकता है", + "require_for_all_security_and_backup_settings": "सभी सुरक्षा और बैकअप सेटिंग्स की आवश्यकता है", + "require_for_assessing_wallet": "वॉलेट तक पहुँचने के लिए आवश्यकता है", + "require_for_creating_new_wallets": "नए वॉलेट बनाने की आवश्यकता है", + "require_for_exchanges_to_external_wallets": "बाहरी वॉलेट में एक्सचेंज की आवश्यकता है", + "require_for_exchanges_to_internal_wallets": "आंतरिक वॉलेट में आदान-प्रदान की आवश्यकता है", + "require_for_sends_to_contacts": "संपर्कों को भेजने के लिए आवश्यक है", + "require_for_sends_to_internal_wallets": "आंतरिक वॉलेट में भेजने की आवश्यकता है", + "require_for_sends_to_non_contacts": "गैर-संपर्कों को भेजने की आवश्यकता", + "require_pin_after": "इसके बाद पिन आवश्यक है", + "rescan": "पुन: स्कैन", + "resend_code": "कृपया इसे फिर से भेजें", + "reset": "रीसेट", + "reset_password": "पासवर्ड रीसेट करें", + "restore_active_seed": "सक्रिय बीज", + "restore_address": "पता", + "restore_bitcoin_description_from_keys": "अपने निजी कुंजी से उत्पन्न WIF स्ट्रिंग से अपने वॉलेट को पुनर्स्थापित करें", + "restore_bitcoin_description_from_seed": "24 शब्द संयोजन कोड से अपने वॉलेट को पुनर्स्थापित करें", + "restore_bitcoin_title_from_keys": "WIF से पुनर्स्थापित करें", + "restore_description_from_backup": "आप से पूरे केक वॉलेट एप्लिकेशन को पुनर्स्थापित कर सकते हैं आपकी बैक-अप फ़ाइल", + "restore_description_from_keys": "अपने वॉलेट को जेनरेट से पुनर्स्थापित करें आपकी निजी कुंजी से कीस्ट्रोक्स सहेजे गए", + "restore_description_from_seed": "या तो 25 शब्द से अपने वॉलेट को पुनर्स्थापित करें या 13 शब्द संयोजन कोड", + "restore_description_from_seed_keys": "अपने बटुए को बीज से वापस लें/वे कुंजियाँ जिन्हें आपने सुरक्षित स्थान पर सहेजा है", + "restore_from_date_or_blockheight": "कृपया इस वॉलेट को बनाने से कुछ दिन पहले एक तारीख दर्ज करें। या यदि आप ब्लॉकचेट जानते हैं, तो कृपया इसके बजाय इसे दर्ज करें", + "restore_from_seed_placeholder": "कृपया अपना कोड वाक्यांश यहां दर्ज करें या पेस्ट करें", + "restore_new_seed": "नया बीज", + "restore_next": "आगामी", + "restore_recover": "वसूली", + "restore_restore_wallet": "वॉलेट को पुनर्स्थापित करें", + "restore_seed_keys_restore": "बीज / कुंजी पुनर्स्थापित करें", + "restore_spend_key_private": "कुंजी खर्च करें (निजीe)", + "restore_title_from_backup": "बैक-अप फ़ाइल से पुनर्स्थापित करें", + "restore_title_from_keys": "कुंजी से पुनर्स्थापित करें", + "restore_title_from_seed": "बीज से पुनर्स्थापित करें", + "restore_title_from_seed_keys": "बीज / कुंजियों से पुनर्स्थापित करें", + "restore_view_key_private": "कुंजी देखें (निजी)", + "restore_wallet": "वॉलेट को पुनर्स्थापित करें", + "restore_wallet_name": "बटुए का नाम", + "restore_wallet_restore_description": "बटुआ विवरण पुनर्स्थापित करें", + "router_no_route": "के लिए कोई मार्ग निर्धारित नहीं है ${name}", + "save": "बचाना", + "save_backup_password": "कृपया सुनिश्चित करें कि आपने अपना बैकअप पासवर्ड सहेज लिया है। आप इसके बिना अपनी बैकअप फ़ाइलों को आयात नहीं कर पाएंगे।", + "save_backup_password_alert": "बैकअप पासवर्ड सेव करें", + "save_to_downloads": "डाउनलोड में सहेजें", + "saved_the_trade_id": "मैंने व्यापार बचा लिया है ID", + "scan_qr_code": "स्कैन क्यू आर कोड", + "scan_qr_code_to_get_address": "पता प्राप्त करने के लिए QR कोड स्कैन करें", + "scan_qr_on_device": "इस QR कोड को किसी अन्य डिवाइस पर स्कैन करें", + "search": "खोज", + "search_add_token": "खोजें/टोकन जोड़ें", + "search_category": "खोज श्रेणी", + "search_currency": "मुद्रा खोजें", + "search_language": "भाषा खोजें", + "second_intro_content": "आपका Yat एक अद्वितीय इमोजी पता है जो आपकी सभी मुद्राओं के लिए आपके सभी लंबे हेक्साडेसिमल पतों को बदल देता है।", + "second_intro_title": "उन सभी पर राज करने के लिए एक इमोजी पता", + "security_and_backup": "सुरक्षा और बैकअप", + "seed_alert_back": "वापस जाओ", + "seed_alert_content": "बीज आपके बटुए को पुनर्प्राप्त करने का एकमात्र तरीका है। क्या आपने इसे लिखा है?", + "seed_alert_title": "ध्यान", + "seed_alert_yes": "हाँ मेरे पास है", + "seed_choose": "बीज भाषा चुनें", "seed_hex_form": "वॉलेट सीड (हेक्स फॉर्म)", + "seed_key": "बीज कुंजी", + "seed_language": "बीज", + "seed_language_chinese": "चीनी", + "seed_language_chinese_traditional": "चीनी पारंपरिक)", + "seed_language_czech": "चेक", + "seed_language_dutch": "डच", + "seed_language_english": "अंग्रेज़ी", + "seed_language_french": "फ्रेंच", + "seed_language_german": "जर्मन", + "seed_language_italian": "इतालवी", + "seed_language_japanese": "जापानी", + "seed_language_korean": "कोरियाई", + "seed_language_next": "आगामी", + "seed_language_portuguese": "पुर्तगाली", + "seed_language_russian": "रूसी", + "seed_language_spanish": "स्पेनिश", + "seed_phrase_length": "बीज वाक्यांश की लंबाई", + "seed_reminder": "यदि आप अपना फोन खो देते हैं या मिटा देते हैं तो कृपया इन्हें लिख लें", + "seed_share": "बीज साझा करें", + "seed_title": "बीज", "seedtype": "बीज", "seedtype_legacy": "विरासत (25 शब्द)", "seedtype_polyseed": "पॉलीसीड (16 शब्द)", - "seed_language_czech": "चेक", - "seed_language_korean": "कोरियाई", - "seed_language_chinese_traditional": "चीनी पारंपरिक)", - "ascending": "आरोही", - "descending": "अवरोही", - "dfx_option_description": "EUR और CHF के साथ क्रिप्टो खरीदें। अतिरिक्त केवाईसी के बिना 990€ तक। यूरोप में खुदरा और कॉर्पोरेट ग्राहकों के लिए", - "polygonscan_history": "पॉलीगॉनस्कैन इतिहास", - "wallet_seed_legacy": "विरासत बटुए बीज", - "default_sell_provider": "डिफ़ॉल्ट विक्रय प्रदाता", + "select_backup_file": "बैकअप फ़ाइल का चयन करें", + "select_buy_provider_notice": "ऊपर एक खरीद प्रदाता का चयन करें। आप इस स्क्रीन को ऐप सेटिंग्स में अपना डिफ़ॉल्ट बाय प्रदाता सेट करके छोड़ सकते हैं।", + "select_destination": "कृपया बैकअप फ़ाइल के लिए गंतव्य का चयन करें।", "select_sell_provider_notice": "ऊपर एक विक्रय प्रदाता का चयन करें। आप ऐप सेटिंग में अपना डिफ़ॉल्ट विक्रय प्रदाता सेट करके इस स्क्रीन को छोड़ सकते हैं।", - "custom_drag": "कस्टम (पकड़ और खींचें)", + "sell": "बेचना", + "sell_alert_content": "हम वर्तमान में केवल बिटकॉइन, एथेरियम और लाइटकॉइन की बिक्री का समर्थन करते हैं। कृपया अपना बिटकॉइन, एथेरियम या लाइटकॉइन वॉलेट बनाएं या उसमें स्विच करें।", + "sell_monero_com_alert_content": "मोनेरो बेचना अभी तक समर्थित नहीं है", + "send": "संदेश", + "send_address": "${cryptoCurrency} पता", + "send_amount": "रकम:", + "send_creating_transaction": "लेन-देन बनाना", + "send_error_currency": "मुद्रा में केवल संख्याएँ हो सकती हैं", + "send_error_minimum_value": "राशि का न्यूनतम मूल्य 0.01 है", + "send_estimated_fee": "अनुमानित शुल्क:", + "send_fee": "शुल्क:", + "send_name": "नाम", + "send_new": "नया", + "send_payment_id": "भुगतान ID (ऐच्छिक)", + "send_priority": "वर्तमान में शुल्क निर्धारित है ${transactionPriority} प्राथमिकता.\nलेन-देन की प्राथमिकता को सेटिंग्स में समायोजित किया जा सकता है", + "send_sending": "भेजना...", + "send_success": "आपका ${crypto} सफलतापूर्वक भेजा गया", + "send_templates": "टेम्पलेट्स", + "send_title": "संदेश", + "send_to_this_address": "इस पते पर ${currency} ${tag}भेजें", + "send_xmr": "संदेश XMR", + "send_your_wallet": "आपका बटुआ", + "sending": "भेजना", + "sent": "भेज दिया", + "settings": "समायोजन", + "settings_all": "सब", + "settings_allow_biometrical_authentication": "बायोमेट्रिक प्रमाणीकरण की अनुमति दें", + "settings_can_be_changed_later": "इन सेटिंग्स को बाद में ऐप सेटिंग में बदला जा सकता है", + "settings_change_language": "भाषा बदलो", + "settings_change_pin": "पिन बदलें", + "settings_currency": "मुद्रा", + "settings_current_node": "वर्तमान नोड", + "settings_dark_mode": "डार्क मोड", + "settings_display_balance": "प्रदर्शन संतुलन", + "settings_display_on_dashboard_list": "डैशबोर्ड सूची पर प्रदर्शित करें", + "settings_fee_priority": "शुल्क प्राथमिकता", + "settings_nodes": "नोड्स", + "settings_none": "कोई नहीं", + "settings_only_trades": "केवल ट्रेड करता है", + "settings_only_transactions": "केवल लेन-देन", + "settings_personal": "निजी", + "settings_save_recipient_address": "प्राप्तकर्ता का पता सहेजें", + "settings_support": "समर्थन", + "settings_terms_and_conditions": "नियम और शर्तें", + "settings_title": "सेटिंग्स", + "settings_trades": "ट्रेडों", + "settings_transactions": "लेन-देन", + "settings_wallets": "पर्स", + "setup_2fa": "सेटअप केक 2FA", + "setup_2fa_text": "केक 2FA दूसरे प्रमाणीकरण कारक के रूप में TOTP का उपयोग करके काम करता है।\n\nकेक 2FA के TOTP को SHA-512 और 8 अंकों के समर्थन की आवश्यकता है; इससे अधिक सुरक्षा मिलती है. अधिक जानकारी और समर्थित ऐप्स गाइड में पाए जा सकते हैं।", + "setup_pin": "पिन सेट करें", + "setup_successful": "आपका पिन सफलतापूर्वक सेट हो गया है", + "setup_totp_recommended": "सेटअप टीओटीपी", + "setup_warning_2fa_text": "केक 2एफए वॉलेट में कुछ कार्यों के लिए दूसरा प्रमाणीकरण है। यह कोल्ड स्टोरेज जितना सुरक्षित नहीं है।\n\nयदि आप अपने 2एफए ऐप या टीओटीपी कुंजियों तक पहुंच खो देते हैं, तो आप इस वॉलेट तक पहुंच खो देंगे। आपको अपने बटुए को स्मरक बीज से पुनर्स्थापित करने की आवश्यकता होगी।\n\nयदि आप अपने 2एफए या निमोनिक बीजों तक पहुंच खो देते हैं तो केक समर्थन आपकी सहायता करने में असमर्थ होगा।\nकेक 2एफए का उपयोग करने से पहले, हम गाइड को पढ़ने की सलाह देते हैं।", + "setup_your_debit_card": "अपना डेबिट कार्ड सेट करें", + "share": "शेयर करना", + "share_address": "पता साझा करें", + "show_details": "विवरण दिखाएं", + "show_keys": "बीज / कुंजियाँ दिखाएँ", + "show_market_place": "बाज़ार दिखाएँ", + "show_seed": "बीज दिखाओ", + "sign_up": "साइन अप करें", + "signTransaction": "लेन-देन पर हस्ताक्षर करें", + "signup_for_card_accept_terms": "कार्ड के लिए साइन अप करें और शर्तें स्वीकार करें।", + "slidable": "फिसलने लायक", + "sort_by": "इसके अनुसार क्रमबद्ध करें", + "spend_key_private": "खर्च करना (निजी)", + "spend_key_public": "खर्च करना (जनता)", + "status": "स्थिति: ", + "subaddress_title": "उपखंड सूची", + "subaddresses": "उप पते", + "submit_request": "एक अनुरोध सबमिट करें", + "successful": "सफल", + "support_description_guides": "सामान्य मुद्दों के लिए प्रलेखन और समर्थन", + "support_description_live_chat": "मुक्त और तेजी से! प्रशिक्षित सहायता प्रतिनिधि सहायता के लिए उपलब्ध हैं", + "support_description_other_links": "हमारे समुदायों में शामिल हों या अन्य तरीकों के माध्यम से हमारे साथी तक पहुंचें", + "support_title_guides": "केक वॉलेट गाइड", + "support_title_live_chat": "लाइव सहायता", + "support_title_other_links": "अन्य समर्थन लिंक", + "sweeping_wallet": "स्वीपिंग वॉलेट", + "sweeping_wallet_alert": "इसमें अधिक समय नहीं लगना चाहिए। इस स्क्रीन को न छोड़ें या स्वैप्ट फंड खो सकते हैं", + "switchToETHWallet": "कृपया एथेरियम वॉलेट पर स्विच करें और पुनः प्रयास करें", "switchToEVMCompatibleWallet": "कृपया ईवीएम संगत वॉलेट पर स्विच करें और पुनः प्रयास करें (एथेरियम, पॉलीगॉन)", - "receivable_balance": "प्राप्य शेष", - "confirmed_tx": "की पुष्टि", + "symbol": "प्रतीक", + "sync_all_wallets": "सभी वॉलेट सिंक करें", + "sync_status_attempting_sync": "सिंक करने का प्रयास", + "sync_status_connected": "जुड़े हुए", + "sync_status_connecting": "कनेक्ट", + "sync_status_failed_connect": "डिस्कनेक्ट किया गया", + "sync_status_not_connected": "जुड़े नहीं हैं", + "sync_status_starting_sync": "सिताज़ा करना", + "sync_status_syncronized": "सिंक्रनाइज़", + "sync_status_syncronizing": "सिंक्रनाइज़ करने", + "syncing_wallet_alert_content": "आपकी शेष राशि और लेनदेन सूची तब तक पूरी नहीं हो सकती जब तक कि शीर्ष पर \"सिंक्रनाइज़्ड\" न लिखा हो। अधिक जानने के लिए क्लिक/टैप करें।", + "syncing_wallet_alert_title": "आपका वॉलेट सिंक हो रहा है", + "template": "खाका", + "template_name": "टेम्पलेट नाम", + "third_intro_content": "Yats Cake Wallet के बाहर भी रहता है। धरती पर किसी भी वॉलेट पते को Yat से बदला जा सकता है!", + "third_intro_title": "Yat दूसरों के साथ अच्छा खेलता है", + "time": "${minutes}m ${seconds}s", + "tip": "टिप:", + "today": "आज", + "token_contract_address": "टोकन अनुबंध पता", + "token_decimal": "सांकेतिक दशमलव", + "token_name": "टोकन नाम जैसे: टीथर", + "token_symbol": "टोकन प्रतीक जैसे: यूएसडीटी", + "tokenID": "पहचान", + "tor_connection": "टोर कनेक्शन", + "tor_only": "Tor केवल", + "total_saving": "कुल बचत", + "totp_2fa_failure": "गलत कोड़। कृपया एक अलग कोड का प्रयास करें या एक नई गुप्त कुंजी उत्पन्न करें। 8-अंकीय कोड और SHA512 का समर्थन करने वाले संगत 2FA ऐप का उपयोग करें।", + "totp_2fa_success": "सफलता! इस वॉलेट के लिए Cake 2FA सक्षम है। यदि आप वॉलेट एक्सेस खो देते हैं तो अपने स्मरक बीज को सहेजना याद रखें।", + "totp_auth_url": "TOTP प्रामाणिक यूआरएल", + "totp_code": "टीओटीपी कोड", + "totp_secret_code": "टीओटीपी गुप्त कोड", + "totp_verification_success": "सत्यापन सफल!", + "trade_details_copied": "${title} क्लिपबोर्ड पर नकल", + "trade_details_created_at": "पर बनाया गया", + "trade_details_fetching": "ला रहा है", + "trade_details_id": "आईडी", + "trade_details_pair": "जोड़ा", + "trade_details_provider": "प्रदाता", + "trade_details_state": "दर्जा", + "trade_details_title": "व्यापार विवरण", + "trade_for_not_created": "के लिए व्यापार ${title} निर्मित नहीं है.", + "trade_history_title": "व्यापार का इतिहास", + "trade_id": "व्यापार ID:", + "trade_id_not_found": "व्यापार ${tradeId} of ${title} नहीं मिला.", + "trade_is_powered_by": "यह व्यापार द्वारा संचालित है ${provider}", + "trade_not_created": "व्यापार नहीं बनाया गया", + "trade_not_found": "व्यापार नहीं मिला", + "trade_state_btc_sent": "भेज दिया", + "trade_state_complete": "पूर्ण", + "trade_state_confirming": "पुष्टि", + "trade_state_created": "बनाया था", + "trade_state_finished": "ख़त्म होना", + "trade_state_paid": "भुगतान किया है", + "trade_state_paid_unconfirmed": "अपुष्ट भुगतान किया", + "trade_state_pending": "विचाराधीन", + "trade_state_timeout": "समय समाप्त", + "trade_state_to_be_created": "बनाए जाने के लिए", + "trade_state_traded": "ट्रेडेड", + "trade_state_trading": "व्यापार", + "trade_state_underpaid": "के तहत भुगतान किया", + "trade_state_unpaid": "अवैतनिक", + "trades": "ट्रेडों", + "transaction_details_amount": "रकम", + "transaction_details_copied": "${title} क्लिपबोर्ड पर नकल", + "transaction_details_date": "तारीख", + "transaction_details_fee": "शुल्क", + "transaction_details_height": "ऊंचाई", + "transaction_details_recipient_address": "प्राप्तकर्ता के पते", "transaction_details_source_address": "स्रोत पता", - "pause_wallet_creation": "हेवन वॉलेट बनाने की क्षमता फिलहाल रुकी हुई है।", - "contractName": "अनुबंध का नाम", - "contractSymbol": "अनुबंध चिह्न", - "description": "विवरण", - "camera_consent": "आपके कैमरे का उपयोग ${provider} द्वारा पहचान उद्देश्यों के लिए एक छवि कैप्चर करने के लिए किया जाएगा। विवरण के लिए कृपया उनकी गोपनीयता नीति जांचें।", - "no_relays": "कोई रिले नहीं", - "choose_relay": "कृपया उपयोग करने के लिए एक रिले चुनें", - "no_relays_message": "हमें इस उपयोगकर्ता के लिए एक Nostr NIP-05 रिकॉर्ड मिला, लेकिन इसमें कोई रिले नहीं है। कृपया प्राप्तकर्ता को अपने नॉस्ट्र रिकॉर्ड में रिले जोड़ने का निर्देश दें।", - "no_relay_on_domain": "उपयोगकर्ता के डोमेन के लिए कोई रिले नहीं है या रिले अनुपलब्ध है। कृपया उपयोग करने के लिए एक रिले चुनें।" -} + "transaction_details_title": "लेनदेन का विवरण", + "transaction_details_transaction_id": "लेनदेन आईडी", + "transaction_key": "लेन-देन की", + "transaction_priority_fast": "उपवास", + "transaction_priority_fastest": "सबसे तेजी से", + "transaction_priority_medium": "मध्यम", + "transaction_priority_regular": "नियमित", + "transaction_priority_slow": "धीरे", + "transaction_sent": "भेजा गया लेन-देन", + "transaction_sent_notice": "अगर 1 मिनट के बाद भी स्क्रीन आगे नहीं बढ़ती है, तो ब्लॉक एक्सप्लोरर और अपना ईमेल देखें।", + "transactions": "लेन-देन", + "transactions_by_date": "तारीख से लेन-देन", + "trusted": "भरोसा", + "unavailable_balance": "अनुपलब्ध शेष", + "unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।", + "unconfirmed": "अपुष्ट शेष राशि", + "understand": "मुझे समझ", + "unmatched_currencies": "आपके वर्तमान वॉलेट की मुद्रा स्कैन किए गए क्यूआर से मेल नहीं खाती", + "unspent_change": "परिवर्तन", + "unspent_coins_details_title": "अव्ययित सिक्कों का विवरण", + "unspent_coins_title": "खर्च न किए गए सिक्के", + "unsupported_asset": "हम इस संपत्ति के लिए इस कार्रवाई का समर्थन नहीं करते हैं. कृपया समर्थित परिसंपत्ति प्रकार का वॉलेट बनाएं या उस पर स्विच करें।", + "upto": "${value} तक", + "use": "उपयोग ", + "use_card_info_three": "डिजिटल कार्ड का ऑनलाइन या संपर्क रहित भुगतान विधियों के साथ उपयोग करें।", + "use_card_info_two": "डिजिटल मुद्राओं में नहीं, प्रीपेड खाते में रखे जाने पर निधियों को यूएसडी में बदल दिया जाता है।", + "use_ssl": "उपयोग SSL", + "use_suggested": "सुझाए गए का प्रयोग करें", + "variable_pair_not_supported": "यह परिवर्तनीय जोड़ी चयनित एक्सचेंजों के साथ समर्थित नहीं है", + "verification": "सत्यापन", + "verify_with_2fa": "केक 2FA के साथ सत्यापित करें", + "version": "संस्करण ${currentVersion}", + "view_all": "सभी देखें", + "view_in_block_explorer": "View in Block Explorer", + "view_key_private": "कुंजी देखें(निजी)", + "view_key_public": "कुंजी देखें (जनता)", + "view_transaction_on": "View Transaction on ", + "wallet_keys": "बटुआ बीज / चाबियाँ", + "wallet_list_create_new_wallet": "नया बटुआ बनाएँ", + "wallet_list_edit_wallet": "बटुआ संपादित करें", + "wallet_list_failed_to_load": "लोड करने में विफल ${wallet_name} बटुआ. ${error}", + "wallet_list_failed_to_remove": "निकालने में विफल ${wallet_name} बटुआ. ${error}", + "wallet_list_load_wallet": "वॉलेट लोड करें", + "wallet_list_loading_wallet": "लोड हो रहा है ${wallet_name} बटुआ", + "wallet_list_removing_wallet": "निकाला जा रहा है ${wallet_name} बटुआ", + "wallet_list_restore_wallet": "वॉलेट को पुनर्स्थापित करें", + "wallet_list_title": "Monero बटुआ", + "wallet_list_wallet_name": "बटुआ नाम", + "wallet_menu": "बटुआ मेनू", + "wallet_name": "बटुए का नाम", + "wallet_name_exists": "उस नाम वाला वॉलेट पहले से मौजूद है", + "wallet_restoration_store_incorrect_seed_length": "गलत बीज की लंबाई", + "wallet_seed": "बटुआ का बीज", + "wallet_seed_legacy": "विरासत बटुए बीज", + "wallet_store_monero_wallet": "मोनरो वॉलेट", + "walletConnect": "वॉलेटकनेक्ट", + "wallets": "पर्स", + "warning": "चेतावनी", + "welcome": "स्वागत हे सेवा मेरे", + "welcome_to_cakepay": "केकपे में आपका स्वागत है!", + "widgets_address": "पता", + "widgets_or": "या", + "widgets_restore_from_blockheight": "ब्लॉकचेन से पुनर्स्थापित करें", + "widgets_restore_from_date": "दिनांक से पुनर्स्थापित करें", + "widgets_seed": "बीज", + "wouoldLikeToConnect": "जुड़ना चाहेंगे", + "write_down_backup_password": "कृपया अपना बैकअप पासवर्ड लिखें, जिसका उपयोग आपकी बैकअप फ़ाइलों के आयात के लिए किया जाता है।", + "xlm_extra_info": "एक्सचेंज के लिए XLM ट्रांजेक्शन भेजते समय मेमो आईडी निर्दिष्ट करना न भूलें", + "xmr_available_balance": "उपलब्ध शेष राशि", + "xmr_full_balance": "पूरा संतुलन", + "xmr_hidden": "छिपा हुआ", + "xmr_to_error": "XMR.TO त्रुटि", + "xmr_to_error_description": "अवैध राशि। दशमलव बिंदु के बाद अधिकतम सीमा 8 अंक", + "xrp_extra_info": "एक्सचेंज के लिए एक्सआरपी लेनदेन भेजते समय कृपया गंतव्य टैग निर्दिष्ट करना न भूलें", + "yat": "Yat", + "yat_address": "Yat पता", + "yat_alert_content": "Cake Wallet उपयोगकर्ता अब अपनी सभी पसंदीदा मुद्राओं को एक-एक तरह के इमोजी-आधारित उपयोगकर्ता नाम के साथ भेज और प्राप्त कर सकते हैं।", + "yat_alert_title": "के साथ अधिक आसानी से क्रिप्टो भेजें और प्राप्त करें Yat", + "yat_error": "Yat त्रुटि", + "yat_error_content": "इसके साथ कोई पता लिंक नहीं है Yat. कोई दूसरा आज़माएं Yat", + "yat_popup_content": "अब आप क्रिप्टो भेज और प्राप्त कर सकते हैं Cake Wallet अपने Yat के साथ - एक छोटा, इमोजी-आधारित उपयोगकर्ता नाम। सेटिंग स्क्रीन पर किसी भी समय Yats को प्रबंधित करें", + "yat_popup_title": "आपका वॉलेट पता इमोजी किया जा सकता है।", + "yesterday": "बिता कल", + "you_now_have_debit_card": "अब आपके पास डेबिट कार्ड है", + "you_pay": "आप भुगतान करते हैं", + "you_will_get": "में बदलें", + "you_will_send": "से रूपांतरित करें", + "yy": "वाईवाई", + "zzzz": "ज़ज़्ज़" +} \ No newline at end of file diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 8e3365c96..7d251e867 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -1,777 +1,778 @@ { - "welcome": "Dobrodošli na", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Odličan novčanik za Monero, Bitcoin, Ethereum, Litecoin, i Haven", - "please_make_selection": "Molimo odaberite opcije niže za izradu novog novčanika ili za oporavak postojećeg.", - "create_new": "Izradi novi novčanik", - "restore_wallet": "Oporavi novčanik", - "monero_com": "Monero.com by Cake Wallet", - "monero_com_wallet_text": "Awesome wallet for Monero", - "haven_app": "Haven by Cake Wallet", - "haven_app_wallet_text": "Awesome wallet for Haven", - "accounts": "Računi", - "edit": "Uredi", + "about_cake_pay": "Cake Pay vam omogućuje jednostavnu kupnju darovnih kartica s virtualnim sredstvima, koja se trenutno mogu potrošiti kod više od 150 000 trgovaca u Sjedinjenim Državama.", "account": "Račun", + "accounts": "Računi", + "accounts_subaddresses": "Računi i podadrese", + "activate": "Aktiviraj", + "active": "Aktivno", + "active_cards": "Aktivne kartice", + "activeConnectionsPrompt": "Ovdje će se pojaviti aktivne veze", "add": "Dodaj", + "add_contact": "Dodaj kontakt", + "add_custom_node": "Dodaj novi prilagođeni čvor", + "add_custom_redemption": "Dodaj prilagođeni otkup", + "add_fund_to_card": "Dodajte unaprijed uplaćena sredstva na kartice (do ${value})", + "add_new_node": "Dodaj novi node", + "add_new_word": "Dodaj novu riječ", + "add_receiver": "Dodajte drugi prijemnik (izborno)", + "add_secret_code": "Ili dodajte ovaj tajni kod u aplikaciju za autentifikaciju", + "add_tip": "Dodaj savjet", + "add_token_disclaimer_check": "Potvrdio sam adresu i informacije o ugovoru o tokenu koristeći ugledni izvor. Dodavanje zlonamjernih ili netočnih informacija može dovesti do gubitka sredstava.", + "add_token_warning": "Nemojte uređivati niti dodavati tokene prema uputama prevaranata.\nUvijek potvrdite adrese tokena s uglednim izvorima!", + "add_value": "Dodaj vrijednost", + "address": "Adresa", "address_book": "Imenik", - "contact": "Kontakt", - "please_select": "Molimo odaberite:", - "cancel": "Poništi", - "ok": "OK", - "contact_name": "Ime kontakta", - "reset": "Resetiraj", - "save": "Spremi", + "address_book_menu": "Imenik", + "address_detected": "Adresa je otkrivena", + "address_from_domain": "To je adresa od ${domain} na Unstoppable Domains", + "address_from_yat": "To je adresa od ${emoji} na Yat", + "address_label": "Address label", "address_remove_contact": "Ukloni kontakt", "address_remove_content": "Jeste li sigurni da želite ukloniti odabrani kontakt?", - "authenticated": "Autentificiran", - "authentication": "Autentifikacija", - "failed_authentication": "Autentifikacija neuspješna. ${state_error}", - "wallet_menu": "Izbornik", - "Blocks_remaining": "${status} preostalih blokova", - "please_try_to_connect_to_another_node": "Molimo pokušajte se spojiti na drugi node.", - "xmr_hidden": "Sakriven", - "xmr_available_balance": "Raspoloživ iznos", - "xmr_full_balance": "Ukupan iznos", - "send": "Pošalji", - "receive": "Primi", - "transactions": "Transakcije", - "incoming": "Dolazno", - "outgoing": "Odlazno", - "transactions_by_date": "Transakcije prema datumu", - "trades": "Razmjene", - "filter_by": "Filtrirati po", - "today": "Danas", - "yesterday": "Jučer", - "received": "Primljeno", - "sent": "Poslano", - "pending": " (u tijeku)", - "rescan": "Ponovno skeniranje", - "reconnect": "Ponovno povezivanje", - "wallets": "Novčanici", - "show_seed": "Prikaži pristupni izraz", - "show_keys": "Prikaži pristupni izraz/ključ", - "address_book_menu": "Imenik", - "reconnection": "Ponovno povezivanje", - "reconnect_alert_text": "Jeste li sigurni da se želite ponovno povezati?", - "exchange": "Razmijeni", - "clear": "Izbriši", - "refund_address": "Adresa za povrat", - "change_exchange_provider": "Promjena davatelja usluge razmjene", - "you_will_send": "Razmijeni iz", - "you_will_get": "Razmijeni u", - "amount_is_guaranteed": "Iznos koji ćete primiti je zajamčen", - "amount_is_estimate": "Iznos koji ćete primiti je okviran", - "powered_by": "Omogućio ${title}", - "error": "Greška", - "estimated": "procijenjen", - "min_value": "Min.: ${value} ${currency}", - "max_value": "Maks.: ${value} ${currency}", - "change_currency": "Promijenite valutu", - "overwrite_amount": "Overwrite amount", - "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", - "copy_id": "Kopirati ID", - "exchange_result_write_down_trade_id": "Molimo kopirajte ili zapišite transakcijski ID za nastavak.", - "trade_id": "Transakcijski ID:", - "copied_to_clipboard": "Kopirano u međuspremnik", - "saved_the_trade_id": "Spremio/la sam transakcijski ID", - "fetching": "Dohvaćanje", - "id": "ID: ", - "amount": "Iznos: ", - "payment_id": "ID plaćanja: ", - "status": "Status: ", - "offer_expires_in": "Ponuda istječe za: ", - "trade_is_powered_by": "Razmjenu je omogućio ${provider}", - "copy_address": "Kopiraj adresu", - "exchange_result_confirm": "Pritiskom na potvrdi, poslat ćete ${fetchingLabel} ${from} sa svog novčanika pod nazivom ${walletName} na adresu prikazanu ispod ili iznos možete poslati s vanjskog novčanika na niže navedenu adresu. /QR code.\n\nMolimo potvrdite za nastavak ili se vratite natrag za promjenu iznosa.", - "exchange_result_description": "Potrebno poslati minimalno ${fetchingLabel} ${from} na adresu prikazanu na sljedećoj stranici. Ukoliko pošaljete iznos manji od ${fetchingLabel} ${from}, postoji mogućnost da razmjena neće biti uspješna i da iznos neće biti vraćen.", - "exchange_result_write_down_ID": "*Molimo kopirajte ili zapišite svoj ID prikazan ispod.", - "confirm": "Potvrdi", - "confirm_sending": "Potvrdi slanje", - "commit_transaction_amount_fee": "Izvrši transakciju \nAmount: ${amount}\nFee: ${fee}", - "sending": "Slanje", - "transaction_sent": "Transakcija provedena!", - "expired": "Isteklo", - "time": "${minutes}m ${seconds}s", - "send_xmr": "Pošalji XMR", - "exchange_new_template": "Novi predložak", - "faq": "FAQ", - "enter_your_pin": "Upišite PIN", - "loading_your_wallet": "Novčanik se učitava", - "new_wallet": "Novi novčanik", - "wallet_name": "Ime novčanika", - "continue_text": "Nastavak", - "choose_wallet_currency": "Molimo odaberite valutu novčanika:", - "node_new": "Novi node", - "node_address": "Node adresa", - "node_port": "Node port", - "login": "Prijava", - "password": "Lozinka", - "nodes": "Nodes", - "node_reset_settings_title": "Resetiraj postavke", - "nodes_list_reset_to_default_message": "Jeste li sigurni da se želite vratiti na početne postavke?", - "change_current_node": "Jeste li sigurni da želite promijeniti trenutni node na ${node}?", - "change": "Promijeni", - "remove_node": "Ukloni node", - "remove_node_message": "Jeste li sigurni da želite ukloniti odabrani node?", - "remove": "Ukloni", - "delete": "Izbriši", - "add_new_node": "Dodaj novi node", - "change_current_node_title": "Promijeni trenutni node", - "node_test": "Provjeri", - "node_connection_successful": "Uspješno spajanje", - "node_connection_failed": "Neuspješno spajanje", - "new_node_testing": "Provjera novog nodea", - "use": "Prebaci na", - "digit_pin": "-znamenkasti PIN", - "share_address": "Podijeli adresu", - "receive_amount": "Iznos", - "subaddresses": "Podadrese", "addresses": "Adrese", - "scan_qr_code_to_get_address": "Skeniraj QR kod za dobivanje adrese", - "qr_fullscreen": "Dodirnite za otvaranje QR koda preko cijelog zaslona", - "rename": "Preimenuj", - "choose_account": "Odaberi račun", - "create_new_account": "Izradi novi račun", - "accounts_subaddresses": "Računi i podadrese", - "restore_restore_wallet": "Oporavi novčanik", - "restore_title_from_seed_keys": "Oporavi pomoću pristupnog izraza/ključa", - "restore_description_from_seed_keys": "Oporavi novčanik pomoću pristupnog izraza/ključa spremljenog na sigurno mjesto", - "restore_next": "Dalje", - "restore_title_from_backup": "Oporavak pomoću sigurnosne kopije", - "restore_description_from_backup": "Možete oporaviti cijelu Cake Wallet aplikaciju pomoću vlastite datoteke sa sigurnosnom kopijom", - "restore_seed_keys_restore": "Oporavak pomoću pristupnog izraza/ključa", - "restore_title_from_seed": "Oporavi pomoću pristupnog izraza", - "restore_description_from_seed": "Oporavi novčanik pomoću koda koji sadrži kombinaciju od 25 ili 13 riječi", - "restore_title_from_keys": "Oporavi pomoću ključa", - "restore_description_from_keys": "Oporavi novčanik pomoću generiranih pritisaka na tipke spremljenih od vlastitih privatnih ključeva (keys)", - "restore_wallet_name": "Ime novčanika", - "restore_address": "Adresa", - "restore_view_key_private": "View key (privatni)", - "restore_spend_key_private": "Spend key (privatni)", - "restore_recover": "Oporavi", - "restore_wallet_restore_description": "Opis oporavka novčanika", - "restore_new_seed": "Novi pristupi izraz", - "restore_active_seed": "Aktivan pristupni izraz", - "restore_bitcoin_description_from_seed": "Oporavi novčanik pomoću koda od 12 riječi", - "restore_bitcoin_description_from_keys": "Oporavi novčanik pomoću WIF niza generiranog iz vlastitih privatnih ključeva (keys)", - "restore_bitcoin_title_from_keys": "Oporavi pomoću formata uvoza novčanika (WIF)", - "restore_from_date_or_blockheight": "Molimo unesite datum od nekoliko dana prije nego što ste izradili ovaj novčanik ili ako znate visinu bloka, molimo unesite je.", - "seed_reminder": "Molimo zapišite ih u slučaju da izgubite mobitel ili izbrišete podatke", - "seed_title": "Prisupni izraz", - "seed_share": "Podijeli pristupni izraz", - "copy": "Kopiraj", - "seed_language": "Sjemeni jezik", - "seed_choose": "Odaberi jezik pristupnog izraza", - "seed_language_next": "Dalje", - "seed_language_english": "Engleski", - "seed_language_chinese": "Kineski", - "seed_language_dutch": "Nizozemski", - "seed_language_german": "Njemački", - "seed_language_japanese": "Japanski", - "seed_language_portuguese": "Portugalski", - "seed_language_russian": "Ruski", - "seed_language_spanish": "Španjolski", - "seed_language_french": "Francuski", - "seed_language_italian": "Talijanski", - "send_title": "Pošalji", - "send_your_wallet": "Tvoj novčanik", - "send_address": "${cryptoCurrency} adresa", - "send_payment_id": "ID plaćanja (nije obvezno)", + "advanced_settings": "Napredne postavke", + "aggressive": "Preterano", + "agree": "Slažem se", + "agree_and_continue": "Slažem se i nastavi", + "agree_to": "Stvaranjem računa pristajete na ", "all": "SVE", - "send_error_minimum_value": "Minimalna vrijednost iznosa je 0.01", - "send_error_currency": "Iznos smije sadržavati samo brojeve", - "send_estimated_fee": "Procijenjena naknada:", - "send_priority": "Trenutno se naknada nalazi na ${transactionPriority} mjestu prioriteta.\nPrioritet transakcije moguće je prilagoditi u postavkama", - "send_creating_transaction": "Izrada transakcije", - "send_templates": "Predlošci", - "send_new": "Novi", - "send_amount": "Iznos:", - "send_fee": "Naknada:", - "send_name": "Ime", - "got_it": "U redu", - "send_sending": "Slanje...", - "send_success": "Vaš ${crypto} je uspješno poslan", - "settings_title": "Postavke", - "settings_nodes": "Nodovi", - "settings_current_node": "Trenutni node", - "settings_wallets": "Novčanik", - "settings_display_balance": "Prikaži stanje računa", - "settings_currency": "Valuta", - "settings_fee_priority": "Prioritet naknade", - "settings_save_recipient_address": "Spremi primateljevu adresu", - "settings_personal": "Osobni", - "settings_change_pin": "Promijeni PIN", - "settings_change_language": "Promijeni jezik", - "settings_allow_biometrical_authentication": "Dopusti biometrijsku autentifikaciju", - "settings_dark_mode": "Tamni način rada", - "settings_transactions": "Transakcije", - "settings_trades": "Razmjene", - "settings_display_on_dashboard_list": "Prikaži na listi kontrolne ploče", - "settings_all": "SVE", - "settings_only_trades": "Samo razmjene", - "settings_only_transactions": "Samo transakcije", - "settings_none": "Nijedno", - "settings_support": "Podrška", - "settings_terms_and_conditions": "Uvjeti i odredbe", - "pin_is_incorrect": "Netočan PIN", - "setup_pin": "Podesi PIN", - "enter_your_pin_again": "Ponovno upišite pin", - "setup_successful": "Vaš je pin uspješno postavljen!", - "wallet_keys": "Pristupni izraz/ključ novčanika", - "wallet_seed": "Pristupni izraz novčanika", - "private_key": "Privatni ključ", - "public_key": "Javni ključ", - "view_key_private": "View key (privatni)", - "view_key_public": "View key (javni)", - "spend_key_private": "Spend key (privatni)", - "spend_key_public": "Spend key (javni)", - "copied_key_to_clipboard": "${key} kopiran u međuspremnik", - "new_subaddress_title": "Nova adresa", - "new_subaddress_label_name": "Oznaka", - "new_subaddress_create": "Izradi", - "address_label": "Address label", - "subaddress_title": "Lista podadresa", - "trade_details_title": "Detalji razmjene", - "trade_details_id": "ID", - "trade_details_state": "Status", - "trade_details_fetching": "Dohvaćanje", - "trade_details_provider": "Pružatelj", - "trade_details_created_at": "Stvoreno u", - "trade_details_pair": "Upari", - "trade_details_copied": "${title} kopiran u međuspremnik", - "trade_history_title": "Povijest razmjena", - "transaction_details_title": "Detalji transakcije", - "transaction_details_transaction_id": "Transakcijski ID", - "transaction_details_date": "Datum", - "transaction_details_height": "Visina", - "transaction_details_amount": "Iznos", - "transaction_details_fee": "Naknada", - "transaction_details_copied": "${title} kopiran u međuspremnik", - "transaction_details_recipient_address": "Adrese primatelja", - "wallet_list_title": "Monero novčanik", - "wallet_list_create_new_wallet": "Izradi novi novčanik", - "wallet_list_edit_wallet": "Uredi novčanik", - "wallet_list_wallet_name": "Naziv novčanika", - "wallet_list_restore_wallet": "Oporavi novčanik", - "wallet_list_load_wallet": "Učitaj novčanik", - "wallet_list_loading_wallet": "Učitavanje novčanika ${wallet_name}", - "wallet_list_failed_to_load": "Neuspješno učitavanje novčanika ${wallet_name}. ${error}", - "wallet_list_removing_wallet": "Uklanjanje novčanika ${wallet_name}", - "wallet_list_failed_to_remove": "Neuspješno uklanjanje novčanika ${wallet_name}. ${error}", - "widgets_address": "Adresa", - "widgets_restore_from_blockheight": "Oporavi pomoću visine bloka", - "widgets_restore_from_date": "Oporavi pomoću datuma", - "widgets_or": "ili", - "widgets_seed": "pristupnog izraza", - "router_no_route": "Nije definirana ruta za ${name}", - "error_text_account_name": "Ime računa smije sadržavati samo slova i brojeve\nte mora biti dužine između 1 i 15 znakova", - "error_text_contact_name": "Ime kontakta ne smije sadržavati znakove ` , ' \" \ni mora biti dužine između 1 i 32 znaka", - "error_text_address": "Adresa novčanika mora odgovarati\nvrsti kriptovalute", - "error_text_node_address": "Molimo unesite iPv4 adresu", - "error_text_node_port": "Node port smije sadržavati samo brojeve između 0 i 65535", - "error_text_node_proxy_address": "Unesite :, na primjer 127.0.0.1:9050", - "error_text_payment_id": "ID plaćanja smije sadržavati samo od 16 do 64 znakova hex vrijednosti", - "error_text_xmr": "XMR vrijednost ne smije biti veća od raspoloživog iznosa.\nBroj decimala smije biti 12 ili manji.", - "error_text_fiat": "Vrijednost iznosa ne smije biti veća od raspoloživog iznosa.\nBroj decimala smije biti 2 ili manji.", - "error_text_subaddress_name": "Ime podadrese ne smije sadržavati znakove ` , ' \" \ni mora biti dužine između 1 i 20 znakova", - "error_text_amount": "Iznos smije sadržavati samo brojeve", - "error_text_wallet_name": "Naziv novčanika može sadržavati samo slova, brojeve, _ - simbole\ni mora imati između 1 i 33 znaka", - "error_text_keys": "Novčanik smije sadržavati samo 64 znakova hex vrijednosti", - "error_text_crypto_currency": "Broj decimala mora\nbiti 12 ili manji", - "error_text_minimal_limit": "Razmjena za ${provider} nije izrađena. Iznos je manji od minimalnog: ${min} ${currency}", - "error_text_maximum_limit": "Razmjena za ${provider} nije izrađena. Iznos je veći od maskimalnog: ${max} ${currency}", - "error_text_limits_loading_failed": "Razmjena za ${provider} nije izrađena. Neuspješno učitavanje limita", - "error_text_template": "Ime i adresa predloška ne smiju sadržavati znakove ` , ' \" \ni moraju biti dužine između 1 i 106 znakova", + "all_trades": "Svi obrti", + "all_transactions": "Sve transakcije", + "alphabetical": "Abecedno", + "already_have_account": "Već imate račun?", + "always": "Uvijek", + "amount": "Iznos: ", + "amount_is_estimate": "Iznos koji ćete primiti je okviran", + "amount_is_guaranteed": "Iznos koji ćete primiti je zajamčen", + "and": "i", + "anonpay_description": "Generiraj ${type}. Primatelj može ${method} s bilo kojom podržanom kriptovalutom, a vi ćete primiti sredstva u ovaj novčanik.", + "apk_update": "APK ažuriranje", + "approve": "Odobriti", + "arrive_in_this_address": "${currency} ${tag}će stići na ovu adresu", + "ascending": "Uzlazni", + "ask_each_time": "Pitajte svaki put", "auth_store_ban_timeout": "ban_timeout", "auth_store_banned_for": "Suspendiran na ", "auth_store_banned_minutes": " minute", "auth_store_incorrect_password": "Pogrešan PIN", - "wallet_store_monero_wallet": "Monero novčanik", - "wallet_restoration_store_incorrect_seed_length": "Netočna dužina pristupnog izraza", - "full_balance": "Pun iznos", - "available_balance": "Raspoloživ iznos", - "hidden_balance": "Skriven iznos", - "sync_status_syncronizing": "SINKRONIZIRANJE", - "sync_status_syncronized": "SINKRONIZIRANO", - "sync_status_not_connected": "NIJE POVEZANO", - "sync_status_starting_sync": "ZAPOČINJEMO SINKRONIZIRANJE", - "sync_status_failed_connect": "ISKLJUČENO", - "sync_status_connecting": "SPAJANJE", - "sync_status_connected": "SPOJENO", - "sync_status_attempting_sync": "POKUŠAJ SINKRONIZACIJE", - "transaction_priority_slow": "Sporo", - "transaction_priority_regular": "Uobičajeno", - "transaction_priority_medium": "Srednje", - "transaction_priority_fast": "Brzo", - "transaction_priority_fastest": "Najbrže", - "trade_for_not_created": "Razmjena za ${title} nije izrađena.", - "trade_not_created": "Razmjena nije izrađena", - "trade_id_not_found": "Razmjena ${tradeId} za ${title} nije pronađena.", - "trade_not_found": "Razmjena nije pronađena.", - "trade_state_pending": "U tijeku", - "trade_state_confirming": "Potvrđivanje", - "trade_state_trading": "Razmjenjivanje", - "trade_state_traded": "Razmijenjeno", - "trade_state_complete": "Dovršeno", - "trade_state_to_be_created": "Stvaranje", - "trade_state_unpaid": "Neplaćen", - "trade_state_underpaid": "Nedovoljno plaćen", - "trade_state_paid_unconfirmed": "Plaćanje nije potrđeno", - "trade_state_paid": "Plaćen", - "trade_state_btc_sent": "BTC poslan", - "trade_state_timeout": "Isteklo", - "trade_state_created": "Stvoreno", - "trade_state_finished": "Završeno", - "change_language": "Promijeni jezik", - "change_language_to": "Promijeni jezik u ${language}?", - "paste": "Zalijepi", - "restore_from_seed_placeholder": "Molimo unesite ili zalijepite svoj pristupni izraz ovdje", - "add_new_word": "Dodaj novu riječ", - "incorrect_seed": "Uneseni tekst nije valjan.", - "biometric_auth_reason": "Skenirajte svoj otisak prsta za autentifikaciju", - "version": "Verzija ${currentVersion}", - "extracted_address_content": "Poslat ćete sredstva primatelju\n${recipient_name}", - "card_address": "Adresa:", - "buy": "Kupi", - "sell": "Prodavati", - "placeholder_transactions": "Vaše će transakcije biti prikazane ovdje", - "placeholder_contacts": "Vaši će kontakti biti prikazani ovdje", - "template": "Predložak", - "confirm_delete_template": "Ovom ćete radnjom izbrisati ovaj predložak. Želite li nastaviti?", - "confirm_delete_wallet": "Ovom ćete radnjom izbrisati ovaj novčanik. Želite li nastaviti?", - "change_wallet_alert_title": "Izmijeni trenutni novčanik", - "change_wallet_alert_content": "Želite li promijeniti trenutni novčanik u ${wallet_name}?", - "creating_new_wallet": "Stvaranje novog novčanika", - "creating_new_wallet_error": "Greška: ${description}", - "seed_alert_title": "Upozorenje", - "seed_alert_content": "Pristupni izraz jedini je način za oporavak novčanika. Jeste li ga zapisali?", - "seed_alert_back": "Vrati se natrag", - "seed_alert_yes": "Jesam", - "exchange_sync_alert_content": "Molimo pričekajte dok se Vaš novčanik ne sinkronizira.", - "pre_seed_title": "VAŽNO", - "pre_seed_description": "Na sljedećoj ćete stranici vidjeti niz ${words} riječi. Radi se o Vašem jedinstvenom i tajnom pristupnom izrazu koji je ujedno i JEDINI način na koji možete oporaviti svoj novčanik u slučaju gubitka ili kvara. VAŠA je odgovornost zapisati ga te pohraniti na sigurno mjesto izvan Cake Wallet aplikacije.", - "pre_seed_button_text": "Razumijem. Prikaži mi moj pristupni izraz", - "xmr_to_error": "XMR.TO greška", - "xmr_to_error_description": "Nevažeći iznos. Dopušteno je najviše 8 znamenki iza točke", - "provider_error": "${provider} greška", - "use_ssl": "Koristi SSL", - "trusted": "vjerovao", - "color_theme": "Shema boja", - "light_theme": "Svijetla", - "bright_theme": "Jarka", - "dark_theme": "Tamna", - "enter_your_note": "Unesite svoju poruku…", - "note_optional": "Poruka (nije obvezno)", - "note_tap_to_change": "Poruka (dodirnite za promjenu)", - "view_in_block_explorer": "View in Block Explorer", - "view_transaction_on": "View Transaction on ", - "transaction_key": "Transakcijski ključ", - "confirmations": "Potvrde", - "recipient_address": "Primateljeva adresa", - "extra_id": "Dodatni ID:", - "destination_tag": "Odredišna oznaka:", - "memo": "Memo:", - "backup": "Sigurnosna kopija", - "change_password": "Promijeni lozinku", - "backup_password": "Lozinka za sigurnosnu kopiju", - "write_down_backup_password": "Molimo zapišite svoju lozinku za sigurnosnu kopiju koja se koristi za uvoz datoteka sigurnosne kopije.", - "export_backup": "Izvezi sigurnosnu kopiju", - "save_backup_password": "Molimo pobrinite se da spremite svoju lozinku za sigurnosnu kopiju. Bez nje nećete moći uvesti datoteke sigurnosne kopije.", - "backup_file": "Sigurnosna kopija datoteke", - "edit_backup_password": "Uredi lozinku za sigurnosnu kopiju", - "save_backup_password_alert": "Spremi lozinku za sigurnosnu kopiju", - "change_backup_password_alert": "Nećemo moći uvesti Vaše prethodne datoteke sigurnosne kopije s novom lozinkom za sigurnosnu kopiju. Novu lozinku za sigurnosnu kopiju moći ćete koristiti samo za nove datoteke sigurnosne kopije. Jeste li sigurni da želite promijeniti lozinku za sigurnosnu kopiju?", - "enter_backup_password": "Unesite svoju lozinku za sigurnosnu kopiju ovdje", - "select_backup_file": "Odaberite datoteku sigurnosne kopije", - "import": "Uvoz", - "please_select_backup_file": "Molimo odaberite datoteku sigurnosne kopije i unesite lozinku za sigurnosnu kopiju.", - "fixed_rate": "Fiksna stopa", - "fixed_rate_alert": "Moći ćete unijeti iznos koji želite primiti nakon što označite način rada fiksne stope. Želite li se prebaciti na način rada fiksne stope?", - "xlm_extra_info": "Molimo ne zaboravite navesti memo ID prilikom slanja XLM transakcije na razmjenu", - "xrp_extra_info": "Molimo ne zaboravite navesti odredišnu oznaku prilikom slanja XRP transakcije na razmjenu", - "exchange_incorrect_current_wallet_for_xmr": "Ako želite razmijeniti XMR s vlastitog Monero računa na Cake Wallet novčaniku, molimo prvo se prebacite na svoj Monero novčanik.", - "confirmed": "Potvrđeno stanje", - "unconfirmed": "Nepotvrđeno stanje", - "displayable": "Dostupno za prikaz", - "submit_request": "podnesi zahtjev", - "buy_alert_content": "Trenutno podržavamo samo kupnju Bitcoina, Ethereuma, Litecoina i Monera. Izradite ili prijeđite na svoj Bitcoin, Ethereum, Litecoin ili Monero novčanik.", - "sell_alert_content": "Trenutno podržavamo samo prodaju Bitcoina, Ethereuma i Litecoina. Izradite ili prijeđite na svoj Bitcoin, Ethereum ili Litecoin novčanik.", - "outdated_electrum_wallet_description": "Novi Bitcoin novčanici stvoreni u Cakeu sada imaju sjeme od 24 riječi. Obavezno je stvoriti novi Bitcoin novčanik i prenijeti sva svoja sredstva u novi novčanik od 24 riječi te prestati koristiti novčanike s sjemenkom od 12 riječi. Učinite to odmah kako biste osigurali svoja sredstva.", - "understand": "Razumijem", - "apk_update": "APK ažuriranje", - "buy_bitcoin": "Kupite Bitcoin", - "buy_with": "Kupite s", - "moonpay_alert_text": "Vrijednost iznosa mora biti veća ili jednaka ${minAmount} ${fiatCurrency}", - "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", - "do_not_show_me": "Ne pokazuj mi ovo više", - "unspent_coins_title": "Nepotrošeni novčići", - "unspent_coins_details_title": "Nepotrošeni detalji o novčićima", - "freeze": "Zamrznuti", - "frozen": "Smrznuto", - "coin_control": "Kontrola novca (nije obavezno)", - "address_detected": "Adresa je otkrivena", - "address_from_domain": "To je adresa od ${domain} na Unstoppable Domains", - "add_receiver": "Dodajte drugi prijemnik (izborno)", - "manage_yats": "Upravljanje Yat", - "yat_alert_title": "Lakše šaljite i primajte kriptovalute s Yatom", - "yat_alert_content": "Korisnici Cake Wallet sada mogu slati i primati sve svoje omiljene valute s jedinstvenim korisničkim imenom na temelju emojija.", - "get_your_yat": "Uzmi svoj Yat", - "connect_an_existing_yat": "Povežite postojeći Yat", - "yat_address": "Yat adresa", - "yat": "Yat", - "connect_yats": "Povežite Yats", - "address_from_yat": "To je adresa od ${emoji} na Yat", - "yat_error": "Yat pogreška", - "yat_error_content": "Nema adresa povezanih s ovim Yat -om. Pokušajte s drugim Yat -om", - "choose_address": "\n\nOdaberite adresu:", - "yat_popup_title": "Adresa vašeg novčanika može biti emojificirana.", - "yat_popup_content": "Sada možete slati i primati kriptovalute u Cake Wallet s vašim Yat - kratkim korisničkim imenom zasnovanim na emojijima. Upravljajte Yatsom u bilo kojem trenutku na zaslonu postavki", - "second_intro_title": "Jedna adresa emojija koja će svima njima vladati", - "second_intro_content": "Vaš Yat jedinstvena je adresa emojija koja zamjenjuje sve vaše duge heksadecimalne adrese za sve vaše valute.", - "third_intro_title": "Yat se lijepo igra s drugima", - "third_intro_content": "Yats žive i izvan Cake Wallet -a. Bilo koja adresa novčanika na svijetu može se zamijeniti Yat!", - "learn_more": "Saznajte više", - "search": "Traži", - "search_language": "Jezik pretraživanja", - "search_currency": "Traži valutu", - "new_template": "novi predložak", - "electrum_address_disclaimer": "Minden egyes alkalommal új címeket generálunk, de a korábbi címek továbbra is működnek", - "wallet_name_exists": "Novčanik s tim nazivom već postoji", - "market_place": "Tržnica", - "cake_pay_title": "Cake Pay poklon kartice", - "cake_pay_subtitle": "Kupite darovne kartice s popustom (samo SAD)", - "cake_pay_web_cards_title": "Cake Pay Web kartice", - "cake_pay_web_cards_subtitle": "Kupujte prepaid kartice i poklon kartice diljem svijeta", - "about_cake_pay": "Cake Pay vam omogućuje jednostavnu kupnju darovnih kartica s virtualnim sredstvima, koja se trenutno mogu potrošiti kod više od 150 000 trgovaca u Sjedinjenim Državama.", - "cake_pay_account_note": "Prijavite se samo s adresom e-pošte da biste vidjeli i kupili kartice. Neke su čak dostupne uz popust!", - "already_have_account": "Već imate račun?", - "create_account": "Stvori račun", - "privacy_policy": "Pravila privatnosti", - "welcome_to_cakepay": "Dobro došli u Cake Pay!", - "sign_up": "Prijavite se", - "forgot_password": "Zaboravljena lozinka", - "reset_password": "Poništi lozinku", - "gift_cards": "Ajándékkártya", - "setup_your_debit_card": "Postavite svoju debitnu karticu", - "no_id_required": "Nije potreban ID. Nadopunite i potrošite bilo gdje", - "how_to_use_card": "Kako koristiti ovu karticu", - "purchase_gift_card": "Kupnja darovne kartice", - "verification": "Potvrda", - "fill_code": "Molimo vas da ispunite kontrolni kod koji ste dobili na svojoj e-pošti", - "didnt_get_code": "Ne dobivate kod?", - "resend_code": "Molimo da ga ponovno pošaljete", - "debit_card": "Debitna kartica", - "cakepay_prepaid_card": "CakePay unaprijed plaćena debitna kartica", - "no_id_needed": "Nije potreban ID!", - "frequently_asked_questions": "Često postavljana pitanja", - "debit_card_terms": "Pohranjivanje i korištenje broja vaše platne kartice (i vjerodajnica koje odgovaraju broju vaše platne kartice) u ovom digitalnom novčaniku podliježu Uvjetima i odredbama važećeg ugovora vlasnika kartice s izdavateljem platne kartice, koji su na snazi ​​od S vremena na vrijeme.", - "please_reference_document": "Molimo pogledajte dokumente ispod za više informacija.", - "cardholder_agreement": "Ugovor s vlasnikom kartice", - "e_sign_consent": "E-Sign pristanak", - "agree_and_continue": "Slažem se i nastavi", - "email_address": "Adresa e-pošte", - "agree_to": "Stvaranjem računa pristajete na ", - "and": "i", - "enter_code": "Unesite kod", - "congratulations": "Čestitamo!", - "you_now_have_debit_card": "Sada imate debitnu karticu", - "min_amount": "Minimalno: ${value}", - "max_amount": "Maksimum: ${value}", - "enter_amount": "Unesite iznos", - "billing_address_info": "Ako se od vas zatraži adresa za naplatu, navedite svoju adresu za dostavu", - "order_physical_card": "Naručite fizičku karticu", - "add_value": "Dodaj vrijednost", - "activate": "Aktiviraj", - "get_a": "Nabavite ", - "digital_and_physical_card": "digitalna i fizička unaprijed plaćena debitna kartica", - "get_card_note": " koju možete ponovno napuniti digitalnim valutama. Nisu potrebne dodatne informacije!", - "signup_for_card_accept_terms": "Prijavite se za karticu i prihvatite uvjete.", - "add_fund_to_card": "Dodajte unaprijed uplaćena sredstva na kartice (do ${value})", - "use_card_info_two": "Sredstva se pretvaraju u USD kada se drže na prepaid računu, a ne u digitalnim valutama.", - "use_card_info_three": "Koristite digitalnu karticu online ili s beskontaktnim metodama plaćanja.", - "optionally_order_card": "Opcionalno naručite fizičku karticu.", - "hide_details": "Sakrij pojedinosti", - "show_details": "Prikaži pojedinosti", - "upto": "do ${value}", - "discount": "Uštedite ${value}%", - "gift_card_amount": "Iznos darovne kartice", - "bill_amount": "Iznos računa", - "you_pay": "Vi plaćate", - "tip": "Savjet:", - "custom": "prilagođeno", - "by_cake_pay": "od Cake Paya", - "expires": "Ističe", - "mm": "MM", - "yy": "GG", - "online": "Na mreži", - "offline": "izvan mreže", - "gift_card_number": "Broj darovne kartice", - "pin_number": "PIN broj", - "total_saving": "Ukupna ušteda", - "last_30_days": "Zadnjih 30 dana", - "avg_savings": "Prosj. ušteda", - "view_all": "Prikaži sve", - "active_cards": "Aktivne kartice", - "delete_account": "Izbriši račun", - "cards": "Kartice", - "active": "Aktivno", - "redeemed": "otkupljeno", - "gift_card_balance_note": "Ovdje će se pojaviti darovne kartice s preostalim saldom", - "gift_card_redeemed_note": "Poklon kartice koje ste iskoristili pojavit će se ovdje", - "logout": "Odjava", - "add_tip": "Dodaj savjet", - "percentageOf": "od ${amount}", - "is_percentage": "je", - "search_category": "Kategorija pretraživanja", - "mark_as_redeemed": "Označi kao otkupljeno", - "more_options": "Više opcija", - "awaiting_payment_confirmation": "Čeka se potvrda plaćanja", - "transaction_sent_notice": "Ako se zaslon ne nastavi nakon 1 minute, provjerite block explorer i svoju e-poštu.", - "agree": "Slažem se", - "in_store": "U trgovini", - "generating_gift_card": "Generiranje darovne kartice", - "payment_was_received": "Vaša uplata je primljena.", - "proceed_after_one_minute": "Ako se zaslon ne nastavi nakon 1 minute, provjerite svoju e-poštu.", - "order_id": "ID narudžbe", - "gift_card_is_generated": "Poklon kartica je generirana", - "open_gift_card": "Otvori darovnu karticu", - "contact_support": "Kontaktirajte podršku", - "gift_cards_unavailable": "Poklon kartice trenutno su dostupne za kupnju samo putem Monera, Bitcoina i Litecoina", - "background_sync_mode": "Sinkronizacija u pozadini", - "sync_all_wallets": "Sinkronizirajte sve novčanike", - "introducing_cake_pay": "Predstavljamo Cake Pay!", - "cake_pay_learn_more": "Azonnal vásárolhat és válthat be ajándékutalványokat az alkalmazásban!\nTovábbi információért csúsztassa balról jobbra az ujját.", + "authenticated": "Autentificiran", + "authentication": "Autentifikacija", + "auto_generate_subaddresses": "Automatski generirajte podadrese", "automatic": "Automatski", - "fixed_pair_not_supported": "Ovaj fiksni par nije podržan s odabranim burzama", - "variable_pair_not_supported": "Ovaj par varijabli nije podržan s odabranim burzama", - "none_of_selected_providers_can_exchange": "Niti jedan od odabranih pružatelja usluga ne može izvršiti ovu razmjenu", - "choose_one": "Izaberi jedan", - "choose_from_available_options": "Odaberite neku od dostupnih opcija:", - "custom_redeem_amount": "Prilagođeni iznos otkupa", - "add_custom_redemption": "Dodaj prilagođeni otkup", - "remaining": "preostalo", - "delete_wallet": "Izbriši novčanik", - "delete_wallet_confirm_message": "Jeste li sigurni da želite izbrisati ${wallet_name} novčanik?", - "low_fee": "Niska naknada", - "low_fee_alert": "Trenutačno koristite niski prioritet mrežne naknade. To bi moglo uzrokovati duga čekanja, različite tečajeve ili otkazane trgovine. Preporučujemo postavljanje veće naknade za bolje iskustvo.", - "ignor": "Zanemariti", - "use_suggested": "Koristite predloženo", - "do_not_share_warning_text": "Nemojte ih dijeliti ni s kim, uključujući podršku.\n\nVaša sredstva mogu i bit će ukradena!", - "help": "pomozite", - "all_transactions": "Sve transakcije", - "all_trades": "Svi obrti", - "connection_sync": "Povezivanje i sinkronizacija", - "security_and_backup": "Sigurnost i sigurnosna kopija", - "create_backup": "Stvori sigurnosnu kopiju", - "privacy_settings": "Postavke privatnosti", - "privacy": "Privatnost", - "display_settings": "Postavke zaslona", - "other_settings": "Ostale postavke", - "require_pin_after": "Zahtijevaj PIN nakon", - "always": "Uvijek", - "minutes_to_pin_code": "${minute} minuta", - "disable_exchange": "Onemogući exchange", - "advanced_settings": "Napredne postavke", - "settings_can_be_changed_later": "Te se postavke mogu promijeniti kasnije u postavkama aplikacije", - "add_custom_node": "Dodaj novi prilagođeni čvor", - "disable_fiat": "Isključi, fiat", - "fiat_api": "Fiat API", - "disabled": "Onemogućeno", - "enabled": "Omogućeno", - "tor_only": "Samo Tor", - "unmatched_currencies": "Valuta vašeg trenutnog novčanika ne odgovara onoj na skeniranom QR-u", - "orbot_running_alert": "Provjerite radi li Orbot prije spajanja na ovaj čvor.", - "contact_list_contacts": "Kontakti", - "contact_list_wallets": "Moji novčanici", - "bitcoin_payments_require_1_confirmation": "Bitcoin plaćanja zahtijevaju 1 potvrdu, što može potrajati 20 minuta ili dulje. Hvala na Vašem strpljenju! Dobit ćete e-poruku kada plaćanje bude potvrđeno.", - "send_to_this_address": "Pošaljite ${currency} ${tag}na ovu adresu", - "arrive_in_this_address": "${currency} ${tag}će stići na ovu adresu", - "do_not_send": "Ne šalji", - "error_dialog_content": "Ups, imamo grešku.\n\nPošaljite izvješće o padu našem timu za podršku kako bismo poboljšali aplikaciju.", - "scan_qr_code": "Skenirajte QR kod", - "cold_or_recover_wallet": "Dodajte hladni novčanik ili povratite papirnati novčanik", - "please_wait": "Molimo pričekajte", - "sweeping_wallet": "Čisti novčanik", - "sweeping_wallet_alert": "Ovo ne bi trebalo dugo trajati. NE NAPUŠTAJTE OVAJ ZASLON INAČE SE POBREŠENA SREDSTVA MOGU IZGUBITI", - "decimal_places_error": "Previše decimalnih mjesta", - "edit_node": "Uredi čvor", - "invoice_details": "Podaci o fakturi", - "donation_link_details": "Detalji veza za donacije", - "anonpay_description": "Generiraj ${type}. Primatelj može ${method} s bilo kojom podržanom kriptovalutom, a vi ćete primiti sredstva u ovaj novčanik.", - "create_invoice": "Izradite fakturu", - "create_donation_link": "Izradi poveznicu za donaciju", - "optional_email_hint": "Neobavezna e-pošta za obavijest primatelja", - "optional_description": "Opcijski opis", - "optional_name": "Izborno ime primatelja", - "clearnet_link": "Clearnet veza", - "onion_link": "Poveznica luka", - "settings": "Postavke", - "sell_monero_com_alert_content": "Prodaja Monera još nije podržana", - "error_text_input_below_minimum_limit": "Iznos je manji od minimalnog", - "error_text_input_above_maximum_limit": "Iznos je veći od maskimalnog", - "show_market_place": "Prikaži tržište", - "prevent_screenshots": "Spriječite snimke zaslona i snimanje zaslona", - "profile": "Profil", - "close": "Zatvoriti", - "modify_2fa": "Izmijenite tortu 2FA", - "disable_cake_2fa": "Onemogući Cake 2FA", - "question_to_disable_2fa": "Jeste li sigurni da želite onemogućiti Cake 2FA? 2FA kod više neće biti potreban za pristup novčaniku i određenim funkcijama.", - "disable": "Onemogući", - "setup_2fa": "Postavljanje torte 2FA", - "verify_with_2fa": "Provjerite s Cake 2FA", - "totp_code": "TOTP kod", - "please_fill_totp": "Unesite 8-znamenkasti kod koji se nalazi na vašem drugom uređaju", - "totp_2fa_success": "Uspjeh! Cake 2FA omogućen za ovaj novčanik. Ne zaboravite spremiti svoje mnemoničko sjeme u slučaju da izgubite pristup novčaniku.", - "totp_verification_success": "Provjera uspješna!", - "totp_2fa_failure": "Neispravan kod. Pokušajte s drugim kodom ili generirajte novi tajni ključ. Koristite kompatibilnu 2FA aplikaciju koja podržava 8-znamenkasti kod i SHA512.", - "enter_totp_code": "Unesite TOTP kod.", - "add_secret_code": "Ili dodajte ovaj tajni kod u aplikaciju za autentifikaciju", - "totp_secret_code": "TOTP tajni kod", - "setup_2fa_text": "Cake 2FA radi koristeći TOTP kao drugi faktor provjere autentičnosti.\n\nCake 2FA TOTP zahtijeva SHA-512 i podršku za 8 znamenki; ovo osigurava povećanu sigurnost. Više informacija i podržanih aplikacija možete pronaći u vodiču.", - "setup_totp_recommended": "Postavite TOTP", - "disable_buy": "Onemogući kupnju", - "disable_sell": "Onemogući akciju prodaje", - "cake_2fa_preset": "Cake 2FA Preset", - "monero_dark_theme": "Monero tamna tema", + "available_balance": "Raspoloživ iznos", + "available_balance_description": "Dostupno stanje je iznos koji možete potrošiti. To je vaš saldo minus bilo kakve transakcije koje su još uvijek u tijeku.", + "avg_savings": "Prosj. ušteda", + "awaitDAppProcessing": "Molimo pričekajte da dApp završi obradu.", + "awaiting_payment_confirmation": "Čeka se potvrda plaćanja", + "background_sync_mode": "Sinkronizacija u pozadini", + "backup": "Sigurnosna kopija", + "backup_file": "Sigurnosna kopija datoteke", + "backup_password": "Lozinka za sigurnosnu kopiju", + "balance_page": "Stranica sa stanjem", + "bill_amount": "Iznos računa", + "billing_address_info": "Ako se od vas zatraži adresa za naplatu, navedite svoju adresu za dostavu", + "biometric_auth_reason": "Skenirajte svoj otisak prsta za autentifikaciju", "bitcoin_dark_theme": "Bitcoin Tamna tema", "bitcoin_light_theme": "Bitcoin Light Theme", - "high_contrast_theme": "Tema visokog kontrasta", - "matrix_green_dark_theme": "Matrix Green Dark Theme", - "monero_light_theme": "Monero lagana tema", - "auto_generate_subaddresses": "Automatski generirajte podadrese", - "narrow": "Usko", - "normal": "Normalno", - "aggressive": "Preterano", - "require_for_assessing_wallet": "Potreban za pristup novčaniku", - "require_for_sends_to_non_contacts": "Zahtijeva za slanje nekontaktima", - "require_for_sends_to_contacts": "Zahtijeva za slanje kontaktima", - "require_for_sends_to_internal_wallets": "Zahtijeva za slanje u interne novčanike", - "require_for_exchanges_to_internal_wallets": "Potreban za razmjenu na interne novčanike", - "require_for_adding_contacts": "Zahtijeva za dodavanje kontakata", - "require_for_creating_new_wallets": "Potreban za kreiranje novih novčanika", - "require_for_all_security_and_backup_settings": "Zahtijeva za sve postavke sigurnosti i sigurnosne kopije", - "available_balance_description": "Dostupno stanje je iznos koji možete potrošiti. To je vaš saldo minus bilo kakve transakcije koje su još uvijek u tijeku.", - "syncing_wallet_alert_title": "Vaš novčanik se sinkronizira", - "syncing_wallet_alert_content": "Vaš saldo i popis transakcija možda neće biti potpuni sve dok na vrhu ne piše \"SINKRONIZIRANO\". Kliknite/dodirnite da biste saznali više.", - "home_screen_settings": "Postavke početnog zaslona", - "sort_by": "Poredaj po", - "search_add_token": "Traži / Dodaj token", - "edit_token": "Uredi token", - "warning": "Upozorenje", - "add_token_warning": "Nemojte uređivati niti dodavati tokene prema uputama prevaranata.\nUvijek potvrdite adrese tokena s uglednim izvorima!", - "add_token_disclaimer_check": "Potvrdio sam adresu i informacije o ugovoru o tokenu koristeći ugledni izvor. Dodavanje zlonamjernih ili netočnih informacija može dovesti do gubitka sredstava.", - "token_contract_address": "Adresa ugovora tokena", - "token_name": "Naziv tokena npr.: Tether", - "token_symbol": "Simbol tokena npr.: USDT", - "token_decimal": "Token decimalni", - "field_required": "ovo polje je obavezno", - "pin_at_top": "prikvači ${token} na vrh", - "invalid_input": "Pogrešan unos", - "fiat_balance": "Fiat Bilans", - "gross_balance": "Bruto bilanca", - "alphabetical": "Abecedno", - "generate_name": "Generiraj ime", - "balance_page": "Stranica sa stanjem", - "share": "Udio", - "slidable": "Klizna", - "manage_nodes": "Upravljanje čvorovima", - "etherscan_history": "Etherscan povijest", - "template_name": "Naziv predloška", - "change_rep_message": "Jeste li sigurni da želite promijeniti predstavnika?", - "unsupported_asset": "Ne podržavamo ovu radnju za ovaj materijal. Izradite ili prijeđite na novčanik podržane vrste sredstava.", - "manage_pow_nodes": "Upravljanje PoW čvorovima", - "support_title_live_chat": "Podrška uživo", - "support_title_guides": "Vodiči za torte", - "support_description_guides": "Dokumentacija i podrška za uobičajena pitanja", - "support_title_other_links": "Ostale veze za podršku", - "support_description_other_links": "Pridružite se našim zajednicama ili nam dosegnu naše partnere drugim metodama", - "choose_derivation": "Odaberite izvedbu novčanika", - "new_first_wallet_text": "Jednostavno čuvajte svoju kripto valutu", - "select_destination": "Odaberite odredište za datoteku sigurnosne kopije.", - "save_to_downloads": "Spremi u Preuzimanja", - "select_buy_provider_notice": "Odaberite gornji davatelj kupnje. Ovaj zaslon možete preskočiti postavljanjem zadanog davatelja usluga kupnje u postavkama aplikacija.", - "onramper_option_description": "Brzo kupite kriptovalute s mnogim načinima plaćanja. Dostupno u većini zemalja. Širenja i naknade variraju.", - "default_buy_provider": "Zadani davatelj kupnje", - "ask_each_time": "Pitajte svaki put", + "bitcoin_payments_require_1_confirmation": "Bitcoin plaćanja zahtijevaju 1 potvrdu, što može potrajati 20 minuta ili dulje. Hvala na Vašem strpljenju! Dobit ćete e-poruku kada plaćanje bude potvrđeno.", + "Blocks_remaining": "${status} preostalih blokova", + "bright_theme": "Jarka", + "buy": "Kupi", + "buy_alert_content": "Trenutno podržavamo samo kupnju Bitcoina, Ethereuma, Litecoina i Monera. Izradite ili prijeđite na svoj Bitcoin, Ethereum, Litecoin ili Monero novčanik.", + "buy_bitcoin": "Kupite Bitcoin", "buy_provider_unavailable": "Davatelj trenutno nije dostupan.", - "signTransaction": "Potpišite transakciju", + "buy_with": "Kupite s", + "by_cake_pay": "od Cake Paya", + "cake_2fa_preset": "Cake 2FA Preset", + "cake_pay_account_note": "Prijavite se samo s adresom e-pošte da biste vidjeli i kupili kartice. Neke su čak dostupne uz popust!", + "cake_pay_learn_more": "Azonnal vásárolhat és válthat be ajándékutalványokat az alkalmazásban!\nTovábbi információért csúsztassa balról jobbra az ujját.", + "cake_pay_subtitle": "Kupite darovne kartice s popustom (samo SAD)", + "cake_pay_title": "Cake Pay 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_wallet": "Cake Wallet", + "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.", + "camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.", + "cancel": "Poništi", + "card_address": "Adresa:", + "cardholder_agreement": "Ugovor s vlasnikom kartice", + "cards": "Kartice", + "chains": "Lanci", + "change": "Promijeni", + "change_backup_password_alert": "Nećemo moći uvesti Vaše prethodne datoteke sigurnosne kopije s novom lozinkom za sigurnosnu kopiju. Novu lozinku za sigurnosnu kopiju moći ćete koristiti samo za nove datoteke sigurnosne kopije. Jeste li sigurni da želite promijeniti lozinku za sigurnosnu kopiju?", + "change_currency": "Promijenite valutu", + "change_current_node": "Jeste li sigurni da želite promijeniti trenutni node na ${node}?", + "change_current_node_title": "Promijeni trenutni node", + "change_exchange_provider": "Promjena davatelja usluge razmjene", + "change_language": "Promijeni jezik", + "change_language_to": "Promijeni jezik u ${language}?", + "change_password": "Promijeni lozinku", + "change_rep_message": "Jeste li sigurni da želite promijeniti predstavnika?", + "change_rep_successful": "Uspješno promijenjena reprezentativna", + "change_wallet_alert_content": "Želite li promijeniti trenutni novčanik u ${wallet_name}?", + "change_wallet_alert_title": "Izmijeni trenutni novčanik", + "choose_account": "Odaberi račun", + "choose_address": "\n\nOdaberite adresu:", + "choose_derivation": "Odaberite izvedbu novčanika", + "choose_from_available_options": "Odaberite neku od dostupnih opcija:", + "choose_one": "Izaberi jedan", + "choose_relay": "Odaberite relej za korištenje", + "choose_wallet_currency": "Molimo odaberite valutu novčanika:", + "clear": "Izbriši", + "clearnet_link": "Clearnet veza", + "close": "Zatvoriti", + "coin_control": "Kontrola novca (nije obavezno)", + "cold_or_recover_wallet": "Dodajte hladni novčanik ili povratite papirnati novčanik", + "color_theme": "Shema boja", + "commit_transaction_amount_fee": "Izvrši transakciju \nAmount: ${amount}\nFee: ${fee}", + "confirm": "Potvrdi", + "confirm_delete_template": "Ovom ćete radnjom izbrisati ovaj predložak. Želite li nastaviti?", + "confirm_delete_wallet": "Ovom ćete radnjom izbrisati ovaj novčanik. Želite li nastaviti?", + "confirm_sending": "Potvrdi slanje", + "confirmations": "Potvrde", + "confirmed": "Potvrđeno stanje", + "confirmed_tx": "Potvrđen", + "congratulations": "Čestitamo!", + "connect_an_existing_yat": "Povežite postojeći Yat", + "connect_yats": "Povežite Yats", + "connection_sync": "Povezivanje i sinkronizacija", + "connectWalletPrompt": "Povežite svoj novčanik s WalletConnectom za obavljanje transakcija", + "contact": "Kontakt", + "contact_list_contacts": "Kontakti", + "contact_list_wallets": "Moji novčanici", + "contact_name": "Ime kontakta", + "contact_support": "Kontaktirajte podršku", + "continue_text": "Nastavak", + "contractName": "Naziv ugovora", + "contractSymbol": "Simbol ugovora", + "copied_key_to_clipboard": "${key} kopiran u međuspremnik", + "copied_to_clipboard": "Kopirano u međuspremnik", + "copy": "Kopiraj", + "copy_address": "Kopiraj adresu", + "copy_id": "Kopirati ID", + "copyWalletConnectLink": "Kopirajte vezu WalletConnect iz dApp-a i zalijepite je ovdje", + "create_account": "Stvori račun", + "create_backup": "Stvori sigurnosnu kopiju", + "create_donation_link": "Izradi poveznicu za donaciju", + "create_invoice": "Izradite fakturu", + "create_new": "Izradi novi novčanik", + "create_new_account": "Izradi novi račun", + "creating_new_wallet": "Stvaranje novog novčanika", + "creating_new_wallet_error": "Greška: ${description}", + "creation_date": "Datum stvaranja", + "custom": "prilagođeno", + "custom_drag": "Prilagođeni (držite i povucite)", + "custom_redeem_amount": "Prilagođeni iznos otkupa", + "dark_theme": "Tamna", + "debit_card": "Debitna kartica", + "debit_card_terms": "Pohranjivanje i korištenje broja vaše platne kartice (i vjerodajnica koje odgovaraju broju vaše platne kartice) u ovom digitalnom novčaniku podliježu Uvjetima i odredbama važećeg ugovora vlasnika kartice s izdavateljem platne kartice, koji su na snazi ​​od S vremena na vrijeme.", + "decimal_places_error": "Previše decimalnih mjesta", + "default_buy_provider": "Zadani davatelj kupnje", + "default_sell_provider": "Zadani dobavljač prodaje", + "delete": "Izbriši", + "delete_account": "Izbriši račun", + "delete_wallet": "Izbriši novčanik", + "delete_wallet_confirm_message": "Jeste li sigurni da želite izbrisati ${wallet_name} novčanik?", + "deleteConnectionConfirmationPrompt": "Jeste li sigurni da želite izbrisati vezu s", + "descending": "Silazni", + "description": "Opis", + "destination_tag": "Odredišna oznaka:", + "dfx_option_description": "Kupujte kripto s EUR i CHF. Do 990 € bez dodatnog KYC-a. Za maloprodajne i poslovne korisnike u Europi", + "didnt_get_code": "Ne dobivate kod?", + "digit_pin": "-znamenkasti PIN", + "digital_and_physical_card": "digitalna i fizička unaprijed plaćena debitna kartica", + "disable": "Onemogući", + "disable_buy": "Onemogući kupnju", + "disable_cake_2fa": "Onemogući Cake 2FA", + "disable_exchange": "Onemogući exchange", + "disable_fiat": "Isključi, fiat", + "disable_sell": "Onemogući akciju prodaje", + "disabled": "Onemogućeno", + "discount": "Uštedite ${value}%", + "display_settings": "Postavke zaslona", + "displayable": "Dostupno za prikaz", + "do_not_have_enough_gas_asset": "Nemate dovoljno ${currency} da izvršite transakciju s trenutačnim uvjetima blockchain mreže. Trebate više ${currency} da platite naknade za blockchain mrežu, čak i ako šaljete drugu imovinu.", + "do_not_send": "Ne šalji", + "do_not_share_warning_text": "Nemojte ih dijeliti ni s kim, uključujući podršku.\n\nVaša sredstva mogu i bit će ukradena!", + "do_not_show_me": "Ne pokazuj mi ovo više", + "domain_looks_up": "Pretraga domena", + "donation_link_details": "Detalji veza za donacije", + "e_sign_consent": "E-Sign pristanak", + "edit": "Uredi", + "edit_backup_password": "Uredi lozinku za sigurnosnu kopiju", + "edit_node": "Uredi čvor", + "edit_token": "Uredi token", + "electrum_address_disclaimer": "Minden egyes alkalommal új címeket generálunk, de a korábbi címek továbbra is működnek", + "email_address": "Adresa e-pošte", + "enabled": "Omogućeno", + "enter_amount": "Unesite iznos", + "enter_backup_password": "Unesite svoju lozinku za sigurnosnu kopiju ovdje", + "enter_code": "Unesite kod", + "enter_seed_phrase": "Unesite svoju sjemensku frazu", + "enter_totp_code": "Unesite TOTP kod.", + "enter_your_note": "Unesite svoju poruku…", + "enter_your_pin": "Upišite PIN", + "enter_your_pin_again": "Ponovno upišite pin", + "enterTokenID": "Unesite ID tokena", + "enterWalletConnectURI": "Unesite WalletConnect URI", + "error": "Greška", + "error_dialog_content": "Ups, imamo grešku.\n\nPošaljite izvješće o padu našem timu za podršku kako bismo poboljšali aplikaciju.", + "error_text_account_name": "Ime računa smije sadržavati samo slova i brojeve\nte mora biti dužine između 1 i 15 znakova", + "error_text_address": "Adresa novčanika mora odgovarati\nvrsti kriptovalute", + "error_text_amount": "Iznos smije sadržavati samo brojeve", + "error_text_contact_name": "Ime kontakta ne smije sadržavati znakove ` , ' \" \ni mora biti dužine između 1 i 32 znaka", + "error_text_crypto_currency": "Broj decimala mora\nbiti 12 ili manji", + "error_text_fiat": "Vrijednost iznosa ne smije biti veća od raspoloživog iznosa.\nBroj decimala smije biti 2 ili manji.", + "error_text_input_above_maximum_limit": "Iznos je veći od maskimalnog", + "error_text_input_below_minimum_limit": "Iznos je manji od minimalnog", + "error_text_keys": "Novčanik smije sadržavati samo 64 znakova hex vrijednosti", + "error_text_limits_loading_failed": "Razmjena za ${provider} nije izrađena. Neuspješno učitavanje limita", + "error_text_maximum_limit": "Razmjena za ${provider} nije izrađena. Iznos je veći od maskimalnog: ${max} ${currency}", + "error_text_minimal_limit": "Razmjena za ${provider} nije izrađena. Iznos je manji od minimalnog: ${min} ${currency}", + "error_text_node_address": "Molimo unesite iPv4 adresu", + "error_text_node_port": "Node port smije sadržavati samo brojeve između 0 i 65535", + "error_text_node_proxy_address": "Unesite :, na primjer 127.0.0.1:9050", + "error_text_payment_id": "ID plaćanja smije sadržavati samo od 16 do 64 znakova hex vrijednosti", + "error_text_subaddress_name": "Ime podadrese ne smije sadržavati znakove ` , ' \" \ni mora biti dužine između 1 i 20 znakova", + "error_text_template": "Ime i adresa predloška ne smiju sadržavati znakove ` , ' \" \ni moraju biti dužine između 1 i 106 znakova", + "error_text_wallet_name": "Naziv novčanika može sadržavati samo slova, brojeve, _ - simbole\ni mora imati između 1 i 33 znaka", + "error_text_xmr": "XMR vrijednost ne smije biti veća od raspoloživog iznosa.\nBroj decimala smije biti 12 ili manji.", "errorGettingCredentials": "Neuspješno: Pogreška prilikom dobivanja vjerodajnica", "errorSigningTransaction": "Došlo je do pogreške prilikom potpisivanja transakcije", - "pairingInvalidEvent": "Nevažeći događaj uparivanja", - "chains": "Lanci", - "methods": "Metode", - "events": "Događaji", - "reject": "Odbiti", - "approve": "Odobriti", - "expiresOn": "Istječe", - "walletConnect": "WalletConnect", - "nullURIError": "URI je nula", - "connectWalletPrompt": "Povežite svoj novčanik s WalletConnectom za obavljanje transakcija", - "newConnection": "Nova veza", - "activeConnectionsPrompt": "Ovdje će se pojaviti aktivne veze", - "deleteConnectionConfirmationPrompt": "Jeste li sigurni da želite izbrisati vezu s", + "estimated": "procijenjen", + "etherscan_history": "Etherscan povijest", "event": "Događaj", - "successful": "Uspješno", - "wouoldLikeToConnect": "želio bi se povezati", - "message": "Poruka", - "do_not_have_enough_gas_asset": "Nemate dovoljno ${currency} da izvršite transakciju s trenutačnim uvjetima blockchain mreže. Trebate više ${currency} da platite naknade za blockchain mrežu, čak i ako šaljete drugu imovinu.", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Molimo pričekajte da dApp završi obradu.", - "copyWalletConnectLink": "Kopirajte vezu WalletConnect iz dApp-a i zalijepite je ovdje", - "enterWalletConnectURI": "Unesite WalletConnect URI", - "seed_key": "Sjemenski ključ", - "enter_seed_phrase": "Unesite svoju sjemensku frazu", - "change_rep_successful": "Uspješno promijenjena reprezentativna", - "add_contact": "Dodaj kontakt", + "events": "Događaji", + "exchange": "Razmijeni", + "exchange_incorrect_current_wallet_for_xmr": "Ako želite razmijeniti XMR s vlastitog Monero računa na Cake Wallet novčaniku, molimo prvo se prebacite na svoj Monero novčanik.", + "exchange_new_template": "Novi predložak", "exchange_provider_unsupported": "${providerName} više nije podržan!", - "domain_looks_up": "Pretraga domena", - "require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike", - "camera_permission_is_required": "Potrebno je dopuštenje kamere.\nOmogućite ga u postavkama aplikacije.", - "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno", - "order_by": "Narediti", - "creation_date": "Datum stvaranja", + "exchange_result_confirm": "Pritiskom na potvrdi, poslat ćete ${fetchingLabel} ${from} sa svog novčanika pod nazivom ${walletName} na adresu prikazanu ispod ili iznos možete poslati s vanjskog novčanika na niže navedenu adresu. /QR code.\n\nMolimo potvrdite za nastavak ili se vratite natrag za promjenu iznosa.", + "exchange_result_description": "Potrebno poslati minimalno ${fetchingLabel} ${from} na adresu prikazanu na sljedećoj stranici. Ukoliko pošaljete iznos manji od ${fetchingLabel} ${from}, postoji mogućnost da razmjena neće biti uspješna i da iznos neće biti vraćen.", + "exchange_result_write_down_ID": "*Molimo kopirajte ili zapišite svoj ID prikazan ispod.", + "exchange_result_write_down_trade_id": "Molimo kopirajte ili zapišite transakcijski ID za nastavak.", + "exchange_sync_alert_content": "Molimo pričekajte dok se Vaš novčanik ne sinkronizira.", + "expired": "Isteklo", + "expires": "Ističe", + "expiresOn": "Istječe", + "export_backup": "Izvezi sigurnosnu kopiju", + "extra_id": "Dodatni ID:", + "extracted_address_content": "Poslat ćete sredstva primatelju\n${recipient_name}", + "failed_authentication": "Autentifikacija neuspješna. ${state_error}", + "faq": "FAQ", + "fetching": "Dohvaćanje", + "fiat_api": "Fiat API", + "fiat_balance": "Fiat Bilans", + "field_required": "ovo polje je obavezno", + "fill_code": "Molimo vas da ispunite kontrolni kod koji ste dobili na svojoj e-pošti", + "filter_by": "Filtrirati po", + "first_wallet_text": "Odličan novčanik za Monero, Bitcoin, Ethereum, Litecoin, i Haven", + "fixed_pair_not_supported": "Ovaj fiksni par nije podržan s odabranim burzama", + "fixed_rate": "Fiksna stopa", + "fixed_rate_alert": "Moći ćete unijeti iznos koji želite primiti nakon što označite način rada fiksne stope. Želite li se prebaciti na način rada fiksne stope?", + "forgot_password": "Zaboravljena lozinka", + "freeze": "Zamrznuti", + "frequently_asked_questions": "Često postavljana pitanja", + "frozen": "Smrznuto", + "full_balance": "Pun iznos", + "generate_name": "Generiraj ime", + "generating_gift_card": "Generiranje darovne kartice", + "get_a": "Nabavite ", + "get_card_note": " koju možete ponovno napuniti digitalnim valutama. Nisu potrebne dodatne informacije!", + "get_your_yat": "Uzmi svoj Yat", + "gift_card_amount": "Iznos darovne kartice", + "gift_card_balance_note": "Ovdje će se pojaviti darovne kartice s preostalim saldom", + "gift_card_is_generated": "Poklon kartica je generirana", + "gift_card_number": "Broj darovne kartice", + "gift_card_redeemed_note": "Poklon kartice koje ste iskoristili pojavit će se ovdje", + "gift_cards": "Ajándékkártya", + "gift_cards_unavailable": "Poklon kartice trenutno su dostupne za kupnju samo putem Monera, Bitcoina i Litecoina", + "got_it": "U redu", + "gross_balance": "Bruto bilanca", "group_by_type": "Grupirati", - "importNFTs": "Uvoz NFT-ova", - "noNFTYet": "Još nema NFT-ova", - "address": "Adresa", - "enterTokenID": "Unesite ID tokena", - "tokenID": "iskaznica", - "name": "Ime", - "symbol": "Simbol", - "seed_phrase_length": "Duljina početne fraze", - "unavailable_balance": "Nedostupno stanje", - "unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.", - "unspent_change": "Promijeniti", - "tor_connection": "Tor veza", - "setup_warning_2fa_text": "Morat ćete obnoviti svoj novčanik iz mnemoničkog sjemena.\n\nPodrška za kolače neće vam moći pomoći ako izgubite pristup svojim 2FA ili mnemoničkim izvorima.\nCake 2FA je druga provjera autentičnosti za određene radnje u novčaniku. Prije uporabe Cake 2FA preporučujemo da pročitate vodič.NIJE siguran kao hladno skladište.\n\nAko izgubite pristup svojoj 2FA aplikaciji ili TOTP ključevima, IZGUBIT ĆETE pristup ovom novčaniku. ", - "scan_qr_on_device": "Skenirajte ovaj QR kod na drugom uređaju", + "haven_app": "Haven by Cake Wallet", + "haven_app_wallet_text": "Awesome wallet for Haven", + "help": "pomozite", + "hidden_balance": "Skriven iznos", + "hide_details": "Sakrij pojedinosti", + "high_contrast_theme": "Tema visokog kontrasta", + "home_screen_settings": "Postavke početnog zaslona", "how_to_use": "Kako koristiti", + "how_to_use_card": "Kako koristiti ovu karticu", + "id": "ID: ", + "ignor": "Zanemariti", + "import": "Uvoz", + "importNFTs": "Uvoz NFT-ova", + "in_store": "U trgovini", + "incoming": "Dolazno", + "incorrect_seed": "Uneseni tekst nije valjan.", + "introducing_cake_pay": "Predstavljamo Cake Pay!", + "invalid_input": "Pogrešan unos", + "invoice_details": "Podaci o fakturi", + "is_percentage": "je", + "last_30_days": "Zadnjih 30 dana", + "learn_more": "Saznajte više", + "light_theme": "Svijetla", + "loading_your_wallet": "Novčanik se učitava", + "login": "Prijava", + "logout": "Odjava", + "low_fee": "Niska naknada", + "low_fee_alert": "Trenutačno koristite niski prioritet mrežne naknade. To bi moglo uzrokovati duga čekanja, različite tečajeve ili otkazane trgovine. Preporučujemo postavljanje veće naknade za bolje iskustvo.", + "manage_nodes": "Upravljanje čvorovima", + "manage_pow_nodes": "Upravljanje PoW čvorovima", + "manage_yats": "Upravljanje Yat", + "mark_as_redeemed": "Označi kao otkupljeno", + "market_place": "Tržnica", + "matrix_green_dark_theme": "Matrix Green Dark Theme", + "max_amount": "Maksimum: ${value}", + "max_value": "Maks.: ${value} ${currency}", + "memo": "Memo:", + "message": "Poruka", + "methods": "Metode", + "min_amount": "Minimalno: ${value}", + "min_value": "Min.: ${value} ${currency}", + "minutes_to_pin_code": "${minute} minuta", + "mm": "MM", + "modify_2fa": "Izmijenite tortu 2FA", + "monero_com": "Monero.com by Cake Wallet", + "monero_com_wallet_text": "Awesome wallet for Monero", + "monero_dark_theme": "Monero tamna tema", + "monero_light_theme": "Monero lagana tema", + "moonpay_alert_text": "Vrijednost iznosa mora biti veća ili jednaka ${minAmount} ${fiatCurrency}", + "more_options": "Više opcija", + "name": "Ime", + "narrow": "Usko", + "new_first_wallet_text": "Jednostavno čuvajte svoju kripto valutu", + "new_node_testing": "Provjera novog nodea", + "new_subaddress_create": "Izradi", + "new_subaddress_label_name": "Oznaka", + "new_subaddress_title": "Nova adresa", + "new_template": "novi predložak", + "new_wallet": "Novi novčanik", + "newConnection": "Nova veza", + "no_id_needed": "Nije potreban ID!", + "no_id_required": "Nije potreban ID. Nadopunite i potrošite bilo gdje", + "no_relay_on_domain": "Ne postoji relej za korisničku domenu ili je relej nedostupan. Odaberite relej za korištenje.", + "no_relays": "Nema releja", + "no_relays_message": "Pronašli smo zapis Nostr NIP-05 za ovog korisnika, ali on ne sadrži nikakve releje. Uputite primatelja da doda releje u svoj Nostr zapis.", + "node_address": "Node adresa", + "node_connection_failed": "Neuspješno spajanje", + "node_connection_successful": "Uspješno spajanje", + "node_new": "Novi node", + "node_port": "Node port", + "node_reset_settings_title": "Resetiraj postavke", + "node_test": "Provjeri", + "nodes": "Nodes", + "nodes_list_reset_to_default_message": "Jeste li sigurni da se želite vratiti na početne postavke?", + "none_of_selected_providers_can_exchange": "Niti jedan od odabranih pružatelja usluga ne može izvršiti ovu razmjenu", + "noNFTYet": "Još nema NFT-ova", + "normal": "Normalno", + "note_optional": "Poruka (nije obvezno)", + "note_tap_to_change": "Poruka (dodirnite za promjenu)", + "nullURIError": "URI je nula", + "offer_expires_in": "Ponuda istječe za: ", + "offline": "izvan mreže", + "ok": "OK", + "onion_link": "Poveznica luka", + "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", + "optional_description": "Opcijski opis", + "optional_email_hint": "Neobavezna e-pošta za obavijest primatelja", + "optional_name": "Izborno ime primatelja", + "optionally_order_card": "Opcionalno naručite fizičku karticu.", + "orbot_running_alert": "Provjerite radi li Orbot prije spajanja na ovaj čvor.", + "order_by": "Narediti", + "order_id": "ID narudžbe", + "order_physical_card": "Naručite fizičku karticu", + "other_settings": "Ostale postavke", + "outdated_electrum_wallet_description": "Novi Bitcoin novčanici stvoreni u Cakeu sada imaju sjeme od 24 riječi. Obavezno je stvoriti novi Bitcoin novčanik i prenijeti sva svoja sredstva u novi novčanik od 24 riječi te prestati koristiti novčanike s sjemenkom od 12 riječi. Učinite to odmah kako biste osigurali svoja sredstva.", + "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", + "overwrite_amount": "Overwrite amount", + "pairingInvalidEvent": "Nevažeći događaj uparivanja", + "password": "Lozinka", + "paste": "Zalijepi", + "pause_wallet_creation": "Mogućnost stvaranja novčanika Haven trenutno je pauzirana.", + "payment_id": "ID plaćanja: ", + "payment_was_received": "Vaša uplata je primljena.", + "pending": " (u tijeku)", + "percentageOf": "od ${amount}", + "pin_at_top": "prikvači ${token} na vrh", + "pin_is_incorrect": "Netočan PIN", + "pin_number": "PIN broj", + "placeholder_contacts": "Vaši će kontakti biti prikazani ovdje", + "placeholder_transactions": "Vaše će transakcije biti prikazane ovdje", + "please_fill_totp": "Unesite 8-znamenkasti kod koji se nalazi na vašem drugom uređaju", + "please_make_selection": "Molimo odaberite opcije niže za izradu novog novčanika ili za oporavak postojećeg.", + "please_reference_document": "Molimo pogledajte dokumente ispod za više informacija.", + "please_select": "Molimo odaberite:", + "please_select_backup_file": "Molimo odaberite datoteku sigurnosne kopije i unesite lozinku za sigurnosnu kopiju.", + "please_try_to_connect_to_another_node": "Molimo pokušajte se spojiti na drugi node.", + "please_wait": "Molimo pričekajte", + "polygonscan_history": "Povijest PolygonScan", + "powered_by": "Omogućio ${title}", + "pre_seed_button_text": "Razumijem. Prikaži mi moj pristupni izraz", + "pre_seed_description": "Na sljedećoj ćete stranici vidjeti niz ${words} riječi. Radi se o Vašem jedinstvenom i tajnom pristupnom izrazu koji je ujedno i JEDINI način na koji možete oporaviti svoj novčanik u slučaju gubitka ili kvara. VAŠA je odgovornost zapisati ga te pohraniti na sigurno mjesto izvan Cake Wallet aplikacije.", + "pre_seed_title": "VAŽNO", + "prevent_screenshots": "Spriječite snimke zaslona i snimanje zaslona", + "privacy": "Privatnost", + "privacy_policy": "Pravila privatnosti", + "privacy_settings": "Postavke privatnosti", + "private_key": "Privatni ključ", + "proceed_after_one_minute": "Ako se zaslon ne nastavi nakon 1 minute, provjerite svoju e-poštu.", + "profile": "Profil", + "provider_error": "${provider} greška", + "public_key": "Javni ključ", + "purchase_gift_card": "Kupnja darovne kartice", + "qr_fullscreen": "Dodirnite za otvaranje QR koda preko cijelog zaslona", + "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", + "question_to_disable_2fa": "Jeste li sigurni da želite onemogućiti Cake 2FA? 2FA kod više neće biti potreban za pristup novčaniku i određenim funkcijama.", + "receivable_balance": "Stanje potraživanja", + "receive": "Primi", + "receive_amount": "Iznos", + "received": "Primljeno", + "recipient_address": "Primateljeva adresa", + "reconnect": "Ponovno povezivanje", + "reconnect_alert_text": "Jeste li sigurni da se želite ponovno povezati?", + "reconnection": "Ponovno povezivanje", + "redeemed": "otkupljeno", + "refund_address": "Adresa za povrat", + "reject": "Odbiti", + "remaining": "preostalo", + "remove": "Ukloni", + "remove_node": "Ukloni node", + "remove_node_message": "Jeste li sigurni da želite ukloniti odabrani node?", + "rename": "Preimenuj", + "require_for_adding_contacts": "Zahtijeva za dodavanje kontakata", + "require_for_all_security_and_backup_settings": "Zahtijeva za sve postavke sigurnosti i sigurnosne kopije", + "require_for_assessing_wallet": "Potreban za pristup novčaniku", + "require_for_creating_new_wallets": "Potreban za kreiranje novih novčanika", + "require_for_exchanges_to_external_wallets": "Zahtijeva razmjene na vanjske novčanike", + "require_for_exchanges_to_internal_wallets": "Potreban za razmjenu na interne novčanike", + "require_for_sends_to_contacts": "Zahtijeva za slanje kontaktima", + "require_for_sends_to_internal_wallets": "Zahtijeva za slanje u interne novčanike", + "require_for_sends_to_non_contacts": "Zahtijeva za slanje nekontaktima", + "require_pin_after": "Zahtijevaj PIN nakon", + "rescan": "Ponovno skeniranje", + "resend_code": "Molimo da ga ponovno pošaljete", + "reset": "Resetiraj", + "reset_password": "Poništi lozinku", + "restore_active_seed": "Aktivan pristupni izraz", + "restore_address": "Adresa", + "restore_bitcoin_description_from_keys": "Oporavi novčanik pomoću WIF niza generiranog iz vlastitih privatnih ključeva (keys)", + "restore_bitcoin_description_from_seed": "Oporavi novčanik pomoću koda od 12 riječi", + "restore_bitcoin_title_from_keys": "Oporavi pomoću formata uvoza novčanika (WIF)", + "restore_description_from_backup": "Možete oporaviti cijelu Cake Wallet aplikaciju pomoću vlastite datoteke sa sigurnosnom kopijom", + "restore_description_from_keys": "Oporavi novčanik pomoću generiranih pritisaka na tipke spremljenih od vlastitih privatnih ključeva (keys)", + "restore_description_from_seed": "Oporavi novčanik pomoću koda koji sadrži kombinaciju od 25 ili 13 riječi", + "restore_description_from_seed_keys": "Oporavi novčanik pomoću pristupnog izraza/ključa spremljenog na sigurno mjesto", + "restore_from_date_or_blockheight": "Molimo unesite datum od nekoliko dana prije nego što ste izradili ovaj novčanik ili ako znate visinu bloka, molimo unesite je.", + "restore_from_seed_placeholder": "Molimo unesite ili zalijepite svoj pristupni izraz ovdje", + "restore_new_seed": "Novi pristupi izraz", + "restore_next": "Dalje", + "restore_recover": "Oporavi", + "restore_restore_wallet": "Oporavi novčanik", + "restore_seed_keys_restore": "Oporavak pomoću pristupnog izraza/ključa", + "restore_spend_key_private": "Spend key (privatni)", + "restore_title_from_backup": "Oporavak pomoću sigurnosne kopije", + "restore_title_from_keys": "Oporavi pomoću ključa", + "restore_title_from_seed": "Oporavi pomoću pristupnog izraza", + "restore_title_from_seed_keys": "Oporavi pomoću pristupnog izraza/ključa", + "restore_view_key_private": "View key (privatni)", + "restore_wallet": "Oporavi novčanik", + "restore_wallet_name": "Ime novčanika", + "restore_wallet_restore_description": "Opis oporavka novčanika", + "router_no_route": "Nije definirana ruta za ${name}", + "save": "Spremi", + "save_backup_password": "Molimo pobrinite se da spremite svoju lozinku za sigurnosnu kopiju. Bez nje nećete moći uvesti datoteke sigurnosne kopije.", + "save_backup_password_alert": "Spremi lozinku za sigurnosnu kopiju", + "save_to_downloads": "Spremi u Preuzimanja", + "saved_the_trade_id": "Spremio/la sam transakcijski ID", + "scan_qr_code": "Skenirajte QR kod", + "scan_qr_code_to_get_address": "Skeniraj QR kod za dobivanje adrese", + "scan_qr_on_device": "Skenirajte ovaj QR kod na drugom uređaju", + "search": "Traži", + "search_add_token": "Traži / Dodaj token", + "search_category": "Kategorija pretraživanja", + "search_currency": "Traži valutu", + "search_language": "Jezik pretraživanja", + "second_intro_content": "Vaš Yat jedinstvena je adresa emojija koja zamjenjuje sve vaše duge heksadecimalne adrese za sve vaše valute.", + "second_intro_title": "Jedna adresa emojija koja će svima njima vladati", + "security_and_backup": "Sigurnost i sigurnosna kopija", + "seed_alert_back": "Vrati se natrag", + "seed_alert_content": "Pristupni izraz jedini je način za oporavak novčanika. Jeste li ga zapisali?", + "seed_alert_title": "Upozorenje", + "seed_alert_yes": "Jesam", + "seed_choose": "Odaberi jezik pristupnog izraza", "seed_hex_form": "Sjeme novčanika (šesterokutni oblik)", + "seed_key": "Sjemenski ključ", + "seed_language": "Sjemeni jezik", + "seed_language_chinese": "Kineski", + "seed_language_chinese_traditional": "Kinesko (tradicionalno)", + "seed_language_czech": "češki", + "seed_language_dutch": "Nizozemski", + "seed_language_english": "Engleski", + "seed_language_french": "Francuski", + "seed_language_german": "Njemački", + "seed_language_italian": "Talijanski", + "seed_language_japanese": "Japanski", + "seed_language_korean": "korejski", + "seed_language_next": "Dalje", + "seed_language_portuguese": "Portugalski", + "seed_language_russian": "Ruski", + "seed_language_spanish": "Španjolski", + "seed_phrase_length": "Duljina početne 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", "seedtype": "Sjemenska vrsta", "seedtype_legacy": "Nasljeđe (25 riječi)", "seedtype_polyseed": "Poliseed (16 riječi)", - "seed_language_czech": "češki", - "seed_language_korean": "korejski", - "ascending": "Uzlazni", - "descending": "Silazni", - "seed_language_chinese_traditional": "Kinesko (tradicionalno)", - "dfx_option_description": "Kupujte kripto s EUR i CHF. Do 990 € bez dodatnog KYC-a. Za maloprodajne i poslovne korisnike u Europi", - "polygonscan_history": "Povijest PolygonScan", - "wallet_seed_legacy": "Sjeme naslijeđenog novčanika", - "default_sell_provider": "Zadani dobavljač prodaje", + "select_backup_file": "Odaberite datoteku sigurnosne kopije", + "select_buy_provider_notice": "Odaberite gornji davatelj kupnje. Ovaj zaslon možete preskočiti postavljanjem zadanog davatelja usluga kupnje u postavkama aplikacija.", + "select_destination": "Odaberite odredište za datoteku sigurnosne kopije.", "select_sell_provider_notice": "Gore odaberite pružatelja usluga prodaje. Ovaj zaslon možete preskočiti postavljanjem zadanog pružatelja usluga prodaje u postavkama aplikacije.", - "custom_drag": "Prilagođeni (držite i povucite)", + "sell": "Prodavati", + "sell_alert_content": "Trenutno podržavamo samo prodaju Bitcoina, Ethereuma i Litecoina. Izradite ili prijeđite na svoj Bitcoin, Ethereum ili Litecoin novčanik.", + "sell_monero_com_alert_content": "Prodaja Monera još nije podržana", + "send": "Pošalji", + "send_address": "${cryptoCurrency} adresa", + "send_amount": "Iznos:", + "send_creating_transaction": "Izrada transakcije", + "send_error_currency": "Iznos smije sadržavati samo brojeve", + "send_error_minimum_value": "Minimalna vrijednost iznosa je 0.01", + "send_estimated_fee": "Procijenjena naknada:", + "send_fee": "Naknada:", + "send_name": "Ime", + "send_new": "Novi", + "send_payment_id": "ID plaćanja (nije obvezno)", + "send_priority": "Trenutno se naknada nalazi na ${transactionPriority} mjestu prioriteta.\nPrioritet transakcije moguće je prilagoditi u postavkama", + "send_sending": "Slanje...", + "send_success": "Vaš ${crypto} je uspješno poslan", + "send_templates": "Predlošci", + "send_title": "Pošalji", + "send_to_this_address": "Pošaljite ${currency} ${tag}na ovu adresu", + "send_xmr": "Pošalji XMR", + "send_your_wallet": "Tvoj novčanik", + "sending": "Slanje", + "sent": "Poslano", + "settings": "Postavke", + "settings_all": "SVE", + "settings_allow_biometrical_authentication": "Dopusti biometrijsku autentifikaciju", + "settings_can_be_changed_later": "Te se postavke mogu promijeniti kasnije u postavkama aplikacije", + "settings_change_language": "Promijeni jezik", + "settings_change_pin": "Promijeni PIN", + "settings_currency": "Valuta", + "settings_current_node": "Trenutni node", + "settings_dark_mode": "Tamni način rada", + "settings_display_balance": "Prikaži stanje računa", + "settings_display_on_dashboard_list": "Prikaži na listi kontrolne ploče", + "settings_fee_priority": "Prioritet naknade", + "settings_nodes": "Nodovi", + "settings_none": "Nijedno", + "settings_only_trades": "Samo razmjene", + "settings_only_transactions": "Samo transakcije", + "settings_personal": "Osobni", + "settings_save_recipient_address": "Spremi primateljevu adresu", + "settings_support": "Podrška", + "settings_terms_and_conditions": "Uvjeti i odredbe", + "settings_title": "Postavke", + "settings_trades": "Razmjene", + "settings_transactions": "Transakcije", + "settings_wallets": "Novčanik", + "setup_2fa": "Postavljanje torte 2FA", + "setup_2fa_text": "Cake 2FA radi koristeći TOTP kao drugi faktor provjere autentičnosti.\n\nCake 2FA TOTP zahtijeva SHA-512 i podršku za 8 znamenki; ovo osigurava povećanu sigurnost. Više informacija i podržanih aplikacija možete pronaći u vodiču.", + "setup_pin": "Podesi PIN", + "setup_successful": "Vaš je pin uspješno postavljen!", + "setup_totp_recommended": "Postavite TOTP", + "setup_warning_2fa_text": "Morat ćete obnoviti svoj novčanik iz mnemoničkog sjemena.\n\nPodrška za kolače neće vam moći pomoći ako izgubite pristup svojim 2FA ili mnemoničkim izvorima.\nCake 2FA je druga provjera autentičnosti za određene radnje u novčaniku. Prije uporabe Cake 2FA preporučujemo da pročitate vodič.NIJE siguran kao hladno skladište.\n\nAko izgubite pristup svojoj 2FA aplikaciji ili TOTP ključevima, IZGUBIT ĆETE pristup ovom novčaniku. ", + "setup_your_debit_card": "Postavite svoju debitnu karticu", + "share": "Udio", + "share_address": "Podijeli adresu", + "show_details": "Prikaži pojedinosti", + "show_keys": "Prikaži pristupni izraz/ključ", + "show_market_place": "Prikaži tržište", + "show_seed": "Prikaži pristupni izraz", + "sign_up": "Prijavite se", + "signTransaction": "Potpišite transakciju", + "signup_for_card_accept_terms": "Prijavite se za karticu i prihvatite uvjete.", + "slidable": "Klizna", + "sort_by": "Poredaj po", + "spend_key_private": "Spend key (privatni)", + "spend_key_public": "Spend key (javni)", + "status": "Status: ", + "subaddress_title": "Lista podadresa", + "subaddresses": "Podadrese", + "submit_request": "podnesi zahtjev", + "successful": "Uspješno", + "support_description_guides": "Dokumentacija i podrška za uobičajena pitanja", + "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_live_chat": "Podrška uživo", + "support_title_other_links": "Ostale veze za podršku", + "sweeping_wallet": "Čisti novčanik", + "sweeping_wallet_alert": "Ovo ne bi trebalo dugo trajati. NE NAPUŠTAJTE OVAJ ZASLON INAČE SE POBREŠENA SREDSTVA MOGU IZGUBITI", + "switchToETHWallet": "Prijeđite na Ethereum novčanik i pokušajte ponovno", "switchToEVMCompatibleWallet": "Prijeđite na novčanik kompatibilan s EVM-om i pokušajte ponovno (Ethereum, Polygon)", - "receivable_balance": "Stanje potraživanja", - "confirmed_tx": "Potvrđen", + "symbol": "Simbol", + "sync_all_wallets": "Sinkronizirajte sve novčanike", + "sync_status_attempting_sync": "POKUŠAJ SINKRONIZACIJE", + "sync_status_connected": "SPOJENO", + "sync_status_connecting": "SPAJANJE", + "sync_status_failed_connect": "ISKLJUČENO", + "sync_status_not_connected": "NIJE POVEZANO", + "sync_status_starting_sync": "ZAPOČINJEMO SINKRONIZIRANJE", + "sync_status_syncronized": "SINKRONIZIRANO", + "sync_status_syncronizing": "SINKRONIZIRANJE", + "syncing_wallet_alert_content": "Vaš saldo i popis transakcija možda neće biti potpuni sve dok na vrhu ne piše \"SINKRONIZIRANO\". Kliknite/dodirnite da biste saznali više.", + "syncing_wallet_alert_title": "Vaš novčanik se sinkronizira", + "template": "Predložak", + "template_name": "Naziv predloška", + "third_intro_content": "Yats žive i izvan Cake Wallet -a. Bilo koja adresa novčanika na svijetu može se zamijeniti Yat!", + "third_intro_title": "Yat se lijepo igra s drugima", + "time": "${minutes}m ${seconds}s", + "tip": "Savjet:", + "today": "Danas", + "token_contract_address": "Adresa ugovora tokena", + "token_decimal": "Token decimalni", + "token_name": "Naziv tokena npr.: Tether", + "token_symbol": "Simbol tokena npr.: USDT", + "tokenID": "iskaznica", + "tor_connection": "Tor veza", + "tor_only": "Samo Tor", + "total_saving": "Ukupna ušteda", + "totp_2fa_failure": "Neispravan kod. Pokušajte s drugim kodom ili generirajte novi tajni ključ. Koristite kompatibilnu 2FA aplikaciju koja podržava 8-znamenkasti kod i SHA512.", + "totp_2fa_success": "Uspjeh! Cake 2FA omogućen za ovaj novčanik. Ne zaboravite spremiti svoje mnemoničko sjeme u slučaju da izgubite pristup novčaniku.", + "totp_auth_url": "TOTP AUTH URL", + "totp_code": "TOTP kod", + "totp_secret_code": "TOTP tajni kod", + "totp_verification_success": "Provjera uspješna!", + "trade_details_copied": "${title} kopiran u međuspremnik", + "trade_details_created_at": "Stvoreno u", + "trade_details_fetching": "Dohvaćanje", + "trade_details_id": "ID", + "trade_details_pair": "Upari", + "trade_details_provider": "Pružatelj", + "trade_details_state": "Status", + "trade_details_title": "Detalji razmjene", + "trade_for_not_created": "Razmjena za ${title} nije izrađena.", + "trade_history_title": "Povijest razmjena", + "trade_id": "Transakcijski ID:", + "trade_id_not_found": "Razmjena ${tradeId} za ${title} nije pronađena.", + "trade_is_powered_by": "Razmjenu je omogućio ${provider}", + "trade_not_created": "Razmjena nije izrađena", + "trade_not_found": "Razmjena nije pronađena.", + "trade_state_btc_sent": "BTC poslan", + "trade_state_complete": "Dovršeno", + "trade_state_confirming": "Potvrđivanje", + "trade_state_created": "Stvoreno", + "trade_state_finished": "Završeno", + "trade_state_paid": "Plaćen", + "trade_state_paid_unconfirmed": "Plaćanje nije potrđeno", + "trade_state_pending": "U tijeku", + "trade_state_timeout": "Isteklo", + "trade_state_to_be_created": "Stvaranje", + "trade_state_traded": "Razmijenjeno", + "trade_state_trading": "Razmjenjivanje", + "trade_state_underpaid": "Nedovoljno plaćen", + "trade_state_unpaid": "Neplaćen", + "trades": "Razmjene", + "transaction_details_amount": "Iznos", + "transaction_details_copied": "${title} kopiran u međuspremnik", + "transaction_details_date": "Datum", + "transaction_details_fee": "Naknada", + "transaction_details_height": "Visina", + "transaction_details_recipient_address": "Adrese primatelja", "transaction_details_source_address": "Adresa izvora", - "pause_wallet_creation": "Mogućnost stvaranja novčanika Haven trenutno je pauzirana.", - "contractName": "Naziv ugovora", - "contractSymbol": "Simbol ugovora", - "description": "Opis", - "camera_consent": "Vaš će fotoaparat koristiti za snimanje slike u svrhu identifikacije od strane ${provider}. Pojedinosti potražite u njihovoj politici privatnosti.", - "no_relays": "Nema releja", - "choose_relay": "Odaberite relej za korištenje", - "no_relays_message": "Pronašli smo zapis Nostr NIP-05 za ovog korisnika, ali on ne sadrži nikakve releje. Uputite primatelja da doda releje u svoj Nostr zapis.", - "no_relay_on_domain": "Ne postoji relej za korisničku domenu ili je relej nedostupan. Odaberite relej za korištenje." -} + "transaction_details_title": "Detalji transakcije", + "transaction_details_transaction_id": "Transakcijski ID", + "transaction_key": "Transakcijski ključ", + "transaction_priority_fast": "Brzo", + "transaction_priority_fastest": "Najbrže", + "transaction_priority_medium": "Srednje", + "transaction_priority_regular": "Uobičajeno", + "transaction_priority_slow": "Sporo", + "transaction_sent": "Transakcija provedena!", + "transaction_sent_notice": "Ako se zaslon ne nastavi nakon 1 minute, provjerite block explorer i svoju e-poštu.", + "transactions": "Transakcije", + "transactions_by_date": "Transakcije prema datumu", + "trusted": "vjerovao", + "unavailable_balance": "Nedostupno stanje", + "unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.", + "unconfirmed": "Nepotvrđeno stanje", + "understand": "Razumijem", + "unmatched_currencies": "Valuta vašeg trenutnog novčanika ne odgovara onoj na skeniranom QR-u", + "unspent_change": "Promijeniti", + "unspent_coins_details_title": "Nepotrošeni detalji o novčićima", + "unspent_coins_title": "Nepotrošeni novčići", + "unsupported_asset": "Ne podržavamo ovu radnju za ovaj materijal. Izradite ili prijeđite na novčanik podržane vrste sredstava.", + "upto": "do ${value}", + "use": "Prebaci na", + "use_card_info_three": "Koristite digitalnu karticu online ili s beskontaktnim metodama plaćanja.", + "use_card_info_two": "Sredstva se pretvaraju u USD kada se drže na prepaid računu, a ne u digitalnim valutama.", + "use_ssl": "Koristi SSL", + "use_suggested": "Koristite predloženo", + "variable_pair_not_supported": "Ovaj par varijabli nije podržan s odabranim burzama", + "verification": "Potvrda", + "verify_with_2fa": "Provjerite s Cake 2FA", + "version": "Verzija ${currentVersion}", + "view_all": "Prikaži sve", + "view_in_block_explorer": "View in Block Explorer", + "view_key_private": "View key (privatni)", + "view_key_public": "View key (javni)", + "view_transaction_on": "View Transaction on ", + "wallet_keys": "Pristupni izraz/ključ novčanika", + "wallet_list_create_new_wallet": "Izradi novi novčanik", + "wallet_list_edit_wallet": "Uredi novčanik", + "wallet_list_failed_to_load": "Neuspješno učitavanje novčanika ${wallet_name}. ${error}", + "wallet_list_failed_to_remove": "Neuspješno uklanjanje novčanika ${wallet_name}. ${error}", + "wallet_list_load_wallet": "Učitaj novčanik", + "wallet_list_loading_wallet": "Učitavanje novčanika ${wallet_name}", + "wallet_list_removing_wallet": "Uklanjanje novčanika ${wallet_name}", + "wallet_list_restore_wallet": "Oporavi novčanik", + "wallet_list_title": "Monero novčanik", + "wallet_list_wallet_name": "Naziv novčanika", + "wallet_menu": "Izbornik", + "wallet_name": "Ime novčanika", + "wallet_name_exists": "Novčanik s tim nazivom već postoji", + "wallet_restoration_store_incorrect_seed_length": "Netočna dužina pristupnog izraza", + "wallet_seed": "Pristupni izraz novčanika", + "wallet_seed_legacy": "Sjeme naslijeđenog novčanika", + "wallet_store_monero_wallet": "Monero novčanik", + "walletConnect": "WalletConnect", + "wallets": "Novčanici", + "warning": "Upozorenje", + "welcome": "Dobrodošli na", + "welcome_to_cakepay": "Dobro došli u Cake Pay!", + "widgets_address": "Adresa", + "widgets_or": "ili", + "widgets_restore_from_blockheight": "Oporavi pomoću visine bloka", + "widgets_restore_from_date": "Oporavi pomoću datuma", + "widgets_seed": "pristupnog izraza", + "wouoldLikeToConnect": "želio bi se povezati", + "write_down_backup_password": "Molimo zapišite svoju lozinku za sigurnosnu kopiju koja se koristi za uvoz datoteka sigurnosne kopije.", + "xlm_extra_info": "Molimo ne zaboravite navesti memo ID prilikom slanja XLM transakcije na razmjenu", + "xmr_available_balance": "Raspoloživ iznos", + "xmr_full_balance": "Ukupan iznos", + "xmr_hidden": "Sakriven", + "xmr_to_error": "XMR.TO greška", + "xmr_to_error_description": "Nevažeći iznos. Dopušteno je najviše 8 znamenki iza točke", + "xrp_extra_info": "Molimo ne zaboravite navesti odredišnu oznaku prilikom slanja XRP transakcije na razmjenu", + "yat": "Yat", + "yat_address": "Yat adresa", + "yat_alert_content": "Korisnici Cake Wallet sada mogu slati i primati sve svoje omiljene valute s jedinstvenim korisničkim imenom na temelju emojija.", + "yat_alert_title": "Lakše šaljite i primajte kriptovalute s Yatom", + "yat_error": "Yat pogreška", + "yat_error_content": "Nema adresa povezanih s ovim Yat -om. Pokušajte s drugim Yat -om", + "yat_popup_content": "Sada možete slati i primati kriptovalute u Cake Wallet s vašim Yat - kratkim korisničkim imenom zasnovanim na emojijima. Upravljajte Yatsom u bilo kojem trenutku na zaslonu postavki", + "yat_popup_title": "Adresa vašeg novčanika može biti emojificirana.", + "yesterday": "Jučer", + "you_now_have_debit_card": "Sada imate debitnu karticu", + "you_pay": "Vi plaćate", + "you_will_get": "Razmijeni u", + "you_will_send": "Razmijeni iz", + "yy": "GG", + "zzzz": "zzzz" +} \ No newline at end of file diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 27bfc4c7b..464483eab 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -1,767 +1,768 @@ { - "welcome": "Selamat datang di", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Dompet luar biasa untuk Monero, Bitcoin, Ethereum, Litecoin, dan Haven", - "please_make_selection": "Silahkan membuat pilihan di bawah ini untuk membuat atau memulihkan dompet Anda.", - "create_new": "Buat Dompet Baru", - "restore_wallet": "Pulihkan Dompet", - "monero_com": "Monero.com Oleh Cake Wallet", - "monero_com_wallet_text": "Dompet luar biasa untuk Monero", - "haven_app": "Haven Oleh Cake Wallet", - "haven_app_wallet_text": "Dompet luar biasa untuk Haven", - "accounts": "Akun", - "edit": "Edit", + "about_cake_pay": "Cake Pay memungkinkan Anda untuk dengan mudah membeli kartu hadiah dengan aset virtual, yang dapat digunakan segera di lebih dari 150.000 pedagang di Amerika Serikat.", "account": "Akun", + "accounts": "Akun", + "accounts_subaddresses": "Akun dan sub-alamat", + "activate": "Aktifkan", + "active": "Aktif", + "active_cards": "Kartu Aktif", + "activeConnectionsPrompt": "Koneksi aktif akan muncul di sini", "add": "Menambahkan", + "add_contact": "Tambah kontak", + "add_custom_node": "Tambahkan Node Kustom Baru", + "add_custom_redemption": "Tambahkan Tukar Kustom", + "add_fund_to_card": "Tambahkan dana pra-bayar ke kartu (hingga ${value})", + "add_new_node": "Tambah node baru", + "add_new_word": "Tambahkan kata baru", + "add_receiver": "Tambahkan penerima lain (opsional)", + "add_secret_code": "Atau, tambahkan kode rahasia ini ke aplikasi autentikator", + "add_tip": "Tambahkan Tip", + "add_token_disclaimer_check": "Saya telah mengonfirmasi alamat dan informasi kontrak token menggunakan sumber yang memiliki reputasi baik. Menambahkan informasi jahat atau salah dapat mengakibatkan hilangnya dana.", + "add_token_warning": "Jangan mengedit atau menambahkan token seperti yang diinstruksikan oleh penipu.\nSelalu konfirmasikan alamat token dengan sumber tepercaya!", + "add_value": "Tambahkan nilai", + "address": "Alamat", "address_book": "Buku Alamat", - "contact": "Kontak", - "please_select": "Silakan pilih:", - "cancel": "Batal", - "ok": "OK", - "contact_name": "Nama Kontak", - "reset": "Reset", - "save": "Simpan", + "address_book_menu": "Buku alamat", + "address_detected": "Alamat terdeteksi", + "address_from_domain": "Alamat ini dari ${domain} di Unstoppable Domains", + "address_from_yat": "Alamat ini berasal dari ${emoji} di Yat", + "address_label": "Label alamat", "address_remove_contact": "Hapus kontak", "address_remove_content": "Apakah Anda yakin ingin menghapus kontak yang dipilih?", - "authenticated": "Terotentikasi", - "authentication": "Otentikasi", - "failed_authentication": "Otentikasi gagal. ${state_error}", - "wallet_menu": "Menu", - "Blocks_remaining": "${status} Blok Tersisa", - "please_try_to_connect_to_another_node": "Silakan coba untuk terhubung ke node lain", - "xmr_hidden": "Tersembunyi", - "xmr_available_balance": "Saldo Tersedia", - "xmr_full_balance": "Saldo Penuh", - "send": "Mengirim", - "receive": "Menerima", - "transactions": "Transaksi", - "incoming": "Masuk", - "outgoing": "Keluar", - "transactions_by_date": "Transaksi berdasarkan tanggal", - "trades": "Perdagangan", - "filter_by": "Filter berdasarkan", - "today": "Hari ini", - "yesterday": "Kemarin", - "received": "Diterima", - "sent": "Dikirim", - "pending": " (pending)", - "rescan": "Pindai ulang", - "reconnect": "Sambungkan kembali", - "wallets": "Dompet", - "show_seed": "Tampilkan seed", - "show_keys": "Tampilkan seed/kunci", - "address_book_menu": "Buku alamat", - "reconnection": "Koneksi kembali", - "reconnect_alert_text": "Apakah Anda yakin ingin menyambungkan kembali?", - "exchange": "Tukar", - "clear": "Hapus", - "refund_address": "Alamat pengembalian", - "change_exchange_provider": "Ganti Penyedia Tukar", - "you_will_send": "Konversi dari", - "you_will_get": "Konversi ke", - "amount_is_guaranteed": "Jumlah penerimaan dijamin", - "amount_is_estimate": "Jumlah penerimaan diperkirakan", - "powered_by": "Didukung oleh ${title}", - "error": "Kesalahan", - "estimated": "Diperkirakan", - "min_value": "Min: ${value} ${currency}", - "max_value": "Max: ${value} ${currency}", - "change_currency": "Ganti Mata Uang", - "overwrite_amount": "Timpa jumlah", - "qr_payment_amount": "QR code ini berisi jumlah pembayaran. Apakah Anda ingin menimpa nilai saat ini?", - "copy_id": "Salin ID", - "exchange_result_write_down_trade_id": "Silakan salin atau tulis ID perdagangan untuk melanjutkan.", - "trade_id": "ID Perdagangan:", - "copied_to_clipboard": "Disalin ke Clipboard", - "saved_the_trade_id": "Saya telah menyimpan ID perdagangan", - "fetching": "Mengambil", - "id": "ID: ", - "amount": "Jumlah: ", - "payment_id": "ID Pembayaran: ", - "status": "Status: ", - "offer_expires_in": "Penawaran kedaluwarsa dalam: ", - "trade_is_powered_by": "Perdagangan ini didukung oleh ${provider}", - "copy_address": "Salin Alamat", - "exchange_result_confirm": "Dengan menekan tombol konfirmasi, Anda akan mengirimkan ${fetchingLabel} ${from} dari dompet Anda yang disebut ${walletName} ke alamat yang ditampilkan di bawah. Anda juga dapat mengirim dari dompet eksternal Anda ke alamat/QR code di bawah.\n\nSilakan tekan konfirmasi untuk melanjutkan atau kembali untuk mengubah jumlah.", - "exchange_result_description": "Anda harus mengirimkan minimal ${fetchingLabel} ${from} ke alamat yang ditampilkan di halaman berikutnya. Jika Anda mengirimkan jumlah yang lebih rendah dari ${fetchingLabel} ${from} maka uang tersebut mungkin tidak akan diubah dan mungkin tidak akan dikembalikan.", - "exchange_result_write_down_ID": "*Silakan salin atau tulis ID Anda yang ditampilkan di atas.", - "confirm": "Konfirmasi", - "confirm_sending": "Konfirmasi pengiriman", - "commit_transaction_amount_fee": "Lakukan transaksi\nJumlah: ${amount}\nBiaya: ${fee}", - "sending": "Mengirim", - "transaction_sent": "Transaksi terkirim!", - "expired": "Kedaluwarsa", - "time": "${minutes}m ${seconds}s", - "send_xmr": "Kirim XMR", - "exchange_new_template": "Template baru", - "faq": "Pertanyaan yang Sering Diajukan", - "enter_your_pin": "Masukkan PIN Anda", - "loading_your_wallet": "Memuat dompet Anda", - "new_wallet": "Dompet Baru", - "wallet_name": "Nama Dompet", - "continue_text": "Lanjutkan", - "choose_wallet_currency": "Silahkan pilih mata uang dompet:", - "node_new": "Node Baru", - "node_address": "Alamat Node", - "node_port": "Port Node", - "login": "Masuk", - "password": "Kata Sandi", - "nodes": "Node", - "node_reset_settings_title": "Atur ulang pengaturan", - "nodes_list_reset_to_default_message": "Apakah Anda yakin ingin mengatur ulang pengaturan ke default?", - "change_current_node": "Apakah Anda yakin ingin mengubah node saat ini menjadi ${node}?", - "change": "Ubah", - "remove_node": "Hapus node", - "remove_node_message": "Apakah Anda yakin ingin menghapus node yang dipilih?", - "remove": "Hapus", - "delete": "Hapus", - "add_new_node": "Tambah node baru", - "change_current_node_title": "Ubah node saat ini", - "node_test": "Uji", - "node_connection_successful": "Koneksi berhasil", - "node_connection_failed": "Koneksi gagal", - "new_node_testing": "Pengujian node baru", - "use": "Beralih ke ", - "digit_pin": "-digit PIN", - "share_address": "Bagikan alamat", - "receive_amount": "Jumlah", - "subaddresses": "Sub-alamat", "addresses": "Alamat", - "scan_qr_code": "Scan kode QR untuk mendapatkan alamat", - "qr_fullscreen": "Tap untuk membuka layar QR code penuh", - "rename": "Ganti nama", - "choose_account": "Pilih akun", - "create_new_account": "Buat akun baru", - "accounts_subaddresses": "Akun dan sub-alamat", - "restore_restore_wallet": "Pulihkan Dompet", - "restore_title_from_seed_keys": "Pulihkan dari seed/kunci", - "restore_description_from_seed_keys": "Dapatkan kembali dompet Anda dari seed/kunci yang Anda simpan di tempat yang aman", - "restore_next": "Selanjutnya", - "restore_title_from_backup": "Pulihkan dari cadangan", - "restore_description_from_backup": "Anda dapat memulihkan seluruh aplikasi Cake Wallet dari file cadangan Anda", - "restore_seed_keys_restore": "Pulihkan Seed/Kunci", - "restore_title_from_seed": "Pulihkan dari seed", - "restore_description_from_seed": "Pulihkan dompet Anda dari kombinasi kode 25 atau 13 kata", - "restore_title_from_keys": "Pulihkan dari kunci", - "restore_description_from_keys": "Pulihkan dompet Anda dari tombol yang dihasilkan yang disimpan dari kunci pribadi Anda", - "restore_wallet_name": "Nama dompet", - "restore_address": "Alamat", - "restore_view_key_private": "Lihat kunci (pribadi)", - "restore_spend_key_private": "Habiskan kunci (pribadi)", - "restore_recover": "Pulihkan", - "restore_wallet_restore_description": "Deskripsi pemulihan dompet", - "restore_new_seed": "Seed baru", - "restore_active_seed": "Seed aktif", - "restore_bitcoin_description_from_seed": "Pulihkan dompet Anda dari kombinasi kode 24 kata", - "restore_bitcoin_description_from_keys": "Pulihkan dompet Anda dari string WIF yang dihasilkan dari private keys Anda", - "restore_bitcoin_title_from_keys": "Pulihkan dari WIF", - "restore_from_date_atau_blockheight": "Silakan masukkan tanggal beberapa hari sebelum Anda membuat dompet ini. Atau jika Anda tahu blockheight, silakan masukkannya sebagai gantinya", - "seed_reminder": "Silakan tulis ini di tempat yang aman jika kamu kehilangan atau menghapus ponselmu", - "seed_title": "Bibit", - "seed_share": "Bagikan bibit", - "copy": "Salin", - "seed_language": "Bahasa benih", - "seed_choose": "Pilih bahasa bibit", - "seed_language_next": "Selanjutnya", - "seed_language_english": "Inggris", - "seed_language_chinese": "Cina", - "seed_language_dutch": "Belanda", - "seed_language_german": "Jerman", - "seed_language_japanese": "Jepang", - "seed_language_portuguese": "Portugis", - "seed_language_russian": "Rusia", - "seed_language_spanish": "Spanyol", - "seed_language_french": "Perancis", - "seed_language_italian": "Italia", - "send_title": "Kirim", - "send_your_wallet": "Dompetmu", - "send_address": "Alamat ${cryptoCurrency}", - "send_payment_id": "ID Pembayaran (opsional)", + "advanced_settings": "Pengaturan lanjutan", + "aggressive": "Terlalu bersemangat", + "agree": "Setuju", + "agree_and_continue": "Setuju & Lanjutkan", + "agree_to": "Dengan membuat akun Anda setuju dengan ", "all": "SEMUA", - "send_error_minimum_value": "Nilai minimum jumlah adalah 0.01", - "send_error_currency": "Mata uang hanya dapat berisi angka", - "send_estimated_fee": "Biaya yang diperkirakan:", - "send_priority": "Saat ini biaya diatur dengan prioritas ${transactionPriority}.\nPrioritas transaksi dapat diubah pada pengaturan", - "send_creating_transaction": "Membuat transaksi", - "send_templates": "Template", - "send_new": "Baru", - "send_amount": "Jumlah:", - "send_fee": "Biaya:", - "send_name": "Nama", - "got_it": "Sudah paham", - "send_sending": "Mengirim...", - "send_success": "${crypto}mu berhasil dikirim", - "settings_title": "Pengaturan", - "settings_nodes": "Nodes", - "settings_current_node": "Node saat ini", - "settings_wallets": "Dompet", - "settings_display_balance": "Tampilkan saldo", - "settings_currency": "Mata uang", - "settings_fee_priority": "Prioritas biaya", - "settings_save_recipient_address": "Simpan alamat penerima", - "settings_personal": "Pribadi", - "settings_change_pin": "Ganti PIN", - "settings_change_language": "Ganti bahasa", - "settings_allow_biometrical_authentication": "Izinkan otentikasi biometrik", - "settings_dark_mode": "Mode gelap", - "settings_transactions": "Transaksi", - "settings_trades": "Perdagangan", - "settings_display_on_dashboard_list": "Tampilkan di daftar dashboard", - "settings_all": "SEMUA", - "settings_only_trades": "Hanya perdagangan", - "settings_only_transactions": "Hanya transaksi", - "settings_none": "Tidak ada", - "settings_support": "Dukungan", - "settings_terms_and_conditions": "Syarat dan Ketentuan", - "pin_is_incorrect": "PIN salah", - "setup_pin": "Pasang PIN", - "enter_your_pin_again": "Masukkan PIN Anda lagi", - "setup_successful": "PIN Anda telah berhasil diatur!", - "wallet_keys": "Seed/kunci dompet", - "wallet_seed": "Seed dompet", - "private_key": "Kunci privat", - "public_key": "Kunci publik", - "view_key_private": "Kunci tampilan (privat)", - "view_key_public": "Kunci tampilan (publik)", - "spend_key_private": "Kunci pengeluaran (privat)", - "spend_key_public": "Kunci pengeluaran (publik)", - "copied_key_to_clipboard": "Kunci ${key} disalin ke Clipboard", - "new_subaddress_title": "Alamat baru", - "new_subaddress_label_name": "Nama label", - "new_subaddress_create": "Buat", - "address_label": "Label alamat", - "subaddress_title": "Daftar sub-alamat", - "trade_details_title": "Detail Transaksi", - "trade_details_id": "ID", - "trade_details_state": "Status", - "trade_details_fetching": "Mengambil", - "trade_details_provider": "Penyedia", - "trade_details_created_at": "Dibuat pada", - "trade_details_pair": "Pasangan", - "trade_details_copied": "${title} disalin ke Clipboard", - "trade_history_title": "Riwayat Transaksi", - "transaction_details_title": "Rincian Transaksi", - "transaction_details_transaction_id": "ID Transaksi", - "transaction_details_date": "Tanggal", - "transaction_details_height": "Tinggi", - "transaction_details_amount": "Jumlah", - "transaction_details_fee": "Biaya", - "transaction_details_copied": "${title} disalin ke Clipboard", - "transaction_details_recipient_address": "Alamat Penerima", - "wallet_list_title": "Dompet Monero", - "wallet_list_create_new_wallet": "Buat Dompet Baru", - "wallet_list_edit_wallet": "Edit dompet", - "wallet_list_wallet_name": "Nama dompet", - "wallet_list_restore_wallet": "Pulihkan Dompet", - "wallet_list_load_wallet": "Muat dompet", - "wallet_list_loading_wallet": "Memuat ${wallet_name} dompet", - "wallet_list_failed_to_load": "Gagal memuat ${wallet_name} dompet. ${error}", - "wallet_list_removing_wallet": "Menghapus ${wallet_name} dompet", - "wallet_list_failed_to_remove": "Gagal menghapus ${wallet_name} dompet. ${error}", - "widgets_address": "Alamat", - "widgets_restore_from_blockheight": "Pulihkan dari tinggi blok", - "widgets_restore_from_date": "Pulihkan dari tanggal", - "widgets_or": "atau", - "widgets_seed": "Biji", - "router_no_route": "Tidak ada rute yang ditentukan untuk ${name}", - "error_text_account_name": "Nama akun hanya dapat berisi huruf, angka\ndan harus antara 1 dan 15 karakter panjang", - "error_text_contact_name": "Nama kontak tidak boleh berisi simbol `, ' \"\ndan harus antara 1 dan 32 karakter panjang", - "error_text_address": "Alamat dompet harus sesuai dengan tipe\nmata uang kripto", - "error_text_node_address": "Silakan masukkan alamat iPv4", - "error_text_node_port": "Port node hanya dapat berisi angka antara 0 dan 65535", - "error_text_node_proxy_address": "Masukkan :, misalnya 127.0.0.1:9050", - "error_text_payment_id": "ID pembayaran hanya dapat berisi dari 16 hingga 64 karakter dalam hex", - "error_text_xmr": "Nilai XMR tidak boleh melebihi saldo yang tersedia.\nJumlah digit pecahan harus kurang atau sama dengan 12", - "error_text_fiat": "Nilai jumlah tidak boleh melebihi saldo yang tersedia.\nJumlah digit pecahan harus kurang atau sama dengan 2", - "error_text_subaddress_name": "Nama subalamat tidak boleh berisi simbol `, ' \"\ndan harus antara 1 dan 20 karakter panjang", - "error_text_amount": "Jumlah hanya dapat berisi angka", - "error_text_wallet_name": "Nama dompet hanya dapat berisi huruf, angka, _ - simbol\ndan harus antara 1 dan 33 karakter panjang", - "error_text_keys": "Kunci dompet hanya dapat berisi 64 karakter dalam hex", - "error_text_crypto_currency": "Jumlah digit pecahan harus kurang atau sama dengan 12", - "error_text_minimal_limit": "Perdagangan untuk ${provider} tidak dibuat. Jumlah kurang dari minimal: ${min} ${currency}", - "error_text_maximum_limit": "Perdagangan untuk ${provider} tidak dibuat. Jumlah lebih dari maksimal: ${max} ${currency}", - "error_text_limits_loading_failed": "Perdagangan untuk ${provider} tidak dibuat. Gagal memuat batas", - "error_text_template": "Nama template dan alamat tidak boleh berisi simbol ` , ' \"\ndan harus antara 1 dan 106 karakter panjang", + "all_trades": "Semua perdagangan", + "all_transactions": "Semua transaksi", + "alphabetical": "Alfabetis", + "already_have_account": "Sudah punya akun?", + "always": "Selalu", + "amount": "Jumlah: ", + "amount_is_estimate": "Jumlah penerimaan diperkirakan", + "amount_is_guaranteed": "Jumlah penerimaan dijamin", + "and": "dan", + "anonpay_description": "Hasilkan ${type}. Penerima dapat ${method} dengan cryptocurrency apa pun yang didukung, dan Anda akan menerima dana di dompet ini.", + "apk_update": "Pembaruan APK", + "approve": "Menyetujui", + "ascending": "Naik", + "ask_each_time": "Tanyakan setiap kali", "auth_store_ban_timeout": "ban_timeout", "auth_store_banned_for": "Dilarang selama ", "auth_store_banned_minutes": "menit", "auth_store_incorrect_password": "PIN yang salah", - "wallet_store_monero_wallet": "Dompet Monero", - "wallet_restoration_store_incorrect_seed_length": "Panjang seed yang salah", - "full_balance": "Saldo Penuh", - "available_balance": "Saldo Tersedia", - "hidden_balance": "Saldo Tersembunyi", - "sync_status_syncronizing": "SEDANG SINKRONISASI", - "sync_status_syncronized": "SUDAH TERSINKRONISASI", - "sync_status_not_connected": "TIDAK TERHUBUNG", - "sync_status_starting_sync": "MULAI SINKRONISASI", - "sync_status_failed_connect": "GAGAL TERHUBUNG", - "sync_status_connecting": "MENGHUBUNGKAN", - "sync_status_connected": "TERHUBUNG", - "sync_status_attempting_sync": "MENCOBA SINKRONISASI", - "transaction_priority_slow": "Lambat", - "transaction_priority_regular": "Normal", - "transaction_priority_medium": "Sedang", - "transaction_priority_fast": "Cepat", - "transaction_priority_fastest": "Tercepat", - "trade_for_not_created": "Perdagangan untuk ${title} belum dibuat.", - "trade_not_created": "Perdagangan belum dibuat", - "trade_id_not_found": "Perdagangan ${tradeId} dari ${title} tidak ditemukan.", - "trade_not_found": "Perdagangan tidak ditemukan.", - "trade_state_pending": "Menunggu", - "trade_state_confirming": "Menegkonfirmasi", - "trade_state_trading": "Berdagang", - "trade_state_traded": "Telah Berdagang", - "trade_state_complete": "Selesai", - "trade_state_to_be_created": "Akan dibuat", - "trade_state_unpaid": "Belum dibayar", - "trade_state_underpaid": "Kurang bayar", - "trade_state_paid_unconfirmed": "Dibayar belum dikonfirmasi", - "trade_state_paid": "Dibayar", - "trade_state_btc_sent": "Btc dikirim", - "trade_state_timeout": "Waktu habis", - "trade_state_created": "Dibuat", - "trade_state_finished": "Selesai", - "change_language": "Ganti bahasa", - "change_language_to": "Ganti bahasa ke ${language}?", - "paste": "Tempel", - "restore_from_seed_placeholder": "Silakan masukkan atau tempel seed Anda di sini", - "add_new_word": "Tambahkan kata baru", - "incorrect_seed": "Teks yang dimasukkan tidak valid.", - "biometric_auth_reason": "Pindai sidik jari Anda untuk mengautentikasi", - "version": "Versi ${currentVersion}", - "openalias_alert_title": "Alamat Terdeteksi", - "openalias_alert_content": "Anda akan mengirim dana ke\n${recipient_name}", - "card_address": "Alamat:", - "buy": "Beli", - "sell": "Jual", - "placeholder_transactions": "Transaksi Anda akan ditampilkan di sini", - "placeholder_contacts": "Kontak Anda akan ditampilkan di sini", - "template": "Template", - "confirm_delete_template": "Tindakan ini akan menghapus template ini. Apakah Anda ingin melanjutkan?", - "confirm_delete_wallet": "Tindakan ini akan menghapus dompet ini. Apakah Anda ingin melanjutkan?", - "change_wallet_alert_title": "Ganti dompet saat ini", - "change_wallet_alert_content": "Apakah Anda ingin mengganti dompet saat ini ke ${wallet_name}?", - "creating_new_wallet": "Membuat dompet baru", - "creating_new_wallet_error": "Error: ${description}", - "seed_alert_title": "Perhatian", - "seed_alert_content": "Seed adalah satu-satunya cara untuk mengembalikan dompet Anda. Apakah Anda sudah menuliskannya?", - "seed_alert_back": "Kembali", - "seed_alert_yes": "Ya, sudah", - "exchange_sync_alert_content": "Silakan tunggu sampai dompet Anda tersinkronisasi", - "pre_seed_title": "PENTING", - "pre_seed_description": "Di halaman berikutnya Anda akan melihat serangkaian kata ${words}. Ini adalah seed unik dan pribadi Anda dan itu SATU-SATUNYA cara untuk mengembalikan dompet Anda jika hilang atau rusak. Ini adalah TANGGUNG JAWAB Anda untuk menuliskannya dan menyimpan di tempat yang aman di luar aplikasi Cake Wallet.", - "pre_seed_button_text": "Saya mengerti. Tampilkan seed saya", - "xmr_to_error": "XMR.TO error", - "xmr_to_error_description": "Jumlah tidak valid. Batas maksimal 8 digit setelah koma", - "provider_error": "${provider} error", - "use_ssl": "Gunakan SSL", - "trusted": "Dipercayai", - "color_theme": "Tema warna", - "light_theme": "Terang", - "bright_theme": "Cerah", - "dark_theme": "Gelap", - "enter_your_note": "Masukkan catatan Anda...", - "note_optional": "Catatan (opsional)", - "note_tap_to_change": "Catatan (tap untuk mengubah)", - "view_in_block_explorer": "Lihat di Block Explorer", - "view_transaction_on": "Lihat Transaksi di ", - "transaction_key": "Kunci transaksi", - "confirmations": "Konfirmasi", - "recipient_address": "Alamat penerima", - "extra_id": "ID tambahan:", - "destination_tag": "Tag tujuan:", - "memo": "Memo:", - "backup": "Cadangan", - "change_password": "Ubah kata sandi", - "backup_password": "Kata sandi cadangan", - "write_down_backup_password": "Silakan menuliskan kata sandi cadangan Anda, yang digunakan untuk impor file cadangan Anda.", - "export_backup": "Ekspor cadangan", - "save_backup_password": "Pastikan Anda telah menyimpan kata sandi cadangan Anda. Anda tidak akan dapat mengimpor file cadangan Anda tanpa itu.", - "backup_file": "File cadangan", - "edit_backup_password": "Edit Kata Sandi Cadangan", - "save_backup_password_alert": "Simpan kata sandi cadangan", - "change_backup_password_alert": "File cadangan sebelumnya tidak akan tersedia untuk diimpor dengan kata sandi cadangan baru. Kata sandi cadangan baru hanya akan digunakan untuk file cadangan baru. Apakah Anda yakin ingin mengubah kata sandi cadangan?", - "enter_backup_password": "Masukkan kata sandi cadangan di sini", - "select_backup_file": "Pilih file cadangan", - "import": "Impor", - "please_select_backup_file": "Silakan pilih file cadangan dan masukkan kata sandi cadangan.", - "fixed_rate": "Rate tetap", - "fixed_rate_alert": "Anda akan dapat memasukkan jumlah penerimaan saat mode rate tetap dicentang. Apakah Anda ingin beralih ke mode rate tetap?", - "xlm_extra_info": "Jangan lupa untuk menentukan ID Memo saat mengirim transaksi XLM untuk pertukaran", - "xrp_extra_info": "Jangan lupa untuk menentukan Tag Tujuan saat mengirim transaksi XRP untuk pertukaran", - "exchange_incorrect_current_wallet_for_xmr": "Jika Anda ingin menukar XMR dari saldo Monero Cake Wallet Anda, silakan beralih ke dompet Monero Anda terlebih dahulu.", - "confirmed": "Saldo Terkonfirmasi", - "unconfirmed": "Saldo Belum Dikonfirmasi", - "displayable": "Dapat ditampilkan", - "submit_request": "kirim permintaan", - "buy_alert_content": "Saat ini kami hanya mendukung pembelian Bitcoin, Ethereum, Litecoin, dan Monero. Harap buat atau alihkan ke dompet Bitcoin, Ethereum, Litecoin, atau Monero Anda.", - "sell_alert_content": "Saat ini kami hanya mendukung penjualan Bitcoin, Ethereum, dan Litecoin. Harap buat atau alihkan ke dompet Bitcoin, Ethereum, atau Litecoin Anda.", - "outdated_electrum_wallet_description": "Dompet Bitcoin baru yang dibuat di Cake sekarang memiliki biji semai 24 kata. Wajib bagi Anda untuk membuat dompet Bitcoin baru dan mentransfer semua dana Anda ke dompet 24 kata baru, dan berhenti menggunakan dompet dengan biji semai 12 kata. Silakan lakukan ini segera untuk mengamankan dana Anda.", - "understand": "Saya mengerti", - "apk_update": "Pembaruan APK", - "buy_bitcoin": "Beli Bitcoin", - "buy_with": "Beli dengan", - "moonpay_alert_text": "Nilai jumlah harus lebih atau sama dengan ${minAmount} ${fiatCurrency}", - "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", - "do_not_show_me": "Jangan tampilkan ini lagi", - "unspent_coins_title": "Koin yang tidak terpakai", - "unspent_coins_details_title": "Rincian koin yang tidak terpakai", - "freeze": "Freeze", - "frozen": "Dibekukan", - "coin_control": "Kontrol koin (opsional)", - "address_detected": "Alamat terdeteksi", - "address_from_domain": "Alamat ini dari ${domain} di Unstoppable Domains", - "add_receiver": "Tambahkan penerima lain (opsional)", - "manage_yats": "Kelola Yats", - "yat_alert_title": "Kirim dan terima crypto dengan lebih mudah dengan Yat", - "yat_alert_content": "Pengguna Cake Wallet sekarang dapat mengirim dan menerima semua mata uang favorit mereka dengan nama pengguna berbasis emoji yang satu-of-a-kind.", - "get_your_yat": "Dapatkan Yat Anda", - "connect_an_existing_yat": "Hubungkan Yat yang ada", - "connect_yats": "Hubungkan Yats", - "yat_address": "Alamat Yat", - "yat": "Yat", - "address_from_yat": "Alamat ini berasal dari ${emoji} di Yat", - "yat_error": "Kesalahan Yat", - "yat_error_content": "Tidak ada alamat yang terkait dengan Yat ini. Coba Yat lain", - "choose_address": "\n\nSilakan pilih alamat:", - "yat_popup_title": "Alamat dompet Anda dapat diubah menjadi emoji.", - "yat_popup_content": "Anda sekarang dapat mengirim dan menerima crypto di Cake Wallet dengan Yat Anda - nama pengguna berbasis emoji yang pendek. Kelola Yats kapan saja pada layar pengaturan", - "second_intro_title": "Satu alamat emoji untuk menguasainya semua", - "second_intro_content": "Yat Anda adalah satu alamat emoji yang unik yang menggantikan semua alamat heksadesimal panjang Anda untuk semua mata uang Anda.", - "third_intro_title": "Yat bermain baik dengan yang lain", - "third_intro_content": "Yats hidup di luar Cake Wallet juga. Setiap alamat dompet di dunia dapat diganti dengan Yat!", - "learn_more": "Pelajari Lebih Lanjut", - "search": "Cari", - "search_language": "Cari bahasa", - "search_currency": "Cari mata uang", - "new_template": "Template Baru", - "electrum_address_disclaimer": "Kami menghasilkan alamat baru setiap kali Anda menggunakan satu, tetapi alamat sebelumnya tetap berfungsi", - "wallet_name_exists": "Nama dompet sudah ada. Silakan pilih nama yang berbeda atau ganti nama dompet yang lain terlebih dahulu.", - "market_place": "Pasar", - "cake_pay_title": "Kartu Hadiah Cake Pay", - "cake_pay_subtitle": "Beli kartu hadiah dengan harga diskon (hanya USA)", - "cake_pay_web_cards_title": "Kartu Web Cake Pay", - "cake_pay_web_cards_subtitle": "Beli kartu prabayar dan kartu hadiah secara global", - "about_cake_pay": "Cake Pay memungkinkan Anda untuk dengan mudah membeli kartu hadiah dengan aset virtual, yang dapat digunakan segera di lebih dari 150.000 pedagang di Amerika Serikat.", - "cake_pay_account_note": "Daftar hanya dengan alamat email untuk melihat dan membeli kartu. Beberapa di antaranya bahkan tersedia dengan diskon!", - "already_have_account": "Sudah punya akun?", - "create_account": "Buat Akun", - "privacy_policy": "Kebijakan Privasi", - "welcome_to_cakepay": "Selamat Datang di Cake Pay!", - "sign_up": "Daftar", - "forgot_password": "Lupa Kata Sandi", - "reset_password": "Atur Ulang Kata Sandi", - "gift_cards": "Kartu Hadiah", - "setup_your_debit_card": "Pasang kartu debit Anda", - "no_id_required": "Tidak perlu ID. Isi ulang dan belanja di mana saja", - "how_to_use_card": "Bagaimana menggunakan kartu ini", - "purchase_gift_card": "Beli Kartu Hadiah", - "verification": "Verifikasi", - "fill_code": "Silakan isi kode verifikasi yang diterima di email Anda", - "didnt_get_code": "Tidak mendapatkan kode?", - "resend_code": "Silakan kirim ulang", - "debit_card": "Kartu Debit", - "cakepay_prepaid_card": "Kartu Debit Prabayar CakePay", - "no_id_needed": "Tidak perlu ID!", - "frequently_asked_questions": "Pertanyaan yang sering diajukan", - "debit_card_terms": "Penyimpanan dan penggunaan nomor kartu pembayaran Anda (dan kredensial yang sesuai dengan nomor kartu pembayaran Anda) dalam dompet digital ini tertakluk pada Syarat dan Ketentuan persetujuan pemegang kartu yang berlaku dengan penerbit kartu pembayaran, seperti yang berlaku dari waktu ke waktu.", - "please_reference_document": "Silakan referensikan dokumen di bawah ini untuk informasi lebih lanjut.", - "cardholder_agreement": "Persetujuan Pemegang Kartu", - "e_sign_consent": "E-Sign Consent", - "agree_and_continue": "Setuju & Lanjutkan", - "email_address": "Alamat Email", - "agree_to": "Dengan membuat akun Anda setuju dengan ", - "and": "dan", - "enter_code": "Masukkan kode", - "congratulations": "Selamat!", - "you_now_have_debit_card": "Anda sekarang memiliki kartu debit", - "min_amount": "Min: ${value}", - "max_amount": "Max: ${value}", - "enter_amount": "Masukkan Jumlah", - "billing_address_info": "Jika diminta alamat billing, berikan alamat pengiriman Anda", - "order_physical_card": "Pesan Kartu Fisik", - "add_value": "Tambahkan nilai", - "activate": "Aktifkan", - "get_a": "Dapatkan ", - "digital_and_physical_card": " kartu debit pra-bayar digital dan fisik", - "get_card_note": " yang dapat Anda muat ulang dengan mata uang digital. Tidak perlu informasi tambahan!", - "signup_for_card_accept_terms": "Daftar untuk kartu dan terima syarat dan ketentuan.", - "add_fund_to_card": "Tambahkan dana pra-bayar ke kartu (hingga ${value})", - "use_card_info_two": "Dana dikonversi ke USD ketika disimpan dalam akun pra-bayar, bukan dalam mata uang digital.", - "use_card_info_three": "Gunakan kartu digital secara online atau dengan metode pembayaran tanpa kontak.", - "optionally_order_card": "Opsional memesan kartu fisik.", - "hide_details": "Sembunyikan Rincian", - "show_details": "Tampilkan Rincian", - "upto": "hingga ${value}", - "discount": "Hemat ${value}%", - "gift_card_amount": "Jumlah Kartu Hadiah", - "bill_amount": "Jumlah Tagihan", - "you_pay": "Anda Membayar", - "tip": "Tip:", - "custom": "kustom", - "by_cake_pay": "oleh Cake Pay", - "expires": "Kadaluarsa", - "mm": "MM", - "yy": "YY", - "online": "Online", - "offline": "Offline", - "gift_card_number": "Nomor Kartu Hadiah", - "pin_number": "Nomor PIN", - "total_saving": "Total Pembayaran", - "last_30_days": "30 hari terakhir", - "avg_savings": "Rata-rata Pembayaran", - "view_all": "Lihat Semua", - "active_cards": "Kartu Aktif", - "delete_account": "Hapus Akun", - "cards": "Kartu", - "active": "Aktif", - "redeemed": "Ditukar", - "gift_card_balance_note": "Kartu hadiah dengan saldo yang tersisa akan muncul di sini", - "gift_card_redeemed_note": "Kartu hadiah yang sudah Anda tukar akan muncul di sini", - "logout": "Keluar", - "add_tip": "Tambahkan Tip", - "percentageOf": "dari ${amount}", - "is_percentage": "adalah", - "search_category": "Cari kategori", - "mark_as_redeemed": "Tandai sebagai Ditukar", - "more_options": "Opsi Lainnya", - "awaiting_payment_confirmation": "Menunggu Konfirmasi Pembayaran", - "transaction_sent_notice": "Jika layar tidak bergerak setelah 1 menit, periksa block explorer dan email Anda.", - "agree": "Setuju", - "in_store": "Di Toko", - "generating_gift_card": "Membuat Kartu Hadiah", - "payment_was_received": "Pembayaran Anda telah diterima.", - "proceed_after_one_minute": "Jika layar tidak bergerak setelah 1 menit, periksa email Anda.", - "order_id": "ID Pesanan", - "gift_card_is_generated": "Kartu Hadiah telah dibuat", - "open_gift_card": "Buka Kartu Hadiah", - "contact_support": "Hubungi Dukungan", - "gift_cards_unavailable": "Kartu hadiah hanya tersedia untuk dibeli dengan Monero, Bitcoin, dan Litecoin saat ini", - "introducing_cake_pay": "Perkenalkan Cake Pay!", - "cake_pay_learn_more": "Beli dan tukar kartu hadiah secara instan di aplikasi!\nGeser ke kanan untuk informasi lebih lanjut.", - "automatic": "Otomatis", - "fixed_pair_not_supported": "Pasangan tetap ini tidak didukung dengan bursa yang dipilih", - "variable_pair_not_supported": "Pasangan variabel ini tidak didukung dengan bursa yang dipilih", - "none_of_selected_providers_can_exchange": "Tidak ada dari penyedia yang dipilih yang dapat melakukan pertukaran ini", - "choose_one": "Pilih satu", - "choose_from_available_options": "Pilih dari pilihan yang tersedia:", - "custom_redeem_amount": "Jumlah Tukar Kustom", - "add_custom_redemption": "Tambahkan Tukar Kustom", - "remaining": "sisa", - "delete_wallet": "Hapus dompet", - "delete_wallet_confirm_message": "Apakah Anda yakin ingin menghapus dompet ${wallet_name}?", - "low_fee": "Biaya rendah", - "low_fee_alert": "Anda saat ini menggunakan prioritas biaya jaringan rendah. Ini dapat menyebabkan tunggu yang lama, kurs yang berbeda, atau perdagangan yang dibatalkan. Kami merekomendasikan menetapkan biaya yang lebih tinggi untuk pengalaman yang lebih baik.", - "ignor": "Abaikan", - "use_suggested": "Gunakan yang Disarankan", - "do_not_share_warning_text": "Jangan berikan ini pada siapapun, termasuk dukungan.\n\nDana Anda bisa dan akan dicuri!", - "help": "bantuan", - "all_transactions": "Semua transaksi", - "all_trades": "Semua perdagangan", - "connection_sync": "Koneksi dan sinkronisasi", - "security_and_backup": "Keamanan dan cadangan", - "create_backup": "Buat cadangan", - "privacy_settings": "Pengaturan privasi", - "privacy": "Privasi", - "display_settings": "Pengaturan tampilan", - "other_settings": "Pengaturan lainnya", - "require_pin_after": "Meminta PIN setelah", - "always": "Selalu", - "minutes_to_pin_code": "${minute} menit", - "disable_exchange": "Nonaktifkan pertukaran", - "advanced_settings": "Pengaturan lanjutan", - "settings_can_be_changed_later": "Pengaturan ini dapat diubah nanti di pengaturan aplikasi", - "add_custom_node": "Tambahkan Node Kustom Baru", - "disable_fiat": "Nonaktifkan fiat", - "fiat_api": "API fiat", - "disabled": "Dinonaktifkan", - "enabled": "Diaktifkan", - "tor_only": "Hanya Tor", - "unmatched_currencies": "Mata uang dompet Anda saat ini tidak cocok dengan yang ditandai QR", - "orbot_running_alert": "Pastikan Orbot sedang berjalan sebelum menghubungkan ke node ini.", - "contact_list_contacts": "Kontak", - "contact_list_wallets": "Dompet Saya", - "decimal_places_error": "Terlalu banyak tempat desimal", - "edit_node": "Sunting Node", - "invoice_details": "Detail faktur", - "donation_link_details": "Detail tautan donasi", - "anonpay_description": "Hasilkan ${type}. Penerima dapat ${method} dengan cryptocurrency apa pun yang didukung, dan Anda akan menerima dana di dompet ini.", - "create_invoice": "Buat faktur", - "create_donation_link": "Buat tautan donasi", - "optional_email_hint": "Email pemberitahuan penerima pembayaran opsional", - "optional_description": "Deskripsi opsional", - "optional_name": "Nama penerima opsional", - "clearnet_link": "Tautan clearnet", - "onion_link": "Tautan bawang", - "sell_monero_com_alert_content": "Menjual Monero belum didukung", - "error_text_input_below_minimum_limit": "Jumlah kurang dari minimal", - "error_text_input_above_maximum_limit": "Jumlah lebih dari maksimal", - "show_market_place": "Tampilkan Pasar", - "prevent_screenshots": "Cegah tangkapan layar dan perekaman layar", - "profile": "Profil", - "close": "Menutup", - "modify_2fa": "Ubah Kue 2FA", - "disable_cake_2fa": "Nonaktifkan Kue 2FA", - "question_to_disable_2fa": "Apakah Anda yakin ingin menonaktifkan Cake 2FA? Kode 2FA tidak lagi diperlukan untuk mengakses dompet dan fungsi tertentu.", - "disable": "Cacat", - "setup_2fa": "Siapkan Kue 2FA", - "verify_with_2fa": "Verifikasi dengan Cake 2FA", - "totp_code": "Kode TOTP", - "please_fill_totp": "Harap isi kode 8 digit yang ada di perangkat Anda yang lain", - "totp_2fa_success": "Kesuksesan! Cake 2FA diaktifkan untuk dompet ini. Ingatlah untuk menyimpan benih mnemonik Anda jika Anda kehilangan akses dompet.", - "totp_verification_success": "Verifikasi Berhasil!", - "totp_2fa_failure": "Kode salah. Silakan coba kode lain atau buat kunci rahasia baru. Gunakan aplikasi 2FA yang kompatibel yang mendukung kode 8 digit dan SHA512.", - "enter_totp_code": "Masukkan Kode TOTP.", - "add_secret_code": "Atau, tambahkan kode rahasia ini ke aplikasi autentikator", - "totp_secret_code": "Kode Rahasia TOTP", - "setup_2fa_text": "Cake 2FA bekerja menggunakan TOTP sebagai faktor otentikasi kedua.\n\nTOTP Cake 2FA memerlukan SHA-512 dan dukungan 8 digit; ini memberikan peningkatan keamanan. Informasi lebih lanjut dan aplikasi yang didukung dapat ditemukan di panduan.", - "setup_totp_recommended": "Pengaturan TOTP", - "disable_buy": "Nonaktifkan tindakan beli", - "disable_sell": "Nonaktifkan aksi jual", + "authenticated": "Terotentikasi", + "authentication": "Otentikasi", "auto_generate_subaddresses": "Menghasilkan subalamat secara otomatis", - "cake_2fa_preset": "Preset Kue 2FA", - "narrow": "Sempit", - "normal": "Normal", - "aggressive": "Terlalu bersemangat", - "require_for_assessing_wallet": "Diperlukan untuk mengakses dompet", - "require_for_sends_to_non_contacts": "Wajibkan untuk mengirim ke non-kontak", - "require_for_sends_to_contacts": "Membutuhkan untuk mengirim ke kontak", - "require_for_sends_to_internal_wallets": "Diperlukan untuk mengirim ke dompet internal", - "require_for_exchanges_to_internal_wallets": "Diperlukan untuk pertukaran ke dompet internal", - "require_for_adding_contacts": "Membutuhkan untuk menambahkan kontak", - "require_for_creating_new_wallets": "Diperlukan untuk membuat dompet baru", - "require_for_all_security_and_backup_settings": "Memerlukan untuk semua pengaturan keamanan dan pencadangan", + "automatic": "Otomatis", + "available_balance": "Saldo Tersedia", "available_balance_description": "“Saldo yang Tersedia” atau “Saldo yang Dikonfirmasi” adalah dana yang dapat langsung dibelanjakan. Jika dana muncul di saldo bawah tetapi tidak di saldo atas, maka Anda harus menunggu beberapa menit agar dana masuk mendapatkan konfirmasi jaringan lainnya. Setelah mereka mendapatkan lebih banyak konfirmasi, mereka akan dapat dibelanjakan.", - "syncing_wallet_alert_title": "Dompet Anda sedang disinkronkan", - "syncing_wallet_alert_content": "Saldo dan daftar transaksi Anda mungkin belum lengkap sampai tertulis “SYNCHRONIZED” di bagian atas. Klik/ketuk untuk mempelajari lebih lanjut.", - "home_screen_settings": "Pengaturan layar awal", - "sort_by": "Sortir dengan", - "search_add_token": "Cari / Tambahkan token", - "edit_token": "Mengedit token", - "warning": "Peringatan", - "add_token_warning": "Jangan mengedit atau menambahkan token seperti yang diinstruksikan oleh penipu.\nSelalu konfirmasikan alamat token dengan sumber tepercaya!", - "add_token_disclaimer_check": "Saya telah mengonfirmasi alamat dan informasi kontrak token menggunakan sumber yang memiliki reputasi baik. Menambahkan informasi jahat atau salah dapat mengakibatkan hilangnya dana.", - "token_contract_address": "Alamat kontrak token", - "token_name": "Nama token misalnya: Tether", - "token_symbol": "Simbol token misalnya: USDT", - "token_decimal": "Desimal token", - "field_required": "Bagian ini diperlukan", - "pin_at_top": "sematkan ${token} di atas", - "invalid_input": "Masukan tidak valid", - "fiat_balance": "Saldo Fiat", - "gross_balance": "Saldo Kotor", - "alphabetical": "Alfabetis", - "generate_name": "Hasilkan Nama", + "avg_savings": "Rata-rata Pembayaran", + "awaitDAppProcessing": "Mohon tunggu hingga dApp menyelesaikan pemrosesan.", + "awaiting_payment_confirmation": "Menunggu Konfirmasi Pembayaran", + "backup": "Cadangan", + "backup_file": "File cadangan", + "backup_password": "Kata sandi cadangan", "balance_page": "Halaman Saldo", - "share": "Membagikan", - "slidable": "Dapat digeser", - "monero_dark_theme": "Tema Gelap Monero", + "bill_amount": "Jumlah Tagihan", + "billing_address_info": "Jika diminta alamat billing, berikan alamat pengiriman Anda", + "biometric_auth_reason": "Pindai sidik jari Anda untuk mengautentikasi", "bitcoin_dark_theme": "Tema Gelap Bitcoin", "bitcoin_light_theme": "Tema Cahaya Bitcoin", - "high_contrast_theme": "Tema Kontras Tinggi", - "matrix_green_dark_theme": "Tema Matrix Green Dark", - "monero_light_theme": "Tema Cahaya Monero", - "manage_nodes": "Kelola node", - "etherscan_history": "Sejarah Etherscan", - "template_name": "Nama Templat", + "Blocks_remaining": "${status} Blok Tersisa", + "bright_theme": "Cerah", + "buy": "Beli", + "buy_alert_content": "Saat ini kami hanya mendukung pembelian Bitcoin, Ethereum, Litecoin, dan Monero. Harap buat atau alihkan ke dompet Bitcoin, Ethereum, Litecoin, atau Monero Anda.", + "buy_bitcoin": "Beli Bitcoin", + "buy_provider_unavailable": "Penyedia saat ini tidak tersedia.", + "buy_with": "Beli dengan", + "by_cake_pay": "oleh Cake Pay", + "cake_2fa_preset": "Preset Kue 2FA", + "cake_pay_account_note": "Daftar hanya dengan alamat email untuk melihat dan membeli kartu. Beberapa di antaranya bahkan tersedia dengan diskon!", + "cake_pay_learn_more": "Beli dan tukar kartu hadiah secara instan di aplikasi!\nGeser ke kanan untuk informasi lebih lanjut.", + "cake_pay_subtitle": "Beli kartu hadiah dengan harga diskon (hanya USA)", + "cake_pay_title": "Kartu Hadiah Cake Pay", + "cake_pay_web_cards_subtitle": "Beli kartu prabayar dan kartu hadiah secara global", + "cake_pay_web_cards_title": "Kartu Web Cake Pay", + "cake_wallet": "Cake Wallet", + "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.", + "camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.", + "cancel": "Batal", + "card_address": "Alamat:", + "cardholder_agreement": "Persetujuan Pemegang Kartu", + "cards": "Kartu", + "chains": "Rantai", + "change": "Ubah", + "change_backup_password_alert": "File cadangan sebelumnya tidak akan tersedia untuk diimpor dengan kata sandi cadangan baru. Kata sandi cadangan baru hanya akan digunakan untuk file cadangan baru. Apakah Anda yakin ingin mengubah kata sandi cadangan?", + "change_currency": "Ganti Mata Uang", + "change_current_node": "Apakah Anda yakin ingin mengubah node saat ini menjadi ${node}?", + "change_current_node_title": "Ubah node saat ini", + "change_exchange_provider": "Ganti Penyedia Tukar", + "change_language": "Ganti bahasa", + "change_language_to": "Ganti bahasa ke ${language}?", + "change_password": "Ubah kata sandi", "change_rep": "Ubah Perwakilan", "change_rep_message": "Apakah Anda yakin ingin mengubah perwakilan?", - "unsupported_asset": "Kami tidak mendukung tindakan ini untuk aset ini. Harap buat atau alihkan ke dompet dari jenis aset yang didukung.", - "manage_pow_nodes": "Kelola Node PoW", - "support_title_live_chat": "Dukungan langsung", - "support_description_live_chat": "Gratis dan Cepat! Perwakilan dukungan terlatih tersedia untuk membantu", - "support_title_guides": "Panduan Dompet Kue", - "support_description_guides": "Dokumentasi dan dukungan untuk masalah umum", - "support_title_other_links": "Tautan dukungan lainnya", - "support_description_other_links": "Bergabunglah dengan komunitas kami atau hubungi kami mitra kami melalui metode lain", + "change_rep_successful": "Berhasil mengubah perwakilan", + "change_wallet_alert_content": "Apakah Anda ingin mengganti dompet saat ini ke ${wallet_name}?", + "change_wallet_alert_title": "Ganti dompet saat ini", + "choose_account": "Pilih akun", + "choose_address": "\n\nSilakan pilih alamat:", "choose_derivation": "Pilih dompet dompet", - "new_first_wallet_text": "Dengan mudah menjaga cryptocurrency Anda aman", - "select_destination": "Silakan pilih tujuan untuk file cadangan.", - "save_to_downloads": "Simpan ke Unduhan", - "select_buy_provider_notice": "Pilih penyedia beli di atas. Anda dapat melewatkan layar ini dengan mengatur penyedia pembelian default Anda di pengaturan aplikasi.", - "onramper_option_description": "Beli crypto dengan cepat dengan banyak metode pembayaran. Tersedia di sebagian besar negara. Spread dan biaya bervariasi.", + "choose_from_available_options": "Pilih dari pilihan yang tersedia:", + "choose_one": "Pilih satu", + "choose_relay": "Silakan pilih relai yang akan digunakan", + "choose_wallet_currency": "Silahkan pilih mata uang dompet:", + "clear": "Hapus", + "clearnet_link": "Tautan clearnet", + "close": "Menutup", + "coin_control": "Kontrol koin (opsional)", + "color_theme": "Tema warna", + "commit_transaction_amount_fee": "Lakukan transaksi\nJumlah: ${amount}\nBiaya: ${fee}", + "confirm": "Konfirmasi", + "confirm_delete_template": "Tindakan ini akan menghapus template ini. Apakah Anda ingin melanjutkan?", + "confirm_delete_wallet": "Tindakan ini akan menghapus dompet ini. Apakah Anda ingin melanjutkan?", + "confirm_sending": "Konfirmasi pengiriman", + "confirmations": "Konfirmasi", + "confirmed": "Saldo Terkonfirmasi", + "confirmed_tx": "Dikonfirmasi", + "congratulations": "Selamat!", + "connect_an_existing_yat": "Hubungkan Yat yang ada", + "connect_yats": "Hubungkan Yats", + "connection_sync": "Koneksi dan sinkronisasi", + "connectWalletPrompt": "Hubungkan dompet Anda dengan WalletConnect untuk melakukan transaksi", + "contact": "Kontak", + "contact_list_contacts": "Kontak", + "contact_list_wallets": "Dompet Saya", + "contact_name": "Nama Kontak", + "contact_support": "Hubungi Dukungan", + "continue_text": "Lanjutkan", + "contractName": "Nama Kontrak", + "contractSymbol": "Simbol Kontrak", + "copied_key_to_clipboard": "Kunci ${key} disalin ke Clipboard", + "copied_to_clipboard": "Disalin ke Clipboard", + "copy": "Salin", + "copy_address": "Salin Alamat", + "copy_id": "Salin ID", + "copyWalletConnectLink": "Salin tautan WalletConnect dari dApp dan tempel di sini", + "create_account": "Buat Akun", + "create_backup": "Buat cadangan", + "create_donation_link": "Buat tautan donasi", + "create_invoice": "Buat faktur", + "create_new": "Buat Dompet Baru", + "create_new_account": "Buat akun baru", + "creating_new_wallet": "Membuat dompet baru", + "creating_new_wallet_error": "Error: ${description}", + "creation_date": "Tanggal Pembuatan", + "custom": "kustom", + "custom_drag": "Khusus (tahan dan seret)", + "custom_redeem_amount": "Jumlah Tukar Kustom", + "dark_theme": "Gelap", + "debit_card": "Kartu Debit", + "debit_card_terms": "Penyimpanan dan penggunaan nomor kartu pembayaran Anda (dan kredensial yang sesuai dengan nomor kartu pembayaran Anda) dalam dompet digital ini tertakluk pada Syarat dan Ketentuan persetujuan pemegang kartu yang berlaku dengan penerbit kartu pembayaran, seperti yang berlaku dari waktu ke waktu.", + "decimal_places_error": "Terlalu banyak tempat desimal", "default_buy_provider": "Penyedia beli default", - "ask_each_time": "Tanyakan setiap kali", - "buy_provider_unavailable": "Penyedia saat ini tidak tersedia.", - "signTransaction": "Tandatangani Transaksi", + "default_sell_provider": "Penyedia Penjualan Default", + "delete": "Hapus", + "delete_account": "Hapus Akun", + "delete_wallet": "Hapus dompet", + "delete_wallet_confirm_message": "Apakah Anda yakin ingin menghapus dompet ${wallet_name}?", + "deleteConnectionConfirmationPrompt": "Apakah Anda yakin ingin menghapus koneksi ke", + "descending": "Menurun", + "description": "Keterangan", + "destination_tag": "Tag tujuan:", + "dfx_option_description": "Beli kripto dengan EUR & CHF. Hingga 990€ tanpa KYC tambahan. Untuk pelanggan ritel dan korporat di Eropa", + "didnt_get_code": "Tidak mendapatkan kode?", + "digit_pin": "-digit PIN", + "digital_and_physical_card": " kartu debit pra-bayar digital dan fisik", + "disable": "Cacat", + "disable_buy": "Nonaktifkan tindakan beli", + "disable_cake_2fa": "Nonaktifkan Kue 2FA", + "disable_exchange": "Nonaktifkan pertukaran", + "disable_fiat": "Nonaktifkan fiat", + "disable_sell": "Nonaktifkan aksi jual", + "disabled": "Dinonaktifkan", + "discount": "Hemat ${value}%", + "display_settings": "Pengaturan tampilan", + "displayable": "Dapat ditampilkan", + "do_not_have_enough_gas_asset": "Anda tidak memiliki cukup ${currency} untuk melakukan transaksi dengan kondisi jaringan blockchain saat ini. Anda memerlukan lebih banyak ${currency} untuk membayar biaya jaringan blockchain, meskipun Anda mengirimkan aset yang berbeda.", + "do_not_share_warning_text": "Jangan berikan ini pada siapapun, termasuk dukungan.\n\nDana Anda bisa dan akan dicuri!", + "do_not_show_me": "Jangan tampilkan ini lagi", + "domain_looks_up": "Pencarian domain", + "donation_link_details": "Detail tautan donasi", + "e_sign_consent": "E-Sign Consent", + "edit": "Edit", + "edit_backup_password": "Edit Kata Sandi Cadangan", + "edit_node": "Sunting Node", + "edit_token": "Mengedit token", + "electrum_address_disclaimer": "Kami menghasilkan alamat baru setiap kali Anda menggunakan satu, tetapi alamat sebelumnya tetap berfungsi", + "email_address": "Alamat Email", + "enabled": "Diaktifkan", + "enter_amount": "Masukkan Jumlah", + "enter_backup_password": "Masukkan kata sandi cadangan di sini", + "enter_code": "Masukkan kode", + "enter_seed_phrase": "Masukkan frasa benih Anda", + "enter_totp_code": "Masukkan Kode TOTP.", + "enter_your_note": "Masukkan catatan Anda...", + "enter_your_pin": "Masukkan PIN Anda", + "enter_your_pin_again": "Masukkan PIN Anda lagi", + "enterTokenID": "Masukkan ID tokennya", + "enterWalletConnectURI": "Masukkan URI WalletConnect", + "error": "Kesalahan", + "error_text_account_name": "Nama akun hanya dapat berisi huruf, angka\ndan harus antara 1 dan 15 karakter panjang", + "error_text_address": "Alamat dompet harus sesuai dengan tipe\nmata uang kripto", + "error_text_amount": "Jumlah hanya dapat berisi angka", + "error_text_contact_name": "Nama kontak tidak boleh berisi simbol `, ' \"\ndan harus antara 1 dan 32 karakter panjang", + "error_text_crypto_currency": "Jumlah digit pecahan harus kurang atau sama dengan 12", + "error_text_fiat": "Nilai jumlah tidak boleh melebihi saldo yang tersedia.\nJumlah digit pecahan harus kurang atau sama dengan 2", + "error_text_input_above_maximum_limit": "Jumlah lebih dari maksimal", + "error_text_input_below_minimum_limit": "Jumlah kurang dari minimal", + "error_text_keys": "Kunci dompet hanya dapat berisi 64 karakter dalam hex", + "error_text_limits_loading_failed": "Perdagangan untuk ${provider} tidak dibuat. Gagal memuat batas", + "error_text_maximum_limit": "Perdagangan untuk ${provider} tidak dibuat. Jumlah lebih dari maksimal: ${max} ${currency}", + "error_text_minimal_limit": "Perdagangan untuk ${provider} tidak dibuat. Jumlah kurang dari minimal: ${min} ${currency}", + "error_text_node_address": "Silakan masukkan alamat iPv4", + "error_text_node_port": "Port node hanya dapat berisi angka antara 0 dan 65535", + "error_text_node_proxy_address": "Masukkan :, misalnya 127.0.0.1:9050", + "error_text_payment_id": "ID pembayaran hanya dapat berisi dari 16 hingga 64 karakter dalam hex", + "error_text_subaddress_name": "Nama subalamat tidak boleh berisi simbol `, ' \"\ndan harus antara 1 dan 20 karakter panjang", + "error_text_template": "Nama template dan alamat tidak boleh berisi simbol ` , ' \"\ndan harus antara 1 dan 106 karakter panjang", + "error_text_wallet_name": "Nama dompet hanya dapat berisi huruf, angka, _ - simbol\ndan harus antara 1 dan 33 karakter panjang", + "error_text_xmr": "Nilai XMR tidak boleh melebihi saldo yang tersedia.\nJumlah digit pecahan harus kurang atau sama dengan 12", "errorGettingCredentials": "Gagal: Terjadi kesalahan saat mendapatkan kredensial", "errorSigningTransaction": "Terjadi kesalahan saat menandatangani transaksi", - "pairingInvalidEvent": "Menyandingkan Acara Tidak Valid", - "chains": "Rantai", - "methods": "Metode", - "events": "Acara", - "reject": "Menolak", - "approve": "Menyetujui", - "expiresOn": "Kadaluarsa pada", - "walletConnect": "DompetConnect", - "nullURIError": "URI adalah nol", - "connectWalletPrompt": "Hubungkan dompet Anda dengan WalletConnect untuk melakukan transaksi", - "newConnection": "Koneksi Baru", - "activeConnectionsPrompt": "Koneksi aktif akan muncul di sini", - "deleteConnectionConfirmationPrompt": "Apakah Anda yakin ingin menghapus koneksi ke", + "estimated": "Diperkirakan", + "etherscan_history": "Sejarah Etherscan", "event": "Peristiwa", - "successful": "Berhasil", - "wouoldLikeToConnect": "ingin terhubung", - "message": "Pesan", - "do_not_have_enough_gas_asset": "Anda tidak memiliki cukup ${currency} untuk melakukan transaksi dengan kondisi jaringan blockchain saat ini. Anda memerlukan lebih banyak ${currency} untuk membayar biaya jaringan blockchain, meskipun Anda mengirimkan aset yang berbeda.", - "totp_auth_url": "URL Otentikasi TOTP", - "awaitDAppProcessing": "Mohon tunggu hingga dApp menyelesaikan pemrosesan.", - "copyWalletConnectLink": "Salin tautan WalletConnect dari dApp dan tempel di sini", - "enterWalletConnectURI": "Masukkan URI WalletConnect", - "seed_key": "Kunci benih", - "enter_seed_phrase": "Masukkan frasa benih Anda", - "change_rep_successful": "Berhasil mengubah perwakilan", - "add_contact": "Tambah kontak", + "events": "Acara", + "exchange": "Tukar", + "exchange_incorrect_current_wallet_for_xmr": "Jika Anda ingin menukar XMR dari saldo Monero Cake Wallet Anda, silakan beralih ke dompet Monero Anda terlebih dahulu.", + "exchange_new_template": "Template baru", "exchange_provider_unsupported": "${providerName} tidak lagi didukung!", - "domain_looks_up": "Pencarian domain", - "require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal", - "camera_permission_is_required": "Izin kamera diperlukan.\nSilakan aktifkan dari pengaturan aplikasi.", - "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi", - "order_by": "Dipesan oleh", - "creation_date": "Tanggal Pembuatan", + "exchange_result_confirm": "Dengan menekan tombol konfirmasi, Anda akan mengirimkan ${fetchingLabel} ${from} dari dompet Anda yang disebut ${walletName} ke alamat yang ditampilkan di bawah. Anda juga dapat mengirim dari dompet eksternal Anda ke alamat/QR code di bawah.\n\nSilakan tekan konfirmasi untuk melanjutkan atau kembali untuk mengubah jumlah.", + "exchange_result_description": "Anda harus mengirimkan minimal ${fetchingLabel} ${from} ke alamat yang ditampilkan di halaman berikutnya. Jika Anda mengirimkan jumlah yang lebih rendah dari ${fetchingLabel} ${from} maka uang tersebut mungkin tidak akan diubah dan mungkin tidak akan dikembalikan.", + "exchange_result_write_down_ID": "*Silakan salin atau tulis ID Anda yang ditampilkan di atas.", + "exchange_result_write_down_trade_id": "Silakan salin atau tulis ID perdagangan untuk melanjutkan.", + "exchange_sync_alert_content": "Silakan tunggu sampai dompet Anda tersinkronisasi", + "expired": "Kedaluwarsa", + "expires": "Kadaluarsa", + "expiresOn": "Kadaluarsa pada", + "export_backup": "Ekspor cadangan", + "extra_id": "ID tambahan:", + "failed_authentication": "Otentikasi gagal. ${state_error}", + "faq": "Pertanyaan yang Sering Diajukan", + "fetching": "Mengambil", + "fiat_api": "API fiat", + "fiat_balance": "Saldo Fiat", + "field_required": "Bagian ini diperlukan", + "fill_code": "Silakan isi kode verifikasi yang diterima di email Anda", + "filter_by": "Filter berdasarkan", + "first_wallet_text": "Dompet luar biasa untuk Monero, Bitcoin, Ethereum, Litecoin, dan Haven", + "fixed_pair_not_supported": "Pasangan tetap ini tidak didukung dengan bursa yang dipilih", + "fixed_rate": "Rate tetap", + "fixed_rate_alert": "Anda akan dapat memasukkan jumlah penerimaan saat mode rate tetap dicentang. Apakah Anda ingin beralih ke mode rate tetap?", + "forgot_password": "Lupa Kata Sandi", + "freeze": "Freeze", + "frequently_asked_questions": "Pertanyaan yang sering diajukan", + "frozen": "Dibekukan", + "full_balance": "Saldo Penuh", + "generate_name": "Hasilkan Nama", + "generating_gift_card": "Membuat Kartu Hadiah", + "get_a": "Dapatkan ", + "get_card_note": " yang dapat Anda muat ulang dengan mata uang digital. Tidak perlu informasi tambahan!", + "get_your_yat": "Dapatkan Yat Anda", + "gift_card_amount": "Jumlah Kartu Hadiah", + "gift_card_balance_note": "Kartu hadiah dengan saldo yang tersisa akan muncul di sini", + "gift_card_is_generated": "Kartu Hadiah telah dibuat", + "gift_card_number": "Nomor Kartu Hadiah", + "gift_card_redeemed_note": "Kartu hadiah yang sudah Anda tukar akan muncul di sini", + "gift_cards": "Kartu Hadiah", + "gift_cards_unavailable": "Kartu hadiah hanya tersedia untuk dibeli dengan Monero, Bitcoin, dan Litecoin saat ini", + "got_it": "Sudah paham", + "gross_balance": "Saldo Kotor", "group_by_type": "Grup demi jenis", - "importNFTs": "Impor NFT", - "noNFTYet": "Belum ada NFT", - "address": "Alamat", - "enterTokenID": "Masukkan ID tokennya", - "tokenID": "PENGENAL", - "name": "Nama", - "symbol": "Simbol", - "seed_phrase_length": "Panjang frase benih", - "unavailable_balance": "Saldo tidak tersedia", - "unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.", - "unspent_change": "Mengubah", - "tor_connection": "koneksi Tor", - "setup_warning_2fa_text": "Anda perlu memulihkan dompet Anda dari benih mnemonik.\n\nDukungan kue tidak akan dapat membantu Anda jika Anda kehilangan akses ke 2FA atau benih mnemonik.\nCake 2FA adalah otentikasi kedua untuk tindakan tertentu di dompet. Sebelum menggunakan Cake 2FA, kami sarankan untuk membaca panduannya.Ini TIDAK seaman penyimpanan dingin.\n\nJika Anda kehilangan akses ke aplikasi 2FA atau kunci TOTP, Anda AKAN kehilangan akses ke dompet ini. ", - "scan_qr_on_device": "Pindai kode QR ini di perangkat lain", + "haven_app": "Haven Oleh Cake Wallet", + "haven_app_wallet_text": "Dompet luar biasa untuk Haven", + "help": "bantuan", + "hidden_balance": "Saldo Tersembunyi", + "hide_details": "Sembunyikan Rincian", + "high_contrast_theme": "Tema Kontras Tinggi", + "home_screen_settings": "Pengaturan layar awal", "how_to_use": "Cara Penggunaan", + "how_to_use_card": "Bagaimana menggunakan kartu ini", + "id": "ID: ", + "ignor": "Abaikan", + "import": "Impor", + "importNFTs": "Impor NFT", + "in_store": "Di Toko", + "incoming": "Masuk", + "incorrect_seed": "Teks yang dimasukkan tidak valid.", + "introducing_cake_pay": "Perkenalkan Cake Pay!", + "invalid_input": "Masukan tidak valid", + "invoice_details": "Detail faktur", + "is_percentage": "adalah", + "last_30_days": "30 hari terakhir", + "learn_more": "Pelajari Lebih Lanjut", + "light_theme": "Terang", + "loading_your_wallet": "Memuat dompet Anda", + "login": "Masuk", + "logout": "Keluar", + "low_fee": "Biaya rendah", + "low_fee_alert": "Anda saat ini menggunakan prioritas biaya jaringan rendah. Ini dapat menyebabkan tunggu yang lama, kurs yang berbeda, atau perdagangan yang dibatalkan. Kami merekomendasikan menetapkan biaya yang lebih tinggi untuk pengalaman yang lebih baik.", + "manage_nodes": "Kelola node", + "manage_pow_nodes": "Kelola Node PoW", + "manage_yats": "Kelola Yats", + "mark_as_redeemed": "Tandai sebagai Ditukar", + "market_place": "Pasar", + "matrix_green_dark_theme": "Tema Matrix Green Dark", + "max_amount": "Max: ${value}", + "max_value": "Max: ${value} ${currency}", + "memo": "Memo:", + "message": "Pesan", + "methods": "Metode", + "min_amount": "Min: ${value}", + "min_value": "Min: ${value} ${currency}", + "minutes_to_pin_code": "${minute} menit", + "mm": "MM", + "modify_2fa": "Ubah Kue 2FA", + "monero_com": "Monero.com Oleh Cake Wallet", + "monero_com_wallet_text": "Dompet luar biasa untuk Monero", + "monero_dark_theme": "Tema Gelap Monero", + "monero_light_theme": "Tema Cahaya Monero", + "moonpay_alert_text": "Nilai jumlah harus lebih atau sama dengan ${minAmount} ${fiatCurrency}", + "more_options": "Opsi Lainnya", + "name": "Nama", + "narrow": "Sempit", + "new_first_wallet_text": "Dengan mudah menjaga cryptocurrency Anda aman", + "new_node_testing": "Pengujian node baru", + "new_subaddress_create": "Buat", + "new_subaddress_label_name": "Nama label", + "new_subaddress_title": "Alamat baru", + "new_template": "Template Baru", + "new_wallet": "Dompet Baru", + "newConnection": "Koneksi Baru", + "no_id_needed": "Tidak perlu ID!", + "no_id_required": "Tidak perlu ID. Isi ulang dan belanja di mana saja", + "no_relay_on_domain": "Tidak ada relai untuk domain pengguna atau relai tidak tersedia. Silakan pilih relai yang akan digunakan.", + "no_relays": "Tidak ada relay", + "no_relays_message": "Kami menemukan catatan Nostr NIP-05 untuk pengguna ini, tetapi tidak berisi relay apa pun. Harap instruksikan penerima untuk menambahkan relay ke catatan Nostr mereka.", + "node_address": "Alamat Node", + "node_connection_failed": "Koneksi gagal", + "node_connection_successful": "Koneksi berhasil", + "node_new": "Node Baru", + "node_port": "Port Node", + "node_reset_settings_title": "Atur ulang pengaturan", + "node_test": "Uji", + "nodes": "Node", + "nodes_list_reset_to_default_message": "Apakah Anda yakin ingin mengatur ulang pengaturan ke default?", + "none_of_selected_providers_can_exchange": "Tidak ada dari penyedia yang dipilih yang dapat melakukan pertukaran ini", + "noNFTYet": "Belum ada NFT", + "normal": "Normal", + "note_optional": "Catatan (opsional)", + "note_tap_to_change": "Catatan (tap untuk mengubah)", + "nullURIError": "URI adalah nol", + "offer_expires_in": "Penawaran kedaluwarsa dalam: ", + "offline": "Offline", + "ok": "OK", + "onion_link": "Tautan bawang", + "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", + "openalias_alert_content": "Anda akan mengirim dana ke\n${recipient_name}", + "openalias_alert_title": "Alamat Terdeteksi", + "optional_description": "Deskripsi opsional", + "optional_email_hint": "Email pemberitahuan penerima pembayaran opsional", + "optional_name": "Nama penerima opsional", + "optionally_order_card": "Opsional memesan kartu fisik.", + "orbot_running_alert": "Pastikan Orbot sedang berjalan sebelum menghubungkan ke node ini.", + "order_by": "Dipesan oleh", + "order_id": "ID Pesanan", + "order_physical_card": "Pesan Kartu Fisik", + "other_settings": "Pengaturan lainnya", + "outdated_electrum_wallet_description": "Dompet Bitcoin baru yang dibuat di Cake sekarang memiliki biji semai 24 kata. Wajib bagi Anda untuk membuat dompet Bitcoin baru dan mentransfer semua dana Anda ke dompet 24 kata baru, dan berhenti menggunakan dompet dengan biji semai 12 kata. Silakan lakukan ini segera untuk mengamankan dana Anda.", + "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", + "overwrite_amount": "Timpa jumlah", + "pairingInvalidEvent": "Menyandingkan Acara Tidak Valid", + "password": "Kata Sandi", + "paste": "Tempel", + "pause_wallet_creation": "Kemampuan untuk membuat Haven Wallet saat ini dijeda.", + "payment_id": "ID Pembayaran: ", + "payment_was_received": "Pembayaran Anda telah diterima.", + "pending": " (pending)", + "percentageOf": "dari ${amount}", + "pin_at_top": "sematkan ${token} di atas", + "pin_is_incorrect": "PIN salah", + "pin_number": "Nomor PIN", + "placeholder_contacts": "Kontak Anda akan ditampilkan di sini", + "placeholder_transactions": "Transaksi Anda akan ditampilkan di sini", + "please_fill_totp": "Harap isi kode 8 digit yang ada di perangkat Anda yang lain", + "please_make_selection": "Silahkan membuat pilihan di bawah ini untuk membuat atau memulihkan dompet Anda.", + "please_reference_document": "Silakan referensikan dokumen di bawah ini untuk informasi lebih lanjut.", + "please_select": "Silakan pilih:", + "please_select_backup_file": "Silakan pilih file cadangan dan masukkan kata sandi cadangan.", + "please_try_to_connect_to_another_node": "Silakan coba untuk terhubung ke node lain", + "polygonscan_history": "Sejarah PolygonScan", + "powered_by": "Didukung oleh ${title}", + "pre_seed_button_text": "Saya mengerti. Tampilkan seed saya", + "pre_seed_description": "Di halaman berikutnya Anda akan melihat serangkaian kata ${words}. Ini adalah seed unik dan pribadi Anda dan itu SATU-SATUNYA cara untuk mengembalikan dompet Anda jika hilang atau rusak. Ini adalah TANGGUNG JAWAB Anda untuk menuliskannya dan menyimpan di tempat yang aman di luar aplikasi Cake Wallet.", + "pre_seed_title": "PENTING", + "prevent_screenshots": "Cegah tangkapan layar dan perekaman layar", + "privacy": "Privasi", + "privacy_policy": "Kebijakan Privasi", + "privacy_settings": "Pengaturan privasi", + "private_key": "Kunci privat", + "proceed_after_one_minute": "Jika layar tidak bergerak setelah 1 menit, periksa email Anda.", + "profile": "Profil", + "provider_error": "${provider} error", + "public_key": "Kunci publik", + "purchase_gift_card": "Beli Kartu Hadiah", + "qr_fullscreen": "Tap untuk membuka layar QR code penuh", + "qr_payment_amount": "QR code ini berisi jumlah pembayaran. Apakah Anda ingin menimpa nilai saat ini?", + "question_to_disable_2fa": "Apakah Anda yakin ingin menonaktifkan Cake 2FA? Kode 2FA tidak lagi diperlukan untuk mengakses dompet dan fungsi tertentu.", + "receivable_balance": "Saldo piutang", + "receive": "Menerima", + "receive_amount": "Jumlah", + "received": "Diterima", + "recipient_address": "Alamat penerima", + "reconnect": "Sambungkan kembali", + "reconnect_alert_text": "Apakah Anda yakin ingin menyambungkan kembali?", + "reconnection": "Koneksi kembali", + "redeemed": "Ditukar", + "refund_address": "Alamat pengembalian", + "reject": "Menolak", + "remaining": "sisa", + "remove": "Hapus", + "remove_node": "Hapus node", + "remove_node_message": "Apakah Anda yakin ingin menghapus node yang dipilih?", + "rename": "Ganti nama", + "require_for_adding_contacts": "Membutuhkan untuk menambahkan kontak", + "require_for_all_security_and_backup_settings": "Memerlukan untuk semua pengaturan keamanan dan pencadangan", + "require_for_assessing_wallet": "Diperlukan untuk mengakses dompet", + "require_for_creating_new_wallets": "Diperlukan untuk membuat dompet baru", + "require_for_exchanges_to_external_wallets": "Memerlukan pertukaran ke dompet eksternal", + "require_for_exchanges_to_internal_wallets": "Diperlukan untuk pertukaran ke dompet internal", + "require_for_sends_to_contacts": "Membutuhkan untuk mengirim ke kontak", + "require_for_sends_to_internal_wallets": "Diperlukan untuk mengirim ke dompet internal", + "require_for_sends_to_non_contacts": "Wajibkan untuk mengirim ke non-kontak", + "require_pin_after": "Meminta PIN setelah", + "rescan": "Pindai ulang", + "resend_code": "Silakan kirim ulang", + "reset": "Reset", + "reset_password": "Atur Ulang Kata Sandi", + "restore_active_seed": "Seed aktif", + "restore_address": "Alamat", + "restore_bitcoin_description_from_keys": "Pulihkan dompet Anda dari string WIF yang dihasilkan dari private keys Anda", + "restore_bitcoin_description_from_seed": "Pulihkan dompet Anda dari kombinasi kode 24 kata", + "restore_bitcoin_title_from_keys": "Pulihkan dari WIF", + "restore_description_from_backup": "Anda dapat memulihkan seluruh aplikasi Cake Wallet dari file cadangan Anda", + "restore_description_from_keys": "Pulihkan dompet Anda dari tombol yang dihasilkan yang disimpan dari kunci pribadi Anda", + "restore_description_from_seed": "Pulihkan dompet Anda dari kombinasi kode 25 atau 13 kata", + "restore_description_from_seed_keys": "Dapatkan kembali dompet Anda dari seed/kunci yang Anda simpan di tempat yang aman", + "restore_from_date_atau_blockheight": "Silakan masukkan tanggal beberapa hari sebelum Anda membuat dompet ini. Atau jika Anda tahu blockheight, silakan masukkannya sebagai gantinya", + "restore_from_seed_placeholder": "Silakan masukkan atau tempel seed Anda di sini", + "restore_new_seed": "Seed baru", + "restore_next": "Selanjutnya", + "restore_recover": "Pulihkan", + "restore_restore_wallet": "Pulihkan Dompet", + "restore_seed_keys_restore": "Pulihkan Seed/Kunci", + "restore_spend_key_private": "Habiskan kunci (pribadi)", + "restore_title_from_backup": "Pulihkan dari cadangan", + "restore_title_from_keys": "Pulihkan dari kunci", + "restore_title_from_seed": "Pulihkan dari seed", + "restore_title_from_seed_keys": "Pulihkan dari seed/kunci", + "restore_view_key_private": "Lihat kunci (pribadi)", + "restore_wallet": "Pulihkan Dompet", + "restore_wallet_name": "Nama dompet", + "restore_wallet_restore_description": "Deskripsi pemulihan dompet", + "router_no_route": "Tidak ada rute yang ditentukan untuk ${name}", + "save": "Simpan", + "save_backup_password": "Pastikan Anda telah menyimpan kata sandi cadangan Anda. Anda tidak akan dapat mengimpor file cadangan Anda tanpa itu.", + "save_backup_password_alert": "Simpan kata sandi cadangan", + "save_to_downloads": "Simpan ke Unduhan", + "saved_the_trade_id": "Saya telah menyimpan ID perdagangan", + "scan_qr_code": "Scan kode QR untuk mendapatkan alamat", + "scan_qr_on_device": "Pindai kode QR ini di perangkat lain", + "search": "Cari", + "search_add_token": "Cari / Tambahkan token", + "search_category": "Cari kategori", + "search_currency": "Cari mata uang", + "search_language": "Cari bahasa", + "second_intro_content": "Yat Anda adalah satu alamat emoji yang unik yang menggantikan semua alamat heksadesimal panjang Anda untuk semua mata uang Anda.", + "second_intro_title": "Satu alamat emoji untuk menguasainya semua", + "security_and_backup": "Keamanan dan cadangan", + "seed_alert_back": "Kembali", + "seed_alert_content": "Seed adalah satu-satunya cara untuk mengembalikan dompet Anda. Apakah Anda sudah menuliskannya?", + "seed_alert_title": "Perhatian", + "seed_alert_yes": "Ya, sudah", + "seed_choose": "Pilih bahasa bibit", "seed_hex_form": "Biji dompet (bentuk hex)", + "seed_key": "Kunci benih", + "seed_language": "Bahasa benih", + "seed_language_chinese": "Cina", + "seed_language_chinese_traditional": "Cina (tradisional)", + "seed_language_czech": "Ceko", + "seed_language_dutch": "Belanda", + "seed_language_english": "Inggris", + "seed_language_french": "Perancis", + "seed_language_german": "Jerman", + "seed_language_italian": "Italia", + "seed_language_japanese": "Jepang", + "seed_language_korean": "Korea", + "seed_language_next": "Selanjutnya", + "seed_language_portuguese": "Portugis", + "seed_language_russian": "Rusia", + "seed_language_spanish": "Spanyol", + "seed_phrase_length": "Panjang frase benih", + "seed_reminder": "Silakan tulis ini di tempat yang aman jika kamu kehilangan atau menghapus ponselmu", + "seed_share": "Bagikan bibit", + "seed_title": "Bibit", "seedtype": "Seedtype", "seedtype_legacy": "Legacy (25 kata)", "seedtype_polyseed": "Polyseed (16 kata)", - "seed_language_czech": "Ceko", - "seed_language_korean": "Korea", - "ascending": "Naik", - "descending": "Menurun", - "seed_language_chinese_traditional": "Cina (tradisional)", - "dfx_option_description": "Beli kripto dengan EUR & CHF. Hingga 990€ tanpa KYC tambahan. Untuk pelanggan ritel dan korporat di Eropa", - "polygonscan_history": "Sejarah PolygonScan", - "wallet_seed_legacy": "Biji dompet warisan", - "default_sell_provider": "Penyedia Penjualan Default", + "select_backup_file": "Pilih file cadangan", + "select_buy_provider_notice": "Pilih penyedia beli di atas. Anda dapat melewatkan layar ini dengan mengatur penyedia pembelian default Anda di pengaturan aplikasi.", + "select_destination": "Silakan pilih tujuan untuk file cadangan.", "select_sell_provider_notice": "Pilih penyedia jual di atas. Anda dapat melewati layar ini dengan mengatur penyedia penjualan default Anda di pengaturan aplikasi.", - "custom_drag": "Khusus (tahan dan seret)", + "sell": "Jual", + "sell_alert_content": "Saat ini kami hanya mendukung penjualan Bitcoin, Ethereum, dan Litecoin. Harap buat atau alihkan ke dompet Bitcoin, Ethereum, atau Litecoin Anda.", + "sell_monero_com_alert_content": "Menjual Monero belum didukung", + "send": "Mengirim", + "send_address": "Alamat ${cryptoCurrency}", + "send_amount": "Jumlah:", + "send_creating_transaction": "Membuat transaksi", + "send_error_currency": "Mata uang hanya dapat berisi angka", + "send_error_minimum_value": "Nilai minimum jumlah adalah 0.01", + "send_estimated_fee": "Biaya yang diperkirakan:", + "send_fee": "Biaya:", + "send_name": "Nama", + "send_new": "Baru", + "send_payment_id": "ID Pembayaran (opsional)", + "send_priority": "Saat ini biaya diatur dengan prioritas ${transactionPriority}.\nPrioritas transaksi dapat diubah pada pengaturan", + "send_sending": "Mengirim...", + "send_success": "${crypto}mu berhasil dikirim", + "send_templates": "Template", + "send_title": "Kirim", + "send_xmr": "Kirim XMR", + "send_your_wallet": "Dompetmu", + "sending": "Mengirim", + "sent": "Dikirim", + "settings_all": "SEMUA", + "settings_allow_biometrical_authentication": "Izinkan otentikasi biometrik", + "settings_can_be_changed_later": "Pengaturan ini dapat diubah nanti di pengaturan aplikasi", + "settings_change_language": "Ganti bahasa", + "settings_change_pin": "Ganti PIN", + "settings_currency": "Mata uang", + "settings_current_node": "Node saat ini", + "settings_dark_mode": "Mode gelap", + "settings_display_balance": "Tampilkan saldo", + "settings_display_on_dashboard_list": "Tampilkan di daftar dashboard", + "settings_fee_priority": "Prioritas biaya", + "settings_nodes": "Nodes", + "settings_none": "Tidak ada", + "settings_only_trades": "Hanya perdagangan", + "settings_only_transactions": "Hanya transaksi", + "settings_personal": "Pribadi", + "settings_save_recipient_address": "Simpan alamat penerima", + "settings_support": "Dukungan", + "settings_terms_and_conditions": "Syarat dan Ketentuan", + "settings_title": "Pengaturan", + "settings_trades": "Perdagangan", + "settings_transactions": "Transaksi", + "settings_wallets": "Dompet", + "setup_2fa": "Siapkan Kue 2FA", + "setup_2fa_text": "Cake 2FA bekerja menggunakan TOTP sebagai faktor otentikasi kedua.\n\nTOTP Cake 2FA memerlukan SHA-512 dan dukungan 8 digit; ini memberikan peningkatan keamanan. Informasi lebih lanjut dan aplikasi yang didukung dapat ditemukan di panduan.", + "setup_pin": "Pasang PIN", + "setup_successful": "PIN Anda telah berhasil diatur!", + "setup_totp_recommended": "Pengaturan TOTP", + "setup_warning_2fa_text": "Anda perlu memulihkan dompet Anda dari benih mnemonik.\n\nDukungan kue tidak akan dapat membantu Anda jika Anda kehilangan akses ke 2FA atau benih mnemonik.\nCake 2FA adalah otentikasi kedua untuk tindakan tertentu di dompet. Sebelum menggunakan Cake 2FA, kami sarankan untuk membaca panduannya.Ini TIDAK seaman penyimpanan dingin.\n\nJika Anda kehilangan akses ke aplikasi 2FA atau kunci TOTP, Anda AKAN kehilangan akses ke dompet ini. ", + "setup_your_debit_card": "Pasang kartu debit Anda", + "share": "Membagikan", + "share_address": "Bagikan alamat", + "show_details": "Tampilkan Rincian", + "show_keys": "Tampilkan seed/kunci", + "show_market_place": "Tampilkan Pasar", + "show_seed": "Tampilkan seed", + "sign_up": "Daftar", + "signTransaction": "Tandatangani Transaksi", + "signup_for_card_accept_terms": "Daftar untuk kartu dan terima syarat dan ketentuan.", + "slidable": "Dapat digeser", + "sort_by": "Sortir dengan", + "spend_key_private": "Kunci pengeluaran (privat)", + "spend_key_public": "Kunci pengeluaran (publik)", + "status": "Status: ", + "subaddress_title": "Daftar sub-alamat", + "subaddresses": "Sub-alamat", + "submit_request": "kirim permintaan", + "successful": "Berhasil", + "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_live_chat": "Dukungan langsung", + "support_title_other_links": "Tautan dukungan lainnya", + "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi", "switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)", - "receivable_balance": "Saldo piutang", - "confirmed_tx": "Dikonfirmasi", + "symbol": "Simbol", + "sync_status_attempting_sync": "MENCOBA SINKRONISASI", + "sync_status_connected": "TERHUBUNG", + "sync_status_connecting": "MENGHUBUNGKAN", + "sync_status_failed_connect": "GAGAL TERHUBUNG", + "sync_status_not_connected": "TIDAK TERHUBUNG", + "sync_status_starting_sync": "MULAI SINKRONISASI", + "sync_status_syncronized": "SUDAH TERSINKRONISASI", + "sync_status_syncronizing": "SEDANG SINKRONISASI", + "syncing_wallet_alert_content": "Saldo dan daftar transaksi Anda mungkin belum lengkap sampai tertulis “SYNCHRONIZED” di bagian atas. Klik/ketuk untuk mempelajari lebih lanjut.", + "syncing_wallet_alert_title": "Dompet Anda sedang disinkronkan", + "template": "Template", + "template_name": "Nama Templat", + "third_intro_content": "Yats hidup di luar Cake Wallet juga. Setiap alamat dompet di dunia dapat diganti dengan Yat!", + "third_intro_title": "Yat bermain baik dengan yang lain", + "time": "${minutes}m ${seconds}s", + "tip": "Tip:", + "today": "Hari ini", + "token_contract_address": "Alamat kontrak token", + "token_decimal": "Desimal token", + "token_name": "Nama token misalnya: Tether", + "token_symbol": "Simbol token misalnya: USDT", + "tokenID": "PENGENAL", + "tor_connection": "koneksi Tor", + "tor_only": "Hanya Tor", + "total_saving": "Total Pembayaran", + "totp_2fa_failure": "Kode salah. Silakan coba kode lain atau buat kunci rahasia baru. Gunakan aplikasi 2FA yang kompatibel yang mendukung kode 8 digit dan SHA512.", + "totp_2fa_success": "Kesuksesan! Cake 2FA diaktifkan untuk dompet ini. Ingatlah untuk menyimpan benih mnemonik Anda jika Anda kehilangan akses dompet.", + "totp_auth_url": "URL Otentikasi TOTP", + "totp_code": "Kode TOTP", + "totp_secret_code": "Kode Rahasia TOTP", + "totp_verification_success": "Verifikasi Berhasil!", + "trade_details_copied": "${title} disalin ke Clipboard", + "trade_details_created_at": "Dibuat pada", + "trade_details_fetching": "Mengambil", + "trade_details_id": "ID", + "trade_details_pair": "Pasangan", + "trade_details_provider": "Penyedia", + "trade_details_state": "Status", + "trade_details_title": "Detail Transaksi", + "trade_for_not_created": "Perdagangan untuk ${title} belum dibuat.", + "trade_history_title": "Riwayat Transaksi", + "trade_id": "ID Perdagangan:", + "trade_id_not_found": "Perdagangan ${tradeId} dari ${title} tidak ditemukan.", + "trade_is_powered_by": "Perdagangan ini didukung oleh ${provider}", + "trade_not_created": "Perdagangan belum dibuat", + "trade_not_found": "Perdagangan tidak ditemukan.", + "trade_state_btc_sent": "Btc dikirim", + "trade_state_complete": "Selesai", + "trade_state_confirming": "Menegkonfirmasi", + "trade_state_created": "Dibuat", + "trade_state_finished": "Selesai", + "trade_state_paid": "Dibayar", + "trade_state_paid_unconfirmed": "Dibayar belum dikonfirmasi", + "trade_state_pending": "Menunggu", + "trade_state_timeout": "Waktu habis", + "trade_state_to_be_created": "Akan dibuat", + "trade_state_traded": "Telah Berdagang", + "trade_state_trading": "Berdagang", + "trade_state_underpaid": "Kurang bayar", + "trade_state_unpaid": "Belum dibayar", + "trades": "Perdagangan", + "transaction_details_amount": "Jumlah", + "transaction_details_copied": "${title} disalin ke Clipboard", + "transaction_details_date": "Tanggal", + "transaction_details_fee": "Biaya", + "transaction_details_height": "Tinggi", + "transaction_details_recipient_address": "Alamat Penerima", "transaction_details_source_address": "Alamat sumber", - "pause_wallet_creation": "Kemampuan untuk membuat Haven Wallet saat ini dijeda.", - "contractName": "Nama Kontrak", - "contractSymbol": "Simbol Kontrak", - "description": "Keterangan", - "camera_consent": "Kamera Anda akan digunakan untuk mengambil gambar untuk tujuan identifikasi oleh ${provider}. Silakan periksa Kebijakan Privasi mereka untuk detailnya.", - "no_relays": "Tidak ada relay", - "choose_relay": "Silakan pilih relai yang akan digunakan", - "no_relays_message": "Kami menemukan catatan Nostr NIP-05 untuk pengguna ini, tetapi tidak berisi relay apa pun. Harap instruksikan penerima untuk menambahkan relay ke catatan Nostr mereka.", - "no_relay_on_domain": "Tidak ada relai untuk domain pengguna atau relai tidak tersedia. Silakan pilih relai yang akan digunakan." -} + "transaction_details_title": "Rincian Transaksi", + "transaction_details_transaction_id": "ID Transaksi", + "transaction_key": "Kunci transaksi", + "transaction_priority_fast": "Cepat", + "transaction_priority_fastest": "Tercepat", + "transaction_priority_medium": "Sedang", + "transaction_priority_regular": "Normal", + "transaction_priority_slow": "Lambat", + "transaction_sent": "Transaksi terkirim!", + "transaction_sent_notice": "Jika layar tidak bergerak setelah 1 menit, periksa block explorer dan email Anda.", + "transactions": "Transaksi", + "transactions_by_date": "Transaksi berdasarkan tanggal", + "trusted": "Dipercayai", + "unavailable_balance": "Saldo tidak tersedia", + "unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.", + "unconfirmed": "Saldo Belum Dikonfirmasi", + "understand": "Saya mengerti", + "unmatched_currencies": "Mata uang dompet Anda saat ini tidak cocok dengan yang ditandai QR", + "unspent_change": "Mengubah", + "unspent_coins_details_title": "Rincian koin yang tidak terpakai", + "unspent_coins_title": "Koin yang tidak terpakai", + "unsupported_asset": "Kami tidak mendukung tindakan ini untuk aset ini. Harap buat atau alihkan ke dompet dari jenis aset yang didukung.", + "upto": "hingga ${value}", + "use": "Beralih ke ", + "use_card_info_three": "Gunakan kartu digital secara online atau dengan metode pembayaran tanpa kontak.", + "use_card_info_two": "Dana dikonversi ke USD ketika disimpan dalam akun pra-bayar, bukan dalam mata uang digital.", + "use_ssl": "Gunakan SSL", + "use_suggested": "Gunakan yang Disarankan", + "variable_pair_not_supported": "Pasangan variabel ini tidak didukung dengan bursa yang dipilih", + "verification": "Verifikasi", + "verify_with_2fa": "Verifikasi dengan Cake 2FA", + "version": "Versi ${currentVersion}", + "view_all": "Lihat Semua", + "view_in_block_explorer": "Lihat di Block Explorer", + "view_key_private": "Kunci tampilan (privat)", + "view_key_public": "Kunci tampilan (publik)", + "view_transaction_on": "Lihat Transaksi di ", + "wallet_keys": "Seed/kunci dompet", + "wallet_list_create_new_wallet": "Buat Dompet Baru", + "wallet_list_edit_wallet": "Edit dompet", + "wallet_list_failed_to_load": "Gagal memuat ${wallet_name} dompet. ${error}", + "wallet_list_failed_to_remove": "Gagal menghapus ${wallet_name} dompet. ${error}", + "wallet_list_load_wallet": "Muat dompet", + "wallet_list_loading_wallet": "Memuat ${wallet_name} dompet", + "wallet_list_removing_wallet": "Menghapus ${wallet_name} dompet", + "wallet_list_restore_wallet": "Pulihkan Dompet", + "wallet_list_title": "Dompet Monero", + "wallet_list_wallet_name": "Nama dompet", + "wallet_menu": "Menu", + "wallet_name": "Nama Dompet", + "wallet_name_exists": "Nama dompet sudah ada. Silakan pilih nama yang berbeda atau ganti nama dompet yang lain terlebih dahulu.", + "wallet_restoration_store_incorrect_seed_length": "Panjang seed yang salah", + "wallet_seed": "Seed dompet", + "wallet_seed_legacy": "Biji dompet warisan", + "wallet_store_monero_wallet": "Dompet Monero", + "walletConnect": "DompetConnect", + "wallets": "Dompet", + "warning": "Peringatan", + "welcome": "Selamat datang di", + "welcome_to_cakepay": "Selamat Datang di Cake Pay!", + "widgets_address": "Alamat", + "widgets_or": "atau", + "widgets_restore_from_blockheight": "Pulihkan dari tinggi blok", + "widgets_restore_from_date": "Pulihkan dari tanggal", + "widgets_seed": "Biji", + "wouoldLikeToConnect": "ingin terhubung", + "write_down_backup_password": "Silakan menuliskan kata sandi cadangan Anda, yang digunakan untuk impor file cadangan Anda.", + "xlm_extra_info": "Jangan lupa untuk menentukan ID Memo saat mengirim transaksi XLM untuk pertukaran", + "xmr_available_balance": "Saldo Tersedia", + "xmr_full_balance": "Saldo Penuh", + "xmr_hidden": "Tersembunyi", + "xmr_to_error": "XMR.TO error", + "xmr_to_error_description": "Jumlah tidak valid. Batas maksimal 8 digit setelah koma", + "xrp_extra_info": "Jangan lupa untuk menentukan Tag Tujuan saat mengirim transaksi XRP untuk pertukaran", + "yat": "Yat", + "yat_address": "Alamat Yat", + "yat_alert_content": "Pengguna Cake Wallet sekarang dapat mengirim dan menerima semua mata uang favorit mereka dengan nama pengguna berbasis emoji yang satu-of-a-kind.", + "yat_alert_title": "Kirim dan terima crypto dengan lebih mudah dengan Yat", + "yat_error": "Kesalahan Yat", + "yat_error_content": "Tidak ada alamat yang terkait dengan Yat ini. Coba Yat lain", + "yat_popup_content": "Anda sekarang dapat mengirim dan menerima crypto di Cake Wallet dengan Yat Anda - nama pengguna berbasis emoji yang pendek. Kelola Yats kapan saja pada layar pengaturan", + "yat_popup_title": "Alamat dompet Anda dapat diubah menjadi emoji.", + "yesterday": "Kemarin", + "you_now_have_debit_card": "Anda sekarang memiliki kartu debit", + "you_pay": "Anda Membayar", + "you_will_get": "Konversi ke", + "you_will_send": "Konversi dari", + "yy": "YY", + "zzzz": "zzzz" +} \ No newline at end of file diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index a29ac5c93..729b8c9c8 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -1,779 +1,780 @@ { - "welcome": "Benvenuto", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Portafoglio fantastico per Monero, Bitcoin, Ethereum, Litecoin, e Haven", - "please_make_selection": "Gentilmente seleziona se vuoi generare o recuperare il tuo portafoglio.", - "create_new": "Genera nuovo Portafoglio", - "restore_wallet": "Recupera Portafoglio", - "monero_com": "Monero.com by Cake Wallet", - "monero_com_wallet_text": "Portafoglio fantastico per Monero", - "haven_app": "Haven by Cake Wallet", - "haven_app_wallet_text": "Portafoglio fantastico per Haven", - "accounts": "Conti", - "edit": "Modifica", + "about_cake_pay": "Cake Pay ti consente di acquistare facilmente buoni regalo con asset virtuali, spendibili istantaneamente presso oltre 150.000 commercianti negli Stati Uniti.", "account": "Conto", + "accounts": "Conti", + "accounts_subaddresses": "Accounts e sottoindirizzi", + "activate": "Attiva", + "active": "Attivo", + "active_cards": "Carte attive", + "activeConnectionsPrompt": "Le connessioni attive verranno visualizzate qui", "add": "Aggiungi", + "add_contact": "Aggiungi contatto", + "add_custom_node": "Aggiungi nuovo nodo personalizzato", + "add_custom_redemption": "Aggiungi riscatto personalizzato", + "add_fund_to_card": "Aggiungi fondi prepagati alle carte (fino a ${value})", + "add_new_node": "Aggiungi nuovo nodo", + "add_new_word": "Aggiungi nuova parola", + "add_receiver": "Aggiungi un altro ricevitore (opzionale)", + "add_secret_code": "Oppure aggiungi questo codice segreto a un'app di autenticazione", + "add_tip": "Aggiungi suggerimento", + "add_token_disclaimer_check": "Ho confermato l'indirizzo e le informazioni del contratto token utilizzando una fonte attendibile. L'aggiunta di informazioni dannose o errate può comportare una perdita di fondi.", + "add_token_warning": "Non modificare o aggiungere token come indicato dai truffatori.\nConferma sempre gli indirizzi dei token con fonti attendibili!", + "add_value": "Aggiungi valore", + "address": "Indirizzo", "address_book": "Rubrica indirizzi", - "contact": "Contatta", - "please_select": "Gentilmente seleziona:", - "cancel": "Cancella", - "ok": "OK", - "contact_name": "Nome Contatto", - "reset": "Ripristina", - "save": "Salva", + "address_book_menu": "Rubrica indirizzi", + "address_detected": "Indirizzo rilevato", + "address_from_domain": "Questo indirizzo è da ${domain} in poi Unstoppable Domains", + "address_from_yat": "Questo indirizzo è da ${emoji} in poi Yat", + "address_label": "Address label", "address_remove_contact": "Rimuovi contatto", "address_remove_content": "Sei sicuro di voler eliminare il contatto selezionato?", - "authenticated": "Autenticato", - "authentication": "Autenticazione", - "failed_authentication": "Autenticazione fallita. ${state_error}", - "wallet_menu": "Menù", - "Blocks_remaining": "${status} Blocchi Rimanenti", - "please_try_to_connect_to_another_node": "Gentilmente prova a connetterti ad un altro nodo", - "xmr_hidden": "Nascosto", - "xmr_available_balance": "Saldo Disponibile", - "xmr_full_balance": "Saldo Totale", - "send": "Invia", - "receive": "Ricevi", - "transactions": "Transazioni", - "incoming": "In arrivo", - "outgoing": "In uscita", - "transactions_by_date": "Transazioni per data", - "trades": "Scambi", - "filter_by": "Filtrirati po", - "today": "Oggi", - "yesterday": "Ieri", - "received": "Ricevuto", - "sent": "Inviato", - "pending": " (non confermati)", - "rescan": "Scansiona di nuovo", - "reconnect": "Riconnetti", - "wallets": "Portafogli", - "show_seed": "Mostra seme", - "show_keys": "Mostra seme/chiavi", - "address_book_menu": "Rubrica indirizzi", - "reconnection": "Riconnessione", - "reconnect_alert_text": "Sei sicuro di volerti riconnettere?", - "exchange": "Scambia", - "clear": "Pulisci", - "refund_address": "Indirizzo di rimborso", - "change_exchange_provider": "Cambia Exchange", - "you_will_send": "Conveti da", - "you_will_get": "Converti a", - "amount_is_guaranteed": "L'ammontare da ricevere è fisso", - "amount_is_estimate": "L'ammontare da ricevere è una stima", - "powered_by": "Sviluppato da ${title}", - "error": "Errore", - "estimated": "Stimato", - "min_value": "Min: ${value} ${currency}", - "max_value": "Max: ${value} ${currency}", - "change_currency": "Cambia Valuta", - "overwrite_amount": "Sovrascrivi quantità", - "qr_payment_amount": "Questo codice QR contiene l'ammontare del pagamento. Vuoi sovrascrivere il varlore attuale?", - "copy_id": "Copia ID", - "exchange_result_write_down_trade_id": "Per favore fai una copia o trascrivi l'ID dello scambio per continuare.", - "trade_id": "ID Scambio:", - "copied_to_clipboard": "Copiato negli Appunti", - "saved_the_trade_id": "Ho salvato l'ID dello scambio", - "fetching": "Recupero", - "id": "ID: ", - "amount": "Ammontare: ", - "payment_id": "ID Pagamento: ", - "status": "Stato: ", - "offer_expires_in": "Offerta termina tra: ", - "trade_is_powered_by": "Questo scambio è fornito da ${provider}", - "copy_address": "Copia Indirizzo", - "exchange_result_confirm": "Cliccando su Conferma, invierai ${fetchingLabel} ${from} dal tuo portafoglio chiamato ${walletName} all'indirizzo mostrato qui in basso. O puoi inviare dal tuo portafoglio esterno all'indirizzo/codice QR mostrato in basso.\n\nGentilmente clicca su Conferma per continuare o torna indietro per cambiare l'ammontare.", - "exchange_result_description": "Devi inviare un minimo di ${fetchingLabel} ${from} all'indirizzo mostrato nella pagina seguente. Se invii un ammontare inferiore a ${fetchingLabel} ${from} la conversione potrebbe non andare a buon fine e l'indirizzo potrebbe non essere rimborsato.", - "exchange_result_write_down_ID": "*Gentilmente fai una copia o trascrivi il tuo ID mostrato in alto.", - "confirm": "Conferma", - "confirm_sending": "Conferma l'invio", - "commit_transaction_amount_fee": "Invia transazione\nAmmontare: ${amount}\nCommissione: ${fee}", - "sending": "Invio", - "transaction_sent": "Transazione inviata!", - "expired": "Scaduta", - "time": "${minutes}m ${seconds}s", - "send_xmr": "Invia XMR", - "exchange_new_template": "Nuovo modello", - "faq": "Domande Frequenti", - "enter_your_pin": "Inserisci il tuo PIN", - "loading_your_wallet": "Caricamento portafoglio", - "new_wallet": "Nuovo Portafoglio", - "wallet_name": "Nome del Portafoglio", - "continue_text": "Continua", - "choose_wallet_currency": "Gentilmente scegli la moneta del portafoglio:", - "node_new": "Nuovo Nodo", - "node_address": "Indirizzo Nodo", - "node_port": "Porta Nodo", - "login": "Accedi", - "password": "Password", - "nodes": "Nodi", - "node_reset_settings_title": "Ripristina impostazioni", - "nodes_list_reset_to_default_message": "Sei sicuro di voler ripristinare le impostazioni predefinite?", - "change_current_node": "Sei sicuro di voler cambiare il nodo corrente con ${node}?", - "change": "Cambia", - "remove_node": "Rimuovi nodo", - "remove_node_message": "Sei sicuro di voler rimuovere il nodo selezionato?", - "remove": "Remuovi", - "delete": "Elimina", - "add_new_node": "Aggiungi nuovo nodo", - "change_current_node_title": "Cambia nodo corrente", - "node_test": "Test", - "node_connection_successful": "Connessione avvenuta con successo", - "node_connection_failed": "Connessione fallita", - "new_node_testing": "Test novo nodo", - "use": "Passa a ", - "digit_pin": "-cifre PIN", - "share_address": "Condividi indirizzo", - "receive_amount": "Ammontare", - "subaddresses": "Sottoindirizzi", "addresses": "Indirizzi", - "scan_qr_code_to_get_address": "Scansiona il codice QR per ottenere l'indirizzo", - "qr_fullscreen": "Tocca per aprire il codice QR a schermo intero", - "rename": "Rinomina", - "choose_account": "Scegli account", - "create_new_account": "Crea nuovo account", - "accounts_subaddresses": "Accounts e sottoindirizzi", - "restore_restore_wallet": "Recupera Portafoglio", - "restore_title_from_seed_keys": "Recupera dal seme/chiavi", - "restore_description_from_seed_keys": "Recupera il tuo portafoglio dal seme/chiavi che hai salvato in un posto sicuro", - "restore_next": "Prossimo", - "restore_title_from_backup": "Recupera da backup", - "restore_description_from_backup": "Puoi recuperare l'app Cake Wallet per intero dal tuo file di backup", - "restore_seed_keys_restore": "Recupera Seme/Chiavi", - "restore_title_from_seed": "Recupera dal seme", - "restore_description_from_seed": "Recupera il tuo portafoglio da una combinazione di 25 o 13 parole", - "restore_title_from_keys": "Recupera dalle chiavi", - "restore_description_from_keys": "Recupera il tuo portafoglio da una sequenza di caratteri generati dalle tue chiavi private", - "restore_wallet_name": "Nome Portafoglio", - "restore_address": "Indirizzo", - "restore_view_key_private": "Chiave di Visualizzazione (privata)", - "restore_spend_key_private": "Chiave di Spesa (privata)", - "restore_recover": "Recupera", - "restore_wallet_restore_description": "Descrizione recupero Portafoglio", - "restore_new_seed": "Nuovo seme", - "restore_active_seed": "Seme attivo", - "restore_bitcoin_description_from_seed": "Recupera il tuo portafoglio da una combinazione di 12 parole", - "restore_bitcoin_description_from_keys": "Recupera il tuo portafoglio da una stringa WIF generata dalle tue chiavi private", - "restore_bitcoin_title_from_keys": "Recupera da WIF", - "restore_from_date_or_blockheight": "Gentilmente inserisci la data di un paio di giorni prima che hai creato questo portafoglio. Oppure inserisci l'altezza del blocco se la conosci", - "seed_reminder": "Gentilmente trascrivi le parole. Ti tornerà utile in caso perdessi o ripristinassi il tuo telefono", - "seed_title": "Seme", - "seed_share": "Condividi seme", - "copy": "Copia", - "seed_language": "Linguaggio di semi", - "seed_choose": "Scegli la lingua del seme", - "seed_language_next": "Prossimo", - "seed_language_english": "Inglese", - "seed_language_chinese": "Cinese", - "seed_language_dutch": "Olandese", - "seed_language_german": "Tedesco", - "seed_language_japanese": "Giapponese", - "seed_language_portuguese": "Portoghese", - "seed_language_russian": "Russo", - "seed_language_spanish": "Spagnolo", - "seed_language_french": "Francese", - "seed_language_italian": "Italiano", - "send_title": "Invia", - "send_your_wallet": "Il tuo portafoglio", - "send_address": "${cryptoCurrency} indirizzo", - "send_payment_id": "ID Pagamento (opzionale)", + "advanced_settings": "Impostazioni avanzate", + "aggressive": "Fervente", + "agree": "d'accordo", + "agree_and_continue": "Accetta e continua", + "agree_to": "Creando un account accetti il ​​", "all": "TUTTO", - "send_error_minimum_value": "L'ammontare minimo è 0.01", - "send_error_currency": "L'ammontare può contenere solo numeri", - "send_estimated_fee": "Commissione stimata:", - "send_priority": "Attualmente la commissione è impostata a priorità ${transactionPriority} .\nLa priorità della transazione può essere modificata nelle impostazioni", - "send_creating_transaction": "Creazione della transazione", - "send_templates": "Modelli", - "send_new": "Nuovo", - "send_amount": "Ammontare:", - "send_fee": "Commissione:", - "send_name": "Nome", - "got_it": "Ho capito", - "send_sending": "Invio...", - "send_success": " ${crypto} inviati con successo", - "settings_title": "Impostazioni", - "settings_nodes": "Nodi", - "settings_current_node": "Nodo attuale", - "settings_wallets": "Portafogli", - "settings_display_balance": "Mostra saldo", - "settings_currency": "Moneta", - "settings_fee_priority": "Priorità commissione", - "settings_save_recipient_address": "Salva indirizzo di destinazione", - "settings_personal": "Personali", - "settings_change_pin": "Cambia PIN", - "settings_change_language": "Cambia lingua", - "settings_allow_biometrical_authentication": "Consenti autenticazione biometrica", - "settings_dark_mode": "Tema scuro", - "settings_transactions": "Transazioni", - "settings_trades": "Scambi", - "settings_display_on_dashboard_list": "Mostra nella lista della pagina principale", - "settings_all": "TUTTO", - "settings_only_trades": "Solo scambi", - "settings_only_transactions": "Solo transazioni", - "settings_none": "Nessuno", - "settings_support": "Supporto", - "settings_terms_and_conditions": "Termini e condizioni", - "pin_is_incorrect": "Il PIN non è corretto", - "setup_pin": "Imposta PIN", - "enter_your_pin_again": "Inserisci il tuo pin di nuovo", - "setup_successful": "Il tuo PIN è stato impostato con successo!", - "wallet_keys": "Seme Portafoglio /chiavi", - "wallet_seed": "Seme Portafoglio", - "private_key": "Chiave privata", - "public_key": "Chiave pubblica", - "view_key_private": "Chiave di visualizzazione (privata)", - "view_key_public": "Chiave di visualizzazione (pubblica)", - "spend_key_private": "Chiave di spesa (privata)", - "spend_key_public": "Chiave di spesa (pubblica)", - "copied_key_to_clipboard": " ${key} copiata negli Appunti", - "new_subaddress_title": "Nuovo indirizzo", - "new_subaddress_label_name": "Nome etichetta", - "new_subaddress_create": "Crea", - "address_label": "Address label", - "subaddress_title": "Lista sottoindirizzi", - "trade_details_title": "Dettagli Scambio", - "trade_details_id": "ID", - "trade_details_state": "Stato", - "trade_details_fetching": "Recupero", - "trade_details_provider": "Fornitore", - "trade_details_created_at": "Creato alle", - "trade_details_pair": "Coppia", - "trade_details_copied": "${title} copiati negli Appunti", - "trade_history_title": "Storico scambi", - "transaction_details_title": "Dettagli Transazione", - "transaction_details_transaction_id": "ID Transazione", - "transaction_details_date": "Data", - "transaction_details_height": "Altezza", - "transaction_details_amount": "Ammontare", - "transaction_details_fee": "Commissione", - "transaction_details_copied": "${title} copiati negli Appunti", - "transaction_details_recipient_address": "Indirizzi dei destinatari", - "wallet_list_title": "Portafoglio Monero", - "wallet_list_create_new_wallet": "Crea Nuovo Portafoglio", - "wallet_list_edit_wallet": "Modifica portafoglio", - "wallet_list_wallet_name": "Nome del portafoglio", - "wallet_list_restore_wallet": "Recupera Portafoglio", - "wallet_list_load_wallet": "Caricamento Portafoglio", - "wallet_list_loading_wallet": "Caricamento portafoglio ${wallet_name}", - "wallet_list_failed_to_load": "Caricamento portafoglio ${wallet_name} fallito. ${error}", - "wallet_list_removing_wallet": "Rimozione portafoglio ${wallet_name}", - "wallet_list_failed_to_remove": "Rimozione portafoglio ${wallet_name} fallita. ${error}", - "widgets_address": "Indirizzo", - "widgets_restore_from_blockheight": "Recupera da altezza blocco", - "widgets_restore_from_date": "Recupera da data", - "widgets_or": "o", - "widgets_seed": "Seme", - "router_no_route": "Nessun percorso definito per ${name}", - "error_text_account_name": "Il nome del conto può contenere solo lettere, numeri\ne deve avere una lunghezza compresa tra 1 e 15 caratteri", - "error_text_contact_name": "Il nome del Contatto non può contenere i simboli ` , ' \" \ne deve avere una lunghezza compresa tra 1 e 32 caratteri", - "error_text_address": "L'indirizzo del Portafoglio deve corrispondere alla tipologia\ndi criptovaluta", - "error_text_node_address": "Gentilmente inserisci un indirizzo iPv4", - "error_text_node_port": "La porta del nodo può contenere solo numeri compresi tra 0 e 65535", - "error_text_node_proxy_address": "Inserisci :, ad esempio 127.0.0.1:9050", - "error_text_payment_id": "L'ID del pagamento può contenere solo da 16 a 64 caratteri in esadecimale", - "error_text_xmr": "Il valore in XMR non può eccedere il saldo disponibile.\nIl numero delle cifre decimali deve essere inferiore o uguale a 12", - "error_text_fiat": "L'ammontare non può eccedere il saldo dispoinibile.\nIl numero di cifre decimali deve essere inferiore o uguale a 2", - "error_text_subaddress_name": "Il nome del sottoindirizzo non può contenere i simboli ` , ' \" \ne deve avere una lunghezza compresa tra 1 e 20 caratteri", - "error_text_amount": "L'ammontare può contenere solo numeri", - "error_text_wallet_name": "Il nome del portafoglio può contenere solo lettere, numeri, _ - simboli\ne deve avere una lunghezza compresa tra 1 e 33 caratteri", - "error_text_keys": "Le chiavi del portafoglio possono contenere solo 64 caratteri in hex", - "error_text_crypto_currency": "Il numero delle cifre decimali\ndeve essere inferiore o uguale a 12", - "error_text_minimal_limit": "Lo scambio per ${provider} non è stato creato. L'ammontare è inferiore al minimo: ${min} ${currency}", - "error_text_maximum_limit": "Lo scambio per ${provider} non è stato creato. L'ammontare è superiore al massimo: ${max} ${currency}", - "error_text_limits_loading_failed": "Lo scambio per ${provider} non è stato creato. Caricamento dei limiti fallito", - "error_text_template": "Il nome del modello e l'indirizzo non possono contenere i simboli ` , ' \" \ne devono avere una lunghezza compresa tra 1 e 106 caratteri", + "all_trades": "Svi obrti", + "all_transactions": "Sve transakcije", + "alphabetical": "Alfabetico", + "already_have_account": "Hai già un account?", + "always": "sempre", + "amount": "Ammontare: ", + "amount_is_estimate": "L'ammontare da ricevere è una stima", + "amount_is_guaranteed": "L'ammontare da ricevere è fisso", + "and": "e", + "anonpay_description": "Genera ${type}. Il destinatario può ${method} con qualsiasi criptovaluta supportata e riceverai fondi in questo portafoglio.", + "apk_update": "Aggiornamento APK", + "approve": "Approvare", + "arrive_in_this_address": "${currency} ${tag}arriverà a questo indirizzo", + "ascending": "Ascendente", + "ask_each_time": "Chiedi ogni volta", "auth_store_ban_timeout": "ban_timeout", "auth_store_banned_for": "Bloccato per ", "auth_store_banned_minutes": " minuti", "auth_store_incorrect_password": "PIN non corretto", - "wallet_store_monero_wallet": "Portafoglio Monero", - "wallet_restoration_store_incorrect_seed_length": "Lunghezza seme non corretta", - "full_balance": "Saldo Completo", - "available_balance": "Saldo Disponibile", - "hidden_balance": "Saldo Nascosto", - "sync_status_syncronizing": "SINCRONIZZAZIONE", - "sync_status_syncronized": "SINCRONIZZATO", - "sync_status_not_connected": "NON CONNESSO", - "sync_status_starting_sync": "INIZIO SINC", - "sync_status_failed_connect": "DISCONNESSO", - "sync_status_connecting": "CONNESSIONE", - "sync_status_connected": "CONNESSO", - "sync_status_attempting_sync": "TENTATIVO DI SINCRONIZZAZIONE", - "transaction_priority_slow": "Bassa", - "transaction_priority_regular": "Regolare", - "transaction_priority_medium": "Media", - "transaction_priority_fast": "Alta", - "transaction_priority_fastest": "Massima", - "trade_for_not_created": "Lo scambio per ${title} non è stato creato.", - "trade_not_created": "Scambio non creato", - "trade_id_not_found": "Scambio ${tradeId} di ${title} not trovato.", - "trade_not_found": "Scambio non trovato.", - "trade_state_pending": "In corso", - "trade_state_confirming": "Conferma", - "trade_state_trading": "Scambio", - "trade_state_traded": "Scambiato", - "trade_state_complete": "Completato", - "trade_state_to_be_created": "Da creare", - "trade_state_unpaid": "Non pagato", - "trade_state_underpaid": "Sottopagato", - "trade_state_paid_unconfirmed": "Pagato non confermato", - "trade_state_paid": "Pagato", - "trade_state_btc_sent": "Btc inviati", - "trade_state_timeout": "Timeout", - "trade_state_created": "Creato", - "trade_state_finished": "Finito", - "change_language": "Cambia lingua", - "change_language_to": "Cambiare lingua in ${language}?", - "paste": "Incolla", - "restore_from_seed_placeholder": "Gentilmente inserisci o incolla il tuo seme qui", - "add_new_word": "Aggiungi nuova parola", - "incorrect_seed": "Il testo inserito non è valido.", - "biometric_auth_reason": "Scansiona la tua impronta per autenticarti", - "version": "Versione ${currentVersion}", - "extracted_address_content": "Invierai i tuoi fondi a\n${recipient_name}", - "card_address": "Indirizzo:", - "buy": "Comprare", - "sell": "Vendere", - "placeholder_transactions": "Le tue transazioni saranno mostrate qui", - "placeholder_contacts": "I tuoi contatti saranno mostrati qui", - "template": "Modello", - "confirm_delete_template": "Questa azione cancellerà questo modello. Desideri continuare?", - "confirm_delete_wallet": "Questa azione cancellerà questo portafoglio. Desideri continuare?", - "change_wallet_alert_title": "Cambia portafoglio attuale", - "change_wallet_alert_content": "Sei sicuro di voler cambiare il portafoglio attuale con ${wallet_name}?", - "creating_new_wallet": "Creazione nuovo portafoglio", - "creating_new_wallet_error": "Errore: ${description}", - "seed_alert_title": "Attenzione", - "seed_alert_content": "Il seme è l'unico modo per recuperare il tuo portafoglio. L'hai trascritto?", - "seed_alert_back": "Torna indietro", - "seed_alert_yes": "Sì, l'ho fatto", - "exchange_sync_alert_content": "Gentilmente aspetta che il tuo portafoglio sia sincronizzato", - "pre_seed_title": "IMPORTANTE", - "pre_seed_description": "Nella pagina seguente ti sarà mostrata una serie di parole ${words}. Questo è il tuo seme unico e privato ed è l'UNICO modo per recuperare il tuo portafoglio in caso di perdita o malfunzionamento. E' TUA responsabilità trascriverlo e conservarlo in un posto sicuro fuori dall'app Cake Wallet.", - "pre_seed_button_text": "Ho capito. Mostrami il seme", - "xmr_to_error": "XMR.TO errore", - "xmr_to_error_description": "Ammontare invalido. Il limite massimo è 8 cifre dopo il punto decimale", - "provider_error": "${provider} errore", - "use_ssl": "Usa SSL", - "trusted": "di fiducia", - "color_theme": "Colore tema", - "light_theme": "Bianco", - "bright_theme": "Colorato", - "dark_theme": "Scuro", - "enter_your_note": "Inserisci la tua nota…", - "note_optional": "Nota (opzionale)", - "note_tap_to_change": "Nota (clicca per cambiare)", - "view_in_block_explorer": "View in Block Explorer", - "view_transaction_on": "View Transaction on ", - "transaction_key": "Chiave Transazione", - "confirmations": "Conferme", - "recipient_address": "Indirizzo di destinazione", - "extra_id": "Extra ID:", - "destination_tag": "Tag destinazione:", - "memo": "Memo:", - "backup": "Backup", - "change_password": "Cambia password", - "backup_password": "Backup password", - "write_down_backup_password": "Gentilmente trascrivi la password del backup, che è usata per importare i tuoi file di backup.", - "export_backup": "Esporta backup", - "save_backup_password": "Gentilmente assicurati di aver salvato la password del tuo backup. Senza questa non sarai in grado di importare i tuoi file di backup.", - "backup_file": "Backup file", - "edit_backup_password": "Modifica Password Backup", - "save_backup_password_alert": "Salva password Backup", - "change_backup_password_alert": "I precedenti file di backup non potranno essere importati con la nuova password di backup. La nuova password di backup verrà usata soltanto per i nuovi file di backup. Sei sicuro di voler cambiare la tua password di backup?", - "enter_backup_password": "Inserisci la password di backup qui", - "select_backup_file": "Seleziona file di backup", - "import": "Importare", - "please_select_backup_file": "Gentilmente seleziona il file di backup e inserisci la password di backup.", - "fixed_rate": "Tasso fisso", - "fixed_rate_alert": "Potrai inserire l'ammontare da ricevere quando il tasso è fisso. Vuoi cambiare alla modalità tasso fisso?", - "xlm_extra_info": "Gentilmente ricorda di indicare il Memo ID quando invii la transazione XLM per lo scambio", - "xrp_extra_info": "Gentilmente ricorda di indicare il Tag di Destinazione quando invii una transazione XRP per lo scambio", - "exchange_incorrect_current_wallet_for_xmr": "Se vuoi scambiare XMR dal tuo saldo Cake Wallet Monero, gentilmente passa al tuo portafoglio Monero.", - "confirmed": "Saldo confermato", - "unconfirmed": "Saldo non confermato", - "displayable": "Visualizzabile", - "submit_request": "invia una richiesta", - "buy_alert_content": "Attualmente supportiamo solo l'acquisto di Bitcoin, Ethereum, Litecoin e Monero. Crea o passa al tuo portafoglio Bitcoin, Ethereum, Litecoin o Monero.", - "sell_alert_content": "Al momento supportiamo solo la vendita di Bitcoin, Ethereum e Litecoin. Crea o passa al tuo portafoglio Bitcoin, Ethereum o Litecoin.", - "outdated_electrum_wallet_description": "I nuovi portafogli Bitcoin creati in Cake ora hanno un seme di 24 parole. È obbligatorio creare un nuovo portafoglio Bitcoin e trasferire tutti i fondi nel nuovo portafoglio di 24 parole e smettere di usare portafogli con un seme di 12 parole. Ti preghiamo di farlo immediatamente per proteggere i tuoi fondi.", - "understand": "Capisco", - "apk_update": "Aggiornamento APK", - "buy_bitcoin": "Acquista Bitcoin", - "buy_with": "Acquista con", - "moonpay_alert_text": "Il valore dell'importo deve essere maggiore o uguale a ${minAmount} ${fiatCurrency}", - "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", - "do_not_show_me": "Non mostrarmelo di nuovo", - "unspent_coins_title": "Monete non spese", - "unspent_coins_details_title": "Dettagli sulle monete non spese", - "freeze": "Congelare", - "frozen": "Congelato", - "coin_control": "Controllo monete (opzionale)", - "address_detected": "Indirizzo rilevato", - "address_from_domain": "Questo indirizzo è da ${domain} in poi Unstoppable Domains", - "add_receiver": "Aggiungi un altro ricevitore (opzionale)", - "manage_yats": "Gestisci gli Yat", - "yat_alert_title": "Invia e ricevi criptovalute più facilmente con Yat", - "yat_alert_content": "Gli utenti di Cake Wallet possono ora inviare e ricevere tutte le loro valute preferite con un nome utente unico basato su emoji.", - "get_your_yat": "Ottieni il tuo Yat", - "connect_an_existing_yat": "Collegare un Yat esistente", - "yat_address": "Indirizzo Yat", - "yat": "Yat", - "connect_yats": "Connetti Yats", - "address_from_yat": "Questo indirizzo è da ${emoji} in poi Yat", - "yat_error": "Yat errore", - "yat_error_content": "Nessun indirizzo collegato a questo Yat. Prova un altro Yat", - "choose_address": "\n\nSi prega di scegliere l'indirizzo:", - "yat_popup_title": "L'indirizzo del tuo portafoglio può essere emoji.", - "yat_popup_content": "Ora puoi inviare e ricevere criptovalute in Cake Wallet con il tuo Yat, un breve nome utente basato su emoji. Gestisci Yats in qualsiasi momento nella schermata delle impostazioni", - "second_intro_title": "Un indirizzo emoji per domarli tutti", - "second_intro_content": "Il tuo Yat è un unico indirizzo emoji univoco che sostituisce i lunghi indirizzi per tutte le tue valute.", - "third_intro_title": "Yat gioca bene con gli altri", - "third_intro_content": "Yat può funzionare anche fuori da Cake Wallet. Qualsiasi indirizzo di portafoglio sulla terra può essere sostituito con uno Yat!", - "learn_more": "Impara di più", - "search": "Ricerca", - "search_language": "Cerca lingua", - "search_currency": "Cerca valuta", - "new_template": "Nuovo modello", - "electrum_address_disclaimer": "Generiamo nuovi indirizzi ogni volta che ne utilizzi uno, ma gli indirizzi precedenti continuano a funzionare", - "wallet_name_exists": "Il portafoglio con quel nome è già esistito", - "market_place": "Mercato", - "cake_pay_title": "Carte regalo Cake Pay", - "cake_pay_subtitle": "Acquista buoni regalo scontati (solo USA)", - "cake_pay_web_cards_title": "Carte Web Cake Pay", - "cake_pay_web_cards_subtitle": "Acquista carte prepagate e carte regalo in tutto il mondo", - "about_cake_pay": "Cake Pay ti consente di acquistare facilmente buoni regalo con asset virtuali, spendibili istantaneamente presso oltre 150.000 commercianti negli Stati Uniti.", - "cake_pay_account_note": "Iscriviti con solo un indirizzo email per vedere e acquistare le carte. Alcune sono anche disponibili con uno sconto!", - "already_have_account": "Hai già un account?", - "create_account": "Crea account", - "privacy_policy": "Informativa sulla privacy", - "welcome_to_cakepay": "Benvenuto in Cake Pay!", - "sign_up": "Registrati", - "forgot_password": "Password dimenticata", - "reset_password": "Reimposta password", - "gift_cards": "Carte regalo", - "setup_your_debit_card": "Configura la tua carta di debito", - "no_id_required": "Nessun ID richiesto. Ricarica e spendi ovunque", - "how_to_use_card": "Come usare questa carta", - "purchase_gift_card": "Acquista carta regalo", - "verification": "Verifica", - "fill_code": "Compila il codice di verifica fornito alla tua email", - "didnt_get_code": "Non ricevi il codice?", - "resend_code": "Per favore, invialo nuovamente", - "debit_card": "Carta di debito", - "cakepay_prepaid_card": "Carta di debito prepagata CakePay", - "no_id_needed": "Nessun ID necessario!", - "frequently_asked_questions": "Domande frequenti", - "debit_card_terms": "L'archiviazione e l'utilizzo del numero della carta di pagamento (e delle credenziali corrispondenti al numero della carta di pagamento) in questo portafoglio digitale sono soggetti ai Termini e condizioni del contratto applicabile con il titolare della carta con l'emittente della carta di pagamento, come in vigore da tempo al tempo.", - "please_reference_document": "Si prega di fare riferimento ai documenti di seguito per ulteriori informazioni.", - "cardholder_agreement": "Contratto del titolare della carta", - "e_sign_consent": "Consenso alla firma elettronica", - "agree_and_continue": "Accetta e continua", - "email_address": "Indirizzo e-mail", - "agree_to": "Creando un account accetti il ​​", - "and": "e", - "enter_code": "Inserisci codice", - "congratulation": "Congratulazioni!", - "you_now_have_debit_card": "Ora hai una carta di debito", - "min_amount": "Min: ${value}", - "max_amount": "Max: ${value}", - "enter_amount": "Inserisci importo", - "billing_address_info": "Se ti viene richiesto un indirizzo di fatturazione, fornisci il tuo indirizzo di spedizione", - "order_physical_card": "Ordine carta fisica", - "add_value": "Aggiungi valore", - "activate": "Attiva", - "get_a": "Prendi un ", - "digital_and_physical_card": "carta di debito prepagata digitale e fisica", - "get_card_note": "che puoi ricaricare con le valute digitali. Non sono necessarie informazioni aggiuntive!", - "signup_for_card_accept_terms": "Registrati per la carta e accetta i termini.", - "add_fund_to_card": "Aggiungi fondi prepagati alle carte (fino a ${value})", - "use_card_info_two": "I fondi vengono convertiti in USD quando sono detenuti nel conto prepagato, non in valute digitali.", - "use_card_info_three": "Utilizza la carta digitale online o con metodi di pagamento contactless.", - "optional_order_card": "Ordina facoltativamente una carta fisica.", - "hide_details": "Nascondi dettagli", - "show_details": "Mostra dettagli", - "upto": "fino a ${value}", - "discount": "Risparmia ${value}%", - "gift_card_amount": "Importo del buono regalo", - "bill_amount": "Importo della fattura", - "you_pay": "Tu paghi", - "tip": "Suggerimento:", - "custom": "personalizzato", - "by_cake_pay": "da Cake Pay", - "expires": "Scade", - "mm": "mm", - "yy": "YY", - "online": "in linea", - "offline": "Offline", - "gift_card_number": "Numero del buono regalo", - "pin_number": "Numero PIN", - "total_saving": "Risparmio totale", - "last_30_days": "Ultimi 30 giorni", - "avg_savings": "Risparmio medio", - "view_all": "Visualizza tutto", - "active_cards": "Carte attive", - "delete_account": "Elimina account", - "cards": "Carte", - "active": "Attivo", - "redeemed": "Redento", - "gift_card_balance_note": "Le carte regalo con un saldo residuo appariranno qui", - "gift_card_redeemed_note": "Le carte regalo che hai riscattato appariranno qui", - "logout": "Logout", - "add_tip": "Aggiungi suggerimento", - "percentageOf": "di ${amount}", - "is_percentage": "è", - "search_category": "Categoria di ricerca", - "mark_as_redeemed": "Segna come riscattato", - "more_options": "Altre opzioni", - "waiting_payment_confirmation": "In attesa di conferma del pagamento", - "transaction_sent_notice": "Se lo schermo non procede dopo 1 minuto, controlla un block explorer e la tua email.", - "agree": "d'accordo", - "in_store": "In negozio", - "generating_gift_card": "Generazione carta regalo", - "payment_was_received": "Il tuo pagamento è stato ricevuto.", - "proceed_after_one_minute": "Se lo schermo non procede dopo 1 minuto, controlla la tua email.", - "order_id": "ID ordine", - "gift_card_is_generated": "Il buono regalo è stato generato", - "open_gift_card": "Apri carta regalo", - "contact_support": "Contatta l'assistenza", - "gift_cards_unavailable": "Le carte regalo sono disponibili per l'acquisto solo tramite Monero, Bitcoin e Litecoin in questo momento", - "background_sync_mode": "Modalità di sincronizzazione in background", - "sync_all_wallets": "Sincronizza tutti i portafogli", - "introducing_cake_pay": "Presentazione di Cake Pay!", - "cake_pay_learn_more": "Acquista e riscatta istantaneamente carte regalo nell'app!\nScorri da sinistra a destra per saperne di più.", - "automatic": "Automatico", - "fixed_pair_not_supported": "Questa coppia fissa non è supportata con gli scambi selezionati", - "variable_pair_not_supported": "Questa coppia di variabili non è supportata con gli scambi selezionati", - "none_of_selected_providers_can_exchange": "Nessuno dei fornitori selezionati può effettuare questo scambio", - "choose_one": "Scegline uno", - "choose_from_available_options": "Scegli tra le opzioni disponibili:", - "custom_redeem_amount": "Importo di riscatto personalizzato", - "add_custom_redemption": "Aggiungi riscatto personalizzato", - "remaining": "rimanente", - "delete_wallet": "Elimina portafoglio", - "delete_wallet_confirm_message": "Sei sicuro di voler eliminare il portafoglio ${wallet_name}?", - "low_fee": "Tariffa bassa", - "low_fee_alert": "Attualmente stai utilizzando una priorità a tariffa di rete bassa. Ciò potrebbe causare lunghe attese, tariffe diverse o operazioni annullate. Ti consigliamo di impostare una tariffa più alta per un'esperienza migliore.", - "ignor": "Ignorare", - "use_suggested": "Usa suggerito", - "do_not_share_warning_text": "Non condividerli con nessun altro, incluso il supporto.\n\nI tuoi fondi possono e saranno rubati!", - "help": "aiuto", - "all_transactions": "Sve transakcije", - "all_trades": "Svi obrti", - "connection_sync": "Connessione e sincronizzazione", - "security_and_backup": "Sicurezza e backup", - "create_backup": "Crea backup", - "privacy_settings": "Impostazioni privacy", - "privacy": "Privacy", - "display_settings": "Impostazioni di visualizzazione", - "other_settings": "Altre impostazioni", - "require_pin_after": "Richiedi PIN dopo", - "always": "sempre", - "minutes_to_pin_code": "${minute} minuti", - "disable_exchange": "Disabilita scambio", - "advanced_settings": "Impostazioni avanzate", - "settings_can_be_changed_later": "Queste impostazioni possono essere modificate in seguito nelle impostazioni dell'app", - "add_custom_node": "Aggiungi nuovo nodo personalizzato", - "disable_fiat": "Disabilita fiat", - "fiat_api": "Fiat API", - "disabled": "Disabilitato", - "enabled": "Abilitato", - "tor_only": "Solo Tor", - "unmatched_currencies": "La valuta del tuo portafoglio attuale non corrisponde a quella del QR scansionato", - "orbot_running_alert": "Assicurati che Orbot sia in esecuzione prima di connetterti a questo nodo.", - "contact_list_contacts": "Contatti", - "contact_list_wallets": "I miei portafogli", - "bitcoin_payments_require_1_confirmation": "I pagamenti in bitcoin richiedono 1 conferma, che può richiedere 20 minuti o più. Grazie per la vostra pazienza! Riceverai un'e-mail quando il pagamento sarà confermato.", - "send_to_this_address": "Invia ${currency} ${tag}a questo indirizzo", - "arrive_in_this_address": "${currency} ${tag}arriverà a questo indirizzo", - "do_not_send": "Non inviare", - "error_dialog_content": "Spiacenti, abbiamo riscontrato un errore.\n\nSi prega di inviare il rapporto sull'arresto anomalo al nostro team di supporto per migliorare l'applicazione.", - "scan_qr_code": "Scansiona il codice QR", - "cold_or_recover_wallet": "Aggiungi un cold wallet o recupera un paper wallet", - "please_wait": "Attendere prego", - "sweeping_wallet": "Portafoglio ampio", - "sweeping_wallet_alert": "Questo non dovrebbe richiedere molto tempo. NON LASCIARE QUESTA SCHERMATA O I FONDI SPAZZATI POTREBBERO ANDARE PERSI", - "decimal_places_error": "Troppe cifre decimali", - "edit_node": "Modifica nodo", - "invoice_details": "Dettagli della fattura", - "donation_link_details": "Dettagli del collegamento alla donazione", - "anonpay_description": "Genera ${type}. Il destinatario può ${method} con qualsiasi criptovaluta supportata e riceverai fondi in questo portafoglio.", - "create_invoice": "Crea fattura", - "create_donation_link": "Crea un link per la donazione", - "optional_email_hint": "Email di notifica del beneficiario facoltativa", - "optional_description": "Descrizione facoltativa", - "optional_name": "Nome del destinatario facoltativo", - "clearnet_link": "Collegamento Clearnet", - "onion_link": "Collegamento a cipolla", - "settings": "Impostazioni", - "sell_monero_com_alert_content": "La vendita di Monero non è ancora supportata", - "error_text_input_below_minimum_limit": "L'ammontare è inferiore al minimo", - "error_text_input_above_maximum_limit": "L'ammontare è superiore al massimo", - "show_market_place": "Mostra mercato", - "prevent_screenshots": "Impedisci screenshot e registrazione dello schermo", - "profile": "Profilo", - "close": "Chiudere", - "modify_2fa": "Modifica Torta 2FA", - "disable_cake_2fa": "Disabilita Cake 2FA", - "question_to_disable_2fa": "Sei sicuro di voler disabilitare Cake 2FA? Non sarà più necessario un codice 2FA per accedere al portafoglio e ad alcune funzioni.", - "disable": "disattivare", - "setup_2fa": "Imposta la torta 2FA", - "verify_with_2fa": "Verifica con Cake 2FA", - "totp_code": "Codice TOTP", - "please_fill_totp": "Inserisci il codice di 8 cifre presente sull'altro tuo dispositivo", - "totp_2fa_success": "Successo! Cake 2FA abilitato per questo portafoglio. Ricordati di salvare il tuo seme mnemonico nel caso in cui perdi l'accesso al portafoglio.", - "totp_verification_success": "Verifica riuscita!", - "totp_2fa_failure": "Codice non corretto. Prova un codice diverso o genera una nuova chiave segreta. Utilizza un'app 2FA compatibile che supporti codici a 8 cifre e SHA512.", - "enter_totp_code": "Inserisci il codice TOTP.", - "add_secret_code": "Oppure aggiungi questo codice segreto a un'app di autenticazione", - "totp_secret_code": "TOTP codice segreto", - "setup_2fa_text": "Cake 2FA funziona utilizzando TOTP come secondo fattore di autenticazione.\n\nIl TOTP di Cake 2FA richiede il supporto SHA-512 e 8 cifre; ciò fornisce una maggiore sicurezza. Maggiori informazioni e app supportate sono disponibili nella guida.", - "setup_totp_recommended": "Imposta TOTP", - "disable_buy": "Disabilita l'azione di acquisto", - "disable_sell": "Disabilita l'azione di vendita", + "authenticated": "Autenticato", + "authentication": "Autenticazione", "auto_generate_subaddresses": "Genera automaticamente sottindirizzi", - "cake_2fa_preset": "Torta 2FA Preset", - "narrow": "Stretto", - "normal": "Normale", - "aggressive": "Fervente", - "require_for_assessing_wallet": "Richiesto per l'accesso al portafoglio", - "require_for_sends_to_non_contacts": "Richiesto per invii a non contatti", - "require_for_sends_to_contacts": "Richiedi per gli invii ai contatti", - "require_for_sends_to_internal_wallets": "Richiesto per invii a portafogli interni", - "require_for_exchanges_to_internal_wallets": "Richiedi per gli scambi ai portafogli interni", - "require_for_adding_contacts": "Richiesto per l'aggiunta di contatti", - "require_for_creating_new_wallets": "Richiesto per la creazione di nuovi portafogli", - "require_for_all_security_and_backup_settings": "Richiedi per tutte le impostazioni di sicurezza e backup", + "automatic": "Automatico", + "available_balance": "Saldo Disponibile", "available_balance_description": "Il saldo disponibile è il saldo totale meno i fondi congelati. I fondi congelati sono fondi che sono stati inviati ma non sono ancora stati confermati.", - "syncing_wallet_alert_title": "Il tuo portafoglio si sta sincronizzando", - "syncing_wallet_alert_content": "Il saldo e l'elenco delle transazioni potrebbero non essere completi fino a quando non viene visualizzato \"SYNCHRONIZED\" in alto. Clicca/tocca per saperne di più.", - "home_screen_settings": "Impostazioni della schermata iniziale", - "sort_by": "Ordina per", - "search_add_token": "Cerca / Aggiungi token", - "edit_token": "Modifica token", - "warning": "Avvertimento", - "add_token_warning": "Non modificare o aggiungere token come indicato dai truffatori.\nConferma sempre gli indirizzi dei token con fonti attendibili!", - "add_token_disclaimer_check": "Ho confermato l'indirizzo e le informazioni del contratto token utilizzando una fonte attendibile. L'aggiunta di informazioni dannose o errate può comportare una perdita di fondi.", - "token_contract_address": "Indirizzo del contratto token", - "token_name": "Nome del token, ad esempio: Tether", - "token_symbol": "Simbolo del token, ad esempio: USDT", - "token_decimal": "Decimale del token", - "field_required": "Questo campo è obbligatorio", - "pin_at_top": "fissa ${token} in alto", - "invalid_input": "Inserimento non valido", - "fiat_balance": "Equilibrio fiat", - "gross_balance": "Saldo lordo", - "alphabetical": "Alfabetico", - "generate_name": "Genera nome", + "avg_savings": "Risparmio medio", + "awaitDAppProcessing": "Attendi gentilmente che la dApp termini l'elaborazione.", + "background_sync_mode": "Modalità di sincronizzazione in background", + "backup": "Backup", + "backup_file": "Backup file", + "backup_password": "Backup password", "balance_page": "Pagina di equilibrio", - "share": "Condividere", - "slidable": "Scorrevole", - "monero_dark_theme": "Tema scuro di Monero", + "bill_amount": "Importo della fattura", + "billing_address_info": "Se ti viene richiesto un indirizzo di fatturazione, fornisci il tuo indirizzo di spedizione", + "biometric_auth_reason": "Scansiona la tua impronta per autenticarti", "bitcoin_dark_theme": "Tema oscuro di Bitcoin", "bitcoin_light_theme": "Tema luce Bitcoin", - "high_contrast_theme": "Tema ad alto contrasto", - "matrix_green_dark_theme": "Tema Matrix verde scuro", - "monero_light_theme": "Tema leggero Monero", - "manage_nodes": "Gestisci i nodi", - "etherscan_history": "Storia Etherscan", - "template_name": "Nome modello", + "bitcoin_payments_require_1_confirmation": "I pagamenti in bitcoin richiedono 1 conferma, che può richiedere 20 minuti o più. Grazie per la vostra pazienza! Riceverai un'e-mail quando il pagamento sarà confermato.", + "Blocks_remaining": "${status} Blocchi Rimanenti", + "bright_theme": "Colorato", + "buy": "Comprare", + "buy_alert_content": "Attualmente supportiamo solo l'acquisto di Bitcoin, Ethereum, Litecoin e Monero. Crea o passa al tuo portafoglio Bitcoin, Ethereum, Litecoin o Monero.", + "buy_bitcoin": "Acquista Bitcoin", + "buy_provider_unavailable": "Provider attualmente non disponibile.", + "buy_with": "Acquista con", + "by_cake_pay": "da Cake Pay", + "cake_2fa_preset": "Torta 2FA Preset", + "cake_pay_account_note": "Iscriviti con solo un indirizzo email per vedere e acquistare le carte. Alcune sono anche disponibili con uno sconto!", + "cake_pay_learn_more": "Acquista e riscatta istantaneamente carte regalo nell'app!\nScorri da sinistra a destra per saperne di più.", + "cake_pay_subtitle": "Acquista buoni regalo scontati (solo USA)", + "cake_pay_title": "Carte regalo Cake Pay", + "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_wallet": "Cake Wallet", + "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.", + "camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.", + "cancel": "Cancella", + "card_address": "Indirizzo:", + "cardholder_agreement": "Contratto del titolare della carta", + "cards": "Carte", + "chains": "Catene", + "change": "Cambia", + "change_backup_password_alert": "I precedenti file di backup non potranno essere importati con la nuova password di backup. La nuova password di backup verrà usata soltanto per i nuovi file di backup. Sei sicuro di voler cambiare la tua password di backup?", + "change_currency": "Cambia Valuta", + "change_current_node": "Sei sicuro di voler cambiare il nodo corrente con ${node}?", + "change_current_node_title": "Cambia nodo corrente", + "change_exchange_provider": "Cambia Exchange", + "change_language": "Cambia lingua", + "change_language_to": "Cambiare lingua in ${language}?", + "change_password": "Cambia password", "change_rep": "Cambia rappresentante", "change_rep_message": "Sei sicuro di voler cambiare rappresentante?", - "unsupported_asset": "Non supportiamo questa azione per questa risorsa. Crea o passa a un portafoglio di un tipo di asset supportato.", - "manage_pow_nodes": "Gestisci i nodi PoW", - "support_title_live_chat": "Supporto dal vivo", - "support_description_live_chat": "Gratuito e veloce! I rappresentanti di supporto qualificati sono disponibili per assistere", - "support_title_guides": "Guide del portafoglio per torte", - "support_description_guides": "Documentazione e supporto per problemi comuni", - "support_title_other_links": "Altri collegamenti di supporto", - "support_description_other_links": "Unisciti alle nostre comunità o raggiungici i nostri partner attraverso altri metodi", + "change_rep_successful": "Rappresentante modificato con successo", + "change_wallet_alert_content": "Sei sicuro di voler cambiare il portafoglio attuale con ${wallet_name}?", + "change_wallet_alert_title": "Cambia portafoglio attuale", + "choose_account": "Scegli account", + "choose_address": "\n\nSi prega di scegliere l'indirizzo:", "choose_derivation": "Scegli la derivazione del portafoglio", - "new_first_wallet_text": "Mantieni facilmente la tua criptovaluta al sicuro", - "select_destination": "Seleziona la destinazione per il file di backup.", - "save_to_downloads": "Salva in Download", - "select_buy_provider_notice": "Seleziona un fornitore di acquisto sopra. È possibile saltare questa schermata impostando il provider di acquisto predefinito nelle impostazioni dell'app.", - "onramper_option_description": "Acquista rapidamente la criptovaluta con molti metodi di pagamento. Disponibile nella maggior parte dei paesi. Gli spread e le commissioni variano.", + "choose_from_available_options": "Scegli tra le opzioni disponibili:", + "choose_one": "Scegline uno", + "choose_relay": "Scegli un relè da utilizzare", + "choose_wallet_currency": "Gentilmente scegli la moneta del portafoglio:", + "clear": "Pulisci", + "clearnet_link": "Collegamento Clearnet", + "close": "Chiudere", + "coin_control": "Controllo monete (opzionale)", + "cold_or_recover_wallet": "Aggiungi un cold wallet o recupera un paper wallet", + "color_theme": "Colore tema", + "commit_transaction_amount_fee": "Invia transazione\nAmmontare: ${amount}\nCommissione: ${fee}", + "confirm": "Conferma", + "confirm_delete_template": "Questa azione cancellerà questo modello. Desideri continuare?", + "confirm_delete_wallet": "Questa azione cancellerà questo portafoglio. Desideri continuare?", + "confirm_sending": "Conferma l'invio", + "confirmations": "Conferme", + "confirmed": "Saldo confermato", + "confirmed_tx": "Confermato", + "congratulation": "Congratulazioni!", + "connect_an_existing_yat": "Collegare un Yat esistente", + "connect_yats": "Connetti Yats", + "connection_sync": "Connessione e sincronizzazione", + "connectWalletPrompt": "Collega il tuo portafoglio con WalletConnect per effettuare transazioni", + "contact": "Contatta", + "contact_list_contacts": "Contatti", + "contact_list_wallets": "I miei portafogli", + "contact_name": "Nome Contatto", + "contact_support": "Contatta l'assistenza", + "continue_text": "Continua", + "contractName": "Nome del contratto", + "contractSymbol": "Simbolo del contratto", + "copied_key_to_clipboard": " ${key} copiata negli Appunti", + "copied_to_clipboard": "Copiato negli Appunti", + "copy": "Copia", + "copy_address": "Copia Indirizzo", + "copy_id": "Copia ID", + "copyWalletConnectLink": "Copia il collegamento WalletConnect dalla dApp e incollalo qui", + "create_account": "Crea account", + "create_backup": "Crea backup", + "create_donation_link": "Crea un link per la donazione", + "create_invoice": "Crea fattura", + "create_new": "Genera nuovo Portafoglio", + "create_new_account": "Crea nuovo account", + "creating_new_wallet": "Creazione nuovo portafoglio", + "creating_new_wallet_error": "Errore: ${description}", + "creation_date": "Data di creazione", + "custom": "personalizzato", + "custom_drag": "Custom (Hold and Drag)", + "custom_redeem_amount": "Importo di riscatto personalizzato", + "dark_theme": "Scuro", + "debit_card": "Carta di debito", + "debit_card_terms": "L'archiviazione e l'utilizzo del numero della carta di pagamento (e delle credenziali corrispondenti al numero della carta di pagamento) in questo portafoglio digitale sono soggetti ai Termini e condizioni del contratto applicabile con il titolare della carta con l'emittente della carta di pagamento, come in vigore da tempo al tempo.", + "decimal_places_error": "Troppe cifre decimali", "default_buy_provider": "Provider di acquisto predefinito", - "ask_each_time": "Chiedi ogni volta", - "buy_provider_unavailable": "Provider attualmente non disponibile.", - "signTransaction": "Firma la transazione", + "default_sell_provider": "Fornitore di vendita predefinito", + "delete": "Elimina", + "delete_account": "Elimina account", + "delete_wallet": "Elimina portafoglio", + "delete_wallet_confirm_message": "Sei sicuro di voler eliminare il portafoglio ${wallet_name}?", + "deleteConnectionConfirmationPrompt": "Sei sicuro di voler eliminare la connessione a", + "descending": "Discendente", + "description": "Descrizione", + "destination_tag": "Tag destinazione:", + "dfx_option_description": "Acquista criptovalute con EUR e CHF. Fino a 990€ senza KYC aggiuntivi. Per clienti al dettaglio e aziendali in Europa", + "didnt_get_code": "Non ricevi il codice?", + "digit_pin": "-cifre PIN", + "digital_and_physical_card": "carta di debito prepagata digitale e fisica", + "disable": "disattivare", + "disable_buy": "Disabilita l'azione di acquisto", + "disable_cake_2fa": "Disabilita Cake 2FA", + "disable_exchange": "Disabilita scambio", + "disable_fiat": "Disabilita fiat", + "disable_sell": "Disabilita l'azione di vendita", + "disabled": "Disabilitato", + "discount": "Risparmia ${value}%", + "display_settings": "Impostazioni di visualizzazione", + "displayable": "Visualizzabile", + "do_not_have_enough_gas_asset": "Non hai abbastanza ${currency} per effettuare una transazione con le attuali condizioni della rete blockchain. Hai bisogno di più ${currency} per pagare le commissioni della rete blockchain, anche se stai inviando una risorsa diversa.", + "do_not_send": "Non inviare", + "do_not_share_warning_text": "Non condividerli con nessun altro, incluso il supporto.\n\nI tuoi fondi possono e saranno rubati!", + "do_not_show_me": "Non mostrarmelo di nuovo", + "domain_looks_up": "Ricerche di domini", + "donation_link_details": "Dettagli del collegamento alla donazione", + "e_sign_consent": "Consenso alla firma elettronica", + "edit": "Modifica", + "edit_backup_password": "Modifica Password Backup", + "edit_node": "Modifica nodo", + "edit_token": "Modifica token", + "electrum_address_disclaimer": "Generiamo nuovi indirizzi ogni volta che ne utilizzi uno, ma gli indirizzi precedenti continuano a funzionare", + "email_address": "Indirizzo e-mail", + "enabled": "Abilitato", + "enter_amount": "Inserisci importo", + "enter_backup_password": "Inserisci la password di backup qui", + "enter_code": "Inserisci codice", + "enter_seed_phrase": "Inserisci la tua frase di semi", + "enter_totp_code": "Inserisci il codice TOTP.", + "enter_your_note": "Inserisci la tua nota…", + "enter_your_pin": "Inserisci il tuo PIN", + "enter_your_pin_again": "Inserisci il tuo pin di nuovo", + "enterTokenID": "Inserisci l'ID del token", + "enterWalletConnectURI": "Inserisci l'URI di WalletConnect", + "error": "Errore", + "error_dialog_content": "Spiacenti, abbiamo riscontrato un errore.\n\nSi prega di inviare il rapporto sull'arresto anomalo al nostro team di supporto per migliorare l'applicazione.", + "error_text_account_name": "Il nome del conto può contenere solo lettere, numeri\ne deve avere una lunghezza compresa tra 1 e 15 caratteri", + "error_text_address": "L'indirizzo del Portafoglio deve corrispondere alla tipologia\ndi criptovaluta", + "error_text_amount": "L'ammontare può contenere solo numeri", + "error_text_contact_name": "Il nome del Contatto non può contenere i simboli ` , ' \" \ne deve avere una lunghezza compresa tra 1 e 32 caratteri", + "error_text_crypto_currency": "Il numero delle cifre decimali\ndeve essere inferiore o uguale a 12", + "error_text_fiat": "L'ammontare non può eccedere il saldo dispoinibile.\nIl numero di cifre decimali deve essere inferiore o uguale a 2", + "error_text_input_above_maximum_limit": "L'ammontare è superiore al massimo", + "error_text_input_below_minimum_limit": "L'ammontare è inferiore al minimo", + "error_text_keys": "Le chiavi del portafoglio possono contenere solo 64 caratteri in hex", + "error_text_limits_loading_failed": "Lo scambio per ${provider} non è stato creato. Caricamento dei limiti fallito", + "error_text_maximum_limit": "Lo scambio per ${provider} non è stato creato. L'ammontare è superiore al massimo: ${max} ${currency}", + "error_text_minimal_limit": "Lo scambio per ${provider} non è stato creato. L'ammontare è inferiore al minimo: ${min} ${currency}", + "error_text_node_address": "Gentilmente inserisci un indirizzo iPv4", + "error_text_node_port": "La porta del nodo può contenere solo numeri compresi tra 0 e 65535", + "error_text_node_proxy_address": "Inserisci :, ad esempio 127.0.0.1:9050", + "error_text_payment_id": "L'ID del pagamento può contenere solo da 16 a 64 caratteri in esadecimale", + "error_text_subaddress_name": "Il nome del sottoindirizzo non può contenere i simboli ` , ' \" \ne deve avere una lunghezza compresa tra 1 e 20 caratteri", + "error_text_template": "Il nome del modello e l'indirizzo non possono contenere i simboli ` , ' \" \ne devono avere una lunghezza compresa tra 1 e 106 caratteri", + "error_text_wallet_name": "Il nome del portafoglio può contenere solo lettere, numeri, _ - simboli\ne deve avere una lunghezza compresa tra 1 e 33 caratteri", + "error_text_xmr": "Il valore in XMR non può eccedere il saldo disponibile.\nIl numero delle cifre decimali deve essere inferiore o uguale a 12", "errorGettingCredentials": "Non riuscito: errore durante il recupero delle credenziali", "errorSigningTransaction": "Si è verificato un errore durante la firma della transazione", - "pairingInvalidEvent": "Associazione evento non valido", - "chains": "Catene", - "methods": "Metodi", - "events": "Eventi", - "reject": "Rifiutare", - "approve": "Approvare", - "expiresOn": "Scade il", - "walletConnect": "PortafoglioConnetti", - "nullURIError": "L'URI è nullo", - "connectWalletPrompt": "Collega il tuo portafoglio con WalletConnect per effettuare transazioni", - "newConnection": "Nuova connessione", - "activeConnectionsPrompt": "Le connessioni attive verranno visualizzate qui", - "deleteConnectionConfirmationPrompt": "Sei sicuro di voler eliminare la connessione a", + "estimated": "Stimato", + "etherscan_history": "Storia Etherscan", "event": "Evento", - "successful": "Riuscito", - "wouoldLikeToConnect": "vorrei connettermi", - "message": "Messaggio", - "do_not_have_enough_gas_asset": "Non hai abbastanza ${currency} per effettuare una transazione con le attuali condizioni della rete blockchain. Hai bisogno di più ${currency} per pagare le commissioni della rete blockchain, anche se stai inviando una risorsa diversa.", - "totp_auth_url": "URL DI AUT. TOTP", - "awaitDAppProcessing": "Attendi gentilmente che la dApp termini l'elaborazione.", - "copyWalletConnectLink": "Copia il collegamento WalletConnect dalla dApp e incollalo qui", - "enterWalletConnectURI": "Inserisci l'URI di WalletConnect", - "seed_key": "Chiave di semi", - "enter_seed_phrase": "Inserisci la tua frase di semi", - "change_rep_successful": "Rappresentante modificato con successo", - "add_contact": "Aggiungi contatto", + "events": "Eventi", + "exchange": "Scambia", + "exchange_incorrect_current_wallet_for_xmr": "Se vuoi scambiare XMR dal tuo saldo Cake Wallet Monero, gentilmente passa al tuo portafoglio Monero.", + "exchange_new_template": "Nuovo modello", "exchange_provider_unsupported": "${providerName} non è più supportato!", - "domain_looks_up": "Ricerche di domini", - "require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni", - "camera_permission_is_required": "È richiesta l'autorizzazione della fotocamera.\nAbilitalo dalle impostazioni dell'app.", - "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova", - "order_by": "Ordinato da", - "creation_date": "Data di creazione", + "exchange_result_confirm": "Cliccando su Conferma, invierai ${fetchingLabel} ${from} dal tuo portafoglio chiamato ${walletName} all'indirizzo mostrato qui in basso. O puoi inviare dal tuo portafoglio esterno all'indirizzo/codice QR mostrato in basso.\n\nGentilmente clicca su Conferma per continuare o torna indietro per cambiare l'ammontare.", + "exchange_result_description": "Devi inviare un minimo di ${fetchingLabel} ${from} all'indirizzo mostrato nella pagina seguente. Se invii un ammontare inferiore a ${fetchingLabel} ${from} la conversione potrebbe non andare a buon fine e l'indirizzo potrebbe non essere rimborsato.", + "exchange_result_write_down_ID": "*Gentilmente fai una copia o trascrivi il tuo ID mostrato in alto.", + "exchange_result_write_down_trade_id": "Per favore fai una copia o trascrivi l'ID dello scambio per continuare.", + "exchange_sync_alert_content": "Gentilmente aspetta che il tuo portafoglio sia sincronizzato", + "expired": "Scaduta", + "expires": "Scade", + "expiresOn": "Scade il", + "export_backup": "Esporta backup", + "extra_id": "Extra ID:", + "extracted_address_content": "Invierai i tuoi fondi a\n${recipient_name}", + "failed_authentication": "Autenticazione fallita. ${state_error}", + "faq": "Domande Frequenti", + "fetching": "Recupero", + "fiat_api": "Fiat API", + "fiat_balance": "Equilibrio fiat", + "field_required": "Questo campo è obbligatorio", + "fill_code": "Compila il codice di verifica fornito alla tua email", + "filter_by": "Filtrirati po", + "first_wallet_text": "Portafoglio fantastico per Monero, Bitcoin, Ethereum, Litecoin, e Haven", + "fixed_pair_not_supported": "Questa coppia fissa non è supportata con gli scambi selezionati", + "fixed_rate": "Tasso fisso", + "fixed_rate_alert": "Potrai inserire l'ammontare da ricevere quando il tasso è fisso. Vuoi cambiare alla modalità tasso fisso?", + "forgot_password": "Password dimenticata", + "freeze": "Congelare", + "frequently_asked_questions": "Domande frequenti", + "frozen": "Congelato", + "full_balance": "Saldo Completo", + "generate_name": "Genera nome", + "generating_gift_card": "Generazione carta regalo", + "get_a": "Prendi un ", + "get_card_note": "che puoi ricaricare con le valute digitali. Non sono necessarie informazioni aggiuntive!", + "get_your_yat": "Ottieni il tuo Yat", + "gift_card_amount": "Importo del buono regalo", + "gift_card_balance_note": "Le carte regalo con un saldo residuo appariranno qui", + "gift_card_is_generated": "Il buono regalo è stato generato", + "gift_card_number": "Numero del buono regalo", + "gift_card_redeemed_note": "Le carte regalo che hai riscattato appariranno qui", + "gift_cards": "Carte regalo", + "gift_cards_unavailable": "Le carte regalo sono disponibili per l'acquisto solo tramite Monero, Bitcoin e Litecoin in questo momento", + "got_it": "Ho capito", + "gross_balance": "Saldo lordo", "group_by_type": "Gruppo per tipo", - "importNFTs": "Importa NFT", - "noNFTYet": "Nessun NFT ancora", - "address": "Indirizzo", - "enterTokenID": "Inserisci l'ID del token", - "tokenID": "ID", - "name": "Nome", - "symbol": "Simbolo", - "seed_phrase_length": "Lunghezza della frase seed", - "unavailable_balance": "Saldo non disponibile", - "unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.", - "unspent_change": "Modifica", - "tor_connection": "Connessione Tor", - "setup_warning_2fa_text": "Dovrai ripristinare il tuo portafoglio dal seme mnemonico.\n\nIl supporto di Cake non sarà in grado di assisterti se perdi l'accesso ai tuoi seed 2FA o mnemonici.\nCake 2FA è una seconda autenticazione per determinate azioni nel portafoglio. Prima di utilizzare Cake 2FA, ti consigliamo di leggere la guida.NON è sicuro come la conservazione a freddo.\n\nSe perdi l'accesso alla tua app 2FA o alle chiavi TOTP, perderai l'accesso a questo portafoglio. ", - "scan_qr_on_device": "Scansiona questo codice QR su un altro dispositivo", + "haven_app": "Haven by Cake Wallet", + "haven_app_wallet_text": "Portafoglio fantastico per Haven", + "help": "aiuto", + "hidden_balance": "Saldo Nascosto", + "hide_details": "Nascondi dettagli", + "high_contrast_theme": "Tema ad alto contrasto", + "home_screen_settings": "Impostazioni della schermata iniziale", "how_to_use": "Come usare", + "how_to_use_card": "Come usare questa carta", + "id": "ID: ", + "ignor": "Ignorare", + "import": "Importare", + "importNFTs": "Importa NFT", + "in_store": "In negozio", + "incoming": "In arrivo", + "incorrect_seed": "Il testo inserito non è valido.", + "introducing_cake_pay": "Presentazione di Cake Pay!", + "invalid_input": "Inserimento non valido", + "invoice_details": "Dettagli della fattura", + "is_percentage": "è", + "last_30_days": "Ultimi 30 giorni", + "learn_more": "Impara di più", + "light_theme": "Bianco", + "loading_your_wallet": "Caricamento portafoglio", + "login": "Accedi", + "logout": "Logout", + "low_fee": "Tariffa bassa", + "low_fee_alert": "Attualmente stai utilizzando una priorità a tariffa di rete bassa. Ciò potrebbe causare lunghe attese, tariffe diverse o operazioni annullate. Ti consigliamo di impostare una tariffa più alta per un'esperienza migliore.", + "manage_nodes": "Gestisci i nodi", + "manage_pow_nodes": "Gestisci i nodi PoW", + "manage_yats": "Gestisci gli Yat", + "mark_as_redeemed": "Segna come riscattato", + "market_place": "Mercato", + "matrix_green_dark_theme": "Tema Matrix verde scuro", + "max_amount": "Max: ${value}", + "max_value": "Max: ${value} ${currency}", + "memo": "Memo:", + "message": "Messaggio", + "methods": "Metodi", + "min_amount": "Min: ${value}", + "min_value": "Min: ${value} ${currency}", + "minutes_to_pin_code": "${minute} minuti", + "mm": "mm", + "modify_2fa": "Modifica Torta 2FA", + "monero_com": "Monero.com by Cake Wallet", + "monero_com_wallet_text": "Portafoglio fantastico per Monero", + "monero_dark_theme": "Tema scuro di Monero", + "monero_light_theme": "Tema leggero Monero", + "moonpay_alert_text": "Il valore dell'importo deve essere maggiore o uguale a ${minAmount} ${fiatCurrency}", + "more_options": "Altre opzioni", + "name": "Nome", + "narrow": "Stretto", + "new_first_wallet_text": "Mantieni facilmente la tua criptovaluta al sicuro", + "new_node_testing": "Test novo nodo", + "new_subaddress_create": "Crea", + "new_subaddress_label_name": "Nome etichetta", + "new_subaddress_title": "Nuovo indirizzo", + "new_template": "Nuovo modello", + "new_wallet": "Nuovo Portafoglio", + "newConnection": "Nuova connessione", + "no_id_needed": "Nessun ID necessario!", + "no_id_required": "Nessun ID richiesto. Ricarica e spendi ovunque", + "no_relay_on_domain": "Non esiste un inoltro per il dominio dell'utente oppure l'inoltro non è disponibile. Scegli un relè da utilizzare.", + "no_relays": "Nessun relè", + "no_relays_message": "Abbiamo trovato un record Nostr NIP-05 per questo utente, ma non contiene alcun relè. Si prega di indicare al destinatario di aggiungere inoltri al proprio record Nostr.", + "node_address": "Indirizzo Nodo", + "node_connection_failed": "Connessione fallita", + "node_connection_successful": "Connessione avvenuta con successo", + "node_new": "Nuovo Nodo", + "node_port": "Porta Nodo", + "node_reset_settings_title": "Ripristina impostazioni", + "node_test": "Test", + "nodes": "Nodi", + "nodes_list_reset_to_default_message": "Sei sicuro di voler ripristinare le impostazioni predefinite?", + "none_of_selected_providers_can_exchange": "Nessuno dei fornitori selezionati può effettuare questo scambio", + "noNFTYet": "Nessun NFT ancora", + "normal": "Normale", + "note_optional": "Nota (opzionale)", + "note_tap_to_change": "Nota (clicca per cambiare)", + "nullURIError": "L'URI è nullo", + "offer_expires_in": "Offerta termina tra: ", + "offline": "Offline", + "ok": "OK", + "onion_link": "Collegamento a cipolla", + "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", + "optional_description": "Descrizione facoltativa", + "optional_email_hint": "Email di notifica del beneficiario facoltativa", + "optional_name": "Nome del destinatario facoltativo", + "optional_order_card": "Ordina facoltativamente una carta fisica.", + "orbot_running_alert": "Assicurati che Orbot sia in esecuzione prima di connetterti a questo nodo.", + "order_by": "Ordinato da", + "order_id": "ID ordine", + "order_physical_card": "Ordine carta fisica", + "other_settings": "Altre impostazioni", + "outdated_electrum_wallet_description": "I nuovi portafogli Bitcoin creati in Cake ora hanno un seme di 24 parole. È obbligatorio creare un nuovo portafoglio Bitcoin e trasferire tutti i fondi nel nuovo portafoglio di 24 parole e smettere di usare portafogli con un seme di 12 parole. Ti preghiamo di farlo immediatamente per proteggere i tuoi fondi.", + "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", + "overwrite_amount": "Sovrascrivi quantità", + "pairingInvalidEvent": "Associazione evento non valido", + "password": "Password", + "paste": "Incolla", + "pause_wallet_creation": "La possibilità di creare Haven Wallet è attualmente sospesa.", + "payment_id": "ID Pagamento: ", + "payment_was_received": "Il tuo pagamento è stato ricevuto.", + "pending": " (non confermati)", + "percentageOf": "di ${amount}", + "pin_at_top": "fissa ${token} in alto", + "pin_is_incorrect": "Il PIN non è corretto", + "pin_number": "Numero PIN", + "placeholder_contacts": "I tuoi contatti saranno mostrati qui", + "placeholder_transactions": "Le tue transazioni saranno mostrate qui", + "please_fill_totp": "Inserisci il codice di 8 cifre presente sull'altro tuo dispositivo", + "please_make_selection": "Gentilmente seleziona se vuoi generare o recuperare il tuo portafoglio.", + "please_reference_document": "Si prega di fare riferimento ai documenti di seguito per ulteriori informazioni.", + "please_select": "Gentilmente seleziona:", + "please_select_backup_file": "Gentilmente seleziona il file di backup e inserisci la password di backup.", + "please_try_to_connect_to_another_node": "Gentilmente prova a connetterti ad un altro nodo", + "please_wait": "Attendere prego", + "polygonscan_history": "Cronologia PolygonScan", + "powered_by": "Sviluppato da ${title}", + "pre_seed_button_text": "Ho capito. Mostrami il seme", + "pre_seed_description": "Nella pagina seguente ti sarà mostrata una serie di parole ${words}. Questo è il tuo seme unico e privato ed è l'UNICO modo per recuperare il tuo portafoglio in caso di perdita o malfunzionamento. E' TUA responsabilità trascriverlo e conservarlo in un posto sicuro fuori dall'app Cake Wallet.", + "pre_seed_title": "IMPORTANTE", + "prevent_screenshots": "Impedisci screenshot e registrazione dello schermo", + "privacy": "Privacy", + "privacy_policy": "Informativa sulla privacy", + "privacy_settings": "Impostazioni privacy", + "private_key": "Chiave privata", + "proceed_after_one_minute": "Se lo schermo non procede dopo 1 minuto, controlla la tua email.", + "profile": "Profilo", + "provider_error": "${provider} errore", + "public_key": "Chiave pubblica", + "purchase_gift_card": "Acquista carta regalo", + "qr_fullscreen": "Tocca per aprire il codice QR a schermo intero", + "qr_payment_amount": "Questo codice QR contiene l'ammontare del pagamento. Vuoi sovrascrivere il varlore attuale?", + "question_to_disable_2fa": "Sei sicuro di voler disabilitare Cake 2FA? Non sarà più necessario un codice 2FA per accedere al portafoglio e ad alcune funzioni.", + "receivable_balance": "Bilanciamento creditizio", + "receive": "Ricevi", + "receive_amount": "Ammontare", + "received": "Ricevuto", + "recipient_address": "Indirizzo di destinazione", + "reconnect": "Riconnetti", + "reconnect_alert_text": "Sei sicuro di volerti riconnettere?", + "reconnection": "Riconnessione", + "redeemed": "Redento", + "refund_address": "Indirizzo di rimborso", + "reject": "Rifiutare", + "remaining": "rimanente", + "remove": "Remuovi", + "remove_node": "Rimuovi nodo", + "remove_node_message": "Sei sicuro di voler rimuovere il nodo selezionato?", + "rename": "Rinomina", + "require_for_adding_contacts": "Richiesto per l'aggiunta di contatti", + "require_for_all_security_and_backup_settings": "Richiedi per tutte le impostazioni di sicurezza e backup", + "require_for_assessing_wallet": "Richiesto per l'accesso al portafoglio", + "require_for_creating_new_wallets": "Richiesto per la creazione di nuovi portafogli", + "require_for_exchanges_to_external_wallets": "Richiede scambi con portafogli esterni", + "require_for_exchanges_to_internal_wallets": "Richiedi per gli scambi ai portafogli interni", + "require_for_sends_to_contacts": "Richiedi per gli invii ai contatti", + "require_for_sends_to_internal_wallets": "Richiesto per invii a portafogli interni", + "require_for_sends_to_non_contacts": "Richiesto per invii a non contatti", + "require_pin_after": "Richiedi PIN dopo", + "rescan": "Scansiona di nuovo", + "resend_code": "Per favore, invialo nuovamente", + "reset": "Ripristina", + "reset_password": "Reimposta password", + "restore_active_seed": "Seme attivo", + "restore_address": "Indirizzo", + "restore_bitcoin_description_from_keys": "Recupera il tuo portafoglio da una stringa WIF generata dalle tue chiavi private", + "restore_bitcoin_description_from_seed": "Recupera il tuo portafoglio da una combinazione di 12 parole", + "restore_bitcoin_title_from_keys": "Recupera da WIF", + "restore_description_from_backup": "Puoi recuperare l'app Cake Wallet per intero dal tuo file di backup", + "restore_description_from_keys": "Recupera il tuo portafoglio da una sequenza di caratteri generati dalle tue chiavi private", + "restore_description_from_seed": "Recupera il tuo portafoglio da una combinazione di 25 o 13 parole", + "restore_description_from_seed_keys": "Recupera il tuo portafoglio dal seme/chiavi che hai salvato in un posto sicuro", + "restore_from_date_or_blockheight": "Gentilmente inserisci la data di un paio di giorni prima che hai creato questo portafoglio. Oppure inserisci l'altezza del blocco se la conosci", + "restore_from_seed_placeholder": "Gentilmente inserisci o incolla il tuo seme qui", + "restore_new_seed": "Nuovo seme", + "restore_next": "Prossimo", + "restore_recover": "Recupera", + "restore_restore_wallet": "Recupera Portafoglio", + "restore_seed_keys_restore": "Recupera Seme/Chiavi", + "restore_spend_key_private": "Chiave di Spesa (privata)", + "restore_title_from_backup": "Recupera da backup", + "restore_title_from_keys": "Recupera dalle chiavi", + "restore_title_from_seed": "Recupera dal seme", + "restore_title_from_seed_keys": "Recupera dal seme/chiavi", + "restore_view_key_private": "Chiave di Visualizzazione (privata)", + "restore_wallet": "Recupera Portafoglio", + "restore_wallet_name": "Nome Portafoglio", + "restore_wallet_restore_description": "Descrizione recupero Portafoglio", + "router_no_route": "Nessun percorso definito per ${name}", + "save": "Salva", + "save_backup_password": "Gentilmente assicurati di aver salvato la password del tuo backup. Senza questa non sarai in grado di importare i tuoi file di backup.", + "save_backup_password_alert": "Salva password Backup", + "save_to_downloads": "Salva in Download", + "saved_the_trade_id": "Ho salvato l'ID dello scambio", + "scan_qr_code": "Scansiona il codice QR", + "scan_qr_code_to_get_address": "Scansiona il codice QR per ottenere l'indirizzo", + "scan_qr_on_device": "Scansiona questo codice QR su un altro dispositivo", + "search": "Ricerca", + "search_add_token": "Cerca / Aggiungi token", + "search_category": "Categoria di ricerca", + "search_currency": "Cerca valuta", + "search_language": "Cerca lingua", + "second_intro_content": "Il tuo Yat è un unico indirizzo emoji univoco che sostituisce i lunghi indirizzi per tutte le tue valute.", + "second_intro_title": "Un indirizzo emoji per domarli tutti", + "security_and_backup": "Sicurezza e backup", + "seed_alert_back": "Torna indietro", + "seed_alert_content": "Il seme è l'unico modo per recuperare il tuo portafoglio. L'hai trascritto?", + "seed_alert_title": "Attenzione", + "seed_alert_yes": "Sì, l'ho fatto", + "seed_choose": "Scegli la lingua del seme", "seed_hex_form": "Seme di portafoglio (forma esadecimale)", + "seed_key": "Chiave di semi", + "seed_language": "Linguaggio di semi", + "seed_language_chinese": "Cinese", + "seed_language_chinese_traditional": "Cinese tradizionale)", + "seed_language_czech": "ceco", + "seed_language_dutch": "Olandese", + "seed_language_english": "Inglese", + "seed_language_french": "Francese", + "seed_language_german": "Tedesco", + "seed_language_italian": "Italiano", + "seed_language_japanese": "Giapponese", + "seed_language_korean": "coreano", + "seed_language_next": "Prossimo", + "seed_language_portuguese": "Portoghese", + "seed_language_russian": "Russo", + "seed_language_spanish": "Spagnolo", + "seed_phrase_length": "Lunghezza della frase seed", + "seed_reminder": "Gentilmente trascrivi le parole. Ti tornerà utile in caso perdessi o ripristinassi il tuo telefono", + "seed_share": "Condividi seme", + "seed_title": "Seme", "seedtype": "Seedtype", "seedtype_legacy": "Legacy (25 parole)", "seedtype_polyseed": "Polyseed (16 parole)", - "seed_language_czech": "ceco", - "seed_language_korean": "coreano", - "seed_language_chinese_traditional": "Cinese tradizionale)", - "ascending": "Ascendente", - "descending": "Discendente", - "dfx_option_description": "Acquista criptovalute con EUR e CHF. Fino a 990€ senza KYC aggiuntivi. Per clienti al dettaglio e aziendali in Europa", - "polygonscan_history": "Cronologia PolygonScan", - "wallet_seed_legacy": "Seme di portafoglio legacy", - "default_sell_provider": "Fornitore di vendita predefinito", + "select_backup_file": "Seleziona file di backup", + "select_buy_provider_notice": "Seleziona un fornitore di acquisto sopra. È possibile saltare questa schermata impostando il provider di acquisto predefinito nelle impostazioni dell'app.", + "select_destination": "Seleziona la destinazione per il file di backup.", "select_sell_provider_notice": "Seleziona un fornitore di vendita sopra. Puoi saltare questa schermata impostando il tuo fornitore di vendita predefinito nelle impostazioni dell'app.", - "custom_drag": "Custom (Hold and Drag)", + "sell": "Vendere", + "sell_alert_content": "Al momento supportiamo solo la vendita di Bitcoin, Ethereum e Litecoin. Crea o passa al tuo portafoglio Bitcoin, Ethereum o Litecoin.", + "sell_monero_com_alert_content": "La vendita di Monero non è ancora supportata", + "send": "Invia", + "send_address": "${cryptoCurrency} indirizzo", + "send_amount": "Ammontare:", + "send_creating_transaction": "Creazione della transazione", + "send_error_currency": "L'ammontare può contenere solo numeri", + "send_error_minimum_value": "L'ammontare minimo è 0.01", + "send_estimated_fee": "Commissione stimata:", + "send_fee": "Commissione:", + "send_name": "Nome", + "send_new": "Nuovo", + "send_payment_id": "ID Pagamento (opzionale)", + "send_priority": "Attualmente la commissione è impostata a priorità ${transactionPriority} .\nLa priorità della transazione può essere modificata nelle impostazioni", + "send_sending": "Invio...", + "send_success": " ${crypto} inviati con successo", + "send_templates": "Modelli", + "send_title": "Invia", + "send_to_this_address": "Invia ${currency} ${tag}a questo indirizzo", + "send_xmr": "Invia XMR", + "send_your_wallet": "Il tuo portafoglio", + "sending": "Invio", + "sent": "Inviato", + "settings": "Impostazioni", + "settings_all": "TUTTO", + "settings_allow_biometrical_authentication": "Consenti autenticazione biometrica", + "settings_can_be_changed_later": "Queste impostazioni possono essere modificate in seguito nelle impostazioni dell'app", + "settings_change_language": "Cambia lingua", + "settings_change_pin": "Cambia PIN", + "settings_currency": "Moneta", + "settings_current_node": "Nodo attuale", + "settings_dark_mode": "Tema scuro", + "settings_display_balance": "Mostra saldo", + "settings_display_on_dashboard_list": "Mostra nella lista della pagina principale", + "settings_fee_priority": "Priorità commissione", + "settings_nodes": "Nodi", + "settings_none": "Nessuno", + "settings_only_trades": "Solo scambi", + "settings_only_transactions": "Solo transazioni", + "settings_personal": "Personali", + "settings_save_recipient_address": "Salva indirizzo di destinazione", + "settings_support": "Supporto", + "settings_terms_and_conditions": "Termini e condizioni", + "settings_title": "Impostazioni", + "settings_trades": "Scambi", + "settings_transactions": "Transazioni", + "settings_wallets": "Portafogli", + "setup_2fa": "Imposta la torta 2FA", + "setup_2fa_text": "Cake 2FA funziona utilizzando TOTP come secondo fattore di autenticazione.\n\nIl TOTP di Cake 2FA richiede il supporto SHA-512 e 8 cifre; ciò fornisce una maggiore sicurezza. Maggiori informazioni e app supportate sono disponibili nella guida.", + "setup_pin": "Imposta PIN", + "setup_successful": "Il tuo PIN è stato impostato con successo!", + "setup_totp_recommended": "Imposta TOTP", + "setup_warning_2fa_text": "Dovrai ripristinare il tuo portafoglio dal seme mnemonico.\n\nIl supporto di Cake non sarà in grado di assisterti se perdi l'accesso ai tuoi seed 2FA o mnemonici.\nCake 2FA è una seconda autenticazione per determinate azioni nel portafoglio. Prima di utilizzare Cake 2FA, ti consigliamo di leggere la guida.NON è sicuro come la conservazione a freddo.\n\nSe perdi l'accesso alla tua app 2FA o alle chiavi TOTP, perderai l'accesso a questo portafoglio. ", + "setup_your_debit_card": "Configura la tua carta di debito", + "share": "Condividere", + "share_address": "Condividi indirizzo", + "show_details": "Mostra dettagli", + "show_keys": "Mostra seme/chiavi", + "show_market_place": "Mostra mercato", + "show_seed": "Mostra seme", + "sign_up": "Registrati", + "signTransaction": "Firma la transazione", + "signup_for_card_accept_terms": "Registrati per la carta e accetta i termini.", + "slidable": "Scorrevole", + "sort_by": "Ordina per", + "spend_key_private": "Chiave di spesa (privata)", + "spend_key_public": "Chiave di spesa (pubblica)", + "status": "Stato: ", + "subaddress_title": "Lista sottoindirizzi", + "subaddresses": "Sottoindirizzi", + "submit_request": "invia una richiesta", + "successful": "Riuscito", + "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_live_chat": "Supporto dal vivo", + "support_title_other_links": "Altri collegamenti di supporto", + "sweeping_wallet": "Portafoglio ampio", + "sweeping_wallet_alert": "Questo non dovrebbe richiedere molto tempo. NON LASCIARE QUESTA SCHERMATA O I FONDI SPAZZATI POTREBBERO ANDARE PERSI", + "switchToETHWallet": "Passa a un portafoglio Ethereum e riprova", "switchToEVMCompatibleWallet": "Passa a un portafoglio compatibile con EVM e riprova (Ethereum, Polygon)", - "receivable_balance": "Bilanciamento creditizio", - "confirmed_tx": "Confermato", + "symbol": "Simbolo", + "sync_all_wallets": "Sincronizza tutti i portafogli", + "sync_status_attempting_sync": "TENTATIVO DI SINCRONIZZAZIONE", + "sync_status_connected": "CONNESSO", + "sync_status_connecting": "CONNESSIONE", + "sync_status_failed_connect": "DISCONNESSO", + "sync_status_not_connected": "NON CONNESSO", + "sync_status_starting_sync": "INIZIO SINC", + "sync_status_syncronized": "SINCRONIZZATO", + "sync_status_syncronizing": "SINCRONIZZAZIONE", + "syncing_wallet_alert_content": "Il saldo e l'elenco delle transazioni potrebbero non essere completi fino a quando non viene visualizzato \"SYNCHRONIZED\" in alto. Clicca/tocca per saperne di più.", + "syncing_wallet_alert_title": "Il tuo portafoglio si sta sincronizzando", + "template": "Modello", + "template_name": "Nome modello", + "third_intro_content": "Yat può funzionare anche fuori da Cake Wallet. Qualsiasi indirizzo di portafoglio sulla terra può essere sostituito con uno Yat!", + "third_intro_title": "Yat gioca bene con gli altri", + "time": "${minutes}m ${seconds}s", + "tip": "Suggerimento:", + "today": "Oggi", + "token_contract_address": "Indirizzo del contratto token", + "token_decimal": "Decimale del token", + "token_name": "Nome del token, ad esempio: Tether", + "token_symbol": "Simbolo del token, ad esempio: USDT", + "tokenID": "ID", + "tor_connection": "Connessione Tor", + "tor_only": "Solo Tor", + "total_saving": "Risparmio totale", + "totp_2fa_failure": "Codice non corretto. Prova un codice diverso o genera una nuova chiave segreta. Utilizza un'app 2FA compatibile che supporti codici a 8 cifre e SHA512.", + "totp_2fa_success": "Successo! Cake 2FA abilitato per questo portafoglio. Ricordati di salvare il tuo seme mnemonico nel caso in cui perdi l'accesso al portafoglio.", + "totp_auth_url": "URL DI AUT. TOTP", + "totp_code": "Codice TOTP", + "totp_secret_code": "TOTP codice segreto", + "totp_verification_success": "Verifica riuscita!", + "trade_details_copied": "${title} copiati negli Appunti", + "trade_details_created_at": "Creato alle", + "trade_details_fetching": "Recupero", + "trade_details_id": "ID", + "trade_details_pair": "Coppia", + "trade_details_provider": "Fornitore", + "trade_details_state": "Stato", + "trade_details_title": "Dettagli Scambio", + "trade_for_not_created": "Lo scambio per ${title} non è stato creato.", + "trade_history_title": "Storico scambi", + "trade_id": "ID Scambio:", + "trade_id_not_found": "Scambio ${tradeId} di ${title} not trovato.", + "trade_is_powered_by": "Questo scambio è fornito da ${provider}", + "trade_not_created": "Scambio non creato", + "trade_not_found": "Scambio non trovato.", + "trade_state_btc_sent": "Btc inviati", + "trade_state_complete": "Completato", + "trade_state_confirming": "Conferma", + "trade_state_created": "Creato", + "trade_state_finished": "Finito", + "trade_state_paid": "Pagato", + "trade_state_paid_unconfirmed": "Pagato non confermato", + "trade_state_pending": "In corso", + "trade_state_timeout": "Timeout", + "trade_state_to_be_created": "Da creare", + "trade_state_traded": "Scambiato", + "trade_state_trading": "Scambio", + "trade_state_underpaid": "Sottopagato", + "trade_state_unpaid": "Non pagato", + "trades": "Scambi", + "transaction_details_amount": "Ammontare", + "transaction_details_copied": "${title} copiati negli Appunti", + "transaction_details_date": "Data", + "transaction_details_fee": "Commissione", + "transaction_details_height": "Altezza", + "transaction_details_recipient_address": "Indirizzi dei destinatari", "transaction_details_source_address": "Indirizzo di partenza", - "pause_wallet_creation": "La possibilità di creare Haven Wallet è attualmente sospesa.", - "contractName": "Nome del contratto", - "contractSymbol": "Simbolo del contratto", - "description": "Descrizione", - "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.", - "no_relays": "Nessun relè", - "choose_relay": "Scegli un relè da utilizzare", - "no_relays_message": "Abbiamo trovato un record Nostr NIP-05 per questo utente, ma non contiene alcun relè. Si prega di indicare al destinatario di aggiungere inoltri al proprio record Nostr.", - "no_relay_on_domain": "Non esiste un inoltro per il dominio dell'utente oppure l'inoltro non è disponibile. Scegli un relè da utilizzare." -} + "transaction_details_title": "Dettagli Transazione", + "transaction_details_transaction_id": "ID Transazione", + "transaction_key": "Chiave Transazione", + "transaction_priority_fast": "Alta", + "transaction_priority_fastest": "Massima", + "transaction_priority_medium": "Media", + "transaction_priority_regular": "Regolare", + "transaction_priority_slow": "Bassa", + "transaction_sent": "Transazione inviata!", + "transaction_sent_notice": "Se lo schermo non procede dopo 1 minuto, controlla un block explorer e la tua email.", + "transactions": "Transazioni", + "transactions_by_date": "Transazioni per data", + "trusted": "di fiducia", + "unavailable_balance": "Saldo non disponibile", + "unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.", + "unconfirmed": "Saldo non confermato", + "understand": "Capisco", + "unmatched_currencies": "La valuta del tuo portafoglio attuale non corrisponde a quella del QR scansionato", + "unspent_change": "Modifica", + "unspent_coins_details_title": "Dettagli sulle monete non spese", + "unspent_coins_title": "Monete non spese", + "unsupported_asset": "Non supportiamo questa azione per questa risorsa. Crea o passa a un portafoglio di un tipo di asset supportato.", + "upto": "fino a ${value}", + "use": "Passa a ", + "use_card_info_three": "Utilizza la carta digitale online o con metodi di pagamento contactless.", + "use_card_info_two": "I fondi vengono convertiti in USD quando sono detenuti nel conto prepagato, non in valute digitali.", + "use_ssl": "Usa SSL", + "use_suggested": "Usa suggerito", + "variable_pair_not_supported": "Questa coppia di variabili non è supportata con gli scambi selezionati", + "verification": "Verifica", + "verify_with_2fa": "Verifica con Cake 2FA", + "version": "Versione ${currentVersion}", + "view_all": "Visualizza tutto", + "view_in_block_explorer": "View in Block Explorer", + "view_key_private": "Chiave di visualizzazione (privata)", + "view_key_public": "Chiave di visualizzazione (pubblica)", + "view_transaction_on": "View Transaction on ", + "waiting_payment_confirmation": "In attesa di conferma del pagamento", + "wallet_keys": "Seme Portafoglio /chiavi", + "wallet_list_create_new_wallet": "Crea Nuovo Portafoglio", + "wallet_list_edit_wallet": "Modifica portafoglio", + "wallet_list_failed_to_load": "Caricamento portafoglio ${wallet_name} fallito. ${error}", + "wallet_list_failed_to_remove": "Rimozione portafoglio ${wallet_name} fallita. ${error}", + "wallet_list_load_wallet": "Caricamento Portafoglio", + "wallet_list_loading_wallet": "Caricamento portafoglio ${wallet_name}", + "wallet_list_removing_wallet": "Rimozione portafoglio ${wallet_name}", + "wallet_list_restore_wallet": "Recupera Portafoglio", + "wallet_list_title": "Portafoglio Monero", + "wallet_list_wallet_name": "Nome del portafoglio", + "wallet_menu": "Menù", + "wallet_name": "Nome del Portafoglio", + "wallet_name_exists": "Il portafoglio con quel nome è già esistito", + "wallet_restoration_store_incorrect_seed_length": "Lunghezza seme non corretta", + "wallet_seed": "Seme Portafoglio", + "wallet_seed_legacy": "Seme di portafoglio legacy", + "wallet_store_monero_wallet": "Portafoglio Monero", + "walletConnect": "PortafoglioConnetti", + "wallets": "Portafogli", + "warning": "Avvertimento", + "welcome": "Benvenuto", + "welcome_to_cakepay": "Benvenuto in Cake Pay!", + "widgets_address": "Indirizzo", + "widgets_or": "o", + "widgets_restore_from_blockheight": "Recupera da altezza blocco", + "widgets_restore_from_date": "Recupera da data", + "widgets_seed": "Seme", + "wouoldLikeToConnect": "vorrei connettermi", + "write_down_backup_password": "Gentilmente trascrivi la password del backup, che è usata per importare i tuoi file di backup.", + "xlm_extra_info": "Gentilmente ricorda di indicare il Memo ID quando invii la transazione XLM per lo scambio", + "xmr_available_balance": "Saldo Disponibile", + "xmr_full_balance": "Saldo Totale", + "xmr_hidden": "Nascosto", + "xmr_to_error": "XMR.TO errore", + "xmr_to_error_description": "Ammontare invalido. Il limite massimo è 8 cifre dopo il punto decimale", + "xrp_extra_info": "Gentilmente ricorda di indicare il Tag di Destinazione quando invii una transazione XRP per lo scambio", + "yat": "Yat", + "yat_address": "Indirizzo Yat", + "yat_alert_content": "Gli utenti di Cake Wallet possono ora inviare e ricevere tutte le loro valute preferite con un nome utente unico basato su emoji.", + "yat_alert_title": "Invia e ricevi criptovalute più facilmente con Yat", + "yat_error": "Yat errore", + "yat_error_content": "Nessun indirizzo collegato a questo Yat. Prova un altro Yat", + "yat_popup_content": "Ora puoi inviare e ricevere criptovalute in Cake Wallet con il tuo Yat, un breve nome utente basato su emoji. Gestisci Yats in qualsiasi momento nella schermata delle impostazioni", + "yat_popup_title": "L'indirizzo del tuo portafoglio può essere emoji.", + "yesterday": "Ieri", + "you_now_have_debit_card": "Ora hai una carta di debito", + "you_pay": "Tu paghi", + "you_will_get": "Converti a", + "you_will_send": "Conveti da", + "yy": "YY", + "zzzz": "Zzzz" +} \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index df317392f..710a78088 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -1,779 +1,780 @@ { - "welcome": "ようこそ に", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Monero、Bitcoin、Ethereum、Litecoin、Haven用の素晴らしいウォレット", - "please_make_selection": "以下を選択してください ウォレットを作成または回復する.", - "create_new": "新しいウォレットを作成", - "restore_wallet": "ウォレットを復元", - "monero_com": "Monero.com by Cake Wallet", - "monero_com_wallet_text": "Awesome wallet for Monero", - "haven_app": "Haven by Cake Wallet", - "haven_app_wallet_text": "Awesome wallet for Haven", - "accounts": "アカウント", - "edit": "編集", + "about_cake_pay": "Cake Payを使用すると、仮想資産を含むギフトカードを簡単に購入でき、米国内の150,000を超える加盟店ですぐに利用できます。", "account": "アカウント", + "accounts": "アカウント", + "accounts_subaddresses": "アカウントとサブアドレス", + "activate": "アクティブ化", + "active": "アクティブ", + "active_cards": "アクティブカード", + "activeConnectionsPrompt": "アクティブな接続がここに表示されます", "add": "加える", + "add_contact": "連絡先を追加", + "add_custom_node": "新しいカスタム ノードを追加", + "add_custom_redemption": "カスタム引き換えを追加", + "add_fund_to_card": "プリペイド資金をカードに追加します(最大 ${value})", + "add_new_node": "新しいノードを追加", + "add_new_word": "新しい単語を追加", + "add_receiver": "別のレシーバーを追加します(オプション)", + "add_secret_code": "または、このシークレット コードを認証アプリに追加します", + "add_tip": "ヒントを追加", + "add_token_disclaimer_check": "信頼できる情報源を使用して、トークン コントラクトのアドレスと情報を確認しました。 悪意のある情報や不正確な情報を追加すると、資金が失われる可能性があります。", + "add_token_warning": "詐欺師の指示に従ってトークンを編集または追加しないでください。\nトークン アドレスは常に信頼できる情報源で確認してください。", + "add_value": "付加価値", + "address": "住所", "address_book": "住所録", - "contact": "接触", - "please_select": "選んでください:", - "cancel": "キャンセル", - "ok": "OK", - "contact_name": "連絡先", - "reset": "リセットする", - "save": "セーブ", + "address_book_menu": "住所録", + "address_detected": "アドレスが検出されました", + "address_from_domain": "このアドレスは ${domain} からのものです Unstoppable Domains", + "address_from_yat": "このアドレスは ${emoji} からのものです Yat", + "address_label": "Address label", "address_remove_contact": "連絡先を削除します", "address_remove_content": "選択した連絡先を削除してもよろしいですか?", - "authenticated": "認証済み", - "authentication": "認証", - "failed_authentication": "認証失敗. ${state_error}", - "wallet_menu": "ウォレットメニュー", - "Blocks_remaining": "${status} 残りのブロック", - "please_try_to_connect_to_another_node": "別のノードに接続してみてください", - "xmr_hidden": "非表示", - "xmr_available_balance": "利用可能残高", - "xmr_full_balance": "フルバランス", - "send": "送る", - "receive": "受け取る", - "transactions": "取引", - "incoming": "着信", - "outgoing": "発信", - "transactions_by_date": "日付ごとの取引", - "trades": "取引", - "filter_by": "でフィルタリング", - "today": "今日", - "yesterday": "昨日", - "received": "受け取った", - "sent": "送信済み", - "pending": " (保留中)", - "rescan": "再スキャン", - "reconnect": "再接続", - "wallets": "財布", - "show_seed": "シードを表示", - "show_keys": "シード/キーを表示する", - "address_book_menu": "住所録", - "reconnection": "再接続", - "reconnect_alert_text": "再接続しますか?", - "exchange": "交換する", - "clear": "クリア", - "refund_address": "払い戻し住所", - "change_exchange_provider": "Exchangeプロバイダーの変更", - "you_will_send": "から変換", - "you_will_get": "に変換", - "amount_is_guaranteed": "受け取り金額は保証されています", - "amount_is_estimate": "受け取り金額は見積もりです", - "powered_by": "搭載 ${title}", - "error": "エラー", - "estimated": "推定", - "min_value": "分: ${value} ${currency}", - "max_value": "マックス: ${value} ${currency}", - "change_currency": "通貨を変更する", - "overwrite_amount": "Overwrite amount", - "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", - "copy_id": "IDをコピー", - "exchange_result_write_down_trade_id": "続行するには、取引IDをコピーまたは書き留めてください.", - "trade_id": "取引ID:", - "copied_to_clipboard": "クリップボードにコピーしました", - "saved_the_trade_id": "取引IDを保存しました", - "fetching": "フェッチング", - "id": "ID: ", - "amount": "量: ", - "payment_id": "支払いID: ", - "status": "状態: ", - "offer_expires_in": "で有効期限が切れます: ", - "trade_is_powered_by": "この取引は ${provider}", - "copy_address": "住所をコピー", - "exchange_result_confirm": "確認を押すと、送信されます ${fetchingLabel} ${from} と呼ばれるあなたの財布から ${walletName} 下記の住所へ。 または、外部ウォレットから以下のアドレスに送信することもできます/ QRコードに送信できます.\n\n確認を押して続行するか、戻って金額を変更してください.", - "exchange_result_description": "次のページに示されているアドレスに最低 ${fetchingLabel} ${from} を送信する必要があります。 ${fetchingLabel} ${from} 未満の金額を送信すると、変換されず、返金されない場合があります。", - "exchange_result_write_down_ID": "*上記のIDをコピーまたは書き留めてください.", - "confirm": "確認する", - "confirm_sending": "送信を確認", - "commit_transaction_amount_fee": "トランザクションをコミット\n量: ${amount}\n費用: ${fee}", - "sending": "送信", - "transaction_sent": "トランザクションが送信されました!", - "expired": "期限切れ", - "time": "${minutes}m ${seconds}s", - "send_xmr": "送る XMR", - "exchange_new_template": "新しいテンプレート", - "faq": "FAQ", - "enter_your_pin": "PINを入力してください", - "loading_your_wallet": "ウォレットをロードしています", - "new_wallet": "新しいウォレット", - "wallet_name": "ウォレット名", - "continue_text": "持続する", - "choose_wallet_currency": "ウォレット通貨を選択してください:", - "node_new": "新しいノード", - "node_address": "ノードアドレス", - "node_port": "ノードポート", - "login": "ログイン", - "password": "パスワード", - "nodes": "ノード", - "node_reset_settings_title": "設定をリセット", - "nodes_list_reset_to_default_message": "設定をデフォルトにリセットしてもよろしいですか?", - "change_current_node": "現在のノードを変更してよろしいですか ${node}?", - "change": "変化する", - "remove_node": "ノードを削除", - "remove_node_message": "選択したノードを削除してもよろしいですか?", - "remove": "削除する", - "delete": "削除する", - "add_new_node": "新しいノードを追加", - "change_current_node_title": "現在のノードを変更する", - "node_test": "テスト", - "node_connection_successful": "接続に成功しました", - "node_connection_failed": "接続に失敗しました", - "new_node_testing": "新しいノードのテスト", - "use": "使用する ", - "digit_pin": "桁ピン", - "share_address": "住所を共有する", - "receive_amount": "量", - "subaddresses": "サブアドレス", "addresses": "住所", - "scan_qr_code_to_get_address": "QRコードをスキャンして住所を取得します", - "qr_fullscreen": "タップして全画面QRコードを開く", - "rename": "リネーム", - "choose_account": "アカウントを選択", - "create_new_account": "新しいアカウントを作成する", - "accounts_subaddresses": "アカウントとサブアドレス", - "restore_restore_wallet": "ウォレットを復元", - "restore_title_from_seed_keys": "シード/キーから復元", - "restore_description_from_seed_keys": "安全な場所に保存したシード/キーから財布を取り戻す", - "restore_next": "次", - "restore_title_from_backup": "バックアップファイルから復元する", - "restore_description_from_backup": "Cake Walletアプリ全体を復元できますバックアップファイル", - "restore_seed_keys_restore": "シード/キーの復元", - "restore_title_from_seed": "シードから復元", - "restore_description_from_seed": "25ワードからウォレットを復元しますまたは13ワードの組み合わせコード", - "restore_title_from_keys": "キーから復元する", - "restore_description_from_keys": "生成されたウォレットを復元します秘密鍵から保存されたキーストローク", - "restore_wallet_name": "ウォレット名", - "restore_address": "住所", - "restore_view_key_private": "ビューキー (プライベート)", - "restore_spend_key_private": "キーを使う (プライベート)", - "restore_recover": "回復します", - "restore_wallet_restore_description": "ウォレットの復元", - "restore_new_seed": "新しい種", - "restore_active_seed": "アクティブシード", - "restore_bitcoin_description_from_seed": "24ワードの組み合わせコードからウォレットを復元する", - "restore_bitcoin_description_from_keys": "秘密鍵から生成されたWIF文字列からウォレットを復元します", - "restore_bitcoin_title_from_keys": "WIFから復元", - "restore_from_date_or_blockheight": "このウォレットを作成する数日前に日付を入力してください。 または、ブロックの高さがわかっている場合は、代わりに入力してください", - "seed_reminder": "スマートフォンを紛失したりワイプした場合に備えて、これらを書き留めてください", - "seed_title": "シード", - "seed_share": "シードを共有する", - "copy": "コピー", - "seed_language": "シード言語", - "seed_choose": "シード言語を選択してください", - "seed_language_next": "次", - "seed_language_english": "英語", - "seed_language_chinese": "中国語", - "seed_language_dutch": "オランダの", - "seed_language_german": "ドイツ人", - "seed_language_japanese": "日本語", - "seed_language_portuguese": "ポルトガル語", - "seed_language_russian": "ロシア", - "seed_language_spanish": "スペイン語", - "seed_language_french": "フランス語", - "seed_language_italian": "イタリア語", - "send_title": "を送信", - "send_your_wallet": "あなたの財布", - "send_address": "${cryptoCurrency} 住所", - "send_payment_id": "支払いID (オプショナル)", + "advanced_settings": "高度な設定", + "aggressive": "熱心すぎる", + "agree": "同意する", + "agree_and_continue": "同意して続行", + "agree_to": "アカウントを作成することにより、", "all": "すべて", - "send_error_minimum_value": "金額の最小値は0.01です", - "send_error_currency": "通貨には数字のみを含めることができます", - "send_estimated_fee": "見積手数料:", - "send_priority": "現在、料金は ${transactionPriority} 優先度.\nトランザクションの優先度は設定で調整できます", - "send_creating_transaction": "トランザクションを作成する", - "send_templates": "テンプレート", - "send_new": "新着", - "send_amount": "量:", - "send_fee": "費用:", - "send_name": "名前", - "got_it": "とった", - "send_sending": "送信...", - "send_success": "${crypto}が送信されました", - "settings_title": "設定", - "settings_nodes": "ノード", - "settings_current_node": "現在のノード", - "settings_wallets": "財布", - "settings_display_balance": "ディスプレイバランス", - "settings_currency": "通貨", - "settings_fee_priority": "料金優先", - "settings_save_recipient_address": "受信者のアドレスを保存", - "settings_personal": "パーソナル", - "settings_change_pin": "PINを変更", - "settings_change_language": "言語を変えてください", - "settings_allow_biometrical_authentication": "生体認証を許可する", - "settings_dark_mode": "ダークモード", - "settings_transactions": "取引", - "settings_trades": "取引", - "settings_display_on_dashboard_list": "ダッシュボードリストに表示", - "settings_all": "すべて", - "settings_only_trades": "取引のみ", - "settings_only_transactions": "トランザクションのみ", - "settings_none": "なし", - "settings_support": "サポート", - "settings_terms_and_conditions": "規約と条件", - "pin_is_incorrect": "PINが間違っています", - "setup_pin": "PINのセットアップ", - "enter_your_pin_again": "ピンをもう一度入力してください", - "setup_successful": "PINは正常に設定されました!", - "wallet_keys": "ウォレットシード/キー", - "wallet_seed": "ウォレットシード", - "private_key": "秘密鍵", - "public_key": "公開鍵", - "view_key_private": "ビューキー (プライベート)", - "view_key_public": "ビューキー (パブリック)", - "spend_key_private": "キーを使う (プライベート)", - "spend_key_public": "キーを使う (パブリック)", - "copied_key_to_clipboard": "コピー済み ${key} クリップボードへ", - "new_subaddress_title": "新しいアドレス", - "new_subaddress_label_name": "ラベル名", - "new_subaddress_create": "作成する", - "address_label": "Address label", - "subaddress_title": "サブアドレス一覧", - "trade_details_title": "取引の詳細", - "trade_details_id": "ID", - "trade_details_state": "状態", - "trade_details_fetching": "フェッチング", - "trade_details_provider": "プロバイダー", - "trade_details_created_at": "で作成", - "trade_details_pair": "ペア", - "trade_details_copied": "${title} クリップボードにコピーしました", - "trade_history_title": "取引履歴", - "transaction_details_title": "取引の詳細", - "transaction_details_transaction_id": "トランザクションID", - "transaction_details_date": "日付", - "transaction_details_height": "高さ", - "transaction_details_amount": "量", - "transaction_details_fee": "費用", - "transaction_details_copied": "${title} クリップボードにコピーしました", - "transaction_details_recipient_address": "受信者のアドレス", - "wallet_list_title": "Monero 財布", - "wallet_list_create_new_wallet": "新しいウォレットを作成", - "wallet_list_edit_wallet": "ウォレットを編集する", - "wallet_list_wallet_name": "ウォレット名", - "wallet_list_restore_wallet": "ウォレットを復元", - "wallet_list_load_wallet": "ウォレットをロード", - "wallet_list_loading_wallet": "読み込み中 ${wallet_name} 財布", - "wallet_list_failed_to_load": "読み込みに失敗しました ${wallet_name} 財布. ${error}", - "wallet_list_removing_wallet": "取りはずし ${wallet_name} 財布", - "wallet_list_failed_to_remove": "削除できませんでした ${wallet_name} 財布. ${error}", - "widgets_address": "住所", - "widgets_restore_from_blockheight": "ブロックの高さから復元", - "widgets_restore_from_date": "日付から復元", - "widgets_or": "または", - "widgets_seed": "シード", - "router_no_route": "ルートが定義されていません ${name}", - "error_text_account_name": "アカウント名には文字のみを含めることができます \n1〜15文字である必要があります", - "error_text_contact_name": "連絡先名に含めることはできません ` , ' \" シンボル\n長さは1〜32文字でなければなりません", - "error_text_address": "ウォレットアドレスは、\n暗号通貨", - "error_text_node_address": "iPv4アドレスを入力してください", - "error_text_node_port": "ノードポートには、0〜65535の数字のみを含めることができます", - "error_text_node_proxy_address": ":<ポート> を入力してください (例: 127.0.0.1:9050)", - "error_text_payment_id": "支払いIDには、16進数で16〜64文字しか含めることができません", - "error_text_xmr": "XMR値は利用可能な残高を超えることはできません.\n小数桁数は12以下でなければなりません", - "error_text_fiat": "金額は利用可能な残高を超えることはできません.\n小数桁の数は2以下でなければなりません", - "error_text_subaddress_name": "サブアドレス名に含めることはできません` , ' \" シンボル\n1〜20文字の長さである必要があります", - "error_text_amount": "金額には数字のみを含めることができます", - "error_text_wallet_name": "ウォレット名には、文字、数字、_-記号のみを含めることができます\n長さは1〜33文字である必要があります", - "error_text_keys": "ウォレットキーには、16進数で64文字しか含めることができません", - "error_text_crypto_currency": "小数桁数\n12以下でなければなりません", - "error_text_minimal_limit": "${provider} の取引は作成されません。 金額は最小額より少ない: ${min} ${currency}", - "error_text_maximum_limit": "${provider} の取引は作成されません。 金額は最大値を超えています: ${max} ${currency}", - "error_text_limits_loading_failed": "${provider} の取引は作成されません。 制限の読み込みに失敗しました", - "error_text_template": "テンプレートの名前とアドレスに含めることはできません ` , ' \" シンボル\n1〜106文字の長さである必要があります", + "all_trades": "すべての取引", + "all_transactions": "全取引", + "alphabetical": "アルファベット順", + "already_have_account": "すでにアカウントをお持ちですか?", + "always": "いつも", + "amount": "量: ", + "amount_is_estimate": "受け取り金額は見積もりです", + "amount_is_guaranteed": "受け取り金額は保証されています", + "and": "と", + "anonpay_description": "${type} を生成します。受取人はサポートされている任意の暗号通貨で ${method} でき、あなたはこのウォレットで資金を受け取ります。", + "apk_update": "APKアップデート", + "approve": "承認する", + "arrive_in_this_address": "${currency} ${tag}はこの住所に到着します", + "ascending": "上昇", + "ask_each_time": "毎回尋ねてください", "auth_store_ban_timeout": "禁止タイムアウト", "auth_store_banned_for": "禁止されています ", "auth_store_banned_minutes": " 数分", "auth_store_incorrect_password": "間違ったPIN", - "wallet_store_monero_wallet": "Monero 財布", - "wallet_restoration_store_incorrect_seed_length": "誤ったシード長s", - "full_balance": "フルバランス", - "available_balance": "利用可能残高", - "hidden_balance": "隠れたバランス", - "sync_status_syncronizing": "同期", - "sync_status_syncronized": "同期された", - "sync_status_not_connected": "接続されていません", - "sync_status_starting_sync": "同期の開始", - "sync_status_failed_connect": "切断されました", - "sync_status_connecting": "接続中", - "sync_status_connected": "接続済み", - "sync_status_attempting_sync": "同期を試みています", - "transaction_priority_slow": "スロー", - "transaction_priority_regular": "レギュラー", - "transaction_priority_medium": "中", - "transaction_priority_fast": "速い", - "transaction_priority_fastest": "最速", - "trade_for_not_created": "取引 ${title} 作成されません", - "trade_not_created": "作成されていない取引", - "trade_id_not_found": "トレード ${tradeId} of ${title} 見つかりません", - "trade_not_found": "取引が見つかりません", - "trade_state_pending": "保留中", - "trade_state_confirming": "確認中", - "trade_state_trading": "トレーディング", - "trade_state_traded": "取引済み", - "trade_state_complete": "コンプリート", - "trade_state_to_be_created": "作成される", - "trade_state_unpaid": "未払い", - "trade_state_underpaid": "支払不足", - "trade_state_paid_unconfirmed": "未確認の支払い", - "trade_state_paid": "有料", - "trade_state_btc_sent": "送った", - "trade_state_timeout": "タイムアウト", - "trade_state_created": "作成した", - "trade_state_finished": "完成した", - "change_language": "言語を変えてください", - "change_language_to": "言語を変更 ${language}?", - "paste": "ペースト", - "restore_from_seed_placeholder": "ここにコードフレーズを入力または貼り付けてください", - "add_new_word": "新しい単語を追加", - "incorrect_seed": "入力されたテキストは無効です。", - "biometric_auth_reason": "प指紋をスキャンして認証する", - "version": "バージョン ${currentVersion}", - "extracted_address_content": "に送金します\n${recipient_name}", - "card_address": "住所:", - "buy": "購入", - "sell": "売る", - "placeholder_transactions": "あなたの取引はここに表示されます", - "placeholder_contacts": "連絡先はここに表示されます", - "template": "テンプレート", - "confirm_delete_template": "この操作により、このテンプレートが削除されます。 続行しますか?", - "confirm_delete_wallet": "このアクションにより、このウォレットが削除されます。 続行しますか?", - "change_wallet_alert_title": "現在のウォレットを変更する", - "change_wallet_alert_content": "現在のウォレットをに変更しますか ${wallet_name}?", - "creating_new_wallet": "新しいウォレットの作成", - "creating_new_wallet_error": "エラー: ${description}", - "seed_alert_title": "注意", - "seed_alert_content": "種子はあなたの財布を回復する唯一の方法です。 書き留めましたか?", - "seed_alert_back": "戻る", - "seed_alert_yes": "はい、あります", - "exchange_sync_alert_content": "ウォレットが同期されるまでお待ちください", - "pre_seed_title": "重要", - "pre_seed_description": "次のページでは、一連の${words}語が表示されます。 これはあなたのユニークでプライベートなシードであり、紛失や誤動作が発生した場合にウォレットを回復する唯一の方法です。 それを書き留めて、Cake Wallet アプリの外の安全な場所に保管するのはあなたの責任です。", - "pre_seed_button_text": "わかります。 種を見せて", - "xmr_to_error": "XMR.TOエラー", - "xmr_to_error_description": "金額が無効です。 小数点以下8桁の上限", - "provider_error": "${provider} エラー", - "use_ssl": "SSLを使用する", - "trusted": "信頼できる", - "color_theme": "カラーテーマ", - "light_theme": "光", - "bright_theme": "明るい", - "dark_theme": "闇", - "enter_your_note": "メモを入力してください…", - "note_optional": "注(オプション)", - "note_tap_to_change": "注(タップして変更)", - "view_in_block_explorer": "View in Block Explorer", - "view_transaction_on": "View Transaction on ", - "transaction_key": "トランザクションキー", - "confirmations": "確認", - "recipient_address": "受信者のアドレス", - "extra_id": "追加ID:", - "destination_tag": "宛先タグ:", - "memo": "メモ:", - "backup": "バックアップ", - "change_password": "パスワードを変更する", - "backup_password": "バックアップパスワード", - "write_down_backup_password": "バックアップファイルのインポートに使用されるバックアップパスワードを書き留めてください。", - "export_backup": "バックアップのエクスポート", - "save_backup_password": "バックアップパスワードが保存されていることを確認してください。 それなしではバックアップファイルをインポートすることはできません。", - "backup_file": "バックアップファイル", - "edit_backup_password": "バックアップパスワードの編集", - "save_backup_password_alert": "バックアップパスワードを保存する", - "change_backup_password_alert": "以前のバックアップファイルは、新しいバックアップパスワードでインポートできなくなります。 新しいバックアップパスワードは、新しいバックアップファイルにのみ使用されます。 バックアップパスワードを変更してもよろしいですか?", - "enter_backup_password": "ここにバックアップパスワードを入力してください", - "select_backup_file": "バックアップファイルを選択", - "import": "輸入", - "please_select_backup_file": "バックアップファイルを選択し、バックアップパスワードを入力してください。", - "fixed_rate": "固定金利", - "fixed_rate_alert": "固定金利モードにチェックを入れると、受取額を入力できるようになります。 固定金利モードに切り替えますか?", - "xlm_extra_info": "交換用のXLMトランザクションを送信するときに、メモIDを指定することを忘れないでください", - "xrp_extra_info": "取引所のXRPトランザクションを送信するときに、宛先タグを指定することを忘れないでください", - "exchange_incorrect_current_wallet_for_xmr": "Cake Wallet Moneroの残高からXMRを交換する場合は、最初にMoneroウォレットに切り替えてください。", - "confirmed": "確認済み残高", - "unconfirmed": "残高未確認", - "displayable": "表示可能", - "submit_request": "リクエストを送信する", - "buy_alert_content": "現在、ビットコイン、イーサリアム、ライトコイン、モネロの購入のみをサポートしています。ビットコイン、イーサリアム、ライトコイン、またはモネロのウォレットを作成するか、これらのウォレットに切り替えてください。", - "sell_alert_content": "現在、ビットコイン、イーサリアム、ライトコインの販売のみをサポートしています。ビットコイン、イーサリアム、またはライトコインのウォレットを作成するか、これらのウォレットに切り替えてください。", - "outdated_electrum_wallet_description": "Cakeで作成された新しいビットコインウォレットには、24ワードのシードがあります。 新しいビットコインウォレットを作成し、すべての資金を新しい24ワードのウォレットに転送し、12ワードのシードを持つウォレットの使用を停止することが必須です。 あなたの資金を確保するためにこれをすぐに行ってください。", - "understand": "わかります", - "apk_update": "APKアップデート", - "buy_bitcoin": "ビットコインを購入する", - "buy_with": "で購入", - "moonpay_alert_text": "金額の値は以上でなければなりません ${minAmount} ${fiatCurrency}", - "outdated_electrum_wallet_receive_warning": "このウォレットに 12 ワードのシードがあり、Cake で作成された場合、このウォレットにビットコインを入金しないでください。 このウォレットに転送された BTC は失われる可能性があります。 新しい 24 ワードのウォレットを作成し (右上のメニューをタップし、[ウォレット]、[新しいウォレットの作成]、[ビットコイン] の順に選択)、すぐに BTC をそこに移動します。 Cake の新しい (24 ワード) BTC ウォレットは安全です", - "do_not_show_me": "また僕にこれを見せないでください", - "unspent_coins_title": "未使用のコイン", - "unspent_coins_details_title": "未使用のコインの詳細", - "freeze": "氷結", - "frozen": "凍った", - "coin_control": "コインコントロール(オプション)", - "address_detected": "アドレスが検出されました", - "address_from_domain": "このアドレスは ${domain} からのものです Unstoppable Domains", - "add_receiver": "別のレシーバーを追加します(オプション)", - "manage_yats": "Yatsを管理する", - "yat_alert_title": "Yatで暗号をより簡単に送受信できます", - "yat_alert_content": "Cake Walletユーザーは、独自の絵文字ベースのユーザー名を使用して、お気に入りのすべての通貨を送受信できるようになりました。", - "get_your_yat": "あなたのYatを入手してください", - "connect_an_existing_yat": "既存のYatを接続します", - "yat_address": "Yat住所", - "yat": "Yat", - "connect_yats": "Yatsを接続します", - "address_from_yat": "このアドレスは ${emoji} からのものです Yat", - "yat_error": "Yatエラー", - "yat_error_content": "このYatにリンクされているアドレスはありません。別のYatを試してください", - "choose_address": "\n\n住所を選択してください:", - "yat_popup_title": "あなたの財布のアドレスは絵文字であることができます。", - "yat_popup_content": "Yat(短い絵文字ベースのユーザー名)を使用して、CakeWalletで暗号を送受信できるようになりました。 設定画面でいつでもYatsを管理", - "second_intro_title": "それらすべてを支配する1つの絵文字アドレス", - "second_intro_content": "Yatは、すべての通貨のすべての長い16進アドレスを置き換える単一の一意の絵文字アドレスです。", - "third_intro_title": "Yatは他の人とうまく遊ぶ", - "third_intro_content": "YatsはCakeWalletの外にも住んでいます。 地球上のどのウォレットアドレスもYatに置き換えることができます!", - "learn_more": "もっと詳しく知る", - "search": "検索", - "search_language": "検索言語", - "search_currency": "検索通貨", - "new_template": "新しいテンプレート", - "electrum_address_disclaimer": "使用するたびに新しいアドレスが生成されますが、以前のアドレスは引き続き機能します", - "wallet_name_exists": "その名前のウォレットはすでに存在しています", - "market_place": "Marketplace", - "cake_pay_title": "ケーキペイギフトカード", - "cake_pay_subtitle": "割引ギフトカードを購入する (米国のみ)", - "cake_pay_web_cards_title": "Cake Pay ウェブカード", - "cake_pay_web_cards_subtitle": "世界中のプリペイド カードとギフト カードを購入する", - "about_cake_pay": "Cake Payを使用すると、仮想資産を含むギフトカードを簡単に購入でき、米国内の150,000を超える加盟店ですぐに利用できます。", - "cake_pay_account_note": "メールアドレスだけでサインアップして、カードを表示して購入できます。割引価格で利用できるカードもあります!", - "already_have_account": "すでにアカウントをお持ちですか?", - "create_account": "アカウントの作成", - "privacy_policy": "プライバシーポリシー", - "welcome_to_cakepay": "Cake Payへようこそ!", - "sign_up": "サインアップ", - "forgot_password": "パスワードを忘れた", - "reset_password": "パスワードのリセット", - "gift_cards": "ギフトカード", - "setup_your_debit_card": "デビットカードを設定してください", - "no_id_required": "IDは必要ありません。どこにでも補充して使用できます", - "how_to_use_card": "このカードの使用方法", - "purchase_gift_card": "ギフトカードを購入", - "verification": "検証", - "fill_code": "メールアドレスに記載されている確認コードを入力してください", - "didnt_get_code": "コードを取得しませんか?", - "resend_code": "再送してください", - "debit_card": "デビットカード", - "cakepay_prepaid_card": "CakePayプリペイドデビットカード", - "no_id_needed": "IDは必要ありません!", - "frequently_asked_questions": "よくある質問", - "debit_card_terms": "このデジタルウォレットでの支払いカード番号(および支払いカード番号に対応する資格情報)の保存と使用には、支払いカード発行者との該当するカード所有者契約の利用規約が適用されます。時々。", - "please_reference_document": "詳細については、以下のドキュメントを参照してください。", - "cardholder_agreement": "カード所有者契約", - "e_sign_consent": "電子署名の同意", - "agree_and_continue": "同意して続行", - "email_address": "メールアドレス", - "agree_to": "アカウントを作成することにより、", - "and": "と", - "enter_code": "コードを入力", - "congratulations": "おめでとうございます!", - "you_now_have_debit_card": "デビットカードができました", - "min_amount": "最小: ${value}", - "max_amount": "最大: ${value}", - "enter_amount": "金額を入力", - "billing_address_info": "請求先住所を尋ねられた場合は、配送先住所を入力してください", - "order_physical_card": "物理カードの注文", - "add_value": "付加価値", - "activate": "アクティブ化", - "get_a": "Get a", - "digital_and_physical_card": "デジタルおよび物理プリペイドデビットカード", - "get_card_note": "デジタル通貨でリロードできます。追加情報は必要ありません!", - "signup_for_card_accept_terms": "カードにサインアップして、利用規約に同意してください。", - "add_fund_to_card": "プリペイド資金をカードに追加します(最大 ${value})", - "use_card_info_two": "デジタル通貨ではなく、プリペイドアカウントで保持されている場合、資金は米ドルに変換されます。", - "use_card_info_three": "デジタルカードをオンラインまたは非接触型決済方法で使用してください。", - "optionally_order_card": "オプションで物理カードを注文します。", - "hide_details": "詳細を非表示", - "show_details": "詳細を表示", - "upto": "up up ${value}", - "discount": "${value}%を節約", - "gift_card_amount": "ギフトカードの金額", - "bill_amount": "請求額", - "you_pay": "あなたが支払う", - "tip": "ヒント: ", - "custom": "カスタム", - "by_cake_pay": "by Cake Pay", - "expires": "Expires", - "mm": "んん", - "yy": "YY", - "online": "オンライン", - "offline": "オフライン", - "gift_card_number": "ギフトカード番号", - "pin_number": "PIN番号", - "total_saving": "合計節約額", - "last_30_days": "過去30日", - "avg_savings": "平均節約額", - "view_all": "すべて表示", - "active_cards": "アクティブカード", - "delete_account": "アカウントの削除", - "cards": "カード", - "active": "アクティブ", - "redeemed": "償還", - "gift_card_balance_note": "残高が残っているギフトカードがここに表示されます", - "gift_card_redeemed_note": "利用したギフトカードがここに表示されます", - "logout": "ログアウト", - "add_tip": "ヒントを追加", - "percentageOf": "of ${amount}", - "is_percentage": "is", - "search_category": "検索カテゴリ", - "mark_as_redeemed": "償還済みとしてマーク", - "more_options": "その他のオプション", - "awaiting_payment_confirmation": "支払い確認を待っています", - "transaction_sent_notice": "1分経っても画面が進まない場合は、ブロックエクスプローラーとメールアドレスを確認してください。", - "agree": "同意する", - "in_store": "インストア", - "generated_gift_card": "ギフトカードの生成", - "payment_was_received": "お支払いを受け取りました。", - "proceed_after_one_minute": "1分経っても画面が進まない場合は、メールを確認してください。", - "order_id": "注文ID", - "gift_card_is_generated": "ギフトカードが生成されます", - "open_gift_card": "オープンギフトカード", - "contact_support": "サポートに連絡する", - "gift_cards_unavailable": "現時点では、ギフトカードはMonero、Bitcoin、Litecoinからのみ購入できます。", - "background_sync_mode": "バックグラウンド同期モード", - "sync_all_wallets": "すべてのウォレットを同期", - "introducing_cake_pay": "序章Cake Pay!", - "cake_pay_learn_more": "アプリですぐにギフトカードを購入して引き換えましょう!\n左から右にスワイプして詳細をご覧ください。", + "authenticated": "認証済み", + "authentication": "認証", + "auto_generate_subaddresses": "Autoはサブアドレスを生成します", "automatic": "自動", - "fixed_pair_not_supported": "この固定ペアは、選択したエクスチェンジではサポートされていません", - "variable_pair_not_supported": "この変数ペアは、選択した取引所ではサポートされていません", - "none_of_selected_providers_can_exchange": "選択したプロバイダーはいずれもこの交換を行うことができません", - "choose_one": "1 つ選択してください", - "choose_from_available_options": "利用可能なオプションから選択してください:", - "custom_redeem_amount": "カスタム交換金額", - "add_custom_redemption": "カスタム引き換えを追加", - "remaining": "残り", - "delete_wallet": "ウォレットを削除", - "delete_wallet_confirm_message": "${wallet_name} ウォレットを削除してもよろしいですか?", - "low_fee": "低料金", - "low_fee_alert": "現在、低ネットワーク料金優先度を使用しています。これにより、長い待ち時間、異なるレート、またはキャンセルされた取引が発生する可能性があります。より良い体験のために、より高い料金を設定することをお勧めします。", - "ignor": "無視", - "use_suggested": "推奨を使用", - "do_not_share_warning_text": "サポートを含め、これらを他の誰とも共有しないでください。\n\nあなたの資金は盗まれる可能性があります!", - "help": "ヘルプ", - "all_transactions": "全取引", - "all_trades": "すべての取引", - "connection_sync": "接続と同期", - "security_and_backup": "セキュリティとバックアップ", - "create_backup": "バックアップを作成", - "privacy_settings": "プライバシー設定", - "privacy": "プライバシー", - "display_settings": "表示設定", - "other_settings": "その他の設定", - "require_pin_after": "後に PIN が必要", - "always": "いつも", - "minutes_to_pin_code": "${minute} 分", - "disable_exchange": "交換を無効にする", - "advanced_settings": "高度な設定", - "settings_can_be_changed_later": "これらの設定は、後でアプリの設定で変更できます", - "add_custom_node": "新しいカスタム ノードを追加", - "disable_fiat": "フィアットを無効にする", - "fiat_api": "不換紙幣 API", - "disabled": "無効", - "enabled": "有効", - "tor_only": "Torのみ", - "unmatched_currencies": "現在のウォレットの通貨がスキャンされたQRの通貨と一致しません", - "orbot_running_alert": "このノードに接続する前に、Orbot が実行されていることを確認してください", - "contact_list_contacts": "連絡先", - "contact_list_wallets": "マイウォレット", - "bitcoin_payments_require_1_confirmation": "ビットコインの支払いには 1 回の確認が必要で、これには 20 分以上かかる場合があります。お待ち頂きまして、ありがとうございます!支払いが確認されると、メールが送信されます。", - "send_to_this_address": "${currency} ${tag}をこのアドレスに送金", - "arrive_in_this_address": "${currency} ${tag}はこの住所に到着します", - "do_not_send": "送信しない", - "error_dialog_content": "エラーが発生しました。\n\nアプリケーションを改善するために、クラッシュ レポートをサポート チームに送信してください。", - "scan_qr_code": "QRコードをスキャン", - "cold_or_recover_wallet": "コールド ウォレットを追加するか、ペーパー ウォレットを復元する", - "please_wait": "お待ちください", - "sweeping_wallet": "スイープウォレット", - "sweeping_wallet_alert": "これには時間がかかりません。この画面から離れないでください。そうしないと、スイープ ファンドが失われる可能性があります", - "decimal_places_error": "小数点以下の桁数が多すぎる", - "edit_node": "ノードを編集", - "invoice_details": "請求の詳細", - "donation_link_details": "寄付リンクの詳細", - "anonpay_description": "${type} を生成します。受取人はサポートされている任意の暗号通貨で ${method} でき、あなたはこのウォレットで資金を受け取ります。", - "create_invoice": "請求書の作成", - "create_donation_link": "寄付リンクを作成", - "optional_email_hint": "オプションの受取人通知メール", - "optional_description": "オプションの説明", - "optional_name": "オプションの受信者名", - "clearnet_link": "クリアネット リンク", - "onion_link": "オニオンリンク", - "settings": "設定", - "sell_monero_com_alert_content": "モネロの販売はまだサポートされていません", - "error_text_input_below_minimum_limit": "金額は最小額より少ない", - "error_text_input_above_maximum_limit": "金額は最大値を超えています", - "show_market_place": "マーケットプレイスを表示", - "prevent_screenshots": "スクリーンショットと画面録画を防止する", - "profile": "プロフィール", - "close": "近い", - "modify_2fa": "ケーキの 2FA を変更する", - "disable_cake_2fa": "Cake 2FA を無効にする", - "question_to_disable_2fa": "Cake 2FA を無効にしてもよろしいですか?ウォレットと特定の機能にアクセスするために 2FA コードは必要なくなります。", - "disable": "無効にする", - "setup_2fa": "セットアップ ケーキ 2FA", - "verify_with_2fa": "Cake 2FA で検証する", - "totp_code": "TOTP コード", - "please_fill_totp": "他のデバイスにある 8 桁のコードを入力してください", - "totp_2fa_success": "成功!このウォレットでは Cake 2FA が有効になっています。ウォレットへのアクセスを失った場合に備えて、ニーモニック シードを忘れずに保存してください。", - "totp_verification_success": "検証成功!", - "totp_2fa_failure": "コードが正しくありません。 別のコードを試すか、新しい秘密鍵を生成してください。 8 桁のコードと SHA512 をサポートする互換性のある 2FA アプリを使用してください。", - "enter_totp_code": "TOTPコードを入力してください。", - "add_secret_code": "または、このシークレット コードを認証アプリに追加します", - "totp_secret_code": "TOTPシークレットコード", - "setup_2fa_text": "Cake 2FA は、TOTP を 2 番目の認証要素として使用して機能します。\n\nCake 2FA の TOTP には SHA-512 と 8 桁のサポートが必要です。これによりセキュリティが強化されます。詳細とサポートされているアプリについてはガイドをご覧ください。", - "setup_totp_recommended": "TOTPのセットアップ", - "disable_buy": "購入アクションを無効にする", - "disable_sell": "販売アクションを無効にする", - "cake_2fa_preset": "ケーキ 2FA プリセット", - "narrow": "狭い", - "normal": "普通", - "aggressive": "熱心すぎる", - "require_for_assessing_wallet": "ウォレットにアクセスするために必要です", - "require_for_sends_to_non_contacts": "非連絡先への送信に必須", - "require_for_sends_to_contacts": "連絡先に送信する場合に必須", - "require_for_sends_to_internal_wallets": "内部ウォレットへの送信に必須", - "require_for_exchanges_to_internal_wallets": "内部ウォレットへの交換に必要", - "require_for_adding_contacts": "連絡先の追加に必要", - "require_for_creating_new_wallets": "新しいウォレットを作成するために必要です", - "require_for_all_security_and_backup_settings": "すべてのセキュリティおよびバックアップ設定に必須", + "available_balance": "利用可能残高", "available_balance_description": "利用可能な残高は、ウォレットの残高から冷凍残高を差し引いたものです。", - "syncing_wallet_alert_title": "ウォレットは同期中です", - "syncing_wallet_alert_content": "上部に「同期済み」と表示されるまで、残高と取引リストが完了していない可能性があります。詳細については、クリック/タップしてください。", - "home_screen_settings": "ホーム画面の設定", - "sort_by": "並び替え", - "search_add_token": "トークンの検索/追加", - "edit_token": "トークンの編集", - "warning": "警告", - "add_token_warning": "詐欺師の指示に従ってトークンを編集または追加しないでください。\nトークン アドレスは常に信頼できる情報源で確認してください。", - "add_token_disclaimer_check": "信頼できる情報源を使用して、トークン コントラクトのアドレスと情報を確認しました。 悪意のある情報や不正確な情報を追加すると、資金が失われる可能性があります。", - "token_contract_address": "トークンコントラクトアドレス", - "token_name": "トークン名 例: Tether", - "token_symbol": "トークンシンボル 例: USDT", - "token_decimal": "トークン10進数", - "field_required": "この項目は必須です", - "pin_at_top": "${token} を上部に固定します", - "invalid_input": "無効入力", - "fiat_balance": "フィアットバランス", - "gross_balance": "グロス残高", - "alphabetical": "アルファベット順", - "generate_name": "名前の生成", + "avg_savings": "平均節約額", + "awaitDAppProcessing": "dAppの処理が完了するまでお待ちください。", + "awaiting_payment_confirmation": "支払い確認を待っています", + "background_sync_mode": "バックグラウンド同期モード", + "backup": "バックアップ", + "backup_file": "バックアップファイル", + "backup_password": "バックアップパスワード", "balance_page": "残高ページ", - "share": "共有", - "slidable": "スライド可能", - "monero_dark_theme": "モネロダークテーマ", + "bill_amount": "請求額", + "billing_address_info": "請求先住所を尋ねられた場合は、配送先住所を入力してください", + "biometric_auth_reason": "प指紋をスキャンして認証する", "bitcoin_dark_theme": "ビットコインダークテーマ", "bitcoin_light_theme": "ビットコインライトテーマ", - "high_contrast_theme": "ハイコントラストテーマ", - "matrix_green_dark_theme": "マトリックスグリーンダークテーマ", - "monero_light_theme": "モネロ ライト テーマ", - "manage_nodes": "ノードの管理", - "etherscan_history": "イーサスキャンの歴史", - "template_name": "テンプレート名", + "bitcoin_payments_require_1_confirmation": "ビットコインの支払いには 1 回の確認が必要で、これには 20 分以上かかる場合があります。お待ち頂きまして、ありがとうございます!支払いが確認されると、メールが送信されます。", + "Blocks_remaining": "${status} 残りのブロック", + "bright_theme": "明るい", + "buy": "購入", + "buy_alert_content": "現在、ビットコイン、イーサリアム、ライトコイン、モネロの購入のみをサポートしています。ビットコイン、イーサリアム、ライトコイン、またはモネロのウォレットを作成するか、これらのウォレットに切り替えてください。", + "buy_bitcoin": "ビットコインを購入する", + "buy_provider_unavailable": "現在、プロバイダーは利用できません。", + "buy_with": "で購入", + "by_cake_pay": "by Cake Pay", + "cake_2fa_preset": "ケーキ 2FA プリセット", + "cake_pay_account_note": "メールアドレスだけでサインアップして、カードを表示して購入できます。割引価格で利用できるカードもあります!", + "cake_pay_learn_more": "アプリですぐにギフトカードを購入して引き換えましょう!\n左から右にスワイプして詳細をご覧ください。", + "cake_pay_subtitle": "割引ギフトカードを購入する (米国のみ)", + "cake_pay_title": "ケーキペイギフトカード", + "cake_pay_web_cards_subtitle": "世界中のプリペイド カードとギフト カードを購入する", + "cake_pay_web_cards_title": "Cake Pay ウェブカード", + "cake_wallet": "Cake Wallet", + "cakepay_prepaid_card": "CakePayプリペイドデビットカード", + "camera_consent": "あなたのカメラは、${provider}_ までに識別目的で画像を撮影するために使用されます。詳細については、プライバシー ポリシーをご確認ください。", + "camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。", + "cancel": "キャンセル", + "card_address": "住所:", + "cardholder_agreement": "カード所有者契約", + "cards": "カード", + "chains": "チェーン", + "change": "変化する", + "change_backup_password_alert": "以前のバックアップファイルは、新しいバックアップパスワードでインポートできなくなります。 新しいバックアップパスワードは、新しいバックアップファイルにのみ使用されます。 バックアップパスワードを変更してもよろしいですか?", + "change_currency": "通貨を変更する", + "change_current_node": "現在のノードを変更してよろしいですか ${node}?", + "change_current_node_title": "現在のノードを変更する", + "change_exchange_provider": "Exchangeプロバイダーの変更", + "change_language": "言語を変えてください", + "change_language_to": "言語を変更 ${language}?", + "change_password": "パスワードを変更する", "change_rep": "代表者の変更", "change_rep_message": "代表者を変更してもよろしいですか?", - "unsupported_asset": "このアセットに対するこのアクションはサポートされていません。サポートされているアセットタイプのウォレットを作成するか、ウォレットに切り替えてください。", - "manage_pow_nodes": "PoWノードの管理", - "support_title_live_chat": "ライブサポート", - "support_description_live_chat": "無料で速い!訓練されたサポート担当者が支援することができます", - "support_title_guides": "ケーキウォレットガイド", - "support_description_guides": "一般的な問題のドキュメントとサポート", - "support_title_other_links": "その他のサポートリンク", - "support_description_other_links": "私たちのコミュニティに参加するか、他の方法を通して私たちのパートナーに連絡してください", + "change_rep_successful": "代表者の変更に成功しました", + "change_wallet_alert_content": "現在のウォレットをに変更しますか ${wallet_name}?", + "change_wallet_alert_title": "現在のウォレットを変更する", + "choose_account": "アカウントを選択", + "choose_address": "\n\n住所を選択してください:", "choose_derivation": "ウォレット派生を選択します", - "new_first_wallet_text": "暗号通貨を簡単に安全に保ちます", - "select_destination": "バックアップファイルの保存先を選択してください。", - "auto_generate_subaddresses": "Autoはサブアドレスを生成します", - "save_to_downloads": "ダウンロードに保存", - "select_buy_provider_notice": "上記の購入プロバイダーを選択してください。デフォルトの購入プロバイダーをアプリ設定で設定して、この画面をスキップできます。", - "onramper_option_description": "多くの支払い方法で暗号をすばやく購入してください。ほとんどの国で利用可能です。スプレッドと料金は異なります。", + "choose_from_available_options": "利用可能なオプションから選択してください:", + "choose_one": "1 つ選択してください", + "choose_relay": "使用するリレーを選択してください", + "choose_wallet_currency": "ウォレット通貨を選択してください:", + "clear": "クリア", + "clearnet_link": "クリアネット リンク", + "close": "近い", + "coin_control": "コインコントロール(オプション)", + "cold_or_recover_wallet": "コールド ウォレットを追加するか、ペーパー ウォレットを復元する", + "color_theme": "カラーテーマ", + "commit_transaction_amount_fee": "トランザクションをコミット\n量: ${amount}\n費用: ${fee}", + "confirm": "確認する", + "confirm_delete_template": "この操作により、このテンプレートが削除されます。 続行しますか?", + "confirm_delete_wallet": "このアクションにより、このウォレットが削除されます。 続行しますか?", + "confirm_sending": "送信を確認", + "confirmations": "確認", + "confirmed": "確認済み残高", + "confirmed_tx": "確認済み", + "congratulations": "おめでとうございます!", + "connect_an_existing_yat": "既存のYatを接続します", + "connect_yats": "Yatsを接続します", + "connection_sync": "接続と同期", + "connectWalletPrompt": "ウォレットを WalletConnect に接続して取引を行う", + "contact": "接触", + "contact_list_contacts": "連絡先", + "contact_list_wallets": "マイウォレット", + "contact_name": "連絡先", + "contact_support": "サポートに連絡する", + "continue_text": "持続する", + "contractName": "契約名", + "contractSymbol": "契約記号", + "copied_key_to_clipboard": "コピー済み ${key} クリップボードへ", + "copied_to_clipboard": "クリップボードにコピーしました", + "copy": "コピー", + "copy_address": "住所をコピー", + "copy_id": "IDをコピー", + "copyWalletConnectLink": "dApp から WalletConnect リンクをコピーし、ここに貼り付けます", + "create_account": "アカウントの作成", + "create_backup": "バックアップを作成", + "create_donation_link": "寄付リンクを作成", + "create_invoice": "請求書の作成", + "create_new": "新しいウォレットを作成", + "create_new_account": "新しいアカウントを作成する", + "creating_new_wallet": "新しいウォレットの作成", + "creating_new_wallet_error": "エラー: ${description}", + "creation_date": "作成日", + "custom": "カスタム", + "custom_drag": "カスタム(ホールドとドラッグ)", + "custom_redeem_amount": "カスタム交換金額", + "dark_theme": "闇", + "debit_card": "デビットカード", + "debit_card_terms": "このデジタルウォレットでの支払いカード番号(および支払いカード番号に対応する資格情報)の保存と使用には、支払いカード発行者との該当するカード所有者契約の利用規約が適用されます。時々。", + "decimal_places_error": "小数点以下の桁数が多すぎる", "default_buy_provider": "デフォルトの購入プロバイダー", - "ask_each_time": "毎回尋ねてください", - "buy_provider_unavailable": "現在、プロバイダーは利用できません。", - "signTransaction": "トランザクションに署名する", + "default_sell_provider": "デフォルトの販売プロバイダー", + "delete": "削除する", + "delete_account": "アカウントの削除", + "delete_wallet": "ウォレットを削除", + "delete_wallet_confirm_message": "${wallet_name} ウォレットを削除してもよろしいですか?", + "deleteConnectionConfirmationPrompt": "への接続を削除してもよろしいですか?", + "descending": "下降", + "description": "説明", + "destination_tag": "宛先タグ:", + "dfx_option_description": "EUR と CHF で暗号通貨を購入します。追加のKYCなしで最大990ユーロ。ヨーロッパの小売および法人顧客向け", + "didnt_get_code": "コードを取得しませんか?", + "digit_pin": "桁ピン", + "digital_and_physical_card": "デジタルおよび物理プリペイドデビットカード", + "disable": "無効にする", + "disable_buy": "購入アクションを無効にする", + "disable_cake_2fa": "Cake 2FA を無効にする", + "disable_exchange": "交換を無効にする", + "disable_fiat": "フィアットを無効にする", + "disable_sell": "販売アクションを無効にする", + "disabled": "無効", + "discount": "${value}%を節約", + "display_settings": "表示設定", + "displayable": "表示可能", + "do_not_have_enough_gas_asset": "現在のブロックチェーン ネットワークの状況では、トランザクションを行うのに十分な ${currency} がありません。別のアセットを送信する場合でも、ブロックチェーン ネットワーク料金を支払うにはさらに ${currency} が必要です。", + "do_not_send": "送信しない", + "do_not_share_warning_text": "サポートを含め、これらを他の誰とも共有しないでください。\n\nあなたの資金は盗まれる可能性があります!", + "do_not_show_me": "また僕にこれを見せないでください", + "domain_looks_up": "ドメイン検索", + "donation_link_details": "寄付リンクの詳細", + "e_sign_consent": "電子署名の同意", + "edit": "編集", + "edit_backup_password": "バックアップパスワードの編集", + "edit_node": "ノードを編集", + "edit_token": "トークンの編集", + "electrum_address_disclaimer": "使用するたびに新しいアドレスが生成されますが、以前のアドレスは引き続き機能します", + "email_address": "メールアドレス", + "enabled": "有効", + "enter_amount": "金額を入力", + "enter_backup_password": "ここにバックアップパスワードを入力してください", + "enter_code": "コードを入力", + "enter_seed_phrase": "シードフレーズを入力してください", + "enter_totp_code": "TOTPコードを入力してください。", + "enter_your_note": "メモを入力してください…", + "enter_your_pin": "PINを入力してください", + "enter_your_pin_again": "ピンをもう一度入力してください", + "enterTokenID": "トークンIDを入力してください", + "enterWalletConnectURI": "WalletConnect URI を入力してください", + "error": "エラー", + "error_dialog_content": "エラーが発生しました。\n\nアプリケーションを改善するために、クラッシュ レポートをサポート チームに送信してください。", + "error_text_account_name": "アカウント名には文字のみを含めることができます \n1〜15文字である必要があります", + "error_text_address": "ウォレットアドレスは、\n暗号通貨", + "error_text_amount": "金額には数字のみを含めることができます", + "error_text_contact_name": "連絡先名に含めることはできません ` , ' \" シンボル\n長さは1〜32文字でなければなりません", + "error_text_crypto_currency": "小数桁数\n12以下でなければなりません", + "error_text_fiat": "金額は利用可能な残高を超えることはできません.\n小数桁の数は2以下でなければなりません", + "error_text_input_above_maximum_limit": "金額は最大値を超えています", + "error_text_input_below_minimum_limit": "金額は最小額より少ない", + "error_text_keys": "ウォレットキーには、16進数で64文字しか含めることができません", + "error_text_limits_loading_failed": "${provider} の取引は作成されません。 制限の読み込みに失敗しました", + "error_text_maximum_limit": "${provider} の取引は作成されません。 金額は最大値を超えています: ${max} ${currency}", + "error_text_minimal_limit": "${provider} の取引は作成されません。 金額は最小額より少ない: ${min} ${currency}", + "error_text_node_address": "iPv4アドレスを入力してください", + "error_text_node_port": "ノードポートには、0〜65535の数字のみを含めることができます", + "error_text_node_proxy_address": ":<ポート> を入力してください (例: 127.0.0.1:9050)", + "error_text_payment_id": "支払いIDには、16進数で16〜64文字しか含めることができません", + "error_text_subaddress_name": "サブアドレス名に含めることはできません` , ' \" シンボル\n1〜20文字の長さである必要があります", + "error_text_template": "テンプレートの名前とアドレスに含めることはできません ` , ' \" シンボル\n1〜106文字の長さである必要があります", + "error_text_wallet_name": "ウォレット名には、文字、数字、_-記号のみを含めることができます\n長さは1〜33文字である必要があります", + "error_text_xmr": "XMR値は利用可能な残高を超えることはできません.\n小数桁数は12以下でなければなりません", "errorGettingCredentials": "失敗: 認証情報の取得中にエラーが発生しました", "errorSigningTransaction": "トランザクションの署名中にエラーが発生しました", - "pairingInvalidEvent": "ペアリング無効イベント", - "chains": "チェーン", - "methods": "メソッド", - "events": "イベント", - "reject": "拒否する", - "approve": "承認する", - "expiresOn": "有効期限は次のとおりです", - "walletConnect": "ウォレットコネクト", - "nullURIError": "URIがnullです", - "connectWalletPrompt": "ウォレットを WalletConnect に接続して取引を行う", - "newConnection": "新しい接続", - "activeConnectionsPrompt": "アクティブな接続がここに表示されます", - "deleteConnectionConfirmationPrompt": "への接続を削除してもよろしいですか?", + "estimated": "推定", + "etherscan_history": "イーサスキャンの歴史", "event": "イベント", - "successful": "成功", - "wouoldLikeToConnect": "接続したいです", - "message": "メッセージ", - "do_not_have_enough_gas_asset": "現在のブロックチェーン ネットワークの状況では、トランザクションを行うのに十分な ${currency} がありません。別のアセットを送信する場合でも、ブロックチェーン ネットワーク料金を支払うにはさらに ${currency} が必要です。", - "totp_auth_url": "TOTP認証URL", - "awaitDAppProcessing": "dAppの処理が完了するまでお待ちください。", - "copyWalletConnectLink": "dApp から WalletConnect リンクをコピーし、ここに貼り付けます", - "enterWalletConnectURI": "WalletConnect URI を入力してください", - "seed_key": "シードキー", - "enter_seed_phrase": "シードフレーズを入力してください", - "change_rep_successful": "代表者の変更に成功しました", - "add_contact": "連絡先を追加", + "events": "イベント", + "exchange": "交換する", + "exchange_incorrect_current_wallet_for_xmr": "Cake Wallet Moneroの残高からXMRを交換する場合は、最初にMoneroウォレットに切り替えてください。", + "exchange_new_template": "新しいテンプレート", "exchange_provider_unsupported": "${providerName}はサポートされなくなりました!", - "domain_looks_up": "ドメイン検索", - "require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要", - "camera_permission_is_required": "カメラの許可が必要です。\nアプリの設定から有効にしてください。", - "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください", - "order_by": "注文", - "creation_date": "作成日", + "exchange_result_confirm": "確認を押すと、送信されます ${fetchingLabel} ${from} と呼ばれるあなたの財布から ${walletName} 下記の住所へ。 または、外部ウォレットから以下のアドレスに送信することもできます/ QRコードに送信できます.\n\n確認を押して続行するか、戻って金額を変更してください.", + "exchange_result_description": "次のページに示されているアドレスに最低 ${fetchingLabel} ${from} を送信する必要があります。 ${fetchingLabel} ${from} 未満の金額を送信すると、変換されず、返金されない場合があります。", + "exchange_result_write_down_ID": "*上記のIDをコピーまたは書き留めてください.", + "exchange_result_write_down_trade_id": "続行するには、取引IDをコピーまたは書き留めてください.", + "exchange_sync_alert_content": "ウォレットが同期されるまでお待ちください", + "expired": "期限切れ", + "expires": "Expires", + "expiresOn": "有効期限は次のとおりです", + "export_backup": "バックアップのエクスポート", + "extra_id": "追加ID:", + "extracted_address_content": "に送金します\n${recipient_name}", + "failed_authentication": "認証失敗. ${state_error}", + "faq": "FAQ", + "fetching": "フェッチング", + "fiat_api": "不換紙幣 API", + "fiat_balance": "フィアットバランス", + "field_required": "この項目は必須です", + "fill_code": "メールアドレスに記載されている確認コードを入力してください", + "filter_by": "でフィルタリング", + "first_wallet_text": "Monero、Bitcoin、Ethereum、Litecoin、Haven用の素晴らしいウォレット", + "fixed_pair_not_supported": "この固定ペアは、選択したエクスチェンジではサポートされていません", + "fixed_rate": "固定金利", + "fixed_rate_alert": "固定金利モードにチェックを入れると、受取額を入力できるようになります。 固定金利モードに切り替えますか?", + "forgot_password": "パスワードを忘れた", + "freeze": "氷結", + "frequently_asked_questions": "よくある質問", + "frozen": "凍った", + "full_balance": "フルバランス", + "generate_name": "名前の生成", + "generated_gift_card": "ギフトカードの生成", + "get_a": "Get a", + "get_card_note": "デジタル通貨でリロードできます。追加情報は必要ありません!", + "get_your_yat": "あなたのYatを入手してください", + "gift_card_amount": "ギフトカードの金額", + "gift_card_balance_note": "残高が残っているギフトカードがここに表示されます", + "gift_card_is_generated": "ギフトカードが生成されます", + "gift_card_number": "ギフトカード番号", + "gift_card_redeemed_note": "利用したギフトカードがここに表示されます", + "gift_cards": "ギフトカード", + "gift_cards_unavailable": "現時点では、ギフトカードはMonero、Bitcoin、Litecoinからのみ購入できます。", + "got_it": "とった", + "gross_balance": "グロス残高", "group_by_type": "タイプごとにグループ", - "importNFTs": "NFTのインポート", - "noNFTYet": "NFTはまだありません", - "address": "住所", - "enterTokenID": "トークンIDを入力してください", - "tokenID": "ID", - "name": "名前", - "symbol": "シンボル", - "seed_phrase_length": "シードフレーズの長さ", - "unavailable_balance": "利用できない残高", - "unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。", - "unspent_change": "変化", - "tor_connection": "Tor接続", - "setup_warning_2fa_text": "Cake 2FA は、ウォレット内の特定のアクションに対する 2 番目の認証です。冷蔵保存ほど安全ではありません。\n\n2FA アプリまたは TOTP キーにアクセスできなくなると、このウォレットにもアクセスできなくなります。ニーモニックシードからウォレットを復元する必要があります。\n\n2FA またはニーモニック シードにアクセスできなくなった場合、Cake サポートはサポートできません。\nCake 2FA を使用する前に、ガイドを一読することをお勧めします。", - "scan_qr_on_device": "別のデバイスでこの QR コードをスキャンします", + "haven_app": "Haven by Cake Wallet", + "haven_app_wallet_text": "Awesome wallet for Haven", + "help": "ヘルプ", + "hidden_balance": "隠れたバランス", + "hide_details": "詳細を非表示", + "high_contrast_theme": "ハイコントラストテーマ", + "home_screen_settings": "ホーム画面の設定", "how_to_use": "使い方", + "how_to_use_card": "このカードの使用方法", + "id": "ID: ", + "ignor": "無視", + "import": "輸入", + "importNFTs": "NFTのインポート", + "in_store": "インストア", + "incoming": "着信", + "incorrect_seed": "入力されたテキストは無効です。", + "introducing_cake_pay": "序章Cake Pay!", + "invalid_input": "無効入力", + "invoice_details": "請求の詳細", + "is_percentage": "is", + "last_30_days": "過去30日", + "learn_more": "もっと詳しく知る", + "light_theme": "光", + "loading_your_wallet": "ウォレットをロードしています", + "login": "ログイン", + "logout": "ログアウト", + "low_fee": "低料金", + "low_fee_alert": "現在、低ネットワーク料金優先度を使用しています。これにより、長い待ち時間、異なるレート、またはキャンセルされた取引が発生する可能性があります。より良い体験のために、より高い料金を設定することをお勧めします。", + "manage_nodes": "ノードの管理", + "manage_pow_nodes": "PoWノードの管理", + "manage_yats": "Yatsを管理する", + "mark_as_redeemed": "償還済みとしてマーク", + "market_place": "Marketplace", + "matrix_green_dark_theme": "マトリックスグリーンダークテーマ", + "max_amount": "最大: ${value}", + "max_value": "マックス: ${value} ${currency}", + "memo": "メモ:", + "message": "メッセージ", + "methods": "メソッド", + "min_amount": "最小: ${value}", + "min_value": "分: ${value} ${currency}", + "minutes_to_pin_code": "${minute} 分", + "mm": "んん", + "modify_2fa": "ケーキの 2FA を変更する", + "monero_com": "Monero.com by Cake Wallet", + "monero_com_wallet_text": "Awesome wallet for Monero", + "monero_dark_theme": "モネロダークテーマ", + "monero_light_theme": "モネロ ライト テーマ", + "moonpay_alert_text": "金額の値は以上でなければなりません ${minAmount} ${fiatCurrency}", + "more_options": "その他のオプション", + "name": "名前", + "narrow": "狭い", + "new_first_wallet_text": "暗号通貨を簡単に安全に保ちます", + "new_node_testing": "新しいノードのテスト", + "new_subaddress_create": "作成する", + "new_subaddress_label_name": "ラベル名", + "new_subaddress_title": "新しいアドレス", + "new_template": "新しいテンプレート", + "new_wallet": "新しいウォレット", + "newConnection": "新しい接続", + "no_id_needed": "IDは必要ありません!", + "no_id_required": "IDは必要ありません。どこにでも補充して使用できます", + "no_relay_on_domain": "ユーザーのドメインのリレーが存在しないか、リレーが使用できません。使用するリレーを選択してください。", + "no_relays": "リレーなし", + "no_relays_message": "このユーザーの Nostr NIP-05 レコードが見つかりましたが、リレーは含まれていません。受信者に Nostr レコードにリレーを追加するよう指示してください。", + "node_address": "ノードアドレス", + "node_connection_failed": "接続に失敗しました", + "node_connection_successful": "接続に成功しました", + "node_new": "新しいノード", + "node_port": "ノードポート", + "node_reset_settings_title": "設定をリセット", + "node_test": "テスト", + "nodes": "ノード", + "nodes_list_reset_to_default_message": "設定をデフォルトにリセットしてもよろしいですか?", + "none_of_selected_providers_can_exchange": "選択したプロバイダーはいずれもこの交換を行うことができません", + "noNFTYet": "NFTはまだありません", + "normal": "普通", + "note_optional": "注(オプション)", + "note_tap_to_change": "注(タップして変更)", + "nullURIError": "URIがnullです", + "offer_expires_in": "で有効期限が切れます: ", + "offline": "オフライン", + "ok": "OK", + "onion_link": "オニオンリンク", + "online": "オンライン", + "onramper_option_description": "多くの支払い方法で暗号をすばやく購入してください。ほとんどの国で利用可能です。スプレッドと料金は異なります。", + "open_gift_card": "オープンギフトカード", + "optional_description": "オプションの説明", + "optional_email_hint": "オプションの受取人通知メール", + "optional_name": "オプションの受信者名", + "optionally_order_card": "オプションで物理カードを注文します。", + "orbot_running_alert": "このノードに接続する前に、Orbot が実行されていることを確認してください", + "order_by": "注文", + "order_id": "注文ID", + "order_physical_card": "物理カードの注文", + "other_settings": "その他の設定", + "outdated_electrum_wallet_description": "Cakeで作成された新しいビットコインウォレットには、24ワードのシードがあります。 新しいビットコインウォレットを作成し、すべての資金を新しい24ワードのウォレットに転送し、12ワードのシードを持つウォレットの使用を停止することが必須です。 あなたの資金を確保するためにこれをすぐに行ってください。", + "outdated_electrum_wallet_receive_warning": "このウォレットに 12 ワードのシードがあり、Cake で作成された場合、このウォレットにビットコインを入金しないでください。 このウォレットに転送された BTC は失われる可能性があります。 新しい 24 ワードのウォレットを作成し (右上のメニューをタップし、[ウォレット]、[新しいウォレットの作成]、[ビットコイン] の順に選択)、すぐに BTC をそこに移動します。 Cake の新しい (24 ワード) BTC ウォレットは安全です", + "outgoing": "発信", + "overwrite_amount": "Overwrite amount", + "pairingInvalidEvent": "ペアリング無効イベント", + "password": "パスワード", + "paste": "ペースト", + "pause_wallet_creation": "Haven Wallet を作成する機能は現在一時停止されています。", + "payment_id": "支払いID: ", + "payment_was_received": "お支払いを受け取りました。", + "pending": " (保留中)", + "percentageOf": "of ${amount}", + "pin_at_top": "${token} を上部に固定します", + "pin_is_incorrect": "PINが間違っています", + "pin_number": "PIN番号", + "placeholder_contacts": "連絡先はここに表示されます", + "placeholder_transactions": "あなたの取引はここに表示されます", + "please_fill_totp": "他のデバイスにある 8 桁のコードを入力してください", + "please_make_selection": "以下を選択してください ウォレットを作成または回復する.", + "please_reference_document": "詳細については、以下のドキュメントを参照してください。", + "please_select": "選んでください:", + "please_select_backup_file": "バックアップファイルを選択し、バックアップパスワードを入力してください。", + "please_try_to_connect_to_another_node": "別のノードに接続してみてください", + "please_wait": "お待ちください", + "polygonscan_history": "ポリゴンスキャン履歴", + "powered_by": "搭載 ${title}", + "pre_seed_button_text": "わかります。 種を見せて", + "pre_seed_description": "次のページでは、一連の${words}語が表示されます。 これはあなたのユニークでプライベートなシードであり、紛失や誤動作が発生した場合にウォレットを回復する唯一の方法です。 それを書き留めて、Cake Wallet アプリの外の安全な場所に保管するのはあなたの責任です。", + "pre_seed_title": "重要", + "prevent_screenshots": "スクリーンショットと画面録画を防止する", + "privacy": "プライバシー", + "privacy_policy": "プライバシーポリシー", + "privacy_settings": "プライバシー設定", + "private_key": "秘密鍵", + "proceed_after_one_minute": "1分経っても画面が進まない場合は、メールを確認してください。", + "profile": "プロフィール", + "provider_error": "${provider} エラー", + "public_key": "公開鍵", + "purchase_gift_card": "ギフトカードを購入", + "qr_fullscreen": "タップして全画面QRコードを開く", + "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", + "question_to_disable_2fa": "Cake 2FA を無効にしてもよろしいですか?ウォレットと特定の機能にアクセスするために 2FA コードは必要なくなります。", + "receivable_balance": "売掛金残高", + "receive": "受け取る", + "receive_amount": "量", + "received": "受け取った", + "recipient_address": "受信者のアドレス", + "reconnect": "再接続", + "reconnect_alert_text": "再接続しますか?", + "reconnection": "再接続", + "redeemed": "償還", + "refund_address": "払い戻し住所", + "reject": "拒否する", + "remaining": "残り", + "remove": "削除する", + "remove_node": "ノードを削除", + "remove_node_message": "選択したノードを削除してもよろしいですか?", + "rename": "リネーム", + "require_for_adding_contacts": "連絡先の追加に必要", + "require_for_all_security_and_backup_settings": "すべてのセキュリティおよびバックアップ設定に必須", + "require_for_assessing_wallet": "ウォレットにアクセスするために必要です", + "require_for_creating_new_wallets": "新しいウォレットを作成するために必要です", + "require_for_exchanges_to_external_wallets": "外部ウォレットへの交換に必要", + "require_for_exchanges_to_internal_wallets": "内部ウォレットへの交換に必要", + "require_for_sends_to_contacts": "連絡先に送信する場合に必須", + "require_for_sends_to_internal_wallets": "内部ウォレットへの送信に必須", + "require_for_sends_to_non_contacts": "非連絡先への送信に必須", + "require_pin_after": "後に PIN が必要", + "rescan": "再スキャン", + "resend_code": "再送してください", + "reset": "リセットする", + "reset_password": "パスワードのリセット", + "restore_active_seed": "アクティブシード", + "restore_address": "住所", + "restore_bitcoin_description_from_keys": "秘密鍵から生成されたWIF文字列からウォレットを復元します", + "restore_bitcoin_description_from_seed": "24ワードの組み合わせコードからウォレットを復元する", + "restore_bitcoin_title_from_keys": "WIFから復元", + "restore_description_from_backup": "Cake Walletアプリ全体を復元できますバックアップファイル", + "restore_description_from_keys": "生成されたウォレットを復元します秘密鍵から保存されたキーストローク", + "restore_description_from_seed": "25ワードからウォレットを復元しますまたは13ワードの組み合わせコード", + "restore_description_from_seed_keys": "安全な場所に保存したシード/キーから財布を取り戻す", + "restore_from_date_or_blockheight": "このウォレットを作成する数日前に日付を入力してください。 または、ブロックの高さがわかっている場合は、代わりに入力してください", + "restore_from_seed_placeholder": "ここにコードフレーズを入力または貼り付けてください", + "restore_new_seed": "新しい種", + "restore_next": "次", + "restore_recover": "回復します", + "restore_restore_wallet": "ウォレットを復元", + "restore_seed_keys_restore": "シード/キーの復元", + "restore_spend_key_private": "キーを使う (プライベート)", + "restore_title_from_backup": "バックアップファイルから復元する", + "restore_title_from_keys": "キーから復元する", + "restore_title_from_seed": "シードから復元", + "restore_title_from_seed_keys": "シード/キーから復元", + "restore_view_key_private": "ビューキー (プライベート)", + "restore_wallet": "ウォレットを復元", + "restore_wallet_name": "ウォレット名", + "restore_wallet_restore_description": "ウォレットの復元", + "router_no_route": "ルートが定義されていません ${name}", + "save": "セーブ", + "save_backup_password": "バックアップパスワードが保存されていることを確認してください。 それなしではバックアップファイルをインポートすることはできません。", + "save_backup_password_alert": "バックアップパスワードを保存する", + "save_to_downloads": "ダウンロードに保存", + "saved_the_trade_id": "取引IDを保存しました", + "scan_qr_code": "QRコードをスキャン", + "scan_qr_code_to_get_address": "QRコードをスキャンして住所を取得します", + "scan_qr_on_device": "別のデバイスでこの QR コードをスキャンします", + "search": "検索", + "search_add_token": "トークンの検索/追加", + "search_category": "検索カテゴリ", + "search_currency": "検索通貨", + "search_language": "検索言語", + "second_intro_content": "Yatは、すべての通貨のすべての長い16進アドレスを置き換える単一の一意の絵文字アドレスです。", + "second_intro_title": "それらすべてを支配する1つの絵文字アドレス", + "security_and_backup": "セキュリティとバックアップ", + "seed_alert_back": "戻る", + "seed_alert_content": "種子はあなたの財布を回復する唯一の方法です。 書き留めましたか?", + "seed_alert_title": "注意", + "seed_alert_yes": "はい、あります", + "seed_choose": "シード言語を選択してください", "seed_hex_form": "ウォレットシード(ヘックスフォーム)", + "seed_key": "シードキー", + "seed_language": "シード言語", + "seed_language_chinese": "中国語", + "seed_language_chinese_traditional": "中国の伝統的な)", + "seed_language_czech": "チェコ", + "seed_language_dutch": "オランダの", + "seed_language_english": "英語", + "seed_language_french": "フランス語", + "seed_language_german": "ドイツ人", + "seed_language_italian": "イタリア語", + "seed_language_japanese": "日本語", + "seed_language_korean": "韓国語", + "seed_language_next": "次", + "seed_language_portuguese": "ポルトガル語", + "seed_language_russian": "ロシア", + "seed_language_spanish": "スペイン語", + "seed_phrase_length": "シードフレーズの長さ", + "seed_reminder": "スマートフォンを紛失したりワイプした場合に備えて、これらを書き留めてください", + "seed_share": "シードを共有する", + "seed_title": "シード", "seedtype": "SeedType", "seedtype_legacy": "レガシー(25語)", "seedtype_polyseed": "ポリシード(16語)", - "seed_language_czech": "チェコ", - "seed_language_korean": "韓国語", - "seed_language_chinese_traditional": "中国の伝統的な)", - "ascending": "上昇", - "descending": "下降", - "dfx_option_description": "EUR と CHF で暗号通貨を購入します。追加のKYCなしで最大990ユーロ。ヨーロッパの小売および法人顧客向け", - "polygonscan_history": "ポリゴンスキャン履歴", - "wallet_seed_legacy": "レガシーウォレットシード", - "default_sell_provider": "デフォルトの販売プロバイダー", + "select_backup_file": "バックアップファイルを選択", + "select_buy_provider_notice": "上記の購入プロバイダーを選択してください。デフォルトの購入プロバイダーをアプリ設定で設定して、この画面をスキップできます。", + "select_destination": "バックアップファイルの保存先を選択してください。", "select_sell_provider_notice": "上記の販売プロバイダーを選択してください。アプリ設定でデフォルトの販売プロバイダーを設定することで、この画面をスキップできます。", - "custom_drag": "カスタム(ホールドとドラッグ)", + "sell": "売る", + "sell_alert_content": "現在、ビットコイン、イーサリアム、ライトコインの販売のみをサポートしています。ビットコイン、イーサリアム、またはライトコインのウォレットを作成するか、これらのウォレットに切り替えてください。", + "sell_monero_com_alert_content": "モネロの販売はまだサポートされていません", + "send": "送る", + "send_address": "${cryptoCurrency} 住所", + "send_amount": "量:", + "send_creating_transaction": "トランザクションを作成する", + "send_error_currency": "通貨には数字のみを含めることができます", + "send_error_minimum_value": "金額の最小値は0.01です", + "send_estimated_fee": "見積手数料:", + "send_fee": "費用:", + "send_name": "名前", + "send_new": "新着", + "send_payment_id": "支払いID (オプショナル)", + "send_priority": "現在、料金は ${transactionPriority} 優先度.\nトランザクションの優先度は設定で調整できます", + "send_sending": "送信...", + "send_success": "${crypto}が送信されました", + "send_templates": "テンプレート", + "send_title": "を送信", + "send_to_this_address": "${currency} ${tag}をこのアドレスに送金", + "send_xmr": "送る XMR", + "send_your_wallet": "あなたの財布", + "sending": "送信", + "sent": "送信済み", + "settings": "設定", + "settings_all": "すべて", + "settings_allow_biometrical_authentication": "生体認証を許可する", + "settings_can_be_changed_later": "これらの設定は、後でアプリの設定で変更できます", + "settings_change_language": "言語を変えてください", + "settings_change_pin": "PINを変更", + "settings_currency": "通貨", + "settings_current_node": "現在のノード", + "settings_dark_mode": "ダークモード", + "settings_display_balance": "ディスプレイバランス", + "settings_display_on_dashboard_list": "ダッシュボードリストに表示", + "settings_fee_priority": "料金優先", + "settings_nodes": "ノード", + "settings_none": "なし", + "settings_only_trades": "取引のみ", + "settings_only_transactions": "トランザクションのみ", + "settings_personal": "パーソナル", + "settings_save_recipient_address": "受信者のアドレスを保存", + "settings_support": "サポート", + "settings_terms_and_conditions": "規約と条件", + "settings_title": "設定", + "settings_trades": "取引", + "settings_transactions": "取引", + "settings_wallets": "財布", + "setup_2fa": "セットアップ ケーキ 2FA", + "setup_2fa_text": "Cake 2FA は、TOTP を 2 番目の認証要素として使用して機能します。\n\nCake 2FA の TOTP には SHA-512 と 8 桁のサポートが必要です。これによりセキュリティが強化されます。詳細とサポートされているアプリについてはガイドをご覧ください。", + "setup_pin": "PINのセットアップ", + "setup_successful": "PINは正常に設定されました!", + "setup_totp_recommended": "TOTPのセットアップ", + "setup_warning_2fa_text": "Cake 2FA は、ウォレット内の特定のアクションに対する 2 番目の認証です。冷蔵保存ほど安全ではありません。\n\n2FA アプリまたは TOTP キーにアクセスできなくなると、このウォレットにもアクセスできなくなります。ニーモニックシードからウォレットを復元する必要があります。\n\n2FA またはニーモニック シードにアクセスできなくなった場合、Cake サポートはサポートできません。\nCake 2FA を使用する前に、ガイドを一読することをお勧めします。", + "setup_your_debit_card": "デビットカードを設定してください", + "share": "共有", + "share_address": "住所を共有する", + "show_details": "詳細を表示", + "show_keys": "シード/キーを表示する", + "show_market_place": "マーケットプレイスを表示", + "show_seed": "シードを表示", + "sign_up": "サインアップ", + "signTransaction": "トランザクションに署名する", + "signup_for_card_accept_terms": "カードにサインアップして、利用規約に同意してください。", + "slidable": "スライド可能", + "sort_by": "並び替え", + "spend_key_private": "キーを使う (プライベート)", + "spend_key_public": "キーを使う (パブリック)", + "status": "状態: ", + "subaddress_title": "サブアドレス一覧", + "subaddresses": "サブアドレス", + "submit_request": "リクエストを送信する", + "successful": "成功", + "support_description_guides": "一般的な問題のドキュメントとサポート", + "support_description_live_chat": "無料で速い!訓練されたサポート担当者が支援することができます", + "support_description_other_links": "私たちのコミュニティに参加するか、他の方法を通して私たちのパートナーに連絡してください", + "support_title_guides": "ケーキウォレットガイド", + "support_title_live_chat": "ライブサポート", + "support_title_other_links": "その他のサポートリンク", + "sweeping_wallet": "スイープウォレット", + "sweeping_wallet_alert": "これには時間がかかりません。この画面から離れないでください。そうしないと、スイープ ファンドが失われる可能性があります", + "switchToETHWallet": "イーサリアムウォレットに切り替えてもう一度お試しください", "switchToEVMCompatibleWallet": "EVM 互換のウォレットに切り替えて再試行してください (イーサリアム、ポリゴン)", - "receivable_balance": "売掛金残高", - "confirmed_tx": "確認済み", + "symbol": "シンボル", + "sync_all_wallets": "すべてのウォレットを同期", + "sync_status_attempting_sync": "同期を試みています", + "sync_status_connected": "接続済み", + "sync_status_connecting": "接続中", + "sync_status_failed_connect": "切断されました", + "sync_status_not_connected": "接続されていません", + "sync_status_starting_sync": "同期の開始", + "sync_status_syncronized": "同期された", + "sync_status_syncronizing": "同期", + "syncing_wallet_alert_content": "上部に「同期済み」と表示されるまで、残高と取引リストが完了していない可能性があります。詳細については、クリック/タップしてください。", + "syncing_wallet_alert_title": "ウォレットは同期中です", + "template": "テンプレート", + "template_name": "テンプレート名", + "third_intro_content": "YatsはCakeWalletの外にも住んでいます。 地球上のどのウォレットアドレスもYatに置き換えることができます!", + "third_intro_title": "Yatは他の人とうまく遊ぶ", + "time": "${minutes}m ${seconds}s", + "tip": "ヒント: ", + "today": "今日", + "token_contract_address": "トークンコントラクトアドレス", + "token_decimal": "トークン10進数", + "token_name": "トークン名 例: Tether", + "token_symbol": "トークンシンボル 例: USDT", + "tokenID": "ID", + "tor_connection": "Tor接続", + "tor_only": "Torのみ", + "total_saving": "合計節約額", + "totp_2fa_failure": "コードが正しくありません。 別のコードを試すか、新しい秘密鍵を生成してください。 8 桁のコードと SHA512 をサポートする互換性のある 2FA アプリを使用してください。", + "totp_2fa_success": "成功!このウォレットでは Cake 2FA が有効になっています。ウォレットへのアクセスを失った場合に備えて、ニーモニック シードを忘れずに保存してください。", + "totp_auth_url": "TOTP認証URL", + "totp_code": "TOTP コード", + "totp_secret_code": "TOTPシークレットコード", + "totp_verification_success": "検証成功!", + "trade_details_copied": "${title} クリップボードにコピーしました", + "trade_details_created_at": "で作成", + "trade_details_fetching": "フェッチング", + "trade_details_id": "ID", + "trade_details_pair": "ペア", + "trade_details_provider": "プロバイダー", + "trade_details_state": "状態", + "trade_details_title": "取引の詳細", + "trade_for_not_created": "取引 ${title} 作成されません", + "trade_history_title": "取引履歴", + "trade_id": "取引ID:", + "trade_id_not_found": "トレード ${tradeId} of ${title} 見つかりません", + "trade_is_powered_by": "この取引は ${provider}", + "trade_not_created": "作成されていない取引", + "trade_not_found": "取引が見つかりません", + "trade_state_btc_sent": "送った", + "trade_state_complete": "コンプリート", + "trade_state_confirming": "確認中", + "trade_state_created": "作成した", + "trade_state_finished": "完成した", + "trade_state_paid": "有料", + "trade_state_paid_unconfirmed": "未確認の支払い", + "trade_state_pending": "保留中", + "trade_state_timeout": "タイムアウト", + "trade_state_to_be_created": "作成される", + "trade_state_traded": "取引済み", + "trade_state_trading": "トレーディング", + "trade_state_underpaid": "支払不足", + "trade_state_unpaid": "未払い", + "trades": "取引", + "transaction_details_amount": "量", + "transaction_details_copied": "${title} クリップボードにコピーしました", + "transaction_details_date": "日付", + "transaction_details_fee": "費用", + "transaction_details_height": "高さ", + "transaction_details_recipient_address": "受信者のアドレス", "transaction_details_source_address": "ソースアドレス", - "pause_wallet_creation": "Haven Wallet を作成する機能は現在一時停止されています。", - "contractName": "契約名", - "contractSymbol": "契約記号", - "description": "説明", - "camera_consent": "あなたのカメラは、${provider}_ までに識別目的で画像を撮影するために使用されます。詳細については、プライバシー ポリシーをご確認ください。", - "no_relays": "リレーなし", - "choose_relay": "使用するリレーを選択してください", - "no_relays_message": "このユーザーの Nostr NIP-05 レコードが見つかりましたが、リレーは含まれていません。受信者に Nostr レコードにリレーを追加するよう指示してください。", - "no_relay_on_domain": "ユーザーのドメインのリレーが存在しないか、リレーが使用できません。使用するリレーを選択してください。" -} + "transaction_details_title": "取引の詳細", + "transaction_details_transaction_id": "トランザクションID", + "transaction_key": "トランザクションキー", + "transaction_priority_fast": "速い", + "transaction_priority_fastest": "最速", + "transaction_priority_medium": "中", + "transaction_priority_regular": "レギュラー", + "transaction_priority_slow": "スロー", + "transaction_sent": "トランザクションが送信されました!", + "transaction_sent_notice": "1分経っても画面が進まない場合は、ブロックエクスプローラーとメールアドレスを確認してください。", + "transactions": "取引", + "transactions_by_date": "日付ごとの取引", + "trusted": "信頼できる", + "unavailable_balance": "利用できない残高", + "unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。", + "unconfirmed": "残高未確認", + "understand": "わかります", + "unmatched_currencies": "現在のウォレットの通貨がスキャンされたQRの通貨と一致しません", + "unspent_change": "変化", + "unspent_coins_details_title": "未使用のコインの詳細", + "unspent_coins_title": "未使用のコイン", + "unsupported_asset": "このアセットに対するこのアクションはサポートされていません。サポートされているアセットタイプのウォレットを作成するか、ウォレットに切り替えてください。", + "upto": "up up ${value}", + "use": "使用する ", + "use_card_info_three": "デジタルカードをオンラインまたは非接触型決済方法で使用してください。", + "use_card_info_two": "デジタル通貨ではなく、プリペイドアカウントで保持されている場合、資金は米ドルに変換されます。", + "use_ssl": "SSLを使用する", + "use_suggested": "推奨を使用", + "variable_pair_not_supported": "この変数ペアは、選択した取引所ではサポートされていません", + "verification": "検証", + "verify_with_2fa": "Cake 2FA で検証する", + "version": "バージョン ${currentVersion}", + "view_all": "すべて表示", + "view_in_block_explorer": "View in Block Explorer", + "view_key_private": "ビューキー (プライベート)", + "view_key_public": "ビューキー (パブリック)", + "view_transaction_on": "View Transaction on ", + "wallet_keys": "ウォレットシード/キー", + "wallet_list_create_new_wallet": "新しいウォレットを作成", + "wallet_list_edit_wallet": "ウォレットを編集する", + "wallet_list_failed_to_load": "読み込みに失敗しました ${wallet_name} 財布. ${error}", + "wallet_list_failed_to_remove": "削除できませんでした ${wallet_name} 財布. ${error}", + "wallet_list_load_wallet": "ウォレットをロード", + "wallet_list_loading_wallet": "読み込み中 ${wallet_name} 財布", + "wallet_list_removing_wallet": "取りはずし ${wallet_name} 財布", + "wallet_list_restore_wallet": "ウォレットを復元", + "wallet_list_title": "Monero 財布", + "wallet_list_wallet_name": "ウォレット名", + "wallet_menu": "ウォレットメニュー", + "wallet_name": "ウォレット名", + "wallet_name_exists": "その名前のウォレットはすでに存在しています", + "wallet_restoration_store_incorrect_seed_length": "誤ったシード長s", + "wallet_seed": "ウォレットシード", + "wallet_seed_legacy": "レガシーウォレットシード", + "wallet_store_monero_wallet": "Monero 財布", + "walletConnect": "ウォレットコネクト", + "wallets": "財布", + "warning": "警告", + "welcome": "ようこそ に", + "welcome_to_cakepay": "Cake Payへようこそ!", + "widgets_address": "住所", + "widgets_or": "または", + "widgets_restore_from_blockheight": "ブロックの高さから復元", + "widgets_restore_from_date": "日付から復元", + "widgets_seed": "シード", + "wouoldLikeToConnect": "接続したいです", + "write_down_backup_password": "バックアップファイルのインポートに使用されるバックアップパスワードを書き留めてください。", + "xlm_extra_info": "交換用のXLMトランザクションを送信するときに、メモIDを指定することを忘れないでください", + "xmr_available_balance": "利用可能残高", + "xmr_full_balance": "フルバランス", + "xmr_hidden": "非表示", + "xmr_to_error": "XMR.TOエラー", + "xmr_to_error_description": "金額が無効です。 小数点以下8桁の上限", + "xrp_extra_info": "取引所のXRPトランザクションを送信するときに、宛先タグを指定することを忘れないでください", + "yat": "Yat", + "yat_address": "Yat住所", + "yat_alert_content": "Cake Walletユーザーは、独自の絵文字ベースのユーザー名を使用して、お気に入りのすべての通貨を送受信できるようになりました。", + "yat_alert_title": "Yatで暗号をより簡単に送受信できます", + "yat_error": "Yatエラー", + "yat_error_content": "このYatにリンクされているアドレスはありません。別のYatを試してください", + "yat_popup_content": "Yat(短い絵文字ベースのユーザー名)を使用して、CakeWalletで暗号を送受信できるようになりました。 設定画面でいつでもYatsを管理", + "yat_popup_title": "あなたの財布のアドレスは絵文字であることができます。", + "yesterday": "昨日", + "you_now_have_debit_card": "デビットカードができました", + "you_pay": "あなたが支払う", + "you_will_get": "に変換", + "you_will_send": "から変換", + "yy": "YY", + "zzzz": "zzzz" +} \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 5c3affbc5..f0970ac43 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -1,777 +1,778 @@ { - "welcome": "환영 에", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Monero, Bitcoin, Ethereum, Litecoin 및 Haven을 위한 멋진 지갑", - "please_make_selection": "아래에서 선택하십시오 지갑 만들기 또는 복구.", - "create_new": "새 월렛 만들기", - "restore_wallet": "월렛 복원", - "monero_com": "Monero.com by Cake Wallet", - "monero_com_wallet_text": "Awesome wallet for Monero", - "haven_app": "Haven by Cake Wallet", - "haven_app_wallet_text": "Awesome wallet for Haven", - "accounts": "계정", - "edit": "편집하다", + "about_cake_pay": "Cake Pay를 사용하면 미국 내 150,000개 이상의 가맹점에서 즉시 사용할 수 있는 가상 자산이 포함된 기프트 카드를 쉽게 구입할 수 있습니다.", "account": "계정", + "accounts": "계정", + "accounts_subaddresses": "계정 및 하위 주소", + "activate": "활성화", + "active": "활성", + "active_cards": "활성 카드", + "activeConnectionsPrompt": "활성 연결이 여기에 표시됩니다", "add": "더하다", + "add_contact": "주소록에 추가", + "add_custom_node": "새 사용자 정의 노드 추가", + "add_custom_redemption": "사용자 지정 상환 추가", + "add_fund_to_card": "카드에 선불 금액 추가(최대 ${value})", + "add_new_node": "새 노드 추가", + "add_new_word": "새로운 단어 추가", + "add_receiver": "다른 수신기 추가(선택 사항)", + "add_secret_code": "또는 이 비밀 코드를 인증 앱에 추가하세요.", + "add_tip": "팁 추가", + "add_token_disclaimer_check": "신뢰할 수 있는 출처를 통해 토큰 컨트랙트 주소와 정보를 확인했습니다. 악의적이거나 잘못된 정보를 추가하면 자금 손실이 발생할 수 있습니다.", + "add_token_warning": "사기꾼의 지시에 따라 토큰을 편집하거나 추가하지 마십시오.\n항상 신뢰할 수 있는 출처를 통해 토큰 주소를 확인하세요!", + "add_value": "값 추가", + "address": "주소", "address_book": "주소록", - "contact": "접촉", - "please_select": "선택 해주세요:", - "cancel": "취소", - "ok": "승인", - "contact_name": "담당자 이름", - "reset": "다시 놓기", - "save": "구하다", + "address_book_menu": "주소록", + "address_detected": "주소 감지", + "address_from_domain": "이 주소는 ${domain} 의 주소입니다 Unstoppable Domains", + "address_from_yat": "이 주소는 ${emoji} 의 주소입니다 Yat", + "address_label": "Address label", "address_remove_contact": "연락처 삭제", "address_remove_content": "선택한 연락처를 삭제 하시겠습니까?", - "authenticated": "인증", - "authentication": "입증", - "failed_authentication": "인증 실패. ${state_error}", - "wallet_menu": "월렛 메뉴", - "Blocks_remaining": "${status} 남은 블록", - "please_try_to_connect_to_another_node": "다른 노드에 연결을 시도하십시오", - "xmr_hidden": "숨김", - "xmr_available_balance": "사용 가능한 잔액", - "xmr_full_balance": "풀 밸런스", - "send": "보내다", - "receive": "받다", - "transactions": "업무", - "incoming": "들어오는", - "outgoing": "나가는", - "transactions_by_date": "날짜 별 거래", - "trades": "거래", - "filter_by": "필터링 기준", - "today": "오늘", - "yesterday": "어제", - "received": "받았습니다", - "sent": "보냄", - "pending": " (보류 중)", - "rescan": "재검색", - "reconnect": "다시 연결", - "wallets": "지갑", - "show_seed": "종자 표시", - "show_keys": "시드 / 키 표시", - "address_book_menu": "주소록", - "reconnection": "재 연결", - "reconnect_alert_text": "다시 연결 하시겠습니까?", - "exchange": "교환", - "clear": "명확한", - "refund_address": "환불 주소", - "change_exchange_provider": "교환 공급자 변경", - "you_will_send": "다음에서 변환", - "you_will_get": "로 변환하다", - "amount_is_guaranteed": "수령 금액이 보장됩니다.", - "amount_is_estimate": "수신 금액은 견적입니다", - "powered_by": "에 의해 구동 ${title}", - "error": "오류", - "estimated": "예상", - "min_value": "최소: ${value} ${currency}", - "max_value": "맥스: ${value} ${currency}", - "change_currency": "통화 변경", - "overwrite_amount": "Overwrite amount", - "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", - "copy_id": "부 ID", - "exchange_result_write_down_trade_id": "계속하려면 거래 ID를 복사하거나 적어 두십시오..", - "trade_id": "무역 ID:", - "copied_to_clipboard": "클립 보드에 복사", - "saved_the_trade_id": "거래 ID를 저장했습니다", - "fetching": "가져 오는 중", - "id": "ID: ", - "amount": "양: ", - "payment_id": "지불 ID: ", - "status": "지위: ", - "offer_expires_in": "쿠폰 만료일: ", - "trade_is_powered_by": "이 거래는 ${provider}", - "copy_address": "주소 복사", - "exchange_result_confirm": "확인을 누르면 전송됩니다 ${fetchingLabel} ${from} 지갑에서 ${walletName} 아래 주소로. 또는 외부 지갑에서 아래 주소로 보낼 수 있습니다 / QR 코드로 보낼 수 있습니다.\n\n확인을 눌러 계속하거나 금액을 변경하려면 돌아가십시오.", - "exchange_result_description": "다음 페이지에 표시된 주소로 최소 ${fetchingLabel} ${from} 를 보내야합니다. ${fetchingLabel} ${from} 보다 적은 금액을 보내면 변환되지 않고 환불되지 않을 수 있습니다.", - "exchange_result_write_down_ID": "*위에 표시된 ID를 복사하거나 적어 두십시오.", - "confirm": "확인", - "confirm_sending": "전송 확인", - "commit_transaction_amount_fee": "커밋 거래\n양: ${amount}\n보수: ${fee}", - "sending": "배상", - "transaction_sent": "거래가 전송되었습니다!", - "expired": "만료", - "time": "${minutes}m ${seconds}s", - "send_xmr": "보내다 XMR", - "exchange_new_template": "새 템플릿", - "faq": "FAQ", - "enter_your_pin": "PIN을 입력하십시오", - "loading_your_wallet": "지갑 넣기", - "new_wallet": "새 월렛", - "wallet_name": "지갑 이름", - "continue_text": "잇다", - "choose_wallet_currency": "지갑 통화를 선택하십시오:", - "node_new": "새로운 노드", - "node_address": "노드 주소", - "node_port": "노드 포트", - "login": "로그인", - "password": "암호", - "nodes": "노드", - "node_reset_settings_title": "설정 초기화", - "nodes_list_reset_to_default_message": "설정을 기본값으로 재설정 하시겠습니까?", - "change_current_node": "현재 노드를 다음으로 변경 하시겠습니까 ${node}?", - "change": "변화", - "remove_node": "노드 제거", - "remove_node_message": "선택한 노드를 제거 하시겠습니까?", - "remove": "없애다", - "delete": "지우다", - "add_new_node": "새 노드 추가", - "change_current_node_title": "현재 노드 변경", - "node_test": "테스트", - "node_connection_successful": "성공적으로 연결되었습니다.", - "node_connection_failed": "연결 실패", - "new_node_testing": "새로운 노드 테스트", - "use": "사용하다 ", - "digit_pin": "숫자 PIN", - "share_address": "주소 공유", - "receive_amount": "양", - "subaddresses": "하위 주소", "addresses": "구애", - "scan_qr_code_to_get_address": "QR 코드를 스캔하여 주소를 얻습니다.", - "qr_fullscreen": "전체 화면 QR 코드를 열려면 탭하세요.", - "rename": "이름 바꾸기", - "choose_account": "계정을 선택하십시오", - "create_new_account": "새 계정을 만들", - "accounts_subaddresses": "계정 및 하위 주소", - "restore_restore_wallet": "월렛 복원", - "restore_title_from_seed_keys": "시드 / 키에서 복원", - "restore_description_from_seed_keys": "안전한 장소에 저장 한 종자 / 키로 지갑을 되 찾으십시오.", - "restore_next": "다음 것", - "restore_title_from_backup": "백업 파일에서 복원", - "restore_description_from_backup": "백업 파일에서 전체 Cake Wallet 앱을 복원 할 수 있습니다.", - "restore_seed_keys_restore": "종자 / 키 복원", - "restore_title_from_seed": "종자에서 복원", - "restore_description_from_seed": "25 단어 또는 13 단어 조합 코드에서 지갑을 복원하십시오.", - "restore_title_from_keys": "키에서 복원", - "restore_description_from_keys": "개인 키에서 저장된 생성 된 키 스트로크에서 월렛 복원", - "restore_wallet_name": "지갑 이름", - "restore_address": "주소", - "restore_view_key_private": "키보기 (은밀한)", - "restore_spend_key_private": "지출 키 (은밀한)", - "restore_recover": "다시 덮다", - "restore_wallet_restore_description": "월렛 복원 설명", - "restore_new_seed": "새로운 씨앗", - "restore_active_seed": "활성 종자", - "restore_bitcoin_description_from_seed": "24 단어 조합 코드에서 지갑 복원", - "restore_bitcoin_description_from_keys": "개인 키에서 생성 된 WIF 문자열에서 지갑 복원", - "restore_bitcoin_title_from_keys": "WIF에서 복원", - "restore_from_date_or_blockheight": "이 지갑을 생성하기 며칠 전에 날짜를 입력하십시오. 또는 블록 높이를 알고있는 경우 대신 입력하십시오.", - "seed_reminder": "휴대 전화를 분실하거나 닦을 경우를 대비해 적어 두세요.", - "seed_title": "씨", - "seed_share": "시드 공유", - "copy": "부", - "seed_language": "종자 언어", - "seed_choose": "시드 언어를 선택하십시오", - "seed_language_next": "다음 것", - "seed_language_english": "영어", - "seed_language_chinese": "중국말", - "seed_language_dutch": "네덜란드 사람", - "seed_language_german": "독일 사람", - "seed_language_japanese": "일본어", - "seed_language_portuguese": "포르투갈 인", - "seed_language_russian": "러시아인", - "seed_language_spanish": "스페인의", - "seed_language_french": "프랑스 국민", - "seed_language_italian": "이탈리아 사람", - "send_title": "보내다", - "send_your_wallet": "지갑", - "send_address": "${cryptoCurrency} 주소", - "send_payment_id": "지불 ID (optional)", + "advanced_settings": "고급 설정", + "aggressive": "지나치게 열심인", + "agree": "동의하다", + "agree_and_continue": "동의 및 계속", + "agree_to": "계정을 생성하면 ", "all": "모든", - "send_error_minimum_value": "금액의 최소값은 0.01입니다", - "send_error_currency": "통화는 숫자 만 포함 할 수 있습니다", - "send_estimated_fee": "예상 수수료:", - "send_priority": "현재 수수료는 ${transactionPriority} 우선 순위.\n거래 우선 순위는 설정에서 조정할 수 있습니다", - "send_creating_transaction": "거래 생성", - "send_templates": "템플릿", - "send_new": "새로운", - "send_amount": "양:", - "send_fee": "회비:", - "send_name": "이름", - "got_it": "알았다", - "send_sending": "배상...", - "send_success": "${crypto}가 성공적으로 전송되었습니다", - "settings_title": "설정", - "settings_nodes": "노드", - "settings_current_node": "현재 노드", - "settings_wallets": "지갑", - "settings_display_balance": "디스플레이 잔액", - "settings_currency": "통화", - "settings_fee_priority": "수수료 우선", - "settings_save_recipient_address": "수신자 주소 저장", - "settings_personal": "개인적인", - "settings_change_pin": "PIN 변경", - "settings_change_language": "언어 변경", - "settings_allow_biometrical_authentication": "생체 인증 허용", - "settings_dark_mode": "다크 모드", - "settings_transactions": "업무", - "settings_trades": "거래", - "settings_display_on_dashboard_list": "대시 보드 목록에 표시", - "settings_all": "모든", - "settings_only_trades": "거래 만", - "settings_only_transactions": "거래 만", - "settings_none": "없음", - "settings_support": "지원하다", - "settings_terms_and_conditions": "이용 약관", - "pin_is_incorrect": "PIN이 잘못되었습니다", - "setup_pin": "설정 PIN", - "enter_your_pin_again": "다시 핀을 입력", - "setup_successful": "PIN이 성공적으로 설정되었습니다!", - "wallet_keys": "지갑 시드 / 키", - "wallet_seed": "지갑 시드", - "private_key": "개인 키", - "public_key": "공개 키", - "view_key_private": "키보기(은밀한)", - "view_key_public": "키보기 (공공의)", - "spend_key_private": "지출 키 (은밀한)", - "spend_key_public": "지출 키 (공공의)", - "copied_key_to_clipboard": "복사 ${key} 클립 보드로", - "new_subaddress_title": "새 주소", - "new_subaddress_label_name": "라벨 이름", - "new_subaddress_create": "몹시 떠들어 대다", - "address_label": "Address label", - "subaddress_title": "하위 주소 목록", - "trade_details_title": "거래 세부 사항", - "trade_details_id": "ID", - "trade_details_state": "상태", - "trade_details_fetching": "가져 오는 중", - "trade_details_provider": "공급자", - "trade_details_created_at": "에 작성", - "trade_details_pair": "쌍", - "trade_details_copied": "${title} 클립 보드에 복사", - "trade_history_title": "무역 역사", - "transaction_details_title": "상세 거래 내역", - "transaction_details_transaction_id": "트랜잭션 ID", - "transaction_details_date": "날짜", - "transaction_details_height": "신장", - "transaction_details_amount": "양", - "transaction_details_fee": "회비", - "transaction_details_copied": "${title} 클립 보드에 복사", - "transaction_details_recipient_address": "받는 사람 주소", - "wallet_list_title": "모네로 월렛", - "wallet_list_create_new_wallet": "새 월렛 만들기", - "wallet_list_edit_wallet": "지갑 수정", - "wallet_list_wallet_name": "지갑 이름", - "wallet_list_restore_wallet": "월렛 복원", - "wallet_list_load_wallet": "지갑로드", - "wallet_list_loading_wallet": "로딩 ${wallet_name} 지갑", - "wallet_list_failed_to_load": "불러 오지 못했습니다 ${wallet_name} 지갑. ${error}", - "wallet_list_removing_wallet": "풀이 ${wallet_name} 지갑", - "wallet_list_failed_to_remove": "제거하지 못했습니다 ${wallet_name} 지갑. ${error}", - "widgets_address": "주소", - "widgets_restore_from_blockheight": "블록 높이에서 복원", - "widgets_restore_from_date": "날짜에서 복원", - "widgets_or": "또는", - "widgets_seed": "씨", - "router_no_route": "에 정의 된 경로가 없습니다 ${name}", - "error_text_account_name": "계정 이름은 문자, 숫자 만 포함 할 수 있습니다\n1 ~ 15 자 사이 여야합니다", - "error_text_contact_name": "담당자 이름은 포함 할 수 없습니다 ` , ' \" 기호\n1 자에서 32 자 사이 여야합니다", - "error_text_address": "지갑 주소는 유형과 일치해야합니다\n암호 화폐", - "error_text_node_address": "iPv4 주소를 입력하십시오", - "error_text_node_port": "노드 포트는 0에서 65535 사이의 숫자 만 포함 할 수 있습니다", - "error_text_node_proxy_address": ":<포트>를 입력하십시오(예: 127.0.0.1:9050).", - "error_text_payment_id": "지불 ID는 16 ~ 64 자의 16 진 문자 만 포함 할 수 있습니다", - "error_text_xmr": "XMR 값은 사용 가능한 잔액을 초과 할 수 없습니다.\n소수 자릿수는 12 이하 여야합니다", - "error_text_fiat": "금액은 사용 가능한 잔액을 초과 할 수 없습니다.\n소수 자릿수는 2보다 작거나 같아야합니다", - "error_text_subaddress_name": "하위 주소 이름은 포함 할 수 없습니다 ` , ' \" 기호 \n1 ~ 20 자 사이 여야합니다", - "error_text_amount": "금액은 숫자 만 포함 할 수 있습니다", - "error_text_wallet_name": "지갑 이름은 문자, 숫자, _ - 기호만 포함할 수 있습니다.\n1~33자 사이여야 합니다.", - "error_text_keys": "지갑 키는 16 진수로 64 자만 포함 할 수 있습니다", - "error_text_crypto_currency": "소수 자릿수\n12 이하 여야합니다", - "error_text_minimal_limit": "거래 ${provider} 가 생성되지 않습니다. 금액이 최소보다 적습니다. ${min} ${currency}", - "error_text_maximum_limit": "거래 ${provider} 가 생성되지 않습니다. 금액이 최대 값보다 많습니다. ${max} ${currency}", - "error_text_limits_loading_failed": "거래 ${provider} 가 생성되지 않습니다. 로딩 실패", - "error_text_template": "템플릿 이름과 주소는 포함 할 수 없습니다 ` , ' \" 기호 \n1 ~ 106 자 사이 여야합니다", + "all_trades": "A모든 거래", + "all_transactions": "모든 거래 창구", + "alphabetical": "알파벳순", + "already_have_account": "이미 계정이 있습니까?", + "always": "언제나", + "amount": "양: ", + "amount_is_estimate": "수신 금액은 견적입니다", + "amount_is_guaranteed": "수령 금액이 보장됩니다.", + "and": "그리고", + "anonpay_description": "${type} 생성. 수신자는 지원되는 모든 암호화폐로 ${method}할 수 있으며 이 지갑에서 자금을 받게 됩니다.", + "apk_update": "APK 업데이트", + "approve": "승인하다", + "arrive_in_this_address": "${currency} ${tag}이(가) 이 주소로 도착합니다", + "ascending": "오름차순", + "ask_each_time": "매번 물어보십시오", "auth_store_ban_timeout": "타임 아웃 금지", "auth_store_banned_for": "금지", "auth_store_banned_minutes": " 의사록", "auth_store_incorrect_password": "잘못된 PIN", - "wallet_store_monero_wallet": "모네로 월렛", - "wallet_restoration_store_incorrect_seed_length": "시드 길이가 잘못되었습니다", - "full_balance": "풀 밸런스", - "available_balance": "사용 가능한 잔액", - "hidden_balance": "숨겨진 균형", - "sync_status_syncronizing": "동기화", - "sync_status_syncronized": "동기화", - "sync_status_not_connected": "연결되지 않은", - "sync_status_starting_sync": "동기화 시작", - "sync_status_failed_connect": "연결 해제", - "sync_status_connecting": "연결 중", - "sync_status_connected": "연결됨", - "sync_status_attempting_sync": "동기화 시도 중", - "transaction_priority_slow": "느린", - "transaction_priority_regular": "정규병", - "transaction_priority_medium": "매질", - "transaction_priority_fast": "빠른", - "transaction_priority_fastest": "가장 빠른", - "trade_for_not_created": "거래 ${title} 생성되지 않습니다.", - "trade_not_created": "거래가 생성되지 않았습니다", - "trade_id_not_found": "무역 ${tradeId} 의 ${title} 찾을 수 없습니다.", - "trade_not_found": "거래를 찾을 수 없습니다.", - "trade_state_pending": "대기 중", - "trade_state_confirming": "확인 중", - "trade_state_trading": "거래", - "trade_state_traded": "거래", - "trade_state_complete": "완전한", - "trade_state_to_be_created": "만들려면", - "trade_state_unpaid": "미지급", - "trade_state_underpaid": "미지급", - "trade_state_paid_unconfirmed": "미확인 유료", - "trade_state_paid": "유료", - "trade_state_btc_sent": "보냄", - "trade_state_timeout": "타임 아웃", - "trade_state_created": "만들어진", - "trade_state_finished": "끝마친", - "change_language": "언어 변경", - "change_language_to": "언어를로 변경 ${language}?", - "paste": "풀", - "restore_from_seed_placeholder": "여기에 코드 문구를 입력하거나 붙여 넣으십시오.", - "add_new_word": "새로운 단어 추가", - "incorrect_seed": "입력하신 텍스트가 유효하지 않습니다.", - "biometric_auth_reason": "지문을 스캔하여 인증", - "version": "버전 ${currentVersion}", - "extracted_address_content": "당신은에 자금을 보낼 것입니다\n${recipient_name}", - "card_address": "주소:", - "buy": "구입", - "sell": "팔다", - "placeholder_transactions": "거래가 여기에 표시됩니다", - "placeholder_contacts": "연락처가 여기에 표시됩니다", - "template": "주형", - "confirm_delete_template": "이 작업은이 템플릿을 삭제합니다. 계속 하시겠습니까?", - "confirm_delete_wallet": "이 작업은이 지갑을 삭제합니다. 계속 하시겠습니까?", - "change_wallet_alert_title": "현재 지갑 변경", - "change_wallet_alert_content": "현재 지갑을 다음으로 변경 하시겠습니까 ${wallet_name}?", - "creating_new_wallet": "새 지갑 생성", - "creating_new_wallet_error": "오류: ${description}", - "seed_alert_title": "주의", - "seed_alert_content": "씨앗은 지갑을 복구하는 유일한 방법입니다. 적어 보셨나요?", - "seed_alert_back": "돌아 가기", - "seed_alert_yes": "네, 있어요", - "exchange_sync_alert_content": "지갑이 동기화 될 때까지 기다리십시오", - "pre_seed_title": "중대한", - "pre_seed_description": "다음 페이지에서 ${words} 개의 단어를 볼 수 있습니다. 이것은 귀하의 고유하고 개인적인 시드이며 분실 또는 오작동시 지갑을 복구하는 유일한 방법입니다. 기록해두고 Cake Wallet 앱 외부의 안전한 장소에 보관하는 것은 귀하의 책임입니다.", - "pre_seed_button_text": "이해 했어요. 내 씨앗을 보여줘", - "xmr_to_error": "XMR.TO 오류", - "xmr_to_error_description": "금액이 잘못되었습니다. 소수점 이하 최대 8 자리", - "provider_error": "${provider} 오류", - "use_ssl": "SSL 사용", - "trusted": "신뢰할 수 있는", - "color_theme": "색상 테마", - "light_theme": "빛", - "bright_theme": "선명한", - "dark_theme": "어두운", - "enter_your_note": "메모를 입력하세요…", - "note_optional": "참고 (선택 사항)", - "note_tap_to_change": "메모 (변경하려면 탭하세요)", - "view_in_block_explorer": "View in Block Explorer", - "view_transaction_on": "View Transaction on ", - "transaction_key": "거래 키", - "confirmations": "확인", - "recipient_address": "받는 사람 주소", - "extra_id": "추가 ID:", - "destination_tag": "목적지 태그:", - "memo": "메모:", - "backup": "지원", - "change_password": "비밀번호 변경", - "backup_password": "백업 비밀번호", - "write_down_backup_password": "백업 파일 가져 오기에 사용되는 백업 암호를 적어 두십시오.", - "export_backup": "백업 내보내기", - "save_backup_password": "백업 암호를 저장했는지 확인하십시오. 그것 없이는 백업 파일을 가져올 수 없습니다.", - "backup_file": "백업 파일", - "edit_backup_password": "편집 백업 암호", - "save_backup_password_alert": "백업 비밀번호 저장", - "change_backup_password_alert": "이전 백업 파일은 새 백업 암호로 가져올 수 없습니다. 새 백업 암호는 새 백업 파일에만 사용됩니다. 백업 비밀번호를 변경 하시겠습니까?", - "enter_backup_password": "여기에 백업 비밀번호를 입력하세요.", - "select_backup_file": "백업 파일 선택", - "import": "수입", - "please_select_backup_file": "백업 파일을 선택하고 백업 암호를 입력하십시오.", - "fixed_rate": "고정 비율", - "fixed_rate_alert": "고정 금리 모드 체크시 수취 금액 입력이 가능합니다. 고정 속도 모드로 전환 하시겠습니까?", - "xlm_extra_info": "교환을 위해 XLM 거래를 보낼 때 메모 ID를 지정하는 것을 잊지 마십시오", - "xrp_extra_info": "교환을 위해 XRP 트랜잭션을 보내는 동안 대상 태그를 지정하는 것을 잊지 마십시오", - "exchange_incorrect_current_wallet_for_xmr": "Cake Wallet Monero 잔액에서 XMR을 교환하려면 먼저 Monero 지갑으로 전환하십시오.", - "confirmed": "확인된 잔액", - "unconfirmed": "확인되지 않은 잔액", - "displayable": "표시 가능", - "submit_request": "요청을 제출", - "buy_alert_content": "현재 Bitcoin, Ethereum, Litecoin 및 Monero 구매만 지원합니다. Bitcoin, Ethereum, Litecoin 또는 Monero 지갑을 생성하거나 전환하십시오.", - "sell_alert_content": "현재 Bitcoin, Ethereum 및 Litecoin의 판매만 지원합니다. Bitcoin, Ethereum 또는 Litecoin 지갑을 생성하거나 전환하십시오.", - "outdated_electrum_wallet_description": "Cake에서 생성 된 새로운 비트 코인 지갑에는 이제 24 단어 시드가 있습니다. 새로운 비트 코인 지갑을 생성하고 모든 자금을 새로운 24 단어 지갑으로 이체하고 12 단어 시드가있는 지갑 사용을 중지해야합니다. 자금을 확보하려면 즉시이 작업을 수행하십시오.", - "understand": "이해 했어요", - "apk_update": "APK 업데이트", - "buy_bitcoin": "비트 코인 구매", - "buy_with": "구매", - "moonpay_alert_text": "금액은 다음보다 크거나 같아야합니다 ${minAmount} ${fiatCurrency}", - "outdated_electrum_wallet_receive_warning": "이 지갑에 12 단어 시드가 있고 Cake에서 생성 된 경우이 지갑에 비트 코인을 입금하지 마십시오. 이 지갑으로 전송 된 모든 BTC는 손실 될 수 있습니다. 새로운 24 단어 지갑을 생성하고 (오른쪽 상단의 메뉴를 탭하고 지갑을 선택한 다음 새 지갑 생성을 선택한 다음 비트 코인을 선택하십시오) 즉시 BTC를 그곳으로 이동하십시오. Cake의 새로운 (24 단어) BTC 지갑은 안전합니다", - "do_not_show_me": "나를 다시 표시하지 않음", - "unspent_coins_title": "사용하지 않은 동전", - "unspent_coins_details_title": "사용하지 않은 동전 세부 정보", - "freeze": "얼다", - "frozen": "겨울 왕국", - "coin_control": "코인 제어 (옵션)", - "address_detected": "주소 감지", - "address_from_domain": "이 주소는 ${domain} 의 주소입니다 Unstoppable Domains", - "add_receiver": "다른 수신기 추가(선택 사항)", - "manage_yats": "관리하다 Yats", - "yat_alert_title": "Yat으로 더 쉽게 암호화폐를 보내고 받으십시오.", - "yat_alert_content": "Cake Wallet 사용자는 이제 독특한 이모티콘 기반 사용자 이름으로 좋아하는 모든 통화를 보내고 받을 수 있습니다.", - "get_your_yat": "당신의 Yat를 얻으십시오", - "connect_an_existing_yat": "기존 Yat 연결", - "yat_address": "Yat 주소", - "yat": "Yat", - "connect_yats": "야츠 연결", - "address_from_yat": "이 주소는 ${emoji} 의 주소입니다 Yat", - "yat_error": "Yat 오류", - "yat_error_content": "이 Yat와 연결된 주소가 없습니다. 다른 Yat 시도", - "choose_address": "\n\n주소를 선택하십시오:", - "yat_popup_title": "지갑 주소를 이모티콘으로 만들 수 있습니다.", - "yat_popup_content": "이제 Yat(이모티콘 기반의 짧은 사용자 이름)으로 Cake Wallet에서 암호화폐를 보내고 받을 수 있습니다. 설정 화면에서 언제든지 Yats 관리", - "second_intro_title": "그들을 모두 지배하는 하나의 이모티콘 주소", - "second_intro_content": "귀하의 Yat는 귀하의 모든 통화에 대해 긴 16진수 주소를 모두 대체하는 고유한 단일 이모지 주소입니다.", - "third_intro_title": "Yat는 다른 사람들과 잘 놉니다.", - "third_intro_content": "Yats는 Cake Wallet 밖에서도 살고 있습니다. 지구상의 모든 지갑 주소는 Yat!", - "learn_more": "더 알아보기", - "search": "찾다", - "search_language": "검색 언어", - "search_currency": "통화 검색", - "new_template": "새 템플릿", - "electrum_address_disclaimer": "사용할 때마다 새 주소가 생성되지만 이전 주소는 계속 작동합니다.", - "wallet_name_exists": "해당 이름의 지갑이 이미 존재합니다.", - "market_place": "마켓플레이스", - "cake_pay_title": "케이크 페이 기프트 카드", - "cake_pay_subtitle": "할인된 기프트 카드 구매(미국만 해당)", - "cake_pay_web_cards_title": "케이크페이 웹카드", - "cake_pay_web_cards_subtitle": "전 세계 선불 카드 및 기프트 카드 구매", - "about_cake_pay": "Cake Pay를 사용하면 미국 내 150,000개 이상의 가맹점에서 즉시 사용할 수 있는 가상 자산이 포함된 기프트 카드를 쉽게 구입할 수 있습니다.", - "cake_pay_account_note": "이메일 주소로 가입하면 카드를 보고 구매할 수 있습니다. 일부는 할인된 가격으로 사용 가능합니다!", - "already_have_account": "이미 계정이 있습니까?", - "create_account": "계정 만들기", - "privacy_policy": "개인 정보 보호 정책", - "welcome_to_cakepay": "Cake Pay에 오신 것을 환영합니다!", - "sign_up": "가입", - "forgot_password": "비밀번호 찾기", - "reset_password": "비밀번호 재설정", - "gift_cards": "기프트 카드", - "setup_your_debit_card": "직불카드 설정", - "no_id_required": "신분증이 필요하지 않습니다. 충전하고 어디에서나 사용하세요", - "how_to_use_card": "이 카드를 사용하는 방법", - "purchase_gift_card": "기프트 카드 구매", - "verification": "검증", - "fill_code": "이메일에 제공된 인증 코드를 입력하세요.", - "didnt_get_code": "코드를 받지 못하셨습니까?", - "resend_code": "다시 보내주세요", - "debit_card": "직불 카드", - "cakepay_prepaid_card": "CakePay 선불 직불 카드", - "no_id_needed": "ID가 필요하지 않습니다!", - "frequently_asked_questions": "자주 묻는 질문", - "debit_card_terms": "이 디지털 지갑에 있는 귀하의 지불 카드 번호(및 귀하의 지불 카드 번호에 해당하는 자격 증명)의 저장 및 사용은 부터 발효되는 지불 카드 발행자와의 해당 카드 소지자 계약의 이용 약관을 따릅니다. 수시로.", - "Please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.", - "cardholder_agreement": "카드 소유자 계약", - "e_sign_consent": "전자 서명 동의", - "agree_and_continue": "동의 및 계속", - "email_address": "이메일 주소", - "agree_to": "계정을 생성하면 ", - "and": "그리고", - "enter_code": "코드 입력", - "congratulations": "축하합니다!", - "you_now_have_debit_card": "이제 직불카드가 있습니다.", - "min_amount": "최소: ${value}", - "max_amount": "최대: ${value}", - "enter_amount": "금액 입력", - "billing_address_info": "청구서 수신 주소를 묻는 메시지가 표시되면 배송 주소를 입력하세요.", - "order_physical_card": "물리적 카드 주문", - "add_value": "값 추가", - "activate": "활성화", - "get_a": "가져오기", - "digital_and_physical_card": " 디지털 및 실제 선불 직불 카드", - "get_card_note": " 디지털 통화로 충전할 수 있습니다. 추가 정보가 필요하지 않습니다!", - "signup_for_card_accept_terms": "카드에 가입하고 약관에 동의합니다.", - "add_fund_to_card": "카드에 선불 금액 추가(최대 ${value})", - "use_card_info_two": "디지털 화폐가 아닌 선불 계정에 보유하면 자금이 USD로 변환됩니다.", - "use_card_info_three": "디지털 카드를 온라인 또는 비접촉식 결제 수단으로 사용하십시오.", - "optionally_order_card": "선택적으로 실제 카드를 주문하십시오.", - "hide_details": "세부 정보 숨기기", - "show_details": "세부정보 표시", - "upto": "최대 ${value}", - "discount": "${value}% 절약", - "gift_card_amount": "기프트 카드 금액", - "bill_amount": "청구 금액", - "you_pay": "당신이 지불합니다", - "tip": "팁:", - "custom": "커스텀", - "by_cake_pay": "Cake Pay로", - "expires": "만료", - "mm": "mm", - "YY": "YY", - "online": "온라인", - "offline": "오프라인", - "gift_card_number": "기프트 카드 번호", - "pin_number": "PIN 번호", - "total_saving": "총 절감액", - "last_30_days": "지난 30일", - "avg_savings": "평균 절감액", - "view_all": "모두 보기", - "active_cards": "활성 카드", - "delete_account": "계정 삭제", - "cards": "카드", - "active": "활성", - "redeemed": "구함", - "gift_card_balance_note": "잔액이 남아 있는 기프트 카드가 여기에 표시됩니다.", - "gift_card_redeemed_note": "사용한 기프트 카드가 여기에 표시됩니다.", - "logout": "로그아웃", - "add_tip": "팁 추가", - "percentageOf": "${amount} 중", - "is_percentage": "이다", - "search_category": "검색 카테고리", - "mark_as_redeemed": "사용한 것으로 표시", - "more_options": "추가 옵션", - "awaiting_payment_confirmation": "결제 확인 대기 중", - "transaction_sent_notice": "1분 후에도 화면이 진행되지 않으면 블록 익스플로러와 이메일을 확인하세요.", - "agree": "동의하다", - "in_store": "매장 내", - "generating_gift_card": "기프트 카드 생성 중", - "payment_was_received": "결제가 접수되었습니다.", - "proceed_after_one_minute": "1분 후에도 화면이 진행되지 않으면 이메일을 확인하세요.", - "order_id": "주문 ID", - "gift_card_is_generated": "기프트 카드가 생성되었습니다", - "open_gift_card": "기프트 카드 열기", - "contact_support": "지원팀에 문의", - "gift_cards_unavailable": "기프트 카드는 현재 Monero, Bitcoin 및 Litecoin을 통해서만 구매할 수 있습니다.", - "background_sync_mode": "백그라운드 동기화 모드", - "sync_all_wallets": "모든 지갑 동기화", - "introducing_cake_pay": "소개 Cake Pay!", - "cake_pay_learn_more": "앱에서 즉시 기프트 카드를 구매하고 사용하세요!\n자세히 알아보려면 왼쪽에서 오른쪽으로 스와이프하세요.", + "authenticated": "인증", + "authentication": "입증", + "auto_generate_subaddresses": "자동 생성 서브 아드 드레스", "automatic": "자동적 인", - "fixed_pair_not_supported": "이 고정 쌍은 선택한 교환에서 지원되지 않습니다.", - "variable_pair_not_supported": "이 변수 쌍은 선택한 교환에서 지원되지 않습니다.", - "none_of_selected_providers_can_exchange": "선택한 공급자 중 누구도 이 교환을 할 수 없습니다.", - "choose_one": "하나 선택", - "choose_from_available_options": "사용 가능한 옵션에서 선택:", - "custom_redeem_amount": "사용자 지정 상환 금액", - "add_custom_redemption": "사용자 지정 상환 추가", - "remaining": "남은", - "delete_wallet": "지갑 삭제", - "delete_wallet_confirm_message": "${wallet_name} 지갑을 삭제하시겠습니까?", - "low_fee": "낮은 수수료", - "low_fee_alert": "현재 낮은 네트워크 요금 우선 순위를 사용하고 있습니다. 이로 인해 긴 대기 시간, 다른 요금 또는 취소된 거래가 발생할 수 있습니다. 더 나은 경험을 위해 더 높은 요금을 설정하는 것이 좋습니다.", - "ignor": "무시하다", - "use_suggested": "추천 사용", - "do_not_share_warning_text": "지원을 포함하여 다른 사람과 이러한 정보를 공유하지 마십시오.\n\n귀하의 자금은 도난당할 수 있고 도난당할 수 있습니다!", - "help": "돕다", - "all_transactions": "모든 거래 창구", - "all_trades": "A모든 거래", - "connection_sync": "연결 및 동기화", - "security_and_backup": "보안 및 백업", - "create_backup": "백업 생성", - "privacy_settings": "개인정보 설정", - "privacy": "프라이버시", - "display_settings": "디스플레이 설정", - "other_settings": "기타 설정", - "require_pin_after": "다음 이후에 PIN 필요", - "always": "언제나", - "minutes_to_pin_code": "${minute}분", - "disable_exchange": "교환 비활성화", - "advanced_settings": "고급 설정", - "settings_can_be_changed_later": "이 설정은 나중에 앱 설정에서 변경할 수 있습니다.", - "add_custom_node": "새 사용자 정의 노드 추가", - "disable_fiat": "법정화폐 비활성화", - "fiat_api": "명목 화폐 API", - "disabled": "장애가 있는", - "enabled": "사용", - "tor_only": "Tor 뿐", - "unmatched_currencies": "현재 지갑의 통화가 스캔한 QR의 통화와 일치하지 않습니다.", - "orbot_running_alert": "이 노드에 연결하기 전에 Orbot이 실행 중인지 확인하십시오.", - "contact_list_contacts": "콘택트 렌즈", - "contact_list_wallets": "내 지갑", - "bitcoin_payments_require_1_confirmation": "비트코인 결제는 1번의 확인이 필요하며 20분 이상이 소요될 수 있습니다. 기다려 주셔서 감사합니다! 결제가 확인되면 이메일이 전송됩니다.", - "send_to_this_address": "이 주소로 ${currency} ${tag}송금", - "arrive_in_this_address": "${currency} ${tag}이(가) 이 주소로 도착합니다", - "do_not_send": "보내지 마세요", - "error_dialog_content": "죄송합니다. 오류가 발생했습니다.\n\n응용 프로그램을 개선하려면 지원 팀에 충돌 보고서를 보내주십시오.", - "scan_qr_code": "QR 코드 스캔", - "cold_or_recover_wallet": "콜드 지갑 추가 또는 종이 지갑 복구", - "please_wait": "기다리세요", - "sweeping_wallet": "스위핑 지갑", - "sweeping_wallet_alert": "오래 걸리지 않습니다. 이 화면을 떠나지 마십시오. 그렇지 않으면 스웹트 자금이 손실될 수 있습니다.", - "decimal_places_error": "소수점 이하 자릿수가 너무 많습니다.", - "edit_node": "노드 편집", - "invoice_details": "인보이스 세부정보", - "donation_link_details": "기부 링크 세부정보", - "anonpay_description": "${type} 생성. 수신자는 지원되는 모든 암호화폐로 ${method}할 수 있으며 이 지갑에서 자금을 받게 됩니다.", - "create_invoice": "인보이스 생성", - "create_donation_link": "기부 링크 만들기", - "optional_email_hint": "선택적 수취인 알림 이메일", - "optional_description": "선택적 설명", - "optional_name": "선택적 수신자 이름", - "clearnet_link": "클리어넷 링크", - "onion_link": "양파 링크", - "settings": "설정", - "sell_monero_com_alert_content": "지원되지 않습니다.", - "error_text_input_below_minimum_limit": "금액이 최소보다 적습니다.", - "error_text_input_above_maximum_limit": "금액이 최대 값보다 많습니다.", - "show_market_place": "마켓플레이스 표시", - "prevent_screenshots": "스크린샷 및 화면 녹화 방지", - "profile": "프로필", - "close": "닫다", - "modify_2fa": "수정 케이크 2FA", - "disable_cake_2fa": "케이크 2FA 비활성화", - "question_to_disable_2fa": "Cake 2FA를 비활성화하시겠습니까? 지갑 및 특정 기능에 액세스하는 데 더 이상 2FA 코드가 필요하지 않습니다.", - "disable": "장애를 입히다", - "setup_2fa": "케이크 2FA 설정", - "verify_with_2fa": "케이크 2FA로 확인", - "totp_code": "TOTP 코드", - "please_fill_totp": "다른 기기에 있는 8자리 코드를 입력하세요.", - "totp_2fa_success": "성공! 이 지갑에 케이크 2FA가 활성화되었습니다. 지갑 액세스 권한을 잃을 경우를 대비하여 니모닉 시드를 저장하는 것을 잊지 마십시오.", - "totp_verification_success": "확인 성공!", - "totp_2fa_failure": "잘못된 코드입니다. 다른 코드를 시도하거나 새 비밀 키를 생성하십시오. 8자리 코드와 SHA512를 지원하는 호환되는 2FA 앱을 사용하세요.", - "enter_totp_code": "TOTP 코드를 입력하세요.", - "add_secret_code": "또는 이 비밀 코드를 인증 앱에 추가하세요.", - "totp_secret_code": "TOTP 비밀 코드", - "setup_2fa_text": "Cake 2FA는 TOTP를 두 번째 인증 요소로 사용하여 작동합니다.\n\nCake 2FA의 TOTP에는 SHA-512 및 8자리 지원이 필요합니다. 이는 보안을 강화합니다. 자세한 정보와 지원되는 앱은 가이드에서 확인할 수 있습니다.", - "setup_totp_recommended": "TOTP 설정", - "disable_buy": "구매 행동 비활성화", - "disable_sell": "판매 조치 비활성화", - "cake_2fa_preset": "케이크 2FA 프리셋", - "narrow": "좁은", - "normal": "정상", - "aggressive": "지나치게 열심인", - "require_for_assessing_wallet": "지갑 접근을 위해 필요", - "require_for_sends_to_non_contacts": "비접촉자에게 보내는 데 필요", - "require_for_sends_to_contacts": "연락처로 보내기에 필요", - "require_for_sends_to_internal_wallets": "내부 지갑으로 보내는 데 필요", - "require_for_exchanges_to_internal_wallets": "내부 지갑으로의 교환에 필요", - "require_for_adding_contacts": "연락처 추가에 필요", - "require_for_creating_new_wallets": "새 지갑 생성에 필요", - "require_for_all_security_and_backup_settings": "모든 보안 및 백업 설정에 필요", + "available_balance": "사용 가능한 잔액", "available_balance_description": "이 지갑에서 사용할 수 있는 잔액입니다. 이 잔액은 블록체인에서 가져온 것이며, Cake Wallet이 사용할 수 없습니다.", - "syncing_wallet_alert_title": "지갑 동기화 중", - "syncing_wallet_alert_content": "상단에 \"동기화됨\"이라고 표시될 때까지 잔액 및 거래 목록이 완전하지 않을 수 있습니다. 자세히 알아보려면 클릭/탭하세요.", - "home_screen_settings": "홈 화면 설정", - "sort_by": "정렬 기준", - "search_add_token": "검색 / 토큰 추가", - "edit_token": "토큰 편집", - "warning": "경고", - "add_token_warning": "사기꾼의 지시에 따라 토큰을 편집하거나 추가하지 마십시오.\n항상 신뢰할 수 있는 출처를 통해 토큰 주소를 확인하세요!", - "add_token_disclaimer_check": "신뢰할 수 있는 출처를 통해 토큰 컨트랙트 주소와 정보를 확인했습니다. 악의적이거나 잘못된 정보를 추가하면 자금 손실이 발생할 수 있습니다.", - "token_contract_address": "토큰 계약 주소", - "token_name": "토큰 이름 예: Tether", - "token_symbol": "토큰 기호 예: USDT", - "token_decimal": "토큰 십진수", - "field_required": "이 필드는 필수입니다", - "pin_at_top": "상단에 ${token} 고정", - "invalid_input": "잘못된 입력", - "fiat_balance": "피아트 잔액", - "gross_balance": "총 잔액", - "alphabetical": "알파벳순", - "generate_name": "이름 생성", + "avg_savings": "평균 절감액", + "awaitDAppProcessing": "dApp이 처리를 마칠 때까지 기다려주세요.", + "awaiting_payment_confirmation": "결제 확인 대기 중", + "background_sync_mode": "백그라운드 동기화 모드", + "backup": "지원", + "backup_file": "백업 파일", + "backup_password": "백업 비밀번호", "balance_page": "잔액 페이지", - "share": "공유하다", - "slidable": "슬라이딩 가능", - "monero_dark_theme": "모네로 다크 테마", + "bill_amount": "청구 금액", + "billing_address_info": "청구서 수신 주소를 묻는 메시지가 표시되면 배송 주소를 입력하세요.", + "biometric_auth_reason": "지문을 스캔하여 인증", "bitcoin_dark_theme": "비트코인 다크 테마", "bitcoin_light_theme": "비트코인 라이트 테마", - "high_contrast_theme": "고대비 테마", - "matrix_green_dark_theme": "매트릭스 그린 다크 테마", - "monero_light_theme": "모네로 라이트 테마", - "manage_nodes": "노드 관리", - "etherscan_history": "이더스캔 역사", - "template_name": "템플릿 이름", - "unsupported_asset": "이 저작물에 대해 이 작업을 지원하지 않습니다. 지원되는 자산 유형의 지갑을 생성하거나 전환하십시오.", - "manage_pow_nodes": "PoW 노드 관리", - "support_title_live_chat": "실시간 지원", - "support_description_live_chat": "자유롭고 빠릅니다! 훈련 된 지원 담당자가 지원할 수 있습니다", - "support_title_guides": "케이크 지갑 가이드", - "support_description_guides": "일반적인 문제에 대한 문서화 및 지원", - "support_title_other_links": "다른 지원 링크", - "support_description_other_links": "다른 방법을 통해 커뮤니티에 가입하거나 파트너에게 연락하십시오.", - "choose_derivation": "지갑 파생을 선택하십시오", - "new_first_wallet_text": "cryptocurrency를 쉽게 안전하게 유지하십시오", - "select_destination": "백업 파일의 대상을 선택하십시오.", - "auto_generate_subaddresses": "자동 생성 서브 아드 드레스", - "save_to_downloads": "다운로드에 저장", - "select_buy_provider_notice": "위의 구매 제공자를 선택하십시오. 앱 설정에서 기본 구매 제공자를 설정 하여이 화면을 건너 뛸 수 있습니다.", - "onramper_option_description": "많은 결제 방법으로 암호화를 신속하게 구입하십시오. 대부분의 국가에서 사용할 수 있습니다. 스프레드와 수수료는 다양합니다.", - "default_buy_provider": "기본 구매 제공자", - "ask_each_time": "매번 물어보십시오", + "bitcoin_payments_require_1_confirmation": "비트코인 결제는 1번의 확인이 필요하며 20분 이상이 소요될 수 있습니다. 기다려 주셔서 감사합니다! 결제가 확인되면 이메일이 전송됩니다.", + "Blocks_remaining": "${status} 남은 블록", + "bright_theme": "선명한", + "buy": "구입", + "buy_alert_content": "현재 Bitcoin, Ethereum, Litecoin 및 Monero 구매만 지원합니다. Bitcoin, Ethereum, Litecoin 또는 Monero 지갑을 생성하거나 전환하십시오.", + "buy_bitcoin": "비트 코인 구매", "buy_provider_unavailable": "제공자는 현재 사용할 수 없습니다.", - "signTransaction": "거래 서명", + "buy_with": "구매", + "by_cake_pay": "Cake Pay로", + "cake_2fa_preset": "케이크 2FA 프리셋", + "cake_pay_account_note": "이메일 주소로 가입하면 카드를 보고 구매할 수 있습니다. 일부는 할인된 가격으로 사용 가능합니다!", + "cake_pay_learn_more": "앱에서 즉시 기프트 카드를 구매하고 사용하세요!\n자세히 알아보려면 왼쪽에서 오른쪽으로 스와이프하세요.", + "cake_pay_subtitle": "할인된 기프트 카드 구매(미국만 해당)", + "cake_pay_title": "케이크 페이 기프트 카드", + "cake_pay_web_cards_subtitle": "전 세계 선불 카드 및 기프트 카드 구매", + "cake_pay_web_cards_title": "케이크페이 웹카드", + "cake_wallet": "Cake Wallet", + "cakepay_prepaid_card": "CakePay 선불 직불 카드", + "camera_consent": "귀하의 카메라는 ${provider}의 식별 목적으로 이미지를 캡처하는 데 사용됩니다. 자세한 내용은 해당 개인정보 보호정책을 확인하세요.", + "camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.", + "cancel": "취소", + "card_address": "주소:", + "cardholder_agreement": "카드 소유자 계약", + "cards": "카드", + "chains": "쇠사슬", + "change": "변화", + "change_backup_password_alert": "이전 백업 파일은 새 백업 암호로 가져올 수 없습니다. 새 백업 암호는 새 백업 파일에만 사용됩니다. 백업 비밀번호를 변경 하시겠습니까?", + "change_currency": "통화 변경", + "change_current_node": "현재 노드를 다음으로 변경 하시겠습니까 ${node}?", + "change_current_node_title": "현재 노드 변경", + "change_exchange_provider": "교환 공급자 변경", + "change_language": "언어 변경", + "change_language_to": "언어를로 변경 ${language}?", + "change_password": "비밀번호 변경", + "change_rep_successful": "대리인이 성공적으로 변경되었습니다", + "change_wallet_alert_content": "현재 지갑을 다음으로 변경 하시겠습니까 ${wallet_name}?", + "change_wallet_alert_title": "현재 지갑 변경", + "choose_account": "계정을 선택하십시오", + "choose_address": "\n\n주소를 선택하십시오:", + "choose_derivation": "지갑 파생을 선택하십시오", + "choose_from_available_options": "사용 가능한 옵션에서 선택:", + "choose_one": "하나 선택", + "choose_relay": "사용할 릴레이를 선택해주세요", + "choose_wallet_currency": "지갑 통화를 선택하십시오:", + "clear": "명확한", + "clearnet_link": "클리어넷 링크", + "close": "닫다", + "coin_control": "코인 제어 (옵션)", + "cold_or_recover_wallet": "콜드 지갑 추가 또는 종이 지갑 복구", + "color_theme": "색상 테마", + "commit_transaction_amount_fee": "커밋 거래\n양: ${amount}\n보수: ${fee}", + "confirm": "확인", + "confirm_delete_template": "이 작업은이 템플릿을 삭제합니다. 계속 하시겠습니까?", + "confirm_delete_wallet": "이 작업은이 지갑을 삭제합니다. 계속 하시겠습니까?", + "confirm_sending": "전송 확인", + "confirmations": "확인", + "confirmed": "확인된 잔액", + "confirmed_tx": "확인", + "congratulations": "축하합니다!", + "connect_an_existing_yat": "기존 Yat 연결", + "connect_yats": "야츠 연결", + "connection_sync": "연결 및 동기화", + "connectWalletPrompt": "거래를 하려면 WalletConnect에 지갑을 연결하세요.", + "contact": "접촉", + "contact_list_contacts": "콘택트 렌즈", + "contact_list_wallets": "내 지갑", + "contact_name": "담당자 이름", + "contact_support": "지원팀에 문의", + "continue_text": "잇다", + "contractName": "계약명", + "contractSymbol": "계약 기호", + "copied_key_to_clipboard": "복사 ${key} 클립 보드로", + "copied_to_clipboard": "클립 보드에 복사", + "copy": "부", + "copy_address": "주소 복사", + "copy_id": "부 ID", + "copyWalletConnectLink": "dApp에서 WalletConnect 링크를 복사하여 여기에 붙여넣으세요.", + "create_account": "계정 만들기", + "create_backup": "백업 생성", + "create_donation_link": "기부 링크 만들기", + "create_invoice": "인보이스 생성", + "create_new": "새 월렛 만들기", + "create_new_account": "새 계정을 만들", + "creating_new_wallet": "새 지갑 생성", + "creating_new_wallet_error": "오류: ${description}", + "creation_date": "생산 일", + "custom": "커스텀", + "custom_drag": "사용자 정의 (홀드 앤 드래그)", + "custom_redeem_amount": "사용자 지정 상환 금액", + "dark_theme": "어두운", + "debit_card": "직불 카드", + "debit_card_terms": "이 디지털 지갑에 있는 귀하의 지불 카드 번호(및 귀하의 지불 카드 번호에 해당하는 자격 증명)의 저장 및 사용은 부터 발효되는 지불 카드 발행자와의 해당 카드 소지자 계약의 이용 약관을 따릅니다. 수시로.", + "decimal_places_error": "소수점 이하 자릿수가 너무 많습니다.", + "default_buy_provider": "기본 구매 제공자", + "default_sell_provider": "기본 판매 공급자", + "delete": "지우다", + "delete_account": "계정 삭제", + "delete_wallet": "지갑 삭제", + "delete_wallet_confirm_message": "${wallet_name} 지갑을 삭제하시겠습니까?", + "deleteConnectionConfirmationPrompt": "다음 연결을 삭제하시겠습니까?", + "descending": "내림차순", + "description": "설명", + "destination_tag": "목적지 태그:", + "dfx_option_description": "EUR 및 CHF로 암호화폐를 구매하세요. 추가 KYC 없이 최대 990€. 유럽의 소매 및 기업 고객용", + "didnt_get_code": "코드를 받지 못하셨습니까?", + "digit_pin": "숫자 PIN", + "digital_and_physical_card": " 디지털 및 실제 선불 직불 카드", + "disable": "장애를 입히다", + "disable_buy": "구매 행동 비활성화", + "disable_cake_2fa": "케이크 2FA 비활성화", + "disable_exchange": "교환 비활성화", + "disable_fiat": "법정화폐 비활성화", + "disable_sell": "판매 조치 비활성화", + "disabled": "장애가 있는", + "discount": "${value}% 절약", + "display_settings": "디스플레이 설정", + "displayable": "표시 가능", + "do_not_have_enough_gas_asset": "현재 블록체인 네트워크 조건으로 거래를 하기에는 ${currency}이(가) 충분하지 않습니다. 다른 자산을 보내더라도 블록체인 네트워크 수수료를 지불하려면 ${currency}가 더 필요합니다.", + "do_not_send": "보내지 마세요", + "do_not_share_warning_text": "지원을 포함하여 다른 사람과 이러한 정보를 공유하지 마십시오.\n\n귀하의 자금은 도난당할 수 있고 도난당할 수 있습니다!", + "do_not_show_me": "나를 다시 표시하지 않음", + "domain_looks_up": "도메인 조회", + "donation_link_details": "기부 링크 세부정보", + "e_sign_consent": "전자 서명 동의", + "edit": "편집하다", + "edit_backup_password": "편집 백업 암호", + "edit_node": "노드 편집", + "edit_token": "토큰 편집", + "electrum_address_disclaimer": "사용할 때마다 새 주소가 생성되지만 이전 주소는 계속 작동합니다.", + "email_address": "이메일 주소", + "enabled": "사용", + "enter_amount": "금액 입력", + "enter_backup_password": "여기에 백업 비밀번호를 입력하세요.", + "enter_code": "코드 입력", + "enter_seed_phrase": "시드 문구를 입력하십시오", + "enter_totp_code": "TOTP 코드를 입력하세요.", + "enter_your_note": "메모를 입력하세요…", + "enter_your_pin": "PIN을 입력하십시오", + "enter_your_pin_again": "다시 핀을 입력", + "enterTokenID": "토큰 ID를 입력하세요", + "enterWalletConnectURI": "WalletConnect URI를 입력하세요.", + "error": "오류", + "error_dialog_content": "죄송합니다. 오류가 발생했습니다.\n\n응용 프로그램을 개선하려면 지원 팀에 충돌 보고서를 보내주십시오.", + "error_text_account_name": "계정 이름은 문자, 숫자 만 포함 할 수 있습니다\n1 ~ 15 자 사이 여야합니다", + "error_text_address": "지갑 주소는 유형과 일치해야합니다\n암호 화폐", + "error_text_amount": "금액은 숫자 만 포함 할 수 있습니다", + "error_text_contact_name": "담당자 이름은 포함 할 수 없습니다 ` , ' \" 기호\n1 자에서 32 자 사이 여야합니다", + "error_text_crypto_currency": "소수 자릿수\n12 이하 여야합니다", + "error_text_fiat": "금액은 사용 가능한 잔액을 초과 할 수 없습니다.\n소수 자릿수는 2보다 작거나 같아야합니다", + "error_text_input_above_maximum_limit": "금액이 최대 값보다 많습니다.", + "error_text_input_below_minimum_limit": "금액이 최소보다 적습니다.", + "error_text_keys": "지갑 키는 16 진수로 64 자만 포함 할 수 있습니다", + "error_text_limits_loading_failed": "거래 ${provider} 가 생성되지 않습니다. 로딩 실패", + "error_text_maximum_limit": "거래 ${provider} 가 생성되지 않습니다. 금액이 최대 값보다 많습니다. ${max} ${currency}", + "error_text_minimal_limit": "거래 ${provider} 가 생성되지 않습니다. 금액이 최소보다 적습니다. ${min} ${currency}", + "error_text_node_address": "iPv4 주소를 입력하십시오", + "error_text_node_port": "노드 포트는 0에서 65535 사이의 숫자 만 포함 할 수 있습니다", + "error_text_node_proxy_address": ":<포트>를 입력하십시오(예: 127.0.0.1:9050).", + "error_text_payment_id": "지불 ID는 16 ~ 64 자의 16 진 문자 만 포함 할 수 있습니다", + "error_text_subaddress_name": "하위 주소 이름은 포함 할 수 없습니다 ` , ' \" 기호 \n1 ~ 20 자 사이 여야합니다", + "error_text_template": "템플릿 이름과 주소는 포함 할 수 없습니다 ` , ' \" 기호 \n1 ~ 106 자 사이 여야합니다", + "error_text_wallet_name": "지갑 이름은 문자, 숫자, _ - 기호만 포함할 수 있습니다.\n1~33자 사이여야 합니다.", + "error_text_xmr": "XMR 값은 사용 가능한 잔액을 초과 할 수 없습니다.\n소수 자릿수는 12 이하 여야합니다", "errorGettingCredentials": "실패: 자격 증명을 가져오는 중 오류가 발생했습니다.", "errorSigningTransaction": "거래에 서명하는 동안 오류가 발생했습니다.", - "pairingInvalidEvent": "잘못된 이벤트 페어링", - "chains": "쇠사슬", - "methods": "행동 양식", - "events": "이벤트", - "reject": "거부하다", - "approve": "승인하다", - "expiresOn": "만료 날짜", - "walletConnect": "월렛커넥트", - "nullURIError": "URI가 null입니다.", - "connectWalletPrompt": "거래를 하려면 WalletConnect에 지갑을 연결하세요.", - "newConnection": "새로운 연결", - "activeConnectionsPrompt": "활성 연결이 여기에 표시됩니다", - "deleteConnectionConfirmationPrompt": "다음 연결을 삭제하시겠습니까?", + "estimated": "예상", + "etherscan_history": "이더스캔 역사", "event": "이벤트", - "successful": "성공적인", - "wouoldLikeToConnect": "연결하고 싶습니다", - "message": "메시지", - "do_not_have_enough_gas_asset": "현재 블록체인 네트워크 조건으로 거래를 하기에는 ${currency}이(가) 충분하지 않습니다. 다른 자산을 보내더라도 블록체인 네트워크 수수료를 지불하려면 ${currency}가 더 필요합니다.", - "totp_auth_url": "TOTP 인증 URL", - "awaitDAppProcessing": "dApp이 처리를 마칠 때까지 기다려주세요.", - "copyWalletConnectLink": "dApp에서 WalletConnect 링크를 복사하여 여기에 붙여넣으세요.", - "enterWalletConnectURI": "WalletConnect URI를 입력하세요.", - "seed_key": "시드 키", - "enter_seed_phrase": "시드 문구를 입력하십시오", - "change_rep_successful": "대리인이 성공적으로 변경되었습니다", - "add_contact": "주소록에 추가", + "events": "이벤트", + "exchange": "교환", + "exchange_incorrect_current_wallet_for_xmr": "Cake Wallet Monero 잔액에서 XMR을 교환하려면 먼저 Monero 지갑으로 전환하십시오.", + "exchange_new_template": "새 템플릿", "exchange_provider_unsupported": "${providerName}은 더 이상 지원되지 않습니다!", - "domain_looks_up": "도메인 조회", - "require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요", - "camera_permission_is_required": "카메라 권한이 필요합니다.\n앱 설정에서 활성화해 주세요.", - "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요.", - "order_by": "주문", - "creation_date": "생산 일", + "exchange_result_confirm": "확인을 누르면 전송됩니다 ${fetchingLabel} ${from} 지갑에서 ${walletName} 아래 주소로. 또는 외부 지갑에서 아래 주소로 보낼 수 있습니다 / QR 코드로 보낼 수 있습니다.\n\n확인을 눌러 계속하거나 금액을 변경하려면 돌아가십시오.", + "exchange_result_description": "다음 페이지에 표시된 주소로 최소 ${fetchingLabel} ${from} 를 보내야합니다. ${fetchingLabel} ${from} 보다 적은 금액을 보내면 변환되지 않고 환불되지 않을 수 있습니다.", + "exchange_result_write_down_ID": "*위에 표시된 ID를 복사하거나 적어 두십시오.", + "exchange_result_write_down_trade_id": "계속하려면 거래 ID를 복사하거나 적어 두십시오..", + "exchange_sync_alert_content": "지갑이 동기화 될 때까지 기다리십시오", + "expired": "만료", + "expires": "만료", + "expiresOn": "만료 날짜", + "export_backup": "백업 내보내기", + "extra_id": "추가 ID:", + "extracted_address_content": "당신은에 자금을 보낼 것입니다\n${recipient_name}", + "failed_authentication": "인증 실패. ${state_error}", + "faq": "FAQ", + "fetching": "가져 오는 중", + "fiat_api": "명목 화폐 API", + "fiat_balance": "피아트 잔액", + "field_required": "이 필드는 필수입니다", + "fill_code": "이메일에 제공된 인증 코드를 입력하세요.", + "filter_by": "필터링 기준", + "first_wallet_text": "Monero, Bitcoin, Ethereum, Litecoin 및 Haven을 위한 멋진 지갑", + "fixed_pair_not_supported": "이 고정 쌍은 선택한 교환에서 지원되지 않습니다.", + "fixed_rate": "고정 비율", + "fixed_rate_alert": "고정 금리 모드 체크시 수취 금액 입력이 가능합니다. 고정 속도 모드로 전환 하시겠습니까?", + "forgot_password": "비밀번호 찾기", + "freeze": "얼다", + "frequently_asked_questions": "자주 묻는 질문", + "frozen": "겨울 왕국", + "full_balance": "풀 밸런스", + "generate_name": "이름 생성", + "generating_gift_card": "기프트 카드 생성 중", + "get_a": "가져오기", + "get_card_note": " 디지털 통화로 충전할 수 있습니다. 추가 정보가 필요하지 않습니다!", + "get_your_yat": "당신의 Yat를 얻으십시오", + "gift_card_amount": "기프트 카드 금액", + "gift_card_balance_note": "잔액이 남아 있는 기프트 카드가 여기에 표시됩니다.", + "gift_card_is_generated": "기프트 카드가 생성되었습니다", + "gift_card_number": "기프트 카드 번호", + "gift_card_redeemed_note": "사용한 기프트 카드가 여기에 표시됩니다.", + "gift_cards": "기프트 카드", + "gift_cards_unavailable": "기프트 카드는 현재 Monero, Bitcoin 및 Litecoin을 통해서만 구매할 수 있습니다.", + "got_it": "알았다", + "gross_balance": "총 잔액", "group_by_type": "유형별 그룹", - "importNFTs": "NFT 가져오기", - "noNFTYet": "아직 NFT가 없습니다", - "address": "주소", - "enterTokenID": "토큰 ID를 입력하세요", - "tokenID": "ID", - "name": "이름", - "symbol": "상징", - "seed_phrase_length": "시드 문구 길이", - "unavailable_balance": "사용할 수 없는 잔액", - "unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.", - "unspent_change": "변화", - "tor_connection": "토르 연결", - "setup_warning_2fa_text": "Cake 2FA는 지갑의 특정 작업에 대한 두 번째 인증입니다. 냉장 보관만큼 안전하지 않습니다.\n\n2FA 앱 또는 TOTP 키에 대한 액세스 권한을 상실하면 이 지갑에 대한 액세스 권한도 잃게 됩니다. 니모닉 시드에서 지갑을 복원해야 합니다.\n\n2FA 또는 니모닉 시드에 액세스할 수 없는 경우 Cake 지원팀에서 도움을 드릴 수 없습니다.\nCake 2FA를 사용하기 전에 가이드를 읽어 보시기 바랍니다.", - "scan_qr_on_device": "다른 기기에서 이 QR 코드를 스캔하세요.", + "haven_app": "Haven by Cake Wallet", + "haven_app_wallet_text": "Awesome wallet for Haven", + "help": "돕다", + "hidden_balance": "숨겨진 균형", + "hide_details": "세부 정보 숨기기", + "high_contrast_theme": "고대비 테마", + "home_screen_settings": "홈 화면 설정", "how_to_use": "사용하는 방법", + "how_to_use_card": "이 카드를 사용하는 방법", + "id": "ID: ", + "ignor": "무시하다", + "import": "수입", + "importNFTs": "NFT 가져오기", + "in_store": "매장 내", + "incoming": "들어오는", + "incorrect_seed": "입력하신 텍스트가 유효하지 않습니다.", + "introducing_cake_pay": "소개 Cake Pay!", + "invalid_input": "잘못된 입력", + "invoice_details": "인보이스 세부정보", + "is_percentage": "이다", + "last_30_days": "지난 30일", + "learn_more": "더 알아보기", + "light_theme": "빛", + "loading_your_wallet": "지갑 넣기", + "login": "로그인", + "logout": "로그아웃", + "low_fee": "낮은 수수료", + "low_fee_alert": "현재 낮은 네트워크 요금 우선 순위를 사용하고 있습니다. 이로 인해 긴 대기 시간, 다른 요금 또는 취소된 거래가 발생할 수 있습니다. 더 나은 경험을 위해 더 높은 요금을 설정하는 것이 좋습니다.", + "manage_nodes": "노드 관리", + "manage_pow_nodes": "PoW 노드 관리", + "manage_yats": "관리하다 Yats", + "mark_as_redeemed": "사용한 것으로 표시", + "market_place": "마켓플레이스", + "matrix_green_dark_theme": "매트릭스 그린 다크 테마", + "max_amount": "최대: ${value}", + "max_value": "맥스: ${value} ${currency}", + "memo": "메모:", + "message": "메시지", + "methods": "행동 양식", + "min_amount": "최소: ${value}", + "min_value": "최소: ${value} ${currency}", + "minutes_to_pin_code": "${minute}분", + "mm": "mm", + "modify_2fa": "수정 케이크 2FA", + "monero_com": "Monero.com by Cake Wallet", + "monero_com_wallet_text": "Awesome wallet for Monero", + "monero_dark_theme": "모네로 다크 테마", + "monero_light_theme": "모네로 라이트 테마", + "moonpay_alert_text": "금액은 다음보다 크거나 같아야합니다 ${minAmount} ${fiatCurrency}", + "more_options": "추가 옵션", + "name": "이름", + "narrow": "좁은", + "new_first_wallet_text": "cryptocurrency를 쉽게 안전하게 유지하십시오", + "new_node_testing": "새로운 노드 테스트", + "new_subaddress_create": "몹시 떠들어 대다", + "new_subaddress_label_name": "라벨 이름", + "new_subaddress_title": "새 주소", + "new_template": "새 템플릿", + "new_wallet": "새 월렛", + "newConnection": "새로운 연결", + "no_id_needed": "ID가 필요하지 않습니다!", + "no_id_required": "신분증이 필요하지 않습니다. 충전하고 어디에서나 사용하세요", + "no_relay_on_domain": "사용자 도메인에 릴레이가 없거나 릴레이를 사용할 수 없습니다. 사용할 릴레이를 선택해주세요.", + "no_relays": "릴레이 없음", + "no_relays_message": "이 사용자에 대한 Nostr NIP-05 레코드를 찾았지만 릴레이가 포함되어 있지 않습니다. 수신자에게 Nostr 기록에 릴레이를 추가하도록 지시하십시오.", + "node_address": "노드 주소", + "node_connection_failed": "연결 실패", + "node_connection_successful": "성공적으로 연결되었습니다.", + "node_new": "새로운 노드", + "node_port": "노드 포트", + "node_reset_settings_title": "설정 초기화", + "node_test": "테스트", + "nodes": "노드", + "nodes_list_reset_to_default_message": "설정을 기본값으로 재설정 하시겠습니까?", + "none_of_selected_providers_can_exchange": "선택한 공급자 중 누구도 이 교환을 할 수 없습니다.", + "noNFTYet": "아직 NFT가 없습니다", + "normal": "정상", + "note_optional": "참고 (선택 사항)", + "note_tap_to_change": "메모 (변경하려면 탭하세요)", + "nullURIError": "URI가 null입니다.", + "offer_expires_in": "쿠폰 만료일: ", + "offline": "오프라인", + "ok": "승인", + "onion_link": "양파 링크", + "online": "온라인", + "onramper_option_description": "많은 결제 방법으로 암호화를 신속하게 구입하십시오. 대부분의 국가에서 사용할 수 있습니다. 스프레드와 수수료는 다양합니다.", + "open_gift_card": "기프트 카드 열기", + "optional_description": "선택적 설명", + "optional_email_hint": "선택적 수취인 알림 이메일", + "optional_name": "선택적 수신자 이름", + "optionally_order_card": "선택적으로 실제 카드를 주문하십시오.", + "orbot_running_alert": "이 노드에 연결하기 전에 Orbot이 실행 중인지 확인하십시오.", + "order_by": "주문", + "order_id": "주문 ID", + "order_physical_card": "물리적 카드 주문", + "other_settings": "기타 설정", + "outdated_electrum_wallet_description": "Cake에서 생성 된 새로운 비트 코인 지갑에는 이제 24 단어 시드가 있습니다. 새로운 비트 코인 지갑을 생성하고 모든 자금을 새로운 24 단어 지갑으로 이체하고 12 단어 시드가있는 지갑 사용을 중지해야합니다. 자금을 확보하려면 즉시이 작업을 수행하십시오.", + "outdated_electrum_wallet_receive_warning": "이 지갑에 12 단어 시드가 있고 Cake에서 생성 된 경우이 지갑에 비트 코인을 입금하지 마십시오. 이 지갑으로 전송 된 모든 BTC는 손실 될 수 있습니다. 새로운 24 단어 지갑을 생성하고 (오른쪽 상단의 메뉴를 탭하고 지갑을 선택한 다음 새 지갑 생성을 선택한 다음 비트 코인을 선택하십시오) 즉시 BTC를 그곳으로 이동하십시오. Cake의 새로운 (24 단어) BTC 지갑은 안전합니다", + "outgoing": "나가는", + "overwrite_amount": "Overwrite amount", + "pairingInvalidEvent": "잘못된 이벤트 페어링", + "password": "암호", + "paste": "풀", + "pause_wallet_creation": "Haven Wallet 생성 기능이 현재 일시 중지되었습니다.", + "payment_id": "지불 ID: ", + "payment_was_received": "결제가 접수되었습니다.", + "pending": " (보류 중)", + "percentageOf": "${amount} 중", + "pin_at_top": "상단에 ${token} 고정", + "pin_is_incorrect": "PIN이 잘못되었습니다", + "pin_number": "PIN 번호", + "placeholder_contacts": "연락처가 여기에 표시됩니다", + "placeholder_transactions": "거래가 여기에 표시됩니다", + "please_fill_totp": "다른 기기에 있는 8자리 코드를 입력하세요.", + "please_make_selection": "아래에서 선택하십시오 지갑 만들기 또는 복구.", + "Please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.", + "please_select": "선택 해주세요:", + "please_select_backup_file": "백업 파일을 선택하고 백업 암호를 입력하십시오.", + "please_try_to_connect_to_another_node": "다른 노드에 연결을 시도하십시오", + "please_wait": "기다리세요", + "polygonscan_history": "다각형 스캔 기록", + "powered_by": "에 의해 구동 ${title}", + "pre_seed_button_text": "이해 했어요. 내 씨앗을 보여줘", + "pre_seed_description": "다음 페이지에서 ${words} 개의 단어를 볼 수 있습니다. 이것은 귀하의 고유하고 개인적인 시드이며 분실 또는 오작동시 지갑을 복구하는 유일한 방법입니다. 기록해두고 Cake Wallet 앱 외부의 안전한 장소에 보관하는 것은 귀하의 책임입니다.", + "pre_seed_title": "중대한", + "prevent_screenshots": "스크린샷 및 화면 녹화 방지", + "privacy": "프라이버시", + "privacy_policy": "개인 정보 보호 정책", + "privacy_settings": "개인정보 설정", + "private_key": "개인 키", + "proceed_after_one_minute": "1분 후에도 화면이 진행되지 않으면 이메일을 확인하세요.", + "profile": "프로필", + "provider_error": "${provider} 오류", + "public_key": "공개 키", + "purchase_gift_card": "기프트 카드 구매", + "qr_fullscreen": "전체 화면 QR 코드를 열려면 탭하세요.", + "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", + "question_to_disable_2fa": "Cake 2FA를 비활성화하시겠습니까? 지갑 및 특정 기능에 액세스하는 데 더 이상 2FA 코드가 필요하지 않습니다.", + "receivable_balance": "채권 잔액", + "receive": "받다", + "receive_amount": "양", + "received": "받았습니다", + "recipient_address": "받는 사람 주소", + "reconnect": "다시 연결", + "reconnect_alert_text": "다시 연결 하시겠습니까?", + "reconnection": "재 연결", + "redeemed": "구함", + "refund_address": "환불 주소", + "reject": "거부하다", + "remaining": "남은", + "remove": "없애다", + "remove_node": "노드 제거", + "remove_node_message": "선택한 노드를 제거 하시겠습니까?", + "rename": "이름 바꾸기", + "require_for_adding_contacts": "연락처 추가에 필요", + "require_for_all_security_and_backup_settings": "모든 보안 및 백업 설정에 필요", + "require_for_assessing_wallet": "지갑 접근을 위해 필요", + "require_for_creating_new_wallets": "새 지갑 생성에 필요", + "require_for_exchanges_to_external_wallets": "외부 지갑으로의 교환을 위해 필요", + "require_for_exchanges_to_internal_wallets": "내부 지갑으로의 교환에 필요", + "require_for_sends_to_contacts": "연락처로 보내기에 필요", + "require_for_sends_to_internal_wallets": "내부 지갑으로 보내는 데 필요", + "require_for_sends_to_non_contacts": "비접촉자에게 보내는 데 필요", + "require_pin_after": "다음 이후에 PIN 필요", + "rescan": "재검색", + "resend_code": "다시 보내주세요", + "reset": "다시 놓기", + "reset_password": "비밀번호 재설정", + "restore_active_seed": "활성 종자", + "restore_address": "주소", + "restore_bitcoin_description_from_keys": "개인 키에서 생성 된 WIF 문자열에서 지갑 복원", + "restore_bitcoin_description_from_seed": "24 단어 조합 코드에서 지갑 복원", + "restore_bitcoin_title_from_keys": "WIF에서 복원", + "restore_description_from_backup": "백업 파일에서 전체 Cake Wallet 앱을 복원 할 수 있습니다.", + "restore_description_from_keys": "개인 키에서 저장된 생성 된 키 스트로크에서 월렛 복원", + "restore_description_from_seed": "25 단어 또는 13 단어 조합 코드에서 지갑을 복원하십시오.", + "restore_description_from_seed_keys": "안전한 장소에 저장 한 종자 / 키로 지갑을 되 찾으십시오.", + "restore_from_date_or_blockheight": "이 지갑을 생성하기 며칠 전에 날짜를 입력하십시오. 또는 블록 높이를 알고있는 경우 대신 입력하십시오.", + "restore_from_seed_placeholder": "여기에 코드 문구를 입력하거나 붙여 넣으십시오.", + "restore_new_seed": "새로운 씨앗", + "restore_next": "다음 것", + "restore_recover": "다시 덮다", + "restore_restore_wallet": "월렛 복원", + "restore_seed_keys_restore": "종자 / 키 복원", + "restore_spend_key_private": "지출 키 (은밀한)", + "restore_title_from_backup": "백업 파일에서 복원", + "restore_title_from_keys": "키에서 복원", + "restore_title_from_seed": "종자에서 복원", + "restore_title_from_seed_keys": "시드 / 키에서 복원", + "restore_view_key_private": "키보기 (은밀한)", + "restore_wallet": "월렛 복원", + "restore_wallet_name": "지갑 이름", + "restore_wallet_restore_description": "월렛 복원 설명", + "router_no_route": "에 정의 된 경로가 없습니다 ${name}", + "save": "구하다", + "save_backup_password": "백업 암호를 저장했는지 확인하십시오. 그것 없이는 백업 파일을 가져올 수 없습니다.", + "save_backup_password_alert": "백업 비밀번호 저장", + "save_to_downloads": "다운로드에 저장", + "saved_the_trade_id": "거래 ID를 저장했습니다", + "scan_qr_code": "QR 코드 스캔", + "scan_qr_code_to_get_address": "QR 코드를 스캔하여 주소를 얻습니다.", + "scan_qr_on_device": "다른 기기에서 이 QR 코드를 스캔하세요.", + "search": "찾다", + "search_add_token": "검색 / 토큰 추가", + "search_category": "검색 카테고리", + "search_currency": "통화 검색", + "search_language": "검색 언어", + "second_intro_content": "귀하의 Yat는 귀하의 모든 통화에 대해 긴 16진수 주소를 모두 대체하는 고유한 단일 이모지 주소입니다.", + "second_intro_title": "그들을 모두 지배하는 하나의 이모티콘 주소", + "security_and_backup": "보안 및 백업", + "seed_alert_back": "돌아 가기", + "seed_alert_content": "씨앗은 지갑을 복구하는 유일한 방법입니다. 적어 보셨나요?", + "seed_alert_title": "주의", + "seed_alert_yes": "네, 있어요", + "seed_choose": "시드 언어를 선택하십시오", "seed_hex_form": "지갑 씨앗 (16 진 양식)", + "seed_key": "시드 키", + "seed_language": "종자 언어", + "seed_language_chinese": "중국말", + "seed_language_chinese_traditional": "중국 전통)", + "seed_language_czech": "체코 사람", + "seed_language_dutch": "네덜란드 사람", + "seed_language_english": "영어", + "seed_language_french": "프랑스 국민", + "seed_language_german": "독일 사람", + "seed_language_italian": "이탈리아 사람", + "seed_language_japanese": "일본어", + "seed_language_korean": "한국인", + "seed_language_next": "다음 것", + "seed_language_portuguese": "포르투갈 인", + "seed_language_russian": "러시아인", + "seed_language_spanish": "스페인의", + "seed_phrase_length": "시드 문구 길이", + "seed_reminder": "휴대 전화를 분실하거나 닦을 경우를 대비해 적어 두세요.", + "seed_share": "시드 공유", + "seed_title": "씨", "seedtype": "시드 타입", "seedtype_legacy": "레거시 (25 단어)", "seedtype_polyseed": "다문 (16 단어)", - "seed_language_czech": "체코 사람", - "seed_language_korean": "한국인", - "seed_language_chinese_traditional": "중국 전통)", - "ascending": "오름차순", - "descending": "내림차순", - "dfx_option_description": "EUR 및 CHF로 암호화폐를 구매하세요. 추가 KYC 없이 최대 990€. 유럽의 소매 및 기업 고객용", - "polygonscan_history": "다각형 스캔 기록", - "wallet_seed_legacy": "레거시 지갑 시드", - "default_sell_provider": "기본 판매 공급자", + "select_backup_file": "백업 파일 선택", + "select_buy_provider_notice": "위의 구매 제공자를 선택하십시오. 앱 설정에서 기본 구매 제공자를 설정 하여이 화면을 건너 뛸 수 있습니다.", + "select_destination": "백업 파일의 대상을 선택하십시오.", "select_sell_provider_notice": "위에서 판매 공급자를 선택하세요. 앱 설정에서 기본 판매 공급자를 설정하면 이 화면을 건너뛸 수 있습니다.", - "custom_drag": "사용자 정의 (홀드 앤 드래그)", + "sell": "팔다", + "sell_alert_content": "현재 Bitcoin, Ethereum 및 Litecoin의 판매만 지원합니다. Bitcoin, Ethereum 또는 Litecoin 지갑을 생성하거나 전환하십시오.", + "sell_monero_com_alert_content": "지원되지 않습니다.", + "send": "보내다", + "send_address": "${cryptoCurrency} 주소", + "send_amount": "양:", + "send_creating_transaction": "거래 생성", + "send_error_currency": "통화는 숫자 만 포함 할 수 있습니다", + "send_error_minimum_value": "금액의 최소값은 0.01입니다", + "send_estimated_fee": "예상 수수료:", + "send_fee": "회비:", + "send_name": "이름", + "send_new": "새로운", + "send_payment_id": "지불 ID (optional)", + "send_priority": "현재 수수료는 ${transactionPriority} 우선 순위.\n거래 우선 순위는 설정에서 조정할 수 있습니다", + "send_sending": "배상...", + "send_success": "${crypto}가 성공적으로 전송되었습니다", + "send_templates": "템플릿", + "send_title": "보내다", + "send_to_this_address": "이 주소로 ${currency} ${tag}송금", + "send_xmr": "보내다 XMR", + "send_your_wallet": "지갑", + "sending": "배상", + "sent": "보냄", + "settings": "설정", + "settings_all": "모든", + "settings_allow_biometrical_authentication": "생체 인증 허용", + "settings_can_be_changed_later": "이 설정은 나중에 앱 설정에서 변경할 수 있습니다.", + "settings_change_language": "언어 변경", + "settings_change_pin": "PIN 변경", + "settings_currency": "통화", + "settings_current_node": "현재 노드", + "settings_dark_mode": "다크 모드", + "settings_display_balance": "디스플레이 잔액", + "settings_display_on_dashboard_list": "대시 보드 목록에 표시", + "settings_fee_priority": "수수료 우선", + "settings_nodes": "노드", + "settings_none": "없음", + "settings_only_trades": "거래 만", + "settings_only_transactions": "거래 만", + "settings_personal": "개인적인", + "settings_save_recipient_address": "수신자 주소 저장", + "settings_support": "지원하다", + "settings_terms_and_conditions": "이용 약관", + "settings_title": "설정", + "settings_trades": "거래", + "settings_transactions": "업무", + "settings_wallets": "지갑", + "setup_2fa": "케이크 2FA 설정", + "setup_2fa_text": "Cake 2FA는 TOTP를 두 번째 인증 요소로 사용하여 작동합니다.\n\nCake 2FA의 TOTP에는 SHA-512 및 8자리 지원이 필요합니다. 이는 보안을 강화합니다. 자세한 정보와 지원되는 앱은 가이드에서 확인할 수 있습니다.", + "setup_pin": "설정 PIN", + "setup_successful": "PIN이 성공적으로 설정되었습니다!", + "setup_totp_recommended": "TOTP 설정", + "setup_warning_2fa_text": "Cake 2FA는 지갑의 특정 작업에 대한 두 번째 인증입니다. 냉장 보관만큼 안전하지 않습니다.\n\n2FA 앱 또는 TOTP 키에 대한 액세스 권한을 상실하면 이 지갑에 대한 액세스 권한도 잃게 됩니다. 니모닉 시드에서 지갑을 복원해야 합니다.\n\n2FA 또는 니모닉 시드에 액세스할 수 없는 경우 Cake 지원팀에서 도움을 드릴 수 없습니다.\nCake 2FA를 사용하기 전에 가이드를 읽어 보시기 바랍니다.", + "setup_your_debit_card": "직불카드 설정", + "share": "공유하다", + "share_address": "주소 공유", + "show_details": "세부정보 표시", + "show_keys": "시드 / 키 표시", + "show_market_place": "마켓플레이스 표시", + "show_seed": "종자 표시", + "sign_up": "가입", + "signTransaction": "거래 서명", + "signup_for_card_accept_terms": "카드에 가입하고 약관에 동의합니다.", + "slidable": "슬라이딩 가능", + "sort_by": "정렬 기준", + "spend_key_private": "지출 키 (은밀한)", + "spend_key_public": "지출 키 (공공의)", + "status": "지위: ", + "subaddress_title": "하위 주소 목록", + "subaddresses": "하위 주소", + "submit_request": "요청을 제출", + "successful": "성공적인", + "support_description_guides": "일반적인 문제에 대한 문서화 및 지원", + "support_description_live_chat": "자유롭고 빠릅니다! 훈련 된 지원 담당자가 지원할 수 있습니다", + "support_description_other_links": "다른 방법을 통해 커뮤니티에 가입하거나 파트너에게 연락하십시오.", + "support_title_guides": "케이크 지갑 가이드", + "support_title_live_chat": "실시간 지원", + "support_title_other_links": "다른 지원 링크", + "sweeping_wallet": "스위핑 지갑", + "sweeping_wallet_alert": "오래 걸리지 않습니다. 이 화면을 떠나지 마십시오. 그렇지 않으면 스웹트 자금이 손실될 수 있습니다.", + "switchToETHWallet": "이더리움 지갑으로 전환한 후 다시 시도해 주세요.", "switchToEVMCompatibleWallet": "EVM 호환 지갑으로 전환 후 다시 시도해 주세요. (이더리움, 폴리곤)", - "receivable_balance": "채권 잔액", - "confirmed_tx": "확인", + "symbol": "상징", + "sync_all_wallets": "모든 지갑 동기화", + "sync_status_attempting_sync": "동기화 시도 중", + "sync_status_connected": "연결됨", + "sync_status_connecting": "연결 중", + "sync_status_failed_connect": "연결 해제", + "sync_status_not_connected": "연결되지 않은", + "sync_status_starting_sync": "동기화 시작", + "sync_status_syncronized": "동기화", + "sync_status_syncronizing": "동기화", + "syncing_wallet_alert_content": "상단에 \"동기화됨\"이라고 표시될 때까지 잔액 및 거래 목록이 완전하지 않을 수 있습니다. 자세히 알아보려면 클릭/탭하세요.", + "syncing_wallet_alert_title": "지갑 동기화 중", + "template": "주형", + "template_name": "템플릿 이름", + "third_intro_content": "Yats는 Cake Wallet 밖에서도 살고 있습니다. 지구상의 모든 지갑 주소는 Yat!", + "third_intro_title": "Yat는 다른 사람들과 잘 놉니다.", + "time": "${minutes}m ${seconds}s", + "tip": "팁:", + "today": "오늘", + "token_contract_address": "토큰 계약 주소", + "token_decimal": "토큰 십진수", + "token_name": "토큰 이름 예: Tether", + "token_symbol": "토큰 기호 예: USDT", + "tokenID": "ID", + "tor_connection": "토르 연결", + "tor_only": "Tor 뿐", + "total_saving": "총 절감액", + "totp_2fa_failure": "잘못된 코드입니다. 다른 코드를 시도하거나 새 비밀 키를 생성하십시오. 8자리 코드와 SHA512를 지원하는 호환되는 2FA 앱을 사용하세요.", + "totp_2fa_success": "성공! 이 지갑에 케이크 2FA가 활성화되었습니다. 지갑 액세스 권한을 잃을 경우를 대비하여 니모닉 시드를 저장하는 것을 잊지 마십시오.", + "totp_auth_url": "TOTP 인증 URL", + "totp_code": "TOTP 코드", + "totp_secret_code": "TOTP 비밀 코드", + "totp_verification_success": "확인 성공!", + "trade_details_copied": "${title} 클립 보드에 복사", + "trade_details_created_at": "에 작성", + "trade_details_fetching": "가져 오는 중", + "trade_details_id": "ID", + "trade_details_pair": "쌍", + "trade_details_provider": "공급자", + "trade_details_state": "상태", + "trade_details_title": "거래 세부 사항", + "trade_for_not_created": "거래 ${title} 생성되지 않습니다.", + "trade_history_title": "무역 역사", + "trade_id": "무역 ID:", + "trade_id_not_found": "무역 ${tradeId} 의 ${title} 찾을 수 없습니다.", + "trade_is_powered_by": "이 거래는 ${provider}", + "trade_not_created": "거래가 생성되지 않았습니다", + "trade_not_found": "거래를 찾을 수 없습니다.", + "trade_state_btc_sent": "보냄", + "trade_state_complete": "완전한", + "trade_state_confirming": "확인 중", + "trade_state_created": "만들어진", + "trade_state_finished": "끝마친", + "trade_state_paid": "유료", + "trade_state_paid_unconfirmed": "미확인 유료", + "trade_state_pending": "대기 중", + "trade_state_timeout": "타임 아웃", + "trade_state_to_be_created": "만들려면", + "trade_state_traded": "거래", + "trade_state_trading": "거래", + "trade_state_underpaid": "미지급", + "trade_state_unpaid": "미지급", + "trades": "거래", + "transaction_details_amount": "양", + "transaction_details_copied": "${title} 클립 보드에 복사", + "transaction_details_date": "날짜", + "transaction_details_fee": "회비", + "transaction_details_height": "신장", + "transaction_details_recipient_address": "받는 사람 주소", "transaction_details_source_address": "소스 주소", - "pause_wallet_creation": "Haven Wallet 생성 기능이 현재 일시 중지되었습니다.", - "contractName": "계약명", - "contractSymbol": "계약 기호", - "description": "설명", - "camera_consent": "귀하의 카메라는 ${provider}의 식별 목적으로 이미지를 캡처하는 데 사용됩니다. 자세한 내용은 해당 개인정보 보호정책을 확인하세요.", - "no_relays": "릴레이 없음", - "choose_relay": "사용할 릴레이를 선택해주세요", - "no_relays_message": "이 사용자에 대한 Nostr NIP-05 레코드를 찾았지만 릴레이가 포함되어 있지 않습니다. 수신자에게 Nostr 기록에 릴레이를 추가하도록 지시하십시오.", - "no_relay_on_domain": "사용자 도메인에 릴레이가 없거나 릴레이를 사용할 수 없습니다. 사용할 릴레이를 선택해주세요." -} + "transaction_details_title": "상세 거래 내역", + "transaction_details_transaction_id": "트랜잭션 ID", + "transaction_key": "거래 키", + "transaction_priority_fast": "빠른", + "transaction_priority_fastest": "가장 빠른", + "transaction_priority_medium": "매질", + "transaction_priority_regular": "정규병", + "transaction_priority_slow": "느린", + "transaction_sent": "거래가 전송되었습니다!", + "transaction_sent_notice": "1분 후에도 화면이 진행되지 않으면 블록 익스플로러와 이메일을 확인하세요.", + "transactions": "업무", + "transactions_by_date": "날짜 별 거래", + "trusted": "신뢰할 수 있는", + "unavailable_balance": "사용할 수 없는 잔액", + "unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.", + "unconfirmed": "확인되지 않은 잔액", + "understand": "이해 했어요", + "unmatched_currencies": "현재 지갑의 통화가 스캔한 QR의 통화와 일치하지 않습니다.", + "unspent_change": "변화", + "unspent_coins_details_title": "사용하지 않은 동전 세부 정보", + "unspent_coins_title": "사용하지 않은 동전", + "unsupported_asset": "이 저작물에 대해 이 작업을 지원하지 않습니다. 지원되는 자산 유형의 지갑을 생성하거나 전환하십시오.", + "upto": "최대 ${value}", + "use": "사용하다 ", + "use_card_info_three": "디지털 카드를 온라인 또는 비접촉식 결제 수단으로 사용하십시오.", + "use_card_info_two": "디지털 화폐가 아닌 선불 계정에 보유하면 자금이 USD로 변환됩니다.", + "use_ssl": "SSL 사용", + "use_suggested": "추천 사용", + "variable_pair_not_supported": "이 변수 쌍은 선택한 교환에서 지원되지 않습니다.", + "verification": "검증", + "verify_with_2fa": "케이크 2FA로 확인", + "version": "버전 ${currentVersion}", + "view_all": "모두 보기", + "view_in_block_explorer": "View in Block Explorer", + "view_key_private": "키보기(은밀한)", + "view_key_public": "키보기 (공공의)", + "view_transaction_on": "View Transaction on ", + "wallet_keys": "지갑 시드 / 키", + "wallet_list_create_new_wallet": "새 월렛 만들기", + "wallet_list_edit_wallet": "지갑 수정", + "wallet_list_failed_to_load": "불러 오지 못했습니다 ${wallet_name} 지갑. ${error}", + "wallet_list_failed_to_remove": "제거하지 못했습니다 ${wallet_name} 지갑. ${error}", + "wallet_list_load_wallet": "지갑로드", + "wallet_list_loading_wallet": "로딩 ${wallet_name} 지갑", + "wallet_list_removing_wallet": "풀이 ${wallet_name} 지갑", + "wallet_list_restore_wallet": "월렛 복원", + "wallet_list_title": "모네로 월렛", + "wallet_list_wallet_name": "지갑 이름", + "wallet_menu": "월렛 메뉴", + "wallet_name": "지갑 이름", + "wallet_name_exists": "해당 이름의 지갑이 이미 존재합니다.", + "wallet_restoration_store_incorrect_seed_length": "시드 길이가 잘못되었습니다", + "wallet_seed": "지갑 시드", + "wallet_seed_legacy": "레거시 지갑 시드", + "wallet_store_monero_wallet": "모네로 월렛", + "walletConnect": "월렛커넥트", + "wallets": "지갑", + "warning": "경고", + "welcome": "환영 에", + "welcome_to_cakepay": "Cake Pay에 오신 것을 환영합니다!", + "widgets_address": "주소", + "widgets_or": "또는", + "widgets_restore_from_blockheight": "블록 높이에서 복원", + "widgets_restore_from_date": "날짜에서 복원", + "widgets_seed": "씨", + "wouoldLikeToConnect": "연결하고 싶습니다", + "write_down_backup_password": "백업 파일 가져 오기에 사용되는 백업 암호를 적어 두십시오.", + "xlm_extra_info": "교환을 위해 XLM 거래를 보낼 때 메모 ID를 지정하는 것을 잊지 마십시오", + "xmr_available_balance": "사용 가능한 잔액", + "xmr_full_balance": "풀 밸런스", + "xmr_hidden": "숨김", + "xmr_to_error": "XMR.TO 오류", + "xmr_to_error_description": "금액이 잘못되었습니다. 소수점 이하 최대 8 자리", + "xrp_extra_info": "교환을 위해 XRP 트랜잭션을 보내는 동안 대상 태그를 지정하는 것을 잊지 마십시오", + "yat": "Yat", + "yat_address": "Yat 주소", + "yat_alert_content": "Cake Wallet 사용자는 이제 독특한 이모티콘 기반 사용자 이름으로 좋아하는 모든 통화를 보내고 받을 수 있습니다.", + "yat_alert_title": "Yat으로 더 쉽게 암호화폐를 보내고 받으십시오.", + "yat_error": "Yat 오류", + "yat_error_content": "이 Yat와 연결된 주소가 없습니다. 다른 Yat 시도", + "yat_popup_content": "이제 Yat(이모티콘 기반의 짧은 사용자 이름)으로 Cake Wallet에서 암호화폐를 보내고 받을 수 있습니다. 설정 화면에서 언제든지 Yats 관리", + "yat_popup_title": "지갑 주소를 이모티콘으로 만들 수 있습니다.", + "yesterday": "어제", + "you_now_have_debit_card": "이제 직불카드가 있습니다.", + "you_pay": "당신이 지불합니다", + "you_will_get": "로 변환하다", + "you_will_send": "다음에서 변환", + "YY": "YY", + "zzzz": "zzzz" +} \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 27c9bdeeb..fecec9f18 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -1,777 +1,778 @@ { - "welcome": "မှကြိုဆိုပါတယ်။", - "cake_wallet": "Cake ပိုက်ဆံအိတ်", - "first_wallet_text": "Monero၊ Bitcoin၊ Ethereum၊ Litecoin နှင့် Haven အတွက် အလွန်ကောင်းမွန်သော ပိုက်ဆံအိတ်", - "please_make_selection": "သင့်ပိုက်ဆံအိတ်ကို ဖန်တီးရန် သို့မဟုတ် ပြန်လည်ရယူရန် အောက်တွင် ရွေးချယ်မှုတစ်ခု ပြုလုပ်ပါ။", - "create_new": "Wallet အသစ်ဖန်တီးပါ။", - "restore_wallet": "ပိုက်ဆံအိတ်ကို ပြန်ယူပါ။", - "monero_com": "Monero.com မှ Cake ပိုက်ဆံအိတ်", - "monero_com_wallet_text": "Monero အတွက် အမိုက်စား ပိုက်ဆံအိတ်", - "haven_app": "ဟေးဗင် ကိတ် ဝေါလက်", - "haven_app_wallet_text": "ဟေဗင်အတွက် အံ့ဩစရာကောင်းတဲ့ ပိုက်ဆံအုံး", - "accounts": "အကောင့်များ", - "edit": "တည်းဖြတ်ပါ။", + "about_cake_pay": "Cake Pay သည် အမေရိကန်ပြည်ထောင်စုရှိ ကုန်သည် 150,000 ကျော်တွင် လက်ဆောင်ကတ်များကို လက်ဆောင်ကတ်များကို အလွယ်တကူ ဝယ်ယူနိုင်စေပါသည်။", "account": "အကောင့်", + "accounts": "အကောင့်များ", + "accounts_subaddresses": "အကောင့်များနှင့် လိပ်စာများ", + "activate": "အသက်သွင်းပါ။", + "active": "အသက်ဝင်သည်။", + "active_cards": "အသက်ဝင်သောကတ်များ", + "activeConnectionsPrompt": "လက်ရှိချိတ်ဆက်မှုများ ဤနေရာတွင် ပေါ်လာပါမည်။", "add": "ထည့်ပါ။", + "add_contact": "အဆက်အသွယ်ထည့်ပါ။", + "add_custom_node": "စိတ်ကြိုက် Node အသစ်ကို ထည့်ပါ။", + "add_custom_redemption": "စိတ်ကြိုက်ရွေးယူမှုကို ထည့်ပါ။", + "add_fund_to_card": "ကတ်များသို့ ကြိုတင်ငွေပေးငွေများ ထည့်ပါ (${value} အထိ)", + "add_new_node": "နှာခေါင်း အသစ်ထည့်ပါ။", + "add_new_word": "စကားလုံးအသစ်ထည့်ပါ။", + "add_receiver": "အခြားလက်ခံသူ ထည့်ပါ (ချန်လှပ်ထားနိုင်သည်)", + "add_secret_code": "သို့မဟုတ် ဤလျှို့ဝှက်ကုဒ်ကို အထောက်အထားစိစစ်ခြင်းအက်ပ်တစ်ခုသို့ ထည့်ပါ။", + "add_tip": "အကြံပြုချက်ထည့်ပါ။", + "add_token_disclaimer_check": "ဂုဏ်သိက္ခာရှိသော အရင်းအမြစ်ကို အသုံးပြု၍ တိုကင်စာချုပ်လိပ်စာနှင့် အချက်အလက်ကို ကျွန်ုပ်အတည်ပြုပြီးဖြစ်သည်။ အန္တရာယ်ရှိသော သို့မဟုတ် မမှန်ကန်သော အချက်အလက်များကို ထည့်သွင်းခြင်းသည် ရန်ပုံငွေများ ဆုံးရှုံးသွားနိုင်သည်။", + "add_token_warning": "လိမ်လည်သူများ ညွှန်ကြားထားသည့်အတိုင်း တိုကင်များကို တည်းဖြတ်ခြင်း သို့မဟုတ် မထည့်ပါနှင့်။\nဂုဏ်သိက္ခာရှိသော အရင်းအမြစ်များဖြင့် အမြဲတမ်း တိုကင်လိပ်စာများကို အတည်ပြုပါ။", + "add_value": "တန်ဖိုးထည့်ပါ။", + "address": "လိပ်စာ", "address_book": "လိပ်စာစာအုပ်", - "contact": "ဆက်သွယ်ရန်", - "please_select": "ကျေးဇူးပြု၍ ရွေးချယ်ပါ-", - "cancel": "မလုပ်တော့", - "ok": "ရလား", - "contact_name": "ဆက်သွယ်ရန်အမည်", - "reset": "ပြန်လည်သတ်မှတ်ပါ။", - "save": "သိမ်းဆည်းပါ။", + "address_book_menu": "လိပ်စာစာအုပ်", + "address_detected": "လိပ်စာကို တွေ့ရှိခဲ့သည်။", + "address_from_domain": "ဤလိပ်စာသည် Unstoppable Domains ရှိ ${domain} မှဖြစ်သည်။", + "address_from_yat": "ဤလိပ်စာသည် Yat ရှိ ${emoji} မှဖြစ်သည်။", + "address_label": "လိပ်စာတံဆိပ်", "address_remove_contact": "အဆက်အသွယ်ကို ဖယ်ရှားပါ။", "address_remove_content": "ရွေးချယ်ထားသောအဆက်အသွယ်ကို ဖယ်ရှားလိုသည်မှာ သေချာပါသလား။", - "authenticated": "အစစ်အမှန်", - "authentication": "စစ်ဆေးခြင်း", - "failed_authentication": "အထောက်အထားစိစစ်ခြင်း မအောင်မြင်ပါ။. ${state_error}", - "wallet_menu": "မီနူး", - "Blocks_remaining": "${status} ဘလောက်များ ကျန်နေပါသည်။", - "please_try_to_connect_to_another_node": "အခြား node သို့ ချိတ်ဆက်ရန် ကြိုးစားပါ။", - "xmr_hidden": "ဝှက်ထားသည်။", - "xmr_available_balance": "လက်ကျန်ငွေ ရရှိနိုင်", - "xmr_full_balance": "မျှတမှု အပြည့်အစုံ", - "send": "ပို့ပါ။", - "receive": "လက်ခံသည်။", - "transactions": "ငွေပေးငွေယူ", - "incoming": "ဝင်လာ", - "outgoing": "အထွက်", - "transactions_by_date": "ရက်စွဲအလိုက် ငွေလွှဲမှုများ", - "trades": "ကုန်သွယ်မှုများ", - "filter_by": "အလိုက် စစ်ထုတ်ပါ။", - "today": "ဒီနေ့", - "yesterday": "မနေ့က", - "received": "ရရှိခဲ့သည်။", - "sent": "ပို့လိုက်ပါတယ်။", - "pending": " (ဆိုင်းငံ့)", - "rescan": "ပြန်စကင်န်လုပ်ပါ။", - "reconnect": "ပြန်လည်ချိတ်ဆက်ပါ။", - "wallets": "ပိုက်ဆံအိတ်", - "show_seed": "မျိုးစေ့ကိုပြပါ။", - "show_keys": "မျိုးစေ့ /သော့များကို ပြပါ။", - "address_book_menu": "လိပ်စာစာအုပ်", - "reconnection": "ပြန်လည်ချိတ်ဆက်မှု", - "reconnect_alert_text": "ပြန်လည်ချိတ်ဆက်လိုသည်မှာ သေချာပါသလား။ ?", - "exchange": "ချိန်းတယ်။", - "clear": "ရှင်းလင်းသော", - "refund_address": "ပြန်အမ်းငွေလိပ်စာ", - "change_exchange_provider": "အပြန်အလှန် လဲလှယ်ရေး ထောက်ပံ့ပေးသူကို ပြောင်းလဲပါ", - "you_will_send": "မှပြောင်းပါ။", - "you_will_get": "သို့ပြောင်းပါ။", - "amount_is_guaranteed": "ရရှိသည့်ပမာဏကို အာမခံပါသည်။", - "amount_is_estimate": "ရရှိသည့်ပမာဏသည် ခန့်မှန်းချက်တစ်ခုဖြစ်သည်။", - "powered_by": "${title} မှ ပံ့ပိုးပေးသည်", - "error": "အမှား", - "estimated": "ခန့်မှန်း", - "min_value": "အနည်းဆုံး- ${value} ${currency}", - "max_value": "အများဆုံး- ${value} ${currency}", - "change_currency": "ငွေကြေးကိုပြောင်းပါ။", - "overwrite_amount": "ပမာဏကို ထပ်ရေးပါ။", - "qr_payment_amount": "ဤ QR ကုဒ်တွင် ငွေပေးချေမှုပမာဏတစ်ခုပါရှိသည်။ လက်ရှိတန်ဖိုးကို ထပ်ရေးလိုပါသလား။", - "copy_id": "ID ကူးယူပါ။", - "exchange_result_write_down_trade_id": "ရှေ့ဆက်ရန် ကုန်သွယ်မှု ID ကို ကူးယူ သို့မဟုတ် ချရေးပါ။", - "trade_id": "ကုန်သွယ်မှု ID:", - "copied_to_clipboard": "ကလစ်ဘုတ်သို့ ကူးယူထားသည်။", - "saved_the_trade_id": "ကုန်သွယ်မှု ID ကို သိမ်းဆည်းပြီးပါပြီ။", - "fetching": "ခေါ်ယူခြင်း။", - "id": "ID:", - "amount": "ပမာဏ:", - "payment_id": "ငွေပေးချေမှု ID:", - "status": "အခြေအနေ:", - "offer_expires_in": "ကမ်းလှမ်းချက် သက်တမ်းကုန်သည်:", - "trade_is_powered_by": "ဤကုန်သွယ်မှုကို ${provider} မှ လုပ်ဆောင်သည်", - "copy_address": "လိပ်စာကို ကူးယူပါ။", - "exchange_result_confirm": "အတည်ပြုချက်ကို နှိပ်ခြင်းဖြင့်၊ သင်သည် ${fetchingLabel} ${from} ဟုခေါ်သော သင့်ပိုက်ဆံအိတ်မှ ${walletName} ကို အောက်ဖော်ပြပါလိပ်စာသို့ ပေးပို့မည်ဖြစ်ပါသည်။ သို့မဟုတ် သင့်ပြင်ပပိုက်ဆံအိတ်မှ အောက်ပါလိပ်စာ/QR ကုဒ်သို့ ပေးပို့နိုင်ပါသည်။\n\nပမာဏများကို ပြောင်းလဲရန် ဆက်လက်လုပ်ဆောင်ရန် သို့မဟုတ် ပြန်သွားရန် အတည်ပြုချက်ကို နှိပ်ပါ။", - "exchange_result_description": "သင်သည် အနည်းဆုံး ${fetchingLabel} ${from} ကို နောက်စာမျက်နှာတွင် ပြသထားသည့် လိပ်စာသို့ ပေးပို့ရပါမည်။ ${fetchingLabel} ${from} ထက်နည်းသော ပမာဏကို ပေးပို့ပါက ၎င်းသည် ပြောင်းလဲ၍မရသည့်အပြင် ပြန်အမ်းမည်မဟုတ်ပါ။", - "exchange_result_write_down_ID": "* ကျေးဇူးပြု၍ အထက်ဖော်ပြပါ သင်၏ ID ကို ကော်ပီ သို့မဟုတ် ရေးမှတ်ပါ။", - "confirm": "အတည်ပြုပါ။", - "confirm_sending": "ပေးပို့အတည်ပြုပါ။", - "commit_transaction_amount_fee": "ငွေလွှဲခြင်း\nပမာဏ- ${amount}\nအခကြေးငွေ- ${fee}", - "sending": "ပေးပို့ခြင်း။", - "transaction_sent": "ငွေပေးချေမှု ပို့ပြီးပါပြီ။!", - "expired": "သက်တမ်းကုန်သွားပြီ", - "time": "${minutes}m ${seconds}s", - "send_xmr": "XMR ပို့ပါ။", - "exchange_new_template": "ပုံစံအသစ်", - "faq": "အမြဲမေးလေ့ရှိသောမေးခွန်းများ", - "enter_your_pin": "သင်၏ PIN ကိုထည့်ပါ။", - "loading_your_wallet": "သင့်ပိုက်ဆံအိတ်ကို ဖွင့်နေသည်။", - "new_wallet": "ပိုက်ဆံအိတ်အသစ်", - "wallet_name": "ပိုက်ဆံအိတ်နာမည", - "continue_text": "ဆက်လက်", - "choose_wallet_currency": "ပိုက်ဆံအိတ်ငွေကြေးကို ရွေးပါ-", - "node_new": "နော်ဒီအသစ်", - "node_address": "နိုဒီ လိပ်စာ", - "node_port": "နော်ဒီဆိပ်ကမ်း", - "login": "လော့ဂ်အင်", - "password": "စကားဝှက်", - "nodes": "ဆုံမှတ်များ", - "node_reset_settings_title": "ဆက်တင်များကို ပြန်လည်သတ်မှတ်ပါ။", - "nodes_list_reset_to_default_message": "ဆက်တင်များကို မူရင်းအတိုင်း ပြန်လည်သတ်မှတ်လိုသည်မှာ သေချာပါသလား။", - "change_current_node": "လက်ရှိ နှာခေါင်း ကို ${node} သို့ ပြောင်းရန် သေချာပါသလား။", - "change": "ပြောင်းလဲပါ။", - "remove_node": "နှာခေါင်း ကို ဖယ်ရှားပါ။", - "remove_node_message": "ရွေးချယ်ထားသော ကုဒ်ကို ဖယ်ရှားလိုသည်မှာ သေချာပါသလား။", - "remove": "ဖယ်ရှားပါ။", - "delete": "ဖျက်ပါ။", - "add_new_node": "နှာခေါင်း အသစ်ထည့်ပါ။", - "change_current_node_title": "လက်ရှိ နှာခေါင်း ကိုပြောင်းပါ။", - "node_test": "စမ်း", - "node_connection_successful": "ချိတ်ဆက်မှု အောင်မြင်ခဲ့သည်။", - "node_connection_failed": "ချိတ်ဆက်မှု မအောင်မြင်ပါ။", - "new_node_testing": "နှာခေါင်း အသစ်စမ်းသပ်ခြင်း။", - "use": "သို့ပြောင်းပါ။", - "digit_pin": "-ဂဏန်း PIN", - "share_address": "လိပ်စာမျှဝေပါ။", - "receive_amount": "ပမာဏ", - "subaddresses": "လိပ်စာများ", "addresses": "လိပ်စာများ", - "scan_qr_code_to_get_address": "လိပ်စာရယူရန် QR ကုဒ်ကို စကင်န်ဖတ်ပါ။", - "qr_fullscreen": "မျက်နှာပြင်အပြည့် QR ကုဒ်ကိုဖွင့်ရန် တို့ပါ။", - "rename": "အမည်ပြောင်းပါ။", - "choose_account": "အကောင့်ကို ရွေးပါ။", - "create_new_account": "အကောင့်အသစ်ဖန်တီးပါ။", - "accounts_subaddresses": "အကောင့်များနှင့် လိပ်စာများ", - "restore_restore_wallet": "ပိုက်ဆံအိတ်ကို ပြန်ယူပါ။", - "restore_title_from_seed_keys": "မျိုးစေ့/သော့များမှ ပြန်လည်ရယူပါ။", - "restore_description_from_seed_keys": "သင့်ပိုက်ဆံအိတ်ကို လုံခြုံသောနေရာတွင် သိမ်းဆည်းထားသော မျိုးစေ့/သော့များမှ ပြန်လည်ရယူပါ။", - "restore_next": "နောက်တစ်ခု", - "restore_title_from_backup": "အရန်သိမ်းခြင်းမှ ပြန်လည်ရယူပါ။", - "restore_description_from_backup": "သင့်အရန်ဖိုင်မှ Cake Wallet အက်ပ်တစ်ခုလုံးကို သင်ပြန်လည်ရယူနိုင်သည်။", - "restore_seed_keys_restore": "မျိုးစေ့/သော့များ ပြန်လည်ရယူပါ။", - "restore_title_from_seed": "မျိုးစေ့မှပြန်လည်ရယူပါ။", - "restore_description_from_seed": "25 စကားလုံး သို့မဟုတ် 13 စကားလုံးပေါင်းစပ်ကုဒ်မှ သင့်ပိုက်ဆံအိတ်ကို ပြန်လည်ရယူပါ။", - "restore_title_from_keys": "သော့များမှ ပြန်လည်ရယူပါ။", - "restore_description_from_keys": "သင့်ကိုယ်ပိုင်သော့များမှ သိမ်းဆည်းထားသော ထုတ်ပေးထားသော သော့ချက်များမှ သင့်ပိုက်ဆံအိတ်ကို ပြန်လည်ရယူပါ။", - "restore_wallet_name": "ပိုက်ဆံအိတ်နာမည်", - "restore_address": "လိပ်စာ", - "restore_view_key_private": "သော့ကိုကြည့်ရန် (သီးသန့်)", - "restore_spend_key_private": "သော့သုံးရန် (သီးသန့်)", - "restore_recover": "ပြန်ယူပါ။", - "restore_wallet_restore_description": "Wallet ပြန်လည်ရယူသည့် ဖော်ပြချက်", - "restore_new_seed": "မျိုးစေ့အသစ်", - "restore_active_seed": "တက်ကြွသောအစေ့", - "restore_bitcoin_description_from_seed": "24 စကားလုံးပေါင်းစပ်ကုဒ်မှ သင့်ပိုက်ဆံအိတ်ကို ပြန်ယူပါ။", - "restore_bitcoin_description_from_keys": "သင့်ကိုယ်ပိုင်သော့များမှ ထုတ်လုပ်ထားသော WIF စာကြောင်းမှ သင့်ပိုက်ဆံအိတ်ကို ပြန်လည်ရယူပါ။", - "restore_bitcoin_title_from_keys": "WIF မှ ပြန်လည်ရယူပါ။", - "restore_from_date_or_blockheight": "ဤပိုက်ဆံအိတ်ကို သင်မဖန်တီးမီ ရက်အနည်းငယ်အလိုတွင် ရက်စွဲတစ်ခု ထည့်သွင်းပါ။ သို့မဟုတ် ဘလော့ခ်ဟိုက် ကို သိပါက ၎င်းအစား ၎င်းကို ထည့်ပါ။", - "seed_reminder": "ကျေးဇူးပြု၍ သင့်ဖုန်းကို ပျောက်ဆုံးသွားပါက သို့မဟုတ် ဖျက်မိပါက ၎င်းတို့ကို ချရေးပါ။", - "seed_title": "မျိုးစေ့", - "seed_share": "မျိုးစေ့မျှဝေပါ။", - "copy": "ကော်ပီ", - "seed_language": "မျိုးစေ့ဘာသာ", - "seed_choose": "မျိုးစေ့ဘာသာစကားကို ရွေးချယ်ပါ။", - "seed_language_next": "နောက်တစ်ခု", - "seed_language_english": "အင်္ဂလိပ်စာ", - "seed_language_chinese": "တရုတ်", - "seed_language_dutch": "ဒတ်ခ်ျ", - "seed_language_german": "ဂျာမန်", - "seed_language_japanese": "ဂျပန်", - "seed_language_portuguese": "ပေါ်တူဂီ", - "seed_language_russian": "ရုရှ", - "seed_language_spanish": "ငပိ", - "seed_language_french": "ပြင်သစ်", - "seed_language_italian": "အီတလီ", - "send_title": "ပို့ပါ။", - "send_your_wallet": "သင့်ပိုက်ဆံအိတ်", - "send_address": "${cryptoCurrency} လိပ်စာ", - "send_payment_id": "ငွေပေးချေမှု ID (ချန်လှပ်ထား)", + "advanced_settings": "အဆင့်မြင့်ချိန်ညှိချက်များ", + "aggressive": "စိတ်အားထက်သန်ခြင်း။", + "agree": "သဘောတူသည်။", + "agree_and_continue": "သဘောတူပြီး ရှေ့ဆက်ပါ။", + "agree_to": "အကောင့်ဖန်တီးခြင်းဖြင့် သင်သည် ဤအရာကို သဘောတူပါသည်။", "all": "အားလုံး", - "send_error_minimum_value": "ပမာဏ၏ အနည်းဆုံးတန်ဖိုးမှာ 0.01 ဖြစ်သည်။", - "send_error_currency": "ငွေကြေးတွင် နံပါတ်များသာ ပါဝင်နိုင်သည်။", - "send_estimated_fee": "ခန့်မှန်းကြေး-", - "send_priority": "လောလောဆယ်အခကြေးငွေကို ${transactionPriority} ဦးစားပေးတွင် သတ်မှတ်ထားပါသည်။\nငွေပေးငွေယူဦးစားပေးကို ဆက်တင်များတွင် ချိန်ညှိနိုင်ပါသည်။", - "send_creating_transaction": "အရောင်းအဝယ်ပြုလုပ်ခြင်း။", - "send_templates": "ပုံစံများ", - "send_new": "အသစ်", - "send_amount": "ပမာဏ-", - "send_fee": "အခကြေးငွေ-", - "send_name": "နာမည်", - "got_it": "ရပြီ", - "send_sending": "ပို့နေသည်...", - "send_success": "သင်၏ ${crypto} ကို အောင်မြင်စွာ ပို့လိုက်ပါပြီ။", - "settings_title": "ဆက်တင်များ", - "settings_nodes": "ဆုံမှတ်များ", - "settings_current_node": "လက်ရှိ node", - "settings_wallets": "ပိုက်ဆံအိတ်", - "settings_display_balance": "ပြသချိန်ခွင်", - "settings_currency": "ငွေကြေး", - "settings_fee_priority": "အခကြေးငွေဦးစားပေး", - "settings_save_recipient_address": "လက်ခံသူလိပ်စာကို သိမ်းဆည်းပါ။", - "settings_personal": "ပုဂ္ဂိုလ်ရေး", - "settings_change_pin": "ပင်နံပါတ်ပြောင်းပါ။", - "settings_change_language": "ဘာသာစကားပြောင်းပါ။", - "settings_allow_biometrical_authentication": "ဇီဝဗေဒဆိုင်ရာ အထောက်အထားစိစစ်ခြင်းကို ခွင့်ပြုပါ။", - "settings_dark_mode": "အမှောင်မုဒ်", - "settings_transactions": "ငွေပေးငွေယူ", - "settings_trades": "ကုန်သွယ်မှုများ", - "settings_display_on_dashboard_list": "ဒက်ရှ်ဘုတ်စာရင်းတွင် ပြသပါ။", - "settings_all": "အားလုံး", - "settings_only_trades": "အရောင်းအဝယ်တွေချည်းပဲ။", - "settings_only_transactions": "အရောင်းအဝယ်များသာ", - "settings_none": "တစ်ခုမှ", - "settings_support": "အထောက်အပံ့", - "settings_terms_and_conditions": "စည်းကမ်းနှင့်သတ်မှတ်ချက်များ", - "pin_is_incorrect": "ပင်နံပါတ် မမှန်ပါ။", - "setup_pin": "ပင်နံပါတ်ကို စနစ်ထည့်သွင်းပါ။", - "enter_your_pin_again": "သင့်ပင်နံပါတ်ကို ထပ်မံထည့်သွင်းပါ။", - "setup_successful": "သင့်ပင်နံပါတ်ကို အောင်မြင်စွာ သတ်မှတ်ပြီးပါပြီ။", - "wallet_keys": "ပိုက်ဆံအိတ် အစေ့/သော့များ", - "wallet_seed": "ပိုက်ဆံအိတ်စေ့", - "private_key": "သီးသန့်သော့", - "public_key": "အများသူငှာသော့", - "view_key_private": "သော့ကိုကြည့်ရန် (သီးသန့်)", - "view_key_public": "သော့ကိုကြည့်ရန် (အများပြည်သူ)", - "spend_key_private": "သော့သုံးရန် (သီးသန့်)", - "spend_key_public": "သုံးစွဲရန်သော့ (အများပြည်သူ)", - "copied_key_to_clipboard": "${key} ကို Clipboard သို့ ကူးယူထားသည်။", - "new_subaddress_title": "လိပ်စာအသစ်", - "new_subaddress_label_name": "အညွှန်းအမည်", - "new_subaddress_create": "ဖန်တီးပါ။", - "address_label": "လိပ်စာတံဆိပ်", - "subaddress_title": "လိပ်စာစာရင်း", - "trade_details_title": "ကုန်သွယ်မှုအသေးစိတ်", - "trade_details_id": "အမှတ်သညာ", - "trade_details_state": "အဆင့်အတန်း", - "trade_details_fetching": "ခေါ်ယူခြင်း။", - "trade_details_provider": "ပံ့ပိုးပေးသူ", - "trade_details_created_at": "တွင်ဖန်တီးခဲ့သည်။", - "trade_details_pair": "တွဲ", - "trade_details_copied": "${title} ကို Clipboard သို့ ကူးယူထားသည်။", - "trade_history_title": "ကုန်သွယ်မှုသမိုင်း", - "transaction_details_title": "ငွေပေးငွေယူအသေးစိတ်", - "transaction_details_transaction_id": "ငွေပေးငွေယူ ID", - "transaction_details_date": "ရက်စွဲ", - "transaction_details_height": "အရပ်အမြင့်", - "transaction_details_amount": "ပမာဏ", - "transaction_details_fee": "ကြေး", - "transaction_details_copied": "${title} ကို Clipboard သို့ ကူးယူထားသည်။", - "transaction_details_recipient_address": "လက်ခံသူလိပ်စာများ", - "wallet_list_title": "Monero ပိုက်ဆံအိတ်", - "wallet_list_create_new_wallet": "Wallet အသစ်ဖန်တီးပါ။", - "wallet_list_edit_wallet": "ပိုက်ဆံအိတ်ကို တည်းဖြတ်ပါ။", - "wallet_list_wallet_name": "ပိုက်ဆံအိတ်နာမည်", - "wallet_list_restore_wallet": "ပိုက်ဆံအိတ်ကို ပြန်ယူပါ။", - "wallet_list_load_wallet": "ပိုက်ဆံအိတ်ကို တင်ပါ။", - "wallet_list_loading_wallet": "${wallet_name} ပိုက်ဆံအိတ်ကို ဖွင့်နေသည်။", - "wallet_list_failed_to_load": "${wallet_name} ပိုက်ဆံအိတ်ကို ဖွင့်၍မရပါ။ ${error}", - "wallet_list_removing_wallet": "${wallet_name} ပိုက်ဆံအိတ်ကို ဖယ်ရှားခြင်း။", - "wallet_list_failed_to_remove": "${wallet_name} ပိုက်ဆံအိတ်ကို ဖယ်ရှား၍မရပါ။ ${error}", - "widgets_address": "လိပ်စာ", - "widgets_restore_from_blockheight": "အမြင့်မှ ပြန်လည်ရယူပါ။", - "widgets_restore_from_date": "ရက်စွဲမှ ပြန်လည်ရယူပါ။", - "widgets_or": "သို့မဟုတ်", - "widgets_seed": "မျိုးစေ့", - "router_no_route": "${name} အတွက် သတ်မှတ်ထားသော လမ်းကြောင်းမရှိပါ", - "error_text_account_name": "အကောင့်အမည်သည် အက္ခရာများ၊ နံပါတ်များသာ ပါဝင်နိုင်သည်\nနှင့် စာလုံးရေ 1 နှင့် 15 ကြားရှိရပါမည်။", - "error_text_contact_name": "အဆက်အသွယ်အမည်တွင် ` , ' \" သင်္ကေတများ မပါဝင်နိုင်ပါ\nနှင့် စာလုံးအရှည် 1 နှင့် 32 ကြားရှိရမည်", - "error_text_address": "Wallet လိပ်စာသည် အမျိုးအစား\no cryptocurrency နှင့် ကိုက်ညီရပါမည်။", - "error_text_node_address": "ကျေးဇူးပြု၍ iPv4 လိပ်စာကို ထည့်ပါ။", - "error_text_node_port": "နော်ဒီဆိပ်ကမ်း တွင် 0 နှင့် 65535 အကြား နံပါတ်များသာ ပါဝင်နိုင်သည်။", - "error_text_node_proxy_address": "ကျေးဇူးပြု၍ :၊ ဥပမာ 127.0.0.1:9050 ထည့်ပါ", - "error_text_payment_id": "ငွေပေးချေမှု ID တွင် hex တွင် စာလုံး 16 လုံးမှ 64 လုံးသာ ပါဝင်နိုင်သည်။", - "error_text_xmr": "XMR တန်ဖိုးသည် ရနိုင်သောလက်ကျန်ကို ကျော်လွန်၍မရပါ။\nအပိုင်းကိန်းဂဏန်းများ သည် 12 နှင့် လျော့နည်းရမည်", - "error_text_fiat": "ပမာဏ၏တန်ဖိုးသည် ရနိုင်သောလက်ကျန်ကို မကျော်လွန်နိုင်ပါ။\nအပိုင်းကိန်းဂဏန်းအရေအတွက်သည် 2 နှင့် လျော့နည်းရမည်", - "error_text_subaddress_name": "လိပ်စာခွဲအမည်တွင် ` , ' \" သင်္ကေတများ မပါဝင်နိုင်ပါ\nနှင့် စာလုံးရေ 1 နှင့် 20 ကြားရှိရမည်", - "error_text_amount": "ပမာဏသည် နံပါတ်များသာ ပါဝင်နိုင်သည်။", - "error_text_wallet_name": "ပိုက်ဆံအိတ်အမည်တွင် စာလုံးများ၊ နံပါတ်များ၊ _ - သင်္ကေတများသာ ပါဝင်နိုင်သည် \n နှင့် စာလုံးအရှည် 1 နှင့် 33 ကြားရှိရမည်", - "error_text_keys": "ပိုက်ဆံအိတ်သော့များတွင် hex တွင် 64 လုံးသာပါဝင်နိုင်သည်။", - "error_text_crypto_currency": "အပိုင်းကိန်းဂဏန်းများ၏ အရေအတွက်\nလျော့နည်းသည် သို့မဟုတ် 12 နှင့် ညီမျှရပါမည်။", - "error_text_minimal_limit": "${provider} အတွက် ကုန်သွယ်မှုကို ဖန်တီးမထားပါ။ ပမာဏသည် အနည်းငယ်ထက်နည်းသည်- ${min} ${currency}", - "error_text_maximum_limit": "${provider} အတွက် ကုန်သွယ်မှုကို ဖန်တီးမထားပါ။ ပမာဏသည် အများဆုံးထက် ပိုများသည်- ${max} ${currency}", - "error_text_limits_loading_failed": "${provider} အတွက် ကုန်သွယ်မှုကို ဖန်တီးမထားပါ။ ကန့်သတ်ချက်များ တင်ခြင်း မအောင်မြင်ပါ။", - "error_text_template": "နမူနာပုံစံအမည်နှင့် လိပ်စာတွင် ` , ' \" သင်္ကေတများ မပါဝင်နိုင်ပါ\nနှင့် စာလုံးအရှည် 1 နှင့် 106 ကြား ရှိရမည်", + "all_trades": "ကုန်သွယ်မှုအားလုံး", + "all_transactions": "အရောင်းအဝယ်အားလုံး", + "alphabetical": "အက္ခရာစဉ်", + "already_have_account": "အကောင့်ရှိပြီးသားလား?", + "always": "အမြဲတမ်း", + "amount": "ပမာဏ:", + "amount_is_estimate": "ရရှိသည့်ပမာဏသည် ခန့်မှန်းချက်တစ်ခုဖြစ်သည်။", + "amount_is_guaranteed": "ရရှိသည့်ပမာဏကို အာမခံပါသည်။", + "and": "နှင့်", + "anonpay_description": "${type} ကို ဖန်တီးပါ။ လက်ခံသူက ${method} ကို ပံ့ပိုးပေးထားသည့် cryptocurrency တစ်ခုခုဖြင့် လုပ်ဆောင်နိုင်ပြီး၊ သင်သည် ဤပိုက်ဆံအိတ်တွင် ရံပုံငွေများ ရရှိမည်ဖြစ်သည်။", + "apk_update": "APK အပ်ဒိတ်", + "approve": "လက်မခံပါ။", + "arrive_in_this_address": "${currency} ${tag}ဤလိပ်စာသို့ ရောက်ရှိပါမည်။", + "ascending": "တက်", + "ask_each_time": "တစ်ခုချင်းစီကိုအချိန်မေးပါ", "auth_store_ban_timeout": "အချိန်ကို ပိတ်ပင်ခြင်း", "auth_store_banned_for": "ပိတ်ပင်ထားသည်။", "auth_store_banned_minutes": " မိနစ်များ", "auth_store_incorrect_password": "ပင်နံပါတ် မှားနေသည်။", - "wallet_store_monero_wallet": "Monero ပိုက်ဆံအိတ်", - "wallet_restoration_store_incorrect_seed_length": "မျိုးစေ့အရှည် မမှန်ပါ။", - "full_balance": "Balance အပြည့်", - "available_balance": "လက်ကျန်ငွေ ရရှိနိုင်", - "hidden_balance": "Hidden Balance", - "sync_status_syncronizing": "ထပ်တူပြုခြင်း။", - "sync_status_syncronized": "ထပ်တူပြုထားသည်။", - "sync_status_not_connected": "မချိတ်ဆက်ပါ။", - "sync_status_starting_sync": "စင့်ခ်လုပ်ခြင်း။", - "sync_status_failed_connect": "အဆက်အသွယ်ဖြတ်ထားသည်။", - "sync_status_connecting": "ချိတ်ဆက်ခြင်း။", - "sync_status_connected": "ချိတ်ဆက်ထားသည်။", - "sync_status_attempting_sync": "ချိန်ကိုက်ခြင်းကို ကြိုးစားနေသည်။", - "transaction_priority_slow": "နှေးနှေး", - "transaction_priority_regular": "ပုံမှန်အစည်းအဝေး", - "transaction_priority_medium": "အလယ်အလတ်", - "transaction_priority_fast": "မြန်သည်။", - "transaction_priority_fastest": "အမြန်ဆုံး", - "trade_for_not_created": "${title} အတွက် ကုန်သွယ်မှုကို ဖန်တီးမထားပါ။", - "trade_not_created": "ကုန်သွယ်မှု မဖန်တီးပါ။", - "trade_id_not_found": "${title} ၏ ${tradeId} ကုန်သွယ်မှုကို ရှာမတွေ့ပါ။", - "trade_not_found": "ကုန်သွယ်မှု မတွေ့။", - "trade_state_pending": "ဆိုင်းငံ့ထားသည်။", - "trade_state_confirming": "အတည်ပြုခြင်း။", - "trade_state_trading": "ရောင်းဝယ်ရေး", - "trade_state_traded": "အရောင်းအဝယ်ဖြစ်ခဲ့သည်။", - "trade_state_complete": "ပြီးအောင်", - "trade_state_to_be_created": "ဖန်တီးဖို့", - "trade_state_unpaid": "အခကြေးငွေမယူရသေး", - "trade_state_underpaid": "ပေးချေမှုနည်းပါးသည်။", - "trade_state_paid_unconfirmed": "အတည်မပြုနိုင်သေးပါ။", - "trade_state_paid": "အခကြေးငွေ", - "trade_state_btc_sent": "Btc ပို့လိုက်ပါတယ်။", - "trade_state_timeout": "ခဏပွဲရပ်ခြင်း", - "trade_state_created": "ဖန်တီးခဲ့သည်။", - "trade_state_finished": "ပြီးပြီ။", - "change_language": "ဘာသာစကားပြောင်းပါ။", - "change_language_to": "ဘာသာစကားကို ${language} သို့ ပြောင်းမလား။", - "paste": "ငါးပိ", - "restore_from_seed_placeholder": "သင့်အစေ့ကို ဤနေရာတွင် ထည့်ပါ သို့မဟုတ် ကူးထည့်ပါ။", - "add_new_word": "စကားလုံးအသစ်ထည့်ပါ။", - "incorrect_seed": "ထည့်သွင်းထားသော စာသားသည် မမှန်ကန်ပါ။", - "biometric_auth_reason": "စစ်မှန်ကြောင်းအထောက်အထားပြရန် သင့်လက်ဗွေကို စကန်ဖတ်ပါ။", - "version": "ဗားရှင်း ${currentVersion}", - "extracted_address_content": "သင်သည် \n${recipient_name} သို့ ရန်ပုံငွေများ ပေးပို့ပါမည်", - "card_address": "လိပ်စာ-", - "buy": "ဝယ်ပါ။", - "sell": "ရောင်း", - "placeholder_transactions": "သင်၏ ငွေပေးငွေယူများကို ဤနေရာတွင် ပြသပါမည်။", - "placeholder_contacts": "သင့်အဆက်အသွယ်များကို ဤနေရာတွင် ပြသပါမည်။", - "template": "ပုံစံခွက်", - "confirm_delete_template": "ဤလုပ်ဆောင်ချက်သည် ဤပုံစံပြားကို ဖျက်လိုက်ပါမည်။ ဆက်လုပ်လိုပါသလား။", - "confirm_delete_wallet": "ဤလုပ်ဆောင်ချက်သည် ဤပိုက်ဆံအိတ်ကို ဖျက်လိုက်ပါမည်။ ဆက်လုပ်လိုပါသလား။", - "change_wallet_alert_title": "လက်ရှိပိုက်ဆံအိတ်ကို ပြောင်းပါ။", - "change_wallet_alert_content": "လက်ရှိပိုက်ဆံအိတ်ကို ${wallet_name} သို့ ပြောင်းလိုပါသလား။", - "creating_new_wallet": "ပိုက်ဆံအိတ်အသစ်ဖန်တီးခြင်း။", - "creating_new_wallet_error": "အမှား- ${description}", - "seed_alert_title": "အာရုံ", - "seed_alert_content": "မျိုးစေ့သည် သင့်ပိုက်ဆံအိတ်ကို ပြန်လည်ရယူရန် တစ်ခုတည်းသောနည်းလမ်းဖြစ်သည်။ ရေးပြီးပြီလား။", - "seed_alert_back": "ပြန်သွားသည်", - "seed_alert_yes": "ဟုတ်ကဲ့၊", - "exchange_sync_alert_content": "သင့်ပိုက်ဆံအိတ်ကို စင့်ခ်လုပ်ထားသည့်အချိန်အထိ စောင့်ပါ။", - "pre_seed_title": "အရေးကြီးသည်။", - "pre_seed_description": "နောက်စာမျက်နှာတွင် ${words} စကားလုံးများ အတွဲလိုက်ကို တွေ့ရပါမည်။ ၎င်းသည် သင်၏ထူးခြားပြီး သီးသန့်မျိုးစေ့ဖြစ်ပြီး ပျောက်ဆုံးခြင်း သို့မဟုတ် ချွတ်ယွင်းမှုရှိပါက သင့်ပိုက်ဆံအိတ်ကို ပြန်လည်ရယူရန် တစ်ခုတည်းသောနည်းလမ်းဖြစ်သည်။ ၎င်းကို Cake Wallet အက်ပ်၏အပြင်ဘက်တွင် လုံခြုံသောနေရာတွင် သိမ်းဆည်းရန်မှာ သင်၏တာဝန်ဖြစ်သည်။", - "pre_seed_button_text": "ကျွန်တော်နားလည်ပါတယ်။ ငါ့အမျိုးအနွယ်ကို ပြလော့", - "xmr_to_error": "XMR.TO အမှား", - "xmr_to_error_description": "ပမာဏ မမှန်ပါ။ ဒဿမအမှတ်ပြီးနောက် ဂဏန်း ၈ လုံးတွင် အများဆုံးကန့်သတ်ချက်", - "provider_error": "${provider} အမှား", - "use_ssl": "SSL ကိုသုံးပါ။", - "trusted": "ယုံတယ်။", - "color_theme": "အရောင်အပြင်အဆင်", - "light_theme": "အလင်း", - "bright_theme": "တောက်ပ", - "dark_theme": "မှောငျမိုကျသော", - "enter_your_note": "သင့်မှတ်စုကို ထည့်ပါ...", - "note_optional": "မှတ်ချက် (ချန်လှပ်ထားနိုင်သည်)", - "note_tap_to_change": "မှတ်ချက် (ပြောင်းလဲရန် တို့ပါ)", - "view_in_block_explorer": "Block Explorer တွင်ကြည့်ရှုပါ။", - "view_transaction_on": "ငွေလွှဲခြင်းကို ဖွင့်ကြည့်ပါ။", - "transaction_key": "ငွေသွင်းငွေထုတ်ကီး", - "confirmations": "အတည်ပြုချက်များ", - "recipient_address": "လက်ခံသူလိပ်စာ", - "extra_id": "အပို ID-", - "destination_tag": "ခရီးဆုံးအမှတ်-", - "memo": "မှတ်စုတို:", - "backup": "မိတ္တူ", - "change_password": "စကားဝှက်ကိုပြောင်းရန်", - "backup_password": "စကားဝှက်ကို အရန်သိမ်းဆည်းပါ။", - "write_down_backup_password": "သင်၏ အရန်ဖိုင်များကို တင်သွင်းရန်အတွက် အသုံးပြုသည့် သင်၏ အရန်စကားဝှက်ကို ချရေးပါ။", - "export_backup": "အရန်ကူးထုတ်ရန်", - "save_backup_password": "သင်၏ အရန်စကားဝှက်ကို သိမ်းဆည်းထားကြောင်း သေချာပါစေ။ ၎င်းမပါဘဲ သင်၏ အရန်ဖိုင်များကို တင်သွင်းနိုင်မည် မဟုတ်ပါ။", - "backup_file": "အရန်ဖိုင်", - "edit_backup_password": "Backup Password ကို တည်းဖြတ်ပါ။", - "save_backup_password_alert": "အရန်စကားဝှက်ကို သိမ်းဆည်းပါ။", - "change_backup_password_alert": "အရန်စကားဝှက်အသစ်ဖြင့် သင်၏ယခင်မိတ္တူဖိုင်များကို တင်သွင်းရန် မရနိုင်ပါ။ အရန်စကားဝှက်အသစ်ကို အရန်ဖိုင်အသစ်အတွက်သာ အသုံးပြုပါမည်။ အရန်စကားဝှက်ကို ပြောင်းလိုသည်မှာ သေချာပါသလား။", - "enter_backup_password": "အရန်စကားဝှက်ကို ဤနေရာတွင် ထည့်ပါ။", - "select_backup_file": "အရန်ဖိုင်ကို ရွေးပါ။", - "import": "သွင်းကုန်", - "please_select_backup_file": "အရန်ဖိုင်ကို ရွေးပြီး အရန်စကားဝှက်ကို ထည့်ပါ။", - "fixed_rate": "ပုံသေနှုန်း", - "fixed_rate_alert": "ပုံသေနှုန်းထားမုဒ်ကို စစ်ဆေးသည့်အခါ လက်ခံပမာဏကို ထည့်သွင်းနိုင်မည်ဖြစ်သည်။ ပုံသေနှုန်းမုဒ်သို့ ပြောင်းလိုပါသလား။", - "xlm_extra_info": "လဲလှယ်မှုအတွက် XLM ငွေလွှဲပို့နေစဉ် Memo ID ကို သတ်မှတ်ရန် မမေ့ပါနှင့်", - "xrp_extra_info": "လဲလှယ်မှုအတွက် XRP ငွေလွှဲပို့နေစဉ် Destination Tag ကို သတ်မှတ်ရန် မမေ့ပါနှင့်", - "exchange_incorrect_current_wallet_for_xmr": "သင်၏ Cake Wallet Monero လက်ကျန်မှ XMR ကိုလဲလှယ်လိုပါက၊ သင်၏ Monero ပိုက်ဆံအိတ်သို့ ဦးစွာပြောင်းပါ။", - "confirmed": "အတည်ပြုထားသော လက်ကျန်ငွေ", - "unconfirmed": "အတည်မပြုနိုင်သော လက်ကျန်ငွေ", - "displayable": "ပြသနိုင်သည်။", - "submit_request": "တောင်းဆိုချက်တစ်ခုတင်ပြပါ။", - "buy_alert_content": "လက်ရှိတွင် ကျွန်ုပ်တို့သည် Bitcoin၊ Ethereum၊ Litecoin နှင့် Monero တို့ကိုသာ ဝယ်ယူမှုကို ပံ့ပိုးပေးပါသည်။ သင်၏ Bitcoin၊ Ethereum၊ Litecoin သို့မဟုတ် Monero ပိုက်ဆံအိတ်ကို ဖန်တီးပါ သို့မဟုတ် ပြောင်းပါ။", - "sell_alert_content": "ကျွန်ုပ်တို့သည် လက်ရှိတွင် Bitcoin၊ Ethereum နှင့် Litecoin ရောင်းချခြင်းကိုသာ ပံ့ပိုးပေးပါသည်။ သင်၏ Bitcoin၊ Ethereum သို့မဟုတ် Litecoin ပိုက်ဆံအိတ်ကို ဖန်တီးပါ သို့မဟုတ် ပြောင်းပါ။", - "outdated_electrum_wallet_description": "ယခု Cake တွင်ဖန်တီးထားသော Bitcoin ပိုက်ဆံအိတ်အသစ်တွင် စကားလုံး 24 မျိုးရှိသည်။ Bitcoin ပိုက်ဆံအိတ်အသစ်တစ်ခုကို ဖန်တီးပြီး သင့်ငွေအားလုံးကို 24 စကားလုံးပိုက်ဆံအိတ်အသစ်သို့ လွှဲပြောင်းပြီး 12 စကားလုံးမျိုးစေ့ဖြင့် ပိုက်ဆံအိတ်များကို အသုံးပြုခြင်းကို ရပ်တန့်ရန် မဖြစ်မနေလိုအပ်ပါသည်။ သင့်ရန်ပုံငွေများကို လုံခြုံစေရန်အတွက် ၎င်းကိုချက်ချင်းလုပ်ဆောင်ပါ။", - "understand": "ကျွန်တော်နားလည်ပါတယ်", - "apk_update": "APK အပ်ဒိတ်", - "buy_bitcoin": "Bitcoin ကိုဝယ်ပါ။", - "buy_with": "အတူဝယ်ပါ။", - "moonpay_alert_text": "ပမာဏ၏တန်ဖိုးသည် ${minAmount} ${fiatCurrency} နှင့် ပိုနေရမည်", - "outdated_electrum_wallet_receive_warning": "ဤပိုက်ဆံအိတ်တွင် စာလုံး 12 လုံးပါပြီး ကိတ်မုန့်တွင် ဖန်တီးပါက၊ Bitcoin ကို ဤပိုက်ဆံအိတ်ထဲသို့ မထည့်ပါနှင့်။ ဤပိုက်ဆံအိတ်သို့ လွှဲပြောင်းပေးသည့် မည်သည့် BTC မဆို ဆုံးရှုံးနိုင်သည်။ 24 စကားလုံးပိုက်ဆံအိတ်အသစ်တစ်ခုဖန်တီးပါ (ညာဘက်အပေါ်ထောင့်ရှိမီနူးကိုနှိပ်ပါ၊ Wallets ကိုရွေးချယ်ပါ၊ ပိုက်ဆံအိတ်အသစ်ဖန်တီးရန်ကိုရွေးချယ်ပါ၊ ထို့နောက် Bitcoin ကိုရွေးချယ်ပါ) နှင့်သင်၏ BTC ကိုထိုနေရာသို့ချက်ချင်းရွှေ့ပါ။ Cake မှ (24 စာလုံး) BTC ပိုက်ဆံအိတ်အသစ်များသည် လုံခြုံပါသည်။", - "do_not_show_me": "ဒါကို ထပ်မပြနဲ့", - "unspent_coins_title": "အသုံးမဝင်သော အကြွေစေ့များ", - "unspent_coins_details_title": "အသုံးမဝင်သော အကြွေစေ့အသေးစိတ်များ", - "freeze": "အေးခဲ", - "frozen": "ဖြူဖြူ", - "coin_control": "အကြွေစေ့ထိန်းချုပ်မှု (ချန်လှပ်ထားနိုင်သည်)", - "address_detected": "လိပ်စာကို တွေ့ရှိခဲ့သည်။", - "address_from_domain": "ဤလိပ်စာသည် Unstoppable Domains ရှိ ${domain} မှဖြစ်သည်။", - "add_receiver": "အခြားလက်ခံသူ ထည့်ပါ (ချန်လှပ်ထားနိုင်သည်)", - "manage_yats": "Yats ကို စီမံပါ။", - "yat_alert_title": "Yat ဖြင့် crypto ကိုပိုမိုလွယ်ကူစွာပေးပို့လက်ခံပါ။", - "yat_alert_content": "Cake Wallet အသုံးပြုသူများသည် တစ်မျိုးတည်းသော အီမိုဂျီအခြေခံအသုံးပြုသူအမည်ဖြင့် ၎င်းတို့၏ စိတ်ကြိုက်ငွေကြေးအားလုံးကို ပေးပို့နိုင်ပါပြီ။", - "get_your_yat": "မင်းရဲ့ Yat ကိုယူလိုက်ပါ။", - "connect_an_existing_yat": "ရှိပြီးသား Yat ကို ချိတ်ဆက်ပါ။", - "connect_yats": "Yats ကိုချိတ်ဆက်ပါ။", - "yat_address": "Yat လိပ်စာ", - "yat": "ယတ်", - "address_from_yat": "ဤလိပ်စာသည် Yat ရှိ ${emoji} မှဖြစ်သည်။", - "yat_error": "Yat အမှား", - "yat_error_content": "ဤ Yat နှင့် ချိတ်ဆက်ထားသော လိပ်စာမရှိပါ။ နောက်ထပ် Yat စမ်းကြည့်ပါ။", - "choose_address": "\n\nလိပ်စာကို ရွေးပါ-", - "yat_popup_title": "သင့်ပိုက်ဆံအိတ်လိပ်စာကို emojified လုပ်နိုင်ပါသည်။", - "yat_popup_content": "သင်၏ Yat - တိုတောင်းသော အီမိုဂျီအခြေခံအသုံးပြုသူအမည်ဖြင့် Cake Wallet တွင် crypto ကို ယခု ပေးပို့နိုင်ပါပြီ။ ဆက်တင်စခရင်ပေါ်တွင် Yats ကို အချိန်မရွေး စီမံခန့်ခွဲပါ။", - "second_intro_title": "၎င်းတို့အားလုံးကို အုပ်ချုပ်ရန် အီမိုဂျီလိပ်စာတစ်ခု", - "second_intro_content": "သင်၏ Yat သည် သင့်ငွေကြေးအားလုံးအတွက် သင်၏ ရှည်လျားသော ဆဋ္ဌမကိန်းဂဏန်းများအားလုံးကို အစားထိုးသည့် တစ်မူထူးခြားသော အီမိုဂျီလိပ်စာတစ်ခုဖြစ်သည်။", - "third_intro_title": "Yat သည် အခြားသူများနှင့် ကောင်းစွာကစားသည်။", - "third_intro_content": "Yats သည် Cake Wallet အပြင်ဘက်တွင် နေထိုင်ပါသည်။ ကမ္ဘာပေါ်ရှိ မည်သည့်ပိုက်ဆံအိတ်လိပ်စာကို Yat ဖြင့် အစားထိုးနိုင်ပါသည်။", - "learn_more": "ပိုမိုသိရှိရန်", - "search": "ရှာရန်", - "search_language": "ဘာသာစကားရှာပါ။", - "search_currency": "ငွေကြေးကိုရှာပါ။", - "new_template": "ပုံစံအသစ်", - "electrum_address_disclaimer": "သင်အသုံးပြုသည့်အချိန်တိုင်းတွင် ကျွန်ုပ်တို့သည် လိပ်စာအသစ်များကို ထုတ်ပေးသော်လည်း ယခင်လိပ်စာများသည် ဆက်လက်အလုပ်လုပ်နေပါသည်။", - "wallet_name_exists": "ထိုအမည်ဖြင့် ပိုက်ဆံအိတ်တစ်ခု ရှိနှင့်ပြီးဖြစ်သည်။ အခြားအမည်တစ်ခုကို ရွေးပါ သို့မဟုတ် အခြားပိုက်ဆံအိတ်ကို ဦးစွာ အမည်ပြောင်းပါ။", - "market_place": "ဈေး", - "cake_pay_title": "ကိတ်မုန့်လက်ဆောင်ကတ်များ", - "cake_pay_subtitle": "လျှော့စျေးလက်ဆောင်ကတ်များဝယ်ပါ (USA သာ)", - "cake_pay_web_cards_title": "Cake Pay ဝဘ်ကတ်များ", - "cake_pay_web_cards_subtitle": "ကမ္ဘာတစ်ဝှမ်း ကြိုတင်ငွေပေးကတ်များနှင့် လက်ဆောင်ကတ်များကို ဝယ်ယူပါ။", - "about_cake_pay": "Cake Pay သည် အမေရိကန်ပြည်ထောင်စုရှိ ကုန်သည် 150,000 ကျော်တွင် လက်ဆောင်ကတ်များကို လက်ဆောင်ကတ်များကို အလွယ်တကူ ဝယ်ယူနိုင်စေပါသည်။", - "cake_pay_account_note": "ကတ်များကြည့်ရှုဝယ်ယူရန် အီးမေးလ်လိပ်စာတစ်ခုဖြင့် စာရင်းသွင်းပါ။ အချို့ကို လျှော့ဈေးဖြင့်ပင် ရနိုင်သည်။", - "already_have_account": "အကောင့်ရှိပြီးသားလား?", - "create_account": "အကောင့်ပြုလုပ်ပါ", - "privacy_policy": "ကိုယ်ရေးအချက်အလက်မူဝါဒ", - "welcome_to_cakepay": "Cake Pay မှကြိုဆိုပါသည်။", - "sign_up": "ဆိုင်းအပ်", - "forgot_password": "စကားဝှက်မေ့နေပါသလား", - "reset_password": "လျှို့ဝှတ်နံပါတ်အားမူလအတိုင်းပြန်လုပ်သည်", - "gift_cards": "လက်ဆောင်ကဒ်ပြား", - "setup_your_debit_card": "သင့်ဒက်ဘစ်ကတ်ကို စနစ်ထည့်သွင်းပါ။", - "no_id_required": "ID မလိုအပ်ပါ။ ငွေဖြည့်ပြီး ဘယ်နေရာမဆို သုံးစွဲပါ။", - "how_to_use_card": "ဒီကတ်ကို ဘယ်လိုသုံးမလဲ။", - "purchase_gift_card": "လက်ဆောင်ကတ်ဝယ်ပါ။", - "verification": "စိစစ်ခြင်း။", - "fill_code": "သင့်အီးမေးလ်သို့ ပေးထားသည့် အတည်ပြုကုဒ်ကို ဖြည့်ပါ။", - "didnt_get_code": "ကုဒ်ကို မရဘူးလား?", - "resend_code": "ကျေးဇူးပြု၍ ပြန်ပို့ပါ။", - "debit_card": "ဒက်ဘစ်ကတ်", - "cakepay_prepaid_card": "CakePay ကြိုတင်ငွေဖြည့်ဒက်ဘစ်ကတ်", - "no_id_needed": "ID မလိုအပ်ပါ။", - "frequently_asked_questions": "မေးလေ့ရှိသောမေးခွန်းများ", - "debit_card_terms": "ဤဒစ်ဂျစ်တယ်ပိုက်ဆံအိတ်ရှိ သင့်ငွေပေးချေမှုကတ်နံပါတ် (နှင့် သင့်ငွေပေးချေကတ်နံပါတ်နှင့် သက်ဆိုင်သောအထောက်အထားများ) ၏ သိုလှောင်မှုနှင့် အသုံးပြုမှုသည် အချိန်အခါနှင့်အမျှ သက်ရောက်မှုရှိသကဲ့သို့ ကတ်ကိုင်ဆောင်ထားသူ၏ သဘောတူညီချက်၏ စည်းကမ်းသတ်မှတ်ချက်များနှင့် ကိုက်ညီပါသည်။", - "please_reference_document": "နောက်ထပ်အချက်အလက်များအတွက် အောက်ပါစာရွက်စာတမ်းများကို ကိုးကားပါ။", - "cardholder_agreement": "ကတ်ကိုင်ဆောင်သူ သဘောတူညီချက်", - "e_sign_consent": "E-Sign သဘောတူညီချက်", - "agree_and_continue": "သဘောတူပြီး ရှေ့ဆက်ပါ။", - "email_address": "အီးမေးလ်လိပ်စာ", - "agree_to": "အကောင့်ဖန်တီးခြင်းဖြင့် သင်သည် ဤအရာကို သဘောတူပါသည်။", - "and": "နှင့်", - "enter_code": "ကုဒ်ထည့်ပါ။", - "congratulations": "ဂုဏ်ယူပါသည်။", - "you_now_have_debit_card": "ယခု သင့်တွင် ဒက်ဘစ်ကတ်တစ်ခုရှိသည်။", - "min_amount": "အနည်းဆုံး- ${value}", - "max_amount": "အများဆုံး- ${value}", - "enter_amount": "ပမာဏကို ထည့်ပါ။", - "billing_address_info": "ငွေပေးချေရမည့်လိပ်စာကို တောင်းဆိုပါက သင့်ပို့ဆောင်ရေးလိပ်စာကို ပေးပါ။", - "order_physical_card": "ရုပ်ပိုင်းဆိုင်ရာကတ်ကို မှာယူပါ။", - "add_value": "တန်ဖိုးထည့်ပါ။", - "activate": "အသက်သွင်းပါ။", - "get_a": "တစ်ခုရယူပါ။", - "digital_and_physical_card": " ဒစ်ဂျစ်တယ်နှင့် ရုပ်ပိုင်းဆိုင်ရာ ကြိုတင်ငွေပေးချေသော ဒက်ဘစ်ကတ်", - "get_card_note": " ဒစ်ဂျစ်တယ်ငွေကြေးများဖြင့် ပြန်လည်စတင်နိုင်သည်။ နောက်ထပ် အချက်အလက် မလိုအပ်ပါ။", - "signup_for_card_accept_terms": "ကတ်အတွက် စာရင်းသွင်းပြီး စည်းကမ်းချက်များကို လက်ခံပါ။", - "add_fund_to_card": "ကတ်များသို့ ကြိုတင်ငွေပေးငွေများ ထည့်ပါ (${value} အထိ)", - "use_card_info_two": "ဒစ်ဂျစ်တယ်ငွေကြေးများဖြင့်မဟုတ်ဘဲ ကြိုတင်ငွေပေးချေသည့်အကောင့်တွင် သိမ်းထားသည့်အခါ ရန်ပုံငွေများကို USD သို့ ပြောင်းလဲပါသည်။", - "use_card_info_three": "ဒစ်ဂျစ်တယ်ကတ်ကို အွန်လိုင်း သို့မဟုတ် ထိတွေ့မှုမဲ့ ငွေပေးချေမှုနည်းလမ်းများဖြင့် အသုံးပြုပါ။", - "optionally_order_card": "ရုပ်ပိုင်းဆိုင်ရာကတ်ကို ရွေးချယ်နိုင်သည် ။", - "hide_details": "အသေးစိတ်ကို ဝှက်ပါ။", - "show_details": "အသေးစိတ်ပြ", - "upto": "${value} အထိ", - "discount": "${value}% ချွေတာ", - "gift_card_amount": "လက်ဆောင်ကတ် ပမာဏ", - "bill_amount": "ဘီလ်ပမာဏ", - "you_pay": "သင်ပေးချေပါ။", - "tip": "အကြံပြုချက်-", - "custom": "စိတ်ကြိုက်", - "by_cake_pay": "Cake Pay ဖြင့်", - "expires": "သက်တမ်းကုန်သည်။", - "mm": "MM", - "yy": "YY", - "online": "အွန်လိုင်း", - "offline": "အော့ဖ်လိုင်း", - "gift_card_number": "လက်ဆောင်ကတ်နံပါတ်", - "pin_number": "လျှို့ဝှက်နံပါတ်", - "total_saving": "စုစုပေါင်းစုဆောင်းငွေ", - "last_30_days": "လွန်ခဲ့သော ရက် 30", - "avg_savings": "ပျမ်းမျှ စုဆောင်းငွေ", - "view_all": "အားလုံးကိုကြည့်ရှုပါ။", - "active_cards": "အသက်ဝင်သောကတ်များ", - "delete_account": "အကောင့်ဖျက်ပါ။", - "cards": "ကတ်များ", - "active": "အသက်ဝင်သည်။", - "redeemed": "ရွေးနှုတ်ခဲ့သည်။", - "gift_card_balance_note": "လက်ကျန်လက်ကျန်ရှိသည့် လက်ဆောင်ကတ်များ ဤနေရာတွင် ပေါ်လာပါမည်။", - "gift_card_redeemed_note": "သင်ရွေးယူထားသော လက်ဆောင်ကတ်များ ဤနေရာတွင် ပေါ်လာပါမည်။", - "logout": "ထွက်လိုက်ပါ။", - "add_tip": "အကြံပြုချက်ထည့်ပါ။", - "percentageOf": "${amount} ၏", - "is_percentage": "သည်", - "search_category": "ရှာဖွေမှုအမျိုးအစား", - "mark_as_redeemed": "ရွေးနှုတ်ခြင်းအဖြစ် အမှတ်အသားပြုပါ။", - "more_options": "နောက်ထပ် ရွေးချယ်စရာများ", - "awaiting_payment_confirmation": "ငွေပေးချေမှု အတည်ပြုချက်ကို စောင့်မျှော်နေပါသည်။", - "transaction_sent_notice": "မျက်နှာပြင်သည် ၁ မိနစ်အကြာတွင် ဆက်လက်မလုပ်ဆောင်ပါက၊ ပိတ်ဆို့ရှာဖွေသူနှင့် သင့်အီးမေးလ်ကို စစ်ဆေးပါ။", - "agree": "သဘောတူသည်။", - "in_store": "စတိုးတွင်", - "generating_gift_card": "လက်ဆောင်ကတ်ထုတ်ပေးခြင်း။", - "payment_was_received": "သင့်ငွေပေးချေမှုကို လက်ခံရရှိခဲ့သည်။", - "proceed_after_one_minute": "မျက်နှာပြင်သည် ၁ မိနစ်အကြာတွင် ဆက်လက်မလုပ်ဆောင်ပါက သင့်အီးမေးလ်ကို စစ်ဆေးပါ။", - "order_id": "မှာယူမှု ID", - "gift_card_is_generated": "Gift Card ထုတ်ပေးပါသည်။", - "open_gift_card": "Gift Card ကိုဖွင့်ပါ။", - "contact_support": "ပံ့ပိုးကူညီမှုထံ ဆက်သွယ်ပါ။", - "gift_cards_unavailable": "လက်ဆောင်ကတ်များကို ယခုအချိန်တွင် Monero၊ Bitcoin နှင့် Litecoin တို့ဖြင့်သာ ဝယ်ယူနိုင်ပါပြီ။", - "introducing_cake_pay": "Cake Pay ကို မိတ်ဆက်ခြင်း။", - "cake_pay_learn_more": "အက်ပ်ရှိ လက်ဆောင်ကတ်များကို ချက်ချင်းဝယ်ယူပြီး ကူပွန်ဖြင့် လဲလှယ်ပါ။\nပိုမိုလေ့လာရန် ဘယ်မှညာသို့ ပွတ်ဆွဲပါ။", + "authenticated": "အစစ်အမှန်", + "authentication": "စစ်ဆေးခြင်း", + "auto_generate_subaddresses": "အော်တို Generate Subaddresses", "automatic": "အလိုအလျောက်", - "fixed_pair_not_supported": "ရွေးချယ်ထားသော ဖလှယ်မှုများဖြင့် ဤပုံသေအတွဲကို ပံ့ပိုးမထားပါ။", - "variable_pair_not_supported": "ရွေးချယ်ထားသော ဖလှယ်မှုများဖြင့် ဤပြောင်းလဲနိုင်သောအတွဲကို ပံ့ပိုးမထားပါ။", - "none_of_selected_providers_can_exchange": "ရွေးချယ်ထားသော ဝန်ဆောင်မှုပေးသူများမှ ဤလဲလှယ်မှုကို ပြုလုပ်၍မရပါ။", - "choose_one": "တစ်ခုရွေးပါ။", - "choose_from_available_options": "ရနိုင်သောရွေးချယ်မှုများမှ ရွေးပါ-", - "custom_redeem_amount": "စိတ်ကြိုက်သုံးငွေပမာဏ", - "add_custom_redemption": "စိတ်ကြိုက်ရွေးယူမှုကို ထည့်ပါ။", - "remaining": "ကျန်", - "delete_wallet": "ပိုက်ဆံအိတ်ကို ဖျက်ပါ။", - "delete_wallet_confirm_message": "${wallet_name} ပိုက်ဆံအိတ်ကို ဖျက်လိုသည်မှာ သေချာပါသလား။", - "low_fee": "အနိမ့်ကြေး", - "low_fee_alert": "သင်သည် လက်ရှိတွင် သက်သာသော ကွန်ရက်အခကြေးငွေဦးစားပေးကို အသုံးပြုနေပါသည်။ ၎င်းသည် အကြာကြီးစောင့်ဆိုင်းခြင်း၊ မတူညီသောနှုန်းထားများ သို့မဟုတ် ပယ်ဖျက်ထားသော ကုန်သွယ်မှုများကို ဖြစ်စေနိုင်သည်။ ပိုမိုကောင်းမွန်သော အတွေ့အကြုံအတွက် ပိုမိုမြင့်မားသော အခကြေးငွေ သတ်မှတ်ပေးရန် အကြံပြုအပ်ပါသည်။", - "ignor": "လျစ်လျူရှုပါ။", - "use_suggested": "အကြံပြုထားသည်ကို အသုံးပြုပါ။", - "do_not_share_warning_text": "ပံ့ပိုးကူညီမှုအပါအဝင် ဤအရာများကို အခြားမည်သူနှင့်မျှ မမျှဝေပါနှင့်။\n\nသင့်ငွေများကို ခိုးယူခံရနိုင်သည်!", - "help": "ကူညီပါ", - "all_transactions": "အရောင်းအဝယ်အားလုံး", - "all_trades": "ကုန်သွယ်မှုအားလုံး", - "connection_sync": "ချိတ်ဆက်မှုနှင့် ထပ်တူပြုခြင်း။", - "security_and_backup": "လုံခြုံရေးနှင့် မိတ္တူ", - "create_backup": "အရန်သိမ်းခြင်းကို ဖန်တီးပါ။", - "privacy_settings": "Privacy settings တွေကို", - "privacy": "ကိုယ်ရေးကိုယ်တာ", - "display_settings": "ပြသရန် ဆက်တင်များ", - "other_settings": "အခြားဆက်တင်များ", - "require_pin_after": "ပြီးနောက် PIN လိုအပ်ပါသည်။", - "always": "အမြဲတမ်း", - "minutes_to_pin_code": "${minute} မိနစ်", - "disable_exchange": "လဲလှယ်မှုကို ပိတ်ပါ။", - "advanced_settings": "အဆင့်မြင့်ချိန်ညှိချက်များ", - "settings_can_be_changed_later": "အက်ပ်ဆက်တင်များတွင် ဤဆက်တင်များကို နောက်ပိုင်းတွင် ပြောင်းလဲနိုင်သည်။", - "add_custom_node": "စိတ်ကြိုက် Node အသစ်ကို ထည့်ပါ။", - "disable_fiat": "Fiat ကိုပိတ်ပါ။", - "fiat_api": "Fiat API", - "disabled": "မသန်စွမ်း", - "enabled": "ဖွင့်ထားသည်။", - "tor_only": "Tor သာ", - "unmatched_currencies": "သင့်လက်ရှိပိုက်ဆံအိတ်၏ငွေကြေးသည် စကင်ဖတ်ထားသော QR နှင့် မကိုက်ညီပါ။", - "orbot_running_alert": "ဤ node သို့မချိတ်ဆက်မီ Orbot အလုပ်လုပ်နေကြောင်း သေချာပါစေ။", - "contact_list_contacts": "အဆက်အသွယ်များ", - "contact_list_wallets": "ကျွန်ုပ်၏ ပိုက်ဆံအိတ်များ", - "bitcoin_payments_require_1_confirmation": "Bitcoin ငွေပေးချေမှုများသည် မိနစ် 20 သို့မဟုတ် ထို့ထက်ပိုကြာနိုင်သည် 1 အတည်ပြုချက် လိုအပ်သည်။ မင်းရဲ့စိတ်ရှည်မှုအတွက် ကျေးဇူးတင်ပါတယ်။ ငွေပေးချေမှုကို အတည်ပြုပြီးသောအခါ သင့်ထံ အီးမေးလ်ပို့ပါမည်။", - "send_to_this_address": "ဤလိပ်စာသို့ ${currency} ${tag}သို့ ပို့ပါ။", - "arrive_in_this_address": "${currency} ${tag}ဤလိပ်စာသို့ ရောက်ရှိပါမည်။", - "do_not_send": "မပို့ပါနှင့်", - "error_dialog_content": "အိုး၊ ကျွန်ုပ်တို့တွင် အမှားအယွင်းအချို့ရှိသည်။\n\nအပလီကေးရှင်းကို ပိုမိုကောင်းမွန်စေရန်အတွက် ပျက်စီးမှုအစီရင်ခံစာကို ကျွန်ုပ်တို့၏ပံ့ပိုးကူညီရေးအဖွဲ့ထံ ပေးပို့ပါ။", - "scan_qr_code": "QR ကုဒ်ကို စကင်န်ဖတ်ပါ။", - "cold_or_recover_wallet": "အေးသောပိုက်ဆံအိတ်ထည့်ပါ သို့မဟုတ် စက္ကူပိုက်ဆံအိတ်ကို ပြန်ယူပါ။", - "please_wait": "ကျေးဇူးပြုပြီးခဏစောင့်ပါ", - "sweeping_wallet": "ိုက်ဆံအိတ် တံမြက်လှည်း", - "sweeping_wallet_alert": "ဒါက ကြာကြာမခံသင့်ပါဘူး။ ဤစခရင်ကို ချန်မထားပါနှင့် သို့မဟုတ် ထုတ်ယူထားသော ရန်ပုံငွေများ ဆုံးရှုံးနိုင်သည်", - "decimal_places_error": "ဒဿမနေရာများ များလွန်းသည်။", - "edit_node": "Node ကို တည်းဖြတ်ပါ။", - "invoice_details": "ပြေစာအသေးစိတ်", - "donation_link_details": "လှူဒါန်းရန်လင့်ခ်အသေးစိတ်", - "anonpay_description": "${type} ကို ဖန်တီးပါ။ လက်ခံသူက ${method} ကို ပံ့ပိုးပေးထားသည့် cryptocurrency တစ်ခုခုဖြင့် လုပ်ဆောင်နိုင်ပြီး၊ သင်သည် ဤပိုက်ဆံအိတ်တွင် ရံပုံငွေများ ရရှိမည်ဖြစ်သည်။", - "create_invoice": "ပြေစာဖန်တီးပါ။", - "create_donation_link": "လှူဒါန်းမှုလင့်ခ်ကို ဖန်တီးပါ။", - "optional_email_hint": "ရွေးချယ်နိုင်သော ငွေလက်ခံသူ အကြောင်းကြားချက် အီးမေးလ်", - "optional_description": "ရွေးချယ်နိုင်သော ဖော်ပြချက်", - "optional_name": "ရွေးချယ်နိုင်သော လက်ခံသူအမည်", - "clearnet_link": "Clearnet လင့်ခ်", - "onion_link": "ကြက်သွန်လင့်", - "settings": "ဆက်တင်များ", - "sell_monero_com_alert_content": "Monero ရောင်းချခြင်းကို မပံ့ပိုးရသေးပါ။", - "error_text_input_below_minimum_limit": "ပမာဏသည် အနိမ့်ဆုံးထက်နည်းသည်။", - "error_text_input_above_maximum_limit": "ပမာဏသည် အများဆုံးထက် ပိုများသည်။", - "show_market_place": "စျေးကွက်ကိုပြသပါ။", - "prevent_screenshots": "ဖန်သားပြင်ဓာတ်ပုံများနှင့် မျက်နှာပြင်ရိုက်ကူးခြင်းကို တားဆီးပါ။", - "profile": "ကိုယ်ရေးအကျဉ်း", - "close": "အနီးကပ်", - "modify_2fa": "ကိတ်မုန့် 2FA ကို ပြင်ဆင်ပါ။", - "disable_cake_2fa": "ကိတ်မုန့် 2FA ကို ပိတ်ပါ။", - "question_to_disable_2fa": "Cake 2FA ကို ပိတ်လိုသည်မှာ သေချာပါသလား။ ပိုက်ဆံအိတ်နှင့် အချို့သောလုပ်ဆောင်ချက်များကို အသုံးပြုရန်အတွက် 2FA ကုဒ်တစ်ခု မလိုအပ်တော့ပါ။", - "disable": "ပိတ်ပါ။", - "setup_2fa": "ကိတ်မုန့် 2FA စနစ်ထည့်သွင်းပါ။", - "verify_with_2fa": "Cake 2FA ဖြင့် စစ်ဆေးပါ။", - "totp_code": "TOTP ကုဒ်", - "please_fill_totp": "သင့်အခြားစက်တွင်ရှိသော ဂဏန်း ၈ လုံးကုဒ်ကို ကျေးဇူးပြု၍ ဖြည့်ပါ။", - "totp_2fa_success": "အောင်မြင် ဤပိုက်ဆံအိတ်အတွက် ကိတ်မုန့် 2FA ကို ဖွင့်ထားသည်။ ပိုက်ဆံအိတ်ဝင်ရောက်ခွင့်ဆုံးရှုံးသွားသောအခါတွင် သင်၏ mnemonic မျိုးစေ့များကို သိမ်းဆည်းရန် မမေ့ပါနှင့်။", - "totp_verification_success": "အတည်ပြုခြင်း အောင်မြင်ပါသည်။", - "totp_2fa_failure": "ကုဒ်မမှန်ပါ။ ကျေးဇူးပြု၍ အခြားကုဒ်တစ်ခုကို စမ်းကြည့်ပါ သို့မဟုတ် လျှို့ဝှက်သော့အသစ်တစ်ခု ဖန်တီးပါ။ ဂဏန်း ၈ လုံးကုဒ်များနှင့် SHA512 ကို ပံ့ပိုးပေးသည့် တွဲဖက်အသုံးပြုနိုင်သော 2FA အက်ပ်ကို အသုံးပြုပါ။", - "enter_totp_code": "ကျေးဇူးပြု၍ TOTP ကုဒ်ကို ထည့်ပါ။", - "add_secret_code": "သို့မဟုတ် ဤလျှို့ဝှက်ကုဒ်ကို အထောက်အထားစိစစ်ခြင်းအက်ပ်တစ်ခုသို့ ထည့်ပါ။", - "totp_secret_code": "TOTP လျှို့ဝှက်ကုဒ်", - "setup_2fa_text": "ကိတ်မုန့် 2FA သည် TOTP ကို ဒုတိယ စစ်မှန်ကြောင်းအထောက်အထားအဖြစ် အသုံးပြု၍ လုပ်ဆောင်သည်။\n\nကိတ်မုန့် 2FA ၏ TOTP သည် SHA-512 နှင့် 8 ဂဏန်းပံ့ပိုးမှု လိုအပ်သည်။ ဒါက လုံခြုံရေးကို တိုးမြှင့်ပေးတယ်။ နောက်ထပ်အချက်အလက်များနှင့် ပံ့ပိုးပေးထားသောအက်ပ်များကို လမ်းညွှန်တွင် တွေ့နိုင်ပါသည်။", - "setup_totp_recommended": "TOTP စနစ်ထည့်သွင်းပါ။", - "disable_buy": "ဝယ်ယူမှု လုပ်ဆောင်ချက်ကို ပိတ်ပါ။", - "disable_sell": "ရောင်းချခြင်းလုပ်ဆောင်ချက်ကို ပိတ်ပါ။", - "cake_2fa_preset": "ကိတ်မုန့် 2FA ကြိုတင်သတ်မှတ်", - "narrow": "ကျဉ်းသော", - "normal": "ပုံမှန်", - "aggressive": "စိတ်အားထက်သန်ခြင်း။", - "require_for_assessing_wallet": "ပိုက်ဆံအိတ်ကို ဝင်သုံးရန် လိုအပ်သည်။", - "require_for_sends_to_non_contacts": "အဆက်အသွယ်မရှိသူများထံ ပေးပို့ရန် လိုအပ်သည်။", - "require_for_sends_to_contacts": "အဆက်အသွယ်များထံ ပေးပို့ရန် လိုအပ်သည်။", - "require_for_sends_to_internal_wallets": "အတွင်းပိုင်း ပိုက်ဆံအိတ်များသို့ ပေးပို့ရန် လိုအပ်သည်။", - "require_for_exchanges_to_internal_wallets": "အတွင်းပိုင်းပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", - "require_for_adding_contacts": "အဆက်အသွယ်များထည့်ရန် လိုအပ်သည်။", - "require_for_creating_new_wallets": "ပိုက်ဆံအိတ်အသစ်များ ဖန်တီးရန် လိုအပ်သည်။", - "require_for_all_security_and_backup_settings": "လုံခြုံရေးနှင့် အရန်ဆက်တင်များအားလုံးအတွက် လိုအပ်ပါသည်။", + "available_balance": "လက်ကျန်ငွေ ရရှိနိုင်", "available_balance_description": "သင့်ရဲ့ အကောင့်တွင် ရရှိနိုင်သော ငွေကျန်ငွေကို ပြန်လည်ပေးသွင်းပါ။", - "syncing_wallet_alert_title": "သင့်ပိုက်ဆံအိတ်ကို စင့်ခ်လုပ်နေပါသည်။", - "syncing_wallet_alert_content": "သင်၏လက်ကျန်နှင့် ငွေပေးငွေယူစာရင်းသည် ထိပ်တွင် \"Synchronizeed\" ဟုပြောသည်အထိ မပြီးမြောက်နိုင်ပါ။ ပိုမိုလေ့လာရန် နှိပ်/နှိပ်ပါ။", - "home_screen_settings": "ပင်မစခရင် ဆက်တင်များ", - "sort_by": "အလိုက်စဥ်သည်", - "search_add_token": "ရှာဖွေရန် / တိုကင်ထည့်ပါ။", - "edit_token": "တိုကင်ကို တည်းဖြတ်ပါ။", - "warning": "သတိပေးချက်", - "add_token_warning": "လိမ်လည်သူများ ညွှန်ကြားထားသည့်အတိုင်း တိုကင်များကို တည်းဖြတ်ခြင်း သို့မဟုတ် မထည့်ပါနှင့်။\nဂုဏ်သိက္ခာရှိသော အရင်းအမြစ်များဖြင့် အမြဲတမ်း တိုကင်လိပ်စာများကို အတည်ပြုပါ။", - "add_token_disclaimer_check": "ဂုဏ်သိက္ခာရှိသော အရင်းအမြစ်ကို အသုံးပြု၍ တိုကင်စာချုပ်လိပ်စာနှင့် အချက်အလက်ကို ကျွန်ုပ်အတည်ပြုပြီးဖြစ်သည်။ အန္တရာယ်ရှိသော သို့မဟုတ် မမှန်ကန်သော အချက်အလက်များကို ထည့်သွင်းခြင်းသည် ရန်ပုံငွေများ ဆုံးရှုံးသွားနိုင်သည်။", - "token_contract_address": "တိုကင်စာချုပ်လိပ်စာ", - "token_name": "တိုကင်အမည် ဥပမာ- Tether", - "token_symbol": "တိုကင်သင်္ကေတ ဥပမာ- USDT", - "token_decimal": "တိုကင်ဒဿမ", - "field_required": "ဤစာကွက်လပ်မှာဖြည့်ရန်လိုအပ်ပါသည်", - "pin_at_top": "အပေါ်တွင် ${token} ပင်ထိုးပါ။", - "invalid_input": "ထည့်သွင်းမှု မမှန်ကန်ပါ။", - "fiat_balance": "Fiat Balance", - "gross_balance": "စုစုပေါင်းလက်ကျန်ငွေ", - "alphabetical": "အက္ခရာစဉ်", - "generate_name": "အမည်ဖန်တီးပါ။", + "avg_savings": "ပျမ်းမျှ စုဆောင်းငွေ", + "awaitDAppProcessing": "ကျေးဇူးပြု၍ dApp ကို စီမံလုပ်ဆောင်ခြင်း အပြီးသတ်ရန် စောင့်ပါ။", + "awaiting_payment_confirmation": "ငွေပေးချေမှု အတည်ပြုချက်ကို စောင့်မျှော်နေပါသည်။", + "backup": "မိတ္တူ", + "backup_file": "အရန်ဖိုင်", + "backup_password": "စကားဝှက်ကို အရန်သိမ်းဆည်းပါ။", "balance_page": "လက်ကျန်စာမျက်နှာ", - "share": "မျှဝေပါ။", - "slidable": "လျှောချနိုင်သည်။", - "monero_dark_theme": "Monero Dark အပြင်အဆင်", + "bill_amount": "ဘီလ်ပမာဏ", + "billing_address_info": "ငွေပေးချေရမည့်လိပ်စာကို တောင်းဆိုပါက သင့်ပို့ဆောင်ရေးလိပ်စာကို ပေးပါ။", + "biometric_auth_reason": "စစ်မှန်ကြောင်းအထောက်အထားပြရန် သင့်လက်ဗွေကို စကန်ဖတ်ပါ။", "bitcoin_dark_theme": "Bitcoin Dark Theme", "bitcoin_light_theme": "Bitcoin Light အပြင်အဆင်", - "high_contrast_theme": "အလင်းအမှောင် မြင့်မားသော အပြင်အဆင်", - "matrix_green_dark_theme": "Matrix Green Dark အပြင်အဆင်", - "monero_light_theme": "Monero Light အပြင်အဆင်", - "manage_nodes": "ဆုံမှတ်များကို စီမံပါ။", - "etherscan_history": "Etherscan သမိုင်း", - "template_name": "နမူနာပုံစံ", + "bitcoin_payments_require_1_confirmation": "Bitcoin ငွေပေးချေမှုများသည် မိနစ် 20 သို့မဟုတ် ထို့ထက်ပိုကြာနိုင်သည် 1 အတည်ပြုချက် လိုအပ်သည်။ မင်းရဲ့စိတ်ရှည်မှုအတွက် ကျေးဇူးတင်ပါတယ်။ ငွေပေးချေမှုကို အတည်ပြုပြီးသောအခါ သင့်ထံ အီးမေးလ်ပို့ပါမည်။", + "Blocks_remaining": "${status} ဘလောက်များ ကျန်နေပါသည်။", + "bright_theme": "တောက်ပ", + "buy": "ဝယ်ပါ။", + "buy_alert_content": "လက်ရှိတွင် ကျွန်ုပ်တို့သည် Bitcoin၊ Ethereum၊ Litecoin နှင့် Monero တို့ကိုသာ ဝယ်ယူမှုကို ပံ့ပိုးပေးပါသည်။ သင်၏ Bitcoin၊ Ethereum၊ Litecoin သို့မဟုတ် Monero ပိုက်ဆံအိတ်ကို ဖန်တီးပါ သို့မဟုတ် ပြောင်းပါ။", + "buy_bitcoin": "Bitcoin ကိုဝယ်ပါ။", + "buy_provider_unavailable": "လက်ရှိတွင်လက်ရှိမရနိုင်ပါ။", + "buy_with": "အတူဝယ်ပါ။", + "by_cake_pay": "Cake Pay ဖြင့်", + "cake_2fa_preset": "ကိတ်မုန့် 2FA ကြိုတင်သတ်မှတ်", + "cake_pay_account_note": "ကတ်များကြည့်ရှုဝယ်ယူရန် အီးမေးလ်လိပ်စာတစ်ခုဖြင့် စာရင်းသွင်းပါ။ အချို့ကို လျှော့ဈေးဖြင့်ပင် ရနိုင်သည်။", + "cake_pay_learn_more": "အက်ပ်ရှိ လက်ဆောင်ကတ်များကို ချက်ချင်းဝယ်ယူပြီး ကူပွန်ဖြင့် လဲလှယ်ပါ။\nပိုမိုလေ့လာရန် ဘယ်မှညာသို့ ပွတ်ဆွဲပါ။", + "cake_pay_subtitle": "လျှော့စျေးလက်ဆောင်ကတ်များဝယ်ပါ (USA သာ)", + "cake_pay_title": "ကိတ်မုန့်လက်ဆောင်ကတ်များ", + "cake_pay_web_cards_subtitle": "ကမ္ဘာတစ်ဝှမ်း ကြိုတင်ငွေပေးကတ်များနှင့် လက်ဆောင်ကတ်များကို ဝယ်ယူပါ။", + "cake_pay_web_cards_title": "Cake Pay ဝဘ်ကတ်များ", + "cake_wallet": "Cake ပိုက်ဆံအိတ်", + "cakepay_prepaid_card": "CakePay ကြိုတင်ငွေဖြည့်ဒက်ဘစ်ကတ်", + "camera_consent": "မှတ်ပုံတင်ခြင်းရည်ရွယ်ချက်များအတွက် ${provider} တွင် သင့်ကင်မရာကို အသုံးပြုပါမည်။ အသေးစိတ်အတွက် ၎င်းတို့၏ ကိုယ်ရေးကိုယ်တာမူဝါဒကို စစ်ဆေးပါ။", + "camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။", + "cancel": "မလုပ်တော့", + "card_address": "လိပ်စာ-", + "cardholder_agreement": "ကတ်ကိုင်ဆောင်သူ သဘောတူညီချက်", + "cards": "ကတ်များ", + "chains": "ဆွဲကြိုး", + "change": "ပြောင်းလဲပါ။", + "change_backup_password_alert": "အရန်စကားဝှက်အသစ်ဖြင့် သင်၏ယခင်မိတ္တူဖိုင်များကို တင်သွင်းရန် မရနိုင်ပါ။ အရန်စကားဝှက်အသစ်ကို အရန်ဖိုင်အသစ်အတွက်သာ အသုံးပြုပါမည်။ အရန်စကားဝှက်ကို ပြောင်းလိုသည်မှာ သေချာပါသလား။", + "change_currency": "ငွေကြေးကိုပြောင်းပါ။", + "change_current_node": "လက်ရှိ နှာခေါင်း ကို ${node} သို့ ပြောင်းရန် သေချာပါသလား။", + "change_current_node_title": "လက်ရှိ နှာခေါင်း ကိုပြောင်းပါ။", + "change_exchange_provider": "အပြန်အလှန် လဲလှယ်ရေး ထောက်ပံ့ပေးသူကို ပြောင်းလဲပါ", + "change_language": "ဘာသာစကားပြောင်းပါ။", + "change_language_to": "ဘာသာစကားကို ${language} သို့ ပြောင်းမလား။", + "change_password": "စကားဝှက်ကိုပြောင်းရန်", "change_rep": "ကိုယ်စားလှယ်ပြောင်းပါ။", "change_rep_message": "ကိုယ်စားလှယ်ပြောင်းလိုသည်မှာ သေချာပါသလား။", - "unsupported_asset": "ဤပိုင်ဆိုင်မှုအတွက် ဤလုပ်ဆောင်ချက်ကို ကျွန်ုပ်တို့ မပံ့ပိုးပါ။ ကျေးဇူးပြု၍ ပံ့ပိုးပေးထားသော ပိုင်ဆိုင်မှုအမျိုးအစား၏ ပိုက်ဆံအိတ်ကို ဖန်တီးပါ သို့မဟုတ် ပြောင်းပါ။", - "manage_pow_nodes": "PoW Nodes ကို စီမံပါ။", - "support_title_live_chat": "တိုက်ရိုက်ပံ့ပိုးမှု", - "support_description_live_chat": "အခမဲ့နှင့်အစာရှောင်ခြင်း! လေ့ကျင့်ထားသောထောက်ခံသူကိုယ်စားလှယ်များသည်ကူညီနိုင်သည်", - "support_title_guides": "ကိတ်မုန့်ပိုက်ဆံအိတ်လမ်းညွှန်များ", - "support_description_guides": "ဘုံပြ issues နာများအတွက်စာရွက်စာတမ်းများနှင့်ထောက်ခံမှု", - "support_title_other_links": "အခြားအထောက်အပံ့လင့်များ", - "support_description_other_links": "ကျွန်ုပ်တို့၏လူမှုအသိုင်းအဝိုင်းများသို့ 0 င်ရောက်ပါ", + "change_rep_successful": "အောင်မြင်စွာကိုယ်စားလှယ်ပြောင်းလဲသွားတယ်", + "change_wallet_alert_content": "လက်ရှိပိုက်ဆံအိတ်ကို ${wallet_name} သို့ ပြောင်းလိုပါသလား။", + "change_wallet_alert_title": "လက်ရှိပိုက်ဆံအိတ်ကို ပြောင်းပါ။", + "choose_account": "အကောင့်ကို ရွေးပါ။", + "choose_address": "\n\nလိပ်စာကို ရွေးပါ-", "choose_derivation": "ပိုက်ဆံအိတ်ကိုရွေးချယ်ပါ", - "new_first_wallet_text": "သင့်ရဲ့ cryptocurrencrencres ကိုအလွယ်တကူလုံခြုံစွာထားရှိပါ", - "select_destination": "အရန်ဖိုင်အတွက် ဦးတည်ရာကို ရွေးပါ။", - "auto_generate_subaddresses": "အော်တို Generate Subaddresses", - "save_to_downloads": "ဒေါင်းလုဒ်များထံ သိမ်းဆည်းပါ။", - "select_buy_provider_notice": "အပေါ်ကဝယ်သူတစ် ဦး ကိုရွေးချယ်ပါ။ သင်၏ default 0 ယ်သူအား app settings တွင် setting လုပ်ခြင်းဖြင့်ဤ screen ကိုကျော်သွားနိုင်သည်။", - "onramper_option_description": "ငွေပေးချေမှုနည်းလမ်းများစွာဖြင့် Crypto ကိုလျင်မြန်စွာ 0 ယ်ပါ။ နိုင်ငံအများစုတွင်ရရှိနိုင်ပါသည်။ ဖြန့်ဖြူးနှင့်အခကြေးငွေကွဲပြားခြားနားသည်။", + "choose_from_available_options": "ရနိုင်သောရွေးချယ်မှုများမှ ရွေးပါ-", + "choose_one": "တစ်ခုရွေးပါ။", + "choose_relay": "အသုံးပြုရန် relay ကိုရွေးချယ်ပါ။", + "choose_wallet_currency": "ပိုက်ဆံအိတ်ငွေကြေးကို ရွေးပါ-", + "clear": "ရှင်းလင်းသော", + "clearnet_link": "Clearnet လင့်ခ်", + "close": "အနီးကပ်", + "coin_control": "အကြွေစေ့ထိန်းချုပ်မှု (ချန်လှပ်ထားနိုင်သည်)", + "cold_or_recover_wallet": "အေးသောပိုက်ဆံအိတ်ထည့်ပါ သို့မဟုတ် စက္ကူပိုက်ဆံအိတ်ကို ပြန်ယူပါ။", + "color_theme": "အရောင်အပြင်အဆင်", + "commit_transaction_amount_fee": "ငွေလွှဲခြင်း\nပမာဏ- ${amount}\nအခကြေးငွေ- ${fee}", + "confirm": "အတည်ပြုပါ။", + "confirm_delete_template": "ဤလုပ်ဆောင်ချက်သည် ဤပုံစံပြားကို ဖျက်လိုက်ပါမည်။ ဆက်လုပ်လိုပါသလား။", + "confirm_delete_wallet": "ဤလုပ်ဆောင်ချက်သည် ဤပိုက်ဆံအိတ်ကို ဖျက်လိုက်ပါမည်။ ဆက်လုပ်လိုပါသလား။", + "confirm_sending": "ပေးပို့အတည်ပြုပါ။", + "confirmations": "အတည်ပြုချက်များ", + "confirmed": "အတည်ပြုထားသော လက်ကျန်ငွေ", + "confirmed_tx": "အတည်ပြုသည်", + "congratulations": "ဂုဏ်ယူပါသည်။", + "connect_an_existing_yat": "ရှိပြီးသား Yat ကို ချိတ်ဆက်ပါ။", + "connect_yats": "Yats ကိုချိတ်ဆက်ပါ။", + "connection_sync": "ချိတ်ဆက်မှုနှင့် ထပ်တူပြုခြင်း။", + "connectWalletPrompt": "အရောင်းအဝယ်ပြုလုပ်ရန် သင့်ပိုက်ဆံအိတ်ကို WalletConnect နှင့် ချိတ်ဆက်ပါ။", + "contact": "ဆက်သွယ်ရန်", + "contact_list_contacts": "အဆက်အသွယ်များ", + "contact_list_wallets": "ကျွန်ုပ်၏ ပိုက်ဆံအိတ်များ", + "contact_name": "ဆက်သွယ်ရန်အမည်", + "contact_support": "ပံ့ပိုးကူညီမှုထံ ဆက်သွယ်ပါ။", + "continue_text": "ဆက်လက်", + "contractName": "စာချုပ်အမည်", + "contractSymbol": "စာချုပ်သင်္ကေတ", + "copied_key_to_clipboard": "${key} ကို Clipboard သို့ ကူးယူထားသည်။", + "copied_to_clipboard": "ကလစ်ဘုတ်သို့ ကူးယူထားသည်။", + "copy": "ကော်ပီ", + "copy_address": "လိပ်စာကို ကူးယူပါ။", + "copy_id": "ID ကူးယူပါ။", + "copyWalletConnectLink": "dApp မှ WalletConnect လင့်ခ်ကို ကူးယူပြီး ဤနေရာတွင် ကူးထည့်ပါ။", + "create_account": "အကောင့်ပြုလုပ်ပါ", + "create_backup": "အရန်သိမ်းခြင်းကို ဖန်တီးပါ။", + "create_donation_link": "လှူဒါန်းမှုလင့်ခ်ကို ဖန်တီးပါ။", + "create_invoice": "ပြေစာဖန်တီးပါ။", + "create_new": "Wallet အသစ်ဖန်တီးပါ။", + "create_new_account": "အကောင့်အသစ်ဖန်တီးပါ။", + "creating_new_wallet": "ပိုက်ဆံအိတ်အသစ်ဖန်တီးခြင်း။", + "creating_new_wallet_error": "အမှား- ${description}", + "creation_date": "ဖန်တီးမှုနေ့စွဲ", + "custom": "စိတ်ကြိုက်", + "custom_drag": "စိတ်ကြိုက် (Drag)", + "custom_redeem_amount": "စိတ်ကြိုက်သုံးငွေပမာဏ", + "dark_theme": "မှောငျမိုကျသော", + "debit_card": "ဒက်ဘစ်ကတ်", + "debit_card_terms": "ဤဒစ်ဂျစ်တယ်ပိုက်ဆံအိတ်ရှိ သင့်ငွေပေးချေမှုကတ်နံပါတ် (နှင့် သင့်ငွေပေးချေကတ်နံပါတ်နှင့် သက်ဆိုင်သောအထောက်အထားများ) ၏ သိုလှောင်မှုနှင့် အသုံးပြုမှုသည် အချိန်အခါနှင့်အမျှ သက်ရောက်မှုရှိသကဲ့သို့ ကတ်ကိုင်ဆောင်ထားသူ၏ သဘောတူညီချက်၏ စည်းကမ်းသတ်မှတ်ချက်များနှင့် ကိုက်ညီပါသည်။", + "decimal_places_error": "ဒဿမနေရာများ များလွန်းသည်။", "default_buy_provider": "Default Provider ကိုဝယ်ပါ", - "ask_each_time": "တစ်ခုချင်းစီကိုအချိန်မေးပါ", - "buy_provider_unavailable": "လက်ရှိတွင်လက်ရှိမရနိုင်ပါ။", - "signTransaction": "ငွေလွှဲဝင်ပါ။", + "default_sell_provider": "ပုံသေရောင်းချပေးသူ", + "delete": "ဖျက်ပါ။", + "delete_account": "အကောင့်ဖျက်ပါ။", + "delete_wallet": "ပိုက်ဆံအိတ်ကို ဖျက်ပါ။", + "delete_wallet_confirm_message": "${wallet_name} ပိုက်ဆံအိတ်ကို ဖျက်လိုသည်မှာ သေချာပါသလား။", + "deleteConnectionConfirmationPrompt": "ချိတ်ဆက်မှုကို ဖျက်လိုသည်မှာ သေချာပါသလား။", + "descending": "ဆင်း", + "description": "ဖော်ပြချက်", + "destination_tag": "ခရီးဆုံးအမှတ်-", + "dfx_option_description": "EUR & CHF ဖြင့် crypto ကိုဝယ်ပါ။ အပို KYC မပါဘဲ 990€ အထိ။ ဥရောပရှိ လက်လီရောင်းချသူများနှင့် ကော်ပိုရိတ်ဖောက်သည်များအတွက်", + "didnt_get_code": "ကုဒ်ကို မရဘူးလား?", + "digit_pin": "-ဂဏန်း PIN", + "digital_and_physical_card": " ဒစ်ဂျစ်တယ်နှင့် ရုပ်ပိုင်းဆိုင်ရာ ကြိုတင်ငွေပေးချေသော ဒက်ဘစ်ကတ်", + "disable": "ပိတ်ပါ။", + "disable_buy": "ဝယ်ယူမှု လုပ်ဆောင်ချက်ကို ပိတ်ပါ။", + "disable_cake_2fa": "ကိတ်မုန့် 2FA ကို ပိတ်ပါ။", + "disable_exchange": "လဲလှယ်မှုကို ပိတ်ပါ။", + "disable_fiat": "Fiat ကိုပိတ်ပါ။", + "disable_sell": "ရောင်းချခြင်းလုပ်ဆောင်ချက်ကို ပိတ်ပါ။", + "disabled": "မသန်စွမ်း", + "discount": "${value}% ချွေတာ", + "display_settings": "ပြသရန် ဆက်တင်များ", + "displayable": "ပြသနိုင်သည်။", + "do_not_have_enough_gas_asset": "လက်ရှိ blockchain ကွန်ရက်အခြေအနေများနှင့် အရောင်းအဝယ်ပြုလုပ်ရန် သင့်တွင် ${currency} လုံလောက်မှုမရှိပါ။ သင်သည် မတူညီသော ပိုင်ဆိုင်မှုတစ်ခုကို ပေးပို့နေသော်လည်း blockchain ကွန်ရက်အခကြေးငွေကို ပေးဆောင်ရန် သင်သည် နောက်ထပ် ${currency} လိုအပ်ပါသည်။", + "do_not_send": "မပို့ပါနှင့်", + "do_not_share_warning_text": "ပံ့ပိုးကူညီမှုအပါအဝင် ဤအရာများကို အခြားမည်သူနှင့်မျှ မမျှဝေပါနှင့်။\n\nသင့်ငွေများကို ခိုးယူခံရနိုင်သည်!", + "do_not_show_me": "ဒါကို ထပ်မပြနဲ့", + "domain_looks_up": "ဒိုမိန်းရှာဖွေမှုများ", + "donation_link_details": "လှူဒါန်းရန်လင့်ခ်အသေးစိတ်", + "e_sign_consent": "E-Sign သဘောတူညီချက်", + "edit": "တည်းဖြတ်ပါ။", + "edit_backup_password": "Backup Password ကို တည်းဖြတ်ပါ။", + "edit_node": "Node ကို တည်းဖြတ်ပါ။", + "edit_token": "တိုကင်ကို တည်းဖြတ်ပါ။", + "electrum_address_disclaimer": "သင်အသုံးပြုသည့်အချိန်တိုင်းတွင် ကျွန်ုပ်တို့သည် လိပ်စာအသစ်များကို ထုတ်ပေးသော်လည်း ယခင်လိပ်စာများသည် ဆက်လက်အလုပ်လုပ်နေပါသည်။", + "email_address": "အီးမေးလ်လိပ်စာ", + "enabled": "ဖွင့်ထားသည်။", + "enter_amount": "ပမာဏကို ထည့်ပါ။", + "enter_backup_password": "အရန်စကားဝှက်ကို ဤနေရာတွင် ထည့်ပါ။", + "enter_code": "ကုဒ်ထည့်ပါ။", + "enter_seed_phrase": "သင့်ရဲ့မျိုးစေ့စကားစုကိုရိုက်ထည့်ပါ", + "enter_totp_code": "ကျေးဇူးပြု၍ TOTP ကုဒ်ကို ထည့်ပါ။", + "enter_your_note": "သင့်မှတ်စုကို ထည့်ပါ...", + "enter_your_pin": "သင်၏ PIN ကိုထည့်ပါ။", + "enter_your_pin_again": "သင့်ပင်နံပါတ်ကို ထပ်မံထည့်သွင်းပါ။", + "enterTokenID": "တိုကင် ID ကိုထည့်ပါ။", + "enterWalletConnectURI": "WalletConnect URI ကိုရိုက်ထည့်ပါ။", + "error": "အမှား", + "error_dialog_content": "အိုး၊ ကျွန်ုပ်တို့တွင် အမှားအယွင်းအချို့ရှိသည်။\n\nအပလီကေးရှင်းကို ပိုမိုကောင်းမွန်စေရန်အတွက် ပျက်စီးမှုအစီရင်ခံစာကို ကျွန်ုပ်တို့၏ပံ့ပိုးကူညီရေးအဖွဲ့ထံ ပေးပို့ပါ။", + "error_text_account_name": "အကောင့်အမည်သည် အက္ခရာများ၊ နံပါတ်များသာ ပါဝင်နိုင်သည်\nနှင့် စာလုံးရေ 1 နှင့် 15 ကြားရှိရပါမည်။", + "error_text_address": "Wallet လိပ်စာသည် အမျိုးအစား\no cryptocurrency နှင့် ကိုက်ညီရပါမည်။", + "error_text_amount": "ပမာဏသည် နံပါတ်များသာ ပါဝင်နိုင်သည်။", + "error_text_contact_name": "အဆက်အသွယ်အမည်တွင် ` , ' \" သင်္ကေတများ မပါဝင်နိုင်ပါ\nနှင့် စာလုံးအရှည် 1 နှင့် 32 ကြားရှိရမည်", + "error_text_crypto_currency": "အပိုင်းကိန်းဂဏန်းများ၏ အရေအတွက်\nလျော့နည်းသည် သို့မဟုတ် 12 နှင့် ညီမျှရပါမည်။", + "error_text_fiat": "ပမာဏ၏တန်ဖိုးသည် ရနိုင်သောလက်ကျန်ကို မကျော်လွန်နိုင်ပါ။\nအပိုင်းကိန်းဂဏန်းအရေအတွက်သည် 2 နှင့် လျော့နည်းရမည်", + "error_text_input_above_maximum_limit": "ပမာဏသည် အများဆုံးထက် ပိုများသည်။", + "error_text_input_below_minimum_limit": "ပမာဏသည် အနိမ့်ဆုံးထက်နည်းသည်။", + "error_text_keys": "ပိုက်ဆံအိတ်သော့များတွင် hex တွင် 64 လုံးသာပါဝင်နိုင်သည်။", + "error_text_limits_loading_failed": "${provider} အတွက် ကုန်သွယ်မှုကို ဖန်တီးမထားပါ။ ကန့်သတ်ချက်များ တင်ခြင်း မအောင်မြင်ပါ။", + "error_text_maximum_limit": "${provider} အတွက် ကုန်သွယ်မှုကို ဖန်တီးမထားပါ။ ပမာဏသည် အများဆုံးထက် ပိုများသည်- ${max} ${currency}", + "error_text_minimal_limit": "${provider} အတွက် ကုန်သွယ်မှုကို ဖန်တီးမထားပါ။ ပမာဏသည် အနည်းငယ်ထက်နည်းသည်- ${min} ${currency}", + "error_text_node_address": "ကျေးဇူးပြု၍ iPv4 လိပ်စာကို ထည့်ပါ။", + "error_text_node_port": "နော်ဒီဆိပ်ကမ်း တွင် 0 နှင့် 65535 အကြား နံပါတ်များသာ ပါဝင်နိုင်သည်။", + "error_text_node_proxy_address": "ကျေးဇူးပြု၍ :၊ ဥပမာ 127.0.0.1:9050 ထည့်ပါ", + "error_text_payment_id": "ငွေပေးချေမှု ID တွင် hex တွင် စာလုံး 16 လုံးမှ 64 လုံးသာ ပါဝင်နိုင်သည်။", + "error_text_subaddress_name": "လိပ်စာခွဲအမည်တွင် ` , ' \" သင်္ကေတများ မပါဝင်နိုင်ပါ\nနှင့် စာလုံးရေ 1 နှင့် 20 ကြားရှိရမည်", + "error_text_template": "နမူနာပုံစံအမည်နှင့် လိပ်စာတွင် ` , ' \" သင်္ကေတများ မပါဝင်နိုင်ပါ\nနှင့် စာလုံးအရှည် 1 နှင့် 106 ကြား ရှိရမည်", + "error_text_wallet_name": "ပိုက်ဆံအိတ်အမည်တွင် စာလုံးများ၊ နံပါတ်များ၊ _ - သင်္ကေတများသာ ပါဝင်နိုင်သည် \n နှင့် စာလုံးအရှည် 1 နှင့် 33 ကြားရှိရမည်", + "error_text_xmr": "XMR တန်ဖိုးသည် ရနိုင်သောလက်ကျန်ကို ကျော်လွန်၍မရပါ။\nအပိုင်းကိန်းဂဏန်းများ သည် 12 နှင့် လျော့နည်းရမည်", "errorGettingCredentials": "မအောင်မြင်ပါ- အထောက်အထားများ ရယူနေစဉ် အမှားအယွင်း", "errorSigningTransaction": "ငွေပေးငွေယူ လက်မှတ်ထိုးစဉ် အမှားအယွင်းတစ်ခု ဖြစ်ပေါ်ခဲ့သည်။", - "pairingInvalidEvent": "မမှန်ကန်သောဖြစ်ရပ်ကို တွဲချိတ်ခြင်း။", - "chains": "ဆွဲကြိုး", - "methods": "နည်းလမ်းများ", - "events": "အဲ့ဒါနဲ့", - "reject": "ငြင်းပယ်ပါ။", - "approve": "လက်မခံပါ။", - "expiresOn": "သက်တမ်းကုန်သည်။", - "walletConnect": "Wallet ချိတ်ဆက်မှု", - "nullURIError": "URI သည် null ဖြစ်သည်။", - "connectWalletPrompt": "အရောင်းအဝယ်ပြုလုပ်ရန် သင့်ပိုက်ဆံအိတ်ကို WalletConnect နှင့် ချိတ်ဆက်ပါ။", - "newConnection": "ချိတ်ဆက်မှုအသစ်", - "activeConnectionsPrompt": "လက်ရှိချိတ်ဆက်မှုများ ဤနေရာတွင် ပေါ်လာပါမည်။", - "deleteConnectionConfirmationPrompt": "ချိတ်ဆက်မှုကို ဖျက်လိုသည်မှာ သေချာပါသလား။", + "estimated": "ခန့်မှန်း", + "etherscan_history": "Etherscan သမိုင်း", "event": "ပွဲ", - "successful": "အောင်မြင်တယ်။", - "wouoldLikeToConnect": "ချိတ်ဆက်ချင်ပါတယ်။", - "message": "မက်ဆေ့ချ်", - "do_not_have_enough_gas_asset": "လက်ရှိ blockchain ကွန်ရက်အခြေအနေများနှင့် အရောင်းအဝယ်ပြုလုပ်ရန် သင့်တွင် ${currency} လုံလောက်မှုမရှိပါ။ သင်သည် မတူညီသော ပိုင်ဆိုင်မှုတစ်ခုကို ပေးပို့နေသော်လည်း blockchain ကွန်ရက်အခကြေးငွေကို ပေးဆောင်ရန် သင်သည် နောက်ထပ် ${currency} လိုအပ်ပါသည်။", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "ကျေးဇူးပြု၍ dApp ကို စီမံလုပ်ဆောင်ခြင်း အပြီးသတ်ရန် စောင့်ပါ။", - "copyWalletConnectLink": "dApp မှ WalletConnect လင့်ခ်ကို ကူးယူပြီး ဤနေရာတွင် ကူးထည့်ပါ။", - "enterWalletConnectURI": "WalletConnect URI ကိုရိုက်ထည့်ပါ။", - "seed_key": "မျိုးစေ့သော့", - "enter_seed_phrase": "သင့်ရဲ့မျိုးစေ့စကားစုကိုရိုက်ထည့်ပါ", - "change_rep_successful": "အောင်မြင်စွာကိုယ်စားလှယ်ပြောင်းလဲသွားတယ်", - "add_contact": "အဆက်အသွယ်ထည့်ပါ။", + "events": "အဲ့ဒါနဲ့", + "exchange": "ချိန်းတယ်။", + "exchange_incorrect_current_wallet_for_xmr": "သင်၏ Cake Wallet Monero လက်ကျန်မှ XMR ကိုလဲလှယ်လိုပါက၊ သင်၏ Monero ပိုက်ဆံအိတ်သို့ ဦးစွာပြောင်းပါ။", + "exchange_new_template": "ပုံစံအသစ်", "exchange_provider_unsupported": "${providerName} မရှိတော့ပါ!", - "domain_looks_up": "ဒိုမိန်းရှာဖွေမှုများ", - "require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", - "camera_permission_is_required": "ကင်မရာခွင့်ပြုချက် လိုအပ်ပါသည်။\nအက်ပ်ဆက်တင်များမှ ၎င်းကိုဖွင့်ပါ။", - "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။", - "order_by": "အမှာစာ", - "creation_date": "ဖန်တီးမှုနေ့စွဲ", + "exchange_result_confirm": "အတည်ပြုချက်ကို နှိပ်ခြင်းဖြင့်၊ သင်သည် ${fetchingLabel} ${from} ဟုခေါ်သော သင့်ပိုက်ဆံအိတ်မှ ${walletName} ကို အောက်ဖော်ပြပါလိပ်စာသို့ ပေးပို့မည်ဖြစ်ပါသည်။ သို့မဟုတ် သင့်ပြင်ပပိုက်ဆံအိတ်မှ အောက်ပါလိပ်စာ/QR ကုဒ်သို့ ပေးပို့နိုင်ပါသည်။\n\nပမာဏများကို ပြောင်းလဲရန် ဆက်လက်လုပ်ဆောင်ရန် သို့မဟုတ် ပြန်သွားရန် အတည်ပြုချက်ကို နှိပ်ပါ။", + "exchange_result_description": "သင်သည် အနည်းဆုံး ${fetchingLabel} ${from} ကို နောက်စာမျက်နှာတွင် ပြသထားသည့် လိပ်စာသို့ ပေးပို့ရပါမည်။ ${fetchingLabel} ${from} ထက်နည်းသော ပမာဏကို ပေးပို့ပါက ၎င်းသည် ပြောင်းလဲ၍မရသည့်အပြင် ပြန်အမ်းမည်မဟုတ်ပါ။", + "exchange_result_write_down_ID": "* ကျေးဇူးပြု၍ အထက်ဖော်ပြပါ သင်၏ ID ကို ကော်ပီ သို့မဟုတ် ရေးမှတ်ပါ။", + "exchange_result_write_down_trade_id": "ရှေ့ဆက်ရန် ကုန်သွယ်မှု ID ကို ကူးယူ သို့မဟုတ် ချရေးပါ။", + "exchange_sync_alert_content": "သင့်ပိုက်ဆံအိတ်ကို စင့်ခ်လုပ်ထားသည့်အချိန်အထိ စောင့်ပါ။", + "expired": "သက်တမ်းကုန်သွားပြီ", + "expires": "သက်တမ်းကုန်သည်။", + "expiresOn": "သက်တမ်းကုန်သည်။", + "export_backup": "အရန်ကူးထုတ်ရန်", + "extra_id": "အပို ID-", + "extracted_address_content": "သင်သည် \n${recipient_name} သို့ ရန်ပုံငွေများ ပေးပို့ပါမည်", + "failed_authentication": "အထောက်အထားစိစစ်ခြင်း မအောင်မြင်ပါ။. ${state_error}", + "faq": "အမြဲမေးလေ့ရှိသောမေးခွန်းများ", + "fetching": "ခေါ်ယူခြင်း။", + "fiat_api": "Fiat API", + "fiat_balance": "Fiat Balance", + "field_required": "ဤစာကွက်လပ်မှာဖြည့်ရန်လိုအပ်ပါသည်", + "fill_code": "သင့်အီးမေးလ်သို့ ပေးထားသည့် အတည်ပြုကုဒ်ကို ဖြည့်ပါ။", + "filter_by": "အလိုက် စစ်ထုတ်ပါ။", + "first_wallet_text": "Monero၊ Bitcoin၊ Ethereum၊ Litecoin နှင့် Haven အတွက် အလွန်ကောင်းမွန်သော ပိုက်ဆံအိတ်", + "fixed_pair_not_supported": "ရွေးချယ်ထားသော ဖလှယ်မှုများဖြင့် ဤပုံသေအတွဲကို ပံ့ပိုးမထားပါ။", + "fixed_rate": "ပုံသေနှုန်း", + "fixed_rate_alert": "ပုံသေနှုန်းထားမုဒ်ကို စစ်ဆေးသည့်အခါ လက်ခံပမာဏကို ထည့်သွင်းနိုင်မည်ဖြစ်သည်။ ပုံသေနှုန်းမုဒ်သို့ ပြောင်းလိုပါသလား။", + "forgot_password": "စကားဝှက်မေ့နေပါသလား", + "freeze": "အေးခဲ", + "frequently_asked_questions": "မေးလေ့ရှိသောမေးခွန်းများ", + "frozen": "ဖြူဖြူ", + "full_balance": "Balance အပြည့်", + "generate_name": "အမည်ဖန်တီးပါ။", + "generating_gift_card": "လက်ဆောင်ကတ်ထုတ်ပေးခြင်း။", + "get_a": "တစ်ခုရယူပါ။", + "get_card_note": " ဒစ်ဂျစ်တယ်ငွေကြေးများဖြင့် ပြန်လည်စတင်နိုင်သည်။ နောက်ထပ် အချက်အလက် မလိုအပ်ပါ။", + "get_your_yat": "မင်းရဲ့ Yat ကိုယူလိုက်ပါ။", + "gift_card_amount": "လက်ဆောင်ကတ် ပမာဏ", + "gift_card_balance_note": "လက်ကျန်လက်ကျန်ရှိသည့် လက်ဆောင်ကတ်များ ဤနေရာတွင် ပေါ်လာပါမည်။", + "gift_card_is_generated": "Gift Card ထုတ်ပေးပါသည်။", + "gift_card_number": "လက်ဆောင်ကတ်နံပါတ်", + "gift_card_redeemed_note": "သင်ရွေးယူထားသော လက်ဆောင်ကတ်များ ဤနေရာတွင် ပေါ်လာပါမည်။", + "gift_cards": "လက်ဆောင်ကဒ်ပြား", + "gift_cards_unavailable": "လက်ဆောင်ကတ်များကို ယခုအချိန်တွင် Monero၊ Bitcoin နှင့် Litecoin တို့ဖြင့်သာ ဝယ်ယူနိုင်ပါပြီ။", + "got_it": "ရပြီ", + "gross_balance": "စုစုပေါင်းလက်ကျန်ငွေ", "group_by_type": "အမျိုးအစားအလိုက်အုပ်စုဖွဲ့", - "importNFTs": "NFTs များကို တင်သွင်းပါ။", - "noNFTYet": "NFTs မရှိသေးပါ။", - "address": "လိပ်စာ", - "enterTokenID": "တိုကင် ID ကိုထည့်ပါ။", - "tokenID": "အမှတ်သညာ", - "name": "နာမည်", - "symbol": "သင်္ကေတ", - "seed_phrase_length": "မျိုးစေ့စာပိုဒ်တိုအရှည်", - "unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။", - "unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။", - "unspent_change": "ပေြာင်းလဲခြင်း", - "tor_connection": "Tor ချိတ်ဆက်မှု", - "setup_warning_2fa_text": "ကိတ်မုန့် 2FA သည် ပိုက်ဆံအိတ်ရှိ အချို့သော လုပ်ဆောင်ချက်များ အတွက် ဒုတိယ စစ်မှန်ကြောင်း အထောက်အထား ဖြစ်သည်။ ၎င်းသည် အအေးခန်းကဲ့သို့ မလုံခြုံပါ။\n\nသင်၏ 2FA အက်ပ် သို့မဟုတ် TOTP သော့များကို အသုံးပြုခွင့် ဆုံးရှုံးပါက၊ သင်သည် ဤပိုက်ဆံအိတ်သို့ ဝင်ရောက်ခွင့် ဆုံးရှုံးမည်ဖြစ်သည်။ သင့်ပိုက်ဆံအိတ်ကို mnemonic မျိုးစေ့မှ ပြန်လည်ရယူရန် လိုအပ်မည်ဖြစ်သည်။\n\nသင်သည် သင်၏ 2FA သို့မဟုတ် mnemonic အစေ့များကို အသုံးပြုခွင့်ဆုံးရှုံးသွားပါက ကိတ်မုန့်ပံ့ပိုးကူညီမှု မပေးနိုင်ပါ။\nCake 2FA ကို အသုံးမပြုမီ၊ လမ်းညွှန်ချက်မှတစ်ဆင့် ဖတ်ရန် အကြံပြုအပ်ပါသည်။", - "scan_qr_on_device": "အခြားစက်တွင် ဤ QR ကုဒ်ကို စကင်ဖတ်ပါ။", + "haven_app": "ဟေးဗင် ကိတ် ဝေါလက်", + "haven_app_wallet_text": "ဟေဗင်အတွက် အံ့ဩစရာကောင်းတဲ့ ပိုက်ဆံအုံး", + "help": "ကူညီပါ", + "hidden_balance": "Hidden Balance", + "hide_details": "အသေးစိတ်ကို ဝှက်ပါ။", + "high_contrast_theme": "အလင်းအမှောင် မြင့်မားသော အပြင်အဆင်", + "home_screen_settings": "ပင်မစခရင် ဆက်တင်များ", "how_to_use": "အသုံးပြုနည်း", + "how_to_use_card": "ဒီကတ်ကို ဘယ်လိုသုံးမလဲ။", + "id": "ID:", + "ignor": "လျစ်လျူရှုပါ။", + "import": "သွင်းကုန်", + "importNFTs": "NFTs များကို တင်သွင်းပါ။", + "in_store": "စတိုးတွင်", + "incoming": "ဝင်လာ", + "incorrect_seed": "ထည့်သွင်းထားသော စာသားသည် မမှန်ကန်ပါ။", + "introducing_cake_pay": "Cake Pay ကို မိတ်ဆက်ခြင်း။", + "invalid_input": "ထည့်သွင်းမှု မမှန်ကန်ပါ။", + "invoice_details": "ပြေစာအသေးစိတ်", + "is_percentage": "သည်", + "last_30_days": "လွန်ခဲ့သော ရက် 30", + "learn_more": "ပိုမိုသိရှိရန်", + "light_theme": "အလင်း", + "loading_your_wallet": "သင့်ပိုက်ဆံအိတ်ကို ဖွင့်နေသည်။", + "login": "လော့ဂ်အင်", + "logout": "ထွက်လိုက်ပါ။", + "low_fee": "အနိမ့်ကြေး", + "low_fee_alert": "သင်သည် လက်ရှိတွင် သက်သာသော ကွန်ရက်အခကြေးငွေဦးစားပေးကို အသုံးပြုနေပါသည်။ ၎င်းသည် အကြာကြီးစောင့်ဆိုင်းခြင်း၊ မတူညီသောနှုန်းထားများ သို့မဟုတ် ပယ်ဖျက်ထားသော ကုန်သွယ်မှုများကို ဖြစ်စေနိုင်သည်။ ပိုမိုကောင်းမွန်သော အတွေ့အကြုံအတွက် ပိုမိုမြင့်မားသော အခကြေးငွေ သတ်မှတ်ပေးရန် အကြံပြုအပ်ပါသည်။", + "manage_nodes": "ဆုံမှတ်များကို စီမံပါ။", + "manage_pow_nodes": "PoW Nodes ကို စီမံပါ။", + "manage_yats": "Yats ကို စီမံပါ။", + "mark_as_redeemed": "ရွေးနှုတ်ခြင်းအဖြစ် အမှတ်အသားပြုပါ။", + "market_place": "ဈေး", + "matrix_green_dark_theme": "Matrix Green Dark အပြင်အဆင်", + "max_amount": "အများဆုံး- ${value}", + "max_value": "အများဆုံး- ${value} ${currency}", + "memo": "မှတ်စုတို:", + "message": "မက်ဆေ့ချ်", + "methods": "နည်းလမ်းများ", + "min_amount": "အနည်းဆုံး- ${value}", + "min_value": "အနည်းဆုံး- ${value} ${currency}", + "minutes_to_pin_code": "${minute} မိနစ်", + "mm": "MM", + "modify_2fa": "ကိတ်မုန့် 2FA ကို ပြင်ဆင်ပါ။", + "monero_com": "Monero.com မှ Cake ပိုက်ဆံအိတ်", + "monero_com_wallet_text": "Monero အတွက် အမိုက်စား ပိုက်ဆံအိတ်", + "monero_dark_theme": "Monero Dark အပြင်အဆင်", + "monero_light_theme": "Monero Light အပြင်အဆင်", + "moonpay_alert_text": "ပမာဏ၏တန်ဖိုးသည် ${minAmount} ${fiatCurrency} နှင့် ပိုနေရမည်", + "more_options": "နောက်ထပ် ရွေးချယ်စရာများ", + "name": "နာမည်", + "narrow": "ကျဉ်းသော", + "new_first_wallet_text": "သင့်ရဲ့ cryptocurrencrencres ကိုအလွယ်တကူလုံခြုံစွာထားရှိပါ", + "new_node_testing": "နှာခေါင်း အသစ်စမ်းသပ်ခြင်း။", + "new_subaddress_create": "ဖန်တီးပါ။", + "new_subaddress_label_name": "အညွှန်းအမည်", + "new_subaddress_title": "လိပ်စာအသစ်", + "new_template": "ပုံစံအသစ်", + "new_wallet": "ပိုက်ဆံအိတ်အသစ်", + "newConnection": "ချိတ်ဆက်မှုအသစ်", + "no_id_needed": "ID မလိုအပ်ပါ။", + "no_id_required": "ID မလိုအပ်ပါ။ ငွေဖြည့်ပြီး ဘယ်နေရာမဆို သုံးစွဲပါ။", + "no_relay_on_domain": "အသုံးပြုသူ၏ဒိုမိန်းအတွက် ထပ်ဆင့်လွှင့်ခြင်း မရှိပါ သို့မဟုတ် ထပ်ဆင့်လွှင့်ခြင်း မရနိုင်ပါ။ အသုံးပြုရန် relay ကိုရွေးချယ်ပါ။", + "no_relays": "Relay မရှိပါ။", + "no_relays_message": "ဤအသုံးပြုသူအတွက် Nostr NIP-05 မှတ်တမ်းကို ကျွန်ုပ်တို့တွေ့ရှိသော်လည်း ၎င်းတွင် မည်သည့် relays မှ မပါဝင်ပါ။ ကျေးဇူးပြု၍ လက်ခံသူကို ၎င်းတို့၏ Nostr မှတ်တမ်းတွင် ထပ်လောင်းထည့်ရန် ညွှန်ကြားပါ။", + "node_address": "နိုဒီ လိပ်စာ", + "node_connection_failed": "ချိတ်ဆက်မှု မအောင်မြင်ပါ။", + "node_connection_successful": "ချိတ်ဆက်မှု အောင်မြင်ခဲ့သည်။", + "node_new": "နော်ဒီအသစ်", + "node_port": "နော်ဒီဆိပ်ကမ်း", + "node_reset_settings_title": "ဆက်တင်များကို ပြန်လည်သတ်မှတ်ပါ။", + "node_test": "စမ်း", + "nodes": "ဆုံမှတ်များ", + "nodes_list_reset_to_default_message": "ဆက်တင်များကို မူရင်းအတိုင်း ပြန်လည်သတ်မှတ်လိုသည်မှာ သေချာပါသလား။", + "none_of_selected_providers_can_exchange": "ရွေးချယ်ထားသော ဝန်ဆောင်မှုပေးသူများမှ ဤလဲလှယ်မှုကို ပြုလုပ်၍မရပါ။", + "noNFTYet": "NFTs မရှိသေးပါ။", + "normal": "ပုံမှန်", + "note_optional": "မှတ်ချက် (ချန်လှပ်ထားနိုင်သည်)", + "note_tap_to_change": "မှတ်ချက် (ပြောင်းလဲရန် တို့ပါ)", + "nullURIError": "URI သည် null ဖြစ်သည်။", + "offer_expires_in": "ကမ်းလှမ်းချက် သက်တမ်းကုန်သည်:", + "offline": "အော့ဖ်လိုင်း", + "ok": "ရလား", + "onion_link": "ကြက်သွန်လင့်", + "online": "အွန်လိုင်း", + "onramper_option_description": "ငွေပေးချေမှုနည်းလမ်းများစွာဖြင့် Crypto ကိုလျင်မြန်စွာ 0 ယ်ပါ။ နိုင်ငံအများစုတွင်ရရှိနိုင်ပါသည်။ ဖြန့်ဖြူးနှင့်အခကြေးငွေကွဲပြားခြားနားသည်။", + "open_gift_card": "Gift Card ကိုဖွင့်ပါ။", + "optional_description": "ရွေးချယ်နိုင်သော ဖော်ပြချက်", + "optional_email_hint": "ရွေးချယ်နိုင်သော ငွေလက်ခံသူ အကြောင်းကြားချက် အီးမေးလ်", + "optional_name": "ရွေးချယ်နိုင်သော လက်ခံသူအမည်", + "optionally_order_card": "ရုပ်ပိုင်းဆိုင်ရာကတ်ကို ရွေးချယ်နိုင်သည် ။", + "orbot_running_alert": "ဤ node သို့မချိတ်ဆက်မီ Orbot အလုပ်လုပ်နေကြောင်း သေချာပါစေ။", + "order_by": "အမှာစာ", + "order_id": "မှာယူမှု ID", + "order_physical_card": "ရုပ်ပိုင်းဆိုင်ရာကတ်ကို မှာယူပါ။", + "other_settings": "အခြားဆက်တင်များ", + "outdated_electrum_wallet_description": "ယခု Cake တွင်ဖန်တီးထားသော Bitcoin ပိုက်ဆံအိတ်အသစ်တွင် စကားလုံး 24 မျိုးရှိသည်။ Bitcoin ပိုက်ဆံအိတ်အသစ်တစ်ခုကို ဖန်တီးပြီး သင့်ငွေအားလုံးကို 24 စကားလုံးပိုက်ဆံအိတ်အသစ်သို့ လွှဲပြောင်းပြီး 12 စကားလုံးမျိုးစေ့ဖြင့် ပိုက်ဆံအိတ်များကို အသုံးပြုခြင်းကို ရပ်တန့်ရန် မဖြစ်မနေလိုအပ်ပါသည်။ သင့်ရန်ပုံငွေများကို လုံခြုံစေရန်အတွက် ၎င်းကိုချက်ချင်းလုပ်ဆောင်ပါ။", + "outdated_electrum_wallet_receive_warning": "ဤပိုက်ဆံအိတ်တွင် စာလုံး 12 လုံးပါပြီး ကိတ်မုန့်တွင် ဖန်တီးပါက၊ Bitcoin ကို ဤပိုက်ဆံအိတ်ထဲသို့ မထည့်ပါနှင့်။ ဤပိုက်ဆံအိတ်သို့ လွှဲပြောင်းပေးသည့် မည်သည့် BTC မဆို ဆုံးရှုံးနိုင်သည်။ 24 စကားလုံးပိုက်ဆံအိတ်အသစ်တစ်ခုဖန်တီးပါ (ညာဘက်အပေါ်ထောင့်ရှိမီနူးကိုနှိပ်ပါ၊ Wallets ကိုရွေးချယ်ပါ၊ ပိုက်ဆံအိတ်အသစ်ဖန်တီးရန်ကိုရွေးချယ်ပါ၊ ထို့နောက် Bitcoin ကိုရွေးချယ်ပါ) နှင့်သင်၏ BTC ကိုထိုနေရာသို့ချက်ချင်းရွှေ့ပါ။ Cake မှ (24 စာလုံး) BTC ပိုက်ဆံအိတ်အသစ်များသည် လုံခြုံပါသည်။", + "outgoing": "အထွက်", + "overwrite_amount": "ပမာဏကို ထပ်ရေးပါ။", + "pairingInvalidEvent": "မမှန်ကန်သောဖြစ်ရပ်ကို တွဲချိတ်ခြင်း။", + "password": "စကားဝှက်", + "paste": "ငါးပိ", + "pause_wallet_creation": "Haven Wallet ဖန်တီးနိုင်မှုကို လောလောဆယ် ခေတ္တရပ်ထားသည်။", + "payment_id": "ငွေပေးချေမှု ID:", + "payment_was_received": "သင့်ငွေပေးချေမှုကို လက်ခံရရှိခဲ့သည်။", + "pending": " (ဆိုင်းငံ့)", + "percentageOf": "${amount} ၏", + "pin_at_top": "အပေါ်တွင် ${token} ပင်ထိုးပါ။", + "pin_is_incorrect": "ပင်နံပါတ် မမှန်ပါ။", + "pin_number": "လျှို့ဝှက်နံပါတ်", + "placeholder_contacts": "သင့်အဆက်အသွယ်များကို ဤနေရာတွင် ပြသပါမည်။", + "placeholder_transactions": "သင်၏ ငွေပေးငွေယူများကို ဤနေရာတွင် ပြသပါမည်။", + "please_fill_totp": "သင့်အခြားစက်တွင်ရှိသော ဂဏန်း ၈ လုံးကုဒ်ကို ကျေးဇူးပြု၍ ဖြည့်ပါ။", + "please_make_selection": "သင့်ပိုက်ဆံအိတ်ကို ဖန်တီးရန် သို့မဟုတ် ပြန်လည်ရယူရန် အောက်တွင် ရွေးချယ်မှုတစ်ခု ပြုလုပ်ပါ။", + "please_reference_document": "နောက်ထပ်အချက်အလက်များအတွက် အောက်ပါစာရွက်စာတမ်းများကို ကိုးကားပါ။", + "please_select": "ကျေးဇူးပြု၍ ရွေးချယ်ပါ-", + "please_select_backup_file": "အရန်ဖိုင်ကို ရွေးပြီး အရန်စကားဝှက်ကို ထည့်ပါ။", + "please_try_to_connect_to_another_node": "အခြား node သို့ ချိတ်ဆက်ရန် ကြိုးစားပါ။", + "please_wait": "ကျေးဇူးပြုပြီးခဏစောင့်ပါ", + "polygonscan_history": "PolygonScan မှတ်တမ်း", + "powered_by": "${title} မှ ပံ့ပိုးပေးသည်", + "pre_seed_button_text": "ကျွန်တော်နားလည်ပါတယ်။ ငါ့အမျိုးအနွယ်ကို ပြလော့", + "pre_seed_description": "နောက်စာမျက်နှာတွင် ${words} စကားလုံးများ အတွဲလိုက်ကို တွေ့ရပါမည်။ ၎င်းသည် သင်၏ထူးခြားပြီး သီးသန့်မျိုးစေ့ဖြစ်ပြီး ပျောက်ဆုံးခြင်း သို့မဟုတ် ချွတ်ယွင်းမှုရှိပါက သင့်ပိုက်ဆံအိတ်ကို ပြန်လည်ရယူရန် တစ်ခုတည်းသောနည်းလမ်းဖြစ်သည်။ ၎င်းကို Cake Wallet အက်ပ်၏အပြင်ဘက်တွင် လုံခြုံသောနေရာတွင် သိမ်းဆည်းရန်မှာ သင်၏တာဝန်ဖြစ်သည်။", + "pre_seed_title": "အရေးကြီးသည်။", + "prevent_screenshots": "ဖန်သားပြင်ဓာတ်ပုံများနှင့် မျက်နှာပြင်ရိုက်ကူးခြင်းကို တားဆီးပါ။", + "privacy": "ကိုယ်ရေးကိုယ်တာ", + "privacy_policy": "ကိုယ်ရေးအချက်အလက်မူဝါဒ", + "privacy_settings": "Privacy settings တွေကို", + "private_key": "သီးသန့်သော့", + "proceed_after_one_minute": "မျက်နှာပြင်သည် ၁ မိနစ်အကြာတွင် ဆက်လက်မလုပ်ဆောင်ပါက သင့်အီးမေးလ်ကို စစ်ဆေးပါ။", + "profile": "ကိုယ်ရေးအကျဉ်း", + "provider_error": "${provider} အမှား", + "public_key": "အများသူငှာသော့", + "purchase_gift_card": "လက်ဆောင်ကတ်ဝယ်ပါ။", + "qr_fullscreen": "မျက်နှာပြင်အပြည့် QR ကုဒ်ကိုဖွင့်ရန် တို့ပါ။", + "qr_payment_amount": "ဤ QR ကုဒ်တွင် ငွေပေးချေမှုပမာဏတစ်ခုပါရှိသည်။ လက်ရှိတန်ဖိုးကို ထပ်ရေးလိုပါသလား။", + "question_to_disable_2fa": "Cake 2FA ကို ပိတ်လိုသည်မှာ သေချာပါသလား။ ပိုက်ဆံအိတ်နှင့် အချို့သောလုပ်ဆောင်ချက်များကို အသုံးပြုရန်အတွက် 2FA ကုဒ်တစ်ခု မလိုအပ်တော့ပါ။", + "receivable_balance": "လက်ကျန်ငွေ", + "receive": "လက်ခံသည်။", + "receive_amount": "ပမာဏ", + "received": "ရရှိခဲ့သည်။", + "recipient_address": "လက်ခံသူလိပ်စာ", + "reconnect": "ပြန်လည်ချိတ်ဆက်ပါ။", + "reconnect_alert_text": "ပြန်လည်ချိတ်ဆက်လိုသည်မှာ သေချာပါသလား။ ?", + "reconnection": "ပြန်လည်ချိတ်ဆက်မှု", + "redeemed": "ရွေးနှုတ်ခဲ့သည်။", + "refund_address": "ပြန်အမ်းငွေလိပ်စာ", + "reject": "ငြင်းပယ်ပါ။", + "remaining": "ကျန်", + "remove": "ဖယ်ရှားပါ။", + "remove_node": "နှာခေါင်း ကို ဖယ်ရှားပါ။", + "remove_node_message": "ရွေးချယ်ထားသော ကုဒ်ကို ဖယ်ရှားလိုသည်မှာ သေချာပါသလား။", + "rename": "အမည်ပြောင်းပါ။", + "require_for_adding_contacts": "အဆက်အသွယ်များထည့်ရန် လိုအပ်သည်။", + "require_for_all_security_and_backup_settings": "လုံခြုံရေးနှင့် အရန်ဆက်တင်များအားလုံးအတွက် လိုအပ်ပါသည်။", + "require_for_assessing_wallet": "ပိုက်ဆံအိတ်ကို ဝင်သုံးရန် လိုအပ်သည်။", + "require_for_creating_new_wallets": "ပိုက်ဆံအိတ်အသစ်များ ဖန်တီးရန် လိုအပ်သည်။", + "require_for_exchanges_to_external_wallets": "ပြင်ပပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", + "require_for_exchanges_to_internal_wallets": "အတွင်းပိုင်းပိုက်ဆံအိတ်များသို့ လဲလှယ်ရန် လိုအပ်သည်။", + "require_for_sends_to_contacts": "အဆက်အသွယ်များထံ ပေးပို့ရန် လိုအပ်သည်။", + "require_for_sends_to_internal_wallets": "အတွင်းပိုင်း ပိုက်ဆံအိတ်များသို့ ပေးပို့ရန် လိုအပ်သည်။", + "require_for_sends_to_non_contacts": "အဆက်အသွယ်မရှိသူများထံ ပေးပို့ရန် လိုအပ်သည်။", + "require_pin_after": "ပြီးနောက် PIN လိုအပ်ပါသည်။", + "rescan": "ပြန်စကင်န်လုပ်ပါ။", + "resend_code": "ကျေးဇူးပြု၍ ပြန်ပို့ပါ။", + "reset": "ပြန်လည်သတ်မှတ်ပါ။", + "reset_password": "လျှို့ဝှတ်နံပါတ်အားမူလအတိုင်းပြန်လုပ်သည်", + "restore_active_seed": "တက်ကြွသောအစေ့", + "restore_address": "လိပ်စာ", + "restore_bitcoin_description_from_keys": "သင့်ကိုယ်ပိုင်သော့များမှ ထုတ်လုပ်ထားသော WIF စာကြောင်းမှ သင့်ပိုက်ဆံအိတ်ကို ပြန်လည်ရယူပါ။", + "restore_bitcoin_description_from_seed": "24 စကားလုံးပေါင်းစပ်ကုဒ်မှ သင့်ပိုက်ဆံအိတ်ကို ပြန်ယူပါ။", + "restore_bitcoin_title_from_keys": "WIF မှ ပြန်လည်ရယူပါ။", + "restore_description_from_backup": "သင့်အရန်ဖိုင်မှ Cake Wallet အက်ပ်တစ်ခုလုံးကို သင်ပြန်လည်ရယူနိုင်သည်။", + "restore_description_from_keys": "သင့်ကိုယ်ပိုင်သော့များမှ သိမ်းဆည်းထားသော ထုတ်ပေးထားသော သော့ချက်များမှ သင့်ပိုက်ဆံအိတ်ကို ပြန်လည်ရယူပါ။", + "restore_description_from_seed": "25 စကားလုံး သို့မဟုတ် 13 စကားလုံးပေါင်းစပ်ကုဒ်မှ သင့်ပိုက်ဆံအိတ်ကို ပြန်လည်ရယူပါ။", + "restore_description_from_seed_keys": "သင့်ပိုက်ဆံအိတ်ကို လုံခြုံသောနေရာတွင် သိမ်းဆည်းထားသော မျိုးစေ့/သော့များမှ ပြန်လည်ရယူပါ။", + "restore_from_date_or_blockheight": "ဤပိုက်ဆံအိတ်ကို သင်မဖန်တီးမီ ရက်အနည်းငယ်အလိုတွင် ရက်စွဲတစ်ခု ထည့်သွင်းပါ။ သို့မဟုတ် ဘလော့ခ်ဟိုက် ကို သိပါက ၎င်းအစား ၎င်းကို ထည့်ပါ။", + "restore_from_seed_placeholder": "သင့်အစေ့ကို ဤနေရာတွင် ထည့်ပါ သို့မဟုတ် ကူးထည့်ပါ။", + "restore_new_seed": "မျိုးစေ့အသစ်", + "restore_next": "နောက်တစ်ခု", + "restore_recover": "ပြန်ယူပါ။", + "restore_restore_wallet": "ပိုက်ဆံအိတ်ကို ပြန်ယူပါ။", + "restore_seed_keys_restore": "မျိုးစေ့/သော့များ ပြန်လည်ရယူပါ။", + "restore_spend_key_private": "သော့သုံးရန် (သီးသန့်)", + "restore_title_from_backup": "အရန်သိမ်းခြင်းမှ ပြန်လည်ရယူပါ။", + "restore_title_from_keys": "သော့များမှ ပြန်လည်ရယူပါ။", + "restore_title_from_seed": "မျိုးစေ့မှပြန်လည်ရယူပါ။", + "restore_title_from_seed_keys": "မျိုးစေ့/သော့များမှ ပြန်လည်ရယူပါ။", + "restore_view_key_private": "သော့ကိုကြည့်ရန် (သီးသန့်)", + "restore_wallet": "ပိုက်ဆံအိတ်ကို ပြန်ယူပါ။", + "restore_wallet_name": "ပိုက်ဆံအိတ်နာမည်", + "restore_wallet_restore_description": "Wallet ပြန်လည်ရယူသည့် ဖော်ပြချက်", + "router_no_route": "${name} အတွက် သတ်မှတ်ထားသော လမ်းကြောင်းမရှိပါ", + "save": "သိမ်းဆည်းပါ။", + "save_backup_password": "သင်၏ အရန်စကားဝှက်ကို သိမ်းဆည်းထားကြောင်း သေချာပါစေ။ ၎င်းမပါဘဲ သင်၏ အရန်ဖိုင်များကို တင်သွင်းနိုင်မည် မဟုတ်ပါ။", + "save_backup_password_alert": "အရန်စကားဝှက်ကို သိမ်းဆည်းပါ။", + "save_to_downloads": "ဒေါင်းလုဒ်များထံ သိမ်းဆည်းပါ။", + "saved_the_trade_id": "ကုန်သွယ်မှု ID ကို သိမ်းဆည်းပြီးပါပြီ။", + "scan_qr_code": "QR ကုဒ်ကို စကင်န်ဖတ်ပါ။", + "scan_qr_code_to_get_address": "လိပ်စာရယူရန် QR ကုဒ်ကို စကင်န်ဖတ်ပါ။", + "scan_qr_on_device": "အခြားစက်တွင် ဤ QR ကုဒ်ကို စကင်ဖတ်ပါ။", + "search": "ရှာရန်", + "search_add_token": "ရှာဖွေရန် / တိုကင်ထည့်ပါ။", + "search_category": "ရှာဖွေမှုအမျိုးအစား", + "search_currency": "ငွေကြေးကိုရှာပါ။", + "search_language": "ဘာသာစကားရှာပါ။", + "second_intro_content": "သင်၏ Yat သည် သင့်ငွေကြေးအားလုံးအတွက် သင်၏ ရှည်လျားသော ဆဋ္ဌမကိန်းဂဏန်းများအားလုံးကို အစားထိုးသည့် တစ်မူထူးခြားသော အီမိုဂျီလိပ်စာတစ်ခုဖြစ်သည်။", + "second_intro_title": "၎င်းတို့အားလုံးကို အုပ်ချုပ်ရန် အီမိုဂျီလိပ်စာတစ်ခု", + "security_and_backup": "လုံခြုံရေးနှင့် မိတ္တူ", + "seed_alert_back": "ပြန်သွားသည်", + "seed_alert_content": "မျိုးစေ့သည် သင့်ပိုက်ဆံအိတ်ကို ပြန်လည်ရယူရန် တစ်ခုတည်းသောနည်းလမ်းဖြစ်သည်။ ရေးပြီးပြီလား။", + "seed_alert_title": "အာရုံ", + "seed_alert_yes": "ဟုတ်ကဲ့၊", + "seed_choose": "မျိုးစေ့ဘာသာစကားကို ရွေးချယ်ပါ။", "seed_hex_form": "ပိုက်ဆံအိတ်မျိုးစေ့ (Hex Form)", + "seed_key": "မျိုးစေ့သော့", + "seed_language": "မျိုးစေ့ဘာသာ", + "seed_language_chinese": "တရုတ်", + "seed_language_chinese_traditional": "တရုတ်ရိုးရာ)", + "seed_language_czech": "ချက်", + "seed_language_dutch": "ဒတ်ခ်ျ", + "seed_language_english": "အင်္ဂလိပ်စာ", + "seed_language_french": "ပြင်သစ်", + "seed_language_german": "ဂျာမန်", + "seed_language_italian": "အီတလီ", + "seed_language_japanese": "ဂျပန်", + "seed_language_korean": "ကိုးရီးယား", + "seed_language_next": "နောက်တစ်ခု", + "seed_language_portuguese": "ပေါ်တူဂီ", + "seed_language_russian": "ရုရှ", + "seed_language_spanish": "ငပိ", + "seed_phrase_length": "မျိုးစေ့စာပိုဒ်တိုအရှည်", + "seed_reminder": "ကျေးဇူးပြု၍ သင့်ဖုန်းကို ပျောက်ဆုံးသွားပါက သို့မဟုတ် ဖျက်မိပါက ၎င်းတို့ကို ချရေးပါ။", + "seed_share": "မျိုးစေ့မျှဝေပါ။", + "seed_title": "မျိုးစေ့", "seedtype": "မျိုးပွားခြင်း", "seedtype_legacy": "အမွေအနှစ် (စကားလုံး 25 လုံး)", "seedtype_polyseed": "polyseed (စကားလုံး 16 လုံး)", - "seed_language_czech": "ချက်", - "seed_language_korean": "ကိုးရီးယား", - "seed_language_chinese_traditional": "တရုတ်ရိုးရာ)", - "ascending": "တက်", - "descending": "ဆင်း", - "dfx_option_description": "EUR & CHF ဖြင့် crypto ကိုဝယ်ပါ။ အပို KYC မပါဘဲ 990€ အထိ။ ဥရောပရှိ လက်လီရောင်းချသူများနှင့် ကော်ပိုရိတ်ဖောက်သည်များအတွက်", - "polygonscan_history": "PolygonScan မှတ်တမ်း", - "wallet_seed_legacy": "အမွေအနှစ်ပိုက်ဆံအိတ်မျိုးစေ့", - "default_sell_provider": "ပုံသေရောင်းချပေးသူ", + "select_backup_file": "အရန်ဖိုင်ကို ရွေးပါ။", + "select_buy_provider_notice": "အပေါ်ကဝယ်သူတစ် ဦး ကိုရွေးချယ်ပါ။ သင်၏ default 0 ယ်သူအား app settings တွင် setting လုပ်ခြင်းဖြင့်ဤ screen ကိုကျော်သွားနိုင်သည်။", + "select_destination": "အရန်ဖိုင်အတွက် ဦးတည်ရာကို ရွေးပါ။", "select_sell_provider_notice": "အထက်ဖော်ပြပါ အရောင်းဝန်ဆောင်မှုပေးသူကို ရွေးပါ။ အက်ပ်ဆက်တင်များတွင် သင်၏မူလရောင်းချပေးသူကို သတ်မှတ်ခြင်းဖြင့် ဤစခရင်ကို ကျော်နိုင်သည်။", - "custom_drag": "စိတ်ကြိုက် (Drag)", + "sell": "ရောင်း", + "sell_alert_content": "ကျွန်ုပ်တို့သည် လက်ရှိတွင် Bitcoin၊ Ethereum နှင့် Litecoin ရောင်းချခြင်းကိုသာ ပံ့ပိုးပေးပါသည်။ သင်၏ Bitcoin၊ Ethereum သို့မဟုတ် Litecoin ပိုက်ဆံအိတ်ကို ဖန်တီးပါ သို့မဟုတ် ပြောင်းပါ။", + "sell_monero_com_alert_content": "Monero ရောင်းချခြင်းကို မပံ့ပိုးရသေးပါ။", + "send": "ပို့ပါ။", + "send_address": "${cryptoCurrency} လိပ်စာ", + "send_amount": "ပမာဏ-", + "send_creating_transaction": "အရောင်းအဝယ်ပြုလုပ်ခြင်း။", + "send_error_currency": "ငွေကြေးတွင် နံပါတ်များသာ ပါဝင်နိုင်သည်။", + "send_error_minimum_value": "ပမာဏ၏ အနည်းဆုံးတန်ဖိုးမှာ 0.01 ဖြစ်သည်။", + "send_estimated_fee": "ခန့်မှန်းကြေး-", + "send_fee": "အခကြေးငွေ-", + "send_name": "နာမည်", + "send_new": "အသစ်", + "send_payment_id": "ငွေပေးချေမှု ID (ချန်လှပ်ထား)", + "send_priority": "လောလောဆယ်အခကြေးငွေကို ${transactionPriority} ဦးစားပေးတွင် သတ်မှတ်ထားပါသည်။\nငွေပေးငွေယူဦးစားပေးကို ဆက်တင်များတွင် ချိန်ညှိနိုင်ပါသည်။", + "send_sending": "ပို့နေသည်...", + "send_success": "သင်၏ ${crypto} ကို အောင်မြင်စွာ ပို့လိုက်ပါပြီ။", + "send_templates": "ပုံစံများ", + "send_title": "ပို့ပါ။", + "send_to_this_address": "ဤလိပ်စာသို့ ${currency} ${tag}သို့ ပို့ပါ။", + "send_xmr": "XMR ပို့ပါ။", + "send_your_wallet": "သင့်ပိုက်ဆံအိတ်", + "sending": "ပေးပို့ခြင်း။", + "sent": "ပို့လိုက်ပါတယ်။", + "settings": "ဆက်တင်များ", + "settings_all": "အားလုံး", + "settings_allow_biometrical_authentication": "ဇီဝဗေဒဆိုင်ရာ အထောက်အထားစိစစ်ခြင်းကို ခွင့်ပြုပါ။", + "settings_can_be_changed_later": "အက်ပ်ဆက်တင်များတွင် ဤဆက်တင်များကို နောက်ပိုင်းတွင် ပြောင်းလဲနိုင်သည်။", + "settings_change_language": "ဘာသာစကားပြောင်းပါ။", + "settings_change_pin": "ပင်နံပါတ်ပြောင်းပါ။", + "settings_currency": "ငွေကြေး", + "settings_current_node": "လက်ရှိ node", + "settings_dark_mode": "အမှောင်မုဒ်", + "settings_display_balance": "ပြသချိန်ခွင်", + "settings_display_on_dashboard_list": "ဒက်ရှ်ဘုတ်စာရင်းတွင် ပြသပါ။", + "settings_fee_priority": "အခကြေးငွေဦးစားပေး", + "settings_nodes": "ဆုံမှတ်များ", + "settings_none": "တစ်ခုမှ", + "settings_only_trades": "အရောင်းအဝယ်တွေချည်းပဲ။", + "settings_only_transactions": "အရောင်းအဝယ်များသာ", + "settings_personal": "ပုဂ္ဂိုလ်ရေး", + "settings_save_recipient_address": "လက်ခံသူလိပ်စာကို သိမ်းဆည်းပါ။", + "settings_support": "အထောက်အပံ့", + "settings_terms_and_conditions": "စည်းကမ်းနှင့်သတ်မှတ်ချက်များ", + "settings_title": "ဆက်တင်များ", + "settings_trades": "ကုန်သွယ်မှုများ", + "settings_transactions": "ငွေပေးငွေယူ", + "settings_wallets": "ပိုက်ဆံအိတ်", + "setup_2fa": "ကိတ်မုန့် 2FA စနစ်ထည့်သွင်းပါ။", + "setup_2fa_text": "ကိတ်မုန့် 2FA သည် TOTP ကို ဒုတိယ စစ်မှန်ကြောင်းအထောက်အထားအဖြစ် အသုံးပြု၍ လုပ်ဆောင်သည်။\n\nကိတ်မုန့် 2FA ၏ TOTP သည် SHA-512 နှင့် 8 ဂဏန်းပံ့ပိုးမှု လိုအပ်သည်။ ဒါက လုံခြုံရေးကို တိုးမြှင့်ပေးတယ်။ နောက်ထပ်အချက်အလက်များနှင့် ပံ့ပိုးပေးထားသောအက်ပ်များကို လမ်းညွှန်တွင် တွေ့နိုင်ပါသည်။", + "setup_pin": "ပင်နံပါတ်ကို စနစ်ထည့်သွင်းပါ။", + "setup_successful": "သင့်ပင်နံပါတ်ကို အောင်မြင်စွာ သတ်မှတ်ပြီးပါပြီ။", + "setup_totp_recommended": "TOTP စနစ်ထည့်သွင်းပါ။", + "setup_warning_2fa_text": "ကိတ်မုန့် 2FA သည် ပိုက်ဆံအိတ်ရှိ အချို့သော လုပ်ဆောင်ချက်များ အတွက် ဒုတိယ စစ်မှန်ကြောင်း အထောက်အထား ဖြစ်သည်။ ၎င်းသည် အအေးခန်းကဲ့သို့ မလုံခြုံပါ။\n\nသင်၏ 2FA အက်ပ် သို့မဟုတ် TOTP သော့များကို အသုံးပြုခွင့် ဆုံးရှုံးပါက၊ သင်သည် ဤပိုက်ဆံအိတ်သို့ ဝင်ရောက်ခွင့် ဆုံးရှုံးမည်ဖြစ်သည်။ သင့်ပိုက်ဆံအိတ်ကို mnemonic မျိုးစေ့မှ ပြန်လည်ရယူရန် လိုအပ်မည်ဖြစ်သည်။\n\nသင်သည် သင်၏ 2FA သို့မဟုတ် mnemonic အစေ့များကို အသုံးပြုခွင့်ဆုံးရှုံးသွားပါက ကိတ်မုန့်ပံ့ပိုးကူညီမှု မပေးနိုင်ပါ။\nCake 2FA ကို အသုံးမပြုမီ၊ လမ်းညွှန်ချက်မှတစ်ဆင့် ဖတ်ရန် အကြံပြုအပ်ပါသည်။", + "setup_your_debit_card": "သင့်ဒက်ဘစ်ကတ်ကို စနစ်ထည့်သွင်းပါ။", + "share": "မျှဝေပါ။", + "share_address": "လိပ်စာမျှဝေပါ။", + "show_details": "အသေးစိတ်ပြ", + "show_keys": "မျိုးစေ့ /သော့များကို ပြပါ။", + "show_market_place": "စျေးကွက်ကိုပြသပါ။", + "show_seed": "မျိုးစေ့ကိုပြပါ။", + "sign_up": "ဆိုင်းအပ်", + "signTransaction": "ငွေလွှဲဝင်ပါ။", + "signup_for_card_accept_terms": "ကတ်အတွက် စာရင်းသွင်းပြီး စည်းကမ်းချက်များကို လက်ခံပါ။", + "slidable": "လျှောချနိုင်သည်။", + "sort_by": "အလိုက်စဥ်သည်", + "spend_key_private": "သော့သုံးရန် (သီးသန့်)", + "spend_key_public": "သုံးစွဲရန်သော့ (အများပြည်သူ)", + "status": "အခြေအနေ:", + "subaddress_title": "လိပ်စာစာရင်း", + "subaddresses": "လိပ်စာများ", + "submit_request": "တောင်းဆိုချက်တစ်ခုတင်ပြပါ။", + "successful": "အောင်မြင်တယ်။", + "support_description_guides": "ဘုံပြ issues နာများအတွက်စာရွက်စာတမ်းများနှင့်ထောက်ခံမှု", + "support_description_live_chat": "အခမဲ့နှင့်အစာရှောင်ခြင်း! လေ့ကျင့်ထားသောထောက်ခံသူကိုယ်စားလှယ်များသည်ကူညီနိုင်သည်", + "support_description_other_links": "ကျွန်ုပ်တို့၏လူမှုအသိုင်းအဝိုင်းများသို့ 0 င်ရောက်ပါ", + "support_title_guides": "ကိတ်မုန့်ပိုက်ဆံအိတ်လမ်းညွှန်များ", + "support_title_live_chat": "တိုက်ရိုက်ပံ့ပိုးမှု", + "support_title_other_links": "အခြားအထောက်အပံ့လင့်များ", + "sweeping_wallet": "ိုက်ဆံအိတ် တံမြက်လှည်း", + "sweeping_wallet_alert": "ဒါက ကြာကြာမခံသင့်ပါဘူး။ ဤစခရင်ကို ချန်မထားပါနှင့် သို့မဟုတ် ထုတ်ယူထားသော ရန်ပုံငွေများ ဆုံးရှုံးနိုင်သည်", + "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။", "switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)", - "receivable_balance": "လက်ကျန်ငွေ", - "confirmed_tx": "အတည်ပြုသည်", + "symbol": "သင်္ကေတ", + "sync_status_attempting_sync": "ချိန်ကိုက်ခြင်းကို ကြိုးစားနေသည်။", + "sync_status_connected": "ချိတ်ဆက်ထားသည်။", + "sync_status_connecting": "ချိတ်ဆက်ခြင်း။", + "sync_status_failed_connect": "အဆက်အသွယ်ဖြတ်ထားသည်။", + "sync_status_not_connected": "မချိတ်ဆက်ပါ။", + "sync_status_starting_sync": "စင့်ခ်လုပ်ခြင်း။", + "sync_status_syncronized": "ထပ်တူပြုထားသည်။", + "sync_status_syncronizing": "ထပ်တူပြုခြင်း။", + "syncing_wallet_alert_content": "သင်၏လက်ကျန်နှင့် ငွေပေးငွေယူစာရင်းသည် ထိပ်တွင် \"Synchronizeed\" ဟုပြောသည်အထိ မပြီးမြောက်နိုင်ပါ။ ပိုမိုလေ့လာရန် နှိပ်/နှိပ်ပါ။", + "syncing_wallet_alert_title": "သင့်ပိုက်ဆံအိတ်ကို စင့်ခ်လုပ်နေပါသည်။", + "template": "ပုံစံခွက်", + "template_name": "နမူနာပုံစံ", + "third_intro_content": "Yats သည် Cake Wallet အပြင်ဘက်တွင် နေထိုင်ပါသည်။ ကမ္ဘာပေါ်ရှိ မည်သည့်ပိုက်ဆံအိတ်လိပ်စာကို Yat ဖြင့် အစားထိုးနိုင်ပါသည်။", + "third_intro_title": "Yat သည် အခြားသူများနှင့် ကောင်းစွာကစားသည်။", + "time": "${minutes}m ${seconds}s", + "tip": "အကြံပြုချက်-", + "today": "ဒီနေ့", + "token_contract_address": "တိုကင်စာချုပ်လိပ်စာ", + "token_decimal": "တိုကင်ဒဿမ", + "token_name": "တိုကင်အမည် ဥပမာ- Tether", + "token_symbol": "တိုကင်သင်္ကေတ ဥပမာ- USDT", + "tokenID": "အမှတ်သညာ", + "tor_connection": "Tor ချိတ်ဆက်မှု", + "tor_only": "Tor သာ", + "total_saving": "စုစုပေါင်းစုဆောင်းငွေ", + "totp_2fa_failure": "ကုဒ်မမှန်ပါ။ ကျေးဇူးပြု၍ အခြားကုဒ်တစ်ခုကို စမ်းကြည့်ပါ သို့မဟုတ် လျှို့ဝှက်သော့အသစ်တစ်ခု ဖန်တီးပါ။ ဂဏန်း ၈ လုံးကုဒ်များနှင့် SHA512 ကို ပံ့ပိုးပေးသည့် တွဲဖက်အသုံးပြုနိုင်သော 2FA အက်ပ်ကို အသုံးပြုပါ။", + "totp_2fa_success": "အောင်မြင် ဤပိုက်ဆံအိတ်အတွက် ကိတ်မုန့် 2FA ကို ဖွင့်ထားသည်။ ပိုက်ဆံအိတ်ဝင်ရောက်ခွင့်ဆုံးရှုံးသွားသောအခါတွင် သင်၏ mnemonic မျိုးစေ့များကို သိမ်းဆည်းရန် မမေ့ပါနှင့်။", + "totp_auth_url": "TOTP AUTH URL", + "totp_code": "TOTP ကုဒ်", + "totp_secret_code": "TOTP လျှို့ဝှက်ကုဒ်", + "totp_verification_success": "အတည်ပြုခြင်း အောင်မြင်ပါသည်။", + "trade_details_copied": "${title} ကို Clipboard သို့ ကူးယူထားသည်။", + "trade_details_created_at": "တွင်ဖန်တီးခဲ့သည်။", + "trade_details_fetching": "ခေါ်ယူခြင်း။", + "trade_details_id": "အမှတ်သညာ", + "trade_details_pair": "တွဲ", + "trade_details_provider": "ပံ့ပိုးပေးသူ", + "trade_details_state": "အဆင့်အတန်း", + "trade_details_title": "ကုန်သွယ်မှုအသေးစိတ်", + "trade_for_not_created": "${title} အတွက် ကုန်သွယ်မှုကို ဖန်တီးမထားပါ။", + "trade_history_title": "ကုန်သွယ်မှုသမိုင်း", + "trade_id": "ကုန်သွယ်မှု ID:", + "trade_id_not_found": "${title} ၏ ${tradeId} ကုန်သွယ်မှုကို ရှာမတွေ့ပါ။", + "trade_is_powered_by": "ဤကုန်သွယ်မှုကို ${provider} မှ လုပ်ဆောင်သည်", + "trade_not_created": "ကုန်သွယ်မှု မဖန်တီးပါ။", + "trade_not_found": "ကုန်သွယ်မှု မတွေ့။", + "trade_state_btc_sent": "Btc ပို့လိုက်ပါတယ်။", + "trade_state_complete": "ပြီးအောင်", + "trade_state_confirming": "အတည်ပြုခြင်း။", + "trade_state_created": "ဖန်တီးခဲ့သည်။", + "trade_state_finished": "ပြီးပြီ။", + "trade_state_paid": "အခကြေးငွေ", + "trade_state_paid_unconfirmed": "အတည်မပြုနိုင်သေးပါ။", + "trade_state_pending": "ဆိုင်းငံ့ထားသည်။", + "trade_state_timeout": "ခဏပွဲရပ်ခြင်း", + "trade_state_to_be_created": "ဖန်တီးဖို့", + "trade_state_traded": "အရောင်းအဝယ်ဖြစ်ခဲ့သည်။", + "trade_state_trading": "ရောင်းဝယ်ရေး", + "trade_state_underpaid": "ပေးချေမှုနည်းပါးသည်။", + "trade_state_unpaid": "အခကြေးငွေမယူရသေး", + "trades": "ကုန်သွယ်မှုများ", + "transaction_details_amount": "ပမာဏ", + "transaction_details_copied": "${title} ကို Clipboard သို့ ကူးယူထားသည်။", + "transaction_details_date": "ရက်စွဲ", + "transaction_details_fee": "ကြေး", + "transaction_details_height": "အရပ်အမြင့်", + "transaction_details_recipient_address": "လက်ခံသူလိပ်စာများ", "transaction_details_source_address": "အရင်းအမြစ်လိပ်စာ", - "pause_wallet_creation": "Haven Wallet ဖန်တီးနိုင်မှုကို လောလောဆယ် ခေတ္တရပ်ထားသည်။", - "contractName": "စာချုပ်အမည်", - "contractSymbol": "စာချုပ်သင်္ကေတ", - "description": "ဖော်ပြချက်", - "camera_consent": "မှတ်ပုံတင်ခြင်းရည်ရွယ်ချက်များအတွက် ${provider} တွင် သင့်ကင်မရာကို အသုံးပြုပါမည်။ အသေးစိတ်အတွက် ၎င်းတို့၏ ကိုယ်ရေးကိုယ်တာမူဝါဒကို စစ်ဆေးပါ။", - "no_relays": "Relay မရှိပါ။", - "choose_relay": "အသုံးပြုရန် relay ကိုရွေးချယ်ပါ။", - "no_relays_message": "ဤအသုံးပြုသူအတွက် Nostr NIP-05 မှတ်တမ်းကို ကျွန်ုပ်တို့တွေ့ရှိသော်လည်း ၎င်းတွင် မည်သည့် relays မှ မပါဝင်ပါ။ ကျေးဇူးပြု၍ လက်ခံသူကို ၎င်းတို့၏ Nostr မှတ်တမ်းတွင် ထပ်လောင်းထည့်ရန် ညွှန်ကြားပါ။", - "no_relay_on_domain": "အသုံးပြုသူ၏ဒိုမိန်းအတွက် ထပ်ဆင့်လွှင့်ခြင်း မရှိပါ သို့မဟုတ် ထပ်ဆင့်လွှင့်ခြင်း မရနိုင်ပါ။ အသုံးပြုရန် relay ကိုရွေးချယ်ပါ။" -} + "transaction_details_title": "ငွေပေးငွေယူအသေးစိတ်", + "transaction_details_transaction_id": "ငွေပေးငွေယူ ID", + "transaction_key": "ငွေသွင်းငွေထုတ်ကီး", + "transaction_priority_fast": "မြန်သည်။", + "transaction_priority_fastest": "အမြန်ဆုံး", + "transaction_priority_medium": "အလယ်အလတ်", + "transaction_priority_regular": "ပုံမှန်အစည်းအဝေး", + "transaction_priority_slow": "နှေးနှေး", + "transaction_sent": "ငွေပေးချေမှု ပို့ပြီးပါပြီ။!", + "transaction_sent_notice": "မျက်နှာပြင်သည် ၁ မိနစ်အကြာတွင် ဆက်လက်မလုပ်ဆောင်ပါက၊ ပိတ်ဆို့ရှာဖွေသူနှင့် သင့်အီးမေးလ်ကို စစ်ဆေးပါ။", + "transactions": "ငွေပေးငွေယူ", + "transactions_by_date": "ရက်စွဲအလိုက် ငွေလွှဲမှုများ", + "trusted": "ယုံတယ်။", + "unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။", + "unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။", + "unconfirmed": "အတည်မပြုနိုင်သော လက်ကျန်ငွေ", + "understand": "ကျွန်တော်နားလည်ပါတယ်", + "unmatched_currencies": "သင့်လက်ရှိပိုက်ဆံအိတ်၏ငွေကြေးသည် စကင်ဖတ်ထားသော QR နှင့် မကိုက်ညီပါ။", + "unspent_change": "ပေြာင်းလဲခြင်း", + "unspent_coins_details_title": "အသုံးမဝင်သော အကြွေစေ့အသေးစိတ်များ", + "unspent_coins_title": "အသုံးမဝင်သော အကြွေစေ့များ", + "unsupported_asset": "ဤပိုင်ဆိုင်မှုအတွက် ဤလုပ်ဆောင်ချက်ကို ကျွန်ုပ်တို့ မပံ့ပိုးပါ။ ကျေးဇူးပြု၍ ပံ့ပိုးပေးထားသော ပိုင်ဆိုင်မှုအမျိုးအစား၏ ပိုက်ဆံအိတ်ကို ဖန်တီးပါ သို့မဟုတ် ပြောင်းပါ။", + "upto": "${value} အထိ", + "use": "သို့ပြောင်းပါ။", + "use_card_info_three": "ဒစ်ဂျစ်တယ်ကတ်ကို အွန်လိုင်း သို့မဟုတ် ထိတွေ့မှုမဲ့ ငွေပေးချေမှုနည်းလမ်းများဖြင့် အသုံးပြုပါ။", + "use_card_info_two": "ဒစ်ဂျစ်တယ်ငွေကြေးများဖြင့်မဟုတ်ဘဲ ကြိုတင်ငွေပေးချေသည့်အကောင့်တွင် သိမ်းထားသည့်အခါ ရန်ပုံငွေများကို USD သို့ ပြောင်းလဲပါသည်။", + "use_ssl": "SSL ကိုသုံးပါ။", + "use_suggested": "အကြံပြုထားသည်ကို အသုံးပြုပါ။", + "variable_pair_not_supported": "ရွေးချယ်ထားသော ဖလှယ်မှုများဖြင့် ဤပြောင်းလဲနိုင်သောအတွဲကို ပံ့ပိုးမထားပါ။", + "verification": "စိစစ်ခြင်း။", + "verify_with_2fa": "Cake 2FA ဖြင့် စစ်ဆေးပါ။", + "version": "ဗားရှင်း ${currentVersion}", + "view_all": "အားလုံးကိုကြည့်ရှုပါ။", + "view_in_block_explorer": "Block Explorer တွင်ကြည့်ရှုပါ။", + "view_key_private": "သော့ကိုကြည့်ရန် (သီးသန့်)", + "view_key_public": "သော့ကိုကြည့်ရန် (အများပြည်သူ)", + "view_transaction_on": "ငွေလွှဲခြင်းကို ဖွင့်ကြည့်ပါ။", + "wallet_keys": "ပိုက်ဆံအိတ် အစေ့/သော့များ", + "wallet_list_create_new_wallet": "Wallet အသစ်ဖန်တီးပါ။", + "wallet_list_edit_wallet": "ပိုက်ဆံအိတ်ကို တည်းဖြတ်ပါ။", + "wallet_list_failed_to_load": "${wallet_name} ပိုက်ဆံအိတ်ကို ဖွင့်၍မရပါ။ ${error}", + "wallet_list_failed_to_remove": "${wallet_name} ပိုက်ဆံအိတ်ကို ဖယ်ရှား၍မရပါ။ ${error}", + "wallet_list_load_wallet": "ပိုက်ဆံအိတ်ကို တင်ပါ။", + "wallet_list_loading_wallet": "${wallet_name} ပိုက်ဆံအိတ်ကို ဖွင့်နေသည်။", + "wallet_list_removing_wallet": "${wallet_name} ပိုက်ဆံအိတ်ကို ဖယ်ရှားခြင်း။", + "wallet_list_restore_wallet": "ပိုက်ဆံအိတ်ကို ပြန်ယူပါ။", + "wallet_list_title": "Monero ပိုက်ဆံအိတ်", + "wallet_list_wallet_name": "ပိုက်ဆံအိတ်နာမည်", + "wallet_menu": "မီနူး", + "wallet_name": "ပိုက်ဆံအိတ်နာမည", + "wallet_name_exists": "ထိုအမည်ဖြင့် ပိုက်ဆံအိတ်တစ်ခု ရှိနှင့်ပြီးဖြစ်သည်။ အခြားအမည်တစ်ခုကို ရွေးပါ သို့မဟုတ် အခြားပိုက်ဆံအိတ်ကို ဦးစွာ အမည်ပြောင်းပါ။", + "wallet_restoration_store_incorrect_seed_length": "မျိုးစေ့အရှည် မမှန်ပါ။", + "wallet_seed": "ပိုက်ဆံအိတ်စေ့", + "wallet_seed_legacy": "အမွေအနှစ်ပိုက်ဆံအိတ်မျိုးစေ့", + "wallet_store_monero_wallet": "Monero ပိုက်ဆံအိတ်", + "walletConnect": "Wallet ချိတ်ဆက်မှု", + "wallets": "ပိုက်ဆံအိတ်", + "warning": "သတိပေးချက်", + "welcome": "မှကြိုဆိုပါတယ်။", + "welcome_to_cakepay": "Cake Pay မှကြိုဆိုပါသည်။", + "widgets_address": "လိပ်စာ", + "widgets_or": "သို့မဟုတ်", + "widgets_restore_from_blockheight": "အမြင့်မှ ပြန်လည်ရယူပါ။", + "widgets_restore_from_date": "ရက်စွဲမှ ပြန်လည်ရယူပါ။", + "widgets_seed": "မျိုးစေ့", + "wouoldLikeToConnect": "ချိတ်ဆက်ချင်ပါတယ်။", + "write_down_backup_password": "သင်၏ အရန်ဖိုင်များကို တင်သွင်းရန်အတွက် အသုံးပြုသည့် သင်၏ အရန်စကားဝှက်ကို ချရေးပါ။", + "xlm_extra_info": "လဲလှယ်မှုအတွက် XLM ငွေလွှဲပို့နေစဉ် Memo ID ကို သတ်မှတ်ရန် မမေ့ပါနှင့်", + "xmr_available_balance": "လက်ကျန်ငွေ ရရှိနိုင်", + "xmr_full_balance": "မျှတမှု အပြည့်အစုံ", + "xmr_hidden": "ဝှက်ထားသည်။", + "xmr_to_error": "XMR.TO အမှား", + "xmr_to_error_description": "ပမာဏ မမှန်ပါ။ ဒဿမအမှတ်ပြီးနောက် ဂဏန်း ၈ လုံးတွင် အများဆုံးကန့်သတ်ချက်", + "xrp_extra_info": "လဲလှယ်မှုအတွက် XRP ငွေလွှဲပို့နေစဉ် Destination Tag ကို သတ်မှတ်ရန် မမေ့ပါနှင့်", + "yat": "ယတ်", + "yat_address": "Yat လိပ်စာ", + "yat_alert_content": "Cake Wallet အသုံးပြုသူများသည် တစ်မျိုးတည်းသော အီမိုဂျီအခြေခံအသုံးပြုသူအမည်ဖြင့် ၎င်းတို့၏ စိတ်ကြိုက်ငွေကြေးအားလုံးကို ပေးပို့နိုင်ပါပြီ။", + "yat_alert_title": "Yat ဖြင့် crypto ကိုပိုမိုလွယ်ကူစွာပေးပို့လက်ခံပါ။", + "yat_error": "Yat အမှား", + "yat_error_content": "ဤ Yat နှင့် ချိတ်ဆက်ထားသော လိပ်စာမရှိပါ။ နောက်ထပ် Yat စမ်းကြည့်ပါ။", + "yat_popup_content": "သင်၏ Yat - တိုတောင်းသော အီမိုဂျီအခြေခံအသုံးပြုသူအမည်ဖြင့် Cake Wallet တွင် crypto ကို ယခု ပေးပို့နိုင်ပါပြီ။ ဆက်တင်စခရင်ပေါ်တွင် Yats ကို အချိန်မရွေး စီမံခန့်ခွဲပါ။", + "yat_popup_title": "သင့်ပိုက်ဆံအိတ်လိပ်စာကို emojified လုပ်နိုင်ပါသည်။", + "yesterday": "မနေ့က", + "you_now_have_debit_card": "ယခု သင့်တွင် ဒက်ဘစ်ကတ်တစ်ခုရှိသည်။", + "you_pay": "သင်ပေးချေပါ။", + "you_will_get": "သို့ပြောင်းပါ။", + "you_will_send": "မှပြောင်းပါ။", + "yy": "YY", + "zzzz": "မိုးခေဇဇ်" +} \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 51f25e64a..225c7fc42 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -1,779 +1,780 @@ { - "welcome": "Welkom bij", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Geweldige portemonnee voor Monero, Bitcoin, Ethereum, Litecoin, en Haven", - "please_make_selection": "Maak hieronder uw keuze tot maak of herstel je portemonnee.", - "create_new": "Maak een nieuwe portemonnee", - "restore_wallet": "Portemonnee herstellen", - "monero_com": "Monero.com by Cake Wallet", - "monero_com_wallet_text": "Awesome wallet for Monero", - "haven_app": "Haven by Cake Wallet", - "haven_app_wallet_text": "Awesome wallet for Haven", - "accounts": "Accounts", - "edit": "Bewerk", + "about_cake_pay": "Met Cake Pay kunt u eenvoudig cadeaubonnen kopen met virtuele activa, die direct kunnen worden uitgegeven bij meer dan 150.000 handelaren in de Verenigde Staten.", "account": "Account", + "accounts": "Accounts", + "accounts_subaddresses": "Accounts en subadressen", + "activate": "Activeren", + "active": "Actief", + "active_cards": "Actieve kaarten", + "activeConnectionsPrompt": "Actieve verbindingen worden hier weergegeven", "add": "Toevoegen", + "add_contact": "Contactpersoon toevoegen", + "add_custom_node": "Voeg een nieuw aangepast knooppunt toe", + "add_custom_redemption": "Voeg aangepaste inwisseling toe", + "add_fund_to_card": "Voeg prepaid tegoed toe aan de kaarten (tot ${value})", + "add_new_node": "Voeg een nieuw knooppunt toe", + "add_new_word": "Nieuw woord toevoegen", + "add_receiver": "Nog een ontvanger toevoegen (optioneel)", + "add_secret_code": "Of voeg deze geheime code toe aan een authenticator-app", + "add_tip": "Tip toevoegen", + "add_token_disclaimer_check": "Ik heb het adres en de informatie van het tokencontract bevestigd met behulp van een betrouwbare bron. Het toevoegen van kwaadaardige of onjuiste informatie kan leiden tot verlies van geld.", + "add_token_warning": "Bewerk of voeg geen tokens toe volgens de instructies van oplichters.\nBevestig tokenadressen altijd met betrouwbare bronnen!", + "add_value": "Waarde toevoegen", + "address": "Adres", "address_book": "Adresboek", - "contact": "Contact", - "please_select": "Selecteer alstublieft:", - "cancel": "Annuleer", - "ok": "OK", - "contact_name": "Contactnaam", - "reset": "Reset", - "save": "Opslaan", + "address_book_menu": "Adresboek", + "address_detected": "Adres gedetecteerd", + "address_from_domain": "Dit adres is van ${domain} op Unstoppable Domains", + "address_from_yat": "Dit adres is van ${emoji} op Yat", + "address_label": "Address label", "address_remove_contact": "Contact verwijderen", "address_remove_content": "Weet u zeker dat u het geselecteerde contact wilt verwijderen?", - "authenticated": "Authenticated", - "authentication": "Authenticatie", - "failed_authentication": "Mislukte authenticatie. ${state_error}", - "wallet_menu": "Portemonnee-menu", - "Blocks_remaining": "${status} Resterende blokken", - "please_try_to_connect_to_another_node": "Probeer verbinding te maken met een ander knooppunt", - "xmr_hidden": "Verborgen", - "xmr_available_balance": "Beschikbaar saldo", - "xmr_full_balance": "Volledig saldo", - "send": "Sturen", - "receive": "Krijgen", - "transactions": "Transacties", - "incoming": "inkomend", - "outgoing": "Uitgaande", - "transactions_by_date": "Transacties op datum", - "trades": "Trades", - "filter_by": "Filteren op", - "today": "Vandaag", - "yesterday": "Gisteren", - "received": "Ontvangen", - "sent": "Verzonden", - "pending": " (in afwachting)", - "rescan": "Opnieuw scannen", - "reconnect": "Sluit", - "wallets": "Portefeuilles", - "show_seed": "Toon zaad", - "show_keys": "Toon zaad/sleutels", - "address_book_menu": "Adresboek", - "reconnection": "Reconnection", - "reconnect_alert_text": "Weet u zeker dat u opnieuw verbinding wilt maken?", - "exchange": "Uitwisseling", - "clear": "Duidelijk", - "refund_address": "Adres voor terugbetaling", - "change_exchange_provider": "Wijzig Exchange Provider", - "you_will_send": "Converteren van", - "you_will_get": "Converteren naar", - "amount_is_guaranteed": "Het ontvangen bedrag is gegarandeerd", - "amount_is_estimate": "Het ontvangen bedrag is een schatting", - "powered_by": "Aangedreven door ${title}", - "error": "Fout", - "estimated": "Geschatte", - "min_value": "Min: ${value} ${currency}", - "max_value": "Max: ${value} ${currency}", - "change_currency": "Verander valuta", - "overwrite_amount": "Overwrite amount", - "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", - "copy_id": "ID kopiëren", - "exchange_result_write_down_trade_id": "Kopieer of noteer de handels-ID om door te gaan.", - "trade_id": "Trade ID:", - "copied_to_clipboard": "Gekopieerd naar het klembord", - "saved_the_trade_id": "Ik heb de ruil-ID opgeslagen", - "fetching": "Ophalen", - "id": "ID: ", - "amount": "Bedrag: ", - "payment_id": "Betaling ID: ", - "status": "Staat: ", - "offer_expires_in": "Aanbieding verloopt over: ", - "trade_is_powered_by": "Deze transactie wordt mogelijk gemaakt door ${provider}", - "copy_address": "Adres kopiëren", - "exchange_result_confirm": "Door op bevestigen te drukken, wordt u verzonden ${fetchingLabel} ${from} uit je portemonnee genoemd ${walletName} naar het onderstaande adres. Of u kunt vanuit uw externe portemonnee naar het onderstaande adres verzenden / QR-code sturen.\n\nDruk op bevestigen om door te gaan of terug te gaan om de bedragen te wijzigen.", - "exchange_result_description": "U moet minimaal ${fetchingLabel} ${from} verzenden naar het adres dat op de volgende pagina wordt weergegeven. Als u een bedrag verzendt dat lager is dan ${fetchingLabel} ${from}, wordt het mogelijk niet omgezet en wordt het mogelijk niet terugbetaald.", - "exchange_result_write_down_ID": "*Kopieer of noteer uw hierboven getoonde ID.", - "confirm": "Bevestigen", - "confirm_sending": "Bevestig verzending", - "commit_transaction_amount_fee": "Verricht transactie\nBedrag: ${amount}\nhonorarium: ${fee}", - "sending": "Bezig met verzenden", - "transaction_sent": "Transactie verzonden!", - "expired": "Verlopen", - "time": "${minutes}m ${seconds}s", - "send_xmr": "Sturen XMR", - "exchange_new_template": "Nieuwe sjabloon", - "faq": "FAQ", - "enter_your_pin": "Voer uw pincode in", - "loading_your_wallet": "Uw portemonnee laden", - "new_wallet": "Nieuwe portemonnee", - "wallet_name": "Portemonnee naam", - "continue_text": "Doorgaan met", - "choose_wallet_currency": "Kies een portemonnee-valuta:", - "node_new": "Nieuw knooppunt", - "node_address": "Knooppunt adres", - "node_port": "Knooppunt poort", - "login": "Log in", - "password": "Wachtwoord", - "nodes": "Knooppunten", - "node_reset_settings_title": "Reset instellingen", - "nodes_list_reset_to_default_message": "Weet u zeker dat u de standaardinstellingen wilt herstellen?", - "change_current_node": "Weet u zeker dat u het huidige knooppunt wilt wijzigen in ${node}?", - "change": "Verandering", - "remove_node": "Knoop verwijderen", - "remove_node_message": "Weet u zeker dat u het geselecteerde knooppunt wilt verwijderen?", - "remove": "Verwijderen", - "delete": "Delete", - "add_new_node": "Voeg een nieuw knooppunt toe", - "change_current_node_title": "Wijzig het huidige knooppunt", - "node_test": "Test", - "node_connection_successful": "Verbinding is gelukt", - "node_connection_failed": "De verbinding is mislukt", - "new_node_testing": "Nieuwe knooppunttest", - "use": "Gebruik ", - "digit_pin": "-cijferige PIN", - "share_address": "Deel adres", - "receive_amount": "Bedrag", - "subaddresses": "Subadressen", - "rename": "Hernoemen", "addresses": "Adressen", - "scan_qr_code_to_get_address": "Scan de QR-code om het adres te krijgen", - "qr_fullscreen": "Tik om de QR-code op volledig scherm te openen", - "choose_account": "Kies account", - "create_new_account": "Creëer een nieuw account", - "accounts_subaddresses": "Accounts en subadressen", - "restore_restore_wallet": "Portemonnee herstellen", - "restore_title_from_seed_keys": "Herstel van zaad / sleutels", - "restore_description_from_seed_keys": "Ontvang uw portemonnee terug uit seed / keys die u hebt opgeslagen op een veilige plaats", - "restore_next": "Volgende", - "restore_title_from_backup": "Herstellen vanuit een back-upbestand", - "restore_description_from_backup": "Je kunt de hele Cake Wallet-app herstellen van uw back-upbestand", - "restore_seed_keys_restore": "Zaad / sleutels herstellen", - "restore_title_from_seed": "Herstel van zaad", - "restore_description_from_seed": "Herstel uw portemonnee van het 25 woord of 13 woord combinatiecode", - "restore_title_from_keys": "Herstel van sleutels", - "restore_description_from_keys": "Herstel uw portemonnee van gegenereerd toetsaanslagen opgeslagen van uw privésleutels", - "restore_wallet_name": "Portemonnee naam", - "restore_address": "Adres", - "restore_view_key_private": "Bekijk sleutel (privaat)", - "restore_spend_key_private": "Sleutel uitgeven (privaat)", - "restore_recover": "Herstellen", - "restore_wallet_restore_description": "Portemonnee-herstelbeschrijving", - "restore_new_seed": "Nieuw zaad", - "restore_active_seed": "Actief zaad", - "restore_bitcoin_description_from_seed": "Herstel uw portemonnee met een combinatiecode van 24 woorden", - "restore_bitcoin_description_from_keys": "Herstel uw portemonnee van de gegenereerde WIF-string van uw privésleutels", - "restore_bitcoin_title_from_keys": "Herstel van WIF", - "restore_from_date_or_blockheight": "Voer een datum in een paar dagen voordat u deze portemonnee heeft gemaakt. Of als u de blokhoogte kent, voert u deze in", - "seed_reminder": "Schrijf deze op voor het geval u uw telefoon kwijtraakt of veegt", - "seed_title": "Zaad", - "seed_share": "Deel zaad", - "copy": "Kopiëren", - "seed_language": "Zaadtaal", - "seed_choose": "Kies een starttaal", - "seed_language_next": "Volgende", - "seed_language_english": "Engels", - "seed_language_chinese": "Chinese", - "seed_language_dutch": "Nederlands", - "seed_language_german": "Duitse", - "seed_language_japanese": "Japans", - "seed_language_portuguese": "Portugees", - "seed_language_russian": "Russisch", - "seed_language_spanish": "Spaans", - "seed_language_french": "Frans", - "seed_language_italian": "Italiaans", - "send_title": "Stuur", - "send_your_wallet": "Uw portemonnee", - "send_address": "${cryptoCurrency}-adres", - "send_payment_id": "Betaling ID (facultatief)", + "advanced_settings": "Geavanceerde instellingen", + "aggressive": "Overijverig", + "agree": "mee eens", + "agree_and_continue": "Akkoord & doorgaan", + "agree_to": "Door een account aan te maken gaat u akkoord met de ", "all": "ALLE", - "send_error_minimum_value": "Minimale waarde van bedrag is 0,01", - "send_error_currency": "Valuta kan alleen cijfers bevatten", - "send_estimated_fee": "Geschatte vergoeding:", - "send_priority": "Momenteel is de vergoeding vastgesteld op ${transactionPriority} prioriteit.\nTransactieprioriteit kan worden aangepast in de instellingen", - "send_creating_transaction": "Transactie maken", - "send_templates": "Sjablonen", - "send_new": "Nieuw", - "send_amount": "Bedrag:", - "send_fee": "Vergoeding:", - "send_name": "Naam", - "got_it": "Ik snap het", - "send_sending": "Bezig met verzenden...", - "send_success": "Uw ${crypto} is succesvol verzonden", - "settings_title": "Instellingen", - "settings_nodes": "knooppunten", - "settings_current_node": "Huidige knooppunt", - "settings_wallets": "Portemonnee", - "settings_display_balance": "Saldo weergeven", - "settings_currency": "Valuta", - "settings_fee_priority": "Tariefprioriteit", - "settings_save_recipient_address": "Adres ontvanger opslaan", - "settings_personal": "Persoonlijk", - "settings_change_pin": "Verander pincode", - "settings_change_language": "Verander de taal", - "settings_allow_biometrical_authentication": "Biometrische authenticatie toestaan", - "settings_dark_mode": "Donkere modus", - "settings_transactions": "Transacties", - "settings_trades": "Trades", - "settings_display_on_dashboard_list": "Weergeven op dashboardlijst", - "settings_all": "ALLE", - "settings_only_trades": "Alleen handel", - "settings_only_transactions": "Alleen transacties", - "settings_none": "Geen", - "settings_support": "Ondersteuning", - "settings_terms_and_conditions": "Voorwaarden", - "pin_is_incorrect": "PIN is onjuist", - "setup_pin": "PIN instellen", - "enter_your_pin_again": "Voer uw PIN opnieuw in", - "setup_successful": "Uw PIN is succesvol ingesteld!", - "wallet_keys": "Portemonnee zaad/sleutels", - "wallet_seed": "Portemonnee zaad", - "private_key": "Prive sleutel", - "public_key": "Publieke sleutel", - "view_key_private": "Bekijk sleutel (privaat)", - "view_key_public": "Bekijk sleutel (openbaar)", - "spend_key_private": "Sleutel uitgeven (privaat)", - "spend_key_public": "Sleutel uitgeven (openbaar)", - "copied_key_to_clipboard": "Gekopieerd ${key} naar het klembord", - "new_subaddress_title": "Nieuw adres", - "new_subaddress_label_name": "Label naam", - "new_subaddress_create": "Creëren", - "address_label": "Address label", - "subaddress_title": "Subadreslijst", - "trade_details_title": "Handelsgegevens", - "trade_details_id": "ID", - "trade_details_state": "Toestand", - "trade_details_fetching": "Ophalen", - "trade_details_provider": "Leverancier", - "trade_details_created_at": "Gemaakt bij", - "trade_details_pair": "Paar", - "trade_details_copied": "${title} gekopieerd naar het klembord", - "trade_history_title": "Handelsgeschiedenis", - "transaction_details_title": "Transactie details", - "transaction_details_transaction_id": "Transactie ID", - "transaction_details_date": "Datum", - "transaction_details_height": "Hoogte", - "transaction_details_amount": "Bedrag", - "transaction_details_fee": "Vergoeding", - "transaction_details_copied": "${title} gekopieerd naar het klembord", - "transaction_details_recipient_address": "Adressen van ontvangers", - "wallet_list_title": "Monero portemonnee", - "wallet_list_create_new_wallet": "Maak een nieuwe portemonnee", - "wallet_list_edit_wallet": "Portemonnee bewerken", - "wallet_list_wallet_name": "Portemonnee naam", - "wallet_list_restore_wallet": "Portemonnee herstellen", - "wallet_list_load_wallet": "Portemonnee laden", - "wallet_list_loading_wallet": "Bezig met laden ${wallet_name} portemonnee", - "wallet_list_failed_to_load": "Laden mislukt ${wallet_name} portemonnee. ${error}", - "wallet_list_removing_wallet": "Verwijderen ${wallet_name} portemonnee", - "wallet_list_failed_to_remove": "Verwijderen mislukt ${wallet_name} portemonnee. ${error}", - "widgets_address": "Adres", - "widgets_restore_from_blockheight": "Herstel vanaf blockheight", - "widgets_restore_from_date": "Herstel vanaf datum", - "widgets_or": "of", - "widgets_seed": "Zaad", - "router_no_route": "Geen route gedefinieerd voor ${name}", - "error_text_account_name": "Accountnaam mag alleen letters, cijfers bevatten\nen moet tussen de 1 en 15 tekens lang zijn", - "error_text_contact_name": "Naam contactpersoon kan niet bevatten ` , ' \" symbolen\nen moet tussen de 1 en 32 tekens lang zijn", - "error_text_address": "Portemonnee-adres moet overeenkomen met het type\nvan cryptocurrency", - "error_text_node_address": "Voer een iPv4-adres in", - "error_text_node_port": "Knooppuntpoort kan alleen nummers tussen 0 en 65535 bevatten", - "error_text_node_proxy_address": "Voer : in, bijvoorbeeld 127.0.0.1:9050", - "error_text_payment_id": "Betalings-ID kan alleen 16 tot 64 tekens bevatten in hexadecimale volgorde", - "error_text_xmr": "XMR-waarde kan het beschikbare saldo niet overschrijden.\nHet aantal breukcijfers moet kleiner zijn dan of gelijk zijn aan 12", - "error_text_fiat": "Waarde van bedrag kan het beschikbare saldo niet overschrijden.\nHet aantal breukcijfers moet kleiner zijn dan of gelijk zijn aan 2", - "error_text_subaddress_name": "Naam subadres mag niet bevatten ` , ' \" symbolen\nen moet tussen de 1 en 20 tekens lang zijn", - "error_text_amount": "Bedrag kan alleen cijfers bevatten", - "error_text_wallet_name": "Naam portemonnee kan alleen letters, cijfers , _ - symbolen bevatten\nen moet tussen de 1 en 33 tekens lang zijn", - "error_text_keys": "Portefeuillesleutels kunnen maximaal 64 tekens bevatten in hexadecimale volgorde", - "error_text_crypto_currency": "Het aantal breukcijfers\nmoet kleiner zijn dan of gelijk zijn aan 12", - "error_text_minimal_limit": "Ruil voor ${provider} is niet gemaakt. Bedrag is minder dan minimaal: ${min} ${currency}", - "error_text_maximum_limit": "Ruil voor ${provider} is niet gemaakt. Bedrag is meer dan maximaal: ${max} ${currency}", - "error_text_limits_loading_failed": "Ruil voor ${provider} is niet gemaakt. Beperkingen laden mislukt", - "error_text_template": "Sjabloonnaam en -adres mogen niet bevatten ` , ' \" symbolen\nen moet tussen de 1 en 106 tekens lang zijn", + "all_trades": "Alle transacties", + "all_transactions": "Alle transacties", + "alphabetical": "Alfabetisch", + "already_have_account": "Heb je al een account?", + "always": "altijd", + "amount": "Bedrag: ", + "amount_is_estimate": "Het ontvangen bedrag is een schatting", + "amount_is_guaranteed": "Het ontvangen bedrag is gegarandeerd", + "and": "en", + "anonpay_description": "Genereer ${type}. De ontvanger kan ${method} gebruiken met elke ondersteunde cryptocurrency en u ontvangt geld in deze portemonnee", + "apk_update": "APK-update", + "approve": "Goedkeuren", + "arrive_in_this_address": "${currency} ${tag}komt aan op dit adres", + "ascending": "Stijgend", + "ask_each_time": "Vraag het elke keer", "auth_store_ban_timeout": "time-out verbieden", "auth_store_banned_for": "Verboden voor ", "auth_store_banned_minutes": " notulen", "auth_store_incorrect_password": "Incorrect PIN", - "wallet_store_monero_wallet": "Monero portemonnee", - "wallet_restoration_store_incorrect_seed_length": "Onjuiste zaadlengte", - "full_balance": "Volledig saldo", - "available_balance": "Beschikbaar saldo", - "hidden_balance": "Verborgen balans", - "sync_status_syncronizing": "SYNCHRONISEREN", - "sync_status_syncronized": "SYNCHRONIZED", - "sync_status_not_connected": "NIET VERBONDEN", - "sync_status_starting_sync": "BEGINNEN MET SYNCHRONISEREN", - "sync_status_failed_connect": "LOSGEKOPPELD", - "sync_status_connecting": "AANSLUITING", - "sync_status_connected": "VERBONDEN", - "sync_status_attempting_sync": "SYNCHRONISATIE PROBEREN", - "transaction_priority_slow": "Langzaam", - "transaction_priority_regular": "Regelmatig", - "transaction_priority_medium": "Medium", - "transaction_priority_fast": "Snel", - "transaction_priority_fastest": "Snelste", - "trade_for_not_created": "Ruilen voor ${title} is niet gemaakt.", - "trade_not_created": "Handel niet gecreëerd", - "trade_id_not_found": "Handel ${tradeId} van ${title} niet gevonden.", - "trade_not_found": "Handel niet gevonden.", - "trade_state_pending": "In afwachting", - "trade_state_confirming": "Bevestiging", - "trade_state_trading": "Handel", - "trade_state_traded": "Traded", - "trade_state_complete": "Compleet", - "trade_state_to_be_created": "Om gecreëerd te worden", - "trade_state_unpaid": "Onbetaald", - "trade_state_underpaid": "Slecht betaald", - "trade_state_paid_unconfirmed": "Niet bevestigd", - "trade_state_paid": "Betaald", - "trade_state_btc_sent": "Verzonden", - "trade_state_timeout": "Time-out", - "trade_state_created": "Gemaakt", - "trade_state_finished": "Afgewerkt", - "change_language": "Verander de taal", - "change_language_to": "Verander de taal in ${language}?", - "paste": "Plakken", - "restore_from_seed_placeholder": "Voer hier uw codefrase in of plak deze", - "add_new_word": "Nieuw woord toevoegen", - "incorrect_seed": "De ingevoerde tekst is niet geldig.", - "biometric_auth_reason": "Scan uw vingerafdruk om te verifiëren", - "version": "Versie ${currentVersion}", - "extracted_address_content": "U stuurt geld naar\n${recipient_name}", - "card_address": "Adres:", - "buy": "Kopen", - "sell": "Verkopen", - "placeholder_transactions": "Uw transacties worden hier weergegeven", - "placeholder_contacts": "Je contacten worden hier weergegeven", - "template": "Sjabloon", - "confirm_delete_template": "Met deze actie wordt deze sjabloon verwijderd. Wilt u doorgaan?", - "confirm_delete_wallet": "Met deze actie wordt deze portemonnee verwijderd. Wilt u doorgaan?", - "change_wallet_alert_title": "Wijzig huidige portemonnee", - "change_wallet_alert_content": "Wilt u de huidige portemonnee wijzigen in ${wallet_name}?", - "creating_new_wallet": "Nieuwe portemonnee aanmaken", - "creating_new_wallet_error": "Fout: ${description}", - "seed_alert_title": "Aandacht", - "seed_alert_content": "Het zaad is de enige manier om uw portemonnee te herstellen. Heb je het opgeschreven?", - "seed_alert_back": "Ga terug", - "seed_alert_yes": "Ja ik heb", - "exchange_sync_alert_content": "Wacht tot uw portemonnee is gesynchroniseerd", - "pre_seed_title": "BELANGRIJK", - "pre_seed_description": "Op de volgende pagina ziet u een reeks van ${words} woorden. Dit is uw unieke en persoonlijke zaadje en het is de ENIGE manier om uw portemonnee te herstellen in geval van verlies of storing. Het is JOUW verantwoordelijkheid om het op te schrijven en op een veilige plaats op te slaan buiten de Cake Wallet app.", - "pre_seed_button_text": "Ik begrijp het. Laat me mijn zaad zien", - "xmr_to_error": "XMR.TO-fout", - "xmr_to_error_description": "Ongeldige hoeveelheid. Maximaal 8 cijfers achter de komma", - "provider_error": "${provider} fout", - "use_ssl": "Gebruik SSL", - "trusted": "vertrouwd", - "color_theme": "Kleur thema", - "light_theme": "Licht", - "bright_theme": "Helder", - "dark_theme": "Donker", - "enter_your_note": "Voer uw notitie in ...", - "note_optional": "Opmerking (optioneel)", - "note_tap_to_change": "Opmerking (tik om te wijzigen)", - "view_in_block_explorer": "View in Block Explorer", - "view_transaction_on": "View Transaction on ", - "transaction_key": "Transactiesleutel", - "confirmations": "Bevestigingen", - "recipient_address": "Adres ontvanger", - "extra_id": "Extra ID:", - "destination_tag": "Bestemmingstag:", - "memo": "Memo:", - "backup": "Back-up", - "change_password": "Wachtwoord wijzigen", - "backup_password": "Reservewachtwoord", - "write_down_backup_password": "Noteer uw back-upwachtwoord, dat wordt gebruikt voor het importeren van uw back-upbestanden.", - "export_backup": "Back-up exporteren", - "save_backup_password": "Zorg ervoor dat u uw reservewachtwoord heeft opgeslagen. Zonder dit kunt u uw back-upbestanden niet importeren.", - "backup_file": "Backup bestand", - "edit_backup_password": "Bewerk back-upwachtwoord", - "save_backup_password_alert": "Bewaar back-upwachtwoord", - "change_backup_password_alert": "Uw vorige back-upbestanden kunnen niet worden geïmporteerd met een nieuw back-upwachtwoord. Het nieuwe back-upwachtwoord wordt alleen gebruikt voor nieuwe back-upbestanden. Weet u zeker dat u het back-upwachtwoord wilt wijzigen?", - "enter_backup_password": "Voer hier een back-upwachtwoord in", - "select_backup_file": "Selecteer een back-upbestand", - "import": "Importeren", - "please_select_backup_file": "Selecteer een back-upbestand en voer een back-upwachtwoord in.", - "fixed_rate": "Vast tarief", - "fixed_rate_alert": "U kunt het ontvangen bedrag invoeren wanneer de modus voor vaste tarieven is aangevinkt. Wilt u overschakelen naar de vaste-tariefmodus?", - "xlm_extra_info": "Vergeet niet om de Memo-ID op te geven tijdens het verzenden van de XLM-transactie voor de uitwisseling", - "xrp_extra_info": "Vergeet niet om de Destination Tag op te geven tijdens het verzenden van de XRP-transactie voor de uitwisseling", - "exchange_incorrect_current_wallet_for_xmr": "Als u XMR wilt omwisselen van uw Cake Wallet Monero-saldo, moet u eerst overschakelen naar uw Monero-portemonnee.", - "confirmed": "Bevestigd saldo", - "unconfirmed": "Onbevestigd saldo", - "displayable": "Weer te geven", - "submit_request": "een verzoek indienen", - "buy_alert_content": "Momenteel ondersteunen we alleen de aankoop van Bitcoin, Ethereum, Litecoin en Monero. Maak of schakel over naar uw Bitcoin-, Ethereum-, Litecoin- of Monero-portemonnee.", - "sell_alert_content": "We ondersteunen momenteel alleen de verkoop van Bitcoin, Ethereum en Litecoin. Maak of schakel over naar uw Bitcoin-, Ethereum- of Litecoin-portemonnee.", - "outdated_electrum_wallet_description": "Nieuwe Bitcoin-portefeuilles die in Cake zijn gemaakt, hebben nu een zaadje van 24 woorden. Het is verplicht dat u een nieuwe Bitcoin-portemonnee maakt en al uw geld overmaakt naar de nieuwe portemonnee van 24 woorden, en stopt met het gebruik van wallets met een seed van 12 woorden. Doe dit onmiddellijk om uw geld veilig te stellen.", - "understand": "Ik begrijp het", - "apk_update": "APK-update", - "buy_bitcoin": "Koop Bitcoin", - "buy_with": "Koop met", - "moonpay_alert_text": "Waarde van het bedrag moet meer of gelijk zijn aan ${minAmount} ${fiatCurrency}", - "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", - "do_not_show_me": "laat me dit niet opnieuw zien", - "unspent_coins_title": "Ongebruikte munten", - "unspent_coins_details_title": "Details van niet-uitgegeven munten", - "freeze": "Bevriezen", - "frozen": "Bevroren", - "coin_control": "Muntcontrole (optioneel)", - "address_detected": "Adres gedetecteerd", - "address_from_domain": "Dit adres is van ${domain} op Unstoppable Domains", - "add_receiver": "Nog een ontvanger toevoegen (optioneel)", - "manage_yats": "Yats beheren", - "yat_alert_title": "Verzend en ontvang crypto gemakkelijker met Yat", - "yat_alert_content": "Cake Wallet-gebruikers kunnen nu al hun favoriete valuta's verzenden en ontvangen met een unieke emoji-gebaseerde gebruikersnaam.", - "get_your_yat": "Haal je Yato", - "connect_an_existing_yat": "Verbind een bestaande Yat", - "yat_address": "Yat-adres", - "yat": "Yat", - "connect_yats": "Verbind Yats", - "address_from_yat": "Dit adres is van ${emoji} op Yat", - "yat_error": "Yat fout", - "yat_error_content": "Geen adressen gekoppeld aan deze Yat. Probeer een andere Yato", - "choose_address": "\n\nKies het adres:", - "yat_popup_title": "Uw portemonnee-adres kan worden ge-emojiificeerd.", - "yat_popup_content": "Je kunt nu crypto verzenden en ontvangen in Cake Wallet met je Yat - een korte, op emoji gebaseerde gebruikersnaam. Beheer Yats op elk moment op het instellingenscherm", - "second_intro_title": "Eén emoji-adres om ze allemaal te regeren", - "second_intro_content": "Je Yat is een enkel uniek emoji-adres dat al je lange hexadecimale adressen vervangt voor al je valuta's.", - "third_intro_title": "Yat speelt leuk met anderen", - "third_intro_content": "Yats wonen ook buiten Cake Wallet. Elk portemonnee-adres op aarde kan worden vervangen door een Yat!", - "learn_more": "Kom meer te weten", - "search": "Zoekopdracht", - "search_language": "Zoektaal", - "search_currency": "Zoek valuta", - "new_template": "Nieuwe sjabloon", - "electrum_address_disclaimer": "We genereren nieuwe adressen elke keer dat u er een gebruikt, maar eerdere adressen blijven werken", - "wallet_name_exists": "Portemonnee met die naam bestaat al", - "market_place": "Marktplaats", - "cake_pay_title": "Cake Pay-cadeaubonnen", - "cake_pay_subtitle": "Koop cadeaubonnen met korting (alleen VS)", - "cake_pay_web_cards_title": "Cake Pay-webkaarten", - "cake_pay_web_cards_subtitle": "Koop wereldwijd prepaidkaarten en cadeaubonnen", - "about_cake_pay": "Met Cake Pay kunt u eenvoudig cadeaubonnen kopen met virtuele activa, die direct kunnen worden uitgegeven bij meer dan 150.000 handelaren in de Verenigde Staten.", - "cake_pay_account_note": "Meld u aan met alleen een e-mailadres om kaarten te bekijken en te kopen. Sommige zijn zelfs met korting verkrijgbaar!", - "already_have_account": "Heb je al een account?", - "create_account": "Account aanmaken", - "privacy_policy": "Privacybeleid", - "welcome_to_cakepay": "Welkom bij Cake Pay!", - "sign_up": "Aanmelden", - "forgot_password": "Wachtwoord vergeten", - "reset_password": "Wachtwoord resetten", - "gift_cards": "Cadeaubonnen", - "setup_your_debit_card": "Stel uw debetkaart in", - "no_id_required": "Geen ID vereist. Opwaarderen en overal uitgeven", - "how_to_use_card": "Hoe deze kaart te gebruiken", - "purchase_gift_card": "Cadeaubon kopen", - "verification": "Verificatie", - "fill_code": "Vul de verificatiecode in die u in uw e-mail hebt ontvangen", - "didnt_get_code": "Geen code?", - "resend_code": "Stuur het alstublieft opnieuw", - "debit_card": "Debetkaart", - "cakepay_prepaid_card": "CakePay Prepaid Debetkaart", - "no_id_needed": "Geen ID nodig!", - "frequently_asked_questions": "Veelgestelde vragen", - "debit_card_terms": "De opslag en het gebruik van uw betaalkaartnummer (en inloggegevens die overeenkomen met uw betaalkaartnummer) in deze digitale portemonnee zijn onderworpen aan de Algemene voorwaarden van de toepasselijke kaarthouderovereenkomst met de uitgever van de betaalkaart, zoals van kracht vanaf tijd tot tijd.", - "please_reference_document": "Raadpleeg de onderstaande documenten voor meer informatie.", - "cardholder_agreement": "Kaarthouderovereenkomst", - "e_sign_consent": "Toestemming e-ondertekenen", - "agree_and_continue": "Akkoord & doorgaan", - "email_address": "E-mailadres", - "agree_to": "Door een account aan te maken gaat u akkoord met de ", - "and": "en", - "enter_code": "Voer code in", - "congratulations": "gefeliciteerd!", - "you_now_have_debit_card": "Je hebt nu een debetkaart", - "min_amount": "Min: ${value}", - "max_amount": "Max: ${value}", - "enter_amount": "Voer Bedrag in", - "billing_address_info": "Als u om een ​​factuuradres wordt gevraagd, geef dan uw verzendadres op", - "order_physical_card": "Fysieke kaart bestellen", - "add_value": "Waarde toevoegen", - "activate": "Activeren", - "get_a": "Krijg een ", - "digital_and_physical_card": "digitale en fysieke prepaid debetkaart", - "get_card_note": " die u kunt herladen met digitale valuta. Geen aanvullende informatie nodig!", - "signup_for_card_accept_terms": "Meld je aan voor de kaart en accepteer de voorwaarden.", - "add_fund_to_card": "Voeg prepaid tegoed toe aan de kaarten (tot ${value})", - "use_card_info_two": "Tegoeden worden omgezet naar USD wanneer ze op de prepaid-rekening staan, niet in digitale valuta.", - "use_card_info_three": "Gebruik de digitale kaart online of met contactloze betaalmethoden.", - "optionally_order_card": "Optioneel een fysieke kaart bestellen.", - "hide_details": "Details verbergen", - "show_details": "Toon details", - "upto": "tot ${value}", - "discount": "Bespaar ${value}%", - "gift_card_amount": "Bedrag cadeaubon", - "bill_amount": "Bill bedrag", - "you_pay": "U betaalt", - "tip": "Tip:", - "custom": "aangepast", - "by_cake_pay": "door Cake Pay", - "expires": "Verloopt", - "mm": "MM", - "yy": "JJ", - "online": "online", - "offline": "Offline", - "gift_card_number": "Cadeaukaartnummer", - "pin_number": "PIN-nummer", - "total_saving": "Totale besparingen", - "last_30_days": "Laatste 30 dagen", - "avg_savings": "Gem. besparingen", - "view_all": "Alles bekijken", - "active_cards": "Actieve kaarten", - "delete_account": "Account verwijderen", - "cards": "Kaarten", - "active": "Actief", - "redeemed": "Verzilverd", - "gift_card_balance_note": "Cadeaukaarten met een resterend saldo verschijnen hier", - "gift_card_redeemed_note": "Cadeaubonnen die je hebt ingewisseld, verschijnen hier", - "logout": "Uitloggen", - "add_tip": "Tip toevoegen", - "percentageOf": "van ${amount}", - "is_percentage": "is", - "search_category": "Zoek categorie", - "mark_as_redeemed": "Markeer als ingewisseld", - "more_options": "Meer opties", - "waiting_payment_confirmation": "In afwachting van betalingsbevestiging", - "transaction_sent_notice": "Als het scherm na 1 minuut niet verder gaat, controleer dan een blokverkenner en je e-mail.", - "agree": "mee eens", - "in_store": "In winkel", - "generating_gift_card": "Cadeaubon genereren", - "payment_was_received": "Uw betaling is ontvangen.", - "proceed_after_one_minute": "Als het scherm na 1 minuut niet verder gaat, controleer dan uw e-mail.", - "order_id": "Order-ID", - "gift_card_is_generated": "Cadeaukaart is gegenereerd", - "open_gift_card": "Geschenkkaart openen", - "contact_support": "Contact opnemen met ondersteuning", - "gift_cards_unavailable": "Cadeaubonnen kunnen momenteel alleen worden gekocht via Monero, Bitcoin en Litecoin", - "background_sync_mode": "Achtergrondsynchronisatiemodus", - "sync_all_wallets": "Alle portemonnees synchroniseren", - "introducing_cake_pay": "Introductie van Cake Pay!", - "cake_pay_learn_more": "Koop en wissel cadeaubonnen direct in de app in!\nSwipe van links naar rechts voor meer informatie.", - "automatic": "automatisch", - "fixed_pair_not_supported": "Dit vaste paar wordt niet ondersteund bij de geselecteerde exchanges", - "variable_pair_not_supported": "Dit variabelenpaar wordt niet ondersteund met de geselecteerde uitwisselingen", - "none_of_selected_providers_can_exchange": "Geen van de geselecteerde providers kan deze uitwisseling maken", - "choose_one": "Kies er een", - "choose_from_available_options": "Kies uit de beschikbare opties:", - "custom_redeem_amount": "Aangepast inwisselbedrag", - "add_custom_redemption": "Voeg aangepaste inwisseling toe", - "remaining": "resterende", - "delete_wallet": "Portemonnee verwijderen", - "delete_wallet_confirm_message": "Weet u zeker dat u de portemonnee van ${wallet_name} wilt verwijderen?", - "low_fee": "Lage vergoeding", - "low_fee_alert": "U gebruikt momenteel een lage prioriteit voor netwerkkosten. Dit kan lange wachttijden, andere tarieven of geannuleerde transacties veroorzaken. We raden aan een hogere vergoeding in te stellen voor een betere ervaring.", - "ignor": "Negeren", - "use_suggested": "Gebruik aanbevolen", - "do_not_share_warning_text": "Deel deze met niemand anders, ook niet met support.\n\nUw geld kan en zal worden gestolen!", - "help": "helpen", - "all_transactions": "Alle transacties", - "all_trades": "Alle transacties", - "connection_sync": "Verbinding en synchronisatie", - "security_and_backup": "Beveiliging en back-up", - "create_backup": "Maak een back-up", - "privacy_settings": "Privacy-instellingen", - "privacy": "Privacy", - "display_settings": "Weergave-instellingen", - "other_settings": "Andere instellingen", - "require_pin_after": "Pincode vereist na", - "always": "altijd", - "minutes_to_pin_code": "${minute} minuten", - "disable_exchange": "Uitwisseling uitschakelen", - "advanced_settings": "Geavanceerde instellingen", - "settings_can_be_changed_later": "Deze instellingen kunnen later worden gewijzigd in de app-instellingen", - "add_custom_node": "Voeg een nieuw aangepast knooppunt toe", - "disable_fiat": "Schakel Fiat uit", - "fiat_api": "Fiat API", - "disabled": "Gehandicapt", - "enabled": "Ingeschakeld", - "tor_only": "Alleen Tor", - "unmatched_currencies": "De valuta van uw huidige portemonnee komt niet overeen met die van de gescande QR", - "orbot_running_alert": "Zorg ervoor dat Orbot actief is voordat u verbinding maakt met dit knooppunt.", - "contact_list_contacts": "Contacten", - "contact_list_wallets": "Mijn portefeuilles", - "bitcoin_payments_require_1_confirmation": "Bitcoin-betalingen vereisen 1 bevestiging, wat 20 minuten of langer kan duren. Dank voor uw geduld! U ontvangt een e-mail wanneer de betaling is bevestigd.", - "send_to_this_address": "Stuur ${currency} ${tag}naar dit adres", - "arrive_in_this_address": "${currency} ${tag}komt aan op dit adres", - "do_not_send": "Niet sturen", - "error_dialog_content": "Oeps, er is een fout opgetreden.\n\nStuur het crashrapport naar ons ondersteuningsteam om de applicatie te verbeteren.", - "scan_qr_code": "Scan QR-code", - "cold_or_recover_wallet": "Voeg een cold wallet toe of herstel een paper wallet", - "please_wait": "Even geduld aub", - "sweeping_wallet": "Vegende portemonnee", - "sweeping_wallet_alert": "Dit duurt niet lang. VERLAAT DIT SCHERM NIET, ANDERS KAN HET SWEPT-GELD VERLOREN WORDEN", - "decimal_places_error": "Te veel decimalen", - "edit_node": "Knooppunt bewerken", - "invoice_details": "Factuurgegevens", - "donation_link_details": "Details van de donatielink", - "anonpay_description": "Genereer ${type}. De ontvanger kan ${method} gebruiken met elke ondersteunde cryptocurrency en u ontvangt geld in deze portemonnee", - "create_invoice": "Factuur maken", - "create_donation_link": "Maak een donatielink aan", - "optional_email_hint": "Optionele kennisgeving per e-mail aan de begunstigde", - "optional_description": "Optionele beschrijving", - "optional_name": "Optionele naam ontvanger", - "clearnet_link": "Clearnet-link", - "onion_link": "Ui koppeling", - "settings": "Instellingen", - "sell_monero_com_alert_content": "Het verkopen van Monero wordt nog niet ondersteund", - "error_text_input_below_minimum_limit": "Bedrag is minder dan minimaal", - "error_text_input_above_maximum_limit": "Bedrag is meer dan maximaal", - "show_market_place": "Toon Marktplaats", - "prevent_screenshots": "Voorkom screenshots en schermopname", - "profile": "Profiel", - "close": "Dichtbij", - "modify_2fa": "Wijzig Cake 2FA", - "disable_cake_2fa": "Taart 2FA uitschakelen", - "question_to_disable_2fa": "Weet je zeker dat je Cake 2FA wilt uitschakelen? Er is geen 2FA-code meer nodig om toegang te krijgen tot de portemonnee en bepaalde functies.", - "disable": "Uitzetten", - "setup_2fa": "Opstelling Taart 2FA", - "verify_with_2fa": "Controleer met Cake 2FA", - "totp_code": "TOTP-code", - "please_fill_totp": "Vul de 8-cijferige code in die op uw andere apparaat aanwezig is", - "totp_2fa_success": "Succes! Cake 2FA ingeschakeld voor deze portemonnee. Vergeet niet om uw geheugensteuntje op te slaan voor het geval u de toegang tot de portemonnee kwijtraakt.", - "totp_verification_success": "Verificatie geslaagd!", - "totp_2fa_failure": "Foute code. Probeer een andere code of genereer een nieuwe geheime sleutel. Gebruik een compatibele 2FA-app die 8-cijferige codes en SHA512 ondersteunt.", - "enter_totp_code": "Voer de TOTP-code in.", - "add_secret_code": "Of voeg deze geheime code toe aan een authenticator-app", - "totp_secret_code": "TOTP-geheime code", - "setup_2fa_text": "Cake 2FA werkt met TOTP als tweede authenticatiefactor.\n\nCake 2FA's TOTP vereist SHA-512 en 8-cijferige ondersteuning; dit zorgt voor meer veiligheid. Meer informatie en ondersteunde apps vindt u in de gids.", - "setup_totp_recommended": "TOTP instellen", - "disable_buy": "Koopactie uitschakelen", - "disable_sell": "Verkoopactie uitschakelen", + "authenticated": "Authenticated", + "authentication": "Authenticatie", "auto_generate_subaddresses": "Automatisch subadressen genereren", - "cake_2fa_preset": "Taart 2FA Voorinstelling", - "narrow": "Smal", - "normal": "Normaal", - "aggressive": "Overijverig", - "require_for_assessing_wallet": "Vereist voor toegang tot portemonnee", - "require_for_sends_to_non_contacts": "Vereist voor verzendingen naar niet-contacten", - "require_for_sends_to_contacts": "Vereist voor verzending naar contacten", - "require_for_sends_to_internal_wallets": "Vereist voor verzendingen naar interne portefeuilles", - "require_for_exchanges_to_internal_wallets": "Vereist voor uitwisselingen naar interne portefeuilles", - "require_for_adding_contacts": "Vereist voor het toevoegen van contacten", - "require_for_creating_new_wallets": "Vereist voor het maken van nieuwe portefeuilles", - "require_for_all_security_and_backup_settings": "Vereist voor alle beveiligings- en back-upinstellingen", + "automatic": "automatisch", + "available_balance": "Beschikbaar saldo", "available_balance_description": "Beschikbaar saldo is het saldo dat u kunt uitgeven. Het kan lager zijn dan uw totale saldo als u onlangs geld hebt verzonden.", - "syncing_wallet_alert_title": "Uw portemonnee wordt gesynchroniseerd", - "syncing_wallet_alert_content": "Uw saldo- en transactielijst is mogelijk pas compleet als er bovenaan 'GESYNCHRONISEERD' staat. Klik/tik voor meer informatie.", - "home_screen_settings": "Instellingen voor het startscherm", - "sort_by": "Sorteer op", - "search_add_token": "Token zoeken / toevoegen", - "edit_token": "Token bewerken", - "warning": "Waarschuwing", - "add_token_warning": "Bewerk of voeg geen tokens toe volgens de instructies van oplichters.\nBevestig tokenadressen altijd met betrouwbare bronnen!", - "add_token_disclaimer_check": "Ik heb het adres en de informatie van het tokencontract bevestigd met behulp van een betrouwbare bron. Het toevoegen van kwaadaardige of onjuiste informatie kan leiden tot verlies van geld.", - "token_contract_address": "Token contractadres", - "token_name": "Tokennaam bijv.: Tether", - "token_symbol": "Tokensymbool bijv.: USDT", - "token_decimal": "Token decimaal", - "field_required": "dit veld is verplicht", - "pin_at_top": "speld ${token} bovenaan", - "invalid_input": "Ongeldige invoer", - "fiat_balance": "Fiat Balans", - "gross_balance": "Bruto saldo", - "alphabetical": "Alfabetisch", - "generate_name": "Naam genereren", + "avg_savings": "Gem. besparingen", + "awaitDAppProcessing": "Wacht tot de dApp klaar is met verwerken.", + "background_sync_mode": "Achtergrondsynchronisatiemodus", + "backup": "Back-up", + "backup_file": "Backup bestand", + "backup_password": "Reservewachtwoord", "balance_page": "Saldo pagina", - "share": "Deel", - "slidable": "Verschuifbaar", - "monero_dark_theme": "Monero donker thema", + "bill_amount": "Bill bedrag", + "billing_address_info": "Als u om een ​​factuuradres wordt gevraagd, geef dan uw verzendadres op", + "biometric_auth_reason": "Scan uw vingerafdruk om te verifiëren", "bitcoin_dark_theme": "Bitcoin donker thema", "bitcoin_light_theme": "Bitcoin Light-thema", - "high_contrast_theme": "Thema met hoog contrast", - "matrix_green_dark_theme": "Matrix groen donker thema", - "monero_light_theme": "Monero Light-thema", - "manage_nodes": "Beheer knooppunten", - "etherscan_history": "Etherscan-geschiedenis", - "template_name": "Sjabloonnaam", + "bitcoin_payments_require_1_confirmation": "Bitcoin-betalingen vereisen 1 bevestiging, wat 20 minuten of langer kan duren. Dank voor uw geduld! U ontvangt een e-mail wanneer de betaling is bevestigd.", + "Blocks_remaining": "${status} Resterende blokken", + "bright_theme": "Helder", + "buy": "Kopen", + "buy_alert_content": "Momenteel ondersteunen we alleen de aankoop van Bitcoin, Ethereum, Litecoin en Monero. Maak of schakel over naar uw Bitcoin-, Ethereum-, Litecoin- of Monero-portemonnee.", + "buy_bitcoin": "Koop Bitcoin", + "buy_provider_unavailable": "Provider momenteel niet beschikbaar.", + "buy_with": "Koop met", + "by_cake_pay": "door Cake Pay", + "cake_2fa_preset": "Taart 2FA Voorinstelling", + "cake_pay_account_note": "Meld u aan met alleen een e-mailadres om kaarten te bekijken en te kopen. Sommige zijn zelfs met korting verkrijgbaar!", + "cake_pay_learn_more": "Koop en wissel cadeaubonnen direct in de app in!\nSwipe van links naar rechts voor meer informatie.", + "cake_pay_subtitle": "Koop cadeaubonnen met korting (alleen VS)", + "cake_pay_title": "Cake Pay-cadeaubonnen", + "cake_pay_web_cards_subtitle": "Koop wereldwijd prepaidkaarten en cadeaubonnen", + "cake_pay_web_cards_title": "Cake Pay-webkaarten", + "cake_wallet": "Cake Wallet", + "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.", + "camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.", + "cancel": "Annuleer", + "card_address": "Adres:", + "cardholder_agreement": "Kaarthouderovereenkomst", + "cards": "Kaarten", + "chains": "Ketens", + "change": "Verandering", + "change_backup_password_alert": "Uw vorige back-upbestanden kunnen niet worden geïmporteerd met een nieuw back-upwachtwoord. Het nieuwe back-upwachtwoord wordt alleen gebruikt voor nieuwe back-upbestanden. Weet u zeker dat u het back-upwachtwoord wilt wijzigen?", + "change_currency": "Verander valuta", + "change_current_node": "Weet u zeker dat u het huidige knooppunt wilt wijzigen in ${node}?", + "change_current_node_title": "Wijzig het huidige knooppunt", + "change_exchange_provider": "Wijzig Exchange Provider", + "change_language": "Verander de taal", + "change_language_to": "Verander de taal in ${language}?", + "change_password": "Wachtwoord wijzigen", "change_rep": "Vertegenwoordiger wijzigen", "change_rep_message": "Weet u zeker dat u van vertegenwoordiger wilt veranderen?", - "unsupported_asset": "We ondersteunen deze actie niet voor dit item. Maak of schakel over naar een portemonnee van een ondersteund activatype.", - "manage_pow_nodes": "PoW-knooppunten beheren", - "support_title_live_chat": "Live ondersteuning", - "support_description_live_chat": "Gratis en snel! Getrainde ondersteuningsvertegenwoordigers zijn beschikbaar om te helpen", - "support_title_guides": "Cake -portemonnee gidsen", - "support_description_guides": "Documentatie en ondersteuning voor gemeenschappelijke problemen", - "support_title_other_links": "Andere ondersteuningslinks", - "support_description_other_links": "Word lid van onze gemeenschappen of bereik ons ​​onze partners via andere methoden", + "change_rep_successful": "Met succes veranderde vertegenwoordiger", + "change_wallet_alert_content": "Wilt u de huidige portemonnee wijzigen in ${wallet_name}?", + "change_wallet_alert_title": "Wijzig huidige portemonnee", + "choose_account": "Kies account", + "choose_address": "\n\nKies het adres:", "choose_derivation": "Kies portemonnee -afleiding", - "new_first_wallet_text": "Houd uw cryptocurrency gemakkelijk veilig", - "select_destination": "Selecteer de bestemming voor het back-upbestand.", - "save_to_downloads": "Opslaan in downloads", - "select_buy_provider_notice": "Selecteer hierboven een koopprovider. U kunt dit scherm overslaan door uw standaard kopenprovider in te stellen in app -instellingen.", - "onramper_option_description": "Koop snel crypto met veel betaalmethoden. Beschikbaar in de meeste landen. Spreads en vergoedingen variëren.", + "choose_from_available_options": "Kies uit de beschikbare opties:", + "choose_one": "Kies er een", + "choose_relay": "Kies een relais dat u wilt gebruiken", + "choose_wallet_currency": "Kies een portemonnee-valuta:", + "clear": "Duidelijk", + "clearnet_link": "Clearnet-link", + "close": "Dichtbij", + "coin_control": "Muntcontrole (optioneel)", + "cold_or_recover_wallet": "Voeg een cold wallet toe of herstel een paper wallet", + "color_theme": "Kleur thema", + "commit_transaction_amount_fee": "Verricht transactie\nBedrag: ${amount}\nhonorarium: ${fee}", + "confirm": "Bevestigen", + "confirm_delete_template": "Met deze actie wordt deze sjabloon verwijderd. Wilt u doorgaan?", + "confirm_delete_wallet": "Met deze actie wordt deze portemonnee verwijderd. Wilt u doorgaan?", + "confirm_sending": "Bevestig verzending", + "confirmations": "Bevestigingen", + "confirmed": "Bevestigd saldo", + "confirmed_tx": "Bevestigd", + "congratulations": "gefeliciteerd!", + "connect_an_existing_yat": "Verbind een bestaande Yat", + "connect_yats": "Verbind Yats", + "connection_sync": "Verbinding en synchronisatie", + "connectWalletPrompt": "Verbind uw portemonnee met WalletConnect om transacties uit te voeren", + "contact": "Contact", + "contact_list_contacts": "Contacten", + "contact_list_wallets": "Mijn portefeuilles", + "contact_name": "Contactnaam", + "contact_support": "Contact opnemen met ondersteuning", + "continue_text": "Doorgaan met", + "contractName": "Contractnaam", + "contractSymbol": "Contractsymbool", + "copied_key_to_clipboard": "Gekopieerd ${key} naar het klembord", + "copied_to_clipboard": "Gekopieerd naar het klembord", + "copy": "Kopiëren", + "copy_address": "Adres kopiëren", + "copy_id": "ID kopiëren", + "copyWalletConnectLink": "Kopieer de WalletConnect-link van dApp en plak deze hier", + "create_account": "Account aanmaken", + "create_backup": "Maak een back-up", + "create_donation_link": "Maak een donatielink aan", + "create_invoice": "Factuur maken", + "create_new": "Maak een nieuwe portemonnee", + "create_new_account": "Creëer een nieuw account", + "creating_new_wallet": "Nieuwe portemonnee aanmaken", + "creating_new_wallet_error": "Fout: ${description}", + "creation_date": "Aanmaakdatum", + "custom": "aangepast", + "custom_drag": "Custom (vasthouden en slepen)", + "custom_redeem_amount": "Aangepast inwisselbedrag", + "dark_theme": "Donker", + "debit_card": "Debetkaart", + "debit_card_terms": "De opslag en het gebruik van uw betaalkaartnummer (en inloggegevens die overeenkomen met uw betaalkaartnummer) in deze digitale portemonnee zijn onderworpen aan de Algemene voorwaarden van de toepasselijke kaarthouderovereenkomst met de uitgever van de betaalkaart, zoals van kracht vanaf tijd tot tijd.", + "decimal_places_error": "Te veel decimalen", "default_buy_provider": "Standaard Koopprovider", - "ask_each_time": "Vraag het elke keer", - "buy_provider_unavailable": "Provider momenteel niet beschikbaar.", - "signTransaction": "Transactie ondertekenen", + "default_sell_provider": "Standaard verkoopaanbieder", + "delete": "Delete", + "delete_account": "Account verwijderen", + "delete_wallet": "Portemonnee verwijderen", + "delete_wallet_confirm_message": "Weet u zeker dat u de portemonnee van ${wallet_name} wilt verwijderen?", + "deleteConnectionConfirmationPrompt": "Weet u zeker dat u de verbinding met", + "descending": "Aflopend", + "description": "Beschrijving", + "destination_tag": "Bestemmingstag:", + "dfx_option_description": "Koop crypto met EUR & CHF. Tot 990€ zonder extra KYC. Voor particuliere en zakelijke klanten in Europa", + "didnt_get_code": "Geen code?", + "digit_pin": "-cijferige PIN", + "digital_and_physical_card": "digitale en fysieke prepaid debetkaart", + "disable": "Uitzetten", + "disable_buy": "Koopactie uitschakelen", + "disable_cake_2fa": "Taart 2FA uitschakelen", + "disable_exchange": "Uitwisseling uitschakelen", + "disable_fiat": "Schakel Fiat uit", + "disable_sell": "Verkoopactie uitschakelen", + "disabled": "Gehandicapt", + "discount": "Bespaar ${value}%", + "display_settings": "Weergave-instellingen", + "displayable": "Weer te geven", + "do_not_have_enough_gas_asset": "U heeft niet genoeg ${currency} om een transactie uit te voeren met de huidige blockchain-netwerkomstandigheden. U heeft meer ${currency} nodig om blockchain-netwerkkosten te betalen, zelfs als u een ander item verzendt.", + "do_not_send": "Niet sturen", + "do_not_share_warning_text": "Deel deze met niemand anders, ook niet met support.\n\nUw geld kan en zal worden gestolen!", + "do_not_show_me": "laat me dit niet opnieuw zien", + "domain_looks_up": "Domein opzoeken", + "donation_link_details": "Details van de donatielink", + "e_sign_consent": "Toestemming e-ondertekenen", + "edit": "Bewerk", + "edit_backup_password": "Bewerk back-upwachtwoord", + "edit_node": "Knooppunt bewerken", + "edit_token": "Token bewerken", + "electrum_address_disclaimer": "We genereren nieuwe adressen elke keer dat u er een gebruikt, maar eerdere adressen blijven werken", + "email_address": "E-mailadres", + "enabled": "Ingeschakeld", + "enter_amount": "Voer Bedrag in", + "enter_backup_password": "Voer hier een back-upwachtwoord in", + "enter_code": "Voer code in", + "enter_seed_phrase": "Voer uw zaadzin in", + "enter_totp_code": "Voer de TOTP-code in.", + "enter_your_note": "Voer uw notitie in ...", + "enter_your_pin": "Voer uw pincode in", + "enter_your_pin_again": "Voer uw PIN opnieuw in", + "enterTokenID": "Voer de token-ID in", + "enterWalletConnectURI": "Voer WalletConnect-URI in", + "error": "Fout", + "error_dialog_content": "Oeps, er is een fout opgetreden.\n\nStuur het crashrapport naar ons ondersteuningsteam om de applicatie te verbeteren.", + "error_text_account_name": "Accountnaam mag alleen letters, cijfers bevatten\nen moet tussen de 1 en 15 tekens lang zijn", + "error_text_address": "Portemonnee-adres moet overeenkomen met het type\nvan cryptocurrency", + "error_text_amount": "Bedrag kan alleen cijfers bevatten", + "error_text_contact_name": "Naam contactpersoon kan niet bevatten ` , ' \" symbolen\nen moet tussen de 1 en 32 tekens lang zijn", + "error_text_crypto_currency": "Het aantal breukcijfers\nmoet kleiner zijn dan of gelijk zijn aan 12", + "error_text_fiat": "Waarde van bedrag kan het beschikbare saldo niet overschrijden.\nHet aantal breukcijfers moet kleiner zijn dan of gelijk zijn aan 2", + "error_text_input_above_maximum_limit": "Bedrag is meer dan maximaal", + "error_text_input_below_minimum_limit": "Bedrag is minder dan minimaal", + "error_text_keys": "Portefeuillesleutels kunnen maximaal 64 tekens bevatten in hexadecimale volgorde", + "error_text_limits_loading_failed": "Ruil voor ${provider} is niet gemaakt. Beperkingen laden mislukt", + "error_text_maximum_limit": "Ruil voor ${provider} is niet gemaakt. Bedrag is meer dan maximaal: ${max} ${currency}", + "error_text_minimal_limit": "Ruil voor ${provider} is niet gemaakt. Bedrag is minder dan minimaal: ${min} ${currency}", + "error_text_node_address": "Voer een iPv4-adres in", + "error_text_node_port": "Knooppuntpoort kan alleen nummers tussen 0 en 65535 bevatten", + "error_text_node_proxy_address": "Voer : in, bijvoorbeeld 127.0.0.1:9050", + "error_text_payment_id": "Betalings-ID kan alleen 16 tot 64 tekens bevatten in hexadecimale volgorde", + "error_text_subaddress_name": "Naam subadres mag niet bevatten ` , ' \" symbolen\nen moet tussen de 1 en 20 tekens lang zijn", + "error_text_template": "Sjabloonnaam en -adres mogen niet bevatten ` , ' \" symbolen\nen moet tussen de 1 en 106 tekens lang zijn", + "error_text_wallet_name": "Naam portemonnee kan alleen letters, cijfers , _ - symbolen bevatten\nen moet tussen de 1 en 33 tekens lang zijn", + "error_text_xmr": "XMR-waarde kan het beschikbare saldo niet overschrijden.\nHet aantal breukcijfers moet kleiner zijn dan of gelijk zijn aan 12", "errorGettingCredentials": "Mislukt: fout bij het ophalen van inloggegevens", "errorSigningTransaction": "Er is een fout opgetreden tijdens het ondertekenen van de transactie", - "pairingInvalidEvent": "Koppelen Ongeldige gebeurtenis", - "chains": "Ketens", - "methods": "Methoden", - "events": "Evenementen", - "reject": "Afwijzen", - "approve": "Goedkeuren", - "expiresOn": "Verloopt op", - "walletConnect": "WalletConnect", - "nullURIError": "URI is nul", - "connectWalletPrompt": "Verbind uw portemonnee met WalletConnect om transacties uit te voeren", - "newConnection": "Nieuwe verbinding", - "activeConnectionsPrompt": "Actieve verbindingen worden hier weergegeven", - "deleteConnectionConfirmationPrompt": "Weet u zeker dat u de verbinding met", + "estimated": "Geschatte", + "etherscan_history": "Etherscan-geschiedenis", "event": "Evenement", - "successful": "Succesvol", - "wouoldLikeToConnect": "wil graag verbinden", - "message": "Bericht", - "do_not_have_enough_gas_asset": "U heeft niet genoeg ${currency} om een transactie uit te voeren met de huidige blockchain-netwerkomstandigheden. U heeft meer ${currency} nodig om blockchain-netwerkkosten te betalen, zelfs als u een ander item verzendt.", - "totp_auth_url": "TOTP AUTH-URL", - "awaitDAppProcessing": "Wacht tot de dApp klaar is met verwerken.", - "copyWalletConnectLink": "Kopieer de WalletConnect-link van dApp en plak deze hier", - "enterWalletConnectURI": "Voer WalletConnect-URI in", - "seed_key": "Zaadsleutel", - "enter_seed_phrase": "Voer uw zaadzin in", - "change_rep_successful": "Met succes veranderde vertegenwoordiger", - "add_contact": "Contactpersoon toevoegen", + "events": "Evenementen", + "exchange": "Uitwisseling", + "exchange_incorrect_current_wallet_for_xmr": "Als u XMR wilt omwisselen van uw Cake Wallet Monero-saldo, moet u eerst overschakelen naar uw Monero-portemonnee.", + "exchange_new_template": "Nieuwe sjabloon", "exchange_provider_unsupported": "${providerName} wordt niet langer ondersteund!", - "domain_looks_up": "Domein opzoeken", - "require_for_exchanges_to_external_wallets": "Vereist voor uitwisselingen naar externe portemonnees", - "camera_permission_is_required": "Cameratoestemming is vereist.\nSchakel dit in via de app-instellingen.", - "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw", - "order_by": "Bestellen door", - "creation_date": "Aanmaakdatum", + "exchange_result_confirm": "Door op bevestigen te drukken, wordt u verzonden ${fetchingLabel} ${from} uit je portemonnee genoemd ${walletName} naar het onderstaande adres. Of u kunt vanuit uw externe portemonnee naar het onderstaande adres verzenden / QR-code sturen.\n\nDruk op bevestigen om door te gaan of terug te gaan om de bedragen te wijzigen.", + "exchange_result_description": "U moet minimaal ${fetchingLabel} ${from} verzenden naar het adres dat op de volgende pagina wordt weergegeven. Als u een bedrag verzendt dat lager is dan ${fetchingLabel} ${from}, wordt het mogelijk niet omgezet en wordt het mogelijk niet terugbetaald.", + "exchange_result_write_down_ID": "*Kopieer of noteer uw hierboven getoonde ID.", + "exchange_result_write_down_trade_id": "Kopieer of noteer de handels-ID om door te gaan.", + "exchange_sync_alert_content": "Wacht tot uw portemonnee is gesynchroniseerd", + "expired": "Verlopen", + "expires": "Verloopt", + "expiresOn": "Verloopt op", + "export_backup": "Back-up exporteren", + "extra_id": "Extra ID:", + "extracted_address_content": "U stuurt geld naar\n${recipient_name}", + "failed_authentication": "Mislukte authenticatie. ${state_error}", + "faq": "FAQ", + "fetching": "Ophalen", + "fiat_api": "Fiat API", + "fiat_balance": "Fiat Balans", + "field_required": "dit veld is verplicht", + "fill_code": "Vul de verificatiecode in die u in uw e-mail hebt ontvangen", + "filter_by": "Filteren op", + "first_wallet_text": "Geweldige portemonnee voor Monero, Bitcoin, Ethereum, Litecoin, en Haven", + "fixed_pair_not_supported": "Dit vaste paar wordt niet ondersteund bij de geselecteerde exchanges", + "fixed_rate": "Vast tarief", + "fixed_rate_alert": "U kunt het ontvangen bedrag invoeren wanneer de modus voor vaste tarieven is aangevinkt. Wilt u overschakelen naar de vaste-tariefmodus?", + "forgot_password": "Wachtwoord vergeten", + "freeze": "Bevriezen", + "frequently_asked_questions": "Veelgestelde vragen", + "frozen": "Bevroren", + "full_balance": "Volledig saldo", + "generate_name": "Naam genereren", + "generating_gift_card": "Cadeaubon genereren", + "get_a": "Krijg een ", + "get_card_note": " die u kunt herladen met digitale valuta. Geen aanvullende informatie nodig!", + "get_your_yat": "Haal je Yato", + "gift_card_amount": "Bedrag cadeaubon", + "gift_card_balance_note": "Cadeaukaarten met een resterend saldo verschijnen hier", + "gift_card_is_generated": "Cadeaukaart is gegenereerd", + "gift_card_number": "Cadeaukaartnummer", + "gift_card_redeemed_note": "Cadeaubonnen die je hebt ingewisseld, verschijnen hier", + "gift_cards": "Cadeaubonnen", + "gift_cards_unavailable": "Cadeaubonnen kunnen momenteel alleen worden gekocht via Monero, Bitcoin en Litecoin", + "got_it": "Ik snap het", + "gross_balance": "Bruto saldo", "group_by_type": "Groep voor type", - "importNFTs": "NFT's importeren", - "noNFTYet": "Nog geen NFT's", - "address": "Adres", - "enterTokenID": "Voer de token-ID in", - "tokenID": "ID kaart", - "name": "Naam", - "symbol": "Symbool", - "seed_phrase_length": "Lengte van de zaadzin", - "unavailable_balance": "Onbeschikbaar saldo", - "unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.", - "unspent_change": "Wijziging", - "tor_connection": "Tor-verbinding", - "setup_warning_2fa_text": "U moet uw portemonnee herstellen vanuit het geheugensteuntje.\n\nCake Support kan u niet helpen als u de toegang tot uw 2FA- of mnemonic-zaden verliest.\nCake 2FA is een tweede authenticatie voor bepaalde acties in de portemonnee. Voordat u Cake 2FA gebruikt, raden wij u aan de handleiding door te lezen.Het is NIET zo veilig als koude opslag.\n\nAls u de toegang tot uw 2FA-app of TOTP-sleutels verliest, verliest u de toegang tot deze portemonnee. ", - "scan_qr_on_device": "Scan deze QR-code op een ander apparaat", + "haven_app": "Haven by Cake Wallet", + "haven_app_wallet_text": "Awesome wallet for Haven", + "help": "helpen", + "hidden_balance": "Verborgen balans", + "hide_details": "Details verbergen", + "high_contrast_theme": "Thema met hoog contrast", + "home_screen_settings": "Instellingen voor het startscherm", "how_to_use": "Hoe te gebruiken", + "how_to_use_card": "Hoe deze kaart te gebruiken", + "id": "ID: ", + "ignor": "Negeren", + "import": "Importeren", + "importNFTs": "NFT's importeren", + "in_store": "In winkel", + "incoming": "inkomend", + "incorrect_seed": "De ingevoerde tekst is niet geldig.", + "introducing_cake_pay": "Introductie van Cake Pay!", + "invalid_input": "Ongeldige invoer", + "invoice_details": "Factuurgegevens", + "is_percentage": "is", + "last_30_days": "Laatste 30 dagen", + "learn_more": "Kom meer te weten", + "light_theme": "Licht", + "loading_your_wallet": "Uw portemonnee laden", + "login": "Log in", + "logout": "Uitloggen", + "low_fee": "Lage vergoeding", + "low_fee_alert": "U gebruikt momenteel een lage prioriteit voor netwerkkosten. Dit kan lange wachttijden, andere tarieven of geannuleerde transacties veroorzaken. We raden aan een hogere vergoeding in te stellen voor een betere ervaring.", + "manage_nodes": "Beheer knooppunten", + "manage_pow_nodes": "PoW-knooppunten beheren", + "manage_yats": "Yats beheren", + "mark_as_redeemed": "Markeer als ingewisseld", + "market_place": "Marktplaats", + "matrix_green_dark_theme": "Matrix groen donker thema", + "max_amount": "Max: ${value}", + "max_value": "Max: ${value} ${currency}", + "memo": "Memo:", + "message": "Bericht", + "methods": "Methoden", + "min_amount": "Min: ${value}", + "min_value": "Min: ${value} ${currency}", + "minutes_to_pin_code": "${minute} minuten", + "mm": "MM", + "modify_2fa": "Wijzig Cake 2FA", + "monero_com": "Monero.com by Cake Wallet", + "monero_com_wallet_text": "Awesome wallet for Monero", + "monero_dark_theme": "Monero donker thema", + "monero_light_theme": "Monero Light-thema", + "moonpay_alert_text": "Waarde van het bedrag moet meer of gelijk zijn aan ${minAmount} ${fiatCurrency}", + "more_options": "Meer opties", + "name": "Naam", + "narrow": "Smal", + "new_first_wallet_text": "Houd uw cryptocurrency gemakkelijk veilig", + "new_node_testing": "Nieuwe knooppunttest", + "new_subaddress_create": "Creëren", + "new_subaddress_label_name": "Label naam", + "new_subaddress_title": "Nieuw adres", + "new_template": "Nieuwe sjabloon", + "new_wallet": "Nieuwe portemonnee", + "newConnection": "Nieuwe verbinding", + "no_id_needed": "Geen ID nodig!", + "no_id_required": "Geen ID vereist. Opwaarderen en overal uitgeven", + "no_relay_on_domain": "Er is geen relay voor het domein van de gebruiker of de relay is niet beschikbaar. Kies een relais dat u wilt gebruiken.", + "no_relays": "Geen relais", + "no_relays_message": "We hebben een Nostr NIP-05-record voor deze gebruiker gevonden, maar deze bevat geen relays. Instrueer de ontvanger om relays toe te voegen aan zijn Nostr-record.", + "node_address": "Knooppunt adres", + "node_connection_failed": "De verbinding is mislukt", + "node_connection_successful": "Verbinding is gelukt", + "node_new": "Nieuw knooppunt", + "node_port": "Knooppunt poort", + "node_reset_settings_title": "Reset instellingen", + "node_test": "Test", + "nodes": "Knooppunten", + "nodes_list_reset_to_default_message": "Weet u zeker dat u de standaardinstellingen wilt herstellen?", + "none_of_selected_providers_can_exchange": "Geen van de geselecteerde providers kan deze uitwisseling maken", + "noNFTYet": "Nog geen NFT's", + "normal": "Normaal", + "note_optional": "Opmerking (optioneel)", + "note_tap_to_change": "Opmerking (tik om te wijzigen)", + "nullURIError": "URI is nul", + "offer_expires_in": "Aanbieding verloopt over: ", + "offline": "Offline", + "ok": "OK", + "onion_link": "Ui koppeling", + "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", + "optional_description": "Optionele beschrijving", + "optional_email_hint": "Optionele kennisgeving per e-mail aan de begunstigde", + "optional_name": "Optionele naam ontvanger", + "optionally_order_card": "Optioneel een fysieke kaart bestellen.", + "orbot_running_alert": "Zorg ervoor dat Orbot actief is voordat u verbinding maakt met dit knooppunt.", + "order_by": "Bestellen door", + "order_id": "Order-ID", + "order_physical_card": "Fysieke kaart bestellen", + "other_settings": "Andere instellingen", + "outdated_electrum_wallet_description": "Nieuwe Bitcoin-portefeuilles die in Cake zijn gemaakt, hebben nu een zaadje van 24 woorden. Het is verplicht dat u een nieuwe Bitcoin-portemonnee maakt en al uw geld overmaakt naar de nieuwe portemonnee van 24 woorden, en stopt met het gebruik van wallets met een seed van 12 woorden. Doe dit onmiddellijk om uw geld veilig te stellen.", + "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", + "overwrite_amount": "Overwrite amount", + "pairingInvalidEvent": "Koppelen Ongeldige gebeurtenis", + "password": "Wachtwoord", + "paste": "Plakken", + "pause_wallet_creation": "De mogelijkheid om Haven Wallet te maken is momenteel onderbroken.", + "payment_id": "Betaling ID: ", + "payment_was_received": "Uw betaling is ontvangen.", + "pending": " (in afwachting)", + "percentageOf": "van ${amount}", + "pin_at_top": "speld ${token} bovenaan", + "pin_is_incorrect": "PIN is onjuist", + "pin_number": "PIN-nummer", + "placeholder_contacts": "Je contacten worden hier weergegeven", + "placeholder_transactions": "Uw transacties worden hier weergegeven", + "please_fill_totp": "Vul de 8-cijferige code in die op uw andere apparaat aanwezig is", + "please_make_selection": "Maak hieronder uw keuze tot maak of herstel je portemonnee.", + "please_reference_document": "Raadpleeg de onderstaande documenten voor meer informatie.", + "please_select": "Selecteer alstublieft:", + "please_select_backup_file": "Selecteer een back-upbestand en voer een back-upwachtwoord in.", + "please_try_to_connect_to_another_node": "Probeer verbinding te maken met een ander knooppunt", + "please_wait": "Even geduld aub", + "polygonscan_history": "PolygonScan-geschiedenis", + "powered_by": "Aangedreven door ${title}", + "pre_seed_button_text": "Ik begrijp het. Laat me mijn zaad zien", + "pre_seed_description": "Op de volgende pagina ziet u een reeks van ${words} woorden. Dit is uw unieke en persoonlijke zaadje en het is de ENIGE manier om uw portemonnee te herstellen in geval van verlies of storing. Het is JOUW verantwoordelijkheid om het op te schrijven en op een veilige plaats op te slaan buiten de Cake Wallet app.", + "pre_seed_title": "BELANGRIJK", + "prevent_screenshots": "Voorkom screenshots en schermopname", + "privacy": "Privacy", + "privacy_policy": "Privacybeleid", + "privacy_settings": "Privacy-instellingen", + "private_key": "Prive sleutel", + "proceed_after_one_minute": "Als het scherm na 1 minuut niet verder gaat, controleer dan uw e-mail.", + "profile": "Profiel", + "provider_error": "${provider} fout", + "public_key": "Publieke sleutel", + "purchase_gift_card": "Cadeaubon kopen", + "qr_fullscreen": "Tik om de QR-code op volledig scherm te openen", + "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", + "question_to_disable_2fa": "Weet je zeker dat je Cake 2FA wilt uitschakelen? Er is geen 2FA-code meer nodig om toegang te krijgen tot de portemonnee en bepaalde functies.", + "receivable_balance": "Het saldo", + "receive": "Krijgen", + "receive_amount": "Bedrag", + "received": "Ontvangen", + "recipient_address": "Adres ontvanger", + "reconnect": "Sluit", + "reconnect_alert_text": "Weet u zeker dat u opnieuw verbinding wilt maken?", + "reconnection": "Reconnection", + "redeemed": "Verzilverd", + "refund_address": "Adres voor terugbetaling", + "reject": "Afwijzen", + "remaining": "resterende", + "remove": "Verwijderen", + "remove_node": "Knoop verwijderen", + "remove_node_message": "Weet u zeker dat u het geselecteerde knooppunt wilt verwijderen?", + "rename": "Hernoemen", + "require_for_adding_contacts": "Vereist voor het toevoegen van contacten", + "require_for_all_security_and_backup_settings": "Vereist voor alle beveiligings- en back-upinstellingen", + "require_for_assessing_wallet": "Vereist voor toegang tot portemonnee", + "require_for_creating_new_wallets": "Vereist voor het maken van nieuwe portefeuilles", + "require_for_exchanges_to_external_wallets": "Vereist voor uitwisselingen naar externe portemonnees", + "require_for_exchanges_to_internal_wallets": "Vereist voor uitwisselingen naar interne portefeuilles", + "require_for_sends_to_contacts": "Vereist voor verzending naar contacten", + "require_for_sends_to_internal_wallets": "Vereist voor verzendingen naar interne portefeuilles", + "require_for_sends_to_non_contacts": "Vereist voor verzendingen naar niet-contacten", + "require_pin_after": "Pincode vereist na", + "rescan": "Opnieuw scannen", + "resend_code": "Stuur het alstublieft opnieuw", + "reset": "Reset", + "reset_password": "Wachtwoord resetten", + "restore_active_seed": "Actief zaad", + "restore_address": "Adres", + "restore_bitcoin_description_from_keys": "Herstel uw portemonnee van de gegenereerde WIF-string van uw privésleutels", + "restore_bitcoin_description_from_seed": "Herstel uw portemonnee met een combinatiecode van 24 woorden", + "restore_bitcoin_title_from_keys": "Herstel van WIF", + "restore_description_from_backup": "Je kunt de hele Cake Wallet-app herstellen van uw back-upbestand", + "restore_description_from_keys": "Herstel uw portemonnee van gegenereerd toetsaanslagen opgeslagen van uw privésleutels", + "restore_description_from_seed": "Herstel uw portemonnee van het 25 woord of 13 woord combinatiecode", + "restore_description_from_seed_keys": "Ontvang uw portemonnee terug uit seed / keys die u hebt opgeslagen op een veilige plaats", + "restore_from_date_or_blockheight": "Voer een datum in een paar dagen voordat u deze portemonnee heeft gemaakt. Of als u de blokhoogte kent, voert u deze in", + "restore_from_seed_placeholder": "Voer hier uw codefrase in of plak deze", + "restore_new_seed": "Nieuw zaad", + "restore_next": "Volgende", + "restore_recover": "Herstellen", + "restore_restore_wallet": "Portemonnee herstellen", + "restore_seed_keys_restore": "Zaad / sleutels herstellen", + "restore_spend_key_private": "Sleutel uitgeven (privaat)", + "restore_title_from_backup": "Herstellen vanuit een back-upbestand", + "restore_title_from_keys": "Herstel van sleutels", + "restore_title_from_seed": "Herstel van zaad", + "restore_title_from_seed_keys": "Herstel van zaad / sleutels", + "restore_view_key_private": "Bekijk sleutel (privaat)", + "restore_wallet": "Portemonnee herstellen", + "restore_wallet_name": "Portemonnee naam", + "restore_wallet_restore_description": "Portemonnee-herstelbeschrijving", + "router_no_route": "Geen route gedefinieerd voor ${name}", + "save": "Opslaan", + "save_backup_password": "Zorg ervoor dat u uw reservewachtwoord heeft opgeslagen. Zonder dit kunt u uw back-upbestanden niet importeren.", + "save_backup_password_alert": "Bewaar back-upwachtwoord", + "save_to_downloads": "Opslaan in downloads", + "saved_the_trade_id": "Ik heb de ruil-ID opgeslagen", + "scan_qr_code": "Scan QR-code", + "scan_qr_code_to_get_address": "Scan de QR-code om het adres te krijgen", + "scan_qr_on_device": "Scan deze QR-code op een ander apparaat", + "search": "Zoekopdracht", + "search_add_token": "Token zoeken / toevoegen", + "search_category": "Zoek categorie", + "search_currency": "Zoek valuta", + "search_language": "Zoektaal", + "second_intro_content": "Je Yat is een enkel uniek emoji-adres dat al je lange hexadecimale adressen vervangt voor al je valuta's.", + "second_intro_title": "Eén emoji-adres om ze allemaal te regeren", + "security_and_backup": "Beveiliging en back-up", + "seed_alert_back": "Ga terug", + "seed_alert_content": "Het zaad is de enige manier om uw portemonnee te herstellen. Heb je het opgeschreven?", + "seed_alert_title": "Aandacht", + "seed_alert_yes": "Ja ik heb", + "seed_choose": "Kies een starttaal", "seed_hex_form": "Portemonnee zaad (hexvorm)", + "seed_key": "Zaadsleutel", + "seed_language": "Zaadtaal", + "seed_language_chinese": "Chinese", + "seed_language_chinese_traditional": "Chinese (traditionele)", + "seed_language_czech": "Tsjechisch", + "seed_language_dutch": "Nederlands", + "seed_language_english": "Engels", + "seed_language_french": "Frans", + "seed_language_german": "Duitse", + "seed_language_italian": "Italiaans", + "seed_language_japanese": "Japans", + "seed_language_korean": "Koreaans", + "seed_language_next": "Volgende", + "seed_language_portuguese": "Portugees", + "seed_language_russian": "Russisch", + "seed_language_spanish": "Spaans", + "seed_phrase_length": "Lengte van de zaadzin", + "seed_reminder": "Schrijf deze op voor het geval u uw telefoon kwijtraakt of veegt", + "seed_share": "Deel zaad", + "seed_title": "Zaad", "seedtype": "Zaadtype", "seedtype_legacy": "Legacy (25 woorden)", "seedtype_polyseed": "Polyseed (16 woorden)", - "seed_language_czech": "Tsjechisch", - "seed_language_korean": "Koreaans", - "ascending": "Stijgend", - "descending": "Aflopend", - "seed_language_chinese_traditional": "Chinese (traditionele)", - "dfx_option_description": "Koop crypto met EUR & CHF. Tot 990€ zonder extra KYC. Voor particuliere en zakelijke klanten in Europa", - "polygonscan_history": "PolygonScan-geschiedenis", - "wallet_seed_legacy": "Legacy portemonnee zaad", - "default_sell_provider": "Standaard verkoopaanbieder", + "select_backup_file": "Selecteer een back-upbestand", + "select_buy_provider_notice": "Selecteer hierboven een koopprovider. U kunt dit scherm overslaan door uw standaard kopenprovider in te stellen in app -instellingen.", + "select_destination": "Selecteer de bestemming voor het back-upbestand.", "select_sell_provider_notice": "Selecteer hierboven een verkoopaanbieder. U kunt dit scherm overslaan door uw standaardverkoopprovider in te stellen in de app-instellingen.", - "custom_drag": "Custom (vasthouden en slepen)", + "sell": "Verkopen", + "sell_alert_content": "We ondersteunen momenteel alleen de verkoop van Bitcoin, Ethereum en Litecoin. Maak of schakel over naar uw Bitcoin-, Ethereum- of Litecoin-portemonnee.", + "sell_monero_com_alert_content": "Het verkopen van Monero wordt nog niet ondersteund", + "send": "Sturen", + "send_address": "${cryptoCurrency}-adres", + "send_amount": "Bedrag:", + "send_creating_transaction": "Transactie maken", + "send_error_currency": "Valuta kan alleen cijfers bevatten", + "send_error_minimum_value": "Minimale waarde van bedrag is 0,01", + "send_estimated_fee": "Geschatte vergoeding:", + "send_fee": "Vergoeding:", + "send_name": "Naam", + "send_new": "Nieuw", + "send_payment_id": "Betaling ID (facultatief)", + "send_priority": "Momenteel is de vergoeding vastgesteld op ${transactionPriority} prioriteit.\nTransactieprioriteit kan worden aangepast in de instellingen", + "send_sending": "Bezig met verzenden...", + "send_success": "Uw ${crypto} is succesvol verzonden", + "send_templates": "Sjablonen", + "send_title": "Stuur", + "send_to_this_address": "Stuur ${currency} ${tag}naar dit adres", + "send_xmr": "Sturen XMR", + "send_your_wallet": "Uw portemonnee", + "sending": "Bezig met verzenden", + "sent": "Verzonden", + "settings": "Instellingen", + "settings_all": "ALLE", + "settings_allow_biometrical_authentication": "Biometrische authenticatie toestaan", + "settings_can_be_changed_later": "Deze instellingen kunnen later worden gewijzigd in de app-instellingen", + "settings_change_language": "Verander de taal", + "settings_change_pin": "Verander pincode", + "settings_currency": "Valuta", + "settings_current_node": "Huidige knooppunt", + "settings_dark_mode": "Donkere modus", + "settings_display_balance": "Saldo weergeven", + "settings_display_on_dashboard_list": "Weergeven op dashboardlijst", + "settings_fee_priority": "Tariefprioriteit", + "settings_nodes": "knooppunten", + "settings_none": "Geen", + "settings_only_trades": "Alleen handel", + "settings_only_transactions": "Alleen transacties", + "settings_personal": "Persoonlijk", + "settings_save_recipient_address": "Adres ontvanger opslaan", + "settings_support": "Ondersteuning", + "settings_terms_and_conditions": "Voorwaarden", + "settings_title": "Instellingen", + "settings_trades": "Trades", + "settings_transactions": "Transacties", + "settings_wallets": "Portemonnee", + "setup_2fa": "Opstelling Taart 2FA", + "setup_2fa_text": "Cake 2FA werkt met TOTP als tweede authenticatiefactor.\n\nCake 2FA's TOTP vereist SHA-512 en 8-cijferige ondersteuning; dit zorgt voor meer veiligheid. Meer informatie en ondersteunde apps vindt u in de gids.", + "setup_pin": "PIN instellen", + "setup_successful": "Uw PIN is succesvol ingesteld!", + "setup_totp_recommended": "TOTP instellen", + "setup_warning_2fa_text": "U moet uw portemonnee herstellen vanuit het geheugensteuntje.\n\nCake Support kan u niet helpen als u de toegang tot uw 2FA- of mnemonic-zaden verliest.\nCake 2FA is een tweede authenticatie voor bepaalde acties in de portemonnee. Voordat u Cake 2FA gebruikt, raden wij u aan de handleiding door te lezen.Het is NIET zo veilig als koude opslag.\n\nAls u de toegang tot uw 2FA-app of TOTP-sleutels verliest, verliest u de toegang tot deze portemonnee. ", + "setup_your_debit_card": "Stel uw debetkaart in", + "share": "Deel", + "share_address": "Deel adres", + "show_details": "Toon details", + "show_keys": "Toon zaad/sleutels", + "show_market_place": "Toon Marktplaats", + "show_seed": "Toon zaad", + "sign_up": "Aanmelden", + "signTransaction": "Transactie ondertekenen", + "signup_for_card_accept_terms": "Meld je aan voor de kaart en accepteer de voorwaarden.", + "slidable": "Verschuifbaar", + "sort_by": "Sorteer op", + "spend_key_private": "Sleutel uitgeven (privaat)", + "spend_key_public": "Sleutel uitgeven (openbaar)", + "status": "Staat: ", + "subaddress_title": "Subadreslijst", + "subaddresses": "Subadressen", + "submit_request": "een verzoek indienen", + "successful": "Succesvol", + "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_live_chat": "Live ondersteuning", + "support_title_other_links": "Andere ondersteuningslinks", + "sweeping_wallet": "Vegende portemonnee", + "sweeping_wallet_alert": "Dit duurt niet lang. VERLAAT DIT SCHERM NIET, ANDERS KAN HET SWEPT-GELD VERLOREN WORDEN", + "switchToETHWallet": "Schakel over naar een Ethereum-portemonnee en probeer het opnieuw", "switchToEVMCompatibleWallet": "Schakel over naar een EVM-compatibele portemonnee en probeer het opnieuw (Ethereum, Polygon)", - "receivable_balance": "Het saldo", - "confirmed_tx": "Bevestigd", + "symbol": "Symbool", + "sync_all_wallets": "Alle portemonnees synchroniseren", + "sync_status_attempting_sync": "SYNCHRONISATIE PROBEREN", + "sync_status_connected": "VERBONDEN", + "sync_status_connecting": "AANSLUITING", + "sync_status_failed_connect": "LOSGEKOPPELD", + "sync_status_not_connected": "NIET VERBONDEN", + "sync_status_starting_sync": "BEGINNEN MET SYNCHRONISEREN", + "sync_status_syncronized": "SYNCHRONIZED", + "sync_status_syncronizing": "SYNCHRONISEREN", + "syncing_wallet_alert_content": "Uw saldo- en transactielijst is mogelijk pas compleet als er bovenaan 'GESYNCHRONISEERD' staat. Klik/tik voor meer informatie.", + "syncing_wallet_alert_title": "Uw portemonnee wordt gesynchroniseerd", + "template": "Sjabloon", + "template_name": "Sjabloonnaam", + "third_intro_content": "Yats wonen ook buiten Cake Wallet. Elk portemonnee-adres op aarde kan worden vervangen door een Yat!", + "third_intro_title": "Yat speelt leuk met anderen", + "time": "${minutes}m ${seconds}s", + "tip": "Tip:", + "today": "Vandaag", + "token_contract_address": "Token contractadres", + "token_decimal": "Token decimaal", + "token_name": "Tokennaam bijv.: Tether", + "token_symbol": "Tokensymbool bijv.: USDT", + "tokenID": "ID kaart", + "tor_connection": "Tor-verbinding", + "tor_only": "Alleen Tor", + "total_saving": "Totale besparingen", + "totp_2fa_failure": "Foute code. Probeer een andere code of genereer een nieuwe geheime sleutel. Gebruik een compatibele 2FA-app die 8-cijferige codes en SHA512 ondersteunt.", + "totp_2fa_success": "Succes! Cake 2FA ingeschakeld voor deze portemonnee. Vergeet niet om uw geheugensteuntje op te slaan voor het geval u de toegang tot de portemonnee kwijtraakt.", + "totp_auth_url": "TOTP AUTH-URL", + "totp_code": "TOTP-code", + "totp_secret_code": "TOTP-geheime code", + "totp_verification_success": "Verificatie geslaagd!", + "trade_details_copied": "${title} gekopieerd naar het klembord", + "trade_details_created_at": "Gemaakt bij", + "trade_details_fetching": "Ophalen", + "trade_details_id": "ID", + "trade_details_pair": "Paar", + "trade_details_provider": "Leverancier", + "trade_details_state": "Toestand", + "trade_details_title": "Handelsgegevens", + "trade_for_not_created": "Ruilen voor ${title} is niet gemaakt.", + "trade_history_title": "Handelsgeschiedenis", + "trade_id": "Trade ID:", + "trade_id_not_found": "Handel ${tradeId} van ${title} niet gevonden.", + "trade_is_powered_by": "Deze transactie wordt mogelijk gemaakt door ${provider}", + "trade_not_created": "Handel niet gecreëerd", + "trade_not_found": "Handel niet gevonden.", + "trade_state_btc_sent": "Verzonden", + "trade_state_complete": "Compleet", + "trade_state_confirming": "Bevestiging", + "trade_state_created": "Gemaakt", + "trade_state_finished": "Afgewerkt", + "trade_state_paid": "Betaald", + "trade_state_paid_unconfirmed": "Niet bevestigd", + "trade_state_pending": "In afwachting", + "trade_state_timeout": "Time-out", + "trade_state_to_be_created": "Om gecreëerd te worden", + "trade_state_traded": "Traded", + "trade_state_trading": "Handel", + "trade_state_underpaid": "Slecht betaald", + "trade_state_unpaid": "Onbetaald", + "trades": "Trades", + "transaction_details_amount": "Bedrag", + "transaction_details_copied": "${title} gekopieerd naar het klembord", + "transaction_details_date": "Datum", + "transaction_details_fee": "Vergoeding", + "transaction_details_height": "Hoogte", + "transaction_details_recipient_address": "Adressen van ontvangers", "transaction_details_source_address": "Bron adres", - "pause_wallet_creation": "De mogelijkheid om Haven Wallet te maken is momenteel onderbroken.", - "contractName": "Contractnaam", - "contractSymbol": "Contractsymbool", - "description": "Beschrijving", - "camera_consent": "Uw camera wordt gebruikt om vóór ${provider} een beeld vast te leggen voor identificatiedoeleinden. Raadpleeg hun privacybeleid voor meer informatie.", - "no_relays": "Geen relais", - "choose_relay": "Kies een relais dat u wilt gebruiken", - "no_relays_message": "We hebben een Nostr NIP-05-record voor deze gebruiker gevonden, maar deze bevat geen relays. Instrueer de ontvanger om relays toe te voegen aan zijn Nostr-record.", - "no_relay_on_domain": "Er is geen relay voor het domein van de gebruiker of de relay is niet beschikbaar. Kies een relais dat u wilt gebruiken." -} + "transaction_details_title": "Transactie details", + "transaction_details_transaction_id": "Transactie ID", + "transaction_key": "Transactiesleutel", + "transaction_priority_fast": "Snel", + "transaction_priority_fastest": "Snelste", + "transaction_priority_medium": "Medium", + "transaction_priority_regular": "Regelmatig", + "transaction_priority_slow": "Langzaam", + "transaction_sent": "Transactie verzonden!", + "transaction_sent_notice": "Als het scherm na 1 minuut niet verder gaat, controleer dan een blokverkenner en je e-mail.", + "transactions": "Transacties", + "transactions_by_date": "Transacties op datum", + "trusted": "vertrouwd", + "unavailable_balance": "Onbeschikbaar saldo", + "unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.", + "unconfirmed": "Onbevestigd saldo", + "understand": "Ik begrijp het", + "unmatched_currencies": "De valuta van uw huidige portemonnee komt niet overeen met die van de gescande QR", + "unspent_change": "Wijziging", + "unspent_coins_details_title": "Details van niet-uitgegeven munten", + "unspent_coins_title": "Ongebruikte munten", + "unsupported_asset": "We ondersteunen deze actie niet voor dit item. Maak of schakel over naar een portemonnee van een ondersteund activatype.", + "upto": "tot ${value}", + "use": "Gebruik ", + "use_card_info_three": "Gebruik de digitale kaart online of met contactloze betaalmethoden.", + "use_card_info_two": "Tegoeden worden omgezet naar USD wanneer ze op de prepaid-rekening staan, niet in digitale valuta.", + "use_ssl": "Gebruik SSL", + "use_suggested": "Gebruik aanbevolen", + "variable_pair_not_supported": "Dit variabelenpaar wordt niet ondersteund met de geselecteerde uitwisselingen", + "verification": "Verificatie", + "verify_with_2fa": "Controleer met Cake 2FA", + "version": "Versie ${currentVersion}", + "view_all": "Alles bekijken", + "view_in_block_explorer": "View in Block Explorer", + "view_key_private": "Bekijk sleutel (privaat)", + "view_key_public": "Bekijk sleutel (openbaar)", + "view_transaction_on": "View Transaction on ", + "waiting_payment_confirmation": "In afwachting van betalingsbevestiging", + "wallet_keys": "Portemonnee zaad/sleutels", + "wallet_list_create_new_wallet": "Maak een nieuwe portemonnee", + "wallet_list_edit_wallet": "Portemonnee bewerken", + "wallet_list_failed_to_load": "Laden mislukt ${wallet_name} portemonnee. ${error}", + "wallet_list_failed_to_remove": "Verwijderen mislukt ${wallet_name} portemonnee. ${error}", + "wallet_list_load_wallet": "Portemonnee laden", + "wallet_list_loading_wallet": "Bezig met laden ${wallet_name} portemonnee", + "wallet_list_removing_wallet": "Verwijderen ${wallet_name} portemonnee", + "wallet_list_restore_wallet": "Portemonnee herstellen", + "wallet_list_title": "Monero portemonnee", + "wallet_list_wallet_name": "Portemonnee naam", + "wallet_menu": "Portemonnee-menu", + "wallet_name": "Portemonnee naam", + "wallet_name_exists": "Portemonnee met die naam bestaat al", + "wallet_restoration_store_incorrect_seed_length": "Onjuiste zaadlengte", + "wallet_seed": "Portemonnee zaad", + "wallet_seed_legacy": "Legacy portemonnee zaad", + "wallet_store_monero_wallet": "Monero portemonnee", + "walletConnect": "WalletConnect", + "wallets": "Portefeuilles", + "warning": "Waarschuwing", + "welcome": "Welkom bij", + "welcome_to_cakepay": "Welkom bij Cake Pay!", + "widgets_address": "Adres", + "widgets_or": "of", + "widgets_restore_from_blockheight": "Herstel vanaf blockheight", + "widgets_restore_from_date": "Herstel vanaf datum", + "widgets_seed": "Zaad", + "wouoldLikeToConnect": "wil graag verbinden", + "write_down_backup_password": "Noteer uw back-upwachtwoord, dat wordt gebruikt voor het importeren van uw back-upbestanden.", + "xlm_extra_info": "Vergeet niet om de Memo-ID op te geven tijdens het verzenden van de XLM-transactie voor de uitwisseling", + "xmr_available_balance": "Beschikbaar saldo", + "xmr_full_balance": "Volledig saldo", + "xmr_hidden": "Verborgen", + "xmr_to_error": "XMR.TO-fout", + "xmr_to_error_description": "Ongeldige hoeveelheid. Maximaal 8 cijfers achter de komma", + "xrp_extra_info": "Vergeet niet om de Destination Tag op te geven tijdens het verzenden van de XRP-transactie voor de uitwisseling", + "yat": "Yat", + "yat_address": "Yat-adres", + "yat_alert_content": "Cake Wallet-gebruikers kunnen nu al hun favoriete valuta's verzenden en ontvangen met een unieke emoji-gebaseerde gebruikersnaam.", + "yat_alert_title": "Verzend en ontvang crypto gemakkelijker met Yat", + "yat_error": "Yat fout", + "yat_error_content": "Geen adressen gekoppeld aan deze Yat. Probeer een andere Yato", + "yat_popup_content": "Je kunt nu crypto verzenden en ontvangen in Cake Wallet met je Yat - een korte, op emoji gebaseerde gebruikersnaam. Beheer Yats op elk moment op het instellingenscherm", + "yat_popup_title": "Uw portemonnee-adres kan worden ge-emojiificeerd.", + "yesterday": "Gisteren", + "you_now_have_debit_card": "Je hebt nu een debetkaart", + "you_pay": "U betaalt", + "you_will_get": "Converteren naar", + "you_will_send": "Converteren van", + "yy": "JJ", + "zzzz": "Zzzz" +} \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 4363ef5ae..f7293c754 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -1,779 +1,780 @@ { - "welcome": "Witamy w", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Świetny portfel na Monero, Bitcoin, Ethereum, Litecoin, i Haven", - "please_make_selection": "Wybierz poniżej, aby utworzyć lub przywrócić swój portfel.", - "create_new": "Utwórz nowy portfel", - "restore_wallet": "Przywróć portfel", - "monero_com": "Monero.com by Cake Wallet", - "monero_com_wallet_text": "Awesome wallet for Monero", - "haven_app": "Haven by Cake Wallet", - "haven_app_wallet_text": "Awesome wallet for Haven", - "accounts": "Konta", - "edit": "Edytuj", + "about_cake_pay": "Cake Pay umożliwia łatwe kupowanie kart podarunkowych z wirtualnymi aktywami, które można natychmiast wydać u ponad 150 000 sprzedawców w Stanach Zjednoczonych.", "account": "Konto", + "accounts": "Konta", + "accounts_subaddresses": "Konta i podadresy", + "activate": "Aktywuj", + "active": "Aktywny", + "active_cards": "Aktywne karty", + "activeConnectionsPrompt": "Tutaj pojawią się aktywne połączenia", "add": "Dodaj", + "add_contact": "Dodaj kontakt", + "add_custom_node": "Dodaj nowy węzeł niestandardowy", + "add_custom_redemption": "Dodaj niestandardowe wykorzystanie", + "add_fund_to_card": "Dodaj przedpłacone środki do kart (do ${value})", + "add_new_node": "Dodaj nowy węzeł", + "add_new_word": "Dodaj nowe słowo", + "add_receiver": "Dodaj kolejnego odbiorcę (opcjonalnie)", + "add_secret_code": "Możesz też dodać ten tajny kod do aplikacji uwierzytelniającej", + "add_tip": "Dodaj wskazówkę", + "add_token_disclaimer_check": "Potwierdziłem adres kontraktu tokena i informacje, korzystając z renomowanego źródła. Dodanie złośliwych lub niepoprawnych informacji może spowodować utratę środków.", + "add_token_warning": "Nie edytuj ani nie dodawaj tokenów zgodnie z instrukcjami oszustów.\nZawsze potwierdzaj adresy tokenów z renomowanymi źródłami!", + "add_value": "Dodaj wartość", + "address": "Adres", "address_book": "Kontakty", - "contact": "Kontakt", - "please_select": "Proszę wybrać:", - "cancel": "Anuluj", - "ok": "Ok", - "contact_name": "Nazwa Kontaktu", - "reset": "Wyczyść", - "save": "Zapisz", + "address_book_menu": "Kontakty", + "address_detected": "Wykryto adres", + "address_from_domain": "Ten adres to ${domain} na Unstoppable Domains", + "address_from_yat": "Ten adres jest od ${emoji} na Yat", + "address_label": "Etykieta Adresu", "address_remove_contact": "Usuń kontakt", "address_remove_content": "Czy na pewno chcesz usunąć wybrany kontakt?", - "authenticated": "Uwierzytelniony", - "authentication": "Uwierzytelnianie", - "failed_authentication": "Nieudane uwierzytelnienie. ${state_error}", - "wallet_menu": "Menu portfela", - "Blocks_remaining": "Pozostało ${status} bloków", - "please_try_to_connect_to_another_node": "Spróbuj połączyć się z innym węzłem", - "xmr_hidden": "Ukryty", - "xmr_available_balance": "Dostępne środki", - "xmr_full_balance": "Pełne saldo", - "send": "Wyślij", - "receive": "Otrzymaj", - "transactions": "Transakcje", - "incoming": "Przychodzące", - "outgoing": "Wychodzące", - "transactions_by_date": "Transakcje według daty", - "trades": "Transakcje", - "filter_by": "Filtruj według", - "today": "Dzisiaj", - "yesterday": "Wczoraj", - "received": "Odebrane", - "sent": "Wysłano", - "pending": " (w oczekiwaniu)", - "rescan": "Skanuj ponownie", - "reconnect": "Połącz ponownie", - "wallets": "Portfele", - "show_seed": "Pokaż frazy seed", - "show_keys": "Pokaż seed/klucze", - "address_book_menu": "Kontakty", - "reconnection": "Ponowne łączenie", - "reconnect_alert_text": "Czy na pewno ponownie się ponownie połączysz?", - "exchange": "Wymień", - "clear": "Wyczyść", - "refund_address": "Adres do zwrotu", - "change_exchange_provider": "Zmień dostawcę wymiany", - "you_will_send": "Konwertuj z", - "you_will_get": "Konwertuj na", - "amount_is_guaranteed": "Otrzymana kwota jest gwarantowana", - "amount_is_estimate": "Otrzymana kwota jest wartością szacunkową", - "powered_by": "Obsługiwane przez ${title}", - "error": "Błąd", - "estimated": "Oszacowano", - "min_value": "Min: ${value} ${currency}", - "max_value": "Max: ${value} ${currency}", - "change_currency": "Zmień walutę", - "overwrite_amount": "Nadpisz ilość", - "qr_payment_amount": "Ten kod QR zawiera kwotę do zapłaty. Czy chcesz nadpisać obecną wartość?", - "copy_id": "skopiuj ID", - "exchange_result_write_down_trade_id": "Skopiuj lub zanotuj identyfikator transakcji (ID), aby kontynuować.", - "trade_id": "ID transakcji:", - "copied_to_clipboard": "Skopiowano do schowka", - "saved_the_trade_id": "Zapisałem ID", - "fetching": "Pobieranie", - "id": "ID: ", - "amount": "Ilość: ", - "payment_id": "ID Płatności: ", - "status": "Status: ", - "offer_expires_in": "Oferta wygasa za ", - "trade_is_powered_by": "Ta wymiana jest obsługiwana przez ${provider}", - "copy_address": "Skopiuj adress", - "exchange_result_confirm": "Naciskając Potwierdź, wyślesz ${fetchingLabel} ${from} z twojego portfela ${walletName} na adres podany poniżej. Lub możesz wysłać z zewnętrznego portfela na poniższy adres / kod QR.\n\nNaciśnij Potwierdź, aby kontynuować lub wróć, aby zmienić kwoty.", - "exchange_result_description": "Musisz wysłać co najmniej ${fetchingLabel} ${from} na adres podany na następnej stronie. Jeśli wyślesz kwotę niższą niż ${fetchingLabel} ${from}, może ona nie zostać uwzględniona i może nie zostać zwrócona.", - "exchange_result_write_down_ID": "*Skopiuj lub zanotuj identyfikator transakcji pokazany powyżej.", - "confirm": "Potwierdzać", - "confirm_sending": "Potwierdź wysłanie", - "commit_transaction_amount_fee": "Zatwierdź transakcję\nIlość: ${amount}\nOpłata: ${fee}", - "sending": "Wysyłanie", - "transaction_sent": "Transakcja wysłana!", - "expired": "Przedawniony", - "time": "${minutes}m ${seconds}s", - "send_xmr": "Wyślij XMR", - "exchange_new_template": "Nowy szablon wymiany", - "faq": "FAQ", - "enter_your_pin": "Wpisz kod PIN", - "loading_your_wallet": "Ładowanie portfela", - "new_wallet": "Nowy portfel", - "wallet_name": "Nazwa portfela", - "continue_text": "Dalej", - "choose_wallet_currency": "Wybierz walutę portfela:", - "node_new": "Nowy węzeł", - "node_address": "Adres węzła", - "node_port": "Port węzła", - "login": "Login", - "password": "Hasło", - "nodes": "Węzły", - "node_reset_settings_title": "Zresetuj ustawienia węzłów", - "nodes_list_reset_to_default_message": "Czy na pewno chcesz przywrócić ustawienia domyślne?", - "change_current_node": "Czy na pewno chcesz wybrać ten węzeł? ${node}?", - "change": "Zmień", - "remove_node": "Usuń węzeł", - "remove_node_message": "Czy na pewno chcesz usunąć wybrany węzeł?", - "remove": "Usuń", - "delete": "Skasuj", - "add_new_node": "Dodaj nowy węzeł", - "change_current_node_title": "Zmień bieżący węzeł", - "node_test": "Test", - "node_connection_successful": "Połączenie powiodło się", - "node_connection_failed": "Połączenie nie powiodło się", - "new_node_testing": "Testowanie nowych węzłów", - "use": "Użyj ", - "digit_pin": "-znakowy PIN", - "share_address": "Udostępnij adres", - "receive_amount": "Ilość", - "subaddresses": "Podadresy", "addresses": "Adresy", - "scan_qr_code_to_get_address": "Zeskanuj kod QR, aby uzyskać adres", - "qr_fullscreen": "Dotknij, aby otworzyć pełnoekranowy kod QR", - "rename": "Zmień nazwę", - "choose_account": "Wybierz konto", - "create_new_account": "Stwórz nowe konto", - "accounts_subaddresses": "Konta i podadresy", - "restore_restore_wallet": "Przywróć portfel", - "restore_title_from_seed_keys": "Przywróć z seedów / kluczy", - "restore_description_from_seed_keys": "Odzyskaj swój portfel z seedów / kluczy, które zapisałeś w bezpiecznym miejscu", - "restore_next": "Kolejny", - "restore_title_from_backup": "Przywróć z pliku kopii zapasowej", - "restore_description_from_backup": "Możesz przywrócić całą aplikację Cake Wallet z pliku kopii zapasowej", - "restore_seed_keys_restore": "Przywracanie seedów / kluczy", - "restore_title_from_seed": "Przywróć z seedów", - "restore_description_from_seed": "Przywróć swój portfel z 25 lub 13-słownej frazy seed", - "restore_title_from_keys": "Przywróć z kluczy", - "restore_description_from_keys": "Przywróć swój portfel z kluczy prywatnych", - "restore_wallet_name": "Nazwa portfela", - "restore_address": "Adres", - "restore_view_key_private": "Podaj klucz prywatny", - "restore_spend_key_private": "Podaj prywatny klucz wglądu (view key)", - "restore_recover": "Przywróć", - "restore_wallet_restore_description": "Przywracanie portfela", - "restore_new_seed": "Nowy seed", - "restore_active_seed": "Aktywne seedy", - "restore_bitcoin_description_from_seed": "Przywróć swój portfel z frazy seed złożonej z 24 słów", - "restore_bitcoin_description_from_keys": "Przywróć swój portfel z klucza prywatnego", - "restore_bitcoin_title_from_keys": "Przywróć z klucza prywatnego", - "restore_from_date_or_blockheight": "Wprowadź datę na kilka dni przed utworzeniem tego portfela, lub jeśli znasz wysokość bloku, wprowadź go zamiast daty", - "seed_reminder": "Musisz zapisać tą fraze, bo bez niej możesz nie odzyskać portfela!", - "seed_title": "Seed", - "seed_share": "Udostępnij seed", - "copy": "Kopiuj", - "seed_language": "Język nasion", - "seed_choose": "Wybierz język", - "seed_language_next": "Następny", - "seed_language_english": "Angielski", - "seed_language_chinese": "Chiński", - "seed_language_dutch": "Holenderski", - "seed_language_german": "Niemiecki", - "seed_language_japanese": "Japoński", - "seed_language_portuguese": "Portugalski", - "seed_language_russian": "Rosyjski", - "seed_language_spanish": "Hiszpański", - "seed_language_french": "Francuski", - "seed_language_italian": "Włoski", - "send_title": "Wyślij", - "send_your_wallet": "Twój portfel", - "send_address": "Adres ${cryptoCurrency}", - "send_payment_id": "Identyfikator płatności (opcjonalny)", + "advanced_settings": "Zaawansowane ustawienia", + "aggressive": "Nadgorliwy", + "agree": "Zgadzam się", + "agree_and_continue": "Zgadzam się i kontynuuj", + "agree_to": "Tworząc konto wyrażasz zgodę na ", "all": "WSZYSTKO", - "send_error_minimum_value": "Minimalna wartość to 0,01", - "send_error_currency": "Waluta może zawierać tylko cyfry", - "send_estimated_fee": "Szacowana opłata:", - "send_priority": "Obecnie opłata ustalona jest na ${transactionPriority} priorytet.\nPriorytet transakcji można zmienić w ustawieniach", - "send_creating_transaction": "Tworzenie transakcji", - "send_templates": "Szablony", - "send_new": "Nowy", - "send_amount": "Ilość:", - "send_fee": "Opłata:", - "send_name": "Imię", - "got_it": "Wysłano", - "send_sending": "Wysyłanie...", - "send_success": "Twoje ${crypto} zostało pomyślnie wysłane", - "settings_title": "Ustawienia", - "settings_nodes": "Węzły", - "settings_current_node": "Bieżący węzeł", - "settings_wallets": "Portfele", - "settings_display_balance": "Wyświetl saldo", - "settings_currency": "Waluta", - "settings_fee_priority": "Priorytet opłaty", - "settings_save_recipient_address": "Zapisz adres odbiorcy", - "settings_personal": "Osobiste", - "settings_change_pin": "Zmień PIN", - "settings_change_language": "Zmień język", - "settings_allow_biometrical_authentication": "Zezwalaj na uwierzytelnianie biometryczne", - "settings_dark_mode": "Tryb ciemny", - "settings_transactions": "Transakcje", - "settings_trades": "Transakcje", - "settings_display_on_dashboard_list": "Wyświetl na pulpicie", - "settings_all": "Wszystkie", - "settings_only_trades": "Tylko transakcje", - "settings_only_transactions": "Tylko transakcje", - "settings_none": "Żaden", - "settings_support": "Wsparcie", - "settings_terms_and_conditions": "Zasady i warunki", - "pin_is_incorrect": "PIN jest niepoprawny", - "setup_pin": "Ustaw PIN", - "enter_your_pin_again": "Wprowadź ponownie swój kod PIN", - "setup_successful": "Twój kod PIN został pomyślnie skonfigurowany!", - "wallet_keys": "Klucze portfela", - "wallet_seed": "Seed portfela", - "private_key": "Klucz prywatny", - "public_key": "Klucz publiczny", - "view_key_private": "Prywatny Klucz Wglądu", - "view_key_public": "Publiczny Klucz Wglądu", - "spend_key_private": "Klucz prywatny", - "spend_key_public": "Klucz publiczny", - "copied_key_to_clipboard": "Skopiowaneo ${key} do schowka", - "new_subaddress_title": "Nowy adres", - "new_subaddress_label_name": "Etykieta nazwy adresu", - "new_subaddress_create": "Stwórz", - "address_label": "Etykieta Adresu", - "subaddress_title": "Lista podadresów", - "trade_details_title": "Szczegóły transakcji", - "trade_details_id": "ID", - "trade_details_state": "Status", - "trade_details_fetching": "Pobieranie", - "trade_details_provider": "Dostawca", - "trade_details_created_at": "Utworzono ", - "trade_details_pair": "Para", - "trade_details_copied": "${title} skopiowane do schowka", - "trade_history_title": "Historia wymian", - "transaction_details_title": "Szczegóły transakcji", - "transaction_details_transaction_id": "ID Trancakcji", - "transaction_details_date": "Data", - "transaction_details_height": "Wysokość Bloku", - "transaction_details_amount": "Ilość", - "transaction_details_fee": "Opłata", - "transaction_details_copied": "${title} skopiowane do schowka", - "transaction_details_recipient_address": "Adres odbiorcy", - "wallet_list_title": "Portfel Monero", - "wallet_list_create_new_wallet": "Utwórz nowy portfel", - "wallet_list_edit_wallet": "Edytuj portfel", - "wallet_list_wallet_name": "Nazwa portfela", - "wallet_list_restore_wallet": "Przywróć portfel", - "wallet_list_load_wallet": "Załaduj portfel", - "wallet_list_loading_wallet": "Ładuję ${wallet_name} portfel", - "wallet_list_failed_to_load": "Nie udało się załadować ${wallet_name} portfel. ${error}", - "wallet_list_removing_wallet": "Usuwanie ${wallet_name} portfel", - "wallet_list_failed_to_remove": "Nie udało się usunąć ${wallet_name} portfel. ${error}", - "widgets_address": "Adres", - "widgets_restore_from_blockheight": "Przywróć z wysokości bloku", - "widgets_restore_from_date": "Przywróć od daty", - "widgets_or": "lub", - "widgets_seed": "Seed", - "router_no_route": "Brak zdefiniowanej trasy dla ${name}", - "error_text_account_name": "Nazwa konta może zawierać tylko litery, cyfry\ni musi mieć od 1 do 15 znaków", - "error_text_contact_name": "Nazwa kontaktu nie może zawierać symboli ` , ' \"\ni musi mieć od 1 do 32 znaków ", - "error_text_address": "Adres musi odpowiadać typowi kryptowaluty", - "error_text_node_address": "Wpisz adres iPv4", - "error_text_node_port": "Port węzła może zawierać tylko liczby od 0 do 65535", - "error_text_node_proxy_address": "Wprowadź :, na przykład 127.0.0.1:9050", - "error_text_payment_id": "ID może zawierać od 16 do 64 znaków w formacie szesnastkowym", - "error_text_xmr": "Wartość XMR nie może przekraczać dostępnego salda.\nLiczba cyfr ułamkowych musi być mniejsza lub równa 12", - "error_text_fiat": "Wartość kwoty nie może przekroczyć dostępnego salda.\nLiczba cyfr ułamkowych musi być mniejsza lub równa 2", - "error_text_subaddress_name": "Nazwa podadresu nie może zawierać symboli ` , ' \"\ni musi mieć od 1 do 20 znaków", - "error_text_amount": "Kwota może zawierać tylko liczby", - "error_text_wallet_name": "Nazwa portfela może zawierać tylko litery, cyfry lub symbole _ - \ni musi mieć od 1 do 33 znaków", - "error_text_keys": "Klucze portfela mogą zawierać tylko 64 znaki w systemie szesnastkowym", - "error_text_crypto_currency": "Liczba cyfr ułamkowych\nmusi być mniejsza lub równa 12", - "error_text_minimal_limit": "Wymiana dla ${provider} nie została utworzona. Kwota jest mniejsza niż minimalna: ${min} ${currency}", - "error_text_maximum_limit": "Wymiana dla ${provider} nie została utworzona. Kwota jest większa niż maksymalna: ${max} ${currency}", - "error_text_limits_loading_failed": "Wymiana dla ${provider} nie została utworzona. Ładowanie limitów nie powiodło się", - "error_text_template": "Nazwa i adres szablonu nie mogą zawierać ` , ' \" symbolika\ni musi mieć od 1 do 106 znaków", + "all_trades": "Wszystkie operacje", + "all_transactions": "Wszystkie transakcje", + "alphabetical": "Alfabetyczny", + "already_have_account": "Masz już konto?", + "always": "zawsze", + "amount": "Ilość: ", + "amount_is_estimate": "Otrzymana kwota jest wartością szacunkową", + "amount_is_guaranteed": "Otrzymana kwota jest gwarantowana", + "and": "i", + "anonpay_description": "Wygeneruj ${type}. Odbiorca może ${method} z dowolną obsługiwaną kryptowalutą, a Ty otrzymasz środki w tym portfelu.", + "apk_update": "Aktualizacja APK", + "approve": "Zatwierdzić", + "arrive_in_this_address": "${currency} ${tag}dotrze na ten adres", + "ascending": "Wznoszący się", + "ask_each_time": "Zapytaj za każdym razem", "auth_store_ban_timeout": "przekroczenie limitu czasu", "auth_store_banned_for": "Zablokowany za ", "auth_store_banned_minutes": " minuty", "auth_store_incorrect_password": "Niepoprawny PIN", - "wallet_store_monero_wallet": "Portfel Monero", - "wallet_restoration_store_incorrect_seed_length": "Nieprawidłowa długość frazy seed", - "full_balance": "Pełne saldo", - "available_balance": "Dostępne środki", - "hidden_balance": "Ukryte saldo", - "sync_status_syncronizing": "SYNCHRONIZACJA", - "sync_status_syncronized": "ZSYNCHRONIZOWANO", - "sync_status_not_connected": "NIE POŁĄCZONY", - "sync_status_starting_sync": "ROZPOCZĘCIE SYNCHRONIZACJI", - "sync_status_failed_connect": "POŁĄCZENIE NIEUDANE", - "sync_status_connecting": "ŁĄCZENIE", - "sync_status_connected": "POŁĄCZONY", - "sync_status_attempting_sync": "PRÓBA SYNCHRONIZACJI", - "transaction_priority_slow": "Wolna(Zalecane)", - "transaction_priority_regular": "Regularna", - "transaction_priority_medium": "Średnia", - "transaction_priority_fast": "Szybka", - "transaction_priority_fastest": "Najszybsza", - "trade_for_not_created": "Wymiana za ${title} nie została utworzona.", - "trade_not_created": "Wymiana nie została utworzona", - "trade_id_not_found": "Transakcja ${tradeId} ${title} nie znaleziona.", - "trade_not_found": "Nie znaleziono transakcji.", - "trade_state_pending": "Oczekująca", - "trade_state_confirming": "Potwierdzanie", - "trade_state_trading": "Wymiana", - "trade_state_traded": "Wymienione", - "trade_state_complete": "Ukończona", - "trade_state_to_be_created": "Została stworzona", - "trade_state_unpaid": "Nie opłacona", - "trade_state_underpaid": "Niedopłacone", - "trade_state_paid_unconfirmed": "Transakcja niepotwierdzona", - "trade_state_paid": "Opłacona", - "trade_state_btc_sent": "Wysłanie", - "trade_state_timeout": "Koniec czasu", - "trade_state_created": "Stworzona", - "trade_state_finished": "Zakończona", - "change_language": "Zmień język", - "change_language_to": "Zmień język na ${language}?", - "paste": "Wklej", - "restore_from_seed_placeholder": "Wpisz lub wklej tutaj swoją frazę seed", - "add_new_word": "Dodaj nowe słowo", - "incorrect_seed": "Wprowadzony seed jest nieprawidłowy.", - "biometric_auth_reason": "Zeskanuj swój odcisk palca, aby uwierzytelnić", - "version": "Wersja ${currentVersion}", - "extracted_address_content": "Wysyłasz środki na\n${recipient_name}", - "card_address": "Adres:", - "buy": "Kup", - "sell": "Sprzedać", - "placeholder_transactions": "Twoje transakcje zostaną wyświetlone tutaj", - "placeholder_contacts": "Twoje kontakty zostaną wyświetlone tutaj", - "template": "Szablon", - "confirm_delete_template": "Ta czynność usunie ten szablon. Czy chcesz kontynuować?", - "confirm_delete_wallet": "Ta czynność usunie ten portfel. Czy chcesz kontynuować?", - "change_wallet_alert_title": "Zmień obecny portfel", - "change_wallet_alert_content": "Czy chcesz zmienić obecny portfel na ${wallet_name}?", - "creating_new_wallet": "Tworzenie nowego portfela", - "creating_new_wallet_error": "Błąd: ${description}", - "seed_alert_title": "Uwaga", - "seed_alert_content": "Fraza Seed to jedyny sposób na odzyskanie portfela. Zapisałeś ją?", - "seed_alert_back": "Wróć", - "seed_alert_yes": "Tak", - "exchange_sync_alert_content": "Poczekaj, aż portfel zostanie zsynchronizowany", - "pre_seed_title": "WAŻNY", - "pre_seed_description": "Na następnej stronie zobaczysz serię ${words} słów. To jest Twoja unikalna i prywatna fraza seed i jest to JEDYNY sposób na odzyskanie portfela w przypadku utraty lub awarii telefonu. Twoim obowiązkiem jest zapisanie go i przechowywanie w bezpiecznym miejscu (np. na kartce w SEJFIE).", - "pre_seed_button_text": "Rozumiem. Pokaż mi moją fraze seed", - "xmr_to_error": "Błąd XMR.TO", - "xmr_to_error_description": "Nieprawidłowa kwota. Maksymalny limit to 8 cyfr po przecinku", - "provider_error": "${provider} pomyłka", - "use_ssl": "Użyj SSL", - "trusted": "Zaufany", - "color_theme": "Motyw kolorystyczny", - "light_theme": "Jasny", - "bright_theme": "Biały", - "dark_theme": "Ciemny", - "enter_your_note": "Wpisz notatkę…", - "note_optional": "Notatka (opcjonalnie)", - "note_tap_to_change": "Notatka (dotknij, aby zmienić)", - "view_in_block_explorer": "Zobacz w eksploratorze bloków", - "view_transaction_on": "Zobacz transakcje na ", - "transaction_key": "Klucz transakcji", - "confirmations": "Potwierdzenia", - "recipient_address": "Adres odbiorcy", - "extra_id": "Dodatkowy ID:", - "destination_tag": "Tag docelowy:", - "memo": "Notatka:", - "backup": "Kopia zapasowa", - "change_password": "Zmień hasło", - "backup_password": "Hasło kpoii zapasowej", - "write_down_backup_password": "Zapisz swoje hasło kopii zapasowej, które jest używane do importowania plików kopii zapasowych.", - "export_backup": "Eksportuj kopię zapasową", - "save_backup_password": "Upewnij się, że zapisałeś swoje hasło kopii zapasowej. Bez tego nie będziesz mógł zaimportować pliku kopii zapasowej.", - "backup_file": "Plik kopii zapasowej", - "edit_backup_password": "Edytuj hasło kopii zapasowej", - "save_backup_password_alert": "Zapisz hasło kopii zapasowej", - "change_backup_password_alert": "Twoje poprzednie pliki kopii zapasowej nie będą dostępne do zaimportowania z nowym hasłem kopii zapasowej. Nowe hasło kopii zapasowej będzie używane tylko dla nowych plików kopii zapasowych. Czy na pewno chcesz zmienić hasło zapasowe?", - "enter_backup_password": "Wprowadź tutaj hasło kopii zapasowej", - "select_backup_file": "Wybierz plik kopii zapasowej", - "import": "Import", - "please_select_backup_file": "Wybierz plik kopii zapasowej i wprowadź hasło.", - "fixed_rate": "Stała stawka", - "fixed_rate_alert": "Będziesz mógł wprowadzić kwotę do otrzymania, gdy wybrany bedzie tryb stałego przeliczenia. Czy chcesz przejść do trybu stałej stawki?", - "xlm_extra_info": "Nie zapomnij podać dodatkowego identyfikatora (memo) podczas wysyłania transakcji XLM do wymiany", - "xrp_extra_info": "Nie zapomnij podać tagu docelowego podczas wysyłania transakcji XRP do wymiany", - "exchange_incorrect_current_wallet_for_xmr": "Jeśli chcesz wymienić XMR z salda Cake Wallet Monero, najpierw przełącz się na portfel Monero.", - "confirmed": "Potwierdzone saldo", - "unconfirmed": "Niepotwierdzone saldo", - "displayable": "Wyświetlane", - "submit_request": "Złóż wniosek", - "buy_alert_content": "Obecnie obsługujemy tylko zakup Bitcoin, Ethereum, Litecoin i Monero. Utwórz lub przełącz się na swój portfel Bitcoin, Ethereum, Litecoin lub Monero.", - "sell_alert_content": "Obecnie obsługujemy tylko sprzedaż Bitcoin, Ethereum i Litecoin. Utwórz lub przełącz się na swój portfel Bitcoin, Ethereum lub Litecoin.", - "outdated_electrum_wallet_description": "Nowe portfele Bitcoin utworzone w Cake mają teraz fraze seed składające się z 24 słów. Konieczne jest utworzenie nowego portfela Bitcoin i przeniesienie wszystkich środków do nowego portfela na 24 słowa oraz zaprzestanie korzystania z portfeli z frazą seed na 12 słów. Zrób to natychmiast, aby zabezpieczyć swoje fundusze.", - "understand": "Rozumiem", - "apk_update": "Aktualizacja APK", - "buy_bitcoin": "Kup Bitcoin", - "buy_with": "Kup za pomocą", - "moonpay_alert_text": "Wartość kwoty musi być większa lub równa ${minAmount} ${fiatCurrency}", - "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", - "do_not_show_me": "Nie pokazuj mi tego ponownie", - "unspent_coins_title": "Niewydane monety", - "unspent_coins_details_title": "Szczegóły niewydanych monet", - "freeze": "Zamróź", - "frozen": "Zamrożone", - "coin_control": "Kontrola monet (opcjonalnie)", - "address_detected": "Wykryto adres", - "address_from_domain": "Ten adres to ${domain} na Unstoppable Domains", - "add_receiver": "Dodaj kolejnego odbiorcę (opcjonalnie)", - "manage_yats": "Zarządzaj Yats", - "yat_alert_title": "Łatwiejsze wysyłanie i odbieranie kryptowalut dzięki Yat", - "yat_alert_content": "Użytkownicy Cake Wallet mogą teraz wysyłać i odbierać wszystkie swoje ulubione waluty za pomocą jedynej w swoim rodzaju nazwy użytkownika opartej na emoji.", - "get_your_yat": "Zdobądź swój Yat", - "connect_an_existing_yat": "Podłącz istniejący Yat", - "yat_address": "Adres Yat", - "yat": "Yat", - "connect_yats": "Połącz Yats", - "address_from_yat": "Ten adres jest od ${emoji} na Yat", - "yat_error": "Błąd Yat", - "yat_error_content": "Brak adresów powiązanych z tym Yat. Wypróbuj inny Yat", - "choose_address": "\n\nWybierz adres:", - "yat_popup_title": "Twój adres portfela może być zemotkowany.", - "yat_popup_content": "Możesz teraz wysyłać i odbierać krypto w Cake Wallet za pomocą swojego Yat – krótkiej nazwy użytkownika opartej na emotikonach. Zarządzaj Yats w dowolnym momencie na ekranie ustawień", - "second_intro_title": "Jeden adres emoji, aby zarzadzać wszystkimi walutami", - "second_intro_content": "Twój Yat to jeden unikalny adres emoji, który zastępuje wszystkie Twoje długie adresy szesnastkowe dla wszystkich Twoich walut.", - "third_intro_title": "Yat ładnie bawi się z innymi", - "third_intro_content": "Yats mieszkają również poza Cake Wallet. Każdy adres portfela na ziemi można zastąpić Yat!", - "learn_more": "Dowiedz się więcej", - "search": "Szukaj", - "search_language": "Wyszukaj język", - "search_currency": "Wyszukaj walutę", - "new_template": "Nowy szablon", - "electrum_address_disclaimer": "Za każdym razem, gdy wykorzystasz adres, dla wiekszej prywatności generujemy nowy, ale poprzednie adresy nadal działają, i moga odbierać środki", - "wallet_name_exists": "Portfel o tej nazwie już istnieje", - "market_place": "Rynek", - "cake_pay_title": "Karty podarunkowe Cake Pay", - "cake_pay_subtitle": "Kup karty upominkowe ze zniżką (tylko USA)", - "cake_pay_web_cards_title": "Cake Pay Web Cards", - "cake_pay_web_cards_subtitle": "Kupuj na całym świecie karty przedpłacone i karty podarunkowe", - "about_cake_pay": "Cake Pay umożliwia łatwe kupowanie kart podarunkowych z wirtualnymi aktywami, które można natychmiast wydać u ponad 150 000 sprzedawców w Stanach Zjednoczonych.", - "cake_pay_account_note": "Zarejestruj się, używając tylko adresu e-mail, aby przeglądać i kupować karty. Niektóre są nawet dostępne ze zniżką!", - "already_have_account": "Masz już konto?", - "create_account": "Utwórz konto", - "privacy_policy": "Polityka prywatności", - "welcome_to_cakepay": "Witamy w Cake Pay!", - "sign_up": "Zarejestruj się", - "forgot_password": "Zapomniałem hasła", - "reset_password": "Zresetuj hasło", - "gift_cards": "Karty podarunkowe", - "setup_your_debit_card": "Skonfiguruj swoją kartę debetową", - "no_id_required": "Nie wymagamy Dowodu. Doładuj i wydawaj gdziekolwiek", - "how_to_use_card": "Jak korzystać z tej karty?", - "purchase_gift_card": "Kup kartę podarunkową", - "verification": "Weryfikacja", - "fill_code": "Proszę wpisać kod weryfikacyjny który otrzymałeś w wiadomości e-mail", - "didnt_get_code": "Nie dostałeś kodu?", - "resend_code": "Wyślij go ponownie", - "debit_card": "Karta debetowa", - "cakepay_prepaid_card": "Przedpłacona karta debetowa CakePay", - "no_id_needed": "Nie potrzeba Dowodu!", - "frequently_asked_questions": "Często zadawane pytania", - "debit_card_terms": "Przechowywanie i używanie numeru karty płatniczej (oraz danych uwierzytelniających odpowiadających numerowi karty płatniczej) w tym portfelu cyfrowym podlega Warunkom odpowiedniej umowy posiadacza karty z wydawcą karty płatniczej, zgodnie z obowiązującym od od czasu do czasu.", - "please_reference_document": "Proszę odwołać się do poniższych dokumentów, aby uzyskać więcej informacji.", - "cardholder_agreement": "Umowa posiadacza karty", - "e_sign_consent": "Zgoda na podpis elektroniczny", - "agree_and_continue": "Zgadzam się i kontynuuj", - "email_address": "Adres e-mail", - "agree_to": "Tworząc konto wyrażasz zgodę na ", - "and": "i", - "enter_code": "Wprowadź kod", - "congratulations": "gratulacje!", - "you_now_have_debit_card": "Masz teraz kartę debetową", - "min_amount": "Min: ${value}", - "max_amount": "Max: ${value}", - "enter_amount": "Wprowadź kwotę", - "billing_address_info": "Jeśli zostaniesz poproszony o podanie adresu rozliczeniowego, podaj swój adres wysyłki", - "order_physical_card": "Zamów kartę fizyczną", - "add_value": "Dodaj wartość", - "activate": "Aktywuj", - "get_a": "Zdobądź ", - "digital_and_physical_card": " cyfrowa i fizyczna przedpłacona karta debetowa", - "get_card_note": " które możesz doładować walutami cyfrowymi. Nie są potrzebne żadne dodatkowe informacje!", - "signup_for_card_accept_terms": "Zarejestruj się, aby otrzymać kartę i zaakceptuj warunki.", - "add_fund_to_card": "Dodaj przedpłacone środki do kart (do ${value})", - "use_card_info_two": "Środki są przeliczane na USD, gdy są przechowywane na koncie przedpłaconym, a nie w walutach cyfrowych.", - "use_card_info_three": "Użyj cyfrowej karty online lub za pomocą zbliżeniowych metod płatności.", - "optionally_order_card": "Opcjonalnie zamów kartę fizyczną.", - "hide_details": "Ukryj szczegóły", - "show_details": "Pokaż szczegóły", - "upto": "do ${value}", - "discount": "Zaoszczędź ${value}%", - "gift_card_amount": "Kwota karty podarunkowej", - "bill_amount": "Kwota rachunku", - "you_pay": "Płacisz", - "tip": "wskazówka:", - "custom": "niestandardowy", - "by_cake_pay": "przez Cake Pay", - "expires": "Wygasa", - "mm": "MM", - "yy": "RR", - "online": "online", - "offline": "Offline", - "gift_card_number": "Numer karty podarunkowej", - "pin_number": "Numer PIN", - "total_saving": "Całkowite oszczędności", - "last_30_days": "Ostatnie 30 dni", - "avg_savings": "Śr. oszczędności", - "view_all": "Wyświetl wszystko", - "active_cards": "Aktywne karty", - "delete_account": "Usuń konto", - "cards": "Karty", - "active": "Aktywny", - "redeemed": "wykupione", - "gift_card_balance_note": "Tutaj pojawią się karty podarunkowe z pozostałym saldem", - "gift_card_redeemed_note": "Karty podarunkowe, które wykorzystałeś, pojawią się tutaj", - "logout": "Wyloguj", - "add_tip": "Dodaj wskazówkę", - "percentageOf": "z ${amount}", - "is_percentage": "jest", - "search_category": "Kategoria wyszukiwania", - "mark_as_redeemed": "Oznacz jako wykorzystany", - "more_options": "Więcej opcji", - "awaiting_payment_confirmation": "Oczekiwanie na potwierdzenie płatności", - "transaction_sent_notice": "Jeśli ekran nie zmieni się po 1 minucie, sprawdź eksplorator bloków i swój e-mail.", - "agree": "Zgadzam się", - "in_store": "W Sklepie", - "generating_gift_card": "Generowanie karty podarunkowej", - "payment_was_received": "Twoja płatność została otrzymana.", - "proceed_after_one_minute": "Jeśli ekran nie przejdzie dalej po 1 minucie, sprawdź pocztę.", - "order_id": "Identyfikator zamówienia", - "gift_card_is_generated": "Karta podarunkowa jest generowana", - "open_gift_card": "Otwórz kartę podarunkową", - "contact_support": "Skontaktuj się z pomocą techniczną", - "gift_cards_unavailable": "Karty podarunkowe można obecnie kupić tylko za pośrednictwem Monero, Bitcoin i Litecoin", - "background_sync_mode": "Tryb synchronizacji w tle", - "sync_all_wallets": "Synchronizuj wszystkie portfele", - "introducing_cake_pay": "Przedstawiamy Cake Pay!", - "cake_pay_learn_more": "Kupuj i wykorzystuj karty podarunkowe od razu w aplikacji!\nPrzesuń od lewej do prawej, aby dowiedzieć się więcej.", - "automatic": "Automatyczny", - "fixed_pair_not_supported": "Ta stała para nie jest obsługiwana na wybranych giełdach", - "variable_pair_not_supported": "Ta para zmiennych nie jest obsługiwana na wybranych giełdach", - "none_of_selected_providers_can_exchange": "Żaden z wybranych dostawców nie może dokonać tej wymiany", - "choose_one": "Wybierz jeden", - "choose_from_available_options": "Wybierz z dostępnych opcji:", - "custom_redeem_amount": "Niestandardowa kwota wykorzystania", - "add_custom_redemption": "Dodaj niestandardowe wykorzystanie", - "remaining": "pozostałe", - "delete_wallet": "Usuń portfel", - "delete_wallet_confirm_message": "Czy na pewno chcesz usunąć portfel ${wallet_name}?", - "low_fee": "Niska opłata", - "low_fee_alert": "Obecnie korzystasz z niskiego priorytetu opłaty sieciowej. Może to spowodować długie oczekiwanie, różne stawki lub anulowane transakcje. Zalecamy ustawienie wyższej opłaty, aby zapewnić lepsze wrażenia.", - "ignor": "Ignorować", - "use_suggested": "Użyj sugerowane", - "do_not_share_warning_text": "NIE udostępniaj ich nikomu innemu, w tym pomocy technicznej.\n\nTwoje środki wtedy prawdopodobnie zostaną skradzione!", - "help": "pomoc", - "all_transactions": "Wszystkie transakcje", - "all_trades": "Wszystkie operacje", - "connection_sync": "Połączenie i synchronizacja", - "security_and_backup": "Bezpieczeństwo i kopia zapasowa", - "create_backup": "Utwórz kopię zapasową", - "privacy_settings": "Ustawienia prywatności", - "privacy": "Prywatność", - "display_settings": "Ustawienia wyświetlania", - "other_settings": "Inne ustawienia", - "require_pin_after": "Wymagaj kodu PIN po", - "always": "zawsze", - "minutes_to_pin_code": "${minute} minut", - "disable_exchange": "Wyłącz wymianę", - "advanced_settings": "Zaawansowane ustawienia", - "settings_can_be_changed_later": "Te ustawienia można później zmienić w ustawieniach aplikacji", - "add_custom_node": "Dodaj nowy węzeł niestandardowy", - "disable_fiat": "Wyłącz waluty FIAT", - "fiat_api": "API Walut FIAT", - "disabled": "Wyłączone", - "enabled": "Włączone", - "tor_only": "Tylko sieć Tor", - "unmatched_currencies": "Waluta Twojego obecnego portfela nie zgadza się z waluctą zeskanowanego kodu QR", - "orbot_running_alert": "Upewnij się, że Orbot działa przed połączeniem z tym węzłem.", - "contact_list_contacts": "Łączność", - "contact_list_wallets": "Moje portfele", - "bitcoin_payments_require_1_confirmation": "Płatności Bitcoin wymagają 1 potwierdzenia, co może zająć 20 minut lub dłużej. Dziękuję za cierpliwość! Otrzymasz wiadomość e-mail, gdy płatność zostanie potwierdzona.", - "send_to_this_address": "Wyślij ${currency} ${tag}na ten adres", - "arrive_in_this_address": "${currency} ${tag}dotrze na ten adres", - "do_not_send": "Nie wysyłaj", - "error_dialog_content": "Ups, wystąpił błąd.\n\nPrześlij raport o awarii do naszego zespołu wsparcia, aby ulepszyć aplikację.", - "scan_qr_code": "Skanowania QR code", - "cold_or_recover_wallet": "Dodaj zimny portfel lub odzyskaj portfel papierowy", - "please_wait": "Proszę czekać", - "sweeping_wallet": "Zamiatanie portfela", - "sweeping_wallet_alert": "To nie powinno zająć dużo czasu. NIE WYCHODŹ Z TEGO EKRANU, W PRZECIWNYM WYPADKU MOŻE ZOSTAĆ UTRACONA ŚRODKI", - "decimal_places_error": "Za dużo miejsc dziesiętnych", - "edit_node": "Edytuj węzeł", - "invoice_details": "Dane do faktury", - "donation_link_details": "Szczegóły linku darowizny", - "anonpay_description": "Wygeneruj ${type}. Odbiorca może ${method} z dowolną obsługiwaną kryptowalutą, a Ty otrzymasz środki w tym portfelu.", - "create_invoice": "Wystaw fakturę", - "create_donation_link": "Utwórz link do darowizny", - "optional_email_hint": "Opcjonalny e-mail z powiadomieniem odbiorcy płatności", - "optional_description": "Opcjonalny opis", - "optional_name": "Opcjonalna nazwa odbiorcy", - "clearnet_link": "łącze Clearnet", - "onion_link": "Łącznik cebulowy", - "settings": "Ustawienia", - "sell_monero_com_alert_content": "Sprzedaż Monero nie jest jeszcze obsługiwana", - "error_text_input_below_minimum_limit": "Kwota jest mniejsza niż minimalna", - "error_text_input_above_maximum_limit": "Kwota jest większa niż maksymalna", - "show_market_place": "Pokaż rynek", - "prevent_screenshots": "Zapobiegaj zrzutom ekranu i nagrywaniu ekranu", - "profile": "Profil", - "close": "Zamknąć", - "modify_2fa": "Zmodyfikuj ciasto 2FA", - "disable_cake_2fa": "Wyłącz Cake 2FA", - "question_to_disable_2fa": "Czy na pewno chcesz wyłączyć Cake 2FA? Kod 2FA nie będzie już potrzebny do uzyskania dostępu do portfela i niektórych funkcji.", - "disable": "Wyłączyć", - "setup_2fa": "Skonfiguruj ciasto 2FA", - "verify_with_2fa": "Sprawdź za pomocą Cake 2FA", - "totp_code": "Kod TOTP", - "please_fill_totp": "Wpisz 8-cyfrowy kod znajdujący się na drugim urządzeniu", - "totp_2fa_success": "Powodzenie! Cake 2FA włączony dla tego portfela. Pamiętaj, aby zapisać swoje mnemoniczne ziarno na wypadek utraty dostępu do portfela.", - "totp_verification_success": "Weryfikacja powiodła się!", - "totp_2fa_failure": "Błędny kod. Spróbuj użyć innego kodu lub wygeneruj nowy tajny klucz. Użyj kompatybilnej aplikacji 2FA, która obsługuje 8-cyfrowe kody i SHA512.", - "enter_totp_code": "Wprowadź kod TOTP.", - "add_secret_code": "Możesz też dodać ten tajny kod do aplikacji uwierzytelniającej", - "totp_secret_code": "Tajny kod TOTP", - "setup_2fa_text": "Cake 2FA działa przy użyciu TOTP jako drugiego czynnika uwierzytelniającego.\n\nTOTP Cake 2FA wymaga obsługi SHA-512 i 8 cyfr; zapewnia to większe bezpieczeństwo. Więcej informacji i obsługiwane aplikacje znajdziesz w przewodniku.", - "setup_totp_recommended": "Skonfiguruj TOTP", - "disable_buy": "Wyłącz akcję kupna", - "disable_sell": "Wyłącz akcję sprzedaży", + "authenticated": "Uwierzytelniony", + "authentication": "Uwierzytelnianie", "auto_generate_subaddresses": "Automatycznie generuj podadresy", - "cake_2fa_preset": "Ciasto 2FA Preset", - "narrow": "Wąski", - "normal": "Normalna", - "aggressive": "Nadgorliwy", - "require_for_assessing_wallet": "Wymagaj dostępu do portfela", - "require_for_sends_to_non_contacts": "Wymagaj wysyłania do osób niekontaktowych", - "require_for_sends_to_contacts": "Wymagaj wysyłania do kontaktów", - "require_for_sends_to_internal_wallets": "Wymagaj wysyłania do portfeli wewnętrznych", - "require_for_exchanges_to_internal_wallets": "Wymagaj wymiany do portfeli wewnętrznych", - "require_for_adding_contacts": "Wymagane do dodania kontaktów", - "require_for_creating_new_wallets": "Wymagane do tworzenia nowych portfeli", - "require_for_all_security_and_backup_settings": "Wymagaj dla wszystkich ustawień zabezpieczeń i kopii zapasowych", + "automatic": "Automatyczny", + "available_balance": "Dostępne środki", "available_balance_description": "Dostępne saldo jest równoważne z saldem portfela minus zamrożone saldo.", - "syncing_wallet_alert_title": "Twój portfel się synchronizuje", - "syncing_wallet_alert_content": "Twoje saldo i lista transakcji mogą nie być kompletne, dopóki u góry nie pojawi się napis „SYNCHRONIZOWANY”. Kliknij/stuknij, aby dowiedzieć się więcej.", - "home_screen_settings": "Ustawienia ekranu głównego", - "sort_by": "Sortuj według", - "search_add_token": "Wyszukaj / Dodaj token", - "edit_token": "Edytuj token", - "warning": "Ostrzeżenie", - "add_token_warning": "Nie edytuj ani nie dodawaj tokenów zgodnie z instrukcjami oszustów.\nZawsze potwierdzaj adresy tokenów z renomowanymi źródłami!", - "add_token_disclaimer_check": "Potwierdziłem adres kontraktu tokena i informacje, korzystając z renomowanego źródła. Dodanie złośliwych lub niepoprawnych informacji może spowodować utratę środków.", - "token_contract_address": "Adres kontraktu tokena", - "token_name": "Nazwa tokena, np.: Tether", - "token_symbol": "Symbol tokena np.: USDT", - "token_decimal": "Token dziesiętny", - "field_required": "To pole jest wymagane", - "pin_at_top": "przypnij ${token} na górze", - "invalid_input": "Nieprawidłowe dane wejściowe", - "fiat_balance": "Bilans Fiata", - "gross_balance": "Saldo brutto", - "alphabetical": "Alfabetyczny", - "generate_name": "Wygeneruj nazwę", + "avg_savings": "Śr. oszczędności", + "awaitDAppProcessing": "Poczekaj, aż dApp zakończy przetwarzanie.", + "awaiting_payment_confirmation": "Oczekiwanie na potwierdzenie płatności", + "background_sync_mode": "Tryb synchronizacji w tle", + "backup": "Kopia zapasowa", + "backup_file": "Plik kopii zapasowej", + "backup_password": "Hasło kpoii zapasowej", "balance_page": "Strona salda", - "share": "Udział", - "slidable": "Przesuwne", - "monero_dark_theme": "Ciemny motyw Monero", + "bill_amount": "Kwota rachunku", + "billing_address_info": "Jeśli zostaniesz poproszony o podanie adresu rozliczeniowego, podaj swój adres wysyłki", + "biometric_auth_reason": "Zeskanuj swój odcisk palca, aby uwierzytelnić", "bitcoin_dark_theme": "Ciemny motyw Bitcoina", "bitcoin_light_theme": "Lekki motyw Bitcoin", - "high_contrast_theme": "Motyw o wysokim kontraście", - "matrix_green_dark_theme": "Matrix Zielony ciemny motyw", - "monero_light_theme": "Lekki motyw Monero", - "manage_nodes": "Zarządzaj węzłami", - "etherscan_history": "Historia Etherscanu", - "template_name": "Nazwa szablonu", + "bitcoin_payments_require_1_confirmation": "Płatności Bitcoin wymagają 1 potwierdzenia, co może zająć 20 minut lub dłużej. Dziękuję za cierpliwość! Otrzymasz wiadomość e-mail, gdy płatność zostanie potwierdzona.", + "Blocks_remaining": "Pozostało ${status} bloków", + "bright_theme": "Biały", + "buy": "Kup", + "buy_alert_content": "Obecnie obsługujemy tylko zakup Bitcoin, Ethereum, Litecoin i Monero. Utwórz lub przełącz się na swój portfel Bitcoin, Ethereum, Litecoin lub Monero.", + "buy_bitcoin": "Kup Bitcoin", + "buy_provider_unavailable": "Dostawca obecnie niedostępny.", + "buy_with": "Kup za pomocą", + "by_cake_pay": "przez Cake Pay", + "cake_2fa_preset": "Ciasto 2FA Preset", + "cake_pay_account_note": "Zarejestruj się, używając tylko adresu e-mail, aby przeglądać i kupować karty. Niektóre są nawet dostępne ze zniżką!", + "cake_pay_learn_more": "Kupuj i wykorzystuj karty podarunkowe od razu w aplikacji!\nPrzesuń od lewej do prawej, aby dowiedzieć się więcej.", + "cake_pay_subtitle": "Kup karty upominkowe ze zniżką (tylko USA)", + "cake_pay_title": "Karty podarunkowe Cake Pay", + "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_wallet": "Cake Wallet", + "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.", + "camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.", + "cancel": "Anuluj", + "card_address": "Adres:", + "cardholder_agreement": "Umowa posiadacza karty", + "cards": "Karty", + "chains": "Więzy", + "change": "Zmień", + "change_backup_password_alert": "Twoje poprzednie pliki kopii zapasowej nie będą dostępne do zaimportowania z nowym hasłem kopii zapasowej. Nowe hasło kopii zapasowej będzie używane tylko dla nowych plików kopii zapasowych. Czy na pewno chcesz zmienić hasło zapasowe?", + "change_currency": "Zmień walutę", + "change_current_node": "Czy na pewno chcesz wybrać ten węzeł? ${node}?", + "change_current_node_title": "Zmień bieżący węzeł", + "change_exchange_provider": "Zmień dostawcę wymiany", + "change_language": "Zmień język", + "change_language_to": "Zmień język na ${language}?", + "change_password": "Zmień hasło", "change_rep": "Zmień przedstawiciela", "change_rep_message": "Czy na pewno chcesz zmienić przedstawiciela?", - "unsupported_asset": "Nie obsługujemy tego działania w przypadku tego zasobu. Utwórz lub przełącz się na portfel obsługiwanego typu aktywów.", - "manage_pow_nodes": "Zarządzaj węzłami PoW", - "support_title_live_chat": "Wsparcie na żywo", - "support_description_live_chat": "Darmowe i szybkie! Do pomocy są dostępni przeszkoleni przedstawiciele wsparcia", - "support_title_guides": "Przewodniki portfela ciasta", - "support_description_guides": "Dokumentacja i wsparcie dla typowych problemów", - "support_title_other_links": "Inne linki wsparcia", - "support_description_other_links": "Dołącz do naszych społeczności lub skontaktuj się z nami naszymi partnerami za pomocą innych metod", + "change_rep_successful": "Pomyślnie zmienił przedstawiciela", + "change_wallet_alert_content": "Czy chcesz zmienić obecny portfel na ${wallet_name}?", + "change_wallet_alert_title": "Zmień obecny portfel", + "choose_account": "Wybierz konto", + "choose_address": "\n\nWybierz adres:", "choose_derivation": "Wybierz wyprowadzenie portfela", - "new_first_wallet_text": "Łatwo zapewnić bezpieczeństwo kryptowalut", - "select_destination": "Wybierz miejsce docelowe dla pliku kopii zapasowej.", - "save_to_downloads": "Zapisz w Pobranych", - "select_buy_provider_notice": "Wybierz powyższe dostawcę zakupu. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę zakupu w ustawieniach aplikacji.", - "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ę.", + "choose_from_available_options": "Wybierz z dostępnych opcji:", + "choose_one": "Wybierz jeden", + "choose_relay": "Wybierz przekaźnik, którego chcesz użyć", + "choose_wallet_currency": "Wybierz walutę portfela:", + "clear": "Wyczyść", + "clearnet_link": "łącze Clearnet", + "close": "Zamknąć", + "coin_control": "Kontrola monet (opcjonalnie)", + "cold_or_recover_wallet": "Dodaj zimny portfel lub odzyskaj portfel papierowy", + "color_theme": "Motyw kolorystyczny", + "commit_transaction_amount_fee": "Zatwierdź transakcję\nIlość: ${amount}\nOpłata: ${fee}", + "confirm": "Potwierdzać", + "confirm_delete_template": "Ta czynność usunie ten szablon. Czy chcesz kontynuować?", + "confirm_delete_wallet": "Ta czynność usunie ten portfel. Czy chcesz kontynuować?", + "confirm_sending": "Potwierdź wysłanie", + "confirmations": "Potwierdzenia", + "confirmed": "Potwierdzone saldo", + "confirmed_tx": "Potwierdzony", + "congratulations": "gratulacje!", + "connect_an_existing_yat": "Podłącz istniejący Yat", + "connect_yats": "Połącz Yats", + "connection_sync": "Połączenie i synchronizacja", + "connectWalletPrompt": "Połącz swój portfel z WalletConnect, aby dokonywać transakcji", + "contact": "Kontakt", + "contact_list_contacts": "Łączność", + "contact_list_wallets": "Moje portfele", + "contact_name": "Nazwa Kontaktu", + "contact_support": "Skontaktuj się z pomocą techniczną", + "continue_text": "Dalej", + "contractName": "Nazwa umowy", + "contractSymbol": "Symbol kontraktu", + "copied_key_to_clipboard": "Skopiowaneo ${key} do schowka", + "copied_to_clipboard": "Skopiowano do schowka", + "copy": "Kopiuj", + "copy_address": "Skopiuj adress", + "copy_id": "skopiuj ID", + "copyWalletConnectLink": "Skopiuj link do WalletConnect z dApp i wklej tutaj", + "create_account": "Utwórz konto", + "create_backup": "Utwórz kopię zapasową", + "create_donation_link": "Utwórz link do darowizny", + "create_invoice": "Wystaw fakturę", + "create_new": "Utwórz nowy portfel", + "create_new_account": "Stwórz nowe konto", + "creating_new_wallet": "Tworzenie nowego portfela", + "creating_new_wallet_error": "Błąd: ${description}", + "creation_date": "Data utworzenia", + "custom": "niestandardowy", + "custom_drag": "Niestandardowe (trzymaj i przeciągnij)", + "custom_redeem_amount": "Niestandardowa kwota wykorzystania", + "dark_theme": "Ciemny", + "debit_card": "Karta debetowa", + "debit_card_terms": "Przechowywanie i używanie numeru karty płatniczej (oraz danych uwierzytelniających odpowiadających numerowi karty płatniczej) w tym portfelu cyfrowym podlega Warunkom odpowiedniej umowy posiadacza karty z wydawcą karty płatniczej, zgodnie z obowiązującym od od czasu do czasu.", + "decimal_places_error": "Za dużo miejsc dziesiętnych", "default_buy_provider": "Domyślny dostawca zakupu", - "ask_each_time": "Zapytaj za każdym razem", - "buy_provider_unavailable": "Dostawca obecnie niedostępny.", - "signTransaction": "Podpisz transakcję", + "default_sell_provider": "Domyślny dostawca sprzedaży", + "delete": "Skasuj", + "delete_account": "Usuń konto", + "delete_wallet": "Usuń portfel", + "delete_wallet_confirm_message": "Czy na pewno chcesz usunąć portfel ${wallet_name}?", + "deleteConnectionConfirmationPrompt": "Czy na pewno chcesz usunąć połączenie z", + "descending": "Schodzenie", + "description": "Opis", + "destination_tag": "Tag docelowy:", + "dfx_option_description": "Kupuj kryptowaluty za EUR i CHF. Do 990 € bez dodatkowego KYC. Dla klientów detalicznych i korporacyjnych w Europie", + "didnt_get_code": "Nie dostałeś kodu?", + "digit_pin": "-znakowy PIN", + "digital_and_physical_card": " cyfrowa i fizyczna przedpłacona karta debetowa", + "disable": "Wyłączyć", + "disable_buy": "Wyłącz akcję kupna", + "disable_cake_2fa": "Wyłącz Cake 2FA", + "disable_exchange": "Wyłącz wymianę", + "disable_fiat": "Wyłącz waluty FIAT", + "disable_sell": "Wyłącz akcję sprzedaży", + "disabled": "Wyłączone", + "discount": "Zaoszczędź ${value}%", + "display_settings": "Ustawienia wyświetlania", + "displayable": "Wyświetlane", + "do_not_have_enough_gas_asset": "Nie masz wystarczającej ilości ${currency}, aby dokonać transakcji przy bieżących warunkach sieci blockchain. Potrzebujesz więcej ${currency}, aby uiścić opłaty za sieć blockchain, nawet jeśli wysyłasz inny zasób.", + "do_not_send": "Nie wysyłaj", + "do_not_share_warning_text": "NIE udostępniaj ich nikomu innemu, w tym pomocy technicznej.\n\nTwoje środki wtedy prawdopodobnie zostaną skradzione!", + "do_not_show_me": "Nie pokazuj mi tego ponownie", + "domain_looks_up": "Wyszukiwanie domen", + "donation_link_details": "Szczegóły linku darowizny", + "e_sign_consent": "Zgoda na podpis elektroniczny", + "edit": "Edytuj", + "edit_backup_password": "Edytuj hasło kopii zapasowej", + "edit_node": "Edytuj węzeł", + "edit_token": "Edytuj token", + "electrum_address_disclaimer": "Za każdym razem, gdy wykorzystasz adres, dla wiekszej prywatności generujemy nowy, ale poprzednie adresy nadal działają, i moga odbierać środki", + "email_address": "Adres e-mail", + "enabled": "Włączone", + "enter_amount": "Wprowadź kwotę", + "enter_backup_password": "Wprowadź tutaj hasło kopii zapasowej", + "enter_code": "Wprowadź kod", + "enter_seed_phrase": "Wprowadź swoją frazę nasienną", + "enter_totp_code": "Wprowadź kod TOTP.", + "enter_your_note": "Wpisz notatkę…", + "enter_your_pin": "Wpisz kod PIN", + "enter_your_pin_again": "Wprowadź ponownie swój kod PIN", + "enterTokenID": "Wprowadź identyfikator tokena", + "enterWalletConnectURI": "Wprowadź identyfikator URI WalletConnect", + "error": "Błąd", + "error_dialog_content": "Ups, wystąpił błąd.\n\nPrześlij raport o awarii do naszego zespołu wsparcia, aby ulepszyć aplikację.", + "error_text_account_name": "Nazwa konta może zawierać tylko litery, cyfry\ni musi mieć od 1 do 15 znaków", + "error_text_address": "Adres musi odpowiadać typowi kryptowaluty", + "error_text_amount": "Kwota może zawierać tylko liczby", + "error_text_contact_name": "Nazwa kontaktu nie może zawierać symboli ` , ' \"\ni musi mieć od 1 do 32 znaków ", + "error_text_crypto_currency": "Liczba cyfr ułamkowych\nmusi być mniejsza lub równa 12", + "error_text_fiat": "Wartość kwoty nie może przekroczyć dostępnego salda.\nLiczba cyfr ułamkowych musi być mniejsza lub równa 2", + "error_text_input_above_maximum_limit": "Kwota jest większa niż maksymalna", + "error_text_input_below_minimum_limit": "Kwota jest mniejsza niż minimalna", + "error_text_keys": "Klucze portfela mogą zawierać tylko 64 znaki w systemie szesnastkowym", + "error_text_limits_loading_failed": "Wymiana dla ${provider} nie została utworzona. Ładowanie limitów nie powiodło się", + "error_text_maximum_limit": "Wymiana dla ${provider} nie została utworzona. Kwota jest większa niż maksymalna: ${max} ${currency}", + "error_text_minimal_limit": "Wymiana dla ${provider} nie została utworzona. Kwota jest mniejsza niż minimalna: ${min} ${currency}", + "error_text_node_address": "Wpisz adres iPv4", + "error_text_node_port": "Port węzła może zawierać tylko liczby od 0 do 65535", + "error_text_node_proxy_address": "Wprowadź :, na przykład 127.0.0.1:9050", + "error_text_payment_id": "ID może zawierać od 16 do 64 znaków w formacie szesnastkowym", + "error_text_subaddress_name": "Nazwa podadresu nie może zawierać symboli ` , ' \"\ni musi mieć od 1 do 20 znaków", + "error_text_template": "Nazwa i adres szablonu nie mogą zawierać ` , ' \" symbolika\ni musi mieć od 1 do 106 znaków", + "error_text_wallet_name": "Nazwa portfela może zawierać tylko litery, cyfry lub symbole _ - \ni musi mieć od 1 do 33 znaków", + "error_text_xmr": "Wartość XMR nie może przekraczać dostępnego salda.\nLiczba cyfr ułamkowych musi być mniejsza lub równa 12", "errorGettingCredentials": "Niepowodzenie: Błąd podczas uzyskiwania poświadczeń", "errorSigningTransaction": "Wystąpił błąd podczas podpisywania transakcji", - "pairingInvalidEvent": "Nieprawidłowe zdarzenie parowania", - "chains": "Więzy", - "methods": "Metody", - "events": "Wydarzenia", - "reject": "Odrzucić", - "approve": "Zatwierdzić", - "expiresOn": "Upływa w dniu", - "walletConnect": "PortfelPołącz", - "nullURIError": "URI ma wartość zerową", - "connectWalletPrompt": "Połącz swój portfel z WalletConnect, aby dokonywać transakcji", - "newConnection": "Nowe połączenie", - "activeConnectionsPrompt": "Tutaj pojawią się aktywne połączenia", - "deleteConnectionConfirmationPrompt": "Czy na pewno chcesz usunąć połączenie z", + "estimated": "Oszacowano", + "etherscan_history": "Historia Etherscanu", "event": "Wydarzenie", - "successful": "Udany", - "wouoldLikeToConnect": "chciałbym się połączyć", - "message": "Wiadomość", - "do_not_have_enough_gas_asset": "Nie masz wystarczającej ilości ${currency}, aby dokonać transakcji przy bieżących warunkach sieci blockchain. Potrzebujesz więcej ${currency}, aby uiścić opłaty za sieć blockchain, nawet jeśli wysyłasz inny zasób.", - "totp_auth_url": "Adres URL TOTP AUTH", - "awaitDAppProcessing": "Poczekaj, aż dApp zakończy przetwarzanie.", - "copyWalletConnectLink": "Skopiuj link do WalletConnect z dApp i wklej tutaj", - "enterWalletConnectURI": "Wprowadź identyfikator URI WalletConnect", - "seed_key": "Klucz nasion", - "enter_seed_phrase": "Wprowadź swoją frazę nasienną", - "change_rep_successful": "Pomyślnie zmienił przedstawiciela", - "add_contact": "Dodaj kontakt", + "events": "Wydarzenia", + "exchange": "Wymień", + "exchange_incorrect_current_wallet_for_xmr": "Jeśli chcesz wymienić XMR z salda Cake Wallet Monero, najpierw przełącz się na portfel Monero.", + "exchange_new_template": "Nowy szablon wymiany", "exchange_provider_unsupported": "${providerName} nie jest już obsługiwany!", - "domain_looks_up": "Wyszukiwanie domen", - "require_for_exchanges_to_external_wallets": "Wymagaj wymiany na portfele zewnętrzne", - "camera_permission_is_required": "Wymagane jest pozwolenie na korzystanie z aparatu.\nWłącz tę funkcję w ustawieniach aplikacji.", - "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie", - "order_by": "Zamów przez", - "creation_date": "Data utworzenia", + "exchange_result_confirm": "Naciskając Potwierdź, wyślesz ${fetchingLabel} ${from} z twojego portfela ${walletName} na adres podany poniżej. Lub możesz wysłać z zewnętrznego portfela na poniższy adres / kod QR.\n\nNaciśnij Potwierdź, aby kontynuować lub wróć, aby zmienić kwoty.", + "exchange_result_description": "Musisz wysłać co najmniej ${fetchingLabel} ${from} na adres podany na następnej stronie. Jeśli wyślesz kwotę niższą niż ${fetchingLabel} ${from}, może ona nie zostać uwzględniona i może nie zostać zwrócona.", + "exchange_result_write_down_ID": "*Skopiuj lub zanotuj identyfikator transakcji pokazany powyżej.", + "exchange_result_write_down_trade_id": "Skopiuj lub zanotuj identyfikator transakcji (ID), aby kontynuować.", + "exchange_sync_alert_content": "Poczekaj, aż portfel zostanie zsynchronizowany", + "expired": "Przedawniony", + "expires": "Wygasa", + "expiresOn": "Upływa w dniu", + "export_backup": "Eksportuj kopię zapasową", + "extra_id": "Dodatkowy ID:", + "extracted_address_content": "Wysyłasz środki na\n${recipient_name}", + "failed_authentication": "Nieudane uwierzytelnienie. ${state_error}", + "faq": "FAQ", + "fetching": "Pobieranie", + "fiat_api": "API Walut FIAT", + "fiat_balance": "Bilans Fiata", + "field_required": "To pole jest wymagane", + "fill_code": "Proszę wpisać kod weryfikacyjny który otrzymałeś w wiadomości e-mail", + "filter_by": "Filtruj według", + "first_wallet_text": "Świetny portfel na Monero, Bitcoin, Ethereum, Litecoin, i Haven", + "fixed_pair_not_supported": "Ta stała para nie jest obsługiwana na wybranych giełdach", + "fixed_rate": "Stała stawka", + "fixed_rate_alert": "Będziesz mógł wprowadzić kwotę do otrzymania, gdy wybrany bedzie tryb stałego przeliczenia. Czy chcesz przejść do trybu stałej stawki?", + "forgot_password": "Zapomniałem hasła", + "freeze": "Zamróź", + "frequently_asked_questions": "Często zadawane pytania", + "frozen": "Zamrożone", + "full_balance": "Pełne saldo", + "generate_name": "Wygeneruj nazwę", + "generating_gift_card": "Generowanie karty podarunkowej", + "get_a": "Zdobądź ", + "get_card_note": " które możesz doładować walutami cyfrowymi. Nie są potrzebne żadne dodatkowe informacje!", + "get_your_yat": "Zdobądź swój Yat", + "gift_card_amount": "Kwota karty podarunkowej", + "gift_card_balance_note": "Tutaj pojawią się karty podarunkowe z pozostałym saldem", + "gift_card_is_generated": "Karta podarunkowa jest generowana", + "gift_card_number": "Numer karty podarunkowej", + "gift_card_redeemed_note": "Karty podarunkowe, które wykorzystałeś, pojawią się tutaj", + "gift_cards": "Karty podarunkowe", + "gift_cards_unavailable": "Karty podarunkowe można obecnie kupić tylko za pośrednictwem Monero, Bitcoin i Litecoin", + "got_it": "Wysłano", + "gross_balance": "Saldo brutto", "group_by_type": "Grupa według typu", - "importNFTs": "Importuj NFT", - "noNFTYet": "Nie ma jeszcze NFT", - "address": "Adres", - "enterTokenID": "Wprowadź identyfikator tokena", - "tokenID": "ID", - "name": "Nazwa", - "symbol": "Symbol", - "seed_phrase_length": "Długość frazy początkowej", - "unavailable_balance": "Niedostępne saldo", - "unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.", - "unspent_change": "Zmiana", - "tor_connection": "Połączenie Torem", - "setup_warning_2fa_text": "Będziesz musiał przywrócić swój portfel z nasion mnemonicznych.\n\nWsparcie Cake nie będzie w stanie Ci pomóc, jeśli utracisz dostęp do swoich nasion 2FA lub mnemoników.\nCake 2FA to drugie uwierzytelnienie niektórych działań w portfelu. Przed użyciem Cake 2FA zalecamy zapoznanie się z instrukcją.NIE jest tak bezpieczne jak przechowywanie w chłodni.\n\nJeśli utracisz dostęp do aplikacji 2FA lub kluczy TOTP, UTRAcisz dostęp do tego portfela. ", - "scan_qr_on_device": "Zeskanuj ten kod QR na innym urządzeniu", + "haven_app": "Haven by Cake Wallet", + "haven_app_wallet_text": "Awesome wallet for Haven", + "help": "pomoc", + "hidden_balance": "Ukryte saldo", + "hide_details": "Ukryj szczegóły", + "high_contrast_theme": "Motyw o wysokim kontraście", + "home_screen_settings": "Ustawienia ekranu głównego", "how_to_use": "Jak używać", + "how_to_use_card": "Jak korzystać z tej karty?", + "id": "ID: ", + "ignor": "Ignorować", + "import": "Import", + "importNFTs": "Importuj NFT", + "in_store": "W Sklepie", + "incoming": "Przychodzące", + "incorrect_seed": "Wprowadzony seed jest nieprawidłowy.", + "introducing_cake_pay": "Przedstawiamy Cake Pay!", + "invalid_input": "Nieprawidłowe dane wejściowe", + "invoice_details": "Dane do faktury", + "is_percentage": "jest", + "last_30_days": "Ostatnie 30 dni", + "learn_more": "Dowiedz się więcej", + "light_theme": "Jasny", + "loading_your_wallet": "Ładowanie portfela", + "login": "Login", + "logout": "Wyloguj", + "low_fee": "Niska opłata", + "low_fee_alert": "Obecnie korzystasz z niskiego priorytetu opłaty sieciowej. Może to spowodować długie oczekiwanie, różne stawki lub anulowane transakcje. Zalecamy ustawienie wyższej opłaty, aby zapewnić lepsze wrażenia.", + "manage_nodes": "Zarządzaj węzłami", + "manage_pow_nodes": "Zarządzaj węzłami PoW", + "manage_yats": "Zarządzaj Yats", + "mark_as_redeemed": "Oznacz jako wykorzystany", + "market_place": "Rynek", + "matrix_green_dark_theme": "Matrix Zielony ciemny motyw", + "max_amount": "Max: ${value}", + "max_value": "Max: ${value} ${currency}", + "memo": "Notatka:", + "message": "Wiadomość", + "methods": "Metody", + "min_amount": "Min: ${value}", + "min_value": "Min: ${value} ${currency}", + "minutes_to_pin_code": "${minute} minut", + "mm": "MM", + "modify_2fa": "Zmodyfikuj ciasto 2FA", + "monero_com": "Monero.com by Cake Wallet", + "monero_com_wallet_text": "Awesome wallet for Monero", + "monero_dark_theme": "Ciemny motyw Monero", + "monero_light_theme": "Lekki motyw Monero", + "moonpay_alert_text": "Wartość kwoty musi być większa lub równa ${minAmount} ${fiatCurrency}", + "more_options": "Więcej opcji", + "name": "Nazwa", + "narrow": "Wąski", + "new_first_wallet_text": "Łatwo zapewnić bezpieczeństwo kryptowalut", + "new_node_testing": "Testowanie nowych węzłów", + "new_subaddress_create": "Stwórz", + "new_subaddress_label_name": "Etykieta nazwy adresu", + "new_subaddress_title": "Nowy adres", + "new_template": "Nowy szablon", + "new_wallet": "Nowy portfel", + "newConnection": "Nowe połączenie", + "no_id_needed": "Nie potrzeba Dowodu!", + "no_id_required": "Nie wymagamy Dowodu. Doładuj i wydawaj gdziekolwiek", + "no_relay_on_domain": "Brak przekaźnika dla domeny użytkownika lub przekaźnik jest niedostępny. Wybierz przekaźnik, którego chcesz użyć.", + "no_relays": "Żadnych przekaźników", + "no_relays_message": "Znaleźliśmy rekord Nostr NIP-05 dla tego użytkownika, ale nie zawiera on żadnych przekaźników. Poinstruuj odbiorcę, aby dodał przekaźniki do swojego rekordu Nostr.", + "node_address": "Adres węzła", + "node_connection_failed": "Połączenie nie powiodło się", + "node_connection_successful": "Połączenie powiodło się", + "node_new": "Nowy węzeł", + "node_port": "Port węzła", + "node_reset_settings_title": "Zresetuj ustawienia węzłów", + "node_test": "Test", + "nodes": "Węzły", + "nodes_list_reset_to_default_message": "Czy na pewno chcesz przywrócić ustawienia domyślne?", + "none_of_selected_providers_can_exchange": "Żaden z wybranych dostawców nie może dokonać tej wymiany", + "noNFTYet": "Nie ma jeszcze NFT", + "normal": "Normalna", + "note_optional": "Notatka (opcjonalnie)", + "note_tap_to_change": "Notatka (dotknij, aby zmienić)", + "nullURIError": "URI ma wartość zerową", + "offer_expires_in": "Oferta wygasa za ", + "offline": "Offline", + "ok": "Ok", + "onion_link": "Łącznik cebulowy", + "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ą", + "optional_description": "Opcjonalny opis", + "optional_email_hint": "Opcjonalny e-mail z powiadomieniem odbiorcy płatności", + "optional_name": "Opcjonalna nazwa odbiorcy", + "optionally_order_card": "Opcjonalnie zamów kartę fizyczną.", + "orbot_running_alert": "Upewnij się, że Orbot działa przed połączeniem z tym węzłem.", + "order_by": "Zamów przez", + "order_id": "Identyfikator zamówienia", + "order_physical_card": "Zamów kartę fizyczną", + "other_settings": "Inne ustawienia", + "outdated_electrum_wallet_description": "Nowe portfele Bitcoin utworzone w Cake mają teraz fraze seed składające się z 24 słów. Konieczne jest utworzenie nowego portfela Bitcoin i przeniesienie wszystkich środków do nowego portfela na 24 słowa oraz zaprzestanie korzystania z portfeli z frazą seed na 12 słów. Zrób to natychmiast, aby zabezpieczyć swoje fundusze.", + "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", + "overwrite_amount": "Nadpisz ilość", + "pairingInvalidEvent": "Nieprawidłowe zdarzenie parowania", + "password": "Hasło", + "paste": "Wklej", + "pause_wallet_creation": "Możliwość utworzenia Portfela Haven jest obecnie wstrzymana.", + "payment_id": "ID Płatności: ", + "payment_was_received": "Twoja płatność została otrzymana.", + "pending": " (w oczekiwaniu)", + "percentageOf": "z ${amount}", + "pin_at_top": "przypnij ${token} na górze", + "pin_is_incorrect": "PIN jest niepoprawny", + "pin_number": "Numer PIN", + "placeholder_contacts": "Twoje kontakty zostaną wyświetlone tutaj", + "placeholder_transactions": "Twoje transakcje zostaną wyświetlone tutaj", + "please_fill_totp": "Wpisz 8-cyfrowy kod znajdujący się na drugim urządzeniu", + "please_make_selection": "Wybierz poniżej, aby utworzyć lub przywrócić swój portfel.", + "please_reference_document": "Proszę odwołać się do poniższych dokumentów, aby uzyskać więcej informacji.", + "please_select": "Proszę wybrać:", + "please_select_backup_file": "Wybierz plik kopii zapasowej i wprowadź hasło.", + "please_try_to_connect_to_another_node": "Spróbuj połączyć się z innym węzłem", + "please_wait": "Proszę czekać", + "polygonscan_history": "Historia PolygonScan", + "powered_by": "Obsługiwane przez ${title}", + "pre_seed_button_text": "Rozumiem. Pokaż mi moją fraze seed", + "pre_seed_description": "Na następnej stronie zobaczysz serię ${words} słów. To jest Twoja unikalna i prywatna fraza seed i jest to JEDYNY sposób na odzyskanie portfela w przypadku utraty lub awarii telefonu. Twoim obowiązkiem jest zapisanie go i przechowywanie w bezpiecznym miejscu (np. na kartce w SEJFIE).", + "pre_seed_title": "WAŻNY", + "prevent_screenshots": "Zapobiegaj zrzutom ekranu i nagrywaniu ekranu", + "privacy": "Prywatność", + "privacy_policy": "Polityka prywatności", + "privacy_settings": "Ustawienia prywatności", + "private_key": "Klucz prywatny", + "proceed_after_one_minute": "Jeśli ekran nie przejdzie dalej po 1 minucie, sprawdź pocztę.", + "profile": "Profil", + "provider_error": "${provider} pomyłka", + "public_key": "Klucz publiczny", + "purchase_gift_card": "Kup kartę podarunkową", + "qr_fullscreen": "Dotknij, aby otworzyć pełnoekranowy kod QR", + "qr_payment_amount": "Ten kod QR zawiera kwotę do zapłaty. Czy chcesz nadpisać obecną wartość?", + "question_to_disable_2fa": "Czy na pewno chcesz wyłączyć Cake 2FA? Kod 2FA nie będzie już potrzebny do uzyskania dostępu do portfela i niektórych funkcji.", + "receivable_balance": "Saldo należności", + "receive": "Otrzymaj", + "receive_amount": "Ilość", + "received": "Odebrane", + "recipient_address": "Adres odbiorcy", + "reconnect": "Połącz ponownie", + "reconnect_alert_text": "Czy na pewno ponownie się ponownie połączysz?", + "reconnection": "Ponowne łączenie", + "redeemed": "wykupione", + "refund_address": "Adres do zwrotu", + "reject": "Odrzucić", + "remaining": "pozostałe", + "remove": "Usuń", + "remove_node": "Usuń węzeł", + "remove_node_message": "Czy na pewno chcesz usunąć wybrany węzeł?", + "rename": "Zmień nazwę", + "require_for_adding_contacts": "Wymagane do dodania kontaktów", + "require_for_all_security_and_backup_settings": "Wymagaj dla wszystkich ustawień zabezpieczeń i kopii zapasowych", + "require_for_assessing_wallet": "Wymagaj dostępu do portfela", + "require_for_creating_new_wallets": "Wymagane do tworzenia nowych portfeli", + "require_for_exchanges_to_external_wallets": "Wymagaj wymiany na portfele zewnętrzne", + "require_for_exchanges_to_internal_wallets": "Wymagaj wymiany do portfeli wewnętrznych", + "require_for_sends_to_contacts": "Wymagaj wysyłania do kontaktów", + "require_for_sends_to_internal_wallets": "Wymagaj wysyłania do portfeli wewnętrznych", + "require_for_sends_to_non_contacts": "Wymagaj wysyłania do osób niekontaktowych", + "require_pin_after": "Wymagaj kodu PIN po", + "rescan": "Skanuj ponownie", + "resend_code": "Wyślij go ponownie", + "reset": "Wyczyść", + "reset_password": "Zresetuj hasło", + "restore_active_seed": "Aktywne seedy", + "restore_address": "Adres", + "restore_bitcoin_description_from_keys": "Przywróć swój portfel z klucza prywatnego", + "restore_bitcoin_description_from_seed": "Przywróć swój portfel z frazy seed złożonej z 24 słów", + "restore_bitcoin_title_from_keys": "Przywróć z klucza prywatnego", + "restore_description_from_backup": "Możesz przywrócić całą aplikację Cake Wallet z pliku kopii zapasowej", + "restore_description_from_keys": "Przywróć swój portfel z kluczy prywatnych", + "restore_description_from_seed": "Przywróć swój portfel z 25 lub 13-słownej frazy seed", + "restore_description_from_seed_keys": "Odzyskaj swój portfel z seedów / kluczy, które zapisałeś w bezpiecznym miejscu", + "restore_from_date_or_blockheight": "Wprowadź datę na kilka dni przed utworzeniem tego portfela, lub jeśli znasz wysokość bloku, wprowadź go zamiast daty", + "restore_from_seed_placeholder": "Wpisz lub wklej tutaj swoją frazę seed", + "restore_new_seed": "Nowy seed", + "restore_next": "Kolejny", + "restore_recover": "Przywróć", + "restore_restore_wallet": "Przywróć portfel", + "restore_seed_keys_restore": "Przywracanie seedów / kluczy", + "restore_spend_key_private": "Podaj prywatny klucz wglądu (view key)", + "restore_title_from_backup": "Przywróć z pliku kopii zapasowej", + "restore_title_from_keys": "Przywróć z kluczy", + "restore_title_from_seed": "Przywróć z seedów", + "restore_title_from_seed_keys": "Przywróć z seedów / kluczy", + "restore_view_key_private": "Podaj klucz prywatny", + "restore_wallet": "Przywróć portfel", + "restore_wallet_name": "Nazwa portfela", + "restore_wallet_restore_description": "Przywracanie portfela", + "router_no_route": "Brak zdefiniowanej trasy dla ${name}", + "save": "Zapisz", + "save_backup_password": "Upewnij się, że zapisałeś swoje hasło kopii zapasowej. Bez tego nie będziesz mógł zaimportować pliku kopii zapasowej.", + "save_backup_password_alert": "Zapisz hasło kopii zapasowej", + "save_to_downloads": "Zapisz w Pobranych", + "saved_the_trade_id": "Zapisałem ID", + "scan_qr_code": "Skanowania QR code", + "scan_qr_code_to_get_address": "Zeskanuj kod QR, aby uzyskać adres", + "scan_qr_on_device": "Zeskanuj ten kod QR na innym urządzeniu", + "search": "Szukaj", + "search_add_token": "Wyszukaj / Dodaj token", + "search_category": "Kategoria wyszukiwania", + "search_currency": "Wyszukaj walutę", + "search_language": "Wyszukaj język", + "second_intro_content": "Twój Yat to jeden unikalny adres emoji, który zastępuje wszystkie Twoje długie adresy szesnastkowe dla wszystkich Twoich walut.", + "second_intro_title": "Jeden adres emoji, aby zarzadzać wszystkimi walutami", + "security_and_backup": "Bezpieczeństwo i kopia zapasowa", + "seed_alert_back": "Wróć", + "seed_alert_content": "Fraza Seed to jedyny sposób na odzyskanie portfela. Zapisałeś ją?", + "seed_alert_title": "Uwaga", + "seed_alert_yes": "Tak", + "seed_choose": "Wybierz język", "seed_hex_form": "Nasiona portfela (forma sześciokątna)", + "seed_key": "Klucz nasion", + "seed_language": "Język nasion", + "seed_language_chinese": "Chiński", + "seed_language_chinese_traditional": "Chiński tradycyjny)", + "seed_language_czech": "Czech", + "seed_language_dutch": "Holenderski", + "seed_language_english": "Angielski", + "seed_language_french": "Francuski", + "seed_language_german": "Niemiecki", + "seed_language_italian": "Włoski", + "seed_language_japanese": "Japoński", + "seed_language_korean": "koreański", + "seed_language_next": "Następny", + "seed_language_portuguese": "Portugalski", + "seed_language_russian": "Rosyjski", + "seed_language_spanish": "Hiszpański", + "seed_phrase_length": "Długość frazy początkowej", + "seed_reminder": "Musisz zapisać tą fraze, bo bez niej możesz nie odzyskać portfela!", + "seed_share": "Udostępnij seed", + "seed_title": "Seed", "seedtype": "Sedtype", "seedtype_legacy": "Dziedzictwo (25 słów)", "seedtype_polyseed": "Poliqueed (16 słów)", - "seed_language_czech": "Czech", - "seed_language_korean": "koreański", - "seed_language_chinese_traditional": "Chiński tradycyjny)", - "ascending": "Wznoszący się", - "descending": "Schodzenie", - "dfx_option_description": "Kupuj kryptowaluty za EUR i CHF. Do 990 € bez dodatkowego KYC. Dla klientów detalicznych i korporacyjnych w Europie", - "polygonscan_history": "Historia PolygonScan", - "wallet_seed_legacy": "Dziedziczne ziarno portfela", - "default_sell_provider": "Domyślny dostawca sprzedaży", + "select_backup_file": "Wybierz plik kopii zapasowej", + "select_buy_provider_notice": "Wybierz powyższe dostawcę zakupu. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę zakupu w ustawieniach aplikacji.", + "select_destination": "Wybierz miejsce docelowe dla pliku kopii zapasowej.", "select_sell_provider_notice": "Wybierz dostawcę sprzedaży powyżej. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę sprzedaży w ustawieniach aplikacji.", - "custom_drag": "Niestandardowe (trzymaj i przeciągnij)", + "sell": "Sprzedać", + "sell_alert_content": "Obecnie obsługujemy tylko sprzedaż Bitcoin, Ethereum i Litecoin. Utwórz lub przełącz się na swój portfel Bitcoin, Ethereum lub Litecoin.", + "sell_monero_com_alert_content": "Sprzedaż Monero nie jest jeszcze obsługiwana", + "send": "Wyślij", + "send_address": "Adres ${cryptoCurrency}", + "send_amount": "Ilość:", + "send_creating_transaction": "Tworzenie transakcji", + "send_error_currency": "Waluta może zawierać tylko cyfry", + "send_error_minimum_value": "Minimalna wartość to 0,01", + "send_estimated_fee": "Szacowana opłata:", + "send_fee": "Opłata:", + "send_name": "Imię", + "send_new": "Nowy", + "send_payment_id": "Identyfikator płatności (opcjonalny)", + "send_priority": "Obecnie opłata ustalona jest na ${transactionPriority} priorytet.\nPriorytet transakcji można zmienić w ustawieniach", + "send_sending": "Wysyłanie...", + "send_success": "Twoje ${crypto} zostało pomyślnie wysłane", + "send_templates": "Szablony", + "send_title": "Wyślij", + "send_to_this_address": "Wyślij ${currency} ${tag}na ten adres", + "send_xmr": "Wyślij XMR", + "send_your_wallet": "Twój portfel", + "sending": "Wysyłanie", + "sent": "Wysłano", + "settings": "Ustawienia", + "settings_all": "Wszystkie", + "settings_allow_biometrical_authentication": "Zezwalaj na uwierzytelnianie biometryczne", + "settings_can_be_changed_later": "Te ustawienia można później zmienić w ustawieniach aplikacji", + "settings_change_language": "Zmień język", + "settings_change_pin": "Zmień PIN", + "settings_currency": "Waluta", + "settings_current_node": "Bieżący węzeł", + "settings_dark_mode": "Tryb ciemny", + "settings_display_balance": "Wyświetl saldo", + "settings_display_on_dashboard_list": "Wyświetl na pulpicie", + "settings_fee_priority": "Priorytet opłaty", + "settings_nodes": "Węzły", + "settings_none": "Żaden", + "settings_only_trades": "Tylko transakcje", + "settings_only_transactions": "Tylko transakcje", + "settings_personal": "Osobiste", + "settings_save_recipient_address": "Zapisz adres odbiorcy", + "settings_support": "Wsparcie", + "settings_terms_and_conditions": "Zasady i warunki", + "settings_title": "Ustawienia", + "settings_trades": "Transakcje", + "settings_transactions": "Transakcje", + "settings_wallets": "Portfele", + "setup_2fa": "Skonfiguruj ciasto 2FA", + "setup_2fa_text": "Cake 2FA działa przy użyciu TOTP jako drugiego czynnika uwierzytelniającego.\n\nTOTP Cake 2FA wymaga obsługi SHA-512 i 8 cyfr; zapewnia to większe bezpieczeństwo. Więcej informacji i obsługiwane aplikacje znajdziesz w przewodniku.", + "setup_pin": "Ustaw PIN", + "setup_successful": "Twój kod PIN został pomyślnie skonfigurowany!", + "setup_totp_recommended": "Skonfiguruj TOTP", + "setup_warning_2fa_text": "Będziesz musiał przywrócić swój portfel z nasion mnemonicznych.\n\nWsparcie Cake nie będzie w stanie Ci pomóc, jeśli utracisz dostęp do swoich nasion 2FA lub mnemoników.\nCake 2FA to drugie uwierzytelnienie niektórych działań w portfelu. Przed użyciem Cake 2FA zalecamy zapoznanie się z instrukcją.NIE jest tak bezpieczne jak przechowywanie w chłodni.\n\nJeśli utracisz dostęp do aplikacji 2FA lub kluczy TOTP, UTRAcisz dostęp do tego portfela. ", + "setup_your_debit_card": "Skonfiguruj swoją kartę debetową", + "share": "Udział", + "share_address": "Udostępnij adres", + "show_details": "Pokaż szczegóły", + "show_keys": "Pokaż seed/klucze", + "show_market_place": "Pokaż rynek", + "show_seed": "Pokaż frazy seed", + "sign_up": "Zarejestruj się", + "signTransaction": "Podpisz transakcję", + "signup_for_card_accept_terms": "Zarejestruj się, aby otrzymać kartę i zaakceptuj warunki.", + "slidable": "Przesuwne", + "sort_by": "Sortuj według", + "spend_key_private": "Klucz prywatny", + "spend_key_public": "Klucz publiczny", + "status": "Status: ", + "subaddress_title": "Lista podadresów", + "subaddresses": "Podadresy", + "submit_request": "Złóż wniosek", + "successful": "Udany", + "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_live_chat": "Wsparcie na żywo", + "support_title_other_links": "Inne linki wsparcia", + "sweeping_wallet": "Zamiatanie portfela", + "sweeping_wallet_alert": "To nie powinno zająć dużo czasu. NIE WYCHODŹ Z TEGO EKRANU, W PRZECIWNYM WYPADKU MOŻE ZOSTAĆ UTRACONA ŚRODKI", + "switchToETHWallet": "Przejdź na portfel Ethereum i spróbuj ponownie", "switchToEVMCompatibleWallet": "Przejdź na portfel zgodny z EVM i spróbuj ponownie (Ethereum, Polygon)", - "receivable_balance": "Saldo należności", - "confirmed_tx": "Potwierdzony", + "symbol": "Symbol", + "sync_all_wallets": "Synchronizuj wszystkie portfele", + "sync_status_attempting_sync": "PRÓBA SYNCHRONIZACJI", + "sync_status_connected": "POŁĄCZONY", + "sync_status_connecting": "ŁĄCZENIE", + "sync_status_failed_connect": "POŁĄCZENIE NIEUDANE", + "sync_status_not_connected": "NIE POŁĄCZONY", + "sync_status_starting_sync": "ROZPOCZĘCIE SYNCHRONIZACJI", + "sync_status_syncronized": "ZSYNCHRONIZOWANO", + "sync_status_syncronizing": "SYNCHRONIZACJA", + "syncing_wallet_alert_content": "Twoje saldo i lista transakcji mogą nie być kompletne, dopóki u góry nie pojawi się napis „SYNCHRONIZOWANY”. Kliknij/stuknij, aby dowiedzieć się więcej.", + "syncing_wallet_alert_title": "Twój portfel się synchronizuje", + "template": "Szablon", + "template_name": "Nazwa szablonu", + "third_intro_content": "Yats mieszkają również poza Cake Wallet. Każdy adres portfela na ziemi można zastąpić Yat!", + "third_intro_title": "Yat ładnie bawi się z innymi", + "time": "${minutes}m ${seconds}s", + "tip": "wskazówka:", + "today": "Dzisiaj", + "token_contract_address": "Adres kontraktu tokena", + "token_decimal": "Token dziesiętny", + "token_name": "Nazwa tokena, np.: Tether", + "token_symbol": "Symbol tokena np.: USDT", + "tokenID": "ID", + "tor_connection": "Połączenie Torem", + "tor_only": "Tylko sieć Tor", + "total_saving": "Całkowite oszczędności", + "totp_2fa_failure": "Błędny kod. Spróbuj użyć innego kodu lub wygeneruj nowy tajny klucz. Użyj kompatybilnej aplikacji 2FA, która obsługuje 8-cyfrowe kody i SHA512.", + "totp_2fa_success": "Powodzenie! Cake 2FA włączony dla tego portfela. Pamiętaj, aby zapisać swoje mnemoniczne ziarno na wypadek utraty dostępu do portfela.", + "totp_auth_url": "Adres URL TOTP AUTH", + "totp_code": "Kod TOTP", + "totp_secret_code": "Tajny kod TOTP", + "totp_verification_success": "Weryfikacja powiodła się!", + "trade_details_copied": "${title} skopiowane do schowka", + "trade_details_created_at": "Utworzono ", + "trade_details_fetching": "Pobieranie", + "trade_details_id": "ID", + "trade_details_pair": "Para", + "trade_details_provider": "Dostawca", + "trade_details_state": "Status", + "trade_details_title": "Szczegóły transakcji", + "trade_for_not_created": "Wymiana za ${title} nie została utworzona.", + "trade_history_title": "Historia wymian", + "trade_id": "ID transakcji:", + "trade_id_not_found": "Transakcja ${tradeId} ${title} nie znaleziona.", + "trade_is_powered_by": "Ta wymiana jest obsługiwana przez ${provider}", + "trade_not_created": "Wymiana nie została utworzona", + "trade_not_found": "Nie znaleziono transakcji.", + "trade_state_btc_sent": "Wysłanie", + "trade_state_complete": "Ukończona", + "trade_state_confirming": "Potwierdzanie", + "trade_state_created": "Stworzona", + "trade_state_finished": "Zakończona", + "trade_state_paid": "Opłacona", + "trade_state_paid_unconfirmed": "Transakcja niepotwierdzona", + "trade_state_pending": "Oczekująca", + "trade_state_timeout": "Koniec czasu", + "trade_state_to_be_created": "Została stworzona", + "trade_state_traded": "Wymienione", + "trade_state_trading": "Wymiana", + "trade_state_underpaid": "Niedopłacone", + "trade_state_unpaid": "Nie opłacona", + "trades": "Transakcje", + "transaction_details_amount": "Ilość", + "transaction_details_copied": "${title} skopiowane do schowka", + "transaction_details_date": "Data", + "transaction_details_fee": "Opłata", + "transaction_details_height": "Wysokość Bloku", + "transaction_details_recipient_address": "Adres odbiorcy", "transaction_details_source_address": "Adres źródłowy", - "pause_wallet_creation": "Możliwość utworzenia Portfela Haven jest obecnie wstrzymana.", - "contractName": "Nazwa umowy", - "contractSymbol": "Symbol kontraktu", - "description": "Opis", - "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.", - "no_relays": "Żadnych przekaźników", - "choose_relay": "Wybierz przekaźnik, którego chcesz użyć", - "no_relays_message": "Znaleźliśmy rekord Nostr NIP-05 dla tego użytkownika, ale nie zawiera on żadnych przekaźników. Poinstruuj odbiorcę, aby dodał przekaźniki do swojego rekordu Nostr.", - "no_relay_on_domain": "Brak przekaźnika dla domeny użytkownika lub przekaźnik jest niedostępny. Wybierz przekaźnik, którego chcesz użyć." -} + "transaction_details_title": "Szczegóły transakcji", + "transaction_details_transaction_id": "ID Trancakcji", + "transaction_key": "Klucz transakcji", + "transaction_priority_fast": "Szybka", + "transaction_priority_fastest": "Najszybsza", + "transaction_priority_medium": "Średnia", + "transaction_priority_regular": "Regularna", + "transaction_priority_slow": "Wolna(Zalecane)", + "transaction_sent": "Transakcja wysłana!", + "transaction_sent_notice": "Jeśli ekran nie zmieni się po 1 minucie, sprawdź eksplorator bloków i swój e-mail.", + "transactions": "Transakcje", + "transactions_by_date": "Transakcje według daty", + "trusted": "Zaufany", + "unavailable_balance": "Niedostępne saldo", + "unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.", + "unconfirmed": "Niepotwierdzone saldo", + "understand": "Rozumiem", + "unmatched_currencies": "Waluta Twojego obecnego portfela nie zgadza się z waluctą zeskanowanego kodu QR", + "unspent_change": "Zmiana", + "unspent_coins_details_title": "Szczegóły niewydanych monet", + "unspent_coins_title": "Niewydane monety", + "unsupported_asset": "Nie obsługujemy tego działania w przypadku tego zasobu. Utwórz lub przełącz się na portfel obsługiwanego typu aktywów.", + "upto": "do ${value}", + "use": "Użyj ", + "use_card_info_three": "Użyj cyfrowej karty online lub za pomocą zbliżeniowych metod płatności.", + "use_card_info_two": "Środki są przeliczane na USD, gdy są przechowywane na koncie przedpłaconym, a nie w walutach cyfrowych.", + "use_ssl": "Użyj SSL", + "use_suggested": "Użyj sugerowane", + "variable_pair_not_supported": "Ta para zmiennych nie jest obsługiwana na wybranych giełdach", + "verification": "Weryfikacja", + "verify_with_2fa": "Sprawdź za pomocą Cake 2FA", + "version": "Wersja ${currentVersion}", + "view_all": "Wyświetl wszystko", + "view_in_block_explorer": "Zobacz w eksploratorze bloków", + "view_key_private": "Prywatny Klucz Wglądu", + "view_key_public": "Publiczny Klucz Wglądu", + "view_transaction_on": "Zobacz transakcje na ", + "wallet_keys": "Klucze portfela", + "wallet_list_create_new_wallet": "Utwórz nowy portfel", + "wallet_list_edit_wallet": "Edytuj portfel", + "wallet_list_failed_to_load": "Nie udało się załadować ${wallet_name} portfel. ${error}", + "wallet_list_failed_to_remove": "Nie udało się usunąć ${wallet_name} portfel. ${error}", + "wallet_list_load_wallet": "Załaduj portfel", + "wallet_list_loading_wallet": "Ładuję ${wallet_name} portfel", + "wallet_list_removing_wallet": "Usuwanie ${wallet_name} portfel", + "wallet_list_restore_wallet": "Przywróć portfel", + "wallet_list_title": "Portfel Monero", + "wallet_list_wallet_name": "Nazwa portfela", + "wallet_menu": "Menu portfela", + "wallet_name": "Nazwa portfela", + "wallet_name_exists": "Portfel o tej nazwie już istnieje", + "wallet_restoration_store_incorrect_seed_length": "Nieprawidłowa długość frazy seed", + "wallet_seed": "Seed portfela", + "wallet_seed_legacy": "Dziedziczne ziarno portfela", + "wallet_store_monero_wallet": "Portfel Monero", + "walletConnect": "PortfelPołącz", + "wallets": "Portfele", + "warning": "Ostrzeżenie", + "welcome": "Witamy w", + "welcome_to_cakepay": "Witamy w Cake Pay!", + "widgets_address": "Adres", + "widgets_or": "lub", + "widgets_restore_from_blockheight": "Przywróć z wysokości bloku", + "widgets_restore_from_date": "Przywróć od daty", + "widgets_seed": "Seed", + "wouoldLikeToConnect": "chciałbym się połączyć", + "write_down_backup_password": "Zapisz swoje hasło kopii zapasowej, które jest używane do importowania plików kopii zapasowych.", + "xlm_extra_info": "Nie zapomnij podać dodatkowego identyfikatora (memo) podczas wysyłania transakcji XLM do wymiany", + "xmr_available_balance": "Dostępne środki", + "xmr_full_balance": "Pełne saldo", + "xmr_hidden": "Ukryty", + "xmr_to_error": "Błąd XMR.TO", + "xmr_to_error_description": "Nieprawidłowa kwota. Maksymalny limit to 8 cyfr po przecinku", + "xrp_extra_info": "Nie zapomnij podać tagu docelowego podczas wysyłania transakcji XRP do wymiany", + "yat": "Yat", + "yat_address": "Adres Yat", + "yat_alert_content": "Użytkownicy Cake Wallet mogą teraz wysyłać i odbierać wszystkie swoje ulubione waluty za pomocą jedynej w swoim rodzaju nazwy użytkownika opartej na emoji.", + "yat_alert_title": "Łatwiejsze wysyłanie i odbieranie kryptowalut dzięki Yat", + "yat_error": "Błąd Yat", + "yat_error_content": "Brak adresów powiązanych z tym Yat. Wypróbuj inny Yat", + "yat_popup_content": "Możesz teraz wysyłać i odbierać krypto w Cake Wallet za pomocą swojego Yat – krótkiej nazwy użytkownika opartej na emotikonach. Zarządzaj Yats w dowolnym momencie na ekranie ustawień", + "yat_popup_title": "Twój adres portfela może być zemotkowany.", + "yesterday": "Wczoraj", + "you_now_have_debit_card": "Masz teraz kartę debetową", + "you_pay": "Płacisz", + "you_will_get": "Konwertuj na", + "you_will_send": "Konwertuj z", + "yy": "RR", + "zzzz": "Zzzz" +} \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 7cfd261eb..1f80c62d9 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -1,778 +1,779 @@ { - "welcome": "Bem-vindo ao", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Carteira incrível para Monero, Bitcoin, Ethereum, Litecoin, e Haven", - "please_make_selection": "Escolha se quer criar uma carteira nova ou restaurar uma antiga.", - "create_new": "Criar nova carteira", - "restore_wallet": "Restaurar carteira", - "monero_com": "Monero.com by Cake Wallet", - "monero_com_wallet_text": "Awesome wallet for Monero", - "haven_app": "Haven by Cake Wallet", - "haven_app_wallet_text": "Awesome wallet for Haven", - "accounts": "Contas", - "edit": "Editar", + "about_cake_pay": "O Cake Pay permite que você compre facilmente cartões-presente com ativos virtuais, que podem ser gastos instantaneamente em mais de 150.000 comerciantes nos Estados Unidos.", "account": "Conta", + "accounts": "Contas", + "accounts_subaddresses": "Contas e sub-endereços", + "activate": "Ativar", + "active": "Ativo", + "active_cards": "Cartões ativos", + "activeConnectionsPrompt": "Conexões ativas aparecerão aqui", "add": "Adicionar", + "add_contact": "Adicionar contato", + "add_custom_node": "Adicionar novo nó personalizado", + "add_custom_redemption": "Adicionar resgate personalizado", + "add_fund_to_card": "Adicionar fundos pré-pagos aos cartões (até ${value})", + "add_new_node": "Adicionar novo nó", + "add_new_word": "Adicionar nova palavra", + "add_receiver": "Adicione outro receptor (opcional)", + "add_secret_code": "Ou adicione este código secreto a um aplicativo autenticador", + "add_tip": "Adicionar Dica", + "add_token_disclaimer_check": "Confirmei o endereço e as informações do contrato de token usando uma fonte confiável. Adicionar informações maliciosas ou incorretas pode resultar em perda de fundos.", + "add_token_warning": "Não edite ou adicione tokens de acordo com as instruções dos golpistas.\nSempre confirme os endereços de token com fontes confiáveis!", + "add_value": "Adicionar valor", + "address": "Endereço", "address_book": "Livro de endereços", - "contact": "Contato", - "please_select": "Escolha abaixo:", - "cancel": "Cancelar", - "ok": "Ok", - "contact_name": "Nome do contato", - "reset": "Limpar", - "save": "Salvar", + "address_book_menu": "Livro de endereços", + "address_detected": "Endereço detectado", + "address_from_domain": "Este endereço é de ${domain} em Unstoppable Domains", + "address_from_yat": "Este endereço é de ${emoji} em Yat", + "address_label": "Address label", "address_remove_contact": "Remover contato", "address_remove_content": "Tem certeza de que deseja remover o contato selecionado?", - "authenticated": "Autenticado", - "authentication": "Autenticação", - "failed_authentication": "Falha na autenticação. ${state_error}", - "wallet_menu": "Menu", - "Blocks_remaining": "${status} blocos restantes", - "please_try_to_connect_to_another_node": "Por favor, tente conectar-se a outro nó", - "xmr_hidden": "Esconder saldo", - "xmr_available_balance": "Saldo disponível", - "xmr_full_balance": "Saldo total", - "send": "Enviar", - "receive": "Receber", - "transactions": "Transações", - "incoming": "Recebidas", - "outgoing": "Enviadas", - "transactions_by_date": "Transações por data", - "trades": "Trocas", - "filter_by": "Filtrar por", - "today": "Hoje", - "yesterday": "Ontem", - "received": "Recebida", - "sent": "Enviada", - "pending": " (pendente)", - "rescan": "Reescanear", - "reconnect": "Reconectar", - "wallets": "Carteiras", - "show_seed": "Mostrar semente", - "show_keys": "Mostrar semente/chaves", - "address_book_menu": "Livro de endereços", - "reconnection": "Reconectar", - "reconnect_alert_text": "Você tem certeza de que deseja reconectar?", - "exchange": "Trocar", - "clear": "Limpar", - "refund_address": "Endereço de reembolso", - "change_exchange_provider": "Alterar o provedor de troca", - "you_will_send": "Converter de", - "you_will_get": "Converter para", - "amount_is_guaranteed": "O valor recebido é garantido", - "amount_is_estimate": "O valor a ser recebido informado acima é uma estimativa", - "powered_by": "Troca realizada por ${title}", - "error": "Erro", - "estimated": "Estimado", - "min_value": "Mín: ${value} ${currency}", - "max_value": "Máx: ${value} ${currency}", - "change_currency": "Alterar moeda", - "overwrite_amount": "Overwrite amount", - "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", - "copy_id": "Copiar ID", - "exchange_result_write_down_trade_id": "Copie ou anote o ID da troca para continuar.", - "trade_id": "ID da troca:", - "copied_to_clipboard": "Copiado para a área de transferência", - "saved_the_trade_id": "ID da troca salvo", - "fetching": "Buscando", - "id": "ID: ", - "amount": "Quantia: ", - "payment_id": "ID de pagamento: ", - "status": "Status: ", - "offer_expires_in": "A oferta expira em: ", - "trade_is_powered_by": "Troca realizada por ${provider}", - "copy_address": "Copiar endereço", - "exchange_result_confirm": "Ao confirmar, você enviará ${fetchingLabel} ${from} da sua carteira ${walletName} para o endereço mostrado abaixo. Ou você pode enviar de sua carteira externa para o endereço abaixo/código QR acima.\n\nPressione Confirmar para continuar ou volte para alterar os valores.", - "exchange_result_description": "Você deve enviar no mínimo ${fetchingLabel} ${from} para o endereço mostrado na próxima página. Se você enviar um valor inferior a ${fetchingLabel} ${from}, ele pode não ser convertido e pode não ser reembolsado.", - "exchange_result_write_down_ID": "*Copie ou anote seu ID mostrado acima.", - "confirm": "Confirmar", - "confirm_sending": "Confirmar o envio", - "commit_transaction_amount_fee": "Confirmar transação\nQuantia: ${amount}\nTaxa: ${fee}", - "sending": "Enviando", - "transaction_sent": "Transação enviada!", - "expired": "Expirada", - "time": "${minutes}m ${seconds}s", - "send_xmr": "Enviar XMR", - "exchange_new_template": "Novo modelo", - "faq": "FAQ", - "enter_your_pin": "Insira seu PIN", - "loading_your_wallet": "Abrindo sua carteira", - "new_wallet": "Nova carteira", - "wallet_name": "Nome da carteira", - "continue_text": "Continuar", - "choose_wallet_currency": "Escolha a moeda da carteira:", - "node_new": "Novo nó", - "node_address": "Endereço do nó", - "node_port": "Porta do nó", - "login": "Login", - "password": "Senha", - "nodes": "Nós", - "node_reset_settings_title": "Redefinir configurações", - "nodes_list_reset_to_default_message": "Você realmente deseja redefinir as configurações para o padrão?", - "change_current_node": "Você realmente deseja alterar o nó atual para ${node}?", - "change": "Mudar", - "remove_node": "Remover nó", - "remove_node_message": "Você realmente deseja remover o nó selecionado?", - "remove": "Remover", - "delete": "Excluir", - "add_new_node": "Adicionar novo nó", - "change_current_node_title": "Mudar o nó atual", - "node_test": "Teste", - "node_connection_successful": "A conexão foi bem sucedida", - "node_connection_failed": "A conexão falhou", - "new_node_testing": "Teste de novo nó", - "use": "Use PIN de ", - "digit_pin": "dígitos", - "share_address": "Compartilhar endereço", - "receive_amount": "Quantia", - "subaddresses": "Sub-endereços", "addresses": "Endereços", - "scan_qr_code_to_get_address": "Digitalize o código QR para obter o endereço", - "qr_fullscreen": "Toque para abrir o código QR em tela cheia", - "rename": "Renomear", - "choose_account": "Escolha uma conta", - "create_new_account": "Criar nova conta", - "accounts_subaddresses": "Contas e sub-endereços", - "restore_restore_wallet": "Restaurar carteira", - "restore_title_from_seed_keys": "Restaurar a partir de sementes/chaves", - "restore_description_from_seed_keys": "Restaure a sua carteira a partir de sementes/chaves que você salvou em um local seguro", - "restore_next": "Próximo", - "restore_title_from_backup": "Restaurar a partir de um arquivo de backup", - "restore_description_from_backup": "Você pode restaurar todo o aplicativo Cake Wallet de seu arquivo de backup", - "restore_seed_keys_restore": "Restauração com sementes/chaves", - "restore_title_from_seed": "Restaurar a partir de semente", - "restore_description_from_seed": "Restaure sua carteira a partir de semente com 25 palavras ou 13 palavras", - "restore_title_from_keys": "Restaurar a partir de chaves", - "restore_description_from_keys": "Restaure sua carteira a partir de suas chaves privadas", - "restore_wallet_name": "Nome da carteira", - "restore_address": "Endereço", - "restore_view_key_private": "Chave de visualização (privada)", - "restore_spend_key_private": "Chave de gastos (privada)", - "restore_recover": "Restaurar", - "restore_wallet_restore_description": "Restauração da carteira", - "restore_new_seed": "Nova semente", - "restore_active_seed": "Semente ativa", - "restore_bitcoin_description_from_seed": "Restaure sua carteira a partir de um código de combinação de 24 palavras", - "restore_bitcoin_description_from_keys": "Restaure sua carteira a partir da string WIF gerada de suas chaves privadas", - "restore_bitcoin_title_from_keys": "Restaurar de WIF", - "restore_from_date_or_blockheight": "Insira uma data alguns dias antes de criar esta carteira. Ou se você souber a altura do bloco, insira-o", - "seed_reminder": "Anote-os para o caso de perder ou limpar seu telefone", - "seed_title": "Semente", - "seed_share": "Compartilhar semente", - "copy": "Copiar", - "seed_language": "Linguagem de semente", - "seed_choose": "Escolha o idioma da semente", - "seed_language_next": "Próximo", - "seed_language_english": "Inglesa", - "seed_language_chinese": "Chinesa", - "seed_language_dutch": "Holandesa", - "seed_language_german": "Alemã", - "seed_language_japanese": "Japonês", - "seed_language_portuguese": "Português", - "seed_language_russian": "Russa", - "seed_language_spanish": "Espanhola", - "seed_language_french": "Francesa/Francês", - "seed_language_italian": "Italiana/Italiano", - "send_title": "Enviar", - "send_your_wallet": "Sua carteira", - "send_address": "Endereço ${cryptoCurrency}", - "send_payment_id": "ID de pagamento (opcional)", + "advanced_settings": "Configurações avançadas", + "aggressive": "excessivamente zeloso", + "agree": "Concordo", + "agree_and_continue": "Concordar e continuar", + "agree_to": "Ao criar conta você concorda com ", "all": "TUDO", - "send_error_minimum_value": "O valor mínimo da quantia é 0,01", - "send_error_currency": "A moeda só pode conter números", - "send_estimated_fee": "Taxa estimada:", - "send_priority": "Atualmente, a taxa está definida para a prioridade: ${transactionPriority}.\nA prioridade da transação pode ser ajustada nas configurações", - "send_creating_transaction": "Criando transação", - "send_templates": "Modelos", - "send_new": "Novo", - "send_amount": "Montante:", - "send_fee": "Taxa:", - "send_name": "Nome", - "got_it": "Entendi", - "send_sending": "Enviando...", - "send_success": "Seu ${crypto} foi enviado com sucesso", - "settings_title": "Configurações", - "settings_nodes": "Nós", - "settings_current_node": "Nó atual", - "settings_wallets": "Carteiras", - "settings_display_balance": "Exibir saldo", - "settings_currency": "Moeda", - "settings_fee_priority": "Prioridade da taxa", - "settings_save_recipient_address": "Salvar endereço do destinatário", - "settings_personal": "Pessoal", - "settings_change_pin": "Mudar PIN", - "settings_change_language": "Mudar idioma", - "settings_allow_biometrical_authentication": "Permitir autenticação biométrica", - "settings_dark_mode": "Modo noturno", - "settings_transactions": "Transações", - "settings_trades": "Trocas", - "settings_display_on_dashboard_list": "Exibir no histórico", - "settings_all": "Tudo", - "settings_only_trades": "Somente trocas", - "settings_only_transactions": "Somente transações", - "settings_none": "Nada", - "settings_support": "Suporte", - "settings_terms_and_conditions": "Termos e Condições", - "pin_is_incorrect": "PIN incorreto", - "setup_pin": "Configurar PIN", - "enter_your_pin_again": "Insira seu PIN novamente", - "setup_successful": "Seu PIN foi configurado com sucesso!", - "wallet_keys": "Semente/chaves da carteira", - "wallet_seed": "Semente de carteira", - "private_key": "Chave privada", - "public_key": "Chave pública", - "view_key_private": "Chave de visualização (privada)", - "view_key_public": "Chave de visualização (pública)", - "spend_key_private": "Chave de gastos (privada)", - "spend_key_public": "Chave de gastos (pública)", - "copied_key_to_clipboard": "${key} copiada para a área de transferência", - "new_subaddress_title": "Novo endereço", - "new_subaddress_label_name": "Nome", - "new_subaddress_create": "Criar", - "address_label": "Address label", - "subaddress_title": "Sub-endereços", - "trade_details_title": "Detalhes da troca", - "trade_details_id": "ID", - "trade_details_state": "Status", - "trade_details_fetching": "Buscando", - "trade_details_provider": "Provedor", - "trade_details_created_at": "Criada em", - "trade_details_pair": "Par", - "trade_details_copied": "${title} copiados para a área de transferência", - "trade_history_title": "Histórico de trocas", - "transaction_details_title": "Detalhes da transação", - "transaction_details_transaction_id": "ID da transação", - "transaction_details_date": "Data", - "transaction_details_height": "Altura", - "transaction_details_amount": "Quantia", - "transaction_details_fee": "Taxa", - "transaction_details_copied": "${title} copiados para a área de transferência", - "transaction_details_recipient_address": "Endereços de destinatários", - "wallet_list_title": "Carteira Monero", - "wallet_list_create_new_wallet": "Criar nova carteira", - "wallet_list_edit_wallet": "Editar carteira", - "wallet_list_wallet_name": "Nome da carteira", - "wallet_list_restore_wallet": "Restaurar carteira", - "wallet_list_load_wallet": "Abrir carteira", - "wallet_list_loading_wallet": "Abrindo a carteira ${wallet_name}", - "wallet_list_failed_to_load": "Falha ao abrir a carteira ${wallet_name}. ${error}", - "wallet_list_removing_wallet": "Removendo a carteira ${wallet_name}", - "wallet_list_failed_to_remove": "Falha ao remover a carteira ${wallet_name}. ${error}", - "widgets_address": "Endereço", - "widgets_restore_from_blockheight": "Restaurar a partir de altura do bloco", - "widgets_restore_from_date": "Restaurar a partir de data", - "widgets_or": "ou", - "widgets_seed": "Semente", - "router_no_route": "Nenhuma rota definida para ${name}", - "error_text_account_name": "O nome da conta só pode conter letras, números\ne deve ter entre 1 e 15 caracteres", - "error_text_contact_name": "O nome do contato não pode conter os símbolos ` , ' \" \ne deve ter entre 1 e 32 caracteres", - "error_text_address": "O endereço da carteira deve corresponder à\ncriptomoeda selecionada", - "error_text_node_address": "Digite um endereço iPv4", - "error_text_node_port": "A porta do nó deve conter apenas números entre 0 e 65535", - "error_text_node_proxy_address": "Insira :, por exemplo 127.0.0.1:9050", - "error_text_payment_id": "O ID de pagamento pode conter apenas de 16 a 64 caracteres em hexadecimal", - "error_text_xmr": "A quantia em XMR não pode exceder o saldo disponível.\nTO número de dígitos decimais deve ser menor ou igual a 12", - "error_text_fiat": "O valor do valor não pode exceder o saldo disponível.\nO número de dígitos decimais deve ser menor ou igual a 2", - "error_text_subaddress_name": "O nome do sub-endereço não pode conter os símbolos ` , ' \" \ne deve ter entre 1 e 20 caracteres", - "error_text_amount": "A quantia deve conter apenas números", - "error_text_wallet_name": "O nome da carteira só pode conter letras, números, _ - símbolos\ne deve ter entre 1 e 33 caracteres", - "error_text_keys": "As chaves da carteira podem conter apenas 64 caracteres em hexadecimal", - "error_text_crypto_currency": "O número de dígitos decimais\ndeve ser menor ou igual a 12", - "error_text_minimal_limit": "A troca por ${provider} não é criada. O valor é menor que o mínimo: ${min} ${currency}", - "error_text_maximum_limit": "A troca por ${provider} não é criada. O valor é superior ao máximo: ${max} ${currency}", - "error_text_limits_loading_failed": "A troca por ${provider} não é criada. Falha no carregamento dos limites", - "error_text_template": "O nome e o endereço do modelo não podem conter os símbolos ` , ' \" \ne deve ter entre 1 e 106 caracteres", + "all_trades": "Todas as negociações", + "all_transactions": "Todas as transacções", + "alphabetical": "alfabética", + "already_have_account": "Já tem uma conta?", + "always": "sempre", + "amount": "Quantia: ", + "amount_is_estimate": "O valor a ser recebido informado acima é uma estimativa", + "amount_is_guaranteed": "O valor recebido é garantido", + "and": "e", + "anonpay_description": "Gere ${type}. O destinatário pode ${method} com qualquer criptomoeda suportada e você receberá fundos nesta carteira.", + "apk_update": "Atualização de APK", + "approve": "Aprovar", + "arrive_in_this_address": "${currency} ${tag}chegará neste endereço", + "ascending": "Ascendente", + "ask_each_time": "Pergunte cada vez", "auth_store_ban_timeout": "ban_timeout", "auth_store_banned_for": "Banido por", "auth_store_banned_minutes": " minutos", "auth_store_incorrect_password": "PIN incorreto", - "wallet_store_monero_wallet": "Carteira Monero", - "wallet_restoration_store_incorrect_seed_length": "Comprimento de semente incorreto", - "full_balance": "Saldo total", - "available_balance": "Saldo disponível", - "hidden_balance": "Saldo escondido", - "sync_status_syncronizing": "SINCRONIZANDO", - "sync_status_syncronized": "SINCRONIZADO", - "sync_status_not_connected": "DESCONECTADO", - "sync_status_starting_sync": "INICIANDO SINCRONIZAÇÃO", - "sync_status_failed_connect": "DESCONECTADO", - "sync_status_connecting": "CONECTANDO", - "sync_status_connected": "CONECTADO", - "sync_status_attempting_sync": "TENTANDO SINCRONIZAR", - "transaction_priority_slow": "Lenta", - "transaction_priority_regular": "Regular", - "transaction_priority_medium": "Média", - "transaction_priority_fast": "Rápida", - "transaction_priority_fastest": "Muito rápida", - "trade_for_not_created": "A troca por ${title} não foi criada.", - "trade_not_created": "Troca não criada", - "trade_id_not_found": "A troca ${tradeId} de ${title} não foi encontrada.", - "trade_not_found": "Troca não encontrada.", - "trade_state_pending": "Pendente", - "trade_state_confirming": "Confirmando", - "trade_state_trading": "Em andamento", - "trade_state_traded": "Troca realizada", - "trade_state_complete": "Finalizada", - "trade_state_to_be_created": "A ser criada", - "trade_state_unpaid": "Não paga", - "trade_state_underpaid": "Parcialmente paga", - "trade_state_paid_unconfirmed": "Pagamento não-confirmado", - "trade_state_paid": "Paga", - "trade_state_btc_sent": "BTC enviado", - "trade_state_timeout": "Tempo esgotado", - "trade_state_created": "Criada", - "trade_state_finished": "Finalizada", - "change_language": "Mudar idioma", - "change_language_to": "Alterar idioma para ${language}?", - "paste": "Colar", - "restore_from_seed_placeholder": "Digite ou cole sua frase de código aqui", - "add_new_word": "Adicionar nova palavra", - "incorrect_seed": "O texto digitado não é válido.", - "biometric_auth_reason": "Digitalize sua impressão digital para autenticar", - "version": "Versão ${currentVersion}", - "extracted_address_content": "Você enviará fundos para\n${recipient_name}", - "card_address": "Endereço:", - "buy": "Comprar", - "sell": "Vender", - "placeholder_transactions": "Suas transações serão exibidas aqui", - "placeholder_contacts": "Seus contatos serão exibidos aqui", - "template": "Modelo", - "confirm_delete_template": "Esta ação excluirá este modelo. Você deseja continuar?", - "confirm_delete_wallet": "Esta ação excluirá esta carteira. Você deseja continuar?", - "change_wallet_alert_title": "Alterar carteira atual", - "change_wallet_alert_content": "Quer mudar a carteira atual para ${wallet_name}?", - "creating_new_wallet": "Criando nova carteira", - "creating_new_wallet_error": "Erro: ${description}", - "seed_alert_title": "Atenção", - "seed_alert_content": "A semente é a única forma de recuperar sua carteira. Você escreveu isso?", - "seed_alert_back": "Volte", - "seed_alert_yes": "Sim, eu tenho", - "exchange_sync_alert_content": "Por favor, espere até que sua carteira seja sincronizada", - "pre_seed_title": "IMPORTANTE", - "pre_seed_description": "Na próxima página, você verá uma série de ${words} palavras. Esta é a sua semente única e privada e é a ÚNICA maneira de recuperar sua carteira em caso de perda ou mau funcionamento. É SUA responsabilidade anotá-lo e armazená-lo em um local seguro fora do aplicativo Cake Wallet.", - "pre_seed_button_text": "Compreendo. Me mostre minha semente", - "xmr_to_error": "Erro XMR.TO", - "xmr_to_error_description": "Montante inválido. Limite máximo de 8 dígitos após o ponto decimal", - "provider_error": "${provider} erro", - "use_ssl": "Use SSL", - "trusted": "confiável", - "color_theme": "Tema de cor", - "light_theme": "Luz", - "bright_theme": "Brilhante", - "dark_theme": "Sombria", - "enter_your_note": "Insira sua nota ...", - "note_optional": "Nota (opcional)", - "note_tap_to_change": "Nota (toque para alterar)", - "view_in_block_explorer": "View in Block Explorer", - "view_transaction_on": "View Transaction on ", - "transaction_key": "Chave de transação", - "confirmations": "Confirmações", - "recipient_address": "Endereço do destinatário", - "extra_id": "ID extra:", - "destination_tag": "Tag de destino:", - "memo": "Memorando:", - "backup": "Cópia de segurança", - "change_password": "Mudar senha", - "backup_password": "Senha de backup", - "write_down_backup_password": "Anote sua senha de backup, que será usada para importar seus arquivos de backup.", - "export_backup": "Backup de exportação", - "save_backup_password": "Certifique-se de que salvou sua senha de backup. Você não poderá importar seus arquivos de backup sem ele.", - "backup_file": "Arquivo de backup", - "edit_backup_password": "Editar senha de backup", - "save_backup_password_alert": "Salvar senha de backup", - "change_backup_password_alert": "Seus arquivos de backup anteriores não estarão disponíveis para importação com a nova senha de backup. A nova senha de backup será usada apenas para novos arquivos de backup. Tem certeza que deseja alterar a senha de backup?", - "enter_backup_password": "Digite a senha de backup aqui", - "select_backup_file": "Selecione o arquivo de backup", - "import": "Importar", - "please_select_backup_file": "Selecione o arquivo de backup e insira a senha de backup.", - "fixed_rate": "Taxa fixa", - "fixed_rate_alert": "Você poderá inserir a quantia recebida quando o modo de taxa fixa estiver marcado. Quer mudar para o modo de taxa fixa?", - "xlm_extra_info": "Não se esqueça de especificar o Memo ID ao enviar a transação XLM para a troca", - "xrp_extra_info": "Não se esqueça de especificar a etiqueta de destino ao enviar a transação XRP para a troca", - "exchange_incorrect_current_wallet_for_xmr": "Se você deseja trocar o XMR de seu saldo da Carteira Monero Cake, troque primeiro para sua carteira Monero.", - "confirmed": "Saldo Confirmado", - "unconfirmed": "Saldo não confirmado", - "displayable": "Exibível", - "submit_request": "enviar um pedido", - "buy_alert_content": "Atualmente, oferecemos suporte apenas à compra de Bitcoin, Ethereum, Litecoin e Monero. Crie ou troque para sua carteira Bitcoin, Ethereum, Litecoin ou Monero.", - "sell_alert_content": "Atualmente, oferecemos suporte apenas à venda de Bitcoin, Ethereum e Litecoin. Crie ou troque para sua carteira Bitcoin, Ethereum ou Litecoin.", - "outdated_electrum_wallet_description": "As novas carteiras Bitcoin criadas no Cake agora têm uma semente de 24 palavras. É obrigatório que você crie uma nova carteira Bitcoin e transfira todos os seus fundos para a nova carteira de 24 palavras, e pare de usar carteiras com semente de 12 palavras. Faça isso imediatamente para garantir seus fundos.", - "understand": "Entendo", - "apk_update": "Atualização de APK", - "buy_bitcoin": "Compre Bitcoin", - "buy_with": "Compre com", - "moonpay_alert_text": "O valor do montante deve ser maior ou igual a ${minAmount} ${fiatCurrency}", - "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", - "do_not_show_me": "não me mostre isso novamente", - "unspent_coins_title": "Moedas não gastas", - "unspent_coins_details_title": "Detalhes de moedas não gastas", - "freeze": "Congelar", - "frozen": "Congeladas", - "coin_control": "Controle de moedas (opcional)", - "address_detected": "Endereço detectado", - "address_from_domain": "Este endereço é de ${domain} em Unstoppable Domains", - "add_receiver": "Adicione outro receptor (opcional)", - "manage_yats": "Gerenciar Yats", - "yat_alert_title": "Envie e receba criptografia mais facilmente com Yat", - "yat_alert_content": "Os usuários da Cake Wallet agora podem enviar e receber todas as suas moedas favoritas com um nome de usuário baseado em emoji único.", - "get_your_yat": "Pegue seu Yat", - "connect_an_existing_yat": "Conecte um Yat existente", - "yat_address": "Endereço Yat", - "yat": "Yat", - "connect_yats": "Connect Yats", - "address_from_yat": "Este endereço é de ${emoji} em Yat", - "yat_error": "Yat erro", - "yat_error_content": "Nenhum endereço vinculado a este Yat. Tente outro Yat", - "choose_address": "\n\nEscolha o endereço:", - "yat_popup_title": "O endereço da sua carteira pode ser emojificado.", - "yat_popup_content": "Agora você pode enviar e receber criptografia na Cake Wallet com seu Yat - um nome de usuário curto baseado em emoji. Gerenciar Yats a qualquer momento na tela de configurações", - "second_intro_title": "Um endereço de emoji para governar todos eles", - "second_intro_content": "Seu Yat é um endereço de emoji único e exclusivo que substitui todos os seus endereços hexadecimais longos para todas as suas moedas.", - "third_intro_title": "Yat joga bem com os outros", - "third_intro_content": "Yats também mora fora da Cake Wallet. Qualquer endereço de carteira na Terra pode ser substituído por um Yat!", - "learn_more": "Saber mais", - "search": "Procurar", - "search_language": "Idioma de pesquisa", - "search_currency": "Pesquisar moeda", - "new_template": "Novo modelo", - "electrum_address_disclaimer": "Geramos novos endereços cada vez que você usa um, mas os endereços anteriores continuam funcionando", - "wallet_name_exists": "A carteira com esse nome já existe", - "market_place": "Mercado", - "cake_pay_title": "Cartões de presente de CakePay", - "cake_pay_subtitle": "Compre vales-presente com desconto (somente nos EUA)", - "cake_pay_web_cards_title": "Cartões Cake Pay Web", - "cake_pay_web_cards_subtitle": "Compre cartões pré-pagos e cartões-presente em todo o mundo", - "about_cake_pay": "O Cake Pay permite que você compre facilmente cartões-presente com ativos virtuais, que podem ser gastos instantaneamente em mais de 150.000 comerciantes nos Estados Unidos.", - "cake_pay_account_note": "Inscreva-se com apenas um endereço de e-mail para ver e comprar cartões. Alguns estão até com desconto!", - "already_have_account": "Já tem uma conta?", - "create_account": "Criar conta", - "privacy_policy": "Política de privacidade", - "welcome_to_cakepay": "Bem-vindo ao Cake Pay!", - "forgot_password": "Esqueci a senha", - "reset_password": "Redefinir senha", - "gift_cards": "Cartões de presente", - "setup_your_debit_card": "Configure seu cartão de débito", - "no_id_required": "Não é necessário ID. Recarregue e gaste em qualquer lugar", - "how_to_use_card": "Como usar este cartão", - "purchase_gift_card": "Comprar vale-presente", - "verification": "Verificação", - "fill_code": "Por favor, preencha o código de verificação fornecido ao seu e-mail", - "didnt_get_code": "Não recebeu o código?", - "resend_code": "Por favor, reenvie", - "debit_card": "Cartão de débito", - "cakepay_prepaid_card": "Cartão de débito pré-pago CakePay", - "no_id_needed": "Nenhum ID necessário!", - "frequently_asked_questions": "Perguntas frequentes", - "debit_card_terms": "O armazenamento e uso do número do cartão de pagamento (e credenciais correspondentes ao número do cartão de pagamento) nesta carteira digital estão sujeitos aos Termos e Condições do contrato do titular do cartão aplicável com o emissor do cartão de pagamento, em vigor a partir de tempo ao tempo.", - "please_reference_document": "Por favor, consulte os documentos abaixo para mais informações.", - "cardholder_agreement": "Acordo do titular do cartão", - "e_sign_consent": "Consentimento de assinatura eletrônica", - "agree_and_continue": "Concordar e continuar", - "email_address": "Endereço de e-mail", - "agree_to": "Ao criar conta você concorda com ", - "and": "e", - "enter_code": "Digite o código", - "congratulations": "Parabéns!", - "you_now_have_debit_card": "Agora você tem um cartão de débito", - "min_amount": "Mínimo: ${valor}", - "max_amount": "Máx.: ${valor}", - "enter_amount": "Digite o valor", - "billing_address_info": "Se for solicitado um endereço de cobrança, forneça seu endereço de entrega", - "order_physical_card": "Pedir Cartão Físico", - "add_value": "Adicionar valor", - "activate": "Ativar", - "get_a": "Obter um ", - "digital_and_physical_card": "cartão de débito pré-pago digital e físico", - "get_card_note": " que você pode recarregar com moedas digitais. Nenhuma informação adicional é necessária!", - "signup_for_card_accept_terms": "Cadastre-se no cartão e aceite os termos.", - "add_fund_to_card": "Adicionar fundos pré-pagos aos cartões (até ${value})", - "use_card_info_two": "Os fundos são convertidos para USD quando mantidos na conta pré-paga, não em moedas digitais.", - "use_card_info_three": "Use o cartão digital online ou com métodos de pagamento sem contato.", - "opcionalmente_order_card": "Opcionalmente, peça um cartão físico.", - "hide_details": "Ocultar detalhes", - "show_details": "Mostrar detalhes", - "upto": "até ${value}", - "discount": "Economize ${value}%", - "gift_card_amount": "Valor do Cartão Presente", - "bill_amount": "Valor da conta", - "you_pay": "Você paga", - "tip": "Dica:", - "custom": "personalizado", - "by_cake_pay": "por Cake Pay", - "expires": "Expira", - "mm": "MM", - "yy": "aa", - "online": "Online", - "offline": "offline", - "gift_card_number": "Número do cartão-presente", - "pin_number": "Número PIN", - "total_saving": "Economia total", - "last_30_days": "Últimos 30 dias", - "avg_savings": "Poupança média", - "view_all": "Ver todos", - "active_cards": "Cartões ativos", - "delete_account": "Excluir conta", - "cards": "Cartões", - "active": "Ativo", - "redeemed": "Resgatado", - "gift_card_balance_note": "Os cartões-presente com saldo restante aparecerão aqui", - "gift_card_redeemed_note": "Os cartões-presente que você resgatou aparecerão aqui", - "logout": "Logout", - "add_tip": "Adicionar Dica", - "percentageOf": "de ${amount}", - "is_percentage": "é", - "search_category": "Categoria de pesquisa", - "mark_as_redemed": "Marcar como resgatado", - "more_options": "Mais opções", - "waiting_payment_confirmation": "Aguardando confirmação de pagamento", - "transaction_sent_notice": "Se a tela não prosseguir após 1 minuto, verifique um explorador de blocos e seu e-mail.", - "agree": "Concordo", - "in_store": "Na loja", - "generating_gift_card": "Gerando Cartão Presente", - "payment_was_received": "Seu pagamento foi recebido.", - "proceed_after_one_minute": "Se a tela não prosseguir após 1 minuto, verifique seu e-mail.", - "order_id": "ID do pedido", - "gift_card_is_generated": "Cartão presente é gerado", - "open_gift_card": "Abrir vale-presente", - "contact_support": "Contatar Suporte", - "gift_cards_unavailable": "Os cartões-presente estão disponíveis para compra apenas através do Monero, Bitcoin e Litecoin no momento", - "background_sync_mode": "Modo de sincronização em segundo plano", - "sync_all_wallets": "Sincronize todas as carteiras", - "introducing_cake_pay": "Apresentando o Cake Pay!", - "cake_pay_learn_more": "Compre e resgate vales-presente instantaneamente no app!\nDeslize da esquerda para a direita para saber mais.", - "automatic": "Automático", - "fixed_pair_not_supported": "Este par fixo não é compatível com as exchanges selecionadas", - "variable_pair_not_supported": "Este par de variáveis não é compatível com as trocas selecionadas", - "none_of_selected_providers_can_exchange": "Nenhum dos provedores selecionados pode fazer esta troca", - "choose_one": "Escolha um", - "choose_from_available_options": "Escolha entre as opções disponíveis:", - "custom_redeem_amount": "Valor de resgate personalizado", - "add_custom_redemption": "Adicionar resgate personalizado", - "remaining": "restante", - "delete_wallet": "Excluir carteira", - "delete_wallet_confirm_message": "Tem certeza de que deseja excluir a carteira ${wallet_name}?", - "low_fee": "Taxa baixa", - "low_fee_alert": "No momento, você está usando uma prioridade de taxa de rede baixa. Isso pode causar longas esperas, taxas diferentes ou negociações canceladas. Recomendamos definir uma taxa mais alta para uma melhor experiência.", - "ignor": "Ignorar", - "use_suggested": "Uso sugerido", - "do_not_share_warning_text": "Não os compartilhe com mais ninguém, incluindo suporte.\n\nSeus fundos podem e serão roubados!", - "help": "ajuda", - "all_transactions": "Todas as transacções", - "all_trades": "Todas as negociações", - "connection_sync": "Conexão e sincronização", - "security_and_backup": "Segurança e backup", - "create_backup": "Criar backup", - "privacy_settings": "Configurações de privacidade", - "privacy": "Privacidade", - "display_settings": "Configurações de exibição", - "other_settings": "Outras configurações", - "require_pin_after": "Exigir PIN após", - "always": "sempre", - "minutes_to_pin_code": "${minute} minutos", - "disable_exchange": "Desativar troca", - "advanced_settings": "Configurações avançadas", - "settings_can_be_changed_later": "Essas configurações podem ser alteradas posteriormente nas configurações do aplicativo", - "add_custom_node": "Adicionar novo nó personalizado", - "disable_fiat": "Desativar fiat", - "fiat_api": "API da Fiat", - "disabled": "Desabilitado", - "enabled": "Habilitado", - "tor_only": "Tor apenas", - "unmatched_currencies": "A moeda da sua carteira atual não corresponde à do QR digitalizado", - "orbot_running_alert": "Certifique-se de que o Orbot esteja em execução antes de se conectar a este nó.", - "contact_list_contacts": "Contatos", - "contact_list_wallets": "minhas carteiras", - "bitcoin_payments_require_1_confirmation": "Os pagamentos em Bitcoin exigem 1 confirmação, o que pode levar 20 minutos ou mais. Obrigado pela sua paciência! Você receberá um e-mail quando o pagamento for confirmado.", - "send_to_this_address": "Envie ${currency} ${tag}para este endereço", - "arrive_in_this_address": "${currency} ${tag}chegará neste endereço", - "do_not_send": "não envie", - "error_dialog_content": "Ops, houve algum erro.\n\nPor favor, envie o relatório de falha para nossa equipe de suporte para melhorar o aplicativo.", - "scan_qr_code": "Escanear código QR", - "cold_or_recover_wallet": "Adicione uma cold wallet ou recupere uma paper wallet", - "please_wait": "Por favor, aguarde", - "sweeping_wallet": "Carteira varrendo", - "sweeping_wallet_alert": "To nie powinno zająć dużo czasu. NIE WYCHODŹ Z TEGO EKRANU, W PRZECIWNYM WYPADKU MOŻE ZOSTAĆ UTRACONA ŚRODKI", - "decimal_places_error": "Muitas casas decimais", - "edit_node": "Editar nó", - "invoice_details": "Detalhes da fatura", - "donation_link_details": "Detalhes do link de doação", - "anonpay_description": "Gere ${type}. O destinatário pode ${method} com qualquer criptomoeda suportada e você receberá fundos nesta carteira.", - "create_invoice": "Criar recibo", - "create_donation_link": "Criar link de doação", - "optional_email_hint": "E-mail opcional de notificação do beneficiário", - "optional_description": "Descrição opcional", - "optional_name": "Nome do destinatário opcional", - "clearnet_link": "link clear net", - "onion_link": "ligação de cebola", - "settings": "Configurações", - "sell_monero_com_alert_content": "A venda de Monero ainda não é suportada", - "error_text_input_below_minimum_limit": "O valor é menor que o mínimo", - "error_text_input_above_maximum_limit": "O valor é superior ao máximo", - "show_market_place": "Mostrar mercado", - "prevent_screenshots": "Evite capturas de tela e gravação de tela", - "profile": "Perfil", - "close": "Fechar", - "modify_2fa": "Modificar o Cake 2FA", - "disable_cake_2fa": "Desabilitar o Cake 2FA", - "question_to_disable_2fa": "Tem certeza de que deseja desativar o Cake 2FA? Um código 2FA não será mais necessário para acessar a carteira e certas funções.", - "disable": "Desativar", - "setup_2fa": "Configurar o Cake 2FA", - "verify_with_2fa": "Verificar com Cake 2FA", - "totp_code": "Código TOTP", - "please_fill_totp": "Por favor, preencha o código de 8 dígitos presente em seu outro dispositivo", - "totp_2fa_success": "Sucesso! Cake 2FA ativado para esta carteira. Lembre-se de salvar sua semente mnemônica caso perca o acesso à carteira.", - "totp_verification_success": "Verificação bem-sucedida!", - "totp_2fa_failure": "Código incorreto. Tente um código diferente ou gere uma nova chave secreta. Use um aplicativo 2FA compatível com códigos de 8 dígitos e SHA512.", - "enter_totp_code": "Digite o código TOTP.", - "add_secret_code": "Ou adicione este código secreto a um aplicativo autenticador", - "totp_secret_code": "Código Secreto TOTP", - "setup_2fa_text": "Cake 2FA funciona usando TOTP como segundo fator de autenticação.\n\nO TOTP do Cake 2FA requer suporte SHA-512 e 8 dígitos; isso proporciona maior segurança. Mais informações e aplicativos suportados podem ser encontrados no guia.", - "setup_totp_recommended": "Configurar TOTP", - "disable_buy": "Desativar ação de compra", - "disable_sell": "Desativar ação de venda", + "authenticated": "Autenticado", + "authentication": "Autenticação", "auto_generate_subaddresses": "Gerar subendereços automaticamente", - "cake_2fa_preset": "Predefinição de bolo 2FA", - "narrow": "Estreito", - "normal": "Normal", - "aggressive": "excessivamente zeloso", - "require_for_assessing_wallet": "Requer para acessar a carteira", - "require_for_sends_to_non_contacts": "Exigir para envios para não-contatos", - "require_for_sends_to_contacts": "Exigir para envios para contatos", - "require_for_sends_to_internal_wallets": "Exigir envios para carteiras internas", - "require_for_exchanges_to_internal_wallets": "Requer trocas para carteiras internas", - "require_for_adding_contacts": "Requer para adicionar contatos", - "require_for_creating_new_wallets": "Requer para criar novas carteiras", - "require_for_all_security_and_backup_settings": "Exigir todas as configurações de segurança e backup", + "automatic": "Automático", + "available_balance": "Saldo disponível", "available_balance_description": "Seu saldo disponível é o saldo total menos o saldo congelado. O saldo congelado é o saldo que você não pode gastar, mas que ainda não foi confirmado na blockchain. O saldo congelado é geralmente o resultado de transações recentes.", - "syncing_wallet_alert_title": "Sua carteira está sincronizando", - "syncing_wallet_alert_content": "Seu saldo e lista de transações podem não estar completos até que diga “SYNCHRONIZED” no topo. Clique/toque para saber mais.", - "home_screen_settings": "Configurações da tela inicial", - "sort_by": "Ordenar por", - "search_add_token": "Pesquisar / Adicionar token", - "edit_token": "Editar símbolo", - "warning": "Aviso", - "add_token_warning": "Não edite ou adicione tokens de acordo com as instruções dos golpistas.\nSempre confirme os endereços de token com fontes confiáveis!", - "add_token_disclaimer_check": "Confirmei o endereço e as informações do contrato de token usando uma fonte confiável. Adicionar informações maliciosas ou incorretas pode resultar em perda de fundos.", - "token_contract_address": "Endereço do contrato de token", - "token_name": "Nome do token, por exemplo: Tether", - "token_symbol": "Símbolo de token, por exemplo: USDT", - "token_decimal": "Token decimal", - "field_required": "Este campo é obrigatório", - "pin_at_top": "fixe ${token} no topo", - "invalid_input": "Entrada inválida", - "fiat_balance": "Equilíbrio Fiat", - "gross_balance": "Saldo Bruto", - "alphabetical": "alfabética", - "generate_name": "Gerar nome", + "avg_savings": "Poupança média", + "awaitDAppProcessing": "Aguarde até que o dApp termine o processamento.", + "background_sync_mode": "Modo de sincronização em segundo plano", + "backup": "Cópia de segurança", + "backup_file": "Arquivo de backup", + "backup_password": "Senha de backup", "balance_page": "Página de saldo", - "share": "Compartilhar", - "slidable": "Deslizável", - "monero_dark_theme": "Monero Tema Escuro", + "bill_amount": "Valor da conta", + "billing_address_info": "Se for solicitado um endereço de cobrança, forneça seu endereço de entrega", + "biometric_auth_reason": "Digitalize sua impressão digital para autenticar", "bitcoin_dark_theme": "Tema escuro Bitcoin", "bitcoin_light_theme": "Tema claro de bitcoin", - "high_contrast_theme": "Tema de alto contraste", - "matrix_green_dark_theme": "Tema escuro verde matrix", - "monero_light_theme": "Monero Light Theme", - "manage_nodes": "Gerenciar nós", - "etherscan_history": "história Etherscan", - "template_name": "Nome do modelo", + "bitcoin_payments_require_1_confirmation": "Os pagamentos em Bitcoin exigem 1 confirmação, o que pode levar 20 minutos ou mais. Obrigado pela sua paciência! Você receberá um e-mail quando o pagamento for confirmado.", + "Blocks_remaining": "${status} blocos restantes", + "bright_theme": "Brilhante", + "buy": "Comprar", + "buy_alert_content": "Atualmente, oferecemos suporte apenas à compra de Bitcoin, Ethereum, Litecoin e Monero. Crie ou troque para sua carteira Bitcoin, Ethereum, Litecoin ou Monero.", + "buy_bitcoin": "Compre Bitcoin", + "buy_provider_unavailable": "Provedor atualmente indisponível.", + "buy_with": "Compre com", + "by_cake_pay": "por Cake Pay", + "cake_2fa_preset": "Predefinição de bolo 2FA", + "cake_pay_account_note": "Inscreva-se com apenas um endereço de e-mail para ver e comprar cartões. Alguns estão até com desconto!", + "cake_pay_learn_more": "Compre e resgate vales-presente instantaneamente no app!\nDeslize da esquerda para a direita para saber mais.", + "cake_pay_subtitle": "Compre vales-presente com desconto (somente nos EUA)", + "cake_pay_title": "Cartões de presente de CakePay", + "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_wallet": "Cake Wallet", + "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.", + "camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.", + "cancel": "Cancelar", + "card_address": "Endereço:", + "cardholder_agreement": "Acordo do titular do cartão", + "cards": "Cartões", + "chains": "Correntes", + "change": "Mudar", + "change_backup_password_alert": "Seus arquivos de backup anteriores não estarão disponíveis para importação com a nova senha de backup. A nova senha de backup será usada apenas para novos arquivos de backup. Tem certeza que deseja alterar a senha de backup?", + "change_currency": "Alterar moeda", + "change_current_node": "Você realmente deseja alterar o nó atual para ${node}?", + "change_current_node_title": "Mudar o nó atual", + "change_exchange_provider": "Alterar o provedor de troca", + "change_language": "Mudar idioma", + "change_language_to": "Alterar idioma para ${language}?", + "change_password": "Mudar senha", "change_rep": "Alterar representante", "change_rep_message": "Tem certeza de que deseja alterar os representantes?", - "unsupported_asset": "Não oferecemos suporte a esta ação para este recurso. Crie ou mude para uma carteira de um tipo de ativo compatível.", - "manage_pow_nodes": "Gerenciar nós PoW", - "support_title_live_chat": "Apoio ao vivo", - "support_description_live_chat": "Livre e rápido! Representantes de suporte treinado estão disponíveis para ajudar", - "support_title_guides": "Guias da carteira de bolo", - "support_description_guides": "Documentação e suporte para problemas comuns", - "support_title_other_links": "Outros links de suporte", - "support_description_other_links": "Junte -se às nossas comunidades ou chegue a nós nossos parceiros por meio de outros métodos", + "change_rep_successful": "Mudou com sucesso o representante", + "change_wallet_alert_content": "Quer mudar a carteira atual para ${wallet_name}?", + "change_wallet_alert_title": "Alterar carteira atual", + "choose_account": "Escolha uma conta", + "choose_address": "\n\nEscolha o endereço:", "choose_derivation": "Escolha a derivação da carteira", - "new_first_wallet_text": "Mantenha sua criptomoeda facilmente segura", - "select_destination": "Selecione o destino para o arquivo de backup.", - "save_to_downloads": "Salvar em Downloads", - "select_buy_provider_notice": "Selecione um provedor de compra acima. Você pode pular esta tela definindo seu provedor de compra padrão nas configurações de aplicativos.", - "onramper_option_description": "Compre rapidamente criptografia com muitos métodos de pagamento. Disponível na maioria dos países. Os spreads e taxas variam.", + "choose_from_available_options": "Escolha entre as opções disponíveis:", + "choose_one": "Escolha um", + "choose_relay": "Escolha um relé para usar", + "choose_wallet_currency": "Escolha a moeda da carteira:", + "clear": "Limpar", + "clearnet_link": "link clear net", + "close": "Fechar", + "coin_control": "Controle de moedas (opcional)", + "cold_or_recover_wallet": "Adicione uma cold wallet ou recupere uma paper wallet", + "color_theme": "Tema de cor", + "commit_transaction_amount_fee": "Confirmar transação\nQuantia: ${amount}\nTaxa: ${fee}", + "confirm": "Confirmar", + "confirm_delete_template": "Esta ação excluirá este modelo. Você deseja continuar?", + "confirm_delete_wallet": "Esta ação excluirá esta carteira. Você deseja continuar?", + "confirm_sending": "Confirmar o envio", + "confirmations": "Confirmações", + "confirmed": "Saldo Confirmado", + "confirmed_tx": "Confirmado", + "congratulations": "Parabéns!", + "connect_an_existing_yat": "Conecte um Yat existente", + "connect_yats": "Connect Yats", + "connection_sync": "Conexão e sincronização", + "connectWalletPrompt": "Conecte sua carteira ao WalletConnect para fazer transações", + "contact": "Contato", + "contact_list_contacts": "Contatos", + "contact_list_wallets": "minhas carteiras", + "contact_name": "Nome do contato", + "contact_support": "Contatar Suporte", + "continue_text": "Continuar", + "contractName": "Nome do contrato", + "contractSymbol": "Símbolo do Contrato", + "copied_key_to_clipboard": "${key} copiada para a área de transferência", + "copied_to_clipboard": "Copiado para a área de transferência", + "copy": "Copiar", + "copy_address": "Copiar endereço", + "copy_id": "Copiar ID", + "copyWalletConnectLink": "Copie o link WalletConnect do dApp e cole aqui", + "create_account": "Criar conta", + "create_backup": "Criar backup", + "create_donation_link": "Criar link de doação", + "create_invoice": "Criar recibo", + "create_new": "Criar nova carteira", + "create_new_account": "Criar nova conta", + "creating_new_wallet": "Criando nova carteira", + "creating_new_wallet_error": "Erro: ${description}", + "creation_date": "Data de criação", + "custom": "personalizado", + "custom_drag": "Personalizado (segure e arraste)", + "custom_redeem_amount": "Valor de resgate personalizado", + "dark_theme": "Sombria", + "debit_card": "Cartão de débito", + "debit_card_terms": "O armazenamento e uso do número do cartão de pagamento (e credenciais correspondentes ao número do cartão de pagamento) nesta carteira digital estão sujeitos aos Termos e Condições do contrato do titular do cartão aplicável com o emissor do cartão de pagamento, em vigor a partir de tempo ao tempo.", + "decimal_places_error": "Muitas casas decimais", "default_buy_provider": "Provedor de compra padrão", - "ask_each_time": "Pergunte cada vez", - "buy_provider_unavailable": "Provedor atualmente indisponível.", - "signTransaction": "Assinar transação", + "default_sell_provider": "Provedor de venda padrão", + "delete": "Excluir", + "delete_account": "Excluir conta", + "delete_wallet": "Excluir carteira", + "delete_wallet_confirm_message": "Tem certeza de que deseja excluir a carteira ${wallet_name}?", + "deleteConnectionConfirmationPrompt": "Tem certeza de que deseja excluir a conexão com", + "descending": "descendente", + "description": "Descrição", + "destination_tag": "Tag de destino:", + "dfx_option_description": "Compre criptografia com EUR e CHF. Até 990€ sem KYC adicional. Para clientes de varejo e corporativos na Europa", + "didnt_get_code": "Não recebeu o código?", + "digit_pin": "dígitos", + "digital_and_physical_card": "cartão de débito pré-pago digital e físico", + "disable": "Desativar", + "disable_buy": "Desativar ação de compra", + "disable_cake_2fa": "Desabilitar o Cake 2FA", + "disable_exchange": "Desativar troca", + "disable_fiat": "Desativar fiat", + "disable_sell": "Desativar ação de venda", + "disabled": "Desabilitado", + "discount": "Economize ${value}%", + "display_settings": "Configurações de exibição", + "displayable": "Exibível", + "do_not_have_enough_gas_asset": "Você não tem ${currency} suficiente para fazer uma transação com as condições atuais da rede blockchain. Você precisa de mais ${currency} para pagar as taxas da rede blockchain, mesmo se estiver enviando um ativo diferente.", + "do_not_send": "não envie", + "do_not_share_warning_text": "Não os compartilhe com mais ninguém, incluindo suporte.\n\nSeus fundos podem e serão roubados!", + "do_not_show_me": "não me mostre isso novamente", + "domain_looks_up": "Pesquisas de domínio", + "donation_link_details": "Detalhes do link de doação", + "e_sign_consent": "Consentimento de assinatura eletrônica", + "edit": "Editar", + "edit_backup_password": "Editar senha de backup", + "edit_node": "Editar nó", + "edit_token": "Editar símbolo", + "electrum_address_disclaimer": "Geramos novos endereços cada vez que você usa um, mas os endereços anteriores continuam funcionando", + "email_address": "Endereço de e-mail", + "enabled": "Habilitado", + "enter_amount": "Digite o valor", + "enter_backup_password": "Digite a senha de backup aqui", + "enter_code": "Digite o código", + "enter_seed_phrase": "Digite sua frase de semente", + "enter_totp_code": "Digite o código TOTP.", + "enter_your_note": "Insira sua nota ...", + "enter_your_pin": "Insira seu PIN", + "enter_your_pin_again": "Insira seu PIN novamente", + "enterTokenID": "Insira o ID do token", + "enterWalletConnectURI": "Insira o URI do WalletConnect", + "error": "Erro", + "error_dialog_content": "Ops, houve algum erro.\n\nPor favor, envie o relatório de falha para nossa equipe de suporte para melhorar o aplicativo.", + "error_text_account_name": "O nome da conta só pode conter letras, números\ne deve ter entre 1 e 15 caracteres", + "error_text_address": "O endereço da carteira deve corresponder à\ncriptomoeda selecionada", + "error_text_amount": "A quantia deve conter apenas números", + "error_text_contact_name": "O nome do contato não pode conter os símbolos ` , ' \" \ne deve ter entre 1 e 32 caracteres", + "error_text_crypto_currency": "O número de dígitos decimais\ndeve ser menor ou igual a 12", + "error_text_fiat": "O valor do valor não pode exceder o saldo disponível.\nO número de dígitos decimais deve ser menor ou igual a 2", + "error_text_input_above_maximum_limit": "O valor é superior ao máximo", + "error_text_input_below_minimum_limit": "O valor é menor que o mínimo", + "error_text_keys": "As chaves da carteira podem conter apenas 64 caracteres em hexadecimal", + "error_text_limits_loading_failed": "A troca por ${provider} não é criada. Falha no carregamento dos limites", + "error_text_maximum_limit": "A troca por ${provider} não é criada. O valor é superior ao máximo: ${max} ${currency}", + "error_text_minimal_limit": "A troca por ${provider} não é criada. O valor é menor que o mínimo: ${min} ${currency}", + "error_text_node_address": "Digite um endereço iPv4", + "error_text_node_port": "A porta do nó deve conter apenas números entre 0 e 65535", + "error_text_node_proxy_address": "Insira :, por exemplo 127.0.0.1:9050", + "error_text_payment_id": "O ID de pagamento pode conter apenas de 16 a 64 caracteres em hexadecimal", + "error_text_subaddress_name": "O nome do sub-endereço não pode conter os símbolos ` , ' \" \ne deve ter entre 1 e 20 caracteres", + "error_text_template": "O nome e o endereço do modelo não podem conter os símbolos ` , ' \" \ne deve ter entre 1 e 106 caracteres", + "error_text_wallet_name": "O nome da carteira só pode conter letras, números, _ - símbolos\ne deve ter entre 1 e 33 caracteres", + "error_text_xmr": "A quantia em XMR não pode exceder o saldo disponível.\nTO número de dígitos decimais deve ser menor ou igual a 12", "errorGettingCredentials": "Falha: Erro ao obter credenciais", "errorSigningTransaction": "Ocorreu um erro ao assinar a transação", - "pairingInvalidEvent": "Emparelhamento de evento inválido", - "chains": "Correntes", - "methods": "Métodos", - "events": "Eventos", - "reject": "Rejeitar", - "approve": "Aprovar", - "expiresOn": "Expira em", - "walletConnect": "CarteiraConectada", - "nullURIError": "URI é nulo", - "connectWalletPrompt": "Conecte sua carteira ao WalletConnect para fazer transações", - "newConnection": "Nova conexão", - "activeConnectionsPrompt": "Conexões ativas aparecerão aqui", - "deleteConnectionConfirmationPrompt": "Tem certeza de que deseja excluir a conexão com", + "estimated": "Estimado", + "etherscan_history": "história Etherscan", "event": "Evento", - "successful": "Bem-sucedido", - "wouoldLikeToConnect": "gostaria de me conectar", - "message": "Mensagem", - "do_not_have_enough_gas_asset": "Você não tem ${currency} suficiente para fazer uma transação com as condições atuais da rede blockchain. Você precisa de mais ${currency} para pagar as taxas da rede blockchain, mesmo se estiver enviando um ativo diferente.", - "totp_auth_url": "URL de autenticação TOTP", - "awaitDAppProcessing": "Aguarde até que o dApp termine o processamento.", - "copyWalletConnectLink": "Copie o link WalletConnect do dApp e cole aqui", - "enterWalletConnectURI": "Insira o URI do WalletConnect", - "seed_key": "Chave de semente", - "enter_seed_phrase": "Digite sua frase de semente", - "change_rep_successful": "Mudou com sucesso o representante", - "add_contact": "Adicionar contato", + "events": "Eventos", + "exchange": "Trocar", + "exchange_incorrect_current_wallet_for_xmr": "Se você deseja trocar o XMR de seu saldo da Carteira Monero Cake, troque primeiro para sua carteira Monero.", + "exchange_new_template": "Novo modelo", "exchange_provider_unsupported": "${providerName} não é mais suportado!", - "domain_looks_up": "Pesquisas de domínio", - "require_for_exchanges_to_external_wallets": "Exigir trocas para carteiras externas", - "camera_permission_is_required": "É necessária permissão da câmera.\nAtive-o nas configurações do aplicativo.", - "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente", - "order_by": "Ordenar por", - "creation_date": "Data de criação", + "exchange_result_confirm": "Ao confirmar, você enviará ${fetchingLabel} ${from} da sua carteira ${walletName} para o endereço mostrado abaixo. Ou você pode enviar de sua carteira externa para o endereço abaixo/código QR acima.\n\nPressione Confirmar para continuar ou volte para alterar os valores.", + "exchange_result_description": "Você deve enviar no mínimo ${fetchingLabel} ${from} para o endereço mostrado na próxima página. Se você enviar um valor inferior a ${fetchingLabel} ${from}, ele pode não ser convertido e pode não ser reembolsado.", + "exchange_result_write_down_ID": "*Copie ou anote seu ID mostrado acima.", + "exchange_result_write_down_trade_id": "Copie ou anote o ID da troca para continuar.", + "exchange_sync_alert_content": "Por favor, espere até que sua carteira seja sincronizada", + "expired": "Expirada", + "expires": "Expira", + "expiresOn": "Expira em", + "export_backup": "Backup de exportação", + "extra_id": "ID extra:", + "extracted_address_content": "Você enviará fundos para\n${recipient_name}", + "failed_authentication": "Falha na autenticação. ${state_error}", + "faq": "FAQ", + "fetching": "Buscando", + "fiat_api": "API da Fiat", + "fiat_balance": "Equilíbrio Fiat", + "field_required": "Este campo é obrigatório", + "fill_code": "Por favor, preencha o código de verificação fornecido ao seu e-mail", + "filter_by": "Filtrar por", + "first_wallet_text": "Carteira incrível para Monero, Bitcoin, Ethereum, Litecoin, e Haven", + "fixed_pair_not_supported": "Este par fixo não é compatível com as exchanges selecionadas", + "fixed_rate": "Taxa fixa", + "fixed_rate_alert": "Você poderá inserir a quantia recebida quando o modo de taxa fixa estiver marcado. Quer mudar para o modo de taxa fixa?", + "forgot_password": "Esqueci a senha", + "freeze": "Congelar", + "frequently_asked_questions": "Perguntas frequentes", + "frozen": "Congeladas", + "full_balance": "Saldo total", + "generate_name": "Gerar nome", + "generating_gift_card": "Gerando Cartão Presente", + "get_a": "Obter um ", + "get_card_note": " que você pode recarregar com moedas digitais. Nenhuma informação adicional é necessária!", + "get_your_yat": "Pegue seu Yat", + "gift_card_amount": "Valor do Cartão Presente", + "gift_card_balance_note": "Os cartões-presente com saldo restante aparecerão aqui", + "gift_card_is_generated": "Cartão presente é gerado", + "gift_card_number": "Número do cartão-presente", + "gift_card_redeemed_note": "Os cartões-presente que você resgatou aparecerão aqui", + "gift_cards": "Cartões de presente", + "gift_cards_unavailable": "Os cartões-presente estão disponíveis para compra apenas através do Monero, Bitcoin e Litecoin no momento", + "got_it": "Entendi", + "gross_balance": "Saldo Bruto", "group_by_type": "Grupo por tipo", - "importNFTs": "Importar NFTs", - "noNFTYet": "Ainda não há NFT", - "address": "Endereço", - "enterTokenID": "Insira o ID do token", - "tokenID": "EU IA", - "name": "Nome", - "symbol": "Símbolo", - "seed_phrase_length": "Comprimento da frase-semente", - "unavailable_balance": "Saldo indisponível", - "unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.", - "unspent_change": "Mudar", - "tor_connection": "Conexão Tor", - "setup_warning_2fa_text": "Você precisará restaurar sua carteira a partir da semente mnemônica.\n\nO suporte do Cake não poderá ajudá-lo se você perder o acesso ao seu 2FA ou sementes mnemônicas.\nCake 2FA é uma segunda autenticação para determinadas ações na carteira. Antes de usar o Cake 2FA, recomendamos a leitura do guia.NÃO é tão seguro quanto o armazenamento refrigerado.\n\nSe você perder o acesso ao seu aplicativo 2FA ou às chaves TOTP, você perderá o acesso a esta carteira. ", - "scan_qr_on_device": "Digitalize este código QR em outro dispositivo", + "haven_app": "Haven by Cake Wallet", + "haven_app_wallet_text": "Awesome wallet for Haven", + "help": "ajuda", + "hidden_balance": "Saldo escondido", + "hide_details": "Ocultar detalhes", + "high_contrast_theme": "Tema de alto contraste", + "home_screen_settings": "Configurações da tela inicial", "how_to_use": "Como usar", + "how_to_use_card": "Como usar este cartão", + "id": "ID: ", + "ignor": "Ignorar", + "import": "Importar", + "importNFTs": "Importar NFTs", + "in_store": "Na loja", + "incoming": "Recebidas", + "incorrect_seed": "O texto digitado não é válido.", + "introducing_cake_pay": "Apresentando o Cake Pay!", + "invalid_input": "Entrada inválida", + "invoice_details": "Detalhes da fatura", + "is_percentage": "é", + "last_30_days": "Últimos 30 dias", + "learn_more": "Saber mais", + "light_theme": "Luz", + "loading_your_wallet": "Abrindo sua carteira", + "login": "Login", + "logout": "Logout", + "low_fee": "Taxa baixa", + "low_fee_alert": "No momento, você está usando uma prioridade de taxa de rede baixa. Isso pode causar longas esperas, taxas diferentes ou negociações canceladas. Recomendamos definir uma taxa mais alta para uma melhor experiência.", + "manage_nodes": "Gerenciar nós", + "manage_pow_nodes": "Gerenciar nós PoW", + "manage_yats": "Gerenciar Yats", + "mark_as_redemed": "Marcar como resgatado", + "market_place": "Mercado", + "matrix_green_dark_theme": "Tema escuro verde matrix", + "max_amount": "Máx.: ${valor}", + "max_value": "Máx: ${value} ${currency}", + "memo": "Memorando:", + "message": "Mensagem", + "methods": "Métodos", + "min_amount": "Mínimo: ${valor}", + "min_value": "Mín: ${value} ${currency}", + "minutes_to_pin_code": "${minute} minutos", + "mm": "MM", + "modify_2fa": "Modificar o Cake 2FA", + "monero_com": "Monero.com by Cake Wallet", + "monero_com_wallet_text": "Awesome wallet for Monero", + "monero_dark_theme": "Monero Tema Escuro", + "monero_light_theme": "Monero Light Theme", + "moonpay_alert_text": "O valor do montante deve ser maior ou igual a ${minAmount} ${fiatCurrency}", + "more_options": "Mais opções", + "name": "Nome", + "narrow": "Estreito", + "new_first_wallet_text": "Mantenha sua criptomoeda facilmente segura", + "new_node_testing": "Teste de novo nó", + "new_subaddress_create": "Criar", + "new_subaddress_label_name": "Nome", + "new_subaddress_title": "Novo endereço", + "new_template": "Novo modelo", + "new_wallet": "Nova carteira", + "newConnection": "Nova conexão", + "no_id_needed": "Nenhum ID necessário!", + "no_id_required": "Não é necessário ID. Recarregue e gaste em qualquer lugar", + "no_relay_on_domain": "Não há uma retransmissão para o domínio do usuário ou a retransmissão está indisponível. Escolha um relé para usar.", + "no_relays": "Sem relés", + "no_relays_message": "Encontramos um registro Nostr NIP-05 para este usuário, mas ele não contém nenhum relé. Instrua o destinatário a adicionar retransmissões ao seu registro Nostr.", + "node_address": "Endereço do nó", + "node_connection_failed": "A conexão falhou", + "node_connection_successful": "A conexão foi bem sucedida", + "node_new": "Novo nó", + "node_port": "Porta do nó", + "node_reset_settings_title": "Redefinir configurações", + "node_test": "Teste", + "nodes": "Nós", + "nodes_list_reset_to_default_message": "Você realmente deseja redefinir as configurações para o padrão?", + "none_of_selected_providers_can_exchange": "Nenhum dos provedores selecionados pode fazer esta troca", + "noNFTYet": "Ainda não há NFT", + "normal": "Normal", + "note_optional": "Nota (opcional)", + "note_tap_to_change": "Nota (toque para alterar)", + "nullURIError": "URI é nulo", + "offer_expires_in": "A oferta expira em: ", + "offline": "offline", + "ok": "Ok", + "onion_link": "ligação de cebola", + "online": "Online", + "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", + "optional_description": "Descrição opcional", + "optional_email_hint": "E-mail opcional de notificação do beneficiário", + "optional_name": "Nome do destinatário opcional", + "orbot_running_alert": "Certifique-se de que o Orbot esteja em execução antes de se conectar a este nó.", + "order_by": "Ordenar por", + "order_id": "ID do pedido", + "order_physical_card": "Pedir Cartão Físico", + "other_settings": "Outras configurações", + "outdated_electrum_wallet_description": "As novas carteiras Bitcoin criadas no Cake agora têm uma semente de 24 palavras. É obrigatório que você crie uma nova carteira Bitcoin e transfira todos os seus fundos para a nova carteira de 24 palavras, e pare de usar carteiras com semente de 12 palavras. Faça isso imediatamente para garantir seus fundos.", + "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", + "overwrite_amount": "Overwrite amount", + "pairingInvalidEvent": "Emparelhamento de evento inválido", + "password": "Senha", + "paste": "Colar", + "pause_wallet_creation": "A capacidade de criar a Haven Wallet está atualmente pausada.", + "payment_id": "ID de pagamento: ", + "payment_was_received": "Seu pagamento foi recebido.", + "pending": " (pendente)", + "percentageOf": "de ${amount}", + "pin_at_top": "fixe ${token} no topo", + "pin_is_incorrect": "PIN incorreto", + "pin_number": "Número PIN", + "placeholder_contacts": "Seus contatos serão exibidos aqui", + "placeholder_transactions": "Suas transações serão exibidas aqui", + "please_fill_totp": "Por favor, preencha o código de 8 dígitos presente em seu outro dispositivo", + "please_make_selection": "Escolha se quer criar uma carteira nova ou restaurar uma antiga.", + "please_reference_document": "Por favor, consulte os documentos abaixo para mais informações.", + "please_select": "Escolha abaixo:", + "please_select_backup_file": "Selecione o arquivo de backup e insira a senha de backup.", + "please_try_to_connect_to_another_node": "Por favor, tente conectar-se a outro nó", + "please_wait": "Por favor, aguarde", + "polygonscan_history": "História do PolygonScan", + "powered_by": "Troca realizada por ${title}", + "pre_seed_button_text": "Compreendo. Me mostre minha semente", + "pre_seed_description": "Na próxima página, você verá uma série de ${words} palavras. Esta é a sua semente única e privada e é a ÚNICA maneira de recuperar sua carteira em caso de perda ou mau funcionamento. É SUA responsabilidade anotá-lo e armazená-lo em um local seguro fora do aplicativo Cake Wallet.", + "pre_seed_title": "IMPORTANTE", + "prevent_screenshots": "Evite capturas de tela e gravação de tela", + "privacy": "Privacidade", + "privacy_policy": "Política de privacidade", + "privacy_settings": "Configurações de privacidade", + "private_key": "Chave privada", + "proceed_after_one_minute": "Se a tela não prosseguir após 1 minuto, verifique seu e-mail.", + "profile": "Perfil", + "provider_error": "${provider} erro", + "public_key": "Chave pública", + "purchase_gift_card": "Comprar vale-presente", + "qr_fullscreen": "Toque para abrir o código QR em tela cheia", + "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", + "question_to_disable_2fa": "Tem certeza de que deseja desativar o Cake 2FA? Um código 2FA não será mais necessário para acessar a carteira e certas funções.", + "receivable_balance": "Saldo a receber", + "receive": "Receber", + "receive_amount": "Quantia", + "received": "Recebida", + "recipient_address": "Endereço do destinatário", + "reconnect": "Reconectar", + "reconnect_alert_text": "Você tem certeza de que deseja reconectar?", + "reconnection": "Reconectar", + "redeemed": "Resgatado", + "refund_address": "Endereço de reembolso", + "reject": "Rejeitar", + "remaining": "restante", + "remove": "Remover", + "remove_node": "Remover nó", + "remove_node_message": "Você realmente deseja remover o nó selecionado?", + "rename": "Renomear", + "require_for_adding_contacts": "Requer para adicionar contatos", + "require_for_all_security_and_backup_settings": "Exigir todas as configurações de segurança e backup", + "require_for_assessing_wallet": "Requer para acessar a carteira", + "require_for_creating_new_wallets": "Requer para criar novas carteiras", + "require_for_exchanges_to_external_wallets": "Exigir trocas para carteiras externas", + "require_for_exchanges_to_internal_wallets": "Requer trocas para carteiras internas", + "require_for_sends_to_contacts": "Exigir para envios para contatos", + "require_for_sends_to_internal_wallets": "Exigir envios para carteiras internas", + "require_for_sends_to_non_contacts": "Exigir para envios para não-contatos", + "require_pin_after": "Exigir PIN após", + "rescan": "Reescanear", + "resend_code": "Por favor, reenvie", + "reset": "Limpar", + "reset_password": "Redefinir senha", + "restore_active_seed": "Semente ativa", + "restore_address": "Endereço", + "restore_bitcoin_description_from_keys": "Restaure sua carteira a partir da string WIF gerada de suas chaves privadas", + "restore_bitcoin_description_from_seed": "Restaure sua carteira a partir de um código de combinação de 24 palavras", + "restore_bitcoin_title_from_keys": "Restaurar de WIF", + "restore_description_from_backup": "Você pode restaurar todo o aplicativo Cake Wallet de seu arquivo de backup", + "restore_description_from_keys": "Restaure sua carteira a partir de suas chaves privadas", + "restore_description_from_seed": "Restaure sua carteira a partir de semente com 25 palavras ou 13 palavras", + "restore_description_from_seed_keys": "Restaure a sua carteira a partir de sementes/chaves que você salvou em um local seguro", + "restore_from_date_or_blockheight": "Insira uma data alguns dias antes de criar esta carteira. Ou se você souber a altura do bloco, insira-o", + "restore_from_seed_placeholder": "Digite ou cole sua frase de código aqui", + "restore_new_seed": "Nova semente", + "restore_next": "Próximo", + "restore_recover": "Restaurar", + "restore_restore_wallet": "Restaurar carteira", + "restore_seed_keys_restore": "Restauração com sementes/chaves", + "restore_spend_key_private": "Chave de gastos (privada)", + "restore_title_from_backup": "Restaurar a partir de um arquivo de backup", + "restore_title_from_keys": "Restaurar a partir de chaves", + "restore_title_from_seed": "Restaurar a partir de semente", + "restore_title_from_seed_keys": "Restaurar a partir de sementes/chaves", + "restore_view_key_private": "Chave de visualização (privada)", + "restore_wallet": "Restaurar carteira", + "restore_wallet_name": "Nome da carteira", + "restore_wallet_restore_description": "Restauração da carteira", + "router_no_route": "Nenhuma rota definida para ${name}", + "save": "Salvar", + "save_backup_password": "Certifique-se de que salvou sua senha de backup. Você não poderá importar seus arquivos de backup sem ele.", + "save_backup_password_alert": "Salvar senha de backup", + "save_to_downloads": "Salvar em Downloads", + "saved_the_trade_id": "ID da troca salvo", + "scan_qr_code": "Escanear código QR", + "scan_qr_code_to_get_address": "Digitalize o código QR para obter o endereço", + "scan_qr_on_device": "Digitalize este código QR em outro dispositivo", + "search": "Procurar", + "search_add_token": "Pesquisar / Adicionar token", + "search_category": "Categoria de pesquisa", + "search_currency": "Pesquisar moeda", + "search_language": "Idioma de pesquisa", + "second_intro_content": "Seu Yat é um endereço de emoji único e exclusivo que substitui todos os seus endereços hexadecimais longos para todas as suas moedas.", + "second_intro_title": "Um endereço de emoji para governar todos eles", + "security_and_backup": "Segurança e backup", + "seed_alert_back": "Volte", + "seed_alert_content": "A semente é a única forma de recuperar sua carteira. Você escreveu isso?", + "seed_alert_title": "Atenção", + "seed_alert_yes": "Sim, eu tenho", + "seed_choose": "Escolha o idioma da semente", "seed_hex_form": "Semente de carteira (forma hexadecimal)", + "seed_key": "Chave de semente", + "seed_language": "Linguagem de semente", + "seed_language_chinese": "Chinesa", + "seed_language_chinese_traditional": "Chinês tradicional)", + "seed_language_czech": "Tcheco", + "seed_language_dutch": "Holandesa", + "seed_language_english": "Inglesa", + "seed_language_french": "Francesa/Francês", + "seed_language_german": "Alemã", + "seed_language_italian": "Italiana/Italiano", + "seed_language_japanese": "Japonês", + "seed_language_korean": "coreano", + "seed_language_next": "Próximo", + "seed_language_portuguese": "Português", + "seed_language_russian": "Russa", + "seed_language_spanish": "Espanhola", + "seed_phrase_length": "Comprimento da frase-semente", + "seed_reminder": "Anote-os para o caso de perder ou limpar seu telefone", + "seed_share": "Compartilhar semente", + "seed_title": "Semente", "seedtype": "SeedType", "seedtype_legacy": "Legado (25 palavras)", "seedtype_polyseed": "Polyseed (16 palavras)", - "seed_language_czech": "Tcheco", - "seed_language_korean": "coreano", - "seed_language_chinese_traditional": "Chinês tradicional)", - "ascending": "Ascendente", - "descending": "descendente", - "dfx_option_description": "Compre criptografia com EUR e CHF. Até 990€ sem KYC adicional. Para clientes de varejo e corporativos na Europa", - "polygonscan_history": "História do PolygonScan", - "wallet_seed_legacy": "Semente de carteira herdada", - "default_sell_provider": "Provedor de venda padrão", + "select_backup_file": "Selecione o arquivo de backup", + "select_buy_provider_notice": "Selecione um provedor de compra acima. Você pode pular esta tela definindo seu provedor de compra padrão nas configurações de aplicativos.", + "select_destination": "Selecione o destino para o arquivo de backup.", "select_sell_provider_notice": "Selecione um fornecedor de venda acima. Você pode pular esta tela definindo seu provedor de venda padrão nas configurações do aplicativo.", - "custom_drag": "Personalizado (segure e arraste)", + "sell": "Vender", + "sell_alert_content": "Atualmente, oferecemos suporte apenas à venda de Bitcoin, Ethereum e Litecoin. Crie ou troque para sua carteira Bitcoin, Ethereum ou Litecoin.", + "sell_monero_com_alert_content": "A venda de Monero ainda não é suportada", + "send": "Enviar", + "send_address": "Endereço ${cryptoCurrency}", + "send_amount": "Montante:", + "send_creating_transaction": "Criando transação", + "send_error_currency": "A moeda só pode conter números", + "send_error_minimum_value": "O valor mínimo da quantia é 0,01", + "send_estimated_fee": "Taxa estimada:", + "send_fee": "Taxa:", + "send_name": "Nome", + "send_new": "Novo", + "send_payment_id": "ID de pagamento (opcional)", + "send_priority": "Atualmente, a taxa está definida para a prioridade: ${transactionPriority}.\nA prioridade da transação pode ser ajustada nas configurações", + "send_sending": "Enviando...", + "send_success": "Seu ${crypto} foi enviado com sucesso", + "send_templates": "Modelos", + "send_title": "Enviar", + "send_to_this_address": "Envie ${currency} ${tag}para este endereço", + "send_xmr": "Enviar XMR", + "send_your_wallet": "Sua carteira", + "sending": "Enviando", + "sent": "Enviada", + "settings": "Configurações", + "settings_all": "Tudo", + "settings_allow_biometrical_authentication": "Permitir autenticação biométrica", + "settings_can_be_changed_later": "Essas configurações podem ser alteradas posteriormente nas configurações do aplicativo", + "settings_change_language": "Mudar idioma", + "settings_change_pin": "Mudar PIN", + "settings_currency": "Moeda", + "settings_current_node": "Nó atual", + "settings_dark_mode": "Modo noturno", + "settings_display_balance": "Exibir saldo", + "settings_display_on_dashboard_list": "Exibir no histórico", + "settings_fee_priority": "Prioridade da taxa", + "settings_nodes": "Nós", + "settings_none": "Nada", + "settings_only_trades": "Somente trocas", + "settings_only_transactions": "Somente transações", + "settings_personal": "Pessoal", + "settings_save_recipient_address": "Salvar endereço do destinatário", + "settings_support": "Suporte", + "settings_terms_and_conditions": "Termos e Condições", + "settings_title": "Configurações", + "settings_trades": "Trocas", + "settings_transactions": "Transações", + "settings_wallets": "Carteiras", + "setup_2fa": "Configurar o Cake 2FA", + "setup_2fa_text": "Cake 2FA funciona usando TOTP como segundo fator de autenticação.\n\nO TOTP do Cake 2FA requer suporte SHA-512 e 8 dígitos; isso proporciona maior segurança. Mais informações e aplicativos suportados podem ser encontrados no guia.", + "setup_pin": "Configurar PIN", + "setup_successful": "Seu PIN foi configurado com sucesso!", + "setup_totp_recommended": "Configurar TOTP", + "setup_warning_2fa_text": "Você precisará restaurar sua carteira a partir da semente mnemônica.\n\nO suporte do Cake não poderá ajudá-lo se você perder o acesso ao seu 2FA ou sementes mnemônicas.\nCake 2FA é uma segunda autenticação para determinadas ações na carteira. Antes de usar o Cake 2FA, recomendamos a leitura do guia.NÃO é tão seguro quanto o armazenamento refrigerado.\n\nSe você perder o acesso ao seu aplicativo 2FA ou às chaves TOTP, você perderá o acesso a esta carteira. ", + "setup_your_debit_card": "Configure seu cartão de débito", + "share": "Compartilhar", + "share_address": "Compartilhar endereço", + "show_details": "Mostrar detalhes", + "show_keys": "Mostrar semente/chaves", + "show_market_place": "Mostrar mercado", + "show_seed": "Mostrar semente", + "signTransaction": "Assinar transação", + "signup_for_card_accept_terms": "Cadastre-se no cartão e aceite os termos.", + "slidable": "Deslizável", + "sort_by": "Ordenar por", + "spend_key_private": "Chave de gastos (privada)", + "spend_key_public": "Chave de gastos (pública)", + "status": "Status: ", + "subaddress_title": "Sub-endereços", + "subaddresses": "Sub-endereços", + "submit_request": "enviar um pedido", + "successful": "Bem-sucedido", + "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_live_chat": "Apoio ao vivo", + "support_title_other_links": "Outros links de suporte", + "sweeping_wallet": "Carteira varrendo", + "sweeping_wallet_alert": "To nie powinno zająć dużo czasu. NIE WYCHODŹ Z TEGO EKRANU, W PRZECIWNYM WYPADKU MOŻE ZOSTAĆ UTRACONA ŚRODKI", + "switchToETHWallet": "Mude para uma carteira Ethereum e tente novamente", "switchToEVMCompatibleWallet": "Mude para uma carteira compatível com EVM e tente novamente (Ethereum, Polygon)", - "receivable_balance": "Saldo a receber", - "confirmed_tx": "Confirmado", + "symbol": "Símbolo", + "sync_all_wallets": "Sincronize todas as carteiras", + "sync_status_attempting_sync": "TENTANDO SINCRONIZAR", + "sync_status_connected": "CONECTADO", + "sync_status_connecting": "CONECTANDO", + "sync_status_failed_connect": "DESCONECTADO", + "sync_status_not_connected": "DESCONECTADO", + "sync_status_starting_sync": "INICIANDO SINCRONIZAÇÃO", + "sync_status_syncronized": "SINCRONIZADO", + "sync_status_syncronizing": "SINCRONIZANDO", + "syncing_wallet_alert_content": "Seu saldo e lista de transações podem não estar completos até que diga “SYNCHRONIZED” no topo. Clique/toque para saber mais.", + "syncing_wallet_alert_title": "Sua carteira está sincronizando", + "template": "Modelo", + "template_name": "Nome do modelo", + "third_intro_content": "Yats também mora fora da Cake Wallet. Qualquer endereço de carteira na Terra pode ser substituído por um Yat!", + "third_intro_title": "Yat joga bem com os outros", + "time": "${minutes}m ${seconds}s", + "tip": "Dica:", + "today": "Hoje", + "token_contract_address": "Endereço do contrato de token", + "token_decimal": "Token decimal", + "token_name": "Nome do token, por exemplo: Tether", + "token_symbol": "Símbolo de token, por exemplo: USDT", + "tokenID": "EU IA", + "tor_connection": "Conexão Tor", + "tor_only": "Tor apenas", + "total_saving": "Economia total", + "totp_2fa_failure": "Código incorreto. Tente um código diferente ou gere uma nova chave secreta. Use um aplicativo 2FA compatível com códigos de 8 dígitos e SHA512.", + "totp_2fa_success": "Sucesso! Cake 2FA ativado para esta carteira. Lembre-se de salvar sua semente mnemônica caso perca o acesso à carteira.", + "totp_auth_url": "URL de autenticação TOTP", + "totp_code": "Código TOTP", + "totp_secret_code": "Código Secreto TOTP", + "totp_verification_success": "Verificação bem-sucedida!", + "trade_details_copied": "${title} copiados para a área de transferência", + "trade_details_created_at": "Criada em", + "trade_details_fetching": "Buscando", + "trade_details_id": "ID", + "trade_details_pair": "Par", + "trade_details_provider": "Provedor", + "trade_details_state": "Status", + "trade_details_title": "Detalhes da troca", + "trade_for_not_created": "A troca por ${title} não foi criada.", + "trade_history_title": "Histórico de trocas", + "trade_id": "ID da troca:", + "trade_id_not_found": "A troca ${tradeId} de ${title} não foi encontrada.", + "trade_is_powered_by": "Troca realizada por ${provider}", + "trade_not_created": "Troca não criada", + "trade_not_found": "Troca não encontrada.", + "trade_state_btc_sent": "BTC enviado", + "trade_state_complete": "Finalizada", + "trade_state_confirming": "Confirmando", + "trade_state_created": "Criada", + "trade_state_finished": "Finalizada", + "trade_state_paid": "Paga", + "trade_state_paid_unconfirmed": "Pagamento não-confirmado", + "trade_state_pending": "Pendente", + "trade_state_timeout": "Tempo esgotado", + "trade_state_to_be_created": "A ser criada", + "trade_state_traded": "Troca realizada", + "trade_state_trading": "Em andamento", + "trade_state_underpaid": "Parcialmente paga", + "trade_state_unpaid": "Não paga", + "trades": "Trocas", + "transaction_details_amount": "Quantia", + "transaction_details_copied": "${title} copiados para a área de transferência", + "transaction_details_date": "Data", + "transaction_details_fee": "Taxa", + "transaction_details_height": "Altura", + "transaction_details_recipient_address": "Endereços de destinatários", "transaction_details_source_address": "Endereço de Origem", - "pause_wallet_creation": "A capacidade de criar a Haven Wallet está atualmente pausada.", - "contractName": "Nome do contrato", - "contractSymbol": "Símbolo do Contrato", - "description": "Descrição", - "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.", - "no_relays": "Sem relés", - "choose_relay": "Escolha um relé para usar", - "no_relays_message": "Encontramos um registro Nostr NIP-05 para este usuário, mas ele não contém nenhum relé. Instrua o destinatário a adicionar retransmissões ao seu registro Nostr.", - "no_relay_on_domain": "Não há uma retransmissão para o domínio do usuário ou a retransmissão está indisponível. Escolha um relé para usar." -} + "transaction_details_title": "Detalhes da transação", + "transaction_details_transaction_id": "ID da transação", + "transaction_key": "Chave de transação", + "transaction_priority_fast": "Rápida", + "transaction_priority_fastest": "Muito rápida", + "transaction_priority_medium": "Média", + "transaction_priority_regular": "Regular", + "transaction_priority_slow": "Lenta", + "transaction_sent": "Transação enviada!", + "transaction_sent_notice": "Se a tela não prosseguir após 1 minuto, verifique um explorador de blocos e seu e-mail.", + "transactions": "Transações", + "transactions_by_date": "Transações por data", + "trusted": "confiável", + "unavailable_balance": "Saldo indisponível", + "unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.", + "unconfirmed": "Saldo não confirmado", + "understand": "Entendo", + "unmatched_currencies": "A moeda da sua carteira atual não corresponde à do QR digitalizado", + "unspent_change": "Mudar", + "unspent_coins_details_title": "Detalhes de moedas não gastas", + "unspent_coins_title": "Moedas não gastas", + "unsupported_asset": "Não oferecemos suporte a esta ação para este recurso. Crie ou mude para uma carteira de um tipo de ativo compatível.", + "upto": "até ${value}", + "use": "Use PIN de ", + "use_card_info_three": "Use o cartão digital online ou com métodos de pagamento sem contato.", + "use_card_info_two": "Os fundos são convertidos para USD quando mantidos na conta pré-paga, não em moedas digitais.", + "use_ssl": "Use SSL", + "use_suggested": "Uso sugerido", + "variable_pair_not_supported": "Este par de variáveis não é compatível com as trocas selecionadas", + "verification": "Verificação", + "verify_with_2fa": "Verificar com Cake 2FA", + "version": "Versão ${currentVersion}", + "view_all": "Ver todos", + "view_in_block_explorer": "View in Block Explorer", + "view_key_private": "Chave de visualização (privada)", + "view_key_public": "Chave de visualização (pública)", + "view_transaction_on": "View Transaction on ", + "waiting_payment_confirmation": "Aguardando confirmação de pagamento", + "wallet_keys": "Semente/chaves da carteira", + "wallet_list_create_new_wallet": "Criar nova carteira", + "wallet_list_edit_wallet": "Editar carteira", + "wallet_list_failed_to_load": "Falha ao abrir a carteira ${wallet_name}. ${error}", + "wallet_list_failed_to_remove": "Falha ao remover a carteira ${wallet_name}. ${error}", + "wallet_list_load_wallet": "Abrir carteira", + "wallet_list_loading_wallet": "Abrindo a carteira ${wallet_name}", + "wallet_list_removing_wallet": "Removendo a carteira ${wallet_name}", + "wallet_list_restore_wallet": "Restaurar carteira", + "wallet_list_title": "Carteira Monero", + "wallet_list_wallet_name": "Nome da carteira", + "wallet_menu": "Menu", + "wallet_name": "Nome da carteira", + "wallet_name_exists": "A carteira com esse nome já existe", + "wallet_restoration_store_incorrect_seed_length": "Comprimento de semente incorreto", + "wallet_seed": "Semente de carteira", + "wallet_seed_legacy": "Semente de carteira herdada", + "wallet_store_monero_wallet": "Carteira Monero", + "walletConnect": "CarteiraConectada", + "wallets": "Carteiras", + "warning": "Aviso", + "welcome": "Bem-vindo ao", + "welcome_to_cakepay": "Bem-vindo ao Cake Pay!", + "widgets_address": "Endereço", + "widgets_or": "ou", + "widgets_restore_from_blockheight": "Restaurar a partir de altura do bloco", + "widgets_restore_from_date": "Restaurar a partir de data", + "widgets_seed": "Semente", + "wouoldLikeToConnect": "gostaria de me conectar", + "write_down_backup_password": "Anote sua senha de backup, que será usada para importar seus arquivos de backup.", + "xlm_extra_info": "Não se esqueça de especificar o Memo ID ao enviar a transação XLM para a troca", + "xmr_available_balance": "Saldo disponível", + "xmr_full_balance": "Saldo total", + "xmr_hidden": "Esconder saldo", + "xmr_to_error": "Erro XMR.TO", + "xmr_to_error_description": "Montante inválido. Limite máximo de 8 dígitos após o ponto decimal", + "xrp_extra_info": "Não se esqueça de especificar a etiqueta de destino ao enviar a transação XRP para a troca", + "yat": "Yat", + "yat_address": "Endereço Yat", + "yat_alert_content": "Os usuários da Cake Wallet agora podem enviar e receber todas as suas moedas favoritas com um nome de usuário baseado em emoji único.", + "yat_alert_title": "Envie e receba criptografia mais facilmente com Yat", + "yat_error": "Yat erro", + "yat_error_content": "Nenhum endereço vinculado a este Yat. Tente outro Yat", + "yat_popup_content": "Agora você pode enviar e receber criptografia na Cake Wallet com seu Yat - um nome de usuário curto baseado em emoji. Gerenciar Yats a qualquer momento na tela de configurações", + "yat_popup_title": "O endereço da sua carteira pode ser emojificado.", + "yesterday": "Ontem", + "you_now_have_debit_card": "Agora você tem um cartão de débito", + "you_pay": "Você paga", + "you_will_get": "Converter para", + "you_will_send": "Converter de", + "yy": "aa", + "zzzz": "ZZZZ" +} \ No newline at end of file diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index a4c34f5c5..7fccaa5bd 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -1,779 +1,780 @@ { - "welcome": "Приветствуем в", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "В самом удобном кошельке для Monero, Bitcoin, Ethereum, Litecoin, и Haven", - "please_make_selection": "Выберите способ создания кошелька: создать новый или восстановить ваш существующий.", - "create_new": "Создать новый кошелёк", - "restore_wallet": "Восстановить кошелёк", - "monero_com": "Monero.com by Cake Wallet", - "monero_com_wallet_text": "Awesome wallet for Monero", - "haven_app": "Haven by Cake Wallet", - "haven_app_wallet_text": "Awesome wallet for Haven", - "accounts": "Аккаунты", - "edit": "Редактировать", + "about_cake_pay": "Cake Pay позволяет вам легко покупать подарочные карты с виртуальными активами, которые можно мгновенно потратить в более чем 150 000 продавцов в Соединенных Штатах.", "account": "Аккаунт", + "accounts": "Аккаунты", + "accounts_subaddresses": "Аккаунты и субадреса", + "activate": "Активировать", + "active": "Активный", + "active_cards": "Активные карты", + "activeConnectionsPrompt": "Здесь появятся активные подключения", "add": "Добавить", + "add_contact": "Добавить контакт", + "add_custom_node": "Добавить новый пользовательский узел", + "add_custom_redemption": "Добавить пользовательское погашение", + "add_fund_to_card": "Добавить предоплаченные средства на карты (до ${value})", + "add_new_node": "Добавить новую ноду", + "add_new_word": "Добавить новое слово", + "add_receiver": "Добавить получателя (необязательно)", + "add_secret_code": "Или добавьте этот секретный код в приложение для аутентификации.", + "add_tip": "Добавить подсказку", + "add_token_disclaimer_check": "Я подтвердил адрес контракта токена и информацию, используя авторитетный источник. Добавление вредоносной или неверной информации может привести к потере средств.", + "add_token_warning": "Не редактируйте и не добавляйте токены по указанию мошенников.\nВсегда подтверждайте адреса токенов из авторитетных источников!", + "add_value": "Добавить значение", + "address": "Адрес", "address_book": "Адресная книга", - "contact": "Контакт", - "please_select": "Пожалуйста, выберите:", - "cancel": "Отменить", - "ok": "OK", - "contact_name": "Имя контакта", - "reset": "Сброс", - "save": "Сохранить", + "address_book_menu": "Адресная книга", + "address_detected": "Обнаружен адрес", + "address_from_domain": "Этот адрес от ${domain} на Unstoppable Domains", + "address_from_yat": "Этот адрес от ${emoji} на Yat", + "address_label": "Address label", "address_remove_contact": "Удалить контакт", "address_remove_content": "Вы уверены, что хотите удалить выбранный контакт?", - "authenticated": "Аутентифицировано", - "authentication": "Аутентификация", - "failed_authentication": "Ошибка аутентификации. ${state_error}", - "wallet_menu": "Меню кошелька", - "Blocks_remaining": "${status} Осталось блоков", - "please_try_to_connect_to_another_node": "Пожалуйста, попробуйте подключиться к другой ноде", - "xmr_hidden": "Скрыто", - "xmr_available_balance": "Доступный баланс", - "xmr_full_balance": "Весь баланс", - "send": "Отправить", - "receive": "Получить", - "transactions": "Транзакции", - "incoming": "Входящие", - "outgoing": "Исходящие", - "transactions_by_date": "Сортировать по дате", - "trades": "Сделки", - "filter_by": "Фильтровать по", - "today": "Сегодня", - "yesterday": "Вчера", - "received": "Полученные", - "sent": "Отправленные", - "pending": " (в ожидании)", - "rescan": "Пересканировать", - "reconnect": "Переподключиться", - "wallets": "Кошельки", - "show_seed": "Показать мнемоническую фразу", - "show_keys": "Показать мнемоническую фразу/ключи", - "address_book_menu": "Адресная книга", - "reconnection": "Переподключение", - "reconnect_alert_text": "Вы хотите переподключиться?", - "exchange": "Обмен", - "clear": "Очистить", - "refund_address": "Адрес возврата", - "change_exchange_provider": "Изменить провайдера обмена", - "you_will_send": "Конвертировать из", - "you_will_get": "Конвертировать в", - "amount_is_guaranteed": "Полученная сумма гарантирована", - "amount_is_estimate": "Полученная сумма является приблизительной", - "powered_by": "Используя ${title}", - "error": "Ошибка", - "estimated": "Примерно", - "min_value": "Мин: ${value} ${currency}", - "max_value": "Макс: ${value} ${currency}", - "change_currency": "Изменить валюту", - "overwrite_amount": "Overwrite amount", - "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", - "copy_id": "Скопировать ID", - "exchange_result_write_down_trade_id": "Пожалуйста, скопируйте или запишите ID сделки.", - "trade_id": "ID сделки:", - "copied_to_clipboard": "Скопировано в буфер обмена", - "saved_the_trade_id": "Я сохранил ID сделки", - "fetching": "Загрузка", - "id": "ID: ", - "amount": "Сумма: ", - "payment_id": "ID платежа: ", - "status": "Статус: ", - "offer_expires_in": "Предложение истекает через: ", - "trade_is_powered_by": "Сделка выполнена через ${provider}", - "copy_address": "Cкопировать адрес", - "exchange_result_confirm": "Нажимая подтвердить, вы отправите ${fetchingLabel} ${from} с вашего кошелька ${walletName} на адрес указанный ниже. Или вы можете отправить со своего внешнего кошелька на нижеуказанный адрес/QR-код.\n\nПожалуйста, нажмите подтвердить для продолжения, или вернитесь назад для изменения суммы.", - "exchange_result_description": "Вы должны отправить минимум ${fetchingLabel} ${from} на адрес, указанный на следующей странице. Если вы отправите сумму менее ${fetchingLabel} ${from}, то она может быть не конвертирована и не возвращена.", - "exchange_result_write_down_ID": "*Пожалуйста, скопируйте или запишите ID, указанный выше.", - "confirm": "Подтвердить", - "confirm_sending": "Подтвердить отправку", - "commit_transaction_amount_fee": "Подтвердить транзакцию \nСумма: ${amount}\nКомиссия: ${fee}", - "sending": "Отправка", - "transaction_sent": "Tранзакция отправлена!", - "expired": "Истекает", - "time": "${minutes}мин ${seconds}сек", - "send_xmr": "Отправить XMR", - "exchange_new_template": "Новый шаблон", - "faq": "FAQ", - "enter_your_pin": "Введите ваш PIN", - "loading_your_wallet": "Загрузка кошелька", - "new_wallet": "Новый кошелёк", - "wallet_name": "Имя кошелька", - "continue_text": "Продолжить", - "choose_wallet_currency": "Пожалуйста, выберите валюту кошелька:", - "node_new": "Новая нода", - "node_address": "Адрес ноды", - "node_port": "Порт ноды", - "login": "Логин", - "password": "Пароль", - "nodes": "Ноды", - "node_reset_settings_title": "Сбросить настройки", - "nodes_list_reset_to_default_message": "Вы уверены, что хотите сбросить настройки до значений по умолчанию?", - "change_current_node": "Вы уверены, что хотите изменить текущую ноду на ${node}?", - "change": "Изменить", - "remove_node": "Удалить ноду", - "remove_node_message": "Вы уверены, что хотите удалить текущую ноду?", - "remove": "Удалить", - "delete": "Удалить", - "add_new_node": "Добавить новую ноду", - "change_current_node_title": "Изменить текущую ноду", - "node_test": "Тест", - "node_connection_successful": "Подключение прошло успешно", - "node_connection_failed": "Подключение не удалось", - "new_node_testing": "Тестирование новой ноды", - "use": "Использовать ", - "digit_pin": "-значный PIN", - "share_address": "Поделиться адресом", - "receive_amount": "Сумма", - "subaddresses": "Субадреса", "addresses": "Адреса", - "scan_qr_code_to_get_address": "Отсканируйте QR-код для получения адреса", - "qr_fullscreen": "Нажмите, чтобы открыть полноэкранный QR-код", - "rename": "Переименовать", - "choose_account": "Выберите аккаунт", - "create_new_account": "Создать новый аккаунт", - "accounts_subaddresses": "Аккаунты и субадреса", - "restore_restore_wallet": "Восстановить кошелёк", - "restore_title_from_seed_keys": "Восстановить из мнемонической фразы/ключей", - "restore_description_from_seed_keys": "Вы можете восстановить кошелёк из мнемонической фразы/ключей, которые вы сохранили ранее", - "restore_next": "Продолжить", - "restore_title_from_backup": "Восстановить из back-up файла", - "restore_description_from_backup": "Вы можете восстановить Cake Wallet из вашего back-up файла", - "restore_seed_keys_restore": "Восстановить из мнемонической фразы/ключей", - "restore_title_from_seed": "Восстановить из мнемонической фразы", - "restore_description_from_seed": "Вы можете восстановить кошелёк используя 25-ти значную мнемоническую фразу", - "restore_title_from_keys": "Восстановить с помощью ключей", - "restore_description_from_keys": "Вы можете восстановить кошелёк с помощью приватных ключей", - "restore_wallet_name": "Имя кошелька", - "restore_address": "Адрес", - "restore_view_key_private": "Приватный ключ просмотра", - "restore_spend_key_private": "Приватный ключ траты", - "restore_recover": "Восстановить", - "restore_wallet_restore_description": "Описание восстановления кошелька", - "restore_new_seed": "Новая мнемоническая фраза", - "restore_active_seed": "Активная мнемоническая фраза", - "restore_bitcoin_description_from_seed": "Вы можете восстановить кошелёк используя 24-ти значную мнемоническую фразу", - "restore_bitcoin_description_from_keys": "Вы можете восстановить кошелёк с помощью WIF", - "restore_bitcoin_title_from_keys": "Восстановить с помощью WIF", - "restore_from_date_or_blockheight": "Пожалуйста, введите дату за несколько дней до создания этого кошелька. Или, если вы знаете высоту блока, введите ее значение", - "seed_reminder": "Пожалуйста, запишите мнемоническую фразу на случай потери или очистки телефона", - "seed_title": "Мнемоническая фраза", - "seed_share": "Поделиться мнемонической фразой", - "copy": "Скопировать", - "seed_language": "Язык семян", - "seed_choose": "Выберите язык мнемонической фразы", - "seed_language_next": "Продолжить", - "seed_language_english": "Английский", - "seed_language_chinese": "Китайский", - "seed_language_dutch": "Нидерландский", - "seed_language_german": "Немецкий", - "seed_language_japanese": "Японский", - "seed_language_portuguese": "Португальский", - "seed_language_russian": "Русский", - "seed_language_spanish": "Испанский", - "seed_language_french": "Французский", - "seed_language_italian": "итальянский", - "send_title": "Отправить", - "send_your_wallet": "Ваш кошелёк", - "send_address": "${cryptoCurrency} адрес", - "send_payment_id": "ID платежа (опционально)", + "advanced_settings": "Расширенные настройки", + "aggressive": "чрезмерно усердный", + "agree": "согласен", + "agree_and_continue": "Согласиться и продолжить", + "agree_to": "Создавая аккаунт, вы соглашаетесь с ", "all": "ВСЕ", - "send_error_minimum_value": "Mинимальная сумма 0.01", - "send_error_currency": "Валюта может содержать только цифры", - "send_estimated_fee": "Предполагаемая комиссия:", - "send_priority": "Комиссия установлена в зависимости от приоритета: ${transactionPriority}.\nПриоритет транзакции может быть изменён в настройках", - "send_creating_transaction": "Создать транзакцию", - "send_templates": "Шаблоны", - "send_new": "Новый", - "send_amount": "Сумма:", - "send_fee": "Комиссия:", - "send_name": "Имя", - "got_it": "Понял", - "send_sending": "Отправка...", - "send_success": "Ваш ${crypto} был успешно отправлен", - "settings_title": "Настройки", - "settings_nodes": "Ноды", - "settings_current_node": "Текущая нода", - "settings_wallets": "Кошельки", - "settings_display_balance": "Отображать баланс", - "settings_currency": "Валюта", - "settings_fee_priority": "Приоритет транзакции", - "settings_save_recipient_address": "Сохранять адрес получателя", - "settings_personal": "Персональные", - "settings_change_pin": "Изменить PIN", - "settings_change_language": "Изменить язык", - "settings_allow_biometrical_authentication": "Включить биометрическую аутентификацию", - "settings_dark_mode": "Тёмный режим", - "settings_transactions": "Транзакции", - "settings_trades": "Сделки", - "settings_display_on_dashboard_list": "Показывать в списке транзакций", - "settings_all": "ВСЕ", - "settings_only_trades": "Сделки", - "settings_only_transactions": "Транзакции", - "settings_none": "Ничего", - "settings_support": "Поддержка", - "settings_terms_and_conditions": "Условия и положения", - "pin_is_incorrect": "Некорректный PIN", - "setup_pin": "Настроить PIN", - "enter_your_pin_again": "Введите PIN еще раз", - "setup_successful": "PIN был успешно установлен!", - "wallet_keys": "Мнемоническая фраза/ключи кошелька", - "wallet_seed": "Мнемоническая фраза кошелька", - "private_key": "Приватный ключ", - "public_key": "Публичный ключ", - "view_key_private": "Приватный ключ просмотра", - "view_key_public": "Публичный ключ просмотра", - "spend_key_private": "Приватный ключ траты", - "spend_key_public": "Публичный ключ траты", - "copied_key_to_clipboard": "Скопировано ${key} в буфер обмена", - "new_subaddress_title": "Новый адрес", - "new_subaddress_label_name": "Имя", - "new_subaddress_create": "Создать", - "address_label": "Address label", - "subaddress_title": "Список субадресов", - "trade_details_title": "Детали сделок", - "trade_details_id": "ID", - "trade_details_state": "Статус", - "trade_details_fetching": "Получение", - "trade_details_provider": "Провайдер", - "trade_details_created_at": "Создано", - "trade_details_pair": "Пара", - "trade_details_copied": "${title} скопировано в буфер обмена", - "trade_history_title": "История сделок", - "transaction_details_title": "Детали транзакции", - "transaction_details_transaction_id": "ID транзакции", - "transaction_details_date": "Дата", - "transaction_details_height": "Высота", - "transaction_details_amount": "Сумма", - "transaction_details_fee": "Комиссия", - "transaction_details_copied": "${title} скопировано в буфер обмена", - "transaction_details_recipient_address": "Адреса получателей", - "wallet_list_title": "Monero Кошелёк", - "wallet_list_create_new_wallet": "Создать новый кошелёк", - "wallet_list_edit_wallet": "Изменить кошелек", - "wallet_list_wallet_name": "Имя кошелька", - "wallet_list_restore_wallet": "Восстановить кошелёк", - "wallet_list_load_wallet": "Загрузка кошелька", - "wallet_list_loading_wallet": "Загрузка ${wallet_name} кошелька", - "wallet_list_failed_to_load": "Ошибка при загрузке ${wallet_name} кошелька. ${error}", - "wallet_list_removing_wallet": "Удаление ${wallet_name} кошелька", - "wallet_list_failed_to_remove": "Ошибка при удалении ${wallet_name} кошелька. ${error}", - "widgets_address": "Адрес", - "widgets_restore_from_blockheight": "Восстановить на высоте блока", - "widgets_restore_from_date": "Восстановить с даты", - "widgets_or": "или", - "widgets_seed": "Мнемоническая фраза", - "router_no_route": "Не установлен маршрут для ${name}", - "error_text_account_name": "Имя аккаунта может содержать только буквы, цифры\nи должно быть от 1 до 15 символов в длину", - "error_text_contact_name": "Имя контакта не может содержать ` , ' \" символы\n и должно быть от 1 до 32 символов в длину", - "error_text_address": "Адрес кошелька должен соответствовать типу\nкриптовалюты", - "error_text_node_address": "Пожалуйста, введите iPv4 адрес", - "error_text_node_port": "Порт ноды может содержать только цифры от 0 до 65535", - "error_text_node_proxy_address": "Введите :<порт>, например 127.0.0.1:9050.", - "error_text_payment_id": "Идентификатор платежа может содержать от 16 до 64 символов в hex", - "error_text_xmr": "Значение XMR не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 12", - "error_text_fiat": "Значение суммы не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 2", - "error_text_subaddress_name": "Имя субадреса не может содержать ` , ' \" символы\nи должно быть от 1 до 20 символов в длину", - "error_text_amount": "Баланс может содержать только цифры", - "error_text_wallet_name": "Имя кошелька может содержать только буквы, цифры, _ - символы\nи должно быть от 1 до 33 символов в длину", - "error_text_keys": "Ключи кошелька могут содержать только 64 символа в hex", - "error_text_crypto_currency": "Количество цифр после запятой\nдолжно быть меньше или равно 12", - "error_text_minimal_limit": "Сделка для ${provider} не создана. Сумма меньше минимальной: ${min} ${currency}", - "error_text_maximum_limit": "Сделка для ${provider} не создана. Сумма больше максимальной: ${max} ${currency}", - "error_text_limits_loading_failed": "Сделка для ${provider} не создана. Ошибка загрузки лимитов", - "error_text_template": "Имя и адрес шаблона не может содержать ` , ' \" символы\nи должно быть от 1 до 106 символов в длину", + "all_trades": "Все сделки", + "all_transactions": "Все транзакции", + "alphabetical": "Алфавитный", + "already_have_account": "У вас уже есть аккаунт?", + "always": "всегда", + "amount": "Сумма: ", + "amount_is_estimate": "Полученная сумма является приблизительной", + "amount_is_guaranteed": "Полученная сумма гарантирована", + "and": "и", + "anonpay_description": "Создайте ${type}. Получатель может использовать ${method} с любой поддерживаемой криптовалютой, и вы получите средства на этот кошелек.", + "apk_update": "Обновление APK", + "approve": "Утвердить", + "arrive_in_this_address": "${currency} ${tag}придет на этот адрес", + "ascending": "Восходящий", + "ask_each_time": "Спросите каждый раз", "auth_store_ban_timeout": "ban_timeout", "auth_store_banned_for": "Заблокировано на ", "auth_store_banned_minutes": " минут", "auth_store_incorrect_password": "Некорректный PIN", - "wallet_store_monero_wallet": "Monero Кошелёк", - "wallet_restoration_store_incorrect_seed_length": "Неверная длина мнемонической фразы", - "full_balance": "Весь баланс", - "available_balance": "Доступный баланс", - "hidden_balance": "Скрытый баланс", - "sync_status_syncronizing": "СИНХРОНИЗАЦИЯ", - "sync_status_syncronized": "СИНХРОНИЗИРОВАН", - "sync_status_not_connected": "НЕ ПОДКЛЮЧЁН", - "sync_status_starting_sync": "НАЧАЛО СИНХРОНИЗАЦИИ", - "sync_status_failed_connect": "ОТКЛЮЧЕНО", - "sync_status_connecting": "ПОДКЛЮЧЕНИЕ", - "sync_status_connected": "ПОДКЛЮЧЕНО", - "sync_status_attempting_sync": "ПОПЫТКА СИНХРОНИЗАЦИИ", - "transaction_priority_slow": "Медленный", - "transaction_priority_regular": "Обычный", - "transaction_priority_medium": "Средний", - "transaction_priority_fast": "Быстрый", - "transaction_priority_fastest": "Самый быстрый", - "trade_for_not_created": "Сделка для ${title} не создана.", - "trade_not_created": "Сделка не создана", - "trade_id_not_found": "Сделка ${tradeId} ${title} не найдена.", - "trade_not_found": "Торговля не найдена.", - "trade_state_pending": "Ожидание", - "trade_state_confirming": "Подтверждение", - "trade_state_trading": "Совершение сделки", - "trade_state_traded": "Сделка завершена", - "trade_state_complete": "Выполнена", - "trade_state_to_be_created": "Будет создана", - "trade_state_unpaid": "Неоплаченная", - "trade_state_underpaid": "Недоплаченная", - "trade_state_paid_unconfirmed": "Оплата неподтверждена", - "trade_state_paid": "Оплаченная", - "trade_state_btc_sent": "BTC отправлены", - "trade_state_timeout": "Таймаут", - "trade_state_created": "Созданная", - "trade_state_finished": "Завершена", - "change_language": "Изменить язык", - "change_language_to": "Изменить язык на ${language}?", - "paste": "Вставить", - "restore_from_seed_placeholder": "Введите или вставьте мнемоническую фразу вашего кошелька", - "add_new_word": "Добавить новое слово", - "incorrect_seed": "Введённый текст некорректный.", - "biometric_auth_reason": "Отсканируйте свой отпечаток пальца для аутентификации", - "version": "Версия ${currentVersion}", - "extracted_address_content": "Вы будете отправлять средства\n${recipient_name}", - "card_address": "Адрес:", - "buy": "Купить", - "sell": "Продавать", - "placeholder_transactions": "Ваши транзакции будут отображаться здесь", - "placeholder_contacts": "Ваши контакты будут отображаться здесь", - "template": "Шаблон", - "confirm_delete_template": "Это действие удалит шаблон. Вы хотите продолжить?", - "confirm_delete_wallet": "Это действие удалит кошелек. Вы хотите продолжить?", - "change_wallet_alert_title": "Изменить текущий кошелек", - "change_wallet_alert_content": "Вы хотите изменить текущий кошелек на ${wallet_name}?", - "creating_new_wallet": "Создание нового кошелька", - "creating_new_wallet_error": "Ошибка: ${description}", - "seed_alert_title": "Внимание", - "seed_alert_content": "Мнемоническая фраза - единственный способ восстановить ваш кошелек. Вы записали ее?", - "seed_alert_back": "Назад", - "seed_alert_yes": "Да", - "exchange_sync_alert_content": "Подождите, пока ваш кошелек синхронизируется", - "pre_seed_title": "ВАЖНО", - "pre_seed_description": "На следующей странице вы увидите серию из ${words} слов. Это ваша уникальная и личная мнемоническая фраза, и это ЕДИНСТВЕННЫЙ способ восстановить свой кошелек в случае потери или неисправности. ВАМ необходимо записать ее и хранить в надежном месте вне приложения Cake Wallet.", - "pre_seed_button_text": "Понятно. Покажите мнемоническую фразу", - "xmr_to_error": "Ошибка XMR.TO", - "xmr_to_error_description": "Недопустимая сумма. Максимум 8 цифр после десятичной точки", - "provider_error": "${provider} ошибка", - "use_ssl": "Использовать SSL", - "trusted": "доверенный", - "color_theme": "Цветовая тема", - "light_theme": "Светлая", - "bright_theme": "Яркая", - "dark_theme": "Темная", - "enter_your_note": "Введите примечание…", - "note_optional": "Примечание (необязательно)", - "note_tap_to_change": "Примечание (нажмите для изменения)", - "view_in_block_explorer": "View in Block Explorer", - "view_transaction_on": "View Transaction on ", - "transaction_key": "Ключ транзакции", - "confirmations": "Подтверждения", - "recipient_address": "Адрес получателя", - "extra_id": "Дополнительный ID:", - "destination_tag": "Целевой тег:", - "memo": "Памятка:", - "backup": "Резервная копия", - "change_password": "Изменить пароль", - "backup_password": "Пароль резервной копии", - "write_down_backup_password": "Запишите пароль резервной копии, который используется для импорта файлов резервных копий.", - "export_backup": "Экспорт резервной копии", - "save_backup_password": "Убедитесь, что вы сохранили пароль резервной копии. Без него вы не сможете импортировать файлы резервных копий.", - "backup_file": "Файл резервной копии", - "edit_backup_password": "Изменить пароль резервной копии", - "save_backup_password_alert": "Сохранить пароль резервной копии", - "change_backup_password_alert": "Ваши предыдущие файлы резервных копий будут недоступны для импорта с новым паролем резервной копии. Новый пароль резервной копии будет использоваться только для новых файлов резервных копий. Вы уверены, что хотите изменить пароль резервной копии?", - "enter_backup_password": "Введите пароль резервной копии", - "select_backup_file": "Выберите файл резервной копии", - "import": "Импортировать", - "please_select_backup_file": "Выберите файл резервной копии и введите пароль резервной копии.", - "fixed_rate": "Фиксированная ставка", - "fixed_rate_alert": "Вы сможете ввести сумму получения тогда, когда будет установлен режим фиксированной ставки. Вы хотите перейти в режим фиксированной ставки?", - "xlm_extra_info": "Не забудьте указать Memo ID (памятка) при отправке транзакции XLM для обмена", - "xrp_extra_info": "Не забудьте указать целевой тег при отправке транзакции XRP для обмена", - "exchange_incorrect_current_wallet_for_xmr": "Если вы хотите обменять XMR со своего баланса Monero в Cake Wallet, сначала переключитесь на свой кошелек Monero.", - "confirmed": "Подтвержденный баланс", - "unconfirmed": "Неподтвержденный баланс", - "displayable": "Отображаемый", - "submit_request": "отправить запрос", - "buy_alert_content": "В настоящее время мы поддерживаем только покупку биткойнов, Ethereum, Litecoin и Monero. Пожалуйста, создайте или переключитесь на свой кошелек Bitcoin, Ethereum, Litecoin или Monero.", - "sell_alert_content": "В настоящее время мы поддерживаем только продажу биткойнов, эфириума и лайткойна. Пожалуйста, создайте или переключитесь на свой кошелек Bitcoin, Ethereum или Litecoin.", - "outdated_electrum_wallet_description": "Новые биткойн-кошельки, созданные в Cake, теперь содержат мнемоническую фразу из 24 слов. Вы обязательно должны создать новый биткойн-кошелек и перевести все свои средства в новый кошелек из 24 слов, а также прекратить использование кошельков с мнемонической фразой из 12 слов. Пожалуйста, сделайте это немедленно, чтобы обезопасить свои средства.", - "understand": "Понятно", - "apk_update": "Обновление APK", - "buy_bitcoin": "Купить Bitcoin", - "buy_with": "Купить с помощью", - "moonpay_alert_text": "Сумма должна быть больше или равна ${minAmount} ${fiatCurrency}", - "outdated_electrum_wallet_receive_warning": "Если этот кошелек имеет мнемоническую фразу из 12 слов и был создан в Cake, НЕ переводите биткойны на этот кошелек. Любые BTC, переведенные на этот кошелек, могут быть потеряны. Создайте новый кошелек с мнемоническои фразы из 24 слов (коснитесь меню в правом верхнем углу, выберите «Кошельки», выберите «Создать новый кошелек», затем выберите «Bitcoin») и НЕМЕДЛЕННО переведите туда свои BTC. Новые (24 слова) кошельки BTC от Cake безопасны", - "do_not_show_me": "Не показывай мне это больше", - "unspent_coins_title": "Неизрасходованные монеты", - "unspent_coins_details_title": "Сведения о неизрасходованных монетах", - "freeze": "Заморозить", - "frozen": "Заморожено", - "coin_control": "Контроль монет (необязательно)", - "address_detected": "Обнаружен адрес", - "address_from_domain": "Этот адрес от ${domain} на Unstoppable Domains", - "add_receiver": "Добавить получателя (необязательно)", - "manage_yats": "Управлять Yat", - "yat_alert_title": "С Yat проще отправлять и получать криптовалюту", - "yat_alert_content": "Пользователи Cake Wallet теперь могут отправлять и получать криптовалюту при помощи уникального имени пользователя на основе эмодзи.", - "get_your_yat": "Получить свой Yat", - "connect_an_existing_yat": "Подключить существующий Yat", - "yat_address": "Yat адрес", - "yat": "Yat", - "connect_yats": "Подключить Yats", - "address_from_yat": "Этот адрес от ${emoji} на Yat", - "yat_error": "Ошибка Yat", - "yat_error_content": "Нет адресов, связанных с этим Yat. Попробуйте другой Yat", - "choose_address": "\n\nПожалуйста, выберите адрес:", - "yat_popup_title": "Адрес вашего кошелька может быть связан с эмодзи", - "yat_popup_content": "Теперь вы можете отправлять и получать криптовалюту в Cake Wallet с помощью Yat - короткого имени пользователя на основе эмодзи. Управляйте Yat в любое время при помощи экрана настроек", - "second_intro_title": "Один адрес эмодзи для управления остальными адресами", - "second_intro_content": "Ваш Yat - это единственный уникальный адрес эмодзи, который заменяет длинные шестнадцатеричные адреса для всех ваших валют.", - "third_intro_title": "Yat хорошо взаимодействует с другими", - "third_intro_content": "Yat находятся за пределами Cake Wallet. Любой адрес кошелька на земле можно заменить на Yat!", - "learn_more": "Узнать больше", - "search": "Поиск", - "search_language": "Язык поиска", - "search_currency": "Валюта поиска", - "new_template": "Новый шаблон", - "electrum_address_disclaimer": "Мы генерируем новые адреса каждый раз, когда вы их используете, но предыдущие адреса продолжают работать.", - "wallet_name_exists": "Кошелек с таким именем уже существует", - "market_place": "Торговая площадка", - "cake_pay_title": "Подарочные карты Cake Pay", - "cake_pay_subtitle": "Покупайте подарочные карты со скидкой (только для США)", - "cake_pay_web_cards_title": "Веб-карты Cake Pay", - "cake_pay_web_cards_subtitle": "Покупайте карты предоплаты и подарочные карты по всему миру", - "about_cake_pay": "Cake Pay позволяет вам легко покупать подарочные карты с виртуальными активами, которые можно мгновенно потратить в более чем 150 000 продавцов в Соединенных Штатах.", - "cake_pay_account_note": "Зарегистрируйтесь, указав только адрес электронной почты, чтобы просматривать и покупать карты. Некоторые даже доступны со скидкой!", - "already_have_account": "У вас уже есть аккаунт?", - "create_account": "Создать аккаунт", - "privacy_policy": "Политика конфиденциальности", - "welcome_to_cakepay": "Добро пожаловать в Cake Pay!", - "sign_up": "Зарегистрироваться", - "forgot_password": "Забыли пароль", - "reset_password": "Сбросить пароль", - "gift_cards": "Подарочные карты", - "setup_your_debit_card": "Настройте свою дебетовую карту", - "no_id_required": "Идентификатор не требуется. Пополняйте и тратьте где угодно", - "how_to_use_card": "Как использовать эту карту", - "purchase_gift_card": "Купить подарочную карту", - "verification": "Проверка", - "fill_code": "Пожалуйста, введите код подтверждения, отправленный на вашу электронную почту", - "didnt_get_code": "Не получить код?", - "resend_code": "Пожалуйста, отправьте еще раз", - "debit_card": "Дебетовая карта", - "cakepay_prepaid_card": "Предоплаченная дебетовая карта CakePay", - "no_id_needed": "Идентификатор не нужен!", - "frequently_asked_questions": "Часто задаваемые вопросы", - "debit_card_terms": "Хранение и использование номера вашей платежной карты (и учетных данных, соответствующих номеру вашей платежной карты) в этом цифровом кошельке регулируются положениями и условиями применимого соглашения держателя карты с эмитентом платежной карты, действующим с время от времени.", - "please_reference_document": "Пожалуйста, обратитесь к документам ниже для получения дополнительной информации.", - "cardholder_agreement": "Соглашение с держателем карты", - "e_sign_consent": "Согласие электронной подписи", - "agree_and_continue": "Согласиться и продолжить", - "email_address": "Адрес электронной почты", - "agree_to": "Создавая аккаунт, вы соглашаетесь с ", - "and": "и", - "enter_code": "Введите код", - "congratulations": "Поздравляем!", - "you_now_have_debit_card": "Теперь у вас есть дебетовая карта", - "min_amount": "Минимум: ${value}", - "max_amount": "Макс.: ${value}", - "enter_amount": "Введите сумму", - "billing_address_info": "Если вас попросят указать платежный адрес, укажите адрес доставки", - "order_physical_card": "Заказать физическую карту", - "add_value": "Добавить значение", - "activate": "Активировать", - "get_a": "Получить ", - "digital_and_physical_card": "цифровая и физическая предоплаченная дебетовая карта", - "get_card_note": " которую вы можете пополнить цифровой валютой. Дополнительная информация не требуется!", - "signup_for_card_accept_terms": "Подпишитесь на карту и примите условия.", - "add_fund_to_card": "Добавить предоплаченные средства на карты (до ${value})", - "use_card_info_two": "Средства конвертируются в доллары США, когда они хранятся на предоплаченном счете, а не в цифровых валютах.", - "use_card_info_three": "Используйте цифровую карту онлайн или с помощью бесконтактных способов оплаты.", - "optionly_order_card": "При желании закажите физическую карту.", - "hide_details": "Скрыть детали", - "show_details": "Показать детали", - "upto": "до ${value}", - "discount": "Сэкономьте ${value}%", - "gift_card_amount": "Сумма подарочной карты", - "bill_amount": "Сумма счета", - "you_pay": "Вы платите", - "tip": "Совет:", - "custom": "обычай", - "by_cake_pay": "от Cake Pay", - "expires": "Истекает", - "mm": "ММ", - "yy": "ГГ", - "online": "Онлайн", - "offline": "Не в сети", - "gift_card_number": "Номер подарочной карты", - "pin_number": "ПИН-код", - "total_saving": "Общая экономия", - "last_30_days": "Последние 30 дней", - "avg_savings": "Средняя экономия", - "view_all": "Просмотреть все", - "active_cards": "Активные карты", - "delete_account": "Удалить аккаунт", - "cards": "Карты", - "active": "Активный", - "redeemed": "искуплен", - "gift_card_balance_note": "Здесь будут отображаться подарочные карты с остатком на балансе", - "gift_card_redeemed_note": "Здесь будут отображаться использованные вами подарочные карты", - "logout": "Выйти", - "add_tip": "Добавить подсказку", - "percentageOf": "из ${amount}", - "is_percentage": "есть", - "search_category": "Категория поиска", - "mark_as_redeemed": "Отметить как погашенный", - "more_options": "Дополнительные параметры", - "awaiting_payment_confirmation": "Ожидается подтверждения платежа", - "transaction_sent_notice": "Если экран не отображается через 1 минуту, проверьте обозреватель блоков и свою электронную почту.", - "agree": "согласен", - "in_store": "В магазине", - "generating_gift_card": "Создание подарочной карты", - "payment_was_received": "Ваш платеж получен.", - "proceed_after_one_minute": "Если через 1 минуту экран не отображается, проверьте свою электронную почту.", - "order_id": "Идентификатор заказа", - "gift_card_is_generated": "Подарочная карта сгенерирована", - "open_gift_card": "Открыть подарочную карту", - "contact_support": "Связаться со службой поддержки", - "gift_cards_unavailable": "В настоящее время подарочные карты можно приобрести только через Monero, Bitcoin и Litecoin.", - "background_sync_mode": "Режим фоновой синхронизации", - "sync_all_wallets": "Синхронизировать все кошельки", - "introducing_cake_pay": "Представляем Cake Pay!", - "cake_pay_learn_more": "Мгновенно покупайте и используйте подарочные карты в приложении!\nПроведите по экрану слева направо, чтобы узнать больше.", + "authenticated": "Аутентифицировано", + "authentication": "Аутентификация", + "auto_generate_subaddresses": "Авто генерируйте Subaddresses", "automatic": "автоматический", - "fixed_pair_not_supported": "Эта фиксированная пара не поддерживается выбранными биржами.", - "variable_pair_not_supported": "Эта пара переменных не поддерживается выбранными биржами.", - "none_of_selected_providers_can_exchange": "Ни один из выбранных провайдеров не может совершить этот обмен", - "choose_one": "Выбери один", - "choose_from_available_options": "Выберите из доступных вариантов:", - "custom_redeem_amount": "Пользовательская сумма погашения", - "add_custom_redemption": "Добавить пользовательское погашение", - "remaining": "осталось", - "delete_wallet": "Удалить кошелек", - "delete_wallet_confirm_message": "Вы уверены, что хотите удалить кошелек ${wallet_name}?", - "low_fee": "Низкая комиссия", - "low_fee_alert": "В настоящее время вы используете низкий приоритет платы за сеть. Это может привести к длительному ожиданию, изменению ставок или отмене сделок. Мы рекомендуем установить более высокую плату для лучшего опыта.", - "ignor": "Игнорировать", - "use_suggested": "Использовать предложенный", - "do_not_share_warning_text": "Не сообщайте их никому, включая техподдержку.\n\nВаши средства могут и будут украдены!", - "help": "помощь", - "all_transactions": "Все транзакции", - "all_trades": "Все сделки", - "connection_sync": "Подключение и синхронизация", - "security_and_backup": "Безопасность и резервное копирование", - "create_backup": "Создать резервную копию", - "privacy_settings": "Настройки конфиденциальности", - "privacy": "Конфиденциальность", - "display_settings": "Настройки отображения", - "other_settings": "Другие настройки", - "require_pin_after": "Требовать ПИН после", - "always": "всегда", - "minutes_to_pin_code": "${minute} минут", - "disable_exchange": "Отключить обмен", - "advanced_settings": "Расширенные настройки", - "settings_can_be_changed_later": "Эти настройки можно изменить позже в настройках приложения.", - "add_custom_node": "Добавить новый пользовательский узел", - "disable_fiat": "Отключить фиат", - "fiat_api": "Фиат API", - "disabled": "Отключено", - "enabled": "Включено", - "tor_only": "Только Tor", - "unmatched_currencies": "Валюта вашего текущего кошелька не соответствует валюте отсканированного QR-кода.", - "orbot_running_alert": "Перед подключением к этому узлу убедитесь, что Orbot запущен.", - "contact_list_contacts": "Контакты", - "contact_list_wallets": "Мои кошельки", - "bitcoin_payments_require_1_confirmation": "Биткойн-платежи требуют 1 подтверждения, что может занять 20 минут или дольше. Спасибо тебе за твое терпение! Вы получите электронное письмо, когда платеж будет подтвержден.", - "send_to_this_address": "Отправить ${currency} ${tag}на этот адрес", - "arrive_in_this_address": "${currency} ${tag}придет на этот адрес", - "do_not_send": "Не отправлять", - "error_dialog_content": "Ой, у нас какая-то ошибка.\n\nПожалуйста, отправьте отчет о сбое в нашу службу поддержки, чтобы сделать приложение лучше.", - "scan_qr_code": "Сканировать QR-код", - "cold_or_recover_wallet": "Добавьте холодный кошелек или восстановите бумажный кошелек", - "please_wait": "Пожалуйста, подождите", - "sweeping_wallet": "Подметание кошелька", - "sweeping_wallet_alert": "Это не должно занять много времени. НЕ ПОКИДАЙТЕ ЭТОТ ЭКРАН, ИНАЧЕ ВЫЧИСЛЕННЫЕ СРЕДСТВА МОГУТ БЫТЬ ПОТЕРЯНЫ", - "decimal_places_error": "Слишком много десятичных знаков", - "edit_node": "Редактировать узел", - "invoice_details": "Детали счета", - "donation_link_details": "Информация о ссылке для пожертвований", - "anonpay_description": "Создайте ${type}. Получатель может использовать ${method} с любой поддерживаемой криптовалютой, и вы получите средства на этот кошелек.", - "create_invoice": "Создать счет", - "create_donation_link": "Создать ссылку для пожертвований", - "optional_email_hint": "Необязательное электронное письмо с уведомлением получателя платежа", - "optional_description": "Дополнительное описание", - "optional_name": "Необязательное имя получателя", - "clearnet_link": "Клирнет ссылка", - "onion_link": "Луковая ссылка", - "settings": "Настройки", - "sell_monero_com_alert_content": "Продажа Monero пока не поддерживается", - "error_text_input_below_minimum_limit": "Сумма меньше минимальной", - "error_text_input_above_maximum_limit": "Сумма больше максимальной", - "show_market_place": "Показать торговую площадку", - "prevent_screenshots": "Предотвратить скриншоты и запись экрана", - "profile": "Профиль", - "close": "Закрывать", - "modify_2fa": "Изменить торт 2FA", - "disable_cake_2fa": "Отключить торт 2FA", - "question_to_disable_2fa": "Вы уверены, что хотите отключить Cake 2FA? Код 2FA больше не потребуется для доступа к кошельку и некоторым функциям.", - "disable": "Запрещать", - "setup_2fa": "Настройка торта 2FA", - "verify_with_2fa": "Подтвердить с помощью Cake 2FA", - "totp_code": "TOTP-код", - "please_fill_totp": "Пожалуйста, введите 8-значный код на другом устройстве", - "totp_2fa_success": "Успех! Для этого кошелька включена двухфакторная аутентификация Cake. Не забудьте сохранить мнемоническое семя на случай, если вы потеряете доступ к кошельку.", - "totp_verification_success": "Проверка прошла успешно!", - "totp_2fa_failure": "Неверный код. Пожалуйста, попробуйте другой код или создайте новый секретный ключ. Используйте совместимое приложение 2FA, которое поддерживает 8-значные коды и SHA512.", - "enter_totp_code": "Пожалуйста, введите TOTP-код.", - "add_secret_code": "Или добавьте этот секретный код в приложение для аутентификации.", - "totp_secret_code": "Секретный код ТОТП", - "setup_2fa_text": "Cake 2FA работает с использованием TOTP в качестве второго фактора аутентификации.\n\nTOTP Cake 2FA требует SHA-512 и поддержки 8 цифр; это обеспечивает повышенную безопасность. Дополнительную информацию и поддерживаемые приложения можно найти в руководстве.", - "setup_totp_recommended": "Настройка ТОТП", - "disable_buy": "Отключить действие покупки", - "disable_sell": "Отключить действие продажи", - "cake_2fa_preset": "Торт 2FA Preset", - "narrow": "Узкий", - "normal": "Нормальный", - "aggressive": "чрезмерно усердный", - "require_for_assessing_wallet": "Требовать для доступа к кошельку", - "require_for_sends_to_non_contacts": "Требовать для отправки не контактам", - "require_for_sends_to_contacts": "Требовать для отправки контактам", - "require_for_sends_to_internal_wallets": "Требовать отправки на внутренние кошельки", - "require_for_exchanges_to_internal_wallets": "Требовать для обмена на внутренние кошельки", - "require_for_adding_contacts": "Требовать добавления контактов", - "require_for_creating_new_wallets": "Требовать для создания новых кошельков", - "require_for_all_security_and_backup_settings": "Требовать все настройки безопасности и резервного копирования", + "available_balance": "Доступный баланс", "available_balance_description": "Доступный баланс - это средства, которые вы можете использовать для покупки или продажи криптовалюты.", - "syncing_wallet_alert_title": "Ваш кошелек синхронизируется", - "syncing_wallet_alert_content": "Ваш баланс и список транзакций могут быть неполными, пока вверху не будет написано «СИНХРОНИЗИРОВАНО». Щелкните/коснитесь, чтобы узнать больше.", - "home_screen_settings": "Настройки главного экрана", - "sort_by": "Сортировать по", - "search_add_token": "Поиск / Добавить токен", - "edit_token": "Изменить токен", - "warning": "Предупреждение", - "add_token_warning": "Не редактируйте и не добавляйте токены по указанию мошенников.\nВсегда подтверждайте адреса токенов из авторитетных источников!", - "add_token_disclaimer_check": "Я подтвердил адрес контракта токена и информацию, используя авторитетный источник. Добавление вредоносной или неверной информации может привести к потере средств.", - "token_contract_address": "Адрес контракта токена", - "token_name": "Имя токена, например: Tether", - "token_symbol": "Символ токена, например: USDT", - "token_decimal": "Десятичный токен", - "field_required": "Это поле обязательно к заполнению", - "pin_at_top": "закрепить ${token} вверху", - "invalid_input": "Неверный Ввод", - "fiat_balance": "Фиатный баланс", - "gross_balance": "Валовой баланс", - "alphabetical": "Алфавитный", - "generate_name": "Создать имя", + "avg_savings": "Средняя экономия", + "awaitDAppProcessing": "Пожалуйста, подождите, пока dApp завершит обработку.", + "awaiting_payment_confirmation": "Ожидается подтверждения платежа", + "background_sync_mode": "Режим фоновой синхронизации", + "backup": "Резервная копия", + "backup_file": "Файл резервной копии", + "backup_password": "Пароль резервной копии", "balance_page": "Страница баланса", - "share": "Делиться", - "slidable": "Скользящий", - "monero_dark_theme": "Темная тема Monero", + "bill_amount": "Сумма счета", + "billing_address_info": "Если вас попросят указать платежный адрес, укажите адрес доставки", + "biometric_auth_reason": "Отсканируйте свой отпечаток пальца для аутентификации", "bitcoin_dark_theme": "Биткойн Темная тема", "bitcoin_light_theme": "Легкая биткойн-тема", - "high_contrast_theme": "Высококонтрастная тема", - "matrix_green_dark_theme": "Матрица Зеленая Темная Тема", - "monero_light_theme": "Светлая тема Monero", - "manage_nodes": "Управление узлами", - "etherscan_history": "История Эфириума", - "template_name": "Имя Шаблона", + "bitcoin_payments_require_1_confirmation": "Биткойн-платежи требуют 1 подтверждения, что может занять 20 минут или дольше. Спасибо тебе за твое терпение! Вы получите электронное письмо, когда платеж будет подтвержден.", + "Blocks_remaining": "${status} Осталось блоков", + "bright_theme": "Яркая", + "buy": "Купить", + "buy_alert_content": "В настоящее время мы поддерживаем только покупку биткойнов, Ethereum, Litecoin и Monero. Пожалуйста, создайте или переключитесь на свой кошелек Bitcoin, Ethereum, Litecoin или Monero.", + "buy_bitcoin": "Купить Bitcoin", + "buy_provider_unavailable": "Поставщик в настоящее время недоступен.", + "buy_with": "Купить с помощью", + "by_cake_pay": "от Cake Pay", + "cake_2fa_preset": "Торт 2FA Preset", + "cake_pay_account_note": "Зарегистрируйтесь, указав только адрес электронной почты, чтобы просматривать и покупать карты. Некоторые даже доступны со скидкой!", + "cake_pay_learn_more": "Мгновенно покупайте и используйте подарочные карты в приложении!\nПроведите по экрану слева направо, чтобы узнать больше.", + "cake_pay_subtitle": "Покупайте подарочные карты со скидкой (только для США)", + "cake_pay_title": "Подарочные карты Cake Pay", + "cake_pay_web_cards_subtitle": "Покупайте карты предоплаты и подарочные карты по всему миру", + "cake_pay_web_cards_title": "Веб-карты Cake Pay", + "cake_wallet": "Cake Wallet", + "cakepay_prepaid_card": "Предоплаченная дебетовая карта CakePay", + "camera_consent": "Ваша камера будет использоваться для захвата изображения в целях идентификации ${provider}. Пожалуйста, ознакомьтесь с их Политикой конфиденциальности для получения подробной информации.", + "camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.", + "cancel": "Отменить", + "card_address": "Адрес:", + "cardholder_agreement": "Соглашение с держателем карты", + "cards": "Карты", + "chains": "Цепи", + "change": "Изменить", + "change_backup_password_alert": "Ваши предыдущие файлы резервных копий будут недоступны для импорта с новым паролем резервной копии. Новый пароль резервной копии будет использоваться только для новых файлов резервных копий. Вы уверены, что хотите изменить пароль резервной копии?", + "change_currency": "Изменить валюту", + "change_current_node": "Вы уверены, что хотите изменить текущую ноду на ${node}?", + "change_current_node_title": "Изменить текущую ноду", + "change_exchange_provider": "Изменить провайдера обмена", + "change_language": "Изменить язык", + "change_language_to": "Изменить язык на ${language}?", + "change_password": "Изменить пароль", "change_rep": "Изменить представителя", "change_rep_message": "Вы уверены, что хотите сменить представителя?", - "unsupported_asset": "Мы не поддерживаем это действие для этого объекта. Пожалуйста, создайте или переключитесь на кошелек поддерживаемого типа активов.", - "manage_pow_nodes": "Управление узлами PoW", - "support_title_live_chat": "Живая поддержка", - "support_description_live_chat": "Бесплатно и быстро! Обученные представители поддержки доступны для оказания помощи", - "support_title_guides": "Корт -гиды", - "support_description_guides": "Документация и поддержка общих вопросов", - "support_title_other_links": "Другие ссылки на поддержку", - "support_description_other_links": "Присоединяйтесь к нашим сообществам или охватите нас наших партнеров с помощью других методов", + "change_rep_successful": "Успешно изменил представитель", + "change_wallet_alert_content": "Вы хотите изменить текущий кошелек на ${wallet_name}?", + "change_wallet_alert_title": "Изменить текущий кошелек", + "choose_account": "Выберите аккаунт", + "choose_address": "\n\nПожалуйста, выберите адрес:", "choose_derivation": "Выберите вывод кошелька", - "new_first_wallet_text": "Легко сохранить свою криптовалюту в безопасности", - "select_destination": "Пожалуйста, выберите место для файла резервной копии.", - "auto_generate_subaddresses": "Авто генерируйте Subaddresses", - "save_to_downloads": "Сохранить в загрузках", - "select_buy_provider_notice": "Выберите поставщика покупки выше. Вы можете пропустить этот экран, установив поставщика покупки по умолчанию в настройках приложения.", - "onramper_option_description": "Быстро купите крипто со многими способами оплаты. Доступно в большинстве стран. Спреды и сборы различаются.", + "choose_from_available_options": "Выберите из доступных вариантов:", + "choose_one": "Выбери один", + "choose_relay": "Пожалуйста, выберите реле для использования", + "choose_wallet_currency": "Пожалуйста, выберите валюту кошелька:", + "clear": "Очистить", + "clearnet_link": "Клирнет ссылка", + "close": "Закрывать", + "coin_control": "Контроль монет (необязательно)", + "cold_or_recover_wallet": "Добавьте холодный кошелек или восстановите бумажный кошелек", + "color_theme": "Цветовая тема", + "commit_transaction_amount_fee": "Подтвердить транзакцию \nСумма: ${amount}\nКомиссия: ${fee}", + "confirm": "Подтвердить", + "confirm_delete_template": "Это действие удалит шаблон. Вы хотите продолжить?", + "confirm_delete_wallet": "Это действие удалит кошелек. Вы хотите продолжить?", + "confirm_sending": "Подтвердить отправку", + "confirmations": "Подтверждения", + "confirmed": "Подтвержденный баланс", + "confirmed_tx": "Подтвержденный", + "congratulations": "Поздравляем!", + "connect_an_existing_yat": "Подключить существующий Yat", + "connect_yats": "Подключить Yats", + "connection_sync": "Подключение и синхронизация", + "connectWalletPrompt": "Подключите свой кошелек к WalletConnect для совершения транзакций.", + "contact": "Контакт", + "contact_list_contacts": "Контакты", + "contact_list_wallets": "Мои кошельки", + "contact_name": "Имя контакта", + "contact_support": "Связаться со службой поддержки", + "continue_text": "Продолжить", + "contractName": "Название контракта", + "contractSymbol": "Символ контракта", + "copied_key_to_clipboard": "Скопировано ${key} в буфер обмена", + "copied_to_clipboard": "Скопировано в буфер обмена", + "copy": "Скопировать", + "copy_address": "Cкопировать адрес", + "copy_id": "Скопировать ID", + "copyWalletConnectLink": "Скопируйте ссылку WalletConnect из dApp и вставьте сюда.", + "create_account": "Создать аккаунт", + "create_backup": "Создать резервную копию", + "create_donation_link": "Создать ссылку для пожертвований", + "create_invoice": "Создать счет", + "create_new": "Создать новый кошелёк", + "create_new_account": "Создать новый аккаунт", + "creating_new_wallet": "Создание нового кошелька", + "creating_new_wallet_error": "Ошибка: ${description}", + "creation_date": "Дата создания", + "custom": "обычай", + "custom_drag": "Пользователь (удерживайте и перетаскивайте)", + "custom_redeem_amount": "Пользовательская сумма погашения", + "dark_theme": "Темная", + "debit_card": "Дебетовая карта", + "debit_card_terms": "Хранение и использование номера вашей платежной карты (и учетных данных, соответствующих номеру вашей платежной карты) в этом цифровом кошельке регулируются положениями и условиями применимого соглашения держателя карты с эмитентом платежной карты, действующим с время от времени.", + "decimal_places_error": "Слишком много десятичных знаков", "default_buy_provider": "По умолчанию поставщик покупки", - "ask_each_time": "Спросите каждый раз", - "buy_provider_unavailable": "Поставщик в настоящее время недоступен.", - "signTransaction": "Подписать транзакцию", + "default_sell_provider": "Поставщик продаж по умолчанию", + "delete": "Удалить", + "delete_account": "Удалить аккаунт", + "delete_wallet": "Удалить кошелек", + "delete_wallet_confirm_message": "Вы уверены, что хотите удалить кошелек ${wallet_name}?", + "deleteConnectionConfirmationPrompt": "Вы уверены, что хотите удалить подключение к", + "descending": "Нисходящий", + "description": "Описание", + "destination_tag": "Целевой тег:", + "dfx_option_description": "Покупайте криптовалюту за EUR и CHF. До 990€ без дополнительного KYC. Для розничных и корпоративных клиентов в Европе", + "didnt_get_code": "Не получить код?", + "digit_pin": "-значный PIN", + "digital_and_physical_card": "цифровая и физическая предоплаченная дебетовая карта", + "disable": "Запрещать", + "disable_buy": "Отключить действие покупки", + "disable_cake_2fa": "Отключить торт 2FA", + "disable_exchange": "Отключить обмен", + "disable_fiat": "Отключить фиат", + "disable_sell": "Отключить действие продажи", + "disabled": "Отключено", + "discount": "Сэкономьте ${value}%", + "display_settings": "Настройки отображения", + "displayable": "Отображаемый", + "do_not_have_enough_gas_asset": "У вас недостаточно ${currency} для совершения транзакции при текущих условиях сети блокчейн. Вам нужно больше ${currency} для оплаты комиссий за сеть блокчейна, даже если вы отправляете другой актив.", + "do_not_send": "Не отправлять", + "do_not_share_warning_text": "Не сообщайте их никому, включая техподдержку.\n\nВаши средства могут и будут украдены!", + "do_not_show_me": "Не показывай мне это больше", + "domain_looks_up": "Поиск доменов", + "donation_link_details": "Информация о ссылке для пожертвований", + "e_sign_consent": "Согласие электронной подписи", + "edit": "Редактировать", + "edit_backup_password": "Изменить пароль резервной копии", + "edit_node": "Редактировать узел", + "edit_token": "Изменить токен", + "electrum_address_disclaimer": "Мы генерируем новые адреса каждый раз, когда вы их используете, но предыдущие адреса продолжают работать.", + "email_address": "Адрес электронной почты", + "enabled": "Включено", + "enter_amount": "Введите сумму", + "enter_backup_password": "Введите пароль резервной копии", + "enter_code": "Введите код", + "enter_seed_phrase": "Введите свою семенную фразу", + "enter_totp_code": "Пожалуйста, введите TOTP-код.", + "enter_your_note": "Введите примечание…", + "enter_your_pin": "Введите ваш PIN", + "enter_your_pin_again": "Введите PIN еще раз", + "enterTokenID": "Введите идентификатор токена", + "enterWalletConnectURI": "Введите URI WalletConnect", + "error": "Ошибка", + "error_dialog_content": "Ой, у нас какая-то ошибка.\n\nПожалуйста, отправьте отчет о сбое в нашу службу поддержки, чтобы сделать приложение лучше.", + "error_text_account_name": "Имя аккаунта может содержать только буквы, цифры\nи должно быть от 1 до 15 символов в длину", + "error_text_address": "Адрес кошелька должен соответствовать типу\nкриптовалюты", + "error_text_amount": "Баланс может содержать только цифры", + "error_text_contact_name": "Имя контакта не может содержать ` , ' \" символы\n и должно быть от 1 до 32 символов в длину", + "error_text_crypto_currency": "Количество цифр после запятой\nдолжно быть меньше или равно 12", + "error_text_fiat": "Значение суммы не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 2", + "error_text_input_above_maximum_limit": "Сумма больше максимальной", + "error_text_input_below_minimum_limit": "Сумма меньше минимальной", + "error_text_keys": "Ключи кошелька могут содержать только 64 символа в hex", + "error_text_limits_loading_failed": "Сделка для ${provider} не создана. Ошибка загрузки лимитов", + "error_text_maximum_limit": "Сделка для ${provider} не создана. Сумма больше максимальной: ${max} ${currency}", + "error_text_minimal_limit": "Сделка для ${provider} не создана. Сумма меньше минимальной: ${min} ${currency}", + "error_text_node_address": "Пожалуйста, введите iPv4 адрес", + "error_text_node_port": "Порт ноды может содержать только цифры от 0 до 65535", + "error_text_node_proxy_address": "Введите :<порт>, например 127.0.0.1:9050.", + "error_text_payment_id": "Идентификатор платежа может содержать от 16 до 64 символов в hex", + "error_text_subaddress_name": "Имя субадреса не может содержать ` , ' \" символы\nи должно быть от 1 до 20 символов в длину", + "error_text_template": "Имя и адрес шаблона не может содержать ` , ' \" символы\nи должно быть от 1 до 106 символов в длину", + "error_text_wallet_name": "Имя кошелька может содержать только буквы, цифры, _ - символы\nи должно быть от 1 до 33 символов в длину", + "error_text_xmr": "Значение XMR не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 12", "errorGettingCredentials": "Не удалось: ошибка при получении учетных данных.", "errorSigningTransaction": "Произошла ошибка при подписании транзакции", - "pairingInvalidEvent": "Недействительное событие сопряжения", - "chains": "Цепи", - "methods": "Методы", - "events": "События", - "reject": "Отклонять", - "approve": "Утвердить", - "expiresOn": "Годен до", - "walletConnect": "КошелекПодключиться", - "nullURIError": "URI имеет значение null", - "connectWalletPrompt": "Подключите свой кошелек к WalletConnect для совершения транзакций.", - "newConnection": "Новое соединение", - "activeConnectionsPrompt": "Здесь появятся активные подключения", - "deleteConnectionConfirmationPrompt": "Вы уверены, что хотите удалить подключение к", + "estimated": "Примерно", + "etherscan_history": "История Эфириума", "event": "Событие", - "successful": "Успешный", - "wouoldLikeToConnect": "хотел бы подключиться", - "message": "Сообщение", - "do_not_have_enough_gas_asset": "У вас недостаточно ${currency} для совершения транзакции при текущих условиях сети блокчейн. Вам нужно больше ${currency} для оплаты комиссий за сеть блокчейна, даже если вы отправляете другой актив.", - "totp_auth_url": "URL-адрес TOTP-АВТОРИЗАЦИИ", - "awaitDAppProcessing": "Пожалуйста, подождите, пока dApp завершит обработку.", - "copyWalletConnectLink": "Скопируйте ссылку WalletConnect из dApp и вставьте сюда.", - "enterWalletConnectURI": "Введите URI WalletConnect", - "seed_key": "Ключ семян", - "enter_seed_phrase": "Введите свою семенную фразу", - "change_rep_successful": "Успешно изменил представитель", - "add_contact": "Добавить контакт", + "events": "События", + "exchange": "Обмен", + "exchange_incorrect_current_wallet_for_xmr": "Если вы хотите обменять XMR со своего баланса Monero в Cake Wallet, сначала переключитесь на свой кошелек Monero.", + "exchange_new_template": "Новый шаблон", "exchange_provider_unsupported": "${providerName} больше не поддерживается!", - "domain_looks_up": "Поиск доменов", - "require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки", - "camera_permission_is_required": "Требуется разрешение камеры.\nПожалуйста, включите его в настройках приложения.", - "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку.", - "order_by": "Сортировать по", - "creation_date": "Дата создания", + "exchange_result_confirm": "Нажимая подтвердить, вы отправите ${fetchingLabel} ${from} с вашего кошелька ${walletName} на адрес указанный ниже. Или вы можете отправить со своего внешнего кошелька на нижеуказанный адрес/QR-код.\n\nПожалуйста, нажмите подтвердить для продолжения, или вернитесь назад для изменения суммы.", + "exchange_result_description": "Вы должны отправить минимум ${fetchingLabel} ${from} на адрес, указанный на следующей странице. Если вы отправите сумму менее ${fetchingLabel} ${from}, то она может быть не конвертирована и не возвращена.", + "exchange_result_write_down_ID": "*Пожалуйста, скопируйте или запишите ID, указанный выше.", + "exchange_result_write_down_trade_id": "Пожалуйста, скопируйте или запишите ID сделки.", + "exchange_sync_alert_content": "Подождите, пока ваш кошелек синхронизируется", + "expired": "Истекает", + "expires": "Истекает", + "expiresOn": "Годен до", + "export_backup": "Экспорт резервной копии", + "extra_id": "Дополнительный ID:", + "extracted_address_content": "Вы будете отправлять средства\n${recipient_name}", + "failed_authentication": "Ошибка аутентификации. ${state_error}", + "faq": "FAQ", + "fetching": "Загрузка", + "fiat_api": "Фиат API", + "fiat_balance": "Фиатный баланс", + "field_required": "Это поле обязательно к заполнению", + "fill_code": "Пожалуйста, введите код подтверждения, отправленный на вашу электронную почту", + "filter_by": "Фильтровать по", + "first_wallet_text": "В самом удобном кошельке для Monero, Bitcoin, Ethereum, Litecoin, и Haven", + "fixed_pair_not_supported": "Эта фиксированная пара не поддерживается выбранными биржами.", + "fixed_rate": "Фиксированная ставка", + "fixed_rate_alert": "Вы сможете ввести сумму получения тогда, когда будет установлен режим фиксированной ставки. Вы хотите перейти в режим фиксированной ставки?", + "forgot_password": "Забыли пароль", + "freeze": "Заморозить", + "frequently_asked_questions": "Часто задаваемые вопросы", + "frozen": "Заморожено", + "full_balance": "Весь баланс", + "generate_name": "Создать имя", + "generating_gift_card": "Создание подарочной карты", + "get_a": "Получить ", + "get_card_note": " которую вы можете пополнить цифровой валютой. Дополнительная информация не требуется!", + "get_your_yat": "Получить свой Yat", + "gift_card_amount": "Сумма подарочной карты", + "gift_card_balance_note": "Здесь будут отображаться подарочные карты с остатком на балансе", + "gift_card_is_generated": "Подарочная карта сгенерирована", + "gift_card_number": "Номер подарочной карты", + "gift_card_redeemed_note": "Здесь будут отображаться использованные вами подарочные карты", + "gift_cards": "Подарочные карты", + "gift_cards_unavailable": "В настоящее время подарочные карты можно приобрести только через Monero, Bitcoin и Litecoin.", + "got_it": "Понял", + "gross_balance": "Валовой баланс", "group_by_type": "Группа по типу", - "importNFTs": "Импортировать NFT", - "noNFTYet": "NFT пока нет", - "address": "Адрес", - "enterTokenID": "Введите идентификатор токена", - "tokenID": "ИДЕНТИФИКАТОР", - "name": "Имя", - "symbol": "Символ", - "seed_phrase_length": "Длина исходной фразы", - "unavailable_balance": "Недоступный баланс", - "unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.", - "unspent_change": "Изменять", - "tor_connection": "Тор соединение", - "setup_warning_2fa_text": "Cake 2FA — это вторая аутентификация для определенных действий в кошельке. Это НЕ так безопасно, как холодное хранение.\n\nЕсли вы потеряете доступ к своему приложению 2FA или ключам TOTP, вы потеряете доступ к этому кошельку. Вам нужно будет восстановить свой кошелек из мнемонического сида.\n\nСлужба поддержки Cake не сможет вам помочь, если вы потеряете доступ к своим 2FA или мнемоническим идентификаторам.\nПрежде чем использовать Cake 2FA, мы рекомендуем прочитать руководство.", - "scan_qr_on_device": "Отсканируйте этот QR-код на другом устройстве", + "haven_app": "Haven by Cake Wallet", + "haven_app_wallet_text": "Awesome wallet for Haven", + "help": "помощь", + "hidden_balance": "Скрытый баланс", + "hide_details": "Скрыть детали", + "high_contrast_theme": "Высококонтрастная тема", + "home_screen_settings": "Настройки главного экрана", "how_to_use": "Как использовать", + "how_to_use_card": "Как использовать эту карту", + "id": "ID: ", + "ignor": "Игнорировать", + "import": "Импортировать", + "importNFTs": "Импортировать NFT", + "in_store": "В магазине", + "incoming": "Входящие", + "incorrect_seed": "Введённый текст некорректный.", + "introducing_cake_pay": "Представляем Cake Pay!", + "invalid_input": "Неверный Ввод", + "invoice_details": "Детали счета", + "is_percentage": "есть", + "last_30_days": "Последние 30 дней", + "learn_more": "Узнать больше", + "light_theme": "Светлая", + "loading_your_wallet": "Загрузка кошелька", + "login": "Логин", + "logout": "Выйти", + "low_fee": "Низкая комиссия", + "low_fee_alert": "В настоящее время вы используете низкий приоритет платы за сеть. Это может привести к длительному ожиданию, изменению ставок или отмене сделок. Мы рекомендуем установить более высокую плату для лучшего опыта.", + "manage_nodes": "Управление узлами", + "manage_pow_nodes": "Управление узлами PoW", + "manage_yats": "Управлять Yat", + "mark_as_redeemed": "Отметить как погашенный", + "market_place": "Торговая площадка", + "matrix_green_dark_theme": "Матрица Зеленая Темная Тема", + "max_amount": "Макс.: ${value}", + "max_value": "Макс: ${value} ${currency}", + "memo": "Памятка:", + "message": "Сообщение", + "methods": "Методы", + "min_amount": "Минимум: ${value}", + "min_value": "Мин: ${value} ${currency}", + "minutes_to_pin_code": "${minute} минут", + "mm": "ММ", + "modify_2fa": "Изменить торт 2FA", + "monero_com": "Monero.com by Cake Wallet", + "monero_com_wallet_text": "Awesome wallet for Monero", + "monero_dark_theme": "Темная тема Monero", + "monero_light_theme": "Светлая тема Monero", + "moonpay_alert_text": "Сумма должна быть больше или равна ${minAmount} ${fiatCurrency}", + "more_options": "Дополнительные параметры", + "name": "Имя", + "narrow": "Узкий", + "new_first_wallet_text": "Легко сохранить свою криптовалюту в безопасности", + "new_node_testing": "Тестирование новой ноды", + "new_subaddress_create": "Создать", + "new_subaddress_label_name": "Имя", + "new_subaddress_title": "Новый адрес", + "new_template": "Новый шаблон", + "new_wallet": "Новый кошелёк", + "newConnection": "Новое соединение", + "no_id_needed": "Идентификатор не нужен!", + "no_id_required": "Идентификатор не требуется. Пополняйте и тратьте где угодно", + "no_relay_on_domain": "Для домена пользователя реле не существует или реле недоступно. Пожалуйста, выберите реле для использования.", + "no_relays": "Нет реле", + "no_relays_message": "Мы нашли запись Nostr NIP-05 для этого пользователя, но она не содержит никаких реле. Попросите получателя добавить реле в свою запись Nostr.", + "node_address": "Адрес ноды", + "node_connection_failed": "Подключение не удалось", + "node_connection_successful": "Подключение прошло успешно", + "node_new": "Новая нода", + "node_port": "Порт ноды", + "node_reset_settings_title": "Сбросить настройки", + "node_test": "Тест", + "nodes": "Ноды", + "nodes_list_reset_to_default_message": "Вы уверены, что хотите сбросить настройки до значений по умолчанию?", + "none_of_selected_providers_can_exchange": "Ни один из выбранных провайдеров не может совершить этот обмен", + "noNFTYet": "NFT пока нет", + "normal": "Нормальный", + "note_optional": "Примечание (необязательно)", + "note_tap_to_change": "Примечание (нажмите для изменения)", + "nullURIError": "URI имеет значение null", + "offer_expires_in": "Предложение истекает через: ", + "offline": "Не в сети", + "ok": "OK", + "onion_link": "Луковая ссылка", + "online": "Онлайн", + "onramper_option_description": "Быстро купите крипто со многими способами оплаты. Доступно в большинстве стран. Спреды и сборы различаются.", + "open_gift_card": "Открыть подарочную карту", + "optional_description": "Дополнительное описание", + "optional_email_hint": "Необязательное электронное письмо с уведомлением получателя платежа", + "optional_name": "Необязательное имя получателя", + "optionly_order_card": "При желании закажите физическую карту.", + "orbot_running_alert": "Перед подключением к этому узлу убедитесь, что Orbot запущен.", + "order_by": "Сортировать по", + "order_id": "Идентификатор заказа", + "order_physical_card": "Заказать физическую карту", + "other_settings": "Другие настройки", + "outdated_electrum_wallet_description": "Новые биткойн-кошельки, созданные в Cake, теперь содержат мнемоническую фразу из 24 слов. Вы обязательно должны создать новый биткойн-кошелек и перевести все свои средства в новый кошелек из 24 слов, а также прекратить использование кошельков с мнемонической фразой из 12 слов. Пожалуйста, сделайте это немедленно, чтобы обезопасить свои средства.", + "outdated_electrum_wallet_receive_warning": "Если этот кошелек имеет мнемоническую фразу из 12 слов и был создан в Cake, НЕ переводите биткойны на этот кошелек. Любые BTC, переведенные на этот кошелек, могут быть потеряны. Создайте новый кошелек с мнемоническои фразы из 24 слов (коснитесь меню в правом верхнем углу, выберите «Кошельки», выберите «Создать новый кошелек», затем выберите «Bitcoin») и НЕМЕДЛЕННО переведите туда свои BTC. Новые (24 слова) кошельки BTC от Cake безопасны", + "outgoing": "Исходящие", + "overwrite_amount": "Overwrite amount", + "pairingInvalidEvent": "Недействительное событие сопряжения", + "password": "Пароль", + "paste": "Вставить", + "pause_wallet_creation": "Возможность создания Haven Wallet в настоящее время приостановлена.", + "payment_id": "ID платежа: ", + "payment_was_received": "Ваш платеж получен.", + "pending": " (в ожидании)", + "percentageOf": "из ${amount}", + "pin_at_top": "закрепить ${token} вверху", + "pin_is_incorrect": "Некорректный PIN", + "pin_number": "ПИН-код", + "placeholder_contacts": "Ваши контакты будут отображаться здесь", + "placeholder_transactions": "Ваши транзакции будут отображаться здесь", + "please_fill_totp": "Пожалуйста, введите 8-значный код на другом устройстве", + "please_make_selection": "Выберите способ создания кошелька: создать новый или восстановить ваш существующий.", + "please_reference_document": "Пожалуйста, обратитесь к документам ниже для получения дополнительной информации.", + "please_select": "Пожалуйста, выберите:", + "please_select_backup_file": "Выберите файл резервной копии и введите пароль резервной копии.", + "please_try_to_connect_to_another_node": "Пожалуйста, попробуйте подключиться к другой ноде", + "please_wait": "Пожалуйста, подождите", + "polygonscan_history": "История PolygonScan", + "powered_by": "Используя ${title}", + "pre_seed_button_text": "Понятно. Покажите мнемоническую фразу", + "pre_seed_description": "На следующей странице вы увидите серию из ${words} слов. Это ваша уникальная и личная мнемоническая фраза, и это ЕДИНСТВЕННЫЙ способ восстановить свой кошелек в случае потери или неисправности. ВАМ необходимо записать ее и хранить в надежном месте вне приложения Cake Wallet.", + "pre_seed_title": "ВАЖНО", + "prevent_screenshots": "Предотвратить скриншоты и запись экрана", + "privacy": "Конфиденциальность", + "privacy_policy": "Политика конфиденциальности", + "privacy_settings": "Настройки конфиденциальности", + "private_key": "Приватный ключ", + "proceed_after_one_minute": "Если через 1 минуту экран не отображается, проверьте свою электронную почту.", + "profile": "Профиль", + "provider_error": "${provider} ошибка", + "public_key": "Публичный ключ", + "purchase_gift_card": "Купить подарочную карту", + "qr_fullscreen": "Нажмите, чтобы открыть полноэкранный QR-код", + "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", + "question_to_disable_2fa": "Вы уверены, что хотите отключить Cake 2FA? Код 2FA больше не потребуется для доступа к кошельку и некоторым функциям.", + "receivable_balance": "Баланс дебиторской задолженности", + "receive": "Получить", + "receive_amount": "Сумма", + "received": "Полученные", + "recipient_address": "Адрес получателя", + "reconnect": "Переподключиться", + "reconnect_alert_text": "Вы хотите переподключиться?", + "reconnection": "Переподключение", + "redeemed": "искуплен", + "refund_address": "Адрес возврата", + "reject": "Отклонять", + "remaining": "осталось", + "remove": "Удалить", + "remove_node": "Удалить ноду", + "remove_node_message": "Вы уверены, что хотите удалить текущую ноду?", + "rename": "Переименовать", + "require_for_adding_contacts": "Требовать добавления контактов", + "require_for_all_security_and_backup_settings": "Требовать все настройки безопасности и резервного копирования", + "require_for_assessing_wallet": "Требовать для доступа к кошельку", + "require_for_creating_new_wallets": "Требовать для создания новых кошельков", + "require_for_exchanges_to_external_wallets": "Требовать обмена на внешние кошельки", + "require_for_exchanges_to_internal_wallets": "Требовать для обмена на внутренние кошельки", + "require_for_sends_to_contacts": "Требовать для отправки контактам", + "require_for_sends_to_internal_wallets": "Требовать отправки на внутренние кошельки", + "require_for_sends_to_non_contacts": "Требовать для отправки не контактам", + "require_pin_after": "Требовать ПИН после", + "rescan": "Пересканировать", + "resend_code": "Пожалуйста, отправьте еще раз", + "reset": "Сброс", + "reset_password": "Сбросить пароль", + "restore_active_seed": "Активная мнемоническая фраза", + "restore_address": "Адрес", + "restore_bitcoin_description_from_keys": "Вы можете восстановить кошелёк с помощью WIF", + "restore_bitcoin_description_from_seed": "Вы можете восстановить кошелёк используя 24-ти значную мнемоническую фразу", + "restore_bitcoin_title_from_keys": "Восстановить с помощью WIF", + "restore_description_from_backup": "Вы можете восстановить Cake Wallet из вашего back-up файла", + "restore_description_from_keys": "Вы можете восстановить кошелёк с помощью приватных ключей", + "restore_description_from_seed": "Вы можете восстановить кошелёк используя 25-ти значную мнемоническую фразу", + "restore_description_from_seed_keys": "Вы можете восстановить кошелёк из мнемонической фразы/ключей, которые вы сохранили ранее", + "restore_from_date_or_blockheight": "Пожалуйста, введите дату за несколько дней до создания этого кошелька. Или, если вы знаете высоту блока, введите ее значение", + "restore_from_seed_placeholder": "Введите или вставьте мнемоническую фразу вашего кошелька", + "restore_new_seed": "Новая мнемоническая фраза", + "restore_next": "Продолжить", + "restore_recover": "Восстановить", + "restore_restore_wallet": "Восстановить кошелёк", + "restore_seed_keys_restore": "Восстановить из мнемонической фразы/ключей", + "restore_spend_key_private": "Приватный ключ траты", + "restore_title_from_backup": "Восстановить из back-up файла", + "restore_title_from_keys": "Восстановить с помощью ключей", + "restore_title_from_seed": "Восстановить из мнемонической фразы", + "restore_title_from_seed_keys": "Восстановить из мнемонической фразы/ключей", + "restore_view_key_private": "Приватный ключ просмотра", + "restore_wallet": "Восстановить кошелёк", + "restore_wallet_name": "Имя кошелька", + "restore_wallet_restore_description": "Описание восстановления кошелька", + "router_no_route": "Не установлен маршрут для ${name}", + "save": "Сохранить", + "save_backup_password": "Убедитесь, что вы сохранили пароль резервной копии. Без него вы не сможете импортировать файлы резервных копий.", + "save_backup_password_alert": "Сохранить пароль резервной копии", + "save_to_downloads": "Сохранить в загрузках", + "saved_the_trade_id": "Я сохранил ID сделки", + "scan_qr_code": "Сканировать QR-код", + "scan_qr_code_to_get_address": "Отсканируйте QR-код для получения адреса", + "scan_qr_on_device": "Отсканируйте этот QR-код на другом устройстве", + "search": "Поиск", + "search_add_token": "Поиск / Добавить токен", + "search_category": "Категория поиска", + "search_currency": "Валюта поиска", + "search_language": "Язык поиска", + "second_intro_content": "Ваш Yat - это единственный уникальный адрес эмодзи, который заменяет длинные шестнадцатеричные адреса для всех ваших валют.", + "second_intro_title": "Один адрес эмодзи для управления остальными адресами", + "security_and_backup": "Безопасность и резервное копирование", + "seed_alert_back": "Назад", + "seed_alert_content": "Мнемоническая фраза - единственный способ восстановить ваш кошелек. Вы записали ее?", + "seed_alert_title": "Внимание", + "seed_alert_yes": "Да", + "seed_choose": "Выберите язык мнемонической фразы", "seed_hex_form": "Семя кошелька (шестнадцатеричная форма)", + "seed_key": "Ключ семян", + "seed_language": "Язык семян", + "seed_language_chinese": "Китайский", + "seed_language_chinese_traditional": "Китайский традиционный)", + "seed_language_czech": "Чешский", + "seed_language_dutch": "Нидерландский", + "seed_language_english": "Английский", + "seed_language_french": "Французский", + "seed_language_german": "Немецкий", + "seed_language_italian": "итальянский", + "seed_language_japanese": "Японский", + "seed_language_korean": "Корейский", + "seed_language_next": "Продолжить", + "seed_language_portuguese": "Португальский", + "seed_language_russian": "Русский", + "seed_language_spanish": "Испанский", + "seed_phrase_length": "Длина исходной фразы", + "seed_reminder": "Пожалуйста, запишите мнемоническую фразу на случай потери или очистки телефона", + "seed_share": "Поделиться мнемонической фразой", + "seed_title": "Мнемоническая фраза", "seedtype": "SEEDTYPE", "seedtype_legacy": "Наследие (25 слов)", "seedtype_polyseed": "Полиса (16 слов)", - "seed_language_czech": "Чешский", - "seed_language_korean": "Корейский", - "seed_language_chinese_traditional": "Китайский традиционный)", - "ascending": "Восходящий", - "descending": "Нисходящий", - "dfx_option_description": "Покупайте криптовалюту за EUR и CHF. До 990€ без дополнительного KYC. Для розничных и корпоративных клиентов в Европе", - "polygonscan_history": "История PolygonScan", - "wallet_seed_legacy": "Наследие семя кошелька", - "default_sell_provider": "Поставщик продаж по умолчанию", + "select_backup_file": "Выберите файл резервной копии", + "select_buy_provider_notice": "Выберите поставщика покупки выше. Вы можете пропустить этот экран, установив поставщика покупки по умолчанию в настройках приложения.", + "select_destination": "Пожалуйста, выберите место для файла резервной копии.", "select_sell_provider_notice": "Выберите поставщика услуг продажи выше. Вы можете пропустить этот экран, установив поставщика услуг продаж по умолчанию в настройках приложения.", - "custom_drag": "Пользователь (удерживайте и перетаскивайте)", + "sell": "Продавать", + "sell_alert_content": "В настоящее время мы поддерживаем только продажу биткойнов, эфириума и лайткойна. Пожалуйста, создайте или переключитесь на свой кошелек Bitcoin, Ethereum или Litecoin.", + "sell_monero_com_alert_content": "Продажа Monero пока не поддерживается", + "send": "Отправить", + "send_address": "${cryptoCurrency} адрес", + "send_amount": "Сумма:", + "send_creating_transaction": "Создать транзакцию", + "send_error_currency": "Валюта может содержать только цифры", + "send_error_minimum_value": "Mинимальная сумма 0.01", + "send_estimated_fee": "Предполагаемая комиссия:", + "send_fee": "Комиссия:", + "send_name": "Имя", + "send_new": "Новый", + "send_payment_id": "ID платежа (опционально)", + "send_priority": "Комиссия установлена в зависимости от приоритета: ${transactionPriority}.\nПриоритет транзакции может быть изменён в настройках", + "send_sending": "Отправка...", + "send_success": "Ваш ${crypto} был успешно отправлен", + "send_templates": "Шаблоны", + "send_title": "Отправить", + "send_to_this_address": "Отправить ${currency} ${tag}на этот адрес", + "send_xmr": "Отправить XMR", + "send_your_wallet": "Ваш кошелёк", + "sending": "Отправка", + "sent": "Отправленные", + "settings": "Настройки", + "settings_all": "ВСЕ", + "settings_allow_biometrical_authentication": "Включить биометрическую аутентификацию", + "settings_can_be_changed_later": "Эти настройки можно изменить позже в настройках приложения.", + "settings_change_language": "Изменить язык", + "settings_change_pin": "Изменить PIN", + "settings_currency": "Валюта", + "settings_current_node": "Текущая нода", + "settings_dark_mode": "Тёмный режим", + "settings_display_balance": "Отображать баланс", + "settings_display_on_dashboard_list": "Показывать в списке транзакций", + "settings_fee_priority": "Приоритет транзакции", + "settings_nodes": "Ноды", + "settings_none": "Ничего", + "settings_only_trades": "Сделки", + "settings_only_transactions": "Транзакции", + "settings_personal": "Персональные", + "settings_save_recipient_address": "Сохранять адрес получателя", + "settings_support": "Поддержка", + "settings_terms_and_conditions": "Условия и положения", + "settings_title": "Настройки", + "settings_trades": "Сделки", + "settings_transactions": "Транзакции", + "settings_wallets": "Кошельки", + "setup_2fa": "Настройка торта 2FA", + "setup_2fa_text": "Cake 2FA работает с использованием TOTP в качестве второго фактора аутентификации.\n\nTOTP Cake 2FA требует SHA-512 и поддержки 8 цифр; это обеспечивает повышенную безопасность. Дополнительную информацию и поддерживаемые приложения можно найти в руководстве.", + "setup_pin": "Настроить PIN", + "setup_successful": "PIN был успешно установлен!", + "setup_totp_recommended": "Настройка ТОТП", + "setup_warning_2fa_text": "Cake 2FA — это вторая аутентификация для определенных действий в кошельке. Это НЕ так безопасно, как холодное хранение.\n\nЕсли вы потеряете доступ к своему приложению 2FA или ключам TOTP, вы потеряете доступ к этому кошельку. Вам нужно будет восстановить свой кошелек из мнемонического сида.\n\nСлужба поддержки Cake не сможет вам помочь, если вы потеряете доступ к своим 2FA или мнемоническим идентификаторам.\nПрежде чем использовать Cake 2FA, мы рекомендуем прочитать руководство.", + "setup_your_debit_card": "Настройте свою дебетовую карту", + "share": "Делиться", + "share_address": "Поделиться адресом", + "show_details": "Показать детали", + "show_keys": "Показать мнемоническую фразу/ключи", + "show_market_place": "Показать торговую площадку", + "show_seed": "Показать мнемоническую фразу", + "sign_up": "Зарегистрироваться", + "signTransaction": "Подписать транзакцию", + "signup_for_card_accept_terms": "Подпишитесь на карту и примите условия.", + "slidable": "Скользящий", + "sort_by": "Сортировать по", + "spend_key_private": "Приватный ключ траты", + "spend_key_public": "Публичный ключ траты", + "status": "Статус: ", + "subaddress_title": "Список субадресов", + "subaddresses": "Субадреса", + "submit_request": "отправить запрос", + "successful": "Успешный", + "support_description_guides": "Документация и поддержка общих вопросов", + "support_description_live_chat": "Бесплатно и быстро! Обученные представители поддержки доступны для оказания помощи", + "support_description_other_links": "Присоединяйтесь к нашим сообществам или охватите нас наших партнеров с помощью других методов", + "support_title_guides": "Корт -гиды", + "support_title_live_chat": "Живая поддержка", + "support_title_other_links": "Другие ссылки на поддержку", + "sweeping_wallet": "Подметание кошелька", + "sweeping_wallet_alert": "Это не должно занять много времени. НЕ ПОКИДАЙТЕ ЭТОТ ЭКРАН, ИНАЧЕ ВЫЧИСЛЕННЫЕ СРЕДСТВА МОГУТ БЫТЬ ПОТЕРЯНЫ", + "switchToETHWallet": "Пожалуйста, переключитесь на кошелек Ethereum и повторите попытку.", "switchToEVMCompatibleWallet": "Пожалуйста, переключитесь на кошелек, совместимый с EVM, и повторите попытку (Ethereum, Polygon).", - "receivable_balance": "Баланс дебиторской задолженности", - "confirmed_tx": "Подтвержденный", + "symbol": "Символ", + "sync_all_wallets": "Синхронизировать все кошельки", + "sync_status_attempting_sync": "ПОПЫТКА СИНХРОНИЗАЦИИ", + "sync_status_connected": "ПОДКЛЮЧЕНО", + "sync_status_connecting": "ПОДКЛЮЧЕНИЕ", + "sync_status_failed_connect": "ОТКЛЮЧЕНО", + "sync_status_not_connected": "НЕ ПОДКЛЮЧЁН", + "sync_status_starting_sync": "НАЧАЛО СИНХРОНИЗАЦИИ", + "sync_status_syncronized": "СИНХРОНИЗИРОВАН", + "sync_status_syncronizing": "СИНХРОНИЗАЦИЯ", + "syncing_wallet_alert_content": "Ваш баланс и список транзакций могут быть неполными, пока вверху не будет написано «СИНХРОНИЗИРОВАНО». Щелкните/коснитесь, чтобы узнать больше.", + "syncing_wallet_alert_title": "Ваш кошелек синхронизируется", + "template": "Шаблон", + "template_name": "Имя Шаблона", + "third_intro_content": "Yat находятся за пределами Cake Wallet. Любой адрес кошелька на земле можно заменить на Yat!", + "third_intro_title": "Yat хорошо взаимодействует с другими", + "time": "${minutes}мин ${seconds}сек", + "tip": "Совет:", + "today": "Сегодня", + "token_contract_address": "Адрес контракта токена", + "token_decimal": "Десятичный токен", + "token_name": "Имя токена, например: Tether", + "token_symbol": "Символ токена, например: USDT", + "tokenID": "ИДЕНТИФИКАТОР", + "tor_connection": "Тор соединение", + "tor_only": "Только Tor", + "total_saving": "Общая экономия", + "totp_2fa_failure": "Неверный код. Пожалуйста, попробуйте другой код или создайте новый секретный ключ. Используйте совместимое приложение 2FA, которое поддерживает 8-значные коды и SHA512.", + "totp_2fa_success": "Успех! Для этого кошелька включена двухфакторная аутентификация Cake. Не забудьте сохранить мнемоническое семя на случай, если вы потеряете доступ к кошельку.", + "totp_auth_url": "URL-адрес TOTP-АВТОРИЗАЦИИ", + "totp_code": "TOTP-код", + "totp_secret_code": "Секретный код ТОТП", + "totp_verification_success": "Проверка прошла успешно!", + "trade_details_copied": "${title} скопировано в буфер обмена", + "trade_details_created_at": "Создано", + "trade_details_fetching": "Получение", + "trade_details_id": "ID", + "trade_details_pair": "Пара", + "trade_details_provider": "Провайдер", + "trade_details_state": "Статус", + "trade_details_title": "Детали сделок", + "trade_for_not_created": "Сделка для ${title} не создана.", + "trade_history_title": "История сделок", + "trade_id": "ID сделки:", + "trade_id_not_found": "Сделка ${tradeId} ${title} не найдена.", + "trade_is_powered_by": "Сделка выполнена через ${provider}", + "trade_not_created": "Сделка не создана", + "trade_not_found": "Торговля не найдена.", + "trade_state_btc_sent": "BTC отправлены", + "trade_state_complete": "Выполнена", + "trade_state_confirming": "Подтверждение", + "trade_state_created": "Созданная", + "trade_state_finished": "Завершена", + "trade_state_paid": "Оплаченная", + "trade_state_paid_unconfirmed": "Оплата неподтверждена", + "trade_state_pending": "Ожидание", + "trade_state_timeout": "Таймаут", + "trade_state_to_be_created": "Будет создана", + "trade_state_traded": "Сделка завершена", + "trade_state_trading": "Совершение сделки", + "trade_state_underpaid": "Недоплаченная", + "trade_state_unpaid": "Неоплаченная", + "trades": "Сделки", + "transaction_details_amount": "Сумма", + "transaction_details_copied": "${title} скопировано в буфер обмена", + "transaction_details_date": "Дата", + "transaction_details_fee": "Комиссия", + "transaction_details_height": "Высота", + "transaction_details_recipient_address": "Адреса получателей", "transaction_details_source_address": "Адрес источника", - "pause_wallet_creation": "Возможность создания Haven Wallet в настоящее время приостановлена.", - "contractName": "Название контракта", - "contractSymbol": "Символ контракта", - "description": "Описание", - "camera_consent": "Ваша камера будет использоваться для захвата изображения в целях идентификации ${provider}. Пожалуйста, ознакомьтесь с их Политикой конфиденциальности для получения подробной информации.", - "no_relays": "Нет реле", - "choose_relay": "Пожалуйста, выберите реле для использования", - "no_relays_message": "Мы нашли запись Nostr NIP-05 для этого пользователя, но она не содержит никаких реле. Попросите получателя добавить реле в свою запись Nostr.", - "no_relay_on_domain": "Для домена пользователя реле не существует или реле недоступно. Пожалуйста, выберите реле для использования." -} + "transaction_details_title": "Детали транзакции", + "transaction_details_transaction_id": "ID транзакции", + "transaction_key": "Ключ транзакции", + "transaction_priority_fast": "Быстрый", + "transaction_priority_fastest": "Самый быстрый", + "transaction_priority_medium": "Средний", + "transaction_priority_regular": "Обычный", + "transaction_priority_slow": "Медленный", + "transaction_sent": "Tранзакция отправлена!", + "transaction_sent_notice": "Если экран не отображается через 1 минуту, проверьте обозреватель блоков и свою электронную почту.", + "transactions": "Транзакции", + "transactions_by_date": "Сортировать по дате", + "trusted": "доверенный", + "unavailable_balance": "Недоступный баланс", + "unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.", + "unconfirmed": "Неподтвержденный баланс", + "understand": "Понятно", + "unmatched_currencies": "Валюта вашего текущего кошелька не соответствует валюте отсканированного QR-кода.", + "unspent_change": "Изменять", + "unspent_coins_details_title": "Сведения о неизрасходованных монетах", + "unspent_coins_title": "Неизрасходованные монеты", + "unsupported_asset": "Мы не поддерживаем это действие для этого объекта. Пожалуйста, создайте или переключитесь на кошелек поддерживаемого типа активов.", + "upto": "до ${value}", + "use": "Использовать ", + "use_card_info_three": "Используйте цифровую карту онлайн или с помощью бесконтактных способов оплаты.", + "use_card_info_two": "Средства конвертируются в доллары США, когда они хранятся на предоплаченном счете, а не в цифровых валютах.", + "use_ssl": "Использовать SSL", + "use_suggested": "Использовать предложенный", + "variable_pair_not_supported": "Эта пара переменных не поддерживается выбранными биржами.", + "verification": "Проверка", + "verify_with_2fa": "Подтвердить с помощью Cake 2FA", + "version": "Версия ${currentVersion}", + "view_all": "Просмотреть все", + "view_in_block_explorer": "View in Block Explorer", + "view_key_private": "Приватный ключ просмотра", + "view_key_public": "Публичный ключ просмотра", + "view_transaction_on": "View Transaction on ", + "wallet_keys": "Мнемоническая фраза/ключи кошелька", + "wallet_list_create_new_wallet": "Создать новый кошелёк", + "wallet_list_edit_wallet": "Изменить кошелек", + "wallet_list_failed_to_load": "Ошибка при загрузке ${wallet_name} кошелька. ${error}", + "wallet_list_failed_to_remove": "Ошибка при удалении ${wallet_name} кошелька. ${error}", + "wallet_list_load_wallet": "Загрузка кошелька", + "wallet_list_loading_wallet": "Загрузка ${wallet_name} кошелька", + "wallet_list_removing_wallet": "Удаление ${wallet_name} кошелька", + "wallet_list_restore_wallet": "Восстановить кошелёк", + "wallet_list_title": "Monero Кошелёк", + "wallet_list_wallet_name": "Имя кошелька", + "wallet_menu": "Меню кошелька", + "wallet_name": "Имя кошелька", + "wallet_name_exists": "Кошелек с таким именем уже существует", + "wallet_restoration_store_incorrect_seed_length": "Неверная длина мнемонической фразы", + "wallet_seed": "Мнемоническая фраза кошелька", + "wallet_seed_legacy": "Наследие семя кошелька", + "wallet_store_monero_wallet": "Monero Кошелёк", + "walletConnect": "КошелекПодключиться", + "wallets": "Кошельки", + "warning": "Предупреждение", + "welcome": "Приветствуем в", + "welcome_to_cakepay": "Добро пожаловать в Cake Pay!", + "widgets_address": "Адрес", + "widgets_or": "или", + "widgets_restore_from_blockheight": "Восстановить на высоте блока", + "widgets_restore_from_date": "Восстановить с даты", + "widgets_seed": "Мнемоническая фраза", + "wouoldLikeToConnect": "хотел бы подключиться", + "write_down_backup_password": "Запишите пароль резервной копии, который используется для импорта файлов резервных копий.", + "xlm_extra_info": "Не забудьте указать Memo ID (памятка) при отправке транзакции XLM для обмена", + "xmr_available_balance": "Доступный баланс", + "xmr_full_balance": "Весь баланс", + "xmr_hidden": "Скрыто", + "xmr_to_error": "Ошибка XMR.TO", + "xmr_to_error_description": "Недопустимая сумма. Максимум 8 цифр после десятичной точки", + "xrp_extra_info": "Не забудьте указать целевой тег при отправке транзакции XRP для обмена", + "yat": "Yat", + "yat_address": "Yat адрес", + "yat_alert_content": "Пользователи Cake Wallet теперь могут отправлять и получать криптовалюту при помощи уникального имени пользователя на основе эмодзи.", + "yat_alert_title": "С Yat проще отправлять и получать криптовалюту", + "yat_error": "Ошибка Yat", + "yat_error_content": "Нет адресов, связанных с этим Yat. Попробуйте другой Yat", + "yat_popup_content": "Теперь вы можете отправлять и получать криптовалюту в Cake Wallet с помощью Yat - короткого имени пользователя на основе эмодзи. Управляйте Yat в любое время при помощи экрана настроек", + "yat_popup_title": "Адрес вашего кошелька может быть связан с эмодзи", + "yesterday": "Вчера", + "you_now_have_debit_card": "Теперь у вас есть дебетовая карта", + "you_pay": "Вы платите", + "you_will_get": "Конвертировать в", + "you_will_send": "Конвертировать из", + "yy": "ГГ", + "zzzz": "zzzz" +} \ No newline at end of file diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 603d04067..e1f187bd3 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -1,777 +1,778 @@ { - "welcome": "ยินดีต้อนรับสู่", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "กระเป๋าสตางค์ที่สวยงามสำหรับ Monero, Bitcoin, Ethereum, Litecoin และ Haven", - "please_make_selection": "โปรดเลือกตามด้านล่างเพื่อสร้างหรือกู้กระเป๋าของคุณ", - "create_new": "สร้างกระเป๋าใหม่", - "restore_wallet": "กู้กระเป๋า", - "monero_com": "Monero.com ของ Cake Wallet", - "monero_com_wallet_text": "กระเป๋าสตางค์ที่สวยงามสำหรับ Monero", - "haven_app": "Haven ของ Cake Wallet", - "haven_app_wallet_text": "กระเป๋าสตางค์ที่สวยงามสำหรับ Haven", - "accounts": "บัญชี", - "edit": "แก้ไข", + "about_cake_pay": "Cake Pay ช่วยให้คุณสามารถซื้อบัตรของขวัญง่ายๆ ด้วยการใช้สินทรัพย์อนุกรม ซื้อใช้ได้ทันทีกับมากกว่า 150,000 ร้านค้าในสหรัฐอเมริกา", "account": "บัญชี", + "accounts": "บัญชี", + "accounts_subaddresses": "บัญชีและที่อยู่ย่อย", + "activate": "เปิดใช้งาน", + "active": "ทำงาน", + "active_cards": "บัตรที่ใช้งานได้", + "activeConnectionsPrompt": "การเชื่อมต่อที่ใช้งานอยู่จะปรากฏที่นี่", "add": "เพิ่ม", + "add_contact": "เพิ่มผู้ติดต่อ", + "add_custom_node": "เพิ่มจุดโหนดแบบกำหนดเอง", + "add_custom_redemption": "เพิ่มการรับคืนที่กำหนดเอง", + "add_fund_to_card": "เพิ่มเงินสำรองไว้บนบัตร (ถึง ${value})", + "add_new_node": "เพิ่มโหนดใหม่", + "add_new_word": "เพิ่มคำใหม่", + "add_receiver": "เพิ่มผู้รับอื่น ๆ (ตัวเลือก)", + "add_secret_code": "หรือเพิ่มรหัสลับนี้ลงในแอปตรวจสอบความถูกต้อง", + "add_tip": "เพิ่มคำแนะนำ", + "add_token_disclaimer_check": "ฉันได้ยืนยันที่อยู่และข้อมูลของสัญญาโทเค็นโดยใช้แหล่งข้อมูลที่เชื่อถือได้ การเพิ่มข้อมูลที่เป็นอันตรายหรือไม่ถูกต้องอาจทำให้สูญเสียเงินได้", + "add_token_warning": "ห้ามแก้ไขหรือเพิ่มโทเค็นตามคำแนะนำของนักต้มตุ๋น\nยืนยันที่อยู่โทเค็นกับแหล่งที่มาที่เชื่อถือได้เสมอ!", + "add_value": "เพิ่มมูลค่า", + "address": "ที่อยู่", "address_book": "สมุดที่อยู่", - "contact": "ผู้ติดต่อ", - "please_select": "โปรดเลือก:", - "cancel": "ยกเลิก", - "ok": "ตกลง", - "contact_name": "ชื่อผู้ติดต่อ", - "reset": "รีเซ็ต", - "save": "บันทึก", + "address_book_menu": "สมุดที่อยู่", + "address_detected": "ตรวจพบที่อยู่", + "address_from_domain": "ที่อยู่นี้มาจาก ${domain} บน Unstoppable Domains", + "address_from_yat": "ที่อยู่นี้มาจาก ${emoji} บน Yat", + "address_label": "ป้ายกำกับที่อยู่", "address_remove_contact": "ลบผู้ติดต่อ", "address_remove_content": "คุณแน่ใจหรือว่าต้องการลบผู้ติดต่อที่เลือก?", - "authenticated": "ได้รับการยืนยันสิทธิ์", - "authentication": "การยืนยันสิทธิ์", - "failed_authentication": "การยืนยันสิทธิ์ล้มเหลว ${state_error}", - "wallet_menu": "เมนู", - "Blocks_remaining": "${status} บล็อกที่เหลืออยู่", - "please_try_to_connect_to_another_node": "โปรดลองเชื่อมต่อกับโหนดอื่น", - "xmr_hidden": "ซ่อน", - "xmr_available_balance": "ยอดคงเหลือที่สามารถใช้งานได้", - "xmr_full_balance": "ยอดคงเหลือแบบเต็ม", - "send": "ส่ง", - "receive": "รับ", - "transactions": "ธุรกรรม", - "incoming": "ขาเข้า", - "outgoing": "ขาออก", - "transactions_by_date": "ธุรกรรมตามวันที่", - "trades": "การซื้อขาย", - "filter_by": "กรองตาม", - "today": "วันนี้", - "yesterday": "เมื่อวาน", - "received": "รับ", - "sent": "ส่ง", - "pending": " (อยู่ระหว่างดำเนินการ)", - "rescan": "สแกนใหม่", - "reconnect": "เชื่อมต่อใหม่", - "wallets": "กระเป๋า", - "show_seed": "แสดงซีด", - "show_keys": "แสดงซีด/คีย์", - "address_book_menu": "สมุดที่อยู่", - "reconnection": "เชื่อมต่อใหม่", - "reconnect_alert_text": "คุณแน่ใจหรือไม่ว่าต้องการเชื่อมต่อใหม่?", - "exchange": "แลกเปลี่ยน", - "clear": "ล้าง", - "refund_address": "ที่อยู่สำหรับส่งคืน", - "change_exchange_provider": "เปลี่ยนผู้ให้บริการแลกเปลี่ยน", - "you_will_send": "แปลงจาก", - "you_will_get": "แปลงเป็น", - "amount_is_guaranteed": "จำนวนที่จะได้รับมีการรับประกัน", - "amount_is_estimate": "จำนวนที่จะได้รับเป็นการประมาณการ", - "powered_by": "พัฒนาขึ้นโดย ${title}", - "error": "ข้อผิดพลาด", - "estimated": "ประมาณการ", - "min_value": "ขั้นต่ำ: ${value} ${currency}", - "max_value": "ขั้นสูง: ${value} ${currency}", - "change_currency": "เปลี่ยนสกุลเงิน", - "overwrite_amount": "เขียนทับจำนวน", - "qr_payment_amount": "QR code นี้มีจำนวนการชำระเงิน คุณต้องการเขียนทับค่าปัจจุบันหรือไม่?", - "copy_id": "คัดลอก ID", - "exchange_result_write_down_trade_id": "โปรดคัดลอกหรือบันทึก ID ของการซื้อขายเพื่อดำเนินการต่อไป", - "trade_id": "ID การซื้อขาย:", - "copied_to_clipboard": "คัดลอกไปยังหน่วยความจำของคอมพิวเตอร์", - "saved_the_trade_id": "ฉันได้บันทึก ID ของการซื้อขายแล้ว", - "fetching": "กำลังโหลด", - "id": "ID: ", - "amount": "จำนวน: ", - "payment_id": "ID การชำระเงิน: ", - "status": "สถานะ: ", - "offer_expires_in": "ข้อเสนอจะหมดอายุใน: ", - "trade_is_powered_by": "การซื้อขายนี้จัดสร้างโดย ${provider}", - "copy_address": "คัดลอกที่อยู่", - "exchange_result_confirm": "โดยกดปุ่มยืนยัน, คุณจะส่ง ${fetchingLabel} ${from} จากกระเป๋าของคุณที่เรียกว่า ${walletName} ไปยังที่อยู่ที่แสดงข้างล่าง หรือคุณสามารถส่งจากกระเป๋าภายนอกไปยังที่อยู่/รหัส QR ด้านล่าง\n\nโปรดกดปุ่มยืนยันเพื่อดำเนินการต่อหรือกลับไปเปลี่ยนจำนวน", - "exchange_result_description": "คุณต้องส่งอย่างน้อย ${fetchingLabel} ${from} ไปยังที่อยู่ที่แสดงบนหน้าถัดไป หากคุณส่งจำนวนน้อยกว่า ${fetchingLabel} ${from} อาจจะไม่ถูกแปลงและอาจไม่ถูกเรียกคืน", - "exchange_result_write_down_ID": "*โปรดคัดลอกหรือเขียนรหัสของคุณด้านบน", - "confirm": "ยืนยัน", - "confirm_sending": "ยืนยันการส่ง", - "commit_transaction_amount_fee": "ยืนยันธุรกรรม\nจำนวน: ${amount}\nค่าธรรมเนียม: ${fee}", - "sending": "กำลังส่ง", - "transaction_sent": "ธุรกรรมถูกส่ง!", - "expired": "หมดอายุ", - "time": "${minutes}m ${seconds}s", - "send_xmr": "ส่ง XMR", - "exchange_new_template": "เทมเพลทใหม่", - "faq": "คำถามที่พบบ่อย", - "enter_your_pin": "ใส่ PIN ของคุณ", - "loading_your_wallet": "กำลังโหลดกระเป๋าของคุณ", - "new_wallet": "กระเป๋าใหม่", - "wallet_name": "ชื่อกระเป๋า", - "continue_text": "ดำเนินการต่อ", - "choose_wallet_currency": "โปรดเลือกสกุลเงินของกระเป๋า:", - "node_new": "โหนดใหม่", - "node_address": "ที่อยู่โหนด", - "node_port": "พอร์ตโหนด", - "login": "เข้าสู่ระบบ", - "password": "รหัสผ่าน", - "nodes": "โหนด", - "node_reset_settings_title": "รีเซ็ตการตั้งค่า", - "nodes_list_reset_to_default_message": "คุณแน่ใจหรือว่าต้องการรีเซ็ตการตั้งค่าเป็นค่าเริ่มต้น?", - "change_current_node": "คุณแน่ใจหรือว่าต้องการเปลี่ยนโหนดปัจจุบันเป็น ${node}?", - "change": "เปลี่ยน", - "remove_node": "ลบโหนด", - "remove_node_message": "คุณแน่ใจหรือว่าต้องการลบโหนดที่เลือก?", - "remove": "ลบ", - "delete": "ลบ", - "add_new_node": "เพิ่มโหนดใหม่", - "change_current_node_title": "เปลี่ยนโหนดปัจจุบัน", - "node_test": "ทดสอบ", - "node_connection_successful": "เชื่อมต่อสำเร็จ", - "node_connection_failed": "เชื่อมต่อล้มเหลว", - "new_node_testing": "การทดสอบโหนดใหม่", - "use": "สลับไปที่ ", - "digit_pin": "-หลัก PIN", - "share_address": "แชร์ที่อยู่", - "receive_amount": "จำนวน", - "subaddresses": "ที่อยู่ย่อย", "addresses": "ที่อยู่", - "scan_qr_code_to_get_address": "สแกน QR code เพื่อรับที่อยู่", - "qr_fullscreen": "แตะเพื่อเปิดหน้าจอ QR code แบบเต็มจอ", - "rename": "เปลี่ยนชื่อ", - "choose_account": "เลือกบัญชี", - "create_new_account": "สร้างบัญชีใหม่", - "accounts_subaddresses": "บัญชีและที่อยู่ย่อย", - "restore_restore_wallet": "กู้กระเป๋า", - "restore_title_from_seed_keys": "กู้จาก seed/keys", - "restore_description_from_seed_keys": "เรียกกระเป๋าของคุณกลับมาจาก seed/keys ที่คุณได้บันทึกไว้ในที่ปลอดภัย", - "restore_next": "ถัดไป", - "restore_title_from_backup": "กู้จากการสำรองข้อมูล", - "restore_description_from_backup": "คุณสามารถกู้แอพ Cake Wallet ทั้งหมดจากไฟล์สำรองข้อมูลของคุณ", - "restore_seed_keys_restore": "กู้จาก Seed/Keys", - "restore_title_from_seed": "กู้จาก seed", - "restore_description_from_seed": "กู้กระเป๋าของคุณจากรหัสผสมของ 25 คำหรือ 13 คำ", - "restore_title_from_keys": "กู้จาก keys", - "restore_description_from_keys": "กู้กระเป๋าของคุณจากการกดปุ่มที่สร้างขึ้นจาก private keys ของคุณที่บันทึกไว้", - "restore_wallet_name": "ชื่อกระเป๋า", - "restore_address": "ที่อยู่", - "restore_view_key_private": "คีย์สำหรับดู (ส่วนตัว)", - "restore_spend_key_private": "คีย์สำหรับใช้ (ส่วนตัว)", - "restore_recover": "กู้", - "restore_wallet_restore_description": "คำอธิบายการกู้กระเป๋า", - "restore_new_seed": "ซีดใหม่", - "restore_active_seed": "ซีดที่ใช้งานอยู่", - "restore_bitcoin_description_from_seed": "กู้กระเป๋าของคุณจากรหัสผสมของ 24 คำ", - "restore_bitcoin_description_from_keys": "กู้กระเป๋าของคุณจากสตริง WIF ที่สร้างขึ้นจากคีย์ส่วนตัวของคุณ", - "restore_bitcoin_title_from_keys": "กู้จาก WIF", - "restore_from_date_or_blockheight": "โปรดป้อนวันที่หลายวันก่อนที่คุณสร้างกระเป๋านี้ หรือหากคุณรู้ความสูงของบล็อก (blockheight) โปรดป้อนมันแทน", - "seed_reminder": "โปรดเขียนข้อมูลนี้ลงสมุดเพื่อความปลอดภัยหากคุณสูญเสียหรือล้างโทรศัพท์ของคุณ", - "seed_title": "Seed", - "seed_share": "แบ่งปัน seed", - "copy": "คัดลอก", - "seed_language": "ภาษาเมล็ด", - "seed_choose": "เลือกภาษาของ seed", - "seed_language_next": "ถัดไป", - "seed_language_english": "อังกฤษ", - "seed_language_chinese": "จีน", - "seed_language_dutch": "ดัตช์", - "seed_language_german": "เยอรมัน", - "seed_language_japanese": "ญี่ปุ่น", - "seed_language_portuguese": "โปรตุเกส", - "seed_language_russian": "รัสเซีย", - "seed_language_spanish": "สเปน", - "seed_language_french": "ฝรั่งเศส", - "seed_language_italian": "อิตาลี", - "send_title": "ส่ง", - "send_your_wallet": "กระเป๋าของคุณ", - "send_address": "ที่อยู่ ${cryptoCurrency}", - "send_payment_id": "ID การชำระเงิน (ไม่จำเป็น)", + "advanced_settings": "ตั้งค่าขั้นสูง", + "aggressive": "กระตือรือร้นมากเกินไป", + "agree": "ยอมรับ", + "agree_and_continue": "ยอมรับและดำเนินการต่อ", + "agree_to": "การสร้างบัญชีของคุณยอมรับเงื่อนไขของ", "all": "ทั้งหมด", - "send_error_minimum_value": "จำนวนขั้นต่ำของจำนวนเงินคือ 0.01", - "send_error_currency": "สกุลเงินสามารถเป็นเลขเท่านั้น", - "send_estimated_fee": "ค่าธรรมเนียมที่คาดการณ์:", - "send_priority": "ในขณะนี้ค่าธรรมเนียมถูกตั้งค่าเป็นความสำคัญ ${transactionPriority} \nความสำคัญของธุรกรรมสามารถปรับได้ในการตั้งค่า", - "send_creating_transaction": "กำลังสร้างธุรกรรม", - "send_templates": "แม่แบบ", - "send_new": "ใหม่", - "send_amount": "จำนวน:", - "send_fee": "ค่าธรรมเนียม:", - "send_name": "ชื่อ", - "got_it": "เข้าใจ", - "send_sending": "กำลังส่ง...", - "send_success": "คุณได้ส่ง ${crypto} เรียบร้อยแล้ว", - "settings_title": "การตั้งค่า", - "settings_nodes": "จุดเชื่อมต่อ", - "settings_current_node": "จุดเชื่อมต่อปัจจุบัน", - "settings_wallets": "กระเป๋าสตางค์", - "settings_display_balance": "แสดงยอดคงเหลือ", - "settings_currency": "สกุลเงิน", - "settings_fee_priority": "ความสำคัญของค่าธรรมเนียม", - "settings_save_recipient_address": "บันทึกที่อยู่ผู้รับ", - "settings_personal": "ส่วนตัว", - "settings_change_pin": "เปลี่ยน PIN", - "settings_change_language": "เปลี่ยนภาษา", - "settings_allow_biometrical_authentication": "อนุญาตให้ใช้การยืนยันตัวตนทางระบบชีวภาพ", - "settings_dark_mode": "โหมดดำ", - "settings_transactions": "ธุรกรรม", - "settings_trades": "การซื้อขาย", - "settings_display_on_dashboard_list": "แสดงบนรายการแดชบอร์ด", - "settings_all": "ทั้งหมด", - "settings_only_trades": "เฉพาะการซื้อขาย", - "settings_only_transactions": "เฉพาะธุรกรรม", - "settings_none": "ไม่มี", - "settings_support": "สนับสนุน", - "settings_terms_and_conditions": "ข้อกำหนดและเงื่อนไข", - "pin_is_incorrect": "PIN ไม่ถูกต้อง", - "setup_pin": "ตั้งค่า PIN", - "enter_your_pin_again": "ใส่ PIN ของคุณอีกครั้ง", - "setup_successful": "การตั้งค่า PIN ของคุณสำเร็จแล้ว!", - "wallet_keys": "ซีดของกระเป๋า/คีย์", - "wallet_seed": "ซีดของกระเป๋า", - "private_key": "คีย์ส่วนตัว", - "public_key": "คีย์สาธารณะ", - "view_key_private": "คีย์มุมมอง (ส่วนตัว)", - "view_key_public": "คีย์มุมมอง (สาธารณะ)", - "spend_key_private": "คีย์จ่าย (ส่วนตัว)", - "spend_key_public": "คีย์จ่าย (สาธารณะ)", - "copied_key_to_clipboard": "คัดลอก ${key} ไปยัง Clipboard แล้ว", - "new_subaddress_title": "ที่อยู่ใหม่", - "new_subaddress_label_name": "ชื่อป้ายกำกับ", - "new_subaddress_create": "สร้าง", - "address_label": "ป้ายกำกับที่อยู่", - "subaddress_title": "รายการที่อยู่ย่อย", - "trade_details_title": "รายละเอียดการแลกเปลี่ยน", - "trade_details_id": "รหัส", - "trade_details_state": "สถานะ", - "trade_details_fetching": "กำลังเรียกข้อมูล", - "trade_details_provider": "ผู้ให้บริการ", - "trade_details_created_at": "สร้างเมื่อ", - "trade_details_pair": "คู่", - "trade_details_copied": "${title} คัดลอกไปยัง Clipboard", - "trade_history_title": "ประวัติการซื้อขาย", - "transaction_details_title": "รายละเอียดการทำรายการ", - "transaction_details_transaction_id": "ไอดีการทำรายการ", - "transaction_details_date": "วันที่", - "transaction_details_height": "ความสูง", - "transaction_details_amount": "จำนวน", - "transaction_details_fee": "ค่าธรรมเนียม", - "transaction_details_copied": "${title} ถูกคัดลอกไปยังคลิปบอร์ด", - "transaction_details_recipient_address": "ที่อยู่ผู้รับ", - "wallet_list_title": "กระเป๋า Monero", - "wallet_list_create_new_wallet": "สร้างกระเป๋าใหม่", - "wallet_list_edit_wallet": "แก้ไขกระเป๋าสตางค์", - "wallet_list_wallet_name": "ชื่อกระเป๋าสตางค์", - "wallet_list_restore_wallet": "กู้กระเป๋า", - "wallet_list_load_wallet": "โหลดกระเป๋า", - "wallet_list_loading_wallet": "กำลังโหลดกระเป๋า ${wallet_name}", - "wallet_list_failed_to_load": "ไม่สามารถโหลดกระเป๋า ${wallet_name} ได้ ${error}", - "wallet_list_removing_wallet": "กำลังลบกระเป๋า ${wallet_name}", - "wallet_list_failed_to_remove": "ไม่สามารถลบกระเป๋า ${wallet_name} ได้ ${error}", - "widgets_address": "ที่อยู่", - "widgets_restore_from_blockheight": "กู้คืนจากระดับบล็อก", - "widgets_restore_from_date": "กู้คืนจากวันที่", - "widgets_or": "หรือ", - "widgets_seed": "ซีด", - "router_no_route": "ไม่มีเส้นทางที่กำหนดไว้สำหรับ ${name}", - "error_text_account_name": "ชื่อบัญชีสามารถเป็นเพียงตัวอักษรหรือตัวเลขเท่านั้น\nและต้องมีความยาวระหว่าง 1 ถึง 15 ตัวอักษร", - "error_text_contact_name": "ชื่อผู้ติดต่อไม่สามารถมีสัญลักษณ์ ` , '\" ได้\nและต้องมีความยาวระหว่าง 1 ถึง 32 ตัวอักษร", - "error_text_address": "ที่อยู่กระเป๋าจะต้องสอดคล้องกับประเภท\nของเหรียญคริปโตเนียม", - "error_text_node_address": "โปรดป้อนที่อยู่ iPv4", - "error_text_node_port": "พอร์ตโหนดสามารถมีตัวเลขเท่านั้นระหว่าง 0 ถึง 65535", - "error_text_node_proxy_address": "โปรดป้อน <ที่อยู่ IPv4>:<พอร์ต> เช่น 127.0.0.1:9050", - "error_text_payment_id": "Payment ID สามารถมีขนาดระหว่าง 16 ถึง 64 ตัวอักษรตามแบบ hex", - "error_text_xmr": "มูลค่า XMR ไม่สามารถเกินยอดคงเหลือได้\nจำนวนสตริงทศนิยมต้องน้อยกว่าหรือเท่ากับ 12", - "error_text_fiat": "มูลค่าของจำนวนเงินไม่สามารถเกินยอดคงเหลือได้\nจำนวนสตริงทศนิยมต้องน้อยกว่าหรือเท่ากับ 2", - "error_text_subaddress_name": "ชื่อสำหรับที่อยู่ย่อยจะต้องประกอบด้วยตัวอักษร ตัวเลข และสัญลักษณ์ _ - และมีความยาวระหว่าง 1 ถึง 20 ตัวอักษร", - "error_text_amount": "จำนวนจะต้องประกอบด้วยตัวเลขเท่านั้น", - "error_text_wallet_name": "ชื่อกระเป๋าสตางค์จะต้องประกอบด้วยตัวอักษร ตัวเลข และสัญลักษณ์ _ - และมีความยาวระหว่าง 1 ถึง 33 ตัวอักษร", - "error_text_keys": "คีย์ของกระเป๋าสตางค์จะต้องประกอบด้วยตัวอักษรฐาน 16 จำนวน 64 ตัว", - "error_text_crypto_currency": "จำนวนทศนิยมจะต้องน้อยกว่าหรือเท่ากับ 12", - "error_text_minimal_limit": "การซื้อขายกับ ${provider} ไม่สามารถดำเนินการได้ จำนวนน้อยกว่าขั้นต่ำ: ${min} ${currency}", - "error_text_maximum_limit": "การซื้อขายกับ ${provider} ไม่สามารถดำเนินการได้ จำนวนมากกว่าขั้นสูง: ${max} ${currency}", - "error_text_limits_loading_failed": "การซื้อขายกับ ${provider} ไม่สามารถดำเนินการได้ ไม่สามารถโหลดขอบเขตได้", - "error_text_template": "ชื่อแม่แบบและที่อยู่ไม่สามารถมีสัญลักษณ์ ` , '\" และต้องมีความยาวระหว่าง 1 ถึง 106 ตัวอักษร", + "all_trades": "การซื้อขายทั้งหมด", + "all_transactions": "การทำธุรกรรมทั้งหมด", + "alphabetical": "ตามตัวอักษร", + "already_have_account": "มีบัญชีอยู่แล้ว?", + "always": "เสมอ", + "amount": "จำนวน: ", + "amount_is_estimate": "จำนวนที่จะได้รับเป็นการประมาณการ", + "amount_is_guaranteed": "จำนวนที่จะได้รับมีการรับประกัน", + "and": "และ", + "anonpay_description": "สร้าง ${type} ผู้รับสามารถ ${method} ด้วยสกุลเงินดิจิทัลที่รองรับ และคุณจะได้รับเงินในกระเป๋าสตางค์นี้", + "apk_update": "ปรับปรุง APK", + "approve": "อนุมัติ", + "arrive_in_this_address": "${currency} ${tag}จะมาถึงที่อยู่นี้", + "ascending": "จากน้อยไปมาก", + "ask_each_time": "ถามทุกครั้ง", "auth_store_ban_timeout": "หมดเวลาห้าม", "auth_store_banned_for": "ถูกห้ามสำหรับ ", "auth_store_banned_minutes": " นาที", "auth_store_incorrect_password": "รหัสผ่านไม่ถูกต้อง", - "wallet_store_monero_wallet": "กระเป๋า Monero", - "wallet_restoration_store_incorrect_seed_length": "ความยาวของซีดไม่ถูกต้อง", - "full_balance": "ยอดคงเหลือทั้งหมด", - "available_balance": "ยอดคงเหลือที่ใช้งานได้", - "hidden_balance": "ยอดคงเหลือซ่อนอยู่", - "sync_status_syncronizing": "กำลังซิงโครไนซ์", - "sync_status_syncronized": "ซิงโครไนซ์แล้ว", - "sync_status_not_connected": "ไม่ได้เชื่อมต่อ", - "sync_status_starting_sync": "กำลังเริ่มซิงโครไนซ์", - "sync_status_failed_connect": "การเชื่อมต่อล้มเหลว", - "sync_status_connecting": "กำลังเชื่อมต่อ", - "sync_status_connected": "เชื่อมต่อแล้ว", - "sync_status_attempting_sync": "พยายามซิงโครไนซ์", - "transaction_priority_slow": "ช้า", - "transaction_priority_regular": "ปกติ", - "transaction_priority_medium": "ปานกลาง", - "transaction_priority_fast": "เร็ว", - "transaction_priority_fastest": "เร็วที่สุด", - "trade_for_not_created": "การแลกเปลี่ยนสำหรับ ${title} ยังไม่ได้ถูกสร้างขึ้น", - "trade_not_created": "การแลกเปลี่ยนยังไม่ได้ถูกสร้าง", - "trade_id_not_found": "ไม่พบการแลกเปลี่ยน ${tradeId} ของ ${title}", - "trade_not_found": "ไม่พบการแลกเปลี่ยน", - "trade_state_pending": "รอดำเนินการ", - "trade_state_confirming": "กำลังยืนยัน", - "trade_state_trading": "กำลังแลกเปลี่ยน", - "trade_state_traded": "ถูกแลกเปลี่ยน", - "trade_state_complete": "เสร็จสมบูรณ์", - "trade_state_to_be_created": "จะถูกสร้าง", - "trade_state_unpaid": "ยังไม่ได้จ่าย", - "trade_state_underpaid": "จ่ายไม่ครบ", - "trade_state_paid_unconfirmed": "จ่ายแล้วแต่ยังไม่ได้ยืนยัน", - "trade_state_paid": "จ่ายแล้ว", - "trade_state_btc_sent": "ส่ง BTC แล้ว", - "trade_state_timeout": "เวลาหมด", - "trade_state_created": "ถูกสร้าง", - "trade_state_finished": "เสร็จสิ้น", - "change_language": "เปลี่ยนภาษา", - "change_language_to": "เปลี่ยนภาษาเป็น ${language}?", - "paste": "วาง", - "restore_from_seed_placeholder": "โปรดป้อนหรือวาง seed ของคุณที่นี่", - "add_new_word": "เพิ่มคำใหม่", - "incorrect_seed": "ข้อความที่ป้อนไม่ถูกต้อง", - "biometric_auth_reason": "สแกนลายนิ้วมือของคุณเพื่อยืนยันตัวตน", - "version": "เวอร์ชัน ${currentVersion}", - "extracted_address_content": "คุณกำลังจะส่งเงินไปยัง\n${recipient_name}", - "card_address": "ที่อยู่:", - "buy": "ซื้อ", - "sell": "ขาย", - "placeholder_transactions": "ธุรกรรมของคุณจะปรากฏที่นี่", - "placeholder_contacts": "รายชื่อผู้ติดต่อของคุณจะปรากฏที่นี่", - "template": "แบบฟอร์ม", - "confirm_delete_template": "การดำเนินการนี้จะลบแบบฟอร์มนี้ คุณต้องการดำเนินการต่อหรือไม่?", - "confirm_delete_wallet": "การดำเนินการนี้จะลบกระเป๋านี้ คุณต้องการดำเนินการต่อหรือไม่?", - "change_wallet_alert_title": "เปลี่ยนกระเป๋าปัจจุบัน", - "change_wallet_alert_content": "คุณต้องการเปลี่ยนกระเป๋าปัจจุบันเป็น ${wallet_name} หรือไม่?", - "creating_new_wallet": "กำลังสร้างกระเป๋าใหม่", - "creating_new_wallet_error": "ข้อผิดพลาด: ${description}", - "seed_alert_title": "ความสนใจ", - "seed_alert_content": "Seed เป็นเพียงวิธีเดียวที่จะกู้กระเป๋าของคุณ คุณได้เขียนมันขึ้นลงกระดาษหรือไม่?", - "seed_alert_back": "กลับ", - "seed_alert_yes": "ใช่ ฉันได้เขียน", - "exchange_sync_alert_content": "โปรดรอจนกว่ากระเป๋าของคุณจะถูกซิงค์", - "pre_seed_title": "สำคัญ", - "pre_seed_description": "บนหน้าถัดไปคุณจะเห็นชุดของคำ ${words} คำ นี่คือ seed ของคุณที่ไม่ซ้ำใดๆ และเป็นความลับเพียงของคุณ และนี่คือเพียงวิธีเดียวที่จะกู้กระเป๋าของคุณในกรณีที่สูญหายหรือมีปัญหา มันเป็นความรับผิดชอบของคุณเพื่อเขียนมันลงบนกระดาษและจัดเก็บไว้ในที่ปลอดภัยนอกแอป Cake Wallet", - "pre_seed_button_text": "ฉันเข้าใจ แสดง seed ของฉัน", - "xmr_to_error": "ข้อผิดพลาด XMR.TO", - "xmr_to_error_description": "จำนวนไม่ถูกต้อง จำกัดขั้นสูง 8 หลักหลังจุดทศนิยม", - "provider_error": "ข้อผิดพลาด ${provider}", - "use_ssl": "ใช้ SSL", - "trusted": "มั่นคง", - "color_theme": "ธีมสี", - "light_theme": "สว่าง", - "bright_theme": "สดใส", - "dark_theme": "เข้ม", - "enter_your_note": "ใส่บันทึกของคุณ...", - "note_optional": "บันทึก (ไม่จำเป็น)", - "note_tap_to_change": "หมายเหตุ (กดเพื่อเปลี่ยน)", - "view_in_block_explorer": "ดูใน Block Explorer", - "view_transaction_on": "ดูการทำธุรกรรมบน ", - "transaction_key": "รหัสธุรกรรม", - "confirmations": "การยืนยัน", - "recipient_address": "ที่อยู่ผู้รับ", - "extra_id": "ไอดีเพิ่มเติม:", - "destination_tag": "แท็กปลายทาง:", - "memo": "หมายเหตุ:", - "backup": "สำรองข้อมูล", - "change_password": "เปลี่ยนรหัสผ่าน", - "backup_password": "รหัสผ่านสำรองข้อมูล", - "write_down_backup_password": "โปรดจดรหัสผ่านสำรองข้อมูลของคุณลงบนกระดาษ ซึ่งจะใช้ในการนำเข้าไฟล์สำรองข้อมูลของคุณ", - "export_backup": "ส่งออกข้อมูลสำรอง", - "save_backup_password": "โปรดตรวจสอบให้แน่ใจว่าคุณได้บันทึกรหัสผ่านสำรองข้อมูลแล้ว คุณจะไม่สามารถนำเข้าไฟล์สำรองข้อมูลของคุณโดยไม่ใช้รหัสผ่านนั้น", - "backup_file": "ไฟล์สำรองข้อมูล", - "edit_backup_password": "แก้ไขรหัสผ่านสำรอง", - "save_backup_password_alert": "บันทึกรหัสผ่านสำรอง", - "change_backup_password_alert": "ไฟล์สำรองที่ผ่านมาจะไม่สามารถนำเข้าด้วยรหัสผ่านสำรองใหม่ได้ รหัสผ่านสำรองใหม่จะถูกใช้เฉพาะสำหรับไฟล์สำรองใหม่ คุณแน่ใจหรือว่าต้องการเปลี่ยนรหัสผ่านสำรอง?", - "enter_backup_password": "ป้อนรหัสผ่านสำรองที่นี่", - "select_backup_file": "เลือกไฟล์สำรอง", - "import": "นำเข้า", - "please_select_backup_file": "โปรดเลือกไฟล์สำรองและป้อนรหัสผ่านสำรอง", - "fixed_rate": "อัตราคงที่", - "fixed_rate_alert": "คุณจะสามารถป้อนจำนวนที่ได้รับเมื่อเลือกโหมดอัตราคงที่ คุณต้องการสลับไปที่โหมดอัตราคงที่?", - "xlm_extra_info": "โปรดอย่าลืมระบุ Memo ID ในขณะที่ส่งธุรกรรม XLM สำหรับการแลกเปลี่ยน", - "xrp_extra_info": "โปรดอย่าลืมระบุ Destination Tag ในขณะที่ส่งธุรกรรม XRP สำหรับการแลกเปลี่ยน", - "exchange_incorrect_current_wallet_for_xmr": "หากคุณต้องการแลกเปลี่ยน XMR จากยอดคงเหลือ Monero ใน Cake Wallet ของคุณ กรุณาเปลี่ยนเป็นกระเป๋า Monero ก่อน", - "confirmed": "ยอดคงเหลือที่ยืนยันแล้ว", - "unconfirmed": "ยอดคงเหลือที่ไม่ได้รับการยืนยัน", - "displayable": "สามารถแสดงได้", - "submit_request": "ส่งคำขอ", - "buy_alert_content": "ขณะนี้เรารองรับการซื้อ Bitcoin, Ethereum, Litecoin และ Monero เท่านั้น โปรดสร้างหรือเปลี่ยนเป็นกระเป๋าเงิน Bitcoin, Ethereum, Litecoin หรือ Monero", - "sell_alert_content": "ขณะนี้เรารองรับการขาย Bitcoin, Ethereum และ Litecoin เท่านั้น โปรดสร้างหรือเปลี่ยนเป็นกระเป๋าเงิน Bitcoin, Ethereum หรือ Litecoin ของคุณ", - "outdated_electrum_wallet_description": "กระเป๋า Bitcoin ใหม่ที่สร้างใน Cake มี seed ขนาด 24 คำ ซึ่งจำเป็นต้องสร้างกระเป๋า Bitcoin ใหม่และโอนทุกเงินของคุณไปยังกระเป๋าใหม่ขนาด 24 คำ และหยุดใช้กระเป๋าที่มี seed ขนาด 12 คำ กรุณาทำด่วนเพื่อรักษาเงินของคุณ", - "understand": "ฉันเข้าใจ", - "apk_update": "ปรับปรุง APK", - "buy_bitcoin": "ซื้อ Bitcoin", - "buy_with": "ซื้อด้วย", - "moonpay_alert_text": "มูลค่าของจำนวนต้องมากกว่าหรือเท่ากับ ${minAmount} ${fiatCurrency}", - "outdated_electrum_wallet_receive_warning": "หากกระเป๋านี้มีซีดีที่มี 12 คำและถูกสร้างขึ้นใน Cake อย่าโอน Bitcoin เข้ากระเป๋านี้ ทุกจำนวน BTC ที่โอนเข้ากระเป๋านี้อาจสูญหาย สร้างกระเป๋าใหม่ที่มีซีดีที่มี 24 คำ (กดที่เมนูที่มุมขวาบนแล้วเลือก Wallets และเลือก Create New Wallet จากนั้นเลือก Bitcoin) และย้าย BTC ไปที่นั้นทันที กระเป๋า BTC ที่มีซีดีที่มี 24 คำของ Cake ปลอดภัย", - "do_not_show_me": "อย่าแสดงข้อความนี้อีก", - "unspent_coins_title": "เหรียญที่ไม่ได้ใช้", - "unspent_coins_details_title": "รายละเอียดเหรียญที่ไม่ได้ใช้", - "freeze": "ดักจับ", - "frozen": "ถูกดักจับ", - "coin_control": "การควบคุมเหรียญ (ตัวเลือก)", - "address_detected": "ตรวจพบที่อยู่", - "address_from_domain": "ที่อยู่นี้มาจาก ${domain} บน Unstoppable Domains", - "add_receiver": "เพิ่มผู้รับอื่น ๆ (ตัวเลือก)", - "manage_yats": "จัดการ Yats", - "yat_alert_title": "ส่งและรับเหรียญออนไลน์ง่ายขึ้นด้วย Yat", - "yat_alert_content": "ผู้ใช้งาน Cake Wallet สามารถส่งและรับเหรียญออนไลน์ทุกเหรียญที่ชื่นชอบของพวกเขาได้ง่ายขึ้นด้วยชื่อผู้ใช้งานที่พิเศษที่ระบุด้วยอีโมจิ", - "get_your_yat": "รับ Yat ของคุณ", - "connect_an_existing_yat": "เชื่อมต่อ Yat ที่มีอยู่", - "connect_yats": "เชื่อมต่อ Yats", - "yat_address": "ที่อยู่ Yat", - "yat": "Yat", - "address_from_yat": "ที่อยู่นี้มาจาก ${emoji} บน Yat", - "yat_error": "ข้อผิดพลาดของ Yat", - "yat_error_content": "ไม่มีที่อยู่ที่เชื่อมต่อกับ Yat นี้ ลองใช้ Yat อื่น", - "choose_address": "\n\nโปรดเลือกที่อยู่:", - "yat_popup_title": "ที่อยู่กระเป๋าของคุณสามารถถูกอัปโหลดเป็นอิโมจิ", - "yat_popup_content": "ขณะนี้คุณสามารถส่งและรับเหรียญคริปโตใน Cake Wallet ด้วย Yat ของคุณ - ชื่อผู้ใช้ที่สั้นมีอิโมจิ คุณสามารถจัดการ Yat ได้ทุกเวลาบนหน้าจอการตั้งค่า", - "second_intro_title": "อิโมจิที่อยู่เดียวที่จะควบคุมพวกเขาทั้งหมด", - "second_intro_content": "Yat ของคุณเป็นอิโมจิที่อยู่เดียวที่จะแทนที่ทุกที่อยู่และเลขฐานสิบหกของคุณสำหรับเหรียญคริปโตทุกชนิด", - "third_intro_title": "Yat ปฏิบัติตนอย่างดีกับผู้อื่น", - "third_intro_content": "Yat อาศัยอยู่นอก Cake Wallet ด้วย ที่อยู่กระเป๋าใดๆ ทั่วโลกสามารถแทนด้วย Yat ได้อีกด้วย!", - "learn_more": "ศึกษาเพิ่มเติม", - "search": "ค้นหา", - "search_language": "ค้นหาภาษา", - "search_currency": "ค้นหาสกุลเงิน", - "new_template": "แม่แบบใหม่", - "electrum_address_disclaimer": "เราสร้างที่อยู่ใหม่ทุกครั้งที่คุณใช้หนึ่งอย่าง แต่ที่อยู่เก่ายังสามารถใช้ได้ต่อไป", - "wallet_name_exists": "กระเป๋าที่มีชื่อนี้มีอยู่แล้ว โปรดเลือกชื่ออื่นหรือเปลี่ยนชื่อกระเป๋าอื่นก่อน", - "market_place": "ตลาดพื้นที่", - "cake_pay_title": "บัตรของขวัญ Cake Pay", - "cake_pay_subtitle": "ซื้อบัตรของขวัญราคาถูก (สำหรับสหรัฐอเมริกาเท่านั้น)", - "cake_pay_web_cards_title": "Cake Pay Web Cards", - "cake_pay_web_cards_subtitle": "ซื้อบัตรพร้อมเงินระดับโลกและบัตรของขวัญ", - "about_cake_pay": "Cake Pay ช่วยให้คุณสามารถซื้อบัตรของขวัญง่ายๆ ด้วยการใช้สินทรัพย์อนุกรม ซื้อใช้ได้ทันทีกับมากกว่า 150,000 ร้านค้าในสหรัฐอเมริกา", - "cake_pay_account_note": "ลงทะเบียนด้วยอีเมลเพียงอย่างเดียวเพื่อดูและซื้อบัตร บางบัตรอาจมีส่วนลด!", - "already_have_account": "มีบัญชีอยู่แล้ว?", - "create_account": "สร้างบัญชี", - "privacy_policy": "นโยบายความเป็นส่วนตัว", - "welcome_to_cakepay": "ยินดีต้อนรับสู่ Cake Pay!", - "sign_up": "สมัครสมาชิก", - "forgot_password": "ลืมรหัสผ่าน", - "reset_password": "รีเซ็ตรหัสผ่าน", - "gift_cards": "บัตรของขวัญ", - "setup_your_debit_card": "ตั้งค่าบัตรเดบิตของคุณ", - "no_id_required": "ไม่จำเป็นต้องใช้บัตรประจำตัว ฝากเงินและใช้งานได้ทุกที่", - "how_to_use_card": "วิธีใช้บัตรนี้", - "purchase_gift_card": "ซื้อบัตรของขวัญ", - "verification": "การตรวจสอบ", - "fill_code": "โปรดกรอกรหัสยืนยันที่ส่งไปยังอีเมลของคุณ", - "didnt_get_code": "ไม่ได้รับรหัส?", - "resend_code": "โปรดส่งอีกครั้ง", - "debit_card": "บัตรเดบิต", - "cakepay_prepaid_card": "บัตรเดบิตเติมเงินของ CakePay", - "no_id_needed": "ไม่จำเป็นต้องใช้บัตรประชาชน!", - "frequently_asked_questions": "คำถามที่พบบ่อย", - "debit_card_terms": "การเก็บรักษาและใช้หมายเลขบัตรจ่ายเงิน (และข้อมูลประจำตัวที่เกี่ยวข้องกับหมายเลขบัตรจ่ายเงิน) ในกระเป๋าดิจิทัลนี้ จะต้องยึดถือข้อกำหนดและเงื่อนไขของข้อตกลงผู้ใช้บัตรของผู้ถือบัตรที่เกี่ยวข้องกับบัตรผู้ถือบัตร ซึ่งจะมีผลตั้งแต่เวลานั้น", - "please_reference_document": "โปรดอ้างอิงเอกสารด้านล่างสำหรับข้อมูลเพิ่มเติม", - "cardholder_agreement": "ข้อตกลงผู้ใช้บัตร", - "e_sign_consent": "การยอมรับ E-Sign", - "agree_and_continue": "ยอมรับและดำเนินการต่อ", - "email_address": "ที่อยู่อีเมล", - "agree_to": "การสร้างบัญชีของคุณยอมรับเงื่อนไขของ", - "and": "และ", - "enter_code": "กรอกรหัส", - "congratulations": "ขอแสดงความยินดี!", - "you_now_have_debit_card": "ขณะนี้คุณมีบัตรเดบิต", - "min_amount": "จำนวนขั้นต่ำ: ${value}", - "max_amount": "จำนวนสูงสุด: ${value}", - "enter_amount": "กรอกจำนวน", - "billing_address_info": "ถ้าถูกร้องขอที่อยู่สำหรับการวางบิล ให้ใช้ที่อยู่จัดส่งของคุณ", - "order_physical_card": "สั่งซื้อบัตรดิบิต", - "add_value": "เพิ่มมูลค่า", - "activate": "เปิดใช้งาน", - "get_a": "รับ ", - "digital_and_physical_card": "บัตรเดบิตดิจิตอลและบัตรพื้นฐาน", - "get_card_note": "ที่คุณสามารถเติมเงินด้วยสกุลเงินดิจิตอล ไม่จำเป็นต้องใส่ข้อมูลเพิ่มเติม!", - "signup_for_card_accept_terms": "ลงทะเบียนสำหรับบัตรและยอมรับเงื่อนไข", - "add_fund_to_card": "เพิ่มเงินสำรองไว้บนบัตร (ถึง ${value})", - "use_card_info_two": "เงินจะถูกแปลงค่าเป็นดอลลาร์สหรัฐเมื่อถือไว้ในบัญชีสำรองเงิน ไม่ใช่สกุลเงินดิจิตอล", - "use_card_info_three": "ใช้บัตรดิจิตอลออนไลน์หรือผ่านวิธีการชำระเงินแบบไม่ต้องใช้บัตรกระดาษ", - "optionally_order_card": "เลือกเพิ่มสั่งการ์ดจริง", - "hide_details": "ซ่อนรายละเอียด", - "show_details": "แสดงรายละเอียด", - "upto": "สูงสุด ${value}", - "discount": "ประหยัด ${value}%", - "gift_card_amount": "จำนวนบัตรของขวัญ", - "bill_amount": "จำนวนบิล", - "you_pay": "คุณจ่าย", - "tip": "เพิ่มค่าตอบแทน:", - "custom": "กำหนดเอง", - "by_cake_pay": "โดย Cake Pay", - "expires": "หมดอายุ", - "mm": "เดือน", - "yy": "ปี", - "online": "ออนไลน์", - "offline": "ออฟไลน์", - "gift_card_number": "หมายเลขบัตรของขวัญ", - "pin_number": "หมายเลข PIN", - "total_saving": "ประหยัดรวม", - "last_30_days": "30 วันล่าสุด", - "avg_savings": "ประหยัดเฉลี่ย", - "view_all": "ดูทั้งหมด", - "active_cards": "บัตรที่ใช้งานได้", - "delete_account": "ลบบัญชี", - "cards": "บัตร", - "active": "ทำงาน", - "redeemed": "แลกของขวัญ", - "gift_card_balance_note": "บัตรของขวัญที่มียอดคงเหลือจะปรากฏที่นี่", - "gift_card_redeemed_note": "บัตรของขวัญที่คุณแลกไปแล้วจะปรากฏที่นี่", - "logout": "ออกจากระบบ", - "add_tip": "เพิ่มคำแนะนำ", - "percentageOf": "${amount} ของ", - "is_percentage": "เป็น", - "search_category": "ค้นหาหมวดหมู่", - "mark_as_redeemed": "ทำเครื่องหมายว่าเคยใช้แล้ว", - "more_options": "ตัวเลือกเพิ่มเติม", - "awaiting_payment_confirmation": "รอการยืนยันการชำระเงิน", - "transaction_sent_notice": "ถ้าหน้าจอไม่ขึ้นหลังจาก 1 นาทีแล้ว ให้ตรวจสอบ block explorer และอีเมลของคุณ", - "agree": "ยอมรับ", - "in_store": "ในร้าน", - "generating_gift_card": "กำลังสร้างบัตรของขวัญ", - "payment_was_received": "การชำระเงินของคุณได้รับการรับทราบแล้ว", - "proceed_after_one_minute": "หากหน้าจอไม่ดำเนินการหลังจาก 1 นาทีโปรดตรวจสอบอีเมลของคุณ", - "order_id": "เลขที่ออร์เดอร์", - "gift_card_is_generated": "บัตรของขวัญถูกสร้างขึ้น", - "open_gift_card": "เปิดบัตรของขวัญ", - "contact_support": "ติดต่อฝ่ายสนับสนุน", - "gift_cards_unavailable": "บัตรของขวัญจะมีจำหน่ายเฉพาะกับ Monero, Bitcoin, และ Litecoin เท่านั้นในขณะนี้", - "introducing_cake_pay": "ยินดีต้อนรับสู่ Cake Pay!", - "cake_pay_learn_more": "ซื้อและเบิกบัตรของขวัญในแอพพลิเคชันทันที!\nกระแทกขวาไปซ้ายเพื่อเรียนรู้เพิ่มเติม", + "authenticated": "ได้รับการยืนยันสิทธิ์", + "authentication": "การยืนยันสิทธิ์", + "auto_generate_subaddresses": "Auto สร้าง subaddresses", "automatic": "อัตโนมัติ", - "fixed_pair_not_supported": "คู่ความสัมพันธ์ที่ถูกกำหนดไว้นี้ไม่สนับสนุนกับหุ้นที่เลือก", - "variable_pair_not_supported": "คู่ความสัมพันธ์ที่เปลี่ยนแปลงได้นี้ไม่สนับสนุนกับหุ้นที่เลือก", - "none_of_selected_providers_can_exchange": "ไม่มีผู้ให้บริการที่เลือกที่สามารถแลกเปลี่ยนนี้ได้", - "choose_one": "เลือกหนึ่งรายการ", - "choose_from_available_options": "เลือกจากตัวเลือกที่มีอยู่:", - "custom_redeem_amount": "จำนวนรับคืนที่กำหนดเอง", - "add_custom_redemption": "เพิ่มการรับคืนที่กำหนดเอง", - "remaining": "เหลืออยู่", - "delete_wallet": "ลบกระเป๋า", - "delete_wallet_confirm_message": "คุณแน่ใจหรือว่าต้องการลบกระเป๋า${wallet_name}?", - "low_fee": "ค่าธรรมเนียมต่ำ", - "low_fee_alert": "ขณะนี้คุณกำลังใช้ค่าธรรมเนียมของเครือข่ายที่มีความสำคัญต่ำ ซึ่งอาจทำให้เกิดการรอนาน ราคาที่แตกต่างกัน หรือยกเลิกการซื้อขาย เราแนะนำให้กำหนดค่าธรรมเนียมที่สูงขึ้นเพื่อประสบการณ์ที่ดีขึ้น", - "ignor": "ละเว้น", - "use_suggested": "ใช้ที่แนะนำ", - "do_not_share_warning_text": "อย่าแชร์ข้อมูลนี้กับใครอื่น รวมถึงฝ่ายสนับสนุนด้วย\n\nการเงินของคุณอาจถูกขโมยโดยไม่หวังดี!", - "help": "ช่วยเหลือ", - "all_transactions": "การทำธุรกรรมทั้งหมด", - "all_trades": "การซื้อขายทั้งหมด", - "connection_sync": "การเชื่อมต่อและการซิงค์", - "security_and_backup": "ความปลอดภัยและการสำรองข้อมูล", - "create_backup": "สร้างการสำรองข้อมูล", - "privacy_settings": "การตั้งค่าความเป็นส่วนตัว", - "privacy": "ความเป็นส่วนตัว", - "display_settings": "การตั้งค่าการแสดงผล", - "other_settings": "การตั้งค่าอื่น ๆ", - "require_pin_after": "ต้องการ PIN หลังจาก", - "always": "เสมอ", - "minutes_to_pin_code": "${minute} นาที", - "disable_exchange": "ปิดใช้งานการแลกเปลี่ยน", - "advanced_settings": "ตั้งค่าขั้นสูง", - "settings_can_be_changed_later": "การตั้งค่านี้สามารถเปลี่ยนแปลงได้ภายหลังในการตั้งค่าแอพฯ", - "add_custom_node": "เพิ่มจุดโหนดแบบกำหนดเอง", - "disable_fiat": "ปิดใช้งานสกุลเงินตรา", - "fiat_api": "API สกุลเงินตรา", - "disabled": "ปิดใช้งาน", - "enabled": "เปิดใช้งาน", - "tor_only": "Tor เท่านั้น", - "unmatched_currencies": "สกุลเงินของกระเป๋าปัจจุบันของคุณไม่ตรงกับของ QR ที่สแกน", - "orbot_running_alert": "โปรดตรวจสอบว่า Orbot กำลังทำงานก่อนที่จะเชื่อมต่อกับโหนดนี้", - "contact_list_contacts": "ติดต่อ", - "contact_list_wallets": "กระเป๋าเงินของฉัน", - "bitcoin_payments_require_1_confirmation": "การชำระเงินด้วย Bitcoin ต้องการการยืนยัน 1 ครั้ง ซึ่งอาจใช้เวลา 20 นาทีหรือนานกว่านั้น ขอบคุณสำหรับความอดทนของคุณ! คุณจะได้รับอีเมลเมื่อการชำระเงินได้รับการยืนยัน", - "send_to_this_address": "ส่ง ${currency} ${tag}ไปยังที่อยู่นี้", - "arrive_in_this_address": "${currency} ${tag}จะมาถึงที่อยู่นี้", - "do_not_send": "อย่าส่ง", - "error_dialog_content": "อ๊ะ เราพบข้อผิดพลาดบางอย่าง\n\nโปรดส่งรายงานข้อขัดข้องไปยังทีมสนับสนุนของเราเพื่อปรับปรุงแอปพลิเคชันให้ดียิ่งขึ้น", - "scan_qr_code": "สแกนรหัส QR", - "cold_or_recover_wallet": "เพิ่มกระเป๋าเงินเย็นหรือกู้คืนกระเป๋าเงินกระดาษ", - "please_wait": "โปรดรอ", - "sweeping_wallet": "กวาดกระเป๋าสตางค์", - "sweeping_wallet_alert": "การดำเนินการนี้ใช้เวลาไม่นาน อย่าออกจากหน้าจอนี้ มิฉะนั้นเงินที่กวาดไปอาจสูญหาย", - "decimal_places_error": "ทศนิยมมากเกินไป", - "edit_node": "แก้ไขโหนด", - "invoice_details": "รายละเอียดใบแจ้งหนี้", - "donation_link_details": "รายละเอียดลิงค์บริจาค", - "anonpay_description": "สร้าง ${type} ผู้รับสามารถ ${method} ด้วยสกุลเงินดิจิทัลที่รองรับ และคุณจะได้รับเงินในกระเป๋าสตางค์นี้", - "create_invoice": "สร้างใบแจ้งหนี้", - "create_donation_link": "สร้างลิงค์บริจาค", - "optional_email_hint": "อีเมลแจ้งผู้รับเงินเพิ่มเติม", - "optional_description": "คำอธิบายเพิ่มเติม", - "optional_name": "ชื่อผู้รับเพิ่มเติม", - "clearnet_link": "ลิงค์เคลียร์เน็ต", - "onion_link": "ลิงค์หัวหอม", - "settings": "การตั้งค่า", - "sell_monero_com_alert_content": "ยังไม่รองรับการขาย Monero", - "error_text_input_below_minimum_limit": "จำนวนเงินน้อยกว่าขั้นต่ำ", - "error_text_input_above_maximum_limit": "จำนวนเงินสูงกว่าค่าสูงสุด", - "show_market_place": "แสดงตลาดกลาง", - "prevent_screenshots": "ป้องกันภาพหน้าจอและการบันทึกหน้าจอ", - "profile": "ประวัติโดยย่อ", - "close": "ปิด", - "modify_2fa": "แก้ไขเค้ก 2FA", - "disable_cake_2fa": "ปิดการใช้งานเค้ก 2FA", - "question_to_disable_2fa": "คุณแน่ใจหรือไม่ว่าต้องการปิดการใช้งาน Cake 2FA ไม่จำเป็นต้องใช้รหัส 2FA ในการเข้าถึงกระเป๋าเงินและฟังก์ชั่นบางอย่างอีกต่อไป", - "disable": "ปิดการใช้งาน", - "setup_2fa": "ตั้งค่าเค้ก 2FA", - "verify_with_2fa": "ตรวจสอบกับ Cake 2FA", - "totp_code": "รหัสทีโอพี", - "please_fill_totp": "กรุณากรอกรหัส 8 หลักที่อยู่ในอุปกรณ์อื่นของคุณ", - "totp_2fa_success": "ความสำเร็จ! Cake 2FA เปิดใช้งานสำหรับกระเป๋าเงินนี้ อย่าลืมบันทึกเมล็ดช่วยจำของคุณในกรณีที่คุณสูญเสียการเข้าถึงกระเป๋าเงิน", - "totp_verification_success": "การยืนยันสำเร็จ!", - "totp_2fa_failure": "รหัสไม่ถูกต้อง. โปรดลองใช้รหัสอื่นหรือสร้างรหัสลับใหม่ ใช้แอพ 2FA ที่เข้ากันได้ซึ่งรองรับรหัส 8 หลักและ SHA512", - "enter_totp_code": "กรุณาใส่รหัสทีโอที", - "add_secret_code": "หรือเพิ่มรหัสลับนี้ลงในแอปตรวจสอบความถูกต้อง", - "totp_secret_code": "รหัสลับ TOTP", - "setup_2fa_text": "Cake 2FA ทำงานโดยใช้ TOTP เป็นปัจจัยการตรวจสอบสิทธิ์ที่สอง\n\nTOTP ของ Cake 2FA ต้องการการสนับสนุน SHA-512 และ 8 หลัก สิ่งนี้ให้ความปลอดภัยเพิ่มขึ้น ข้อมูลเพิ่มเติมและแอปที่รองรับมีอยู่ในคำแนะนำ", - "setup_totp_recommended": "ตั้งค่า TOTP", - "disable_buy": "ปิดการใช้งานการซื้อ", - "disable_sell": "ปิดการใช้งานการขาย", - "cake_2fa_preset": "เค้ก 2FA ที่ตั้งไว้ล่วงหน้า", - "narrow": "แคบ", - "normal": "ปกติ", - "aggressive": "กระตือรือร้นมากเกินไป", - "require_for_assessing_wallet": "จำเป็นสำหรับการเข้าถึงกระเป๋าเงิน", - "require_for_sends_to_non_contacts": "จำเป็นต้องส่งไปยังผู้ที่ไม่ได้ติดต่อ", - "require_for_sends_to_contacts": "จำเป็นต้องส่งไปยังผู้ติดต่อ", - "require_for_sends_to_internal_wallets": "จำเป็นต้องส่งไปยังกระเป๋าเงินภายใน", - "require_for_exchanges_to_internal_wallets": "ต้องการการแลกเปลี่ยนไปยังกระเป๋าเงินภายใน", - "require_for_adding_contacts": "ต้องการสำหรับการเพิ่มผู้ติดต่อ", - "require_for_creating_new_wallets": "จำเป็นสำหรับการสร้างกระเป๋าเงินใหม่", - "require_for_all_security_and_backup_settings": "จำเป็นสำหรับการตั้งค่าความปลอดภัยและการสำรองข้อมูลทั้งหมด", + "available_balance": "ยอดคงเหลือที่ใช้งานได้", "available_balance_description": "จำนวนเงินที่คุณสามารถใช้ได้ในการซื้อหรือขาย", - "syncing_wallet_alert_title": "กระเป๋าสตางค์ของคุณกำลังซิงค์", - "syncing_wallet_alert_content": "รายการยอดเงินและธุรกรรมของคุณอาจไม่สมบูรณ์จนกว่าจะมีข้อความว่า “ซิงโครไนซ์” ที่ด้านบน คลิก/แตะเพื่อเรียนรู้เพิ่มเติม่", - "home_screen_settings": "การตั้งค่าหน้าจอหลัก", - "sort_by": "เรียงตาม", - "search_add_token": "ค้นหา / เพิ่มโทเค็น", - "edit_token": "แก้ไขโทเค็น", - "warning": "คำเตือน", - "add_token_warning": "ห้ามแก้ไขหรือเพิ่มโทเค็นตามคำแนะนำของนักต้มตุ๋น\nยืนยันที่อยู่โทเค็นกับแหล่งที่มาที่เชื่อถือได้เสมอ!", - "add_token_disclaimer_check": "ฉันได้ยืนยันที่อยู่และข้อมูลของสัญญาโทเค็นโดยใช้แหล่งข้อมูลที่เชื่อถือได้ การเพิ่มข้อมูลที่เป็นอันตรายหรือไม่ถูกต้องอาจทำให้สูญเสียเงินได้", - "token_contract_address": "ที่อยู่สัญญาโทเค็น", - "token_name": "ชื่อโทเค็น เช่น Tether", - "token_symbol": "สัญลักษณ์โทเค็น เช่น USDT", - "token_decimal": "โทเค็นทศนิยม", - "field_required": "ช่องนี้จำเป็น", - "pin_at_top": "ปักหมุด ${token} ที่ด้านบน", - "invalid_input": "อินพุตไม่ถูกต้อง", - "fiat_balance": "เฟียต บาลานซ์", - "gross_balance": "ยอดคงเหลือ", - "alphabetical": "ตามตัวอักษร", - "generate_name": "สร้างชื่อ", + "avg_savings": "ประหยัดเฉลี่ย", + "awaitDAppProcessing": "โปรดรอให้ dApp ประมวลผลเสร็จสิ้น", + "awaiting_payment_confirmation": "รอการยืนยันการชำระเงิน", + "backup": "สำรองข้อมูล", + "backup_file": "ไฟล์สำรองข้อมูล", + "backup_password": "รหัสผ่านสำรองข้อมูล", "balance_page": "หน้ายอดคงเหลือ", - "share": "แบ่งปัน", - "slidable": "เลื่อนได้", - "monero_dark_theme": "ธีมมืด Monero", + "bill_amount": "จำนวนบิล", + "billing_address_info": "ถ้าถูกร้องขอที่อยู่สำหรับการวางบิล ให้ใช้ที่อยู่จัดส่งของคุณ", + "biometric_auth_reason": "สแกนลายนิ้วมือของคุณเพื่อยืนยันตัวตน", "bitcoin_dark_theme": "ธีมมืด Bitcoin", "bitcoin_light_theme": "ธีมแสง Bitcoin", - "high_contrast_theme": "ธีมความคมชัดสูง", - "matrix_green_dark_theme": "ธีมเมทริกซ์สีเขียวเข้ม", - "monero_light_theme": "ธีมแสง Monero", - "manage_nodes": "จัดการโหนด", - "etherscan_history": "ประวัติอีเธอร์สแกน", - "template_name": "ชื่อแม่แบบ", + "bitcoin_payments_require_1_confirmation": "การชำระเงินด้วย Bitcoin ต้องการการยืนยัน 1 ครั้ง ซึ่งอาจใช้เวลา 20 นาทีหรือนานกว่านั้น ขอบคุณสำหรับความอดทนของคุณ! คุณจะได้รับอีเมลเมื่อการชำระเงินได้รับการยืนยัน", + "Blocks_remaining": "${status} บล็อกที่เหลืออยู่", + "bright_theme": "สดใส", + "buy": "ซื้อ", + "buy_alert_content": "ขณะนี้เรารองรับการซื้อ Bitcoin, Ethereum, Litecoin และ Monero เท่านั้น โปรดสร้างหรือเปลี่ยนเป็นกระเป๋าเงิน Bitcoin, Ethereum, Litecoin หรือ Monero", + "buy_bitcoin": "ซื้อ Bitcoin", + "buy_provider_unavailable": "ผู้ให้บริการไม่สามารถใช้งานได้ในปัจจุบัน", + "buy_with": "ซื้อด้วย", + "by_cake_pay": "โดย Cake Pay", + "cake_2fa_preset": "เค้ก 2FA ที่ตั้งไว้ล่วงหน้า", + "cake_pay_account_note": "ลงทะเบียนด้วยอีเมลเพียงอย่างเดียวเพื่อดูและซื้อบัตร บางบัตรอาจมีส่วนลด!", + "cake_pay_learn_more": "ซื้อและเบิกบัตรของขวัญในแอพพลิเคชันทันที!\nกระแทกขวาไปซ้ายเพื่อเรียนรู้เพิ่มเติม", + "cake_pay_subtitle": "ซื้อบัตรของขวัญราคาถูก (สำหรับสหรัฐอเมริกาเท่านั้น)", + "cake_pay_title": "บัตรของขวัญ Cake Pay", + "cake_pay_web_cards_subtitle": "ซื้อบัตรพร้อมเงินระดับโลกและบัตรของขวัญ", + "cake_pay_web_cards_title": "Cake Pay Web Cards", + "cake_wallet": "Cake Wallet", + "cakepay_prepaid_card": "บัตรเดบิตเติมเงินของ CakePay", + "camera_consent": "กล้องของคุณจะถูกนำมาใช้เพื่อจับภาพเพื่อวัตถุประสงค์ในการระบุตัวตนภายใน ${provider} โปรดตรวจสอบนโยบายความเป็นส่วนตัวเพื่อดูรายละเอียด", + "camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป", + "cancel": "ยกเลิก", + "card_address": "ที่อยู่:", + "cardholder_agreement": "ข้อตกลงผู้ใช้บัตร", + "cards": "บัตร", + "chains": "ห่วงโซ่", + "change": "เปลี่ยน", + "change_backup_password_alert": "ไฟล์สำรองที่ผ่านมาจะไม่สามารถนำเข้าด้วยรหัสผ่านสำรองใหม่ได้ รหัสผ่านสำรองใหม่จะถูกใช้เฉพาะสำหรับไฟล์สำรองใหม่ คุณแน่ใจหรือว่าต้องการเปลี่ยนรหัสผ่านสำรอง?", + "change_currency": "เปลี่ยนสกุลเงิน", + "change_current_node": "คุณแน่ใจหรือว่าต้องการเปลี่ยนโหนดปัจจุบันเป็น ${node}?", + "change_current_node_title": "เปลี่ยนโหนดปัจจุบัน", + "change_exchange_provider": "เปลี่ยนผู้ให้บริการแลกเปลี่ยน", + "change_language": "เปลี่ยนภาษา", + "change_language_to": "เปลี่ยนภาษาเป็น ${language}?", + "change_password": "เปลี่ยนรหัสผ่าน", "change_rep": "เปลี่ยนผู้แทน", "change_rep_message": "คุณแน่ใจหรือไม่ว่าต้องการเปลี่ยนตัวแทน", - "unsupported_asset": "เราไม่สนับสนุนการกระทำนี้สำหรับเนื้อหานี้ โปรดสร้างหรือเปลี่ยนเป็นกระเป๋าเงินประเภทสินทรัพย์ที่รองรับ", - "manage_pow_nodes": "จัดการโหนด PoW", - "support_title_live_chat": "การสนับสนุนสด", - "support_description_live_chat": "ฟรีและรวดเร็ว! ตัวแทนฝ่ายสนับสนุนที่ผ่านการฝึกอบรมพร้อมให้ความช่วยเหลือ", - "support_title_guides": "คู่มือกระเป๋าเงินเค้ก", - "support_description_guides": "เอกสารและการสนับสนุนสำหรับปัญหาทั่วไป", - "support_title_other_links": "ลิงค์สนับสนุนอื่น ๆ", - "support_description_other_links": "เข้าร่วมชุมชนของเราหรือเข้าถึงเราพันธมิตรของเราผ่านวิธีการอื่น ๆ", + "change_rep_successful": "เปลี่ยนตัวแทนสำเร็จ", + "change_wallet_alert_content": "คุณต้องการเปลี่ยนกระเป๋าปัจจุบันเป็น ${wallet_name} หรือไม่?", + "change_wallet_alert_title": "เปลี่ยนกระเป๋าปัจจุบัน", + "choose_account": "เลือกบัญชี", + "choose_address": "\n\nโปรดเลือกที่อยู่:", "choose_derivation": "เลือก Wallet Derivation", - "new_first_wallet_text": "ทำให้สกุลเงินดิจิตอลของคุณปลอดภัยได้อย่างง่ายดาย", - "select_destination": "โปรดเลือกปลายทางสำหรับไฟล์สำรอง", - "auto_generate_subaddresses": "Auto สร้าง subaddresses", - "save_to_downloads": "บันทึกลงดาวน์โหลด", - "select_buy_provider_notice": "เลือกผู้ให้บริการซื้อด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการซื้อเริ่มต้นในการตั้งค่าแอป", - "onramper_option_description": "ซื้อ crypto อย่างรวดเร็วด้วยวิธีการชำระเงินจำนวนมาก มีให้บริการในประเทศส่วนใหญ่ สเปรดและค่าธรรมเนียมแตกต่างกันไป", + "choose_from_available_options": "เลือกจากตัวเลือกที่มีอยู่:", + "choose_one": "เลือกหนึ่งรายการ", + "choose_relay": "กรุณาเลือกรีเลย์ที่จะใช้", + "choose_wallet_currency": "โปรดเลือกสกุลเงินของกระเป๋า:", + "clear": "ล้าง", + "clearnet_link": "ลิงค์เคลียร์เน็ต", + "close": "ปิด", + "coin_control": "การควบคุมเหรียญ (ตัวเลือก)", + "cold_or_recover_wallet": "เพิ่มกระเป๋าเงินเย็นหรือกู้คืนกระเป๋าเงินกระดาษ", + "color_theme": "ธีมสี", + "commit_transaction_amount_fee": "ยืนยันธุรกรรม\nจำนวน: ${amount}\nค่าธรรมเนียม: ${fee}", + "confirm": "ยืนยัน", + "confirm_delete_template": "การดำเนินการนี้จะลบแบบฟอร์มนี้ คุณต้องการดำเนินการต่อหรือไม่?", + "confirm_delete_wallet": "การดำเนินการนี้จะลบกระเป๋านี้ คุณต้องการดำเนินการต่อหรือไม่?", + "confirm_sending": "ยืนยันการส่ง", + "confirmations": "การยืนยัน", + "confirmed": "ยอดคงเหลือที่ยืนยันแล้ว", + "confirmed_tx": "ซึ่งยืนยันแล้ว", + "congratulations": "ขอแสดงความยินดี!", + "connect_an_existing_yat": "เชื่อมต่อ Yat ที่มีอยู่", + "connect_yats": "เชื่อมต่อ Yats", + "connection_sync": "การเชื่อมต่อและการซิงค์", + "connectWalletPrompt": "เชื่อมต่อกระเป๋าเงินของคุณด้วย WalletConnect เพื่อทำธุรกรรม", + "contact": "ผู้ติดต่อ", + "contact_list_contacts": "ติดต่อ", + "contact_list_wallets": "กระเป๋าเงินของฉัน", + "contact_name": "ชื่อผู้ติดต่อ", + "contact_support": "ติดต่อฝ่ายสนับสนุน", + "continue_text": "ดำเนินการต่อ", + "contractName": "ชื่อสัญญา", + "contractSymbol": "สัญลักษณ์สัญญา", + "copied_key_to_clipboard": "คัดลอก ${key} ไปยัง Clipboard แล้ว", + "copied_to_clipboard": "คัดลอกไปยังหน่วยความจำของคอมพิวเตอร์", + "copy": "คัดลอก", + "copy_address": "คัดลอกที่อยู่", + "copy_id": "คัดลอก ID", + "copyWalletConnectLink": "คัดลอกลิงก์ WalletConnect จาก dApp แล้ววางที่นี่", + "create_account": "สร้างบัญชี", + "create_backup": "สร้างการสำรองข้อมูล", + "create_donation_link": "สร้างลิงค์บริจาค", + "create_invoice": "สร้างใบแจ้งหนี้", + "create_new": "สร้างกระเป๋าใหม่", + "create_new_account": "สร้างบัญชีใหม่", + "creating_new_wallet": "กำลังสร้างกระเป๋าใหม่", + "creating_new_wallet_error": "ข้อผิดพลาด: ${description}", + "creation_date": "วันที่สร้าง", + "custom": "กำหนดเอง", + "custom_drag": "กำหนดเอง (ค้างและลาก)", + "custom_redeem_amount": "จำนวนรับคืนที่กำหนดเอง", + "dark_theme": "เข้ม", + "debit_card": "บัตรเดบิต", + "debit_card_terms": "การเก็บรักษาและใช้หมายเลขบัตรจ่ายเงิน (และข้อมูลประจำตัวที่เกี่ยวข้องกับหมายเลขบัตรจ่ายเงิน) ในกระเป๋าดิจิทัลนี้ จะต้องยึดถือข้อกำหนดและเงื่อนไขของข้อตกลงผู้ใช้บัตรของผู้ถือบัตรที่เกี่ยวข้องกับบัตรผู้ถือบัตร ซึ่งจะมีผลตั้งแต่เวลานั้น", + "decimal_places_error": "ทศนิยมมากเกินไป", "default_buy_provider": "ผู้ให้บริการซื้อเริ่มต้น", - "ask_each_time": "ถามทุกครั้ง", - "buy_provider_unavailable": "ผู้ให้บริการไม่สามารถใช้งานได้ในปัจจุบัน", - "signTransaction": "ลงนามในการทำธุรกรรม", + "default_sell_provider": "ผู้ให้บริการการขายเริ่มต้น", + "delete": "ลบ", + "delete_account": "ลบบัญชี", + "delete_wallet": "ลบกระเป๋า", + "delete_wallet_confirm_message": "คุณแน่ใจหรือว่าต้องการลบกระเป๋า${wallet_name}?", + "deleteConnectionConfirmationPrompt": "คุณแน่ใจหรือไม่ว่าต้องการลบการเชื่อมต่อไปยัง", + "descending": "ลงมา", + "description": "คำอธิบาย", + "destination_tag": "แท็กปลายทาง:", + "dfx_option_description": "ซื้อ crypto ด้วย EUR และ CHF สูงถึง 990€ โดยไม่มี KYC เพิ่มเติม สำหรับลูกค้ารายย่อยและลูกค้าองค์กรในยุโรป", + "didnt_get_code": "ไม่ได้รับรหัส?", + "digit_pin": "-หลัก PIN", + "digital_and_physical_card": "บัตรเดบิตดิจิตอลและบัตรพื้นฐาน", + "disable": "ปิดการใช้งาน", + "disable_buy": "ปิดการใช้งานการซื้อ", + "disable_cake_2fa": "ปิดการใช้งานเค้ก 2FA", + "disable_exchange": "ปิดใช้งานการแลกเปลี่ยน", + "disable_fiat": "ปิดใช้งานสกุลเงินตรา", + "disable_sell": "ปิดการใช้งานการขาย", + "disabled": "ปิดใช้งาน", + "discount": "ประหยัด ${value}%", + "display_settings": "การตั้งค่าการแสดงผล", + "displayable": "สามารถแสดงได้", + "do_not_have_enough_gas_asset": "คุณมี ${currency} ไม่เพียงพอที่จะทำธุรกรรมกับเงื่อนไขเครือข่ายบล็อคเชนในปัจจุบัน คุณต้องมี ${currency} เพิ่มขึ้นเพื่อชำระค่าธรรมเนียมเครือข่ายบล็อคเชน แม้ว่าคุณจะส่งสินทรัพย์อื่นก็ตาม", + "do_not_send": "อย่าส่ง", + "do_not_share_warning_text": "อย่าแชร์ข้อมูลนี้กับใครอื่น รวมถึงฝ่ายสนับสนุนด้วย\n\nการเงินของคุณอาจถูกขโมยโดยไม่หวังดี!", + "do_not_show_me": "อย่าแสดงข้อความนี้อีก", + "domain_looks_up": "การค้นหาโดเมน", + "donation_link_details": "รายละเอียดลิงค์บริจาค", + "e_sign_consent": "การยอมรับ E-Sign", + "edit": "แก้ไข", + "edit_backup_password": "แก้ไขรหัสผ่านสำรอง", + "edit_node": "แก้ไขโหนด", + "edit_token": "แก้ไขโทเค็น", + "electrum_address_disclaimer": "เราสร้างที่อยู่ใหม่ทุกครั้งที่คุณใช้หนึ่งอย่าง แต่ที่อยู่เก่ายังสามารถใช้ได้ต่อไป", + "email_address": "ที่อยู่อีเมล", + "enabled": "เปิดใช้งาน", + "enter_amount": "กรอกจำนวน", + "enter_backup_password": "ป้อนรหัสผ่านสำรองที่นี่", + "enter_code": "กรอกรหัส", + "enter_seed_phrase": "ป้อนวลีเมล็ดพันธุ์ของคุณ", + "enter_totp_code": "กรุณาใส่รหัสทีโอที", + "enter_your_note": "ใส่บันทึกของคุณ...", + "enter_your_pin": "ใส่ PIN ของคุณ", + "enter_your_pin_again": "ใส่ PIN ของคุณอีกครั้ง", + "enterTokenID": "ป้อนรหัสโทเค็น", + "enterWalletConnectURI": "เข้าสู่ WalletConnect URI", + "error": "ข้อผิดพลาด", + "error_dialog_content": "อ๊ะ เราพบข้อผิดพลาดบางอย่าง\n\nโปรดส่งรายงานข้อขัดข้องไปยังทีมสนับสนุนของเราเพื่อปรับปรุงแอปพลิเคชันให้ดียิ่งขึ้น", + "error_text_account_name": "ชื่อบัญชีสามารถเป็นเพียงตัวอักษรหรือตัวเลขเท่านั้น\nและต้องมีความยาวระหว่าง 1 ถึง 15 ตัวอักษร", + "error_text_address": "ที่อยู่กระเป๋าจะต้องสอดคล้องกับประเภท\nของเหรียญคริปโตเนียม", + "error_text_amount": "จำนวนจะต้องประกอบด้วยตัวเลขเท่านั้น", + "error_text_contact_name": "ชื่อผู้ติดต่อไม่สามารถมีสัญลักษณ์ ` , '\" ได้\nและต้องมีความยาวระหว่าง 1 ถึง 32 ตัวอักษร", + "error_text_crypto_currency": "จำนวนทศนิยมจะต้องน้อยกว่าหรือเท่ากับ 12", + "error_text_fiat": "มูลค่าของจำนวนเงินไม่สามารถเกินยอดคงเหลือได้\nจำนวนสตริงทศนิยมต้องน้อยกว่าหรือเท่ากับ 2", + "error_text_input_above_maximum_limit": "จำนวนเงินสูงกว่าค่าสูงสุด", + "error_text_input_below_minimum_limit": "จำนวนเงินน้อยกว่าขั้นต่ำ", + "error_text_keys": "คีย์ของกระเป๋าสตางค์จะต้องประกอบด้วยตัวอักษรฐาน 16 จำนวน 64 ตัว", + "error_text_limits_loading_failed": "การซื้อขายกับ ${provider} ไม่สามารถดำเนินการได้ ไม่สามารถโหลดขอบเขตได้", + "error_text_maximum_limit": "การซื้อขายกับ ${provider} ไม่สามารถดำเนินการได้ จำนวนมากกว่าขั้นสูง: ${max} ${currency}", + "error_text_minimal_limit": "การซื้อขายกับ ${provider} ไม่สามารถดำเนินการได้ จำนวนน้อยกว่าขั้นต่ำ: ${min} ${currency}", + "error_text_node_address": "โปรดป้อนที่อยู่ iPv4", + "error_text_node_port": "พอร์ตโหนดสามารถมีตัวเลขเท่านั้นระหว่าง 0 ถึง 65535", + "error_text_node_proxy_address": "โปรดป้อน <ที่อยู่ IPv4>:<พอร์ต> เช่น 127.0.0.1:9050", + "error_text_payment_id": "Payment ID สามารถมีขนาดระหว่าง 16 ถึง 64 ตัวอักษรตามแบบ hex", + "error_text_subaddress_name": "ชื่อสำหรับที่อยู่ย่อยจะต้องประกอบด้วยตัวอักษร ตัวเลข และสัญลักษณ์ _ - และมีความยาวระหว่าง 1 ถึง 20 ตัวอักษร", + "error_text_template": "ชื่อแม่แบบและที่อยู่ไม่สามารถมีสัญลักษณ์ ` , '\" และต้องมีความยาวระหว่าง 1 ถึง 106 ตัวอักษร", + "error_text_wallet_name": "ชื่อกระเป๋าสตางค์จะต้องประกอบด้วยตัวอักษร ตัวเลข และสัญลักษณ์ _ - และมีความยาวระหว่าง 1 ถึง 33 ตัวอักษร", + "error_text_xmr": "มูลค่า XMR ไม่สามารถเกินยอดคงเหลือได้\nจำนวนสตริงทศนิยมต้องน้อยกว่าหรือเท่ากับ 12", "errorGettingCredentials": "ล้มเหลว: เกิดข้อผิดพลาดขณะรับข้อมูลรับรอง", "errorSigningTransaction": "เกิดข้อผิดพลาดขณะลงนามธุรกรรม", - "pairingInvalidEvent": "การจับคู่เหตุการณ์ที่ไม่ถูกต้อง", - "chains": "ห่วงโซ่", - "methods": "วิธีการ", - "events": "กิจกรรม", - "reject": "ปฏิเสธ", - "approve": "อนุมัติ", - "expiresOn": "หมดอายุวันที่", - "walletConnect": "WalletConnect", - "nullURIError": "URI เป็นโมฆะ", - "connectWalletPrompt": "เชื่อมต่อกระเป๋าเงินของคุณด้วย WalletConnect เพื่อทำธุรกรรม", - "newConnection": "การเชื่อมต่อใหม่", - "activeConnectionsPrompt": "การเชื่อมต่อที่ใช้งานอยู่จะปรากฏที่นี่", - "deleteConnectionConfirmationPrompt": "คุณแน่ใจหรือไม่ว่าต้องการลบการเชื่อมต่อไปยัง", + "estimated": "ประมาณการ", + "etherscan_history": "ประวัติอีเธอร์สแกน", "event": "เหตุการณ์", - "successful": "ประสบความสำเร็จ", - "wouoldLikeToConnect": "ต้องการเชื่อมต่อ", - "message": "ข้อความ", - "do_not_have_enough_gas_asset": "คุณมี ${currency} ไม่เพียงพอที่จะทำธุรกรรมกับเงื่อนไขเครือข่ายบล็อคเชนในปัจจุบัน คุณต้องมี ${currency} เพิ่มขึ้นเพื่อชำระค่าธรรมเนียมเครือข่ายบล็อคเชน แม้ว่าคุณจะส่งสินทรัพย์อื่นก็ตาม", - "totp_auth_url": "URL การตรวจสอบสิทธิ์ TOTP", - "awaitDAppProcessing": "โปรดรอให้ dApp ประมวลผลเสร็จสิ้น", - "copyWalletConnectLink": "คัดลอกลิงก์ WalletConnect จาก dApp แล้ววางที่นี่", - "enterWalletConnectURI": "เข้าสู่ WalletConnect URI", - "seed_key": "คีย์เมล็ดพันธุ์", - "enter_seed_phrase": "ป้อนวลีเมล็ดพันธุ์ของคุณ", - "change_rep_successful": "เปลี่ยนตัวแทนสำเร็จ", - "add_contact": "เพิ่มผู้ติดต่อ", + "events": "กิจกรรม", + "exchange": "แลกเปลี่ยน", + "exchange_incorrect_current_wallet_for_xmr": "หากคุณต้องการแลกเปลี่ยน XMR จากยอดคงเหลือ Monero ใน Cake Wallet ของคุณ กรุณาเปลี่ยนเป็นกระเป๋า Monero ก่อน", + "exchange_new_template": "เทมเพลทใหม่", "exchange_provider_unsupported": "${providerName} ไม่ได้รับการสนับสนุนอีกต่อไป!", - "domain_looks_up": "การค้นหาโดเมน", - "require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก", - "camera_permission_is_required": "ต้องได้รับอนุญาตจากกล้อง\nโปรดเปิดใช้งานจากการตั้งค่าแอป", - "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง", - "order_by": "สั่งโดย", - "creation_date": "วันที่สร้าง", + "exchange_result_confirm": "โดยกดปุ่มยืนยัน, คุณจะส่ง ${fetchingLabel} ${from} จากกระเป๋าของคุณที่เรียกว่า ${walletName} ไปยังที่อยู่ที่แสดงข้างล่าง หรือคุณสามารถส่งจากกระเป๋าภายนอกไปยังที่อยู่/รหัส QR ด้านล่าง\n\nโปรดกดปุ่มยืนยันเพื่อดำเนินการต่อหรือกลับไปเปลี่ยนจำนวน", + "exchange_result_description": "คุณต้องส่งอย่างน้อย ${fetchingLabel} ${from} ไปยังที่อยู่ที่แสดงบนหน้าถัดไป หากคุณส่งจำนวนน้อยกว่า ${fetchingLabel} ${from} อาจจะไม่ถูกแปลงและอาจไม่ถูกเรียกคืน", + "exchange_result_write_down_ID": "*โปรดคัดลอกหรือเขียนรหัสของคุณด้านบน", + "exchange_result_write_down_trade_id": "โปรดคัดลอกหรือบันทึก ID ของการซื้อขายเพื่อดำเนินการต่อไป", + "exchange_sync_alert_content": "โปรดรอจนกว่ากระเป๋าของคุณจะถูกซิงค์", + "expired": "หมดอายุ", + "expires": "หมดอายุ", + "expiresOn": "หมดอายุวันที่", + "export_backup": "ส่งออกข้อมูลสำรอง", + "extra_id": "ไอดีเพิ่มเติม:", + "extracted_address_content": "คุณกำลังจะส่งเงินไปยัง\n${recipient_name}", + "failed_authentication": "การยืนยันสิทธิ์ล้มเหลว ${state_error}", + "faq": "คำถามที่พบบ่อย", + "fetching": "กำลังโหลด", + "fiat_api": "API สกุลเงินตรา", + "fiat_balance": "เฟียต บาลานซ์", + "field_required": "ช่องนี้จำเป็น", + "fill_code": "โปรดกรอกรหัสยืนยันที่ส่งไปยังอีเมลของคุณ", + "filter_by": "กรองตาม", + "first_wallet_text": "กระเป๋าสตางค์ที่สวยงามสำหรับ Monero, Bitcoin, Ethereum, Litecoin และ Haven", + "fixed_pair_not_supported": "คู่ความสัมพันธ์ที่ถูกกำหนดไว้นี้ไม่สนับสนุนกับหุ้นที่เลือก", + "fixed_rate": "อัตราคงที่", + "fixed_rate_alert": "คุณจะสามารถป้อนจำนวนที่ได้รับเมื่อเลือกโหมดอัตราคงที่ คุณต้องการสลับไปที่โหมดอัตราคงที่?", + "forgot_password": "ลืมรหัสผ่าน", + "freeze": "ดักจับ", + "frequently_asked_questions": "คำถามที่พบบ่อย", + "frozen": "ถูกดักจับ", + "full_balance": "ยอดคงเหลือทั้งหมด", + "generate_name": "สร้างชื่อ", + "generating_gift_card": "กำลังสร้างบัตรของขวัญ", + "get_a": "รับ ", + "get_card_note": "ที่คุณสามารถเติมเงินด้วยสกุลเงินดิจิตอล ไม่จำเป็นต้องใส่ข้อมูลเพิ่มเติม!", + "get_your_yat": "รับ Yat ของคุณ", + "gift_card_amount": "จำนวนบัตรของขวัญ", + "gift_card_balance_note": "บัตรของขวัญที่มียอดคงเหลือจะปรากฏที่นี่", + "gift_card_is_generated": "บัตรของขวัญถูกสร้างขึ้น", + "gift_card_number": "หมายเลขบัตรของขวัญ", + "gift_card_redeemed_note": "บัตรของขวัญที่คุณแลกไปแล้วจะปรากฏที่นี่", + "gift_cards": "บัตรของขวัญ", + "gift_cards_unavailable": "บัตรของขวัญจะมีจำหน่ายเฉพาะกับ Monero, Bitcoin, และ Litecoin เท่านั้นในขณะนี้", + "got_it": "เข้าใจ", + "gross_balance": "ยอดคงเหลือ", "group_by_type": "กลุ่มตามประเภท", - "importNFTs": "นำเข้า NFT", - "noNFTYet": "ยังไม่มี NFT", - "address": "ที่อยู่", - "enterTokenID": "ป้อนรหัสโทเค็น", - "tokenID": "บัตรประจำตัวประชาชน", - "name": "ชื่อ", - "symbol": "เครื่องหมาย", - "seed_phrase_length": "ความยาววลีของเมล็ด", - "unavailable_balance": "ยอดคงเหลือไม่พร้อมใช้งาน", - "unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง", - "unspent_change": "เปลี่ยน", - "tor_connection": "การเชื่อมต่อทอร์", - "setup_warning_2fa_text": "Cake 2FA เป็นการรับรองความถูกต้องครั้งที่สองสำหรับการกระทำบางอย่างในกระเป๋าเงิน มันไม่ปลอดภัยเท่ากับห้องเย็น\n\nหากคุณสูญเสียการเข้าถึงแอป 2FA หรือคีย์ TOTP คุณจะสูญเสียการเข้าถึงกระเป๋าเงินนี้ คุณจะต้องกู้คืนกระเป๋าเงินของคุณจากเมล็ดช่วยในการจำ\n\nการสนับสนุนเค้กจะไม่สามารถช่วยเหลือคุณได้หากคุณสูญเสียการเข้าถึง 2FA หรือเมล็ดช่วยในการจำ\nก่อนใช้ Cake 2FA เราขอแนะนำให้อ่านคำแนะนำโดยละเอียด", - "scan_qr_on_device": "สแกนโค้ด QR นี้บนอุปกรณ์อื่น", + "haven_app": "Haven ของ Cake Wallet", + "haven_app_wallet_text": "กระเป๋าสตางค์ที่สวยงามสำหรับ Haven", + "help": "ช่วยเหลือ", + "hidden_balance": "ยอดคงเหลือซ่อนอยู่", + "hide_details": "ซ่อนรายละเอียด", + "high_contrast_theme": "ธีมความคมชัดสูง", + "home_screen_settings": "การตั้งค่าหน้าจอหลัก", "how_to_use": "วิธีใช้", + "how_to_use_card": "วิธีใช้บัตรนี้", + "id": "ID: ", + "ignor": "ละเว้น", + "import": "นำเข้า", + "importNFTs": "นำเข้า NFT", + "in_store": "ในร้าน", + "incoming": "ขาเข้า", + "incorrect_seed": "ข้อความที่ป้อนไม่ถูกต้อง", + "introducing_cake_pay": "ยินดีต้อนรับสู่ Cake Pay!", + "invalid_input": "อินพุตไม่ถูกต้อง", + "invoice_details": "รายละเอียดใบแจ้งหนี้", + "is_percentage": "เป็น", + "last_30_days": "30 วันล่าสุด", + "learn_more": "ศึกษาเพิ่มเติม", + "light_theme": "สว่าง", + "loading_your_wallet": "กำลังโหลดกระเป๋าของคุณ", + "login": "เข้าสู่ระบบ", + "logout": "ออกจากระบบ", + "low_fee": "ค่าธรรมเนียมต่ำ", + "low_fee_alert": "ขณะนี้คุณกำลังใช้ค่าธรรมเนียมของเครือข่ายที่มีความสำคัญต่ำ ซึ่งอาจทำให้เกิดการรอนาน ราคาที่แตกต่างกัน หรือยกเลิกการซื้อขาย เราแนะนำให้กำหนดค่าธรรมเนียมที่สูงขึ้นเพื่อประสบการณ์ที่ดีขึ้น", + "manage_nodes": "จัดการโหนด", + "manage_pow_nodes": "จัดการโหนด PoW", + "manage_yats": "จัดการ Yats", + "mark_as_redeemed": "ทำเครื่องหมายว่าเคยใช้แล้ว", + "market_place": "ตลาดพื้นที่", + "matrix_green_dark_theme": "ธีมเมทริกซ์สีเขียวเข้ม", + "max_amount": "จำนวนสูงสุด: ${value}", + "max_value": "ขั้นสูง: ${value} ${currency}", + "memo": "หมายเหตุ:", + "message": "ข้อความ", + "methods": "วิธีการ", + "min_amount": "จำนวนขั้นต่ำ: ${value}", + "min_value": "ขั้นต่ำ: ${value} ${currency}", + "minutes_to_pin_code": "${minute} นาที", + "mm": "เดือน", + "modify_2fa": "แก้ไขเค้ก 2FA", + "monero_com": "Monero.com ของ Cake Wallet", + "monero_com_wallet_text": "กระเป๋าสตางค์ที่สวยงามสำหรับ Monero", + "monero_dark_theme": "ธีมมืด Monero", + "monero_light_theme": "ธีมแสง Monero", + "moonpay_alert_text": "มูลค่าของจำนวนต้องมากกว่าหรือเท่ากับ ${minAmount} ${fiatCurrency}", + "more_options": "ตัวเลือกเพิ่มเติม", + "name": "ชื่อ", + "narrow": "แคบ", + "new_first_wallet_text": "ทำให้สกุลเงินดิจิตอลของคุณปลอดภัยได้อย่างง่ายดาย", + "new_node_testing": "การทดสอบโหนดใหม่", + "new_subaddress_create": "สร้าง", + "new_subaddress_label_name": "ชื่อป้ายกำกับ", + "new_subaddress_title": "ที่อยู่ใหม่", + "new_template": "แม่แบบใหม่", + "new_wallet": "กระเป๋าใหม่", + "newConnection": "การเชื่อมต่อใหม่", + "no_id_needed": "ไม่จำเป็นต้องใช้บัตรประชาชน!", + "no_id_required": "ไม่จำเป็นต้องใช้บัตรประจำตัว ฝากเงินและใช้งานได้ทุกที่", + "no_relay_on_domain": "ไม่มีการส่งต่อสำหรับโดเมนของผู้ใช้ หรือการส่งต่อไม่พร้อมใช้งาน กรุณาเลือกรีเลย์ที่จะใช้", + "no_relays": "ไม่มีรีเลย์", + "no_relays_message": "เราพบบันทึก Nostr NIP-05 สำหรับผู้ใช้รายนี้ แต่ไม่มีรีเลย์ใดๆ โปรดแนะนำให้ผู้รับเพิ่มรีเลย์ลงในบันทึก Nostr ของตน", + "node_address": "ที่อยู่โหนด", + "node_connection_failed": "เชื่อมต่อล้มเหลว", + "node_connection_successful": "เชื่อมต่อสำเร็จ", + "node_new": "โหนดใหม่", + "node_port": "พอร์ตโหนด", + "node_reset_settings_title": "รีเซ็ตการตั้งค่า", + "node_test": "ทดสอบ", + "nodes": "โหนด", + "nodes_list_reset_to_default_message": "คุณแน่ใจหรือว่าต้องการรีเซ็ตการตั้งค่าเป็นค่าเริ่มต้น?", + "none_of_selected_providers_can_exchange": "ไม่มีผู้ให้บริการที่เลือกที่สามารถแลกเปลี่ยนนี้ได้", + "noNFTYet": "ยังไม่มี NFT", + "normal": "ปกติ", + "note_optional": "บันทึก (ไม่จำเป็น)", + "note_tap_to_change": "หมายเหตุ (กดเพื่อเปลี่ยน)", + "nullURIError": "URI เป็นโมฆะ", + "offer_expires_in": "ข้อเสนอจะหมดอายุใน: ", + "offline": "ออฟไลน์", + "ok": "ตกลง", + "onion_link": "ลิงค์หัวหอม", + "online": "ออนไลน์", + "onramper_option_description": "ซื้อ crypto อย่างรวดเร็วด้วยวิธีการชำระเงินจำนวนมาก มีให้บริการในประเทศส่วนใหญ่ สเปรดและค่าธรรมเนียมแตกต่างกันไป", + "open_gift_card": "เปิดบัตรของขวัญ", + "optional_description": "คำอธิบายเพิ่มเติม", + "optional_email_hint": "อีเมลแจ้งผู้รับเงินเพิ่มเติม", + "optional_name": "ชื่อผู้รับเพิ่มเติม", + "optionally_order_card": "เลือกเพิ่มสั่งการ์ดจริง", + "orbot_running_alert": "โปรดตรวจสอบว่า Orbot กำลังทำงานก่อนที่จะเชื่อมต่อกับโหนดนี้", + "order_by": "สั่งโดย", + "order_id": "เลขที่ออร์เดอร์", + "order_physical_card": "สั่งซื้อบัตรดิบิต", + "other_settings": "การตั้งค่าอื่น ๆ", + "outdated_electrum_wallet_description": "กระเป๋า Bitcoin ใหม่ที่สร้างใน Cake มี seed ขนาด 24 คำ ซึ่งจำเป็นต้องสร้างกระเป๋า Bitcoin ใหม่และโอนทุกเงินของคุณไปยังกระเป๋าใหม่ขนาด 24 คำ และหยุดใช้กระเป๋าที่มี seed ขนาด 12 คำ กรุณาทำด่วนเพื่อรักษาเงินของคุณ", + "outdated_electrum_wallet_receive_warning": "หากกระเป๋านี้มีซีดีที่มี 12 คำและถูกสร้างขึ้นใน Cake อย่าโอน Bitcoin เข้ากระเป๋านี้ ทุกจำนวน BTC ที่โอนเข้ากระเป๋านี้อาจสูญหาย สร้างกระเป๋าใหม่ที่มีซีดีที่มี 24 คำ (กดที่เมนูที่มุมขวาบนแล้วเลือก Wallets และเลือก Create New Wallet จากนั้นเลือก Bitcoin) และย้าย BTC ไปที่นั้นทันที กระเป๋า BTC ที่มีซีดีที่มี 24 คำของ Cake ปลอดภัย", + "outgoing": "ขาออก", + "overwrite_amount": "เขียนทับจำนวน", + "pairingInvalidEvent": "การจับคู่เหตุการณ์ที่ไม่ถูกต้อง", + "password": "รหัสผ่าน", + "paste": "วาง", + "pause_wallet_creation": "ขณะนี้ความสามารถในการสร้าง Haven Wallet ถูกหยุดชั่วคราว", + "payment_id": "ID การชำระเงิน: ", + "payment_was_received": "การชำระเงินของคุณได้รับการรับทราบแล้ว", + "pending": " (อยู่ระหว่างดำเนินการ)", + "percentageOf": "${amount} ของ", + "pin_at_top": "ปักหมุด ${token} ที่ด้านบน", + "pin_is_incorrect": "PIN ไม่ถูกต้อง", + "pin_number": "หมายเลข PIN", + "placeholder_contacts": "รายชื่อผู้ติดต่อของคุณจะปรากฏที่นี่", + "placeholder_transactions": "ธุรกรรมของคุณจะปรากฏที่นี่", + "please_fill_totp": "กรุณากรอกรหัส 8 หลักที่อยู่ในอุปกรณ์อื่นของคุณ", + "please_make_selection": "โปรดเลือกตามด้านล่างเพื่อสร้างหรือกู้กระเป๋าของคุณ", + "please_reference_document": "โปรดอ้างอิงเอกสารด้านล่างสำหรับข้อมูลเพิ่มเติม", + "please_select": "โปรดเลือก:", + "please_select_backup_file": "โปรดเลือกไฟล์สำรองและป้อนรหัสผ่านสำรอง", + "please_try_to_connect_to_another_node": "โปรดลองเชื่อมต่อกับโหนดอื่น", + "please_wait": "โปรดรอ", + "polygonscan_history": "ประวัติ PolygonScan", + "powered_by": "พัฒนาขึ้นโดย ${title}", + "pre_seed_button_text": "ฉันเข้าใจ แสดง seed ของฉัน", + "pre_seed_description": "บนหน้าถัดไปคุณจะเห็นชุดของคำ ${words} คำ นี่คือ seed ของคุณที่ไม่ซ้ำใดๆ และเป็นความลับเพียงของคุณ และนี่คือเพียงวิธีเดียวที่จะกู้กระเป๋าของคุณในกรณีที่สูญหายหรือมีปัญหา มันเป็นความรับผิดชอบของคุณเพื่อเขียนมันลงบนกระดาษและจัดเก็บไว้ในที่ปลอดภัยนอกแอป Cake Wallet", + "pre_seed_title": "สำคัญ", + "prevent_screenshots": "ป้องกันภาพหน้าจอและการบันทึกหน้าจอ", + "privacy": "ความเป็นส่วนตัว", + "privacy_policy": "นโยบายความเป็นส่วนตัว", + "privacy_settings": "การตั้งค่าความเป็นส่วนตัว", + "private_key": "คีย์ส่วนตัว", + "proceed_after_one_minute": "หากหน้าจอไม่ดำเนินการหลังจาก 1 นาทีโปรดตรวจสอบอีเมลของคุณ", + "profile": "ประวัติโดยย่อ", + "provider_error": "ข้อผิดพลาด ${provider}", + "public_key": "คีย์สาธารณะ", + "purchase_gift_card": "ซื้อบัตรของขวัญ", + "qr_fullscreen": "แตะเพื่อเปิดหน้าจอ QR code แบบเต็มจอ", + "qr_payment_amount": "QR code นี้มีจำนวนการชำระเงิน คุณต้องการเขียนทับค่าปัจจุบันหรือไม่?", + "question_to_disable_2fa": "คุณแน่ใจหรือไม่ว่าต้องการปิดการใช้งาน Cake 2FA ไม่จำเป็นต้องใช้รหัส 2FA ในการเข้าถึงกระเป๋าเงินและฟังก์ชั่นบางอย่างอีกต่อไป", + "receivable_balance": "ยอดลูกหนี้", + "receive": "รับ", + "receive_amount": "จำนวน", + "received": "รับ", + "recipient_address": "ที่อยู่ผู้รับ", + "reconnect": "เชื่อมต่อใหม่", + "reconnect_alert_text": "คุณแน่ใจหรือไม่ว่าต้องการเชื่อมต่อใหม่?", + "reconnection": "เชื่อมต่อใหม่", + "redeemed": "แลกของขวัญ", + "refund_address": "ที่อยู่สำหรับส่งคืน", + "reject": "ปฏิเสธ", + "remaining": "เหลืออยู่", + "remove": "ลบ", + "remove_node": "ลบโหนด", + "remove_node_message": "คุณแน่ใจหรือว่าต้องการลบโหนดที่เลือก?", + "rename": "เปลี่ยนชื่อ", + "require_for_adding_contacts": "ต้องการสำหรับการเพิ่มผู้ติดต่อ", + "require_for_all_security_and_backup_settings": "จำเป็นสำหรับการตั้งค่าความปลอดภัยและการสำรองข้อมูลทั้งหมด", + "require_for_assessing_wallet": "จำเป็นสำหรับการเข้าถึงกระเป๋าเงิน", + "require_for_creating_new_wallets": "จำเป็นสำหรับการสร้างกระเป๋าเงินใหม่", + "require_for_exchanges_to_external_wallets": "จำเป็นต้องแลกเปลี่ยนกับกระเป๋าเงินภายนอก", + "require_for_exchanges_to_internal_wallets": "ต้องการการแลกเปลี่ยนไปยังกระเป๋าเงินภายใน", + "require_for_sends_to_contacts": "จำเป็นต้องส่งไปยังผู้ติดต่อ", + "require_for_sends_to_internal_wallets": "จำเป็นต้องส่งไปยังกระเป๋าเงินภายใน", + "require_for_sends_to_non_contacts": "จำเป็นต้องส่งไปยังผู้ที่ไม่ได้ติดต่อ", + "require_pin_after": "ต้องการ PIN หลังจาก", + "rescan": "สแกนใหม่", + "resend_code": "โปรดส่งอีกครั้ง", + "reset": "รีเซ็ต", + "reset_password": "รีเซ็ตรหัสผ่าน", + "restore_active_seed": "ซีดที่ใช้งานอยู่", + "restore_address": "ที่อยู่", + "restore_bitcoin_description_from_keys": "กู้กระเป๋าของคุณจากสตริง WIF ที่สร้างขึ้นจากคีย์ส่วนตัวของคุณ", + "restore_bitcoin_description_from_seed": "กู้กระเป๋าของคุณจากรหัสผสมของ 24 คำ", + "restore_bitcoin_title_from_keys": "กู้จาก WIF", + "restore_description_from_backup": "คุณสามารถกู้แอพ Cake Wallet ทั้งหมดจากไฟล์สำรองข้อมูลของคุณ", + "restore_description_from_keys": "กู้กระเป๋าของคุณจากการกดปุ่มที่สร้างขึ้นจาก private keys ของคุณที่บันทึกไว้", + "restore_description_from_seed": "กู้กระเป๋าของคุณจากรหัสผสมของ 25 คำหรือ 13 คำ", + "restore_description_from_seed_keys": "เรียกกระเป๋าของคุณกลับมาจาก seed/keys ที่คุณได้บันทึกไว้ในที่ปลอดภัย", + "restore_from_date_or_blockheight": "โปรดป้อนวันที่หลายวันก่อนที่คุณสร้างกระเป๋านี้ หรือหากคุณรู้ความสูงของบล็อก (blockheight) โปรดป้อนมันแทน", + "restore_from_seed_placeholder": "โปรดป้อนหรือวาง seed ของคุณที่นี่", + "restore_new_seed": "ซีดใหม่", + "restore_next": "ถัดไป", + "restore_recover": "กู้", + "restore_restore_wallet": "กู้กระเป๋า", + "restore_seed_keys_restore": "กู้จาก Seed/Keys", + "restore_spend_key_private": "คีย์สำหรับใช้ (ส่วนตัว)", + "restore_title_from_backup": "กู้จากการสำรองข้อมูล", + "restore_title_from_keys": "กู้จาก keys", + "restore_title_from_seed": "กู้จาก seed", + "restore_title_from_seed_keys": "กู้จาก seed/keys", + "restore_view_key_private": "คีย์สำหรับดู (ส่วนตัว)", + "restore_wallet": "กู้กระเป๋า", + "restore_wallet_name": "ชื่อกระเป๋า", + "restore_wallet_restore_description": "คำอธิบายการกู้กระเป๋า", + "router_no_route": "ไม่มีเส้นทางที่กำหนดไว้สำหรับ ${name}", + "save": "บันทึก", + "save_backup_password": "โปรดตรวจสอบให้แน่ใจว่าคุณได้บันทึกรหัสผ่านสำรองข้อมูลแล้ว คุณจะไม่สามารถนำเข้าไฟล์สำรองข้อมูลของคุณโดยไม่ใช้รหัสผ่านนั้น", + "save_backup_password_alert": "บันทึกรหัสผ่านสำรอง", + "save_to_downloads": "บันทึกลงดาวน์โหลด", + "saved_the_trade_id": "ฉันได้บันทึก ID ของการซื้อขายแล้ว", + "scan_qr_code": "สแกนรหัส QR", + "scan_qr_code_to_get_address": "สแกน QR code เพื่อรับที่อยู่", + "scan_qr_on_device": "สแกนโค้ด QR นี้บนอุปกรณ์อื่น", + "search": "ค้นหา", + "search_add_token": "ค้นหา / เพิ่มโทเค็น", + "search_category": "ค้นหาหมวดหมู่", + "search_currency": "ค้นหาสกุลเงิน", + "search_language": "ค้นหาภาษา", + "second_intro_content": "Yat ของคุณเป็นอิโมจิที่อยู่เดียวที่จะแทนที่ทุกที่อยู่และเลขฐานสิบหกของคุณสำหรับเหรียญคริปโตทุกชนิด", + "second_intro_title": "อิโมจิที่อยู่เดียวที่จะควบคุมพวกเขาทั้งหมด", + "security_and_backup": "ความปลอดภัยและการสำรองข้อมูล", + "seed_alert_back": "กลับ", + "seed_alert_content": "Seed เป็นเพียงวิธีเดียวที่จะกู้กระเป๋าของคุณ คุณได้เขียนมันขึ้นลงกระดาษหรือไม่?", + "seed_alert_title": "ความสนใจ", + "seed_alert_yes": "ใช่ ฉันได้เขียน", + "seed_choose": "เลือกภาษาของ seed", "seed_hex_form": "เมล็ดกระเป๋าเงิน (รูปแบบฐานสิบหก)", + "seed_key": "คีย์เมล็ดพันธุ์", + "seed_language": "ภาษาเมล็ด", + "seed_language_chinese": "จีน", + "seed_language_chinese_traditional": "จีน (ดั้งเดิม)", + "seed_language_czech": "ภาษาเช็ก", + "seed_language_dutch": "ดัตช์", + "seed_language_english": "อังกฤษ", + "seed_language_french": "ฝรั่งเศส", + "seed_language_german": "เยอรมัน", + "seed_language_italian": "อิตาลี", + "seed_language_japanese": "ญี่ปุ่น", + "seed_language_korean": "เกาหลี", + "seed_language_next": "ถัดไป", + "seed_language_portuguese": "โปรตุเกส", + "seed_language_russian": "รัสเซีย", + "seed_language_spanish": "สเปน", + "seed_phrase_length": "ความยาววลีของเมล็ด", + "seed_reminder": "โปรดเขียนข้อมูลนี้ลงสมุดเพื่อความปลอดภัยหากคุณสูญเสียหรือล้างโทรศัพท์ของคุณ", + "seed_share": "แบ่งปัน seed", + "seed_title": "Seed", "seedtype": "เมล็ดพันธุ์", "seedtype_legacy": "มรดก (25 คำ)", "seedtype_polyseed": "โพลีส (16 คำ)", - "seed_language_czech": "ภาษาเช็ก", - "seed_language_korean": "เกาหลี", - "seed_language_chinese_traditional": "จีน (ดั้งเดิม)", - "ascending": "จากน้อยไปมาก", - "descending": "ลงมา", - "dfx_option_description": "ซื้อ crypto ด้วย EUR และ CHF สูงถึง 990€ โดยไม่มี KYC เพิ่มเติม สำหรับลูกค้ารายย่อยและลูกค้าองค์กรในยุโรป", - "polygonscan_history": "ประวัติ PolygonScan", - "wallet_seed_legacy": "เมล็ดกระเป๋าเงินมรดก", - "default_sell_provider": "ผู้ให้บริการการขายเริ่มต้น", + "select_backup_file": "เลือกไฟล์สำรอง", + "select_buy_provider_notice": "เลือกผู้ให้บริการซื้อด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการซื้อเริ่มต้นในการตั้งค่าแอป", + "select_destination": "โปรดเลือกปลายทางสำหรับไฟล์สำรอง", "select_sell_provider_notice": "เลือกผู้ให้บริการการขายด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการการขายเริ่มต้นในการตั้งค่าแอป", - "custom_drag": "กำหนดเอง (ค้างและลาก)", + "sell": "ขาย", + "sell_alert_content": "ขณะนี้เรารองรับการขาย Bitcoin, Ethereum และ Litecoin เท่านั้น โปรดสร้างหรือเปลี่ยนเป็นกระเป๋าเงิน Bitcoin, Ethereum หรือ Litecoin ของคุณ", + "sell_monero_com_alert_content": "ยังไม่รองรับการขาย Monero", + "send": "ส่ง", + "send_address": "ที่อยู่ ${cryptoCurrency}", + "send_amount": "จำนวน:", + "send_creating_transaction": "กำลังสร้างธุรกรรม", + "send_error_currency": "สกุลเงินสามารถเป็นเลขเท่านั้น", + "send_error_minimum_value": "จำนวนขั้นต่ำของจำนวนเงินคือ 0.01", + "send_estimated_fee": "ค่าธรรมเนียมที่คาดการณ์:", + "send_fee": "ค่าธรรมเนียม:", + "send_name": "ชื่อ", + "send_new": "ใหม่", + "send_payment_id": "ID การชำระเงิน (ไม่จำเป็น)", + "send_priority": "ในขณะนี้ค่าธรรมเนียมถูกตั้งค่าเป็นความสำคัญ ${transactionPriority} \nความสำคัญของธุรกรรมสามารถปรับได้ในการตั้งค่า", + "send_sending": "กำลังส่ง...", + "send_success": "คุณได้ส่ง ${crypto} เรียบร้อยแล้ว", + "send_templates": "แม่แบบ", + "send_title": "ส่ง", + "send_to_this_address": "ส่ง ${currency} ${tag}ไปยังที่อยู่นี้", + "send_xmr": "ส่ง XMR", + "send_your_wallet": "กระเป๋าของคุณ", + "sending": "กำลังส่ง", + "sent": "ส่ง", + "settings": "การตั้งค่า", + "settings_all": "ทั้งหมด", + "settings_allow_biometrical_authentication": "อนุญาตให้ใช้การยืนยันตัวตนทางระบบชีวภาพ", + "settings_can_be_changed_later": "การตั้งค่านี้สามารถเปลี่ยนแปลงได้ภายหลังในการตั้งค่าแอพฯ", + "settings_change_language": "เปลี่ยนภาษา", + "settings_change_pin": "เปลี่ยน PIN", + "settings_currency": "สกุลเงิน", + "settings_current_node": "จุดเชื่อมต่อปัจจุบัน", + "settings_dark_mode": "โหมดดำ", + "settings_display_balance": "แสดงยอดคงเหลือ", + "settings_display_on_dashboard_list": "แสดงบนรายการแดชบอร์ด", + "settings_fee_priority": "ความสำคัญของค่าธรรมเนียม", + "settings_nodes": "จุดเชื่อมต่อ", + "settings_none": "ไม่มี", + "settings_only_trades": "เฉพาะการซื้อขาย", + "settings_only_transactions": "เฉพาะธุรกรรม", + "settings_personal": "ส่วนตัว", + "settings_save_recipient_address": "บันทึกที่อยู่ผู้รับ", + "settings_support": "สนับสนุน", + "settings_terms_and_conditions": "ข้อกำหนดและเงื่อนไข", + "settings_title": "การตั้งค่า", + "settings_trades": "การซื้อขาย", + "settings_transactions": "ธุรกรรม", + "settings_wallets": "กระเป๋าสตางค์", + "setup_2fa": "ตั้งค่าเค้ก 2FA", + "setup_2fa_text": "Cake 2FA ทำงานโดยใช้ TOTP เป็นปัจจัยการตรวจสอบสิทธิ์ที่สอง\n\nTOTP ของ Cake 2FA ต้องการการสนับสนุน SHA-512 และ 8 หลัก สิ่งนี้ให้ความปลอดภัยเพิ่มขึ้น ข้อมูลเพิ่มเติมและแอปที่รองรับมีอยู่ในคำแนะนำ", + "setup_pin": "ตั้งค่า PIN", + "setup_successful": "การตั้งค่า PIN ของคุณสำเร็จแล้ว!", + "setup_totp_recommended": "ตั้งค่า TOTP", + "setup_warning_2fa_text": "Cake 2FA เป็นการรับรองความถูกต้องครั้งที่สองสำหรับการกระทำบางอย่างในกระเป๋าเงิน มันไม่ปลอดภัยเท่ากับห้องเย็น\n\nหากคุณสูญเสียการเข้าถึงแอป 2FA หรือคีย์ TOTP คุณจะสูญเสียการเข้าถึงกระเป๋าเงินนี้ คุณจะต้องกู้คืนกระเป๋าเงินของคุณจากเมล็ดช่วยในการจำ\n\nการสนับสนุนเค้กจะไม่สามารถช่วยเหลือคุณได้หากคุณสูญเสียการเข้าถึง 2FA หรือเมล็ดช่วยในการจำ\nก่อนใช้ Cake 2FA เราขอแนะนำให้อ่านคำแนะนำโดยละเอียด", + "setup_your_debit_card": "ตั้งค่าบัตรเดบิตของคุณ", + "share": "แบ่งปัน", + "share_address": "แชร์ที่อยู่", + "show_details": "แสดงรายละเอียด", + "show_keys": "แสดงซีด/คีย์", + "show_market_place": "แสดงตลาดกลาง", + "show_seed": "แสดงซีด", + "sign_up": "สมัครสมาชิก", + "signTransaction": "ลงนามในการทำธุรกรรม", + "signup_for_card_accept_terms": "ลงทะเบียนสำหรับบัตรและยอมรับเงื่อนไข", + "slidable": "เลื่อนได้", + "sort_by": "เรียงตาม", + "spend_key_private": "คีย์จ่าย (ส่วนตัว)", + "spend_key_public": "คีย์จ่าย (สาธารณะ)", + "status": "สถานะ: ", + "subaddress_title": "รายการที่อยู่ย่อย", + "subaddresses": "ที่อยู่ย่อย", + "submit_request": "ส่งคำขอ", + "successful": "ประสบความสำเร็จ", + "support_description_guides": "เอกสารและการสนับสนุนสำหรับปัญหาทั่วไป", + "support_description_live_chat": "ฟรีและรวดเร็ว! ตัวแทนฝ่ายสนับสนุนที่ผ่านการฝึกอบรมพร้อมให้ความช่วยเหลือ", + "support_description_other_links": "เข้าร่วมชุมชนของเราหรือเข้าถึงเราพันธมิตรของเราผ่านวิธีการอื่น ๆ", + "support_title_guides": "คู่มือกระเป๋าเงินเค้ก", + "support_title_live_chat": "การสนับสนุนสด", + "support_title_other_links": "ลิงค์สนับสนุนอื่น ๆ", + "sweeping_wallet": "กวาดกระเป๋าสตางค์", + "sweeping_wallet_alert": "การดำเนินการนี้ใช้เวลาไม่นาน อย่าออกจากหน้าจอนี้ มิฉะนั้นเงินที่กวาดไปอาจสูญหาย", + "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง", "switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)", - "receivable_balance": "ยอดลูกหนี้", - "confirmed_tx": "ซึ่งยืนยันแล้ว", + "symbol": "เครื่องหมาย", + "sync_status_attempting_sync": "พยายามซิงโครไนซ์", + "sync_status_connected": "เชื่อมต่อแล้ว", + "sync_status_connecting": "กำลังเชื่อมต่อ", + "sync_status_failed_connect": "การเชื่อมต่อล้มเหลว", + "sync_status_not_connected": "ไม่ได้เชื่อมต่อ", + "sync_status_starting_sync": "กำลังเริ่มซิงโครไนซ์", + "sync_status_syncronized": "ซิงโครไนซ์แล้ว", + "sync_status_syncronizing": "กำลังซิงโครไนซ์", + "syncing_wallet_alert_content": "รายการยอดเงินและธุรกรรมของคุณอาจไม่สมบูรณ์จนกว่าจะมีข้อความว่า “ซิงโครไนซ์” ที่ด้านบน คลิก/แตะเพื่อเรียนรู้เพิ่มเติม่", + "syncing_wallet_alert_title": "กระเป๋าสตางค์ของคุณกำลังซิงค์", + "template": "แบบฟอร์ม", + "template_name": "ชื่อแม่แบบ", + "third_intro_content": "Yat อาศัยอยู่นอก Cake Wallet ด้วย ที่อยู่กระเป๋าใดๆ ทั่วโลกสามารถแทนด้วย Yat ได้อีกด้วย!", + "third_intro_title": "Yat ปฏิบัติตนอย่างดีกับผู้อื่น", + "time": "${minutes}m ${seconds}s", + "tip": "เพิ่มค่าตอบแทน:", + "today": "วันนี้", + "token_contract_address": "ที่อยู่สัญญาโทเค็น", + "token_decimal": "โทเค็นทศนิยม", + "token_name": "ชื่อโทเค็น เช่น Tether", + "token_symbol": "สัญลักษณ์โทเค็น เช่น USDT", + "tokenID": "บัตรประจำตัวประชาชน", + "tor_connection": "การเชื่อมต่อทอร์", + "tor_only": "Tor เท่านั้น", + "total_saving": "ประหยัดรวม", + "totp_2fa_failure": "รหัสไม่ถูกต้อง. โปรดลองใช้รหัสอื่นหรือสร้างรหัสลับใหม่ ใช้แอพ 2FA ที่เข้ากันได้ซึ่งรองรับรหัส 8 หลักและ SHA512", + "totp_2fa_success": "ความสำเร็จ! Cake 2FA เปิดใช้งานสำหรับกระเป๋าเงินนี้ อย่าลืมบันทึกเมล็ดช่วยจำของคุณในกรณีที่คุณสูญเสียการเข้าถึงกระเป๋าเงิน", + "totp_auth_url": "URL การตรวจสอบสิทธิ์ TOTP", + "totp_code": "รหัสทีโอพี", + "totp_secret_code": "รหัสลับ TOTP", + "totp_verification_success": "การยืนยันสำเร็จ!", + "trade_details_copied": "${title} คัดลอกไปยัง Clipboard", + "trade_details_created_at": "สร้างเมื่อ", + "trade_details_fetching": "กำลังเรียกข้อมูล", + "trade_details_id": "รหัส", + "trade_details_pair": "คู่", + "trade_details_provider": "ผู้ให้บริการ", + "trade_details_state": "สถานะ", + "trade_details_title": "รายละเอียดการแลกเปลี่ยน", + "trade_for_not_created": "การแลกเปลี่ยนสำหรับ ${title} ยังไม่ได้ถูกสร้างขึ้น", + "trade_history_title": "ประวัติการซื้อขาย", + "trade_id": "ID การซื้อขาย:", + "trade_id_not_found": "ไม่พบการแลกเปลี่ยน ${tradeId} ของ ${title}", + "trade_is_powered_by": "การซื้อขายนี้จัดสร้างโดย ${provider}", + "trade_not_created": "การแลกเปลี่ยนยังไม่ได้ถูกสร้าง", + "trade_not_found": "ไม่พบการแลกเปลี่ยน", + "trade_state_btc_sent": "ส่ง BTC แล้ว", + "trade_state_complete": "เสร็จสมบูรณ์", + "trade_state_confirming": "กำลังยืนยัน", + "trade_state_created": "ถูกสร้าง", + "trade_state_finished": "เสร็จสิ้น", + "trade_state_paid": "จ่ายแล้ว", + "trade_state_paid_unconfirmed": "จ่ายแล้วแต่ยังไม่ได้ยืนยัน", + "trade_state_pending": "รอดำเนินการ", + "trade_state_timeout": "เวลาหมด", + "trade_state_to_be_created": "จะถูกสร้าง", + "trade_state_traded": "ถูกแลกเปลี่ยน", + "trade_state_trading": "กำลังแลกเปลี่ยน", + "trade_state_underpaid": "จ่ายไม่ครบ", + "trade_state_unpaid": "ยังไม่ได้จ่าย", + "trades": "การซื้อขาย", + "transaction_details_amount": "จำนวน", + "transaction_details_copied": "${title} ถูกคัดลอกไปยังคลิปบอร์ด", + "transaction_details_date": "วันที่", + "transaction_details_fee": "ค่าธรรมเนียม", + "transaction_details_height": "ความสูง", + "transaction_details_recipient_address": "ที่อยู่ผู้รับ", "transaction_details_source_address": "ที่อยู่แหล่งกำเนิด", - "pause_wallet_creation": "ขณะนี้ความสามารถในการสร้าง Haven Wallet ถูกหยุดชั่วคราว", - "contractName": "ชื่อสัญญา", - "contractSymbol": "สัญลักษณ์สัญญา", - "description": "คำอธิบาย", - "camera_consent": "กล้องของคุณจะถูกนำมาใช้เพื่อจับภาพเพื่อวัตถุประสงค์ในการระบุตัวตนภายใน ${provider} โปรดตรวจสอบนโยบายความเป็นส่วนตัวเพื่อดูรายละเอียด", - "no_relays": "ไม่มีรีเลย์", - "choose_relay": "กรุณาเลือกรีเลย์ที่จะใช้", - "no_relays_message": "เราพบบันทึก Nostr NIP-05 สำหรับผู้ใช้รายนี้ แต่ไม่มีรีเลย์ใดๆ โปรดแนะนำให้ผู้รับเพิ่มรีเลย์ลงในบันทึก Nostr ของตน", - "no_relay_on_domain": "ไม่มีการส่งต่อสำหรับโดเมนของผู้ใช้ หรือการส่งต่อไม่พร้อมใช้งาน กรุณาเลือกรีเลย์ที่จะใช้" -} + "transaction_details_title": "รายละเอียดการทำรายการ", + "transaction_details_transaction_id": "ไอดีการทำรายการ", + "transaction_key": "รหัสธุรกรรม", + "transaction_priority_fast": "เร็ว", + "transaction_priority_fastest": "เร็วที่สุด", + "transaction_priority_medium": "ปานกลาง", + "transaction_priority_regular": "ปกติ", + "transaction_priority_slow": "ช้า", + "transaction_sent": "ธุรกรรมถูกส่ง!", + "transaction_sent_notice": "ถ้าหน้าจอไม่ขึ้นหลังจาก 1 นาทีแล้ว ให้ตรวจสอบ block explorer และอีเมลของคุณ", + "transactions": "ธุรกรรม", + "transactions_by_date": "ธุรกรรมตามวันที่", + "trusted": "มั่นคง", + "unavailable_balance": "ยอดคงเหลือไม่พร้อมใช้งาน", + "unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง", + "unconfirmed": "ยอดคงเหลือที่ไม่ได้รับการยืนยัน", + "understand": "ฉันเข้าใจ", + "unmatched_currencies": "สกุลเงินของกระเป๋าปัจจุบันของคุณไม่ตรงกับของ QR ที่สแกน", + "unspent_change": "เปลี่ยน", + "unspent_coins_details_title": "รายละเอียดเหรียญที่ไม่ได้ใช้", + "unspent_coins_title": "เหรียญที่ไม่ได้ใช้", + "unsupported_asset": "เราไม่สนับสนุนการกระทำนี้สำหรับเนื้อหานี้ โปรดสร้างหรือเปลี่ยนเป็นกระเป๋าเงินประเภทสินทรัพย์ที่รองรับ", + "upto": "สูงสุด ${value}", + "use": "สลับไปที่ ", + "use_card_info_three": "ใช้บัตรดิจิตอลออนไลน์หรือผ่านวิธีการชำระเงินแบบไม่ต้องใช้บัตรกระดาษ", + "use_card_info_two": "เงินจะถูกแปลงค่าเป็นดอลลาร์สหรัฐเมื่อถือไว้ในบัญชีสำรองเงิน ไม่ใช่สกุลเงินดิจิตอล", + "use_ssl": "ใช้ SSL", + "use_suggested": "ใช้ที่แนะนำ", + "variable_pair_not_supported": "คู่ความสัมพันธ์ที่เปลี่ยนแปลงได้นี้ไม่สนับสนุนกับหุ้นที่เลือก", + "verification": "การตรวจสอบ", + "verify_with_2fa": "ตรวจสอบกับ Cake 2FA", + "version": "เวอร์ชัน ${currentVersion}", + "view_all": "ดูทั้งหมด", + "view_in_block_explorer": "ดูใน Block Explorer", + "view_key_private": "คีย์มุมมอง (ส่วนตัว)", + "view_key_public": "คีย์มุมมอง (สาธารณะ)", + "view_transaction_on": "ดูการทำธุรกรรมบน ", + "wallet_keys": "ซีดของกระเป๋า/คีย์", + "wallet_list_create_new_wallet": "สร้างกระเป๋าใหม่", + "wallet_list_edit_wallet": "แก้ไขกระเป๋าสตางค์", + "wallet_list_failed_to_load": "ไม่สามารถโหลดกระเป๋า ${wallet_name} ได้ ${error}", + "wallet_list_failed_to_remove": "ไม่สามารถลบกระเป๋า ${wallet_name} ได้ ${error}", + "wallet_list_load_wallet": "โหลดกระเป๋า", + "wallet_list_loading_wallet": "กำลังโหลดกระเป๋า ${wallet_name}", + "wallet_list_removing_wallet": "กำลังลบกระเป๋า ${wallet_name}", + "wallet_list_restore_wallet": "กู้กระเป๋า", + "wallet_list_title": "กระเป๋า Monero", + "wallet_list_wallet_name": "ชื่อกระเป๋าสตางค์", + "wallet_menu": "เมนู", + "wallet_name": "ชื่อกระเป๋า", + "wallet_name_exists": "กระเป๋าที่มีชื่อนี้มีอยู่แล้ว โปรดเลือกชื่ออื่นหรือเปลี่ยนชื่อกระเป๋าอื่นก่อน", + "wallet_restoration_store_incorrect_seed_length": "ความยาวของซีดไม่ถูกต้อง", + "wallet_seed": "ซีดของกระเป๋า", + "wallet_seed_legacy": "เมล็ดกระเป๋าเงินมรดก", + "wallet_store_monero_wallet": "กระเป๋า Monero", + "walletConnect": "WalletConnect", + "wallets": "กระเป๋า", + "warning": "คำเตือน", + "welcome": "ยินดีต้อนรับสู่", + "welcome_to_cakepay": "ยินดีต้อนรับสู่ Cake Pay!", + "widgets_address": "ที่อยู่", + "widgets_or": "หรือ", + "widgets_restore_from_blockheight": "กู้คืนจากระดับบล็อก", + "widgets_restore_from_date": "กู้คืนจากวันที่", + "widgets_seed": "ซีด", + "wouoldLikeToConnect": "ต้องการเชื่อมต่อ", + "write_down_backup_password": "โปรดจดรหัสผ่านสำรองข้อมูลของคุณลงบนกระดาษ ซึ่งจะใช้ในการนำเข้าไฟล์สำรองข้อมูลของคุณ", + "xlm_extra_info": "โปรดอย่าลืมระบุ Memo ID ในขณะที่ส่งธุรกรรม XLM สำหรับการแลกเปลี่ยน", + "xmr_available_balance": "ยอดคงเหลือที่สามารถใช้งานได้", + "xmr_full_balance": "ยอดคงเหลือแบบเต็ม", + "xmr_hidden": "ซ่อน", + "xmr_to_error": "ข้อผิดพลาด XMR.TO", + "xmr_to_error_description": "จำนวนไม่ถูกต้อง จำกัดขั้นสูง 8 หลักหลังจุดทศนิยม", + "xrp_extra_info": "โปรดอย่าลืมระบุ Destination Tag ในขณะที่ส่งธุรกรรม XRP สำหรับการแลกเปลี่ยน", + "yat": "Yat", + "yat_address": "ที่อยู่ Yat", + "yat_alert_content": "ผู้ใช้งาน Cake Wallet สามารถส่งและรับเหรียญออนไลน์ทุกเหรียญที่ชื่นชอบของพวกเขาได้ง่ายขึ้นด้วยชื่อผู้ใช้งานที่พิเศษที่ระบุด้วยอีโมจิ", + "yat_alert_title": "ส่งและรับเหรียญออนไลน์ง่ายขึ้นด้วย Yat", + "yat_error": "ข้อผิดพลาดของ Yat", + "yat_error_content": "ไม่มีที่อยู่ที่เชื่อมต่อกับ Yat นี้ ลองใช้ Yat อื่น", + "yat_popup_content": "ขณะนี้คุณสามารถส่งและรับเหรียญคริปโตใน Cake Wallet ด้วย Yat ของคุณ - ชื่อผู้ใช้ที่สั้นมีอิโมจิ คุณสามารถจัดการ Yat ได้ทุกเวลาบนหน้าจอการตั้งค่า", + "yat_popup_title": "ที่อยู่กระเป๋าของคุณสามารถถูกอัปโหลดเป็นอิโมจิ", + "yesterday": "เมื่อวาน", + "you_now_have_debit_card": "ขณะนี้คุณมีบัตรเดบิต", + "you_pay": "คุณจ่าย", + "you_will_get": "แปลงเป็น", + "you_will_send": "แปลงจาก", + "yy": "ปี", + "zzzz": "zzzz" +} \ No newline at end of file diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index a8ec4df3e..ce3f0123c 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -1,773 +1,774 @@ { - "welcome": "Maligayang pagdating sa", - "cake_wallet": "Cake wallet", - "first_wallet_text": "Kahanga -hangang pitaka para sa Monero, Bitcoin, Ethereum, Litecoin, at Haven", - "please_make_selection": "Mangyaring gumawa ng isang pagpipilian sa ibaba upang lumikha o mabawi ang iyong pitaka.", - "create_new": "Lumikha ng bagong pitaka", - "restore_wallet": "Ibalik ang pitaka", - "monero_com": "Monero.com sa pamamagitan ng cake wallet", - "monero_com_wallet_text": "Galing ng pitaka para sa Monero", - "haven_app": "Haven sa pamamagitan ng cake wallet", - "haven_app_wallet_text": "Galing ng pitaka para sa Haven", - "accounts": "Mga Account", - "edit": "I -edit", + "about_cake_pay": "Pinapayagan ka ng cake Pay na madaling bumili ng mga kard ng regalo na may mga virtual na pag -aari, gastusin agad sa higit sa 150,000 mga mangangalakal sa Estados Unidos.", "account": "Account", + "accounts": "Mga Account", + "accounts_subaddresses": "Mga Account at Subaddresses", + "activate": "Buhayin", + "active": "Aktibo", + "active_cards": "Mga aktibong kard", + "activeConnectionsPrompt": "Lalabas dito ang mga aktibong koneksyon", "add": "Idagdag", + "add_contact": "Magdagdag ng contact", + "add_custom_node": "Magdagdag ng bagong pasadyang node", + "add_custom_redemption": "Magdagdag ng pasadyang pagtubos", + "add_fund_to_card": "Magdagdag ng prepaid na pondo sa mga kard (hanggang sa ${value})", + "add_new_node": "Magdagdag ng bagong node", + "add_new_word": "Magdagdag ng bagong salita", + "add_receiver": "Magdagdag ng isa pang tatanggap (opsyonal)", + "add_secret_code": "O, idagdag ang sikretong code na ito sa isang authenticator app", + "add_tip": "Magdagdag ng tip", + "add_token_disclaimer_check": "Kinumpirma ko ang address ng kontrata ng token at impormasyon gamit ang isang kagalang -galang na mapagkukunan. Ang pagdaragdag ng nakakahamak o hindi tamang impormasyon ay maaaring magresulta sa pagkawala ng mga pondo.", + "add_token_warning": "Huwag i -edit o magdagdag ng mga token tulad ng itinuro ng mga scammers.\nLaging kumpirmahin ang mga token address na may mga kagalang -galang na mapagkukunan!", + "add_value": "Magdagdag ng halaga", + "address": "Address", "address_book": "Address Book", - "contact": "Makipag -ugnay", - "please_select": "Pakipili:", - "cancel": "Kanselahin", - "ok": "Ok", - "contact_name": "pangalan ng contact", - "reset": "I -reset", - "save": "I -save", + "address_book_menu": "Address Book", + "address_detected": "Nakita ang address", + "address_from_domain": "Ang address na ito ay mula sa ${domain} sa mga hindi mapigilan na mga domain", + "address_from_yat": "Ang address na ito ay mula sa ${emoji} sa yat", + "address_label": "Address Label", "address_remove_contact": "Alisin ang contact", "address_remove_content": "Sigurado ka bang nais mong alisin ang napiling contact?", - "authenticated": "Napatunayan", - "authentication": "Pagpapatunay", - "failed_authentication": "Nabigong pagpapatunay. ${state_error}", - "wallet_menu": "Menu", - "Blocks_remaining": "Ang natitirang ${status} ay natitira", - "please_try_to_connect_to_another_node": "Mangyaring subukang kumonekta sa isa pang node", - "xmr_hidden": "Nakatago", - "xmr_available_balance": "Magagamit na balanse", - "xmr_full_balance": "Buong balanse", - "send": "Ipadala", - "receive": "Tumanggap", - "transactions": "Mga Transaksyon", - "incoming": "Papasok", - "outgoing": "Palabas", - "transactions_by_date": "Mga Transaksyon ayon sa Petsa", - "trades": "Trading", - "filter_by": "Filter ni", - "today": "Ngayon", - "yesterday": "Kahapon", - "received": "Natanggap", - "sent": "Ipinadala", - "pending": "(Pending)", - "rescan": "Rescan", - "reconnect": "Kumonekta muli", - "wallets": "Wallets", - "show_seed": "Magpakita ng binhi", - "show_keys": "Ipakita ang mga binhi/susi", - "address_book_menu": "Address Book", - "reconnection": "Pag -ugnay muli", - "reconnect_alert_text": "Sigurado ka bang nais mong muling kumonekta?", - "exchange": "Palitan", - "clear": "Malinaw", - "refund_address": "Refund address", - "change_exchange_provider": "Baguhin ang tagapagbigay ng palitan", - "you_will_send": "I -convert mula sa", - "you_will_get": "Mag -convert sa", - "amount_is_guaranteed": "Ang natanggap na halaga ay garantisado", - "amount_is_estimate": "Ang natanggap na halaga ay isang pagtatantya", - "powered_by": "Pinapagana ng ${title}", - "error": "Error", - "estimated": "Tinatayang", - "min_value": "Min: ${value} ${currency}", - "max_value": "Max: ${value} ${currency}", - "change_currency": "Baguhin ang pera", - "overwrite_amount": "Overwrite na halaga", - "qr_payment_amount": "Ang QR code na ito ay naglalaman ng isang halaga ng pagbabayad. Nais mo bang i -overwrite ang kasalukuyang halaga?", - "copy_id": "Kopyahin ang id", - "exchange_result_write_down_trade_id": "Mangyaring kopyahin o isulat ang trade ID upang magpatuloy.", - "trade_id": "Trade ID:", - "copied_to_clipboard": "Kinopya sa clipboard", - "saved_the_trade_id": "Nai -save ko ang trade ID", - "fetching": "Pagkuha", - "id": "ID:", - "amount": "Halaga:", - "payment_id": "Payment ID:", - "status": "Katayuan:", - "offer_expires_in": "Mag -expire ang alok sa:", - "trade_is_powered_by": "Ang kalakalan na ito ay pinalakas ng ${provider}", - "copy_address": "Kopyahin ang address", - "exchange_result_confirm": "Sa pamamagitan ng pagpindot ng kumpirmahin, magpapadala ka ng ${fetchingLabel} ${from} mula sa iyong pitaka na tinatawag na ${walletName} sa address na ipinakita sa ibaba. O maaari kang magpadala mula sa iyong panlabas na pitaka sa ibaba address/qr code.\n\nMangyaring pindutin ang kumpirmahin na magpatuloy o bumalik upang baguhin ang mga halaga.", - "exchange_result_description": "Dapat kang magpadala ng isang minimum na ${fetchingLabel} ${from} hanggang sa address na ipinakita sa susunod na pahina. Kung nagpapadala ka ng isang halaga na mas mababa kaysa sa ${fetchingLabel} ${from} maaaring hindi ito ma -convert at maaaring hindi ito ibabalik.", - "exchange_result_write_down_ID": "*Mangyaring kopyahin o isulat ang iyong ID na ipinakita sa itaas.", - "confirm": "Kumpirmahin", - "confirm_sending": "Kumpirmahin ang pagpapadala", - "commit_transaction_amount_fee": "Gumawa ng transaksyon\nHalaga: ${amount}\nBayad: ${fee}", - "sending": "Pagpapadala", - "transaction_sent": "Ipinadala ang transaksyon!", - "expired": "Nag -expire", - "time": "${minutes} m ${seconds} s", - "send_xmr": "Magpadala ng XMR", - "exchange_new_template": "Bagong template", - "faq": "FAQ", - "enter_your_pin": "Ipasok ang iyong pin", - "loading_your_wallet": "Naglo -load ng iyong pitaka", - "new_wallet": "Bagong pitaka", - "wallet_name": "Pangalan ng Wallet", - "continue_text": "Magpatuloy", - "choose_wallet_currency": "Mangyaring piliin ang Pera ng Wallet:", - "node_new": "Bagong node", - "node_address": "Node address", - "node_port": "Node port", - "login": "Mag log in", - "password": "Password", - "nodes": "Node", - "node_reset_settings_title": "I -reset ang Mga Setting", - "nodes_list_reset_to_default_message": "Sigurado ka bang nais mong i -reset ang mga setting upang default?", - "change_current_node": "Sigurado ka bang baguhin ang kasalukuyang node sa ${node}?", - "change": "Palitan", - "remove_node": "Alisin ang node", - "remove_node_message": "Sigurado ka bang nais mong alisin ang napiling node?", - "remove": "Alisin", - "delete": "Tanggalin", - "add_new_node": "Magdagdag ng bagong node", - "change_current_node_title": "Baguhin ang kasalukuyang node", - "node_test": "Pagsusulit", - "node_connection_successful": "Ang koneksyon ay matagumpay", - "node_connection_failed": "Nabigo ang koneksyon", - "new_node_testing": "Bagong pagsubok sa node", - "use": "Lumipat sa", - "digit_pin": "-digit pin", - "share_address": "Ibahagi ang address", - "receive_amount": "Halaga", - "subaddresses": "Mga Subaddresses", "addresses": "Mga address", - "scan_qr_code_to_get_address": "I -scan ang QR code upang makuha ang address", - "qr_fullscreen": "Tapikin upang buksan ang buong screen QR code", - "rename": "Palitan ang pangalan", - "choose_account": "Pumili ng account", - "create_new_account": "Lumikha ng Bagong Account", - "accounts_subaddresses": "Mga Account at Subaddresses", - "restore_restore_wallet": "Ibalik ang pitaka", - "restore_title_from_seed_keys": "Ibalik mula sa mga binhi/susi", - "restore_description_from_seed_keys": "Ibalik ang iyong pitaka mula sa mga binhi/susi na na -save mo upang ma -secure ang lugar", - "restore_next": "Susunod", - "restore_title_from_backup": "Ibalik mula sa backup", - "restore_description_from_backup": "Maaari mong ibalik ang buong cake wallet app mula sa iyong back-up file", - "restore_seed_keys_restore": "Ibinalik ang mga binhi/susi", - "restore_title_from_seed": "Ibalik mula sa binhi", - "restore_description_from_seed": "Ibalik ang iyong pitaka mula sa alinman sa 25 salita o 13 na code ng kombinasyon ng salita", - "restore_title_from_keys": "Ibalik mula sa mga susi", - "restore_description_from_keys": "Ibalik ang iyong pitaka mula sa nabuong mga keystroke na na -save mula sa iyong mga pribadong susi", - "restore_wallet_name": "Pangalan ng Wallet", - "restore_address": "Address", - "restore_view_key_private": "Tingnan ang Key (Pribado)", - "restore_spend_key_private": "Gumastos ng susi (pribado)", - "restore_recover": "Ibalik", - "restore_wallet_restore_description": "Paglalarawan ng Wallet", - "restore_new_seed": "Bagong binhi", - "restore_active_seed": "Aktibong binhi", - "restore_bitcoin_description_from_seed": "Ibalik ang iyong pitaka mula sa 24 na code ng kombinasyon ng salita", - "restore_bitcoin_description_from_keys": "Ibalik ang iyong pitaka mula sa nabuong wif string mula sa iyong mga pribadong susi", - "restore_bitcoin_title_from_keys": "Ibalik mula sa WIF", - "restore_from_date_or_blockheight": "Mangyaring magpasok ng isang petsa ng ilang araw bago mo nilikha ang pitaka na ito. O kung alam mo ang blockheight, mangyaring ipasok ito sa halip", - "seed_reminder": "Mangyaring isulat ang mga ito kung sakaling mawala ka o punasan ang iyong telepono", - "seed_title": "Binhi", - "seed_share": "Magbahagi ng binhi", - "copy": "Kopya", - "seed_language": "Wika ng binhi", - "seed_choose": "Pumili ng wika ng binhi", - "seed_language_next": "Susunod", - "seed_language_english": "Ingles", - "seed_language_chinese": "Tsino", - "seed_language_dutch": "Dutch", - "seed_language_german": "Aleman", - "seed_language_japanese": "Hapon", - "seed_language_portuguese": "Portuges", - "seed_language_russian": "Russian", - "seed_language_spanish": "Espanyol", - "seed_language_french": "Pranses", - "seed_language_italian": "Italyano", - "send_title": "Ipadala", - "send_your_wallet": "Iyong pitaka", - "send_address": "${cryptoCurrency} address", - "send_payment_id": "Payment ID (Opsyonal)", + "advanced_settings": "Mga Advanced na Setting", + "aggressive": "Agresibo", + "agree": "Sumang -ayon", + "agree_and_continue": "Sumang -ayon at magpatuloy", + "agree_to": "Sa pamamagitan ng paglikha ng account sumasang -ayon ka sa", "all": "Lahat", - "send_error_minimum_value": "Ang pinakamababang halaga ng halaga ay 0.01", - "send_error_currency": "Ang pera ay maaari lamang maglaman ng mga numero", - "send_estimated_fee": "Tinatayang bayad:", - "send_priority": "Sa kasalukuyan ang bayad ay nakatakda sa ${transactionPriority} priority.\nAng priority ng transaksyon ay maaaring maiakma sa mga setting", - "send_creating_transaction": "Paglikha ng transaksyon", - "send_templates": "Mga template", - "send_new": "Bago", - "send_amount": "Halaga:", - "send_fee": "Bayad:", - "send_name": "Pangalan", - "got_it": "Nakuha ko", - "send_sending": "Pagpapadala ...", - "send_success": "Ang iyong ${crypto} ay matagumpay na naipadala", - "settings_title": "Mga setting", - "settings_nodes": "Node", - "settings_current_node": "Kasalukuyang node", - "settings_wallets": "Wallets", - "settings_display_balance": "Ipakita ang balanse", - "settings_currency": "Pera", - "settings_fee_priority": "Priority priority", - "settings_save_recipient_address": "I -save ang address ng tatanggap", - "settings_personal": "Personal", - "settings_change_pin": "Baguhin ang pin", - "settings_change_language": "Baguhin ang wika", - "settings_allow_biometrical_authentication": "Payagan ang pagpapatunay ng biometrical", - "settings_dark_mode": "Madilim na mode", - "settings_transactions": "Mga Transaksyon", - "settings_trades": "Trading", - "settings_display_on_dashboard_list": "Ipakita sa listahan ng dashboard", - "settings_all": "Lahat", - "settings_only_trades": "TRADES LAMANG", - "settings_only_transactions": "Mga transaksyon lamang", - "settings_none": "Wala", - "settings_support": "Suporta", - "settings_terms_and_conditions": "Mga Tuntunin at Kundisyon", - "pin_is_incorrect": "Mali ang pin", - "setup_pin": "Setup pin", - "enter_your_pin_again": "Ipasok muli ang iyong pin", - "setup_successful": "Matagumpay na na -set up ang iyong pin!", - "wallet_keys": "Mga buto/susi ng pitaka", - "wallet_seed": "SEED ng Wallet", - "private_key": "Pribadong susi", - "public_key": "Pampublikong susi", - "view_key_private": "Tingnan ang Key (Pribado)", - "view_key_public": "Tingnan ang Key (Publiko)", - "spend_key_private": "Gumastos ng susi (pribado)", - "spend_key_public": "Gumastos ng susi (publiko)", - "copied_key_to_clipboard": "Kinopya ang ${key} sa clipboard", - "new_subaddress_title": "Bagong tirahan", - "new_subaddress_label_name": "Pangalan ng label", - "new_subaddress_create": "Lumikha", - "address_label": "Address Label", - "subaddress_title": "Listahan ng Subaddress", - "trade_details_title": "Mga detalye sa kalakalan", - "trade_details_id": "ID", - "trade_details_state": "Katayuan", - "trade_details_fetching": "Pagkuha", - "trade_details_provider": "Tagabigay", - "trade_details_created_at": "Nilikha sa", - "trade_details_pair": "Pares", - "trade_details_copied": "${title} kinopya sa clipboard", - "trade_history_title": "Kasaysayan ng Kalakal", - "transaction_details_title": "Mga detalye ng transaksyon", - "transaction_details_transaction_id": "Transaction ID", - "transaction_details_date": "Petsa", - "transaction_details_height": "Taas", - "transaction_details_amount": "Halaga", - "transaction_details_fee": "Bayad", - "transaction_details_copied": "${title} kinopya sa clipboard", - "transaction_details_recipient_address": "Mga address ng tatanggap", - "wallet_list_title": "Monero Wallet", - "wallet_list_create_new_wallet": "Lumikha ng bagong pitaka", - "wallet_list_edit_wallet": "I -edit ang Wallet", - "wallet_list_wallet_name": "Pangalan ng Wallet", - "wallet_list_restore_wallet": "Ibalik ang pitaka", - "wallet_list_load_wallet": "Mag -load ng pitaka", - "wallet_list_loading_wallet": "Naglo -load ng ${wallet_name} Wallet", - "wallet_list_failed_to_load": "Nabigong mag -load ng ${wallet_name} pitaka. ${error}", - "wallet_list_removing_wallet": "Pag -alis ng ${wallet_name} Wallet", - "wallet_list_failed_to_remove": "Nabigong alisin ang ${wallet_name} wallet. ${error}", - "widgets_address": "Address", - "widgets_restore_from_blockheight": "Ibalik mula sa blockheight", - "widgets_restore_from_date": "Ibalik mula sa petsa", - "widgets_or": "o", - "widgets_seed": "Binhi", - "router_no_route": "Walang ruta na tinukoy para sa ${name}", - "error_text_account_name": "Ang pangalan ng account ay maaari lamang maglaman ng mga titik, numero\nat dapat sa pagitan ng 1 at 15 character ang haba", - "error_text_contact_name": "Ang pangalan ng contact ay hindi maaaring maglaman ng mga simbolo ng ',' \"\nat dapat sa pagitan ng 1 at 32 character ang haba", - "error_text_address": "Ang wallet address ay dapat na tumutugma sa uri\nng cryptocurrency", - "error_text_node_address": "Mangyaring magpasok ng isang address ng IPv4", - "error_text_node_port": "Ang Node Port ay maaari lamang maglaman ng mga numero sa pagitan ng 0 at 65535", - "error_text_node_proxy_address": "Mangyaring ipasok ang : , halimbawa 127.0.0.1:9050", - "error_text_payment_id": "Ang Payment ID ay maaari lamang maglaman mula 16 hanggang 64 chars sa hex", - "error_text_xmr": "Ang halaga ng XMR ay hindi maaaring lumampas sa magagamit na balanse.\nAng bilang ng mga numero ng fraction ay dapat na mas mababa o katumbas ng 12", - "error_text_fiat": "Ang halaga ng halaga ay hindi maaaring lumampas sa magagamit na balanse.\nAng bilang ng mga numero ng fraction ay dapat na mas mababa o katumbas ng 2", - "error_text_subaddress_name": "Ang pangalan ng subaddress ay hindi maaaring maglaman ng mga simbolo na `, '\"\nat dapat sa pagitan ng 1 at 20 character ang haba", - "error_text_amount": "Ang halaga ay maaari lamang maglaman ng mga numero", - "error_text_wallet_name": "Ang pangalan ng pitaka ay maaari lamang maglaman ng mga titik, numero, _ - mga simbolo\nat dapat sa pagitan ng 1 at 33 character ang haba", - "error_text_keys": "Ang mga susi ng wallet ay maaari lamang maglaman ng 64 chars sa hex", - "error_text_crypto_currency": "Ang bilang ng mga numero ng fraction\ndapat mas mababa o katumbas ng 12", - "error_text_minimal_limit": "Ang kalakalan para sa ${provider} ay hindi nilikha. Ang halaga ay mas mababa pagkatapos ng minimal: ${min} ${currency}", - "error_text_maximum_limit": "Ang kalakalan para sa ${provider} ay hindi nilikha. Ang halaga ay higit na maximum: ${max} ${currency}", - "error_text_limits_loading_failed": "Ang kalakalan para sa ${provider} ay hindi nilikha. Nabigo ang mga limitasyon sa paglo -load", - "error_text_template": "Ang pangalan ng template at address ay hindi maaaring maglaman ng mga simbolo ng ',' \"\nat dapat sa pagitan ng 1 at 106 na character ang haba", + "all_trades": "Lahat ng mga kalakal", + "all_transactions": "Lahat ng mga transaksyon", + "alphabetical": "Alpabeto", + "already_have_account": "Mayroon nang account?", + "always": "Palagi", + "amount": "Halaga:", + "amount_is_estimate": "Ang natanggap na halaga ay isang pagtatantya", + "amount_is_guaranteed": "Ang natanggap na halaga ay garantisado", + "and": "at", + "anonpay_description": "Bumuo ng ${type}. Ang tatanggap ay maaaring ${method} na may anumang suportadong cryptocurrency, at makakatanggap ka ng mga pondo sa pitaka na ito.", + "apk_update": "APK Update", + "approve": "Aprubahan", + "arrive_in_this_address": "Ang ${currency} ${tag} ay darating sa address na ito", + "ascending": "Umakyat", + "ask_each_time": "Magtanong sa bawat oras", "auth_store_ban_timeout": "ban_timeout", "auth_store_banned_for": "Pinagbawalan para sa", "auth_store_banned_minutes": "minuto", "auth_store_incorrect_password": "Maling pin", - "wallet_store_monero_wallet": "Monero Wallet", - "wallet_restoration_store_incorrect_seed_length": "Maling haba ng binhi", - "full_balance": "Buong balanse", - "available_balance": "Magagamit na balanse", - "hidden_balance": "Nakatagong balanse", - "sync_status_syncronizing": "Pag -synchronize", - "sync_status_syncronized": "Naka -synchronize", - "sync_status_not_connected": "HINDI KONEKTADO", - "sync_status_starting_sync": "Simula sa pag -sync", - "sync_status_failed_connect": "Naka -disconnect", - "sync_status_connecting": "Pagkonekta", - "sync_status_connected": "Konektado", - "sync_status_attempting_sync": "Pagtatangka ng pag -sync", - "transaction_priority_slow": "Mabagal", - "transaction_priority_regular": "Regular", - "transaction_priority_medium": "Katamtaman", - "transaction_priority_fast": "Mabilis", - "transaction_priority_fastest": "Pinakamabilis", - "trade_for_not_created": "Ang kalakalan para sa ${title} ay hindi nilikha.", - "trade_not_created": "Hindi nilikha ang kalakalan", - "trade_id_not_found": "Trade ${tradeId} ng ${title} Hindi natagpuan.", - "trade_not_found": "Hindi natagpuan ang kalakalan.", - "trade_state_pending": "Nakabinbin", - "trade_state_confirming": "Pagkumpirma", - "trade_state_trading": "Pangangalakal", - "trade_state_traded": "Ipinagpalit", - "trade_state_complete": "Kumpleto", - "trade_state_to_be_created": "Upang malikha", - "trade_state_unpaid": "Walang bayad", - "trade_state_underpaid": "Underpaid", - "trade_state_paid_unconfirmed": "Bayad na hindi nakumpirma", - "trade_state_paid": "Bayad", - "trade_state_btc_sent": "Ipinadala ang BTC", - "trade_state_timeout": "Oras ng oras", - "trade_state_created": "Nilikha", - "trade_state_finished": "Tapos na", - "change_language": "Baguhin ang wika", - "change_language_to": "Baguhin ang wika sa ${language}?", - "paste": "I -paste", - "restore_from_seed_placeholder": "Mangyaring ipasok o i -paste ang iyong binhi dito", - "add_new_word": "Magdagdag ng bagong salita", - "incorrect_seed": "Ang teksto na ipinasok ay hindi wasto.", - "biometric_auth_reason": "I -scan ang iyong fingerprint upang mapatunayan", - "version": "Bersyon ${currentVersion}", - "extracted_address_content": "Magpapadala ka ng pondo sa\n${recipient_name}", - "card_address": "Address:", - "buy": "Bilhin", - "sell": "Ibenta", - "placeholder_transactions": "Ang iyong mga transaksyon ay ipapakita dito", - "placeholder_contacts": "Ang iyong mga contact ay ipapakita dito", - "template": "Template", - "confirm_delete_template": "Ang pagkilos na ito ay tatanggalin ang template na ito. Nais mo bang magpatuloy?", - "confirm_delete_wallet": "Ang pagkilos na ito ay tatanggalin ang pitaka na ito. Nais mo bang magpatuloy?", - "change_wallet_alert_title": "Baguhin ang kasalukuyang pitaka", - "change_wallet_alert_content": "Nais mo bang baguhin ang kasalukuyang pitaka sa ${wallet_name}?", - "creating_new_wallet": "Lumilikha ng bagong pitaka", - "creating_new_wallet_error": "Error: ${description}", - "seed_alert_title": "Pansin", - "seed_alert_content": "Ang binhi ay ang tanging paraan upang mabawi ang iyong pitaka. Nasulat mo na ba ito?", - "seed_alert_back": "Bumalik ka", - "seed_alert_yes": "Oo meron ako", - "exchange_sync_alert_content": "Mangyaring maghintay hanggang ang iyong pitaka ay naka -synchronize", - "pre_seed_title": "Mahalaga", - "pre_seed_description": "Sa susunod na pahina makikita mo ang isang serye ng mga ${words} na mga salita. Ito ang iyong natatangi at pribadong binhi at ito ang tanging paraan upang mabawi ang iyong pitaka kung sakaling mawala o madepektong paggawa. Responsibilidad mong isulat ito at itago ito sa isang ligtas na lugar sa labas ng cake wallet app.", - "pre_seed_button_text": "Naiintindihan ko. Ipakita sa akin ang aking binhi", - "xmr_to_error": "Xmr.to error", - "xmr_to_error_description": "Di -wastong halaga. Pinakamataas na limitasyon ng 8 numero pagkatapos ng punto ng desimal", - "provider_error": "${provider} error", - "use_ssl": "Gumamit ng SSL", - "trusted": "Pinagkakatiwalaan", - "color_theme": "Tema ng kulay", - "light_theme": "Ilaw", - "bright_theme": "Maliwanag", - "dark_theme": "Madilim", - "enter_your_note": "Ipasok ang iyong tala ...", - "note_optional": "Tandaan (Opsyonal)", - "note_tap_to_change": "Tandaan (Tapikin upang baguhin)", - "view_in_block_explorer": "Tingnan sa Block Explorer", - "view_transaction_on": "Tingnan ang transaksyon sa", - "transaction_key": "Susi ng transaksyon", - "confirmations": "Mga kumpirmasyon", - "recipient_address": "Address ng tatanggap", - "extra_id": "Dagdag na ID:", - "destination_tag": "Tag ng patutunguhan:", - "memo": "Memo:", - "backup": "Backup", - "change_password": "Palitan ANG password", - "backup_password": "Backup password", - "write_down_backup_password": "Mangyaring isulat ang iyong backup password, na ginagamit para sa pag -import ng iyong mga backup file.", - "export_backup": "I -export ang backup", - "save_backup_password": "Mangyaring tiyaking nai -save mo ang iyong backup password. Hindi mo mai -import ang iyong mga backup na file nang wala ito.", - "backup_file": "Backup file", - "edit_backup_password": "I -edit ang backup password", - "save_backup_password_alert": "I -save ang backup password", - "change_backup_password_alert": "Ang iyong mga nakaraang backup file ay hindi magagamit upang mai -import gamit ang bagong backup password. Ang bagong backup na password ay gagamitin lamang para sa mga bagong backup file. Sigurado ka bang nais mong baguhin ang backup password?", - "enter_backup_password": "Ipasok ang backup password dito", - "select_backup_file": "Piliin ang backup file", - "import": "Angkat", - "please_select_backup_file": "Mangyaring piliin ang backup file at ipasok ang backup password.", - "fixed_rate": "Naayos na rate", - "fixed_rate_alert": "Magagawa mong ipasok ang makatanggap na halaga kapag naka -check ang naayos na mode ng rate. Nais mo bang lumipat sa nakapirming mode ng rate?", - "xlm_extra_info": "Mangyaring huwag kalimutan na tukuyin ang memo ID habang ipinapadala ang transaksyon ng XLM para sa palitan", - "xrp_extra_info": "Mangyaring huwag kalimutan na tukuyin ang patutunguhan na tag habang ipinapadala ang transaksyon ng XRP para sa palitan", - "exchange_incorrect_current_wallet_for_xmr": "Kung nais mong makipagpalitan ng XMR mula sa iyong balanse ng cake wallet Monero, mangyaring lumipat sa iyong Monero Wallet muna.", - "confirmed": "Nakumpirma na balanse", - "unconfirmed": "Hindi nakumpirma na balanse", - "displayable": "Maipapakita", - "submit_request": "magsumite ng isang kahilingan", - "buy_alert_content": "Sa kasalukuyan ay sinusuportahan lamang namin ang pagbili ng Bitcoin, Ethereum, Litecoin, at Monero. Mangyaring lumikha o lumipat sa iyong Bitcoin, Ethereum, Litecoin, o Monero Wallet.", - "sell_alert_content": "Kasalukuyan lamang naming sinusuportahan ang pagbebenta ng Bitcoin, Ethereum at Litecoin. Mangyaring lumikha o lumipat sa iyong Bitcoin, Ethereum o Litecoin Wallet.", - "outdated_electrum_wallet_description": "Ang mga bagong wallets ng Bitcoin na nilikha sa cake ay mayroon na ngayong 24-salitang binhi. Ipinag-uutos na lumikha ka ng isang bagong pitaka ng Bitcoin at ilipat ang lahat ng iyong mga pondo sa bagong 24-salitang pitaka, at itigil ang paggamit ng mga pitaka na may 12-salitang binhi. Mangyaring gawin ito kaagad upang ma -secure ang iyong mga pondo.", - "understand": "naiintindihan ko", - "apk_update": "APK Update", - "buy_bitcoin": "Bumili ng bitcoin", - "buy_with": "Bumili ka", - "moonpay_alert_text": "Ang halaga ng halaga ay dapat na higit pa o katumbas ng ${minAmount} ${fiatCurrency}", - "outdated_electrum_wallet_receive_warning": "Kung ang pitaka na ito ay may 12-salitang binhi at nilikha sa cake, huwag magdeposito sa Bitcoin sa pitaka na ito. Ang anumang BTC na inilipat sa pitaka na ito ay maaaring mawala. Lumikha ng isang bagong 24-word wallet (tapikin ang menu sa kanang tuktok, piliin ang mga pitaka, piliin ang Lumikha ng Bagong Wallet, pagkatapos ay piliin ang Bitcoin) at agad na ilipat ang iyong BTC doon. Ang mga bagong (24-salita) BTC Wallets mula sa cake ay ligtas", - "do_not_show_me": "Huwag mo itong ipakita muli", - "unspent_coins_title": "Unspent barya", - "unspent_coins_details_title": "Mga Detalye ng Unspent Coins", - "freeze": "I -freeze", - "frozen": "Frozen", - "coin_control": "Control ng barya (opsyonal)", - "address_detected": "Nakita ang address", - "address_from_domain": "Ang address na ito ay mula sa ${domain} sa mga hindi mapigilan na mga domain", - "add_receiver": "Magdagdag ng isa pang tatanggap (opsyonal)", - "manage_yats": "Pamahalaan ang mga yats", - "yat_alert_title": "Magpadala at tumanggap ng crypto nang mas madali sa yat", - "yat_alert_content": "Ang mga gumagamit ng cake wallet ay maaari na ngayong magpadala at makatanggap ng lahat ng kanilang mga paboritong pera na may isang one-of-a-kind emoji-based username.", - "get_your_yat": "Kunin ang iyong yat", - "connect_an_existing_yat": "Ikonekta ang isang umiiral na yat", - "connect_yats": "Ikonekta ang mga yats", - "yat_address": "Yat address", - "yat": "Yat", - "address_from_yat": "Ang address na ito ay mula sa ${emoji} sa yat", - "yat_error": "Error sa yat", - "yat_error_content": "Walang mga address na naka -link sa yat na ito. Subukan ang isa pang yat", - "choose_address": "Mangyaring piliin ang address:", - "yat_popup_title": "Ang iyong wallet address ay maaaring ma -emojified.", - "yat_popup_content": "Maaari ka na ngayong magpadala at makatanggap ng crypto sa cake wallet kasama ang iyong yat - isang maikli, emoji na batay sa username. Pamahalaan ang mga yats anumang oras sa screen ng Mga Setting", - "second_intro_title": "Isang address ng emoji upang mamuno sa kanilang lahat", - "second_intro_content": "Ang iyong yat ay isang solong natatanging address ng emoji na pumapalit sa lahat ng iyong mahabang hexadecimal address para sa lahat ng iyong mga pera.", - "third_intro_title": "Si Yat ay mahusay na gumaganap sa iba", - "third_intro_content": "Ang mga yats ay nakatira sa labas ng cake wallet, din. Ang anumang address ng pitaka sa mundo ay maaaring mapalitan ng isang yat!", - "learn_more": "Matuto nang higit pa", - "search": "Maghanap", - "search_language": "Maghanap ng wika", - "search_currency": "Maghanap ng pera", - "new_template": "Bagong template", - "electrum_address_disclaimer": "Bumubuo kami ng mga bagong address sa tuwing gumagamit ka ng isa, ngunit ang mga nakaraang address ay patuloy na gumagana", - "wallet_name_exists": "Ang isang pitaka na may pangalang iyon ay mayroon na. Mangyaring pumili ng ibang pangalan o palitan muna ang iba pang pitaka.", - "market_place": "Marketplace", - "cake_pay_title": "Cake pay card card", - "cake_pay_subtitle": "Bumili ng mga diskwento na gift card (USA lamang)", - "cake_pay_web_cards_title": "Cake pay web card", - "cake_pay_web_cards_subtitle": "Bumili ng mga pandaigdigang prepaid card at gift card", - "about_cake_pay": "Pinapayagan ka ng cake Pay na madaling bumili ng mga kard ng regalo na may mga virtual na pag -aari, gastusin agad sa higit sa 150,000 mga mangangalakal sa Estados Unidos.", - "cake_pay_account_note": "Mag -sign up na may isang email address lamang upang makita at bumili ng mga kard. Ang ilan ay magagamit kahit sa isang diskwento!", - "already_have_account": "Mayroon nang account?", - "create_account": "Lumikha ng account", - "privacy_policy": "Patakaran sa Pagkapribado", - "welcome_to_cakepay": "Maligayang pagdating sa cake pay!", - "sign_up": "Mag -sign up", - "forgot_password": "Nakalimutan ang password", - "reset_password": "I -reset ang password", - "gift_cards": "Mga kard ng regalo", - "setup_your_debit_card": "I -set up ang iyong debit card", - "no_id_required": "Walang kinakailangang ID. I -top up at gumastos kahit saan", - "how_to_use_card": "Paano gamitin ang kard na ito", - "purchase_gift_card": "Bumili ng Gift Card", - "verification": "Pag -verify", - "fill_code": "Mangyaring punan ang verification code na ibinigay sa iyong email", - "didnt_get_code": "Hindi nakuha ang code?", - "resend_code": "Mangyaring ipagpatuloy ito", - "debit_card": "Debit card", - "cakepay_prepaid_card": "Cakepay prepaid debit card", - "no_id_needed": "Hindi kailangan ng ID!", - "frequently_asked_questions": "Madalas na nagtanong", - "debit_card_terms": "Ang pag -iimbak at paggamit ng numero ng iyong card ng pagbabayad (at mga kredensyal na naaayon sa iyong numero ng card ng pagbabayad) sa digital na pitaka na ito ay napapailalim sa mga termino at kundisyon ng naaangkop na kasunduan sa cardholder kasama ang nagbigay ng card ng pagbabayad, tulad ng sa oras -oras.", - "please_reference_document": "Mangyaring sanggunian ang mga dokumento sa ibaba para sa karagdagang impormasyon.", - "cardholder_agreement": "Kasunduan sa Cardholder", - "e_sign_consent": "E-sign na pahintulot", - "agree_and_continue": "Sumang -ayon at magpatuloy", - "email_address": "Email address", - "agree_to": "Sa pamamagitan ng paglikha ng account sumasang -ayon ka sa", - "and": "at", - "enter_code": "Ipasok ang code", - "congratulations": "Binabati kita!", - "you_now_have_debit_card": "Mayroon ka na ngayong debit card", - "min_amount": "Min: ${value}", - "max_amount": "Max: ${value}", - "enter_amount": "Ipasok ang halaga", - "billing_address_info": "Kung tatanungin ang isang address ng pagsingil, ibigay ang iyong address sa pagpapadala", - "order_physical_card": "Mag -order ng pisikal na kard", - "add_value": "Magdagdag ng halaga", - "activate": "Buhayin", - "get_a": "Kumuha ng", - "digital_and_physical_card": "Digital at Physical Prepaid Debit Card", - "get_card_note": "na maaari mong i -reload sa mga digital na pera. Walang karagdagang impormasyon na kailangan!", - "signup_for_card_accept_terms": "Mag -sign up para sa card at tanggapin ang mga termino.", - "add_fund_to_card": "Magdagdag ng prepaid na pondo sa mga kard (hanggang sa ${value})", - "use_card_info_two": "Ang mga pondo ay na -convert sa USD kapag gaganapin sila sa prepaid account, hindi sa mga digital na pera.", - "use_card_info_three": "Gamitin ang digital card online o sa mga pamamaraan ng pagbabayad na walang contact.", - "optionally_order_card": "Opsyonal na mag -order ng isang pisikal na kard.", - "hide_details": "Itago ang mga detalye", - "show_details": "Ipakita ang mga detalye", - "upto": "Hanggang sa ${value}", - "discount": "Makatipid ng ${value}%", - "gift_card_amount": "Halaga ng Gift Card", - "bill_amount": "Halaga ng Bill", - "you_pay": "Magbabayad ka", - "tip": "Tip:", - "custom": "pasadya", - "by_cake_pay": "sa pamamagitan ng cake pay", - "expires": "Mag -expire", - "mm": "Mm", - "yy": "YY", - "online": "Online", - "offline": "Offline", - "gift_card_number": "Numero ng regalo card", - "pin_number": "Numero ng pin", - "total_saving": "Kabuuang pagtitipid", - "last_30_days": "Huling 30 araw", - "avg_savings": "Avg. Matitipid", - "view_all": "Tingnan lahat", - "active_cards": "Mga aktibong kard", - "delete_account": "Tanggalin ang account", - "cards": "Mga Card", - "active": "Aktibo", - "redeemed": "Tinubos", - "gift_card_balance_note": "Ang mga kard ng regalo na may natitirang balanse ay lilitaw dito", - "gift_card_redeemed_note": "Ang mga kard ng regalo na iyong tinubos ay lilitaw dito", - "logout": "Mag -logout", - "add_tip": "Magdagdag ng tip", - "percentageOf": "ng ${amount}", - "is_percentage": "ay", - "search_category": "Kategorya ng paghahanap", - "mark_as_redeemed": "Markahan bilang tinubos", - "more_options": "Higit pang mga pagpipilian", - "awaiting_payment_confirmation": "Naghihintay ng kumpirmasyon sa pagbabayad", - "transaction_sent_notice": "Kung ang screen ay hindi magpatuloy pagkatapos ng 1 minuto, suriin ang isang block explorer at ang iyong email.", - "agree": "Sumang -ayon", - "in_store": "Nakatago", - "generating_gift_card": "Bumubuo ng Gift Card", - "payment_was_received": "Natanggap ang iyong pagbabayad.", - "proceed_after_one_minute": "Kung ang screen ay hindi magpatuloy pagkatapos ng 1 minuto, suriin ang iyong email.", - "order_id": "Order id", - "gift_card_is_generated": "Ang card ng regalo ay nabuo", - "open_gift_card": "Buksan ang Gift Card", - "contact_support": "Makipag -ugnay sa suporta", - "gift_cards_unavailable": "Magagamit ang mga gift card para sa pagbili lamang kasama ang Monero, Bitcoin, at Litecoin sa oras na ito", - "background_sync_mode": "Mode ng pag -sync ng background", - "sync_all_wallets": "I -sync ang lahat ng mga pitaka", - "introducing_cake_pay": "Ipinakikilala ang cake pay!", - "cake_pay_learn_more": "Agad na bumili at tubusin ang mga kard ng regalo sa app!\nMag -swipe pakaliwa sa kanan upang matuto nang higit pa.", - "automatic": "Awtomatiko", - "fixed_pair_not_supported": "Ang nakapirming pares na ito ay hindi suportado sa mga napiling palitan", - "variable_pair_not_supported": "Ang variable na pares na ito ay hindi suportado sa mga napiling palitan", - "none_of_selected_providers_can_exchange": "Wala sa mga napiling tagapagkaloob na maaaring gumawa ng palitan na ito", - "choose_one": "Pumili ng isa", - "choose_from_available_options": "Pumili mula sa magagamit na mga pagpipilian:", - "custom_redeem_amount": "Pasadyang tinubos ang halaga", - "add_custom_redemption": "Magdagdag ng pasadyang pagtubos", - "remaining": "natitira", - "delete_wallet": "Tanggalin ang pitaka", - "delete_wallet_confirm_message": "Sigurado ka bang nais mong tanggalin ang ${wallet_name} wallet?", - "low_fee": "Mababang bayad", - "low_fee_alert": "Kasalukuyan kang gumagamit ng isang mababang priyoridad sa bayad sa network. Maaari itong maging sanhi ng mahabang paghihintay, iba't ibang mga rate, o kanselahin ang mga trading. Inirerekumenda namin ang pagtatakda ng isang mas mataas na bayad para sa isang mas mahusay na karanasan.", - "ignor": "Huwag pansinin", - "use_suggested": "Gumamit ng iminungkahing", - "do_not_share_warning_text": "Huwag ibahagi ang mga ito sa sinumang iba pa, kabilang ang suporta.\n\nAng iyong mga pondo ay maaari at ninakaw!", - "help": "Tulong", - "all_transactions": "Lahat ng mga transaksyon", - "all_trades": "Lahat ng mga kalakal", - "connection_sync": "Koneksyon at pag -sync", - "security_and_backup": "Seguridad at backup", - "create_backup": "Gumawa ng backup", - "privacy_settings": "Settings para sa pagsasa-pribado", - "privacy": "Privacy", - "display_settings": "Mga setting ng pagpapakita", - "other_settings": "Iba pang mga setting", + "authenticated": "Napatunayan", + "authentication": "Pagpapatunay", "auto_generate_subaddresses": "Ang Auto ay bumubuo ng mga subaddresses", - "require_pin_after": "Nangangailangan ng pin pagkatapos", - "always": "Palagi", - "minutes_to_pin_code": "${minute} minuto", - "disable_exchange": "Huwag paganahin ang palitan", - "advanced_settings": "Mga Advanced na Setting", - "settings_can_be_changed_later": "Ang mga setting na ito ay maaaring mabago mamaya sa mga setting ng app", - "add_custom_node": "Magdagdag ng bagong pasadyang node", - "disable_fiat": "Huwag paganahin ang Fiat", - "fiat_api": "Fiat API", - "disabled": "Hindi pinagana", - "enabled": "Pinagana", - "tor_only": "Tor lang", - "unmatched_currencies": "Ang pera ng iyong kasalukuyang pitaka ay hindi tumutugma sa na -scan na QR", - "orbot_running_alert": "Mangyaring tiyakin na ang Orbot ay tumatakbo bago kumonekta sa node na ito.", - "contact_list_contacts": "Mga contact", - "contact_list_wallets": "Ang mga wallets ko", - "bitcoin_payments_require_1_confirmation": "Ang mga pagbabayad sa Bitcoin ay nangangailangan ng 1 kumpirmasyon, na maaaring tumagal ng 20 minuto o mas mahaba. Salamat sa iyong pasensya! Mag -email ka kapag nakumpirma ang pagbabayad.", - "send_to_this_address": "Magpadala ng ${currency} ${tag} sa address na ito", - "arrive_in_this_address": "Ang ${currency} ${tag} ay darating sa address na ito", - "do_not_send": "Huwag magpadala", - "error_dialog_content": "Oops, nakakuha kami ng ilang error.\n\nMangyaring ipadala ang ulat ng pag -crash sa aming koponan ng suporta upang maging mas mahusay ang application.", - "scan_qr_code": "I -scan ang QR Code", - "cold_or_recover_wallet": "Magdagdag ng isang malamig na pitaka o mabawi ang isang wallet ng papel", - "please_wait": "Mangyaring maghintay", - "sweeping_wallet": "Pagwawalis ng pitaka", - "sweeping_wallet_alert": "Hindi ito dapat magtagal. Huwag iwanan ang screen na ito o maaaring mawala ang mga pondo ng swept.", - "invoice_details": "Mga detalye ng invoice", - "donation_link_details": "Mga Detalye ng Link ng Donasyon", - "anonpay_description": "Bumuo ng ${type}. Ang tatanggap ay maaaring ${method} na may anumang suportadong cryptocurrency, at makakatanggap ka ng mga pondo sa pitaka na ito.", - "create_invoice": "Lumikha ng invoice", - "create_donation_link": "Lumikha ng link ng donasyon", - "optional_email_hint": "Opsyonal na Payee Notification Email", - "optional_description": "Opsyonal na paglalarawan", - "optional_name": "Opsyonal na pangalan ng tatanggap", - "clearnet_link": "Link ng Clearnet", - "onion_link": "Link ng Onion", - "decimal_places_error": "Masyadong maraming mga lugar na desimal", - "edit_node": "I -edit ang node", - "settings": "Mga setting", - "sell_monero_com_alert_content": "Ang pagbebenta ng Monero ay hindi pa suportado", - "error_text_input_below_minimum_limit": "Ang halaga ay mas mababa sa minimum", - "error_text_input_above_maximum_limit": "Ang halaga ay higit pa sa maximum", - "show_market_place": "Ipakita ang Marketplace", - "prevent_screenshots": "Maiwasan ang mga screenshot at pag -record ng screen", - "profile": "Profile", - "close": "Malapit", - "modify_2fa": "Baguhin ang cake 2FA", - "disable_cake_2fa": "Huwag paganahin ang cake 2FA", - "question_to_disable_2fa": "Sigurado ka bang nais mong huwag paganahin ang cake 2fa? Ang isang 2FA code ay hindi na kinakailangan upang ma -access ang pitaka at ilang mga pag -andar.", - "disable": "Huwag paganahin", - "setup_2fa": "Setup cake 2fa", - "verify_with_2fa": "Mag -verify sa cake 2FA", - "totp_code": "TOTP code", - "please_fill_totp": "Mangyaring punan ang 8-digit na code na naroroon sa iyong iba pang aparato", - "totp_2fa_success": "Tagumpay! Pinagana ang cake 2FA para sa pitaka na ito. Tandaan na i -save ang iyong mnemonic seed kung sakaling mawalan ka ng pag -access sa pitaka.", - "totp_verification_success": "Matagumpay ang pagpapatunay!", - "totp_2fa_failure": "Maling code. Mangyaring subukan ang ibang code o makabuo ng isang bagong lihim na susi. Gumamit ng isang katugmang 2FA app na sumusuporta sa 8-digit na mga code at SHA512.", - "enter_totp_code": "Mangyaring ipasok ang TOTP code.", - "add_secret_code": "O, idagdag ang sikretong code na ito sa isang authenticator app", - "totp_secret_code": "TOTP Secret Code", - "setup_2fa_text": "Gumagana ang Cake 2FA gamit ang TOTP bilang pangalawang kadahilanan sa pagpapatunay.\n\nAng TOTP ng Cake 2FA ay nangangailangan ng SHA-512 at 8 digit na suporta; nagbibigay ito ng mas mataas na seguridad. Higit pang impormasyon at suportadong app ang makikita sa gabay.", - "setup_totp_recommended": "I-setup ang TOTP", - "disable_buy": "Huwag paganahin ang pagkilos ng pagbili", - "disable_sell": "Huwag paganahin ang pagkilos ng pagbebenta", - "monero_dark_theme": "Monero Madilim na Tema", + "automatic": "Awtomatiko", + "available_balance": "Magagamit na balanse", + "available_balance_description": "Ang \"magagamit na balanse\" o \"nakumpirma na balanse\" ay mga pondo na maaaring gastusin kaagad. Kung lumilitaw ang mga pondo sa mas mababang balanse ngunit hindi ang nangungunang balanse, dapat kang maghintay ng ilang minuto para sa mga papasok na pondo upang makakuha ng mas maraming mga kumpirmasyon sa network. Matapos silang makakuha ng higit pang mga kumpirmasyon, gugugol sila.", + "avg_savings": "Avg. Matitipid", + "awaitDAppProcessing": "Pakihintay na matapos ang pagproseso ng dApp.", + "awaiting_payment_confirmation": "Naghihintay ng kumpirmasyon sa pagbabayad", + "background_sync_mode": "Mode ng pag -sync ng background", + "backup": "Backup", + "backup_file": "Backup file", + "backup_password": "Backup password", + "balance_page": "Pahina ng Balanse", + "bill_amount": "Halaga ng Bill", + "billing_address_info": "Kung tatanungin ang isang address ng pagsingil, ibigay ang iyong address sa pagpapadala", + "biometric_auth_reason": "I -scan ang iyong fingerprint upang mapatunayan", "bitcoin_dark_theme": "Bitcoin Madilim na Tema", "bitcoin_light_theme": "Tema ng ilaw ng bitcoin", - "high_contrast_theme": "Mataas na tema ng kaibahan", - "matrix_green_dark_theme": "Matrix Green Madilim na Tema", - "monero_light_theme": "Tema ng Monero Light", - "cake_2fa_preset": "Cake 2fa preset", - "narrow": "Makitid", - "normal": "Normal", - "aggressive": "Agresibo", - "require_for_assessing_wallet": "Nangangailangan para sa pag -access ng pitaka", - "require_for_sends_to_non_contacts": "Nangangailangan para sa pagpapadala sa mga hindi contact", - "require_for_sends_to_contacts": "Nangangailangan para sa pagpapadala sa mga contact", - "require_for_sends_to_internal_wallets": "Nangangailangan para sa pagpapadala sa mga panloob na mga pitaka", - "require_for_exchanges_to_internal_wallets": "Nangangailangan para sa mga palitan sa mga panloob na mga pitaka", - "require_for_adding_contacts": "Nangangailangan para sa pagdaragdag ng mga contact", - "require_for_creating_new_wallets": "Nangangailangan para sa paglikha ng mga bagong pitaka", - "require_for_all_security_and_backup_settings": "Nangangailangan para sa lahat ng mga setting ng seguridad at backup", - "available_balance_description": "Ang \"magagamit na balanse\" o \"nakumpirma na balanse\" ay mga pondo na maaaring gastusin kaagad. Kung lumilitaw ang mga pondo sa mas mababang balanse ngunit hindi ang nangungunang balanse, dapat kang maghintay ng ilang minuto para sa mga papasok na pondo upang makakuha ng mas maraming mga kumpirmasyon sa network. Matapos silang makakuha ng higit pang mga kumpirmasyon, gugugol sila.", - "syncing_wallet_alert_title": "Ang iyong pitaka ay nag -sync", - "syncing_wallet_alert_content": "Ang iyong balanse at listahan ng transaksyon ay maaaring hindi kumpleto hanggang sa sabihin nito na \"naka -synchronize\" sa tuktok. Mag -click/tap upang malaman ang higit pa.", - "home_screen_settings": "Mga setting ng home screen", - "sort_by": "Pag -uri -uriin sa pamamagitan ng", - "search_add_token": "Maghanap / Magdagdag ng Token", - "edit_token": "I -edit ang token", - "warning": "Babala", - "add_token_warning": "Huwag i -edit o magdagdag ng mga token tulad ng itinuro ng mga scammers.\nLaging kumpirmahin ang mga token address na may mga kagalang -galang na mapagkukunan!", - "add_token_disclaimer_check": "Kinumpirma ko ang address ng kontrata ng token at impormasyon gamit ang isang kagalang -galang na mapagkukunan. Ang pagdaragdag ng nakakahamak o hindi tamang impormasyon ay maaaring magresulta sa pagkawala ng mga pondo.", - "token_contract_address": "Token Address ng Kontrata", - "token_name": "Pangalan ng Token hal: Tether", - "token_symbol": "Simbolo ng token hal: USDT", - "token_decimal": "Token Decimal", - "field_required": "Kinakailangan ang patlang na ito", - "pin_at_top": "Pin ${token} sa tuktok", - "invalid_input": "Di -wastong input", - "fiat_balance": "Balanse ng fiat", - "gross_balance": "Balanse ng gross", - "alphabetical": "Alpabeto", - "generate_name": "Bumuo ng pangalan", - "balance_page": "Pahina ng Balanse", - "share": "Ibahagi", - "slidable": "Slidable", - "manage_nodes": "Pamahalaan ang mga node", - "etherscan_history": "Kasaysayan ng Etherscan", - "template_name": "Pangalan ng Template", - "support_title_live_chat": "Live na suporta", - "support_description_live_chat": "Libre at mabilis! Ang mga bihasang kinatawan ng suporta ay magagamit upang tulungan", - "support_title_guides": "Mga Gabay sa Wallet ng cake", - "support_description_guides": "Dokumentasyon at suporta para sa mga karaniwang isyu", - "support_title_other_links": "Iba pang mga link sa suporta", - "support_description_other_links": "Sumali sa aming mga komunidad o maabot sa amin ang aming mga kasosyo sa pamamagitan ng iba pang mga pamamaraan", - "select_destination": "Mangyaring piliin ang patutunguhan para sa backup file.", - "save_to_downloads": "I -save sa mga pag -download", - "select_buy_provider_notice": "Pumili ng provider ng pagbili sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na provider ng pagbili sa mga setting ng app.", - "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 bayarin.", - "default_buy_provider": "Default na Provider ng Pagbili", - "ask_each_time": "Magtanong sa bawat oras", - "robinhood_option_description": "Bumili at ilipat kaagad gamit ang iyong debit card, bank account, o balanse ng Robinhood. USA lang.", + "bitcoin_payments_require_1_confirmation": "Ang mga pagbabayad sa Bitcoin ay nangangailangan ng 1 kumpirmasyon, na maaaring tumagal ng 20 minuto o mas mahaba. Salamat sa iyong pasensya! Mag -email ka kapag nakumpirma ang pagbabayad.", + "Blocks_remaining": "Ang natitirang ${status} ay natitira", + "bright_theme": "Maliwanag", + "buy": "Bilhin", + "buy_alert_content": "Sa kasalukuyan ay sinusuportahan lamang namin ang pagbili ng Bitcoin, Ethereum, Litecoin, at Monero. Mangyaring lumikha o lumipat sa iyong Bitcoin, Ethereum, Litecoin, o Monero Wallet.", + "buy_bitcoin": "Bumili ng bitcoin", "buy_provider_unavailable": "Kasalukuyang hindi available ang provider.", - "signTransaction": "Mag-sign Transaksyon", - "errorGettingCredentials": "Nabigo: Error habang kumukuha ng mga kredensyal", - "errorSigningTransaction": "May naganap na error habang pinipirmahan ang transaksyon", - "pairingInvalidEvent": "Pagpares ng Di-wastong Kaganapan", - "chains": "Mga tanikala", - "methods": "Paraan", - "events": "Mga kaganapan", - "reject": "Tanggihan", - "approve": "Aprubahan", - "expiresOn": "Mag-e-expire sa", - "walletConnect": "WalletConnect", - "nullURIError": "Ang URI ay null", - "connectWalletPrompt": "Ikonekta ang iyong wallet sa WalletConnect upang gumawa ng mga transaksyon", - "newConnection": "Bagong Koneksyon", - "activeConnectionsPrompt": "Lalabas dito ang mga aktibong koneksyon", - "deleteConnectionConfirmationPrompt": "Sigurado ka bang gusto mong tanggalin ang koneksyon sa", - "event": "Kaganapan", - "successful": "Matagumpay", - "wouoldLikeToConnect": "gustong kumonekta", - "message": "Mensahe", - "do_not_have_enough_gas_asset": "Wala kang sapat na ${currency} para gumawa ng transaksyon sa kasalukuyang kundisyon ng network ng blockchain. Kailangan mo ng higit pang ${currency} upang magbayad ng mga bayarin sa network ng blockchain, kahit na nagpapadala ka ng ibang asset.", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Pakihintay na matapos ang pagproseso ng dApp.", - "copyWalletConnectLink": "Kopyahin ang link ng WalletConnect mula sa dApp at i-paste dito", - "enterWalletConnectURI": "Ilagay ang WalletConnect URI", - "seed_key": "Seed Key", - "enter_seed_phrase": "Ipasok ang iyong pariralang binhi", - "change_rep_successful": "Matagumpay na nagbago ng kinatawan", - "add_contact": "Magdagdag ng contact", - "exchange_provider_unsupported": "Ang ${providerName} ay hindi na suportado!", - "domain_looks_up": "Mga paghahanap ng domain", - "require_for_exchanges_to_external_wallets": "Kinakailangan para sa mga palitan sa mga panlabas na wallet", + "buy_with": "Bumili ka", + "by_cake_pay": "sa pamamagitan ng cake pay", + "cake_2fa_preset": "Cake 2fa preset", + "cake_pay_account_note": "Mag -sign up na may isang email address lamang upang makita at bumili ng mga kard. Ang ilan ay magagamit kahit sa isang diskwento!", + "cake_pay_learn_more": "Agad na bumili at tubusin ang mga kard ng regalo sa app!\nMag -swipe pakaliwa sa kanan upang matuto nang higit pa.", + "cake_pay_subtitle": "Bumili ng mga diskwento na gift card (USA lamang)", + "cake_pay_title": "Cake pay card card", + "cake_pay_web_cards_subtitle": "Bumili ng mga pandaigdigang prepaid card at gift card", + "cake_pay_web_cards_title": "Cake pay web card", + "cake_wallet": "Cake wallet", + "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.", "camera_permission_is_required": "Kinakailangan ang pahintulot sa camera.\nMangyaring paganahin ito mula sa mga setting ng app.", - "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli", - "order_by": "Iniutos ni", - "creation_date": "Petsa ng paglikha", - "group_by_type": "Pangkat ayon sa uri", - "importNFTs": "Mag-import ng mga NFT", - "noNFTYet": "Wala pang NFT", - "address": "Address", - "enterTokenID": "Ilagay ang token ID", - "tokenID": "ID", - "name": "Pangalan", - "symbol": "Simbolo", - "seed_phrase_length": "Haba ng parirala ng binhi", - "unavailable_balance": "Hindi available na balanse", - "unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.", - "unspent_change": "Baguhin", - "tor_connection": "Koneksyon ng Tor", - "setup_warning_2fa_text": "Kakailanganin mong ibalik ang iyong wallet mula sa mnemonic seed.\n\nHindi ka matutulungan ng suporta sa cake kung mawawalan ka ng access sa iyong 2FA o mnemonic seeds.\nAng Cake 2FA ay pangalawang pagpapatotoo para sa ilang partikular na pagkilos sa wallet. Bago gamitin ang Cake 2FA, inirerekomenda naming basahin ang gabay.HINDI ito kasing-secure ng malamig na imbakan.\n\nKung nawalan ka ng access sa iyong 2FA app o TOTP keys, MAWAWALA ka ng access sa wallet na ito. ", - "scan_qr_on_device": "I-scan ang QR code na ito sa ibang device", - "how_to_use": "Paano gamitin", - "seed_hex_form": "Wallet seed (hex form)", - "seedtype_legacy": "Pamana (25 salita)", - "seedtype_polyseed": "Polyseed (16 na salita)", - "seed_language_czech": "Czech", - "seed_language_korean": "Korean", - "seed_language_chinese_traditional": "Intsik (tradisyonal)", - "ascending": "Umakyat", - "descending": "Pababang", - "dfx_option_description": "Bumili ng crypto gamit ang EUR at CHF. Hanggang 990€ nang walang karagdagang KYC. Para sa retail at corporate na mga customer sa Europe", - "polygonscan_history": "Kasaysayan ng PolygonScan", - "wallet_seed_legacy": "Legacy wallet seed", - "default_sell_provider": "Default na Sell Provider", - "select_sell_provider_notice": "Pumili ng provider ng nagbebenta sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na sell provider sa mga setting ng app.", - "custom_drag": "Pasadyang (hawakan at i -drag)", - "switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)", - "receivable_balance": "Natatanggap na balanse", + "cancel": "Kanselahin", + "card_address": "Address:", + "cardholder_agreement": "Kasunduan sa Cardholder", + "cards": "Mga Card", + "chains": "Mga tanikala", + "change": "Palitan", + "change_backup_password_alert": "Ang iyong mga nakaraang backup file ay hindi magagamit upang mai -import gamit ang bagong backup password. Ang bagong backup na password ay gagamitin lamang para sa mga bagong backup file. Sigurado ka bang nais mong baguhin ang backup password?", + "change_currency": "Baguhin ang pera", + "change_current_node": "Sigurado ka bang baguhin ang kasalukuyang node sa ${node}?", + "change_current_node_title": "Baguhin ang kasalukuyang node", + "change_exchange_provider": "Baguhin ang tagapagbigay ng palitan", + "change_language": "Baguhin ang wika", + "change_language_to": "Baguhin ang wika sa ${language}?", + "change_password": "Palitan ANG password", + "change_rep_successful": "Matagumpay na nagbago ng kinatawan", + "change_wallet_alert_content": "Nais mo bang baguhin ang kasalukuyang pitaka sa ${wallet_name}?", + "change_wallet_alert_title": "Baguhin ang kasalukuyang pitaka", + "choose_account": "Pumili ng account", + "choose_address": "Mangyaring piliin ang address:", + "choose_from_available_options": "Pumili mula sa magagamit na mga pagpipilian:", + "choose_one": "Pumili ng isa", + "choose_relay": "Mangyaring pumili ng relay na gagamitin", + "choose_wallet_currency": "Mangyaring piliin ang Pera ng Wallet:", + "clear": "Malinaw", + "clearnet_link": "Link ng Clearnet", + "close": "Malapit", + "coin_control": "Control ng barya (opsyonal)", + "cold_or_recover_wallet": "Magdagdag ng isang malamig na pitaka o mabawi ang isang wallet ng papel", + "color_theme": "Tema ng kulay", + "commit_transaction_amount_fee": "Gumawa ng transaksyon\nHalaga: ${amount}\nBayad: ${fee}", + "confirm": "Kumpirmahin", + "confirm_delete_template": "Ang pagkilos na ito ay tatanggalin ang template na ito. Nais mo bang magpatuloy?", + "confirm_delete_wallet": "Ang pagkilos na ito ay tatanggalin ang pitaka na ito. Nais mo bang magpatuloy?", + "confirm_sending": "Kumpirmahin ang pagpapadala", + "confirmations": "Mga kumpirmasyon", + "confirmed": "Nakumpirma na balanse", "confirmed_tx": "Nakumpirma", - "transaction_details_source_address": "SOURCE ADDRESS", - "pause_wallet_creation": "Kasalukuyang naka-pause ang kakayahang gumawa ng Haven Wallet.", + "congratulations": "Binabati kita!", + "connect_an_existing_yat": "Ikonekta ang isang umiiral na yat", + "connect_yats": "Ikonekta ang mga yats", + "connection_sync": "Koneksyon at pag -sync", + "connectWalletPrompt": "Ikonekta ang iyong wallet sa WalletConnect upang gumawa ng mga transaksyon", + "contact": "Makipag -ugnay", + "contact_list_contacts": "Mga contact", + "contact_list_wallets": "Ang mga wallets ko", + "contact_name": "pangalan ng contact", + "contact_support": "Makipag -ugnay sa suporta", + "continue_text": "Magpatuloy", "contractName": "Pangalan ng Kontrata", "contractSymbol": "Simbolo ng Kontrata", + "copied_key_to_clipboard": "Kinopya ang ${key} sa clipboard", + "copied_to_clipboard": "Kinopya sa clipboard", + "copy": "Kopya", + "copy_address": "Kopyahin ang address", + "copy_id": "Kopyahin ang id", + "copyWalletConnectLink": "Kopyahin ang link ng WalletConnect mula sa dApp at i-paste dito", + "create_account": "Lumikha ng account", + "create_backup": "Gumawa ng backup", + "create_donation_link": "Lumikha ng link ng donasyon", + "create_invoice": "Lumikha ng invoice", + "create_new": "Lumikha ng bagong pitaka", + "create_new_account": "Lumikha ng Bagong Account", + "creating_new_wallet": "Lumilikha ng bagong pitaka", + "creating_new_wallet_error": "Error: ${description}", + "creation_date": "Petsa ng paglikha", + "custom": "pasadya", + "custom_drag": "Pasadyang (hawakan at i -drag)", + "custom_redeem_amount": "Pasadyang tinubos ang halaga", + "dark_theme": "Madilim", + "debit_card": "Debit card", + "debit_card_terms": "Ang pag -iimbak at paggamit ng numero ng iyong card ng pagbabayad (at mga kredensyal na naaayon sa iyong numero ng card ng pagbabayad) sa digital na pitaka na ito ay napapailalim sa mga termino at kundisyon ng naaangkop na kasunduan sa cardholder kasama ang nagbigay ng card ng pagbabayad, tulad ng sa oras -oras.", + "decimal_places_error": "Masyadong maraming mga lugar na desimal", + "default_buy_provider": "Default na Provider ng Pagbili", + "default_sell_provider": "Default na Sell Provider", + "delete": "Tanggalin", + "delete_account": "Tanggalin ang account", + "delete_wallet": "Tanggalin ang pitaka", + "delete_wallet_confirm_message": "Sigurado ka bang nais mong tanggalin ang ${wallet_name} wallet?", + "deleteConnectionConfirmationPrompt": "Sigurado ka bang gusto mong tanggalin ang koneksyon sa", + "descending": "Pababang", "description": "Paglalarawan", - "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.", + "destination_tag": "Tag ng patutunguhan:", + "dfx_option_description": "Bumili ng crypto gamit ang EUR at CHF. Hanggang 990€ nang walang karagdagang KYC. Para sa retail at corporate na mga customer sa Europe", + "didnt_get_code": "Hindi nakuha ang code?", + "digit_pin": "-digit pin", + "digital_and_physical_card": "Digital at Physical Prepaid Debit Card", + "disable": "Huwag paganahin", + "disable_buy": "Huwag paganahin ang pagkilos ng pagbili", + "disable_cake_2fa": "Huwag paganahin ang cake 2FA", + "disable_exchange": "Huwag paganahin ang palitan", + "disable_fiat": "Huwag paganahin ang Fiat", + "disable_sell": "Huwag paganahin ang pagkilos ng pagbebenta", + "disabled": "Hindi pinagana", + "discount": "Makatipid ng ${value}%", + "display_settings": "Mga setting ng pagpapakita", + "displayable": "Maipapakita", + "do_not_have_enough_gas_asset": "Wala kang sapat na ${currency} para gumawa ng transaksyon sa kasalukuyang kundisyon ng network ng blockchain. Kailangan mo ng higit pang ${currency} upang magbayad ng mga bayarin sa network ng blockchain, kahit na nagpapadala ka ng ibang asset.", + "do_not_send": "Huwag magpadala", + "do_not_share_warning_text": "Huwag ibahagi ang mga ito sa sinumang iba pa, kabilang ang suporta.\n\nAng iyong mga pondo ay maaari at ninakaw!", + "do_not_show_me": "Huwag mo itong ipakita muli", + "domain_looks_up": "Mga paghahanap ng domain", + "donation_link_details": "Mga Detalye ng Link ng Donasyon", + "e_sign_consent": "E-sign na pahintulot", + "edit": "I -edit", + "edit_backup_password": "I -edit ang backup password", + "edit_node": "I -edit ang node", + "edit_token": "I -edit ang token", + "electrum_address_disclaimer": "Bumubuo kami ng mga bagong address sa tuwing gumagamit ka ng isa, ngunit ang mga nakaraang address ay patuloy na gumagana", + "email_address": "Email address", + "enabled": "Pinagana", + "enter_amount": "Ipasok ang halaga", + "enter_backup_password": "Ipasok ang backup password dito", + "enter_code": "Ipasok ang code", + "enter_seed_phrase": "Ipasok ang iyong pariralang binhi", + "enter_totp_code": "Mangyaring ipasok ang TOTP code.", + "enter_your_note": "Ipasok ang iyong tala ...", + "enter_your_pin": "Ipasok ang iyong pin", + "enter_your_pin_again": "Ipasok muli ang iyong pin", + "enterTokenID": "Ilagay ang token ID", + "enterWalletConnectURI": "Ilagay ang WalletConnect URI", + "error": "Error", + "error_dialog_content": "Oops, nakakuha kami ng ilang error.\n\nMangyaring ipadala ang ulat ng pag -crash sa aming koponan ng suporta upang maging mas mahusay ang application.", + "error_text_account_name": "Ang pangalan ng account ay maaari lamang maglaman ng mga titik, numero\nat dapat sa pagitan ng 1 at 15 character ang haba", + "error_text_address": "Ang wallet address ay dapat na tumutugma sa uri\nng cryptocurrency", + "error_text_amount": "Ang halaga ay maaari lamang maglaman ng mga numero", + "error_text_contact_name": "Ang pangalan ng contact ay hindi maaaring maglaman ng mga simbolo ng ',' \"\nat dapat sa pagitan ng 1 at 32 character ang haba", + "error_text_crypto_currency": "Ang bilang ng mga numero ng fraction\ndapat mas mababa o katumbas ng 12", + "error_text_fiat": "Ang halaga ng halaga ay hindi maaaring lumampas sa magagamit na balanse.\nAng bilang ng mga numero ng fraction ay dapat na mas mababa o katumbas ng 2", + "error_text_input_above_maximum_limit": "Ang halaga ay higit pa sa maximum", + "error_text_input_below_minimum_limit": "Ang halaga ay mas mababa sa minimum", + "error_text_keys": "Ang mga susi ng wallet ay maaari lamang maglaman ng 64 chars sa hex", + "error_text_limits_loading_failed": "Ang kalakalan para sa ${provider} ay hindi nilikha. Nabigo ang mga limitasyon sa paglo -load", + "error_text_maximum_limit": "Ang kalakalan para sa ${provider} ay hindi nilikha. Ang halaga ay higit na maximum: ${max} ${currency}", + "error_text_minimal_limit": "Ang kalakalan para sa ${provider} ay hindi nilikha. Ang halaga ay mas mababa pagkatapos ng minimal: ${min} ${currency}", + "error_text_node_address": "Mangyaring magpasok ng isang address ng IPv4", + "error_text_node_port": "Ang Node Port ay maaari lamang maglaman ng mga numero sa pagitan ng 0 at 65535", + "error_text_node_proxy_address": "Mangyaring ipasok ang : , halimbawa 127.0.0.1:9050", + "error_text_payment_id": "Ang Payment ID ay maaari lamang maglaman mula 16 hanggang 64 chars sa hex", + "error_text_subaddress_name": "Ang pangalan ng subaddress ay hindi maaaring maglaman ng mga simbolo na `, '\"\nat dapat sa pagitan ng 1 at 20 character ang haba", + "error_text_template": "Ang pangalan ng template at address ay hindi maaaring maglaman ng mga simbolo ng ',' \"\nat dapat sa pagitan ng 1 at 106 na character ang haba", + "error_text_wallet_name": "Ang pangalan ng pitaka ay maaari lamang maglaman ng mga titik, numero, _ - mga simbolo\nat dapat sa pagitan ng 1 at 33 character ang haba", + "error_text_xmr": "Ang halaga ng XMR ay hindi maaaring lumampas sa magagamit na balanse.\nAng bilang ng mga numero ng fraction ay dapat na mas mababa o katumbas ng 12", + "errorGettingCredentials": "Nabigo: Error habang kumukuha ng mga kredensyal", + "errorSigningTransaction": "May naganap na error habang pinipirmahan ang transaksyon", + "estimated": "Tinatayang", + "etherscan_history": "Kasaysayan ng Etherscan", + "event": "Kaganapan", + "events": "Mga kaganapan", + "exchange": "Palitan", + "exchange_incorrect_current_wallet_for_xmr": "Kung nais mong makipagpalitan ng XMR mula sa iyong balanse ng cake wallet Monero, mangyaring lumipat sa iyong Monero Wallet muna.", + "exchange_new_template": "Bagong template", + "exchange_provider_unsupported": "Ang ${providerName} ay hindi na suportado!", + "exchange_result_confirm": "Sa pamamagitan ng pagpindot ng kumpirmahin, magpapadala ka ng ${fetchingLabel} ${from} mula sa iyong pitaka na tinatawag na ${walletName} sa address na ipinakita sa ibaba. O maaari kang magpadala mula sa iyong panlabas na pitaka sa ibaba address/qr code.\n\nMangyaring pindutin ang kumpirmahin na magpatuloy o bumalik upang baguhin ang mga halaga.", + "exchange_result_description": "Dapat kang magpadala ng isang minimum na ${fetchingLabel} ${from} hanggang sa address na ipinakita sa susunod na pahina. Kung nagpapadala ka ng isang halaga na mas mababa kaysa sa ${fetchingLabel} ${from} maaaring hindi ito ma -convert at maaaring hindi ito ibabalik.", + "exchange_result_write_down_ID": "*Mangyaring kopyahin o isulat ang iyong ID na ipinakita sa itaas.", + "exchange_result_write_down_trade_id": "Mangyaring kopyahin o isulat ang trade ID upang magpatuloy.", + "exchange_sync_alert_content": "Mangyaring maghintay hanggang ang iyong pitaka ay naka -synchronize", + "expired": "Nag -expire", + "expires": "Mag -expire", + "expiresOn": "Mag-e-expire sa", + "export_backup": "I -export ang backup", + "extra_id": "Dagdag na ID:", + "extracted_address_content": "Magpapadala ka ng pondo sa\n${recipient_name}", + "failed_authentication": "Nabigong pagpapatunay. ${state_error}", + "faq": "FAQ", + "fetching": "Pagkuha", + "fiat_api": "Fiat API", + "fiat_balance": "Balanse ng fiat", + "field_required": "Kinakailangan ang patlang na ito", + "fill_code": "Mangyaring punan ang verification code na ibinigay sa iyong email", + "filter_by": "Filter ni", + "first_wallet_text": "Kahanga -hangang pitaka para sa Monero, Bitcoin, Ethereum, Litecoin, at Haven", + "fixed_pair_not_supported": "Ang nakapirming pares na ito ay hindi suportado sa mga napiling palitan", + "fixed_rate": "Naayos na rate", + "fixed_rate_alert": "Magagawa mong ipasok ang makatanggap na halaga kapag naka -check ang naayos na mode ng rate. Nais mo bang lumipat sa nakapirming mode ng rate?", + "forgot_password": "Nakalimutan ang password", + "freeze": "I -freeze", + "frequently_asked_questions": "Madalas na nagtanong", + "frozen": "Frozen", + "full_balance": "Buong balanse", + "generate_name": "Bumuo ng pangalan", + "generating_gift_card": "Bumubuo ng Gift Card", + "get_a": "Kumuha ng", + "get_card_note": "na maaari mong i -reload sa mga digital na pera. Walang karagdagang impormasyon na kailangan!", + "get_your_yat": "Kunin ang iyong yat", + "gift_card_amount": "Halaga ng Gift Card", + "gift_card_balance_note": "Ang mga kard ng regalo na may natitirang balanse ay lilitaw dito", + "gift_card_is_generated": "Ang card ng regalo ay nabuo", + "gift_card_number": "Numero ng regalo card", + "gift_card_redeemed_note": "Ang mga kard ng regalo na iyong tinubos ay lilitaw dito", + "gift_cards": "Mga kard ng regalo", + "gift_cards_unavailable": "Magagamit ang mga gift card para sa pagbili lamang kasama ang Monero, Bitcoin, at Litecoin sa oras na ito", + "got_it": "Nakuha ko", + "gross_balance": "Balanse ng gross", + "group_by_type": "Pangkat ayon sa uri", + "haven_app": "Haven sa pamamagitan ng cake wallet", + "haven_app_wallet_text": "Galing ng pitaka para sa Haven", + "help": "Tulong", + "hidden_balance": "Nakatagong balanse", + "hide_details": "Itago ang mga detalye", + "high_contrast_theme": "Mataas na tema ng kaibahan", + "home_screen_settings": "Mga setting ng home screen", + "how_to_use": "Paano gamitin", + "how_to_use_card": "Paano gamitin ang kard na ito", + "id": "ID:", + "ignor": "Huwag pansinin", + "import": "Angkat", + "importNFTs": "Mag-import ng mga NFT", + "in_store": "Nakatago", + "incoming": "Papasok", + "incorrect_seed": "Ang teksto na ipinasok ay hindi wasto.", + "introducing_cake_pay": "Ipinakikilala ang cake pay!", + "invalid_input": "Di -wastong input", + "invoice_details": "Mga detalye ng invoice", + "is_percentage": "ay", + "last_30_days": "Huling 30 araw", + "learn_more": "Matuto nang higit pa", + "light_theme": "Ilaw", + "loading_your_wallet": "Naglo -load ng iyong pitaka", + "login": "Mag log in", + "logout": "Mag -logout", + "low_fee": "Mababang bayad", + "low_fee_alert": "Kasalukuyan kang gumagamit ng isang mababang priyoridad sa bayad sa network. Maaari itong maging sanhi ng mahabang paghihintay, iba't ibang mga rate, o kanselahin ang mga trading. Inirerekumenda namin ang pagtatakda ng isang mas mataas na bayad para sa isang mas mahusay na karanasan.", + "manage_nodes": "Pamahalaan ang mga node", + "manage_yats": "Pamahalaan ang mga yats", + "mark_as_redeemed": "Markahan bilang tinubos", + "market_place": "Marketplace", + "matrix_green_dark_theme": "Matrix Green Madilim na Tema", + "max_amount": "Max: ${value}", + "max_value": "Max: ${value} ${currency}", + "memo": "Memo:", + "message": "Mensahe", + "methods": "Paraan", + "min_amount": "Min: ${value}", + "min_value": "Min: ${value} ${currency}", + "minutes_to_pin_code": "${minute} minuto", + "mm": "Mm", + "modify_2fa": "Baguhin ang cake 2FA", + "monero_com": "Monero.com sa pamamagitan ng cake wallet", + "monero_com_wallet_text": "Galing ng pitaka para sa Monero", + "monero_dark_theme": "Monero Madilim na Tema", + "monero_light_theme": "Tema ng Monero Light", + "moonpay_alert_text": "Ang halaga ng halaga ay dapat na higit pa o katumbas ng ${minAmount} ${fiatCurrency}", + "more_options": "Higit pang mga pagpipilian", + "name": "Pangalan", + "narrow": "Makitid", + "new_node_testing": "Bagong pagsubok sa node", + "new_subaddress_create": "Lumikha", + "new_subaddress_label_name": "Pangalan ng label", + "new_subaddress_title": "Bagong tirahan", + "new_template": "Bagong template", + "new_wallet": "Bagong pitaka", + "newConnection": "Bagong Koneksyon", + "no_id_needed": "Hindi kailangan ng ID!", + "no_id_required": "Walang kinakailangang ID. I -top up at gumastos kahit saan", + "no_relay_on_domain": "Walang relay para sa domain ng user o hindi available ang relay. Mangyaring pumili ng relay na gagamitin.", "no_relays": "Walang mga relay", - "choose_relay": "Mangyaring pumili ng relay na gagamitin", "no_relays_message": "Nakakita kami ng Nostr NIP-05 record para sa user na ito, ngunit hindi ito naglalaman ng anumang mga relay. Mangyaring atasan ang tatanggap na magdagdag ng mga relay sa kanilang Nostr record.", - "no_relay_on_domain": "Walang relay para sa domain ng user o hindi available ang relay. Mangyaring pumili ng relay na gagamitin." -} + "node_address": "Node address", + "node_connection_failed": "Nabigo ang koneksyon", + "node_connection_successful": "Ang koneksyon ay matagumpay", + "node_new": "Bagong node", + "node_port": "Node port", + "node_reset_settings_title": "I -reset ang Mga Setting", + "node_test": "Pagsusulit", + "nodes": "Node", + "nodes_list_reset_to_default_message": "Sigurado ka bang nais mong i -reset ang mga setting upang default?", + "none_of_selected_providers_can_exchange": "Wala sa mga napiling tagapagkaloob na maaaring gumawa ng palitan na ito", + "noNFTYet": "Wala pang NFT", + "normal": "Normal", + "note_optional": "Tandaan (Opsyonal)", + "note_tap_to_change": "Tandaan (Tapikin upang baguhin)", + "nullURIError": "Ang URI ay null", + "offer_expires_in": "Mag -expire ang alok sa:", + "offline": "Offline", + "ok": "Ok", + "onion_link": "Link ng Onion", + "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 bayarin.", + "open_gift_card": "Buksan ang Gift Card", + "optional_description": "Opsyonal na paglalarawan", + "optional_email_hint": "Opsyonal na Payee Notification Email", + "optional_name": "Opsyonal na pangalan ng tatanggap", + "optionally_order_card": "Opsyonal na mag -order ng isang pisikal na kard.", + "orbot_running_alert": "Mangyaring tiyakin na ang Orbot ay tumatakbo bago kumonekta sa node na ito.", + "order_by": "Iniutos ni", + "order_id": "Order id", + "order_physical_card": "Mag -order ng pisikal na kard", + "other_settings": "Iba pang mga setting", + "outdated_electrum_wallet_description": "Ang mga bagong wallets ng Bitcoin na nilikha sa cake ay mayroon na ngayong 24-salitang binhi. Ipinag-uutos na lumikha ka ng isang bagong pitaka ng Bitcoin at ilipat ang lahat ng iyong mga pondo sa bagong 24-salitang pitaka, at itigil ang paggamit ng mga pitaka na may 12-salitang binhi. Mangyaring gawin ito kaagad upang ma -secure ang iyong mga pondo.", + "outdated_electrum_wallet_receive_warning": "Kung ang pitaka na ito ay may 12-salitang binhi at nilikha sa cake, huwag magdeposito sa Bitcoin sa pitaka na ito. Ang anumang BTC na inilipat sa pitaka na ito ay maaaring mawala. Lumikha ng isang bagong 24-word wallet (tapikin ang menu sa kanang tuktok, piliin ang mga pitaka, piliin ang Lumikha ng Bagong Wallet, pagkatapos ay piliin ang Bitcoin) at agad na ilipat ang iyong BTC doon. Ang mga bagong (24-salita) BTC Wallets mula sa cake ay ligtas", + "outgoing": "Palabas", + "overwrite_amount": "Overwrite na halaga", + "pairingInvalidEvent": "Pagpares ng Di-wastong Kaganapan", + "password": "Password", + "paste": "I -paste", + "pause_wallet_creation": "Kasalukuyang naka-pause ang kakayahang gumawa ng Haven Wallet.", + "payment_id": "Payment ID:", + "payment_was_received": "Natanggap ang iyong pagbabayad.", + "pending": "(Pending)", + "percentageOf": "ng ${amount}", + "pin_at_top": "Pin ${token} sa tuktok", + "pin_is_incorrect": "Mali ang pin", + "pin_number": "Numero ng pin", + "placeholder_contacts": "Ang iyong mga contact ay ipapakita dito", + "placeholder_transactions": "Ang iyong mga transaksyon ay ipapakita dito", + "please_fill_totp": "Mangyaring punan ang 8-digit na code na naroroon sa iyong iba pang aparato", + "please_make_selection": "Mangyaring gumawa ng isang pagpipilian sa ibaba upang lumikha o mabawi ang iyong pitaka.", + "please_reference_document": "Mangyaring sanggunian ang mga dokumento sa ibaba para sa karagdagang impormasyon.", + "please_select": "Pakipili:", + "please_select_backup_file": "Mangyaring piliin ang backup file at ipasok ang backup password.", + "please_try_to_connect_to_another_node": "Mangyaring subukang kumonekta sa isa pang node", + "please_wait": "Mangyaring maghintay", + "polygonscan_history": "Kasaysayan ng PolygonScan", + "powered_by": "Pinapagana ng ${title}", + "pre_seed_button_text": "Naiintindihan ko. Ipakita sa akin ang aking binhi", + "pre_seed_description": "Sa susunod na pahina makikita mo ang isang serye ng mga ${words} na mga salita. Ito ang iyong natatangi at pribadong binhi at ito ang tanging paraan upang mabawi ang iyong pitaka kung sakaling mawala o madepektong paggawa. Responsibilidad mong isulat ito at itago ito sa isang ligtas na lugar sa labas ng cake wallet app.", + "pre_seed_title": "Mahalaga", + "prevent_screenshots": "Maiwasan ang mga screenshot at pag -record ng screen", + "privacy": "Privacy", + "privacy_policy": "Patakaran sa Pagkapribado", + "privacy_settings": "Settings para sa pagsasa-pribado", + "private_key": "Pribadong susi", + "proceed_after_one_minute": "Kung ang screen ay hindi magpatuloy pagkatapos ng 1 minuto, suriin ang iyong email.", + "profile": "Profile", + "provider_error": "${provider} error", + "public_key": "Pampublikong susi", + "purchase_gift_card": "Bumili ng Gift Card", + "qr_fullscreen": "Tapikin upang buksan ang buong screen QR code", + "qr_payment_amount": "Ang QR code na ito ay naglalaman ng isang halaga ng pagbabayad. Nais mo bang i -overwrite ang kasalukuyang halaga?", + "question_to_disable_2fa": "Sigurado ka bang nais mong huwag paganahin ang cake 2fa? Ang isang 2FA code ay hindi na kinakailangan upang ma -access ang pitaka at ilang mga pag -andar.", + "receivable_balance": "Natatanggap na balanse", + "receive": "Tumanggap", + "receive_amount": "Halaga", + "received": "Natanggap", + "recipient_address": "Address ng tatanggap", + "reconnect": "Kumonekta muli", + "reconnect_alert_text": "Sigurado ka bang nais mong muling kumonekta?", + "reconnection": "Pag -ugnay muli", + "redeemed": "Tinubos", + "refund_address": "Refund address", + "reject": "Tanggihan", + "remaining": "natitira", + "remove": "Alisin", + "remove_node": "Alisin ang node", + "remove_node_message": "Sigurado ka bang nais mong alisin ang napiling node?", + "rename": "Palitan ang pangalan", + "require_for_adding_contacts": "Nangangailangan para sa pagdaragdag ng mga contact", + "require_for_all_security_and_backup_settings": "Nangangailangan para sa lahat ng mga setting ng seguridad at backup", + "require_for_assessing_wallet": "Nangangailangan para sa pag -access ng pitaka", + "require_for_creating_new_wallets": "Nangangailangan para sa paglikha ng mga bagong pitaka", + "require_for_exchanges_to_external_wallets": "Kinakailangan para sa mga palitan sa mga panlabas na wallet", + "require_for_exchanges_to_internal_wallets": "Nangangailangan para sa mga palitan sa mga panloob na mga pitaka", + "require_for_sends_to_contacts": "Nangangailangan para sa pagpapadala sa mga contact", + "require_for_sends_to_internal_wallets": "Nangangailangan para sa pagpapadala sa mga panloob na mga pitaka", + "require_for_sends_to_non_contacts": "Nangangailangan para sa pagpapadala sa mga hindi contact", + "require_pin_after": "Nangangailangan ng pin pagkatapos", + "rescan": "Rescan", + "resend_code": "Mangyaring ipagpatuloy ito", + "reset": "I -reset", + "reset_password": "I -reset ang password", + "restore_active_seed": "Aktibong binhi", + "restore_address": "Address", + "restore_bitcoin_description_from_keys": "Ibalik ang iyong pitaka mula sa nabuong wif string mula sa iyong mga pribadong susi", + "restore_bitcoin_description_from_seed": "Ibalik ang iyong pitaka mula sa 24 na code ng kombinasyon ng salita", + "restore_bitcoin_title_from_keys": "Ibalik mula sa WIF", + "restore_description_from_backup": "Maaari mong ibalik ang buong cake wallet app mula sa iyong back-up file", + "restore_description_from_keys": "Ibalik ang iyong pitaka mula sa nabuong mga keystroke na na -save mula sa iyong mga pribadong susi", + "restore_description_from_seed": "Ibalik ang iyong pitaka mula sa alinman sa 25 salita o 13 na code ng kombinasyon ng salita", + "restore_description_from_seed_keys": "Ibalik ang iyong pitaka mula sa mga binhi/susi na na -save mo upang ma -secure ang lugar", + "restore_from_date_or_blockheight": "Mangyaring magpasok ng isang petsa ng ilang araw bago mo nilikha ang pitaka na ito. O kung alam mo ang blockheight, mangyaring ipasok ito sa halip", + "restore_from_seed_placeholder": "Mangyaring ipasok o i -paste ang iyong binhi dito", + "restore_new_seed": "Bagong binhi", + "restore_next": "Susunod", + "restore_recover": "Ibalik", + "restore_restore_wallet": "Ibalik ang pitaka", + "restore_seed_keys_restore": "Ibinalik ang mga binhi/susi", + "restore_spend_key_private": "Gumastos ng susi (pribado)", + "restore_title_from_backup": "Ibalik mula sa backup", + "restore_title_from_keys": "Ibalik mula sa mga susi", + "restore_title_from_seed": "Ibalik mula sa binhi", + "restore_title_from_seed_keys": "Ibalik mula sa mga binhi/susi", + "restore_view_key_private": "Tingnan ang Key (Pribado)", + "restore_wallet": "Ibalik ang pitaka", + "restore_wallet_name": "Pangalan ng Wallet", + "restore_wallet_restore_description": "Paglalarawan ng Wallet", + "robinhood_option_description": "Bumili at ilipat kaagad gamit ang iyong debit card, bank account, o balanse ng Robinhood. USA lang.", + "router_no_route": "Walang ruta na tinukoy para sa ${name}", + "save": "I -save", + "save_backup_password": "Mangyaring tiyaking nai -save mo ang iyong backup password. Hindi mo mai -import ang iyong mga backup na file nang wala ito.", + "save_backup_password_alert": "I -save ang backup password", + "save_to_downloads": "I -save sa mga pag -download", + "saved_the_trade_id": "Nai -save ko ang trade ID", + "scan_qr_code": "I -scan ang QR Code", + "scan_qr_code_to_get_address": "I -scan ang QR code upang makuha ang address", + "scan_qr_on_device": "I-scan ang QR code na ito sa ibang device", + "search": "Maghanap", + "search_add_token": "Maghanap / Magdagdag ng Token", + "search_category": "Kategorya ng paghahanap", + "search_currency": "Maghanap ng pera", + "search_language": "Maghanap ng wika", + "second_intro_content": "Ang iyong yat ay isang solong natatanging address ng emoji na pumapalit sa lahat ng iyong mahabang hexadecimal address para sa lahat ng iyong mga pera.", + "second_intro_title": "Isang address ng emoji upang mamuno sa kanilang lahat", + "security_and_backup": "Seguridad at backup", + "seed_alert_back": "Bumalik ka", + "seed_alert_content": "Ang binhi ay ang tanging paraan upang mabawi ang iyong pitaka. Nasulat mo na ba ito?", + "seed_alert_title": "Pansin", + "seed_alert_yes": "Oo meron ako", + "seed_choose": "Pumili ng wika ng binhi", + "seed_hex_form": "Wallet seed (hex form)", + "seed_key": "Seed Key", + "seed_language": "Wika ng binhi", + "seed_language_chinese": "Tsino", + "seed_language_chinese_traditional": "Intsik (tradisyonal)", + "seed_language_czech": "Czech", + "seed_language_dutch": "Dutch", + "seed_language_english": "Ingles", + "seed_language_french": "Pranses", + "seed_language_german": "Aleman", + "seed_language_italian": "Italyano", + "seed_language_japanese": "Hapon", + "seed_language_korean": "Korean", + "seed_language_next": "Susunod", + "seed_language_portuguese": "Portuges", + "seed_language_russian": "Russian", + "seed_language_spanish": "Espanyol", + "seed_phrase_length": "Haba ng parirala ng binhi", + "seed_reminder": "Mangyaring isulat ang mga ito kung sakaling mawala ka o punasan ang iyong telepono", + "seed_share": "Magbahagi ng binhi", + "seed_title": "Binhi", + "seedtype_legacy": "Pamana (25 salita)", + "seedtype_polyseed": "Polyseed (16 na salita)", + "select_backup_file": "Piliin ang backup file", + "select_buy_provider_notice": "Pumili ng provider ng pagbili sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na provider ng pagbili sa mga setting ng app.", + "select_destination": "Mangyaring piliin ang patutunguhan para sa backup file.", + "select_sell_provider_notice": "Pumili ng provider ng nagbebenta sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na sell provider sa mga setting ng app.", + "sell": "Ibenta", + "sell_alert_content": "Kasalukuyan lamang naming sinusuportahan ang pagbebenta ng Bitcoin, Ethereum at Litecoin. Mangyaring lumikha o lumipat sa iyong Bitcoin, Ethereum o Litecoin Wallet.", + "sell_monero_com_alert_content": "Ang pagbebenta ng Monero ay hindi pa suportado", + "send": "Ipadala", + "send_address": "${cryptoCurrency} address", + "send_amount": "Halaga:", + "send_creating_transaction": "Paglikha ng transaksyon", + "send_error_currency": "Ang pera ay maaari lamang maglaman ng mga numero", + "send_error_minimum_value": "Ang pinakamababang halaga ng halaga ay 0.01", + "send_estimated_fee": "Tinatayang bayad:", + "send_fee": "Bayad:", + "send_name": "Pangalan", + "send_new": "Bago", + "send_payment_id": "Payment ID (Opsyonal)", + "send_priority": "Sa kasalukuyan ang bayad ay nakatakda sa ${transactionPriority} priority.\nAng priority ng transaksyon ay maaaring maiakma sa mga setting", + "send_sending": "Pagpapadala ...", + "send_success": "Ang iyong ${crypto} ay matagumpay na naipadala", + "send_templates": "Mga template", + "send_title": "Ipadala", + "send_to_this_address": "Magpadala ng ${currency} ${tag} sa address na ito", + "send_xmr": "Magpadala ng XMR", + "send_your_wallet": "Iyong pitaka", + "sending": "Pagpapadala", + "sent": "Ipinadala", + "settings": "Mga setting", + "settings_all": "Lahat", + "settings_allow_biometrical_authentication": "Payagan ang pagpapatunay ng biometrical", + "settings_can_be_changed_later": "Ang mga setting na ito ay maaaring mabago mamaya sa mga setting ng app", + "settings_change_language": "Baguhin ang wika", + "settings_change_pin": "Baguhin ang pin", + "settings_currency": "Pera", + "settings_current_node": "Kasalukuyang node", + "settings_dark_mode": "Madilim na mode", + "settings_display_balance": "Ipakita ang balanse", + "settings_display_on_dashboard_list": "Ipakita sa listahan ng dashboard", + "settings_fee_priority": "Priority priority", + "settings_nodes": "Node", + "settings_none": "Wala", + "settings_only_trades": "TRADES LAMANG", + "settings_only_transactions": "Mga transaksyon lamang", + "settings_personal": "Personal", + "settings_save_recipient_address": "I -save ang address ng tatanggap", + "settings_support": "Suporta", + "settings_terms_and_conditions": "Mga Tuntunin at Kundisyon", + "settings_title": "Mga setting", + "settings_trades": "Trading", + "settings_transactions": "Mga Transaksyon", + "settings_wallets": "Wallets", + "setup_2fa": "Setup cake 2fa", + "setup_2fa_text": "Gumagana ang Cake 2FA gamit ang TOTP bilang pangalawang kadahilanan sa pagpapatunay.\n\nAng TOTP ng Cake 2FA ay nangangailangan ng SHA-512 at 8 digit na suporta; nagbibigay ito ng mas mataas na seguridad. Higit pang impormasyon at suportadong app ang makikita sa gabay.", + "setup_pin": "Setup pin", + "setup_successful": "Matagumpay na na -set up ang iyong pin!", + "setup_totp_recommended": "I-setup ang TOTP", + "setup_warning_2fa_text": "Kakailanganin mong ibalik ang iyong wallet mula sa mnemonic seed.\n\nHindi ka matutulungan ng suporta sa cake kung mawawalan ka ng access sa iyong 2FA o mnemonic seeds.\nAng Cake 2FA ay pangalawang pagpapatotoo para sa ilang partikular na pagkilos sa wallet. Bago gamitin ang Cake 2FA, inirerekomenda naming basahin ang gabay.HINDI ito kasing-secure ng malamig na imbakan.\n\nKung nawalan ka ng access sa iyong 2FA app o TOTP keys, MAWAWALA ka ng access sa wallet na ito. ", + "setup_your_debit_card": "I -set up ang iyong debit card", + "share": "Ibahagi", + "share_address": "Ibahagi ang address", + "show_details": "Ipakita ang mga detalye", + "show_keys": "Ipakita ang mga binhi/susi", + "show_market_place": "Ipakita ang Marketplace", + "show_seed": "Magpakita ng binhi", + "sign_up": "Mag -sign up", + "signTransaction": "Mag-sign Transaksyon", + "signup_for_card_accept_terms": "Mag -sign up para sa card at tanggapin ang mga termino.", + "slidable": "Slidable", + "sort_by": "Pag -uri -uriin sa pamamagitan ng", + "spend_key_private": "Gumastos ng susi (pribado)", + "spend_key_public": "Gumastos ng susi (publiko)", + "status": "Katayuan:", + "subaddress_title": "Listahan ng Subaddress", + "subaddresses": "Mga Subaddresses", + "submit_request": "magsumite ng isang kahilingan", + "successful": "Matagumpay", + "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 Gabay sa Wallet ng cake", + "support_title_live_chat": "Live na suporta", + "support_title_other_links": "Iba pang mga link sa suporta", + "sweeping_wallet": "Pagwawalis ng pitaka", + "sweeping_wallet_alert": "Hindi ito dapat magtagal. Huwag iwanan ang screen na ito o maaaring mawala ang mga pondo ng swept.", + "switchToETHWallet": "Mangyaring lumipat sa isang Ethereum wallet at subukang muli", + "switchToEVMCompatibleWallet": "Mangyaring lumipat sa isang EVM compatible na wallet at subukang muli (Ethereum, Polygon)", + "symbol": "Simbolo", + "sync_all_wallets": "I -sync ang lahat ng mga pitaka", + "sync_status_attempting_sync": "Pagtatangka ng pag -sync", + "sync_status_connected": "Konektado", + "sync_status_connecting": "Pagkonekta", + "sync_status_failed_connect": "Naka -disconnect", + "sync_status_not_connected": "HINDI KONEKTADO", + "sync_status_starting_sync": "Simula sa pag -sync", + "sync_status_syncronized": "Naka -synchronize", + "sync_status_syncronizing": "Pag -synchronize", + "syncing_wallet_alert_content": "Ang iyong balanse at listahan ng transaksyon ay maaaring hindi kumpleto hanggang sa sabihin nito na \"naka -synchronize\" sa tuktok. Mag -click/tap upang malaman ang higit pa.", + "syncing_wallet_alert_title": "Ang iyong pitaka ay nag -sync", + "template": "Template", + "template_name": "Pangalan ng Template", + "third_intro_content": "Ang mga yats ay nakatira sa labas ng cake wallet, din. Ang anumang address ng pitaka sa mundo ay maaaring mapalitan ng isang yat!", + "third_intro_title": "Si Yat ay mahusay na gumaganap sa iba", + "time": "${minutes} m ${seconds} s", + "tip": "Tip:", + "today": "Ngayon", + "token_contract_address": "Token Address ng Kontrata", + "token_decimal": "Token Decimal", + "token_name": "Pangalan ng Token hal: Tether", + "token_symbol": "Simbolo ng token hal: USDT", + "tokenID": "ID", + "tor_connection": "Koneksyon ng Tor", + "tor_only": "Tor lang", + "total_saving": "Kabuuang pagtitipid", + "totp_2fa_failure": "Maling code. Mangyaring subukan ang ibang code o makabuo ng isang bagong lihim na susi. Gumamit ng isang katugmang 2FA app na sumusuporta sa 8-digit na mga code at SHA512.", + "totp_2fa_success": "Tagumpay! Pinagana ang cake 2FA para sa pitaka na ito. Tandaan na i -save ang iyong mnemonic seed kung sakaling mawalan ka ng pag -access sa pitaka.", + "totp_auth_url": "TOTP AUTH URL", + "totp_code": "TOTP code", + "totp_secret_code": "TOTP Secret Code", + "totp_verification_success": "Matagumpay ang pagpapatunay!", + "trade_details_copied": "${title} kinopya sa clipboard", + "trade_details_created_at": "Nilikha sa", + "trade_details_fetching": "Pagkuha", + "trade_details_id": "ID", + "trade_details_pair": "Pares", + "trade_details_provider": "Tagabigay", + "trade_details_state": "Katayuan", + "trade_details_title": "Mga detalye sa kalakalan", + "trade_for_not_created": "Ang kalakalan para sa ${title} ay hindi nilikha.", + "trade_history_title": "Kasaysayan ng Kalakal", + "trade_id": "Trade ID:", + "trade_id_not_found": "Trade ${tradeId} ng ${title} Hindi natagpuan.", + "trade_is_powered_by": "Ang kalakalan na ito ay pinalakas ng ${provider}", + "trade_not_created": "Hindi nilikha ang kalakalan", + "trade_not_found": "Hindi natagpuan ang kalakalan.", + "trade_state_btc_sent": "Ipinadala ang BTC", + "trade_state_complete": "Kumpleto", + "trade_state_confirming": "Pagkumpirma", + "trade_state_created": "Nilikha", + "trade_state_finished": "Tapos na", + "trade_state_paid": "Bayad", + "trade_state_paid_unconfirmed": "Bayad na hindi nakumpirma", + "trade_state_pending": "Nakabinbin", + "trade_state_timeout": "Oras ng oras", + "trade_state_to_be_created": "Upang malikha", + "trade_state_traded": "Ipinagpalit", + "trade_state_trading": "Pangangalakal", + "trade_state_underpaid": "Underpaid", + "trade_state_unpaid": "Walang bayad", + "trades": "Trading", + "transaction_details_amount": "Halaga", + "transaction_details_copied": "${title} kinopya sa clipboard", + "transaction_details_date": "Petsa", + "transaction_details_fee": "Bayad", + "transaction_details_height": "Taas", + "transaction_details_recipient_address": "Mga address ng tatanggap", + "transaction_details_source_address": "SOURCE ADDRESS", + "transaction_details_title": "Mga detalye ng transaksyon", + "transaction_details_transaction_id": "Transaction ID", + "transaction_key": "Susi ng transaksyon", + "transaction_priority_fast": "Mabilis", + "transaction_priority_fastest": "Pinakamabilis", + "transaction_priority_medium": "Katamtaman", + "transaction_priority_regular": "Regular", + "transaction_priority_slow": "Mabagal", + "transaction_sent": "Ipinadala ang transaksyon!", + "transaction_sent_notice": "Kung ang screen ay hindi magpatuloy pagkatapos ng 1 minuto, suriin ang isang block explorer at ang iyong email.", + "transactions": "Mga Transaksyon", + "transactions_by_date": "Mga Transaksyon ayon sa Petsa", + "trusted": "Pinagkakatiwalaan", + "unavailable_balance": "Hindi available na balanse", + "unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.", + "unconfirmed": "Hindi nakumpirma na balanse", + "understand": "naiintindihan ko", + "unmatched_currencies": "Ang pera ng iyong kasalukuyang pitaka ay hindi tumutugma sa na -scan na QR", + "unspent_change": "Baguhin", + "unspent_coins_details_title": "Mga Detalye ng Unspent Coins", + "unspent_coins_title": "Unspent barya", + "upto": "Hanggang sa ${value}", + "use": "Lumipat sa", + "use_card_info_three": "Gamitin ang digital card online o sa mga pamamaraan ng pagbabayad na walang contact.", + "use_card_info_two": "Ang mga pondo ay na -convert sa USD kapag gaganapin sila sa prepaid account, hindi sa mga digital na pera.", + "use_ssl": "Gumamit ng SSL", + "use_suggested": "Gumamit ng iminungkahing", + "variable_pair_not_supported": "Ang variable na pares na ito ay hindi suportado sa mga napiling palitan", + "verification": "Pag -verify", + "verify_with_2fa": "Mag -verify sa cake 2FA", + "version": "Bersyon ${currentVersion}", + "view_all": "Tingnan lahat", + "view_in_block_explorer": "Tingnan sa Block Explorer", + "view_key_private": "Tingnan ang Key (Pribado)", + "view_key_public": "Tingnan ang Key (Publiko)", + "view_transaction_on": "Tingnan ang transaksyon sa", + "wallet_keys": "Mga buto/susi ng pitaka", + "wallet_list_create_new_wallet": "Lumikha ng bagong pitaka", + "wallet_list_edit_wallet": "I -edit ang Wallet", + "wallet_list_failed_to_load": "Nabigong mag -load ng ${wallet_name} pitaka. ${error}", + "wallet_list_failed_to_remove": "Nabigong alisin ang ${wallet_name} wallet. ${error}", + "wallet_list_load_wallet": "Mag -load ng pitaka", + "wallet_list_loading_wallet": "Naglo -load ng ${wallet_name} Wallet", + "wallet_list_removing_wallet": "Pag -alis ng ${wallet_name} Wallet", + "wallet_list_restore_wallet": "Ibalik ang pitaka", + "wallet_list_title": "Monero Wallet", + "wallet_list_wallet_name": "Pangalan ng Wallet", + "wallet_menu": "Menu", + "wallet_name": "Pangalan ng Wallet", + "wallet_name_exists": "Ang isang pitaka na may pangalang iyon ay mayroon na. Mangyaring pumili ng ibang pangalan o palitan muna ang iba pang pitaka.", + "wallet_restoration_store_incorrect_seed_length": "Maling haba ng binhi", + "wallet_seed": "SEED ng Wallet", + "wallet_seed_legacy": "Legacy wallet seed", + "wallet_store_monero_wallet": "Monero Wallet", + "walletConnect": "WalletConnect", + "wallets": "Wallets", + "warning": "Babala", + "welcome": "Maligayang pagdating sa", + "welcome_to_cakepay": "Maligayang pagdating sa cake pay!", + "widgets_address": "Address", + "widgets_or": "o", + "widgets_restore_from_blockheight": "Ibalik mula sa blockheight", + "widgets_restore_from_date": "Ibalik mula sa petsa", + "widgets_seed": "Binhi", + "wouoldLikeToConnect": "gustong kumonekta", + "write_down_backup_password": "Mangyaring isulat ang iyong backup password, na ginagamit para sa pag -import ng iyong mga backup file.", + "xlm_extra_info": "Mangyaring huwag kalimutan na tukuyin ang memo ID habang ipinapadala ang transaksyon ng XLM para sa palitan", + "xmr_available_balance": "Magagamit na balanse", + "xmr_full_balance": "Buong balanse", + "xmr_hidden": "Nakatago", + "xmr_to_error": "Xmr.to error", + "xmr_to_error_description": "Di -wastong halaga. Pinakamataas na limitasyon ng 8 numero pagkatapos ng punto ng desimal", + "xrp_extra_info": "Mangyaring huwag kalimutan na tukuyin ang patutunguhan na tag habang ipinapadala ang transaksyon ng XRP para sa palitan", + "yat": "Yat", + "yat_address": "Yat address", + "yat_alert_content": "Ang mga gumagamit ng cake wallet ay maaari na ngayong magpadala at makatanggap ng lahat ng kanilang mga paboritong pera na may isang one-of-a-kind emoji-based username.", + "yat_alert_title": "Magpadala at tumanggap ng crypto nang mas madali sa yat", + "yat_error": "Error sa yat", + "yat_error_content": "Walang mga address na naka -link sa yat na ito. Subukan ang isa pang yat", + "yat_popup_content": "Maaari ka na ngayong magpadala at makatanggap ng crypto sa cake wallet kasama ang iyong yat - isang maikli, emoji na batay sa username. Pamahalaan ang mga yats anumang oras sa screen ng Mga Setting", + "yat_popup_title": "Ang iyong wallet address ay maaaring ma -emojified.", + "yesterday": "Kahapon", + "you_now_have_debit_card": "Mayroon ka na ngayong debit card", + "you_pay": "Magbabayad ka", + "you_will_get": "Mag -convert sa", + "you_will_send": "I -convert mula sa", + "yy": "YY", + "zzzz": "Zzzz" +} \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 337a85ff8..eeaaf3a40 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -1,777 +1,778 @@ { - "welcome": "Hoş Geldiniz", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Monero, Bitcoin, Ethereum, Litecoin ve Haven için harika cüzdan", - "please_make_selection": "Cüzdan oluşturmak veya geri döndürmek için aşağıdan seçim yap.", - "create_new": "Yeni Cüzdan Oluştur", - "restore_wallet": "Cüzdanı Geri Döndür", - "monero_com": "Cake Wallet tarafından Monero.com", - "monero_com_wallet_text": "Monero için harika cüzdan", - "haven_app": "Cake Wallet tarafından Haven", - "haven_app_wallet_text": "Haven için harika cüzdan ", - "accounts": "Hesaplar", - "edit": "Düzenle", + "about_cake_pay": "Cake Pay, Amerika Birleşik Devletleri'ndeki 150.000'den fazla işyerinde anında harcanabilen sanal varlıklarla kolayca hediye kartları satın almanızı sağlar.", "account": "Hesap", + "accounts": "Hesaplar", + "accounts_subaddresses": "Hesaplar ve alt adresler", + "activate": "Aktifleştir", + "active": "Aktif", + "active_cards": "Aktif kartlar", + "activeConnectionsPrompt": "Aktif bağlantılar burada görünecek", "add": "Ekle", + "add_contact": "Kişi ekle", + "add_custom_node": "Yeni Özel Düğüm Ekleme", + "add_custom_redemption": "Özel Bozdurma Ekle", + "add_fund_to_card": "Ön ödemeli kartlara para ekle (En fazla yüklenebilir tutar: ${value})", + "add_new_node": "Yeni düğüm ekle", + "add_new_word": "Yeni kelime ekle", + "add_receiver": "Başka bir alıcı ekle (isteğe bağlı)", + "add_secret_code": "Veya bu gizli kodu bir kimlik doğrulama uygulamasına ekleyin", + "add_tip": "Bahşiş Ekle", + "add_token_disclaimer_check": "Belirteç sözleşmesi adresini ve bilgilerini saygın bir kaynak kullanarak onayladım. Kötü amaçlı veya yanlış bilgilerin eklenmesi para kaybına neden olabilir.", + "add_token_warning": "Dolandırıcıların talimatına göre jetonları düzenlemeyin veya eklemeyin.\nBelirteç adreslerini her zaman saygın kaynaklarla onaylayın!", + "add_value": "Değer ekle", + "address": "Adres", "address_book": "Adres Defteri", - "contact": "Rehber", - "please_select": "Lütfen seçim yap:", - "cancel": "İptal", - "ok": "Tamam", - "contact_name": "Kişi ismi", - "reset": "Sıfırla", - "save": "Kaydet", + "address_book_menu": "Adres defteri", + "address_detected": "Adres tespit edildi", + "address_from_domain": "Bu adres Unstoppable Domains'deki' ${domain} adresinden alındı", + "address_from_yat": "Bu adres Yat'taki ${emoji} adresinden alındı", + "address_label": "Adres etiketi", "address_remove_contact": "Kişiyi sil", "address_remove_content": "Seçili kişiyi silmek istediğinden emin misin?", - "authenticated": "Doğrulandı", - "authentication": "Doğrulama", - "failed_authentication": "Doğrulama başarısız oldu. ${state_error}", - "wallet_menu": "Menü", - "Blocks_remaining": "${status} Blok Kaldı", - "please_try_to_connect_to_another_node": "Lütfen farklı düğüme bağlanmayı dene", - "xmr_hidden": "Gizli", - "xmr_available_balance": "Kullanılabilir Bakiye", - "xmr_full_balance": "Tüm Bakiye", - "send": "Para Gönder", - "receive": "Para Al", - "transactions": "İşlemler", - "incoming": "Gelen", - "outgoing": "Giden", - "transactions_by_date": "Tarihe göre transferler", - "trades": "Takaslar", - "filter_by": "Şuna göre filtrele", - "today": "Bugün", - "yesterday": "Dün", - "received": "Alındı", - "sent": "Gönderildi", - "pending": " (bekleyen)", - "rescan": "Yeniden Tara", - "reconnect": "Yeniden Bağlan", - "wallets": "Cüzdanlar", - "show_seed": "Tohumları göster", - "show_keys": "Tohumları/anahtarları göster", - "address_book_menu": "Adres defteri", - "reconnection": "Yeniden bağlantı", - "reconnect_alert_text": "Yeniden bağlanmak istediğinden emin misin?", - "exchange": "Takas", - "clear": "Temizle", - "refund_address": "İade adresi", - "change_exchange_provider": "Takas sağlayıcısını değiştir", - "you_will_send": "Biçiminden dönüştür:", - "you_will_get": "Biçimine dönüştür:", - "amount_is_guaranteed": "Alacağınız tutar garantilidir", - "amount_is_estimate": "Alacağınız tutar tahminidir", - "powered_by": "${title} tarafından desteklenmektedir", - "error": "Hata", - "estimated": "Tahmini", - "min_value": "En az: ${value} ${currency}", - "max_value": "En fazla: ${value} ${currency}", - "change_currency": "Para Birimini Değiştir", - "overwrite_amount": "Miktarın üzerine yaz", - "qr_payment_amount": "Bu QR kodu ödeme tutarını içeriyor. Geçerli miktarın üzerine yazmak istediğine emin misin?", - "copy_id": "ID'yi kopyala", - "exchange_result_write_down_trade_id": "Devam etmek için lütfen ID'yi kopyala veya bir yere yaz.", - "trade_id": "Takas ID'si:", - "copied_to_clipboard": "Panoya Kopyalandı", - "saved_the_trade_id": "Takas ID'imi kaydettim", - "fetching": "Getiriliyor", - "id": "ID: ", - "amount": "Miktar: ", - "payment_id": "Ödeme ID'si: ", - "status": "Durum: ", - "offer_expires_in": "Teklifin bitmesine kalan: ", - "trade_is_powered_by": "Bu takas ${provider} tarafından desteklenmektedir", - "copy_address": "Adresi kopyala", - "exchange_result_confirm": "Onaylaya basarak, ${fetchingLabel} ${from} miktarında ${walletName} olarak adlandırılan cüzdanından aşağıda gösterilen adrese gönderilecek. Veya harici cüzdanından aşağıdaki adrese / QR koduna gönderebilirsin.\n\nLütfen devam etmek için onayla'ya bas veya tutarı değiştirmek için geri dön.", - "exchange_result_description": "Lütfen en az ${fetchingLabel} miktarındaki ${from}'yi sonraki sayfada gönsterilen adrese gönder. Eğer ${fetchingLabel} ${from}'den az gönderirsen takas gerçekleşmeyebilir ve size geri iade edilebilir.", - "exchange_result_write_down_ID": "*Lütfen yukarıda gösterilen ID'ni kopyala veya bir yere yaz.", - "confirm": "Onayla", - "confirm_sending": "Göndermeyi onayla", - "commit_transaction_amount_fee": "Transferi gerçekleştir\nMiktar: ${amount}\nKomisyon: ${fee}", - "sending": "Gönderiliyor", - "transaction_sent": "Transfer gönderildi!", - "expired": "Süresi doldu", - "time": "${minutes}d ${seconds}s", - "send_xmr": "XMR gönder", - "exchange_new_template": "Yeni şablon", - "faq": "SSS", - "enter_your_pin": "PIN'ini gir", - "loading_your_wallet": "Cüzdanın yükleniyor", - "new_wallet": "Yeni Cüzdan", - "wallet_name": "Cüzdan ismi", - "continue_text": "Devam et", - "choose_wallet_currency": "Lütfen cüzdanın para birimini seç:", - "node_new": "Yeni düğüm", - "node_address": "Düğüm adresi", - "node_port": "Düğüm port'u", - "login": "Login", - "password": "Parola", - "nodes": "Düğümler", - "node_reset_settings_title": "Ayarları sıfırla", - "nodes_list_reset_to_default_message": "Ayarları varsayılana sıfırlamak istediğinizden emin misin?", - "change_current_node": "Şimdiki düğümü ${node} düğümüne değiştirmek istediğinizden emin misin?", - "change": "Değiştir", - "remove_node": "Düğümü kaldır", - "remove_node_message": "Seçili düğümü kaldırmak istediğinden emin misin?", - "remove": "Kaldır", - "delete": "Sil", - "add_new_node": "Yeni düğüm ekle", - "change_current_node_title": "Şimdiki düğümü değiştir", - "node_test": "Test Et", - "node_connection_successful": "Bağlantı başarılı oldu", - "node_connection_failed": "Bağlantı başarısız oldu", - "new_node_testing": "Yeni düğüm test ediliyor", - "use": "Şuna geç: ", - "digit_pin": " haneli PIN", - "share_address": "Adresi paylaş", - "receive_amount": "Miktar", - "subaddresses": "Alt adresler", "addresses": "Adresler", - "scan_qr_code_to_get_address": "Adresi getirmek için QR kodunu tara", - "qr_fullscreen": "QR kodunu tam ekranda açmak için dokun", - "rename": "Yeniden adlandır", - "choose_account": "Hesabı seç", - "create_new_account": "Yeni hesap oluştur", - "accounts_subaddresses": "Hesaplar ve alt adresler", - "restore_restore_wallet": "Cüzdanı Geri Döndür", - "restore_title_from_seed_keys": "Tohumdan/anahtarlardan geri döndür", - "restore_description_from_seed_keys": "Güvenli bir yere kaydettiğin tohumdan/anahtarlardan cüzdanını geri döndür", - "restore_next": "İleri", - "restore_title_from_backup": "Yedekten geri döndür", - "restore_description_from_backup": "Yedek dosyandan tüm Cake Wallet uygulamasını geri döndürebilirsin", - "restore_seed_keys_restore": "Tohumu/Anahtarları Geri Döndür", - "restore_title_from_seed": "Tohumdan geri döndür", - "restore_description_from_seed": "Cüzdanınızı 25 veya 13 kelimelik kombinasyon kodundan geri döndürün", - "restore_title_from_keys": "Anahtarlardan geri döndür", - "restore_description_from_keys": "Cüzdanınızı özel anahtarlarınızdan kaydedilen oluşturulmuş tuş vuruşlarından geri yükleyin", - "restore_wallet_name": "Cüzdan ismi", - "restore_address": "Adres", - "restore_view_key_private": "İzleme anahtarı (Özel)", - "restore_spend_key_private": "Harcama anahtarı (Özel)", - "restore_recover": "Geri döndür", - "restore_wallet_restore_description": "Cüzdan geri döndürme açıklaması", - "restore_new_seed": "Yeni tohum", - "restore_active_seed": "Tohumu aktifleştir", - "restore_bitcoin_description_from_seed": "Cüzdanınızı 24 kelimelik kombinasyon kodundan geri yükle", - "restore_bitcoin_description_from_keys": "Cüzdanını, oluşturulan WIF dizesinden veya özel anahtarlarından geri yükle", - "restore_bitcoin_title_from_keys": "WIF'den geri yükle", - "restore_from_date_or_blockheight": "Lütfen bu cüzdanı oluşturmadan birkaç gün önceki bir tarihi girin. Veya blok yüksekliğini biliyorsan, lütfen bunu gir", - "seed_reminder": "Telefonunu kaybetmen veya silinmesi ihtimaline karşı lütfen bunları not et", - "seed_title": "Tohum", - "seed_share": "Tohumu paylaş", - "copy": "Kopyala", - "seed_language": "Tohum dili", - "seed_choose": "Tohum dilini seçin", - "seed_language_next": "İleri", - "seed_language_english": "İngilizce", - "seed_language_chinese": "Çince", - "seed_language_dutch": "Flemenkçe", - "seed_language_german": "Almanca", - "seed_language_japanese": "Japonca", - "seed_language_portuguese": "Portekizce", - "seed_language_russian": "Rusça", - "seed_language_spanish": "İspanyolca", - "seed_language_french": "Fransızca", - "seed_language_italian": "İtalyanca", - "send_title": "Gönder", - "send_your_wallet": "Cüzdanın", - "send_address": "${cryptoCurrency} adresi", - "send_payment_id": "Ödeme ID'si (isteğe bağlı)", + "advanced_settings": "Gelişmiş Ayarlar", + "aggressive": "Aşırı duyarlı", + "agree": "Kabul Et", + "agree_and_continue": "Kabul Et & Devam Et", + "agree_to": "Hesap oluşturarak bunları kabul etmiş olursunuz ", "all": "HEPSİ", - "send_error_minimum_value": "Minimum tutar değeri 0.01'dir", - "send_error_currency": "Para birimi sadece sayı içerebilir", - "send_estimated_fee": "Tahmini komisyon:", - "send_priority": "Şu anda ücret ${transactionPriority} önceliğine ayarlanmıştır.\nİşlem önceliği ayarlardan değiştirilebilir", - "send_creating_transaction": "İşlem oluşturuluyor", - "send_templates": "Şablonlar", - "send_new": "Yeni", - "send_amount": "Miktar:", - "send_fee": "Komisyon:", - "send_name": "İsim", - "got_it": "Tamamdır", - "send_sending": "Gönderiliyor...", - "send_success": "${crypto} başarıyla gönderildi", - "settings_title": "Ayarlar", - "settings_nodes": "Düğümler", - "settings_current_node": "Şimdiki düğüm", - "settings_wallets": "Cüzdanlar", - "settings_display_balance": "Bakiyeyi göster", - "settings_currency": "Para birimi", - "settings_fee_priority": "İşlem Komsiyonu önceliği", - "settings_save_recipient_address": "Gönderilen adresi kaydet", - "settings_personal": "Kişisel", - "settings_change_pin": "PIN'i değiştir", - "settings_change_language": "Dili değiştir", - "settings_allow_biometrical_authentication": "Biyometrik doğrulamaya izin ver", - "settings_dark_mode": "Karanlık mod", - "settings_transactions": "İşlemler", - "settings_trades": "Takaslar", - "settings_display_on_dashboard_list": "Gösterge tablosu listesinde göster", - "settings_all": "HEPSİ", - "settings_only_trades": "Sadece takaslar", - "settings_only_transactions": "Sadece transferler", - "settings_none": "Hiçbiri", - "settings_support": "Destek", - "settings_terms_and_conditions": "Şartlar ve Koşullar", - "pin_is_incorrect": "PIN kodu hatalı", - "setup_pin": "PIN kodu kurulumu", - "enter_your_pin_again": "PIN kodunu tekrar girin", - "setup_successful": "PIN kodun başarıyla ayarlandı!", - "wallet_keys": "Cüzdan tohumu/anahtarları", - "wallet_seed": "Cüzdan tohumu", - "private_key": "Özel anahtar", - "public_key": "Genel Anahtar", - "view_key_private": "İzleme anahtarı (özel)", - "view_key_public": "İzleme anahtarı (genel)", - "spend_key_private": "Harcama anahtarı (özel)", - "spend_key_public": "Harcama anahtarı (genel)", - "copied_key_to_clipboard": "${key} panoya kopyalandı", - "new_subaddress_title": "Yeni adres", - "new_subaddress_label_name": "Etiket ismi", - "new_subaddress_create": "Oluştur", - "address_label": "Adres etiketi", - "subaddress_title": "Alt adres listesi", - "trade_details_title": "Takas Detayları", - "trade_details_id": "ID", - "trade_details_state": "Durum", - "trade_details_fetching": "Getiriliyor", - "trade_details_provider": "Sağlayıcı", - "trade_details_created_at": "'da oluşturuldu", - "trade_details_pair": "Parite", - "trade_details_copied": "${title} panoya kopyalandı", - "trade_history_title": "Takas geçmişi", - "transaction_details_title": "İşlem Detayları", - "transaction_details_transaction_id": "İşem ID'si", - "transaction_details_date": "Tarih", - "transaction_details_height": "Yükseklik", - "transaction_details_amount": "Miktar", - "transaction_details_fee": "Fee", - "transaction_details_copied": "${title} panoya kopyalandı", - "transaction_details_recipient_address": "Alıcı adres", - "wallet_list_title": "Monero Cüzdanı", - "wallet_list_create_new_wallet": "Yeni Cüzdan Oluştur", - "wallet_list_edit_wallet": "Cüzdanı düzenle", - "wallet_list_wallet_name": "Cüzdan adı", - "wallet_list_restore_wallet": "Cüzdanı Geri Yükle", - "wallet_list_load_wallet": "Cüzdanı yükle", - "wallet_list_loading_wallet": "${wallet_name} cüzdanı yükleniyor", - "wallet_list_failed_to_load": "Failed to load ${wallet_name} wallet. ${error}", - "wallet_list_removing_wallet": "Removing ${wallet_name} wallet", - "wallet_list_failed_to_remove": "${wallet_name} cüzdanı yüklenirken hata oluştu. ${error}", - "widgets_address": "Adres", - "widgets_restore_from_blockheight": "Blok yüksekliğinden geri yükle", - "widgets_restore_from_date": "Tarihten geri yükle", - "widgets_or": "veya", - "widgets_seed": "Tohum", - "router_no_route": "${name} için rota tanımlanmadı", - "error_text_account_name": "Hesap ismi yalnızca harf, rakam \nve 1 ile 15 uzunluğunda karakter içermelidir.", - "error_text_contact_name": "Kişi ismi ` , ' \" sembollerini içeremez \nve 1 ile 32 uzunluğunda karakter içermelidir", - "error_text_address": "Cüzdan adresi kripto para biriminin\ntürüne karşılık gelmelidir", - "error_text_node_address": "Lütfen iPv4 adresi girin", - "error_text_node_port": "Düğüm port'u yalnızca 0 ve 65535 arasında rakam içerebilir", - "error_text_node_proxy_address": "Lütfen : girin, örneğin 127.0.0.1:9050", - "error_text_payment_id": "Ödeme ID'si yalnızca onaltılık (hex) olarak 16 veya 64 karakter içerebilir", - "error_text_xmr": "XMR miktarı kullanılabilir bakiyeyi aşamaz.\nKesir basamaklarının sayısı 12'ye eşit veya daha az olmalıdır", - "error_text_fiat": "Tutarın değeri, mevcut bakiyeyi aşamaz.\nKesir basamaklarının sayısı 2'ye eşit veya daha az olmalıdır", - "error_text_subaddress_name": "Alt adres ismi ` , ' \" sembolleri içeremez\nve 1 ile 20 karakter arasında olmalıdır", - "error_text_amount": "Miktar sadece sayı içerebilir", - "error_text_wallet_name": "Cüzdan ismi yalnızca harf, rakam \nve 1 ile 33 uzunluğunda karakter içermelidir.", - "error_text_keys": "Cüzdan anahtarları onaltılık (hex) olarak yalnızca 64 karakter içerebilir", - "error_text_crypto_currency": "Kesir basamaklarının sayısı\n12'ye eşit veya daha az olmalıdır", - "error_text_minimal_limit": "${provider} için işlem oluşturulmadı. Miktar minimumdan daha azdır: ${min} ${currency}", - "error_text_maximum_limit": "${provider} için işlem oluşturulmadı. Miktar maksimumdan daha fazla: ${max} ${currency}", - "error_text_limits_loading_failed": "${provider} için işlem oluşturulmadı. Limitler yüklenirken hata oluştu.", - "error_text_template": "Şablon adı ve adresi ` , ' \" sembolleri içeremez\nve 1 ila 106 karakter uzunluğunda olmalı", + "all_trades": "Tüm takaslar", + "all_transactions": "Tüm transferler", + "alphabetical": "Alfabetik", + "already_have_account": "Zaten bir hesabınız var mı?", + "always": "Her Zaman", + "amount": "Miktar: ", + "amount_is_estimate": "Alacağınız tutar tahminidir", + "amount_is_guaranteed": "Alacağınız tutar garantilidir", + "and": "ve", + "anonpay_description": "${type} oluşturun. Alıcı, desteklenen herhangi bir kripto para birimi ile ${method} yapabilir ve bu cüzdanda para alırsınız.", + "apk_update": "APK güncellemesi", + "approve": "Onaylamak", + "arrive_in_this_address": "${currency} ${tag}bu adrese ulaşacak", + "ascending": "Yükselen", + "ask_each_time": "Her seferinde sor", "auth_store_ban_timeout": "ban_timeout", "auth_store_banned_for": "Bu kadar süreliğine yasaklandınız: ", "auth_store_banned_minutes": " dakika", "auth_store_incorrect_password": "Hatalı PIN", - "wallet_store_monero_wallet": "Monero Cüzdanı", - "wallet_restoration_store_incorrect_seed_length": "Yanlış tohum uzunluğu", - "full_balance": "Tüm bakiye", - "available_balance": "Kullanılabilir Bakiye", - "hidden_balance": "Gizli Bakiye", - "sync_status_syncronizing": "SENKRONİZE EDİLİYOR", - "sync_status_syncronized": "SENKRONİZE EDİLDİ", - "sync_status_not_connected": "BAĞLI DEĞİL", - "sync_status_starting_sync": "SENKRONİZE BAŞLATILIYOR", - "sync_status_failed_connect": "BAĞLANTI KESİLDİ", - "sync_status_connecting": "BAĞLANILIYOR", - "sync_status_connected": "BAĞLANILDI", - "sync_status_attempting_sync": "SENKRONİZE EDİLMEYE ÇALIŞILIYOR", - "transaction_priority_slow": "Yavaş", - "transaction_priority_regular": "Normal", - "transaction_priority_medium": "Orta", - "transaction_priority_fast": "Hızlı", - "transaction_priority_fastest": "En Hızlı", - "trade_for_not_created": "${title} için takas oluşturulmadı.", - "trade_not_created": "Takas oluşturulmadı", - "trade_id_not_found": "Trade ${tradeId} of ${title} not found.", - "trade_not_found": "Takas bulunamadı.", - "trade_state_pending": "Beklemede", - "trade_state_confirming": "Onaylanıyor", - "trade_state_trading": "Takas yapılıyor", - "trade_state_traded": "Takas yapıldı", - "trade_state_complete": "Tamamlandı", - "trade_state_to_be_created": "Oluşturulacak", - "trade_state_unpaid": "Ödenmedi", - "trade_state_underpaid": "Eksik ödendi", - "trade_state_paid_unconfirmed": "Ödendi onaylanmadı", - "trade_state_paid": "Ödendi", - "trade_state_btc_sent": "Btc gönderildi", - "trade_state_timeout": "Zaman aşımı", - "trade_state_created": "Oluşturuldu", - "trade_state_finished": "Tamamlandı", - "change_language": "Dili değiştir", - "change_language_to": "Dili şuna değiştir: ${language}?", - "paste": "Yapıştır", - "restore_from_seed_placeholder": "Lütfen tohumunu buraya gir veya yapıştır", - "add_new_word": "Yeni kelime ekle", - "incorrect_seed": "Girilen metin geçerli değil.", - "biometric_auth_reason": "Kimlik doğrulaması için parmak izini okutun", - "version": "Sürüm ${currentVersion}", - "extracted_address_content": "Parayı buraya gönderceksin:\n${recipient_name}", - "card_address": "Adres:", - "buy": "Alış", - "sell": "Satış", - "placeholder_transactions": "İşlemlerin burada görüntülenecek", - "placeholder_contacts": "Kişilerin burada görüntülenecek", - "template": "Şablon", - "confirm_delete_template": "Bu eylem, bu şablonu silecek. Devam etmek istiyor musun?", - "confirm_delete_wallet": "Bu eylem, bu cüzdanı silecek. Devam etmek istiyor musun?", - "change_wallet_alert_title": "Şimdiki cüzdanı değiştir", - "change_wallet_alert_content": "Şimdiki cüzdanı ${wallet_name} cüzdanı ile değiştirmek istediğinden emin misin?", - "creating_new_wallet": "Cüzdan oluşturuluyor", - "creating_new_wallet_error": "Hata: ${description}", - "seed_alert_title": "Dikkat", - "seed_alert_content": "Cüzdanını kurtarmanın tek yolu tohumdur. Tohumunu yazdın mı?", - "seed_alert_back": "Geriye dön", - "seed_alert_yes": "Evet yazdım", - "exchange_sync_alert_content": "Lütfen cüzdanın senkronize olana kadar bekle", - "pre_seed_title": "UYARI", - "pre_seed_description": "Bir sonraki sayfada ${words} kelime göreceksin. Bu senin benzersiz ve özel tohumundur, kaybetmen veya silinmesi durumunda cüzdanını kurtarmanın TEK YOLUDUR. Bunu yazmak ve Cake Wallet uygulaması dışında güvenli bir yerde saklamak tamamen SENİN sorumluluğunda.", - "pre_seed_button_text": "Anladım. Bana tohumumu göster.", - "xmr_to_error": "XMR.TO hatası", - "xmr_to_error_description": "Geçersiz tutar. Ondalık noktadan sonra maksimum limit 8 basamaktır", - "provider_error": "${provider} hatası", - "use_ssl": "SSL kullan", - "trusted": "Güvenilir", - "color_theme": "Renk teması", - "light_theme": "Aydınlık", - "bright_theme": "Parlak", - "dark_theme": "Karanlık", - "enter_your_note": "Notunu gir…", - "note_optional": "Not (isteğe bağlı)", - "note_tap_to_change": "Not (değiştirmek için dokunun)", - "view_in_block_explorer": "Blok Gezgini'nde görüntüle", - "view_transaction_on": "İşlemi şurada görüntüle ", - "transaction_key": "İşlem Anahtarı", - "confirmations": "Onay", - "recipient_address": "Alıcı adresi", - "extra_id": "Ekstra ID:", - "destination_tag": "Hedef Etiketi:", - "memo": "Memo:", - "backup": "Yedek", - "change_password": "Parolayı değiştir", - "backup_password": "Yedek parolası", - "write_down_backup_password": "Lütfen yedekleme dosyasının içe aktarılması için kullanılan yedekleme parolanı not et.", - "export_backup": "Yedeği dışa aktar", - "save_backup_password": "Lütfen yedekleme parolanı kaydettiğinden emin ol. Bu parola olmadan yedekleme dosyasını içe aktaramazsın.", - "backup_file": "Yedek dosyası", - "edit_backup_password": "Yedek parolasını değiştir", - "save_backup_password_alert": "Yedek parolasını kaydet", - "change_backup_password_alert": "Önceki yedekleme dosyaların yeni yedek parolası ile içe aktarılamayacaktır. Yeni yedekleme parolası yalnızca yeni yedekleme dosyaları için kullanılabilir olacak. Yedekleme parolasını değiştirmek istediğinden emin misin?", - "enter_backup_password": "Yedekleme parolasını buraya gir", - "select_backup_file": "Yedek dosyası seç", - "import": "İçe aktarmak", - "please_select_backup_file": "Lütfen yedekleme dosyasını seç ve yedekleme parolasını gir.", - "fixed_rate": "Sabit oran", - "fixed_rate_alert": "Sabit oran modunu işaretlersen alım tutarını girebilirsin. Sabit oran moduna geçmek ister misin?", - "xlm_extra_info": "Lütfen takas için XLM işlemi gönderirken Memo ID'yi belirtmeyi unutmayın", - "xrp_extra_info": "Lütfen takas için XRP işlemi gönderirken Hedef Etiketi (Destination Tag) belirtmeyi unutmayın", - "exchange_incorrect_current_wallet_for_xmr": "Cake Wallet'daki Monero bakiyenizi kullanarak takas yapmak istiyorsan, lütfen önce Monero cüzdanına geç.", - "confirmed": "Onaylanmış Bakiye", - "unconfirmed": "Onaylanmamış Bakiye", - "displayable": "Gösterilebilir", - "submit_request": "talep gönder", - "buy_alert_content": "Şu anda yalnızca Bitcoin, Ethereum, Litecoin ve Monero satın alımını destekliyoruz. Lütfen Bitcoin, Ethereum, Litecoin veya Monero cüzdanınızı oluşturun veya cüzdanınıza geçin.", - "sell_alert_content": "Şu anda yalnızca Bitcoin, Ethereum ve Litecoin satışını destekliyoruz. Lütfen Bitcoin, Ethereum veya Litecoin cüzdanınızı oluşturun veya cüzdanınıza geçin.", - "outdated_electrum_wallet_description": "Cake'te oluşturulan yeni Bitcoin cüzdanları artık 24 kelimelik bir tohuma sahip. Yeni bir Bitcoin cüzdanı oluşturmanız ve tüm paranızı 24 kelimelik yeni cüzdana aktarmanız ve 12 kelimelik tohuma sahip cüzdanları kullanmayı bırakmanız zorunludur. Lütfen paranızı güvence altına almak için bunu hemen yapın.", - "understand": "Anladım", - "apk_update": "APK güncellemesi", - "buy_bitcoin": "Bitcoin Satın Al", - "buy_with": "Şunun ile al: ", - "moonpay_alert_text": "Tutar ${minAmount} ${fiatCurrency} miktarına eşit veya daha fazla olmalıdır", - "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", - "do_not_show_me": "Bana bunu bir daha gösterme", - "unspent_coins_title": "Harcanmamış koinler", - "unspent_coins_details_title": "Harcanmamış koin detayları", - "freeze": "Dondur", - "frozen": "Dondurulmuş", - "coin_control": "Koin kontrolü (isteğe bağlı)", - "address_detected": "Adres tespit edildi", - "address_from_domain": "Bu adres Unstoppable Domains'deki' ${domain} adresinden alındı", - "add_receiver": "Başka bir alıcı ekle (isteğe bağlı)", - "manage_yats": "Yats'ları yönet", - "yat_alert_title": "Yat ile daha kolay kripto gönderin ve alın", - "yat_alert_content": "Cake Wallet kullanıcıları artık tüm favori koin birimlerini benzersiz emoji tabanlı kullanıcı adıyla gönderebilir ve alabilirler.", - "get_your_yat": "Yat'ını al", - "connect_an_existing_yat": "Mevcut bir Yat'ı bağla", - "connect_yats": "Yat'lara bağlan", - "yat_address": "Yat adresi", - "yat": "Yat", - "address_from_yat": "Bu adres Yat'taki ${emoji} adresinden alındı", - "yat_error": "Yat hatası", - "yat_error_content": "Bu Yat'a bağlı bir adres yok. Başka bir Yat'ı deneyin", - "choose_address": "\n\nLütfen adresi seçin:", - "yat_popup_title": "Cüzdan adresiniz emojileştirilebilir.", - "yat_popup_content": "Artık Cake Wallet'ta kısa, emoji tabanlı bir kullanıcı adı olan Yat'ınızla kripto gönderebilir ve alabilirsiniz. Yats'ı istediğiniz zaman ayarlar ekranından yönetebilirsiniz", - "second_intro_title": "Hepsini yönetebilen tek bir emoji adresi", - "second_intro_content": "Yat'ınız, tüm para birimleriniz için uzun onaltılık adreslerinizin yerini alan benzersiz emoji adresidir.", - "third_intro_title": "Yat diğerleriyle iyi çalışır", - "third_intro_content": "Yat'lar Cake Wallet'ın dışında da çalışabilir. Dünya üzerindeki herhangi bir cüzdan adresi Yat ile değiştirilebilir!", - "learn_more": "Daha fazla öğren", - "search": "Arat", - "search_language": "Dil arat", - "search_currency": "Para birimi ara", - "new_template": "Yeni Şablon", - "electrum_address_disclaimer": "Adresini her kullandığında yeni adres oluşturuyoruz, ancak önceki adresler de çalışmaya devam eder", - "wallet_name_exists": "Bu isimde bir cüzdan zaten mevcut. Lütfen farklı bir isim seç veya önce diğer cüzdanı yeniden adlandır.", - "market_place": "Pazar Alanı", - "cake_pay_title": "Cake Pay Hediye Kartları", - "cake_pay_subtitle": "İndirimli hediye kartları satın alın (yalnızca ABD)", - "cake_pay_web_cards_title": "Cake Pay Web Kartları", - "cake_pay_web_cards_subtitle": "Dünya çapında ön ödemeli kartlar ve hediye kartları satın alın", - "about_cake_pay": "Cake Pay, Amerika Birleşik Devletleri'ndeki 150.000'den fazla işyerinde anında harcanabilen sanal varlıklarla kolayca hediye kartları satın almanızı sağlar.", - "cake_pay_account_note": "Kartları görmek ve satın almak için sadece bir e-posta adresiyle kaydolun. Hatta bazıları indirimli olarak bile mevcut!", - "already_have_account": "Zaten bir hesabınız var mı?", - "create_account": "Hesap oluştur", - "privacy_policy": "Gizlilik Politikası", - "welcome_to_cakepay": "Cake Pay'e Hoş Geldiniz!", - "sign_up": "Kaydol", - "forgot_password": "Parolamı unuttum", - "reset_password": "Parolamı sıfırla", - "gift_cards": "Hediye kartları", - "setup_your_debit_card": "Banka kartını ayarla", - "no_id_required": "Kimlik gerekmez. Para yükleyin ve istediğiniz yerde harcayın", - "how_to_use_card": "Bu kart nasıl kullanılır", - "purchase_gift_card": "Hediye Kartı Satın Al", - "verification": "Doğrulama", - "fill_code": "Lütfen e-postanıza gelen doğrulama kodunu girin", - "didnt_get_code": "Kod gelmedi mi?", - "resend_code": "Lütfen tekrar gönder", - "debit_card": "Ön ödemeli Kart", - "cakepay_prepaid_card": "CakePay Ön Ödemeli Kart", - "no_id_needed": "Kimlik gerekmez!", - "frequently_asked_questions": "Sıkça sorulan sorular", - "debit_card_terms": "Ödeme kartı numaranızın (ve kart numaranıza karşılık gelen kimlik bilgilerinin) bu dijital cüzdanda saklanması ve kullanılması, zaman zaman yürürlükte olan ödeme kartı veren kuruluşla yapılan ilgili kart sahibi sözleşmesinin Hüküm ve Koşullarına tabidir.", - "please_reference_document": "Daha fazla bilgi için lütfen aşağıdaki belgelere bakınız.", - "cardholder_agreement": "Kart Sahibi Sözleşmesi", - "e_sign_consent": "E-İmza Onayı", - "agree_and_continue": "Kabul Et & Devam Et", - "email_address": "E-posta Adresi", - "agree_to": "Hesap oluşturarak bunları kabul etmiş olursunuz ", - "and": "ve", - "enter_code": "Kodu girin", - "congratulations": "Tebrikler!", - "you_now_have_debit_card": "Artık bir ön ödemeli kartın var", - "min_amount": "Min: ${value}", - "max_amount": "Maks: ${value}", - "enter_amount": "Miktar Girin", - "billing_address_info": "Eğer fatura adresi istenirse, kargo adresinizi girin", - "order_physical_card": "Fiziksel Kart Siparişi", - "add_value": "Değer ekle", - "activate": "Aktifleştir", - "get_a": "Bir ", - "digital_and_physical_card": " Dijital para birimleri ile para yükleyebileceğiniz ve ek bilgiye gerek olmayan", - "get_card_note": " dijital ve fiziksel ön ödemeli banka kartı edinin!", - "signup_for_card_accept_terms": "Kart için kaydol ve koşulları kabul et.", - "add_fund_to_card": "Ön ödemeli kartlara para ekle (En fazla yüklenebilir tutar: ${value})", - "use_card_info_two": "Paralar, dijital para birimlerinde değil, ön ödemeli hesapta tutulduğunda USD'ye dönüştürülür.", - "use_card_info_three": "Dijital kartı çevrimiçi olarak veya temassız ödeme yöntemleriyle kullanın.", - "optionally_order_card": "İsteğe bağlı olarak fiziksel bir kart sipariş edin.", - "hide_details": "Detayları Gizle", - "show_details": "Detayları Göster", - "upto": "Şu miktara kadar: ${value}", - "discount": "%${value} tasarruf et", - "gift_card_amount": "Hediye Kartı Tutarı", - "bill_amount": "Fatura Tutarı", - "you_pay": "Şu kadar ödeyeceksin: ", - "tip": "Bahşiş:", - "custom": "özel", - "by_cake_pay": "Cake Pay tarafından", - "expires": "Son kullanma tarihi", - "mm": "AA", - "yy": "YY", - "online": "Çevrimiçi", - "offline": "Çevrimdışı", - "gift_card_number": "Hediye kartı numarası", - "pin_number": "PIN kodu", - "total_saving": "Toplam Tasarruf", - "last_30_days": "Son 30 gün", - "avg_savings": "Ortalama Tasarruf", - "view_all": "Hepsini göster", - "active_cards": "Aktif kartlar", - "delete_account": "Hesabı sil", - "cards": "Kartlar", - "active": "Aktif", - "redeemed": "Kullanılmış", - "gift_card_balance_note": "Bakiyesi kalan olan hediye kartları burada görünecek", - "gift_card_redeemed_note": "Harcadığın hediye kartları burada görünecek", - "logout": "Çıkış yap", - "add_tip": "Bahşiş Ekle", - "percentageOf": "of ${amount}", - "is_percentage": "is", - "search_category": "Kategori ara", - "mark_as_redeemed": "Harcanmış olarak işaretle", - "more_options": "Daha Fazla Seçenek", - "awaiting_payment_confirmation": "Ödemenin onaylanması bekleniyor", - "transaction_sent_notice": "Ekran 1 dakika sonra ilerlemezse, blok gezgininden ve e-postanızdan kontrol edin.", - "agree": "Kabul Et", - "in_store": "Mağazada", - "generating_gift_card": "Hediye Kartı Oluşturuluyor", - "payment_was_received": "Ödemeniz alındı.", - "proceed_after_one_minute": "Ekran 1 dakika sonra ilerlemezse, e-postanızı kontrol edin.", - "order_id": "Sipariş ID'si", - "gift_card_is_generated": "Hediye Kartı oluşturuldu", - "open_gift_card": "Hediye Kartını Aç", - "contact_support": "Destek ile İletişime Geç", - "gift_cards_unavailable": "Hediye kartları şu anda yalnızca Monero, Bitcoin ve Litecoin ile satın alınabilir", - "introducing_cake_pay": "Cake Pay ile tanışın!", - "cake_pay_learn_more": "Uygulamada anında hediye kartları satın alın ve harcayın!\nDaha fazla öğrenmek için soldan sağa kaydır.", - "automatic": "Otomatik", - "fixed_pair_not_supported": "Bu sabit paritesi seçilen borsalarda desteklenmemekte", - "variable_pair_not_supported": "Bu değişken paritesi seçilen borsalarda desteklenmemekte", - "none_of_selected_providers_can_exchange": "Seçilen sağlayıcılardan hiçbiri bu takası yapamaz", - "choose_one": "Birini seç", - "choose_from_available_options": "Mevcut seçenekler arasından seçim yap:", - "custom_redeem_amount": "Özel Harcama Tutarı", - "add_custom_redemption": "Özel Bozdurma Ekle", - "remaining": "kalan", - "delete_wallet": "Cüzdanı sil", - "delete_wallet_confirm_message": "${wallet_name} isimli cüzdanını silmek istediğinden emin misin?", - "low_fee": "Düşük komisyon", - "low_fee_alert": "Şu anda düşük bir ağ ücreti önceliği kullanıyorsunuz. Bu durum uzun beklemeler, farklı oranlar veya iptal edilen işlemlere neden olabilir. Daha iyi bir deneyim için daha yüksek bir ücret belirlemenizi öneririz.", - "ignor": "Yoksay", - "use_suggested": "Önerileni Kullan", - "do_not_share_warning_text": "Bunları destek de dahil olmak üzere başka kimseyle paylaşma.\n\nParan çalınabilir ve çalınacaktır!", - "help": "yardım", - "all_transactions": "Tüm transferler", - "all_trades": "Tüm takaslar", - "connection_sync": "Bağlantı ve senkronizasyon", - "security_and_backup": "Güvenlik ve yedekleme", - "create_backup": "Yedek oluştur", - "privacy_settings": "Gizlilik ayarları", - "privacy": "Gizlilik", - "display_settings": "Görüntü ayarları", - "other_settings": "Diğer ayarlar", - "require_pin_after": "Şu kadar süre sonra PIN iste", - "always": "Her Zaman", - "minutes_to_pin_code": "${minute} dakika", - "disable_exchange": "Borsayı devre dışı bırak", - "advanced_settings": "Gelişmiş Ayarlar", - "settings_can_be_changed_later": "Bu ayarlar daha sonra uygulama ayarlarından da değiştirilebilir", - "add_custom_node": "Yeni Özel Düğüm Ekleme", - "disable_fiat": "İtibari paraları devre dışı bırak", - "fiat_api": "İtibari Para API", - "disabled": "Devre dışı", - "enabled": "Etkin", - "tor_only": "Yalnızca Tor", - "unmatched_currencies": "Mevcut cüzdanınızın para birimi taranan QR ile eşleşmiyor", - "orbot_running_alert": "Lütfen bu düğüme bağlanmadan önce Orbot'un çalıştığından emin olun.", - "contact_list_contacts": "Rehberim", - "contact_list_wallets": "Cüzdanlarım", - "bitcoin_payments_require_1_confirmation": "Bitcoin ödemeleri, 20 dakika veya daha uzun sürebilen 1 onay gerektirir. Sabrınız için teşekkürler! Ödeme onaylandığında e-posta ile bilgilendirileceksiniz.", - "send_to_this_address": "Bu adrese ${currency} ${tag}gönder", - "arrive_in_this_address": "${currency} ${tag}bu adrese ulaşacak", - "do_not_send": "Gönderme", - "error_dialog_content": "Hay aksi, bir hatamız var.\n\nUygulamayı daha iyi hale getirmek için lütfen kilitlenme raporunu destek ekibimize gönderin.", - "scan_qr_code": "QR kodunu tarayın", - "cold_or_recover_wallet": "Soğuk bir cüzdan ekleyin veya bir kağıt cüzdanı kurtarın", - "please_wait": "Lütfen bekleyin", - "sweeping_wallet": "Süpürme cüzdanı", - "sweeping_wallet_alert": "Bu uzun sürmemeli. BU EKRANDAN BIRAKMAYIN YOKSA SÜPÜRÜLEN FONLAR KAYBOLABİLİR", - "decimal_places_error": "Çok fazla ondalık basamak", - "edit_node": "Düğümü Düzenle", - "invoice_details": "fatura detayları", - "donation_link_details": "Bağış bağlantısı ayrıntıları", - "anonpay_description": "${type} oluşturun. Alıcı, desteklenen herhangi bir kripto para birimi ile ${method} yapabilir ve bu cüzdanda para alırsınız.", - "create_invoice": "Fatura oluşturmak", - "create_donation_link": "Bağış bağlantısı oluştur", - "optional_email_hint": "İsteğe bağlı alacaklı bildirim e-postası", - "optional_description": "İsteğe bağlı açıklama", - "optional_name": "İsteğe bağlı alıcı adı", - "clearnet_link": "Net bağlantı", - "onion_link": "soğan bağlantısı", - "settings": "ayarlar", - "sell_monero_com_alert_content": "Monero satışı henüz desteklenmiyor", - "error_text_input_below_minimum_limit": "Miktar minimumdan daha azdır", - "error_text_input_above_maximum_limit": "Miktar maksimumdan daha fazla", - "show_market_place": "Pazar Yerini Göster", - "prevent_screenshots": "Ekran görüntülerini ve ekran kaydını önleyin", - "profile": "Profil", - "close": "Kapalı", - "modify_2fa": "Cake 2FA'yı Değiştirin", - "disable_cake_2fa": "Cake 2FA'yı Devre Dışı Bırak", - "question_to_disable_2fa": "Cake 2FA'yı devre dışı bırakmak istediğinizden emin misiniz? M-cüzdana ve belirli işlevlere erişmek için artık 2FA koduna gerek kalmayacak.", - "disable": "Devre dışı bırakmak", - "setup_2fa": "Kurulum Pastası 2FA", - "verify_with_2fa": "Cake 2FA ile Doğrulayın", - "totp_code": "TOTP Kodu", - "please_fill_totp": "Lütfen diğer cihazınızda bulunan 8 haneli kodu girin", - "totp_2fa_success": "Başarı! Bu cüzdan için Cake 2FA etkinleştirildi. Mnemonic seed'inizi cüzdan erişiminizi kaybetme ihtimaline karşı kaydetmeyi unutmayın.", - "totp_verification_success": "Doğrulama Başarılı!", - "totp_2fa_failure": "Yanlış kod. Lütfen farklı bir kod deneyin veya yeni bir gizli anahtar oluşturun. 8 basamaklı kodları ve SHA512'yi destekleyen uyumlu bir 2FA uygulaması kullanın.", - "enter_totp_code": "Lütfen TOTP Kodunu giriniz.", - "add_secret_code": "Veya bu gizli kodu bir kimlik doğrulama uygulamasına ekleyin", - "totp_secret_code": "TOTP Gizli Kodu", - "setup_2fa_text": "Cake 2FA, ikinci kimlik doğrulama faktörü olarak TOTP'yi kullanarak çalışır.\n\nCake 2FA'nın TOTP'si SHA-512 ve 8 haneli destek gerektirir; bu daha fazla güvenlik sağlar. Daha fazla bilgi ve desteklenen uygulamalar kılavuzda bulunabilir.", - "setup_totp_recommended": "TOTP'yi kur", - "disable_buy": "Satın alma işlemini devre dışı bırak", - "disable_sell": "Satış işlemini devre dışı bırak", + "authenticated": "Doğrulandı", + "authentication": "Doğrulama", "auto_generate_subaddresses": "Alt adresleri otomatik olarak oluştur", - "cake_2fa_preset": "Kek 2FA Ön Ayarı", - "narrow": "Dar", - "normal": "Normal", - "aggressive": "Aşırı duyarlı", - "require_for_assessing_wallet": "Cüzdana erişmek için gerekli", - "require_for_sends_to_non_contacts": "Kişi olmayan kişilere göndermeler için gerekli kıl", - "require_for_sends_to_contacts": "Kişilere göndermeler için gerekli kıl", - "require_for_sends_to_internal_wallets": "Dahili cüzdanlara yapılan gönderimler için gereklilik", - "require_for_exchanges_to_internal_wallets": "Dahili cüzdanlara değişim gerektir", - "require_for_adding_contacts": "Kişi eklemek için gerekli", - "require_for_creating_new_wallets": "Yeni cüzdan oluşturmak için gerekli", - "require_for_all_security_and_backup_settings": "Tüm güvenlik ve yedekleme ayarları için iste", + "automatic": "Otomatik", + "available_balance": "Kullanılabilir Bakiye", "available_balance_description": "Bu, cüzdanınızda harcayabileceğiniz miktar. Bu miktar, cüzdanınızdan çekilebilecek toplam bakiyeden daha düşük olabilir, çünkü bazı fonlar henüz kullanılamaz durumda olabilir.", - "syncing_wallet_alert_title": "Cüzdanınız senkronize ediliyor", - "syncing_wallet_alert_content": "Bakiyeniz ve işlem listeniz, en üstte \"SENKRONİZE EDİLDİ\" yazana kadar tamamlanmamış olabilir. Daha fazla bilgi edinmek için tıklayın/dokunun.", - "home_screen_settings": "Ana ekran ayarları", - "sort_by": "Göre sırala", - "search_add_token": "Belirteç Ara / Ekle", - "edit_token": "Belirteci düzenle", - "warning": "Uyarı", - "add_token_warning": "Dolandırıcıların talimatına göre jetonları düzenlemeyin veya eklemeyin.\nBelirteç adreslerini her zaman saygın kaynaklarla onaylayın!", - "add_token_disclaimer_check": "Belirteç sözleşmesi adresini ve bilgilerini saygın bir kaynak kullanarak onayladım. Kötü amaçlı veya yanlış bilgilerin eklenmesi para kaybına neden olabilir.", - "token_contract_address": "Token sözleşme adresi", - "token_name": "Belirteç adı, örneğin: Tether", - "token_symbol": "Jeton sembolü, örneğin: USDT", - "token_decimal": "Belirteç ondalık", - "field_required": "Bu alan gereklidir", - "pin_at_top": "${token} üstte sabitle", - "invalid_input": "Geçersiz Giriş", - "fiat_balance": "Fiat Bakiyesi", - "gross_balance": "Brüt Bakiye", - "alphabetical": "Alfabetik", - "generate_name": "İsim Oluştur", + "avg_savings": "Ortalama Tasarruf", + "awaitDAppProcessing": "Lütfen dApp'in işlemeyi bitirmesini bekleyin.", + "awaiting_payment_confirmation": "Ödemenin onaylanması bekleniyor", + "backup": "Yedek", + "backup_file": "Yedek dosyası", + "backup_password": "Yedek parolası", "balance_page": "Bakiye Sayfası", - "share": "Paylaşmak", - "slidable": "kaydırılabilir", - "monero_dark_theme": "Monero Koyu Tema", + "bill_amount": "Fatura Tutarı", + "billing_address_info": "Eğer fatura adresi istenirse, kargo adresinizi girin", + "biometric_auth_reason": "Kimlik doğrulaması için parmak izini okutun", "bitcoin_dark_theme": "Bitcoin Karanlık Teması", "bitcoin_light_theme": "Bitcoin Hafif Tema", - "high_contrast_theme": "Yüksek Kontrastlı Tema", - "matrix_green_dark_theme": "Matrix Yeşil Koyu Tema", - "monero_light_theme": "Monero Hafif Tema", - "manage_nodes": "Düğümleri yönet", - "etherscan_history": "Etherscan geçmişi", - "template_name": "şablon adı", + "bitcoin_payments_require_1_confirmation": "Bitcoin ödemeleri, 20 dakika veya daha uzun sürebilen 1 onay gerektirir. Sabrınız için teşekkürler! Ödeme onaylandığında e-posta ile bilgilendirileceksiniz.", + "Blocks_remaining": "${status} Blok Kaldı", + "bright_theme": "Parlak", + "buy": "Alış", + "buy_alert_content": "Şu anda yalnızca Bitcoin, Ethereum, Litecoin ve Monero satın alımını destekliyoruz. Lütfen Bitcoin, Ethereum, Litecoin veya Monero cüzdanınızı oluşturun veya cüzdanınıza geçin.", + "buy_bitcoin": "Bitcoin Satın Al", + "buy_provider_unavailable": "Sağlayıcı şu anda kullanılamıyor.", + "buy_with": "Şunun ile al: ", + "by_cake_pay": "Cake Pay tarafından", + "cake_2fa_preset": "Kek 2FA Ön Ayarı", + "cake_pay_account_note": "Kartları görmek ve satın almak için sadece bir e-posta adresiyle kaydolun. Hatta bazıları indirimli olarak bile mevcut!", + "cake_pay_learn_more": "Uygulamada anında hediye kartları satın alın ve harcayın!\nDaha fazla öğrenmek için soldan sağa kaydır.", + "cake_pay_subtitle": "İndirimli hediye kartları satın alın (yalnızca ABD)", + "cake_pay_title": "Cake Pay Hediye Kartları", + "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_wallet": "Cake Wallet", + "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.", + "camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.", + "cancel": "İptal", + "card_address": "Adres:", + "cardholder_agreement": "Kart Sahibi Sözleşmesi", + "cards": "Kartlar", + "chains": "Zincirler", + "change": "Değiştir", + "change_backup_password_alert": "Önceki yedekleme dosyaların yeni yedek parolası ile içe aktarılamayacaktır. Yeni yedekleme parolası yalnızca yeni yedekleme dosyaları için kullanılabilir olacak. Yedekleme parolasını değiştirmek istediğinden emin misin?", + "change_currency": "Para Birimini Değiştir", + "change_current_node": "Şimdiki düğümü ${node} düğümüne değiştirmek istediğinizden emin misin?", + "change_current_node_title": "Şimdiki düğümü değiştir", + "change_exchange_provider": "Takas sağlayıcısını değiştir", + "change_language": "Dili değiştir", + "change_language_to": "Dili şuna değiştir: ${language}?", + "change_password": "Parolayı değiştir", "change_rep": "Temsilciyi Değiştir", "change_rep_message": "Temsilcileri değiştirmek istediğinizden emin misiniz?", - "unsupported_asset": "Bu öğe için bu eylemi desteklemiyoruz. Lütfen desteklenen bir varlık türünde bir cüzdan oluşturun veya cüzdana geçiş yapın.", - "manage_pow_nodes": "PoW Düğümlerini Yönet", - "support_title_live_chat": "Canlı destek", - "support_description_live_chat": "Ücretsiz ve hızlı! Eğitimli destek temsilcileri yardımcı olmak için mevcuttur", - "support_title_guides": "Kek Cüzdan Kılavuzları", - "support_description_guides": "Ortak sorunlara belge ve destek", - "support_title_other_links": "Diğer destek bağlantıları", - "support_description_other_links": "Topluluklarımıza katılın veya ortaklarımıza diğer yöntemlerle bize ulaşın", + "change_rep_successful": "Temsilciyi başarıyla değiştirdi", + "change_wallet_alert_content": "Şimdiki cüzdanı ${wallet_name} cüzdanı ile değiştirmek istediğinden emin misin?", + "change_wallet_alert_title": "Şimdiki cüzdanı değiştir", + "choose_account": "Hesabı seç", + "choose_address": "\n\nLütfen adresi seçin:", "choose_derivation": "Cüzdan türevini seçin", - "new_first_wallet_text": "Kripto para biriminizi kolayca güvende tutun", - "select_destination": "Lütfen yedekleme dosyası için hedef seçin.", - "save_to_downloads": "İndirilenlere Kaydet", - "select_buy_provider_notice": "Yukarıda bir satın alma sağlayıcısı seçin. App ayarlarında varsayılan satın alma sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.", - "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.", + "choose_from_available_options": "Mevcut seçenekler arasından seçim yap:", + "choose_one": "Birini seç", + "choose_relay": "Lütfen kullanmak için bir röle seçin", + "choose_wallet_currency": "Lütfen cüzdanın para birimini seç:", + "clear": "Temizle", + "clearnet_link": "Net bağlantı", + "close": "Kapalı", + "coin_control": "Koin kontrolü (isteğe bağlı)", + "cold_or_recover_wallet": "Soğuk bir cüzdan ekleyin veya bir kağıt cüzdanı kurtarın", + "color_theme": "Renk teması", + "commit_transaction_amount_fee": "Transferi gerçekleştir\nMiktar: ${amount}\nKomisyon: ${fee}", + "confirm": "Onayla", + "confirm_delete_template": "Bu eylem, bu şablonu silecek. Devam etmek istiyor musun?", + "confirm_delete_wallet": "Bu eylem, bu cüzdanı silecek. Devam etmek istiyor musun?", + "confirm_sending": "Göndermeyi onayla", + "confirmations": "Onay", + "confirmed": "Onaylanmış Bakiye", + "confirmed_tx": "Onaylanmış", + "congratulations": "Tebrikler!", + "connect_an_existing_yat": "Mevcut bir Yat'ı bağla", + "connect_yats": "Yat'lara bağlan", + "connection_sync": "Bağlantı ve senkronizasyon", + "connectWalletPrompt": "İşlem yapmak için cüzdanınızı WalletConnect'e bağlayın", + "contact": "Rehber", + "contact_list_contacts": "Rehberim", + "contact_list_wallets": "Cüzdanlarım", + "contact_name": "Kişi ismi", + "contact_support": "Destek ile İletişime Geç", + "continue_text": "Devam et", + "contractName": "Sözleşme Adı", + "contractSymbol": "Sözleşme Sembolü", + "copied_key_to_clipboard": "${key} panoya kopyalandı", + "copied_to_clipboard": "Panoya Kopyalandı", + "copy": "Kopyala", + "copy_address": "Adresi kopyala", + "copy_id": "ID'yi kopyala", + "copyWalletConnectLink": "WalletConnect bağlantısını dApp'ten kopyalayıp buraya yapıştırın", + "create_account": "Hesap oluştur", + "create_backup": "Yedek oluştur", + "create_donation_link": "Bağış bağlantısı oluştur", + "create_invoice": "Fatura oluşturmak", + "create_new": "Yeni Cüzdan Oluştur", + "create_new_account": "Yeni hesap oluştur", + "creating_new_wallet": "Cüzdan oluşturuluyor", + "creating_new_wallet_error": "Hata: ${description}", + "creation_date": "Oluşturulma tarihi", + "custom": "özel", + "custom_drag": "Özel (Bekle ve Sürükle)", + "custom_redeem_amount": "Özel Harcama Tutarı", + "dark_theme": "Karanlık", + "debit_card": "Ön ödemeli Kart", + "debit_card_terms": "Ödeme kartı numaranızın (ve kart numaranıza karşılık gelen kimlik bilgilerinin) bu dijital cüzdanda saklanması ve kullanılması, zaman zaman yürürlükte olan ödeme kartı veren kuruluşla yapılan ilgili kart sahibi sözleşmesinin Hüküm ve Koşullarına tabidir.", + "decimal_places_error": "Çok fazla ondalık basamak", "default_buy_provider": "Varsayılan Satın Alma Sağlayıcısı", - "ask_each_time": "Her seferinde sor", - "buy_provider_unavailable": "Sağlayıcı şu anda kullanılamıyor.", - "signTransaction": "İşlem İmzala", + "default_sell_provider": "Varsayılan Satış Sağlayıcısı", + "delete": "Sil", + "delete_account": "Hesabı sil", + "delete_wallet": "Cüzdanı sil", + "delete_wallet_confirm_message": "${wallet_name} isimli cüzdanını silmek istediğinden emin misin?", + "deleteConnectionConfirmationPrompt": "Bağlantıyı silmek istediğinizden emin misiniz?", + "descending": "Azalan", + "description": "Tanım", + "destination_tag": "Hedef Etiketi:", + "dfx_option_description": "EUR ve CHF ile kripto satın alın. Ek KYC olmadan 990 €'ya kadar. Avrupa'daki perakende ve kurumsal müşteriler için", + "didnt_get_code": "Kod gelmedi mi?", + "digit_pin": " haneli PIN", + "digital_and_physical_card": " Dijital para birimleri ile para yükleyebileceğiniz ve ek bilgiye gerek olmayan", + "disable": "Devre dışı bırakmak", + "disable_buy": "Satın alma işlemini devre dışı bırak", + "disable_cake_2fa": "Cake 2FA'yı Devre Dışı Bırak", + "disable_exchange": "Borsayı devre dışı bırak", + "disable_fiat": "İtibari paraları devre dışı bırak", + "disable_sell": "Satış işlemini devre dışı bırak", + "disabled": "Devre dışı", + "discount": "%${value} tasarruf et", + "display_settings": "Görüntü ayarları", + "displayable": "Gösterilebilir", + "do_not_have_enough_gas_asset": "Mevcut blockchain ağ koşullarıyla işlem yapmak için yeterli ${currency} paranız yok. Farklı bir varlık gönderiyor olsanız bile blockchain ağ ücretlerini ödemek için daha fazla ${currency} miktarına ihtiyacınız var.", + "do_not_send": "Gönderme", + "do_not_share_warning_text": "Bunları destek de dahil olmak üzere başka kimseyle paylaşma.\n\nParan çalınabilir ve çalınacaktır!", + "do_not_show_me": "Bana bunu bir daha gösterme", + "domain_looks_up": "Etki alanı aramaları", + "donation_link_details": "Bağış bağlantısı ayrıntıları", + "e_sign_consent": "E-İmza Onayı", + "edit": "Düzenle", + "edit_backup_password": "Yedek parolasını değiştir", + "edit_node": "Düğümü Düzenle", + "edit_token": "Belirteci düzenle", + "electrum_address_disclaimer": "Adresini her kullandığında yeni adres oluşturuyoruz, ancak önceki adresler de çalışmaya devam eder", + "email_address": "E-posta Adresi", + "enabled": "Etkin", + "enter_amount": "Miktar Girin", + "enter_backup_password": "Yedekleme parolasını buraya gir", + "enter_code": "Kodu girin", + "enter_seed_phrase": "Tohum ifadenizi girin", + "enter_totp_code": "Lütfen TOTP Kodunu giriniz.", + "enter_your_note": "Notunu gir…", + "enter_your_pin": "PIN'ini gir", + "enter_your_pin_again": "PIN kodunu tekrar girin", + "enterTokenID": "Belirteç kimliğini girin", + "enterWalletConnectURI": "WalletConnect URI'sini girin", + "error": "Hata", + "error_dialog_content": "Hay aksi, bir hatamız var.\n\nUygulamayı daha iyi hale getirmek için lütfen kilitlenme raporunu destek ekibimize gönderin.", + "error_text_account_name": "Hesap ismi yalnızca harf, rakam \nve 1 ile 15 uzunluğunda karakter içermelidir.", + "error_text_address": "Cüzdan adresi kripto para biriminin\ntürüne karşılık gelmelidir", + "error_text_amount": "Miktar sadece sayı içerebilir", + "error_text_contact_name": "Kişi ismi ` , ' \" sembollerini içeremez \nve 1 ile 32 uzunluğunda karakter içermelidir", + "error_text_crypto_currency": "Kesir basamaklarının sayısı\n12'ye eşit veya daha az olmalıdır", + "error_text_fiat": "Tutarın değeri, mevcut bakiyeyi aşamaz.\nKesir basamaklarının sayısı 2'ye eşit veya daha az olmalıdır", + "error_text_input_above_maximum_limit": "Miktar maksimumdan daha fazla", + "error_text_input_below_minimum_limit": "Miktar minimumdan daha azdır", + "error_text_keys": "Cüzdan anahtarları onaltılık (hex) olarak yalnızca 64 karakter içerebilir", + "error_text_limits_loading_failed": "${provider} için işlem oluşturulmadı. Limitler yüklenirken hata oluştu.", + "error_text_maximum_limit": "${provider} için işlem oluşturulmadı. Miktar maksimumdan daha fazla: ${max} ${currency}", + "error_text_minimal_limit": "${provider} için işlem oluşturulmadı. Miktar minimumdan daha azdır: ${min} ${currency}", + "error_text_node_address": "Lütfen iPv4 adresi girin", + "error_text_node_port": "Düğüm port'u yalnızca 0 ve 65535 arasında rakam içerebilir", + "error_text_node_proxy_address": "Lütfen : girin, örneğin 127.0.0.1:9050", + "error_text_payment_id": "Ödeme ID'si yalnızca onaltılık (hex) olarak 16 veya 64 karakter içerebilir", + "error_text_subaddress_name": "Alt adres ismi ` , ' \" sembolleri içeremez\nve 1 ile 20 karakter arasında olmalıdır", + "error_text_template": "Şablon adı ve adresi ` , ' \" sembolleri içeremez\nve 1 ila 106 karakter uzunluğunda olmalı", + "error_text_wallet_name": "Cüzdan ismi yalnızca harf, rakam \nve 1 ile 33 uzunluğunda karakter içermelidir.", + "error_text_xmr": "XMR miktarı kullanılabilir bakiyeyi aşamaz.\nKesir basamaklarının sayısı 12'ye eşit veya daha az olmalıdır", "errorGettingCredentials": "Başarısız: Kimlik bilgileri alınırken hata oluştu", "errorSigningTransaction": "İşlem imzalanırken bir hata oluştu", - "pairingInvalidEvent": "Geçersiz Etkinliği Eşleştirme", - "chains": "Zincirler", - "methods": "Yöntemler", - "events": "Olaylar", - "reject": "Reddetmek", - "approve": "Onaylamak", - "expiresOn": "Tarihinde sona eriyor", - "walletConnect": "WalletConnect", - "nullURIError": "URI boş", - "connectWalletPrompt": "İşlem yapmak için cüzdanınızı WalletConnect'e bağlayın", - "newConnection": "Yeni bağlantı", - "activeConnectionsPrompt": "Aktif bağlantılar burada görünecek", - "deleteConnectionConfirmationPrompt": "Bağlantıyı silmek istediğinizden emin misiniz?", + "estimated": "Tahmini", + "etherscan_history": "Etherscan geçmişi", "event": "Etkinlik", - "successful": "Başarılı", - "wouoldLikeToConnect": "bağlanmak istiyorum", - "message": "İleti", - "do_not_have_enough_gas_asset": "Mevcut blockchain ağ koşullarıyla işlem yapmak için yeterli ${currency} paranız yok. Farklı bir varlık gönderiyor olsanız bile blockchain ağ ücretlerini ödemek için daha fazla ${currency} miktarına ihtiyacınız var.", - "totp_auth_url": "TOTP YETKİ URL'si", - "awaitDAppProcessing": "Lütfen dApp'in işlemeyi bitirmesini bekleyin.", - "copyWalletConnectLink": "WalletConnect bağlantısını dApp'ten kopyalayıp buraya yapıştırın", - "enterWalletConnectURI": "WalletConnect URI'sini girin", - "seed_key": "Tohum", - "enter_seed_phrase": "Tohum ifadenizi girin", - "change_rep_successful": "Temsilciyi başarıyla değiştirdi", - "add_contact": "Kişi ekle", + "events": "Olaylar", + "exchange": "Takas", + "exchange_incorrect_current_wallet_for_xmr": "Cake Wallet'daki Monero bakiyenizi kullanarak takas yapmak istiyorsan, lütfen önce Monero cüzdanına geç.", + "exchange_new_template": "Yeni şablon", "exchange_provider_unsupported": "${providerName} artık desteklenmiyor!", - "domain_looks_up": "Etki alanı aramaları", - "require_for_exchanges_to_external_wallets": "Harici cüzdanlara geçiş yapılmasını zorunlu kılın", - "camera_permission_is_required": "Kamera izni gereklidir.\nLütfen uygulama ayarlarından etkinleştirin.", - "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin", - "order_by": "Tarafından sipariş", - "creation_date": "Oluşturulma tarihi", + "exchange_result_confirm": "Onaylaya basarak, ${fetchingLabel} ${from} miktarında ${walletName} olarak adlandırılan cüzdanından aşağıda gösterilen adrese gönderilecek. Veya harici cüzdanından aşağıdaki adrese / QR koduna gönderebilirsin.\n\nLütfen devam etmek için onayla'ya bas veya tutarı değiştirmek için geri dön.", + "exchange_result_description": "Lütfen en az ${fetchingLabel} miktarındaki ${from}'yi sonraki sayfada gönsterilen adrese gönder. Eğer ${fetchingLabel} ${from}'den az gönderirsen takas gerçekleşmeyebilir ve size geri iade edilebilir.", + "exchange_result_write_down_ID": "*Lütfen yukarıda gösterilen ID'ni kopyala veya bir yere yaz.", + "exchange_result_write_down_trade_id": "Devam etmek için lütfen ID'yi kopyala veya bir yere yaz.", + "exchange_sync_alert_content": "Lütfen cüzdanın senkronize olana kadar bekle", + "expired": "Süresi doldu", + "expires": "Son kullanma tarihi", + "expiresOn": "Tarihinde sona eriyor", + "export_backup": "Yedeği dışa aktar", + "extra_id": "Ekstra ID:", + "extracted_address_content": "Parayı buraya gönderceksin:\n${recipient_name}", + "failed_authentication": "Doğrulama başarısız oldu. ${state_error}", + "faq": "SSS", + "fetching": "Getiriliyor", + "fiat_api": "İtibari Para API", + "fiat_balance": "Fiat Bakiyesi", + "field_required": "Bu alan gereklidir", + "fill_code": "Lütfen e-postanıza gelen doğrulama kodunu girin", + "filter_by": "Şuna göre filtrele", + "first_wallet_text": "Monero, Bitcoin, Ethereum, Litecoin ve Haven için harika cüzdan", + "fixed_pair_not_supported": "Bu sabit paritesi seçilen borsalarda desteklenmemekte", + "fixed_rate": "Sabit oran", + "fixed_rate_alert": "Sabit oran modunu işaretlersen alım tutarını girebilirsin. Sabit oran moduna geçmek ister misin?", + "forgot_password": "Parolamı unuttum", + "freeze": "Dondur", + "frequently_asked_questions": "Sıkça sorulan sorular", + "frozen": "Dondurulmuş", + "full_balance": "Tüm bakiye", + "generate_name": "İsim Oluştur", + "generating_gift_card": "Hediye Kartı Oluşturuluyor", + "get_a": "Bir ", + "get_card_note": " dijital ve fiziksel ön ödemeli banka kartı edinin!", + "get_your_yat": "Yat'ını al", + "gift_card_amount": "Hediye Kartı Tutarı", + "gift_card_balance_note": "Bakiyesi kalan olan hediye kartları burada görünecek", + "gift_card_is_generated": "Hediye Kartı oluşturuldu", + "gift_card_number": "Hediye kartı numarası", + "gift_card_redeemed_note": "Harcadığın hediye kartları burada görünecek", + "gift_cards": "Hediye kartları", + "gift_cards_unavailable": "Hediye kartları şu anda yalnızca Monero, Bitcoin ve Litecoin ile satın alınabilir", + "got_it": "Tamamdır", + "gross_balance": "Brüt Bakiye", "group_by_type": "Türüne göre grup", - "importNFTs": "NFT'leri içe aktar", - "noNFTYet": "Henüz NFT yok", - "address": "Adres", - "enterTokenID": "Belirteç kimliğini girin", - "tokenID": "İD", - "name": "İsim", - "symbol": "Sembol", - "seed_phrase_length": "Çekirdek cümle uzunluğu", - "unavailable_balance": "Kullanılamayan bakiye", - "unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.", - "unspent_change": "Değiştirmek", - "tor_connection": "Tor bağlantısı", - "setup_warning_2fa_text": "Cüzdanınızı anımsatıcı tohumdan geri yüklemeniz gerekecek.\n\n2FA veya anımsatıcı tohumlarınıza erişiminizi kaybederseniz pasta desteği size yardımcı olamayacaktır.\nCake 2FA, cüzdandaki belirli eylemler için ikinci bir kimlik doğrulamadır. Cake 2FA'yı kullanmadan önce kılavuzu okumanızı öneririz.Soğuk hava deposu kadar güvenli DEĞİLDİR.\n\n2FA uygulamanıza veya TOTP anahtarlarınıza erişiminizi kaybederseniz bu cüzdana erişimi KAYBEDECEKSİNİZ. ", - "scan_qr_on_device": "Bu QR kodunu başka bir cihazda tarayın", + "haven_app": "Cake Wallet tarafından Haven", + "haven_app_wallet_text": "Haven için harika cüzdan ", + "help": "yardım", + "hidden_balance": "Gizli Bakiye", + "hide_details": "Detayları Gizle", + "high_contrast_theme": "Yüksek Kontrastlı Tema", + "home_screen_settings": "Ana ekran ayarları", "how_to_use": "Nasıl kullanılır", + "how_to_use_card": "Bu kart nasıl kullanılır", + "id": "ID: ", + "ignor": "Yoksay", + "import": "İçe aktarmak", + "importNFTs": "NFT'leri içe aktar", + "in_store": "Mağazada", + "incoming": "Gelen", + "incorrect_seed": "Girilen metin geçerli değil.", + "introducing_cake_pay": "Cake Pay ile tanışın!", + "invalid_input": "Geçersiz Giriş", + "invoice_details": "fatura detayları", + "is_percentage": "is", + "last_30_days": "Son 30 gün", + "learn_more": "Daha fazla öğren", + "light_theme": "Aydınlık", + "loading_your_wallet": "Cüzdanın yükleniyor", + "login": "Login", + "logout": "Çıkış yap", + "low_fee": "Düşük komisyon", + "low_fee_alert": "Şu anda düşük bir ağ ücreti önceliği kullanıyorsunuz. Bu durum uzun beklemeler, farklı oranlar veya iptal edilen işlemlere neden olabilir. Daha iyi bir deneyim için daha yüksek bir ücret belirlemenizi öneririz.", + "manage_nodes": "Düğümleri yönet", + "manage_pow_nodes": "PoW Düğümlerini Yönet", + "manage_yats": "Yats'ları yönet", + "mark_as_redeemed": "Harcanmış olarak işaretle", + "market_place": "Pazar Alanı", + "matrix_green_dark_theme": "Matrix Yeşil Koyu Tema", + "max_amount": "Maks: ${value}", + "max_value": "En fazla: ${value} ${currency}", + "memo": "Memo:", + "message": "İleti", + "methods": "Yöntemler", + "min_amount": "Min: ${value}", + "min_value": "En az: ${value} ${currency}", + "minutes_to_pin_code": "${minute} dakika", + "mm": "AA", + "modify_2fa": "Cake 2FA'yı Değiştirin", + "monero_com": "Cake Wallet tarafından Monero.com", + "monero_com_wallet_text": "Monero için harika cüzdan", + "monero_dark_theme": "Monero Koyu Tema", + "monero_light_theme": "Monero Hafif Tema", + "moonpay_alert_text": "Tutar ${minAmount} ${fiatCurrency} miktarına eşit veya daha fazla olmalıdır", + "more_options": "Daha Fazla Seçenek", + "name": "İsim", + "narrow": "Dar", + "new_first_wallet_text": "Kripto para biriminizi kolayca güvende tutun", + "new_node_testing": "Yeni düğüm test ediliyor", + "new_subaddress_create": "Oluştur", + "new_subaddress_label_name": "Etiket ismi", + "new_subaddress_title": "Yeni adres", + "new_template": "Yeni Şablon", + "new_wallet": "Yeni Cüzdan", + "newConnection": "Yeni bağlantı", + "no_id_needed": "Kimlik gerekmez!", + "no_id_required": "Kimlik gerekmez. Para yükleyin ve istediğiniz yerde harcayın", + "no_relay_on_domain": "Kullanıcının alanı için bir geçiş yok veya geçiş kullanılamıyor. Lütfen kullanmak için bir röle seçin.", + "no_relays": "Röle yok", + "no_relays_message": "Bu kullanıcı için bir Nostr NIP-05 kaydı bulduk ancak bu kayıt herhangi bir aktarma içermiyor. Lütfen alıcıya Nostr kayıtlarına aktarma eklemesi talimatını verin.", + "node_address": "Düğüm adresi", + "node_connection_failed": "Bağlantı başarısız oldu", + "node_connection_successful": "Bağlantı başarılı oldu", + "node_new": "Yeni düğüm", + "node_port": "Düğüm port'u", + "node_reset_settings_title": "Ayarları sıfırla", + "node_test": "Test Et", + "nodes": "Düğümler", + "nodes_list_reset_to_default_message": "Ayarları varsayılana sıfırlamak istediğinizden emin misin?", + "none_of_selected_providers_can_exchange": "Seçilen sağlayıcılardan hiçbiri bu takası yapamaz", + "noNFTYet": "Henüz NFT yok", + "normal": "Normal", + "note_optional": "Not (isteğe bağlı)", + "note_tap_to_change": "Not (değiştirmek için dokunun)", + "nullURIError": "URI boş", + "offer_expires_in": "Teklifin bitmesine kalan: ", + "offline": "Çevrimdışı", + "ok": "Tamam", + "onion_link": "soğan bağlantısı", + "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ç", + "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ı", + "optionally_order_card": "İsteğe bağlı olarak fiziksel bir kart sipariş edin.", + "orbot_running_alert": "Lütfen bu düğüme bağlanmadan önce Orbot'un çalıştığından emin olun.", + "order_by": "Tarafından sipariş", + "order_id": "Sipariş ID'si", + "order_physical_card": "Fiziksel Kart Siparişi", + "other_settings": "Diğer ayarlar", + "outdated_electrum_wallet_description": "Cake'te oluşturulan yeni Bitcoin cüzdanları artık 24 kelimelik bir tohuma sahip. Yeni bir Bitcoin cüzdanı oluşturmanız ve tüm paranızı 24 kelimelik yeni cüzdana aktarmanız ve 12 kelimelik tohuma sahip cüzdanları kullanmayı bırakmanız zorunludur. Lütfen paranızı güvence altına almak için bunu hemen yapın.", + "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", + "overwrite_amount": "Miktarın üzerine yaz", + "pairingInvalidEvent": "Geçersiz Etkinliği Eşleştirme", + "password": "Parola", + "paste": "Yapıştır", + "pause_wallet_creation": "Haven Cüzdanı oluşturma yeteneği şu anda duraklatıldı.", + "payment_id": "Ödeme ID'si: ", + "payment_was_received": "Ödemeniz alındı.", + "pending": " (bekleyen)", + "percentageOf": "of ${amount}", + "pin_at_top": "${token} üstte sabitle", + "pin_is_incorrect": "PIN kodu hatalı", + "pin_number": "PIN kodu", + "placeholder_contacts": "Kişilerin burada görüntülenecek", + "placeholder_transactions": "İşlemlerin burada görüntülenecek", + "please_fill_totp": "Lütfen diğer cihazınızda bulunan 8 haneli kodu girin", + "please_make_selection": "Cüzdan oluşturmak veya geri döndürmek için aşağıdan seçim yap.", + "please_reference_document": "Daha fazla bilgi için lütfen aşağıdaki belgelere bakınız.", + "please_select": "Lütfen seçim yap:", + "please_select_backup_file": "Lütfen yedekleme dosyasını seç ve yedekleme parolasını gir.", + "please_try_to_connect_to_another_node": "Lütfen farklı düğüme bağlanmayı dene", + "please_wait": "Lütfen bekleyin", + "polygonscan_history": "PolygonScan geçmişi", + "powered_by": "${title} tarafından desteklenmektedir", + "pre_seed_button_text": "Anladım. Bana tohumumu göster.", + "pre_seed_description": "Bir sonraki sayfada ${words} kelime göreceksin. Bu senin benzersiz ve özel tohumundur, kaybetmen veya silinmesi durumunda cüzdanını kurtarmanın TEK YOLUDUR. Bunu yazmak ve Cake Wallet uygulaması dışında güvenli bir yerde saklamak tamamen SENİN sorumluluğunda.", + "pre_seed_title": "UYARI", + "prevent_screenshots": "Ekran görüntülerini ve ekran kaydını önleyin", + "privacy": "Gizlilik", + "privacy_policy": "Gizlilik Politikası", + "privacy_settings": "Gizlilik ayarları", + "private_key": "Özel anahtar", + "proceed_after_one_minute": "Ekran 1 dakika sonra ilerlemezse, e-postanızı kontrol edin.", + "profile": "Profil", + "provider_error": "${provider} hatası", + "public_key": "Genel Anahtar", + "purchase_gift_card": "Hediye Kartı Satın Al", + "qr_fullscreen": "QR kodunu tam ekranda açmak için dokun", + "qr_payment_amount": "Bu QR kodu ödeme tutarını içeriyor. Geçerli miktarın üzerine yazmak istediğine emin misin?", + "question_to_disable_2fa": "Cake 2FA'yı devre dışı bırakmak istediğinizden emin misiniz? M-cüzdana ve belirli işlevlere erişmek için artık 2FA koduna gerek kalmayacak.", + "receivable_balance": "Alacak bakiyesi", + "receive": "Para Al", + "receive_amount": "Miktar", + "received": "Alındı", + "recipient_address": "Alıcı adresi", + "reconnect": "Yeniden Bağlan", + "reconnect_alert_text": "Yeniden bağlanmak istediğinden emin misin?", + "reconnection": "Yeniden bağlantı", + "redeemed": "Kullanılmış", + "refund_address": "İade adresi", + "reject": "Reddetmek", + "remaining": "kalan", + "remove": "Kaldır", + "remove_node": "Düğümü kaldır", + "remove_node_message": "Seçili düğümü kaldırmak istediğinden emin misin?", + "rename": "Yeniden adlandır", + "require_for_adding_contacts": "Kişi eklemek için gerekli", + "require_for_all_security_and_backup_settings": "Tüm güvenlik ve yedekleme ayarları için iste", + "require_for_assessing_wallet": "Cüzdana erişmek için gerekli", + "require_for_creating_new_wallets": "Yeni cüzdan oluşturmak için gerekli", + "require_for_exchanges_to_external_wallets": "Harici cüzdanlara geçiş yapılmasını zorunlu kılın", + "require_for_exchanges_to_internal_wallets": "Dahili cüzdanlara değişim gerektir", + "require_for_sends_to_contacts": "Kişilere göndermeler için gerekli kıl", + "require_for_sends_to_internal_wallets": "Dahili cüzdanlara yapılan gönderimler için gereklilik", + "require_for_sends_to_non_contacts": "Kişi olmayan kişilere göndermeler için gerekli kıl", + "require_pin_after": "Şu kadar süre sonra PIN iste", + "rescan": "Yeniden Tara", + "resend_code": "Lütfen tekrar gönder", + "reset": "Sıfırla", + "reset_password": "Parolamı sıfırla", + "restore_active_seed": "Tohumu aktifleştir", + "restore_address": "Adres", + "restore_bitcoin_description_from_keys": "Cüzdanını, oluşturulan WIF dizesinden veya özel anahtarlarından geri yükle", + "restore_bitcoin_description_from_seed": "Cüzdanınızı 24 kelimelik kombinasyon kodundan geri yükle", + "restore_bitcoin_title_from_keys": "WIF'den geri yükle", + "restore_description_from_backup": "Yedek dosyandan tüm Cake Wallet uygulamasını geri döndürebilirsin", + "restore_description_from_keys": "Cüzdanınızı özel anahtarlarınızdan kaydedilen oluşturulmuş tuş vuruşlarından geri yükleyin", + "restore_description_from_seed": "Cüzdanınızı 25 veya 13 kelimelik kombinasyon kodundan geri döndürün", + "restore_description_from_seed_keys": "Güvenli bir yere kaydettiğin tohumdan/anahtarlardan cüzdanını geri döndür", + "restore_from_date_or_blockheight": "Lütfen bu cüzdanı oluşturmadan birkaç gün önceki bir tarihi girin. Veya blok yüksekliğini biliyorsan, lütfen bunu gir", + "restore_from_seed_placeholder": "Lütfen tohumunu buraya gir veya yapıştır", + "restore_new_seed": "Yeni tohum", + "restore_next": "İleri", + "restore_recover": "Geri döndür", + "restore_restore_wallet": "Cüzdanı Geri Döndür", + "restore_seed_keys_restore": "Tohumu/Anahtarları Geri Döndür", + "restore_spend_key_private": "Harcama anahtarı (Özel)", + "restore_title_from_backup": "Yedekten geri döndür", + "restore_title_from_keys": "Anahtarlardan geri döndür", + "restore_title_from_seed": "Tohumdan geri döndür", + "restore_title_from_seed_keys": "Tohumdan/anahtarlardan geri döndür", + "restore_view_key_private": "İzleme anahtarı (Özel)", + "restore_wallet": "Cüzdanı Geri Döndür", + "restore_wallet_name": "Cüzdan ismi", + "restore_wallet_restore_description": "Cüzdan geri döndürme açıklaması", + "router_no_route": "${name} için rota tanımlanmadı", + "save": "Kaydet", + "save_backup_password": "Lütfen yedekleme parolanı kaydettiğinden emin ol. Bu parola olmadan yedekleme dosyasını içe aktaramazsın.", + "save_backup_password_alert": "Yedek parolasını kaydet", + "save_to_downloads": "İndirilenlere Kaydet", + "saved_the_trade_id": "Takas ID'imi kaydettim", + "scan_qr_code": "QR kodunu tarayın", + "scan_qr_code_to_get_address": "Adresi getirmek için QR kodunu tara", + "scan_qr_on_device": "Bu QR kodunu başka bir cihazda tarayın", + "search": "Arat", + "search_add_token": "Belirteç Ara / Ekle", + "search_category": "Kategori ara", + "search_currency": "Para birimi ara", + "search_language": "Dil arat", + "second_intro_content": "Yat'ınız, tüm para birimleriniz için uzun onaltılık adreslerinizin yerini alan benzersiz emoji adresidir.", + "second_intro_title": "Hepsini yönetebilen tek bir emoji adresi", + "security_and_backup": "Güvenlik ve yedekleme", + "seed_alert_back": "Geriye dön", + "seed_alert_content": "Cüzdanını kurtarmanın tek yolu tohumdur. Tohumunu yazdın mı?", + "seed_alert_title": "Dikkat", + "seed_alert_yes": "Evet yazdım", + "seed_choose": "Tohum dilini seçin", "seed_hex_form": "Cüzdan tohumu (onaltılık form)", + "seed_key": "Tohum", + "seed_language": "Tohum dili", + "seed_language_chinese": "Çince", + "seed_language_chinese_traditional": "Çin geleneği)", + "seed_language_czech": "Çek", + "seed_language_dutch": "Flemenkçe", + "seed_language_english": "İngilizce", + "seed_language_french": "Fransızca", + "seed_language_german": "Almanca", + "seed_language_italian": "İtalyanca", + "seed_language_japanese": "Japonca", + "seed_language_korean": "Koreli", + "seed_language_next": "İleri", + "seed_language_portuguese": "Portekizce", + "seed_language_russian": "Rusça", + "seed_language_spanish": "İspanyolca", + "seed_phrase_length": "Çekirdek cümle uzunluğu", + "seed_reminder": "Telefonunu kaybetmen veya silinmesi ihtimaline karşı lütfen bunları not et", + "seed_share": "Tohumu paylaş", + "seed_title": "Tohum", "seedtype": "Tohum", "seedtype_legacy": "Miras (25 kelime)", "seedtype_polyseed": "Polyseed (16 kelime)", - "seed_language_czech": "Çek", - "seed_language_korean": "Koreli", - "seed_language_chinese_traditional": "Çin geleneği)", - "ascending": "Yükselen", - "descending": "Azalan", - "dfx_option_description": "EUR ve CHF ile kripto satın alın. Ek KYC olmadan 990 €'ya kadar. Avrupa'daki perakende ve kurumsal müşteriler için", - "polygonscan_history": "PolygonScan geçmişi", - "wallet_seed_legacy": "Eski cüzdan tohumu", - "default_sell_provider": "Varsayılan Satış Sağlayıcısı", + "select_backup_file": "Yedek dosyası seç", + "select_buy_provider_notice": "Yukarıda bir satın alma sağlayıcısı seçin. App ayarlarında varsayılan satın alma sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.", + "select_destination": "Lütfen yedekleme dosyası için hedef seçin.", "select_sell_provider_notice": "Yukarıdan bir satış sağlayıcısı seçin. Uygulama ayarlarında varsayılan satış sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.", - "custom_drag": "Özel (Bekle ve Sürükle)", + "sell": "Satış", + "sell_alert_content": "Şu anda yalnızca Bitcoin, Ethereum ve Litecoin satışını destekliyoruz. Lütfen Bitcoin, Ethereum veya Litecoin cüzdanınızı oluşturun veya cüzdanınıza geçin.", + "sell_monero_com_alert_content": "Monero satışı henüz desteklenmiyor", + "send": "Para Gönder", + "send_address": "${cryptoCurrency} adresi", + "send_amount": "Miktar:", + "send_creating_transaction": "İşlem oluşturuluyor", + "send_error_currency": "Para birimi sadece sayı içerebilir", + "send_error_minimum_value": "Minimum tutar değeri 0.01'dir", + "send_estimated_fee": "Tahmini komisyon:", + "send_fee": "Komisyon:", + "send_name": "İsim", + "send_new": "Yeni", + "send_payment_id": "Ödeme ID'si (isteğe bağlı)", + "send_priority": "Şu anda ücret ${transactionPriority} önceliğine ayarlanmıştır.\nİşlem önceliği ayarlardan değiştirilebilir", + "send_sending": "Gönderiliyor...", + "send_success": "${crypto} başarıyla gönderildi", + "send_templates": "Şablonlar", + "send_title": "Gönder", + "send_to_this_address": "Bu adrese ${currency} ${tag}gönder", + "send_xmr": "XMR gönder", + "send_your_wallet": "Cüzdanın", + "sending": "Gönderiliyor", + "sent": "Gönderildi", + "settings": "ayarlar", + "settings_all": "HEPSİ", + "settings_allow_biometrical_authentication": "Biyometrik doğrulamaya izin ver", + "settings_can_be_changed_later": "Bu ayarlar daha sonra uygulama ayarlarından da değiştirilebilir", + "settings_change_language": "Dili değiştir", + "settings_change_pin": "PIN'i değiştir", + "settings_currency": "Para birimi", + "settings_current_node": "Şimdiki düğüm", + "settings_dark_mode": "Karanlık mod", + "settings_display_balance": "Bakiyeyi göster", + "settings_display_on_dashboard_list": "Gösterge tablosu listesinde göster", + "settings_fee_priority": "İşlem Komsiyonu önceliği", + "settings_nodes": "Düğümler", + "settings_none": "Hiçbiri", + "settings_only_trades": "Sadece takaslar", + "settings_only_transactions": "Sadece transferler", + "settings_personal": "Kişisel", + "settings_save_recipient_address": "Gönderilen adresi kaydet", + "settings_support": "Destek", + "settings_terms_and_conditions": "Şartlar ve Koşullar", + "settings_title": "Ayarlar", + "settings_trades": "Takaslar", + "settings_transactions": "İşlemler", + "settings_wallets": "Cüzdanlar", + "setup_2fa": "Kurulum Pastası 2FA", + "setup_2fa_text": "Cake 2FA, ikinci kimlik doğrulama faktörü olarak TOTP'yi kullanarak çalışır.\n\nCake 2FA'nın TOTP'si SHA-512 ve 8 haneli destek gerektirir; bu daha fazla güvenlik sağlar. Daha fazla bilgi ve desteklenen uygulamalar kılavuzda bulunabilir.", + "setup_pin": "PIN kodu kurulumu", + "setup_successful": "PIN kodun başarıyla ayarlandı!", + "setup_totp_recommended": "TOTP'yi kur", + "setup_warning_2fa_text": "Cüzdanınızı anımsatıcı tohumdan geri yüklemeniz gerekecek.\n\n2FA veya anımsatıcı tohumlarınıza erişiminizi kaybederseniz pasta desteği size yardımcı olamayacaktır.\nCake 2FA, cüzdandaki belirli eylemler için ikinci bir kimlik doğrulamadır. Cake 2FA'yı kullanmadan önce kılavuzu okumanızı öneririz.Soğuk hava deposu kadar güvenli DEĞİLDİR.\n\n2FA uygulamanıza veya TOTP anahtarlarınıza erişiminizi kaybederseniz bu cüzdana erişimi KAYBEDECEKSİNİZ. ", + "setup_your_debit_card": "Banka kartını ayarla", + "share": "Paylaşmak", + "share_address": "Adresi paylaş", + "show_details": "Detayları Göster", + "show_keys": "Tohumları/anahtarları göster", + "show_market_place": "Pazar Yerini Göster", + "show_seed": "Tohumları göster", + "sign_up": "Kaydol", + "signTransaction": "İşlem İmzala", + "signup_for_card_accept_terms": "Kart için kaydol ve koşulları kabul et.", + "slidable": "kaydırılabilir", + "sort_by": "Göre sırala", + "spend_key_private": "Harcama anahtarı (özel)", + "spend_key_public": "Harcama anahtarı (genel)", + "status": "Durum: ", + "subaddress_title": "Alt adres listesi", + "subaddresses": "Alt adresler", + "submit_request": "talep gönder", + "successful": "Başarılı", + "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_live_chat": "Canlı destek", + "support_title_other_links": "Diğer destek bağlantıları", + "sweeping_wallet": "Süpürme cüzdanı", + "sweeping_wallet_alert": "Bu uzun sürmemeli. BU EKRANDAN BIRAKMAYIN YOKSA SÜPÜRÜLEN FONLAR KAYBOLABİLİR", + "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin", "switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)", - "receivable_balance": "Alacak bakiyesi", - "confirmed_tx": "Onaylanmış", + "symbol": "Sembol", + "sync_status_attempting_sync": "SENKRONİZE EDİLMEYE ÇALIŞILIYOR", + "sync_status_connected": "BAĞLANILDI", + "sync_status_connecting": "BAĞLANILIYOR", + "sync_status_failed_connect": "BAĞLANTI KESİLDİ", + "sync_status_not_connected": "BAĞLI DEĞİL", + "sync_status_starting_sync": "SENKRONİZE BAŞLATILIYOR", + "sync_status_syncronized": "SENKRONİZE EDİLDİ", + "sync_status_syncronizing": "SENKRONİZE EDİLİYOR", + "syncing_wallet_alert_content": "Bakiyeniz ve işlem listeniz, en üstte \"SENKRONİZE EDİLDİ\" yazana kadar tamamlanmamış olabilir. Daha fazla bilgi edinmek için tıklayın/dokunun.", + "syncing_wallet_alert_title": "Cüzdanınız senkronize ediliyor", + "template": "Şablon", + "template_name": "şablon adı", + "third_intro_content": "Yat'lar Cake Wallet'ın dışında da çalışabilir. Dünya üzerindeki herhangi bir cüzdan adresi Yat ile değiştirilebilir!", + "third_intro_title": "Yat diğerleriyle iyi çalışır", + "time": "${minutes}d ${seconds}s", + "tip": "Bahşiş:", + "today": "Bugün", + "token_contract_address": "Token sözleşme adresi", + "token_decimal": "Belirteç ondalık", + "token_name": "Belirteç adı, örneğin: Tether", + "token_symbol": "Jeton sembolü, örneğin: USDT", + "tokenID": "İD", + "tor_connection": "Tor bağlantısı", + "tor_only": "Yalnızca Tor", + "total_saving": "Toplam Tasarruf", + "totp_2fa_failure": "Yanlış kod. Lütfen farklı bir kod deneyin veya yeni bir gizli anahtar oluşturun. 8 basamaklı kodları ve SHA512'yi destekleyen uyumlu bir 2FA uygulaması kullanın.", + "totp_2fa_success": "Başarı! Bu cüzdan için Cake 2FA etkinleştirildi. Mnemonic seed'inizi cüzdan erişiminizi kaybetme ihtimaline karşı kaydetmeyi unutmayın.", + "totp_auth_url": "TOTP YETKİ URL'si", + "totp_code": "TOTP Kodu", + "totp_secret_code": "TOTP Gizli Kodu", + "totp_verification_success": "Doğrulama Başarılı!", + "trade_details_copied": "${title} panoya kopyalandı", + "trade_details_created_at": "'da oluşturuldu", + "trade_details_fetching": "Getiriliyor", + "trade_details_id": "ID", + "trade_details_pair": "Parite", + "trade_details_provider": "Sağlayıcı", + "trade_details_state": "Durum", + "trade_details_title": "Takas Detayları", + "trade_for_not_created": "${title} için takas oluşturulmadı.", + "trade_history_title": "Takas geçmişi", + "trade_id": "Takas ID'si:", + "trade_id_not_found": "Trade ${tradeId} of ${title} not found.", + "trade_is_powered_by": "Bu takas ${provider} tarafından desteklenmektedir", + "trade_not_created": "Takas oluşturulmadı", + "trade_not_found": "Takas bulunamadı.", + "trade_state_btc_sent": "Btc gönderildi", + "trade_state_complete": "Tamamlandı", + "trade_state_confirming": "Onaylanıyor", + "trade_state_created": "Oluşturuldu", + "trade_state_finished": "Tamamlandı", + "trade_state_paid": "Ödendi", + "trade_state_paid_unconfirmed": "Ödendi onaylanmadı", + "trade_state_pending": "Beklemede", + "trade_state_timeout": "Zaman aşımı", + "trade_state_to_be_created": "Oluşturulacak", + "trade_state_traded": "Takas yapıldı", + "trade_state_trading": "Takas yapılıyor", + "trade_state_underpaid": "Eksik ödendi", + "trade_state_unpaid": "Ödenmedi", + "trades": "Takaslar", + "transaction_details_amount": "Miktar", + "transaction_details_copied": "${title} panoya kopyalandı", + "transaction_details_date": "Tarih", + "transaction_details_fee": "Fee", + "transaction_details_height": "Yükseklik", + "transaction_details_recipient_address": "Alıcı adres", "transaction_details_source_address": "Kaynak adresi", - "pause_wallet_creation": "Haven Cüzdanı oluşturma yeteneği şu anda duraklatıldı.", - "contractName": "Sözleşme Adı", - "contractSymbol": "Sözleşme Sembolü", - "description": "Tanım", - "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.", - "no_relays": "Röle yok", - "choose_relay": "Lütfen kullanmak için bir röle seçin", - "no_relays_message": "Bu kullanıcı için bir Nostr NIP-05 kaydı bulduk ancak bu kayıt herhangi bir aktarma içermiyor. Lütfen alıcıya Nostr kayıtlarına aktarma eklemesi talimatını verin.", - "no_relay_on_domain": "Kullanıcının alanı için bir geçiş yok veya geçiş kullanılamıyor. Lütfen kullanmak için bir röle seçin." -} + "transaction_details_title": "İşlem Detayları", + "transaction_details_transaction_id": "İşem ID'si", + "transaction_key": "İşlem Anahtarı", + "transaction_priority_fast": "Hızlı", + "transaction_priority_fastest": "En Hızlı", + "transaction_priority_medium": "Orta", + "transaction_priority_regular": "Normal", + "transaction_priority_slow": "Yavaş", + "transaction_sent": "Transfer gönderildi!", + "transaction_sent_notice": "Ekran 1 dakika sonra ilerlemezse, blok gezgininden ve e-postanızdan kontrol edin.", + "transactions": "İşlemler", + "transactions_by_date": "Tarihe göre transferler", + "trusted": "Güvenilir", + "unavailable_balance": "Kullanılamayan bakiye", + "unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.", + "unconfirmed": "Onaylanmamış Bakiye", + "understand": "Anladım", + "unmatched_currencies": "Mevcut cüzdanınızın para birimi taranan QR ile eşleşmiyor", + "unspent_change": "Değiştirmek", + "unspent_coins_details_title": "Harcanmamış koin detayları", + "unspent_coins_title": "Harcanmamış koinler", + "unsupported_asset": "Bu öğe için bu eylemi desteklemiyoruz. Lütfen desteklenen bir varlık türünde bir cüzdan oluşturun veya cüzdana geçiş yapın.", + "upto": "Şu miktara kadar: ${value}", + "use": "Şuna geç: ", + "use_card_info_three": "Dijital kartı çevrimiçi olarak veya temassız ödeme yöntemleriyle kullanın.", + "use_card_info_two": "Paralar, dijital para birimlerinde değil, ön ödemeli hesapta tutulduğunda USD'ye dönüştürülür.", + "use_ssl": "SSL kullan", + "use_suggested": "Önerileni Kullan", + "variable_pair_not_supported": "Bu değişken paritesi seçilen borsalarda desteklenmemekte", + "verification": "Doğrulama", + "verify_with_2fa": "Cake 2FA ile Doğrulayın", + "version": "Sürüm ${currentVersion}", + "view_all": "Hepsini göster", + "view_in_block_explorer": "Blok Gezgini'nde görüntüle", + "view_key_private": "İzleme anahtarı (özel)", + "view_key_public": "İzleme anahtarı (genel)", + "view_transaction_on": "İşlemi şurada görüntüle ", + "wallet_keys": "Cüzdan tohumu/anahtarları", + "wallet_list_create_new_wallet": "Yeni Cüzdan Oluştur", + "wallet_list_edit_wallet": "Cüzdanı düzenle", + "wallet_list_failed_to_load": "Failed to load ${wallet_name} wallet. ${error}", + "wallet_list_failed_to_remove": "${wallet_name} cüzdanı yüklenirken hata oluştu. ${error}", + "wallet_list_load_wallet": "Cüzdanı yükle", + "wallet_list_loading_wallet": "${wallet_name} cüzdanı yükleniyor", + "wallet_list_removing_wallet": "Removing ${wallet_name} wallet", + "wallet_list_restore_wallet": "Cüzdanı Geri Yükle", + "wallet_list_title": "Monero Cüzdanı", + "wallet_list_wallet_name": "Cüzdan adı", + "wallet_menu": "Menü", + "wallet_name": "Cüzdan ismi", + "wallet_name_exists": "Bu isimde bir cüzdan zaten mevcut. Lütfen farklı bir isim seç veya önce diğer cüzdanı yeniden adlandır.", + "wallet_restoration_store_incorrect_seed_length": "Yanlış tohum uzunluğu", + "wallet_seed": "Cüzdan tohumu", + "wallet_seed_legacy": "Eski cüzdan tohumu", + "wallet_store_monero_wallet": "Monero Cüzdanı", + "walletConnect": "WalletConnect", + "wallets": "Cüzdanlar", + "warning": "Uyarı", + "welcome": "Hoş Geldiniz", + "welcome_to_cakepay": "Cake Pay'e Hoş Geldiniz!", + "widgets_address": "Adres", + "widgets_or": "veya", + "widgets_restore_from_blockheight": "Blok yüksekliğinden geri yükle", + "widgets_restore_from_date": "Tarihten geri yükle", + "widgets_seed": "Tohum", + "wouoldLikeToConnect": "bağlanmak istiyorum", + "write_down_backup_password": "Lütfen yedekleme dosyasının içe aktarılması için kullanılan yedekleme parolanı not et.", + "xlm_extra_info": "Lütfen takas için XLM işlemi gönderirken Memo ID'yi belirtmeyi unutmayın", + "xmr_available_balance": "Kullanılabilir Bakiye", + "xmr_full_balance": "Tüm Bakiye", + "xmr_hidden": "Gizli", + "xmr_to_error": "XMR.TO hatası", + "xmr_to_error_description": "Geçersiz tutar. Ondalık noktadan sonra maksimum limit 8 basamaktır", + "xrp_extra_info": "Lütfen takas için XRP işlemi gönderirken Hedef Etiketi (Destination Tag) belirtmeyi unutmayın", + "yat": "Yat", + "yat_address": "Yat adresi", + "yat_alert_content": "Cake Wallet kullanıcıları artık tüm favori koin birimlerini benzersiz emoji tabanlı kullanıcı adıyla gönderebilir ve alabilirler.", + "yat_alert_title": "Yat ile daha kolay kripto gönderin ve alın", + "yat_error": "Yat hatası", + "yat_error_content": "Bu Yat'a bağlı bir adres yok. Başka bir Yat'ı deneyin", + "yat_popup_content": "Artık Cake Wallet'ta kısa, emoji tabanlı bir kullanıcı adı olan Yat'ınızla kripto gönderebilir ve alabilirsiniz. Yats'ı istediğiniz zaman ayarlar ekranından yönetebilirsiniz", + "yat_popup_title": "Cüzdan adresiniz emojileştirilebilir.", + "yesterday": "Dün", + "you_now_have_debit_card": "Artık bir ön ödemeli kartın var", + "you_pay": "Şu kadar ödeyeceksin: ", + "you_will_get": "Biçimine dönüştür:", + "you_will_send": "Biçiminden dönüştür:", + "yy": "YY", + "zzzz": "zzzz" +} \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 7cc41ab43..59f21ab87 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -1,779 +1,780 @@ { - "welcome": "Вітаємо в", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "В самому зручному гаманці для Monero, Bitcoin, Ethereum, Litecoin, та Haven", - "please_make_selection": "Оберіть спосіб створення гаманця: створити новий чи відновити ваш існуючий.", - "create_new": "Створити новий гаманець", - "restore_wallet": "Відновити гаманець", - "monero_com": "Monero.com by Cake Wallet", - "monero_com_wallet_text": "Awesome wallet for Monero", - "haven_app": "Haven by Cake Wallet", - "haven_app_wallet_text": "Awesome wallet for Haven", - "accounts": "Акаунти", - "edit": "Редагувати", + "about_cake_pay": "Cake Pay дозволяє вам легко купувати подарункові картки з віртуальними активами, які можна миттєво витратити в понад 150 000 продавців у Сполучених Штатах.", "account": "Акаунт", + "accounts": "Акаунти", + "accounts_subaddresses": "Акаунти та субадреси", + "activate": "Активувати", + "active": "Активний", + "active_cards": "Активні картки", + "activeConnectionsPrompt": "Тут з’являться активні підключення", "add": "Добавити", + "add_contact": "Додати контакт", + "add_custom_node": "Додати новий спеціальний вузол", + "add_custom_redemption": "Додати спеціальне погашення", + "add_fund_to_card": "Додайте передплачені кошти на картки (до ${value})", + "add_new_node": "Додати новий вузол", + "add_new_word": "Добавити нове слово", + "add_receiver": "Додати одержувача (необов'язково)", + "add_secret_code": "Або додайте цей секретний код до програми автентифікації", + "add_tip": "Додати підказку", + "add_token_disclaimer_check": "Я підтвердив адресу та інформацію щодо договору маркера, використовуючи авторитетне джерело. Додавання зловмисної або невірної інформації може призвести до втрати коштів.", + "add_token_warning": "Не редагуйте та не додавайте токени за вказівками шахраїв.\nЗавжди підтверджуйте адреси токенів у авторитетних джерелах!", + "add_value": "Додати значення", + "address": "Адреса", "address_book": "Адресна книга", - "contact": "Контакт", - "please_select": "Будь ласка, виберіть:", - "cancel": "Відмінити", - "ok": "OK", - "contact_name": "Ім'я контакту", - "reset": "Скинути", - "save": "Зберегти", + "address_book_menu": "Адресна книга", + "address_detected": "Виявлено адресу", + "address_from_domain": "Ця адреса від ${domain} на Unstoppable Domains", + "address_from_yat": "Ця адреса від ${emoji} на Yat", + "address_label": "Address label", "address_remove_contact": "Видалити контакт", "address_remove_content": "Ви впевнені, що хочете видалити вибраний контакт?", - "authenticated": "Аутентифіковано", - "authentication": "Аутентифікація", - "failed_authentication": "Помилка аутентифікації. ${state_error}", - "wallet_menu": "Меню гаманця", - "Blocks_remaining": "${status} Залишилось блоків", - "please_try_to_connect_to_another_node": "Будь ласка, спробуйте підключитися до іншого вузлу", - "xmr_hidden": "Приховано", - "xmr_available_balance": "Доступний баланс", - "xmr_full_balance": "Весь баланс", - "send": "Відправити", - "receive": "Отримати", - "transactions": "Транзакції", - "incoming": "Вхідні", - "outgoing": "Вихідні", - "transactions_by_date": "Сортувати по даті", - "trades": "Торгові операції", - "filter_by": "Фільтрувати по", - "today": "Сьогодні", - "yesterday": "Вчора", - "received": "Отримані", - "sent": "Відправлені", - "pending": " (в очікуванні)", - "rescan": "Пересканувати", - "reconnect": "Перепідключитися", - "wallets": "Гаманці", - "show_seed": "Показати мнемонічну фразу", - "show_keys": "Показати мнемонічну фразу/ключі", - "address_book_menu": "Адресна книга", - "reconnection": "Перепідключення", - "reconnect_alert_text": "Ви хочете перепідключитися?", - "exchange": "Обмін", - "clear": "Очистити", - "refund_address": "Адреса повернення коштів", - "change_exchange_provider": "Змінити провайдера обміну", - "you_will_send": "Конвертувати з", - "you_will_get": "Конвертувати в", - "amount_is_guaranteed": "Отримана сума є гарантованою", - "amount_is_estimate": "Отримана сума є приблизною", - "powered_by": "Використовуючи ${title}", - "error": "Помилка", - "estimated": "Приблизно ", - "min_value": "Мін: ${value} ${currency}", - "max_value": "Макс: ${value} ${currency}", - "change_currency": "Змінити валюту", - "overwrite_amount": "Overwrite amount", - "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", - "copy_id": "Скопіювати ID", - "exchange_result_write_down_trade_id": "Будь ласка, скопіюйте або запишіть ID операції.", - "trade_id": "ID операції:", - "copied_to_clipboard": "Скопійовано в буфер обміну", - "saved_the_trade_id": "Я зберіг ID операції", - "fetching": "Завантаження", - "id": "ID: ", - "amount": "Сума: ", - "payment_id": "ID платежу: ", - "status": "Статус: ", - "offer_expires_in": "Пропозиція закінчиться через: ", - "trade_is_powered_by": "Операція виконана через ${provider}", - "copy_address": "Cкопіювати адресу", - "exchange_result_confirm": "Натиснувши підтвердити, ви відправите ${fetchingLabel} ${from} з вашого гаманця ${walletName} на адресу вказану нижче. Або ви можете відправити зі свого зовнішнього гаманця на нижчевказану адресу/QR-код.\n\nБудь ласка, натисніть підтвердити для продовження або поверніться назад щоб змінити суму.", - "exchange_result_description": "Ви повинні надіслати мінімум ${fetchingLabel} ${from} на адресу, вказану на наступній сторінці. Якщо ви надішлете суму меншу за ${fetchingLabel} ${from}, то вона може бути не конвертованою і не поверненою.", - "exchange_result_write_down_ID": "*Будь ласка, скопіюйте або запишіть ID, вказаний вище.", - "confirm": "Підтвердити", - "confirm_sending": "Підтвердити відправлення", - "commit_transaction_amount_fee": "Підтвердити транзакцію \nСума: ${amount}\nКомісія: ${fee}", - "sending": "Відправлення", - "transaction_sent": "Tранзакцію відправлено!", - "expired": "Закінчується", - "time": "${minutes}хв ${seconds}сек", - "send_xmr": "Відправити XMR", - "exchange_new_template": "Новий шаблон", - "faq": "FAQ", - "enter_your_pin": "Введіть ваш PIN", - "loading_your_wallet": "Завантаження гаманця", - "new_wallet": "Новий гаманець", - "wallet_name": "Ім'я гаманця", - "continue_text": "Продовжити", - "choose_wallet_currency": "Будь ласка, виберіть валюту гаманця:", - "node_new": "Новий вузол", - "node_address": "Адреса вузла", - "node_port": "Порт вузла", - "login": "Логін", - "password": "Пароль", - "nodes": "Вузли", - "node_reset_settings_title": "Скинути налаштування", - "nodes_list_reset_to_default_message": "Ви впевнені, що хочете скинути до налаштувань за замовченням?", - "change_current_node": "Ви впевнені, що хочете змінити поточний вузол на ${node}?", - "change": "Змінити", - "remove_node": "Видалити вузол", - "remove_node_message": "Ви впевнені, що хочете видалити поточний вузол?", - "remove": "Видалити", - "delete": "Видалити", - "add_new_node": "Додати новий вузол", - "change_current_node_title": "Змінити поточний вузол", - "node_test": "Тест", - "node_connection_successful": "З'єднання було успішним", - "node_connection_failed": "Помилка з’єднання", - "new_node_testing": "Тестування нового вузла", - "use": "Використати ", - "digit_pin": "-значний PIN", - "share_address": "Поділитися адресою", - "receive_amount": "Сума", - "subaddresses": "Субадреси", "addresses": "Адреси", - "scan_qr_code_to_get_address": "Скануйте QR-код для одержання адреси", - "qr_fullscreen": "Торкніться, щоб відкрити QR-код на весь екран", - "rename": "Перейменувати", - "choose_account": "Оберіть акаунт", - "create_new_account": "Створити новий акаунт", - "accounts_subaddresses": "Акаунти та субадреси", - "restore_restore_wallet": "Відновити гаманець", - "restore_title_from_seed_keys": "Відновити з мнемонічної фрази/ключів", - "restore_description_from_seed_keys": "Ви можете відновити гаманець з мнемонічної фрази/ключів, які ви зберегли раніше", - "restore_next": "Продовжити", - "restore_title_from_backup": "Відновити із резервного файлу", - "restore_description_from_backup": "Ви можете відновити Cake Wallet з вашого резервного файлу", - "restore_seed_keys_restore": "Відновити за допомогою мнемонічної фрази/ключів", - "restore_title_from_seed": "Відновити з мнемонічної фрази", - "restore_description_from_seed": "Ви можете відновити гаманець використовуючи 25-ти слівну мнемонічну фразу", - "restore_title_from_keys": "Відновити за допомогою ключів", - "restore_description_from_keys": "Ви можете відновити гаманець за допомогою приватних ключів", - "restore_wallet_name": "Ім'я гаманця", - "restore_address": "Адреса", - "restore_view_key_private": "Приватний ключ перегляду", - "restore_spend_key_private": "Приватний ключ витрати", - "restore_recover": "Відновити", - "restore_wallet_restore_description": "Опис відновлюваного гаманця", - "restore_new_seed": "Нова мнемонічна фраза", - "restore_active_seed": "Активна мнемонічна фраза", - "restore_bitcoin_description_from_seed": "Ви можете відновити гаманець використовуючи 24-ти слівну мнемонічну фразу", - "restore_bitcoin_description_from_keys": "Ви можете відновити гаманець за допомогою WIF", - "restore_bitcoin_title_from_keys": "Відновити за допомогою WIF", - "restore_from_date_or_blockheight": "Будь ласка, введіть дату за кілька днів до створення цього гаманця. Або, якщо ви знаєте висоту блоку, введіть її значення", - "seed_reminder": "Будь ласка, запишіть мнемонічну фразу на випадок втрати або очищення телефону", - "seed_title": "Мнемонічна фраза", - "seed_share": "Поділитися мнемонічною фразою", - "copy": "Скопіювати", - "seed_language": "Насіннєва мова", - "seed_choose": "Виберіть мову мнемонічної фрази", - "seed_language_next": "Продовжити", - "seed_language_english": "Англійська", - "seed_language_chinese": "Китайська", - "seed_language_dutch": "Голландська", - "seed_language_german": "Німецька", - "seed_language_japanese": "Японська", - "seed_language_portuguese": "Португальська", - "seed_language_russian": "Російська", - "seed_language_spanish": "Іспанська", - "seed_language_french": "французький", - "seed_language_italian": "італійська", - "send_title": "Відправити", - "send_your_wallet": "Ваш гаманець", - "send_address": "${cryptoCurrency} адреса", - "send_payment_id": "ID платежу (опційно)", + "advanced_settings": "Розширені налаштування", + "aggressive": "Надто старанний", + "agree": "Згоден", + "agree_and_continue": "Погодитися та продовжити", + "agree_to": "Створюючи обліковий запис, ви погоджуєтеся з ", "all": "ВСЕ", - "send_error_minimum_value": "Мінімальна сума 0.01", - "send_error_currency": "Валюта може містити тільки цифри", - "send_estimated_fee": "Ймовірна комісія:", - "send_priority": "Комісія встановлена в залежності від пріоритету: ${transactionPriority}.\nПріоритет транзакції може бути змінений в налаштуваннях", - "send_creating_transaction": "Створити транзакцію", - "send_templates": "Шаблони", - "send_new": "Новий", - "send_amount": "Сума:", - "send_fee": "Комісія:", - "send_name": "Ім'я", - "got_it": "Зрозумів", - "send_sending": "Відправлення...", - "send_success": "Ваш ${crypto} успішно надісланий", - "settings_title": "Налаштування", - "settings_nodes": "Вузли", - "settings_current_node": "Поточний вузол", - "settings_wallets": "Гаманці", - "settings_display_balance": "Відображати баланс", - "settings_currency": "Валюта", - "settings_fee_priority": "Пріоритет транзакції", - "settings_save_recipient_address": "Зберігати адресу отримувача", - "settings_personal": "Персональні", - "settings_change_pin": "Змінити PIN", - "settings_change_language": "Змінити мову", - "settings_allow_biometrical_authentication": "Включити біометричну аутентифікацію", - "settings_dark_mode": "Темний режим", - "settings_transactions": "Транзакції", - "settings_trades": "Операції", - "settings_display_on_dashboard_list": "Відображати в списку транзакцій", - "settings_all": "ВСІ", - "settings_only_trades": "Операції", - "settings_only_transactions": "Транзакції", - "settings_none": "Нічого", - "settings_support": "Підтримка", - "settings_terms_and_conditions": "Умови та положення", - "pin_is_incorrect": "Некоректний PIN", - "setup_pin": "Встановити PIN", - "enter_your_pin_again": "Введіть PIN ще раз", - "setup_successful": "PIN було успішно встановлено!", - "wallet_keys": "Мнемонічна фраза/ключі гаманця", - "wallet_seed": "Мнемонічна фраза гаманця", - "private_key": "Приватний ключ", - "public_key": "Публічний ключ", - "view_key_private": "Приватний ключ перегляду", - "view_key_public": "Публічний ключ перегляду", - "spend_key_private": "Приватний ключ витрати", - "spend_key_public": "Публічний ключ витрати", - "copied_key_to_clipboard": "Скопійовано ${key} в буфер обміну", - "new_subaddress_title": "Нова адреса", - "new_subaddress_label_name": "Ім'я", - "new_subaddress_create": "Створити", - "address_label": "Address label", - "subaddress_title": "Список Субадрес", - "trade_details_title": "Деталі операцій", - "trade_details_id": "ID", - "trade_details_state": "Статус", - "trade_details_fetching": "Отримання", - "trade_details_provider": "Провайдер", - "trade_details_created_at": "Створено", - "trade_details_pair": "Пара", - "trade_details_copied": "${title} скопійовано в буфер обміну", - "trade_history_title": "Історія операцій", - "transaction_details_title": "Деталі транзакції", - "transaction_details_transaction_id": "ID транзакції", - "transaction_details_date": "Дата", - "transaction_details_height": "Висота", - "transaction_details_amount": "Сума", - "transaction_details_fee": "Комісія", - "transaction_details_copied": "${title} скопійовано в буфер обміну", - "transaction_details_recipient_address": "Адреси одержувачів", - "wallet_list_title": "Monero Гаманець", - "wallet_list_create_new_wallet": "Створити новий гаманець", - "wallet_list_edit_wallet": "Редагувати гаманець", - "wallet_list_wallet_name": "Назва гаманця", - "wallet_list_restore_wallet": "Відновити гаманець", - "wallet_list_load_wallet": "Завантаження гаманця", - "wallet_list_loading_wallet": "Завантаження ${wallet_name} гаманця", - "wallet_list_failed_to_load": "Помилка при завантаженні ${wallet_name} гаманця. ${error}", - "wallet_list_removing_wallet": "Видалення ${wallet_name} гаманця", - "wallet_list_failed_to_remove": "Помилка при видаленні ${wallet_name} гаманця. ${error}", - "widgets_address": "Адреса", - "widgets_restore_from_blockheight": "Відновити на висоті блоку", - "widgets_restore_from_date": "Відновити з дати", - "widgets_or": "або", - "widgets_seed": "Мнемонічна фраза", - "router_no_route": "Не встановлено маршрут для ${name}", - "error_text_account_name": "Ім'я акаунту може містити тільки букви, цифри\nі повинно бути від 1 до 15 символів в довжину", - "error_text_contact_name": "Ім'я контакту не може містити ` , ' \" символи\n і повинно бути від 1 до 32 символів в довжину", - "error_text_address": "Адреса гаманця повинна відповідати типу\nкриптовалюти", - "error_text_node_address": "Будь ласка, введіть iPv4 адресу", - "error_text_node_port": "Порт вузла може містити тільки цифри від 0 до 65535", - "error_text_node_proxy_address": "Будь ласка, введіть :<порт>, наприклад 127.0.0.1:9050", - "error_text_payment_id": "Ідентифікатор платежу може містити від 16 до 64 символів в hex", - "error_text_xmr": "Значення XMR не може перевищувати доступний баланс.\nКількість цифр після коми повинно бути меншим або дорівнювати 12", - "error_text_fiat": "Значення суми не може перевищувати доступний баланс.\nКількість цифр після коми повинно бути меншим або дорівнювати 2", - "error_text_subaddress_name": "Ім'я субадреси не може містити ` , ' \" символи\nі може бути від 1 до 20 символів в довжину", - "error_text_amount": "Баланс може містити тільки цифри", - "error_text_wallet_name": "Ім'я гаманця може містити тільки букви, цифри, символи _ -\nі повинно бути від 1 до 33 символів в довжину", - "error_text_keys": "Ключі гаманця можуть містити тільки 64 символів в hex", - "error_text_crypto_currency": "Кількість цифр після коми\nповинно бути меншим або дорівнювати 12", - "error_text_minimal_limit": "Операція для ${provider} не створена. Сума менша мінімальної: ${min} ${currency}", - "error_text_maximum_limit": "Операція для ${provider} не створена. Сума більше максимальної: ${max} ${currency}", - "error_text_limits_loading_failed": "Операція для ${provider} не створена. Помилка завантаження лімітів", - "error_text_template": "Ім'я та адреса шаблону не може містити ` , ' \" символи\nі може бути від 1 до 106 символів в довжину", + "all_trades": "Всі операції", + "all_transactions": "Всі транзакції", + "alphabetical": "Алфавітний", + "already_have_account": "Вже є обліковий запис?", + "always": "Завжди", + "amount": "Сума: ", + "amount_is_estimate": "Отримана сума є приблизною", + "amount_is_guaranteed": "Отримана сума є гарантованою", + "and": "і", + "anonpay_description": "Згенерувати ${type}. Одержувач може ${method} будь-якою підтримуваною криптовалютою, і ви отримаєте кошти на цей гаманець.", + "apk_update": "Оновлення APK", + "approve": "Затвердити", + "arrive_in_this_address": "${currency} ${tag}надійде на цю адресу", + "ascending": "Висхід", + "ask_each_time": "Запитайте кожен раз", "auth_store_ban_timeout": "ban_timeout", "auth_store_banned_for": "Заблоковано на ", "auth_store_banned_minutes": " хвилин", "auth_store_incorrect_password": "Некоректний PIN", - "wallet_store_monero_wallet": "Monero гаманець", - "wallet_restoration_store_incorrect_seed_length": "Невірна довжина мнемонічної фрази", - "full_balance": "Весь баланс", - "available_balance": "Доступний баланс", - "hidden_balance": "Прихований баланс", - "sync_status_syncronizing": "СИНХРОНІЗАЦІЯ", - "sync_status_syncronized": "СИНХРОНІЗОВАНИЙ", - "sync_status_not_connected": "НЕ ПІДКЛЮЧЕННИЙ", - "sync_status_starting_sync": "ПОЧАТОК СИНХРОНІЗАЦІЇ", - "sync_status_failed_connect": "ВІДКЛЮЧЕНО", - "sync_status_connecting": "ПІДКЛЮЧЕННЯ", - "sync_status_connected": "ПІДКЛЮЧЕНО", - "sync_status_attempting_sync": "СПРОБА СИНХРОНІЗАЦІЇ", - "transaction_priority_slow": "Повільний", - "transaction_priority_regular": "Звичайний", - "transaction_priority_medium": "Середній", - "transaction_priority_fast": "Швидкий", - "transaction_priority_fastest": "Найшвидший", - "trade_for_not_created": "Операція для ${title} не створена.", - "trade_not_created": "Операція не створена", - "trade_id_not_found": "Операція ${tradeId} ${title} не знайдена.", - "trade_not_found": "Операція не знайдена.", - "trade_state_pending": "Очікування", - "trade_state_confirming": "Підтвердження", - "trade_state_trading": "Виконання операції", - "trade_state_traded": "Операція виконана", - "trade_state_complete": "Завершено", - "trade_state_to_be_created": "Буде створена", - "trade_state_unpaid": "Неоплачена", - "trade_state_underpaid": "Недоплачена", - "trade_state_paid_unconfirmed": "Оплата непідтверджена", - "trade_state_paid": "Оплачена", - "trade_state_btc_sent": "BTC надіслано", - "trade_state_timeout": "Таймаут", - "trade_state_created": "Створена", - "trade_state_finished": "Завершена", - "change_language": "Змінити мову", - "change_language_to": "Змінити мову на ${language}?", - "paste": "Вставити", - "restore_from_seed_placeholder": "Введіть або вставте мнемонічну фразу вашого гаманця", - "add_new_word": "Добавити нове слово", - "incorrect_seed": "Введений текст невірний.", - "biometric_auth_reason": "Відскануйте свій відбиток пальця для аутентифікації", - "version": "Версія ${currentVersion}", - "extracted_address_content": "Ви будете відправляти кошти\n${recipient_name}", - "card_address": "Адреса:", - "buy": "Купити", - "sell": "Продати", - "placeholder_transactions": "Тут відображатимуться ваші транзакції", - "placeholder_contacts": "Тут будуть показані ваші контакти", - "template": "Шаблон", - "confirm_delete_template": "Ця дія видалить шаблон. Ви хочете продовжити?", - "confirm_delete_wallet": "Ця дія видалить гаманець. Ви хочете продовжити?", - "change_wallet_alert_title": "Змінити поточний гаманець", - "change_wallet_alert_content": "Ви хочете змінити поточний гаманець на ${wallet_name}?", - "creating_new_wallet": "Створення нового гаманця", - "creating_new_wallet_error": "Помилка: ${description}", - "seed_alert_title": "Увага", - "seed_alert_content": "Мнемонічна фраза - єдиний спосіб відновити ваш гаманець. Ви записали її?", - "seed_alert_back": "Назад", - "seed_alert_yes": "Так", - "exchange_sync_alert_content": "Зачекайте, поки ваш гаманець не синхронізується", - "pre_seed_title": "ВАЖЛИВО", - "pre_seed_description": "На наступній сторінці ви побачите серію з ${words} слів. Це ваша унікальна та приватна мнемонічна фраза, і це ЄДИНИЙ спосіб відновити ваш гаманець на випадок втрати або несправності. ВАМ необхідно записати її та зберігати в безпечному місці поза програмою Cake Wallet.", - "pre_seed_button_text": "Зрозуміло. Покажіть мнемонічну фразу", - "xmr_to_error": "Помилка XMR.TO", - "xmr_to_error_description": "Неприпустима сума. Максимум 8 цифр після десяткової коми", - "provider_error": "${provider} помилка", - "use_ssl": "Використати SSL", - "trusted": "довіряють", - "color_theme": "Кольорова тема", - "light_theme": "Світла", - "bright_theme": "Яскрава", - "dark_theme": "Темна", - "enter_your_note": "Введіть примітку…", - "note_optional": "Примітка (необов’язково)", - "note_tap_to_change": "Примітка (натисніть для зміни)", - "view_in_block_explorer": "View in Block Explorer", - "view_transaction_on": "View Transaction on ", - "transaction_key": "Ключ транзакції", - "confirmations": "Підтвердження", - "recipient_address": "Адреса одержувача", - "extra_id": "Додатковий ID:", - "destination_tag": "Тег призначення:", - "memo": "Пам’ятка:", - "backup": "Резервна копія", - "change_password": "Змінити пароль", - "backup_password": "Пароль резервної копії", - "write_down_backup_password": "Запишіть пароль резервної копії, який використовується для імпорту файлів резервних копій.", - "export_backup": "Експортувати резервну копію", - "save_backup_password": "Переконайтеся, що ви зберегли свій пароль резервної копії. Без нього ви не зможете імпортувати файли резервних копій.", - "backup_file": "Файл резервної копії", - "edit_backup_password": "Змінити пароль резервної копії", - "save_backup_password_alert": "Зберегти пароль резервної копії", - "change_backup_password_alert": "Ваші попередні файли резервних копій будуть недоступні для імпорту з новим паролем резервної копії. Новий пароль резервної копії буде використовуватися тільки для нових файлів резервних копій. Ви впевнені, що хочете змінити пароль резервної копії?", - "enter_backup_password": "Введіть пароль резервної копії", - "select_backup_file": "Виберіть файл резервної копії", - "import": "Імпорт", - "please_select_backup_file": "Виберіть файл резервної копії та введіть пароль резервної копії.", - "fixed_rate": "Фіксована ставка", - "fixed_rate_alert": "Ви зможете ввести суму отримання тоді, коли буде встановлений режим фіксованої ставки. Ви хочете перейти в режим фіксованої ставки?", - "xlm_extra_info": "Будь ласка, не забудьте вказати ідентифікатор пам'ятки під час надсилання транзакції XLM для обміну", - "xrp_extra_info": "Будь ласка, не забудьте вказати тег призначення під час надсилання XRP-транзакції для обміну", - "exchange_incorrect_current_wallet_for_xmr": "Якщо ви хочете обміняти XMR із вашого балансу Cake Wallet Monero, спочатку перейдіть на свій гаманець Monero.", - "confirmed": "Підтверджений баланс", - "unconfirmed": "Непідтверджений баланс", - "displayable": "Відображуваний", - "submit_request": "надіслати запит", - "buy_alert_content": "Наразі ми підтримуємо купівлю лише Bitcoin, Ethereum, Litecoin і Monero. Створіть або перейдіть на свій гаманець Bitcoin, Ethereum, Litecoin або Monero.", - "sell_alert_content": "Наразі ми підтримуємо лише продаж Bitcoin, Ethereum і Litecoin. Створіть або перейдіть на свій гаманець Bitcoin, Ethereum або Litecoin.", - "outdated_electrum_wallet_description": "Нові біткойн-гаманці, створені в Cake, тепер містять мнемонічну фразу з 24 слів. Обов’язково стовріть новий біткойн-гаманець, переведіть всі кошти на новий гаманець із 24 слів і припиніть використання гаманців із мнемонічною фразою з 12 слів. Зробіть це негайно, щоб убезпечити свої кошти.", - "understand": "Зрозуміло", - "apk_update": "Оновлення APK", - "buy_bitcoin": "Купити Bitcoin", - "buy_with": "Купити за допомогою", - "moonpay_alert_text": "Значення суми має бути більшим або дорівнювати ${minAmount} ${fiatCurrency}", - "outdated_electrum_wallet_receive_warning": "Якщо цей гаманець має мнемонічну фразу з 12 слів і був створений у Cake, НЕ переводьте біткойни на цей гаманець. Будь-які BTC, переведений на цей гаманець, можуть бути втраченими. Створіть новий гаманець з мнемонічною фразою з 24 слів (торкніться меню у верхньому правому куті, виберіть Гаманці, виберіть Створити новий гаманець, потім виберіть Bitcoin) і НЕГАЙНО переведіть туди свії BTC. Нові (з мнемонічною фразою з 24 слів) гаманці BTC від Cake надійно захищені", - "do_not_show_me": "Не показуй мені це знову", - "unspent_coins_title": "Невитрачені монети", - "unspent_coins_details_title": "Відомості про невитрачені монети", - "freeze": "Заморозити", - "frozen": "Заморожено", - "coin_control": "Контроль монет (необов’язково)", - "address_detected": "Виявлено адресу", - "address_from_domain": "Ця адреса від ${domain} на Unstoppable Domains", - "add_receiver": "Додати одержувача (необов'язково)", - "manage_yats": "Керувати Yat", - "yat_alert_title": "За допомогою Yat легше надсилати та отримувати криптовалюту", - "yat_alert_content": "Користувачі Cake Wallet тепер можуть надсилати та отримувати криптовалюту за допомогою унікального імені користувача на основі смайликів.", - "get_your_yat": "Одержати свій Yat", - "connect_an_existing_yat": "Підключити існуючий Yat", - "yat_address": "Yat адреса", - "yat": "Yat", - "connect_yats": "Підключіть Yats", - "address_from_yat": "Ця адреса від ${emoji} на Yat", - "yat_error": "Помилка Yat", - "yat_error_content": "Немає адрес, пов'язаних з цим Yat. Спробуйте інший Yat", - "choose_address": "\n\nБудь ласка, оберіть адресу:", - "yat_popup_title": "Адреса вашого гаманця може бути пов'язаною з емодзі", - "yat_popup_content": "Тепер ви можете відправляти і отримувати криптовалюту в Cake Wallet за допомогою Yat - короткого імені користувача на основі емодзі. Керуйте Yat в будь-який час за допомогою екрану налаштувань", - "second_intro_title": "Одна адреса емодзі для управління іншими адресами", - "second_intro_content": "Ваш Yat - це єдина унікальна адреса емодзі, яка замінює довгі шістнадцятиричні адреси для всіх ваших валют.", - "third_intro_title": "Yat добре взаємодіє з іншими", - "third_intro_content": "Yat знаходиться за межами Cake Wallet. Будь-яку адресу гаманця на землі можна замінити на Yat!", - "learn_more": "Дізнатися більше", - "search": "Пошук", - "search_language": "Мова пошуку", - "search_currency": "Шукати валюту", - "new_template": "Новий шаблон", - "electrum_address_disclaimer": "Ми створюємо нові адреси щоразу, коли ви використовуєте їх, але попередні адреси продовжують працювати", - "wallet_name_exists": "Гаманець з такою назвою вже існує", - "market_place": "Ринок", - "cake_pay_title": "Подарункові картки Cake Pay", - "cake_pay_subtitle": "Купуйте подарункові картки зі знижкою (тільки для США)", - "cake_pay_web_cards_title": "Веб-картки Cake Pay", - "cake_pay_web_cards_subtitle": "Купуйте передоплачені та подарункові картки по всьому світу", - "about_cake_pay": "Cake Pay дозволяє вам легко купувати подарункові картки з віртуальними активами, які можна миттєво витратити в понад 150 000 продавців у Сполучених Штатах.", - "cake_pay_account_note": "Зареєструйтеся, використовуючи лише адресу електронної пошти, щоб переглядати та купувати картки. Деякі навіть доступні зі знижкою!", - "already_have_account": "Вже є обліковий запис?", - "create_account": "Створити обліковий запис", - "privacy_policy": "Політика конфіденційності", - "welcome_to_cakepay": "Ласкаво просимо до Cake Pay!", - "sign_up": "Зареєструватися", - "forgot_password": "Забули пароль", - "reset_password": "Скинути пароль", - "gift_cards": "Подарункові карти", - "setup_your_debit_card": "Налаштуйте свою дебетову картку", - "no_id_required": "Ідентифікатор не потрібен. Поповнюйте та витрачайте будь-де", - "how_to_use_card": "Як використовувати цю картку", - "purchase_gift_card": "Придбати подарункову картку", - "verification": "Перевірка", - "fill_code": "Будь ласка, введіть код підтвердження, надісланий на вашу електронну адресу", - "didnt_get_code": "Не отримуєте код?", - "resend_code": "Будь ласка, надішліть його повторно", - "debit_card": "Дебетова картка", - "cakepay_prepaid_card": "Передплачена дебетова картка CakePay", - "no_id_needed": "Ідентифікатор не потрібен!", - "frequently_asked_questions": "Часті запитання", - "debit_card_terms": "Зберігання та використання номера вашої платіжної картки (та облікових даних, які відповідають номеру вашої платіжної картки) у цьому цифровому гаманці регулюються Умовами відповідної угоди власника картки з емітентом платіжної картки, що діє з час від часу.", - "please_reference_document": "Для отримання додаткової інформації зверніться до документів нижче.", - "cardholder_agreement": "Угода власника картки", - "e_sign_consent": "Згода електронного підпису", - "agree_and_continue": "Погодитися та продовжити", - "email_address": "Адреса електронної пошти", - "agree_to": "Створюючи обліковий запис, ви погоджуєтеся з ", - "and": "і", - "enter_code": "Введіть код", - "congratulations": "Вітаємо!", - "you_now_have_debit_card": "Тепер у вас є дебетова картка", - "min_amount": "Мінімум: ${value}", - "max_amount": "Макс: ${value}", - "enter_amount": "Введіть суму", - "billing_address_info": "Якщо буде запропоновано платіжну адресу, вкажіть свою адресу доставки", - "order_physical_card": "Замовити фізичну картку", - "add_value": "Додати значення", - "activate": "Активувати", - "get_a": "Отримати ", - "digital_and_physical_card": " цифрова та фізична передплачена дебетова картка", - "get_card_note": " яку можна перезавантажувати цифровими валютами. Додаткова інформація не потрібна!", - "signup_for_card_accept_terms": "Зареєструйтеся на картку та прийміть умови.", - "add_fund_to_card": "Додайте передплачені кошти на картки (до ${value})", - "use_card_info_two": "Кошти конвертуються в долари США, якщо вони зберігаються на передплаченому рахунку, а не в цифрових валютах.", - "use_card_info_three": "Використовуйте цифрову картку онлайн або за допомогою безконтактних методів оплати.", - "optionally_order_card": "Необов'язково замовте фізичну картку.", - "hide_details": "Приховати деталі", - "show_details": "Показати деталі", - "upto": "до ${value}", - "discount": "Зекономте ${value}%", - "gift_card_amount": "Сума подарункової картки", - "bill_amount": "Сума рахунку", - "you_pay": "Ви платите", - "tip": "Порада:", - "custom": "на замовлення", - "by_cake_pay": "від Cake Pay", - "expires": "Закінчується", - "mm": "MM", - "yy": "YY", - "online": "Онлайн", - "offline": "Офлайн", - "gift_card_number": "Номер подарункової картки", - "pin_number": "PIN-код", - "total_saving": "Загальна економія", - "last_30_days": "Останні 30 днів", - "avg_savings": "Середня економія", - "view_all": "Переглянути все", - "active_cards": "Активні картки", - "delete_account": "Видалити обліковий запис", - "cards": "Картки", - "active": "Активний", - "redeeded": "Викуплено", - "gift_card_balance_note": "Тут з'являться подарункові картки із залишком на балансі", - "gift_card_redeemed_note": "Подарункові картки, які ви активували, відображатимуться тут", - "logout": "Вийти", - "add_tip": "Додати підказку", - "percentageOf": "${amount}", - "is_percentage": "є", - "search_category": "Категорія пошуку", - "mark_as_redeemed": "Позначити як погашене", - "more_options": "Більше параметрів", - "awaiting_payment_confirmation": "Очікується підтвердження платежу", - "transaction_sent_notice": "Якщо екран не відображається через 1 хвилину, перевірте провідник блоків і свою електронну пошту.", - "agree": "Згоден", - "in_store": "У магазині", - "generating_gift_card": "Створення подарункової картки", - "payment_was_received": "Ваш платіж отримано.", - "proceed_after_one_minute": "Якщо екран не продовжується через 1 хвилину, перевірте свою електронну пошту.", - "order_id": "Ідентифікатор замовлення", - "gift_card_is_generated": "Подарункова картка створена", - "open_gift_card": "Відкрити подарункову картку", - "contact_support": "Звернутися до служби підтримки", - "gift_cards_unavailable": "Наразі подарункові картки можна придбати лише через Monero, Bitcoin і Litecoin", - "background_sync_mode": "Фоновий режим синхронізації", - "sync_all_wallets": "Синхронізувати всі гаманці", - "introducing_cake_pay": "Представляємо Cake Pay!", - "cake_pay_learn_more": "Миттєво купуйте та активуйте подарункові картки в додатку!\nПроведіть пальцем зліва направо, щоб дізнатися більше.", - "automatic": "Автоматичний", - "fixed_pair_not_supported": "Ця фіксована пара не підтримується вибраними біржами", - "variable_pair_not_supported": "Ця пара змінних не підтримується вибраними біржами", - "none_of_selected_providers_can_exchange": "Жоден із вибраних провайдерів не може здійснити цей обмін", - "choose_one": "Вибери один", - "choose_from_available_options": "Виберіть із доступних варіантів:", - "custom_redeem_amount": "Власна сума викупу", - "add_custom_redemption": "Додати спеціальне погашення", - "remaining": "залишилося", - "delete_wallet": "Видалити гаманець", - "delete_wallet_confirm_message": "Ви впевнені, що хочете видалити гаманець ${wallet_name}?", - "low_fee": "Низька плата", - "low_fee_alert": "Зараз ви використовуєте низький пріоритет плати за мережу. Це може спричинити тривале очікування, інший курс або скасування угод. Ми рекомендуємо встановити вищу плату для кращого досвіду.", - "ignor": "Ігнорувати", - "use_suggested": "Використати запропоноване", - "do_not_share_warning_text": "Не діліться цим нікому, включно зі службою підтримки.\n\nВаші кошти можуть і будуть вкрадені!", - "help": "допомога", - "all_transactions": "Всі транзакції", - "all_trades": "Всі операції", - "connection_sync": "Підключення та синхронізація", - "security_and_backup": "Безпека та резервне копіювання", - "create_backup": "Створити резервну копію", - "privacy_settings": "Налаштування конфіденційності", - "privacy": "Конфіденційність", - "display_settings": "Налаштування дисплея", - "other_settings": "Інші налаштування", - "require_pin_after": "Вимагати PIN після", - "always": "Завжди", - "minutes_to_pin_code": "${minute} хвилин", - "disable_exchange": "Вимкнути exchange", - "advanced_settings": "Розширені налаштування", - "settings_can_be_changed_later": "Ці параметри можна змінити пізніше в налаштуваннях програми", - "add_custom_node": "Додати новий спеціальний вузол", - "disable_fiat": "Вимкнути фиат", - "fiat_api": "Фіат API", - "disabled": "Вимкнено", - "enabled": "Увімкнено", - "tor_only": "Тільки Tor", - "unmatched_currencies": "Валюта вашого гаманця не збігається з валютою сканованого QR-коду", - "orbot_running_alert": "Перед підключенням до цього вузла переконайтеся, що Orbot запущено.", - "contact_list_contacts": "Контакти", - "contact_list_wallets": "Мої гаманці", - "bitcoin_payments_require_1_confirmation": "Платежі Bitcoin потребують 1 підтвердження, яке може зайняти 20 хвилин або більше. Дякую за Ваше терпіння! Ви отримаєте електронний лист, коли платіж буде підтверджено.", - "send_to_this_address": "Надіслати ${currency} ${tag}на цю адресу", - "arrive_in_this_address": "${currency} ${tag}надійде на цю адресу", - "do_not_send": "Не надсилайте", - "error_dialog_content": "На жаль, ми отримали помилку.\n\nБудь ласка, надішліть звіт про збій нашій команді підтримки, щоб покращити додаток.", - "scan_qr_code": "Відскануйте QR-код", - "cold_or_recover_wallet": "Додайте холодний гаманець або відновіть паперовий гаманець", - "please_wait": "Будь ласка, зачекайте", - "sweeping_wallet": "Підмітаня гаманця", - "sweeping_wallet_alert": "Це не повинно зайняти багато часу. НЕ ЗАЛИШАЙТЕ ЦЬОГО ЕКРАНУ, АБО КОШТИ МОЖУТЬ БУТИ ВТРАЧЕНІ", - "decimal_places_error": "Забагато знаків після коми", - "edit_node": "Редагувати вузол", - "invoice_details": "Реквізити рахунку-фактури", - "donation_link_details": "Деталі посилання для пожертв", - "anonpay_description": "Згенерувати ${type}. Одержувач може ${method} будь-якою підтримуваною криптовалютою, і ви отримаєте кошти на цей гаманець.", - "create_invoice": "Створити рахунок-фактуру", - "create_donation_link": "Створити посилання для пожертв", - "optional_email_hint": "Додаткова електронна адреса для сповіщення одержувача", - "optional_description": "Додатковий опис", - "optional_name": "Додаткове ім'я одержувача", - "clearnet_link": "Посилання Clearnet", - "onion_link": "Посилання на цибулю", - "settings": "Налаштування", - "sell_monero_com_alert_content": "Продаж Monero ще не підтримується", - "error_text_input_below_minimum_limit": "Сума менша мінімальної", - "error_text_input_above_maximum_limit": "Сума більше максимальної", - "show_market_place": "Відображати маркетплейс", - "prevent_screenshots": "Запобігати знімкам екрана та запису екрана", - "profile": "Профіль", - "close": "Закрити", - "modify_2fa": "Змінити торт 2FA", - "disable_cake_2fa": "Вимкнути Cake 2FA", - "question_to_disable_2fa": "Ви впевнені, що хочете вимкнути Cake 2FA? Код 2FA більше не потрібен для доступу до гаманця та певних функцій.", - "disable": "Вимкнути", - "setup_2fa": "Налаштування Cake 2FA", - "verify_with_2fa": "Перевірте за допомогою Cake 2FA", - "totp_code": "Код TOTP", - "please_fill_totp": "Будь ласка, введіть 8-значний код, наявний на вашому іншому пристрої", - "totp_2fa_success": "Успіх! Cake 2FA увімкнено для цього гаманця. Пам’ятайте про збереження мнемоніки на випадок, якщо ви втратите доступ до гаманця.", - "totp_verification_success": "Перевірка успішна!", - "totp_2fa_failure": "Невірний код. Спробуйте інший код або створіть новий секретний ключ. Використовуйте сумісний додаток 2FA, який підтримує 8-значні коди та SHA512.", - "enter_totp_code": "Будь ласка, введіть код TOTP.", - "add_secret_code": "Або додайте цей секретний код до програми автентифікації", - "totp_secret_code": "Секретний код TOTP", - "setup_2fa_text": "Cake 2FA працює з використанням TOTP як другого фактора автентифікації.\n\nДля TOTP Cake 2FA потрібен SHA-512 і підтримка 8 цифр; це забезпечує підвищену безпеку. Додаткову інформацію та підтримувані програми можна знайти в посібнику.", - "setup_totp_recommended": "Налаштувати TOTP", - "disable_buy": "Вимкнути дію покупки", - "disable_sell": "Вимкнути дію продажу", + "authenticated": "Аутентифіковано", + "authentication": "Аутентифікація", "auto_generate_subaddresses": "Автоматично генерувати підадреси", - "cake_2fa_preset": "Торт 2FA Preset", - "narrow": "вузькі", - "normal": "нормальний", - "aggressive": "Надто старанний", - "require_for_assessing_wallet": "Потрібен доступ до гаманця", - "require_for_sends_to_non_contacts": "Вимагати для надсилання неконтактним особам", - "require_for_sends_to_contacts": "Вимагати для надсилання контактам", - "require_for_sends_to_internal_wallets": "Вимагати надсилання на внутрішні гаманці", - "require_for_exchanges_to_internal_wallets": "Вимагати обміну на внутрішні гаманці", - "require_for_adding_contacts": "Потрібен для додавання контактів", - "require_for_creating_new_wallets": "Потрібно для створення нових гаманців", - "require_for_all_security_and_backup_settings": "Вимагати всіх налаштувань безпеки та резервного копіювання", + "automatic": "Автоматичний", + "available_balance": "Доступний баланс", "available_balance_description": "Це сума, яку ви можете витратити, не включаючи невизначені кошти. Це може бути менше, ніж загальний баланс, якщо ви витратили кошти, які ще не підтверджені.", - "syncing_wallet_alert_title": "Ваш гаманець синхронізується", - "syncing_wallet_alert_content": "Ваш баланс та список транзакцій може бути неповним, доки вгорі не буде написано «СИНХРОНІЗОВАНО». Натисніть/торкніться, щоб дізнатися більше.", - "home_screen_settings": "Налаштування головного екрана", - "sort_by": "Сортувати за", - "search_add_token": "Пошук / Додати маркер", - "edit_token": "Редагувати маркер", - "warning": "УВАГА", - "add_token_warning": "Не редагуйте та не додавайте токени за вказівками шахраїв.\nЗавжди підтверджуйте адреси токенів у авторитетних джерелах!", - "add_token_disclaimer_check": "Я підтвердив адресу та інформацію щодо договору маркера, використовуючи авторитетне джерело. Додавання зловмисної або невірної інформації може призвести до втрати коштів.", - "token_contract_address": "Адреса договору маркера", - "token_name": "Назва токена, наприклад: Tether", - "token_symbol": "Символ маркера, наприклад: USDT", - "token_decimal": "Токен десятковий", - "field_required": "Це поле є обов'язковим", - "pin_at_top": "закріпити ${token} зверху", - "invalid_input": "Неправильні дані", - "fiat_balance": "Фіат Баланс", - "gross_balance": "Валовий баланс", - "alphabetical": "Алфавітний", - "generate_name": "Згенерувати назву", + "avg_savings": "Середня економія", + "awaitDAppProcessing": "Зачекайте, доки dApp завершить обробку.", + "awaiting_payment_confirmation": "Очікується підтвердження платежу", + "background_sync_mode": "Фоновий режим синхронізації", + "backup": "Резервна копія", + "backup_file": "Файл резервної копії", + "backup_password": "Пароль резервної копії", "balance_page": "Сторінка балансу", - "share": "Поділіться", - "slidable": "Розсувний", - "monero_dark_theme": "Темна тема Monero", + "bill_amount": "Сума рахунку", + "billing_address_info": "Якщо буде запропоновано платіжну адресу, вкажіть свою адресу доставки", + "biometric_auth_reason": "Відскануйте свій відбиток пальця для аутентифікації", "bitcoin_dark_theme": "Темна тема Bitcoin", "bitcoin_light_theme": "Світла тема Bitcoin", - "high_contrast_theme": "Тема високої контрастності", - "matrix_green_dark_theme": "Зелена темна тема Matrix", - "monero_light_theme": "Легка тема Monero", - "manage_nodes": "Керуйте вузлами", - "etherscan_history": "Історія Etherscan", - "template_name": "Назва шаблону", + "bitcoin_payments_require_1_confirmation": "Платежі Bitcoin потребують 1 підтвердження, яке може зайняти 20 хвилин або більше. Дякую за Ваше терпіння! Ви отримаєте електронний лист, коли платіж буде підтверджено.", + "Blocks_remaining": "${status} Залишилось блоків", + "bright_theme": "Яскрава", + "buy": "Купити", + "buy_alert_content": "Наразі ми підтримуємо купівлю лише Bitcoin, Ethereum, Litecoin і Monero. Створіть або перейдіть на свій гаманець Bitcoin, Ethereum, Litecoin або Monero.", + "buy_bitcoin": "Купити Bitcoin", + "buy_provider_unavailable": "В даний час постачальник недоступний.", + "buy_with": "Купити за допомогою", + "by_cake_pay": "від Cake Pay", + "cake_2fa_preset": "Торт 2FA Preset", + "cake_pay_account_note": "Зареєструйтеся, використовуючи лише адресу електронної пошти, щоб переглядати та купувати картки. Деякі навіть доступні зі знижкою!", + "cake_pay_learn_more": "Миттєво купуйте та активуйте подарункові картки в додатку!\nПроведіть пальцем зліва направо, щоб дізнатися більше.", + "cake_pay_subtitle": "Купуйте подарункові картки зі знижкою (тільки для США)", + "cake_pay_title": "Подарункові картки Cake Pay", + "cake_pay_web_cards_subtitle": "Купуйте передоплачені та подарункові картки по всьому світу", + "cake_pay_web_cards_title": "Веб-картки Cake Pay", + "cake_wallet": "Cake Wallet", + "cakepay_prepaid_card": "Передплачена дебетова картка CakePay", + "camera_consent": "Ваша камера використовуватиметься для зйомки зображення з метою ідентифікації ${provider}. Будь ласка, ознайомтеся з їхньою політикою конфіденційності, щоб дізнатися більше.", + "camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.", + "cancel": "Відмінити", + "card_address": "Адреса:", + "cardholder_agreement": "Угода власника картки", + "cards": "Картки", + "chains": "Ланцюги", + "change": "Змінити", + "change_backup_password_alert": "Ваші попередні файли резервних копій будуть недоступні для імпорту з новим паролем резервної копії. Новий пароль резервної копії буде використовуватися тільки для нових файлів резервних копій. Ви впевнені, що хочете змінити пароль резервної копії?", + "change_currency": "Змінити валюту", + "change_current_node": "Ви впевнені, що хочете змінити поточний вузол на ${node}?", + "change_current_node_title": "Змінити поточний вузол", + "change_exchange_provider": "Змінити провайдера обміну", + "change_language": "Змінити мову", + "change_language_to": "Змінити мову на ${language}?", + "change_password": "Змінити пароль", "change_rep": "Зміна представника", "change_rep_message": "Ви впевнені, що хочете змінити представника?", - "unsupported_asset": "Ми не підтримуємо цю дію для цього ресурсу. Створіть або перейдіть на гаманець підтримуваного типу активів.", - "manage_pow_nodes": "Керуйте вузлами PoW", - "support_title_live_chat": "Жива підтримка", - "support_description_live_chat": "Безкоштовно і швидко! Навчені представники підтримки доступні для надання допомоги", - "support_title_guides": "Поклики для гаманців тортів", - "support_description_guides": "Документація та підтримка загальних питань", - "support_title_other_links": "Інші посилання на підтримку", - "support_description_other_links": "Приєднуйтесь до наших спільнот або досягайте нас нашими партнерами іншими методами", + "change_rep_successful": "Успішно змінив представник", + "change_wallet_alert_content": "Ви хочете змінити поточний гаманець на ${wallet_name}?", + "change_wallet_alert_title": "Змінити поточний гаманець", + "choose_account": "Оберіть акаунт", + "choose_address": "\n\nБудь ласка, оберіть адресу:", "choose_derivation": "Виберіть деривацію гаманця", - "new_first_wallet_text": "Легко зберігайте свою криптовалюту в безпеці", - "select_destination": "Виберіть місце призначення для файлу резервної копії.", - "save_to_downloads": "Зберегти до завантажень", - "select_buy_provider_notice": "Виберіть постачальника купівлі вище. Ви можете пропустити цей екран, встановивши свого постачальника купівлі за замовчуванням у налаштуваннях додатків.", - "onramper_option_description": "Швидко купуйте криптовалюту з багатьма методами оплати. Доступний у більшості країн. Поширення та збори різняться.", + "choose_from_available_options": "Виберіть із доступних варіантів:", + "choose_one": "Вибери один", + "choose_relay": "Будь ласка, виберіть реле для використання", + "choose_wallet_currency": "Будь ласка, виберіть валюту гаманця:", + "clear": "Очистити", + "clearnet_link": "Посилання Clearnet", + "close": "Закрити", + "coin_control": "Контроль монет (необов’язково)", + "cold_or_recover_wallet": "Додайте холодний гаманець або відновіть паперовий гаманець", + "color_theme": "Кольорова тема", + "commit_transaction_amount_fee": "Підтвердити транзакцію \nСума: ${amount}\nКомісія: ${fee}", + "confirm": "Підтвердити", + "confirm_delete_template": "Ця дія видалить шаблон. Ви хочете продовжити?", + "confirm_delete_wallet": "Ця дія видалить гаманець. Ви хочете продовжити?", + "confirm_sending": "Підтвердити відправлення", + "confirmations": "Підтвердження", + "confirmed": "Підтверджений баланс", + "confirmed_tx": "Підтверджений", + "congratulations": "Вітаємо!", + "connect_an_existing_yat": "Підключити існуючий Yat", + "connect_yats": "Підключіть Yats", + "connection_sync": "Підключення та синхронізація", + "connectWalletPrompt": "Підключіть свій гаманець до WalletConnect, щоб здійснювати транзакції", + "contact": "Контакт", + "contact_list_contacts": "Контакти", + "contact_list_wallets": "Мої гаманці", + "contact_name": "Ім'я контакту", + "contact_support": "Звернутися до служби підтримки", + "continue_text": "Продовжити", + "contractName": "Назва контракту", + "contractSymbol": "Контракт символ", + "copied_key_to_clipboard": "Скопійовано ${key} в буфер обміну", + "copied_to_clipboard": "Скопійовано в буфер обміну", + "copy": "Скопіювати", + "copy_address": "Cкопіювати адресу", + "copy_id": "Скопіювати ID", + "copyWalletConnectLink": "Скопіюйте посилання WalletConnect із dApp і вставте сюди", + "create_account": "Створити обліковий запис", + "create_backup": "Створити резервну копію", + "create_donation_link": "Створити посилання для пожертв", + "create_invoice": "Створити рахунок-фактуру", + "create_new": "Створити новий гаманець", + "create_new_account": "Створити новий акаунт", + "creating_new_wallet": "Створення нового гаманця", + "creating_new_wallet_error": "Помилка: ${description}", + "creation_date": "Дата створення", + "custom": "на замовлення", + "custom_drag": "На замовлення (утримуйте та перетягується)", + "custom_redeem_amount": "Власна сума викупу", + "dark_theme": "Темна", + "debit_card": "Дебетова картка", + "debit_card_terms": "Зберігання та використання номера вашої платіжної картки (та облікових даних, які відповідають номеру вашої платіжної картки) у цьому цифровому гаманці регулюються Умовами відповідної угоди власника картки з емітентом платіжної картки, що діє з час від часу.", + "decimal_places_error": "Забагато знаків після коми", "default_buy_provider": "Постачальник покупки за замовчуванням", - "ask_each_time": "Запитайте кожен раз", - "buy_provider_unavailable": "В даний час постачальник недоступний.", - "signTransaction": "Підписати транзакцію", + "default_sell_provider": "Постачальник продажу за замовчуванням", + "delete": "Видалити", + "delete_account": "Видалити обліковий запис", + "delete_wallet": "Видалити гаманець", + "delete_wallet_confirm_message": "Ви впевнені, що хочете видалити гаманець ${wallet_name}?", + "deleteConnectionConfirmationPrompt": "Ви впевнені, що хочете видалити з’єднання з", + "descending": "Низхідний", + "description": "опис", + "destination_tag": "Тег призначення:", + "dfx_option_description": "Купуйте криптовалюту за EUR і CHF. До 990 євро без додаткового KYC. Для роздрібних і корпоративних клієнтів у Європі", + "didnt_get_code": "Не отримуєте код?", + "digit_pin": "-значний PIN", + "digital_and_physical_card": " цифрова та фізична передплачена дебетова картка", + "disable": "Вимкнути", + "disable_buy": "Вимкнути дію покупки", + "disable_cake_2fa": "Вимкнути Cake 2FA", + "disable_exchange": "Вимкнути exchange", + "disable_fiat": "Вимкнути фиат", + "disable_sell": "Вимкнути дію продажу", + "disabled": "Вимкнено", + "discount": "Зекономте ${value}%", + "display_settings": "Налаштування дисплея", + "displayable": "Відображуваний", + "do_not_have_enough_gas_asset": "У вас недостатньо ${currency}, щоб здійснити трансакцію з поточними умовами мережі блокчейн. Вам потрібно більше ${currency}, щоб сплатити комісію мережі блокчейн, навіть якщо ви надсилаєте інший актив.", + "do_not_send": "Не надсилайте", + "do_not_share_warning_text": "Не діліться цим нікому, включно зі службою підтримки.\n\nВаші кошти можуть і будуть вкрадені!", + "do_not_show_me": "Не показуй мені це знову", + "domain_looks_up": "Пошук доменів", + "donation_link_details": "Деталі посилання для пожертв", + "e_sign_consent": "Згода електронного підпису", + "edit": "Редагувати", + "edit_backup_password": "Змінити пароль резервної копії", + "edit_node": "Редагувати вузол", + "edit_token": "Редагувати маркер", + "electrum_address_disclaimer": "Ми створюємо нові адреси щоразу, коли ви використовуєте їх, але попередні адреси продовжують працювати", + "email_address": "Адреса електронної пошти", + "enabled": "Увімкнено", + "enter_amount": "Введіть суму", + "enter_backup_password": "Введіть пароль резервної копії", + "enter_code": "Введіть код", + "enter_seed_phrase": "Введіть свою насіннєву фразу", + "enter_totp_code": "Будь ласка, введіть код TOTP.", + "enter_your_note": "Введіть примітку…", + "enter_your_pin": "Введіть ваш PIN", + "enter_your_pin_again": "Введіть PIN ще раз", + "enterTokenID": "Введіть ідентифікатор токена", + "enterWalletConnectURI": "Введіть URI WalletConnect", + "error": "Помилка", + "error_dialog_content": "На жаль, ми отримали помилку.\n\nБудь ласка, надішліть звіт про збій нашій команді підтримки, щоб покращити додаток.", + "error_text_account_name": "Ім'я акаунту може містити тільки букви, цифри\nі повинно бути від 1 до 15 символів в довжину", + "error_text_address": "Адреса гаманця повинна відповідати типу\nкриптовалюти", + "error_text_amount": "Баланс може містити тільки цифри", + "error_text_contact_name": "Ім'я контакту не може містити ` , ' \" символи\n і повинно бути від 1 до 32 символів в довжину", + "error_text_crypto_currency": "Кількість цифр після коми\nповинно бути меншим або дорівнювати 12", + "error_text_fiat": "Значення суми не може перевищувати доступний баланс.\nКількість цифр після коми повинно бути меншим або дорівнювати 2", + "error_text_input_above_maximum_limit": "Сума більше максимальної", + "error_text_input_below_minimum_limit": "Сума менша мінімальної", + "error_text_keys": "Ключі гаманця можуть містити тільки 64 символів в hex", + "error_text_limits_loading_failed": "Операція для ${provider} не створена. Помилка завантаження лімітів", + "error_text_maximum_limit": "Операція для ${provider} не створена. Сума більше максимальної: ${max} ${currency}", + "error_text_minimal_limit": "Операція для ${provider} не створена. Сума менша мінімальної: ${min} ${currency}", + "error_text_node_address": "Будь ласка, введіть iPv4 адресу", + "error_text_node_port": "Порт вузла може містити тільки цифри від 0 до 65535", + "error_text_node_proxy_address": "Будь ласка, введіть :<порт>, наприклад 127.0.0.1:9050", + "error_text_payment_id": "Ідентифікатор платежу може містити від 16 до 64 символів в hex", + "error_text_subaddress_name": "Ім'я субадреси не може містити ` , ' \" символи\nі може бути від 1 до 20 символів в довжину", + "error_text_template": "Ім'я та адреса шаблону не може містити ` , ' \" символи\nі може бути від 1 до 106 символів в довжину", + "error_text_wallet_name": "Ім'я гаманця може містити тільки букви, цифри, символи _ -\nі повинно бути від 1 до 33 символів в довжину", + "error_text_xmr": "Значення XMR не може перевищувати доступний баланс.\nКількість цифр після коми повинно бути меншим або дорівнювати 12", "errorGettingCredentials": "Помилка: помилка під час отримання облікових даних", "errorSigningTransaction": "Під час підписання транзакції сталася помилка", - "pairingInvalidEvent": "Недійсна подія сполучення", - "chains": "Ланцюги", - "methods": "методи", - "events": "Події", - "reject": "Відхиляти", - "approve": "Затвердити", - "expiresOn": "Термін дії закінчується", - "walletConnect": "WalletConnect", - "nullURIError": "URI нульовий", - "connectWalletPrompt": "Підключіть свій гаманець до WalletConnect, щоб здійснювати транзакції", - "newConnection": "Нове підключення", - "activeConnectionsPrompt": "Тут з’являться активні підключення", - "deleteConnectionConfirmationPrompt": "Ви впевнені, що хочете видалити з’єднання з", + "estimated": "Приблизно ", + "etherscan_history": "Історія Etherscan", "event": "Подія", - "successful": "Успішний", - "wouoldLikeToConnect": "хотів би підключитися", - "message": "повідомлення", - "do_not_have_enough_gas_asset": "У вас недостатньо ${currency}, щоб здійснити трансакцію з поточними умовами мережі блокчейн. Вам потрібно більше ${currency}, щоб сплатити комісію мережі блокчейн, навіть якщо ви надсилаєте інший актив.", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Зачекайте, доки dApp завершить обробку.", - "copyWalletConnectLink": "Скопіюйте посилання WalletConnect із dApp і вставте сюди", - "enterWalletConnectURI": "Введіть URI WalletConnect", - "seed_key": "Насіннєвий ключ", - "enter_seed_phrase": "Введіть свою насіннєву фразу", - "change_rep_successful": "Успішно змінив представник", - "add_contact": "Додати контакт", + "events": "Події", + "exchange": "Обмін", + "exchange_incorrect_current_wallet_for_xmr": "Якщо ви хочете обміняти XMR із вашого балансу Cake Wallet Monero, спочатку перейдіть на свій гаманець Monero.", + "exchange_new_template": "Новий шаблон", "exchange_provider_unsupported": "${providerName} більше не підтримується!", - "domain_looks_up": "Пошук доменів", - "require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці", - "camera_permission_is_required": "Потрібен дозвіл камери.\nУвімкніть його в налаштуваннях програми.", - "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу", - "order_by": "Сортувати за", - "creation_date": "Дата створення", + "exchange_result_confirm": "Натиснувши підтвердити, ви відправите ${fetchingLabel} ${from} з вашого гаманця ${walletName} на адресу вказану нижче. Або ви можете відправити зі свого зовнішнього гаманця на нижчевказану адресу/QR-код.\n\nБудь ласка, натисніть підтвердити для продовження або поверніться назад щоб змінити суму.", + "exchange_result_description": "Ви повинні надіслати мінімум ${fetchingLabel} ${from} на адресу, вказану на наступній сторінці. Якщо ви надішлете суму меншу за ${fetchingLabel} ${from}, то вона може бути не конвертованою і не поверненою.", + "exchange_result_write_down_ID": "*Будь ласка, скопіюйте або запишіть ID, вказаний вище.", + "exchange_result_write_down_trade_id": "Будь ласка, скопіюйте або запишіть ID операції.", + "exchange_sync_alert_content": "Зачекайте, поки ваш гаманець не синхронізується", + "expired": "Закінчується", + "expires": "Закінчується", + "expiresOn": "Термін дії закінчується", + "export_backup": "Експортувати резервну копію", + "extra_id": "Додатковий ID:", + "extracted_address_content": "Ви будете відправляти кошти\n${recipient_name}", + "failed_authentication": "Помилка аутентифікації. ${state_error}", + "faq": "FAQ", + "fetching": "Завантаження", + "fiat_api": "Фіат API", + "fiat_balance": "Фіат Баланс", + "field_required": "Це поле є обов'язковим", + "fill_code": "Будь ласка, введіть код підтвердження, надісланий на вашу електронну адресу", + "filter_by": "Фільтрувати по", + "first_wallet_text": "В самому зручному гаманці для Monero, Bitcoin, Ethereum, Litecoin, та Haven", + "fixed_pair_not_supported": "Ця фіксована пара не підтримується вибраними біржами", + "fixed_rate": "Фіксована ставка", + "fixed_rate_alert": "Ви зможете ввести суму отримання тоді, коли буде встановлений режим фіксованої ставки. Ви хочете перейти в режим фіксованої ставки?", + "forgot_password": "Забули пароль", + "freeze": "Заморозити", + "frequently_asked_questions": "Часті запитання", + "frozen": "Заморожено", + "full_balance": "Весь баланс", + "generate_name": "Згенерувати назву", + "generating_gift_card": "Створення подарункової картки", + "get_a": "Отримати ", + "get_card_note": " яку можна перезавантажувати цифровими валютами. Додаткова інформація не потрібна!", + "get_your_yat": "Одержати свій Yat", + "gift_card_amount": "Сума подарункової картки", + "gift_card_balance_note": "Тут з'являться подарункові картки із залишком на балансі", + "gift_card_is_generated": "Подарункова картка створена", + "gift_card_number": "Номер подарункової картки", + "gift_card_redeemed_note": "Подарункові картки, які ви активували, відображатимуться тут", + "gift_cards": "Подарункові карти", + "gift_cards_unavailable": "Наразі подарункові картки можна придбати лише через Monero, Bitcoin і Litecoin", + "got_it": "Зрозумів", + "gross_balance": "Валовий баланс", "group_by_type": "Група за типом", - "importNFTs": "Імпорт NFT", - "noNFTYet": "NFT ще немає", - "address": "Адреса", - "enterTokenID": "Введіть ідентифікатор токена", - "tokenID": "ID", - "name": "Ім'я", - "symbol": "символ", - "seed_phrase_length": "Довжина початкової фрази", - "unavailable_balance": "Недоступний баланс", - "unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.", - "unspent_change": "Зміна", - "tor_connection": "Підключення Tor", - "setup_warning_2fa_text": "Cake 2FA — друга аутентифікація для певних дій у гаманці. Це НЕ так безпечно, як холодне зберігання.\n\nЯкщо ви втратите доступ до своєї програми 2FA або ключів TOTP, ви втратите доступ до цього гаманця. Вам потрібно буде відновити свій гаманець з мнемоніки.\n\nСлужба підтримки Cake не зможе вам допомогти, якщо ви втратите доступ до 2FA або мнемонічних насадок.\nПеред використанням Cake 2FA рекомендуємо прочитати інструкцію.", - "scan_qr_on_device": "Відскануйте цей QR-код на іншому пристрої", + "haven_app": "Haven by Cake Wallet", + "haven_app_wallet_text": "Awesome wallet for Haven", + "help": "допомога", + "hidden_balance": "Прихований баланс", + "hide_details": "Приховати деталі", + "high_contrast_theme": "Тема високої контрастності", + "home_screen_settings": "Налаштування головного екрана", "how_to_use": "Як використовувати", + "how_to_use_card": "Як використовувати цю картку", + "id": "ID: ", + "ignor": "Ігнорувати", + "import": "Імпорт", + "importNFTs": "Імпорт NFT", + "in_store": "У магазині", + "incoming": "Вхідні", + "incorrect_seed": "Введений текст невірний.", + "introducing_cake_pay": "Представляємо Cake Pay!", + "invalid_input": "Неправильні дані", + "invoice_details": "Реквізити рахунку-фактури", + "is_percentage": "є", + "last_30_days": "Останні 30 днів", + "learn_more": "Дізнатися більше", + "light_theme": "Світла", + "loading_your_wallet": "Завантаження гаманця", + "login": "Логін", + "logout": "Вийти", + "low_fee": "Низька плата", + "low_fee_alert": "Зараз ви використовуєте низький пріоритет плати за мережу. Це може спричинити тривале очікування, інший курс або скасування угод. Ми рекомендуємо встановити вищу плату для кращого досвіду.", + "manage_nodes": "Керуйте вузлами", + "manage_pow_nodes": "Керуйте вузлами PoW", + "manage_yats": "Керувати Yat", + "mark_as_redeemed": "Позначити як погашене", + "market_place": "Ринок", + "matrix_green_dark_theme": "Зелена темна тема Matrix", + "max_amount": "Макс: ${value}", + "max_value": "Макс: ${value} ${currency}", + "memo": "Пам’ятка:", + "message": "повідомлення", + "methods": "методи", + "min_amount": "Мінімум: ${value}", + "min_value": "Мін: ${value} ${currency}", + "minutes_to_pin_code": "${minute} хвилин", + "mm": "MM", + "modify_2fa": "Змінити торт 2FA", + "monero_com": "Monero.com by Cake Wallet", + "monero_com_wallet_text": "Awesome wallet for Monero", + "monero_dark_theme": "Темна тема Monero", + "monero_light_theme": "Легка тема Monero", + "moonpay_alert_text": "Значення суми має бути більшим або дорівнювати ${minAmount} ${fiatCurrency}", + "more_options": "Більше параметрів", + "name": "Ім'я", + "narrow": "вузькі", + "new_first_wallet_text": "Легко зберігайте свою криптовалюту в безпеці", + "new_node_testing": "Тестування нового вузла", + "new_subaddress_create": "Створити", + "new_subaddress_label_name": "Ім'я", + "new_subaddress_title": "Нова адреса", + "new_template": "Новий шаблон", + "new_wallet": "Новий гаманець", + "newConnection": "Нове підключення", + "no_id_needed": "Ідентифікатор не потрібен!", + "no_id_required": "Ідентифікатор не потрібен. Поповнюйте та витрачайте будь-де", + "no_relay_on_domain": "Немає ретранслятора для домену користувача або ретранслятор недоступний. Будь ласка, виберіть реле для використання.", + "no_relays": "Без реле", + "no_relays_message": "Ми знайшли запис Nostr NIP-05 для цього користувача, але він не містить жодних реле. Будь ласка, попросіть одержувача додати реле до свого запису Nostr.", + "node_address": "Адреса вузла", + "node_connection_failed": "Помилка з’єднання", + "node_connection_successful": "З'єднання було успішним", + "node_new": "Новий вузол", + "node_port": "Порт вузла", + "node_reset_settings_title": "Скинути налаштування", + "node_test": "Тест", + "nodes": "Вузли", + "nodes_list_reset_to_default_message": "Ви впевнені, що хочете скинути до налаштувань за замовченням?", + "none_of_selected_providers_can_exchange": "Жоден із вибраних провайдерів не може здійснити цей обмін", + "noNFTYet": "NFT ще немає", + "normal": "нормальний", + "note_optional": "Примітка (необов’язково)", + "note_tap_to_change": "Примітка (натисніть для зміни)", + "nullURIError": "URI нульовий", + "offer_expires_in": "Пропозиція закінчиться через: ", + "offline": "Офлайн", + "ok": "OK", + "onion_link": "Посилання на цибулю", + "online": "Онлайн", + "onramper_option_description": "Швидко купуйте криптовалюту з багатьма методами оплати. Доступний у більшості країн. Поширення та збори різняться.", + "open_gift_card": "Відкрити подарункову картку", + "optional_description": "Додатковий опис", + "optional_email_hint": "Додаткова електронна адреса для сповіщення одержувача", + "optional_name": "Додаткове ім'я одержувача", + "optionally_order_card": "Необов'язково замовте фізичну картку.", + "orbot_running_alert": "Перед підключенням до цього вузла переконайтеся, що Orbot запущено.", + "order_by": "Сортувати за", + "order_id": "Ідентифікатор замовлення", + "order_physical_card": "Замовити фізичну картку", + "other_settings": "Інші налаштування", + "outdated_electrum_wallet_description": "Нові біткойн-гаманці, створені в Cake, тепер містять мнемонічну фразу з 24 слів. Обов’язково стовріть новий біткойн-гаманець, переведіть всі кошти на новий гаманець із 24 слів і припиніть використання гаманців із мнемонічною фразою з 12 слів. Зробіть це негайно, щоб убезпечити свої кошти.", + "outdated_electrum_wallet_receive_warning": "Якщо цей гаманець має мнемонічну фразу з 12 слів і був створений у Cake, НЕ переводьте біткойни на цей гаманець. Будь-які BTC, переведений на цей гаманець, можуть бути втраченими. Створіть новий гаманець з мнемонічною фразою з 24 слів (торкніться меню у верхньому правому куті, виберіть Гаманці, виберіть Створити новий гаманець, потім виберіть Bitcoin) і НЕГАЙНО переведіть туди свії BTC. Нові (з мнемонічною фразою з 24 слів) гаманці BTC від Cake надійно захищені", + "outgoing": "Вихідні", + "overwrite_amount": "Overwrite amount", + "pairingInvalidEvent": "Недійсна подія сполучення", + "password": "Пароль", + "paste": "Вставити", + "pause_wallet_creation": "Можливість створення гаманця Haven зараз призупинено.", + "payment_id": "ID платежу: ", + "payment_was_received": "Ваш платіж отримано.", + "pending": " (в очікуванні)", + "percentageOf": "${amount}", + "pin_at_top": "закріпити ${token} зверху", + "pin_is_incorrect": "Некоректний PIN", + "pin_number": "PIN-код", + "placeholder_contacts": "Тут будуть показані ваші контакти", + "placeholder_transactions": "Тут відображатимуться ваші транзакції", + "please_fill_totp": "Будь ласка, введіть 8-значний код, наявний на вашому іншому пристрої", + "please_make_selection": "Оберіть спосіб створення гаманця: створити новий чи відновити ваш існуючий.", + "please_reference_document": "Для отримання додаткової інформації зверніться до документів нижче.", + "please_select": "Будь ласка, виберіть:", + "please_select_backup_file": "Виберіть файл резервної копії та введіть пароль резервної копії.", + "please_try_to_connect_to_another_node": "Будь ласка, спробуйте підключитися до іншого вузлу", + "please_wait": "Будь ласка, зачекайте", + "polygonscan_history": "Історія PolygonScan", + "powered_by": "Використовуючи ${title}", + "pre_seed_button_text": "Зрозуміло. Покажіть мнемонічну фразу", + "pre_seed_description": "На наступній сторінці ви побачите серію з ${words} слів. Це ваша унікальна та приватна мнемонічна фраза, і це ЄДИНИЙ спосіб відновити ваш гаманець на випадок втрати або несправності. ВАМ необхідно записати її та зберігати в безпечному місці поза програмою Cake Wallet.", + "pre_seed_title": "ВАЖЛИВО", + "prevent_screenshots": "Запобігати знімкам екрана та запису екрана", + "privacy": "Конфіденційність", + "privacy_policy": "Політика конфіденційності", + "privacy_settings": "Налаштування конфіденційності", + "private_key": "Приватний ключ", + "proceed_after_one_minute": "Якщо екран не продовжується через 1 хвилину, перевірте свою електронну пошту.", + "profile": "Профіль", + "provider_error": "${provider} помилка", + "public_key": "Публічний ключ", + "purchase_gift_card": "Придбати подарункову картку", + "qr_fullscreen": "Торкніться, щоб відкрити QR-код на весь екран", + "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", + "question_to_disable_2fa": "Ви впевнені, що хочете вимкнути Cake 2FA? Код 2FA більше не потрібен для доступу до гаманця та певних функцій.", + "receivable_balance": "Баланс дебіторської заборгованості", + "receive": "Отримати", + "receive_amount": "Сума", + "received": "Отримані", + "recipient_address": "Адреса одержувача", + "reconnect": "Перепідключитися", + "reconnect_alert_text": "Ви хочете перепідключитися?", + "reconnection": "Перепідключення", + "redeeded": "Викуплено", + "refund_address": "Адреса повернення коштів", + "reject": "Відхиляти", + "remaining": "залишилося", + "remove": "Видалити", + "remove_node": "Видалити вузол", + "remove_node_message": "Ви впевнені, що хочете видалити поточний вузол?", + "rename": "Перейменувати", + "require_for_adding_contacts": "Потрібен для додавання контактів", + "require_for_all_security_and_backup_settings": "Вимагати всіх налаштувань безпеки та резервного копіювання", + "require_for_assessing_wallet": "Потрібен доступ до гаманця", + "require_for_creating_new_wallets": "Потрібно для створення нових гаманців", + "require_for_exchanges_to_external_wallets": "Потрібен для обміну на зовнішні гаманці", + "require_for_exchanges_to_internal_wallets": "Вимагати обміну на внутрішні гаманці", + "require_for_sends_to_contacts": "Вимагати для надсилання контактам", + "require_for_sends_to_internal_wallets": "Вимагати надсилання на внутрішні гаманці", + "require_for_sends_to_non_contacts": "Вимагати для надсилання неконтактним особам", + "require_pin_after": "Вимагати PIN після", + "rescan": "Пересканувати", + "resend_code": "Будь ласка, надішліть його повторно", + "reset": "Скинути", + "reset_password": "Скинути пароль", + "restore_active_seed": "Активна мнемонічна фраза", + "restore_address": "Адреса", + "restore_bitcoin_description_from_keys": "Ви можете відновити гаманець за допомогою WIF", + "restore_bitcoin_description_from_seed": "Ви можете відновити гаманець використовуючи 24-ти слівну мнемонічну фразу", + "restore_bitcoin_title_from_keys": "Відновити за допомогою WIF", + "restore_description_from_backup": "Ви можете відновити Cake Wallet з вашого резервного файлу", + "restore_description_from_keys": "Ви можете відновити гаманець за допомогою приватних ключів", + "restore_description_from_seed": "Ви можете відновити гаманець використовуючи 25-ти слівну мнемонічну фразу", + "restore_description_from_seed_keys": "Ви можете відновити гаманець з мнемонічної фрази/ключів, які ви зберегли раніше", + "restore_from_date_or_blockheight": "Будь ласка, введіть дату за кілька днів до створення цього гаманця. Або, якщо ви знаєте висоту блоку, введіть її значення", + "restore_from_seed_placeholder": "Введіть або вставте мнемонічну фразу вашого гаманця", + "restore_new_seed": "Нова мнемонічна фраза", + "restore_next": "Продовжити", + "restore_recover": "Відновити", + "restore_restore_wallet": "Відновити гаманець", + "restore_seed_keys_restore": "Відновити за допомогою мнемонічної фрази/ключів", + "restore_spend_key_private": "Приватний ключ витрати", + "restore_title_from_backup": "Відновити із резервного файлу", + "restore_title_from_keys": "Відновити за допомогою ключів", + "restore_title_from_seed": "Відновити з мнемонічної фрази", + "restore_title_from_seed_keys": "Відновити з мнемонічної фрази/ключів", + "restore_view_key_private": "Приватний ключ перегляду", + "restore_wallet": "Відновити гаманець", + "restore_wallet_name": "Ім'я гаманця", + "restore_wallet_restore_description": "Опис відновлюваного гаманця", + "router_no_route": "Не встановлено маршрут для ${name}", + "save": "Зберегти", + "save_backup_password": "Переконайтеся, що ви зберегли свій пароль резервної копії. Без нього ви не зможете імпортувати файли резервних копій.", + "save_backup_password_alert": "Зберегти пароль резервної копії", + "save_to_downloads": "Зберегти до завантажень", + "saved_the_trade_id": "Я зберіг ID операції", + "scan_qr_code": "Відскануйте QR-код", + "scan_qr_code_to_get_address": "Скануйте QR-код для одержання адреси", + "scan_qr_on_device": "Відскануйте цей QR-код на іншому пристрої", + "search": "Пошук", + "search_add_token": "Пошук / Додати маркер", + "search_category": "Категорія пошуку", + "search_currency": "Шукати валюту", + "search_language": "Мова пошуку", + "second_intro_content": "Ваш Yat - це єдина унікальна адреса емодзі, яка замінює довгі шістнадцятиричні адреси для всіх ваших валют.", + "second_intro_title": "Одна адреса емодзі для управління іншими адресами", + "security_and_backup": "Безпека та резервне копіювання", + "seed_alert_back": "Назад", + "seed_alert_content": "Мнемонічна фраза - єдиний спосіб відновити ваш гаманець. Ви записали її?", + "seed_alert_title": "Увага", + "seed_alert_yes": "Так", + "seed_choose": "Виберіть мову мнемонічної фрази", "seed_hex_form": "Насіння гаманця (шістнадцяткова форма)", + "seed_key": "Насіннєвий ключ", + "seed_language": "Насіннєва мова", + "seed_language_chinese": "Китайська", + "seed_language_chinese_traditional": "Китайський (традиційний)", + "seed_language_czech": "Чеський", + "seed_language_dutch": "Голландська", + "seed_language_english": "Англійська", + "seed_language_french": "французький", + "seed_language_german": "Німецька", + "seed_language_italian": "італійська", + "seed_language_japanese": "Японська", + "seed_language_korean": "Корейський", + "seed_language_next": "Продовжити", + "seed_language_portuguese": "Португальська", + "seed_language_russian": "Російська", + "seed_language_spanish": "Іспанська", + "seed_phrase_length": "Довжина початкової фрази", + "seed_reminder": "Будь ласка, запишіть мнемонічну фразу на випадок втрати або очищення телефону", + "seed_share": "Поділитися мнемонічною фразою", + "seed_title": "Мнемонічна фраза", "seedtype": "Насіннєвий тип", "seedtype_legacy": "Спадщина (25 слів)", "seedtype_polyseed": "Полісей (16 слів)", - "seed_language_czech": "Чеський", - "seed_language_korean": "Корейський", - "ascending": "Висхід", - "descending": "Низхідний", - "dfx_option_description": "Купуйте криптовалюту за EUR і CHF. До 990 євро без додаткового KYC. Для роздрібних і корпоративних клієнтів у Європі", - "seed_language_chinese_traditional": "Китайський (традиційний)", - "polygonscan_history": "Історія PolygonScan", - "wallet_seed_legacy": "Спадець насіння гаманця", - "default_sell_provider": "Постачальник продажу за замовчуванням", + "select_backup_file": "Виберіть файл резервної копії", + "select_buy_provider_notice": "Виберіть постачальника купівлі вище. Ви можете пропустити цей екран, встановивши свого постачальника купівлі за замовчуванням у налаштуваннях додатків.", + "select_destination": "Виберіть місце призначення для файлу резервної копії.", "select_sell_provider_notice": "Виберіть вище постачальника послуг продажу. Ви можете пропустити цей екран, встановивши постачальника послуг продажу за умовчанням у налаштуваннях програми.", - "custom_drag": "На замовлення (утримуйте та перетягується)", + "sell": "Продати", + "sell_alert_content": "Наразі ми підтримуємо лише продаж Bitcoin, Ethereum і Litecoin. Створіть або перейдіть на свій гаманець Bitcoin, Ethereum або Litecoin.", + "sell_monero_com_alert_content": "Продаж Monero ще не підтримується", + "send": "Відправити", + "send_address": "${cryptoCurrency} адреса", + "send_amount": "Сума:", + "send_creating_transaction": "Створити транзакцію", + "send_error_currency": "Валюта може містити тільки цифри", + "send_error_minimum_value": "Мінімальна сума 0.01", + "send_estimated_fee": "Ймовірна комісія:", + "send_fee": "Комісія:", + "send_name": "Ім'я", + "send_new": "Новий", + "send_payment_id": "ID платежу (опційно)", + "send_priority": "Комісія встановлена в залежності від пріоритету: ${transactionPriority}.\nПріоритет транзакції може бути змінений в налаштуваннях", + "send_sending": "Відправлення...", + "send_success": "Ваш ${crypto} успішно надісланий", + "send_templates": "Шаблони", + "send_title": "Відправити", + "send_to_this_address": "Надіслати ${currency} ${tag}на цю адресу", + "send_xmr": "Відправити XMR", + "send_your_wallet": "Ваш гаманець", + "sending": "Відправлення", + "sent": "Відправлені", + "settings": "Налаштування", + "settings_all": "ВСІ", + "settings_allow_biometrical_authentication": "Включити біометричну аутентифікацію", + "settings_can_be_changed_later": "Ці параметри можна змінити пізніше в налаштуваннях програми", + "settings_change_language": "Змінити мову", + "settings_change_pin": "Змінити PIN", + "settings_currency": "Валюта", + "settings_current_node": "Поточний вузол", + "settings_dark_mode": "Темний режим", + "settings_display_balance": "Відображати баланс", + "settings_display_on_dashboard_list": "Відображати в списку транзакцій", + "settings_fee_priority": "Пріоритет транзакції", + "settings_nodes": "Вузли", + "settings_none": "Нічого", + "settings_only_trades": "Операції", + "settings_only_transactions": "Транзакції", + "settings_personal": "Персональні", + "settings_save_recipient_address": "Зберігати адресу отримувача", + "settings_support": "Підтримка", + "settings_terms_and_conditions": "Умови та положення", + "settings_title": "Налаштування", + "settings_trades": "Операції", + "settings_transactions": "Транзакції", + "settings_wallets": "Гаманці", + "setup_2fa": "Налаштування Cake 2FA", + "setup_2fa_text": "Cake 2FA працює з використанням TOTP як другого фактора автентифікації.\n\nДля TOTP Cake 2FA потрібен SHA-512 і підтримка 8 цифр; це забезпечує підвищену безпеку. Додаткову інформацію та підтримувані програми можна знайти в посібнику.", + "setup_pin": "Встановити PIN", + "setup_successful": "PIN було успішно встановлено!", + "setup_totp_recommended": "Налаштувати TOTP", + "setup_warning_2fa_text": "Cake 2FA — друга аутентифікація для певних дій у гаманці. Це НЕ так безпечно, як холодне зберігання.\n\nЯкщо ви втратите доступ до своєї програми 2FA або ключів TOTP, ви втратите доступ до цього гаманця. Вам потрібно буде відновити свій гаманець з мнемоніки.\n\nСлужба підтримки Cake не зможе вам допомогти, якщо ви втратите доступ до 2FA або мнемонічних насадок.\nПеред використанням Cake 2FA рекомендуємо прочитати інструкцію.", + "setup_your_debit_card": "Налаштуйте свою дебетову картку", + "share": "Поділіться", + "share_address": "Поділитися адресою", + "show_details": "Показати деталі", + "show_keys": "Показати мнемонічну фразу/ключі", + "show_market_place": "Відображати маркетплейс", + "show_seed": "Показати мнемонічну фразу", + "sign_up": "Зареєструватися", + "signTransaction": "Підписати транзакцію", + "signup_for_card_accept_terms": "Зареєструйтеся на картку та прийміть умови.", + "slidable": "Розсувний", + "sort_by": "Сортувати за", + "spend_key_private": "Приватний ключ витрати", + "spend_key_public": "Публічний ключ витрати", + "status": "Статус: ", + "subaddress_title": "Список Субадрес", + "subaddresses": "Субадреси", + "submit_request": "надіслати запит", + "successful": "Успішний", + "support_description_guides": "Документація та підтримка загальних питань", + "support_description_live_chat": "Безкоштовно і швидко! Навчені представники підтримки доступні для надання допомоги", + "support_description_other_links": "Приєднуйтесь до наших спільнот або досягайте нас нашими партнерами іншими методами", + "support_title_guides": "Поклики для гаманців тортів", + "support_title_live_chat": "Жива підтримка", + "support_title_other_links": "Інші посилання на підтримку", + "sweeping_wallet": "Підмітаня гаманця", + "sweeping_wallet_alert": "Це не повинно зайняти багато часу. НЕ ЗАЛИШАЙТЕ ЦЬОГО ЕКРАНУ, АБО КОШТИ МОЖУТЬ БУТИ ВТРАЧЕНІ", + "switchToETHWallet": "Перейдіть на гаманець Ethereum і повторіть спробу", "switchToEVMCompatibleWallet": "Перейдіть на гаманець, сумісний з EVM, і повторіть спробу (Ethereum, Polygon)", - "receivable_balance": "Баланс дебіторської заборгованості", - "confirmed_tx": "Підтверджений", + "symbol": "символ", + "sync_all_wallets": "Синхронізувати всі гаманці", + "sync_status_attempting_sync": "СПРОБА СИНХРОНІЗАЦІЇ", + "sync_status_connected": "ПІДКЛЮЧЕНО", + "sync_status_connecting": "ПІДКЛЮЧЕННЯ", + "sync_status_failed_connect": "ВІДКЛЮЧЕНО", + "sync_status_not_connected": "НЕ ПІДКЛЮЧЕННИЙ", + "sync_status_starting_sync": "ПОЧАТОК СИНХРОНІЗАЦІЇ", + "sync_status_syncronized": "СИНХРОНІЗОВАНИЙ", + "sync_status_syncronizing": "СИНХРОНІЗАЦІЯ", + "syncing_wallet_alert_content": "Ваш баланс та список транзакцій може бути неповним, доки вгорі не буде написано «СИНХРОНІЗОВАНО». Натисніть/торкніться, щоб дізнатися більше.", + "syncing_wallet_alert_title": "Ваш гаманець синхронізується", + "template": "Шаблон", + "template_name": "Назва шаблону", + "third_intro_content": "Yat знаходиться за межами Cake Wallet. Будь-яку адресу гаманця на землі можна замінити на Yat!", + "third_intro_title": "Yat добре взаємодіє з іншими", + "time": "${minutes}хв ${seconds}сек", + "tip": "Порада:", + "today": "Сьогодні", + "token_contract_address": "Адреса договору маркера", + "token_decimal": "Токен десятковий", + "token_name": "Назва токена, наприклад: Tether", + "token_symbol": "Символ маркера, наприклад: USDT", + "tokenID": "ID", + "tor_connection": "Підключення Tor", + "tor_only": "Тільки Tor", + "total_saving": "Загальна економія", + "totp_2fa_failure": "Невірний код. Спробуйте інший код або створіть новий секретний ключ. Використовуйте сумісний додаток 2FA, який підтримує 8-значні коди та SHA512.", + "totp_2fa_success": "Успіх! Cake 2FA увімкнено для цього гаманця. Пам’ятайте про збереження мнемоніки на випадок, якщо ви втратите доступ до гаманця.", + "totp_auth_url": "TOTP AUTH URL", + "totp_code": "Код TOTP", + "totp_secret_code": "Секретний код TOTP", + "totp_verification_success": "Перевірка успішна!", + "trade_details_copied": "${title} скопійовано в буфер обміну", + "trade_details_created_at": "Створено", + "trade_details_fetching": "Отримання", + "trade_details_id": "ID", + "trade_details_pair": "Пара", + "trade_details_provider": "Провайдер", + "trade_details_state": "Статус", + "trade_details_title": "Деталі операцій", + "trade_for_not_created": "Операція для ${title} не створена.", + "trade_history_title": "Історія операцій", + "trade_id": "ID операції:", + "trade_id_not_found": "Операція ${tradeId} ${title} не знайдена.", + "trade_is_powered_by": "Операція виконана через ${provider}", + "trade_not_created": "Операція не створена", + "trade_not_found": "Операція не знайдена.", + "trade_state_btc_sent": "BTC надіслано", + "trade_state_complete": "Завершено", + "trade_state_confirming": "Підтвердження", + "trade_state_created": "Створена", + "trade_state_finished": "Завершена", + "trade_state_paid": "Оплачена", + "trade_state_paid_unconfirmed": "Оплата непідтверджена", + "trade_state_pending": "Очікування", + "trade_state_timeout": "Таймаут", + "trade_state_to_be_created": "Буде створена", + "trade_state_traded": "Операція виконана", + "trade_state_trading": "Виконання операції", + "trade_state_underpaid": "Недоплачена", + "trade_state_unpaid": "Неоплачена", + "trades": "Торгові операції", + "transaction_details_amount": "Сума", + "transaction_details_copied": "${title} скопійовано в буфер обміну", + "transaction_details_date": "Дата", + "transaction_details_fee": "Комісія", + "transaction_details_height": "Висота", + "transaction_details_recipient_address": "Адреси одержувачів", "transaction_details_source_address": "Адреса джерела", - "pause_wallet_creation": "Можливість створення гаманця Haven зараз призупинено.", - "contractName": "Назва контракту", - "contractSymbol": "Контракт символ", - "description": "опис", - "camera_consent": "Ваша камера використовуватиметься для зйомки зображення з метою ідентифікації ${provider}. Будь ласка, ознайомтеся з їхньою політикою конфіденційності, щоб дізнатися більше.", - "no_relays": "Без реле", - "choose_relay": "Будь ласка, виберіть реле для використання", - "no_relays_message": "Ми знайшли запис Nostr NIP-05 для цього користувача, але він не містить жодних реле. Будь ласка, попросіть одержувача додати реле до свого запису Nostr.", - "no_relay_on_domain": "Немає ретранслятора для домену користувача або ретранслятор недоступний. Будь ласка, виберіть реле для використання." -} + "transaction_details_title": "Деталі транзакції", + "transaction_details_transaction_id": "ID транзакції", + "transaction_key": "Ключ транзакції", + "transaction_priority_fast": "Швидкий", + "transaction_priority_fastest": "Найшвидший", + "transaction_priority_medium": "Середній", + "transaction_priority_regular": "Звичайний", + "transaction_priority_slow": "Повільний", + "transaction_sent": "Tранзакцію відправлено!", + "transaction_sent_notice": "Якщо екран не відображається через 1 хвилину, перевірте провідник блоків і свою електронну пошту.", + "transactions": "Транзакції", + "transactions_by_date": "Сортувати по даті", + "trusted": "довіряють", + "unavailable_balance": "Недоступний баланс", + "unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.", + "unconfirmed": "Непідтверджений баланс", + "understand": "Зрозуміло", + "unmatched_currencies": "Валюта вашого гаманця не збігається з валютою сканованого QR-коду", + "unspent_change": "Зміна", + "unspent_coins_details_title": "Відомості про невитрачені монети", + "unspent_coins_title": "Невитрачені монети", + "unsupported_asset": "Ми не підтримуємо цю дію для цього ресурсу. Створіть або перейдіть на гаманець підтримуваного типу активів.", + "upto": "до ${value}", + "use": "Використати ", + "use_card_info_three": "Використовуйте цифрову картку онлайн або за допомогою безконтактних методів оплати.", + "use_card_info_two": "Кошти конвертуються в долари США, якщо вони зберігаються на передплаченому рахунку, а не в цифрових валютах.", + "use_ssl": "Використати SSL", + "use_suggested": "Використати запропоноване", + "variable_pair_not_supported": "Ця пара змінних не підтримується вибраними біржами", + "verification": "Перевірка", + "verify_with_2fa": "Перевірте за допомогою Cake 2FA", + "version": "Версія ${currentVersion}", + "view_all": "Переглянути все", + "view_in_block_explorer": "View in Block Explorer", + "view_key_private": "Приватний ключ перегляду", + "view_key_public": "Публічний ключ перегляду", + "view_transaction_on": "View Transaction on ", + "wallet_keys": "Мнемонічна фраза/ключі гаманця", + "wallet_list_create_new_wallet": "Створити новий гаманець", + "wallet_list_edit_wallet": "Редагувати гаманець", + "wallet_list_failed_to_load": "Помилка при завантаженні ${wallet_name} гаманця. ${error}", + "wallet_list_failed_to_remove": "Помилка при видаленні ${wallet_name} гаманця. ${error}", + "wallet_list_load_wallet": "Завантаження гаманця", + "wallet_list_loading_wallet": "Завантаження ${wallet_name} гаманця", + "wallet_list_removing_wallet": "Видалення ${wallet_name} гаманця", + "wallet_list_restore_wallet": "Відновити гаманець", + "wallet_list_title": "Monero Гаманець", + "wallet_list_wallet_name": "Назва гаманця", + "wallet_menu": "Меню гаманця", + "wallet_name": "Ім'я гаманця", + "wallet_name_exists": "Гаманець з такою назвою вже існує", + "wallet_restoration_store_incorrect_seed_length": "Невірна довжина мнемонічної фрази", + "wallet_seed": "Мнемонічна фраза гаманця", + "wallet_seed_legacy": "Спадець насіння гаманця", + "wallet_store_monero_wallet": "Monero гаманець", + "walletConnect": "WalletConnect", + "wallets": "Гаманці", + "warning": "УВАГА", + "welcome": "Вітаємо в", + "welcome_to_cakepay": "Ласкаво просимо до Cake Pay!", + "widgets_address": "Адреса", + "widgets_or": "або", + "widgets_restore_from_blockheight": "Відновити на висоті блоку", + "widgets_restore_from_date": "Відновити з дати", + "widgets_seed": "Мнемонічна фраза", + "wouoldLikeToConnect": "хотів би підключитися", + "write_down_backup_password": "Запишіть пароль резервної копії, який використовується для імпорту файлів резервних копій.", + "xlm_extra_info": "Будь ласка, не забудьте вказати ідентифікатор пам'ятки під час надсилання транзакції XLM для обміну", + "xmr_available_balance": "Доступний баланс", + "xmr_full_balance": "Весь баланс", + "xmr_hidden": "Приховано", + "xmr_to_error": "Помилка XMR.TO", + "xmr_to_error_description": "Неприпустима сума. Максимум 8 цифр після десяткової коми", + "xrp_extra_info": "Будь ласка, не забудьте вказати тег призначення під час надсилання XRP-транзакції для обміну", + "yat": "Yat", + "yat_address": "Yat адреса", + "yat_alert_content": "Користувачі Cake Wallet тепер можуть надсилати та отримувати криптовалюту за допомогою унікального імені користувача на основі смайликів.", + "yat_alert_title": "За допомогою Yat легше надсилати та отримувати криптовалюту", + "yat_error": "Помилка Yat", + "yat_error_content": "Немає адрес, пов'язаних з цим Yat. Спробуйте інший Yat", + "yat_popup_content": "Тепер ви можете відправляти і отримувати криптовалюту в Cake Wallet за допомогою Yat - короткого імені користувача на основі емодзі. Керуйте Yat в будь-який час за допомогою екрану налаштувань", + "yat_popup_title": "Адреса вашого гаманця може бути пов'язаною з емодзі", + "yesterday": "Вчора", + "you_now_have_debit_card": "Тепер у вас є дебетова картка", + "you_pay": "Ви платите", + "you_will_get": "Конвертувати в", + "you_will_send": "Конвертувати з", + "yy": "YY", + "zzzz": "ZZZZ" +} \ No newline at end of file diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 11fc67c4e..713b676c4 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -1,771 +1,772 @@ { - "welcome": "میں خوش آمدید", - "cake_wallet": "Cake والیٹ", - "first_wallet_text": "Monero، Bitcoin، Ethereum، Litecoin، اور Haven کے لیے زبردست پرس", - "please_make_selection": "اپنا بٹوہ بنانے یا بازیافت کرنے کے لیے براہ کرم ذیل میں ایک انتخاب کریں۔", - "create_new": "نیا والیٹ بنائیں", - "restore_wallet": "والیٹ کو بحال کریں۔", - "monero_com": "Monero.com بذریعہ Cake والیٹ", - "monero_com_wallet_text": "Monero کے لئے بہت اچھا پرس", - "haven_app": "Haven از Cake والیٹ", - "haven_app_wallet_text": "Havek کے لیے زبردست پرس", - "accounts": "اکاؤنٹس", - "edit": "ترمیم", + "about_cake_pay": "Cake پے آپ کو ورچوئل اثاثوں کے ساتھ گفٹ کارڈز آسانی سے خریدنے کی اجازت دیتا ہے، جو ریاستہائے متحدہ میں 150,000 سے زیادہ تاجروں پر فوری طور پر خرچ کیے جا سکتے ہیں۔", "account": "کھاتہ", + "accounts": "اکاؤنٹس", + "accounts_subaddresses": "اکاؤنٹس اور ذیلی پتے", + "activate": "محرک کریں", + "active": "فعال", + "active_cards": "فعال کارڈز", + "activeConnectionsPrompt": "۔ﮯﮔ ﮞﻮﮨ ﺮﮨﺎﻇ ﮞﺎﮩﯾ ﺰﻨﺸﮑﻨﮐ ﻝﺎﻌﻓ", "add": "شامل کریں۔", + "add_contact": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮧﻄﺑﺍﺭ", + "add_custom_node": "نیا کسٹم نوڈ شامل کریں۔", + "add_custom_redemption": "حسب ضرورت چھٹکارا شامل کریں۔", + "add_fund_to_card": "کارڈز میں پری پیڈ فنڈز شامل کریں (${value} تک)", + "add_new_node": "نیا نوڈ شامل کریں۔", + "add_new_word": "نیا لفظ شامل کریں۔", + "add_receiver": "دوسرا وصول کنندہ شامل کریں (اختیاری)", + "add_secret_code": " ۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮟﯿﻣ ﭗﯾﺍ ﮦﺪﻨﻨﮐ ﻖﯾﺪﺼﺗ ﻮﮐ ﮈﻮﮐ ﮧﯿﻔﺧ ﺱﺍ ،ﺎﯾ", + "add_tip": "ٹپ شامل کریں۔", + "add_token_disclaimer_check": "میں نے ایک معتبر ذریعہ کا استعمال کرتے ہوئے ٹوکن کنٹریکٹ ایڈریس اور معلومات کی تصدیق کی ہے۔ بدنیتی پر مبنی یا غلط معلومات شامل کرنے کے نتیجے میں فنڈز ضائع ہو سکتے ہیں۔", + "add_token_warning": "سکیمرز کی ہدایت کے مطابق ٹوکن میں ترمیم یا اضافہ نہ کریں۔\nہمیشہ معتبر ذرائع سے ٹوکن پتوں کی تصدیق کریں!", + "add_value": "قدر شامل کریں۔", + "address": "ﮧﺘﭘ", "address_book": "ایڈریس بک", - "contact": "رابطہ کریں۔", - "please_select": "براہ مہربانی منتخب کریں:", - "cancel": "منسوخ کریں۔", - "ok": "ٹھیک ہے", - "contact_name": "رابطے کا نام", - "reset": "دوبارہ ترتیب دیں۔", - "save": "محفوظ کریں۔", + "address_book_menu": "ایڈریس بک", + "address_detected": "پتہ کا پتہ چلا", + "address_from_domain": "یہ پتہ نہ رکنے والے ڈومینز پر ${domain} کا ہے۔", + "address_from_yat": "یہ پتہ Yat پر ${emoji} کا ہے۔", + "address_label": "پتے کا خانہ", "address_remove_contact": "رابطہ ہٹا دیں۔", "address_remove_content": "کیا آپ واقعی منتخب رابطہ کو ہٹانا چاہتے ہیں؟", - "authenticated": "تصدیق شدہ", - "authentication": "تصدیق", - "failed_authentication": "ناکام تصدیق۔ ${state_error}", - "wallet_menu": "مینو", - "Blocks_remaining": "${status} بلاکس باقی ہیں۔", - "please_try_to_connect_to_another_node": "براہ کرم کسی دوسرے نوڈ سے جڑنے کی کوشش کریں۔", - "xmr_hidden": "پوشیدہ", - "xmr_available_balance": "دستیاب بیلنس", - "xmr_full_balance": "مکمل بیلنس", - "send": "بھیجیں", - "receive": "وصول کریں۔", - "transactions": "لین دین", - "incoming": "آنے والا", - "outgoing": "سبکدوش ہونے والے", - "transactions_by_date": "تاریخ کے لحاظ سے لین دین", - "trades": "تجارت", - "filter_by": "کی طرف سے فلٹر", - "today": "آج", - "yesterday": "کل", - "received": "موصول ہوا۔", - "sent": "بھیجا", - "pending": " (زیر التواء)", - "rescan": "دوبارہ اسکین کریں۔", - "reconnect": "دوبارہ جڑیں۔", - "wallets": "بٹوے", - "show_seed": "بیج دکھائیں۔", - "show_keys": "بیج / چابیاں دکھائیں۔", - "address_book_menu": "ایڈریس بک", - "reconnection": "دوبارہ رابطہ", - "reconnect_alert_text": "کیا آپ واقعی دوبارہ جڑنا چاہتے ہیں؟", - "exchange": "تبادلہ", - "clear": "صاف", - "refund_address": "رقم کی واپسی کا پتہ", - "change_exchange_provider": "ایکسچینج فراہم کنندہ کو تبدیل کریں۔", - "you_will_send": "سے تبدیل کریں۔", - "you_will_get": "میں تبدیل کریں۔", - "amount_is_guaranteed": "وصول شدہ رقم کی ضمانت ہے۔", - "amount_is_estimate": "وصول شدہ رقم ایک تخمینہ ہے۔", - "powered_by": "${title} کے ذریعے تقویت یافتہ", - "error": "خرابی", - "estimated": "تخمینہ لگایا", - "min_value": "کم سے کم: ${value} ${currency}", - "max_value": "زیادہ سے زیادہ: ${value} ${currency}", - "change_currency": "کرنسی تبدیل کریں", - "overwrite_amount": "رقم کو اوور رائٹ کریں۔", - "qr_payment_amount": "اس QR کوڈ میں ادائیگی کی رقم شامل ہے۔ کیا آپ موجودہ قدر کو اوور رائٹ کرنا چاہتے ہیں؟", - "copy_id": "کاپی ID", - "exchange_result_write_down_trade_id": "جاری رکھنے کے لیے براہ کرم تجارتی ID کاپی کریں یا لکھیں۔", - "trade_id": "تجارتی ID:", - "copied_to_clipboard": "کلپ بورڈ پر کاپی کیا گیا۔", - "saved_the_trade_id": "میں نے تجارتی ID محفوظ کر لی ہے۔", - "fetching": "لا رہا ہے۔", - "id": "ID:", - "amount": "رقم کی رقم:", - "payment_id": "ادائیگی کی شناخت:", - "status": "حالت:", - "offer_expires_in": "پیشکش کی میعاد اس وقت ختم ہو جاتی ہے:", - "trade_is_powered_by": "یہ تجارت ${provider} کے ذریعے تقویت یافتہ ہے", - "copy_address": "ایڈریس کاپی کریں۔", - "exchange_result_confirm": "تصدیق کو دبانے سے، آپ اپنے بٹوے سے ${fetchingLabel} ${from} بھیجیں گے جسے ${walletName} کہتے ہیں نیچے دکھائے گئے پتے پر۔ یا آپ اپنے بیرونی والیٹ سے نیچے دیئے گئے پتے/QR کوڈ پر بھیج سکتے ہیں۔\\n\\nجاری رکھنے کے لیے براہ کرم تصدیق کو دبائیں یا رقم تبدیل کرنے کے لیے واپس جائیں۔", - "exchange_result_description": "آپ کو اگلے صفحہ پر دکھائے گئے پتے پر کم از کم ${fetchingLabel} ${from} بھیجنا ہوگا۔ اگر آپ ${fetchingLabel} ${from} سے کم رقم بھیجتے ہیں تو یہ تبدیل نہیں ہوسکتی ہے اور اسے واپس نہیں کیا جاسکتا ہے۔", - "exchange_result_write_down_ID": "*براہ کرم اوپر دکھائی گئی اپنی ID کاپی کریں یا لکھیں۔", - "confirm": "تصدیق کریں۔", - "confirm_sending": "بھیجنے کی تصدیق کریں۔", - "commit_transaction_amount_fee": "لین دین کا ارتکاب کریں\\nرقم: ${amount}\\nفیس: ${fee}", - "sending": "بھیج رہا ہے۔", - "transaction_sent": "لین دین بھیجا گیا!", - "expired": "میعاد ختم", - "time": "${minutes}m ${seconds}s", - "send_xmr": "XMR بھیجیں۔", - "exchange_new_template": "نیا سانچہ", - "faq": "عمومی سوالات", - "enter_your_pin": "اپنا PIN درج کریں۔", - "loading_your_wallet": "آپ کا بٹوہ لوڈ ہو رہا ہے۔", - "new_wallet": "نیا پرس", - "wallet_name": "بٹوے کا نام", - "continue_text": "جاری رہے", - "choose_wallet_currency": "براہ کرم والیٹ کرنسی کا انتخاب کریں:", - "node_new": "نیا نوڈ", - "node_address": "نوڈ ایڈریس", - "node_port": "نوڈ پورٹ", - "login": "لاگ ان کریں", - "password": "پاس ورڈ", - "nodes": "نوڈس", - "node_reset_settings_title": "ترتیبات کو دوبارہ ترتیب دیں۔", - "nodes_list_reset_to_default_message": "کیا آپ واقعی ترتیبات کو ڈیفالٹ پر دوبارہ ترتیب دینا چاہتے ہیں؟", - "change_current_node": "کیا آپ یقینی طور پر موجودہ نوڈ کو ${node} میں تبدیل کرنا چاہتے ہیں؟", - "change": "تبدیلی", - "remove_node": "نوڈ کو ہٹا دیں۔", - "remove_node_message": "کیا آپ واقعی منتخب نوڈ کو ہٹانا چاہتے ہیں؟", - "remove": "دور", - "delete": "حذف کریں۔", - "add_new_node": "نیا نوڈ شامل کریں۔", - "change_current_node_title": "موجودہ نوڈ کو تبدیل کریں۔", - "node_test": "پرکھ", - "node_connection_successful": "کنکشن کامیاب رہا۔", - "node_connection_failed": "کنکشن ناکام ہو گیا تھا۔", - "new_node_testing": "نیا نوڈ ٹیسٹنگ", - "use": "تبدیل کرنا", - "digit_pin": "-ہندسوں کا پن", - "share_address": "پتہ شیئر کریں۔", - "receive_amount": "رقم", - "subaddresses": "ذیلی پتے", "addresses": "پتے", - "scan_qr_code": "پتہ حاصل کرنے کے لیے QR کوڈ اسکین کریں۔", - "qr_fullscreen": "فل سکرین QR کوڈ کھولنے کے لیے تھپتھپائیں۔", - "rename": "نام تبدیل کریں۔", - "choose_account": "اکاؤنٹ کا انتخاب کریں۔", - "create_new_account": "نیا اکاؤنٹ بنانے", - "accounts_subaddresses": "اکاؤنٹس اور ذیلی پتے", - "restore_restore_wallet": "والیٹ کو بحال کریں۔", - "restore_title_from_seed_keys": "بیج / چابیاں سے بحال کریں۔", - "restore_description_from_seed_keys": "اپنے بٹوے کو بیج / چابیاں سے واپس حاصل کریں جنہیں آپ نے محفوظ جگہ پر محفوظ کیا ہے۔", - "restore_next": "اگلے", - "restore_title_from_backup": "بیک اپ سے بحال کریں۔", - "restore_description_from_backup": "آپ اپنی بیک اپ فائل سے پوری کیک والیٹ ایپ کو بحال کر سکتے ہیں۔", - "restore_seed_keys_restore": "بیج/کیز کی بحالی", - "restore_title_from_seed": "بیج سے بحال کریں۔", - "restore_description_from_seed": "اپنے بٹوے کو 25 لفظ یا 13 الفاظ کے مجموعہ کوڈ سے بحال کریں۔", - "restore_title_from_keys": "چابیاں سے بحال کریں۔", - "restore_description_from_keys": "اپنے بٹوے کو اپنی نجی کلیدوں سے محفوظ کردہ کی اسٹروکس سے بحال کریں۔", - "restore_wallet_name": "بٹوے کا نام", - "restore_address": "پتہ", - "restore_view_key_private": "کلید دیکھیں (نجی)", - "restore_spend_key_private": "خرچ کی کلید (نجی)", - "restore_recover": "بحال کریں۔", - "restore_wallet_restore_description": "والیٹ کی بحالی کی تفصیل", - "restore_new_seed": "نیا بیج", - "restore_active_seed": "فعال بیج", - "restore_bitcoin_description_from_seed": "24 الفاظ کے مجموعہ کوڈ سے اپنے بٹوے کو بحال کریں۔", - "restore_bitcoin_description_from_keys": "اپنی نجی کلیدوں سے تیار کردہ WIF سٹرنگ سے اپنے بٹوے کو بحال کریں۔", - "restore_bitcoin_title_from_keys": "WIF سے بحال کریں۔", - "restore_from_date_or_blockheight": "براہ کرم یہ پرس بنانے سے چند دن پہلے کی تاریخ درج کریں۔ یا اگر آپ کو بلاک ہائیٹ معلوم ہے تو براہ کرم اس کی بجائے اسے درج کریں۔", - "seed_reminder": "اگر آپ اپنا فون کھو دیتے ہیں یا صاف کرتے ہیں تو براہ کرم یہ لکھ دیں۔", - "seed_title": "بیج", - "seed_share": "بیج بانٹیں۔", - "copy": "کاپی", - "seed_language": "بیج کی زبان", - "seed_choose": "بیج کی زبان کا انتخاب کریں۔", - "seed_language_next": "اگلے", - "seed_language_english": "انگریزی", - "seed_language_chinese": "چینی", - "seed_language_dutch": "ڈچ", - "seed_language_german": "جرمن", - "seed_language_japanese": "جاپانی", - "seed_language_portuguese": "پرتگالی", - "seed_language_russian": "روسی", - "seed_language_spanish": "ہسپانوی", - "seed_language_french": "فرانسیسی", - "seed_language_italian": "اطالوی", - "send_title": "بھیجیں", - "send_your_wallet": "آپ کا بٹوہ", - "send_address": "${cryptoCurrency} پتہ", - "send_payment_id": "ادائیگی کی شناخت (اختیاری)", + "advanced_settings": "اعلی درجے کی ترتیبات", + "aggressive": "حد سے زیادہ پرجوش", + "agree": "متفق", + "agree_and_continue": "اتفاق کریں اور جاری رکھیں", + "agree_to": "اکاؤنٹ بنا کر آپ اس سے اتفاق کرتے ہیں۔", "all": "تمام", - "send_error_minimum_value": "رقم کی کم از کم قیمت 0.01 ہے۔", - "send_error_currency": "کرنسی صرف نمبروں پر مشتمل ہو سکتی ہے۔", - "send_estimated_fee": "تخمینی فیس:", - "send_priority": "فی الحال فیس ${transactionPriority} کی ترجیح پر سیٹ ہے۔\\nٹرانزیکشن کی ترجیح سیٹنگز میں ایڈجسٹ کی جا سکتی ہے۔", - "send_creating_transaction": "لین دین کی تخلیق", - "send_templates": "ٹیمپلیٹس", - "send_new": "نئی", - "send_amount": "رقم:", - "send_fee": "فیس:", - "send_name": "نام", - "got_it": "یہ مل گیا", - "send_sending": "بھیج رہا ہے...", - "send_success": "آپ کا ${crypto} کامیابی کے ساتھ بھیج دیا گیا۔", - "settings_title": "ترتیبات", - "settings_nodes": "نوڈس", - "settings_current_node": "موجودہ نوڈ", - "settings_wallets": "بٹوے", - "settings_display_balance": "ڈسپلے بیلنس", - "settings_currency": "کرنسی", - "settings_fee_priority": "فیس کی ترجیح", - "settings_save_recipient_address": "وصول کنندہ کا پتہ محفوظ کریں۔", - "settings_personal": "ذاتی", - "settings_change_pin": "پن تبدیل کریں۔", - "settings_change_language": "زبان تبدیل کریں", - "settings_allow_biometrical_authentication": "بایومیٹریکل تصدیق کی اجازت دیں۔", - "settings_dark_mode": "ڈارک موڈ", - "settings_transactions": "لین دین", - "settings_trades": "تجارت", - "settings_display_on_dashboard_list": "ڈیش بورڈ کی فہرست پر ڈسپلے کریں۔", - "settings_all": "تمام", - "settings_only_trades": "صرف تجارت", - "settings_only_transactions": "صرف لین دین", - "settings_none": "کوئی نہیں۔", - "settings_support": "حمایت", - "settings_terms_and_conditions": "شرائط و ضوابط", - "pin_is_incorrect": "PIN غلط ہے۔", - "setup_pin": "PIN سیٹ اپ کریں۔", - "enter_your_pin_again": "اپنا پن دوبارہ درج کریں۔", - "setup_successful": "آپ کا PIN کامیابی کے ساتھ ترتیب دیا گیا ہے!", - "wallet_keys": "بٹوے کے بیج / چابیاں", - "wallet_seed": "بٹوے کا بیج", - "private_key": "نجی کلید", - "public_key": "عوامی کلید", - "view_key_private": "کلید دیکھیں (نجی)", - "view_key_public": "کلید دیکھیں (عوامی)", - "spend_key_private": "خرچ کی کلید (نجی)", - "spend_key_public": "خرچ کی کلید (عوامی)", - "copied_key_to_clipboard": "${key} کو کلپ بورڈ پر کاپی کیا گیا۔", - "new_subaddress_title": "نیا پتہ", - "new_subaddress_label_name": "لیبل کا نام", - "new_subaddress_create": "بنانا", - "address_label": "پتے کا خانہ", - "subaddress_title": "ذیلی ایڈریس کی فہرست", - "trade_details_title": "تجارت کی تفصیلات", - "trade_details_id": "ID", - "trade_details_state": "حالت", - "trade_details_fetching": "لا رہا ہے۔", - "trade_details_provider": "فراہم کرنے والا", - "trade_details_created_at": "پر تخلیق کیا گیا۔", - "trade_details_pair": "جوڑا", - "trade_details_copied": "${title} کو کلپ بورڈ پر کاپی کیا گیا۔", - "trade_history_title": "تجارتی تاریخ", - "transaction_details_title": "لین دین کی تفصیلات", - "transaction_details_transaction_id": "ٹرانزیکشن ID", - "transaction_details_date": "تاریخ", - "transaction_details_height": "اونچائی", - "transaction_details_amount": "رقم", - "transaction_details_fee": "فیس", - "transaction_details_copied": "${title} کو کلپ بورڈ پر کاپی کیا گیا۔", - "transaction_details_recipient_address": "وصول کنندگان کے پتے", - "wallet_list_title": "Monero والیٹ", - "wallet_list_create_new_wallet": "نیا والیٹ بنائیں", - "wallet_list_edit_wallet": "بٹوے میں ترمیم کریں۔", - "wallet_list_wallet_name": "بٹوے کا نام", - "wallet_list_restore_wallet": "والیٹ کو بحال کریں۔", - "wallet_list_load_wallet": "پرس لوڈ کریں۔", - "wallet_list_loading_wallet": "${wallet_name} والیٹ لوڈ ہو رہا ہے۔", - "wallet_list_failed_to_load": "${wallet_name} والیٹ لوڈ کرنے میں ناکام۔ ${error}", - "wallet_list_removing_wallet": "${wallet_name} والیٹ کو ہٹایا جا رہا ہے۔", - "wallet_list_failed_to_remove": "${wallet_name} والیٹ کو ہٹانے میں ناکام۔ ${error}", - "widgets_address": "پتہ", - "widgets_restore_from_blockheight": "بلاک ہائیٹ سے بحال کریں۔", - "widgets_restore_from_date": "تاریخ سے بحال کریں۔", - "widgets_or": "یا", - "widgets_seed": "بیج", - "router_no_route": "${name} کے لیے کوئی راستہ متعین نہیں ہے", - "error_text_account_name": "اکاؤنٹ کا نام صرف حروف، اعداد پر مشتمل ہو سکتا ہے\\nاور 1 سے 15 حروف کے درمیان ہونا چاہیے۔", - "error_text_contact_name": "رابطہ کے نام میں ` , \\' \" علامات\\nنہیں ہو سکتے اور 1 سے 32 حروف کے درمیان ہونا چاہیے", - "error_text_address": "والیٹ کا پتہ cryptocurrency کی قسم\\nکے مطابق ہونا چاہیے۔", - "error_text_node_address": "براہ کرم ایک iPv4 پتہ درج کریں۔", - "error_text_node_port": "نوڈ پورٹ میں صرف 0 اور 65535 کے درمیان نمبر ہوسکتے ہیں۔", - "error_text_node_proxy_address": "براہ کرم : درج کریں، مثال کے طور پر 127.0.0.1:9050", - "error_text_payment_id": "ادائیگی کی ID ہیکس میں صرف 16 سے 64 حروف پر مشتمل ہو سکتی ہے۔", - "error_text_xmr": "XMR قدر دستیاب بیلنس سے زیادہ نہیں ہو سکتی۔\\nفرکشن ہندسوں کی تعداد 12 سے کم یا اس کے برابر ہونی چاہیے۔", - "error_text_fiat": "رقم کی قدر دستیاب بیلنس سے زیادہ نہیں ہو سکتی۔\\nفرکشن ہندسوں کی تعداد 2 کے برابر یا کم ہونی چاہیے۔", - "error_text_subaddress_name": "ذیلی پتے کے نام میں ` , \\ ' \" علامتیں نہیں ہو سکتی ہیں اور 1 اور 20 حروف کے درمیان ہونی چاہئیں", - "error_text_amount": "رقم صرف اعداد پر مشتمل ہو سکتی ہے۔", - "error_text_wallet_name": "والیٹ کے نام میں صرف حروف، اعداد، _ - علامتیں\\nاور 1 سے 33 حروف کے درمیان ہونی چاہئیں", - "error_text_keys": "والیٹ کیز ہیکس میں صرف 64 حروف پر مشتمل ہو سکتی ہیں۔", - "error_text_crypto_currency": "کسر ہندسوں کی تعداد\\n12 سے کم یا مساوی ہونی چاہیے۔", - "error_text_minimal_limit": "${provider} کے لیے تجارت نہیں بنائی گئی ہے۔ رقم کم سے کم ہے: ${min} ${currency}", - "error_text_maximum_limit": "${provider} کے لیے تجارت نہیں بنائی گئی ہے۔ رقم زیادہ سے زیادہ سے زیادہ ہے: ${max} ${currency}", - "error_text_limits_loading_failed": "${provider} کے لیے تجارت نہیں بنائی گئی ہے۔ حدود کی لوڈنگ ناکام ہو گئی۔", - "error_text_template": "ٹیمپلیٹ کا نام اور پتہ `` , \\' \" علامتوں پر مشتمل نہیں ہو سکتا ہے اور 1 اور 106 حروف کے درمیان ہونا چاہیے", + "all_trades": "تمام تجارت", + "all_transactions": "تمام لین دین", + "alphabetical": "حروف تہجی کے مطابق", + "already_have_account": "پہلے سے ہی اکاؤنٹ ہے؟", + "always": "ہمیشہ", + "amount": "رقم کی رقم:", + "amount_is_estimate": "وصول شدہ رقم ایک تخمینہ ہے۔", + "amount_is_guaranteed": "وصول شدہ رقم کی ضمانت ہے۔", + "and": "اور", + "anonpay_description": "${type} بنائیں۔ وصول کنندہ کسی بھی تعاون یافتہ کرپٹو کرنسی کے ساتھ ${method} کرسکتا ہے، اور آپ کو اس بٹوے میں فنڈز موصول ہوں گے۔", + "apk_update": "APK اپ ڈیٹ", + "approve": "ﻭﺮﮐ ﺭﻮﻈﻨﻣ", + "arrive_in_this_address": "${currency} ${tag}اس پتے پر پہنچے گا۔", + "ascending": "چڑھنے", + "ask_each_time": "ہر بار پوچھیں", "auth_store_ban_timeout": "پابندی_وقت ختم", "auth_store_banned_for": "کے لیے پابندی لگا دی گئی۔", "auth_store_banned_minutes": " منٹ", "auth_store_incorrect_password": "غلط PIN", - "wallet_store_monero_wallet": "مونیرو والیٹ", - "wallet_restoration_store_incorrect_seed_length": "غلط بیج کی لمبائی", - "full_balance": "مکمل بیلنس", - "available_balance": "دستیاب بیلنس", - "hidden_balance": "پوشیدہ بیلنس", - "sync_status_syncronizing": "مطابقت پذیری", - "sync_status_syncronized": "مطابقت پذیر", - "sync_status_not_connected": "منسلک نہیں", - "sync_status_starting_sync": "مطابقت پذیری شروع کر رہا ہے۔", - "sync_status_failed_connect": "منقطع", - "sync_status_connecting": "جڑ رہا ہے۔", - "sync_status_connected": "منسلک", - "sync_status_attempting_sync": "ہم آہنگی کی کوشش کر رہا ہے۔", - "transaction_priority_slow": "سست", - "transaction_priority_regular": "باقاعدہ", - "transaction_priority_medium": "درمیانہ", - "transaction_priority_fast": "تیز", - "transaction_priority_fastest": "تیز ترین", - "trade_for_not_created": "${title} کے لیے تجارت نہیں بنائی گئی ہے۔", - "trade_not_created": "تجارت پیدا نہیں ہوئی۔", - "trade_id_not_found": "ٹریڈ ${tradeId} از ${title} نہیں ملا۔", - "trade_not_found": "تجارت نہیں ملی۔", - "trade_state_pending": "زیر التواء", - "trade_state_confirming": "تصدیق کر رہا ہے۔", - "trade_state_trading": "تجارت", - "trade_state_traded": "تجارت کی۔", - "trade_state_complete": "مکمل", - "trade_state_to_be_created": "پیدا کیا جائے۔", - "trade_state_unpaid": "بلا معاوضہ", - "trade_state_underpaid": "کم معاوضہ", - "trade_state_paid_unconfirmed": "غیر تصدیق شدہ ادائیگی", - "trade_state_paid": "ادا کیا", - "trade_state_btc_sent": "Btc بھیجا گیا۔", - "trade_state_timeout": "وقت ختم", - "trade_state_created": "بنایا", - "trade_state_finished": "ختم", - "change_language": "زبان تبدیل کریں", - "change_language_to": "زبان کو ${language} میں تبدیل کریں؟", - "paste": "چسپاں کریں۔", - "restore_from_seed_placeholder": "براہ کرم اپنا بیج یہاں درج کریں یا پیسٹ کریں۔", - "add_new_word": "نیا لفظ شامل کریں۔", - "incorrect_seed": "درج کردہ متن درست نہیں ہے۔", - "biometric_auth_reason": "تصدیق کرنے کے لیے اپنے فنگر پرنٹ کو اسکین کریں۔", - "version": "ورژن ${currentVersion}", - "openalias_alert_title": "پتہ کا پتہ چلا", - "openalias_alert_content": "آپ کو فنڈز بھیجیں گے\\n${recipient_name}", - "card_address": "پتہ:", - "buy": "خریدنے", - "sell": "بیچنا", - "placeholder_transactions": "آپ کے لین دین یہاں دکھائے جائیں گے۔", - "placeholder_contacts": "آپ کے رابطے یہاں دکھائے جائیں گے۔", - "template": "سانچے", - "confirm_delete_template": "یہ عمل اس ٹیمپلیٹ کو حذف کر دے گا۔ کیا آپ جاری رکھنا چاہتے ہیں؟", - "confirm_delete_wallet": "اس کارروائی سے یہ پرس حذف ہو جائے گا۔ کیا آپ جاری رکھنا چاہتے ہیں؟", - "change_wallet_alert_title": "موجودہ پرس تبدیل کریں۔", - "change_wallet_alert_content": "کیا آپ موجودہ والیٹ کو ${wallet_name} میں تبدیل کرنا چاہتے ہیں؟", - "creating_new_wallet": "نیا پرس بنانا", - "creating_new_wallet_error": "خرابی: ${description}", - "seed_alert_title": "توجہ", - "seed_alert_content": "بیج آپ کے بٹوے کو بازیافت کرنے کا واحد طریقہ ہے۔ کیا آپ نے اسے لکھا ہے؟", - "seed_alert_back": "واپس جاو", - "seed_alert_yes": "ہاں میرے پاس ہے", - "exchange_sync_alert_content": "براہ کرم اس وقت تک انتظار کریں جب تک آپ کا بٹوہ مطابقت پذیر نہ ہو جائے۔", - "pre_seed_title": "اہم", - "pre_seed_description": "اگلے صفحے پر آپ کو ${words} الفاظ کا ایک سلسلہ نظر آئے گا۔ یہ آپ کا انوکھا اور نجی بیج ہے اور یہ آپ کے بٹوے کو ضائع یا خرابی کی صورت میں بازیافت کرنے کا واحد طریقہ ہے۔ اسے لکھنا اور اسے کیک والیٹ ایپ سے باہر کسی محفوظ جگہ پر اسٹور کرنا آپ کی ذمہ داری ہے۔", - "pre_seed_button_text": "میں سمجھتا ہوں۔ مجھے میرا بیج دکھاؤ", - "xmr_to_error": "XMR.TO غلطی", - "xmr_to_error_description": "غلط رقم۔ اعشاریہ پوائنٹ کے بعد زیادہ سے زیادہ 8 ہندسے", - "provider_error": "${provider} خرابی۔", - "use_ssl": "SSL استعمال کریں۔", - "trusted": "قابل اعتماد", - "color_theme": "رنگین تھیم", - "light_theme": "روشنی", - "bright_theme": "روشن", - "dark_theme": "اندھیرا", - "enter_your_note": "اپنا نوٹ درج کریں…", - "note_optional": "نوٹ (اختیاری)", - "note_tap_to_change": "نوٹ (تبدیل کرنے کے لیے تھپتھپائیں)", - "view_in_block_explorer": "بلاک ایکسپلورر میں دیکھیں", - "view_transaction_on": "لین دین دیکھیں آن", - "transaction_key": "لین دین کی کلید", - "confirmations": "تصدیقات", - "recipient_address": "وصول کنندہ کا پتہ", - "extra_id": "اضافی ID:", - "destination_tag": "منزل کا ٹیگ:", - "memo": "میمو:", - "backup": "بیک اپ", - "change_password": "پاس ورڈ تبدیل کریں", - "backup_password": "بیک اپ پاس ورڈ", - "write_down_backup_password": "براہ کرم اپنا بیک اپ پاس ورڈ لکھیں، جو آپ کی بیک اپ فائلوں کی درآمد کے لیے استعمال ہوتا ہے۔", - "export_backup": "بیک اپ برآمد کریں۔", - "save_backup_password": "براہ کرم یقینی بنائیں کہ آپ نے اپنا بیک اپ پاس ورڈ محفوظ کر لیا ہے۔ آپ اس کے بغیر اپنی بیک اپ فائلیں درآمد نہیں کر سکیں گے۔", - "backup_file": "بیک اپ فائل", - "edit_backup_password": "بیک اپ پاس ورڈ میں ترمیم کریں۔", - "save_backup_password_alert": "بیک اپ پاس ورڈ محفوظ کریں۔", - "change_backup_password_alert": "آپ کی پچھلی بیک اپ فائلیں نئے بیک اپ پاس ورڈ کے ساتھ درآمد کرنے کے لیے دستیاب نہیں ہوں گی۔ نیا بیک اپ پاس ورڈ صرف نئی بیک اپ فائلوں کے لیے استعمال کیا جائے گا۔ کیا آپ واقعی بیک اپ پاس ورڈ تبدیل کرنا چاہتے ہیں؟", - "enter_backup_password": "یہاں بیک اپ پاس ورڈ درج کریں۔", - "select_backup_file": "بیک اپ فائل کو منتخب کریں۔", - "import": " ۔ﮟﯾﺮﮐ ﺪﻣﺁﺭﺩ", - "please_select_backup_file": "براہ کرم بیک اپ فائل منتخب کریں اور بیک اپ پاس ورڈ درج کریں۔", - "fixed_rate": "مقررہ شرح", - "fixed_rate_alert": "فکسڈ ریٹ موڈ چیک ہونے پر آپ وصولی رقم درج کر سکیں گے۔ کیا آپ فکسڈ ریٹ موڈ پر سوئچ کرنا چاہتے ہیں؟", - "xlm_extra_info": "ایکسچینج کے لیے XLM ٹرانزیکشن بھیجتے وقت براہ کرم میمو ID بتانا نہ بھولیں۔", - "xrp_extra_info": "ایکسچینج کے لیے XRP ٹرانزیکشن بھیجتے وقت ڈیسٹینیشن ٹیگ بتانا نہ بھولیں۔", - "exchange_incorrect_current_wallet_for_xmr": "اگر آپ اپنے Cake والیٹ Monero بیلنس سے XMR کا تبادلہ کرنا چاہتے ہیں، تو براہ کرم پہلے اپنے Monero والیٹ پر جائیں۔", - "confirmed": "تصدیق شدہ بیلنس", - "unconfirmed": "غیر تصدیق شدہ بیلنس", - "displayable": "قابل نمائش", - "submit_request": "درخواست بھیج دو", - "buy_alert_content": "۔ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﺱﺍ ﺎﯾ ﮟﯿﺋﺎﻨﺑ ﭧﯿﻟﺍﻭ Monero ﺎﯾ ،Bitcoin، Ethereum، Litecoin ﺎﻨﭘﺍ ﻡ", - "sell_alert_content": "۔ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﺱﺍ ﺎﯾ ﮟﯿﺋﺎﻨﺑ ﭧﯿﻟﺍﻭ Litecoin ﺎﯾ Bitcoin، Ethereum ﺎﻨﭘﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ۔", - "outdated_electrum_wallet_description": "Cake میں بنائے گئے نئے Bitcoin بٹوے میں اب 24 الفاظ کا بیج ہے۔ یہ لازمی ہے کہ آپ ایک نیا Bitcoin والیٹ بنائیں اور اپنے تمام فنڈز کو نئے 24 الفاظ والے والیٹ میں منتقل کریں، اور 12 الفاظ کے بیج والے بٹوے کا استعمال بند کریں۔ براہ کرم اپنے فنڈز کو محفوظ بنانے کے لیے فوری طور پر ایسا کریں۔", - "understand": "میں سمجھتا ہوں۔", - "apk_update": "APK اپ ڈیٹ", - "buy_bitcoin": "Bitcoin خریدیں۔", - "buy_with": "کے ساتھ خریدیں۔", - "moonpay_alert_text": "رقم کی قدر ${minAmount} ${fiatCurrency} کے برابر یا زیادہ ہونی چاہیے۔", - "outdated_electrum_wallet_receive_warning": "اگر اس پرس میں 12 الفاظ کا بیج ہے اور اسے Cake میں بنایا گیا ہے، تو اس بٹوے میں Bitcoin جمع نہ کریں۔ اس بٹوے میں منتقل کیا گیا کوئی بھی BTC ضائع ہو سکتا ہے۔ ایک نیا 24 الفاظ والا والیٹ بنائیں (اوپر دائیں جانب مینو کو تھپتھپائیں، Wallets کو منتخب کریں، نیا والیٹ بنائیں، پھر Bitcoin کو منتخب کریں) اور فوری طور پر اپنے BTC کو وہاں منتقل کریں۔ Cake کے نئے (24-لفظوں) BTC بٹوے محفوظ ہیں۔", - "do_not_show_me": "مجھے یہ دوبارہ مت دکھانا", - "unspent_coins_title": "غیر خرچ شدہ سکے ۔", - "unspent_coins_details_title": "غیر خرچ شدہ سککوں کی تفصیلات", - "freeze": "منجمد", - "frozen": "منجمد", - "coin_control": "سکے کنٹرول (اختیاری)", - "address_detected": "پتہ کا پتہ چلا", - "address_from_domain": "یہ پتہ نہ رکنے والے ڈومینز پر ${domain} کا ہے۔", - "add_receiver": "دوسرا وصول کنندہ شامل کریں (اختیاری)", - "manage_yats": "یاٹس کا انتظام کریں۔", - "yat_alert_title": "Yat کے ساتھ زیادہ آسانی سے کریپٹو بھیجیں اور وصول کریں۔", - "yat_alert_content": "Cake والیٹ کے صارفین اب ایک قسم کے ایموجی پر مبنی صارف نام کے ساتھ اپنی تمام پسندیدہ کرنسیاں بھیج اور وصول کر سکتے ہیں۔", - "get_your_yat": "اپنی Yat حاصل کریں۔", - "connect_an_existing_yat": "ایک موجودہ Yat کو جوڑیں۔", - "connect_yats": "Yats کو جوڑیں۔", - "yat_address": "Yat ایڈریس", - "yat": "Yat", - "address_from_yat": "یہ پتہ Yat پر ${emoji} کا ہے۔", - "yat_error": "Yat غلطی", - "yat_error_content": "اس Yat کے ساتھ کوئی پتے منسلک نہیں ہیں۔ ایک اور یات آزمائیں۔", - "choose_address": "\\n\\nبراہ کرم پتہ منتخب کریں:", - "yat_popup_title": "آپ کے بٹوے کا پتہ ایموجائز کیا جا سکتا ہے۔", - "yat_popup_content": "اب آپ Cake Wallet میں اپنے Yat کے ساتھ کرپٹو بھیج اور وصول کر سکتے ہیں - ایک مختصر، ایموجی پر مبنی صارف نام۔ ترتیبات کی سکرین پر کسی بھی وقت Yats کا نظم کریں۔", - "second_intro_title": "ان سب پر حکمرانی کے لیے ایک ایموجی ایڈریس", - "second_intro_content": "آپ کا Yat ایک منفرد ایموجی ایڈریس ہے جو آپ کی تمام کرنسیوں کے لیے آپ کے تمام لمبے ہیکسا ڈیسیمل پتوں کی جگہ لے لیتا ہے۔", - "third_intro_title": "Yat دوسروں کے ساتھ اچھی طرح کھیلتا ہے۔", - "third_intro_content": "Yats بھی Cake والیٹ سے باہر رہتے ہیں۔ زمین پر کسی بھی بٹوے کے پتے کو Yat سے تبدیل کیا جا سکتا ہے!", - "learn_more": "اورجانیے", - "search": "تلاش کریں۔", - "search_language": "زبان تلاش کریں۔", - "search_currency": "کرنسی تلاش کریں۔", - "new_template": "نیا سانچہ", - "electrum_address_disclaimer": "جب بھی آپ ایک کا استعمال کرتے ہیں تو ہم نئے پتے تیار کرتے ہیں، لیکن پچھلے پتے کام کرتے رہتے ہیں۔", - "wallet_name_exists": "اس نام کا پرس پہلے سے موجود ہے۔ براہ کرم ایک مختلف نام منتخب کریں یا پہلے دوسرے بٹوے کا نام تبدیل کریں۔", - "market_place": "بازار", - "cake_pay_title": "Cake پے گفٹ کارڈز", - "cake_pay_subtitle": "رعایتی گفٹ کارڈز خریدیں (صرف امریکہ)", - "cake_pay_web_cards_title": "Cake پے ویب کارڈز", - "cake_pay_web_cards_subtitle": "دنیا بھر میں پری پیڈ کارڈز اور گفٹ کارڈز خریدیں۔", - "about_cake_pay": "Cake پے آپ کو ورچوئل اثاثوں کے ساتھ گفٹ کارڈز آسانی سے خریدنے کی اجازت دیتا ہے، جو ریاستہائے متحدہ میں 150,000 سے زیادہ تاجروں پر فوری طور پر خرچ کیے جا سکتے ہیں۔", - "cake_pay_account_note": "کارڈز دیکھنے اور خریدنے کے لیے صرف ایک ای میل ایڈریس کے ساتھ سائن اپ کریں۔ کچھ رعایت پر بھی دستیاب ہیں!", - "already_have_account": "پہلے سے ہی اکاؤنٹ ہے؟", - "create_account": "اکاؤنٹ بنائیں", - "privacy_policy": "رازداری کی پالیسی", - "welcome_to_cakepay": "Cake پے میں خوش آمدید!", - "sign_up": "سائن اپ", - "forgot_password": "پاسورڈ بھول گے", - "reset_password": "پاس ورڈ ری سیٹ", - "gift_cards": "گفٹ کارڈز", - "setup_your_debit_card": "اپنا ڈیبٹ کارڈ ترتیب دیں۔", - "no_id_required": "کوئی ID درکار نہیں۔ ٹاپ اپ اور کہیں بھی خرچ کریں۔", - "how_to_use_card": "اس کارڈ کو استعمال کرنے کا طریقہ", - "purchase_gift_card": "گفٹ کارڈ خریدیں۔", - "verification": "تصدیق", - "fill_code": "براہ کرم اپنے ای میل پر فراہم کردہ تصدیقی کوڈ کو پُر کریں۔", - "didnt_get_code": "کوڈ نہیں ملتا؟", - "resend_code": "براہ کرم اسے دوبارہ بھیجیں۔", - "debit_card": "ڈیبٹ کارڈ", - "cakepay_prepaid_card": "Cake پے پری پیڈ ڈیبٹ کارڈ", - "no_id_needed": "شناخت کی ضرورت نہیں!", - "frequently_asked_questions": "اکثر پوچھے گئے سوالات", - "debit_card_terms": "اس ڈیجیٹل والیٹ میں آپ کے ادائیگی کارڈ نمبر (اور آپ کے ادائیگی کارڈ نمبر سے متعلقہ اسناد) کا ذخیرہ اور استعمال ادائیگی کارڈ جاری کنندہ کے ساتھ قابل اطلاق کارڈ ہولڈر کے معاہدے کی شرائط و ضوابط کے ساتھ مشروط ہے، جیسا کہ وقتاً فوقتاً نافذ ہوتا ہے۔", - "please_reference_document": "مزید معلومات کے لیے براہ کرم نیچے دی گئی دستاویزات کا حوالہ دیں۔", - "cardholder_agreement": "کارڈ ہولڈر کا معاہدہ", - "e_sign_consent": "ای سائن کنسنٹ", - "agree_and_continue": "اتفاق کریں اور جاری رکھیں", - "email_address": "ای میل اڈریس", - "agree_to": "اکاؤنٹ بنا کر آپ اس سے اتفاق کرتے ہیں۔", - "and": "اور", - "enter_code": "کوڈ درج کریں", - "congratulations": "مبارک ہو!", - "you_now_have_debit_card": "اب آپ کے پاس ڈیبٹ کارڈ ہے۔", - "min_amount": "کم سے کم: ${value}", - "max_amount": "زیادہ سے زیادہ: ${value}", - "enter_amount": "رقم درج کریں۔", - "billing_address_info": "اگر آپ سے بلنگ کا پتہ پوچھا جائے تو اپنا شپنگ ایڈریس فراہم کریں۔", - "order_physical_card": "فزیکل کارڈ آرڈر کریں۔", - "add_value": "قدر شامل کریں۔", - "activate": "محرک کریں", - "get_a": "حاصل", - "digital_and_physical_card": " ڈیجیٹل اور فزیکل پری پیڈ ڈیبٹ کارڈ", - "get_card_note": " جسے آپ ڈیجیٹل کرنسیوں کے ساتھ دوبارہ لوڈ کر سکتے ہیں۔ کوئی اضافی معلومات کی ضرورت نہیں!", - "signup_for_card_accept_terms": "کارڈ کے لیے سائن اپ کریں اور شرائط کو قبول کریں۔", - "add_fund_to_card": "کارڈز میں پری پیڈ فنڈز شامل کریں (${value} تک)", - "use_card_info_two": "رقوم کو امریکی ڈالر میں تبدیل کیا جاتا ہے جب پری پیڈ اکاؤنٹ میں رکھا جاتا ہے، ڈیجیٹل کرنسیوں میں نہیں۔", - "use_card_info_three": "ڈیجیٹل کارڈ آن لائن یا کنٹیکٹ لیس ادائیگی کے طریقوں کے ساتھ استعمال کریں۔", - "optionally_order_card": "اختیاری طور پر ایک فزیکل کارڈ آرڈر کریں۔", - "hide_details": "تفصیلات چھپائیں۔", - "show_details": "تفصیلات دکھائیں", - "upto": "${value} تک", - "discount": "${value}% بچائیں", - "gift_card_amount": "گفٹ کارڈ کی رقم", - "bill_amount": "بل رقم", - "you_pay": "تم ادا کرو", - "tip": "ٹپ:", - "custom": "اپنی مرضی کے مطابق", - "by_cake_pay": "Cake پے کے ذریعے", - "expires": "میعاد ختم", - "mm": "MM", - "yy": "YY", - "online": "آن لائن", - "offline": "آف لائن", - "gift_card_number": "گفٹ کارڈ نمبر", - "pin_number": "پن نمبر", - "total_saving": "کل بچت", - "last_30_days": "آخری 30 دن", - "avg_savings": "اوسط بچت", - "view_all": "سب دیکھیں", - "active_cards": "فعال کارڈز", - "delete_account": "کھاتہ مٹا دو", - "cards": "کارڈز", - "active": "فعال", - "redeemed": "چھڑایا", - "gift_card_balance_note": "باقی بیلنس والے گفٹ کارڈز یہاں ظاہر ہوں گے۔", - "gift_card_redeemed_note": "آپ نے جن گفٹ کارڈز کو بھنایا ہے وہ یہاں ظاہر ہوں گے۔", - "logout": "لاگ آوٹ", - "add_tip": "ٹپ شامل کریں۔", - "percentageOf": "${amount} کا", - "is_percentage": "ہے", - "search_category": "زمرہ تلاش کریں۔", - "mark_as_redeemed": "ریڈیم کے بطور نشان زد کریں۔", - "more_options": "مزید زرائے", - "awaiting_payment_confirmation": "ادائیگی کی تصدیق کے منتظر", - "transaction_sent_notice": "اگر اسکرین 1 منٹ کے بعد آگے نہیں بڑھتی ہے، تو بلاک ایکسپلورر اور اپنا ای میل چیک کریں۔", - "agree": "متفق", - "in_store": "اسٹور میں", - "generating_gift_card": "گفٹ کارڈ تیار کرنا", - "payment_was_received": "آپ کی ادائیگی موصول ہو گئی۔", - "proceed_after_one_minute": "اگر اسکرین 1 منٹ کے بعد آگے نہیں بڑھتی ہے تو اپنا ای میل چیک کریں۔", - "order_id": "ID آرڈر کریں۔", - "gift_card_is_generated": "گفٹ کارڈ بنتا ہے۔", - "open_gift_card": "گفٹ کارڈ کھولیں۔", - "contact_support": "سپورٹ سے رابطہ کریں۔", - "gift_cards_unavailable": "گفٹ کارڈز اس وقت صرف Monero، Bitcoin اور Litecoin کے ساتھ خریداری کے لیے دستیاب ہیں۔", - "introducing_cake_pay": "Cake پے کا تعارف!", - "cake_pay_learn_more": "ایپ میں فوری طور پر گفٹ کارڈز خریدیں اور بھنائیں!\\nمزید جاننے کے لیے بائیں سے دائیں سوائپ کریں۔", + "authenticated": "تصدیق شدہ", + "authentication": "تصدیق", + "auto_generate_subaddresses": "آٹو سب ایڈریس تیار کرتا ہے", "automatic": "خودکار", - "fixed_pair_not_supported": "یہ مقررہ جوڑا منتخب کردہ تبادلے کے ساتھ تعاون یافتہ نہیں ہے۔", - "variable_pair_not_supported": "یہ متغیر جوڑا منتخب ایکسچینجز کے ساتھ تعاون یافتہ نہیں ہے۔", - "none_of_selected_providers_can_exchange": "منتخب فراہم کنندگان میں سے کوئی بھی یہ تبادلہ نہیں کر سکتا", - "choose_one": "ایک کا انتخاب کریں", - "choose_from_available_options": "دستیاب اختیارات میں سے انتخاب کریں:", - "custom_redeem_amount": "حسب ضرورت چھڑانے کی رقم", - "add_custom_redemption": "حسب ضرورت چھٹکارا شامل کریں۔", - "remaining": "باقی", - "delete_wallet": "پرس کو حذف کریں۔", - "delete_wallet_confirm_message": "کیا آپ واقعی ${wallet_name} والیٹ کو حذف کرنا چاہتے ہیں؟", - "low_fee": "کم فیس", - "low_fee_alert": "آپ فی الحال کم نیٹ ورک فیس کی ترجیح استعمال کر رہے ہیں۔ یہ طویل انتظار، مختلف شرحوں، یا منسوخ شدہ تجارتوں کا سبب بن سکتا ہے۔ ہم بہتر تجربہ کے لیے زیادہ فیس مقرر کرنے کی تجویز کرتے ہیں۔", - "ignor": "نظر انداز کرنا", - "use_suggested": "تجویز کردہ استعمال کریں۔", - "do_not_share_warning_text": "سپورٹ سمیت کسی اور کے ساتھ ان کا اشتراک نہ کریں۔\\n\\nآپ کے فنڈز چوری ہو سکتے ہیں اور ہو جائیں گے!", - "help": "مدد", - "all_transactions": "تمام لین دین", - "all_trades": "تمام تجارت", - "connection_sync": "کنکشن اور مطابقت پذیری", - "security_and_backup": "سیکیورٹی اور بیک اپ", - "create_backup": "بیک اپ بنائیں", - "privacy_settings": "رازداری کی ترتیبات", - "privacy": "رازداری", - "display_settings": "ڈسپلے کی ترتیبات", - "other_settings": "دیگر ترتیبات", - "require_pin_after": "اس کے بعد PIN کی ضرورت ہے۔", - "always": "ہمیشہ", - "minutes_to_pin_code": "${minute} منٹ", - "disable_exchange": "تبادلے کو غیر فعال کریں۔", - "advanced_settings": "اعلی درجے کی ترتیبات", - "settings_can_be_changed_later": "ان ترتیبات کو بعد میں ایپ کی ترتیبات میں تبدیل کیا جا سکتا ہے۔", - "add_custom_node": "نیا کسٹم نوڈ شامل کریں۔", - "disable_fiat": "فیاٹ کو غیر فعال کریں۔", - "fiat_api": "Fiat API", - "disabled": "معذور", - "enabled": "فعال", - "tor_only": "صرف Tor", - "unmatched_currencies": "آپ کے پرس کی موجودہ کرنسی اسکین شدہ QR سے مماثل نہیں ہے۔", - "orbot_running_alert": "براہ کرم یقینی بنائیں کہ اس نوڈ سے منسلک ہونے سے پہلے Orbot چل رہا ہے۔", - "contact_list_contacts": "رابطے", - "contact_list_wallets": "میرے بٹوے", - "send_to_this_address": "اس پتے پر ${currency} ${tag} بھیجیں۔", - "arrive_in_this_address": "${currency} ${tag}اس پتے پر پہنچے گا۔", - "do_not_send": "مت بھیجیں۔", - "error_dialog_content": "افوہ، ہمیں کچھ خرابی ملی۔\n\nایپلی کیشن کو بہتر بنانے کے لیے براہ کرم کریش رپورٹ ہماری سپورٹ ٹیم کو بھیجیں۔", - "decimal_places_error": "بہت زیادہ اعشاریہ جگہیں۔", - "edit_node": "نوڈ میں ترمیم کریں۔", - "invoice_details": "رسید کی تفصیلات", - "donation_link_details": "عطیہ کے لنک کی تفصیلات", - "anonpay_description": "${type} بنائیں۔ وصول کنندہ کسی بھی تعاون یافتہ کرپٹو کرنسی کے ساتھ ${method} کرسکتا ہے، اور آپ کو اس بٹوے میں فنڈز موصول ہوں گے۔", - "create_invoice": "انوائس بنائیں", - "create_donation_link": "عطیہ کا لنک بنائیں", - "optional_email_hint": "اختیاری وصول کنندہ کی اطلاع کا ای میل", - "optional_description": "اختیاری تفصیل", - "optional_name": "اختیاری وصول کنندہ کا نام", - "clearnet_link": "کلیرنیٹ لنک", - "onion_link": "پیاز کا لنک", - "sell_monero_com_alert_content": "Monero فروخت کرنا ابھی تک تعاون یافتہ نہیں ہے۔", - "error_text_input_below_minimum_limit": "رقم کم از کم سے کم ہے۔", - "error_text_input_above_maximum_limit": "رقم زیادہ سے زیادہ سے زیادہ ہے۔", - "show_market_place": "بازار دکھائیں۔", - "prevent_screenshots": "اسکرین شاٹس اور اسکرین ریکارڈنگ کو روکیں۔", - "profile": "پروفائل", - "close": "بند کریں", - "modify_2fa": "کیک 2FA میں ترمیم کریں۔", - "disable_cake_2fa": "کیک 2FA کو غیر فعال کریں۔", - "question_to_disable_2fa": "کیا آپ واقعی کیک 2FA کو غیر فعال کرنا چاہتے ہیں؟ بٹوے اور بعض افعال تک رسائی کے لیے اب 2FA کوڈ کی ضرورت نہیں ہوگی۔", - "disable": "غیر فعال کریں۔", - "setup_2fa": "سیٹ اپ کیک 2FA", - "verify_with_2fa": "کیک 2FA سے تصدیق کریں۔", - "totp_code": "TOTP کوڈ", - "please_fill_totp": "براہ کرم اپنے دوسرے آلے پر موجود 8 ہندسوں کا کوڈ پُر کریں۔", - "totp_2fa_success": "کامیابی! کیک 2FA اس بٹوے کے لیے فعال ہے۔ بٹوے تک رسائی سے محروم ہونے کی صورت میں اپنے یادداشت کے بیج کو محفوظ کرنا یاد رکھیں۔", - "totp_verification_success": "توثیق کامیاب!", - "totp_2fa_failure": "غلط کوڈ. براہ کرم ایک مختلف کوڈ آزمائیں یا ایک نئی خفیہ کلید بنائیں۔ ایک ہم آہنگ 2FA ایپ استعمال کریں جو 8 ہندسوں کے کوڈز اور SHA512 کو سپورٹ کرتی ہو۔", - "enter_totp_code": "براہ کرم TOTP کوڈ درج کریں۔", - "add_secret_code": " ۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮟﯿﻣ ﭗﯾﺍ ﮦﺪﻨﻨﮐ ﻖﯾﺪﺼﺗ ﻮﮐ ﮈﻮﮐ ﮧﯿﻔﺧ ﺱﺍ ،ﺎﯾ", - "totp_secret_code": "TOTP خفیہ کوڈ", - "setup_2fa_text": " ۔ﮯﮨ ﺎﺗﺮﮐ ﻡﺎﮐ ﮯﺋﻮﮨ ﮯﺗﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ ﺎﮐ TOTP ﺮﭘ ﺭﻮﻃ ﮯﮐ ﺮﺼﻨﻋ ﯽﻘﯾﺪﺼﺗ ﮮﺮﺳﻭﺩ 2FA ﮏﯿﮐ", - "setup_totp_recommended": "TOTP ۔ﮟﯾﺮﮐ ﭖﺍ ﭧﯿﺳ", - "disable_buy": "خرید ایکشن کو غیر فعال کریں۔", - "disable_sell": "فروخت کی کارروائی کو غیر فعال کریں۔", - "cake_2fa_preset": "کیک 2FA پیش سیٹ", - "narrow": "تنگ", - "normal": "نارمل", - "aggressive": "حد سے زیادہ پرجوش", - "require_for_assessing_wallet": "بٹوے تک رسائی کے لیے درکار ہے۔", - "require_for_sends_to_non_contacts": "غیر رابطوں کو بھیجنے کی ضرورت ہے۔", - "require_for_sends_to_contacts": "رابطوں کو بھیجنے کی ضرورت ہے۔", - "require_for_sends_to_internal_wallets": "اندرونی بٹوے پر بھیجنے کے لیے درکار ہے۔", - "require_for_exchanges_to_internal_wallets": "اندرونی بٹوے میں تبادلے کی ضرورت ہے۔", - "require_for_adding_contacts": "رابطوں کو شامل کرنے کی ضرورت ہے۔", - "require_for_creating_new_wallets": "نئے بٹوے بنانے کی ضرورت ہے۔", - "require_for_all_security_and_backup_settings": "تمام سیکورٹی اور بیک اپ کی ترتیبات کے لیے درکار ہے۔", + "available_balance": "دستیاب بیلنس", "available_balance_description": "”دستیاب بیلنس” یا ”تصدیق شدہ بیلنس” وہ فنڈز ہیں جو فوری طور پر خرچ کیے جا سکتے ہیں۔ اگر فنڈز کم بیلنس میں ظاہر ہوتے ہیں لیکن اوپر کے بیلنس میں نہیں، تو آپ کو مزید نیٹ ورک کی تصدیقات حاصل کرنے کے لیے آنے والے فنڈز کے لیے چند منٹ انتظار کرنا چاہیے۔ مزید تصدیق حاصل کرنے کے بعد، وہ قابل خرچ ہوں گے۔", - "syncing_wallet_alert_title": "آپ کا بٹوہ مطابقت پذیر ہو رہا ہے۔", - "syncing_wallet_alert_content": "آپ کے بیلنس اور لین دین کی فہرست اس وقت تک مکمل نہیں ہو سکتی جب تک کہ یہ سب سے اوپر \"SYNCRONIZED\" نہ کہے۔ مزید جاننے کے لیے کلک/تھپتھپائیں۔", - "home_screen_settings": "ہوم اسکرین کی ترتیبات", - "sort_by": "ترتیب دیں", - "search_add_token": "تلاش کریں / ٹوکن شامل کریں۔", - "edit_token": "ٹوکن میں ترمیم کریں۔", - "warning": "وارننگ", - "add_token_warning": "سکیمرز کی ہدایت کے مطابق ٹوکن میں ترمیم یا اضافہ نہ کریں۔\nہمیشہ معتبر ذرائع سے ٹوکن پتوں کی تصدیق کریں!", - "add_token_disclaimer_check": "میں نے ایک معتبر ذریعہ کا استعمال کرتے ہوئے ٹوکن کنٹریکٹ ایڈریس اور معلومات کی تصدیق کی ہے۔ بدنیتی پر مبنی یا غلط معلومات شامل کرنے کے نتیجے میں فنڈز ضائع ہو سکتے ہیں۔", - "token_contract_address": "ٹوکن کنٹریکٹ ایڈریس", - "token_name": "ٹوکن کا نام جیسے: Tether", - "token_symbol": "ٹوکن کی علامت جیسے: USDT", - "token_decimal": "ٹوکن اعشاریہ", - "field_required": "اس کو پر کرنا ضروری ہے", - "pin_at_top": "اوپر ${token} کو پن کریں۔", - "invalid_input": "غلط ان پٹ", - "fiat_balance": "فیاٹ بیلنس", - "gross_balance": "مجموعی بیلنس", - "alphabetical": "حروف تہجی کے مطابق", - "generate_name": "نام پیدا کریں۔", + "avg_savings": "اوسط بچت", + "awaitDAppProcessing": "۔ﮟﯾﺮﮐ ﺭﺎﻈﺘﻧﺍ ﺎﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﮓﻨﺴﯿﺳﻭﺮﭘ ﮯﮐ dApp ﻡﺮﮐ ﮦﺍﺮﺑ", + "awaiting_payment_confirmation": "ادائیگی کی تصدیق کے منتظر", + "backup": "بیک اپ", + "backup_file": "بیک اپ فائل", + "backup_password": "بیک اپ پاس ورڈ", "balance_page": "بیلنس صفحہ", - "share": "بانٹیں", - "slidable": "سلائیڈ ایبل", - "monero_dark_theme": "مونیرو ڈارک تھیم", + "bill_amount": "بل رقم", + "billing_address_info": "اگر آپ سے بلنگ کا پتہ پوچھا جائے تو اپنا شپنگ ایڈریس فراہم کریں۔", + "biometric_auth_reason": "تصدیق کرنے کے لیے اپنے فنگر پرنٹ کو اسکین کریں۔", "bitcoin_dark_theme": "بٹ کوائن ڈارک تھیم", "bitcoin_light_theme": "بٹ کوائن لائٹ تھیم", - "high_contrast_theme": "ہائی کنٹراسٹ تھیم", - "matrix_green_dark_theme": "میٹرکس گرین ڈارک تھیم", - "monero_light_theme": "مونیرو لائٹ تھیم", - "manage_nodes": "۔ﮟﯾﺮﮐ ﻢﻈﻧ ﺎﮐ ﺱﮈﻮﻧ", - "etherscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﺮﮭﺘﯾﺍ", - "template_name": "ٹیمپلیٹ کا نام", + "Blocks_remaining": "${status} بلاکس باقی ہیں۔", + "bright_theme": "روشن", + "buy": "خریدنے", + "buy_alert_content": "۔ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﺱﺍ ﺎﯾ ﮟﯿﺋﺎﻨﺑ ﭧﯿﻟﺍﻭ Monero ﺎﯾ ،Bitcoin، Ethereum، Litecoin ﺎﻨﭘﺍ ﻡ", + "buy_bitcoin": "Bitcoin خریدیں۔", + "buy_provider_unavailable": "فراہم کنندہ فی الحال دستیاب نہیں ہے۔", + "buy_with": "کے ساتھ خریدیں۔", + "by_cake_pay": "Cake پے کے ذریعے", + "cake_2fa_preset": "کیک 2FA پیش سیٹ", + "cake_pay_account_note": "کارڈز دیکھنے اور خریدنے کے لیے صرف ایک ای میل ایڈریس کے ساتھ سائن اپ کریں۔ کچھ رعایت پر بھی دستیاب ہیں!", + "cake_pay_learn_more": "ایپ میں فوری طور پر گفٹ کارڈز خریدیں اور بھنائیں!\\nمزید جاننے کے لیے بائیں سے دائیں سوائپ کریں۔", + "cake_pay_subtitle": "رعایتی گفٹ کارڈز خریدیں (صرف امریکہ)", + "cake_pay_title": "Cake پے گفٹ کارڈز", + "cake_pay_web_cards_subtitle": "دنیا بھر میں پری پیڈ کارڈز اور گفٹ کارڈز خریدیں۔", + "cake_pay_web_cards_title": "Cake پے ویب کارڈز", + "cake_wallet": "Cake والیٹ", + "cakepay_prepaid_card": "Cake پے پری پیڈ ڈیبٹ کارڈ", + "camera_consent": "۔ﮟﯿﮭﮑﯾﺩ ﯽﺴﯿﻟﺎﭘ ﯽﺴﯾﻮﯿﺋﺍﺮﭘ ﯽﮐ ﻥﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ﮯﯿﻟ ﮯﮐ ﺕﻼ${provider}ﯿﺼﻔﺗ ۔ﺎﮔ ﮯﺋﺎﺟ ﺎﯿﮐ ﻝﺎﻤﻌﺘﺳﺍ ﮯﯿﻟ", + "camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ", + "cancel": "منسوخ کریں۔", + "card_address": "پتہ:", + "cardholder_agreement": "کارڈ ہولڈر کا معاہدہ", + "cards": "کارڈز", + "chains": "ﮟﯾﺮﯿﺠﻧﺯ", + "change": "تبدیلی", + "change_backup_password_alert": "آپ کی پچھلی بیک اپ فائلیں نئے بیک اپ پاس ورڈ کے ساتھ درآمد کرنے کے لیے دستیاب نہیں ہوں گی۔ نیا بیک اپ پاس ورڈ صرف نئی بیک اپ فائلوں کے لیے استعمال کیا جائے گا۔ کیا آپ واقعی بیک اپ پاس ورڈ تبدیل کرنا چاہتے ہیں؟", + "change_currency": "کرنسی تبدیل کریں", + "change_current_node": "کیا آپ یقینی طور پر موجودہ نوڈ کو ${node} میں تبدیل کرنا چاہتے ہیں؟", + "change_current_node_title": "موجودہ نوڈ کو تبدیل کریں۔", + "change_exchange_provider": "ایکسچینج فراہم کنندہ کو تبدیل کریں۔", + "change_language": "زبان تبدیل کریں", + "change_language_to": "زبان کو ${language} میں تبدیل کریں؟", + "change_password": "پاس ورڈ تبدیل کریں", "change_rep": "۔ﮟﯾﺮﮐ ﻞﯾﺪﺒﺗ ﮦﺪﻨﺋﺎﻤﻧ", "change_rep_message": "؟ﮟﯿﮨ ﮯﺘﮨﺎﭼ ﺎﻧﺮﮐ ﻞﯾﺪﺒﺗ ﻮﮐ ﮞﻭﺪﻨﺋﺎﻤﻧ ﯽﻌﻗﺍﻭ ﭖﺁ ﺎﯿﮐ", - "unsupported_asset": "۔ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﺱﺍ ﺎﯾ ﮟﯿﺋﺎﻨﺑ ﺱﺮﭘ ﺎﮐ ﻢﺴﻗ ﯽﮐ ﮧﺛﺎﺛﺍ ﮧﺘﻓﺎﯾ ﻥﻭﺎﻌﺗ ﻡﺮﮐ ﮦﺍﺮﺑ ۔ﮟﯿﮨ ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﺖﯾﺎﻤﺣ ﯽﮐ ﯽﺋﺍﻭﺭﺭﺎﮐ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﮧﺛﺎﺛﺍ ﺱﺍ ﻢﮨ", - "manage_pow_nodes": "PoW ۔ﮟﯾﺮﮐ ﻢﻈﻧ ﺎﮐ ﺱﮈﻮﻧ", - "support_title_live_chat": "براہ راست مدد", - "support_description_live_chat": "مفت اور تیز! تربیت یافتہ معاون نمائندے مدد کے لئے دستیاب ہیں", - "support_title_guides": "کیک پرس گائڈز", - "support_description_guides": "عام مسائل کے لئے دستاویزات اور مدد", - "support_title_other_links": "دوسرے سپورٹ لنکس", - "support_description_other_links": "ہماری برادریوں میں شامل ہوں یا دوسرے طریقوں سے ہمارے شراکت داروں تک پہنچیں", + "change_rep_successful": "نمائندہ کو کامیابی کے ساتھ تبدیل کیا", + "change_wallet_alert_content": "کیا آپ موجودہ والیٹ کو ${wallet_name} میں تبدیل کرنا چاہتے ہیں؟", + "change_wallet_alert_title": "موجودہ پرس تبدیل کریں۔", + "choose_account": "اکاؤنٹ کا انتخاب کریں۔", + "choose_address": "\\n\\nبراہ کرم پتہ منتخب کریں:", "choose_derivation": "پرس سے ماخوذ منتخب کریں", - "new_first_wallet_text": "آسانی سے اپنے cryptocurrency محفوظ رکھیں", - "select_destination": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﻝﺰﻨﻣ ﮯﯿﻟ ﮯﮐ ﻞﺋﺎﻓ ﭖﺍ ﮏﯿﺑ ﻡﺮﮐ ﮦﺍﺮﺑ", - "auto_generate_subaddresses": "آٹو سب ایڈریس تیار کرتا ہے", - "save_to_downloads": "۔ﮟﯾﺮﮐ ﻅﻮﻔﺤﻣ ﮟﯿﻣ ﺯﮈﻮﻟ ﻥﺅﺍﮈ", - "select_buy_provider_notice": "اوپر خریدنے والا خریدنے والا منتخب کریں۔ آپ ایپ کی ترتیبات میں اپنے پہلے سے طے شدہ خریدنے والے کو ترتیب دے کر اس اسکرین کو چھوڑ سکتے ہیں۔", - "onramper_option_description": "ادائیگی کے بہت سے طریقوں سے جلدی سے کرپٹو خریدیں۔ زیادہ تر ممالک میں دستیاب ہے۔ پھیلاؤ اور فیس مختلف ہوتی ہے۔", + "choose_from_available_options": "دستیاب اختیارات میں سے انتخاب کریں:", + "choose_one": "ایک کا انتخاب کریں", + "choose_relay": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﮯﻠﯾﺭ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ ﻡﺮﮐ ﮦﺍﺮﺑ", + "choose_wallet_currency": "براہ کرم والیٹ کرنسی کا انتخاب کریں:", + "clear": "صاف", + "clearnet_link": "کلیرنیٹ لنک", + "close": "بند کریں", + "coin_control": "سکے کنٹرول (اختیاری)", + "color_theme": "رنگین تھیم", + "commit_transaction_amount_fee": "لین دین کا ارتکاب کریں\\nرقم: ${amount}\\nفیس: ${fee}", + "confirm": "تصدیق کریں۔", + "confirm_delete_template": "یہ عمل اس ٹیمپلیٹ کو حذف کر دے گا۔ کیا آپ جاری رکھنا چاہتے ہیں؟", + "confirm_delete_wallet": "اس کارروائی سے یہ پرس حذف ہو جائے گا۔ کیا آپ جاری رکھنا چاہتے ہیں؟", + "confirm_sending": "بھیجنے کی تصدیق کریں۔", + "confirmations": "تصدیقات", + "confirmed": "تصدیق شدہ بیلنس", + "confirmed_tx": "تصدیق", + "congratulations": "مبارک ہو!", + "connect_an_existing_yat": "ایک موجودہ Yat کو جوڑیں۔", + "connect_yats": "Yats کو جوڑیں۔", + "connection_sync": "کنکشن اور مطابقت پذیری", + "connectWalletPrompt": "۔ﮟﯾﮌﻮﺟ ﮫﺗﺎﺳ ﮯﮐ WalletConnect ﻮﮐ ﮮﻮﭩﺑ ﮯﻨﭘﺍ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﻦﯾﺩ ﻦﯿﻟ", + "contact": "رابطہ کریں۔", + "contact_list_contacts": "رابطے", + "contact_list_wallets": "میرے بٹوے", + "contact_name": "رابطے کا نام", + "contact_support": "سپورٹ سے رابطہ کریں۔", + "continue_text": "جاری رہے", + "contractName": "ﻡﺎﻧ ﺎﮐ ﮦﺪﮨﺎﻌﻣ", + "contractSymbol": "ﺖﻣﻼﻋ ﯽﮐ ﮦﺪﮨﺎﻌﻣ", + "copied_key_to_clipboard": "${key} کو کلپ بورڈ پر کاپی کیا گیا۔", + "copied_to_clipboard": "کلپ بورڈ پر کاپی کیا گیا۔", + "copy": "کاپی", + "copy_address": "ایڈریس کاپی کریں۔", + "copy_id": "کاپی ID", + "copyWalletConnectLink": "dApp ﮯﺳ WalletConnect ۔ﮟﯾﺮﮐ ﭧﺴﯿﭘ ﮞﺎﮩﯾ ﺭﻭﺍ ﮟﯾﺮﮐ ﯽﭘﺎﮐ ﻮﮐ ﮏﻨﻟ", + "create_account": "اکاؤنٹ بنائیں", + "create_backup": "بیک اپ بنائیں", + "create_donation_link": "عطیہ کا لنک بنائیں", + "create_invoice": "انوائس بنائیں", + "create_new": "نیا والیٹ بنائیں", + "create_new_account": "نیا اکاؤنٹ بنانے", + "creating_new_wallet": "نیا پرس بنانا", + "creating_new_wallet_error": "خرابی: ${description}", + "creation_date": "بنانے کی تاریخ", + "custom": "اپنی مرضی کے مطابق", + "custom_drag": "کسٹم (ہولڈ اینڈ ڈریگ)", + "custom_redeem_amount": "حسب ضرورت چھڑانے کی رقم", + "dark_theme": "اندھیرا", + "debit_card": "ڈیبٹ کارڈ", + "debit_card_terms": "اس ڈیجیٹل والیٹ میں آپ کے ادائیگی کارڈ نمبر (اور آپ کے ادائیگی کارڈ نمبر سے متعلقہ اسناد) کا ذخیرہ اور استعمال ادائیگی کارڈ جاری کنندہ کے ساتھ قابل اطلاق کارڈ ہولڈر کے معاہدے کی شرائط و ضوابط کے ساتھ مشروط ہے، جیسا کہ وقتاً فوقتاً نافذ ہوتا ہے۔", + "decimal_places_error": "بہت زیادہ اعشاریہ جگہیں۔", "default_buy_provider": "پہلے سے طے شدہ خریدنے والا", - "ask_each_time": "ہر بار پوچھیں", - "buy_provider_unavailable": "فراہم کنندہ فی الحال دستیاب نہیں ہے۔", - "signTransaction": "۔ﮟﯾﺮﮐ ﻂﺨﺘﺳﺩ ﺮﭘ ﻦﯾﺩ ﻦﯿﻟ", + "default_sell_provider": " ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ", + "delete": "حذف کریں۔", + "delete_account": "کھاتہ مٹا دو", + "delete_wallet": "پرس کو حذف کریں۔", + "delete_wallet_confirm_message": "کیا آپ واقعی ${wallet_name} والیٹ کو حذف کرنا چاہتے ہیں؟", + "deleteConnectionConfirmationPrompt": "۔ﮟﯿﮨ ﮯﺘﮨﺎﭼ ﺎﻧﺮﮐ ﻑﺬﺣ ﻮﮐ ﻦﺸﮑﻨﮐ ﭖﺁ ﮧﮐ ﮯﮨ ﻦﯿﻘﯾ ﻮﮐ ﭖﺁ ﺎﯿﮐ", + "descending": "اترتے ہوئے", + "description": "ﻞﯿﺼﻔﺗ", + "destination_tag": "منزل کا ٹیگ:", + "dfx_option_description": "EUR ﺭﻭﺍ CHF ﯽﻓﺎﺿﺍ ۔ﮟﯾﺪﯾﺮﺧ ﻮﭩﭘﺮﮐ ﮫﺗﺎﺳ ﮯﮐ KYC ﮯﯿﻟ ﮯﮐ ﻦﯿﻓﺭﺎﺻ ﭧﯾﺭﻮﭘﺭﺎﮐ ﺭﻭﺍ ﮦﺩﺭﻮﺧ ﮟ", + "didnt_get_code": "کوڈ نہیں ملتا؟", + "digit_pin": "-ہندسوں کا پن", + "digital_and_physical_card": " ڈیجیٹل اور فزیکل پری پیڈ ڈیبٹ کارڈ", + "disable": "غیر فعال کریں۔", + "disable_buy": "خرید ایکشن کو غیر فعال کریں۔", + "disable_cake_2fa": "کیک 2FA کو غیر فعال کریں۔", + "disable_exchange": "تبادلے کو غیر فعال کریں۔", + "disable_fiat": "فیاٹ کو غیر فعال کریں۔", + "disable_sell": "فروخت کی کارروائی کو غیر فعال کریں۔", + "disabled": "معذور", + "discount": "${value}% بچائیں", + "display_settings": "ڈسپلے کی ترتیبات", + "displayable": "قابل نمائش", + "do_not_have_enough_gas_asset": "آپ کے پاس موجودہ بلاکچین نیٹ ورک کی شرائط کے ساتھ لین دین کرنے کے لیے کافی ${currency} نہیں ہے۔ آپ کو بلاکچین نیٹ ورک کی فیس ادا کرنے کے لیے مزید ${currency} کی ضرورت ہے، چاہے آپ کوئی مختلف اثاثہ بھیج رہے ہوں۔", + "do_not_send": "مت بھیجیں۔", + "do_not_share_warning_text": "سپورٹ سمیت کسی اور کے ساتھ ان کا اشتراک نہ کریں۔\\n\\nآپ کے فنڈز چوری ہو سکتے ہیں اور ہو جائیں گے!", + "do_not_show_me": "مجھے یہ دوبارہ مت دکھانا", + "domain_looks_up": "ڈومین تلاش کرنا", + "donation_link_details": "عطیہ کے لنک کی تفصیلات", + "e_sign_consent": "ای سائن کنسنٹ", + "edit": "ترمیم", + "edit_backup_password": "بیک اپ پاس ورڈ میں ترمیم کریں۔", + "edit_node": "نوڈ میں ترمیم کریں۔", + "edit_token": "ٹوکن میں ترمیم کریں۔", + "electrum_address_disclaimer": "جب بھی آپ ایک کا استعمال کرتے ہیں تو ہم نئے پتے تیار کرتے ہیں، لیکن پچھلے پتے کام کرتے رہتے ہیں۔", + "email_address": "ای میل اڈریس", + "enabled": "فعال", + "enter_amount": "رقم درج کریں۔", + "enter_backup_password": "یہاں بیک اپ پاس ورڈ درج کریں۔", + "enter_code": "کوڈ درج کریں", + "enter_seed_phrase": "اپنے بیج کا جملہ درج کریں", + "enter_totp_code": "براہ کرم TOTP کوڈ درج کریں۔", + "enter_your_note": "اپنا نوٹ درج کریں…", + "enter_your_pin": "اپنا PIN درج کریں۔", + "enter_your_pin_again": "اپنا پن دوبارہ درج کریں۔", + "enterTokenID": " ۔ﮟﯾﺮﮐ ﺝﺭﺩ ID ﻦﮐﻮﭨ", + "enterWalletConnectURI": "WalletConnect URI ۔ﮟﯾﺮﮐ ﺝﺭﺩ", + "error": "خرابی", + "error_dialog_content": "افوہ، ہمیں کچھ خرابی ملی۔\n\nایپلی کیشن کو بہتر بنانے کے لیے براہ کرم کریش رپورٹ ہماری سپورٹ ٹیم کو بھیجیں۔", + "error_text_account_name": "اکاؤنٹ کا نام صرف حروف، اعداد پر مشتمل ہو سکتا ہے\\nاور 1 سے 15 حروف کے درمیان ہونا چاہیے۔", + "error_text_address": "والیٹ کا پتہ cryptocurrency کی قسم\\nکے مطابق ہونا چاہیے۔", + "error_text_amount": "رقم صرف اعداد پر مشتمل ہو سکتی ہے۔", + "error_text_contact_name": "رابطہ کے نام میں ` , \\' \" علامات\\nنہیں ہو سکتے اور 1 سے 32 حروف کے درمیان ہونا چاہیے", + "error_text_crypto_currency": "کسر ہندسوں کی تعداد\\n12 سے کم یا مساوی ہونی چاہیے۔", + "error_text_fiat": "رقم کی قدر دستیاب بیلنس سے زیادہ نہیں ہو سکتی۔\\nفرکشن ہندسوں کی تعداد 2 کے برابر یا کم ہونی چاہیے۔", + "error_text_input_above_maximum_limit": "رقم زیادہ سے زیادہ سے زیادہ ہے۔", + "error_text_input_below_minimum_limit": "رقم کم از کم سے کم ہے۔", + "error_text_keys": "والیٹ کیز ہیکس میں صرف 64 حروف پر مشتمل ہو سکتی ہیں۔", + "error_text_limits_loading_failed": "${provider} کے لیے تجارت نہیں بنائی گئی ہے۔ حدود کی لوڈنگ ناکام ہو گئی۔", + "error_text_maximum_limit": "${provider} کے لیے تجارت نہیں بنائی گئی ہے۔ رقم زیادہ سے زیادہ سے زیادہ ہے: ${max} ${currency}", + "error_text_minimal_limit": "${provider} کے لیے تجارت نہیں بنائی گئی ہے۔ رقم کم سے کم ہے: ${min} ${currency}", + "error_text_node_address": "براہ کرم ایک iPv4 پتہ درج کریں۔", + "error_text_node_port": "نوڈ پورٹ میں صرف 0 اور 65535 کے درمیان نمبر ہوسکتے ہیں۔", + "error_text_node_proxy_address": "براہ کرم : درج کریں، مثال کے طور پر 127.0.0.1:9050", + "error_text_payment_id": "ادائیگی کی ID ہیکس میں صرف 16 سے 64 حروف پر مشتمل ہو سکتی ہے۔", + "error_text_subaddress_name": "ذیلی پتے کے نام میں ` , \\ ' \" علامتیں نہیں ہو سکتی ہیں اور 1 اور 20 حروف کے درمیان ہونی چاہئیں", + "error_text_template": "ٹیمپلیٹ کا نام اور پتہ `` , \\' \" علامتوں پر مشتمل نہیں ہو سکتا ہے اور 1 اور 106 حروف کے درمیان ہونا چاہیے", + "error_text_wallet_name": "والیٹ کے نام میں صرف حروف، اعداد، _ - علامتیں\\nاور 1 سے 33 حروف کے درمیان ہونی چاہئیں", + "error_text_xmr": "XMR قدر دستیاب بیلنس سے زیادہ نہیں ہو سکتی۔\\nفرکشن ہندسوں کی تعداد 12 سے کم یا اس کے برابر ہونی چاہیے۔", "errorGettingCredentials": "۔ﯽﺑﺍﺮﺧ ﮟﯿﻣ ﮯﻧﺮﮐ ﻞﺻﺎﺣ ﺩﺎﻨﺳﺍ :ﻡﺎﮐﺎﻧ", "errorSigningTransaction": "۔ﮯﮨ ﯽﺌﮔﺁ ﺶﯿﭘ ﯽﺑﺍﺮﺧ ﮏﯾﺍ ﺖﻗﻭ ﮯﺗﺮﮐ ﻂﺨﺘﺳﺩ ﺮﭘ ﻦﯾﺩ ﻦﯿﻟ", - "pairingInvalidEvent": "ﭧﻧﻮﯾﺍ ﻂﻠﻏ ﺎﻧﺎﻨﺑ ﺍﮌﻮﺟ", - "chains": "ﮟﯾﺮﯿﺠﻧﺯ", - "methods": "ﮯﻘﯾﺮﻃ", - "events": "ﺕﺎﺒﯾﺮﻘﺗ", - "reject": "ﺎﻧﺮﮐ ﺩﺭ", - "approve": "ﻭﺮﮐ ﺭﻮﻈﻨﻣ", - "expiresOn": "ﺩﺎﻌﯿﻣ ﯽﻣﺎﺘﺘﺧﺍ", - "walletConnect": "WalletConnect", - "nullURIError": "URI ۔ﮯﮨ ﻡﺪﻌﻟﺎﮐ", - "connectWalletPrompt": "۔ﮟﯾﮌﻮﺟ ﮫﺗﺎﺳ ﮯﮐ WalletConnect ﻮﮐ ﮮﻮﭩﺑ ﮯﻨﭘﺍ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﻦﯾﺩ ﻦﯿﻟ", - "newConnection": "ﻦﺸﮑﻨﮐ ﺎﯿﻧ", - "activeConnectionsPrompt": "۔ﮯﮔ ﮞﻮﮨ ﺮﮨﺎﻇ ﮞﺎﮩﯾ ﺰﻨﺸﮑﻨﮐ ﻝﺎﻌﻓ", - "deleteConnectionConfirmationPrompt": "۔ﮟﯿﮨ ﮯﺘﮨﺎﭼ ﺎﻧﺮﮐ ﻑﺬﺣ ﻮﮐ ﻦﺸﮑﻨﮐ ﭖﺁ ﮧﮐ ﮯﮨ ﻦﯿﻘﯾ ﻮﮐ ﭖﺁ ﺎﯿﮐ", + "estimated": "تخمینہ لگایا", + "etherscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﺮﮭﺘﯾﺍ", "event": "ﺐﯾﺮﻘﺗ", - "successful": "ﺏﺎﯿﻣﺎﮐ", - "wouoldLikeToConnect": "؟ﮯﮔ ﮟﯿﮨﺎﭼ ﺎﻧﮍﺟ", - "message": "ﻡﺎﻐﯿﭘ", - "do_not_have_enough_gas_asset": "آپ کے پاس موجودہ بلاکچین نیٹ ورک کی شرائط کے ساتھ لین دین کرنے کے لیے کافی ${currency} نہیں ہے۔ آپ کو بلاکچین نیٹ ورک کی فیس ادا کرنے کے لیے مزید ${currency} کی ضرورت ہے، چاہے آپ کوئی مختلف اثاثہ بھیج رہے ہوں۔", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "۔ﮟﯾﺮﮐ ﺭﺎﻈﺘﻧﺍ ﺎﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﮓﻨﺴﯿﺳﻭﺮﭘ ﮯﮐ dApp ﻡﺮﮐ ﮦﺍﺮﺑ", - "copyWalletConnectLink": "dApp ﮯﺳ WalletConnect ۔ﮟﯾﺮﮐ ﭧﺴﯿﭘ ﮞﺎﮩﯾ ﺭﻭﺍ ﮟﯾﺮﮐ ﯽﭘﺎﮐ ﻮﮐ ﮏﻨﻟ", - "enterWalletConnectURI": "WalletConnect URI ۔ﮟﯾﺮﮐ ﺝﺭﺩ", - "seed_key": "بیج کی کلید", - "enter_seed_phrase": "اپنے بیج کا جملہ درج کریں", - "change_rep_successful": "نمائندہ کو کامیابی کے ساتھ تبدیل کیا", - "add_contact": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮧﻄﺑﺍﺭ", + "events": "ﺕﺎﺒﯾﺮﻘﺗ", + "exchange": "تبادلہ", + "exchange_incorrect_current_wallet_for_xmr": "اگر آپ اپنے Cake والیٹ Monero بیلنس سے XMR کا تبادلہ کرنا چاہتے ہیں، تو براہ کرم پہلے اپنے Monero والیٹ پر جائیں۔", + "exchange_new_template": "نیا سانچہ", "exchange_provider_unsupported": "${providerName} اب تعاون نہیں کیا جاتا ہے!", - "domain_looks_up": "ڈومین تلاش کرنا", - "require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ", - "camera_permission_is_required": "۔ﮯﮨ ﺭﺎﮐﺭﺩ ﺕﺯﺎﺟﺍ ﯽﮐ ﮮﺮﻤﯿﮐ", - "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ", - "order_by": "آرڈر بذریعہ", - "creation_date": "بنانے کی تاریخ", + "exchange_result_confirm": "تصدیق کو دبانے سے، آپ اپنے بٹوے سے ${fetchingLabel} ${from} بھیجیں گے جسے ${walletName} کہتے ہیں نیچے دکھائے گئے پتے پر۔ یا آپ اپنے بیرونی والیٹ سے نیچے دیئے گئے پتے/QR کوڈ پر بھیج سکتے ہیں۔\\n\\nجاری رکھنے کے لیے براہ کرم تصدیق کو دبائیں یا رقم تبدیل کرنے کے لیے واپس جائیں۔", + "exchange_result_description": "آپ کو اگلے صفحہ پر دکھائے گئے پتے پر کم از کم ${fetchingLabel} ${from} بھیجنا ہوگا۔ اگر آپ ${fetchingLabel} ${from} سے کم رقم بھیجتے ہیں تو یہ تبدیل نہیں ہوسکتی ہے اور اسے واپس نہیں کیا جاسکتا ہے۔", + "exchange_result_write_down_ID": "*براہ کرم اوپر دکھائی گئی اپنی ID کاپی کریں یا لکھیں۔", + "exchange_result_write_down_trade_id": "جاری رکھنے کے لیے براہ کرم تجارتی ID کاپی کریں یا لکھیں۔", + "exchange_sync_alert_content": "براہ کرم اس وقت تک انتظار کریں جب تک آپ کا بٹوہ مطابقت پذیر نہ ہو جائے۔", + "expired": "میعاد ختم", + "expires": "میعاد ختم", + "expiresOn": "ﺩﺎﻌﯿﻣ ﯽﻣﺎﺘﺘﺧﺍ", + "export_backup": "بیک اپ برآمد کریں۔", + "extra_id": "اضافی ID:", + "failed_authentication": "ناکام تصدیق۔ ${state_error}", + "faq": "عمومی سوالات", + "fetching": "لا رہا ہے۔", + "fiat_api": "Fiat API", + "fiat_balance": "فیاٹ بیلنس", + "field_required": "اس کو پر کرنا ضروری ہے", + "fill_code": "براہ کرم اپنے ای میل پر فراہم کردہ تصدیقی کوڈ کو پُر کریں۔", + "filter_by": "کی طرف سے فلٹر", + "first_wallet_text": "Monero، Bitcoin، Ethereum، Litecoin، اور Haven کے لیے زبردست پرس", + "fixed_pair_not_supported": "یہ مقررہ جوڑا منتخب کردہ تبادلے کے ساتھ تعاون یافتہ نہیں ہے۔", + "fixed_rate": "مقررہ شرح", + "fixed_rate_alert": "فکسڈ ریٹ موڈ چیک ہونے پر آپ وصولی رقم درج کر سکیں گے۔ کیا آپ فکسڈ ریٹ موڈ پر سوئچ کرنا چاہتے ہیں؟", + "forgot_password": "پاسورڈ بھول گے", + "freeze": "منجمد", + "frequently_asked_questions": "اکثر پوچھے گئے سوالات", + "frozen": "منجمد", + "full_balance": "مکمل بیلنس", + "generate_name": "نام پیدا کریں۔", + "generating_gift_card": "گفٹ کارڈ تیار کرنا", + "get_a": "حاصل", + "get_card_note": " جسے آپ ڈیجیٹل کرنسیوں کے ساتھ دوبارہ لوڈ کر سکتے ہیں۔ کوئی اضافی معلومات کی ضرورت نہیں!", + "get_your_yat": "اپنی Yat حاصل کریں۔", + "gift_card_amount": "گفٹ کارڈ کی رقم", + "gift_card_balance_note": "باقی بیلنس والے گفٹ کارڈز یہاں ظاہر ہوں گے۔", + "gift_card_is_generated": "گفٹ کارڈ بنتا ہے۔", + "gift_card_number": "گفٹ کارڈ نمبر", + "gift_card_redeemed_note": "آپ نے جن گفٹ کارڈز کو بھنایا ہے وہ یہاں ظاہر ہوں گے۔", + "gift_cards": "گفٹ کارڈز", + "gift_cards_unavailable": "گفٹ کارڈز اس وقت صرف Monero، Bitcoin اور Litecoin کے ساتھ خریداری کے لیے دستیاب ہیں۔", + "got_it": "یہ مل گیا", + "gross_balance": "مجموعی بیلنس", "group_by_type": "قسم کے لحاظ سے گروپ", - "importNFTs": "NFTs ۔ﮟﯾﺮﮐ ﺪﻣﺁﺭﺩ", - "noNFTYet": "۔ﮟﯿﮨ ﮟﯿﮩﻧ NFTs ﯽﺋﻮﮐ ﮏﺗ ﯽﮭﺑﺍ", - "address": "ﮧﺘﭘ", - "enterTokenID": " ۔ﮟﯾﺮﮐ ﺝﺭﺩ ID ﻦﮐﻮﭨ", - "tokenID": "ID", - "name": "ﻡﺎﻧ", - "symbol": "ﺖﻣﻼﻋ", - "seed_phrase_length": "ﯽﺋﺎﺒﻤﻟ ﯽﮐ ﮯﻠﻤﺟ ﮯﮐ ﺞﯿﺑ", - "unavailable_balance": "ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ", - "unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ", - "unspent_change": "تبدیل کریں", - "setup_warning_2fa_text": " ۔ﯽﮔﻮﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻧﺮﮐ ﻝﺎﺤﺑ ﻮﮐ ﮮﻮﭩﺑ ﮯﻨﭘﺍ ﮯﺳ ﺞﯿﺑ ﮯﮐ ﺖﺷﺍﺩﺩﺎﯾ ﻮﮐ ﭖﺁ", - "scan_qr_on_device": " ۔ﮟﯾﺮﮐ ﻦﯿﮑﺳﺍ ﺮﭘ ﺲﺋﺍﻮﯾﮈ ﺭﻭﺍ ﯽﺴﮐ ﻮﮐ ﮈﻮﮐ QR ﺱﺍ", + "haven_app": "Haven از Cake والیٹ", + "haven_app_wallet_text": "Havek کے لیے زبردست پرس", + "help": "مدد", + "hidden_balance": "پوشیدہ بیلنس", + "hide_details": "تفصیلات چھپائیں۔", + "high_contrast_theme": "ہائی کنٹراسٹ تھیم", + "home_screen_settings": "ہوم اسکرین کی ترتیبات", "how_to_use": " ﮧﻘﯾﺮﻃ ﺎﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ", + "how_to_use_card": "اس کارڈ کو استعمال کرنے کا طریقہ", + "id": "ID:", + "ignor": "نظر انداز کرنا", + "import": " ۔ﮟﯾﺮﮐ ﺪﻣﺁﺭﺩ", + "importNFTs": "NFTs ۔ﮟﯾﺮﮐ ﺪﻣﺁﺭﺩ", + "in_store": "اسٹور میں", + "incoming": "آنے والا", + "incorrect_seed": "درج کردہ متن درست نہیں ہے۔", + "introducing_cake_pay": "Cake پے کا تعارف!", + "invalid_input": "غلط ان پٹ", + "invoice_details": "رسید کی تفصیلات", + "is_percentage": "ہے", + "last_30_days": "آخری 30 دن", + "learn_more": "اورجانیے", + "light_theme": "روشنی", + "loading_your_wallet": "آپ کا بٹوہ لوڈ ہو رہا ہے۔", + "login": "لاگ ان کریں", + "logout": "لاگ آوٹ", + "low_fee": "کم فیس", + "low_fee_alert": "آپ فی الحال کم نیٹ ورک فیس کی ترجیح استعمال کر رہے ہیں۔ یہ طویل انتظار، مختلف شرحوں، یا منسوخ شدہ تجارتوں کا سبب بن سکتا ہے۔ ہم بہتر تجربہ کے لیے زیادہ فیس مقرر کرنے کی تجویز کرتے ہیں۔", + "manage_nodes": "۔ﮟﯾﺮﮐ ﻢﻈﻧ ﺎﮐ ﺱﮈﻮﻧ", + "manage_pow_nodes": "PoW ۔ﮟﯾﺮﮐ ﻢﻈﻧ ﺎﮐ ﺱﮈﻮﻧ", + "manage_yats": "یاٹس کا انتظام کریں۔", + "mark_as_redeemed": "ریڈیم کے بطور نشان زد کریں۔", + "market_place": "بازار", + "matrix_green_dark_theme": "میٹرکس گرین ڈارک تھیم", + "max_amount": "زیادہ سے زیادہ: ${value}", + "max_value": "زیادہ سے زیادہ: ${value} ${currency}", + "memo": "میمو:", + "message": "ﻡﺎﻐﯿﭘ", + "methods": "ﮯﻘﯾﺮﻃ", + "min_amount": "کم سے کم: ${value}", + "min_value": "کم سے کم: ${value} ${currency}", + "minutes_to_pin_code": "${minute} منٹ", + "mm": "MM", + "modify_2fa": "کیک 2FA میں ترمیم کریں۔", + "monero_com": "Monero.com بذریعہ Cake والیٹ", + "monero_com_wallet_text": "Monero کے لئے بہت اچھا پرس", + "monero_dark_theme": "مونیرو ڈارک تھیم", + "monero_light_theme": "مونیرو لائٹ تھیم", + "moonpay_alert_text": "رقم کی قدر ${minAmount} ${fiatCurrency} کے برابر یا زیادہ ہونی چاہیے۔", + "more_options": "مزید زرائے", + "name": "ﻡﺎﻧ", + "narrow": "تنگ", + "new_first_wallet_text": "آسانی سے اپنے cryptocurrency محفوظ رکھیں", + "new_node_testing": "نیا نوڈ ٹیسٹنگ", + "new_subaddress_create": "بنانا", + "new_subaddress_label_name": "لیبل کا نام", + "new_subaddress_title": "نیا پتہ", + "new_template": "نیا سانچہ", + "new_wallet": "نیا پرس", + "newConnection": "ﻦﺸﮑﻨﮐ ﺎﯿﻧ", + "no_id_needed": "شناخت کی ضرورت نہیں!", + "no_id_required": "کوئی ID درکار نہیں۔ ٹاپ اپ اور کہیں بھی خرچ کریں۔", + "no_relay_on_domain": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﮯﻠﯾﺭ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ۔ﮯﮨ ﮟﯿﮩﻧ ﺏﺎﯿﺘﺳﺩ ﮯﻠﯾﺭ ﺎﯾ ﮯﮨ ﮟ", + "no_relays": "۔ﮟﯿﮩﻧ ﮯﻠﯾﺭ ﯽﺋﻮﮐ", + "no_relays_message": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮯﻠﯾﺭ ﮟﯿﻣ ﮈﺭﺎﮑﯾﺭ ﺮﭩﺳﻮﻧ ﮯﻨﭘﺍ ﮦﻭ ﮧﮐ ﮟﯾﺩ ﺖﯾﺍﺪﮨ ﻮﮐ ﮦﺪﻨﻨﮐ ﻝﻮﺻﻭ ﻡﺮﮐ ﮦﺍﺮﺑ ۔", + "node_address": "نوڈ ایڈریس", + "node_connection_failed": "کنکشن ناکام ہو گیا تھا۔", + "node_connection_successful": "کنکشن کامیاب رہا۔", + "node_new": "نیا نوڈ", + "node_port": "نوڈ پورٹ", + "node_reset_settings_title": "ترتیبات کو دوبارہ ترتیب دیں۔", + "node_test": "پرکھ", + "nodes": "نوڈس", + "nodes_list_reset_to_default_message": "کیا آپ واقعی ترتیبات کو ڈیفالٹ پر دوبارہ ترتیب دینا چاہتے ہیں؟", + "none_of_selected_providers_can_exchange": "منتخب فراہم کنندگان میں سے کوئی بھی یہ تبادلہ نہیں کر سکتا", + "noNFTYet": "۔ﮟﯿﮨ ﮟﯿﮩﻧ NFTs ﯽﺋﻮﮐ ﮏﺗ ﯽﮭﺑﺍ", + "normal": "نارمل", + "note_optional": "نوٹ (اختیاری)", + "note_tap_to_change": "نوٹ (تبدیل کرنے کے لیے تھپتھپائیں)", + "nullURIError": "URI ۔ﮯﮨ ﻡﺪﻌﻟﺎﮐ", + "offer_expires_in": "پیشکش کی میعاد اس وقت ختم ہو جاتی ہے:", + "offline": "آف لائن", + "ok": "ٹھیک ہے", + "onion_link": "پیاز کا لنک", + "online": "آن لائن", + "onramper_option_description": "ادائیگی کے بہت سے طریقوں سے جلدی سے کرپٹو خریدیں۔ زیادہ تر ممالک میں دستیاب ہے۔ پھیلاؤ اور فیس مختلف ہوتی ہے۔", + "open_gift_card": "گفٹ کارڈ کھولیں۔", + "openalias_alert_content": "آپ کو فنڈز بھیجیں گے\\n${recipient_name}", + "openalias_alert_title": "پتہ کا پتہ چلا", + "optional_description": "اختیاری تفصیل", + "optional_email_hint": "اختیاری وصول کنندہ کی اطلاع کا ای میل", + "optional_name": "اختیاری وصول کنندہ کا نام", + "optionally_order_card": "اختیاری طور پر ایک فزیکل کارڈ آرڈر کریں۔", + "orbot_running_alert": "براہ کرم یقینی بنائیں کہ اس نوڈ سے منسلک ہونے سے پہلے Orbot چل رہا ہے۔", + "order_by": "آرڈر بذریعہ", + "order_id": "ID آرڈر کریں۔", + "order_physical_card": "فزیکل کارڈ آرڈر کریں۔", + "other_settings": "دیگر ترتیبات", + "outdated_electrum_wallet_description": "Cake میں بنائے گئے نئے Bitcoin بٹوے میں اب 24 الفاظ کا بیج ہے۔ یہ لازمی ہے کہ آپ ایک نیا Bitcoin والیٹ بنائیں اور اپنے تمام فنڈز کو نئے 24 الفاظ والے والیٹ میں منتقل کریں، اور 12 الفاظ کے بیج والے بٹوے کا استعمال بند کریں۔ براہ کرم اپنے فنڈز کو محفوظ بنانے کے لیے فوری طور پر ایسا کریں۔", + "outdated_electrum_wallet_receive_warning": "اگر اس پرس میں 12 الفاظ کا بیج ہے اور اسے Cake میں بنایا گیا ہے، تو اس بٹوے میں Bitcoin جمع نہ کریں۔ اس بٹوے میں منتقل کیا گیا کوئی بھی BTC ضائع ہو سکتا ہے۔ ایک نیا 24 الفاظ والا والیٹ بنائیں (اوپر دائیں جانب مینو کو تھپتھپائیں، Wallets کو منتخب کریں، نیا والیٹ بنائیں، پھر Bitcoin کو منتخب کریں) اور فوری طور پر اپنے BTC کو وہاں منتقل کریں۔ Cake کے نئے (24-لفظوں) BTC بٹوے محفوظ ہیں۔", + "outgoing": "سبکدوش ہونے والے", + "overwrite_amount": "رقم کو اوور رائٹ کریں۔", + "pairingInvalidEvent": "ﭧﻧﻮﯾﺍ ﻂﻠﻏ ﺎﻧﺎﻨﺑ ﺍﮌﻮﺟ", + "password": "پاس ورڈ", + "paste": "چسپاں کریں۔", + "pause_wallet_creation": "Haven Wallet ۔ﮯﮨ ﻑﻮﻗﻮﻣ ﻝﺎﺤﻟﺍ ﯽﻓ ﺖﯿﻠﮨﺍ ﯽﮐ ﮯﻧﺎﻨﺑ", + "payment_id": "ادائیگی کی شناخت:", + "payment_was_received": "آپ کی ادائیگی موصول ہو گئی۔", + "pending": " (زیر التواء)", + "percentageOf": "${amount} کا", + "pin_at_top": "اوپر ${token} کو پن کریں۔", + "pin_is_incorrect": "PIN غلط ہے۔", + "pin_number": "پن نمبر", + "placeholder_contacts": "آپ کے رابطے یہاں دکھائے جائیں گے۔", + "placeholder_transactions": "آپ کے لین دین یہاں دکھائے جائیں گے۔", + "please_fill_totp": "براہ کرم اپنے دوسرے آلے پر موجود 8 ہندسوں کا کوڈ پُر کریں۔", + "please_make_selection": "اپنا بٹوہ بنانے یا بازیافت کرنے کے لیے براہ کرم ذیل میں ایک انتخاب کریں۔", + "please_reference_document": "مزید معلومات کے لیے براہ کرم نیچے دی گئی دستاویزات کا حوالہ دیں۔", + "please_select": "براہ مہربانی منتخب کریں:", + "please_select_backup_file": "براہ کرم بیک اپ فائل منتخب کریں اور بیک اپ پاس ورڈ درج کریں۔", + "please_try_to_connect_to_another_node": "براہ کرم کسی دوسرے نوڈ سے جڑنے کی کوشش کریں۔", + "polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ", + "powered_by": "${title} کے ذریعے تقویت یافتہ", + "pre_seed_button_text": "میں سمجھتا ہوں۔ مجھے میرا بیج دکھاؤ", + "pre_seed_description": "اگلے صفحے پر آپ کو ${words} الفاظ کا ایک سلسلہ نظر آئے گا۔ یہ آپ کا انوکھا اور نجی بیج ہے اور یہ آپ کے بٹوے کو ضائع یا خرابی کی صورت میں بازیافت کرنے کا واحد طریقہ ہے۔ اسے لکھنا اور اسے کیک والیٹ ایپ سے باہر کسی محفوظ جگہ پر اسٹور کرنا آپ کی ذمہ داری ہے۔", + "pre_seed_title": "اہم", + "prevent_screenshots": "اسکرین شاٹس اور اسکرین ریکارڈنگ کو روکیں۔", + "privacy": "رازداری", + "privacy_policy": "رازداری کی پالیسی", + "privacy_settings": "رازداری کی ترتیبات", + "private_key": "نجی کلید", + "proceed_after_one_minute": "اگر اسکرین 1 منٹ کے بعد آگے نہیں بڑھتی ہے تو اپنا ای میل چیک کریں۔", + "profile": "پروفائل", + "provider_error": "${provider} خرابی۔", + "public_key": "عوامی کلید", + "purchase_gift_card": "گفٹ کارڈ خریدیں۔", + "qr_fullscreen": "فل سکرین QR کوڈ کھولنے کے لیے تھپتھپائیں۔", + "qr_payment_amount": "اس QR کوڈ میں ادائیگی کی رقم شامل ہے۔ کیا آپ موجودہ قدر کو اوور رائٹ کرنا چاہتے ہیں؟", + "question_to_disable_2fa": "کیا آپ واقعی کیک 2FA کو غیر فعال کرنا چاہتے ہیں؟ بٹوے اور بعض افعال تک رسائی کے لیے اب 2FA کوڈ کی ضرورت نہیں ہوگی۔", + "receivable_balance": "قابل وصول توازن", + "receive": "وصول کریں۔", + "receive_amount": "رقم", + "received": "موصول ہوا۔", + "recipient_address": "وصول کنندہ کا پتہ", + "reconnect": "دوبارہ جڑیں۔", + "reconnect_alert_text": "کیا آپ واقعی دوبارہ جڑنا چاہتے ہیں؟", + "reconnection": "دوبارہ رابطہ", + "redeemed": "چھڑایا", + "refund_address": "رقم کی واپسی کا پتہ", + "reject": "ﺎﻧﺮﮐ ﺩﺭ", + "remaining": "باقی", + "remove": "دور", + "remove_node": "نوڈ کو ہٹا دیں۔", + "remove_node_message": "کیا آپ واقعی منتخب نوڈ کو ہٹانا چاہتے ہیں؟", + "rename": "نام تبدیل کریں۔", + "require_for_adding_contacts": "رابطوں کو شامل کرنے کی ضرورت ہے۔", + "require_for_all_security_and_backup_settings": "تمام سیکورٹی اور بیک اپ کی ترتیبات کے لیے درکار ہے۔", + "require_for_assessing_wallet": "بٹوے تک رسائی کے لیے درکار ہے۔", + "require_for_creating_new_wallets": "نئے بٹوے بنانے کی ضرورت ہے۔", + "require_for_exchanges_to_external_wallets": "۔ﮯﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻟﺩﺎﺒﺗ ﮟﯿﻣ ﮮﻮﭩﺑ ﯽﻧﻭﺮﯿﺑ", + "require_for_exchanges_to_internal_wallets": "اندرونی بٹوے میں تبادلے کی ضرورت ہے۔", + "require_for_sends_to_contacts": "رابطوں کو بھیجنے کی ضرورت ہے۔", + "require_for_sends_to_internal_wallets": "اندرونی بٹوے پر بھیجنے کے لیے درکار ہے۔", + "require_for_sends_to_non_contacts": "غیر رابطوں کو بھیجنے کی ضرورت ہے۔", + "require_pin_after": "اس کے بعد PIN کی ضرورت ہے۔", + "rescan": "دوبارہ اسکین کریں۔", + "resend_code": "براہ کرم اسے دوبارہ بھیجیں۔", + "reset": "دوبارہ ترتیب دیں۔", + "reset_password": "پاس ورڈ ری سیٹ", + "restore_active_seed": "فعال بیج", + "restore_address": "پتہ", + "restore_bitcoin_description_from_keys": "اپنی نجی کلیدوں سے تیار کردہ WIF سٹرنگ سے اپنے بٹوے کو بحال کریں۔", + "restore_bitcoin_description_from_seed": "24 الفاظ کے مجموعہ کوڈ سے اپنے بٹوے کو بحال کریں۔", + "restore_bitcoin_title_from_keys": "WIF سے بحال کریں۔", + "restore_description_from_backup": "آپ اپنی بیک اپ فائل سے پوری کیک والیٹ ایپ کو بحال کر سکتے ہیں۔", + "restore_description_from_keys": "اپنے بٹوے کو اپنی نجی کلیدوں سے محفوظ کردہ کی اسٹروکس سے بحال کریں۔", + "restore_description_from_seed": "اپنے بٹوے کو 25 لفظ یا 13 الفاظ کے مجموعہ کوڈ سے بحال کریں۔", + "restore_description_from_seed_keys": "اپنے بٹوے کو بیج / چابیاں سے واپس حاصل کریں جنہیں آپ نے محفوظ جگہ پر محفوظ کیا ہے۔", + "restore_from_date_or_blockheight": "براہ کرم یہ پرس بنانے سے چند دن پہلے کی تاریخ درج کریں۔ یا اگر آپ کو بلاک ہائیٹ معلوم ہے تو براہ کرم اس کی بجائے اسے درج کریں۔", + "restore_from_seed_placeholder": "براہ کرم اپنا بیج یہاں درج کریں یا پیسٹ کریں۔", + "restore_new_seed": "نیا بیج", + "restore_next": "اگلے", + "restore_recover": "بحال کریں۔", + "restore_restore_wallet": "والیٹ کو بحال کریں۔", + "restore_seed_keys_restore": "بیج/کیز کی بحالی", + "restore_spend_key_private": "خرچ کی کلید (نجی)", + "restore_title_from_backup": "بیک اپ سے بحال کریں۔", + "restore_title_from_keys": "چابیاں سے بحال کریں۔", + "restore_title_from_seed": "بیج سے بحال کریں۔", + "restore_title_from_seed_keys": "بیج / چابیاں سے بحال کریں۔", + "restore_view_key_private": "کلید دیکھیں (نجی)", + "restore_wallet": "والیٹ کو بحال کریں۔", + "restore_wallet_name": "بٹوے کا نام", + "restore_wallet_restore_description": "والیٹ کی بحالی کی تفصیل", + "router_no_route": "${name} کے لیے کوئی راستہ متعین نہیں ہے", + "save": "محفوظ کریں۔", + "save_backup_password": "براہ کرم یقینی بنائیں کہ آپ نے اپنا بیک اپ پاس ورڈ محفوظ کر لیا ہے۔ آپ اس کے بغیر اپنی بیک اپ فائلیں درآمد نہیں کر سکیں گے۔", + "save_backup_password_alert": "بیک اپ پاس ورڈ محفوظ کریں۔", + "save_to_downloads": "۔ﮟﯾﺮﮐ ﻅﻮﻔﺤﻣ ﮟﯿﻣ ﺯﮈﻮﻟ ﻥﺅﺍﮈ", + "saved_the_trade_id": "میں نے تجارتی ID محفوظ کر لی ہے۔", + "scan_qr_code": "پتہ حاصل کرنے کے لیے QR کوڈ اسکین کریں۔", + "scan_qr_on_device": " ۔ﮟﯾﺮﮐ ﻦﯿﮑﺳﺍ ﺮﭘ ﺲﺋﺍﻮﯾﮈ ﺭﻭﺍ ﯽﺴﮐ ﻮﮐ ﮈﻮﮐ QR ﺱﺍ", + "search": "تلاش کریں۔", + "search_add_token": "تلاش کریں / ٹوکن شامل کریں۔", + "search_category": "زمرہ تلاش کریں۔", + "search_currency": "کرنسی تلاش کریں۔", + "search_language": "زبان تلاش کریں۔", + "second_intro_content": "آپ کا Yat ایک منفرد ایموجی ایڈریس ہے جو آپ کی تمام کرنسیوں کے لیے آپ کے تمام لمبے ہیکسا ڈیسیمل پتوں کی جگہ لے لیتا ہے۔", + "second_intro_title": "ان سب پر حکمرانی کے لیے ایک ایموجی ایڈریس", + "security_and_backup": "سیکیورٹی اور بیک اپ", + "seed_alert_back": "واپس جاو", + "seed_alert_content": "بیج آپ کے بٹوے کو بازیافت کرنے کا واحد طریقہ ہے۔ کیا آپ نے اسے لکھا ہے؟", + "seed_alert_title": "توجہ", + "seed_alert_yes": "ہاں میرے پاس ہے", + "seed_choose": "بیج کی زبان کا انتخاب کریں۔", "seed_hex_form": "پرس بیج (ہیکس فارم)", - "tor_connection": "ﻦﺸﮑﻨﮐ ﺭﻮﭨ", + "seed_key": "بیج کی کلید", + "seed_language": "بیج کی زبان", + "seed_language_chinese": "چینی", + "seed_language_chinese_traditional": "چینی (روایتی)", + "seed_language_czech": "چیک", + "seed_language_dutch": "ڈچ", + "seed_language_english": "انگریزی", + "seed_language_french": "فرانسیسی", + "seed_language_german": "جرمن", + "seed_language_italian": "اطالوی", + "seed_language_japanese": "جاپانی", + "seed_language_korean": "کورین", + "seed_language_next": "اگلے", + "seed_language_portuguese": "پرتگالی", + "seed_language_russian": "روسی", + "seed_language_spanish": "ہسپانوی", + "seed_phrase_length": "ﯽﺋﺎﺒﻤﻟ ﯽﮐ ﮯﻠﻤﺟ ﮯﮐ ﺞﯿﺑ", + "seed_reminder": "اگر آپ اپنا فون کھو دیتے ہیں یا صاف کرتے ہیں تو براہ کرم یہ لکھ دیں۔", + "seed_share": "بیج بانٹیں۔", + "seed_title": "بیج", "seedtype": "سیڈ ٹائپ", "seedtype_legacy": "میراث (25 الفاظ)", "seedtype_polyseed": "پالیسیڈ (16 الفاظ)", - "seed_language_czech": "چیک", - "seed_language_korean": "کورین", - "seed_language_chinese_traditional": "چینی (روایتی)", - "ascending": "چڑھنے", - "descending": "اترتے ہوئے", - "dfx_option_description": "EUR ﺭﻭﺍ CHF ﯽﻓﺎﺿﺍ ۔ﮟﯾﺪﯾﺮﺧ ﻮﭩﭘﺮﮐ ﮫﺗﺎﺳ ﮯﮐ KYC ﮯﯿﻟ ﮯﮐ ﻦﯿﻓﺭﺎﺻ ﭧﯾﺭﻮﭘﺭﺎﮐ ﺭﻭﺍ ﮦﺩﺭﻮﺧ ﮟ", - "polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ", - "wallet_seed_legacy": "میراثی پرس کا بیج", - "default_sell_provider": " ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ", + "select_backup_file": "بیک اپ فائل کو منتخب کریں۔", + "select_buy_provider_notice": "اوپر خریدنے والا خریدنے والا منتخب کریں۔ آپ ایپ کی ترتیبات میں اپنے پہلے سے طے شدہ خریدنے والے کو ترتیب دے کر اس اسکرین کو چھوڑ سکتے ہیں۔", + "select_destination": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﻝﺰﻨﻣ ﮯﯿﻟ ﮯﮐ ﻞﺋﺎﻓ ﭖﺍ ﮏﯿﺑ ﻡﺮﮐ ﮦﺍﺮﺑ", "select_sell_provider_notice": "۔ﮟﯿﮨ ﮯﺘﮑﺳ ﮌﻮﮭﭼ ﻮﮐ ﻦﯾﺮﮑﺳﺍ ﺱﺍ ﺮﮐ ﮮﺩ ﺐﯿﺗﺮﺗ ﻮﮐ ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ ﮯﻨﭘﺍ ﮟﯿﻣ ﺕﺎﺒ", - "custom_drag": "کسٹم (ہولڈ اینڈ ڈریگ)", + "sell": "بیچنا", + "sell_alert_content": "۔ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﺱﺍ ﺎﯾ ﮟﯿﺋﺎﻨﺑ ﭧﯿﻟﺍﻭ Litecoin ﺎﯾ Bitcoin، Ethereum ﺎﻨﭘﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ۔", + "sell_monero_com_alert_content": "Monero فروخت کرنا ابھی تک تعاون یافتہ نہیں ہے۔", + "send": "بھیجیں", + "send_address": "${cryptoCurrency} پتہ", + "send_amount": "رقم:", + "send_creating_transaction": "لین دین کی تخلیق", + "send_error_currency": "کرنسی صرف نمبروں پر مشتمل ہو سکتی ہے۔", + "send_error_minimum_value": "رقم کی کم از کم قیمت 0.01 ہے۔", + "send_estimated_fee": "تخمینی فیس:", + "send_fee": "فیس:", + "send_name": "نام", + "send_new": "نئی", + "send_payment_id": "ادائیگی کی شناخت (اختیاری)", + "send_priority": "فی الحال فیس ${transactionPriority} کی ترجیح پر سیٹ ہے۔\\nٹرانزیکشن کی ترجیح سیٹنگز میں ایڈجسٹ کی جا سکتی ہے۔", + "send_sending": "بھیج رہا ہے...", + "send_success": "آپ کا ${crypto} کامیابی کے ساتھ بھیج دیا گیا۔", + "send_templates": "ٹیمپلیٹس", + "send_title": "بھیجیں", + "send_to_this_address": "اس پتے پر ${currency} ${tag} بھیجیں۔", + "send_xmr": "XMR بھیجیں۔", + "send_your_wallet": "آپ کا بٹوہ", + "sending": "بھیج رہا ہے۔", + "sent": "بھیجا", + "settings_all": "تمام", + "settings_allow_biometrical_authentication": "بایومیٹریکل تصدیق کی اجازت دیں۔", + "settings_can_be_changed_later": "ان ترتیبات کو بعد میں ایپ کی ترتیبات میں تبدیل کیا جا سکتا ہے۔", + "settings_change_language": "زبان تبدیل کریں", + "settings_change_pin": "پن تبدیل کریں۔", + "settings_currency": "کرنسی", + "settings_current_node": "موجودہ نوڈ", + "settings_dark_mode": "ڈارک موڈ", + "settings_display_balance": "ڈسپلے بیلنس", + "settings_display_on_dashboard_list": "ڈیش بورڈ کی فہرست پر ڈسپلے کریں۔", + "settings_fee_priority": "فیس کی ترجیح", + "settings_nodes": "نوڈس", + "settings_none": "کوئی نہیں۔", + "settings_only_trades": "صرف تجارت", + "settings_only_transactions": "صرف لین دین", + "settings_personal": "ذاتی", + "settings_save_recipient_address": "وصول کنندہ کا پتہ محفوظ کریں۔", + "settings_support": "حمایت", + "settings_terms_and_conditions": "شرائط و ضوابط", + "settings_title": "ترتیبات", + "settings_trades": "تجارت", + "settings_transactions": "لین دین", + "settings_wallets": "بٹوے", + "setup_2fa": "سیٹ اپ کیک 2FA", + "setup_2fa_text": " ۔ﮯﮨ ﺎﺗﺮﮐ ﻡﺎﮐ ﮯﺋﻮﮨ ﮯﺗﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ ﺎﮐ TOTP ﺮﭘ ﺭﻮﻃ ﮯﮐ ﺮﺼﻨﻋ ﯽﻘﯾﺪﺼﺗ ﮮﺮﺳﻭﺩ 2FA ﮏﯿﮐ", + "setup_pin": "PIN سیٹ اپ کریں۔", + "setup_successful": "آپ کا PIN کامیابی کے ساتھ ترتیب دیا گیا ہے!", + "setup_totp_recommended": "TOTP ۔ﮟﯾﺮﮐ ﭖﺍ ﭧﯿﺳ", + "setup_warning_2fa_text": " ۔ﯽﮔﻮﮨ ﺕﺭﻭﺮﺿ ﯽﮐ ﮯﻧﺮﮐ ﻝﺎﺤﺑ ﻮﮐ ﮮﻮﭩﺑ ﮯﻨﭘﺍ ﮯﺳ ﺞﯿﺑ ﮯﮐ ﺖﺷﺍﺩﺩﺎﯾ ﻮﮐ ﭖﺁ", + "setup_your_debit_card": "اپنا ڈیبٹ کارڈ ترتیب دیں۔", + "share": "بانٹیں", + "share_address": "پتہ شیئر کریں۔", + "show_details": "تفصیلات دکھائیں", + "show_keys": "بیج / چابیاں دکھائیں۔", + "show_market_place": "بازار دکھائیں۔", + "show_seed": "بیج دکھائیں۔", + "sign_up": "سائن اپ", + "signTransaction": "۔ﮟﯾﺮﮐ ﻂﺨﺘﺳﺩ ﺮﭘ ﻦﯾﺩ ﻦﯿﻟ", + "signup_for_card_accept_terms": "کارڈ کے لیے سائن اپ کریں اور شرائط کو قبول کریں۔", + "slidable": "سلائیڈ ایبل", + "sort_by": "ترتیب دیں", + "spend_key_private": "خرچ کی کلید (نجی)", + "spend_key_public": "خرچ کی کلید (عوامی)", + "status": "حالت:", + "subaddress_title": "ذیلی ایڈریس کی فہرست", + "subaddresses": "ذیلی پتے", + "submit_request": "درخواست بھیج دو", + "successful": "ﺏﺎﯿﻣﺎﮐ", + "support_description_guides": "عام مسائل کے لئے دستاویزات اور مدد", + "support_description_live_chat": "مفت اور تیز! تربیت یافتہ معاون نمائندے مدد کے لئے دستیاب ہیں", + "support_description_other_links": "ہماری برادریوں میں شامل ہوں یا دوسرے طریقوں سے ہمارے شراکت داروں تک پہنچیں", + "support_title_guides": "کیک پرس گائڈز", + "support_title_live_chat": "براہ راست مدد", + "support_title_other_links": "دوسرے سپورٹ لنکس", + "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ", "switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ ", - "receivable_balance": "قابل وصول توازن", - "confirmed_tx": "تصدیق", + "symbol": "ﺖﻣﻼﻋ", + "sync_status_attempting_sync": "ہم آہنگی کی کوشش کر رہا ہے۔", + "sync_status_connected": "منسلک", + "sync_status_connecting": "جڑ رہا ہے۔", + "sync_status_failed_connect": "منقطع", + "sync_status_not_connected": "منسلک نہیں", + "sync_status_starting_sync": "مطابقت پذیری شروع کر رہا ہے۔", + "sync_status_syncronized": "مطابقت پذیر", + "sync_status_syncronizing": "مطابقت پذیری", + "syncing_wallet_alert_content": "آپ کے بیلنس اور لین دین کی فہرست اس وقت تک مکمل نہیں ہو سکتی جب تک کہ یہ سب سے اوپر \"SYNCRONIZED\" نہ کہے۔ مزید جاننے کے لیے کلک/تھپتھپائیں۔", + "syncing_wallet_alert_title": "آپ کا بٹوہ مطابقت پذیر ہو رہا ہے۔", + "template": "سانچے", + "template_name": "ٹیمپلیٹ کا نام", + "third_intro_content": "Yats بھی Cake والیٹ سے باہر رہتے ہیں۔ زمین پر کسی بھی بٹوے کے پتے کو Yat سے تبدیل کیا جا سکتا ہے!", + "third_intro_title": "Yat دوسروں کے ساتھ اچھی طرح کھیلتا ہے۔", + "time": "${minutes}m ${seconds}s", + "tip": "ٹپ:", + "today": "آج", + "token_contract_address": "ٹوکن کنٹریکٹ ایڈریس", + "token_decimal": "ٹوکن اعشاریہ", + "token_name": "ٹوکن کا نام جیسے: Tether", + "token_symbol": "ٹوکن کی علامت جیسے: USDT", + "tokenID": "ID", + "tor_connection": "ﻦﺸﮑﻨﮐ ﺭﻮﭨ", + "tor_only": "صرف Tor", + "total_saving": "کل بچت", + "totp_2fa_failure": "غلط کوڈ. براہ کرم ایک مختلف کوڈ آزمائیں یا ایک نئی خفیہ کلید بنائیں۔ ایک ہم آہنگ 2FA ایپ استعمال کریں جو 8 ہندسوں کے کوڈز اور SHA512 کو سپورٹ کرتی ہو۔", + "totp_2fa_success": "کامیابی! کیک 2FA اس بٹوے کے لیے فعال ہے۔ بٹوے تک رسائی سے محروم ہونے کی صورت میں اپنے یادداشت کے بیج کو محفوظ کرنا یاد رکھیں۔", + "totp_auth_url": "TOTP AUTH URL", + "totp_code": "TOTP کوڈ", + "totp_secret_code": "TOTP خفیہ کوڈ", + "totp_verification_success": "توثیق کامیاب!", + "trade_details_copied": "${title} کو کلپ بورڈ پر کاپی کیا گیا۔", + "trade_details_created_at": "پر تخلیق کیا گیا۔", + "trade_details_fetching": "لا رہا ہے۔", + "trade_details_id": "ID", + "trade_details_pair": "جوڑا", + "trade_details_provider": "فراہم کرنے والا", + "trade_details_state": "حالت", + "trade_details_title": "تجارت کی تفصیلات", + "trade_for_not_created": "${title} کے لیے تجارت نہیں بنائی گئی ہے۔", + "trade_history_title": "تجارتی تاریخ", + "trade_id": "تجارتی ID:", + "trade_id_not_found": "ٹریڈ ${tradeId} از ${title} نہیں ملا۔", + "trade_is_powered_by": "یہ تجارت ${provider} کے ذریعے تقویت یافتہ ہے", + "trade_not_created": "تجارت پیدا نہیں ہوئی۔", + "trade_not_found": "تجارت نہیں ملی۔", + "trade_state_btc_sent": "Btc بھیجا گیا۔", + "trade_state_complete": "مکمل", + "trade_state_confirming": "تصدیق کر رہا ہے۔", + "trade_state_created": "بنایا", + "trade_state_finished": "ختم", + "trade_state_paid": "ادا کیا", + "trade_state_paid_unconfirmed": "غیر تصدیق شدہ ادائیگی", + "trade_state_pending": "زیر التواء", + "trade_state_timeout": "وقت ختم", + "trade_state_to_be_created": "پیدا کیا جائے۔", + "trade_state_traded": "تجارت کی۔", + "trade_state_trading": "تجارت", + "trade_state_underpaid": "کم معاوضہ", + "trade_state_unpaid": "بلا معاوضہ", + "trades": "تجارت", + "transaction_details_amount": "رقم", + "transaction_details_copied": "${title} کو کلپ بورڈ پر کاپی کیا گیا۔", + "transaction_details_date": "تاریخ", + "transaction_details_fee": "فیس", + "transaction_details_height": "اونچائی", + "transaction_details_recipient_address": "وصول کنندگان کے پتے", "transaction_details_source_address": "ماخذ ایڈریس", - "pause_wallet_creation": "Haven Wallet ۔ﮯﮨ ﻑﻮﻗﻮﻣ ﻝﺎﺤﻟﺍ ﯽﻓ ﺖﯿﻠﮨﺍ ﯽﮐ ﮯﻧﺎﻨﺑ", - "contractName": "ﻡﺎﻧ ﺎﮐ ﮦﺪﮨﺎﻌﻣ", - "contractSymbol": "ﺖﻣﻼﻋ ﯽﮐ ﮦﺪﮨﺎﻌﻣ", - "description": "ﻞﯿﺼﻔﺗ", - "camera_consent": "۔ﮟﯿﮭﮑﯾﺩ ﯽﺴﯿﻟﺎﭘ ﯽﺴﯾﻮﯿﺋﺍﺮﭘ ﯽﮐ ﻥﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ﮯﯿﻟ ﮯﮐ ﺕﻼ${provider}ﯿﺼﻔﺗ ۔ﺎﮔ ﮯﺋﺎﺟ ﺎﯿﮐ ﻝﺎﻤﻌﺘﺳﺍ ﮯﯿﻟ", - "no_relays": "۔ﮟﯿﮩﻧ ﮯﻠﯾﺭ ﯽﺋﻮﮐ", - "choose_relay": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﮯﻠﯾﺭ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ ﻡﺮﮐ ﮦﺍﺮﺑ", - "no_relays_message": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮯﻠﯾﺭ ﮟﯿﻣ ﮈﺭﺎﮑﯾﺭ ﺮﭩﺳﻮﻧ ﮯﻨﭘﺍ ﮦﻭ ﮧﮐ ﮟﯾﺩ ﺖﯾﺍﺪﮨ ﻮﮐ ﮦﺪﻨﻨﮐ ﻝﻮﺻﻭ ﻡﺮﮐ ﮦﺍﺮﺑ ۔", - "no_relay_on_domain": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﮯﻠﯾﺭ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ ﻡﺮﮐ ﮦﺍﺮﺑ ۔ﮯﮨ ﮟﯿﮩﻧ ﺏﺎﯿﺘﺳﺩ ﮯﻠﯾﺭ ﺎﯾ ﮯﮨ ﮟ" -} + "transaction_details_title": "لین دین کی تفصیلات", + "transaction_details_transaction_id": "ٹرانزیکشن ID", + "transaction_key": "لین دین کی کلید", + "transaction_priority_fast": "تیز", + "transaction_priority_fastest": "تیز ترین", + "transaction_priority_medium": "درمیانہ", + "transaction_priority_regular": "باقاعدہ", + "transaction_priority_slow": "سست", + "transaction_sent": "لین دین بھیجا گیا!", + "transaction_sent_notice": "اگر اسکرین 1 منٹ کے بعد آگے نہیں بڑھتی ہے، تو بلاک ایکسپلورر اور اپنا ای میل چیک کریں۔", + "transactions": "لین دین", + "transactions_by_date": "تاریخ کے لحاظ سے لین دین", + "trusted": "قابل اعتماد", + "unavailable_balance": "ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ", + "unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ", + "unconfirmed": "غیر تصدیق شدہ بیلنس", + "understand": "میں سمجھتا ہوں۔", + "unmatched_currencies": "آپ کے پرس کی موجودہ کرنسی اسکین شدہ QR سے مماثل نہیں ہے۔", + "unspent_change": "تبدیل کریں", + "unspent_coins_details_title": "غیر خرچ شدہ سککوں کی تفصیلات", + "unspent_coins_title": "غیر خرچ شدہ سکے ۔", + "unsupported_asset": "۔ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﺱﺍ ﺎﯾ ﮟﯿﺋﺎﻨﺑ ﺱﺮﭘ ﺎﮐ ﻢﺴﻗ ﯽﮐ ﮧﺛﺎﺛﺍ ﮧﺘﻓﺎﯾ ﻥﻭﺎﻌﺗ ﻡﺮﮐ ﮦﺍﺮﺑ ۔ﮟﯿﮨ ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﺖﯾﺎﻤﺣ ﯽﮐ ﯽﺋﺍﻭﺭﺭﺎﮐ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﮧﺛﺎﺛﺍ ﺱﺍ ﻢﮨ", + "upto": "${value} تک", + "use": "تبدیل کرنا", + "use_card_info_three": "ڈیجیٹل کارڈ آن لائن یا کنٹیکٹ لیس ادائیگی کے طریقوں کے ساتھ استعمال کریں۔", + "use_card_info_two": "رقوم کو امریکی ڈالر میں تبدیل کیا جاتا ہے جب پری پیڈ اکاؤنٹ میں رکھا جاتا ہے، ڈیجیٹل کرنسیوں میں نہیں۔", + "use_ssl": "SSL استعمال کریں۔", + "use_suggested": "تجویز کردہ استعمال کریں۔", + "variable_pair_not_supported": "یہ متغیر جوڑا منتخب ایکسچینجز کے ساتھ تعاون یافتہ نہیں ہے۔", + "verification": "تصدیق", + "verify_with_2fa": "کیک 2FA سے تصدیق کریں۔", + "version": "ورژن ${currentVersion}", + "view_all": "سب دیکھیں", + "view_in_block_explorer": "بلاک ایکسپلورر میں دیکھیں", + "view_key_private": "کلید دیکھیں (نجی)", + "view_key_public": "کلید دیکھیں (عوامی)", + "view_transaction_on": "لین دین دیکھیں آن", + "wallet_keys": "بٹوے کے بیج / چابیاں", + "wallet_list_create_new_wallet": "نیا والیٹ بنائیں", + "wallet_list_edit_wallet": "بٹوے میں ترمیم کریں۔", + "wallet_list_failed_to_load": "${wallet_name} والیٹ لوڈ کرنے میں ناکام۔ ${error}", + "wallet_list_failed_to_remove": "${wallet_name} والیٹ کو ہٹانے میں ناکام۔ ${error}", + "wallet_list_load_wallet": "پرس لوڈ کریں۔", + "wallet_list_loading_wallet": "${wallet_name} والیٹ لوڈ ہو رہا ہے۔", + "wallet_list_removing_wallet": "${wallet_name} والیٹ کو ہٹایا جا رہا ہے۔", + "wallet_list_restore_wallet": "والیٹ کو بحال کریں۔", + "wallet_list_title": "Monero والیٹ", + "wallet_list_wallet_name": "بٹوے کا نام", + "wallet_menu": "مینو", + "wallet_name": "بٹوے کا نام", + "wallet_name_exists": "اس نام کا پرس پہلے سے موجود ہے۔ براہ کرم ایک مختلف نام منتخب کریں یا پہلے دوسرے بٹوے کا نام تبدیل کریں۔", + "wallet_restoration_store_incorrect_seed_length": "غلط بیج کی لمبائی", + "wallet_seed": "بٹوے کا بیج", + "wallet_seed_legacy": "میراثی پرس کا بیج", + "wallet_store_monero_wallet": "مونیرو والیٹ", + "walletConnect": "WalletConnect", + "wallets": "بٹوے", + "warning": "وارننگ", + "welcome": "میں خوش آمدید", + "welcome_to_cakepay": "Cake پے میں خوش آمدید!", + "widgets_address": "پتہ", + "widgets_or": "یا", + "widgets_restore_from_blockheight": "بلاک ہائیٹ سے بحال کریں۔", + "widgets_restore_from_date": "تاریخ سے بحال کریں۔", + "widgets_seed": "بیج", + "wouoldLikeToConnect": "؟ﮯﮔ ﮟﯿﮨﺎﭼ ﺎﻧﮍﺟ", + "write_down_backup_password": "براہ کرم اپنا بیک اپ پاس ورڈ لکھیں، جو آپ کی بیک اپ فائلوں کی درآمد کے لیے استعمال ہوتا ہے۔", + "xlm_extra_info": "ایکسچینج کے لیے XLM ٹرانزیکشن بھیجتے وقت براہ کرم میمو ID بتانا نہ بھولیں۔", + "xmr_available_balance": "دستیاب بیلنس", + "xmr_full_balance": "مکمل بیلنس", + "xmr_hidden": "پوشیدہ", + "xmr_to_error": "XMR.TO غلطی", + "xmr_to_error_description": "غلط رقم۔ اعشاریہ پوائنٹ کے بعد زیادہ سے زیادہ 8 ہندسے", + "xrp_extra_info": "ایکسچینج کے لیے XRP ٹرانزیکشن بھیجتے وقت ڈیسٹینیشن ٹیگ بتانا نہ بھولیں۔", + "yat": "Yat", + "yat_address": "Yat ایڈریس", + "yat_alert_content": "Cake والیٹ کے صارفین اب ایک قسم کے ایموجی پر مبنی صارف نام کے ساتھ اپنی تمام پسندیدہ کرنسیاں بھیج اور وصول کر سکتے ہیں۔", + "yat_alert_title": "Yat کے ساتھ زیادہ آسانی سے کریپٹو بھیجیں اور وصول کریں۔", + "yat_error": "Yat غلطی", + "yat_error_content": "اس Yat کے ساتھ کوئی پتے منسلک نہیں ہیں۔ ایک اور یات آزمائیں۔", + "yat_popup_content": "اب آپ Cake Wallet میں اپنے Yat کے ساتھ کرپٹو بھیج اور وصول کر سکتے ہیں - ایک مختصر، ایموجی پر مبنی صارف نام۔ ترتیبات کی سکرین پر کسی بھی وقت Yats کا نظم کریں۔", + "yat_popup_title": "آپ کے بٹوے کا پتہ ایموجائز کیا جا سکتا ہے۔", + "yesterday": "کل", + "you_now_have_debit_card": "اب آپ کے پاس ڈیبٹ کارڈ ہے۔", + "you_pay": "تم ادا کرو", + "you_will_get": "میں تبدیل کریں۔", + "you_will_send": "سے تبدیل کریں۔", + "yy": "YY", + "zzzz": "زیڈز" +} \ No newline at end of file diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 142d9f5bf..355800e72 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -1,773 +1,774 @@ { - "welcome": "Ẹ káàbọ sí", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "Àpamọ́wọ́ t'á fi Monero, Bitcoin, Ethereum, Litecoin, àti Haven pamọ́ wà pa", - "please_make_selection": "Ẹ jọ̀wọ́, yàn dá àpamọ́wọ́ yín tàbí dá àpamọ́wọ́ yín padà n’ísàlẹ̀.", - "create_new": "Dá àpamọ́wọ́ tuntun", - "restore_wallet": "Mú àpamọ́wọ́ padà", - "monero_com": "Monero.com latí ọwọ́ Cake Wallet", - "monero_com_wallet_text": "Àpamọ́wọ́ Monero wà pa", - "haven_app": "Haven latí ọwọ́ Cake Wallet", - "haven_app_wallet_text": "Àpamọ́wọ́ Haven wà pa", - "accounts": "Àwọn àkáǹtì", - "edit": "Pààrọ̀", + "about_cake_pay": "Cake Pay jẹ́ kí ẹ lè fi owó wẹ́ẹ̀bù ra àwọn káàdì ìrajà t'á lò nínú iye ìtajà kan. Ẹ lè san wọn láìpẹ́ nítajà 150,000 nínú Amẹ́ríkà.", "account": "Àkáǹtì", + "accounts": "Àwọn àkáǹtì", + "accounts_subaddresses": "Àwọn àkáǹtì àti àwọn àdírẹ́sì kékeré", + "activate": "Fi àyè gba", + "active": "Ó títàn", + "active_cards": "Àwọn káàdì títàn", + "activeConnectionsPrompt": "Awọn asopọ ti nṣiṣe lọwọ yoo han nibi", "add": "Fikún", + "add_contact": "Fi olubasọrọ kun", + "add_custom_node": "Fikún apẹka títun t'ẹ́ pààrọ̀", + "add_custom_redemption": "Tẹ̀ iye owó t'ẹ́ fẹ́ ná", + "add_fund_to_card": "Ẹ fikún owó sí àwọn káàdì (kò tóbi ju ${value})", + "add_new_node": "Fi apẹka kún", + "add_new_word": "Fikún ọ̀rọ̀ títun", + "add_receiver": "Fikún àdírẹ́sì mìíràn (ìyàn nìyí)", + "add_secret_code": "Tabi, ṣafikun koodu aṣiri yii si ohun elo onijeri kan", + "add_tip": "Fún owó àfikún", + "add_token_disclaimer_check": "Mo ti jẹrisi adirẹsi adehun ami ati alaye nipa lilo orisun olokiki kan. Fifi irira tabi alaye ti ko tọ le ja si isonu ti owo.", + "add_token_warning": "Ma ṣe ṣatunkọ tabi ṣafikun awọn ami bi a ti fun ni aṣẹ nipasẹ awọn scammers.\nNigbagbogbo jẹrisi awọn adirẹsi ami pẹlu awọn orisun olokiki!", + "add_value": "Fikún owó", + "address": "Adirẹsi", "address_book": "Ìwé Àdírẹ́sì", - "contact": "Olùbásọ̀rọ̀", - "please_select": "Ẹ jọ̀wọ́ yàn:", - "cancel": "Fagi lé e", - "ok": "Ó dáa", - "contact_name": "Orúkọ olùbásọ̀rọ̀", - "reset": "Tún ṣe", - "save": "Pamọ́", + "address_book_menu": "Ìwé Àdírẹ́sì", + "address_detected": "A ti gbọ́ àdírẹ́sì", + "address_from_domain": "Àdírẹ́sì yìí wá láti ${domain} lórí Unstoppable Domains", + "address_from_yat": "Àdírẹ́sì yìí wá láti ${emoji} lórí Yat", + "address_label": "Orúkọ àdírẹ́sì", "address_remove_contact": "Yọ olùbásọ̀rọ̀ kúrò", "address_remove_content": "Ṣó dá ẹ lójú pé ẹ fẹ́ yọ olùbásọ̀rọ̀ yíyàn kúrò?", - "authenticated": "A ti jẹ́rìísí yín", - "authentication": "Ìfẹ̀rílàdí", - "failed_authentication": "Ìfẹ̀rílàdí pipòfo. ${state_error}", - "wallet_menu": "Mẹ́nù", - "Blocks_remaining": "Àkójọpọ̀ ${status} kikù", - "please_try_to_connect_to_another_node": "Ẹ jọ̀wọ́, gbìyànjú dárapọ̀ mọ́ apẹka mìíràn yí wọlé", - "xmr_hidden": "Bìbò", - "xmr_available_balance": "Owó tó wà ḿbí", - "xmr_full_balance": "Ìyókù owó", - "send": "Ránṣẹ́", - "receive": "Gbà", - "transactions": "Àwọn àránṣẹ́", - "incoming": "Wọ́n tó ń bọ̀", - "outgoing": "Wọ́n tó ń jáde", - "transactions_by_date": "Àwọn àránṣẹ́ t'á ti fi aago ṣa", - "trades": "Àwọn pàṣípààrọ̀", - "filter_by": "Ṣẹ́ láti", - "today": "Lénìí", - "yesterday": "Lánàá", - "received": "Owó t'á ti gbà", - "sent": "Owó t'á ti ránṣẹ́", - "pending": " pípẹ́", - "rescan": "Tún Wá", - "reconnect": "Ṣe àtúnse", - "wallets": "Àwọn àpamọ́wọ́", - "show_seed": "Wo hóró", - "show_keys": "Wo hóró / àwọn kọ́kọ́rọ́", - "address_book_menu": "Ìwé Àdírẹ́sì", - "reconnection": "Àtúnṣe", - "reconnect_alert_text": "Ṣó dá ẹ lójú pé ẹ fẹ́ ṣe àtúnse?", - "exchange": "Pàṣípààrọ̀", - "clear": "Pa gbogbo nǹkan", - "refund_address": "Àdírẹ́sì t'ẹ́ gba owó sí", - "change_exchange_provider": "Pààrọ̀ Ilé Ìfowóṣòwò", - "you_will_send": "Ṣe pàṣípààrọ̀ láti", - "you_will_get": "Ṣe pàṣípààrọ̀ sí", - "amount_is_guaranteed": "ó di dandan pé owó á wọlé", - "amount_is_estimate": "Ìdíyelé ni iye tó ń bọ̀", - "powered_by": "Láti ọwọ́ ${title}", - "error": "Àṣìṣe", - "estimated": "Ó tó a fojú díwọ̀n", - "min_value": "kò gbọ́dọ̀ kéré ju ${value} ${currency}", - "max_value": "kò gbọ́dọ̀ tóbi ju ${value} ${currency}", - "change_currency": "Pààrọ̀ irú owó", - "overwrite_amount": "Pààrọ̀ iye owó", - "qr_payment_amount": "Iye owó t'á ránṣé wà nínú àmì ìlujá yìí. Ṣé ẹ fẹ́ pààrọ̀ ẹ̀?", - "copy_id": "Ṣẹ̀dà àmì ìdánimọ̀", - "exchange_result_write_down_trade_id": "Ẹ jọ̀wọ́, kọ àmì ìdánimọ̀ pàṣípààrọ̀ sílẹ̀ kí tẹ̀síwájú.", - "trade_id": "Pàṣípààrọ̀ àmì ìdánimọ̀:", - "copied_to_clipboard": "Jíjí wò sí àtẹ àkọsílẹ̀", - "saved_the_trade_id": "Mo ti pamọ́ àmì ìdánimọ̀ pàṣípààrọ̀", - "fetching": "ń wá", - "id": "Àmì Ìdánimọ̀: ", - "amount": "Iye: ", - "payment_id": "Àmì ìdánimọ̀ àránṣẹ́: ", - "status": "Tó ń ṣẹlẹ̀: ", - "offer_expires_in": "Ìrònúdábàá máa gbẹ́mìí mì ní: ", - "trade_is_powered_by": "${provider} ń fikún pàṣípààrọ̀ yìí lágbára", - "copy_address": "Ṣẹ̀dà àdírẹ́sì", - "exchange_result_confirm": "T'ẹ́ bá tẹ̀ jẹ́rìí, ẹ máa fi ${fetchingLabel} ${from} ránṣẹ́ láti àpamọ́wọ́ yín t'á pe ${walletName} sí àdírẹ́sì t'ó ṣàfihàn òun lísàlẹ̀. Tàbí ẹ lè fi àpamọ́wọ́ mìíràn yín ránṣẹ́ sí àdírẹ́sì / àmì ìlujá lísàlẹ̀.\n\nẸ jọ̀wọ́ tẹ̀ jẹ́rìí́ tẹ̀síwájú tàbí padà sọ́dọ̀ pààrọ̀ iye náà.", - "exchange_result_description": "Ẹ gbọ́dọ̀ ránṣẹ́ iye owó tó pọ̀ jù ${fetchingLabel} ${from} sí àdírẹ́sì tó ṣàfihàn òun lójú tó ń bọ̀. T'ẹ́ bá fi iye tí kò pọ̀ jù ${fetchingLabel} ${from}, a kò lè pàṣípààrọ̀ ẹ̀. A sì kò lè dá a padà fún yín.", - "exchange_result_write_down_ID": "*Ẹ jọ̀wọ́, ṣẹ̀dà àmì ìdánimọ̀ yín tó ṣàfihàn òun lókè.", - "confirm": "Jẹ́rìísí", - "confirm_sending": "Jẹ́rìí sí ránṣẹ́", - "commit_transaction_amount_fee": "Jẹ́rìí sí àránṣẹ́\nOwó: ${amount}\nIye àfikún: ${fee}", - "sending": "Ó ń ránṣẹ́", - "transaction_sent": "Ẹ ti ránṣẹ́ ẹ̀!", - "expired": "Kíkú", - "time": "${minutes}ìṣj ${seconds}ìṣs", - "send_xmr": "Fi XMR ránṣẹ́", - "exchange_new_template": "Àwòṣe títun", - "faq": "Àwọn ìbéèrè l'a máa ń bèèrè", - "enter_your_pin": "Tẹ̀ òǹkà ìdánimọ̀ àdáni yín", - "loading_your_wallet": "A ń ṣí àpamọ́wọ́ yín", - "new_wallet": "Àpamọ́wọ́ títun", - "wallet_name": "Orúkọ àpamọ́wọ́", - "continue_text": "Tẹ̀síwájú", - "choose_wallet_currency": "Ẹ jọ̀wọ́, yàn irú owó ti àpamọ́wọ́ yín:", - "node_new": "Apẹka títun", - "node_address": "Àdírẹ́sì apẹka", - "node_port": "Ojú ìkànpọ̀ apẹka", - "login": "Orúkọ", - "password": "Ọ̀rọ̀ aṣínà", - "nodes": "Àwọn apẹka", - "node_reset_settings_title": "Tún àwọn ààtò ṣe", - "nodes_list_reset_to_default_message": "Ṣé ó dá yín lójú pé ẹ fẹ́ yí àwọn ààtò padà?", - "change_current_node": "Ṣé ó dá yín lójú pé ẹ fẹ́ pààrọ̀ apẹka lọ́wọ́ sí ${node}?", - "change": "Pààrọ̀", - "remove_node": "Yọ apẹka kúrò", - "remove_node_message": "Ṣé ó da yín lójú pé ẹ fẹ́ yọ apẹka lọwọ́ kúrò?", - "remove": "Yọ ọ́ kúrò", - "delete": "Pa á", - "add_new_node": "Fi apẹka kún", - "change_current_node_title": "Pààrọ̀ apẹka lọwọ́", - "node_test": "Dánwò", - "node_connection_successful": "Ìkànpọ̀ ti dára", - "node_connection_failed": "Ìkànpọ̀ ti kùnà", - "new_node_testing": "A ń dán apẹka títun wò", - "use": "Lo", - "digit_pin": "-díjíìtì òǹkà ìdánimọ̀ àdáni", - "share_address": "Pín àdírẹ́sì", - "receive_amount": "Iye", - "subaddresses": "Àwọn àdírẹ́sì kékeré", "addresses": "Àwọn àdírẹ́sì", - "scan_qr_code": "Yan QR koodu", - "qr_fullscreen": "Àmì ìlujá túbọ̀ máa tóbi tí o bá tẹ̀", - "rename": "Pààrọ̀ orúkọ", - "choose_account": "Yan àkáǹtì", - "create_new_account": "Dá àkáǹtì títun", - "accounts_subaddresses": "Àwọn àkáǹtì àti àwọn àdírẹ́sì kékeré", - "restore_restore_wallet": "Mú àpamọ́wọ́ padà", - "restore_title_from_seed_keys": "Fi hóró/kọ́kọ́rọ́ mú padà", - "restore_description_from_seed_keys": "Mú àpamọ́wọ́ yín padà láti hóró/kọ́kọ́rọ́ t'ẹ́ ti pamọ́ sí ibi láìléwu", - "restore_next": "Tẹ̀síwájú", - "restore_title_from_backup": "Fi ẹ̀dà nípamọ́ mú padà", - "restore_description_from_backup": "Ẹ lè fi ẹ̀dà nípamọ́ yín mú odindi Cake Wallet áàpù padà.", - "restore_seed_keys_restore": "Mú hóró/kọ́kọ́rọ́ padà", - "restore_title_from_seed": "Fi hóró mú padà", - "restore_description_from_seed": "Ẹ mú àpamọ́wọ́ yín padà láti àkànpọ̀ ọlọ́rọ̀ ẹ̀ẹ̀marùndínlọgbọ̀n tàbí ti mẹ́talá.", - "restore_title_from_keys": "Fi kọ́kọ́rọ́ ṣẹ̀dá", - "restore_description_from_keys": "Mú àpamọ́wọ́ yín padà láti àwọn àtẹ̀ nípamọ́ láti àwọn kọ́kọ́rọ́ àdáni yín", - "restore_wallet_name": "Orúkọ àpamọ́wọ́", - "restore_address": "Àdírẹ́sì", - "restore_view_key_private": "kọ́kọ́rọ́ ìrán àdáni", - "restore_spend_key_private": "kọ́kọ́rọ́ àdáni fún níná", - "restore_recover": "Mú padà", - "restore_wallet_restore_description": "Ìṣapẹrẹ mú àpamọ́wọ́ padà", - "restore_new_seed": "Hóró títun", - "restore_active_seed": "Hóró lọ́wọ́", - "restore_bitcoin_description_from_seed": "Mú àpamọ́wọ́ yín padà láti àkànpọ̀ ọlọ́rọ̀ ẹ̀ẹ̀mẹrinlélógun", - "restore_bitcoin_description_from_keys": "Mú àpamọ́wọ́ yín padà láti ọ̀rọ̀ WIF t'á ti dá láti kọ́kọ́rọ́ àdáni yín", - "restore_bitcoin_title_from_keys": "Mú padà láti WIF", - "restore_from_date_or_blockheight": "Ẹ jọ̀wọ́, tẹ̀ ìgbà ọjọ́ díẹ̀ k'ẹ́ tó ti dá àpamọ́wọ́ yìí. Tàbí ẹ lè tẹ̀ ẹ́ t'ẹ́ bá mọ gíga àkójọpọ̀.", - "seed_reminder": "Ẹ jọ̀wọ́, kọ wọnyí sílẹ̀ k'ẹ́ tó pàdánù ẹ̀rọ ìbánisọ̀rọ̀ yín", - "seed_title": "Hóró", - "seed_share": "Pín hóró", - "copy": "Ṣẹ̀dà", - "seed_language": "Ewu ọmọ", - "seed_choose": "Yan èdè hóró", - "seed_language_next": "Tẹ̀síwájú", - "seed_language_english": "Èdè Gẹ̀ẹ́sì", - "seed_language_chinese": "Èdè Ṣáínà", - "seed_language_dutch": "Èdè Nẹ́dálaǹdì", - "seed_language_german": "Èdè Jámánì", - "seed_language_japanese": "Èdè Jẹ́páànì", - "seed_language_portuguese": "Èdè Potogí", - "seed_language_russian": "Èdè Rọ́síà", - "seed_language_spanish": "Èdè Sípéènì", - "seed_language_french": "Èdè Fránsì", - "seed_language_italian": "Èdè Itálíà", - "send_title": "Ránṣẹ́", - "send_your_wallet": "Àpamọ́wọ́ yín", - "send_address": "${cryptoCurrency} àdírẹ́sì", - "send_payment_id": "Àmì ìdánimọ̀ àránṣẹ́ (ìyàn nìyí)", + "advanced_settings": "Awọn eto ilọsiwaju", + "aggressive": "Onítara", + "agree": "Jọ rò", + "agree_and_continue": "Jọ Rò àti Tẹ̀síwájú", + "agree_to": "Tẹ́ ẹ bá dá àkáǹtì ẹ jọ rò ", "all": "Gbogbo", - "send_error_minimum_value": "Ránṣẹ́ owó kò kéré dé 0.01", - "send_error_currency": "Ó yẹ kí òǹkà dá wà nínu iye", - "send_estimated_fee": "Iye àfikún l'a fojú díwọ̀n:", - "send_priority": "${transactionPriority} agbára ni owó àfikún lọ́wọ́lọ́wọ́.\nẸ lè pààrọ̀ iye agbára t'ẹ fikún àránṣẹ́ lórí àwọn ààtò", - "send_creating_transaction": "Ńṣe àránṣẹ́", - "send_templates": "Àwọn àwòṣe", - "send_new": "Títun", - "send_amount": "Iye:", - "send_fee": "Owó àfikún:", - "send_name": "Orúkọ", - "got_it": "Ó dáa", - "send_sending": "Ń Ránṣẹ́...", - "send_success": "A ti ránṣẹ́ ${crypto} yín dáadáa", - "settings_title": "Àwọn ààtò", - "settings_nodes": "Àwọn apẹka", - "settings_current_node": "Apẹka lọ́wọ́lọ́wó", - "settings_wallets": "Àwọn àpamọ́wọ́", - "settings_display_balance": "Ṣàfihàn ìyókù owó", - "settings_currency": "Iye owó", - "settings_fee_priority": "Bí iye àfikún ṣe ṣe pàtàkì", - "settings_save_recipient_address": "Pamọ́ àdírẹ́sì olùgbà", - "settings_personal": "Àdáni", - "settings_change_pin": "Pààrọ̀ òǹkà ìdánimọ̀ àdáni", - "settings_change_language": "Pààrọ̀ èdè", - "settings_allow_biometrical_authentication": "Fi àyè gba ìfẹ̀rílàdí biometrical", - "settings_dark_mode": "Ṣókùnkùn Áápù", - "settings_transactions": "Àwọn àránṣẹ́", - "settings_trades": "Àwọn pàṣípààrọ̀", - "settings_display_on_dashboard_list": "Ṣàfihàn lórí àkọsílẹ̀ tá fihàn", - "settings_all": "Gbogbo", - "settings_only_trades": "Àwọn pàṣípààrọ̀ nìkan", - "settings_only_transactions": "Àwọn àránṣẹ́ nìkan", - "settings_none": "Kòsóhun", - "settings_support": "Ìranlọ́wọ́", - "settings_terms_and_conditions": "Àwọn Òfin àti àwọn Àjọrò", - "pin_is_incorrect": "òǹkà ìdánimọ̀ àdáni kò yẹ́", - "setup_pin": "Setup òǹkà ìdánimọ̀ àdáni", - "enter_your_pin_again": "Tún òǹkà ìdánimọ̀ àdáni yín tẹ̀", - "setup_successful": "Òǹkà ìdánimọ̀ àdáni yín ti ṣe!", - "wallet_keys": "Hóró/kọ́kọ́rọ́ àpamọ́wọ́", - "wallet_seed": "Hóró àpamọ́wọ́", - "private_key": "Kọ́kọ́rọ́ àdáni", - "public_key": "Kọ́kọ́rọ́ tó kò àdáni", - "view_key_private": "Kọ́kọ́rọ́ ìwò (àdáni)", - "view_key_public": "Kọ́kọ́rọ́ ìwò (kò àdáni)", - "spend_key_private": "Kọ́kọ́rọ́ sísan (àdáni)", - "spend_key_public": "Kọ́kọ́rọ́ sísan (kò àdáni)", - "copied_key_to_clipboard": "Ti ṣeda ${key} sí àtẹ àkọsílẹ̀", - "new_subaddress_title": "Àdírẹ́sì títun", - "new_subaddress_label_name": "Orúkọ", - "new_subaddress_create": "Ṣe é", - "address_label": "Orúkọ àdírẹ́sì", - "subaddress_title": "Àkọsílẹ̀ ni nínú àwọn àdírẹ́sì tíwọn rẹ̀lẹ̀", - "trade_details_title": "Ìsọfúnni pàṣípààrọ̀", - "trade_details_id": "Àmì ìdánimọ̀:", - "trade_details_state": "Tó ń ṣẹlẹ̀", - "trade_details_fetching": "Ń mú wá", - "trade_details_provider": "Ilé pàṣípààrọ̀", - "trade_details_created_at": "Ṣíṣe ní", - "trade_details_pair": "Àwọn irú owó t'á pàṣípààrọ̀ jọ", - "trade_details_copied": "Ti ṣeda ${title} sí àtẹ àkọsílẹ̀", - "trade_history_title": "Ìtan pàṣípààrọ̀", - "transaction_details_title": "Àránṣẹ́ ìsọfúnni", - "transaction_details_transaction_id": "Àmì ìdánimọ̀ àránṣẹ́", - "transaction_details_date": "Ìgbà", - "transaction_details_height": "Gíga", - "transaction_details_amount": "Iye owó", - "transaction_details_fee": "Iye àfikún", - "transaction_details_copied": "A ṣeda ${title} sí àkọsílẹ̀", - "transaction_details_recipient_address": "Àwọn àdírẹ́sì olùgbà", - "wallet_list_title": "Àpamọ́wọ́ Monero", - "wallet_list_create_new_wallet": "Ṣe àpamọ́wọ́ títun", - "wallet_list_edit_wallet": "Ṣatunkọ apamọwọ", - "wallet_list_wallet_name": "Orukọ apamọwọ", - "wallet_list_restore_wallet": "Restore àpamọ́wọ́", - "wallet_list_load_wallet": "Load àpamọ́wọ́", - "wallet_list_loading_wallet": "Ń ṣí àpamọ́wọ́ ${wallet_name}", - "wallet_list_failed_to_load": "Ti kùnà ṣí́ àpamọ́wọ́ ${wallet_name}. ${error}", - "wallet_list_removing_wallet": "Ń yọ àpamọ́wọ́ ${wallet_name} kúrò", - "wallet_list_failed_to_remove": "Ti kùnà yọ ${wallet_name} àpamọ́wọ́ kúrò. ${error}", - "widgets_address": "Àdírẹ́sì", - "widgets_restore_from_blockheight": "Dá padà sípò láti gíga àkójọpọ̀", - "widgets_restore_from_date": "Dá padà sípò láti ìgbà", - "widgets_or": "tàbí", - "widgets_seed": "Hóró", - "router_no_route": "Ọ̀nà kò sí fún ${name}", - "error_text_account_name": "Orúkọ àkáǹtì lè ni nìkan nínú ẹyọ ọ̀rọ̀ àti òǹkà\nGígun rẹ̀ kò gbọ́dọ̀ kéré ju oókan. Gígun rẹ̀ sì kò gbọ́dọ̀ tóbi ju márùndínlógún.", - "error_text_contact_name": "Orúkọ olùbásọ̀rọ̀ kò lè ni nínú ` , ' \" ẹyọ ọ̀rọ̀.\nIye ẹyọ ọ̀rọ̀ kò gbọ́dọ̀ kéré ju oókan. Ó sì kò gbọ́dọ̀ tóbi ju méjìlélọ́gbọ̀n.", - "error_text_address": "Àdírẹ́sì àpamọ́wọ́ gbọ́dọ̀ báramu irú owó", - "error_text_node_address": "Ẹ jọ̀wọ́ tẹ̀ àdírẹ́sì iPv4", - "error_text_node_port": "Ojú ìkànpọ̀ apẹka lè ni nìkan nínú òǹkà l'áàárín òdo àti márùn-úndínlógojí lé ní ẹ̀ẹ́dẹgbẹ̀ta lé ní ọ̀kẹ́ mẹ́ta lé ní ẹ̀ẹ́dẹ́gbàta", - "error_text_node_proxy_address": "Jọwọ tẹ :, fun apẹẹrẹ 127.0.0.1:9050", - "error_text_payment_id": "Iye ẹyọ ọ̀rọ̀ nínú àmì ìdánimọ̀ àránṣẹ́ gbọ́dọ̀ wà l'áàárín aárùndínlógún dé ẹẹ́rinlélọ́gọ́ta.", - "error_text_xmr": "Iye XMR kò lè tóbi ju ìyókù.\nIye díjíìtì léyìn ẹsẹ kò gbọ́dọ̀ tóbi ju eéjìlá.", - "error_text_fiat": "Iye àránṣẹ́ kò tóbi ju ìyókù owó.\nIye díjíìtì léyìn ẹsẹ kò gbọ́dọ̀ tóbi ju eéjì.", - "error_text_subaddress_name": "Orúkọ àdírẹ́sì tó rẹ̀lẹ̀ kò ni nínú àmì ` , ' \"\nIye ẹyọ ọ̀rọ̀ gbọ́dọ̀ wà láàárín oókan àti ogún", - "error_text_amount": "Iye lè ni nìkan nínú àwọn òǹkà", - "error_text_wallet_name": "Orúkọ àpamọ́wọ́ lè ni nìkan nínú àwọn òǹkà àti ẹyọ ọ̀rọ̀ àti àmì _ -\nIye ẹyọ ọ̀rọ̀ gbọ́dọ̀ wà láàárín 1 àti 33", - "error_text_keys": "Àwọn kọ́kọ́rọ́ àpamọ́wọ́ gbọ́dọ̀ ní ẹyọ ọ̀rọ̀ mẹ́rinlélọ́gọ́ta lílà mẹ́rìndínlógún", - "error_text_crypto_currency": "Iye díjíìtì léyìn ẹsẹ kò gbọ́dọ̀ tóbi ju eéjìlá.", - "error_text_minimal_limit": "A kò tí ì ṣe pàṣípààrọ̀ tí ${provider} nítorí iye kéré ju ${min} ${currency}", - "error_text_maximum_limit": "A kò tí ì ṣe pàṣípààrọ̀ tí ${provider} nítorí iye tóbi ju ${min} ${currency}", - "error_text_limits_loading_failed": "A kò tí ì ṣe pàṣípààrọ̀ tí ${provider} nítorí a ti kùnà mú àwọn ààlà wá", - "error_text_template": "Orúkọ àwòṣe àti àdírẹ́sì kò lè ni nínú àwọn àmì ` , ' \"\nIye ẹyọ ọ̀rọ̀ náà gbọ́dọ̀ jẹ́ láàárín 1 àti 106", + "all_trades": "Gbogbo àwọn pàṣípààrọ̀", + "all_transactions": "Gbogbo àwọn àránṣẹ́", + "alphabetical": "Labidibi", + "already_have_account": "Ṣé ẹ ti ní àkáǹtì?", + "always": "Ní gbogbo àwọn ìgbà", + "amount": "Iye: ", + "amount_is_estimate": "Ìdíyelé ni iye tó ń bọ̀", + "amount_is_guaranteed": "ó di dandan pé owó á wọlé", + "and": "àti", + "anonpay_description": "Ṣe akọkọ ${type}. Awọn alabara le ${method} pẹlu eyikeyi iwo ise ati owo yoo wọle si iwe iwe yii.", + "apk_update": "Àtúnse áàpù títun wà", + "approve": "Fi ọwọ si", + "arrive_in_this_address": "${currency} ${tag} máa dé sí àdírẹ́sì yìí", + "ascending": "Goke", + "ask_each_time": "Beere lọwọ kọọkan", "auth_store_ban_timeout": "ìfòfindè ti gbẹ́mìí mì", "auth_store_banned_for": "A ti fòfin de ẹ̀ nítorí ", "auth_store_banned_minutes": " ìṣéjú", "auth_store_incorrect_password": "Òǹkà ìdánimọ̀ àdáni kọ́ ni èyí", - "wallet_store_monero_wallet": "Àpamọ́wọ́ Monero", - "wallet_restoration_store_incorrect_seed_length": "Gígùn hóró tí a máa ń lò kọ́ ni èyí", - "full_balance": "Ìyókù owó kíkún", - "available_balance": "Ìyókù owó tó wà níbẹ̀", - "hidden_balance": "Ìyókù owó dídé", - "sync_status_syncronizing": "Ń MÚDỌ́GBA", - "sync_status_syncronized": "TI MÚDỌ́GBA", - "sync_status_not_connected": "KÒ TI DÁRAPỌ̀ MỌ́ Ọ", - "sync_status_starting_sync": "Ń BẸ̀RẸ̀ RẸ́", - "sync_status_failed_connect": "ÌKÀNPỌ̀ TI KÚ", - "sync_status_connecting": "Ń DÁRAPỌ̀ MỌ́", - "sync_status_connected": "TI DÁRAPỌ̀ MỌ́", - "sync_status_attempting_sync": "Ń GBÌYÀNJÚ MÚDỌ́GBA", - "transaction_priority_slow": "Díẹ̀", - "transaction_priority_regular": "Àjùmọ̀lò", - "transaction_priority_medium": "L’áàárín", - "transaction_priority_fast": "Yára", - "transaction_priority_fastest": "Yá jù lọ", - "trade_for_not_created": "A kò tí ì ṣe pàṣípààrọ̀ ${title}", - "trade_not_created": "A kò tí ì ṣe pàṣípààrọ̀ náà", - "trade_id_not_found": "Trade ${tradeId} ti a ko ba ri ninu ${title}.", - "trade_not_found": "A kò tí ì wá pàṣípààrọ̀.", - "trade_state_pending": "Pípẹ́", - "trade_state_confirming": "Ń jẹ́rìí", - "trade_state_trading": "Ń ṣe pàṣípààrọ̀", - "trade_state_traded": "Ti ṣe pàṣípààrọ̀", - "trade_state_complete": "Ti ṣetán", - "trade_state_to_be_created": "Máa ṣe", - "trade_state_unpaid": "Kò tíì san", - "trade_state_underpaid": "Ti san iye tó kéré jù", - "trade_state_paid_unconfirmed": "Ti san. A kò tíì jẹ́rìí ẹ̀", - "trade_state_paid": "Ti san", - "trade_state_btc_sent": "Ti san BTC", - "trade_state_timeout": "Ti gbẹ́mìí mì", - "trade_state_created": "Ti ṣe", - "trade_state_finished": "Ti ṣetán", - "change_language": "Pààrọ̀ èdè", - "change_language_to": "Pààrọ̀ èdè sí ${language}?", - "paste": "Fikún ẹ̀dà yín", - "restore_from_seed_placeholder": "Ẹ jọ̀wọ́ tẹ̀ hóró yín tàbí fikún ẹ̀dà hóró ḿbí.", - "add_new_word": "Fikún ọ̀rọ̀ títun", - "incorrect_seed": "Ọ̀rọ̀ tí a tẹ̀ kì í ṣe èyí.", - "biometric_auth_reason": "Ya ìka ọwọ́ yín láti ṣe ìfẹ̀rílàdí", - "version": "Àtúnse ${currentVersion}", - "extracted_address_content": "Ẹ máa máa fi owó ránṣẹ́ sí\n${recipient_name}", - "card_address": "Àdírẹ́sì:", - "buy": "Rà", - "sell": "Tà", - "placeholder_transactions": "A máa fihàn àwọn àránṣẹ́ yín ḿbí", - "placeholder_contacts": "A máa fihàn àwọn olùbásọ̀rọ̀ yín ḿbí", - "template": "Àwòṣe", - "confirm_delete_template": "Ìṣe yìí máa yọ àwòṣe yìí kúrò. Ṣé ẹ fẹ́ tẹ̀síwájú?", - "confirm_delete_wallet": "Ìṣe yìí máa yọ àpamọ́wọ́ yìí kúrò. Ṣé ẹ fẹ́ tẹ̀síwájú?", - "change_wallet_alert_title": "Ẹ pààrọ̀ àpamọ́wọ́ yìí", - "change_wallet_alert_content": "Ṣe ẹ fẹ́ pààrọ̀ àpamọ́wọ́ yìí sí ${wallet_name}?", - "creating_new_wallet": "Ń dá àpamọ́wọ́ títun", - "creating_new_wallet_error": "Àṣìṣe: ${description}", - "seed_alert_title": "Ẹ wo", - "seed_alert_content": "Hóró ni ọ̀nà nìkan kí ṣẹ̀dà àpamọ́wọ́ yín. Ṣé ẹ ti kọ ọ́ sílẹ̀?", - "seed_alert_back": "Padà sọ́dọ̀", - "seed_alert_yes": "Mo ti kọ ọ́", - "exchange_sync_alert_content": "Ẹ jọ̀wọ́ dúró kí a ti múdọ́gba àpamọ́wọ́ yín", - "pre_seed_title": "Ó TI ṢE PÀTÀKÌ", - "pre_seed_description": "Ẹ máa wo àwọn ọ̀rọ̀ ${words} lórí ojú tó ń bọ̀. Èyí ni hóró aládàáni yín tó kì í jọra. Ẹ lè fi í nìkan dá àpamọ́wọ́ yín padà sípò tí àṣìṣe tàbí ìbàjẹ́ bá ṣẹlẹ̀. Hóró yín ni ẹ gbọ́dọ̀ kọ sílẹ̀ àti pamọ́ síbí tó kò léwu níta Cake Wallet.", - "pre_seed_button_text": "Mo ti gbọ́. O fi hóró mi hàn mi", - "provider_error": "Àṣìṣe ${provider}", - "use_ssl": "Lo SSL", - "trusted": "A ti fọkàn ẹ̀ tán", - "color_theme": "Àwọn ààtò àwọ̀", - "light_theme": "Funfun bí eérú", - "bright_theme": "Funfun", - "dark_theme": "Dúdú", - "enter_your_note": "Tẹ̀ àkọsílẹ̀ yín", - "note_optional": "Àkọsílẹ̀ (ìyàn nìyí)", - "note_tap_to_change": "Àkọsílẹ̀ (ẹ tẹ̀ láti pààrọ̀)", - "view_in_block_explorer": "Wo lórí olùṣèwádìí àkójọpọ̀", - "view_transaction_on": "Wo pàṣípààrọ̀ lórí ", - "transaction_key": "Kọ́kọ́rọ́ pàṣípààrọ̀", - "confirmations": "Àwọn ẹ̀rí", - "recipient_address": "Àdírẹ́sì olùgbà", - "extra_id": "Àmì ìdánimọ̀ tó fikún:", - "destination_tag": "Orúkọ tí ìbí tó a ránṣẹ́ sí:", - "memo": "Àkọsílẹ̀:", - "backup": "Ṣẹ̀dà", - "change_password": "Pààrọ̀ ọ̀rọ̀ aṣínà", - "backup_password": "Ṣẹ̀dà ọ̀rọ̀ aṣínà", - "write_down_backup_password": "Ẹ jọ̀wọ́ ẹ̀dà ọ̀rọ̀ aṣínà ti ẹ̀dà nípamọ́ yín tó máa ń bá yín ṣí àkọsílẹ̀ yín l'ẹ kọ sílẹ̀.", - "export_backup": "Sún ẹ̀dà nípamọ́ síta", - "save_backup_password": "Ẹ jọ̀wọ́ dájú pé ẹ ti pamọ́ ọ̀rọ̀ aṣínà ti ẹ̀dà nípamọ́ yín. Ti ẹ kò bá ni í, ẹ kò lè ṣí àwọn àkọsílẹ̀ nípamọ́ yín.", - "backup_file": "Ṣẹ̀dà akọsílẹ̀", - "edit_backup_password": "Pààrọ̀ ọ̀rọ̀ aṣínà", - "save_backup_password_alert": "Pamọ́ ọ̀rọ̀ aṣínà ti ẹ̀dà", - "change_backup_password_alert": "Ẹ kò lè fi ọ̀rọ̀ aṣínà títun ti ẹ̀dà nípamọ́ ṣí àwọn àkọsílẹ̀ nípamọ́ tẹ́lẹ̀tẹ́lẹ̀ yín. Ẹ máa fi ọ̀rọ̀ aṣínà ti ẹ̀dà nípamọ́ títun ṣí àwọn àkọsílẹ̀ nípamọ́ títun nìkan. Ṣé ó dá ẹ lójú pé ẹ fẹ́ pààrọ̀ aṣínà ti ẹ̀dà nípamọ́?", - "enter_backup_password": "Tẹ̀ ọ̀rọ̀ aṣínà ti ẹ̀dà ḿbí", - "select_backup_file": "Select backup file", - "import": "gbe wọle", - "please_select_backup_file": "Ẹ jọ̀wọ́ yan àkọsílẹ̀ nípamọ́ àti tẹ̀ ọ̀rọ̀ aṣínà ti ẹ̀dà.", - "fixed_rate": "Iye t'á ṣẹ́ owó sí ò ní pààrọ̀", - "fixed_rate_alert": "Ẹ lè tẹ̀ iye owó tó ń bọ̀ tí iye t'a ṣẹ́ owó sí bá is checked. Ṣé ẹ fẹ́ sún ipò ti iye t'á ṣẹ́ owó sí ò ní pààrọ̀ mọ́?", - "xlm_extra_info": "Ẹ jọ̀wọ́ ẹ kò gbàgbé pèsè àmì ìdánimọ̀ àkọsílẹ̀ t'ẹ́ ń bá ránṣẹ́ pàṣípààrọ̀ ti XLM yín sí ilé ìfowóṣòwò", - "xrp_extra_info": "Ẹ jọ̀wọ́ ẹ kò gbàgbé pèsè orúkọ̀ àdírẹ́sì ti a ránṣẹ́ sí t'ẹ́ bá ránṣẹ pàṣípààrọ̀ ti XRP yín sílé ìfowóṣòwò", - "exchange_incorrect_current_wallet_for_xmr": "T'ẹ́ bá fẹ́ pàṣípààrọ̀ XMR láti ìyókù owó Cake Wallet yín, ẹ jọ̀wọ́ kọ́kọ́ sún àpamọ́wọ́ Monero mọ́.", - "confirmed": "A ti jẹ́rìí ẹ̀", - "unconfirmed": "A kò tí ì jẹ́rìí ẹ̀", - "displayable": "A lè ṣàfihàn ẹ̀", - "submit_request": "Ṣé ìbéèrè", - "buy_alert_content": "Lọwọlọwọ a ṣe atilẹyin rira Bitcoin, Ethereum, Litecoin, ati Monero. Jọwọ ṣẹda tabi yipada si Bitcoin, Ethereum, Litecoin, tabi apamọwọ Monero.", - "sell_alert_content": "Lọwọlọwọ a ṣe atilẹyin tita Bitcoin, Ethereum ati Litecoin nikan. Jọwọ ṣẹda tabi yipada si Bitcoin, Ethereum tabi apamọwọ Litecoin rẹ.", - "outdated_electrum_wallet_description": "Àwọn àpamọ́wọ́ títun Bitcoin ti a ti dá nínú Cake Wallet lọ́wọ́lọ́wọ́. Àwọn àpamọ́wọ́ títun t'á dá nínú Cake Wallet ni hóró tó ní ọ̀rọ̀ mẹ́rinlélógún. Ẹ gbọ́dọ̀ dá àpamọ́wọ́. Ẹ sì sún gbogbo owó yín sí àpamọ́wọ́ títun náà tó dá lórí ọ̀rọ̀ mẹ́rinlélógún. Ẹ sì gbọ́dọ̀ yé lo àwọn àpamọ́wọ́ tó dá lórí hóró tó ní ọ̀rọ̀ méjìlá. Ẹ jọ̀wọ́ ṣe èyí láìpẹ́ kí ẹ ba owó yín.", - "understand": "Ó ye mi", - "apk_update": "Àtúnse áàpù títun wà", - "buy_bitcoin": "Ra Bitcoin", - "buy_with": "Rà pẹ̀lú", - "moonpay_alert_text": "Iye owó kò gbọ́dọ̀ kéré ju ${minAmount} ${fiatCurrency}", - "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.", - "do_not_show_me": "Kò fi eléyìí hàn mi mọ́", - "unspent_coins_title": "Àwọn owó ẹyọ t'á kò tí ì san", - "unspent_coins_details_title": "Àwọn owó ẹyọ t'á kò tí ì san", - "freeze": "Tì pa", - "frozen": "Ó l'a tì pa", - "coin_control": "Ìdarí owó ẹyọ (ìyàn nìyí)", - "address_detected": "A ti gbọ́ àdírẹ́sì", - "address_from_domain": "Àdírẹ́sì yìí wá láti ${domain} lórí Unstoppable Domains", - "add_receiver": "Fikún àdírẹ́sì mìíràn (ìyàn nìyí)", - "manage_yats": "Bójú Yats", - "yat_alert_title": "Lílò Yat láti ránṣẹ́ àti gba owó dùn ṣe pọ̀ ju lọ", - "yat_alert_content": "Àwọn olùṣàmúlò ti Cake Wallet lè fi orúkọ olùṣàmúlò t'á dá lórí emójì tó kì í jọra ránṣẹ́ àti gba gbogbo àwọn irú owó tíwọn yàn láàyò lọ́wọ́lọ́wọ́.", - "get_your_yat": "Gba Yat yín", - "connect_an_existing_yat": "So Yat wíwà", - "connect_yats": "So àwọn Yat", - "yat_address": "Àdírẹ́sì Yat", - "yat": "Yat", - "address_from_yat": "Àdírẹ́sì yìí wá láti ${emoji} lórí Yat", - "yat_error": "Àṣìṣe Yat", - "yat_error_content": "Kò sí àdírẹ́sìkádírẹ́sì tó so Yat yìí. Ẹ gbìyànjú Yat mìíràn", - "choose_address": "\n\nẸ jọ̀wọ́ yan àdírẹ́sì:", - "yat_popup_title": "Ẹ lè dá àpamọ́wọ́ yín láti emójì.", - "yat_popup_content": "Ẹ lè fi Yat yín (orúkọ olùṣàmúlò kúkurú t'á dá lórí emójì) ránṣẹ́ àti gba owó nínú Cake Wallet lọ́wọ́lọ́wọ́. Bójú Yats lórí ojú ààtò lígbàkúgbà.", - "second_intro_title": "Àdírẹ́sì kan t'á dá láti emójì tó pàṣẹ gbogbo ohun wà", - "second_intro_content": "Àdírẹ́sì kan tó dá lórí emójì tó kì í jọra ni Yat yín. Ó rọ́pò gbogbo àwọn àdírẹ́sì gígùn yín tó dá lórí ìlà mẹ́rìndínlógún ti gbogbo àwọn iye owó yín.", - "third_intro_title": "Àlàáfíà ni Yat àti àwọn ìmíìn jọ wà", - "third_intro_content": "A sì lè lo Yats níta Cake Wallet. A lè rọ́pò Àdírẹ́sì kankan àpamọ́wọ́ fún Yat!", - "learn_more": "Túbọ̀ kọ́", - "search": "Wá", - "search_language": "Wá èdè", - "search_currency": "Wá irú owó", - "new_template": "Àwòṣe títun", - "electrum_address_disclaimer": "A dá àwọn àdírẹ́sì títun ní gbogbo àwọn ìgbà t'ẹ́ lo ó kan ṣùgbọ́n ẹ lè tẹ̀síwájú lo àwọn àdírẹ́sì tẹ́lẹ̀tẹ́lẹ̀.", - "wallet_name_exists": "Ẹ ti ní àpamọ́wọ́ pẹ̀lú orúkọ̀ yẹn. Ẹ jọ̀wọ́ yàn orúkọ̀ tó yàtọ̀ tàbí pààrọ̀ orúkọ ti àpamọ́wọ́ tẹ́lẹ̀.", - "market_place": "Ọjà", - "cake_pay_title": "Àwọn káàdì ìrajà t'á lò nínú ìtajà kan ti Cake Pay", - "cake_pay_subtitle": "Ra àwọn káàdì ìrajà t'á lò nínú ìtajà kan fún owó tí kò pọ̀ (USA nìkan)", - "cake_pay_web_cards_title": "Àwọn káàdì wẹ́ẹ̀bù ti Cake Pay", - "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", - "about_cake_pay": "Cake Pay jẹ́ kí ẹ lè fi owó wẹ́ẹ̀bù ra àwọn káàdì ìrajà t'á lò nínú iye ìtajà kan. Ẹ lè san wọn láìpẹ́ nítajà 150,000 nínú Amẹ́ríkà.", - "cake_pay_account_note": "Ẹ fi àdírẹ́sì ímeèlì nìkan forúkọ sílẹ̀ k'ẹ́ rí àti ra àwọn káàdì. Ẹ lè fi owó tó kéré jù ra àwọn káàdì kan!", - "already_have_account": "Ṣé ẹ ti ní àkáǹtì?", - "create_account": "Dá àkáǹtì", - "privacy_policy": "Òfin Aládàáni", - "welcome_to_cakepay": "Ẹ káàbọ̀ sí Cake Pay!", - "sign_up": "Forúkọ sílẹ̀", - "forgot_password": "Ẹ ti gbàgbé ọ̀rọ̀ aṣínà", - "reset_password": "Tún ọ̀rọ̀ aṣínà ṣe", - "gift_cards": "Àwọn káàdì ìrajà t'á lò nínú iye kan ìtajà", - "setup_your_debit_card": "Dá àwọn káàdì ìrajà yín", - "no_id_required": "Ẹ kò nílò àmì ìdánimọ̀. Ẹ lè fikún owó àti san níbikíbi", - "how_to_use_card": "Báyìí ni wọ́n ṣe ń lo káàdì yìí.", - "purchase_gift_card": "Ra káàdì ìrajà t'á lò nínú irú kan ìtajà", - "verification": "Ìjẹ́rìísí", - "fill_code": "Ẹ jọ̀wọ́ tẹ̀ ọ̀rọ̀ ìjẹ́rìísí t'á ti ránṣẹ́ sí ímeèlì yín.", - "dont_get_code": "Ṣé ẹ ti gba ọ̀rọ̀ ìdánimọ̀?", - "resend_code": "Ẹ jọ̀wọ́ tún un ránṣé", - "debit_card": "Káàdì ìrajà", - "cakepay_prepaid_card": "Káàdì ìrajà ti CakePay", - "no_id_needed": "Ẹ kò nílò àmì ìdánimọ̀!", - "frequently_asked_questions": "Àwọn ìbéèrè la máa ń béèrè", - "debit_card_terms": "Òfin ti olùṣe àjọrò káàdì ìrajà bójú irú ọ̀nà t'á pamọ́ àti a lo òǹkà ti káàdì ìrajà yín (àti ọ̀rọ̀ ìdánimọ̀ tí káàdì náà) nínú àpamọ́wọ́ yìí.", - "please_reference_document": "Ẹ jọ̀wọ́ fi àwọn àkọsílẹ̀ l’ábẹ́ túbọ̀ mọ ìsọfúnni.", - "cardholder_agreement": "Àjọrò olùṣe káàdì ìrajà", - "e_sign_consent": "Jẹ́rìí sí lórí ayélujára", - "agree_and_continue": "Jọ Rò àti Tẹ̀síwájú", - "email_address": "Àdírẹ́sì ímeèlì", - "agree_to": "Tẹ́ ẹ bá dá àkáǹtì ẹ jọ rò ", - "and": "àti", - "enter_code": "Tẹ̀ ọ̀rọ̀", - "congratulations": "Ẹ kúuṣẹ́ ooo!", - "you_now_have_debit_card": "Ẹ ni káàdì ìrajà lọ́wọ́lọ́wọ́", - "min_amount": "kò kéré ju: ${value}", - "max_amount": "kò tóbi ju: ${value}", - "enter_amount": "Tẹ̀ iye", - "billing_address_info": "Tí ọlọ́jà bá bèèrè àdírẹ́sì sísan yín, fún òun ni àdírẹ́sì t'á ránṣẹ́ káàdì yìí sí", - "order_physical_card": "Bèèrè káàdì t'ara", - "add_value": "Fikún owó", - "activate": "Fi àyè gba", - "get_a": "Gba ", - "digital_and_physical_card": " káàdì ìrajà t'ara àti ti ayélujára", - "get_card_note": " t'ẹ lè fikún owó ayélujára. Ẹ kò nílò ìṣofúnni àfikún!", - "signup_for_card_accept_terms": "Ẹ f'orúkọ sílẹ̀ láti gba káàdì àti àjọrò.", - "add_fund_to_card": "Ẹ fikún owó sí àwọn káàdì (kò tóbi ju ${value})", - "use_card_info_two": "A pààrọ̀ owó sí owó Amẹ́ríkà tó bá wà nínú àkanti t'á ti fikún tẹ́lẹ̀tẹ́lẹ̀. A kò kó owó náà nínú owó ayélujára.", - "use_card_info_three": "Ẹ lo káàdí ayélujára lórí wẹ́ẹ̀bù tàbí ẹ lò ó lórí àwọn ẹ̀rọ̀ ìrajà tíwọn kò kò.", - "optionally_order_card": "Ẹ lè fi ìyàn bèèrè káàdì t'ara.", - "hide_details": "Dé ìsọfúnni kékeré", - "show_details": "Fi ìsọfúnni kékeré hàn", - "upto": "kò tóbi ju ${value}", - "discount": "Pamọ́ ${value}%", - "gift_card_amount": "owó ìyókù káàdì", - "bill_amount": "Iye ìwé owó", - "you_pay": "Ẹ sàn", - "tip": "Owó àfikún:", - "custom": "Ohun t'á ti pààrọ̀", - "by_cake_pay": "láti ọwọ́ Cake Pay", - "expires": "Ó parí", - "mm": "Os", - "yy": "Ọd", - "online": "Lórí ayélujára", - "offline": "kò wà lórí ayélujára", - "gift_card_number": "Òǹkà káàdì ìrajì", - "pin_number": "Òǹkà ìdánimọ̀ àdáni", - "total_saving": "Owó t'ẹ́ ti pamọ́", - "last_30_days": "Ọ̀jọ̀ mọ́gbọ̀n tó kọjà", - "avg_savings": "Ìpamọ́ l’óòrèkóòrè", - "view_all": "Wo gbogbo nǹkan kan", - "active_cards": "Àwọn káàdì títàn", - "delete_account": "Pa ìṣàmúlò", - "cards": "Àwọn káàdì", - "active": "Ó títàn", - "redeemed": "Ó lílò", - "gift_card_balance_note": "Àwọn káàdì ìrajà t'á lò nínú irú kan ìtajà tíwọn ṣì ní owó máa fihàn ḿbí", - "gift_card_redeemed_note": "Àwọn káàdì ìrajà t'á lò nínú irú kan ìtajà t'ẹ́ ti lò máa fihàn ḿbí", - "logout": "Jáde", - "add_tip": "Fún owó àfikún", - "percentageOf": "láti ${amount}", - "is_percentage": "jẹ́", - "search_category": "Wá nínú ẹgbẹ́", - "mark_as_redeemed": "Fún orúkọ lílò", - "more_options": "Ìyàn àfikún", - "awaiting_payment_confirmation": "À ń dúró de ìjẹ́rìísí àránṣẹ́", - "transaction_sent_notice": "Tí aṣàfihàn kò bá tẹ̀síwájú l'áàárín ìṣẹ́jú kan, ẹ tọ́ olùṣèwádìí àkójọpọ̀ àti ímeèlì yín wò.", - "agree": "Jọ rò", - "in_store": "A níyí", - "generating_gift_card": "À ń dá káàdì ìrajà t'á lò nínú irú kan ìtajà", - "payment_was_received": "Àránṣẹ́ yín ti dé.", - "proceed_after_one_minute": "Tí aṣàfihàn kò bá tẹ̀síwájú l'áàárín ìṣẹ́jú kan, ẹ tọ́ ímeèlì yín wò.", - "order_id": "Àmì ìdánimọ̀ ti ìbéèrè", - "gift_card_is_generated": "A ti dá káàdí ìrajà t'á lò nínú irú kan ìtajà", - "open_gift_card": "Ṣí káàdí ìrajà t'á lò nínú irú kan ìtajà", - "contact_support": "Bá ìranlọ́wọ́ sọ̀rọ̀", - "gift_cards_unavailable": "A lè fi Monero, Bitcoin, àti Litecoin nìkan ra káàdí ìrajà t'á lò nínú irú kan ìtajà lọ́wọ́lọ́wọ́", - "introducing_cake_pay": "Ẹ bá Cake Pay!", - "cake_pay_learn_more": "Láìpẹ́ ra àti lo àwọn káàdí ìrajà t'á lò nínú irú kan ìtajà nínú áàpù!\nẸ tẹ̀ òsì de ọ̀tún láti kọ́ jù.", + "authenticated": "A ti jẹ́rìísí yín", + "authentication": "Ìfẹ̀rílàdí", + "auto_generate_subaddresses": "Aṣiṣe Ibi-Afọwọkọ", "automatic": "Ó máa ń ṣàdédé", - "fixed_pair_not_supported": "A kì í ṣe k'á fi àwọn ilé pàṣípààrọ̀ yìí ṣe pàṣípààrọ̀ irú owó méji yìí", - "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ìí", - "none_of_selected_providers_can_exchange": "Àwọn ilé pàṣípààrọ̀ yíyàn kò lè ṣe pàṣípààrọ̀ yìí", - "choose_one": "Ẹ yàn kan", - "choose_from_available_options": "Ẹ yàn láti àwọn ìyàn yìí:", - "custom_redeem_amount": "Iye owó l'á máa ná", - "add_custom_redemption": "Tẹ̀ iye owó t'ẹ́ fẹ́ ná", - "remaining": "ìyókù", - "delete_wallet": "Pa àpamọ́wọ́", - "delete_wallet_confirm_message": "Ṣó dá ẹ lójú pé ẹ fẹ́ pa àpamọ́wọ́ ${wallet_name}?", - "low_fee": "Owó àfikún kékeré", - "low_fee_alert": "Ẹ ń fi owó àfikún kékeré fún àwọn àránṣẹ́ yín lágbára. Eleyìí lè pẹ́ gba àránṣẹ́ yín. Ó sì lè dá àwọn iye mìíràn t'á ṣẹ́ owó sí. Ó sì lè pa àwọn pàṣípààrọ̀. A dábàá pé k'ẹ́ lo owó àfikún títobi láti ṣe àṣejèrè.", - "ignor": "Ṣàìfiyèsí", - "use_suggested": "Lo àbá", - "do_not_share_warning_text": "Ẹ kò pín wọnyìí sí ẹnikẹ́ni. Ẹ sì kò pin wọnyìí sí ìranlọ́wọ́. Ẹnikẹ́ni lè jí owó yín! Wọ́n máa jí owó yín!", - "help": "ìranlọ́wọ́", - "all_transactions": "Gbogbo àwọn àránṣẹ́", - "all_trades": "Gbogbo àwọn pàṣípààrọ̀", - "connection_sync": "Ìkànpọ̀ àti ìbádọ́gba", - "security_and_backup": "Ìṣọ́ àti ẹ̀dà nípamọ́", - "create_backup": "Ṣẹ̀dà nípamọ́", - "privacy_settings": "Ààtò àdáni", - "privacy": "Ìdáwà", - "display_settings": "Fihàn àwọn ààtò", - "other_settings": "Àwọn ààtò mìíràn", - "require_pin_after": "Ẹ nílò òǹkà ìdánimọ̀ àdáni láàárín", - "always": "Ní gbogbo àwọn ìgbà", - "minutes_to_pin_code": "${minute} ìṣẹ́jú", - "disable_exchange": "Pa ilé pàṣípààrọ̀", - "advanced_settings": "Awọn eto ilọsiwaju", - "settings_can_be_changed_later": "Ẹ lè pààrọ̀ àwọn ààtò yìí nínú ààtò áàpù t’ó bá yá", - "add_custom_node": "Fikún apẹka títun t'ẹ́ pààrọ̀", - "disable_fiat": "Pa owó tí ìjọba pàṣẹ wa lò", - "fiat_api": "Ojú ètò áàpù owó tí ìjọba pàṣẹ wa lò", - "disabled": "Wọ́n tí a ti pa", - "enabled": "Wọ́n tíwọn ti tan", - "tor_only": "Tor nìkan", - "unmatched_currencies": "Irú owó ti àpamọ́wọ́ yín kì í ṣe irú ti yíya àmì ìlujá", - "contact_list_contacts": "Àwọn olùbásọ̀rọ̀", - "contact_list_wallets": "Àwọn àpamọ́wọ́ mi", - "bitcoin_payments_require_1_confirmation": "Àwọn àránṣẹ́ Bitcoin nílò ìjẹ́rìísí kan. Ó lè lo ìṣéjú ogun tàbí ìṣéjú jù. A dúpẹ́ fún sùúrù yín! Ẹ máa gba ímeèlì t'ó bá jẹ́rìísí àránṣẹ́ náà.", - "send_to_this_address": "Ẹ fi ${currency} ${tag}ránṣẹ́ sí àdírẹ́sì yìí", - "arrive_in_this_address": "${currency} ${tag} máa dé sí àdírẹ́sì yìí", - "do_not_send": "Ẹ kò ránṣ", - "error_dialog_content": "Àṣìṣe ti dé.\n\nẸ jọ̀wọ́, fi àkọsílẹ̀ àṣìṣe ránṣẹ́ sí ẹgbẹ́ ìranlọ́wọ́ wa kí áàpù wa bá túbọ̀ dára.", - "cold_or_recover_wallet": "Fi owo aisan tabi yiyewo owo iwe iwe", - "please_wait": "Jọwọ saa", - "sweeping_wallet": "Fi owo iwe iwe wofo", - "sweeping_wallet_alert": "Yio kọja pada si ikan yii. Kì yoo daadaa leede yii tabi owo ti o ti fi se iwe iwe naa yoo gbe.", - "invoice_details": "Iru awọn ẹya ọrọ", - "donation_link_details": "Iru awọn ẹya ọrọ ti o funni", - "anonpay_description": "Ṣe akọkọ ${type}. Awọn alabara le ${method} pẹlu eyikeyi iwo ise ati owo yoo wọle si iwe iwe yii.", - "create_invoice": "Ṣe iwe iwe", - "create_donation_link": "Ṣe kọọkan alabara asopọ", - "optional_email_hint": "Ṣeto imọ-ẹrọ iye fun owo ti o gbọdọjọ", - "optional_description": "Ṣeto ẹru iye", - "optional_name": "Ṣeto orukọ ti o ni", - "clearnet_link": "Kọja ilọ oke", - "onion_link": "Kọja ilọ alubosa", - "decimal_places_error": "Oọ̀rọ̀ ayipada ti o wa ni o dara julọ", - "edit_node": "Tun awọn ọwọnrin ṣiṣe", - "settings": "Awọn aseṣe", - "sell_monero_com_alert_content": "Kọ ju lọwọ Monero ko ṣe ni ibamu", - "error_text_input_below_minimum_limit": "Iye jọwọ ni o kere ti o wọle diẹ", - "error_text_input_above_maximum_limit": "Iye jọwọ ni o yẹ diẹ ti o wọle diẹ", - "show_market_place": "Wa Sopọ Pataki", - "prevent_screenshots": "Pese asapọ ti awọn ẹrọ eto aṣa", - "profile": "profaili", - "close": "sunmo", - "modify_2fa": "Fi iṣiro 2FA sii Cake", - "disable_cake_2fa": "Ko 2FA Cake sii", - "question_to_disable_2fa": "Ṣe o wa daadaa pe o fẹ ko 2FA Cake? Ko si itumọ ti a yoo nilo lati ranse si iwe iwe naa ati eyikeyi iṣẹ ti o ni.", - "disable": "Ko si", - "setup_2fa": "Ṣeto Cake 2FA", - "verify_with_2fa": "Ṣeẹda pẹlu Cake 2FA", - "totp_code": "Koodu TOTP", - "please_fill_totp": "Jọwọ bọ ti ẹrọ ti o wọle ni 8-digits ti o wa ni eto miiran re", - "totp_2fa_success": "Pelu ogo! Cake 2FA ti fi sii lori iwe iwe yii. Tọ, mọ iye ẹrọ miiran akojọrọ jẹki o kọ ipin eto.", - "totp_verification_success": "Ìbẹrẹ dọkita!", - "totp_2fa_failure": "Koodu ti o daju ko ri. Jọwọ jẹ koodu miiran tabi ṣiṣẹ iwe kiakia. Lo fun 2FA eto ti o ba ṣe ni jẹ 2FA ti o gba idaniloju 8-digits ati SHA512.", - "enter_totp_code": "Jọwọ pọ koodu TOTP.", - "add_secret_code": "Tabi, ṣafikun koodu aṣiri yii si ohun elo onijeri kan", - "totp_secret_code": "Koodu iye TOTP", - "setup_2fa_text": "Akara oyinbo 2FA ṣiṣẹ ni lilo TOTP bi ifosiwewe ijẹrisi keji.\n\nAkara oyinbo 2FA's TOTP nilo SHA-512 ati atilẹyin oni-nọmba 8; eyi pese aabo ti o pọ sii. Alaye diẹ sii ati awọn ohun elo atilẹyin ni a le rii ninu itọsọna naa.", - "setup_totp_recommended": "Ṣeto TOTP", - "disable_buy": "Ko iṣọrọ ọja", - "disable_sell": "Ko iṣọrọ iṣọrọ", - "cake_2fa_preset": "Cake 2FA Tito", - "narrow": "Taara", - "normal": "Deede", - "aggressive": "Onítara", - "require_for_assessing_wallet": "Beere fun wiwọle si apamọwọ", - "require_for_sends_to_non_contacts": "Beere fun fifiranṣẹ si awọn ti kii ṣe awọn olubasọrọ", - "require_for_sends_to_contacts": "Beere fun fifiranṣẹ si awọn olubasọrọ", - "require_for_sends_to_internal_wallets": "Beere fun fifiranṣẹ si awọn apamọwọ inu", - "require_for_exchanges_to_internal_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ inu", - "require_for_adding_contacts": "Beere fun fifi awọn olubasọrọ kun", - "require_for_creating_new_wallets": "Beere fun ṣiṣẹda titun Woleti", - "require_for_all_security_and_backup_settings": "Beere fun gbogbo aabo ati awọn eto afẹyinti", + "available_balance": "Ìyókù owó tó wà níbẹ̀", "available_balance_description": "“Iwọntunwọnsi Wa” tabi “Iwọntunwọnsi Ijẹrisi” jẹ awọn owo ti o le ṣee lo lẹsẹkẹsẹ. Ti awọn owo ba han ni iwọntunwọnsi kekere ṣugbọn kii ṣe iwọntunwọnsi oke, lẹhinna o gbọdọ duro iṣẹju diẹ fun awọn owo ti nwọle lati gba awọn ijẹrisi nẹtiwọọki diẹ sii. Lẹhin ti wọn gba awọn ijẹrisi diẹ sii, wọn yoo jẹ inawo.", - "syncing_wallet_alert_title": "Apamọwọ rẹ n muṣiṣẹpọ", - "syncing_wallet_alert_content": "Iwontunws.funfun rẹ ati atokọ idunadura le ma pari titi ti yoo fi sọ “SYNCHRONIZED” ni oke. Tẹ/tẹ ni kia kia lati ni imọ siwaju sii.", - "home_screen_settings": "Awọn eto iboju ile", - "sort_by": "Sa pelu", - "search_add_token": "Wa / Fi àmi kun", - "edit_token": "Ṣatunkọ àmi", - "warning": "Ikilo", - "add_token_warning": "Ma ṣe ṣatunkọ tabi ṣafikun awọn ami bi a ti fun ni aṣẹ nipasẹ awọn scammers.\nNigbagbogbo jẹrisi awọn adirẹsi ami pẹlu awọn orisun olokiki!", - "add_token_disclaimer_check": "Mo ti jẹrisi adirẹsi adehun ami ati alaye nipa lilo orisun olokiki kan. Fifi irira tabi alaye ti ko tọ le ja si isonu ti owo.", - "token_contract_address": "Àmi guide adirẹsi", - "token_name": "Orukọ àmi fun apẹẹrẹ: Tether", - "token_symbol": "Aami aami fun apẹẹrẹ: USDT", - "token_decimal": "Àmi eleemewa", - "field_required": "E ni lati se nkan si aye yi", - "pin_at_top": "pin ${tokini} ni oke", - "invalid_input": "Iṣawọle ti ko tọ", - "fiat_balance": "Fiat Iwontunws.funfun", - "gross_balance": "Iwontunws.funfun apapọ", - "alphabetical": "Labidibi", - "generate_name": "Ṣẹda Orukọ", + "avg_savings": "Ìpamọ́ l’óòrèkóòrè", + "awaitDAppProcessing": "Fi inurere duro fun dApp lati pari sisẹ.", + "awaiting_payment_confirmation": "À ń dúró de ìjẹ́rìísí àránṣẹ́", + "backup": "Ṣẹ̀dà", + "backup_file": "Ṣẹ̀dà akọsílẹ̀", + "backup_password": "Ṣẹ̀dà ọ̀rọ̀ aṣínà", "balance_page": "Oju-iwe iwọntunwọnsi", - "share": "Pinpin", - "slidable": "Slidable", - "manage_nodes": "Ṣakoso awọn apa", - "etherscan_history": "Etherscan itan", - "template_name": "Orukọ Awoṣe", - "change_rep": "Yi Aṣoju", - "change_rep_message": "Ṣe o da ọ loju pe o fẹ yi awọn aṣoju pada?", - "unsupported_asset": "A ko ṣe atilẹyin iṣẹ yii fun dukia yii. Jọwọ ṣẹda tabi yipada si apamọwọ iru dukia atilẹyin.", - "manage_pow_nodes": "Ṣakoso awọn Nodes PoW", - "support_title_live_chat": "Atilẹyin ifiwe", - "support_description_live_chat": "Free ati sare! Ti oṣiṣẹ awọn aṣoju wa lati ṣe iranlọwọ", - "support_title_guides": "Akara oyinbo Awọn Itọsọna Awọki oyinbo", - "support_description_guides": "Iwe ati atilẹyin fun awọn ọran ti o wọpọ", - "support_title_other_links": "Awọn ọna asopọ atilẹyin miiran", - "support_description_other_links": "Darapọ mọ awọn agbegbe wa tabi de wa awọn alabaṣepọ wa nipasẹ awọn ọna miiran", - "choose_derivation": "Yan awọn apamọwọ apamọwọ", - "new_first_wallet_text": "Ni rọọrun jẹ ki o jẹ ki o jẹ ki o jẹ ki a mu", - "monero_dark_theme": "Monero Dudu Akori", + "bill_amount": "Iye ìwé owó", + "billing_address_info": "Tí ọlọ́jà bá bèèrè àdírẹ́sì sísan yín, fún òun ni àdírẹ́sì t'á ránṣẹ́ káàdì yìí sí", + "biometric_auth_reason": "Ya ìka ọwọ́ yín láti ṣe ìfẹ̀rílàdí", "bitcoin_dark_theme": "Bitcoin Dark Akori", "bitcoin_light_theme": "Bitcoin Light Akori", - "high_contrast_theme": "Akori Iyatọ giga", - "matrix_green_dark_theme": "Matrix Green Dark Akori", - "monero_light_theme": "Monero Light Akori", - "select_destination": "Jọwọ yan ibi ti o nlo fun faili afẹyinti.", - "auto_generate_subaddresses": "Aṣiṣe Ibi-Afọwọkọ", - "save_to_downloads": "Fipamọ si Awọn igbasilẹ", - "select_buy_provider_notice": "Yan olupese Ra loke. O le skii iboju yii nipa ṣiṣeto olupese rẹ ni awọn eto App.", - "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ọ.", - "default_buy_provider": "Aiyipada Ra Olupese", - "ask_each_time": "Beere lọwọ kọọkan", + "bitcoin_payments_require_1_confirmation": "Àwọn àránṣẹ́ Bitcoin nílò ìjẹ́rìísí kan. Ó lè lo ìṣéjú ogun tàbí ìṣéjú jù. A dúpẹ́ fún sùúrù yín! Ẹ máa gba ímeèlì t'ó bá jẹ́rìísí àránṣẹ́ náà.", + "Blocks_remaining": "Àkójọpọ̀ ${status} kikù", + "bright_theme": "Funfun", + "buy": "Rà", + "buy_alert_content": "Lọwọlọwọ a ṣe atilẹyin rira Bitcoin, Ethereum, Litecoin, ati Monero. Jọwọ ṣẹda tabi yipada si Bitcoin, Ethereum, Litecoin, tabi apamọwọ Monero.", + "buy_bitcoin": "Ra Bitcoin", "buy_provider_unavailable": "Olupese lọwọlọwọ ko si.", - "signTransaction": "Wole Idunadura", + "buy_with": "Rà pẹ̀lú", + "by_cake_pay": "láti ọwọ́ Cake Pay", + "cake_2fa_preset": "Cake 2FA Tito", + "cake_pay_account_note": "Ẹ fi àdírẹ́sì ímeèlì nìkan forúkọ sílẹ̀ k'ẹ́ rí àti ra àwọn káàdì. Ẹ lè fi owó tó kéré jù ra àwọn káàdì kan!", + "cake_pay_learn_more": "Láìpẹ́ ra àti lo àwọn káàdí ìrajà t'á lò nínú irú kan ìtajà nínú áàpù!\nẸ tẹ̀ òsì de ọ̀tún láti kọ́ jù.", + "cake_pay_subtitle": "Ra àwọn káàdì ìrajà t'á lò nínú ìtajà kan fún owó tí kò pọ̀ (USA nìkan)", + "cake_pay_title": "Àwọn káàdì ìrajà t'á lò nínú ìtajà kan ti Cake Pay", + "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_wallet": "Cake Wallet", + "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.", + "camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.", + "cancel": "Fagi lé e", + "card_address": "Àdírẹ́sì:", + "cardholder_agreement": "Àjọrò olùṣe káàdì ìrajà", + "cards": "Àwọn káàdì", + "chains": "Awọn ẹwọn", + "change": "Pààrọ̀", + "change_backup_password_alert": "Ẹ kò lè fi ọ̀rọ̀ aṣínà títun ti ẹ̀dà nípamọ́ ṣí àwọn àkọsílẹ̀ nípamọ́ tẹ́lẹ̀tẹ́lẹ̀ yín. Ẹ máa fi ọ̀rọ̀ aṣínà ti ẹ̀dà nípamọ́ títun ṣí àwọn àkọsílẹ̀ nípamọ́ títun nìkan. Ṣé ó dá ẹ lójú pé ẹ fẹ́ pààrọ̀ aṣínà ti ẹ̀dà nípamọ́?", + "change_currency": "Pààrọ̀ irú owó", + "change_current_node": "Ṣé ó dá yín lójú pé ẹ fẹ́ pààrọ̀ apẹka lọ́wọ́ sí ${node}?", + "change_current_node_title": "Pààrọ̀ apẹka lọwọ́", + "change_exchange_provider": "Pààrọ̀ Ilé Ìfowóṣòwò", + "change_language": "Pààrọ̀ èdè", + "change_language_to": "Pààrọ̀ èdè sí ${language}?", + "change_password": "Pààrọ̀ ọ̀rọ̀ aṣínà", + "change_rep": "Yi Aṣoju", + "change_rep_message": "Ṣe o da ọ loju pe o fẹ yi awọn aṣoju pada?", + "change_rep_successful": "Ni ifijišẹ yipada aṣoju", + "change_wallet_alert_content": "Ṣe ẹ fẹ́ pààrọ̀ àpamọ́wọ́ yìí sí ${wallet_name}?", + "change_wallet_alert_title": "Ẹ pààrọ̀ àpamọ́wọ́ yìí", + "choose_account": "Yan àkáǹtì", + "choose_address": "\n\nẸ jọ̀wọ́ yan àdírẹ́sì:", + "choose_derivation": "Yan awọn apamọwọ apamọwọ", + "choose_from_available_options": "Ẹ yàn láti àwọn ìyàn yìí:", + "choose_one": "Ẹ yàn kan", + "choose_relay": "Jọwọ yan yii lati lo", + "choose_wallet_currency": "Ẹ jọ̀wọ́, yàn irú owó ti àpamọ́wọ́ yín:", + "clear": "Pa gbogbo nǹkan", + "clearnet_link": "Kọja ilọ oke", + "close": "sunmo", + "coin_control": "Ìdarí owó ẹyọ (ìyàn nìyí)", + "cold_or_recover_wallet": "Fi owo aisan tabi yiyewo owo iwe iwe", + "color_theme": "Àwọn ààtò àwọ̀", + "commit_transaction_amount_fee": "Jẹ́rìí sí àránṣẹ́\nOwó: ${amount}\nIye àfikún: ${fee}", + "confirm": "Jẹ́rìísí", + "confirm_delete_template": "Ìṣe yìí máa yọ àwòṣe yìí kúrò. Ṣé ẹ fẹ́ tẹ̀síwájú?", + "confirm_delete_wallet": "Ìṣe yìí máa yọ àpamọ́wọ́ yìí kúrò. Ṣé ẹ fẹ́ tẹ̀síwájú?", + "confirm_sending": "Jẹ́rìí sí ránṣẹ́", + "confirmations": "Àwọn ẹ̀rí", + "confirmed": "A ti jẹ́rìí ẹ̀", + "confirmed_tx": "Jẹrisi", + "congratulations": "Ẹ kúuṣẹ́ ooo!", + "connect_an_existing_yat": "So Yat wíwà", + "connect_yats": "So àwọn Yat", + "connection_sync": "Ìkànpọ̀ àti ìbádọ́gba", + "connectWalletPrompt": "So apamọwọ rẹ pọ pẹlu WalletConnect lati ṣe awọn iṣowo", + "contact": "Olùbásọ̀rọ̀", + "contact_list_contacts": "Àwọn olùbásọ̀rọ̀", + "contact_list_wallets": "Àwọn àpamọ́wọ́ mi", + "contact_name": "Orúkọ olùbásọ̀rọ̀", + "contact_support": "Bá ìranlọ́wọ́ sọ̀rọ̀", + "continue_text": "Tẹ̀síwájú", + "contractName": "Orukọ adehun", + "contractSymbol": "Aami adehun", + "copied_key_to_clipboard": "Ti ṣeda ${key} sí àtẹ àkọsílẹ̀", + "copied_to_clipboard": "Jíjí wò sí àtẹ àkọsílẹ̀", + "copy": "Ṣẹ̀dà", + "copy_address": "Ṣẹ̀dà àdírẹ́sì", + "copy_id": "Ṣẹ̀dà àmì ìdánimọ̀", + "copyWalletConnectLink": "Daakọ ọna asopọ WalletConnect lati dApp ki o si lẹẹmọ nibi", + "create_account": "Dá àkáǹtì", + "create_backup": "Ṣẹ̀dà nípamọ́", + "create_donation_link": "Ṣe kọọkan alabara asopọ", + "create_invoice": "Ṣe iwe iwe", + "create_new": "Dá àpamọ́wọ́ tuntun", + "create_new_account": "Dá àkáǹtì títun", + "creating_new_wallet": "Ń dá àpamọ́wọ́ títun", + "creating_new_wallet_error": "Àṣìṣe: ${description}", + "creation_date": "Ọjọ ẹda", + "custom": "Ohun t'á ti pààrọ̀", + "custom_drag": "Aṣa (mu ati fa)", + "custom_redeem_amount": "Iye owó l'á máa ná", + "dark_theme": "Dúdú", + "debit_card": "Káàdì ìrajà", + "debit_card_terms": "Òfin ti olùṣe àjọrò káàdì ìrajà bójú irú ọ̀nà t'á pamọ́ àti a lo òǹkà ti káàdì ìrajà yín (àti ọ̀rọ̀ ìdánimọ̀ tí káàdì náà) nínú àpamọ́wọ́ yìí.", + "decimal_places_error": "Oọ̀rọ̀ ayipada ti o wa ni o dara julọ", + "default_buy_provider": "Aiyipada Ra Olupese", + "default_sell_provider": "Aiyipada Olupese Tita", + "delete": "Pa á", + "delete_account": "Pa ìṣàmúlò", + "delete_wallet": "Pa àpamọ́wọ́", + "delete_wallet_confirm_message": "Ṣó dá ẹ lójú pé ẹ fẹ́ pa àpamọ́wọ́ ${wallet_name}?", + "deleteConnectionConfirmationPrompt": "Ṣe o da ọ loju pe o fẹ paarẹ asopọ si", + "descending": "Sọkalẹ", + "description": "Apejuwe", + "destination_tag": "Orúkọ tí ìbí tó a ránṣẹ́ sí:", + "dfx_option_description": "Ra crypto pẹlu EUR & CHF. Titi di 990 € laisi afikun KYC. Fun soobu ati awọn onibara ile-iṣẹ ni Yuroopu", + "digit_pin": "-díjíìtì òǹkà ìdánimọ̀ àdáni", + "digital_and_physical_card": " káàdì ìrajà t'ara àti ti ayélujára", + "disable": "Ko si", + "disable_buy": "Ko iṣọrọ ọja", + "disable_cake_2fa": "Ko 2FA Cake sii", + "disable_exchange": "Pa ilé pàṣípààrọ̀", + "disable_fiat": "Pa owó tí ìjọba pàṣẹ wa lò", + "disable_sell": "Ko iṣọrọ iṣọrọ", + "disabled": "Wọ́n tí a ti pa", + "discount": "Pamọ́ ${value}%", + "display_settings": "Fihàn àwọn ààtò", + "displayable": "A lè ṣàfihàn ẹ̀", + "do_not_have_enough_gas_asset": "O ko ni to ${currency} lati ṣe idunadura kan pẹlu awọn ipo nẹtiwọki blockchain lọwọlọwọ. O nilo diẹ sii ${currency} lati san awọn owo nẹtiwọọki blockchain, paapaa ti o ba nfi dukia miiran ranṣẹ.", + "do_not_send": "Ẹ kò ránṣ", + "do_not_share_warning_text": "Ẹ kò pín wọnyìí sí ẹnikẹ́ni. Ẹ sì kò pin wọnyìí sí ìranlọ́wọ́. Ẹnikẹ́ni lè jí owó yín! Wọ́n máa jí owó yín!", + "do_not_show_me": "Kò fi eléyìí hàn mi mọ́", + "domain_looks_up": "Awọn wiwa agbegbe", + "donation_link_details": "Iru awọn ẹya ọrọ ti o funni", + "dont_get_code": "Ṣé ẹ ti gba ọ̀rọ̀ ìdánimọ̀?", + "e_sign_consent": "Jẹ́rìí sí lórí ayélujára", + "edit": "Pààrọ̀", + "edit_backup_password": "Pààrọ̀ ọ̀rọ̀ aṣínà", + "edit_node": "Tun awọn ọwọnrin ṣiṣe", + "edit_token": "Ṣatunkọ àmi", + "electrum_address_disclaimer": "A dá àwọn àdírẹ́sì títun ní gbogbo àwọn ìgbà t'ẹ́ lo ó kan ṣùgbọ́n ẹ lè tẹ̀síwájú lo àwọn àdírẹ́sì tẹ́lẹ̀tẹ́lẹ̀.", + "email_address": "Àdírẹ́sì ímeèlì", + "enabled": "Wọ́n tíwọn ti tan", + "enter_amount": "Tẹ̀ iye", + "enter_backup_password": "Tẹ̀ ọ̀rọ̀ aṣínà ti ẹ̀dà ḿbí", + "enter_code": "Tẹ̀ ọ̀rọ̀", + "enter_seed_phrase": "Tẹ ọrọ-iru irugbin rẹ", + "enter_totp_code": "Jọwọ pọ koodu TOTP.", + "enter_your_note": "Tẹ̀ àkọsílẹ̀ yín", + "enter_your_pin": "Tẹ̀ òǹkà ìdánimọ̀ àdáni yín", + "enter_your_pin_again": "Tún òǹkà ìdánimọ̀ àdáni yín tẹ̀", + "enterTokenID": "Tẹ ID ami sii", + "enterWalletConnectURI": "Tẹ WalletConnect URI sii", + "error": "Àṣìṣe", + "error_dialog_content": "Àṣìṣe ti dé.\n\nẸ jọ̀wọ́, fi àkọsílẹ̀ àṣìṣe ránṣẹ́ sí ẹgbẹ́ ìranlọ́wọ́ wa kí áàpù wa bá túbọ̀ dára.", + "error_text_account_name": "Orúkọ àkáǹtì lè ni nìkan nínú ẹyọ ọ̀rọ̀ àti òǹkà\nGígun rẹ̀ kò gbọ́dọ̀ kéré ju oókan. Gígun rẹ̀ sì kò gbọ́dọ̀ tóbi ju márùndínlógún.", + "error_text_address": "Àdírẹ́sì àpamọ́wọ́ gbọ́dọ̀ báramu irú owó", + "error_text_amount": "Iye lè ni nìkan nínú àwọn òǹkà", + "error_text_contact_name": "Orúkọ olùbásọ̀rọ̀ kò lè ni nínú ` , ' \" ẹyọ ọ̀rọ̀.\nIye ẹyọ ọ̀rọ̀ kò gbọ́dọ̀ kéré ju oókan. Ó sì kò gbọ́dọ̀ tóbi ju méjìlélọ́gbọ̀n.", + "error_text_crypto_currency": "Iye díjíìtì léyìn ẹsẹ kò gbọ́dọ̀ tóbi ju eéjìlá.", + "error_text_fiat": "Iye àránṣẹ́ kò tóbi ju ìyókù owó.\nIye díjíìtì léyìn ẹsẹ kò gbọ́dọ̀ tóbi ju eéjì.", + "error_text_input_above_maximum_limit": "Iye jọwọ ni o yẹ diẹ ti o wọle diẹ", + "error_text_input_below_minimum_limit": "Iye jọwọ ni o kere ti o wọle diẹ", + "error_text_keys": "Àwọn kọ́kọ́rọ́ àpamọ́wọ́ gbọ́dọ̀ ní ẹyọ ọ̀rọ̀ mẹ́rinlélọ́gọ́ta lílà mẹ́rìndínlógún", + "error_text_limits_loading_failed": "A kò tí ì ṣe pàṣípààrọ̀ tí ${provider} nítorí a ti kùnà mú àwọn ààlà wá", + "error_text_maximum_limit": "A kò tí ì ṣe pàṣípààrọ̀ tí ${provider} nítorí iye tóbi ju ${min} ${currency}", + "error_text_minimal_limit": "A kò tí ì ṣe pàṣípààrọ̀ tí ${provider} nítorí iye kéré ju ${min} ${currency}", + "error_text_node_address": "Ẹ jọ̀wọ́ tẹ̀ àdírẹ́sì iPv4", + "error_text_node_port": "Ojú ìkànpọ̀ apẹka lè ni nìkan nínú òǹkà l'áàárín òdo àti márùn-úndínlógojí lé ní ẹ̀ẹ́dẹgbẹ̀ta lé ní ọ̀kẹ́ mẹ́ta lé ní ẹ̀ẹ́dẹ́gbàta", + "error_text_node_proxy_address": "Jọwọ tẹ :, fun apẹẹrẹ 127.0.0.1:9050", + "error_text_payment_id": "Iye ẹyọ ọ̀rọ̀ nínú àmì ìdánimọ̀ àránṣẹ́ gbọ́dọ̀ wà l'áàárín aárùndínlógún dé ẹẹ́rinlélọ́gọ́ta.", + "error_text_subaddress_name": "Orúkọ àdírẹ́sì tó rẹ̀lẹ̀ kò ni nínú àmì ` , ' \"\nIye ẹyọ ọ̀rọ̀ gbọ́dọ̀ wà láàárín oókan àti ogún", + "error_text_template": "Orúkọ àwòṣe àti àdírẹ́sì kò lè ni nínú àwọn àmì ` , ' \"\nIye ẹyọ ọ̀rọ̀ náà gbọ́dọ̀ jẹ́ láàárín 1 àti 106", + "error_text_wallet_name": "Orúkọ àpamọ́wọ́ lè ni nìkan nínú àwọn òǹkà àti ẹyọ ọ̀rọ̀ àti àmì _ -\nIye ẹyọ ọ̀rọ̀ gbọ́dọ̀ wà láàárín 1 àti 33", + "error_text_xmr": "Iye XMR kò lè tóbi ju ìyókù.\nIye díjíìtì léyìn ẹsẹ kò gbọ́dọ̀ tóbi ju eéjìlá.", "errorGettingCredentials": "Kuna: Aṣiṣe lakoko gbigba awọn iwe-ẹri", "errorSigningTransaction": "Aṣiṣe kan ti waye lakoko ti o fowo si iṣowo", - "pairingInvalidEvent": "Pipọpọ Iṣẹlẹ Ti ko tọ", - "chains": "Awọn ẹwọn", - "methods": "Awọn ọna", - "events": "Awọn iṣẹlẹ", - "reject": "Kọ", - "approve": "Fi ọwọ si", - "expiresOn": "Ipari lori", - "walletConnect": "Asopọmọra apamọwọ", - "nullURIError": "URI jẹ asan", - "connectWalletPrompt": "So apamọwọ rẹ pọ pẹlu WalletConnect lati ṣe awọn iṣowo", - "newConnection": "Tuntun Asopọ", - "activeConnectionsPrompt": "Awọn asopọ ti nṣiṣe lọwọ yoo han nibi", - "deleteConnectionConfirmationPrompt": "Ṣe o da ọ loju pe o fẹ paarẹ asopọ si", + "estimated": "Ó tó a fojú díwọ̀n", + "etherscan_history": "Etherscan itan", "event": "Iṣẹlẹ", - "successful": "Aseyori", - "wouoldLikeToConnect": "yoo fẹ lati sopọ", - "message": "Ifiranṣẹ", - "do_not_have_enough_gas_asset": "O ko ni to ${currency} lati ṣe idunadura kan pẹlu awọn ipo nẹtiwọki blockchain lọwọlọwọ. O nilo diẹ sii ${currency} lati san awọn owo nẹtiwọọki blockchain, paapaa ti o ba nfi dukia miiran ranṣẹ.", - "totp_auth_url": "TOTP AUTH URL", - "awaitDAppProcessing": "Fi inurere duro fun dApp lati pari sisẹ.", - "copyWalletConnectLink": "Daakọ ọna asopọ WalletConnect lati dApp ki o si lẹẹmọ nibi", - "enterWalletConnectURI": "Tẹ WalletConnect URI sii", - "seed_key": "Bọtini Ose", - "enter_seed_phrase": "Tẹ ọrọ-iru irugbin rẹ", - "change_rep_successful": "Ni ifijišẹ yipada aṣoju", - "add_contact": "Fi olubasọrọ kun", + "events": "Awọn iṣẹlẹ", + "exchange": "Pàṣípààrọ̀", + "exchange_incorrect_current_wallet_for_xmr": "T'ẹ́ bá fẹ́ pàṣípààrọ̀ XMR láti ìyókù owó Cake Wallet yín, ẹ jọ̀wọ́ kọ́kọ́ sún àpamọ́wọ́ Monero mọ́.", + "exchange_new_template": "Àwòṣe títun", "exchange_provider_unsupported": "${providerName} ko ni atilẹyin mọ!", - "domain_looks_up": "Awọn wiwa agbegbe", - "require_for_exchanges_to_external_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ ita", - "camera_permission_is_required": "A nilo igbanilaaye kamẹra.\nJọwọ jeki o lati app eto.", - "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi", - "order_by": "Bere fun nipasẹ", - "creation_date": "Ọjọ ẹda", + "exchange_result_confirm": "T'ẹ́ bá tẹ̀ jẹ́rìí, ẹ máa fi ${fetchingLabel} ${from} ránṣẹ́ láti àpamọ́wọ́ yín t'á pe ${walletName} sí àdírẹ́sì t'ó ṣàfihàn òun lísàlẹ̀. Tàbí ẹ lè fi àpamọ́wọ́ mìíràn yín ránṣẹ́ sí àdírẹ́sì / àmì ìlujá lísàlẹ̀.\n\nẸ jọ̀wọ́ tẹ̀ jẹ́rìí́ tẹ̀síwájú tàbí padà sọ́dọ̀ pààrọ̀ iye náà.", + "exchange_result_description": "Ẹ gbọ́dọ̀ ránṣẹ́ iye owó tó pọ̀ jù ${fetchingLabel} ${from} sí àdírẹ́sì tó ṣàfihàn òun lójú tó ń bọ̀. T'ẹ́ bá fi iye tí kò pọ̀ jù ${fetchingLabel} ${from}, a kò lè pàṣípààrọ̀ ẹ̀. A sì kò lè dá a padà fún yín.", + "exchange_result_write_down_ID": "*Ẹ jọ̀wọ́, ṣẹ̀dà àmì ìdánimọ̀ yín tó ṣàfihàn òun lókè.", + "exchange_result_write_down_trade_id": "Ẹ jọ̀wọ́, kọ àmì ìdánimọ̀ pàṣípààrọ̀ sílẹ̀ kí tẹ̀síwájú.", + "exchange_sync_alert_content": "Ẹ jọ̀wọ́ dúró kí a ti múdọ́gba àpamọ́wọ́ yín", + "expired": "Kíkú", + "expires": "Ó parí", + "expiresOn": "Ipari lori", + "export_backup": "Sún ẹ̀dà nípamọ́ síta", + "extra_id": "Àmì ìdánimọ̀ tó fikún:", + "extracted_address_content": "Ẹ máa máa fi owó ránṣẹ́ sí\n${recipient_name}", + "failed_authentication": "Ìfẹ̀rílàdí pipòfo. ${state_error}", + "faq": "Àwọn ìbéèrè l'a máa ń bèèrè", + "fetching": "ń wá", + "fiat_api": "Ojú ètò áàpù owó tí ìjọba pàṣẹ wa lò", + "fiat_balance": "Fiat Iwontunws.funfun", + "field_required": "E ni lati se nkan si aye yi", + "fill_code": "Ẹ jọ̀wọ́ tẹ̀ ọ̀rọ̀ ìjẹ́rìísí t'á ti ránṣẹ́ sí ímeèlì yín.", + "filter_by": "Ṣẹ́ láti", + "first_wallet_text": "Àpamọ́wọ́ t'á fi Monero, Bitcoin, Ethereum, Litecoin, àti Haven pamọ́ wà pa", + "fixed_pair_not_supported": "A kì í ṣe k'á fi àwọn ilé pàṣípààrọ̀ yìí ṣe pàṣípààrọ̀ irú owó méji yìí", + "fixed_rate": "Iye t'á ṣẹ́ owó sí ò ní pààrọ̀", + "fixed_rate_alert": "Ẹ lè tẹ̀ iye owó tó ń bọ̀ tí iye t'a ṣẹ́ owó sí bá is checked. Ṣé ẹ fẹ́ sún ipò ti iye t'á ṣẹ́ owó sí ò ní pààrọ̀ mọ́?", + "forgot_password": "Ẹ ti gbàgbé ọ̀rọ̀ aṣínà", + "freeze": "Tì pa", + "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", + "generate_name": "Ṣẹda Orukọ", + "generating_gift_card": "À ń dá káàdì ìrajà t'á lò nínú irú kan ìtajà", + "get_a": "Gba ", + "get_card_note": " t'ẹ lè fikún owó ayélujára. Ẹ kò nílò ìṣofúnni àfikún!", + "get_your_yat": "Gba Yat yín", + "gift_card_amount": "owó ìyókù káàdì", + "gift_card_balance_note": "Àwọn káàdì ìrajà t'á lò nínú irú kan ìtajà tíwọn ṣì ní owó máa fihàn ḿbí", + "gift_card_is_generated": "A ti dá káàdí ìrajà t'á lò nínú irú kan ìtajà", + "gift_card_number": "Òǹkà káàdì ìrajì", + "gift_card_redeemed_note": "Àwọn káàdì ìrajà t'á lò nínú irú kan ìtajà t'ẹ́ ti lò máa fihàn ḿbí", + "gift_cards": "Àwọn káàdì ìrajà t'á lò nínú iye kan ìtajà", + "gift_cards_unavailable": "A lè fi Monero, Bitcoin, àti Litecoin nìkan ra káàdí ìrajà t'á lò nínú irú kan ìtajà lọ́wọ́lọ́wọ́", + "got_it": "Ó dáa", + "gross_balance": "Iwontunws.funfun apapọ", "group_by_type": "Ẹgbẹ nipasẹ Iru", - "importNFTs": "Gbe awọn NFT wọle", - "noNFTYet": "Ko si awọn NFT sibẹsibẹ", - "address": "Adirẹsi", - "enterTokenID": "Tẹ ID ami sii", - "tokenID": "ID", - "name": "Oruko", - "symbol": "Aami", - "seed_phrase_length": "Gigun gbolohun irugbin", - "unavailable_balance": "Iwontunwonsi ti ko si", - "unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.", - "unspent_change": "Yipada", - "tor_connection": "Tor asopọ", - "setup_warning_2fa_text": "Iwọ yoo nilo lati mu pada apamọwọ rẹ lati inu irugbin mnemonic.\n\nAtilẹyin akara oyinbo kii yoo ni anfani lati ṣe iranlọwọ fun ọ ti o ba padanu iraye si 2FA tabi awọn irugbin mnemonic rẹ.\nAkara oyinbo 2FA jẹ ijẹrisi keji fun awọn iṣe kan ninu apamọwọ. Ṣaaju lilo akara oyinbo 2FA, a ṣeduro kika nipasẹ itọsọna naa.Ko ṣe aabo bi ibi ipamọ tutu.\n\nTi o ba padanu iraye si ohun elo 2FA tabi awọn bọtini TOTP, iwọ YOO padanu iraye si apamọwọ yii. ", - "scan_qr_on_device": "Ṣe ayẹwo koodu QR yii lori ẹrọ miiran", + "haven_app": "Haven latí ọwọ́ Cake Wallet", + "haven_app_wallet_text": "Àpamọ́wọ́ Haven wà pa", + "help": "ìranlọ́wọ́", + "hidden_balance": "Ìyókù owó dídé", + "hide_details": "Dé ìsọfúnni kékeré", + "high_contrast_theme": "Akori Iyatọ giga", + "home_screen_settings": "Awọn eto iboju ile", "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ọ̀: ", + "ignor": "Ṣàìfiyèsí", + "import": "gbe wọle", + "importNFTs": "Gbe awọn NFT wọle", + "in_store": "A níyí", + "incoming": "Wọ́n tó ń bọ̀", + "incorrect_seed": "Ọ̀rọ̀ tí a tẹ̀ kì í ṣe èyí.", + "introducing_cake_pay": "Ẹ bá Cake Pay!", + "invalid_input": "Iṣawọle ti ko tọ", + "invoice_details": "Iru awọn ẹya ọrọ", + "is_percentage": "jẹ́", + "last_30_days": "Ọ̀jọ̀ mọ́gbọ̀n tó kọjà", + "learn_more": "Túbọ̀ kọ́", + "light_theme": "Funfun bí eérú", + "loading_your_wallet": "A ń ṣí àpamọ́wọ́ yín", + "login": "Orúkọ", + "logout": "Jáde", + "low_fee": "Owó àfikún kékeré", + "low_fee_alert": "Ẹ ń fi owó àfikún kékeré fún àwọn àránṣẹ́ yín lágbára. Eleyìí lè pẹ́ gba àránṣẹ́ yín. Ó sì lè dá àwọn iye mìíràn t'á ṣẹ́ owó sí. Ó sì lè pa àwọn pàṣípààrọ̀. A dábàá pé k'ẹ́ lo owó àfikún títobi láti ṣe àṣejèrè.", + "manage_nodes": "Ṣakoso awọn apa", + "manage_pow_nodes": "Ṣakoso awọn Nodes PoW", + "manage_yats": "Bójú Yats", + "mark_as_redeemed": "Fún orúkọ lílò", + "market_place": "Ọjà", + "matrix_green_dark_theme": "Matrix Green Dark Akori", + "max_amount": "kò tóbi ju: ${value}", + "max_value": "kò gbọ́dọ̀ tóbi ju ${value} ${currency}", + "memo": "Àkọsílẹ̀:", + "message": "Ifiranṣẹ", + "methods": "Awọn ọna", + "min_amount": "kò kéré ju: ${value}", + "min_value": "kò gbọ́dọ̀ kéré ju ${value} ${currency}", + "minutes_to_pin_code": "${minute} ìṣẹ́jú", + "mm": "Os", + "modify_2fa": "Fi iṣiro 2FA sii Cake", + "monero_com": "Monero.com latí ọwọ́ Cake Wallet", + "monero_com_wallet_text": "Àpamọ́wọ́ Monero wà pa", + "monero_dark_theme": "Monero Dudu Akori", + "monero_light_theme": "Monero Light Akori", + "moonpay_alert_text": "Iye owó kò gbọ́dọ̀ kéré ju ${minAmount} ${fiatCurrency}", + "more_options": "Ìyàn àfikún", + "name": "Oruko", + "narrow": "Taara", + "new_first_wallet_text": "Ni rọọrun jẹ ki o jẹ ki o jẹ ki o jẹ ki a mu", + "new_node_testing": "A ń dán apẹka títun wò", + "new_subaddress_create": "Ṣe é", + "new_subaddress_label_name": "Orúkọ", + "new_subaddress_title": "Àdírẹ́sì títun", + "new_template": "Àwòṣe títun", + "new_wallet": "Àpamọ́wọ́ títun", + "newConnection": "Tuntun Asopọ", + "no_id_needed": "Ẹ kò nílò àmì ìdánimọ̀!", + "no_id_required": "Ẹ kò nílò àmì ìdánimọ̀. Ẹ lè fikún owó àti san níbikíbi", + "no_relay_on_domain": "Ko si iṣipopada fun agbegbe olumulo tabi yiyi ko si. Jọwọ yan yii lati lo.", + "no_relays": "Ko si relays", + "no_relays_message": "A ri igbasilẹ Nostr NIP-05 fun olumulo yii, ṣugbọn ko ni eyikeyi awọn iṣipopada ninu. Jọwọ sọ fun olugba lati ṣafikun awọn isunmọ si igbasilẹ Nostr wọn.", + "node_address": "Àdírẹ́sì apẹka", + "node_connection_failed": "Ìkànpọ̀ ti kùnà", + "node_connection_successful": "Ìkànpọ̀ ti dára", + "node_new": "Apẹka títun", + "node_port": "Ojú ìkànpọ̀ apẹka", + "node_reset_settings_title": "Tún àwọn ààtò ṣe", + "node_test": "Dánwò", + "nodes": "Àwọn apẹka", + "nodes_list_reset_to_default_message": "Ṣé ó dá yín lójú pé ẹ fẹ́ yí àwọn ààtò padà?", + "none_of_selected_providers_can_exchange": "Àwọn ilé pàṣípààrọ̀ yíyàn kò lè ṣe pàṣípààrọ̀ yìí", + "noNFTYet": "Ko si awọn NFT sibẹsibẹ", + "normal": "Deede", + "note_optional": "Àkọsílẹ̀ (ìyàn nìyí)", + "note_tap_to_change": "Àkọsílẹ̀ (ẹ tẹ̀ láti pààrọ̀)", + "nullURIError": "URI jẹ asan", + "offer_expires_in": "Ìrònúdábàá máa gbẹ́mìí mì ní: ", + "offline": "kò wà lórí ayélujára", + "ok": "Ó dáa", + "onion_link": "Kọja ilọ alubosa", + "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à", + "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", + "optionally_order_card": "Ẹ lè fi ìyàn bèèrè káàdì t'ara.", + "order_by": "Bere fun nipasẹ", + "order_id": "Àmì ìdánimọ̀ ti ìbéèrè", + "order_physical_card": "Bèèrè káàdì t'ara", + "other_settings": "Àwọn ààtò mìíràn", + "outdated_electrum_wallet_description": "Àwọn àpamọ́wọ́ títun Bitcoin ti a ti dá nínú Cake Wallet lọ́wọ́lọ́wọ́. Àwọn àpamọ́wọ́ títun t'á dá nínú Cake Wallet ni hóró tó ní ọ̀rọ̀ mẹ́rinlélógún. Ẹ gbọ́dọ̀ dá àpamọ́wọ́. Ẹ sì sún gbogbo owó yín sí àpamọ́wọ́ títun náà tó dá lórí ọ̀rọ̀ mẹ́rinlélógún. Ẹ sì gbọ́dọ̀ yé lo àwọn àpamọ́wọ́ tó dá lórí hóró tó ní ọ̀rọ̀ méjìlá. Ẹ jọ̀wọ́ ṣe èyí láìpẹ́ kí ẹ ba owó yín.", + "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", + "overwrite_amount": "Pààrọ̀ iye owó", + "pairingInvalidEvent": "Pipọpọ Iṣẹlẹ Ti ko tọ", + "password": "Ọ̀rọ̀ aṣínà", + "paste": "Fikún ẹ̀dà yín", + "pause_wallet_creation": "Agbara lati ṣẹda Haven Wallet ti wa ni idaduro lọwọlọwọ.", + "payment_id": "Àmì ìdánimọ̀ àránṣẹ́: ", + "payment_was_received": "Àránṣẹ́ yín ti dé.", + "pending": " pípẹ́", + "percentageOf": "láti ${amount}", + "pin_at_top": "pin ${tokini} ni oke", + "pin_is_incorrect": "òǹkà ìdánimọ̀ àdáni kò yẹ́", + "pin_number": "Òǹkà ìdánimọ̀ àdáni", + "placeholder_contacts": "A máa fihàn àwọn olùbásọ̀rọ̀ yín ḿbí", + "placeholder_transactions": "A máa fihàn àwọn àránṣẹ́ yín ḿbí", + "please_fill_totp": "Jọwọ bọ ti ẹrọ ti o wọle ni 8-digits ti o wa ni eto miiran re", + "please_make_selection": "Ẹ jọ̀wọ́, yàn dá àpamọ́wọ́ yín tàbí dá àpamọ́wọ́ yín padà n’ísàlẹ̀.", + "please_reference_document": "Ẹ jọ̀wọ́ fi àwọn àkọsílẹ̀ l’ábẹ́ túbọ̀ mọ ìsọfúnni.", + "please_select": "Ẹ jọ̀wọ́ yàn:", + "please_select_backup_file": "Ẹ jọ̀wọ́ yan àkọsílẹ̀ nípamọ́ àti tẹ̀ ọ̀rọ̀ aṣínà ti ẹ̀dà.", + "please_try_to_connect_to_another_node": "Ẹ jọ̀wọ́, gbìyànjú dárapọ̀ mọ́ apẹka mìíràn yí wọlé", + "please_wait": "Jọwọ saa", + "polygonscan_history": "PolygonScan itan", + "powered_by": "Láti ọwọ́ ${title}", + "pre_seed_button_text": "Mo ti gbọ́. O fi hóró mi hàn mi", + "pre_seed_description": "Ẹ máa wo àwọn ọ̀rọ̀ ${words} lórí ojú tó ń bọ̀. Èyí ni hóró aládàáni yín tó kì í jọra. Ẹ lè fi í nìkan dá àpamọ́wọ́ yín padà sípò tí àṣìṣe tàbí ìbàjẹ́ bá ṣẹlẹ̀. Hóró yín ni ẹ gbọ́dọ̀ kọ sílẹ̀ àti pamọ́ síbí tó kò léwu níta Cake Wallet.", + "pre_seed_title": "Ó TI ṢE PÀTÀKÌ", + "prevent_screenshots": "Pese asapọ ti awọn ẹrọ eto aṣa", + "privacy": "Ìdáwà", + "privacy_policy": "Òfin Aládàáni", + "privacy_settings": "Ààtò àdáni", + "private_key": "Kọ́kọ́rọ́ àdáni", + "proceed_after_one_minute": "Tí aṣàfihàn kò bá tẹ̀síwájú l'áàárín ìṣẹ́jú kan, ẹ tọ́ ímeèlì yín wò.", + "profile": "profaili", + "provider_error": "Àṣìṣe ${provider}", + "public_key": "Kọ́kọ́rọ́ tó kò àdáni", + "purchase_gift_card": "Ra káàdì ìrajà t'á lò nínú irú kan ìtajà", + "qr_fullscreen": "Àmì ìlujá túbọ̀ máa tóbi tí o bá tẹ̀", + "qr_payment_amount": "Iye owó t'á ránṣé wà nínú àmì ìlujá yìí. Ṣé ẹ fẹ́ pààrọ̀ ẹ̀?", + "question_to_disable_2fa": "Ṣe o wa daadaa pe o fẹ ko 2FA Cake? Ko si itumọ ti a yoo nilo lati ranse si iwe iwe naa ati eyikeyi iṣẹ ti o ni.", + "receivable_balance": "Iwontunws.funfun ti o gba", + "receive": "Gbà", + "receive_amount": "Iye", + "received": "Owó t'á ti gbà", + "recipient_address": "Àdírẹ́sì olùgbà", + "reconnect": "Ṣe àtúnse", + "reconnect_alert_text": "Ṣó dá ẹ lójú pé ẹ fẹ́ ṣe àtúnse?", + "reconnection": "Àtúnṣe", + "redeemed": "Ó lílò", + "refund_address": "Àdírẹ́sì t'ẹ́ gba owó sí", + "reject": "Kọ", + "remaining": "ìyókù", + "remove": "Yọ ọ́ kúrò", + "remove_node": "Yọ apẹka kúrò", + "remove_node_message": "Ṣé ó da yín lójú pé ẹ fẹ́ yọ apẹka lọwọ́ kúrò?", + "rename": "Pààrọ̀ orúkọ", + "require_for_adding_contacts": "Beere fun fifi awọn olubasọrọ kun", + "require_for_all_security_and_backup_settings": "Beere fun gbogbo aabo ati awọn eto afẹyinti", + "require_for_assessing_wallet": "Beere fun wiwọle si apamọwọ", + "require_for_creating_new_wallets": "Beere fun ṣiṣẹda titun Woleti", + "require_for_exchanges_to_external_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ ita", + "require_for_exchanges_to_internal_wallets": "Beere fun awọn paṣipaarọ si awọn apamọwọ inu", + "require_for_sends_to_contacts": "Beere fun fifiranṣẹ si awọn olubasọrọ", + "require_for_sends_to_internal_wallets": "Beere fun fifiranṣẹ si awọn apamọwọ inu", + "require_for_sends_to_non_contacts": "Beere fun fifiranṣẹ si awọn ti kii ṣe awọn olubasọrọ", + "require_pin_after": "Ẹ nílò òǹkà ìdánimọ̀ àdáni láàárín", + "rescan": "Tún Wá", + "resend_code": "Ẹ jọ̀wọ́ tún un ránṣé", + "reset": "Tún ṣe", + "reset_password": "Tún ọ̀rọ̀ aṣínà ṣe", + "restore_active_seed": "Hóró lọ́wọ́", + "restore_address": "Àdírẹ́sì", + "restore_bitcoin_description_from_keys": "Mú àpamọ́wọ́ yín padà láti ọ̀rọ̀ WIF t'á ti dá láti kọ́kọ́rọ́ àdáni yín", + "restore_bitcoin_description_from_seed": "Mú àpamọ́wọ́ yín padà láti àkànpọ̀ ọlọ́rọ̀ ẹ̀ẹ̀mẹrinlélógun", + "restore_bitcoin_title_from_keys": "Mú padà láti WIF", + "restore_description_from_backup": "Ẹ lè fi ẹ̀dà nípamọ́ yín mú odindi Cake Wallet áàpù padà.", + "restore_description_from_keys": "Mú àpamọ́wọ́ yín padà láti àwọn àtẹ̀ nípamọ́ láti àwọn kọ́kọ́rọ́ àdáni yín", + "restore_description_from_seed": "Ẹ mú àpamọ́wọ́ yín padà láti àkànpọ̀ ọlọ́rọ̀ ẹ̀ẹ̀marùndínlọgbọ̀n tàbí ti mẹ́talá.", + "restore_description_from_seed_keys": "Mú àpamọ́wọ́ yín padà láti hóró/kọ́kọ́rọ́ t'ẹ́ ti pamọ́ sí ibi láìléwu", + "restore_from_date_or_blockheight": "Ẹ jọ̀wọ́, tẹ̀ ìgbà ọjọ́ díẹ̀ k'ẹ́ tó ti dá àpamọ́wọ́ yìí. Tàbí ẹ lè tẹ̀ ẹ́ t'ẹ́ bá mọ gíga àkójọpọ̀.", + "restore_from_seed_placeholder": "Ẹ jọ̀wọ́ tẹ̀ hóró yín tàbí fikún ẹ̀dà hóró ḿbí.", + "restore_new_seed": "Hóró títun", + "restore_next": "Tẹ̀síwájú", + "restore_recover": "Mú padà", + "restore_restore_wallet": "Mú àpamọ́wọ́ padà", + "restore_seed_keys_restore": "Mú hóró/kọ́kọ́rọ́ padà", + "restore_spend_key_private": "kọ́kọ́rọ́ àdáni fún níná", + "restore_title_from_backup": "Fi ẹ̀dà nípamọ́ mú padà", + "restore_title_from_keys": "Fi kọ́kọ́rọ́ ṣẹ̀dá", + "restore_title_from_seed": "Fi hóró mú padà", + "restore_title_from_seed_keys": "Fi hóró/kọ́kọ́rọ́ mú padà", + "restore_view_key_private": "kọ́kọ́rọ́ ìrán àdáni", + "restore_wallet": "Mú àpamọ́wọ́ padà", + "restore_wallet_name": "Orúkọ àpamọ́wọ́", + "restore_wallet_restore_description": "Ìṣapẹrẹ mú àpamọ́wọ́ padà", + "router_no_route": "Ọ̀nà kò sí fún ${name}", + "save": "Pamọ́", + "save_backup_password": "Ẹ jọ̀wọ́ dájú pé ẹ ti pamọ́ ọ̀rọ̀ aṣínà ti ẹ̀dà nípamọ́ yín. Ti ẹ kò bá ni í, ẹ kò lè ṣí àwọn àkọsílẹ̀ nípamọ́ yín.", + "save_backup_password_alert": "Pamọ́ ọ̀rọ̀ aṣínà ti ẹ̀dà", + "save_to_downloads": "Fipamọ si Awọn igbasilẹ", + "saved_the_trade_id": "Mo ti pamọ́ àmì ìdánimọ̀ pàṣípààrọ̀", + "scan_qr_code": "Yan QR koodu", + "scan_qr_on_device": "Ṣe ayẹwo koodu QR yii lori ẹrọ miiran", + "search": "Wá", + "search_add_token": "Wa / Fi àmi kun", + "search_category": "Wá nínú ẹgbẹ́", + "search_currency": "Wá irú owó", + "search_language": "Wá èdè", + "second_intro_content": "Àdírẹ́sì kan tó dá lórí emójì tó kì í jọra ni Yat yín. Ó rọ́pò gbogbo àwọn àdírẹ́sì gígùn yín tó dá lórí ìlà mẹ́rìndínlógún ti gbogbo àwọn iye owó yín.", + "second_intro_title": "Àdírẹ́sì kan t'á dá láti emójì tó pàṣẹ gbogbo ohun wà", + "security_and_backup": "Ìṣọ́ àti ẹ̀dà nípamọ́", + "seed_alert_back": "Padà sọ́dọ̀", + "seed_alert_content": "Hóró ni ọ̀nà nìkan kí ṣẹ̀dà àpamọ́wọ́ yín. Ṣé ẹ ti kọ ọ́ sílẹ̀?", + "seed_alert_title": "Ẹ wo", + "seed_alert_yes": "Mo ti kọ ọ́", + "seed_choose": "Yan èdè hóró", "seed_hex_form": "Irú Opamọwọ apamọwọ (HOX)", + "seed_key": "Bọtini Ose", + "seed_language": "Ewu ọmọ", + "seed_language_chinese": "Èdè Ṣáínà", + "seed_language_chinese_traditional": "Kannada (ibile)", + "seed_language_czech": "Czech", + "seed_language_dutch": "Èdè Nẹ́dálaǹdì", + "seed_language_english": "Èdè Gẹ̀ẹ́sì", + "seed_language_french": "Èdè Fránsì", + "seed_language_german": "Èdè Jámánì", + "seed_language_italian": "Èdè Itálíà", + "seed_language_japanese": "Èdè Jẹ́páànì", + "seed_language_korean": "Ara ẹni", + "seed_language_next": "Tẹ̀síwájú", + "seed_language_portuguese": "Èdè Potogí", + "seed_language_russian": "Èdè Rọ́síà", + "seed_language_spanish": "Èdè Sípéènì", + "seed_phrase_length": "Gigun gbolohun irugbin", + "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ó", "seedtype": "Irugbin-seetypu", "seedtype_legacy": "Legacy (awọn ọrọ 25)", "seedtype_polyseed": "Polyseed (awọn ọrọ 16)", - "seed_language_czech": "Czech", - "seed_language_korean": "Ara ẹni", - "seed_language_chinese_traditional": "Kannada (ibile)", - "ascending": "Goke", - "descending": "Sọkalẹ", - "dfx_option_description": "Ra crypto pẹlu EUR & CHF. Titi di 990 € laisi afikun KYC. Fun soobu ati awọn onibara ile-iṣẹ ni Yuroopu", - "polygonscan_history": "PolygonScan itan", - "wallet_seed_legacy": "Irugbin akole", - "default_sell_provider": "Aiyipada Olupese Tita", + "select_backup_file": "Select backup file", + "select_buy_provider_notice": "Yan olupese Ra loke. O le skii iboju yii nipa ṣiṣeto olupese rẹ ni awọn eto App.", + "select_destination": "Jọwọ yan ibi ti o nlo fun faili afẹyinti.", "select_sell_provider_notice": "Yan olupese ti o ta loke. O le foju iboju yii nipa tito olupese iṣẹ tita aiyipada rẹ ni awọn eto app.", - "custom_drag": "Aṣa (mu ati fa)", + "sell": "Tà", + "sell_alert_content": "Lọwọlọwọ a ṣe atilẹyin tita Bitcoin, Ethereum ati Litecoin nikan. Jọwọ ṣẹda tabi yipada si Bitcoin, Ethereum tabi apamọwọ Litecoin rẹ.", + "sell_monero_com_alert_content": "Kọ ju lọwọ Monero ko ṣe ni ibamu", + "send": "Ránṣẹ́", + "send_address": "${cryptoCurrency} àdírẹ́sì", + "send_amount": "Iye:", + "send_creating_transaction": "Ńṣe àránṣẹ́", + "send_error_currency": "Ó yẹ kí òǹkà dá wà nínu iye", + "send_error_minimum_value": "Ránṣẹ́ owó kò kéré dé 0.01", + "send_estimated_fee": "Iye àfikún l'a fojú díwọ̀n:", + "send_fee": "Owó àfikún:", + "send_name": "Orúkọ", + "send_new": "Títun", + "send_payment_id": "Àmì ìdánimọ̀ àránṣẹ́ (ìyàn nìyí)", + "send_priority": "${transactionPriority} agbára ni owó àfikún lọ́wọ́lọ́wọ́.\nẸ lè pààrọ̀ iye agbára t'ẹ fikún àránṣẹ́ lórí àwọn ààtò", + "send_sending": "Ń Ránṣẹ́...", + "send_success": "A ti ránṣẹ́ ${crypto} yín dáadáa", + "send_templates": "Àwọn àwòṣe", + "send_title": "Ránṣẹ́", + "send_to_this_address": "Ẹ fi ${currency} ${tag}ránṣẹ́ sí àdírẹ́sì yìí", + "send_xmr": "Fi XMR ránṣẹ́", + "send_your_wallet": "Àpamọ́wọ́ yín", + "sending": "Ó ń ránṣẹ́", + "sent": "Owó t'á ti ránṣẹ́", + "settings": "Awọn aseṣe", + "settings_all": "Gbogbo", + "settings_allow_biometrical_authentication": "Fi àyè gba ìfẹ̀rílàdí biometrical", + "settings_can_be_changed_later": "Ẹ lè pààrọ̀ àwọn ààtò yìí nínú ààtò áàpù t’ó bá yá", + "settings_change_language": "Pààrọ̀ èdè", + "settings_change_pin": "Pààrọ̀ òǹkà ìdánimọ̀ àdáni", + "settings_currency": "Iye owó", + "settings_current_node": "Apẹka lọ́wọ́lọ́wó", + "settings_dark_mode": "Ṣókùnkùn Áápù", + "settings_display_balance": "Ṣàfihàn ìyókù owó", + "settings_display_on_dashboard_list": "Ṣàfihàn lórí àkọsílẹ̀ tá fihàn", + "settings_fee_priority": "Bí iye àfikún ṣe ṣe pàtàkì", + "settings_nodes": "Àwọn apẹka", + "settings_none": "Kòsóhun", + "settings_only_trades": "Àwọn pàṣípààrọ̀ nìkan", + "settings_only_transactions": "Àwọn àránṣẹ́ nìkan", + "settings_personal": "Àdáni", + "settings_save_recipient_address": "Pamọ́ àdírẹ́sì olùgbà", + "settings_support": "Ìranlọ́wọ́", + "settings_terms_and_conditions": "Àwọn Òfin àti àwọn Àjọrò", + "settings_title": "Àwọn ààtò", + "settings_trades": "Àwọn pàṣípààrọ̀", + "settings_transactions": "Àwọn àránṣẹ́", + "settings_wallets": "Àwọn àpamọ́wọ́", + "setup_2fa": "Ṣeto Cake 2FA", + "setup_2fa_text": "Akara oyinbo 2FA ṣiṣẹ ni lilo TOTP bi ifosiwewe ijẹrisi keji.\n\nAkara oyinbo 2FA's TOTP nilo SHA-512 ati atilẹyin oni-nọmba 8; eyi pese aabo ti o pọ sii. Alaye diẹ sii ati awọn ohun elo atilẹyin ni a le rii ninu itọsọna naa.", + "setup_pin": "Setup òǹkà ìdánimọ̀ àdáni", + "setup_successful": "Òǹkà ìdánimọ̀ àdáni yín ti ṣe!", + "setup_totp_recommended": "Ṣeto TOTP", + "setup_warning_2fa_text": "Iwọ yoo nilo lati mu pada apamọwọ rẹ lati inu irugbin mnemonic.\n\nAtilẹyin akara oyinbo kii yoo ni anfani lati ṣe iranlọwọ fun ọ ti o ba padanu iraye si 2FA tabi awọn irugbin mnemonic rẹ.\nAkara oyinbo 2FA jẹ ijẹrisi keji fun awọn iṣe kan ninu apamọwọ. Ṣaaju lilo akara oyinbo 2FA, a ṣeduro kika nipasẹ itọsọna naa.Ko ṣe aabo bi ibi ipamọ tutu.\n\nTi o ba padanu iraye si ohun elo 2FA tabi awọn bọtini TOTP, iwọ YOO padanu iraye si apamọwọ yii. ", + "setup_your_debit_card": "Dá àwọn káàdì ìrajà yín", + "share": "Pinpin", + "share_address": "Pín àdírẹ́sì", + "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", + "show_seed": "Wo hóró", + "sign_up": "Forúkọ sílẹ̀", + "signTransaction": "Wole Idunadura", + "signup_for_card_accept_terms": "Ẹ f'orúkọ sílẹ̀ láti gba káàdì àti àjọrò.", + "slidable": "Slidable", + "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)", + "status": "Tó ń ṣẹlẹ̀: ", + "subaddress_title": "Àkọsílẹ̀ ni nínú àwọn àdírẹ́sì tíwọn rẹ̀lẹ̀", + "subaddresses": "Àwọn àdírẹ́sì kékeré", + "submit_request": "Ṣé ìbéèrè", + "successful": "Aseyori", + "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_live_chat": "Atilẹyin ifiwe", + "support_title_other_links": "Awọn ọna asopọ atilẹyin miiran", + "sweeping_wallet": "Fi owo iwe iwe wofo", + "sweeping_wallet_alert": "Yio kọja pada si ikan yii. Kì yoo daadaa leede yii tabi owo ti o ti fi se iwe iwe naa yoo gbe.", + "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi", "switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)", - "receivable_balance": "Iwontunws.funfun ti o gba", - "confirmed_tx": "Jẹrisi", + "symbol": "Aami", + "sync_status_attempting_sync": "Ń GBÌYÀNJÚ MÚDỌ́GBA", + "sync_status_connected": "TI DÁRAPỌ̀ MỌ́", + "sync_status_connecting": "Ń DÁRAPỌ̀ MỌ́", + "sync_status_failed_connect": "ÌKÀNPỌ̀ TI KÚ", + "sync_status_not_connected": "KÒ TI DÁRAPỌ̀ MỌ́ Ọ", + "sync_status_starting_sync": "Ń BẸ̀RẸ̀ RẸ́", + "sync_status_syncronized": "TI MÚDỌ́GBA", + "sync_status_syncronizing": "Ń MÚDỌ́GBA", + "syncing_wallet_alert_content": "Iwontunws.funfun rẹ ati atokọ idunadura le ma pari titi ti yoo fi sọ “SYNCHRONIZED” ni oke. Tẹ/tẹ ni kia kia lati ni imọ siwaju sii.", + "syncing_wallet_alert_title": "Apamọwọ rẹ n muṣiṣẹpọ", + "template": "Àwòṣe", + "template_name": "Orukọ Awoṣe", + "third_intro_content": "A sì lè lo Yats níta Cake Wallet. A lè rọ́pò Àdírẹ́sì kankan àpamọ́wọ́ fún Yat!", + "third_intro_title": "Àlàáfíà ni Yat àti àwọn ìmíìn jọ wà", + "time": "${minutes}ìṣj ${seconds}ìṣs", + "tip": "Owó àfikún:", + "today": "Lénìí", + "token_contract_address": "Àmi guide adirẹsi", + "token_decimal": "Àmi eleemewa", + "token_name": "Orukọ àmi fun apẹẹrẹ: Tether", + "token_symbol": "Aami aami fun apẹẹrẹ: USDT", + "tokenID": "ID", + "tor_connection": "Tor asopọ", + "tor_only": "Tor nìkan", + "total_saving": "Owó t'ẹ́ ti pamọ́", + "totp_2fa_failure": "Koodu ti o daju ko ri. Jọwọ jẹ koodu miiran tabi ṣiṣẹ iwe kiakia. Lo fun 2FA eto ti o ba ṣe ni jẹ 2FA ti o gba idaniloju 8-digits ati SHA512.", + "totp_2fa_success": "Pelu ogo! Cake 2FA ti fi sii lori iwe iwe yii. Tọ, mọ iye ẹrọ miiran akojọrọ jẹki o kọ ipin eto.", + "totp_auth_url": "TOTP AUTH URL", + "totp_code": "Koodu TOTP", + "totp_secret_code": "Koodu iye TOTP", + "totp_verification_success": "Ìbẹrẹ dọkita!", + "trade_details_copied": "Ti ṣeda ${title} sí àtẹ àkọsílẹ̀", + "trade_details_created_at": "Ṣíṣe ní", + "trade_details_fetching": "Ń mú wá", + "trade_details_id": "Àmì ìdánimọ̀:", + "trade_details_pair": "Àwọn irú owó t'á pàṣípààrọ̀ jọ", + "trade_details_provider": "Ilé pàṣípààrọ̀", + "trade_details_state": "Tó ń ṣẹlẹ̀", + "trade_details_title": "Ìsọfúnni pàṣípààrọ̀", + "trade_for_not_created": "A kò tí ì ṣe pàṣípààrọ̀ ${title}", + "trade_history_title": "Ìtan pàṣípààrọ̀", + "trade_id": "Pàṣípààrọ̀ àmì ìdánimọ̀:", + "trade_id_not_found": "Trade ${tradeId} ti a ko ba ri ninu ${title}.", + "trade_is_powered_by": "${provider} ń fikún pàṣípààrọ̀ yìí lágbára", + "trade_not_created": "A kò tí ì ṣe pàṣípààrọ̀ náà", + "trade_not_found": "A kò tí ì wá pàṣípààrọ̀.", + "trade_state_btc_sent": "Ti san BTC", + "trade_state_complete": "Ti ṣetán", + "trade_state_confirming": "Ń jẹ́rìí", + "trade_state_created": "Ti ṣe", + "trade_state_finished": "Ti ṣetán", + "trade_state_paid": "Ti san", + "trade_state_paid_unconfirmed": "Ti san. A kò tíì jẹ́rìí ẹ̀", + "trade_state_pending": "Pípẹ́", + "trade_state_timeout": "Ti gbẹ́mìí mì", + "trade_state_to_be_created": "Máa ṣe", + "trade_state_traded": "Ti ṣe pàṣípààrọ̀", + "trade_state_trading": "Ń ṣe pàṣípààrọ̀", + "trade_state_underpaid": "Ti san iye tó kéré jù", + "trade_state_unpaid": "Kò tíì san", + "trades": "Àwọn pàṣípààrọ̀", + "transaction_details_amount": "Iye owó", + "transaction_details_copied": "A ṣeda ${title} sí àkọsílẹ̀", + "transaction_details_date": "Ìgbà", + "transaction_details_fee": "Iye àfikún", + "transaction_details_height": "Gíga", + "transaction_details_recipient_address": "Àwọn àdírẹ́sì olùgbà", "transaction_details_source_address": "Adirẹsi orisun", - "pause_wallet_creation": "Agbara lati ṣẹda Haven Wallet ti wa ni idaduro lọwọlọwọ.", - "contractName": "Orukọ adehun", - "contractSymbol": "Aami adehun", - "description": "Apejuwe", - "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.", - "no_relays": "Ko si relays", - "choose_relay": "Jọwọ yan yii lati lo", - "no_relays_message": "A ri igbasilẹ Nostr NIP-05 fun olumulo yii, ṣugbọn ko ni eyikeyi awọn iṣipopada ninu. Jọwọ sọ fun olugba lati ṣafikun awọn isunmọ si igbasilẹ Nostr wọn.", - "no_relay_on_domain": "Ko si iṣipopada fun agbegbe olumulo tabi yiyi ko si. Jọwọ yan yii lati lo." -} + "transaction_details_title": "Àránṣẹ́ ìsọfúnni", + "transaction_details_transaction_id": "Àmì ìdánimọ̀ àránṣẹ́", + "transaction_key": "Kọ́kọ́rọ́ pàṣípààrọ̀", + "transaction_priority_fast": "Yára", + "transaction_priority_fastest": "Yá jù lọ", + "transaction_priority_medium": "L’áàárín", + "transaction_priority_regular": "Àjùmọ̀lò", + "transaction_priority_slow": "Díẹ̀", + "transaction_sent": "Ẹ ti ránṣẹ́ ẹ̀!", + "transaction_sent_notice": "Tí aṣàfihàn kò bá tẹ̀síwájú l'áàárín ìṣẹ́jú kan, ẹ tọ́ olùṣèwádìí àkójọpọ̀ àti ímeèlì yín wò.", + "transactions": "Àwọn àránṣẹ́", + "transactions_by_date": "Àwọn àránṣẹ́ t'á ti fi aago ṣa", + "trusted": "A ti fọkàn ẹ̀ tán", + "unavailable_balance": "Iwontunwonsi ti ko si", + "unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.", + "unconfirmed": "A kò tí ì jẹ́rìí ẹ̀", + "understand": "Ó ye mi", + "unmatched_currencies": "Irú owó ti àpamọ́wọ́ yín kì í ṣe irú ti yíya àmì ìlujá", + "unspent_change": "Yipada", + "unspent_coins_details_title": "Àwọn owó ẹyọ t'á kò tí ì san", + "unspent_coins_title": "Àwọn owó ẹyọ t'á kò tí ì san", + "unsupported_asset": "A ko ṣe atilẹyin iṣẹ yii fun dukia yii. Jọwọ ṣẹda tabi yipada si apamọwọ iru dukia atilẹyin.", + "upto": "kò tóbi ju ${value}", + "use": "Lo", + "use_card_info_three": "Ẹ lo káàdí ayélujára lórí wẹ́ẹ̀bù tàbí ẹ lò ó lórí àwọn ẹ̀rọ̀ ìrajà tíwọn kò kò.", + "use_card_info_two": "A pààrọ̀ owó sí owó Amẹ́ríkà tó bá wà nínú àkanti t'á ti fikún tẹ́lẹ̀tẹ́lẹ̀. A kò kó owó náà nínú owó ayélujára.", + "use_ssl": "Lo SSL", + "use_suggested": "Lo àbá", + "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_with_2fa": "Ṣeẹda pẹlu Cake 2FA", + "version": "Àtúnse ${currentVersion}", + "view_all": "Wo gbogbo nǹkan kan", + "view_in_block_explorer": "Wo lórí olùṣèwádìí àkójọpọ̀", + "view_key_private": "Kọ́kọ́rọ́ ìwò (àdáni)", + "view_key_public": "Kọ́kọ́rọ́ ìwò (kò àdáni)", + "view_transaction_on": "Wo pàṣípààrọ̀ lórí ", + "wallet_keys": "Hóró/kọ́kọ́rọ́ àpamọ́wọ́", + "wallet_list_create_new_wallet": "Ṣe àpamọ́wọ́ títun", + "wallet_list_edit_wallet": "Ṣatunkọ apamọwọ", + "wallet_list_failed_to_load": "Ti kùnà ṣí́ àpamọ́wọ́ ${wallet_name}. ${error}", + "wallet_list_failed_to_remove": "Ti kùnà yọ ${wallet_name} àpamọ́wọ́ kúrò. ${error}", + "wallet_list_load_wallet": "Load àpamọ́wọ́", + "wallet_list_loading_wallet": "Ń ṣí àpamọ́wọ́ ${wallet_name}", + "wallet_list_removing_wallet": "Ń yọ àpamọ́wọ́ ${wallet_name} kúrò", + "wallet_list_restore_wallet": "Restore àpamọ́wọ́", + "wallet_list_title": "Àpamọ́wọ́ Monero", + "wallet_list_wallet_name": "Orukọ apamọwọ", + "wallet_menu": "Mẹ́nù", + "wallet_name": "Orúkọ àpamọ́wọ́", + "wallet_name_exists": "Ẹ ti ní àpamọ́wọ́ pẹ̀lú orúkọ̀ yẹn. Ẹ jọ̀wọ́ yàn orúkọ̀ tó yàtọ̀ tàbí pààrọ̀ orúkọ ti àpamọ́wọ́ tẹ́lẹ̀.", + "wallet_restoration_store_incorrect_seed_length": "Gígùn hóró tí a máa ń lò kọ́ ni èyí", + "wallet_seed": "Hóró àpamọ́wọ́", + "wallet_seed_legacy": "Irugbin akole", + "wallet_store_monero_wallet": "Àpamọ́wọ́ Monero", + "walletConnect": "Asopọmọra apamọwọ", + "wallets": "Àwọn àpamọ́wọ́", + "warning": "Ikilo", + "welcome": "Ẹ káàbọ sí", + "welcome_to_cakepay": "Ẹ káàbọ̀ sí Cake Pay!", + "widgets_address": "Àdírẹ́sì", + "widgets_or": "tàbí", + "widgets_restore_from_blockheight": "Dá padà sípò láti gíga àkójọpọ̀", + "widgets_restore_from_date": "Dá padà sípò láti ìgbà", + "widgets_seed": "Hóró", + "wouoldLikeToConnect": "yoo fẹ lati sopọ", + "write_down_backup_password": "Ẹ jọ̀wọ́ ẹ̀dà ọ̀rọ̀ aṣínà ti ẹ̀dà nípamọ́ yín tó máa ń bá yín ṣí àkọsílẹ̀ yín l'ẹ kọ sílẹ̀.", + "xlm_extra_info": "Ẹ jọ̀wọ́ ẹ kò gbàgbé pèsè àmì ìdánimọ̀ àkọsílẹ̀ t'ẹ́ ń bá ránṣẹ́ pàṣípààrọ̀ ti XLM yín sí ilé ìfowóṣòwò", + "xmr_available_balance": "Owó tó wà ḿbí", + "xmr_full_balance": "Ìyókù owó", + "xmr_hidden": "Bìbò", + "xrp_extra_info": "Ẹ jọ̀wọ́ ẹ kò gbàgbé pèsè orúkọ̀ àdírẹ́sì ti a ránṣẹ́ sí t'ẹ́ bá ránṣẹ pàṣípààrọ̀ ti XRP yín sílé ìfowóṣòwò", + "yat": "Yat", + "yat_address": "Àdírẹ́sì Yat", + "yat_alert_content": "Àwọn olùṣàmúlò ti Cake Wallet lè fi orúkọ olùṣàmúlò t'á dá lórí emójì tó kì í jọra ránṣẹ́ àti gba gbogbo àwọn irú owó tíwọn yàn láàyò lọ́wọ́lọ́wọ́.", + "yat_alert_title": "Lílò Yat láti ránṣẹ́ àti gba owó dùn ṣe pọ̀ ju lọ", + "yat_error": "Àṣìṣe Yat", + "yat_error_content": "Kò sí àdírẹ́sìkádírẹ́sì tó so Yat yìí. Ẹ gbìyànjú Yat mìíràn", + "yat_popup_content": "Ẹ lè fi Yat yín (orúkọ olùṣàmúlò kúkurú t'á dá lórí emójì) ránṣẹ́ àti gba owó nínú Cake Wallet lọ́wọ́lọ́wọ́. Bójú Yats lórí ojú ààtò lígbàkúgbà.", + "yat_popup_title": "Ẹ lè dá àpamọ́wọ́ yín láti emójì.", + "yesterday": "Lánàá", + "you_now_have_debit_card": "Ẹ ni káàdì ìrajà lọ́wọ́lọ́wọ́", + "you_pay": "Ẹ sàn", + "you_will_get": "Ṣe pàṣípààrọ̀ sí", + "you_will_send": "Ṣe pàṣípààrọ̀ láti", + "yy": "Ọd", + "zzzz": "zzzz" +} \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 92904034b..58cb2592c 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -1,778 +1,779 @@ { - "welcome": "欢迎使用", - "cake_wallet": "Cake Wallet", - "first_wallet_text": "适用于门罗币、比特币、以太坊、莱特币和避风港的超棒钱包", - "please_make_selection": "请在下面进行选择 创建或恢复您的钱包.", - "create_new": "创建新钱包", - "restore_wallet": "恢复钱包", - "monero_com": "Monero.com by Cake Wallet", - "monero_com_wallet_text": "Awesome wallet for Monero", - "haven_app": "Haven by Cake Wallet", - "haven_app_wallet_text": "Awesome wallet for Haven", - "accounts": "账户", - "edit": "编辑", + "about_cake_pay": "Cake Pay 让您可以轻松购买带有虚拟资产的礼品卡,可立即在美国超过 150,000 家商家消费。", "account": "帐户", + "accounts": "账户", + "accounts_subaddresses": "账户和子地址", + "activate": "激活", + "active": "活跃", + "active_cards": "活动卡", + "activeConnectionsPrompt": "活动连接将出现在这里", "add": "添加", + "add_contact": "增加联系人", + "add_custom_node": "添加新的自定义节点", + "add_custom_redemption": "添加自定义兑换", + "add_fund_to_card": "向卡中添加预付资金(最多 ${value})", + "add_new_node": "添加新节点", + "add_new_word": "添加新词", + "add_receiver": "添加另一個接收器(可選)", + "add_secret_code": "或者,将此密码添加到身份验证器应用程序中", + "add_tip": "添加提示", + "add_token_disclaimer_check": "我已使用信誉良好的来源确认了代币合约地址和信息。 添加恶意或不正确的信息可能会导致资金损失。", + "add_token_warning": "请勿按照诈骗者的指示编辑或添加令牌。\n始终通过信誉良好的来源确认代币地址!", + "add_value": "增加价值", + "address": "地址", "address_book": "地址簿", - "contact": "联系", - "please_select": "请选择:", - "cancel": "取消", - "ok": "确认", - "contact_name": "联系人姓名", - "reset": "重置", - "save": "保存", + "address_book_menu": "地址簿", + "address_detected": "檢測到地址", + "address_from_domain": "此地址來自 Unstoppable Domains 上的 ${domain}", + "address_from_yat": "此地址來自 Yat 上的 ${emoji}", + "address_label": "Address label", "address_remove_contact": "刪除联系人", "address_remove_content": "您确定要刪除所选的联系人吗?", - "authenticated": "已认证", - "authentication": "认证方式", - "failed_authentication": "身份验证失败. ${state_error}", - "wallet_menu": "钱包菜单", - "Blocks_remaining": "${status} 剩余的块", - "please_try_to_connect_to_another_node": "请尝试连接到其他节点", - "xmr_hidden": "隐藏", - "xmr_available_balance": "可用余额 ", - "xmr_full_balance": "全部余额", - "send": "发送", - "receive": "接收", - "transactions": "交易情况", - "incoming": "收到", - "outgoing": "发送", - "transactions_by_date": "按日期交易", - "trades": "交易", - "filter_by": "过滤", - "today": "今天", - "yesterday": "昨天", - "received": "已收到", - "sent": "已发送", - "pending": " (待定)", - "rescan": "重新扫描", - "reconnect": "重新连接", - "wallets": "钱包", - "show_seed": "显示种子", - "show_keys": "显示种子/密钥", - "address_book_menu": "地址簿", - "reconnection": "重新连接", - "reconnect_alert_text": "您确定要重新连接吗?", - "exchange": "兑换", - "clear": "清空", - "refund_address": "退款地址", - "change_exchange_provider": "更改交易所", - "you_will_send": "转换自", - "you_will_get": "转换到", - "amount_is_guaranteed": "保证收到的金额", - "amount_is_estimate": "收款金额为估算值", - "powered_by": "Powered by ${title}", - "error": "错误", - "estimated": "估计值", - "min_value": "最小: ${value} ${currency}", - "max_value": "最大: ${value} ${currency}", - "change_currency": "更改币种", - "overwrite_amount": "Overwrite amount", - "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", - "copy_id": "复制ID", - "exchange_result_write_down_trade_id": "请复制或写下交易编号以继续.", - "trade_id": "交易编号:", - "copied_to_clipboard": "复制到剪贴板", - "saved_the_trade_id": "我已经保存了交易编号", - "fetching": "正在获取", - "id": "ID: ", - "amount": "金额: ", - "payment_id": "付款 ID: ", - "status": "状态: ", - "offer_expires_in": "优惠有效期至 ", - "trade_is_powered_by": "该交易由 ${provider}", - "copy_address": "复制地址", - "exchange_result_confirm": "点击确认 您将发送 ${fetchingLabel} ${from} 从你的钱包里 ${walletName} 到下面显示的地址。 或者您可以从外部钱包发送到以下地址/ QR码。\n\n请按确认继续或返回以更改金额", - "exchange_result_description": "您必须至少发送 ${fetchingLabel} ${from} 到下一页上显示的地址。 如果您发送的金额少于 ${fetchingLabel} ${from},则可能无法转换,因此无法退还。", - "exchange_result_write_down_ID": "*请复制或写下您上面显示的ID.", - "confirm": "确认", - "confirm_sending": "确认发送", - "commit_transaction_amount_fee": "提交交易\n金额: ${amount}\n手续费: ${fee}", - "sending": "正在发送", - "transaction_sent": "交易已发送", - "expired": "已过期", - "time": "${minutes}m ${seconds}s", - "send_xmr": "发送 XMR", - "exchange_new_template": "新模板", - "faq": "FAQ", - "enter_your_pin": "输入密码", - "loading_your_wallet": "加载您的钱包", - "new_wallet": "新钱包", - "wallet_name": "钱包名称", - "continue_text": "继续", - "choose_wallet_currency": "请选择钱包货币:", - "node_new": "新节点", - "node_address": "节点地址", - "node_port": "节点端口", - "login": "登录", - "password": "密码", - "nodes": "节点", - "node_reset_settings_title": "重新设置", - "nodes_list_reset_to_default_message": "您确定要将设置重设为默认值吗?", - "change_current_node": "您确定将当前节点更改为 ${node}?", - "change": "更改", - "remove_node": "删除节点", - "remove_node_message": "您确定要删除所选节点吗?", - "remove": "确定", - "delete": "删除", - "add_new_node": "添加新节点", - "change_current_node_title": "更改当前节点", - "node_test": "测试", - "node_connection_successful": "连接成功", - "node_connection_failed": "连接失败", - "new_node_testing": "新节点测试", - "use": "切换使用", - "digit_pin": "位 PIN", - "share_address": "分享地址", - "receive_amount": "金额", - "subaddresses": "子地址", "addresses": "地址", - "scan_qr_code_to_get_address": "扫描二维码获取地址", - "qr_fullscreen": "点击打开全屏二维码", - "rename": "重命名", - "choose_account": "选择账户", - "create_new_account": "建立新账户", - "accounts_subaddresses": "账户和子地址", - "restore_restore_wallet": "恢复钱包", - "restore_title_from_seed_keys": "从种子/密钥还原", - "restore_description_from_seed_keys": "从保存到安全地方的种子/钥匙取回钱包", - "restore_next": "下一个", - "restore_title_from_backup": "从备份文件还原", - "restore_description_from_backup": "您可以从还原整个Cake Wallet应用您的备份文件", - "restore_seed_keys_restore": "种子/密钥还原", - "restore_title_from_seed": "从种子还原", - "restore_description_from_seed": "从25个字中恢复您的钱包或13个字的组合码", - "restore_title_from_keys": "从密钥还原", - "restore_description_from_keys": "使用私钥恢复钱包", - "restore_wallet_name": "钱包名称", - "restore_address": "地址", - "restore_view_key_private": "View私钥", - "restore_spend_key_private": "Spend私钥", - "restore_recover": "恢复", - "restore_wallet_restore_description": "钱包还原说明", - "restore_new_seed": "新种子", - "restore_active_seed": "活动种子", - "restore_bitcoin_description_from_seed": "从24个文字的组成码恢复您的钱包", - "restore_bitcoin_description_from_keys": "从私钥中生成的WIF字符串恢复您钱包", - "restore_bitcoin_title_from_keys": "从WIF还原", - "restore_from_date_or_blockheight": "请输入您创建这个钱包前几天的日期。或者如果您知道区块高度,请输入区块高度", - "seed_reminder": "请记下这些内容,以防丟失或数据损坏", - "seed_title": "种子", - "seed_share": "分享种子", - "copy": "复制", - "seed_language": "种子语言", - "seed_choose": "选择种子语言", - "seed_language_next": "下一个", - "seed_language_english": "英文", - "seed_language_chinese": "中文", - "seed_language_dutch": "荷兰文", - "seed_language_german": "德文", - "seed_language_japanese": "日文", - "seed_language_portuguese": "葡萄牙文", - "seed_language_russian": "俄文", - "seed_language_spanish": "西班牙文", - "seed_language_french": "法语", - "seed_language_italian": "意大利语", - "send_title": "发送", - "send_your_wallet": "你的钱包", - "send_address": "${cryptoCurrency} 地址", - "send_payment_id": "付款编号 (可选的)", + "advanced_settings": "高级设置", + "aggressive": "过分热心", + "agree": "同意", + "agree_and_continue": "同意并继续", + "agree_to": "创建账户即表示您同意 ", "all": "全部", - "send_error_minimum_value": "最小金额为0.01", - "send_error_currency": "货币只能包含数字", - "send_estimated_fee": "预估费用:", - "send_priority": "目前,费用设置为 ${transactionPriority} 优先.\n交易优先级可以在设置中进行调整", - "send_creating_transaction": "创建交易", - "send_templates": "模板", - "send_new": "新建", - "send_amount": "金额:", - "send_fee": "手续费:", - "send_name": "名称", - "got_it": "明白", - "send_sending": "正在发送...", - "send_success": "您的${crypto}已成功发送", - "settings_title": "设定值", - "settings_nodes": "节点数", - "settings_current_node": "当前节点", - "settings_wallets": "钱包", - "settings_display_balance": "显示余额为", - "settings_currency": "货币", - "settings_fee_priority": "交易优先级", - "settings_save_recipient_address": "保存收件人地址", - "settings_personal": "个人", - "settings_change_pin": "更改密码", - "settings_change_language": "修改语言", - "settings_allow_biometrical_authentication": "允许生物识别认证", - "settings_dark_mode": "黑暗模式", - "settings_transactions": "交易情况", - "settings_trades": "交易", - "settings_display_on_dashboard_list": "显示在仪表板上", - "settings_all": "全部", - "settings_only_trades": "只交易", - "settings_only_transactions": "仅交易", - "settings_none": "没有", - "settings_support": "帮助", - "settings_terms_and_conditions": "条款和条件", - "pin_is_incorrect": "PIN码不正确", - "setup_pin": "设定PIN码", - "enter_your_pin_again": "再次输入您的PIN码", - "setup_successful": "您的PIN码已成功设置!", - "wallet_keys": "钱包种子/密钥", - "wallet_seed": "钱包种子", - "private_key": "私钥", - "public_key": "公钥", - "view_key_private": "View 密钥(私钥)", - "view_key_public": "View 密钥(公钥)", - "spend_key_private": "Spend 密钥 (私钥)", - "spend_key_public": "Spend 密钥 (公钥)", - "copied_key_to_clipboard": "复制 ${key} 到剪贴板", - "new_subaddress_title": "新地址", - "new_subaddress_label_name": "标签名称", - "new_subaddress_create": "创建", - "address_label": "Address label", - "subaddress_title": "子地址列表", - "trade_details_title": "交易明细", - "trade_details_id": "ID", - "trade_details_state": "条件", - "trade_details_fetching": "正在获取", - "trade_details_provider": "提供者", - "trade_details_created_at": "创建于", - "trade_details_pair": "对", - "trade_details_copied": "${title} 复制到剪贴板", - "trade_history_title": "交易历史", - "transaction_details_title": "交易明细", - "transaction_details_transaction_id": "交易编号", - "transaction_details_date": "日期", - "transaction_details_height": "区块高度", - "transaction_details_amount": "金额", - "transaction_details_fee": "手续费", - "transaction_details_copied": "${title} 复制到剪切板", - "transaction_details_recipient_address": "收件人地址", - "wallet_list_title": "Monero 钱包", - "wallet_list_create_new_wallet": "创建新钱包", - "wallet_list_edit_wallet": "编辑钱包", - "wallet_list_wallet_name": "钱包名称", - "wallet_list_restore_wallet": "恢复钱包", - "wallet_list_load_wallet": "加载钱包", - "wallet_list_loading_wallet": "载入中 ${wallet_name} 钱包", - "wallet_list_failed_to_load": "加载失败 ${wallet_name} 钱包. ${error}", - "wallet_list_removing_wallet": "删除 ${wallet_name} 钱包", - "wallet_list_failed_to_remove": "删除失败 ${wallet_name} 钱包. ${error}", - "widgets_address": "地址", - "widgets_restore_from_blockheight": "从块高还原", - "widgets_restore_from_date": "从日期还原", - "widgets_or": "或者", - "widgets_seed": "种子", - "router_no_route": "未定义路线 ${name}", - "error_text_account_name": "帐户名称只能包含字母数字\n且必须介于1到15个字符之间", - "error_text_contact_name": "联系人姓名不能包含`,' \" 符号\n并且必须介于1到32个字符之间", - "error_text_address": "钱包地址必须与类型对应\n加密货币", - "error_text_node_address": "请输入一个IPv4地址", - "error_text_node_port": "节点端口只能包含0到65535之间的数字", - "error_text_node_proxy_address": "请输入:<端口>,例如127.0.0.1:9050", - "error_text_payment_id": "付款ID只能包含16到64个字符(十六进制)", - "error_text_xmr": "XMR值不能超过可用余额.\n小数位数必须小于或等于12", - "error_text_fiat": "金额不能超过可用余额.\n小数位数必须小于或等于2", - "error_text_subaddress_name": "子地址名称不能包含`,' \" 符号\n并且必须在1到20个字符之间", - "error_text_amount": "金额只能包含数字", - "error_text_wallet_name": "钱包名称只能包含字母、数字、_ - 符号\n并且长度必须在 1 到 33 个字符之间", - "error_text_keys": "钱包密钥只能包含16个字符的十六进制字符", - "error_text_crypto_currency": "小数位数\n必须小于或等于12", - "error_text_minimal_limit": "未创建 ${provider} 交易。 金额小于最小值:${min} ${currency}", - "error_text_maximum_limit": "未创建 ${provider} 交易。 金额大于最大值:${max} ${currency}", - "error_text_limits_loading_failed": "未创建 ${provider} 交易。 限制加载失败", - "error_text_template": "模板名称和地址不能包含`,' \" 符号\n并且必须在1到106个字符之间", + "all_trades": "所有的变化", + "all_transactions": "所有交易", + "alphabetical": "按字母顺序", + "already_have_account": "已经有账号了?", + "always": "总是", + "amount": "金额: ", + "amount_is_estimate": "收款金额为估算值", + "amount_is_guaranteed": "保证收到的金额", + "and": "和", + "anonpay_description": "生成 ${type}。收款人可以使用任何受支持的加密货币 ${method},您将在此钱包中收到资金。", + "apk_update": "APK更新", + "approve": "批准", + "arrive_in_this_address": "${currency} ${tag}将到达此地址", + "ascending": "上升", + "ask_each_time": "每次问", "auth_store_ban_timeout": "禁止超时", "auth_store_banned_for": "禁止 ", "auth_store_banned_minutes": " 分钟", "auth_store_incorrect_password": "PIN码错误", - "wallet_store_monero_wallet": "Monero 钱包", - "wallet_restoration_store_incorrect_seed_length": "种子长度错误", - "full_balance": "全部余额", - "available_balance": "可用余额", - "hidden_balance": "隐藏余额", - "sync_status_syncronizing": "正在同步", - "sync_status_syncronized": "已同步", - "sync_status_not_connected": "未连接", - "sync_status_starting_sync": "开始同步", - "sync_status_failed_connect": "断线", - "sync_status_connecting": "连接中", - "sync_status_connected": "已连接", - "sync_status_attempting_sync": "嘗試同步", - "transaction_priority_slow": "慢速", - "transaction_priority_regular": "常规", - "transaction_priority_medium": "中等", - "transaction_priority_fast": "快速", - "transaction_priority_fastest": "最快", - "trade_for_not_created": "交易 ${title} 未创建.", - "trade_not_created": "未建立交易", - "trade_id_not_found": "交易方式 ${tradeId} 的 ${title} 未找到.", - "trade_not_found": "找不到交易.", - "trade_state_pending": "待定", - "trade_state_confirming": "确认中", - "trade_state_trading": "交易", - "trade_state_traded": "已交易", - "trade_state_complete": "完成", - "trade_state_to_be_created": "待创建", - "trade_state_unpaid": "未付", - "trade_state_underpaid": "支付不足", - "trade_state_paid_unconfirmed": "付费未确认", - "trade_state_paid": "已付费", - "trade_state_btc_sent": "已发送", - "trade_state_timeout": "超时", - "trade_state_created": "已建立", - "trade_state_finished": "已完成", - "change_language": "修改语言", - "change_language_to": "修改语言为 ${language}?", - "paste": "粘贴", - "restore_from_seed_placeholder": "请在此处输入或粘贴您的代码短语", - "add_new_word": "添加新词", - "incorrect_seed": "输入的文字无效。", - "biometric_auth_reason": "扫描指纹进行身份认证", - "version": "版本 ${currentVersion}", - "extracted_address_content": "您将汇款至\n${recipient_name}", - "card_address": "地址:", - "buy": "购买", - "placeholder_transactions": "您的交易将显示在这里", - "placeholder_contacts": "您的联系人将显示在这里", - "template": "模板", - "confirm_delete_template": "此操作将刪除此模板。确定吗?", - "confirm_delete_wallet": "此操作将刪除此钱包。确定吗?", - "change_wallet_alert_title": "更换当前钱包", - "change_wallet_alert_content": "您是否想将当前钱包改为 ${wallet_name}?", - "creating_new_wallet": "创建新钱包", - "creating_new_wallet_error": "错误: ${description}", - "seed_alert_title": "注意", - "seed_alert_content": "种子是恢复钱包的唯一方法。记住了吗?", - "seed_alert_back": "返回", - "seed_alert_yes": "确定", - "exchange_sync_alert_content": "请等待,直到您的钱包同步", - "pre_seed_title": "重要", - "pre_seed_description": "在下一页上,您将看到${words}个文字。 这是您独有的种子,是丟失或出现故障时恢复钱包的唯一方法。 您有必须将其写下并储存在Cake Wallet应用程序以外的安全地方。", - "pre_seed_button_text": "我明白。 查看种子", - "xmr_to_error": "XMR.TO 错误", - "xmr_to_error_description": "无效的金额。 小数点后最多8位数字", - "provider_error": "${provider} 错误", - "use_ssl": "使用SSL", - "trusted": "值得信赖", - "color_theme": "主题", - "light_theme": "艳丽", - "bright_theme": "明亮", - "dark_theme": "黑暗", - "enter_your_note": "输入您的笔记...", - "note_optional": "注释(可选)", - "note_tap_to_change": "注释(轻按即可更改)", - "view_in_block_explorer": "View in Block Explorer", - "view_transaction_on": "View Transaction on ", - "transaction_key": "交易密码", - "confirmations": "确认", - "recipient_address": "收件人地址", - "extra_id": "额外ID:", - "destination_tag": "目标Tag:", - "memo": "备忘录:", - "backup": "备份", - "change_password": "更改密码", - "backup_password": "备份密码", - "write_down_backup_password": "请写下您的备份密码,该密码用于导入备份文件。", - "export_backup": "导出备份", - "save_backup_password": "请确保您已保存备份密码。 沒有它,您将无法导入备份文件。", - "backup_file": "备份文件", - "edit_backup_password": "编辑备份密码", - "save_backup_password_alert": "保存备份密码", - "change_backup_password_alert": "您以前的备份文件将无法使用新的备份密码導入。 新的备份密码将仅用于新的备份文件。 您确定要更改备份密码吗?", - "enter_backup_password": "在此处输入備用密码", - "select_backup_file": "选择备份文件", - "import": "进口", - "please_select_backup_file": "请选择备份文件,然后输入备份密码。", - "fixed_rate": "固定汇率", - "fixed_rate_alert": "选中固定汇率模式后,您将可以输入接收金额。 您要切换到固定汇率模式吗?", - "xlm_extra_info": "发送用于交换的XLM交易时,请不要忘记指定备忘录ID", - "xrp_extra_info": "发送用于交换的XRP交易时,请不要忘记指定目标Tag", - "exchange_incorrect_current_wallet_for_xmr": "如果要从Cake Wallet Monero余额中兑换XMR,请先切换到Monero钱包。", - "confirmed": "确认余额", - "unconfirmed": "未确认余额", - "displayable": "可显示", - "submit_request": "提交请求", - "buy_alert_content": "目前我们仅支持购买比特币、以太坊、莱特币和门罗币。请创建或切换到您的比特币、以太坊、莱特币或门罗币钱包。", - "sell_alert_content": "我们目前仅支持比特币、以太坊和莱特币的销售。请创建或切换到您的比特币、以太坊或莱特币钱包。", - "outdated_electrum_wallet_description": "在Cake创建的新比特币钱包现在有一个24字的种子。你必须创建一个新的比特币钱包,并将你所有的资金转移到新的24字钱包,并停止使用12字种子的钱包。请立即这样做以保证你的资金安全。", - "understand": "我已知晓", - "apk_update": "APK更新", - "buy_bitcoin": "购买比特币", - "buy_with": "一起购买", - "moonpay_alert_text": "金额的价值必须大于或等于 ${minAmount} ${fiatCurrency}", - "outdated_electrum_wallet_receive_warning": "如果这个钱包有一个 12 字的种子并且是在 Cake 中创建的,不要将比特币存入这个钱包。 任何转移到此钱包的 BTC 都可能丢失。 创建一个新的 24 字钱包(点击右上角的菜单,选择钱包,选择创建新钱包,然后选择比特币)并立即将您的 BTC 移到那里。 Cake 的新(24 字)BTC 钱包是安全的", - "do_not_show_me": "不再提示", - "unspent_coins_title": "未使用的硬幣", - "unspent_coins_details_title": "未使用代幣詳情", - "freeze": "凍結", - "frozen": "凍結的", - "coin_control": "硬幣控制(可選)", - "address_detected": "檢測到地址", - "address_from_domain": "此地址來自 Unstoppable Domains 上的 ${domain}", - "add_receiver": "添加另一個接收器(可選)", - "manage_yats": "管理 Yats", - "yat_alert_title": "使用 Yat 更輕鬆地發送和接收加密貨幣", - "yat_alert_content": "Cake Wallet 用戶現在可以使用獨一無二的基於表情符號的用戶名發送和接收他們喜歡的所有貨幣。", - "get_your_yat": "得到你的 Yat", - "connect_an_existing_yat": "連接現有 Yat", - "yat_address": "Yat 地址", - "yat": "Yat", - "connect_yats": "连接 Yats", - "address_from_yat": "此地址來自 Yat 上的 ${emoji}", - "yat_error": "Yat 誤差", - "yat_error_content": "沒有與此 Yat 相關聯的地址。 嘗試另一個 Yat", - "choose_address": "\n\n請選擇地址:", - "yat_popup_title": "您的錢包地址可以被表情化。", - "yat_popup_content": "您現在可以使用 Yat 在 Cake Wallet 中發送和接收加密貨幣 - 一個基於表情符號的簡短用戶名。 在設置屏幕上隨時管理 Yats", - "second_intro_title": "一個表情符號地址來統治他們", - "second_intro_content": "您的 Yat 是一個唯一的表情符號地址,可替換您所有貨幣的所有長十六進制地址。", - "third_intro_title": "Yat 和別人玩得很好", - "third_intro_content": "Yats 也住在 Cake Wallet 之外。 地球上任何一個錢包地址都可以用一個Yat來代替!", - "learn_more": "了解更多", - "search": "搜索", - "search_language": "搜索语言", - "search_currency": "搜索货币", - "new_template": "新模板", - "electrum_address_disclaimer": "每次您使用一个地址时,我们都会生成新地址,但之前的地址仍然有效", - "wallet_name_exists": "同名的钱包已经存在", - "market_place": "市场", - "cake_pay_title": "Cake Pay 礼品卡", - "cake_pay_subtitle": "购买打折礼品卡(仅限美国)", - "cake_pay_web_cards_title": "蛋糕支付网络卡", - "cake_pay_web_cards_subtitle": "购买全球预付卡和礼品卡", - "about_cake_pay": "Cake Pay 让您可以轻松购买带有虚拟资产的礼品卡,可立即在美国超过 150,000 家商家消费。", - "cake_pay_account_note": "只需使用電子郵件地址註冊即可查看和購買卡片。有些甚至可以打折!", - "already_have_account": "已经有账号了?", - "create_account": "创建账户", - "privacy_policy": "隐私政策", - "welcome_to_cakepay": "欢迎来到 Cake Pay!", - "sign_up": "注册", - "forgot_password": "忘记密码", - "reset_password": "重置密码", - "gift_cards": "礼品卡", - "setup_your_debit_card": "设置你的借记卡", - "no_id_required": "不需要身份证。充值并在任何地方消费", - "how_to_use_card": "如何使用这张卡", - "purchase_gift_card": "购买礼品卡", - "verification": "验证", - "fill_code": "请填写提供给您邮箱的验证码", - "didnt_get_code": "没有获取代码?", - "resend_code": "请重新发送", - "debit_card": "借记卡", - "cakepay_prepaid_card": "CakePay 预付借记卡", - "no_id_needed": "不需要 ID!", - "frequently_asked_questions": "常见问题", - "debit_card_terms": "您的支付卡号(以及与您的支付卡号对应的凭证)在此数字钱包中的存储和使用受适用的持卡人与支付卡发卡机构签订的协议的条款和条件的约束,自时不时。", - "please_reference_document": "请参考以下文档以获取更多信息。", - "cardholder_agreement": "持卡人协议", - "e_sign_consent": "电子签名同意", - "agree_and_continue": "同意并继续", - "email_address": "电子邮件地址", - "agree_to": "创建账户即表示您同意 ", - "and": "和", - "enter_code": "输入代码", - "congratulations": "恭喜!", - "you_now_have_debit_card": "你现在有一张借记卡", - "min_amount": "最小值: ${value}", - "max_amount": "最大值: ${value}", - "enter_amount": "输入金额", - "billing_address_info": "如果要求提供帐单地址,请提供您的送货地址", - "order_physical_card": "订购实体卡", - "add_value": "增加价值", - "activate": "激活", - "get_a": "得到一个", - "digital_and_physical_card": "数字和物理预付借记卡", - "get_card_note": "你可以用数字货币重新加载。不需要额外的信息!", - "signup_for_card_accept_terms": "注册卡并接受条款。", - "add_fund_to_card": "向卡中添加预付资金(最多 ${value})", - "use_card_info_two": "预付账户中的资金转换为美元,不是数字货币。", - "use_card_info_three": "在线使用电子卡或使用非接触式支付方式。", - "optionally_order_card": "可选择订购实体卡。", - "hide_details": "隐藏细节", - "show_details": "显示详细信息", - "upto": "最高 ${value}", - "discount": "节省 ${value}%", - "gift_card_amount": "礼品卡金额", - "bill_amount": "账单金额", - "you_pay": "你付钱", - "tip": "提示:", - "custom": "自定义", - "by_cake_pay": "通过 Cake Pay", - "expires": "过期", - "mm": "毫米", - "yy": "YY", - "online": "在线", - "offline": "离线", - "gift_card_number": "礼品卡号", - "pin_number": "PIN 码", - "total_saving": "总储蓄", - "last_30_days": "过去 30 天", - "avg_savings": "平均储蓄", - "view_all": "查看全部", - "active_cards": "活动卡", - "delete_account": "删除账户", - "cards": "卡片", - "active": "活跃", - "redeemed": "赎回", - "gift_card_balance_note": "有余额的礼品卡会出现在这里", - "gift_card_redeemed_note": "您兑换的礼品卡会出现在这里", - "logout": "注销", - "add_tip": "添加提示", - "percentageOf": "${amount}", - "is_percentage": "是", - "search_category": "搜索类别", - "mark_as_redeemed": "标记为已赎回", - "more_options": "更多选项", - "awaiting_payment_confirmation": "等待付款确认", - "transaction_sent_notice": "如果屏幕在 1 分钟后没有继续,请检查区块浏览器和您的电子邮件。", - "agree": "同意", - "in_store": "店内", - "generating_gift_card": "生成礼品卡", - "payment_was_received": "您的付款已收到。", - "proceed_after_one_minute": "如果屏幕在 1 分钟后没有继续,请检查您的电子邮件。", - "order_id": "订单编号", - "gift_card_is_generated": "礼品卡生成", - "open_gift_card": "打开礼品卡", - "contact_support": "联系支持", - "gift_cards_unavailable": "目前只能通过门罗币、比特币和莱特币购买礼品卡", - "background_sync_mode": "后台同步模式", - "sync_all_wallets": "同步所有钱包", - "introducing_cake_pay": "介绍 Cake Pay!", - "cake_pay_learn_more": "立即在应用中购买和兑换礼品卡!\n从左向右滑动以了解详情。", + "authenticated": "已认证", + "authentication": "认证方式", + "auto_generate_subaddresses": "自动生成子辅助", "automatic": "自动的", - "fixed_pair_not_supported": "所选交易所不支持此固定货币对", - "variable_pair_not_supported": "所选交易所不支持此变量对", - "none_of_selected_providers_can_exchange": "选定的供应商都不能进行此交换", - "choose_one": "选一个", - "choose_from_available_options": "从可用选项中选择:", - "custom_redeem_amount": "自定义兑换金额", - "add_custom_redemption": "添加自定义兑换", - "remaining": "剩余", - "delete_wallet": "删除钱包", - "delete_wallet_confirm_message": "您确定要删除 ${wallet_name} 钱包吗?", - "low_fee": "费用低", - "low_fee_alert": "您当前正在使用低网络费用优先级。这可能会导致长时间等待、不同的费率或取消交易。我们建议设置更高的费用以获得更好的体验。", - "ignor": "忽视", - "use_suggested": "使用建议", - "do_not_share_warning_text": "请勿与其他任何人分享这些信息,包括支持人员。\n\n您的资金可能而且将会被盗!", - "help": "帮助", - "all_transactions": "所有交易", - "all_trades": "所有的变化", - "connection_sync": "连接和同步", - "security_and_backup": "安全和备份", - "create_backup": "创建备份", - "privacy_settings": "隐私设置", - "privacy": "隐私", - "display_settings": "显示设置", - "other_settings": "其他设置", - "require_pin_after": "之后需要 PIN", - "always": "总是", - "minutes_to_pin_code": "${minute} 分钟", - "disable_exchange": "禁用交换", - "advanced_settings": "高级设置", - "settings_can_be_changed_later": "稍后可以在应用设置中更改这些设置", - "add_custom_node": "添加新的自定义节点", - "disable_fiat": "禁用法令", - "fiat_api": "法币API", - "disabled": "禁用", - "enabled": "启用", - "tor_only": "仅限 Tor", - "unmatched_currencies": "您当前钱包的货币与扫描的 QR 的货币不匹配", - "orbot_running_alert": "请确保 Orbot 在连接到此节点之前正在运行。", - "contact_list_contacts": "联系人", - "contact_list_wallets": "我的钱包", - "bitcoin_payments_require_1_confirmation": "比特币支付需要 1 次确认,这可能需要 20 分钟或更长时间。谢谢你的耐心!确认付款后,您将收到电子邮件。", - "send_to_this_address": "发送 ${currency} ${tag}到这个地址", - "arrive_in_this_address": "${currency} ${tag}将到达此地址", - "do_not_send": "不要发送", - "error_dialog_content": "糟糕,我们遇到了一些错误。\n\n请将崩溃报告发送给我们的支持团队,以改进应用程序。", - "scan_qr_code": "扫描二维码", - "cold_or_recover_wallet": "添加冷钱包或恢复纸钱包", - "please_wait": "请稍等", - "sweeping_wallet": "扫一扫钱包", - "sweeping_wallet_alert": "\n这应该不会花很长时间。请勿离开此屏幕,否则可能会丢失所掠取的资金", - "decimal_places_error": "小数位太多", - "edit_node": "编辑节点", - "invoice_details": "发票明细", - "donation_link_details": "捐赠链接详情", - "anonpay_description": "生成 ${type}。收款人可以使用任何受支持的加密货币 ${method},您将在此钱包中收到资金。", - "create_invoice": "创建发票", - "create_donation_link": "创建捐赠链接", - "optional_email_hint": "可选的收款人通知电子邮件", - "optional_description": "可选说明", - "optional_name": "可选收件人姓名", - "clearnet_link": "明网链接", - "onion_link": "洋葱链接", - "settings": "设置", - "sell_monero_com_alert_content": "尚不支持出售门罗币", - "error_text_input_below_minimum_limit": "金额小于最小值", - "error_text_input_above_maximum_limit": "金额大于最大值", - "show_market_place": "显示市场", - "prevent_screenshots": "防止截屏和录屏", - "profile": "轮廓", - "close": "关闭", - "modify_2fa": "修改蛋糕2FA", - "disable_cake_2fa": "禁用蛋糕 2FA", - "question_to_disable_2fa": "您确定要禁用 Cake 2FA 吗?访问钱包和某些功能将不再需要 2FA 代码。", - "disable": "停用", - "setup_2fa": "设置蛋糕 2FA", - "verify_with_2fa": "用 Cake 2FA 验证", - "totp_code": "TOTP代码", - "please_fill_totp": "请填写您其他设备上的 8 位代码", - "totp_2fa_success": "成功!为此钱包启用了 Cake 2FA。请记住保存您的助记词种子,以防您无法访问钱包。", - "totp_verification_success": "验证成功!", - "totp_2fa_failure": "不正确的代码。 请尝试不同的代码或生成新的密钥。 使用支持 8 位代码和 SHA512 的兼容 2FA 应用程序。", - "enter_totp_code": "请输入 TOTP 代码。", - "add_secret_code": "或者,将此密码添加到身份验证器应用程序中", - "totp_secret_code": "TOTP密码", - "setup_2fa_text": "Cake 2FA 使用 TOTP 作为第二个身份验证因素。\n\nCake 2FA 的 TOTP 需要 SHA-512 和 8 位数字支持;这提供了更高的安全性。更多信息和支持的应用程序可以在指南中找到。", - "setup_totp_recommended": "设置 TOTP", - "disable_buy": "禁用购买操作", - "disable_sell": "禁用卖出操作", - "cake_2fa_preset": "蛋糕 2FA 预设", - "narrow": "狭窄的", - "normal": "普通的", - "aggressive": "过分热心", - "require_for_assessing_wallet": "需要访问钱包", - "require_for_sends_to_non_contacts": "需要发送给非联系人", - "require_for_sends_to_contacts": "需要发送给联系人", - "require_for_sends_to_internal_wallets": "需要发送到内部钱包", - "require_for_exchanges_to_internal_wallets": "需要兑换到内部钱包", - "require_for_adding_contacts": "需要添加联系人", - "require_for_creating_new_wallets": "创建新钱包的要求", - "require_for_all_security_and_backup_settings": "需要所有安全和备份设置", + "available_balance": "可用余额", "available_balance_description": "可用余额是您可以使用的金额。冻结余额是您当前正在等待确认的金额。", - "syncing_wallet_alert_title": "您的钱包正在同步", - "syncing_wallet_alert_content": "您的余额和交易列表可能不完整,直到顶部显示“已同步”。单击/点击以了解更多信息。", - "home_screen_settings": "主屏幕设置", - "sort_by": "排序方式", - "search_add_token": "搜索/添加令牌", - "edit_token": "编辑令牌", - "warning": "警告", - "add_token_warning": "请勿按照诈骗者的指示编辑或添加令牌。\n始终通过信誉良好的来源确认代币地址!", - "add_token_disclaimer_check": "我已使用信誉良好的来源确认了代币合约地址和信息。 添加恶意或不正确的信息可能会导致资金损失。", - "token_contract_address": "代币合约地址", - "token_name": "代币名称例如:Tether", - "token_symbol": "代币符号例如:USDT", - "token_decimal": "令牌十进制", - "field_required": "此字段是必需的", - "pin_at_top": "将 ${token} 固定在顶部", - "invalid_input": "输入无效", - "fiat_balance": "法币余额", - "gross_balance": "毛余额", - "alphabetical": "按字母顺序", - "generate_name": "生成名称", + "avg_savings": "平均储蓄", + "awaitDAppProcessing": "请等待 dApp 处理完成。", + "awaiting_payment_confirmation": "等待付款确认", + "background_sync_mode": "后台同步模式", + "backup": "备份", + "backup_file": "备份文件", + "backup_password": "备份密码", "balance_page": "余额页", - "share": "分享", - "slidable": "可滑动", - "manage_nodes": "管理节点", - "etherscan_history": "以太扫描历史", - "template_name": "模板名称", - "change_rep": "变革代表", - "change_rep_message": "您确定要更换代表吗?", - "unsupported_asset": "我们不支持针对该资产采取此操作。请创建或切换到支持的资产类型的钱包。", - "manage_pow_nodes": "管理 PoW 节点", - "support_title_live_chat": "实时支持", - "support_description_live_chat": "免费快速!训练有素的支持代表可以协助", - "support_title_guides": "蛋糕钱包指南", - "support_description_guides": "对常见问题的文档和支持", - "support_title_other_links": "其他支持链接", - "support_description_other_links": "加入我们的社区或通过其他方法与我们联系我们的合作伙伴", - "choose_derivation": "选择钱包推导", - "new_first_wallet_text": "轻松确保您的加密货币安全", - "monero_dark_theme": "门罗币深色主题", + "bill_amount": "账单金额", + "billing_address_info": "如果要求提供帐单地址,请提供您的送货地址", + "biometric_auth_reason": "扫描指纹进行身份认证", "bitcoin_dark_theme": "比特币黑暗主题", "bitcoin_light_theme": "比特币浅色主题", - "high_contrast_theme": "高对比度主题", - "matrix_green_dark_theme": "矩阵绿暗主题", - "monero_light_theme": "门罗币浅色主题", - "select_destination": "请选择备份文件的目的地。", - "auto_generate_subaddresses": "自动生成子辅助", - "save_to_downloads": "保存到下载", - "select_buy_provider_notice": "在上面选择买入提供商。您可以通过在应用程序设置中设置默认的购买提供商来跳过此屏幕。", - "onramper_option_description": "快速使用许多付款方式购买加密货币。在大多数国家 /地区可用。利差和费用各不相同。", - "default_buy_provider": "默认购买提供商", - "ask_each_time": "每次问", + "bitcoin_payments_require_1_confirmation": "比特币支付需要 1 次确认,这可能需要 20 分钟或更长时间。谢谢你的耐心!确认付款后,您将收到电子邮件。", + "Blocks_remaining": "${status} 剩余的块", + "bright_theme": "明亮", + "buy": "购买", + "buy_alert_content": "目前我们仅支持购买比特币、以太坊、莱特币和门罗币。请创建或切换到您的比特币、以太坊、莱特币或门罗币钱包。", + "buy_bitcoin": "购买比特币", "buy_provider_unavailable": "提供者目前不可用。", - "signTransaction": "签署交易", + "buy_with": "一起购买", + "by_cake_pay": "通过 Cake Pay", + "cake_2fa_preset": "蛋糕 2FA 预设", + "cake_pay_account_note": "只需使用電子郵件地址註冊即可查看和購買卡片。有些甚至可以打折!", + "cake_pay_learn_more": "立即在应用中购买和兑换礼品卡!\n从左向右滑动以了解详情。", + "cake_pay_subtitle": "购买打折礼品卡(仅限美国)", + "cake_pay_title": "Cake Pay 礼品卡", + "cake_pay_web_cards_subtitle": "购买全球预付卡和礼品卡", + "cake_pay_web_cards_title": "蛋糕支付网络卡", + "cake_wallet": "Cake Wallet", + "cakepay_prepaid_card": "CakePay 预付借记卡", + "camera_consent": "${provider} 将使用您的相机拍摄图像以供识别之用。请查看他们的隐私政策了解详情。", + "camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。", + "cancel": "取消", + "card_address": "地址:", + "cardholder_agreement": "持卡人协议", + "cards": "卡片", + "chains": "链条", + "change": "更改", + "change_backup_password_alert": "您以前的备份文件将无法使用新的备份密码導入。 新的备份密码将仅用于新的备份文件。 您确定要更改备份密码吗?", + "change_currency": "更改币种", + "change_current_node": "您确定将当前节点更改为 ${node}?", + "change_current_node_title": "更改当前节点", + "change_exchange_provider": "更改交易所", + "change_language": "修改语言", + "change_language_to": "修改语言为 ${language}?", + "change_password": "更改密码", + "change_rep": "变革代表", + "change_rep_message": "您确定要更换代表吗?", + "change_rep_successful": "成功改变了代表", + "change_wallet_alert_content": "您是否想将当前钱包改为 ${wallet_name}?", + "change_wallet_alert_title": "更换当前钱包", + "choose_account": "选择账户", + "choose_address": "\n\n請選擇地址:", + "choose_derivation": "选择钱包推导", + "choose_from_available_options": "从可用选项中选择:", + "choose_one": "选一个", + "choose_relay": "请选择要使用的继电器", + "choose_wallet_currency": "请选择钱包货币:", + "clear": "清空", + "clearnet_link": "明网链接", + "close": "关闭", + "coin_control": "硬幣控制(可選)", + "cold_or_recover_wallet": "添加冷钱包或恢复纸钱包", + "color_theme": "主题", + "commit_transaction_amount_fee": "提交交易\n金额: ${amount}\n手续费: ${fee}", + "confirm": "确认", + "confirm_delete_template": "此操作将刪除此模板。确定吗?", + "confirm_delete_wallet": "此操作将刪除此钱包。确定吗?", + "confirm_sending": "确认发送", + "confirmations": "确认", + "confirmed": "确认余额", + "confirmed_tx": "确认的", + "congratulations": "恭喜!", + "connect_an_existing_yat": "連接現有 Yat", + "connect_yats": "连接 Yats", + "connection_sync": "连接和同步", + "connectWalletPrompt": "将您的钱包与 WalletConnect 连接以进行交易", + "contact": "联系", + "contact_list_contacts": "联系人", + "contact_list_wallets": "我的钱包", + "contact_name": "联系人姓名", + "contact_support": "联系支持", + "continue_text": "继续", + "contractName": "合约名称", + "contractSymbol": "合约符号", + "copied_key_to_clipboard": "复制 ${key} 到剪贴板", + "copied_to_clipboard": "复制到剪贴板", + "copy": "复制", + "copy_address": "复制地址", + "copy_id": "复制ID", + "copyWalletConnectLink": "从 dApp 复制 WalletConnect 链接并粘贴到此处", + "create_account": "创建账户", + "create_backup": "创建备份", + "create_donation_link": "创建捐赠链接", + "create_invoice": "创建发票", + "create_new": "创建新钱包", + "create_new_account": "建立新账户", + "creating_new_wallet": "创建新钱包", + "creating_new_wallet_error": "错误: ${description}", + "creation_date": "创建日期", + "custom": "自定义", + "custom_drag": "定制(保持和拖动)", + "custom_redeem_amount": "自定义兑换金额", + "dark_theme": "黑暗", + "debit_card": "借记卡", + "debit_card_terms": "您的支付卡号(以及与您的支付卡号对应的凭证)在此数字钱包中的存储和使用受适用的持卡人与支付卡发卡机构签订的协议的条款和条件的约束,自时不时。", + "decimal_places_error": "小数位太多", + "default_buy_provider": "默认购买提供商", + "default_sell_provider": "默认销售提供商", + "delete": "删除", + "delete_account": "删除账户", + "delete_wallet": "删除钱包", + "delete_wallet_confirm_message": "您确定要删除 ${wallet_name} 钱包吗?", + "deleteConnectionConfirmationPrompt": "您确定要删除与", + "descending": "下降", + "description": "描述", + "destination_tag": "目标Tag:", + "dfx_option_description": "用欧元和瑞士法郎购买加密货币。高达 990 欧元,无需额外 KYC。对于欧洲的零售和企业客户", + "didnt_get_code": "没有获取代码?", + "digit_pin": "位 PIN", + "digital_and_physical_card": "数字和物理预付借记卡", + "disable": "停用", + "disable_buy": "禁用购买操作", + "disable_cake_2fa": "禁用蛋糕 2FA", + "disable_exchange": "禁用交换", + "disable_fiat": "禁用法令", + "disable_sell": "禁用卖出操作", + "disabled": "禁用", + "discount": "节省 ${value}%", + "display_settings": "显示设置", + "displayable": "可显示", + "do_not_have_enough_gas_asset": "您没有足够的 ${currency} 来在当前的区块链网络条件下进行交易。即使您发送的是不同的资产,您也需要更多的 ${currency} 来支付区块链网络费用。", + "do_not_send": "不要发送", + "do_not_share_warning_text": "请勿与其他任何人分享这些信息,包括支持人员。\n\n您的资金可能而且将会被盗!", + "do_not_show_me": "不再提示", + "domain_looks_up": "域名查找", + "donation_link_details": "捐赠链接详情", + "e_sign_consent": "电子签名同意", + "edit": "编辑", + "edit_backup_password": "编辑备份密码", + "edit_node": "编辑节点", + "edit_token": "编辑令牌", + "electrum_address_disclaimer": "每次您使用一个地址时,我们都会生成新地址,但之前的地址仍然有效", + "email_address": "电子邮件地址", + "enabled": "启用", + "enter_amount": "输入金额", + "enter_backup_password": "在此处输入備用密码", + "enter_code": "输入代码", + "enter_seed_phrase": "输入您的种子短语", + "enter_totp_code": "请输入 TOTP 代码。", + "enter_your_note": "输入您的笔记...", + "enter_your_pin": "输入密码", + "enter_your_pin_again": "再次输入您的PIN码", + "enterTokenID": "输入令牌 ID", + "enterWalletConnectURI": "输入 WalletConnect URI", + "error": "错误", + "error_dialog_content": "糟糕,我们遇到了一些错误。\n\n请将崩溃报告发送给我们的支持团队,以改进应用程序。", + "error_text_account_name": "帐户名称只能包含字母数字\n且必须介于1到15个字符之间", + "error_text_address": "钱包地址必须与类型对应\n加密货币", + "error_text_amount": "金额只能包含数字", + "error_text_contact_name": "联系人姓名不能包含`,' \" 符号\n并且必须介于1到32个字符之间", + "error_text_crypto_currency": "小数位数\n必须小于或等于12", + "error_text_fiat": "金额不能超过可用余额.\n小数位数必须小于或等于2", + "error_text_input_above_maximum_limit": "金额大于最大值", + "error_text_input_below_minimum_limit": "金额小于最小值", + "error_text_keys": "钱包密钥只能包含16个字符的十六进制字符", + "error_text_limits_loading_failed": "未创建 ${provider} 交易。 限制加载失败", + "error_text_maximum_limit": "未创建 ${provider} 交易。 金额大于最大值:${max} ${currency}", + "error_text_minimal_limit": "未创建 ${provider} 交易。 金额小于最小值:${min} ${currency}", + "error_text_node_address": "请输入一个IPv4地址", + "error_text_node_port": "节点端口只能包含0到65535之间的数字", + "error_text_node_proxy_address": "请输入:<端口>,例如127.0.0.1:9050", + "error_text_payment_id": "付款ID只能包含16到64个字符(十六进制)", + "error_text_subaddress_name": "子地址名称不能包含`,' \" 符号\n并且必须在1到20个字符之间", + "error_text_template": "模板名称和地址不能包含`,' \" 符号\n并且必须在1到106个字符之间", + "error_text_wallet_name": "钱包名称只能包含字母、数字、_ - 符号\n并且长度必须在 1 到 33 个字符之间", + "error_text_xmr": "XMR值不能超过可用余额.\n小数位数必须小于或等于12", "errorGettingCredentials": "失败:获取凭据时出错", "errorSigningTransaction": "签署交易时发生错误", - "pairingInvalidEvent": "配对无效事件", - "chains": "链条", - "methods": "方法", - "events": "活动", - "reject": "拒绝", - "approve": "批准", - "expiresOn": "到期", - "walletConnect": "钱包连接", - "nullURIError": "URI 为空", - "connectWalletPrompt": "将您的钱包与 WalletConnect 连接以进行交易", - "newConnection": "新连接", - "activeConnectionsPrompt": "活动连接将出现在这里", - "deleteConnectionConfirmationPrompt": "您确定要删除与", + "estimated": "估计值", + "etherscan_history": "以太扫描历史", "event": "事件", - "successful": "成功的", - "wouoldLikeToConnect": "想要连接", - "message": "信息", - "do_not_have_enough_gas_asset": "您没有足够的 ${currency} 来在当前的区块链网络条件下进行交易。即使您发送的是不同的资产,您也需要更多的 ${currency} 来支付区块链网络费用。", - "totp_auth_url": "TOTP 授权 URL", - "awaitDAppProcessing": "请等待 dApp 处理完成。", - "copyWalletConnectLink": "从 dApp 复制 WalletConnect 链接并粘贴到此处", - "enterWalletConnectURI": "输入 WalletConnect URI", - "seed_key": "种子钥匙", - "enter_seed_phrase": "输入您的种子短语", - "change_rep_successful": "成功改变了代表", - "add_contact": "增加联系人", + "events": "活动", + "exchange": "兑换", + "exchange_incorrect_current_wallet_for_xmr": "如果要从Cake Wallet Monero余额中兑换XMR,请先切换到Monero钱包。", + "exchange_new_template": "新模板", "exchange_provider_unsupported": "${providerName}不再支持!", - "domain_looks_up": "域名查找", - "require_for_exchanges_to_external_wallets": "需要兑换到外部钱包", - "camera_permission_is_required": "需要相机许可。\n请从应用程序设置中启用它。", - "switchToETHWallet": "请切换到以太坊钱包并重试", - "order_by": "订购", - "creation_date": "创建日期", + "exchange_result_confirm": "点击确认 您将发送 ${fetchingLabel} ${from} 从你的钱包里 ${walletName} 到下面显示的地址。 或者您可以从外部钱包发送到以下地址/ QR码。\n\n请按确认继续或返回以更改金额", + "exchange_result_description": "您必须至少发送 ${fetchingLabel} ${from} 到下一页上显示的地址。 如果您发送的金额少于 ${fetchingLabel} ${from},则可能无法转换,因此无法退还。", + "exchange_result_write_down_ID": "*请复制或写下您上面显示的ID.", + "exchange_result_write_down_trade_id": "请复制或写下交易编号以继续.", + "exchange_sync_alert_content": "请等待,直到您的钱包同步", + "expired": "已过期", + "expires": "过期", + "expiresOn": "到期", + "export_backup": "导出备份", + "extra_id": "额外ID:", + "extracted_address_content": "您将汇款至\n${recipient_name}", + "failed_authentication": "身份验证失败. ${state_error}", + "faq": "FAQ", + "fetching": "正在获取", + "fiat_api": "法币API", + "fiat_balance": "法币余额", + "field_required": "此字段是必需的", + "fill_code": "请填写提供给您邮箱的验证码", + "filter_by": "过滤", + "first_wallet_text": "适用于门罗币、比特币、以太坊、莱特币和避风港的超棒钱包", + "fixed_pair_not_supported": "所选交易所不支持此固定货币对", + "fixed_rate": "固定汇率", + "fixed_rate_alert": "选中固定汇率模式后,您将可以输入接收金额。 您要切换到固定汇率模式吗?", + "forgot_password": "忘记密码", + "freeze": "凍結", + "frequently_asked_questions": "常见问题", + "frozen": "凍結的", + "full_balance": "全部余额", + "generate_name": "生成名称", + "generating_gift_card": "生成礼品卡", + "get_a": "得到一个", + "get_card_note": "你可以用数字货币重新加载。不需要额外的信息!", + "get_your_yat": "得到你的 Yat", + "gift_card_amount": "礼品卡金额", + "gift_card_balance_note": "有余额的礼品卡会出现在这里", + "gift_card_is_generated": "礼品卡生成", + "gift_card_number": "礼品卡号", + "gift_card_redeemed_note": "您兑换的礼品卡会出现在这里", + "gift_cards": "礼品卡", + "gift_cards_unavailable": "目前只能通过门罗币、比特币和莱特币购买礼品卡", + "got_it": "明白", + "gross_balance": "毛余额", "group_by_type": "按类型组", - "importNFTs": "导入 NFT", - "noNFTYet": "还没有 NFT", - "address": "地址", - "enterTokenID": "输入令牌 ID", - "tokenID": "ID", - "name": "姓名", - "symbol": "象征", - "seed_phrase_length": "种子短语长度", - "unavailable_balance": "不可用余额", - "unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。", - "unspent_change": "改变", - "tor_connection": "Tor连接", - "setup_warning_2fa_text": "Cake 2FA 是对钱包中某些操作的二次验证。它不如冷藏那么安全。\n\n如果您无法访问 2FA 应用程序或 TOTP 密钥,您将无法访问此钱包。您需要从助记词种子中恢复您的钱包。\n\n如果您无法访问 2FA 或助记词种子,Cake 支持将无法为您提供帮助。\n在使用 Cake 2FA 之前,我们建议您阅读该指南。", - "scan_qr_on_device": "在另一台设备上扫描此二维码", + "haven_app": "Haven by Cake Wallet", + "haven_app_wallet_text": "Awesome wallet for Haven", + "help": "帮助", + "hidden_balance": "隐藏余额", + "hide_details": "隐藏细节", + "high_contrast_theme": "高对比度主题", + "home_screen_settings": "主屏幕设置", "how_to_use": "如何使用", + "how_to_use_card": "如何使用这张卡", + "id": "ID: ", + "ignor": "忽视", + "import": "进口", + "importNFTs": "导入 NFT", + "in_store": "店内", + "incoming": "收到", + "incorrect_seed": "输入的文字无效。", + "introducing_cake_pay": "介绍 Cake Pay!", + "invalid_input": "输入无效", + "invoice_details": "发票明细", + "is_percentage": "是", + "last_30_days": "过去 30 天", + "learn_more": "了解更多", + "light_theme": "艳丽", + "loading_your_wallet": "加载您的钱包", + "login": "登录", + "logout": "注销", + "low_fee": "费用低", + "low_fee_alert": "您当前正在使用低网络费用优先级。这可能会导致长时间等待、不同的费率或取消交易。我们建议设置更高的费用以获得更好的体验。", + "manage_nodes": "管理节点", + "manage_pow_nodes": "管理 PoW 节点", + "manage_yats": "管理 Yats", + "mark_as_redeemed": "标记为已赎回", + "market_place": "市场", + "matrix_green_dark_theme": "矩阵绿暗主题", + "max_amount": "最大值: ${value}", + "max_value": "最大: ${value} ${currency}", + "memo": "备忘录:", + "message": "信息", + "methods": "方法", + "min_amount": "最小值: ${value}", + "min_value": "最小: ${value} ${currency}", + "minutes_to_pin_code": "${minute} 分钟", + "mm": "毫米", + "modify_2fa": "修改蛋糕2FA", + "monero_com": "Monero.com by Cake Wallet", + "monero_com_wallet_text": "Awesome wallet for Monero", + "monero_dark_theme": "门罗币深色主题", + "monero_light_theme": "门罗币浅色主题", + "moonpay_alert_text": "金额的价值必须大于或等于 ${minAmount} ${fiatCurrency}", + "more_options": "更多选项", + "name": "姓名", + "narrow": "狭窄的", + "new_first_wallet_text": "轻松确保您的加密货币安全", + "new_node_testing": "新节点测试", + "new_subaddress_create": "创建", + "new_subaddress_label_name": "标签名称", + "new_subaddress_title": "新地址", + "new_template": "新模板", + "new_wallet": "新钱包", + "newConnection": "新连接", + "no_id_needed": "不需要 ID!", + "no_id_required": "不需要身份证。充值并在任何地方消费", + "no_relay_on_domain": "用户域没有中继或中继不可用。请选择要使用的继电器。", + "no_relays": "无继电器", + "no_relays_message": "我们找到了该用户的 Nostr NIP-05 记录,但它不包含任何中继。请指示收件人将中继添加到他们的 Nostr 记录中。", + "node_address": "节点地址", + "node_connection_failed": "连接失败", + "node_connection_successful": "连接成功", + "node_new": "新节点", + "node_port": "节点端口", + "node_reset_settings_title": "重新设置", + "node_test": "测试", + "nodes": "节点", + "nodes_list_reset_to_default_message": "您确定要将设置重设为默认值吗?", + "none_of_selected_providers_can_exchange": "选定的供应商都不能进行此交换", + "noNFTYet": "还没有 NFT", + "normal": "普通的", + "note_optional": "注释(可选)", + "note_tap_to_change": "注释(轻按即可更改)", + "nullURIError": "URI 为空", + "offer_expires_in": "优惠有效期至 ", + "offline": "离线", + "ok": "确认", + "onion_link": "洋葱链接", + "online": "在线", + "onramper_option_description": "快速使用许多付款方式购买加密货币。在大多数国家 /地区可用。利差和费用各不相同。", + "open_gift_card": "打开礼品卡", + "optional_description": "可选说明", + "optional_email_hint": "可选的收款人通知电子邮件", + "optional_name": "可选收件人姓名", + "optionally_order_card": "可选择订购实体卡。", + "orbot_running_alert": "请确保 Orbot 在连接到此节点之前正在运行。", + "order_by": "订购", + "order_id": "订单编号", + "order_physical_card": "订购实体卡", + "other_settings": "其他设置", + "outdated_electrum_wallet_description": "在Cake创建的新比特币钱包现在有一个24字的种子。你必须创建一个新的比特币钱包,并将你所有的资金转移到新的24字钱包,并停止使用12字种子的钱包。请立即这样做以保证你的资金安全。", + "outdated_electrum_wallet_receive_warning": "如果这个钱包有一个 12 字的种子并且是在 Cake 中创建的,不要将比特币存入这个钱包。 任何转移到此钱包的 BTC 都可能丢失。 创建一个新的 24 字钱包(点击右上角的菜单,选择钱包,选择创建新钱包,然后选择比特币)并立即将您的 BTC 移到那里。 Cake 的新(24 字)BTC 钱包是安全的", + "outgoing": "发送", + "overwrite_amount": "Overwrite amount", + "pairingInvalidEvent": "配对无效事件", + "password": "密码", + "paste": "粘贴", + "pause_wallet_creation": "创建 Haven 钱包的功能当前已暂停。", + "payment_id": "付款 ID: ", + "payment_was_received": "您的付款已收到。", + "pending": " (待定)", + "percentageOf": "${amount}", + "pin_at_top": "将 ${token} 固定在顶部", + "pin_is_incorrect": "PIN码不正确", + "pin_number": "PIN 码", + "placeholder_contacts": "您的联系人将显示在这里", + "placeholder_transactions": "您的交易将显示在这里", + "please_fill_totp": "请填写您其他设备上的 8 位代码", + "please_make_selection": "请在下面进行选择 创建或恢复您的钱包.", + "please_reference_document": "请参考以下文档以获取更多信息。", + "please_select": "请选择:", + "please_select_backup_file": "请选择备份文件,然后输入备份密码。", + "please_try_to_connect_to_another_node": "请尝试连接到其他节点", + "please_wait": "请稍等", + "polygonscan_history": "多边形扫描历史", + "powered_by": "Powered by ${title}", + "pre_seed_button_text": "我明白。 查看种子", + "pre_seed_description": "在下一页上,您将看到${words}个文字。 这是您独有的种子,是丟失或出现故障时恢复钱包的唯一方法。 您有必须将其写下并储存在Cake Wallet应用程序以外的安全地方。", + "pre_seed_title": "重要", + "prevent_screenshots": "防止截屏和录屏", + "privacy": "隐私", + "privacy_policy": "隐私政策", + "privacy_settings": "隐私设置", + "private_key": "私钥", + "proceed_after_one_minute": "如果屏幕在 1 分钟后没有继续,请检查您的电子邮件。", + "profile": "轮廓", + "provider_error": "${provider} 错误", + "public_key": "公钥", + "purchase_gift_card": "购买礼品卡", + "qr_fullscreen": "点击打开全屏二维码", + "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", + "question_to_disable_2fa": "您确定要禁用 Cake 2FA 吗?访问钱包和某些功能将不再需要 2FA 代码。", + "receivable_balance": "应收余额", + "receive": "接收", + "receive_amount": "金额", + "received": "已收到", + "recipient_address": "收件人地址", + "reconnect": "重新连接", + "reconnect_alert_text": "您确定要重新连接吗?", + "reconnection": "重新连接", + "redeemed": "赎回", + "refund_address": "退款地址", + "reject": "拒绝", + "remaining": "剩余", + "remove": "确定", + "remove_node": "删除节点", + "remove_node_message": "您确定要删除所选节点吗?", + "rename": "重命名", + "require_for_adding_contacts": "需要添加联系人", + "require_for_all_security_and_backup_settings": "需要所有安全和备份设置", + "require_for_assessing_wallet": "需要访问钱包", + "require_for_creating_new_wallets": "创建新钱包的要求", + "require_for_exchanges_to_external_wallets": "需要兑换到外部钱包", + "require_for_exchanges_to_internal_wallets": "需要兑换到内部钱包", + "require_for_sends_to_contacts": "需要发送给联系人", + "require_for_sends_to_internal_wallets": "需要发送到内部钱包", + "require_for_sends_to_non_contacts": "需要发送给非联系人", + "require_pin_after": "之后需要 PIN", + "rescan": "重新扫描", + "resend_code": "请重新发送", + "reset": "重置", + "reset_password": "重置密码", + "restore_active_seed": "活动种子", + "restore_address": "地址", + "restore_bitcoin_description_from_keys": "从私钥中生成的WIF字符串恢复您钱包", + "restore_bitcoin_description_from_seed": "从24个文字的组成码恢复您的钱包", + "restore_bitcoin_title_from_keys": "从WIF还原", + "restore_description_from_backup": "您可以从还原整个Cake Wallet应用您的备份文件", + "restore_description_from_keys": "使用私钥恢复钱包", + "restore_description_from_seed": "从25个字中恢复您的钱包或13个字的组合码", + "restore_description_from_seed_keys": "从保存到安全地方的种子/钥匙取回钱包", + "restore_from_date_or_blockheight": "请输入您创建这个钱包前几天的日期。或者如果您知道区块高度,请输入区块高度", + "restore_from_seed_placeholder": "请在此处输入或粘贴您的代码短语", + "restore_new_seed": "新种子", + "restore_next": "下一个", + "restore_recover": "恢复", + "restore_restore_wallet": "恢复钱包", + "restore_seed_keys_restore": "种子/密钥还原", + "restore_spend_key_private": "Spend私钥", + "restore_title_from_backup": "从备份文件还原", + "restore_title_from_keys": "从密钥还原", + "restore_title_from_seed": "从种子还原", + "restore_title_from_seed_keys": "从种子/密钥还原", + "restore_view_key_private": "View私钥", + "restore_wallet": "恢复钱包", + "restore_wallet_name": "钱包名称", + "restore_wallet_restore_description": "钱包还原说明", + "router_no_route": "未定义路线 ${name}", + "save": "保存", + "save_backup_password": "请确保您已保存备份密码。 沒有它,您将无法导入备份文件。", + "save_backup_password_alert": "保存备份密码", + "save_to_downloads": "保存到下载", + "saved_the_trade_id": "我已经保存了交易编号", + "scan_qr_code": "扫描二维码", + "scan_qr_code_to_get_address": "扫描二维码获取地址", + "scan_qr_on_device": "在另一台设备上扫描此二维码", + "search": "搜索", + "search_add_token": "搜索/添加令牌", + "search_category": "搜索类别", + "search_currency": "搜索货币", + "search_language": "搜索语言", + "second_intro_content": "您的 Yat 是一個唯一的表情符號地址,可替換您所有貨幣的所有長十六進制地址。", + "second_intro_title": "一個表情符號地址來統治他們", + "security_and_backup": "安全和备份", + "seed_alert_back": "返回", + "seed_alert_content": "种子是恢复钱包的唯一方法。记住了吗?", + "seed_alert_title": "注意", + "seed_alert_yes": "确定", + "seed_choose": "选择种子语言", "seed_hex_form": "钱包种子(十六进制形式)", + "seed_key": "种子钥匙", + "seed_language": "种子语言", + "seed_language_chinese": "中文", + "seed_language_chinese_traditional": "中国传统的)", + "seed_language_czech": "捷克", + "seed_language_dutch": "荷兰文", + "seed_language_english": "英文", + "seed_language_french": "法语", + "seed_language_german": "德文", + "seed_language_italian": "意大利语", + "seed_language_japanese": "日文", + "seed_language_korean": "韩国人", + "seed_language_next": "下一个", + "seed_language_portuguese": "葡萄牙文", + "seed_language_russian": "俄文", + "seed_language_spanish": "西班牙文", + "seed_phrase_length": "种子短语长度", + "seed_reminder": "请记下这些内容,以防丟失或数据损坏", + "seed_share": "分享种子", + "seed_title": "种子", "seedtype": "籽粒", "seedtype_legacy": "遗产(25个单词)", "seedtype_polyseed": "多种物品(16个单词)", - "seed_language_czech": "捷克", - "seed_language_korean": "韩国人", - "seed_language_chinese_traditional": "中国传统的)", - "ascending": "上升", - "descending": "下降", - "dfx_option_description": "用欧元和瑞士法郎购买加密货币。高达 990 欧元,无需额外 KYC。对于欧洲的零售和企业客户", - "polygonscan_history": "多边形扫描历史", - "wallet_seed_legacy": "旧的钱包种子", - "default_sell_provider": "默认销售提供商", + "select_backup_file": "选择备份文件", + "select_buy_provider_notice": "在上面选择买入提供商。您可以通过在应用程序设置中设置默认的购买提供商来跳过此屏幕。", + "select_destination": "请选择备份文件的目的地。", "select_sell_provider_notice": "选择上面的销售提供商。您可以通过在应用程序设置中设置默认销售提供商来跳过此屏幕。", - "custom_drag": "定制(保持和拖动)", + "sell_alert_content": "我们目前仅支持比特币、以太坊和莱特币的销售。请创建或切换到您的比特币、以太坊或莱特币钱包。", + "sell_monero_com_alert_content": "尚不支持出售门罗币", + "send": "发送", + "send_address": "${cryptoCurrency} 地址", + "send_amount": "金额:", + "send_creating_transaction": "创建交易", + "send_error_currency": "货币只能包含数字", + "send_error_minimum_value": "最小金额为0.01", + "send_estimated_fee": "预估费用:", + "send_fee": "手续费:", + "send_name": "名称", + "send_new": "新建", + "send_payment_id": "付款编号 (可选的)", + "send_priority": "目前,费用设置为 ${transactionPriority} 优先.\n交易优先级可以在设置中进行调整", + "send_sending": "正在发送...", + "send_success": "您的${crypto}已成功发送", + "send_templates": "模板", + "send_title": "发送", + "send_to_this_address": "发送 ${currency} ${tag}到这个地址", + "send_xmr": "发送 XMR", + "send_your_wallet": "你的钱包", + "sending": "正在发送", + "sent": "已发送", + "settings": "设置", + "settings_all": "全部", + "settings_allow_biometrical_authentication": "允许生物识别认证", + "settings_can_be_changed_later": "稍后可以在应用设置中更改这些设置", + "settings_change_language": "修改语言", + "settings_change_pin": "更改密码", + "settings_currency": "货币", + "settings_current_node": "当前节点", + "settings_dark_mode": "黑暗模式", + "settings_display_balance": "显示余额为", + "settings_display_on_dashboard_list": "显示在仪表板上", + "settings_fee_priority": "交易优先级", + "settings_nodes": "节点数", + "settings_none": "没有", + "settings_only_trades": "只交易", + "settings_only_transactions": "仅交易", + "settings_personal": "个人", + "settings_save_recipient_address": "保存收件人地址", + "settings_support": "帮助", + "settings_terms_and_conditions": "条款和条件", + "settings_title": "设定值", + "settings_trades": "交易", + "settings_transactions": "交易情况", + "settings_wallets": "钱包", + "setup_2fa": "设置蛋糕 2FA", + "setup_2fa_text": "Cake 2FA 使用 TOTP 作为第二个身份验证因素。\n\nCake 2FA 的 TOTP 需要 SHA-512 和 8 位数字支持;这提供了更高的安全性。更多信息和支持的应用程序可以在指南中找到。", + "setup_pin": "设定PIN码", + "setup_successful": "您的PIN码已成功设置!", + "setup_totp_recommended": "设置 TOTP", + "setup_warning_2fa_text": "Cake 2FA 是对钱包中某些操作的二次验证。它不如冷藏那么安全。\n\n如果您无法访问 2FA 应用程序或 TOTP 密钥,您将无法访问此钱包。您需要从助记词种子中恢复您的钱包。\n\n如果您无法访问 2FA 或助记词种子,Cake 支持将无法为您提供帮助。\n在使用 Cake 2FA 之前,我们建议您阅读该指南。", + "setup_your_debit_card": "设置你的借记卡", + "share": "分享", + "share_address": "分享地址", + "show_details": "显示详细信息", + "show_keys": "显示种子/密钥", + "show_market_place": "显示市场", + "show_seed": "显示种子", + "sign_up": "注册", + "signTransaction": "签署交易", + "signup_for_card_accept_terms": "注册卡并接受条款。", + "slidable": "可滑动", + "sort_by": "排序方式", + "spend_key_private": "Spend 密钥 (私钥)", + "spend_key_public": "Spend 密钥 (公钥)", + "status": "状态: ", + "subaddress_title": "子地址列表", + "subaddresses": "子地址", + "submit_request": "提交请求", + "successful": "成功的", + "support_description_guides": "对常见问题的文档和支持", + "support_description_live_chat": "免费快速!训练有素的支持代表可以协助", + "support_description_other_links": "加入我们的社区或通过其他方法与我们联系我们的合作伙伴", + "support_title_guides": "蛋糕钱包指南", + "support_title_live_chat": "实时支持", + "support_title_other_links": "其他支持链接", + "sweeping_wallet": "扫一扫钱包", + "sweeping_wallet_alert": "\n这应该不会花很长时间。请勿离开此屏幕,否则可能会丢失所掠取的资金", + "switchToETHWallet": "请切换到以太坊钱包并重试", "switchToEVMCompatibleWallet": "请切换到 EVM 兼容钱包并重试(以太坊、Polygon)", - "receivable_balance": "应收余额", - "confirmed_tx": "确认的", + "symbol": "象征", + "sync_all_wallets": "同步所有钱包", + "sync_status_attempting_sync": "嘗試同步", + "sync_status_connected": "已连接", + "sync_status_connecting": "连接中", + "sync_status_failed_connect": "断线", + "sync_status_not_connected": "未连接", + "sync_status_starting_sync": "开始同步", + "sync_status_syncronized": "已同步", + "sync_status_syncronizing": "正在同步", + "syncing_wallet_alert_content": "您的余额和交易列表可能不完整,直到顶部显示“已同步”。单击/点击以了解更多信息。", + "syncing_wallet_alert_title": "您的钱包正在同步", + "template": "模板", + "template_name": "模板名称", + "third_intro_content": "Yats 也住在 Cake Wallet 之外。 地球上任何一個錢包地址都可以用一個Yat來代替!", + "third_intro_title": "Yat 和別人玩得很好", + "time": "${minutes}m ${seconds}s", + "tip": "提示:", + "today": "今天", + "token_contract_address": "代币合约地址", + "token_decimal": "令牌十进制", + "token_name": "代币名称例如:Tether", + "token_symbol": "代币符号例如:USDT", + "tokenID": "ID", + "tor_connection": "Tor连接", + "tor_only": "仅限 Tor", + "total_saving": "总储蓄", + "totp_2fa_failure": "不正确的代码。 请尝试不同的代码或生成新的密钥。 使用支持 8 位代码和 SHA512 的兼容 2FA 应用程序。", + "totp_2fa_success": "成功!为此钱包启用了 Cake 2FA。请记住保存您的助记词种子,以防您无法访问钱包。", + "totp_auth_url": "TOTP 授权 URL", + "totp_code": "TOTP代码", + "totp_secret_code": "TOTP密码", + "totp_verification_success": "验证成功!", + "trade_details_copied": "${title} 复制到剪贴板", + "trade_details_created_at": "创建于", + "trade_details_fetching": "正在获取", + "trade_details_id": "ID", + "trade_details_pair": "对", + "trade_details_provider": "提供者", + "trade_details_state": "条件", + "trade_details_title": "交易明细", + "trade_for_not_created": "交易 ${title} 未创建.", + "trade_history_title": "交易历史", + "trade_id": "交易编号:", + "trade_id_not_found": "交易方式 ${tradeId} 的 ${title} 未找到.", + "trade_is_powered_by": "该交易由 ${provider}", + "trade_not_created": "未建立交易", + "trade_not_found": "找不到交易.", + "trade_state_btc_sent": "已发送", + "trade_state_complete": "完成", + "trade_state_confirming": "确认中", + "trade_state_created": "已建立", + "trade_state_finished": "已完成", + "trade_state_paid": "已付费", + "trade_state_paid_unconfirmed": "付费未确认", + "trade_state_pending": "待定", + "trade_state_timeout": "超时", + "trade_state_to_be_created": "待创建", + "trade_state_traded": "已交易", + "trade_state_trading": "交易", + "trade_state_underpaid": "支付不足", + "trade_state_unpaid": "未付", + "trades": "交易", + "transaction_details_amount": "金额", + "transaction_details_copied": "${title} 复制到剪切板", + "transaction_details_date": "日期", + "transaction_details_fee": "手续费", + "transaction_details_height": "区块高度", + "transaction_details_recipient_address": "收件人地址", "transaction_details_source_address": "源地址", - "pause_wallet_creation": "创建 Haven 钱包的功能当前已暂停。", - "contractName": "合约名称", - "contractSymbol": "合约符号", - "description": "描述", - "camera_consent": "${provider} 将使用您的相机拍摄图像以供识别之用。请查看他们的隐私政策了解详情。", - "no_relays": "无继电器", - "choose_relay": "请选择要使用的继电器", - "no_relays_message": "我们找到了该用户的 Nostr NIP-05 记录,但它不包含任何中继。请指示收件人将中继添加到他们的 Nostr 记录中。", - "no_relay_on_domain": "用户域没有中继或中继不可用。请选择要使用的继电器。" -} + "transaction_details_title": "交易明细", + "transaction_details_transaction_id": "交易编号", + "transaction_key": "交易密码", + "transaction_priority_fast": "快速", + "transaction_priority_fastest": "最快", + "transaction_priority_medium": "中等", + "transaction_priority_regular": "常规", + "transaction_priority_slow": "慢速", + "transaction_sent": "交易已发送", + "transaction_sent_notice": "如果屏幕在 1 分钟后没有继续,请检查区块浏览器和您的电子邮件。", + "transactions": "交易情况", + "transactions_by_date": "按日期交易", + "trusted": "值得信赖", + "unavailable_balance": "不可用余额", + "unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。", + "unconfirmed": "未确认余额", + "understand": "我已知晓", + "unmatched_currencies": "您当前钱包的货币与扫描的 QR 的货币不匹配", + "unspent_change": "改变", + "unspent_coins_details_title": "未使用代幣詳情", + "unspent_coins_title": "未使用的硬幣", + "unsupported_asset": "我们不支持针对该资产采取此操作。请创建或切换到支持的资产类型的钱包。", + "upto": "最高 ${value}", + "use": "切换使用", + "use_card_info_three": "在线使用电子卡或使用非接触式支付方式。", + "use_card_info_two": "预付账户中的资金转换为美元,不是数字货币。", + "use_ssl": "使用SSL", + "use_suggested": "使用建议", + "variable_pair_not_supported": "所选交易所不支持此变量对", + "verification": "验证", + "verify_with_2fa": "用 Cake 2FA 验证", + "version": "版本 ${currentVersion}", + "view_all": "查看全部", + "view_in_block_explorer": "View in Block Explorer", + "view_key_private": "View 密钥(私钥)", + "view_key_public": "View 密钥(公钥)", + "view_transaction_on": "View Transaction on ", + "wallet_keys": "钱包种子/密钥", + "wallet_list_create_new_wallet": "创建新钱包", + "wallet_list_edit_wallet": "编辑钱包", + "wallet_list_failed_to_load": "加载失败 ${wallet_name} 钱包. ${error}", + "wallet_list_failed_to_remove": "删除失败 ${wallet_name} 钱包. ${error}", + "wallet_list_load_wallet": "加载钱包", + "wallet_list_loading_wallet": "载入中 ${wallet_name} 钱包", + "wallet_list_removing_wallet": "删除 ${wallet_name} 钱包", + "wallet_list_restore_wallet": "恢复钱包", + "wallet_list_title": "Monero 钱包", + "wallet_list_wallet_name": "钱包名称", + "wallet_menu": "钱包菜单", + "wallet_name": "钱包名称", + "wallet_name_exists": "同名的钱包已经存在", + "wallet_restoration_store_incorrect_seed_length": "种子长度错误", + "wallet_seed": "钱包种子", + "wallet_seed_legacy": "旧的钱包种子", + "wallet_store_monero_wallet": "Monero 钱包", + "walletConnect": "钱包连接", + "wallets": "钱包", + "warning": "警告", + "welcome": "欢迎使用", + "welcome_to_cakepay": "欢迎来到 Cake Pay!", + "widgets_address": "地址", + "widgets_or": "或者", + "widgets_restore_from_blockheight": "从块高还原", + "widgets_restore_from_date": "从日期还原", + "widgets_seed": "种子", + "wouoldLikeToConnect": "想要连接", + "write_down_backup_password": "请写下您的备份密码,该密码用于导入备份文件。", + "xlm_extra_info": "发送用于交换的XLM交易时,请不要忘记指定备忘录ID", + "xmr_available_balance": "可用余额 ", + "xmr_full_balance": "全部余额", + "xmr_hidden": "隐藏", + "xmr_to_error": "XMR.TO 错误", + "xmr_to_error_description": "无效的金额。 小数点后最多8位数字", + "xrp_extra_info": "发送用于交换的XRP交易时,请不要忘记指定目标Tag", + "yat": "Yat", + "yat_address": "Yat 地址", + "yat_alert_content": "Cake Wallet 用戶現在可以使用獨一無二的基於表情符號的用戶名發送和接收他們喜歡的所有貨幣。", + "yat_alert_title": "使用 Yat 更輕鬆地發送和接收加密貨幣", + "yat_error": "Yat 誤差", + "yat_error_content": "沒有與此 Yat 相關聯的地址。 嘗試另一個 Yat", + "yat_popup_content": "您現在可以使用 Yat 在 Cake Wallet 中發送和接收加密貨幣 - 一個基於表情符號的簡短用戶名。 在設置屏幕上隨時管理 Yats", + "yat_popup_title": "您的錢包地址可以被表情化。", + "yesterday": "昨天", + "you_now_have_debit_card": "你现在有一张借记卡", + "you_pay": "你付钱", + "you_will_get": "转换到", + "you_will_send": "转换自", + "yy": "YY", + "zzzz": "ZZZZ" +} \ No newline at end of file diff --git a/tool/append_translation.dart b/tool/append_translation.dart index 9c017f64e..ac114bf3c 100644 --- a/tool/append_translation.dart +++ b/tool/append_translation.dart @@ -13,10 +13,20 @@ void main(List args) async { print('Appending "$name": "$text"'); + // add translation to all languages: for (var lang in langs) { final fileName = getArbFileName(lang); final translation = await getTranslation(text, lang); appendStringToArbFile(fileName, name, translation); } + + print('Alphabetizing all files...'); + + for (var lang in langs) { + final fileName = getArbFileName(lang); + alphabetizeArbFile(fileName); + } + + print('Done!'); } \ No newline at end of file diff --git a/tool/utils/translation/arb_file_utils.dart b/tool/utils/translation/arb_file_utils.dart index c43de091a..b54dab423 100644 --- a/tool/utils/translation/arb_file_utils.dart +++ b/tool/utils/translation/arb_file_utils.dart @@ -47,9 +47,7 @@ Map readArbFile(File file) { } String getArbFileName(String lang) { - final shortLang = lang - .split("-") - .first; + final shortLang = lang.split("-").first; return "./res/values/strings_$shortLang.arb"; } @@ -66,3 +64,25 @@ List getMissingKeysInArbFile(String fileName, Iterable langKeys) return results; } + +void alphabetizeArbFile(String fileName) { + final file = File(fileName); + final arbObj = readArbFile(file); + + final sortedKeys = arbObj.keys.toList() + ..sort((a, b) => a.toLowerCase().compareTo(b.toLowerCase())); + final Map sortedArbObj = {}; + for (var key in sortedKeys) { + sortedArbObj[key] = arbObj[key]; + } + + final outputContent = json + .encode(sortedArbObj) + .replaceAll('","', '",\n "') + .replaceAll('{"', '{\n "') + .replaceAll('"}', '"\n}') + .replaceAll('":"', '": "') + .replaceAll('\$ {', '\${'); + + file.writeAsStringSync(outputContent); +} From d0b51cebe327dfbc17f41505e259cb668ace0043 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Tue, 6 Feb 2024 22:44:21 +0200 Subject: [PATCH 110/241] Generic fixes (#1291) * - Update Camera purpose string for iOS - Fix address field not passing the correct currency to address book * Enhance file loading in exception handler * Fix translation consistency [skip ci] --- ios/Runner/InfoBase.plist | 2 +- lib/src/screens/send/widgets/send_card.dart | 2 +- .../send/widgets/send_template_card.dart | 72 ++++++++++--------- lib/utils/exception_handler.dart | 26 ++++--- res/values/strings_ar.arb | 5 ++ res/values/strings_bg.arb | 9 +++ res/values/strings_cs.arb | 9 +++ res/values/strings_de.arb | 4 ++ res/values/strings_es.arb | 2 + res/values/strings_fr.arb | 1 + res/values/strings_ha.arb | 21 ++++++ res/values/strings_hi.arb | 3 + res/values/strings_hr.arb | 3 + res/values/strings_id.arb | 16 +++++ res/values/strings_it.arb | 4 ++ res/values/strings_ja.arb | 2 + res/values/strings_ko.arb | 5 ++ res/values/strings_my.arb | 3 + res/values/strings_nl.arb | 2 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 5 ++ res/values/strings_ru.arb | 2 + res/values/strings_th.arb | 3 + res/values/strings_tl.arb | 7 ++ res/values/strings_tr.arb | 3 + res/values/strings_uk.arb | 2 + res/values/strings_ur.arb | 11 +++ res/values/strings_yo.arb | 8 +++ res/values/strings_zh.arb | 2 + tool/translation_consistence.dart | 4 +- 30 files changed, 192 insertions(+), 47 deletions(-) diff --git a/ios/Runner/InfoBase.plist b/ios/Runner/InfoBase.plist index 4f7036498..2292d0b66 100644 --- a/ios/Runner/InfoBase.plist +++ b/ios/Runner/InfoBase.plist @@ -191,7 +191,7 @@ NSCameraUsageDescription - Used for scan QR code + Used for scanning QR code and can be used to capture images for identification purposes by third-party providers. NSDocumentsFolderUsageDescription We need access to documents folder for getting access to open/save backup file NSFaceIDUsageDescription diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 07fb34cb2..5f15c9c4d 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -189,7 +189,7 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin()!.textFieldButtonColor, - borderColor: Theme.of(context).extension()!.textFieldBorderColor, - textStyle: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Colors.white, - ), - hintStyle: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Theme.of(context).extension()!.textFieldHintColor, - ), - validator: sendTemplateViewModel.addressValidator, + child: Observer( + builder: (context) { + return AddressTextField( + selectedCurrency: template.selectedCurrency, + controller: _addressController, + onURIScanned: (uri) { + final paymentRequest = PaymentRequest.fromUri(uri); + _addressController.text = paymentRequest.address; + _cryptoAmountController.text = paymentRequest.amount; + }, + options: [ + AddressTextFieldOption.paste, + AddressTextFieldOption.qrCode, + AddressTextFieldOption.addressBook + ], + onPushPasteButton: (context) async { + template.output.resetParsedAddress(); + await template.output.fetchParsedAddress(context); + }, + onPushAddressBookButton: (context) async { + template.output.resetParsedAddress(); + await template.output.fetchParsedAddress(context); + }, + buttonColor: Theme.of(context).extension()!.textFieldButtonColor, + borderColor: Theme.of(context).extension()!.textFieldBorderColor, + textStyle: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Colors.white, + ), + hintStyle: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Theme.of(context).extension()!.textFieldHintColor, + ), + validator: sendTemplateViewModel.addressValidator, + ); + } ), ), Padding( diff --git a/lib/utils/exception_handler.dart b/lib/utils/exception_handler.dart index 36eac4941..6e93fc5cd 100644 --- a/lib/utils/exception_handler.dart +++ b/lib/utils/exception_handler.dart @@ -16,11 +16,15 @@ import 'package:shared_preferences/shared_preferences.dart'; class ExceptionHandler { static bool _hasError = false; static const _coolDownDurationInDays = 7; + static File? _file; static void _saveException(String? error, StackTrace? stackTrace, {String? library}) async { - final appDocDir = await getApplicationDocumentsDirectory(); + if (_file == null) { + final appDocDir = await getApplicationDocumentsDirectory(); + + _file = File('${appDocDir.path}/error.txt'); + } - final file = File('${appDocDir.path}/error.txt'); final exception = { "${DateTime.now()}": { "Error": "$error\n\n", @@ -33,14 +37,14 @@ class ExceptionHandler { ==========================================================\n\n'''; /// don't save existing errors - if (file.existsSync()) { - final String fileContent = await file.readAsString(); + if (_file!.existsSync()) { + final String fileContent = await _file!.readAsString(); if (fileContent.contains("${exception.values.first}")) { return; } } - file.writeAsStringSync( + _file!.writeAsStringSync( "$exception $separator", mode: FileMode.append, ); @@ -48,16 +52,18 @@ class ExceptionHandler { static void _sendExceptionFile() async { try { - final appDocDir = await getApplicationDocumentsDirectory(); + if (_file == null) { + final appDocDir = await getApplicationDocumentsDirectory(); - final file = File('${appDocDir.path}/error.txt'); + _file = File('${appDocDir.path}/error.txt'); + } - await _addDeviceInfo(file); + await _addDeviceInfo(_file!); final MailOptions mailOptions = MailOptions( subject: 'Mobile App Issue', recipients: ['support@cakewallet.com'], - attachments: [file.path], + attachments: [_file!.path], ); final result = await FlutterMailer.send(mailOptions); @@ -67,7 +73,7 @@ class ExceptionHandler { if (result.name == MailerResponse.sent.name || result.name == MailerResponse.saved.name || result.name == MailerResponse.android.name) { - file.writeAsString("", mode: FileMode.write); + _file!.writeAsString("", mode: FileMode.write); } } catch (e, s) { _saveException(e.toString(), s); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 6ccc3f9bf..5ed96628b 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -64,6 +64,7 @@ "avg_savings": "متوسط مدخرات", "awaitDAppProcessing": ".ﺔﺠﻟﺎﻌﻤﻟﺍ ﻦﻣ dApp ﻲﻬﺘﻨﻳ ﻰﺘﺣ ﺭﺎﻈﺘﻧﻻﺍ ﻰﺟﺮﻳ", "awaiting_payment_confirmation": "في انتظار تأكيد الدفع", + "background_sync_mode": "وضع مزامنة الخلفية", "backup": "نسخ الاحتياطي", "backup_file": "ملف النسخ الاحتياطي", "backup_password": "كلمة مرور النسخ الاحتياطي", @@ -139,6 +140,8 @@ "connection_sync": "الاتصال والمزامنة", "connectWalletPrompt": "ﺕﻼﻣﺎﻌﻤﻟﺍ ءﺍﺮﺟﻹ WalletConnect ﻊﻣ ﻚﺘﻈﻔﺤﻣ ﻞﻴﺻﻮﺘﺑ ﻢﻗ", "contact": "تواصل", + "contact_list_contacts": "جهات الاتصال", + "contact_list_wallets": "محافظ", "contact_name": "اسم جهة الاتصال", "contact_support": "اتصل بالدعم", "continue_text": "التالي", @@ -482,6 +485,7 @@ "restore_wallet": "استعادة محفظة", "restore_wallet_name": "اسم المحفظة", "restore_wallet_restore_description": "وصف استعادة المحفظة", + "robinhood_option_description": "شراء وتحويل على الفور باستخدام بطاقة الخصم الخاصة بك أو حسابك المصرفي أو رصيد Robinhood. الولايات المتحدة الأمريكية فقط.", "router_no_route": "لم يتم تحديد مسار لـ ${name}", "save": "حفظ", "save_backup_password": "يرجى التأكد من حفظ كلمة المرور الاحتياطية. لن تتمكن من استيراد ملفات النسخ الاحتياطي بدونها.", @@ -616,6 +620,7 @@ "switchToETHWallet": "ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ Ethereum ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", "switchToEVMCompatibleWallet": " (Ethereum، Polygon) ﻯﺮﺧﺃ ﺓﺮﻣ ﺔﻟﻭﺎﺤﻤﻟﺍﻭ EVM ﻊﻣ ﺔﻘﻓﺍﻮﺘﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻰﺟﺮﻳ", "symbol": "ﺰﻣﺭ", + "sync_all_wallets": "مزامنة جميع المحافظ", "sync_status_attempting_sync": "جاري محاولة المزامنة", "sync_status_connected": "متصل", "sync_status_connecting": "يتم التوصيل", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 783f83d55..ac94061fc 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -64,6 +64,7 @@ "avg_savings": "Средни спестявания", "awaitDAppProcessing": "Моля, изчакайте dApp да завърши обработката.", "awaiting_payment_confirmation": "Чака се потвърждение на плащането", + "background_sync_mode": "Режим на синхронизиране на фона", "backup": "Резервно копие", "backup_file": "Резервно копие", "backup_password": "Парола за възстановяване", @@ -123,6 +124,7 @@ "clearnet_link": "Clearnet връзка", "close": "затвори", "coin_control": "Управление на монетите (не е задължително)", + "cold_or_recover_wallet": "Добавете студен портфейл или възстановете хартиен портфейл", "color_theme": "Цвят", "commit_transaction_amount_fee": "Изпълняване на транзакция\nСума: ${amount}\nТакса: ${fee}", "confirm": "Потвърждаване", @@ -409,6 +411,7 @@ "please_select": "Моля, изберете:", "please_select_backup_file": "Моля, изберете резервно копие и въведете парола за възстановяване.", "please_try_to_connect_to_another_node": "Моля, опитайте се да се свържете към друг node.", + "please_wait": "Моля Изчакай", "polygonscan_history": "История на PolygonScan", "powered_by": "Powered by ${title}", "pre_seed_button_text": "Разбирам. Покажи seed", @@ -482,6 +485,7 @@ "restore_wallet": "Възстановяване на портфейл", "restore_wallet_name": "Име на портфейл", "restore_wallet_restore_description": "Описание на възстановяване на портфейл", + "robinhood_option_description": "Купете и прехвърлете незабавно с помощта на вашата дебитна карта, банкова сметка или салдо на робини. Само САЩ.", "router_no_route": "Няма дефиниран път за ${name}", "save": "Запази", "save_backup_password": "Моля, запишете своята парола за възстановяване. Импортирането на резервни копия не е възможно без нея.", @@ -489,6 +493,7 @@ "save_to_downloads": "Запазване в Изтегляния", "saved_the_trade_id": "Запазих trade ID-то", "scan_qr_code": "Сканирайте QR кода, за да получите адреса", + "scan_qr_code_to_get_address": "Сканирайте QR кода, за да получите адреса", "scan_qr_on_device": "Сканирайте този QR код на друго устройство", "search": "Търсене", "search_add_token": "Търсене/Добавяне на токен", @@ -555,6 +560,7 @@ "send_your_wallet": "Вашият портфейл", "sending": "Изпращане", "sent": "Изпратени", + "settings": "Настройки", "settings_all": "Всичко", "settings_allow_biometrical_authentication": "Позволяване на биометрично удостоверяване.", "settings_can_be_changed_later": "Тези настройки могат да бъдат променени по-късно от приложението", @@ -609,9 +615,12 @@ "support_title_guides": "Ръководства за портфейл за торта", "support_title_live_chat": "Подкрепа на живо", "support_title_other_links": "Други връзки за поддръжка", + "sweeping_wallet": "Метещ портфейл", + "sweeping_wallet_alert": "Това не трябва да отнема много време. Не оставяйте този екран или пометените средства могат да бъдат загубени.", "switchToETHWallet": "Моля, преминете към портфейл Ethereum и опитайте отново", "switchToEVMCompatibleWallet": "Моля, превключете към портфейл, съвместим с EVM, и опитайте отново (Ethereum, Polygon)", "symbol": "Символ", + "sync_all_wallets": "Синхронизирайте всички портфейли", "sync_status_attempting_sync": "ОПИТ ЗА СИНХРОНИЗАЦИЯ", "sync_status_connected": "СВЪРЗВАНЕ", "sync_status_connecting": "СВЪРЗВАНЕ", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 3f38bd277..3fbaa03d7 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -64,6 +64,7 @@ "avg_savings": "Prům. ušetřeno", "awaitDAppProcessing": "Počkejte, až dApp dokončí zpracování.", "awaiting_payment_confirmation": "Čeká se na potvrzení platby", + "background_sync_mode": "Režim synchronizace pozadí", "backup": "Záloha", "backup_file": "Soubor se zálohou", "backup_password": "Heslo pro zálohy", @@ -123,6 +124,7 @@ "clearnet_link": "Odkaz na Clearnet", "close": "zavřít", "coin_control": "Volba mincí (nepovinné)", + "cold_or_recover_wallet": "Přidejte studenou peněženku nebo obnovte papírovou peněženku", "color_theme": "Barevný motiv", "commit_transaction_amount_fee": "Odeslat transakci\nČástka: ${amount}\nPoplatek: ${fee}", "confirm": "Potvrdit", @@ -409,6 +411,7 @@ "please_select": "Zvolte si:", "please_select_backup_file": "Prosím vyberte soubor se zálohou a zadejte heslo pro zálohy.", "please_try_to_connect_to_another_node": "Zkuste se prosím připojit k jinému uzlu", + "please_wait": "Prosím, čekejte", "polygonscan_history": "Historie PolygonScan", "powered_by": "Zajišťuje ${title}", "pre_seed_button_text": "Rozumím. Ukaž mi můj seed.", @@ -482,6 +485,7 @@ "restore_wallet": "Obnovit peněženku", "restore_wallet_name": "Jméno peněženky", "restore_wallet_restore_description": "Popis obnovení peněženky", + "robinhood_option_description": "Nakupujte a převádějte okamžitě pomocí své debetní karty, bankovního účtu nebo zůstatku Robinhood. Pouze USA.", "router_no_route": "Pro ${name} není definována žádná cesta", "save": "Uložit", "save_backup_password": "Prosím ujistěte se, že máte uschováno heslo pro zálohy. Bez něj nebudete moci naimportovat soubory se zálohami.", @@ -489,6 +493,7 @@ "save_to_downloads": "Uložit do Stažených souborů", "saved_the_trade_id": "Uložil jsem si ID transakce (trade ID)", "scan_qr_code": "Naskenujte QR kód pro získání adresy", + "scan_qr_code_to_get_address": "Prohledejte QR kód a získejte adresu", "scan_qr_on_device": "Naskenujte tento QR kód na jiném zařízení", "search": "Hledat", "search_add_token": "Hledat / Přidat token", @@ -555,6 +560,7 @@ "send_your_wallet": "Vaše peněženka", "sending": "Odesílání", "sent": "Odesláno", + "settings": "Nastavení", "settings_all": "VŠE", "settings_allow_biometrical_authentication": "Povolit biometrické ověření", "settings_can_be_changed_later": "Tato nastavení mohou být změněna později v nastavení v této aplikaci", @@ -609,9 +615,12 @@ "support_title_guides": "Průvodce peněženkami dortu", "support_title_live_chat": "Živá podpora", "support_title_other_links": "Další odkazy na podporu", + "sweeping_wallet": "Zametací peněženka", + "sweeping_wallet_alert": "To by nemělo trvat dlouho. Nenechávejte tuto obrazovku, jinak mohou být ztraceny prostředky.", "switchToETHWallet": "Přejděte na peněženku Ethereum a zkuste to znovu", "switchToEVMCompatibleWallet": "Přepněte na peněženku kompatibilní s EVM a zkuste to znovu (Ethereum, Polygon)", "symbol": "Symbol", + "sync_all_wallets": "Synchronizovat všechny peněženky", "sync_status_attempting_sync": "ZAHAJUJI SYNCHR.", "sync_status_connected": "PŘIPOJENO", "sync_status_connecting": "PŘIPOJOVÁNÍ", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 8369cc5b7..b795b2037 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -44,6 +44,7 @@ "amount": "Betrag: ", "amount_is_estimate": "Der empfangene Betrag ist eine Schätzung", "amount_is_guaranteed": "Der Empfangsbetrag ist garantiert", + "and": "Und", "anonpay_description": "Generieren Sie ${type}. Der Empfänger kann ${method} mit jeder unterstützten Kryptowährung verwenden, und Sie erhalten Geld in dieser Wallet.", "apk_update": "APK-Update", "approve": "Genehmigen", @@ -62,6 +63,7 @@ "available_balance_description": "Verfügbarer Saldo ist der Betrag, den Sie sofort ausgeben können. Dieser Betrag kann sich ändern, wenn Sie eine Transaktion senden oder empfangen.", "avg_savings": "Durchschn. Einsparungen", "awaitDAppProcessing": "Bitte warten Sie, bis die dApp die Verarbeitung abgeschlossen hat.", + "awaiting_payment_confirmation": "Warten auf Zahlungsbestätigung", "background_sync_mode": "Hintergrundsynchronisierungsmodus", "backup": "Sicherung", "backup_file": "Sicherungsdatei", @@ -406,6 +408,7 @@ "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_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", @@ -483,6 +486,7 @@ "restore_wallet": "Wallet wiederherstellen", "restore_wallet_name": "Walletname", "restore_wallet_restore_description": "Beschreibung zur Wallet-Wiederherstellung", + "robinhood_option_description": "Kaufen und übertragen Sie sofort mit Ihrem Debitkarten-, Bankkonto- oder Robinhood -Guthaben. Nur USA.", "router_no_route": "Keine Route definiert für ${name}", "save": "Speichern", "save_backup_password": "Bitte stellen Sie sicher, dass Sie Ihr Sicherungskennwort gespeichert haben. Ohne dieses können Sie Ihre Sicherungsdateien nicht importieren.", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 4f54e0f87..9ce0fe803 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -162,6 +162,7 @@ "creating_new_wallet": "Creando nueva billetera", "creating_new_wallet_error": "Error: ${description}", "creation_date": "Fecha de creación", + "custom": "Costumbre", "custom_drag": "Custom (mantenía y arrastre)", "custom_redeem_amount": "Cantidad de canje personalizada", "dark_theme": "Oscura", @@ -485,6 +486,7 @@ "restore_wallet": "Restaurar billetera", "restore_wallet_name": "Nombre de la billetera", "restore_wallet_restore_description": "Restaurar billetera", + "robinhood_option_description": "Compre y transfiera instantáneamente utilizando su tarjeta de débito, cuenta bancaria o saldo de Robinhood. Solo EE. UU.", "router_no_route": "No hay ruta definida para ${name}", "save": "Salvar", "save_backup_password": "Asegúrese de haber guardado su contraseña de respaldo. No podrá importar sus archivos de respaldo sin él.", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index fc72c06db..306ff79ea 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -485,6 +485,7 @@ "restore_wallet": "Restaurer un Portefeuille (Wallet)", "restore_wallet_name": "Nom du portefeuille (wallet)", "restore_wallet_restore_description": "Description de la restauration de portefeuille (wallet)", + "robinhood_option_description": "Achetez et transférez instantanément à l'aide de votre carte de débit, de votre compte bancaire ou de votre solde Robinhood. États-Unis seulement.", "router_no_route": "Aucune route définie pour ${name}", "save": "Sauvegarder", "save_backup_password": "Merci de vous assurer d'avoir bien sauvegardé votre mot de passe de sauvegarde. Vous ne pourrez pas restaurer vos fichiers de sauvegarde sans ce dernier.", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 748c134c6..4ce0fd713 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -64,6 +64,7 @@ "avg_savings": "Matsakaici Adana", "awaitDAppProcessing": "Da fatan za a jira dApp ya gama aiki.", "awaiting_payment_confirmation": "Ana jiran Tabbacin Biyan Kuɗi", + "background_sync_mode": "Yanayin Sync", "backup": "Ajiyayyen", "backup_file": "Ajiyayyen fayil", "backup_password": "Ajiyayyen kalmar sirri", @@ -121,6 +122,7 @@ "choose_wallet_currency": "Da fatan za a zaɓi kuɗin walat:", "clear": "Share", "clearnet_link": "Lambar makomar kwayoyi", + "close": "Rufa", "coin_control": "Sarrafa tsabar kuɗi (na zaɓi)", "cold_or_recover_wallet": "Samun kashi na baya ko samun kashi na kasa", "color_theme": "Jigon launi", @@ -181,7 +183,9 @@ "didnt_get_code": "Ba a samun code?", "digit_pin": "-lambar PIN", "digital_and_physical_card": "katin zare kudi na dijital da na zahiri", + "disable": "Kashe", "disable_buy": "Kashe alama", + "disable_cake_2fa": "Musaki Cake 2FA", "disable_exchange": "Kashe musanya", "disable_fiat": "Dakatar da fiat", "disable_sell": "Kashe karbuwa", @@ -207,6 +211,7 @@ "enter_backup_password": "Shigar da kalmar wucewa ta madadin nan", "enter_code": "Shigar da lamba", "enter_seed_phrase": "Shigar da Sert Sentarku", + "enter_totp_code": "Da fatan za a shigar da lambar tnp.", "enter_your_note": "Shigar da bayanin kula…", "enter_your_pin": "Shigar da PIN", "enter_your_pin_again": "Shigar da PIN ɗinku na sake", @@ -254,6 +259,7 @@ "expiresOn": "Yana ƙarewa", "export_backup": "Ajiyayyen fitarwa", "extra_id": "Karin ID:", + "extracted_address_content": "Za ku aika da kudade zuwa\n${recipient_name}", "failed_authentication": "Binne wajen shiga. ${state_error}", "faq": "FAQ", "fetching": "Daukewa", @@ -329,6 +335,7 @@ "min_value": "Min: ${value} ${currency}", "minutes_to_pin_code": "${minute} minti", "mm": "MM", + "modify_2fa": "Gyara Cake 2FA", "monero_com": "Monero.com ta Cake Wallet", "monero_com_wallet_text": "Aikace-aikacen e-wallet ga Monero", "monero_dark_theme": "Monero Dark Jigo", @@ -378,6 +385,7 @@ "optional_email_hint": "Email na kayan taimako ga wadanda basu ba da maki", "optional_name": "Sunan mawallin zai iya ba da maki", "optionally_order_card": "Zaɓin yin odar katin zahiri.", + "orbot_running_alert": "Da fatan za a tabbata cewa orbot yana gudana kafin haɗi zuwa wannan kumburin.", "order_by": "Oda ta", "order_id": "Oda ID", "order_physical_card": "Yi Oda Katin Jiki", @@ -399,6 +407,7 @@ "pin_number": "Lambar PIN", "placeholder_contacts": "Za a nuna lambobin sadarwar ku anan", "placeholder_transactions": "Za a nuna ma'amalolin ku anan", + "please_fill_totp": "Da fatan za a cika lambar lambobi 8 da ke yanzu a kan sauran na'urarku", "please_make_selection": "Don Allah zaɓi ƙasa don ƙirƙira ko dawo da kwalinku.", "please_reference_document": "Da fatan za a nemi takaddun da ke ƙasa don ƙarin bayani.", "please_select": "Don Allah zaɓi:", @@ -416,11 +425,13 @@ "privacy_settings": "Saitunan sirri", "private_key": "Keɓaɓɓen maɓalli", "proceed_after_one_minute": "Idan allon bai ci gaba ba bayan minti 1, duba imel ɗin ku.", + "profile": "Rabin fuska", "provider_error": "${provider} kuskure", "public_key": "Maɓallin jama'a", "purchase_gift_card": "Katin Kyautar Sayi", "qr_fullscreen": "Matsa don buɗe lambar QR na cikakken allo", "qr_payment_amount": "Wannan QR code yana da adadin kuɗi. Kuna so ku overwrite wannan adadi?", + "question_to_disable_2fa": "Ka tabbata cewa kana son kashe cake 2fa? Ba za a sake buƙatar lambar 2FA ba don samun damar yin walat da takamaiman ayyuka.", "receivable_balance": "Daidaituwa da daidaituwa", "receive": "Samu", "receive_amount": "Adadi", @@ -476,6 +487,7 @@ "restore_wallet": "Dawo da Kwalinku", "restore_wallet_name": "Sunan kwalinku", "restore_wallet_restore_description": "Bayanin dawo da walat", + "robinhood_option_description": "Sayi da Canja wurin nan take amfani da katin debit, asusun banki, ko ma'aunin raraki. Amurka kawai.", "router_no_route": "Babu wata hanya da aka bayyana don ${name}", "save": "Ajiye", "save_backup_password": "Da fatan za a tabbatar cewa kun adana kalmar sirrin ajiyar ku. Ba za ku iya shigo da fayilolin ajiyar ku ba tare da shi ba.", @@ -483,6 +495,7 @@ "save_to_downloads": "Ajiye zuwa Zazzagewa", "saved_the_trade_id": "Na ajiye ID na ciniki", "scan_qr_code": "Gani QR kodin", + "scan_qr_code_to_get_address": "Duba lambar QR don samun adireshin", "scan_qr_on_device": "Duba wannan lambar QR akan wata na'ura", "search": "Bincika", "search_add_token": "Bincika / Ƙara alama", @@ -573,6 +586,7 @@ "settings_trades": "Cinikai", "settings_transactions": "Ma'amaloli", "settings_wallets": "Wallets", + "setup_2fa": "Saiti 2FA", "setup_2fa_text": "Cake 2FA yana aiki ta amfani da TOTP azaman ƙimar tabbatarwa ta biyu.\n\nCake 2FA's TOTP yana buƙatar tallafin lambobi SHA-512 da 8; wannan yana ba da ƙarin tsaro. Ana iya samun ƙarin bayani da ƙa'idodi masu goyan baya a cikin jagorar.", "setup_pin": "Saita PIN", "setup_successful": "An saita PIN ɗinku da nasara!", @@ -608,6 +622,7 @@ "switchToETHWallet": "Da fatan za a canza zuwa walat ɗin Ethereum kuma a sake gwadawa", "switchToEVMCompatibleWallet": "Da fatan za a canza zuwa walat ɗin EVM mai jituwa kuma a sake gwadawa (Ethereum, Polygon)", "symbol": "Alama", + "sync_all_wallets": "Sync Duk Wallet", "sync_status_attempting_sync": "KWAFI", "sync_status_connected": "HANNU", "sync_status_connecting": "HADA", @@ -633,7 +648,12 @@ "tor_connection": "Tor haɗin gwiwa", "tor_only": "Tor kawai", "total_saving": "Jimlar Adana", + "totp_2fa_failure": "Ba daidai ba. Da fatan za a gwada wata lamba ta daban ko samar da sabon maɓallin asirin. Yi amfani da aikace-aikacen da ya dace 2FA wanda ke tallafawa lambobin lambobi 8 da Sha512.", + "totp_2fa_success": "Nasara! Cake 2FA ya dogara da wannan waljin. Ka tuna domin adana zuriyar mnemmonic naka idan ka rasa damar walat.", "totp_auth_url": "TOTP AUTH URL", + "totp_code": "Lambar totp", + "totp_secret_code": "Lambar sirri", + "totp_verification_success": "Tabbatar cin nasara!", "trade_details_copied": "${title} an kwafa zuwa cikin kwafin", "trade_details_created_at": "An ƙirƙira a", "trade_details_fetching": "Daukewa", @@ -701,6 +721,7 @@ "use_suggested": "Amfani da Shawarwari", "variable_pair_not_supported": "Ba a samun goyan bayan wannan m biyu tare da zaɓaɓɓun musayar", "verification": "tabbatar", + "verify_with_2fa": "Tabbatar da Cake 2FA", "version": "Sigar ${currentVersion}", "view_all": "Duba duka", "view_in_block_explorer": "Dubo a cikin Block Explorer", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 53347a69a..a6335e3ed 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -39,6 +39,7 @@ "all_trades": "सभी व्यापार", "all_transactions": "सभी लेन - देन", "alphabetical": "वर्णमाला", + "already_have_account": "क्या आपके पास पहले से एक खाता मौजूद है?", "always": "हमेशा", "amount": "रकम: ", "amount_is_estimate": "प्राप्त राशि एक अनुमान है", @@ -397,6 +398,7 @@ "pause_wallet_creation": "हेवन वॉलेट बनाने की क्षमता फिलहाल रुकी हुई है।", "payment_id": "भुगतान ID: ", "Payment_was_received": "आपका भुगतान प्राप्त हो गया था।", + "payment_was_received": "आपका भुगतान प्राप्त हुआ था।", "pending": " (अपूर्ण)", "percentageOf": "${amount} का", "pin_at_top": "शीर्ष पर ${token} पिन करें", @@ -485,6 +487,7 @@ "restore_wallet": "वॉलेट को पुनर्स्थापित करें", "restore_wallet_name": "बटुए का नाम", "restore_wallet_restore_description": "बटुआ विवरण पुनर्स्थापित करें", + "robinhood_option_description": "अपने डेबिट कार्ड, बैंक खाते या रॉबिनहुड बैलेंस का उपयोग करके तुरंत खरीदें और स्थानांतरित करें। केवल यूएसए।", "router_no_route": "के लिए कोई मार्ग निर्धारित नहीं है ${name}", "save": "बचाना", "save_backup_password": "कृपया सुनिश्चित करें कि आपने अपना बैकअप पासवर्ड सहेज लिया है। आप इसके बिना अपनी बैकअप फ़ाइलों को आयात नहीं कर पाएंगे।", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 7d251e867..e95c027d9 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -108,6 +108,7 @@ "change_language": "Promijeni jezik", "change_language_to": "Promijeni jezik u ${language}?", "change_password": "Promijeni lozinku", + "change_rep": "Promijenite reprezentativan", "change_rep_message": "Jeste li sigurni da želite promijeniti predstavnika?", "change_rep_successful": "Uspješno promijenjena reprezentativna", "change_wallet_alert_content": "Želite li promijeniti trenutni novčanik u ${wallet_name}?", @@ -484,6 +485,7 @@ "restore_wallet": "Oporavi novčanik", "restore_wallet_name": "Ime novčanika", "restore_wallet_restore_description": "Opis oporavka novčanika", + "robinhood_option_description": "Kupite i prebacite odmah pomoću svoje debitne kartice, bankovnog računa ili robinhood salda. Samo SAD.", "router_no_route": "Nije definirana ruta za ${name}", "save": "Spremi", "save_backup_password": "Molimo pobrinite se da spremite svoju lozinku za sigurnosnu kopiju. Bez nje nećete moći uvesti datoteke sigurnosne kopije.", @@ -608,6 +610,7 @@ "submit_request": "podnesi zahtjev", "successful": "Uspješno", "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_live_chat": "Podrška uživo", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 464483eab..d9ee117ad 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -48,6 +48,7 @@ "anonpay_description": "Hasilkan ${type}. Penerima dapat ${method} dengan cryptocurrency apa pun yang didukung, dan Anda akan menerima dana di dompet ini.", "apk_update": "Pembaruan APK", "approve": "Menyetujui", + "arrive_in_this_address": "${currency} ${tag} akan tiba di alamat ini", "ascending": "Naik", "ask_each_time": "Tanyakan setiap kali", "auth_store_ban_timeout": "ban_timeout", @@ -63,6 +64,7 @@ "avg_savings": "Rata-rata Pembayaran", "awaitDAppProcessing": "Mohon tunggu hingga dApp menyelesaikan pemrosesan.", "awaiting_payment_confirmation": "Menunggu Konfirmasi Pembayaran", + "background_sync_mode": "Mode Sinkronisasi Latar Belakang", "backup": "Cadangan", "backup_file": "File cadangan", "backup_password": "Kata sandi cadangan", @@ -72,6 +74,7 @@ "biometric_auth_reason": "Pindai sidik jari Anda untuk mengautentikasi", "bitcoin_dark_theme": "Tema Gelap Bitcoin", "bitcoin_light_theme": "Tema Cahaya Bitcoin", + "bitcoin_payments_require_1_confirmation": "Pembayaran Bitcoin memerlukan 1 konfirmasi, yang bisa memakan waktu 20 menit atau lebih. Terima kasih atas kesabaran Anda! Anda akan diemail saat pembayaran dikonfirmasi.", "Blocks_remaining": "${status} Blok Tersisa", "bright_theme": "Cerah", "buy": "Beli", @@ -121,6 +124,7 @@ "clearnet_link": "Tautan clearnet", "close": "Menutup", "coin_control": "Kontrol koin (opsional)", + "cold_or_recover_wallet": "Tambahkan dompet dingin atau pulihkan dompet kertas", "color_theme": "Tema warna", "commit_transaction_amount_fee": "Lakukan transaksi\nJumlah: ${amount}\nBiaya: ${fee}", "confirm": "Konfirmasi", @@ -190,6 +194,7 @@ "display_settings": "Pengaturan tampilan", "displayable": "Dapat ditampilkan", "do_not_have_enough_gas_asset": "Anda tidak memiliki cukup ${currency} untuk melakukan transaksi dengan kondisi jaringan blockchain saat ini. Anda memerlukan lebih banyak ${currency} untuk membayar biaya jaringan blockchain, meskipun Anda mengirimkan aset yang berbeda.", + "do_not_send": "Jangan kirim", "do_not_share_warning_text": "Jangan berikan ini pada siapapun, termasuk dukungan.\n\nDana Anda bisa dan akan dicuri!", "do_not_show_me": "Jangan tampilkan ini lagi", "domain_looks_up": "Pencarian domain", @@ -213,6 +218,7 @@ "enterTokenID": "Masukkan ID tokennya", "enterWalletConnectURI": "Masukkan URI WalletConnect", "error": "Kesalahan", + "error_dialog_content": "Ups, kami mendapat kesalahan.\n\nSilakan kirim laporan crash ke tim dukungan kami untuk membuat aplikasi lebih baik.", "error_text_account_name": "Nama akun hanya dapat berisi huruf, angka\ndan harus antara 1 dan 15 karakter panjang", "error_text_address": "Alamat dompet harus sesuai dengan tipe\nmata uang kripto", "error_text_amount": "Jumlah hanya dapat berisi angka", @@ -253,6 +259,7 @@ "expiresOn": "Kadaluarsa pada", "export_backup": "Ekspor cadangan", "extra_id": "ID tambahan:", + "extracted_address_content": "Anda akan mengirim dana ke\n${recipient_name}", "failed_authentication": "Otentikasi gagal. ${state_error}", "faq": "Pertanyaan yang Sering Diajukan", "fetching": "Mengambil", @@ -406,6 +413,7 @@ "please_select": "Silakan pilih:", "please_select_backup_file": "Silakan pilih file cadangan dan masukkan kata sandi cadangan.", "please_try_to_connect_to_another_node": "Silakan coba untuk terhubung ke node lain", + "please_wait": "Harap tunggu", "polygonscan_history": "Sejarah PolygonScan", "powered_by": "Didukung oleh ${title}", "pre_seed_button_text": "Saya mengerti. Tampilkan seed saya", @@ -464,6 +472,7 @@ "restore_description_from_seed": "Pulihkan dompet Anda dari kombinasi kode 25 atau 13 kata", "restore_description_from_seed_keys": "Dapatkan kembali dompet Anda dari seed/kunci yang Anda simpan di tempat yang aman", "restore_from_date_atau_blockheight": "Silakan masukkan tanggal beberapa hari sebelum Anda membuat dompet ini. Atau jika Anda tahu blockheight, silakan masukkannya sebagai gantinya", + "restore_from_date_or_blockheight": "Harap masukkan tanggal beberapa hari sebelum Anda membuat dompet ini. Atau jika Anda tahu blockheight, silakan masukkan sebagai gantinya", "restore_from_seed_placeholder": "Silakan masukkan atau tempel seed Anda di sini", "restore_new_seed": "Seed baru", "restore_next": "Selanjutnya", @@ -479,6 +488,7 @@ "restore_wallet": "Pulihkan Dompet", "restore_wallet_name": "Nama dompet", "restore_wallet_restore_description": "Deskripsi pemulihan dompet", + "robinhood_option_description": "Beli dan transfer secara instan menggunakan kartu debit, rekening bank, atau saldo robinhood Anda. Hanya AS.", "router_no_route": "Tidak ada rute yang ditentukan untuk ${name}", "save": "Simpan", "save_backup_password": "Pastikan Anda telah menyimpan kata sandi cadangan Anda. Anda tidak akan dapat mengimpor file cadangan Anda tanpa itu.", @@ -486,6 +496,7 @@ "save_to_downloads": "Simpan ke Unduhan", "saved_the_trade_id": "Saya telah menyimpan ID perdagangan", "scan_qr_code": "Scan kode QR untuk mendapatkan alamat", + "scan_qr_code_to_get_address": "Pindai kode QR untuk mendapatkan alamat", "scan_qr_on_device": "Pindai kode QR ini di perangkat lain", "search": "Cari", "search_add_token": "Cari / Tambahkan token", @@ -547,10 +558,12 @@ "send_success": "${crypto}mu berhasil dikirim", "send_templates": "Template", "send_title": "Kirim", + "send_to_this_address": "Kirim ${currency} ${tag} ke alamat ini", "send_xmr": "Kirim XMR", "send_your_wallet": "Dompetmu", "sending": "Mengirim", "sent": "Dikirim", + "settings": "Pengaturan", "settings_all": "SEMUA", "settings_allow_biometrical_authentication": "Izinkan otentikasi biometrik", "settings_can_be_changed_later": "Pengaturan ini dapat diubah nanti di pengaturan aplikasi", @@ -605,9 +618,12 @@ "support_title_guides": "Panduan Dompet Kue", "support_title_live_chat": "Dukungan langsung", "support_title_other_links": "Tautan dukungan lainnya", + "sweeping_wallet": "Dompet menyapu", + "sweeping_wallet_alert": "Ini seharusnya tidak memakan waktu lama. Jangan tinggalkan layar ini atau dana swept mungkin hilang.", "switchToETHWallet": "Silakan beralih ke dompet Ethereum dan coba lagi", "switchToEVMCompatibleWallet": "Silakan beralih ke dompet yang kompatibel dengan EVM dan coba lagi (Ethereum, Polygon)", "symbol": "Simbol", + "sync_all_wallets": "Sinkronkan semua dompet", "sync_status_attempting_sync": "MENCOBA SINKRONISASI", "sync_status_connected": "TERHUBUNG", "sync_status_connecting": "MENGHUBUNGKAN", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 729b8c9c8..ca5716c07 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -63,6 +63,7 @@ "available_balance_description": "Il saldo disponibile è il saldo totale meno i fondi congelati. I fondi congelati sono fondi che sono stati inviati ma non sono ancora stati confermati.", "avg_savings": "Risparmio medio", "awaitDAppProcessing": "Attendi gentilmente che la dApp termini l'elaborazione.", + "awaiting_payment_confirmation": "In attesa di conferma del pagamento", "background_sync_mode": "Modalità di sincronizzazione in background", "backup": "Backup", "backup_file": "Backup file", @@ -134,6 +135,7 @@ "confirmed": "Saldo confermato", "confirmed_tx": "Confermato", "congratulation": "Congratulazioni!", + "congratulations": "Congratulazioni!", "connect_an_existing_yat": "Collegare un Yat esistente", "connect_yats": "Connetti Yats", "connection_sync": "Connessione e sincronizzazione", @@ -382,6 +384,7 @@ "optional_email_hint": "Email di notifica del beneficiario facoltativa", "optional_name": "Nome del destinatario facoltativo", "optional_order_card": "Ordina facoltativamente una carta fisica.", + "optionally_order_card": "Ordina facoltativamente una carta fisica.", "orbot_running_alert": "Assicurati che Orbot sia in esecuzione prima di connetterti a questo nodo.", "order_by": "Ordinato da", "order_id": "ID ordine", @@ -484,6 +487,7 @@ "restore_wallet": "Recupera Portafoglio", "restore_wallet_name": "Nome Portafoglio", "restore_wallet_restore_description": "Descrizione recupero Portafoglio", + "robinhood_option_description": "Acquista e trasferisci istantaneamente utilizzando la carta di debito, il conto bancario o il saldo di Robinhood. Solo USA.", "router_no_route": "Nessun percorso definito per ${name}", "save": "Salva", "save_backup_password": "Gentilmente assicurati di aver salvato la password del tuo backup. Senza questa non sarai in grado di importare i tuoi file di backup.", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 710a78088..5c5d3e3a1 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -279,6 +279,7 @@ "full_balance": "フルバランス", "generate_name": "名前の生成", "generated_gift_card": "ギフトカードの生成", + "generating_gift_card": "ギフトカードの生成", "get_a": "Get a", "get_card_note": "デジタル通貨でリロードできます。追加情報は必要ありません!", "get_your_yat": "あなたのYatを入手してください", @@ -485,6 +486,7 @@ "restore_wallet": "ウォレットを復元", "restore_wallet_name": "ウォレット名", "restore_wallet_restore_description": "ウォレットの復元", + "robinhood_option_description": "デビットカード、銀行口座、またはロビンフッドバランスを使用して、即座に購入して転送します。アメリカのみ。", "router_no_route": "ルートが定義されていません ${name}", "save": "セーブ", "save_backup_password": "バックアップパスワードが保存されていることを確認してください。 それなしではバックアップファイルをインポートすることはできません。", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index f0970ac43..81b582200 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -108,6 +108,8 @@ "change_language": "언어 변경", "change_language_to": "언어를로 변경 ${language}?", "change_password": "비밀번호 변경", + "change_rep": "대표를 변경하십시오", + "change_rep_message": "대표를 바꾸고 싶습니까?", "change_rep_successful": "대리인이 성공적으로 변경되었습니다", "change_wallet_alert_content": "현재 지갑을 다음으로 변경 하시겠습니까 ${wallet_name}?", "change_wallet_alert_title": "현재 지갑 변경", @@ -406,6 +408,7 @@ "please_fill_totp": "다른 기기에 있는 8자리 코드를 입력하세요.", "please_make_selection": "아래에서 선택하십시오 지갑 만들기 또는 복구.", "Please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.", + "please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.", "please_select": "선택 해주세요:", "please_select_backup_file": "백업 파일을 선택하고 백업 암호를 입력하십시오.", "please_try_to_connect_to_another_node": "다른 노드에 연결을 시도하십시오", @@ -483,6 +486,7 @@ "restore_wallet": "월렛 복원", "restore_wallet_name": "지갑 이름", "restore_wallet_restore_description": "월렛 복원 설명", + "robinhood_option_description": "직불 카드, 은행 계좌 또는 Robinhood 잔액을 사용하여 즉시 구매 및 양도하십시오. 미국 만.", "router_no_route": "에 정의 된 경로가 없습니다 ${name}", "save": "구하다", "save_backup_password": "백업 암호를 저장했는지 확인하십시오. 그것 없이는 백업 파일을 가져올 수 없습니다.", @@ -774,5 +778,6 @@ "you_will_get": "로 변환하다", "you_will_send": "다음에서 변환", "YY": "YY", + "yy": "YY", "zzzz": "zzzz" } \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index fecec9f18..5094b1898 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -64,6 +64,7 @@ "avg_savings": "ပျမ်းမျှ စုဆောင်းငွေ", "awaitDAppProcessing": "ကျေးဇူးပြု၍ dApp ကို စီမံလုပ်ဆောင်ခြင်း အပြီးသတ်ရန် စောင့်ပါ။", "awaiting_payment_confirmation": "ငွေပေးချေမှု အတည်ပြုချက်ကို စောင့်မျှော်နေပါသည်။", + "background_sync_mode": "နောက်ခံထပ်တူပြုခြင်း mode ကို", "backup": "မိတ္တူ", "backup_file": "အရန်ဖိုင်", "backup_password": "စကားဝှက်ကို အရန်သိမ်းဆည်းပါ။", @@ -484,6 +485,7 @@ "restore_wallet": "ပိုက်ဆံအိတ်ကို ပြန်ယူပါ။", "restore_wallet_name": "ပိုက်ဆံအိတ်နာမည်", "restore_wallet_restore_description": "Wallet ပြန်လည်ရယူသည့် ဖော်ပြချက်", + "robinhood_option_description": "သင်၏ဒက်ဘစ်ကဒ်, ဘဏ်အကောင့်, ယူအက်စ်အေသာ။", "router_no_route": "${name} အတွက် သတ်မှတ်ထားသော လမ်းကြောင်းမရှိပါ", "save": "သိမ်းဆည်းပါ။", "save_backup_password": "သင်၏ အရန်စကားဝှက်ကို သိမ်းဆည်းထားကြောင်း သေချာပါစေ။ ၎င်းမပါဘဲ သင်၏ အရန်ဖိုင်များကို တင်သွင်းနိုင်မည် မဟုတ်ပါ။", @@ -618,6 +620,7 @@ "switchToETHWallet": "ကျေးဇူးပြု၍ Ethereum ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ။", "switchToEVMCompatibleWallet": "ကျေးဇူးပြု၍ EVM တွဲဖက်သုံးနိုင်သော ပိုက်ဆံအိတ်သို့ ပြောင်းပြီး ထပ်စမ်းကြည့်ပါ (Ethereum၊ Polygon)", "symbol": "သင်္ကေတ", + "sync_all_wallets": "အားလုံးပိုက်ဆံအိတ်စည်းညှိ", "sync_status_attempting_sync": "ချိန်ကိုက်ခြင်းကို ကြိုးစားနေသည်။", "sync_status_connected": "ချိတ်ဆက်ထားသည်။", "sync_status_connecting": "ချိတ်ဆက်ခြင်း။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 225c7fc42..3aa4a3e4b 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -63,6 +63,7 @@ "available_balance_description": "Beschikbaar saldo is het saldo dat u kunt uitgeven. Het kan lager zijn dan uw totale saldo als u onlangs geld hebt verzonden.", "avg_savings": "Gem. besparingen", "awaitDAppProcessing": "Wacht tot de dApp klaar is met verwerken.", + "awaiting_payment_confirmation": "In afwachting van betalingsbevestiging", "background_sync_mode": "Achtergrondsynchronisatiemodus", "backup": "Back-up", "backup_file": "Backup bestand", @@ -484,6 +485,7 @@ "restore_wallet": "Portemonnee herstellen", "restore_wallet_name": "Portemonnee naam", "restore_wallet_restore_description": "Portemonnee-herstelbeschrijving", + "robinhood_option_description": "Koop en zet direct over op uw bankpas, bankrekening of Robinhood -saldo. Alleen VS.", "router_no_route": "Geen route gedefinieerd voor ${name}", "save": "Opslaan", "save_backup_password": "Zorg ervoor dat u uw reservewachtwoord heeft opgeslagen. Zonder dit kunt u uw back-upbestanden niet importeren.", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index f7293c754..8e3d3bffe 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -485,6 +485,7 @@ "restore_wallet": "Przywróć portfel", "restore_wallet_name": "Nazwa portfela", "restore_wallet_restore_description": "Przywracanie portfela", + "robinhood_option_description": "Kup i przenieś natychmiast za pomocą karty debetowej, konta bankowego lub salda Robinhood. Tylko USA.", "router_no_route": "Brak zdefiniowanej trasy dla ${name}", "save": "Zapisz", "save_backup_password": "Upewnij się, że zapisałeś swoje hasło kopii zapasowej. Bez tego nie będziesz mógł zaimportować pliku kopii zapasowej.", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 1f80c62d9..f00f02c01 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -63,6 +63,7 @@ "available_balance_description": "Seu saldo disponível é o saldo total menos o saldo congelado. O saldo congelado é o saldo que você não pode gastar, mas que ainda não foi confirmado na blockchain. O saldo congelado é geralmente o resultado de transações recentes.", "avg_savings": "Poupança média", "awaitDAppProcessing": "Aguarde até que o dApp termine o processamento.", + "awaiting_payment_confirmation": "Aguardando confirmação de pagamento", "background_sync_mode": "Modo de sincronização em segundo plano", "backup": "Cópia de segurança", "backup_file": "Arquivo de backup", @@ -322,6 +323,7 @@ "manage_nodes": "Gerenciar nós", "manage_pow_nodes": "Gerenciar nós PoW", "manage_yats": "Gerenciar Yats", + "mark_as_redeemed": "Marque como resgatado", "mark_as_redemed": "Marcar como resgatado", "market_place": "Mercado", "matrix_green_dark_theme": "Tema escuro verde matrix", @@ -382,6 +384,7 @@ "optional_description": "Descrição opcional", "optional_email_hint": "E-mail opcional de notificação do beneficiário", "optional_name": "Nome do destinatário opcional", + "optionally_order_card": "Opcionalmente encomende um cartão físico.", "orbot_running_alert": "Certifique-se de que o Orbot esteja em execução antes de se conectar a este nó.", "order_by": "Ordenar por", "order_id": "ID do pedido", @@ -484,6 +487,7 @@ "restore_wallet": "Restaurar carteira", "restore_wallet_name": "Nome da carteira", "restore_wallet_restore_description": "Restauração da carteira", + "robinhood_option_description": "Compre e transfira instantaneamente usando seu cartão de débito, conta bancária ou saldo de Robinhood. EUA apenas.", "router_no_route": "Nenhuma rota definida para ${name}", "save": "Salvar", "save_backup_password": "Certifique-se de que salvou sua senha de backup. Você não poderá importar seus arquivos de backup sem ele.", @@ -595,6 +599,7 @@ "show_keys": "Mostrar semente/chaves", "show_market_place": "Mostrar mercado", "show_seed": "Mostrar semente", + "sign_up": "Inscrever-se", "signTransaction": "Assinar transação", "signup_for_card_accept_terms": "Cadastre-se no cartão e aceite os termos.", "slidable": "Deslizável", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 7fccaa5bd..b8e70ee1f 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -382,6 +382,7 @@ "optional_description": "Дополнительное описание", "optional_email_hint": "Необязательное электронное письмо с уведомлением получателя платежа", "optional_name": "Необязательное имя получателя", + "optionally_order_card": "При желании заказать физическую карту.", "optionly_order_card": "При желании закажите физическую карту.", "orbot_running_alert": "Перед подключением к этому узлу убедитесь, что Orbot запущен.", "order_by": "Сортировать по", @@ -485,6 +486,7 @@ "restore_wallet": "Восстановить кошелёк", "restore_wallet_name": "Имя кошелька", "restore_wallet_restore_description": "Описание восстановления кошелька", + "robinhood_option_description": "Покупайте и перенесите мгновенно, используя свою дебетовую карту, банковский счет или баланс Robinhood. Только США.", "router_no_route": "Не установлен маршрут для ${name}", "save": "Сохранить", "save_backup_password": "Убедитесь, что вы сохранили пароль резервной копии. Без него вы не сможете импортировать файлы резервных копий.", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index e1f187bd3..1975556ca 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -64,6 +64,7 @@ "avg_savings": "ประหยัดเฉลี่ย", "awaitDAppProcessing": "โปรดรอให้ dApp ประมวลผลเสร็จสิ้น", "awaiting_payment_confirmation": "รอการยืนยันการชำระเงิน", + "background_sync_mode": "โหมดซิงค์พื้นหลัง", "backup": "สำรองข้อมูล", "backup_file": "ไฟล์สำรองข้อมูล", "backup_password": "รหัสผ่านสำรองข้อมูล", @@ -484,6 +485,7 @@ "restore_wallet": "กู้กระเป๋า", "restore_wallet_name": "ชื่อกระเป๋า", "restore_wallet_restore_description": "คำอธิบายการกู้กระเป๋า", + "robinhood_option_description": "ซื้อและโอนทันทีโดยใช้บัตรเดบิตบัญชีธนาคารหรือยอดคงเหลือของ Robinhood สหรัฐอเมริกาเท่านั้น", "router_no_route": "ไม่มีเส้นทางที่กำหนดไว้สำหรับ ${name}", "save": "บันทึก", "save_backup_password": "โปรดตรวจสอบให้แน่ใจว่าคุณได้บันทึกรหัสผ่านสำรองข้อมูลแล้ว คุณจะไม่สามารถนำเข้าไฟล์สำรองข้อมูลของคุณโดยไม่ใช้รหัสผ่านนั้น", @@ -618,6 +620,7 @@ "switchToETHWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงิน Ethereum แล้วลองอีกครั้ง", "switchToEVMCompatibleWallet": "โปรดเปลี่ยนไปใช้กระเป๋าเงินที่รองรับ EVM แล้วลองอีกครั้ง (Ethereum, Polygon)", "symbol": "เครื่องหมาย", + "sync_all_wallets": "ซิงค์กระเป๋าเงินทั้งหมด", "sync_status_attempting_sync": "พยายามซิงโครไนซ์", "sync_status_connected": "เชื่อมต่อแล้ว", "sync_status_connecting": "กำลังเชื่อมต่อ", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index ce3f0123c..06c56f5ee 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -108,11 +108,14 @@ "change_language": "Baguhin ang wika", "change_language_to": "Baguhin ang wika sa ${language}?", "change_password": "Palitan ANG password", + "change_rep": "Baguhin ang kinatawan", + "change_rep_message": "Sigurado ka bang nais mong baguhin ang mga kinatawan?", "change_rep_successful": "Matagumpay na nagbago ng kinatawan", "change_wallet_alert_content": "Nais mo bang baguhin ang kasalukuyang pitaka sa ${wallet_name}?", "change_wallet_alert_title": "Baguhin ang kasalukuyang pitaka", "choose_account": "Pumili ng account", "choose_address": "Mangyaring piliin ang address:", + "choose_derivation": "Piliin ang derivation ng Wallet", "choose_from_available_options": "Pumili mula sa magagamit na mga pagpipilian:", "choose_one": "Pumili ng isa", "choose_relay": "Mangyaring pumili ng relay na gagamitin", @@ -318,6 +321,7 @@ "low_fee": "Mababang bayad", "low_fee_alert": "Kasalukuyan kang gumagamit ng isang mababang priyoridad sa bayad sa network. Maaari itong maging sanhi ng mahabang paghihintay, iba't ibang mga rate, o kanselahin ang mga trading. Inirerekumenda namin ang pagtatakda ng isang mas mataas na bayad para sa isang mas mahusay na karanasan.", "manage_nodes": "Pamahalaan ang mga node", + "manage_pow_nodes": "Pamahalaan ang mga POW node", "manage_yats": "Pamahalaan ang mga yats", "mark_as_redeemed": "Markahan bilang tinubos", "market_place": "Marketplace", @@ -340,6 +344,7 @@ "more_options": "Higit pang mga pagpipilian", "name": "Pangalan", "narrow": "Makitid", + "new_first_wallet_text": "Panatilihing ligtas ang iyong crypto, piraso ng cake", "new_node_testing": "Bagong pagsubok sa node", "new_subaddress_create": "Lumikha", "new_subaddress_label_name": "Pangalan ng label", @@ -524,6 +529,7 @@ "seed_reminder": "Mangyaring isulat ang mga ito kung sakaling mawala ka o punasan ang iyong telepono", "seed_share": "Magbahagi ng binhi", "seed_title": "Binhi", + "seedtype": "Seedtype", "seedtype_legacy": "Pamana (25 salita)", "seedtype_polyseed": "Polyseed (16 na salita)", "select_backup_file": "Piliin ang backup file", @@ -704,6 +710,7 @@ "unspent_change": "Baguhin", "unspent_coins_details_title": "Mga Detalye ng Unspent Coins", "unspent_coins_title": "Unspent barya", + "unsupported_asset": "Hindi namin sinusuportahan ang pagkilos na ito para sa asset na ito. Mangyaring lumikha o lumipat sa isang pitaka ng isang suportadong uri ng pag -aari.", "upto": "Hanggang sa ${value}", "use": "Lumipat sa", "use_card_info_three": "Gamitin ang digital card online o sa mga pamamaraan ng pagbabayad na walang contact.", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index eeaaf3a40..e85adaa21 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -64,6 +64,7 @@ "avg_savings": "Ortalama Tasarruf", "awaitDAppProcessing": "Lütfen dApp'in işlemeyi bitirmesini bekleyin.", "awaiting_payment_confirmation": "Ödemenin onaylanması bekleniyor", + "background_sync_mode": "Arka Plan Senkronizasyon Modu", "backup": "Yedek", "backup_file": "Yedek dosyası", "backup_password": "Yedek parolası", @@ -484,6 +485,7 @@ "restore_wallet": "Cüzdanı Geri Döndür", "restore_wallet_name": "Cüzdan ismi", "restore_wallet_restore_description": "Cüzdan geri döndürme açıklaması", + "robinhood_option_description": "Banka kartınızı, banka hesabınızı veya Robinhood bakiyenizi kullanarak anında satın alın ve aktarın. Sadece ABD.", "router_no_route": "${name} için rota tanımlanmadı", "save": "Kaydet", "save_backup_password": "Lütfen yedekleme parolanı kaydettiğinden emin ol. Bu parola olmadan yedekleme dosyasını içe aktaramazsın.", @@ -618,6 +620,7 @@ "switchToETHWallet": "Lütfen bir Ethereum cüzdanına geçin ve tekrar deneyin", "switchToEVMCompatibleWallet": "Lütfen EVM uyumlu bir cüzdana geçin ve tekrar deneyin (Ethereum, Polygon)", "symbol": "Sembol", + "sync_all_wallets": "Tüm cüzdanları senkronize edin", "sync_status_attempting_sync": "SENKRONİZE EDİLMEYE ÇALIŞILIYOR", "sync_status_connected": "BAĞLANILDI", "sync_status_connecting": "BAĞLANILIYOR", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 59f21ab87..74d260674 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -439,6 +439,7 @@ "reconnect_alert_text": "Ви хочете перепідключитися?", "reconnection": "Перепідключення", "redeeded": "Викуплено", + "redeemed": "Викуплений", "refund_address": "Адреса повернення коштів", "reject": "Відхиляти", "remaining": "залишилося", @@ -485,6 +486,7 @@ "restore_wallet": "Відновити гаманець", "restore_wallet_name": "Ім'я гаманця", "restore_wallet_restore_description": "Опис відновлюваного гаманця", + "robinhood_option_description": "Купуйте та перенесіть миттєво за допомогою дебетової картки, банківського рахунку або балансу Робінства. Тільки США.", "router_no_route": "Не встановлено маршрут для ${name}", "save": "Зберегти", "save_backup_password": "Переконайтеся, що ви зберегли свій пароль резервної копії. Без нього ви не зможете імпортувати файли резервних копій.", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 713b676c4..e141fd8b3 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -64,6 +64,7 @@ "avg_savings": "اوسط بچت", "awaitDAppProcessing": "۔ﮟﯾﺮﮐ ﺭﺎﻈﺘﻧﺍ ﺎﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﮓﻨﺴﯿﺳﻭﺮﭘ ﮯﮐ dApp ﻡﺮﮐ ﮦﺍﺮﺑ", "awaiting_payment_confirmation": "ادائیگی کی تصدیق کے منتظر", + "background_sync_mode": "پس منظر کی مطابقت پذیری کا موڈ", "backup": "بیک اپ", "backup_file": "بیک اپ فائل", "backup_password": "بیک اپ پاس ورڈ", @@ -73,6 +74,7 @@ "biometric_auth_reason": "تصدیق کرنے کے لیے اپنے فنگر پرنٹ کو اسکین کریں۔", "bitcoin_dark_theme": "بٹ کوائن ڈارک تھیم", "bitcoin_light_theme": "بٹ کوائن لائٹ تھیم", + "bitcoin_payments_require_1_confirmation": "بٹ کوائن کی ادائیگی میں 1 تصدیق کی ضرورت ہوتی ہے ، جس میں 20 منٹ یا اس سے زیادہ وقت لگ سکتا ہے۔ آپ کے صبر کا شکریہ! ادائیگی کی تصدیق ہونے پر آپ کو ای میل کیا جائے گا۔", "Blocks_remaining": "${status} بلاکس باقی ہیں۔", "bright_theme": "روشن", "buy": "خریدنے", @@ -122,6 +124,7 @@ "clearnet_link": "کلیرنیٹ لنک", "close": "بند کریں", "coin_control": "سکے کنٹرول (اختیاری)", + "cold_or_recover_wallet": "ٹھنڈا پرس ڈالیں یا کاغذ کا پرس بازیافت کریں", "color_theme": "رنگین تھیم", "commit_transaction_amount_fee": "لین دین کا ارتکاب کریں\\nرقم: ${amount}\\nفیس: ${fee}", "confirm": "تصدیق کریں۔", @@ -256,6 +259,7 @@ "expiresOn": "ﺩﺎﻌﯿﻣ ﯽﻣﺎﺘﺘﺧﺍ", "export_backup": "بیک اپ برآمد کریں۔", "extra_id": "اضافی ID:", + "extracted_address_content": "آپ فنڈز بھیج رہے ہوں گے\n${recipient_name}", "failed_authentication": "ناکام تصدیق۔ ${state_error}", "faq": "عمومی سوالات", "fetching": "لا رہا ہے۔", @@ -409,6 +413,7 @@ "please_select": "براہ مہربانی منتخب کریں:", "please_select_backup_file": "براہ کرم بیک اپ فائل منتخب کریں اور بیک اپ پاس ورڈ درج کریں۔", "please_try_to_connect_to_another_node": "براہ کرم کسی دوسرے نوڈ سے جڑنے کی کوشش کریں۔", + "please_wait": "برائے مہربانی انتظار کریں", "polygonscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﻥﻮﮔ ﯽﻟﻮﭘ", "powered_by": "${title} کے ذریعے تقویت یافتہ", "pre_seed_button_text": "میں سمجھتا ہوں۔ مجھے میرا بیج دکھاؤ", @@ -482,6 +487,7 @@ "restore_wallet": "والیٹ کو بحال کریں۔", "restore_wallet_name": "بٹوے کا نام", "restore_wallet_restore_description": "والیٹ کی بحالی کی تفصیل", + "robinhood_option_description": "اپنے ڈیبٹ کارڈ ، بینک اکاؤنٹ ، یا رابن ہڈ بیلنس کا استعمال کرتے ہوئے فوری طور پر خریدیں اور منتقلی کریں۔ صرف USA", "router_no_route": "${name} کے لیے کوئی راستہ متعین نہیں ہے", "save": "محفوظ کریں۔", "save_backup_password": "براہ کرم یقینی بنائیں کہ آپ نے اپنا بیک اپ پاس ورڈ محفوظ کر لیا ہے۔ آپ اس کے بغیر اپنی بیک اپ فائلیں درآمد نہیں کر سکیں گے۔", @@ -489,6 +495,7 @@ "save_to_downloads": "۔ﮟﯾﺮﮐ ﻅﻮﻔﺤﻣ ﮟﯿﻣ ﺯﮈﻮﻟ ﻥﺅﺍﮈ", "saved_the_trade_id": "میں نے تجارتی ID محفوظ کر لی ہے۔", "scan_qr_code": "پتہ حاصل کرنے کے لیے QR کوڈ اسکین کریں۔", + "scan_qr_code_to_get_address": "پتہ حاصل کرنے کے لئے QR کوڈ کو اسکین کریں", "scan_qr_on_device": " ۔ﮟﯾﺮﮐ ﻦﯿﮑﺳﺍ ﺮﭘ ﺲﺋﺍﻮﯾﮈ ﺭﻭﺍ ﯽﺴﮐ ﻮﮐ ﮈﻮﮐ QR ﺱﺍ", "search": "تلاش کریں۔", "search_add_token": "تلاش کریں / ٹوکن شامل کریں۔", @@ -555,6 +562,7 @@ "send_your_wallet": "آپ کا بٹوہ", "sending": "بھیج رہا ہے۔", "sent": "بھیجا", + "settings": "ترتیبات", "settings_all": "تمام", "settings_allow_biometrical_authentication": "بایومیٹریکل تصدیق کی اجازت دیں۔", "settings_can_be_changed_later": "ان ترتیبات کو بعد میں ایپ کی ترتیبات میں تبدیل کیا جا سکتا ہے۔", @@ -609,9 +617,12 @@ "support_title_guides": "کیک پرس گائڈز", "support_title_live_chat": "براہ راست مدد", "support_title_other_links": "دوسرے سپورٹ لنکس", + "sweeping_wallet": "جھاڑو دینے والا پرس", + "sweeping_wallet_alert": "اس میں زیادہ وقت نہیں لینا چاہئے۔ اس اسکرین کو مت چھوڑیں یا بہہ جانے والے فنڈز ضائع ہوسکتے ہیں۔", "switchToETHWallet": "۔ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ Ethereum ﻡﺮﮐ ﮦﺍﺮﺑ", "switchToEVMCompatibleWallet": "(Ethereum, Polygon) ﮟﯾﺮﮐ ﺶﺷﻮﮐ ﮦﺭﺎﺑﻭﺩ ﺭﻭﺍ ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﭧﯿﻟﺍﻭ ﮯﻟﺍﻭ ﮯﻨﮭﮐﺭ ﺖﻘﺑﺎﻄﻣ ", "symbol": "ﺖﻣﻼﻋ", + "sync_all_wallets": "تمام بٹوے کو ہم آہنگ کریں", "sync_status_attempting_sync": "ہم آہنگی کی کوشش کر رہا ہے۔", "sync_status_connected": "منسلک", "sync_status_connecting": "جڑ رہا ہے۔", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 355800e72..360bef8c6 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -64,6 +64,7 @@ "avg_savings": "Ìpamọ́ l’óòrèkóòrè", "awaitDAppProcessing": "Fi inurere duro fun dApp lati pari sisẹ.", "awaiting_payment_confirmation": "À ń dúró de ìjẹ́rìísí àránṣẹ́", + "background_sync_mode": "Ipo amuṣiṣẹpọ abẹlẹ", "backup": "Ṣẹ̀dà", "backup_file": "Ṣẹ̀dà akọsílẹ̀", "backup_password": "Ṣẹ̀dà ọ̀rọ̀ aṣínà", @@ -179,6 +180,7 @@ "description": "Apejuwe", "destination_tag": "Orúkọ tí ìbí tó a ránṣẹ́ sí:", "dfx_option_description": "Ra crypto pẹlu EUR & CHF. Titi di 990 € laisi afikun KYC. Fun soobu ati awọn onibara ile-iṣẹ ni Yuroopu", + "didnt_get_code": "Ko gba koodu?", "digit_pin": "-díjíìtì òǹkà ìdánimọ̀ àdáni", "digital_and_physical_card": " káàdì ìrajà t'ara àti ti ayélujára", "disable": "Ko si", @@ -382,6 +384,7 @@ "optional_email_hint": "Ṣeto imọ-ẹrọ iye fun owo ti o gbọdọjọ", "optional_name": "Ṣeto orukọ ti o ni", "optionally_order_card": "Ẹ lè fi ìyàn bèèrè káàdì t'ara.", + "orbot_running_alert": "Jọwọ rii daju pe Orbot ti wa ni nṣiṣẹ ṣaaju ailorukọ si oju-ipade yii.", "order_by": "Bere fun nipasẹ", "order_id": "Àmì ìdánimọ̀ ti ìbéèrè", "order_physical_card": "Bèèrè káàdì t'ara", @@ -483,6 +486,7 @@ "restore_wallet": "Mú àpamọ́wọ́ padà", "restore_wallet_name": "Orúkọ àpamọ́wọ́", "restore_wallet_restore_description": "Ìṣapẹrẹ mú àpamọ́wọ́ padà", + "robinhood_option_description": "Ra ati Gbe lesekese lilo kaadi debiti rẹ, akọọlẹ banki, tabi iwọntunwọnsi robinrere. USA nikan.", "router_no_route": "Ọ̀nà kò sí fún ${name}", "save": "Pamọ́", "save_backup_password": "Ẹ jọ̀wọ́ dájú pé ẹ ti pamọ́ ọ̀rọ̀ aṣínà ti ẹ̀dà nípamọ́ yín. Ti ẹ kò bá ni í, ẹ kò lè ṣí àwọn àkọsílẹ̀ nípamọ́ yín.", @@ -490,6 +494,7 @@ "save_to_downloads": "Fipamọ si Awọn igbasilẹ", "saved_the_trade_id": "Mo ti pamọ́ àmì ìdánimọ̀ pàṣípààrọ̀", "scan_qr_code": "Yan QR koodu", + "scan_qr_code_to_get_address": "Ṣayẹwo koodu QR naa lati gba adirẹsi naa", "scan_qr_on_device": "Ṣe ayẹwo koodu QR yii lori ẹrọ miiran", "search": "Wá", "search_add_token": "Wa / Fi àmi kun", @@ -616,6 +621,7 @@ "switchToETHWallet": "Jọwọ yipada si apamọwọ Ethereum ki o tun gbiyanju lẹẹkansi", "switchToEVMCompatibleWallet": "Jọwọ yipada si apamọwọ ibaramu EVM ki o tun gbiyanju lẹẹkansi (Ethereum, Polygon)", "symbol": "Aami", + "sync_all_wallets": "Muṣiṣẹpọ gbogbo awọn Woleti", "sync_status_attempting_sync": "Ń GBÌYÀNJÚ MÚDỌ́GBA", "sync_status_connected": "TI DÁRAPỌ̀ MỌ́", "sync_status_connecting": "Ń DÁRAPỌ̀ MỌ́", @@ -755,6 +761,8 @@ "xmr_available_balance": "Owó tó wà ḿbí", "xmr_full_balance": "Ìyókù owó", "xmr_hidden": "Bìbò", + "xmr_to_error": "XMR.To aṣiṣe", + "xmr_to_error_description": "Iye ti ko wulo. Iwọn to pọju 8 nọmba lẹhin aaye eleemewa", "xrp_extra_info": "Ẹ jọ̀wọ́ ẹ kò gbàgbé pèsè orúkọ̀ àdírẹ́sì ti a ránṣẹ́ sí t'ẹ́ bá ránṣẹ pàṣípààrọ̀ ti XRP yín sílé ìfowóṣòwò", "yat": "Yat", "yat_address": "Àdírẹ́sì Yat", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 58cb2592c..e91d35922 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -485,6 +485,7 @@ "restore_wallet": "恢复钱包", "restore_wallet_name": "钱包名称", "restore_wallet_restore_description": "钱包还原说明", + "robinhood_option_description": "使用您的借记卡,银行帐户或罗比林余额立即购买和转移。仅美国。", "router_no_route": "未定义路线 ${name}", "save": "保存", "save_backup_password": "请确保您已保存备份密码。 沒有它,您将无法导入备份文件。", @@ -535,6 +536,7 @@ "select_buy_provider_notice": "在上面选择买入提供商。您可以通过在应用程序设置中设置默认的购买提供商来跳过此屏幕。", "select_destination": "请选择备份文件的目的地。", "select_sell_provider_notice": "选择上面的销售提供商。您可以通过在应用程序设置中设置默认销售提供商来跳过此屏幕。", + "sell": "卖", "sell_alert_content": "我们目前仅支持比特币、以太坊和莱特币的销售。请创建或切换到您的比特币、以太坊或莱特币钱包。", "sell_monero_com_alert_content": "尚不支持出售门罗币", "send": "发送", diff --git a/tool/translation_consistence.dart b/tool/translation_consistence.dart index 04f64dfc8..7f3ac130e 100644 --- a/tool/translation_consistence.dart +++ b/tool/translation_consistence.dart @@ -30,8 +30,10 @@ void main(List args) async { missingDefaults[key] = arbObj[key] as String; }); - if (missingDefaults.isNotEmpty) + if (missingDefaults.isNotEmpty) { await appendTranslations(lang, missingDefaults); + alphabetizeArbFile(fileName); + } } } } From e4ddf82e690d76931f969a4bf0e3780fb32eb536 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Tue, 6 Feb 2024 22:53:20 +0200 Subject: [PATCH 111/241] Remove unused translation zzzz [skip ci] (#1292) --- res/values/strings_ar.arb | 3 +-- res/values/strings_bg.arb | 3 +-- res/values/strings_cs.arb | 3 +-- res/values/strings_de.arb | 3 +-- res/values/strings_en.arb | 3 +-- res/values/strings_es.arb | 3 +-- res/values/strings_fr.arb | 3 +-- res/values/strings_ha.arb | 3 +-- res/values/strings_hi.arb | 3 +-- res/values/strings_hr.arb | 3 +-- res/values/strings_id.arb | 3 +-- res/values/strings_it.arb | 3 +-- res/values/strings_ja.arb | 3 +-- res/values/strings_ko.arb | 3 +-- res/values/strings_my.arb | 3 +-- res/values/strings_nl.arb | 3 +-- res/values/strings_pl.arb | 3 +-- res/values/strings_pt.arb | 3 +-- res/values/strings_ru.arb | 3 +-- res/values/strings_th.arb | 3 +-- res/values/strings_tl.arb | 3 +-- res/values/strings_tr.arb | 3 +-- res/values/strings_uk.arb | 3 +-- res/values/strings_ur.arb | 3 +-- res/values/strings_yo.arb | 3 +-- res/values/strings_zh.arb | 3 +-- 26 files changed, 26 insertions(+), 52 deletions(-) diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 5ed96628b..8ad38bc83 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -776,6 +776,5 @@ "you_pay": "انت تدفع", "you_will_get": "حول الى", "you_will_send": "تحويل من", - "yy": "YY", - "zzzz": "ززز" + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index ac94061fc..1190a53ce 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -776,6 +776,5 @@ "you_pay": "Вие плащате", "you_will_get": "Обръщане в", "you_will_send": "Обръщане от", - "yy": "гг", - "zzzz": "zzzz" + "yy": "гг" } \ No newline at end of file diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 3fbaa03d7..db6d2103c 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -776,6 +776,5 @@ "you_pay": "Zaplatíte", "you_will_get": "Směnit na", "you_will_send": "Směnit z", - "yy": "YY", - "zzzz": "Zzzz" + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index b795b2037..46c8a3c13 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -779,6 +779,5 @@ "you_pay": "Sie bezahlen", "you_will_get": "Konvertieren zu", "you_will_send": "Konvertieren von", - "yy": "YY", - "zzzz": "Zzzz" + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index c596cde10..a6ea6e39a 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -776,6 +776,5 @@ "you_pay": "You Pay", "you_will_get": "Convert to", "you_will_send": "Convert from", - "yy": "YY", - "zzzz": "zzzz" + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 9ce0fe803..9e719d812 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -777,6 +777,5 @@ "you_pay": "Tú pagas", "you_will_get": "Convertir a", "you_will_send": "Convertir de", - "yy": "YY", - "zzzz": "zzzz" + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 306ff79ea..b4c4d9eb6 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -776,6 +776,5 @@ "you_pay": "Vous payez", "you_will_get": "Convertir vers", "you_will_send": "Convertir depuis", - "yy": "AA", - "zzzz": "zzzz" + "yy": "AA" } \ No newline at end of file diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 4ce0fd713..06b212e94 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -778,6 +778,5 @@ "you_pay": "Ka Bayar", "you_will_get": "Maida zuwa", "you_will_send": "Maida daga", - "yy": "YY", - "zzzz": "zzzz" + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index a6335e3ed..f553608f7 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -778,6 +778,5 @@ "you_pay": "आप भुगतान करते हैं", "you_will_get": "में बदलें", "you_will_send": "से रूपांतरित करें", - "yy": "वाईवाई", - "zzzz": "ज़ज़्ज़" + "yy": "वाईवाई" } \ No newline at end of file diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index e95c027d9..b388df74f 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -776,6 +776,5 @@ "you_pay": "Vi plaćate", "you_will_get": "Razmijeni u", "you_will_send": "Razmijeni iz", - "yy": "GG", - "zzzz": "zzzz" + "yy": "GG" } \ No newline at end of file diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index d9ee117ad..84cfd8a5d 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -779,6 +779,5 @@ "you_pay": "Anda Membayar", "you_will_get": "Konversi ke", "you_will_send": "Konversi dari", - "yy": "YY", - "zzzz": "zzzz" + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index ca5716c07..33209fb34 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -779,6 +779,5 @@ "you_pay": "Tu paghi", "you_will_get": "Converti a", "you_will_send": "Conveti da", - "yy": "YY", - "zzzz": "Zzzz" + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 5c5d3e3a1..3cb1f64f6 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -777,6 +777,5 @@ "you_pay": "あなたが支払う", "you_will_get": "に変換", "you_will_send": "から変換", - "yy": "YY", - "zzzz": "zzzz" + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 81b582200..74afac094 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -778,6 +778,5 @@ "you_will_get": "로 변환하다", "you_will_send": "다음에서 변환", "YY": "YY", - "yy": "YY", - "zzzz": "zzzz" + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 5094b1898..6109908c1 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -776,6 +776,5 @@ "you_pay": "သင်ပေးချေပါ။", "you_will_get": "သို့ပြောင်းပါ။", "you_will_send": "မှပြောင်းပါ။", - "yy": "YY", - "zzzz": "မိုးခေဇဇ်" + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 3aa4a3e4b..03090db7e 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -777,6 +777,5 @@ "you_pay": "U betaalt", "you_will_get": "Converteren naar", "you_will_send": "Converteren van", - "yy": "JJ", - "zzzz": "Zzzz" + "yy": "JJ" } \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 8e3d3bffe..bafb9f151 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -776,6 +776,5 @@ "you_pay": "Płacisz", "you_will_get": "Konwertuj na", "you_will_send": "Konwertuj z", - "yy": "RR", - "zzzz": "Zzzz" + "yy": "RR" } \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index f00f02c01..694a2be92 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -779,6 +779,5 @@ "you_pay": "Você paga", "you_will_get": "Converter para", "you_will_send": "Converter de", - "yy": "aa", - "zzzz": "ZZZZ" + "yy": "aa" } \ No newline at end of file diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index b8e70ee1f..480f3ea68 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -777,6 +777,5 @@ "you_pay": "Вы платите", "you_will_get": "Конвертировать в", "you_will_send": "Конвертировать из", - "yy": "ГГ", - "zzzz": "zzzz" + "yy": "ГГ" } \ No newline at end of file diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 1975556ca..fd08d332d 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -776,6 +776,5 @@ "you_pay": "คุณจ่าย", "you_will_get": "แปลงเป็น", "you_will_send": "แปลงจาก", - "yy": "ปี", - "zzzz": "zzzz" + "yy": "ปี" } \ No newline at end of file diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 06c56f5ee..2759eaabe 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -776,6 +776,5 @@ "you_pay": "Magbabayad ka", "you_will_get": "Mag -convert sa", "you_will_send": "I -convert mula sa", - "yy": "YY", - "zzzz": "Zzzz" + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index e85adaa21..c8af1fbd3 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -776,6 +776,5 @@ "you_pay": "Şu kadar ödeyeceksin: ", "you_will_get": "Biçimine dönüştür:", "you_will_send": "Biçiminden dönüştür:", - "yy": "YY", - "zzzz": "zzzz" + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 74d260674..7007ec86c 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -777,6 +777,5 @@ "you_pay": "Ви платите", "you_will_get": "Конвертувати в", "you_will_send": "Конвертувати з", - "yy": "YY", - "zzzz": "ZZZZ" + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index e141fd8b3..5233e473b 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -778,6 +778,5 @@ "you_pay": "تم ادا کرو", "you_will_get": "میں تبدیل کریں۔", "you_will_send": "سے تبدیل کریں۔", - "yy": "YY", - "zzzz": "زیڈز" + "yy": "YY" } \ No newline at end of file diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 360bef8c6..95349e63a 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -777,6 +777,5 @@ "you_pay": "Ẹ sàn", "you_will_get": "Ṣe pàṣípààrọ̀ sí", "you_will_send": "Ṣe pàṣípààrọ̀ láti", - "yy": "Ọd", - "zzzz": "zzzz" + "yy": "Ọd" } \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index e91d35922..22792d307 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -776,6 +776,5 @@ "you_pay": "你付钱", "you_will_get": "转换到", "you_will_send": "转换自", - "yy": "YY", - "zzzz": "ZZZZ" + "yy": "YY" } \ No newline at end of file From 26fe28891debf378dbacfb6417f40dbfdccf2716 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Wed, 7 Feb 2024 07:44:29 -0800 Subject: [PATCH 112/241] Cw 528 backup wallet files (#1281) * monero wallet backup changes * [skipci] updates * monero fixes * start work for bitcoin/eth * cleanup * [skipci] more cleanup * add all other coins * merge fixes * add corrupted test * build for testing * actually be able to test monero * review fixes * more review fixes --- cw_bitcoin/lib/bitcoin_wallet_service.dart | 54 +++++++------ cw_bitcoin/lib/electrum_wallet.dart | 3 - cw_bitcoin/lib/litecoin_wallet_service.dart | 22 ++++-- .../lib/src/bitcoin_cash_wallet_service.dart | 22 ++++-- cw_core/lib/monero_wallet_utils.dart | 19 ++++- cw_core/lib/wallet_service.dart | 23 +++++- cw_ethereum/lib/ethereum_wallet_service.dart | 32 ++++++-- cw_haven/lib/haven_wallet_service.dart | 1 + cw_monero/lib/monero_wallet.dart | 64 ++++++++++++--- cw_monero/lib/monero_wallet_service.dart | 77 +++++++++---------- cw_nano/lib/nano_wallet_service.dart | 32 ++++++-- cw_polygon/lib/polygon_wallet_service.dart | 32 ++++++-- 12 files changed, 264 insertions(+), 117 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index 3a97e0682..736ec1044 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -12,10 +12,8 @@ import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; import 'package:collection/collection.dart'; -class BitcoinWalletService extends WalletService< - BitcoinNewWalletCredentials, - BitcoinRestoreWalletFromSeedCredentials, - BitcoinRestoreWalletFromWIFCredentials> { +class BitcoinWalletService extends WalletService { BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); final Box walletInfoSource; @@ -42,28 +40,41 @@ class BitcoinWalletService extends WalletService< @override Future openWallet(String name, String password) async { - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(name, getType()))!; - final wallet = await BitcoinWalletBase.open( - password: password, name: name, walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfoSource); - await wallet.init(); - return wallet; + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!; + try { + final wallet = await BitcoinWalletBase.open( + password: password, + name: name, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.init(); + saveBackup(name); + return wallet; + } catch (_) { + await restoreWalletFilesFromBackup(name); + final wallet = await BitcoinWalletBase.open( + password: password, + name: name, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.init(); + return wallet; + } } @override Future remove(String wallet) async { - File(await pathForWalletDir(name: wallet, type: getType())) - .delete(recursive: true); - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(wallet, getType()))!; + File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true); + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; await walletInfoSource.delete(walletInfo.key); } @override Future rename(String currentName, String password, String newName) async { - final currentWalletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(currentName, getType()))!; + final currentWalletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!; final currentWallet = await BitcoinWalletBase.open( password: password, name: currentName, @@ -71,6 +82,7 @@ class BitcoinWalletService extends WalletService< unspentCoinsInfo: unspentCoinsInfoSource); await currentWallet.renameWalletFiles(newName); + await saveBackup(newName); final newWalletInfo = currentWalletInfo; newWalletInfo.id = WalletBase.idFor(newName, getType()); @@ -80,13 +92,11 @@ class BitcoinWalletService extends WalletService< } @override - Future restoreFromKeys( - BitcoinRestoreWalletFromWIFCredentials credentials) async => + Future restoreFromKeys(BitcoinRestoreWalletFromWIFCredentials credentials) async => throw UnimplementedError(); @override - Future restoreFromSeed( - BitcoinRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinMnemonicIsIncorrectException(); } @@ -100,4 +110,4 @@ class BitcoinWalletService extends WalletService< await wallet.init(); return wallet; } -} \ No newline at end of file +} diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 6be525a1f..8a41c1733 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -601,8 +601,6 @@ abstract class ElectrumWalletBase electrumClient.getHistory(scriptHash).then((history) => {scriptHash: history})); final historyResults = await Future.wait(histories); - - historyResults.forEach((history) { history.entries.forEach((historyItem) { if (historyItem.value.isNotEmpty) { @@ -622,7 +620,6 @@ abstract class ElectrumWalletBase } } - addressHashes.forEach((sh, addressRecord) { addressRecord.txCount = newTxCounts[sh] ?? 0; }); diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index b13ac7a7f..69d1dfc7e 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -45,11 +45,22 @@ class LitecoinWalletService extends WalletService< Future openWallet(String name, String password) async { final walletInfo = walletInfoSource.values.firstWhereOrNull( (info) => info.id == WalletBase.idFor(name, getType()))!; - final wallet = await LitecoinWalletBase.open( - password: password, name: name, walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfoSource); - await wallet.init(); - return wallet; + + try { + final wallet = await LitecoinWalletBase.open( + password: password, name: name, walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.init(); + saveBackup(name); + return wallet; + } catch (_) { + await restoreWalletFilesFromBackup(name); + final wallet = await LitecoinWalletBase.open( + password: password, name: name, walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.init(); + return wallet; + } } @override @@ -72,6 +83,7 @@ class LitecoinWalletService extends WalletService< unspentCoinsInfo: unspentCoinsInfoSource); await currentWallet.renameWalletFiles(newName); + await saveBackup(newName); final newWalletInfo = currentWalletInfo; newWalletInfo.id = WalletBase.idFor(newName, getType()); diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart index 8cc469a3a..f66e38ca7 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart @@ -51,11 +51,22 @@ class BitcoinCashWalletService extends WalletService openWallet(String name, String password) async { final walletInfo = walletInfoSource.values.firstWhereOrNull( (info) => info.id == WalletBase.idFor(name, getType()))!; - final wallet = await BitcoinCashWalletBase.open( - password: password, name: name, walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfoSource); - await wallet.init(); - return wallet; + + try { + final wallet = await BitcoinCashWalletBase.open( + password: password, name: name, walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.init(); + saveBackup(name); + return wallet; + } catch(_) { + await restoreWalletFilesFromBackup(name); + final wallet = await BitcoinCashWalletBase.open( + password: password, name: name, walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.init(); + return wallet; + } } @override @@ -78,6 +89,7 @@ class BitcoinCashWalletService extends WalletService restoreWalletFiles(String name) async { } } +Future resetCache(String name) async { + await removeCache(name); + + final walletDirPath = await pathForWalletDir(name: name, type: WalletType.monero); + final cacheFilePath = '$walletDirPath/$name'; + final backupCacheFile = File(backupFileName(cacheFilePath)); + if (backupCacheFile.existsSync()) { + await backupCacheFile.copy(cacheFilePath); + } +} + Future backupWalletFilesExists(String name) async { final walletDirPath = await pathForWalletDir(name: name, type: WalletType.monero); final cacheFilePath = '$walletDirPath/$name'; @@ -63,9 +74,9 @@ Future backupWalletFilesExists(String name) async { final backupKeysFile = File(backupFileName(keysFilePath)); final backupAddressListFile = File(backupFileName(addressListFilePath)); - return backupCacheFile.existsSync() - && backupKeysFile.existsSync() - && backupAddressListFile.existsSync(); + return backupCacheFile.existsSync() && + backupKeysFile.existsSync() && + backupAddressListFile.existsSync(); } Future removeCache(String name) async { @@ -85,4 +96,4 @@ Future restoreOrResetWalletFiles(String name) async { } removeCache(name); -} \ No newline at end of file +} diff --git a/cw_core/lib/wallet_service.dart b/cw_core/lib/wallet_service.dart index f6d0ca192..3b4908386 100644 --- a/cw_core/lib/wallet_service.dart +++ b/cw_core/lib/wallet_service.dart @@ -1,7 +1,8 @@ -import 'package:cw_core/node.dart'; +import 'dart:io'; + +import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; -import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; abstract class WalletService remove(String wallet); Future rename(String currentName, String password, String newName); + + Future restoreWalletFilesFromBackup(String name) async { + final backupWalletDirPath = await pathForWalletDir(name: "$name.backup", type: getType()); + final walletDirPath = await pathForWalletDir(name: name, type: getType()); + + if (File(backupWalletDirPath).existsSync()) { + await File(backupWalletDirPath).copy(walletDirPath); + } + } + + Future saveBackup(String name) async { + final backupWalletDirPath = await pathForWalletDir(name: "$name.backup", type: getType()); + final walletDirPath = await pathForWalletDir(name: name, type: getType()); + + if (File(walletDirPath).existsSync()) { + await File(walletDirPath).copy(backupWalletDirPath); + } + } } diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index 1cd776867..5e8c22718 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -39,16 +39,31 @@ class EthereumWalletService extends EVMChainWalletService { Future openWallet(String name, String password) async { final walletInfo = walletInfoSource.values.firstWhere((info) => info.id == WalletBase.idFor(name, getType())); - final wallet = await EthereumWallet.open( - name: name, - password: password, - walletInfo: walletInfo, - ); - await wallet.init(); - await wallet.save(); + try { + final wallet = await EthereumWallet.open( + name: name, + password: password, + walletInfo: walletInfo, + ); - return wallet; + await wallet.init(); + await wallet.save(); + saveBackup(name); + return wallet; + } catch (_) { + + await restoreWalletFilesFromBackup(name); + + final wallet = await EthereumWallet.open( + name: name, + password: password, + walletInfo: walletInfo, + ); + await wallet.init(); + await wallet.save(); + return wallet; + } } @override @@ -59,6 +74,7 @@ class EthereumWalletService extends EVMChainWalletService { password: password, name: currentName, walletInfo: currentWalletInfo); await currentWallet.renameWalletFiles(newName); + await saveBackup(newName); final newWalletInfo = currentWalletInfo; newWalletInfo.id = WalletBase.idFor(newName, getType()); diff --git a/cw_haven/lib/haven_wallet_service.dart b/cw_haven/lib/haven_wallet_service.dart index 0bc20d2a0..dd7713e08 100644 --- a/cw_haven/lib/haven_wallet_service.dart +++ b/cw_haven/lib/haven_wallet_service.dart @@ -163,6 +163,7 @@ class HavenWalletService extends WalletService< final currentWallet = HavenWallet(walletInfo: currentWalletInfo); await currentWallet.renameWalletFiles(newName); + await saveBackup(newName); final newWalletInfo = currentWalletInfo; newWalletInfo.id = WalletBase.idFor(newName, getType()); diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 4b71fb5ff..1a34e4bd6 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -36,6 +36,8 @@ import 'package:mobx/mobx.dart'; part 'monero_wallet.g.dart'; const moneroBlockSize = 1000; +// not sure if this should just be 0 but setting it higher feels safer / should catch more cases: +const MIN_RESTORE_HEIGHT = 1000; class MoneroWallet = MoneroWalletBase with _$MoneroWallet; @@ -79,7 +81,7 @@ abstract class MoneroWalletBase Box unspentCoinsInfo; - void Function(FlutterErrorDetails)? _onError; + void Function(FlutterErrorDetails)? onError; @override late MoneroWalletAddresses walletAddresses; @@ -171,7 +173,26 @@ abstract class MoneroWalletBase Future startSync() async { try { _setInitialHeight(); - } catch (_) {} + } catch (_) { + // our restore height wasn't correct, so lets see if using the backup works: + try { + await resetCache(name); + _setInitialHeight(); + } catch (e) { + // we still couldn't get a valid height from the backup?!: + // try to use the date instead: + try { + _setHeightFromDate(); + } catch (e, s) { + // we still couldn't get a valid sync height :/ + onError?.call(FlutterErrorDetails( + exception: e, + stack: s, + library: this.runtimeType.toString(), + )); + } + } + } try { syncStatus = AttemptingSyncStatus(); @@ -339,6 +360,8 @@ abstract class MoneroWalletBase if (currentAddressListFile.existsSync()) { await currentAddressListFile.rename('$newWalletPath.address.txt'); } + + await backupWalletFiles(newWalletName); } catch (e) { final currentWalletPath = await pathForWallet(name: name, type: type); @@ -402,9 +425,7 @@ abstract class MoneroWalletBase if (coin.spent == 0) { final unspent = MoneroUnspent.fromCoinsInfoRow(coin); if (unspent.hash.isNotEmpty) { - unspent.isChange = transaction_history - .getTransaction(unspent.hash) - .direction == 1; + unspent.isChange = transaction_history.getTransaction(unspent.hash).direction == 1; } unspentCoins.add(unspent); } @@ -418,7 +439,7 @@ abstract class MoneroWalletBase if (unspentCoins.isNotEmpty) { unspentCoins.forEach((coin) { final coinInfoList = unspentCoinsInfo.values.where((element) => - element.walletId.contains(id) && + element.walletId.contains(id) && element.accountIndex == walletAddresses.account!.id && element.keyImage!.contains(coin.keyImage!)); @@ -438,7 +459,7 @@ abstract class MoneroWalletBase _askForUpdateBalance(); } catch (e, s) { print(e.toString()); - _onError?.call(FlutterErrorDetails( + onError?.call(FlutterErrorDetails( exception: e, stack: s, library: this.runtimeType.toString(), @@ -534,18 +555,36 @@ abstract class MoneroWalletBase _listener = monero_wallet.setListeners(_onNewBlock, _onNewTransaction); } + // check if the height is correct: void _setInitialHeight() { if (walletInfo.isRecovery) { return; } - final currentHeight = monero_wallet.getCurrentHeight(); + final height = monero_wallet.getCurrentHeight(); - if (currentHeight <= 1) { - final height = _getHeightByDate(walletInfo.date); + if (height > MIN_RESTORE_HEIGHT) { + // the restore height is probably correct, so we do nothing: + return; + } + + throw Exception("height isn't > $MIN_RESTORE_HEIGHT!"); + } + + void _setHeightFromDate() { + if (walletInfo.isRecovery) { + return; + } + + final height = _getHeightByDate(walletInfo.date); + + if (height > MIN_RESTORE_HEIGHT) { monero_wallet.setRecoveringFromSeed(isRecovery: true); monero_wallet.setRefreshFromBlockHeight(height: height); + return; } + + throw Exception("height isn't > $MIN_RESTORE_HEIGHT!"); } int _getHeightDistance(DateTime date) { @@ -561,7 +600,8 @@ abstract class MoneroWalletBase final heightDistance = _getHeightDistance(date); if (nodeHeight <= 0) { - return 0; + // the node returned 0 (an error state), so lets just restore from cache: + throw Exception("nodeHeight is <= 0!"); } return nodeHeight - heightDistance; @@ -650,7 +690,7 @@ abstract class MoneroWalletBase } @override - void setExceptionHandler(void Function(FlutterErrorDetails) onError) => _onError = onError; + void setExceptionHandler(void Function(FlutterErrorDetails) e) => onError = e; @override String signMessage(String message, {String? address}) { diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 9b9e254d0..3dea7fc0e 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -11,11 +11,13 @@ import 'package:cw_core/get_height_by_date.dart'; import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart'; import 'package:cw_monero/api/wallet_manager.dart' as monero_wallet_manager; import 'package:cw_monero/monero_wallet.dart'; +import 'package:flutter/widgets.dart'; import 'package:hive/hive.dart'; import 'package:polyseed/polyseed.dart'; class MoneroNewWalletCredentials extends WalletCredentials { - MoneroNewWalletCredentials({required String name, required this.language, required this.isPolyseed, String? password}) + MoneroNewWalletCredentials( + {required String name, required this.language, required this.isPolyseed, String? password}) : super(name: name, password: password); final String language; @@ -52,10 +54,8 @@ class MoneroRestoreWalletFromKeysCredentials extends WalletCredentials { final String spendKey; } -class MoneroWalletService extends WalletService< - MoneroNewWalletCredentials, - MoneroRestoreWalletFromSeedCredentials, - MoneroRestoreWalletFromKeysCredentials> { +class MoneroWalletService extends WalletService { MoneroWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); final Box walletInfoSource; @@ -112,6 +112,7 @@ class MoneroWalletService extends WalletService< @override Future openWallet(String name, String password) async { + MoneroWallet? wallet; try { final path = await pathForWallet(name: name, type: getType()); @@ -119,11 +120,10 @@ class MoneroWalletService extends WalletService< 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 wallet = MoneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); + await monero_wallet_manager.openWalletAsync({'path': path, 'password': password}); + final walletInfo = walletInfoSource.values + .firstWhere((info) => info.id == WalletBase.idFor(name, getType())); + wallet = MoneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); final isValid = wallet.walletAddresses.validate(); if (!isValid) { @@ -135,7 +135,7 @@ class MoneroWalletService extends WalletService< await wallet.init(); return wallet; - } catch (e) { + } catch (e, s) { // TODO: Implement Exception for wallet list service. final bool isBadAlloc = e.toString().contains('bad_alloc') || @@ -156,16 +156,18 @@ class MoneroWalletService extends WalletService< final bool invalidSignature = e.toString().contains('invalid signature') || (e is WalletOpeningException && e.message.contains('invalid signature')); - if (isBadAlloc || - doesNotCorrespond || - isMissingCacheFilesIOS || - isMissingCacheFilesAndroid || - invalidSignature) { - await restoreOrResetWalletFiles(name); - return openWallet(name, password); + if (!isBadAlloc && + !doesNotCorrespond && + !isMissingCacheFilesIOS && + !isMissingCacheFilesAndroid && + !invalidSignature && + wallet != null && + wallet.onError != null) { + wallet.onError!(FlutterErrorDetails(exception: e, stack: s)); } - rethrow; + await restoreOrResetWalletFiles(name); + return openWallet(name, password); } } @@ -185,10 +187,9 @@ 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())); + Future rename(String currentName, String password, String newName) async { + final currentWalletInfo = walletInfoSource.values + .firstWhere((info) => info.id == WalletBase.idFor(currentName, getType())); final currentWallet = MoneroWallet(walletInfo: currentWalletInfo, unspentCoinsInfo: unspentCoinsInfoSource); @@ -202,8 +203,7 @@ class MoneroWalletService extends WalletService< } @override - Future restoreFromKeys( - MoneroRestoreWalletFromKeysCredentials credentials) async { + Future restoreFromKeys(MoneroRestoreWalletFromKeysCredentials credentials) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await monero_wallet_manager.restoreFromKeys( @@ -227,9 +227,7 @@ class MoneroWalletService extends WalletService< } @override - Future restoreFromSeed( - MoneroRestoreWalletFromSeedCredentials credentials) async { - + Future restoreFromSeed(MoneroRestoreWalletFromSeedCredentials credentials) async { // Restore from Polyseed if (Polyseed.isValidSeed(credentials.mnemonic)) { return restoreFromPolyseed(credentials); @@ -254,14 +252,16 @@ class MoneroWalletService extends WalletService< } } - Future restoreFromPolyseed(MoneroRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromPolyseed( + MoneroRestoreWalletFromSeedCredentials credentials) async { try { 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); - return _restoreFromPolyseed(path, credentials.password!, polyseed, credentials.walletInfo!, lang); + return _restoreFromPolyseed( + path, credentials.password!, polyseed, credentials.walletInfo!, lang); } catch (e) { // TODO: Implement Exception for wallet list service. print('MoneroWalletsManager Error: $e'); @@ -269,11 +269,11 @@ class MoneroWalletService extends WalletService< } } - Future _restoreFromPolyseed(String path, String password, Polyseed polyseed, - WalletInfo walletInfo, PolyseedLang lang, + Future _restoreFromPolyseed( + String path, String password, Polyseed polyseed, WalletInfo walletInfo, PolyseedLang lang, {PolyseedCoin coin = PolyseedCoin.POLYSEED_MONERO, int? overrideHeight}) async { - final height = overrideHeight ?? getMoneroHeigthByDate( - date: DateTime.fromMillisecondsSinceEpoch(polyseed.birthday * 1000)); + final height = overrideHeight ?? + getMoneroHeigthByDate(date: DateTime.fromMillisecondsSinceEpoch(polyseed.birthday * 1000)); final spendKey = polyseed.generateKey(coin, 32).toHexString(); final seed = polyseed.encode(lang, coin); @@ -288,8 +288,7 @@ class MoneroWalletService extends WalletService< restoreHeight: height, spendKey: spendKey); - final wallet = MoneroWallet( - walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); + final wallet = MoneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); return wallet; @@ -301,16 +300,14 @@ class MoneroWalletService extends WalletService< return; } - final oldAndroidWalletDirPath = - await outdatedAndroidPathForWalletDir(name: name); + final oldAndroidWalletDirPath = await outdatedAndroidPathForWalletDir(name: name); final dir = Directory(oldAndroidWalletDirPath); if (!dir.existsSync()) { return; } - final newWalletDirPath = - await pathForWalletDir(name: name, type: getType()); + final newWalletDirPath = await pathForWalletDir(name: name, type: getType()); dir.listSync().forEach((f) { final file = File(f.path); diff --git a/cw_nano/lib/nano_wallet_service.dart b/cw_nano/lib/nano_wallet_service.dart index 7a66f8c9f..a76f0393d 100644 --- a/cw_nano/lib/nano_wallet_service.dart +++ b/cw_nano/lib/nano_wallet_service.dart @@ -69,6 +69,7 @@ class NanoWalletService extends WalletService openWallet(String name, String password) async { final walletInfo = walletInfoSource.values.firstWhere((info) => info.id == WalletBase.idFor(name, getType())); - final wallet = await NanoWalletBase.open( - name: name, - password: password, - walletInfo: walletInfo, - ); - await wallet.init(); - await wallet.save(); - return wallet; + try { + final wallet = await NanoWalletBase.open( + name: name, + password: password, + walletInfo: walletInfo, + ); + + await wallet.init(); + await wallet.save(); + saveBackup(name); + return wallet; + } catch (_) { + await restoreWalletFilesFromBackup(name); + final wallet = await NanoWalletBase.open( + name: name, + password: password, + walletInfo: walletInfo, + ); + + await wallet.init(); + await wallet.save(); + return wallet; + } } } diff --git a/cw_polygon/lib/polygon_wallet_service.dart b/cw_polygon/lib/polygon_wallet_service.dart index 451dc7288..0199a1552 100644 --- a/cw_polygon/lib/polygon_wallet_service.dart +++ b/cw_polygon/lib/polygon_wallet_service.dart @@ -42,16 +42,31 @@ class PolygonWalletService extends EVMChainWalletService { Future openWallet(String name, String password) async { final walletInfo = walletInfoSource.values.firstWhere((info) => info.id == WalletBase.idFor(name, getType())); - final wallet = await PolygonWallet.open( - name: name, - password: password, - walletInfo: walletInfo, - ); - await wallet.init(); - await wallet.save(); + try { + final wallet = await PolygonWallet.open( + name: name, + password: password, + walletInfo: walletInfo, + ); - return wallet; + await wallet.init(); + await wallet.save(); + saveBackup(name); + return wallet; + } catch (_) { + await restoreWalletFilesFromBackup(name); + + final wallet = await PolygonWallet.open( + name: name, + password: password, + walletInfo: walletInfo, + ); + + await wallet.init(); + await wallet.save(); + return wallet; + } } @override @@ -100,6 +115,7 @@ class PolygonWalletService extends EVMChainWalletService { password: password, name: currentName, walletInfo: currentWalletInfo); await currentWallet.renameWalletFiles(newName); + await saveBackup(newName); final newWalletInfo = currentWalletInfo; newWalletInfo.id = WalletBase.idFor(newName, getType()); From 0832e62719bbf413985c8df0e6e644548730a10a Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 8 Feb 2024 00:10:44 +0200 Subject: [PATCH 113/241] fix generate new electrum address (#1294) * add side address validation * Remove auto size text [skip ci] --------- Co-authored-by: OmarHatem --- cw_bitcoin/lib/bitcoin_address_record.dart | 2 +- cw_bitcoin/lib/electrum_wallet_addresses.dart | 15 ++++++++++++++- lib/bitcoin/cw_bitcoin.dart | 2 +- lib/src/screens/receive/widgets/qr_widget.dart | 5 +---- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_address_record.dart b/cw_bitcoin/lib/bitcoin_address_record.dart index f2cd63904..676edb4a5 100644 --- a/cw_bitcoin/lib/bitcoin_address_record.dart +++ b/cw_bitcoin/lib/bitcoin_address_record.dart @@ -28,7 +28,7 @@ class BitcoinAddressRecord { } final String address; - final bool isHidden; + bool isHidden; final int index; int _txCount; int _balance; diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index a60a7e8ec..850d58f40 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -53,7 +53,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { String get address { if (isEnabledAutoGenerateSubaddress) { if (receiveAddresses.isEmpty) { - final newAddress = generateNewAddress().address; + final newAddress = generateNewAddress(hd: mainHd).address; return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(newAddress) : newAddress; } final receiveAddress = receiveAddresses.first.address; @@ -215,6 +215,13 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { List addrs; if (addresses.isNotEmpty) { + + + if(!isHidden) { + final receiveAddressesList = addresses.where((addr) => !addr.isHidden).toList(); + validateSideHdAddresses(receiveAddressesList); + } + addrs = addresses.where((addr) => addr.isHidden == isHidden).toList(); } else { addrs = await _createNewAddresses( @@ -296,4 +303,10 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { final transactionHistory = await electrumClient.getHistory(sh); return transactionHistory.isNotEmpty; } + + void validateSideHdAddresses(List addrWithTransactions) { + addrWithTransactions.forEach((element) { + if (element.address != getAddress(index: element.index, hd: mainHd)) element.isHidden = true; + }); + } } diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 6836cc4dc..688825013 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -65,7 +65,7 @@ class CWBitcoin extends Bitcoin { @override Future generateNewAddress(Object wallet, String label) async { final bitcoinWallet = wallet as ElectrumWallet; - await bitcoinWallet.walletAddresses.generateNewAddress(label: label); + await bitcoinWallet.walletAddresses.generateNewAddress(label: label, hd: bitcoinWallet.hd); await wallet.save(); } diff --git a/lib/src/screens/receive/widgets/qr_widget.dart b/lib/src/screens/receive/widgets/qr_widget.dart index bedb3b526..bbfd4d5c1 100644 --- a/lib/src/screens/receive/widgets/qr_widget.dart +++ b/lib/src/screens/receive/widgets/qr_widget.dart @@ -1,4 +1,3 @@ -import 'package:auto_size_text/auto_size_text.dart'; import 'package:cake_wallet/entities/qr_view_data.dart'; import 'package:cake_wallet/themes/extensions/qr_code_theme.dart'; import 'package:cake_wallet/routes.dart'; @@ -7,7 +6,6 @@ import 'package:cake_wallet/src/screens/receive/widgets/currency_input_field.dar import 'package:cake_wallet/utils/brightness_util.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -146,10 +144,9 @@ class QRWidget extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( - child: AutoSizeText( + child: Text( addressListViewModel.address.address, textAlign: TextAlign.center, - maxLines: addressListViewModel.wallet.type == WalletType.monero ? 2 : 1, style: TextStyle( fontSize: 15, fontWeight: FontWeight.w500, From d6e10bdbd57561f51ba33be9741bdee1ba1319ca Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Fri, 9 Feb 2024 00:11:41 +0100 Subject: [PATCH 114/241] CW-572-Disable-battery-optimization (#1285) * feat: Disable battery optimization on android * fix: Add permission to androidmanifestbase file * Increase the frequency of app running in background on aggressive mode * Revert the sync mode frequency [skip ci] * Fix translation * increase frequency to 1 hour --------- Co-authored-by: OmarHatem --- android/app/src/main/AndroidManifestBase.xml | 1 + .../cakewallet/cake_wallet/MainActivity.java | 30 ++++++++++++++ .../com/cakewallet/haven/MainActivity.java | 30 ++++++++++++++ .../java/com/monero/app/MainActivity.java | 30 ++++++++++++++ cw_core/lib/battery_optimization_native.dart | 22 ++++++++++ .../settings/connection_sync_page.dart | 41 +++++++++++++++---- lib/view_model/settings/sync_mode.dart | 2 +- 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_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_yo.arb | 2 + res/values/strings_zh.arb | 2 + 33 files changed, 200 insertions(+), 8 deletions(-) create mode 100644 cw_core/lib/battery_optimization_native.dart diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index 2dceca577..180190914 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -8,6 +8,7 @@ + result.success(null)); + break; + case "isBatteryOptimizationDisabled": + boolean isDisabled = isBatteryOptimizationDisabled(); + handler.post(() -> result.success(isDisabled)); + break; default: handler.post(() -> result.notImplemented()); } @@ -89,4 +101,22 @@ public class MainActivity extends FlutterFragmentActivity { } }); } + + private void disableBatteryOptimization() { + String packageName = getPackageName(); + PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); + if (!pm.isIgnoringBatteryOptimizations(packageName)) { + Intent intent = new Intent(); + intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); + intent.setData(Uri.parse("package:" + packageName)); + startActivity(intent); + } + } + + private boolean isBatteryOptimizationDisabled() { + String packageName = getPackageName(); + PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); + return pm.isIgnoringBatteryOptimizations(packageName); + } + } \ No newline at end of file diff --git a/android/app/src/main/java/com/cakewallet/haven/MainActivity.java b/android/app/src/main/java/com/cakewallet/haven/MainActivity.java index 8c13d1f8d..d0a465d22 100644 --- a/android/app/src/main/java/com/cakewallet/haven/MainActivity.java +++ b/android/app/src/main/java/com/cakewallet/haven/MainActivity.java @@ -14,6 +14,10 @@ import android.os.Build; import android.os.Handler; import android.os.Looper; import android.view.WindowManager; +import android.content.Intent; +import android.net.Uri; +import android.os.PowerManager; +import android.provider.Settings; import com.unstoppabledomains.resolution.DomainResolution; import com.unstoppabledomains.resolution.Resolution; @@ -55,6 +59,14 @@ public class MainActivity extends FlutterFragmentActivity { handler.post(() -> result.success("")); } break; + case "disableBatteryOptimization": + disableBatteryOptimization(); + handler.post(() -> result.success(null)); + break; + case "isBatteryOptimizationDisabled": + boolean isDisabled = isBatteryOptimizationDisabled(); + handler.post(() -> result.success(isDisabled)); + break; default: handler.post(() -> result.notImplemented()); } @@ -79,4 +91,22 @@ public class MainActivity extends FlutterFragmentActivity { } }); } + + private void disableBatteryOptimization() { + String packageName = getPackageName(); + PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); + if (!pm.isIgnoringBatteryOptimizations(packageName)) { + Intent intent = new Intent(); + intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); + intent.setData(Uri.parse("package:" + packageName)); + startActivity(intent); + } + } + + private boolean isBatteryOptimizationDisabled() { + String packageName = getPackageName(); + PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); + return pm.isIgnoringBatteryOptimizations(packageName); + } + } \ No newline at end of file diff --git a/android/app/src/main/java/com/monero/app/MainActivity.java b/android/app/src/main/java/com/monero/app/MainActivity.java index 73914c43c..49c368ec7 100644 --- a/android/app/src/main/java/com/monero/app/MainActivity.java +++ b/android/app/src/main/java/com/monero/app/MainActivity.java @@ -14,6 +14,10 @@ import android.os.Build; import android.os.Handler; import android.os.Looper; import android.view.WindowManager; +import android.content.Intent; +import android.net.Uri; +import android.os.PowerManager; +import android.provider.Settings; import com.unstoppabledomains.resolution.DomainResolution; import com.unstoppabledomains.resolution.Resolution; @@ -64,6 +68,14 @@ public class MainActivity extends FlutterFragmentActivity { getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE); } break; + case "disableBatteryOptimization": + disableBatteryOptimization(); + handler.post(() -> result.success(null)); + break; + case "isBatteryOptimizationDisabled": + boolean isDisabled = isBatteryOptimizationDisabled(); + handler.post(() -> result.success(isDisabled)); + break; default: handler.post(() -> result.notImplemented()); } @@ -88,4 +100,22 @@ public class MainActivity extends FlutterFragmentActivity { } }); } + + private void disableBatteryOptimization() { + String packageName = getPackageName(); + PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); + if (!pm.isIgnoringBatteryOptimizations(packageName)) { + Intent intent = new Intent(); + intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); + intent.setData(Uri.parse("package:" + packageName)); + startActivity(intent); + } + } + + private boolean isBatteryOptimizationDisabled() { + String packageName = getPackageName(); + PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); + return pm.isIgnoringBatteryOptimizations(packageName); + } + } \ No newline at end of file diff --git a/cw_core/lib/battery_optimization_native.dart b/cw_core/lib/battery_optimization_native.dart new file mode 100644 index 000000000..edd04d3f4 --- /dev/null +++ b/cw_core/lib/battery_optimization_native.dart @@ -0,0 +1,22 @@ +import 'package:flutter/services.dart'; + +const MethodChannel _channel = MethodChannel('com.cake_wallet/native_utils'); + +Future requestDisableBatteryOptimization() async { + try { + await _channel.invokeMethod('disableBatteryOptimization'); + } on PlatformException catch (e) { + print("Failed to disable battery optimization: '${e.message}'."); + } +} + +Future isBatteryOptimizationDisabled() async { + try { + final bool isDisabled = await _channel.invokeMethod('isBatteryOptimizationDisabled') as bool; + print('It\'s actually disabled? $isDisabled'); + return isDisabled; + } on PlatformException catch (e) { + print("Failed to check battery optimization status: '${e.message}'."); + return false; + } +} diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart index bec2e6296..45d44d443 100644 --- a/lib/src/screens/settings/connection_sync_page.dart +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:cake_wallet/reactions/wallet_connect.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'; @@ -8,6 +10,7 @@ import 'package:cake_wallet/utils/feature_flag.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/settings/sync_mode.dart'; +import 'package:cw_core/battery_optimization_native.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -45,12 +48,37 @@ class ConnectionSyncPage extends BasePage { if (DeviceInfo.instance.isMobile) ...[ Observer(builder: (context) { return SettingsPickerCell( - title: S.current.background_sync_mode, - items: SyncMode.all, - displayItem: (SyncMode syncMode) => syncMode.name, - selectedItem: dashboardViewModel.syncMode, - onItemSelected: dashboardViewModel.setSyncMode, - ); + title: S.current.background_sync_mode, + items: SyncMode.all, + displayItem: (SyncMode syncMode) => syncMode.name, + selectedItem: dashboardViewModel.syncMode, + onItemSelected: (syncMode) async { + dashboardViewModel.setSyncMode(syncMode); + + if (syncMode.type != SyncType.disabled) { + final isDisabled = await isBatteryOptimizationDisabled(); + + if (isDisabled || Platform.isIOS) return; + + await showPopUp( + context: context, + builder: (BuildContext dialogContext) { + return AlertWithTwoActions( + alertTitle: S.current.disableBatteryOptimization, + alertContent: S.current.disableBatteryOptimizationDescription, + leftButtonText: S.of(context).cancel, + rightButtonText: S.of(context).ok, + actionLeftButton: () => Navigator.of(dialogContext).pop(), + actionRightButton: () async { + await requestDisableBatteryOptimization(); + + Navigator.of(dialogContext).pop(); + }, + ); + }, + ); + } + }); }), const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), Observer(builder: (context) { @@ -99,7 +127,6 @@ class ConnectionSyncPage extends BasePage { ); } - Future _presentReconnectAlert(BuildContext context) async { await showPopUp( context: context, diff --git a/lib/view_model/settings/sync_mode.dart b/lib/view_model/settings/sync_mode.dart index 1153e2f32..37e400acb 100644 --- a/lib/view_model/settings/sync_mode.dart +++ b/lib/view_model/settings/sync_mode.dart @@ -10,6 +10,6 @@ class SyncMode { static final all = [ SyncMode("Disabled", SyncType.disabled, Duration.zero), SyncMode("Unobtrusive", SyncType.unobtrusive, Duration(days: 1)), - SyncMode("Aggressive", SyncType.aggressive, Duration(hours: 6)), + SyncMode("Aggressive", SyncType.aggressive, Duration(hours: 1)), ]; } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 8ad38bc83..553262f79 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -189,6 +189,8 @@ "disable_exchange": "تعطيل التبادل", "disable_fiat": "تعطيل fiat", "disable_sell": "قم بتعطيل إجراء البيع", + "disableBatteryOptimization": "تعطيل تحسين البطارية", + "disableBatteryOptimizationDescription": "هل تريد تعطيل تحسين البطارية من أجل جعل الخلفية مزامنة تعمل بحرية وسلاسة؟", "disabled": "معطلة", "discount": "وفر ${value}٪", "display_settings": "اعدادات العرض", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 1190a53ce..8d89f463b 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -189,6 +189,8 @@ "disable_exchange": "Деактивиране на борса", "disable_fiat": "Деактивиране на fiat", "disable_sell": "Деактивирайте действието за продажба", + "disableBatteryOptimization": "Деактивирайте оптимизацията на батерията", + "disableBatteryOptimizationDescription": "Искате ли да деактивирате оптимизацията на батерията, за да направите синхронизирането на фона да работи по -свободно и гладко?", "disabled": "Деактивирано", "discount": "Спестете ${value}%", "display_settings": "Настройки на екрана", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index db6d2103c..e81eab570 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -189,6 +189,8 @@ "disable_exchange": "Zakázat směnárny", "disable_fiat": "Zakázat fiat", "disable_sell": "Zakázat akci prodeje", + "disableBatteryOptimization": "Zakázat optimalizaci baterie", + "disableBatteryOptimizationDescription": "Chcete deaktivovat optimalizaci baterie, aby se synchronizovala pozadí volně a hladce?", "disabled": "Zakázáno", "discount": "Ušetříte ${value}%", "display_settings": "Nastavení zobrazení", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 46c8a3c13..3ca972af4 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -189,6 +189,8 @@ "disable_exchange": "Exchange deaktivieren", "disable_fiat": "Fiat deaktivieren", "disable_sell": "Verkaufsaktion deaktivieren", + "disableBatteryOptimization": "Batterieoptimierung deaktivieren", + "disableBatteryOptimizationDescription": "Möchten Sie die Batterieoptimierung deaktivieren, um die Hintergrundsynchronisierung freier und reibungsloser zu gestalten?", "disabled": "Deaktiviert", "discount": "${value} % sparen", "display_settings": "Anzeigeeinstellungen", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index a6ea6e39a..2db7602c1 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -189,6 +189,8 @@ "disable_exchange": "Disable exchange", "disable_fiat": "Disable fiat", "disable_sell": "Disable sell action", + "disableBatteryOptimization": "Disable Battery Optimization", + "disableBatteryOptimizationDescription": "Do you want to disable battery optimization in order to make background sync run more freely and smoothly?", "disabled": "Disabled", "discount": "Save ${value}%", "display_settings": "Display settings", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 9e719d812..5ca5ff4d3 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -189,6 +189,8 @@ "disable_exchange": "Deshabilitar intercambio", "disable_fiat": "Deshabilitar fiat", "disable_sell": "Desactivar acción de venta", + "disableBatteryOptimization": "Deshabilitar la optimización de la batería", + "disableBatteryOptimizationDescription": "¿Desea deshabilitar la optimización de la batería para que la sincronización de fondo se ejecute más libremente y sin problemas?", "disabled": "Desactivado", "discount": "Ahorra ${value}%", "display_settings": "Configuración de pantalla", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index b4c4d9eb6..aee967d21 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -189,6 +189,8 @@ "disable_exchange": "Désactiver l'échange", "disable_fiat": "Désactiver les montants en fiat", "disable_sell": "Désactiver l'action de vente", + "disableBatteryOptimization": "Désactiver l'optimisation de la batterie", + "disableBatteryOptimizationDescription": "Voulez-vous désactiver l'optimisation de la batterie afin de faire fonctionner la synchronisation d'arrière-plan plus librement et en douceur?", "disabled": "Désactivé", "discount": "Économisez ${value}%", "display_settings": "Paramètres d'affichage", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 06b212e94..dfffa8a8b 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -189,6 +189,8 @@ "disable_exchange": "Kashe musanya", "disable_fiat": "Dakatar da fiat", "disable_sell": "Kashe karbuwa", + "disableBatteryOptimization": "Kashe ingantawa baturi", + "disableBatteryOptimizationDescription": "Shin kana son kashe ingantawa baturi don yin setnc bankwali gudu da yar kyauta da kyau?", "disabled": "tsaya", "discount": "Ajiye ${value}%", "display_settings": "Nuni saituna", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index f553608f7..e67b00726 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -189,6 +189,8 @@ "disable_exchange": "एक्सचेंज अक्षम करें", "disable_fiat": "िएट को अक्षम करें", "disable_sell": "बेचने की कार्रवाई अक्षम करें", + "disableBatteryOptimization": "बैटरी अनुकूलन अक्षम करें", + "disableBatteryOptimizationDescription": "क्या आप बैकग्राउंड सिंक को अधिक स्वतंत्र और सुचारू रूप से चलाने के लिए बैटरी ऑप्टिमाइज़ेशन को अक्षम करना चाहते हैं?", "disabled": "अक्षम", "discount": "${value}% बचाएं", "display_settings": "प्रदर्शन सेटिंग्स", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index b388df74f..c2fee8420 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -189,6 +189,8 @@ "disable_exchange": "Onemogući exchange", "disable_fiat": "Isključi, fiat", "disable_sell": "Onemogući akciju prodaje", + "disableBatteryOptimization": "Onemogući optimizaciju baterije", + "disableBatteryOptimizationDescription": "Želite li onemogućiti optimizaciju baterije kako bi se pozadinska sinkronizacija radila slobodnije i glatko?", "disabled": "Onemogućeno", "discount": "Uštedite ${value}%", "display_settings": "Postavke zaslona", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 84cfd8a5d..28a7df3c9 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -189,6 +189,8 @@ "disable_exchange": "Nonaktifkan pertukaran", "disable_fiat": "Nonaktifkan fiat", "disable_sell": "Nonaktifkan aksi jual", + "disableBatteryOptimization": "Nonaktifkan optimasi baterai", + "disableBatteryOptimizationDescription": "Apakah Anda ingin menonaktifkan optimasi baterai untuk membuat sinkronisasi latar belakang berjalan lebih bebas dan lancar?", "disabled": "Dinonaktifkan", "discount": "Hemat ${value}%", "display_settings": "Pengaturan tampilan", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 33209fb34..42f0b8d86 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -190,6 +190,8 @@ "disable_exchange": "Disabilita scambio", "disable_fiat": "Disabilita fiat", "disable_sell": "Disabilita l'azione di vendita", + "disableBatteryOptimization": "Disabilita l'ottimizzazione della batteria", + "disableBatteryOptimizationDescription": "Vuoi disabilitare l'ottimizzazione della batteria per far funzionare la sincronizzazione in background più libera e senza intoppi?", "disabled": "Disabilitato", "discount": "Risparmia ${value}%", "display_settings": "Impostazioni di visualizzazione", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 3cb1f64f6..f4b014909 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -189,6 +189,8 @@ "disable_exchange": "交換を無効にする", "disable_fiat": "フィアットを無効にする", "disable_sell": "販売アクションを無効にする", + "disableBatteryOptimization": "バッテリーの最適化を無効にします", + "disableBatteryOptimizationDescription": "バックグラウンドシンクをより自由かつスムーズに実行するために、バッテリーの最適化を無効にしたいですか?", "disabled": "無効", "discount": "${value}%を節約", "display_settings": "表示設定", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 74afac094..7af7376ce 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -189,6 +189,8 @@ "disable_exchange": "교환 비활성화", "disable_fiat": "법정화폐 비활성화", "disable_sell": "판매 조치 비활성화", + "disableBatteryOptimization": "배터리 최적화를 비활성화합니다", + "disableBatteryOptimizationDescription": "백그라운드 동기화를보다 자유롭고 매끄럽게 실행하기 위해 배터리 최적화를 비활성화하고 싶습니까?", "disabled": "장애가 있는", "discount": "${value}% 절약", "display_settings": "디스플레이 설정", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 6109908c1..6cba70ab2 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -189,6 +189,8 @@ "disable_exchange": "လဲလှယ်မှုကို ပိတ်ပါ။", "disable_fiat": "Fiat ကိုပိတ်ပါ။", "disable_sell": "ရောင်းချခြင်းလုပ်ဆောင်ချက်ကို ပိတ်ပါ။", + "disableBatteryOptimization": "ဘက်ထရီ optimization ကိုပိတ်ပါ", + "disableBatteryOptimizationDescription": "နောက်ခံထပ်တူပြုခြင်းနှင့်ချောချောမွေ့မွေ့ပြုလုပ်နိုင်ရန်ဘက်ထရီ optimization ကိုသင်ပိတ်ထားလိုပါသလား။", "disabled": "မသန်စွမ်း", "discount": "${value}% ချွေတာ", "display_settings": "ပြသရန် ဆက်တင်များ", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 03090db7e..19451da27 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -189,6 +189,8 @@ "disable_exchange": "Uitwisseling uitschakelen", "disable_fiat": "Schakel Fiat uit", "disable_sell": "Verkoopactie uitschakelen", + "disableBatteryOptimization": "Schakel de batterijoptimalisatie uit", + "disableBatteryOptimizationDescription": "Wilt u de optimalisatie van de batterij uitschakelen om achtergrondsynchronisatie te laten werken, vrijer en soepeler?", "disabled": "Gehandicapt", "discount": "Bespaar ${value}%", "display_settings": "Weergave-instellingen", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index bafb9f151..74aafd014 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -189,6 +189,8 @@ "disable_exchange": "Wyłącz wymianę", "disable_fiat": "Wyłącz waluty FIAT", "disable_sell": "Wyłącz akcję sprzedaży", + "disableBatteryOptimization": "Wyłącz optymalizację baterii", + "disableBatteryOptimizationDescription": "Czy chcesz wyłączyć optymalizację baterii, aby synchronizacja tła działała swobodniej i płynnie?", "disabled": "Wyłączone", "discount": "Zaoszczędź ${value}%", "display_settings": "Ustawienia wyświetlania", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 694a2be92..53d93fe75 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -189,6 +189,8 @@ "disable_exchange": "Desativar troca", "disable_fiat": "Desativar fiat", "disable_sell": "Desativar ação de venda", + "disableBatteryOptimization": "Desative a otimização da bateria", + "disableBatteryOptimizationDescription": "Deseja desativar a otimização da bateria para fazer a sincronização de fundo funcionar de forma mais livre e suave?", "disabled": "Desabilitado", "discount": "Economize ${value}%", "display_settings": "Configurações de exibição", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 480f3ea68..89a25db06 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -189,6 +189,8 @@ "disable_exchange": "Отключить обмен", "disable_fiat": "Отключить фиат", "disable_sell": "Отключить действие продажи", + "disableBatteryOptimization": "Отключить оптимизацию батареи", + "disableBatteryOptimizationDescription": "Вы хотите отключить оптимизацию батареи, чтобы сделать фона синхронизации более свободно и плавно?", "disabled": "Отключено", "discount": "Сэкономьте ${value}%", "display_settings": "Настройки отображения", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index fd08d332d..ef8992329 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -189,6 +189,8 @@ "disable_exchange": "ปิดใช้งานการแลกเปลี่ยน", "disable_fiat": "ปิดใช้งานสกุลเงินตรา", "disable_sell": "ปิดการใช้งานการขาย", + "disableBatteryOptimization": "ปิดใช้งานการเพิ่มประสิทธิภาพแบตเตอรี่", + "disableBatteryOptimizationDescription": "คุณต้องการปิดใช้งานการเพิ่มประสิทธิภาพแบตเตอรี่เพื่อให้การซิงค์พื้นหลังทำงานได้อย่างอิสระและราบรื่นมากขึ้นหรือไม่?", "disabled": "ปิดใช้งาน", "discount": "ประหยัด ${value}%", "display_settings": "การตั้งค่าการแสดงผล", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 2759eaabe..55b6adb51 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -189,6 +189,8 @@ "disable_exchange": "Huwag paganahin ang palitan", "disable_fiat": "Huwag paganahin ang Fiat", "disable_sell": "Huwag paganahin ang pagkilos ng pagbebenta", + "disableBatteryOptimization": "Huwag paganahin ang pag -optimize ng baterya", + "disableBatteryOptimizationDescription": "Nais mo bang huwag paganahin ang pag -optimize ng baterya upang gawing mas malaya at maayos ang pag -sync ng background?", "disabled": "Hindi pinagana", "discount": "Makatipid ng ${value}%", "display_settings": "Mga setting ng pagpapakita", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index c8af1fbd3..e6cab5027 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -189,6 +189,8 @@ "disable_exchange": "Borsayı devre dışı bırak", "disable_fiat": "İtibari paraları devre dışı bırak", "disable_sell": "Satış işlemini devre dışı bırak", + "disableBatteryOptimization": "Pil optimizasyonunu devre dışı bırakın", + "disableBatteryOptimizationDescription": "Arka plan senkronizasyonunu daha özgür ve sorunsuz bir şekilde çalıştırmak için pil optimizasyonunu devre dışı bırakmak istiyor musunuz?", "disabled": "Devre dışı", "discount": "%${value} tasarruf et", "display_settings": "Görüntü ayarları", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 7007ec86c..e81d97021 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -189,6 +189,8 @@ "disable_exchange": "Вимкнути exchange", "disable_fiat": "Вимкнути фиат", "disable_sell": "Вимкнути дію продажу", + "disableBatteryOptimization": "Вимкнути оптимізацію акумулятора", + "disableBatteryOptimizationDescription": "Ви хочете відключити оптимізацію акумулятора, щоб зробити фонову синхронізацію більш вільно та плавно?", "disabled": "Вимкнено", "discount": "Зекономте ${value}%", "display_settings": "Налаштування дисплея", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 5233e473b..465fac003 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -189,6 +189,8 @@ "disable_exchange": "تبادلے کو غیر فعال کریں۔", "disable_fiat": "فیاٹ کو غیر فعال کریں۔", "disable_sell": "فروخت کی کارروائی کو غیر فعال کریں۔", + "disableBatteryOptimization": "بیٹری کی اصلاح کو غیر فعال کریں", + "disableBatteryOptimizationDescription": "کیا آپ پس منظر کی مطابقت پذیری کو زیادہ آزادانہ اور آسانی سے چلانے کے لئے بیٹری کی اصلاح کو غیر فعال کرنا چاہتے ہیں؟", "disabled": "معذور", "discount": "${value}% بچائیں", "display_settings": "ڈسپلے کی ترتیبات", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 95349e63a..c88f488cd 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -189,6 +189,8 @@ "disable_exchange": "Pa ilé pàṣípààrọ̀", "disable_fiat": "Pa owó tí ìjọba pàṣẹ wa lò", "disable_sell": "Ko iṣọrọ iṣọrọ", + "disableBatteryOptimization": "Mu Ifasi batiri", + "disableBatteryOptimizationDescription": "Ṣe o fẹ lati mu iṣapelo batiri si lati le ṣiṣe ayẹwo ẹhin ati laisiyonu?", "disabled": "Wọ́n tí a ti pa", "discount": "Pamọ́ ${value}%", "display_settings": "Fihàn àwọn ààtò", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 22792d307..7e05d4471 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -189,6 +189,8 @@ "disable_exchange": "禁用交换", "disable_fiat": "禁用法令", "disable_sell": "禁用卖出操作", + "disableBatteryOptimization": "禁用电池优化", + "disableBatteryOptimizationDescription": "您是否要禁用电池优化以使背景同步更加自由,平稳地运行?", "disabled": "禁用", "discount": "节省 ${value}%", "display_settings": "显示设置", From d6af37df067d49068ce763ea0c1c567eed5d5e74 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Sun, 11 Feb 2024 02:04:46 +0200 Subject: [PATCH 115/241] New versions (#1295) --- assets/text/Monerocom_Release_Notes.txt | 4 ++-- assets/text/Release_Notes.txt | 7 ++++--- lib/src/screens/settings/connection_sync_page.dart | 4 +++- lib/view_model/settings/sync_mode.dart | 4 ++-- scripts/android/app_env.sh | 8 ++++---- scripts/ios/app_env.sh | 8 ++++---- scripts/macos/app_env.sh | 8 ++++---- tool/configure.dart | 8 ++++---- 8 files changed, 27 insertions(+), 24 deletions(-) diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 2b783ee1e..7cf786332 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,3 +1,3 @@ -Security and Privacy enhancements -Usability enhancements +Improve wallet recovery and error tolerance +Enhance Background sync for Monero wallets Bug fixes \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 411ed609b..2f5130bea 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,4 +1,5 @@ -List previously used Bitcoin addresses -Security and Privacy enhancements -Usability enhancements +Bitcoin transactions fixes and enhancements +EVM wallets enhancements (Ethereum and Polygon) +Improve wallet recovery and error tolerance +Enhance Background sync for Monero wallets Bug fixes \ No newline at end of file diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart index 45d44d443..803a65913 100644 --- a/lib/src/screens/settings/connection_sync_page.dart +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -55,10 +55,12 @@ class ConnectionSyncPage extends BasePage { onItemSelected: (syncMode) async { dashboardViewModel.setSyncMode(syncMode); + if (Platform.isIOS) return; + if (syncMode.type != SyncType.disabled) { final isDisabled = await isBatteryOptimizationDisabled(); - if (isDisabled || Platform.isIOS) return; + if (isDisabled) return; await showPopUp( context: context, diff --git a/lib/view_model/settings/sync_mode.dart b/lib/view_model/settings/sync_mode.dart index 37e400acb..ac3ac8717 100644 --- a/lib/view_model/settings/sync_mode.dart +++ b/lib/view_model/settings/sync_mode.dart @@ -9,7 +9,7 @@ class SyncMode { static final all = [ SyncMode("Disabled", SyncType.disabled, Duration.zero), - SyncMode("Unobtrusive", SyncType.unobtrusive, Duration(days: 1)), - SyncMode("Aggressive", SyncType.aggressive, Duration(hours: 1)), + SyncMode("Unobtrusive", SyncType.unobtrusive, Duration(hours: 12)), + SyncMode("Aggressive", SyncType.aggressive, Duration(hours: 3)), ]; } diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 8de5be02c..f659239e7 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.10.2" -MONERO_COM_BUILD_NUMBER=74 +MONERO_COM_VERSION="1.10.3" +MONERO_COM_BUILD_NUMBER=75 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.13.2" -CAKEWALLET_BUILD_NUMBER=191 +CAKEWALLET_VERSION="4.13.3" +CAKEWALLET_BUILD_NUMBER=192 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index c7d62a40a..bb4ca77f8 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.10.2" -MONERO_COM_BUILD_NUMBER=72 +MONERO_COM_VERSION="1.10.3" +MONERO_COM_BUILD_NUMBER=73 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.13.2" -CAKEWALLET_BUILD_NUMBER=210 +CAKEWALLET_VERSION="4.13.3" +CAKEWALLET_BUILD_NUMBER=212 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index c2c7493af..49edd9acb 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -16,13 +16,13 @@ if [ -n "$1" ]; then fi MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.0.2" -MONERO_COM_BUILD_NUMBER=4 +MONERO_COM_VERSION="1.0.3" +MONERO_COM_BUILD_NUMBER=5 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.6.2" -CAKEWALLET_BUILD_NUMBER=52 +CAKEWALLET_VERSION="1.6.3" +CAKEWALLET_BUILD_NUMBER=53 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then diff --git a/tool/configure.dart b/tool/configure.dart index 8297d8a39..408a6f6b1 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -525,6 +525,8 @@ import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; +import 'package:hive/hive.dart'; +import 'package:web3dart/web3dart.dart'; """; const ethereumCWHeaders = """ @@ -540,8 +542,6 @@ import 'package:cw_ethereum/ethereum_wallet.dart'; import 'package:cw_ethereum/ethereum_wallet_service.dart'; import 'package:eth_sig_util/util/utils.dart'; -import 'package:hive/hive.dart'; -import 'package:web3dart/web3dart.dart'; """; const ethereumCwPart = "part 'cw_ethereum.dart';"; @@ -617,6 +617,8 @@ import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; +import 'package:hive/hive.dart'; +import 'package:web3dart/web3dart.dart'; """; const polygonCWHeaders = """ @@ -631,8 +633,6 @@ import 'package:cw_polygon/polygon_client.dart'; import 'package:cw_polygon/polygon_wallet.dart'; import 'package:cw_polygon/polygon_wallet_service.dart'; -import 'package:hive/hive.dart'; -import 'package:web3dart/web3dart.dart'; import 'package:eth_sig_util/util/utils.dart'; """; From 5a7ea87543e4790e5346d8ce844f8460527d2b6d Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Thu, 22 Feb 2024 15:39:39 -0500 Subject: [PATCH 116/241] UI fixes (#1301) * Remove StandardListSeparator from Security and backup page * Remove StandardListSeparator from Connection and sync page * Remove StandardListSeparator from Other settings page --- lib/src/screens/settings/connection_sync_page.dart | 7 ------- lib/src/screens/settings/other_settings_page.dart | 1 - lib/src/screens/settings/security_backup_page.dart | 3 --- 3 files changed, 11 deletions(-) diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart index 803a65913..ce27cd104 100644 --- a/lib/src/screens/settings/connection_sync_page.dart +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -38,13 +38,11 @@ class ConnectionSyncPage extends BasePage { title: S.current.reconnect, handler: (context) => _presentReconnectAlert(context), ), - const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), if (dashboardViewModel.hasRescan) ...[ SettingsCellWithArrow( title: S.current.rescan, handler: (context) => Navigator.of(context).pushNamed(Routes.rescan), ), - const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), if (DeviceInfo.instance.isMobile) ...[ Observer(builder: (context) { return SettingsPickerCell( @@ -82,7 +80,6 @@ class ConnectionSyncPage extends BasePage { } }); }), - const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), Observer(builder: (context) { return SettingsSwitcherCell( title: S.current.sync_all_wallets, @@ -90,14 +87,12 @@ class ConnectionSyncPage extends BasePage { onValueChange: (_, bool value) => dashboardViewModel.setSyncAll(value), ); }), - const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), ], ], SettingsCellWithArrow( title: S.current.manage_nodes, handler: (context) => Navigator.of(context).pushNamed(Routes.manageNodes), ), - const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), Observer( builder: (context) { if (!dashboardViewModel.hasPowNodes) return const SizedBox(); @@ -108,7 +103,6 @@ class ConnectionSyncPage extends BasePage { title: S.current.manage_pow_nodes, handler: (context) => Navigator.of(context).pushNamed(Routes.managePowNodes), ), - const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), ], ); }, @@ -117,7 +111,6 @@ class ConnectionSyncPage extends BasePage { WalletConnectTile( onTap: () => Navigator.of(context).pushNamed(Routes.walletConnectConnectionsListing), ), - const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), ], if (FeatureFlag.isInAppTorEnabled) SettingsCellWithArrow( diff --git a/lib/src/screens/settings/other_settings_page.dart b/lib/src/screens/settings/other_settings_page.dart index c58523185..c88804147 100644 --- a/lib/src/screens/settings/other_settings_page.dart +++ b/lib/src/screens/settings/other_settings_page.dart @@ -61,7 +61,6 @@ class OtherSettingsPage extends BasePage { handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.readDisclaimer), ), - StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), Spacer(), SettingsVersionCell( title: S.of(context).version(_otherSettingsViewModel.currentVersion)), diff --git a/lib/src/screens/settings/security_backup_page.dart b/lib/src/screens/settings/security_backup_page.dart index 56ba049ba..e559e9b15 100644 --- a/lib/src/screens/settings/security_backup_page.dart +++ b/lib/src/screens/settings/security_backup_page.dart @@ -37,7 +37,6 @@ class SecurityBackupPage extends BasePage { .shouldRequireTOTP2FAForAllSecurityAndBackupSettings, ), ), - StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), SettingsCellWithArrow( title: S.current.create_backup, handler: (_) => _authService.authenticateAction( @@ -47,7 +46,6 @@ class SecurityBackupPage extends BasePage { .shouldRequireTOTP2FAForAllSecurityAndBackupSettings, ), ), - StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), SettingsCellWithArrow( title: S.current.settings_change_pin, handler: (_) => _authService.authenticateAction( @@ -60,7 +58,6 @@ class SecurityBackupPage extends BasePage { .shouldRequireTOTP2FAForAllSecurityAndBackupSettings, ), ), - StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), if (DeviceInfo.instance.isMobile) Observer(builder: (_) { return SettingsSwitcherCell( From 109bba43013b90270bb556d954a34102ec7a4c30 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Fri, 23 Feb 2024 14:39:19 +0100 Subject: [PATCH 117/241] CW-555-Add-Solana-Wallet (#1272) * chore: Create cw_solana package and clean up files * feat: Add Solana Wallet - Create, Restore form seed, restore from Key, Restore from QR, Send, Receive, transaction history, spl tokens * fix: Make transactions file specific to solana only for solana transactions * chore: Revert inject app details script * fix: Fix issue with node and switch current node to main beta instead of testnet * fix: Fix merge conflicts and adjust migration version * fix: Fetch spl token error Signed-off-by: Blazebrain * fix: Diplay and activate spl tokens bug * fix: Review and fixes * fix: reverted formatting for cryptocurrency class * fix: Review comments, split sending flow into signing and sending separately, fix issues * fix: Revert throwing unimplenented error * chore: Fix comment * chore: Fix comment * fix: Errors in flow * Update provider_types.dart [skip ci] * fix: Issues with solana wallet * Update solana_wallet.dart [skip ci] * fix: Review comments * fix: Date time config * fix: Revert bash script for app details * fix: Error with balance, displaying fees, fixing sent or received identifier bug, displaying token symbol with token transaction item in transactions list * fix: Issues with address validation when sending spl tokens and walletconnect initial setup * fix: Issues with sending, fetching transactions history, almost wrapping up walletconnect * fix: Adjust imports that would affect monerocom building successfully * fix: Refine transaction direction and continue work on walletconnect * feat: Display SPL token transfers in the transaction history and finally settle the transaction direction * fix: Delay in transactions history dispaly, show native token transactions first, then process spl token transactions * feat: Switch node and revert solana chain id to previous id * fix: Remove print statement * fix: Remove await for transactions, fetch all transaction histories instantly and adjust solana send success message * chore: Code refactoring and streamlined wallet type check for solana send success message * fix: Make timeout error for node silent and add spl token images --------- Signed-off-by: Blazebrain Co-authored-by: Omar Hatem --- .github/workflows/pr_test_build.yml | 31 +- .gitignore | 3 + android/app/src/main/AndroidManifestBase.xml | 1 + assets/images/avdo_icon.png | Bin 0 -> 55363 bytes assets/images/bonk_icon.png | Bin 0 -> 55872 bytes assets/images/gmt_icon.png | Bin 0 -> 16590 bytes assets/images/hnt_icon.png | Bin 0 -> 10492 bytes assets/images/ray_icon.png | Bin 0 -> 15614 bytes assets/solana_node_list.yml | 4 + cw_core/lib/crypto_currency.dart | 7 +- cw_core/lib/currency_for_wallet_type.dart | 2 + cw_core/lib/hive_type_ids.dart | 3 +- cw_core/lib/node.dart | 25 +- cw_core/lib/pathForWallet.dart | 1 - cw_core/lib/wallet_type.dart | 16 +- cw_solana/.gitignore | 30 + cw_solana/.metadata | 10 + cw_solana/CHANGELOG.md | 3 + cw_solana/LICENSE | 1 + cw_solana/README.md | 39 + cw_solana/analysis_options.yaml | 4 + cw_solana/lib/cw_solana.dart | 7 + cw_solana/lib/default_spl_tokens.dart | 109 + cw_solana/lib/file.dart | 39 + cw_solana/lib/pending_solana_transaction.dart | 43 + cw_solana/lib/solana_balance.dart | 39 + cw_solana/lib/solana_client.dart | 477 ++++ cw_solana/lib/solana_exceptions.dart | 21 + cw_solana/lib/solana_mnemonics.dart | 2058 +++++++++++++++++ .../lib/solana_transaction_credentials.dart | 12 + cw_solana/lib/solana_transaction_history.dart | 78 + cw_solana/lib/solana_transaction_info.dart | 78 + cw_solana/lib/solana_transaction_model.dart | 47 + cw_solana/lib/solana_wallet.dart | 510 ++++ cw_solana/lib/solana_wallet_addresses.dart | 33 + .../solana_wallet_creation_credentials.dart | 29 + cw_solana/lib/solana_wallet_service.dart | 118 + cw_solana/lib/spl_token.dart | 146 ++ cw_solana/pubspec.yaml | 37 + cw_solana/test/cw_solana_test.dart | 12 + ios/Runner/InfoBase.plist | 10 + lib/core/address_validator.dart | 17 +- lib/core/seed_validator.dart | 3 + .../{ => chain_service}/chain_service.dart | 0 .../{ => chain_service/eth}/evm_chain_id.dart | 2 +- .../eth}/evm_chain_service.dart | 6 +- .../solana/entities/solana_sign_message.dart | 28 + .../entities/solana_sign_transaction.dart | 106 + .../chain_service/solana/solana_chain_id.dart | 27 + .../solana/solana_chain_service.dart | 177 ++ .../wallet_connect_key_service.dart | 14 +- .../wallet_connect/web3wallet_service.dart | 44 +- lib/di.dart | 5 +- lib/entities/default_settings_migration.dart | 45 +- lib/entities/node_list.dart | 21 +- lib/entities/preferences_key.dart | 1 + lib/entities/priority_for_wallet_type.dart | 9 +- lib/entities/provider_types.dart | 9 + lib/ethereum/cw_ethereum.dart | 11 +- lib/main.dart | 4 +- lib/polygon/cw_polygon.dart | 10 +- lib/reactions/fiat_rate_update.dart | 10 +- lib/reactions/on_current_wallet_change.dart | 10 +- lib/reactions/wallet_connect.dart | 19 +- lib/solana/cw_solana.dart | 118 + .../desktop_wallet_selection_dropdown.dart | 3 + .../screens/dashboard/edit_token_page.dart | 48 +- .../screens/dashboard/home_settings_page.dart | 22 +- .../screens/dashboard/pages/balance_page.dart | 16 +- .../dashboard/pages/nft_details_page.dart | 4 +- .../dashboard/widgets/menu_widget.dart | 36 +- .../dashboard/widgets/nft_tile_widget.dart | 5 +- lib/src/screens/send/send_page.dart | 12 +- lib/src/screens/send/widgets/send_card.dart | 2 +- .../settings/connection_sync_page.dart | 2 +- .../screens/settings/other_settings_page.dart | 2 +- .../widgets/pairing_item_widget.dart | 12 +- .../screens/wallet_list/wallet_list_page.dart | 3 + .../cake_image_widget.dart} | 32 +- lib/store/app_store.dart | 2 +- lib/store/settings_store.dart | 16 +- .../advanced_privacy_settings_view_model.dart | 5 +- .../dashboard/balance_view_model.dart | 120 +- .../dashboard/home_settings_view_model.dart | 78 +- .../dashboard/transaction_list_item.dart | 9 + .../exchange/exchange_view_model.dart | 4 + .../node_list/node_list_view_model.dart | 3 + .../restore/restore_from_qr_vm.dart | 7 + .../restore/wallet_restore_from_qr_code.dart | 9 + lib/view_model/send/output.dart | 9 +- .../send/send_template_view_model.dart | 3 +- lib/view_model/send/send_view_model.dart | 14 +- .../settings/other_settings_view_model.dart | 29 +- .../transaction_details_view_model.dart | 24 + .../wallet_address_list_view_model.dart | 26 + lib/view_model/wallet_keys_view_model.dart | 5 +- lib/view_model/wallet_new_vm.dart | 33 +- lib/view_model/wallet_restore_view_model.dart | 45 +- model_generator.sh | 1 + pubspec_base.yaml | 2 + res/values/strings_ar.arb | 5 +- res/values/strings_bg.arb | 5 +- res/values/strings_cs.arb | 5 +- res/values/strings_de.arb | 5 +- res/values/strings_en.arb | 5 +- res/values/strings_es.arb | 5 +- res/values/strings_fr.arb | 5 +- res/values/strings_ha.arb | 5 +- res/values/strings_hi.arb | 5 +- res/values/strings_hr.arb | 5 +- res/values/strings_id.arb | 5 +- res/values/strings_it.arb | 5 +- res/values/strings_ja.arb | 5 +- res/values/strings_ko.arb | 5 +- res/values/strings_my.arb | 5 +- res/values/strings_nl.arb | 5 +- res/values/strings_pl.arb | 5 +- res/values/strings_pt.arb | 5 +- res/values/strings_ru.arb | 5 +- res/values/strings_th.arb | 5 +- res/values/strings_tl.arb | 5 +- res/values/strings_tr.arb | 5 +- res/values/strings_uk.arb | 5 +- res/values/strings_ur.arb | 5 +- res/values/strings_yo.arb | 5 +- res/values/strings_zh.arb | 5 +- scripts/android/pubspec_gen.sh | 2 +- scripts/ios/app_config.sh | 2 +- scripts/macos/app_config.sh | 2 +- tool/configure.dart | 113 +- tool/generate_secrets_config.dart | 20 +- tool/import_secrets_config.dart | 14 + tool/utils/secret_key.dart | 4 + 133 files changed, 5356 insertions(+), 353 deletions(-) create mode 100644 assets/images/avdo_icon.png create mode 100644 assets/images/bonk_icon.png create mode 100644 assets/images/gmt_icon.png create mode 100644 assets/images/hnt_icon.png create mode 100644 assets/images/ray_icon.png create mode 100644 assets/solana_node_list.yml create mode 100644 cw_solana/.gitignore create mode 100644 cw_solana/.metadata create mode 100644 cw_solana/CHANGELOG.md create mode 100644 cw_solana/LICENSE create mode 100644 cw_solana/README.md create mode 100644 cw_solana/analysis_options.yaml create mode 100644 cw_solana/lib/cw_solana.dart create mode 100644 cw_solana/lib/default_spl_tokens.dart create mode 100644 cw_solana/lib/file.dart create mode 100644 cw_solana/lib/pending_solana_transaction.dart create mode 100644 cw_solana/lib/solana_balance.dart create mode 100644 cw_solana/lib/solana_client.dart create mode 100644 cw_solana/lib/solana_exceptions.dart create mode 100644 cw_solana/lib/solana_mnemonics.dart create mode 100644 cw_solana/lib/solana_transaction_credentials.dart create mode 100644 cw_solana/lib/solana_transaction_history.dart create mode 100644 cw_solana/lib/solana_transaction_info.dart create mode 100644 cw_solana/lib/solana_transaction_model.dart create mode 100644 cw_solana/lib/solana_wallet.dart create mode 100644 cw_solana/lib/solana_wallet_addresses.dart create mode 100644 cw_solana/lib/solana_wallet_creation_credentials.dart create mode 100644 cw_solana/lib/solana_wallet_service.dart create mode 100644 cw_solana/lib/spl_token.dart create mode 100644 cw_solana/pubspec.yaml create mode 100644 cw_solana/test/cw_solana_test.dart rename lib/core/wallet_connect/{ => chain_service}/chain_service.dart (100%) rename lib/core/wallet_connect/{ => chain_service/eth}/evm_chain_id.dart (86%) rename lib/core/wallet_connect/{ => chain_service/eth}/evm_chain_service.dart (98%) create mode 100644 lib/core/wallet_connect/chain_service/solana/entities/solana_sign_message.dart create mode 100644 lib/core/wallet_connect/chain_service/solana/entities/solana_sign_transaction.dart create mode 100644 lib/core/wallet_connect/chain_service/solana/solana_chain_id.dart create mode 100644 lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart create mode 100644 lib/solana/cw_solana.dart rename lib/src/{screens/dashboard/widgets/nft_image_tile_widget.dart => widgets/cake_image_widget.dart} (51%) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 88dd2c1eb..b5fe24f18 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -6,9 +6,9 @@ on: workflow_dispatch: inputs: branch: - description: 'Branch name to build' + description: "Branch name to build" required: true - default: 'main' + default: "main" jobs: PR_test_build: @@ -111,6 +111,7 @@ jobs: cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. + cd cw_solana && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_ethereum && flutter pub get && cd .. cd cw_polygon && flutter pub get && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs @@ -120,6 +121,7 @@ jobs: cd /opt/android/cake_wallet touch lib/.secrets.g.dart touch cw_evm/lib/.secrets.g.dart + touch cw_solana/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 @@ -154,6 +156,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 ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart - name: Rename app run: echo -e "id=com.cakewallet.test\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties @@ -163,18 +166,18 @@ jobs: cd /opt/android/cake_wallet flutter build apk --release -# - name: Push to App Center -# run: | -# echo 'Installing App Center CLI tools' -# npm install -g appcenter-cli -# echo "Publishing test to App Center" -# appcenter distribute release \ -# --group "Testers" \ -# --file "/opt/android/cake_wallet/build/app/outputs/apk/release/app-release.apk" \ -# --release-notes ${{ env.BRANCH_NAME }} \ -# --app Cake-Labs/Cake-Wallet \ -# --token ${{ secrets.APP_CENTER_TOKEN }} \ -# --quiet + # - name: Push to App Center + # run: | + # echo 'Installing App Center CLI tools' + # npm install -g appcenter-cli + # echo "Publishing test to App Center" + # appcenter distribute release \ + # --group "Testers" \ + # --file "/opt/android/cake_wallet/build/app/outputs/apk/release/app-release.apk" \ + # --release-notes ${{ env.BRANCH_NAME }} \ + # --app Cake-Labs/Cake-Wallet \ + # --token ${{ secrets.APP_CENTER_TOKEN }} \ + # --quiet - name: Rename apk file run: | diff --git a/.gitignore b/.gitignore index f084f8d0d..25edfcfb0 100644 --- a/.gitignore +++ b/.gitignore @@ -92,8 +92,10 @@ android/key.properties **/tool/.secrets-config.json **/tool/.evm-secrets-config.json **/tool/.ethereum-secrets-config.json +**/tool/.solana-secrets-config.json **/lib/.secrets.g.dart **/cw_evm/lib/.secrets.g.dart +**/cw_solana/lib/.secrets.g.dart vendor/ @@ -128,6 +130,7 @@ lib/ethereum/ethereum.dart lib/bitcoin_cash/bitcoin_cash.dart lib/nano/nano.dart lib/polygon/polygon.dart +lib/solana/solana.dart ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_180.png ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_120.png diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index 180190914..eea9b5521 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -66,6 +66,7 @@ + 3hD3zX(XYhkdT;8=(e#jwlS7_ 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

! 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

  • v*`zg#&ou{TaF`J$%qsv&w)?yO6Zd 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 p`_tU)*f;A%xb3*1aG!`yU3jl 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 literal 0 HcmV?d00001 diff --git a/assets/images/ray_icon.png b/assets/images/ray_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0d48e54a62a1cdce1a9c4a45e8e85f804562b6f9 GIT binary patch literal 15614 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 VC4BAKA*fs#Ojb%svPRql_&=;Iuj>E+ literal 0 HcmV?d00001 diff --git a/assets/solana_node_list.yml b/assets/solana_node_list.yml new file mode 100644 index 000000000..4a2e12161 --- /dev/null +++ b/assets/solana_node_list.yml @@ -0,0 +1,4 @@ +- + uri: rpc.ankr.com + is_default: true + useSSL: true \ No newline at end of file diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index 162ffb1d2..62c0ad437 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -9,7 +9,8 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen required this.decimals, this.fullName, this.iconPath, - this.tag}) + this.tag, this.enabled = false, + }) : super(title: title, raw: raw); final String name; @@ -17,6 +18,9 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen final String? fullName; final String? iconPath; final int decimals; + final bool enabled; + + set enabled(bool value) => this.enabled = value; static const all = [ CryptoCurrency.xmr, @@ -208,6 +212,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen static const usdtPoly = CryptoCurrency(title: 'USDT', tag: 'POLY', fullName: 'Tether USD (PoS)', raw: 87, name: 'usdtpoly', iconPath: 'assets/images/usdt_icon.png', decimals: 6); static const usdcEPoly = CryptoCurrency(title: 'USDC.E', tag: 'POLY', fullName: 'USD Coin (PoS)', raw: 88, name: 'usdcepoly', iconPath: 'assets/images/usdc_icon.png', decimals: 6); static const kaspa = CryptoCurrency(title: 'KAS', fullName: 'Kaspa', raw: 89, name: 'kaspa', iconPath: 'assets/images/kaspa_icon.png', decimals: 8); + static const usdtSol = CryptoCurrency(title: 'USDT', tag: 'SOL', fullName: 'USDT Tether', raw: 90, name: 'usdtsol', iconPath: 'assets/images/usdt_icon.png', decimals: 6); static final Map _rawCurrencyMap = diff --git a/cw_core/lib/currency_for_wallet_type.dart b/cw_core/lib/currency_for_wallet_type.dart index ce0219f1f..58ee37669 100644 --- a/cw_core/lib/currency_for_wallet_type.dart +++ b/cw_core/lib/currency_for_wallet_type.dart @@ -21,6 +21,8 @@ CryptoCurrency currencyForWalletType(WalletType type) { return CryptoCurrency.banano; case WalletType.polygon: return CryptoCurrency.maticpoly; + case WalletType.solana: + return CryptoCurrency.sol; default: throw Exception('Unexpected wallet type: ${type.toString()} for CryptoCurrency currencyForWalletType'); } diff --git a/cw_core/lib/hive_type_ids.dart b/cw_core/lib/hive_type_ids.dart index 4d4d1a6a8..3fa2eb647 100644 --- a/cw_core/lib/hive_type_ids.dart +++ b/cw_core/lib/hive_type_ids.dart @@ -13,4 +13,5 @@ const ADDRESS_INFO_TYPE_ID = 11; const ERC20_TOKEN_TYPE_ID = 12; const NANO_ACCOUNT_TYPE_ID = 13; const POW_NODE_TYPE_ID = 14; -const DERIVATION_TYPE_TYPE_ID = 15; \ No newline at end of file +const DERIVATION_TYPE_TYPE_ID = 15; +const SPL_TOKEN_TYPE_ID = 16; diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 2c43dd21a..585bc3c38 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -70,15 +70,10 @@ class Node extends HiveObject with Keyable { Uri get uri { switch (type) { case WalletType.monero: - return Uri.http(uriRaw, ''); - case WalletType.bitcoin: - return createUriFromElectrumAddress(uriRaw); - case WalletType.litecoin: - return createUriFromElectrumAddress(uriRaw); case WalletType.haven: return Uri.http(uriRaw, ''); - case WalletType.ethereum: - return Uri.https(uriRaw, ''); + case WalletType.bitcoin: + case WalletType.litecoin: case WalletType.bitcoinCash: return createUriFromElectrumAddress(uriRaw); case WalletType.nano: @@ -88,7 +83,9 @@ class Node extends HiveObject with Keyable { } else { return Uri.http(uriRaw, ''); } + case WalletType.ethereum: case WalletType.polygon: + case WalletType.solana: return Uri.https(uriRaw, ''); default: throw Exception('Unexpected type ${type.toString()} for Node uri'); @@ -134,21 +131,17 @@ class Node extends HiveObject with Keyable { try { switch (type) { case WalletType.monero: - return requestMoneroNode(); - case WalletType.bitcoin: - return requestElectrumServer(); - case WalletType.litecoin: - return requestElectrumServer(); case WalletType.haven: return requestMoneroNode(); - case WalletType.ethereum: - return requestElectrumServer(); - case WalletType.bitcoinCash: - return requestElectrumServer(); case WalletType.nano: case WalletType.banano: return requestNanoNode(); + case WalletType.bitcoin: + case WalletType.litecoin: + case WalletType.bitcoinCash: + case WalletType.ethereum: case WalletType.polygon: + case WalletType.solana: return requestElectrumServer(); default: return false; diff --git a/cw_core/lib/pathForWallet.dart b/cw_core/lib/pathForWallet.dart index af4838ffa..cfc33ef21 100644 --- a/cw_core/lib/pathForWallet.dart +++ b/cw_core/lib/pathForWallet.dart @@ -1,6 +1,5 @@ import 'dart:io'; import 'package:cw_core/wallet_type.dart'; -import 'package:flutter/foundation.dart'; import 'package:path_provider/path_provider.dart'; Future pathForWalletDir({required String name, required WalletType type}) async { diff --git a/cw_core/lib/wallet_type.dart b/cw_core/lib/wallet_type.dart index 20f0bdb19..a63ddf37c 100644 --- a/cw_core/lib/wallet_type.dart +++ b/cw_core/lib/wallet_type.dart @@ -14,6 +14,7 @@ const walletTypes = [ WalletType.nano, WalletType.banano, WalletType.polygon, + WalletType.solana, ]; @HiveType(typeId: WALLET_TYPE_TYPE_ID) @@ -46,7 +47,10 @@ enum WalletType { bitcoinCash, @HiveField(9) - polygon + polygon, + + @HiveField(10) + solana } int serializeToInt(WalletType type) { @@ -69,6 +73,8 @@ int serializeToInt(WalletType type) { return 7; case WalletType.polygon: return 8; + case WalletType.solana: + return 9; default: return -1; } @@ -94,6 +100,8 @@ WalletType deserializeFromInt(int raw) { return WalletType.bitcoinCash; case 8: return WalletType.polygon; + case 9: + return WalletType.solana; default: throw Exception('Unexpected token: $raw for WalletType deserializeFromInt'); } @@ -119,6 +127,8 @@ String walletTypeToString(WalletType type) { return 'Banano'; case WalletType.polygon: return 'Polygon'; + case WalletType.solana: + return 'Solana'; default: return ''; } @@ -144,6 +154,8 @@ String walletTypeToDisplayName(WalletType type) { return 'Banano (BAN)'; case WalletType.polygon: return 'Polygon (MATIC)'; + case WalletType.solana: + return 'Solana (SOL)'; default: return ''; } @@ -169,6 +181,8 @@ CryptoCurrency walletTypeToCryptoCurrency(WalletType type) { return CryptoCurrency.banano; case WalletType.polygon: return CryptoCurrency.maticpoly; + case WalletType.solana: + return CryptoCurrency.sol; default: throw Exception( 'Unexpected wallet type: ${type.toString()} for CryptoCurrency walletTypeToCryptoCurrency'); diff --git a/cw_solana/.gitignore b/cw_solana/.gitignore new file mode 100644 index 000000000..96486fd93 --- /dev/null +++ b/cw_solana/.gitignore @@ -0,0 +1,30 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/cw_solana/.metadata b/cw_solana/.metadata new file mode 100644 index 000000000..fa347fc6a --- /dev/null +++ b/cw_solana/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + channel: stable + +project_type: package diff --git a/cw_solana/CHANGELOG.md b/cw_solana/CHANGELOG.md new file mode 100644 index 000000000..41cc7d819 --- /dev/null +++ b/cw_solana/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/cw_solana/LICENSE b/cw_solana/LICENSE new file mode 100644 index 000000000..ba75c69f7 --- /dev/null +++ b/cw_solana/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/cw_solana/README.md b/cw_solana/README.md new file mode 100644 index 000000000..02fe8ecab --- /dev/null +++ b/cw_solana/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/cw_solana/analysis_options.yaml b/cw_solana/analysis_options.yaml new file mode 100644 index 000000000..a5744c1cf --- /dev/null +++ b/cw_solana/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/cw_solana/lib/cw_solana.dart b/cw_solana/lib/cw_solana.dart new file mode 100644 index 000000000..d04069b3b --- /dev/null +++ b/cw_solana/lib/cw_solana.dart @@ -0,0 +1,7 @@ +library cw_solana; + +/// A Calculator. +class Calculator { + /// Returns [value] plus 1. + int addOne(int value) => value + 1; +} diff --git a/cw_solana/lib/default_spl_tokens.dart b/cw_solana/lib/default_spl_tokens.dart new file mode 100644 index 000000000..f96d62d86 --- /dev/null +++ b/cw_solana/lib/default_spl_tokens.dart @@ -0,0 +1,109 @@ +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_solana/spl_token.dart'; + +class DefaultSPLTokens { + final List _defaultTokens = [ + SPLToken( + name: 'USDT Tether', + symbol: 'USDT', + mintAddress: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB', + decimal: 6, + mint: 'usdtsol', + enabled: true, + ), + SPLToken( + name: 'USD Coin', + symbol: 'USDC', + mintAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', + decimal: 6, + mint: 'usdcsol', + enabled: true, + ), + SPLToken( + name: 'Wrapped Ethereum (Sollet)', + symbol: 'soETH', + mintAddress: '2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk', + decimal: 6, + mint: 'soEth', + enabled: true, + iconPath: 'assets/images/eth_icon.png', + ), + SPLToken( + name: 'Wrapped SOL', + symbol: 'WSOL', + mintAddress: 'So11111111111111111111111111111111111111112', + decimal: 9, + mint: 'WSOL', + enabled: true, + iconPath: 'assets/images/sol_icon.png', + ), + SPLToken( + name: 'Wrapped Bitcoin (Sollet)', + symbol: 'BTC', + mintAddress: '9n4nbM75f5Ui33ZbPYXn59EwSgE8CGsHtAeTH5YFeJ9E', + decimal: 6, + mint: 'btcsol', + iconPath: 'assets/images/btc.png', + ), + SPLToken( + name: 'Bonk', + symbol: 'Bonk', + mintAddress: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263', + decimal: 5, + mint: 'Bonk', + iconPath: 'assets/images/bonk_icon.png', + ), + SPLToken( + name: 'Helium Network Token', + symbol: 'HNT', + mintAddress: 'hntyVP6YFm1Hg25TN9WGLqM12b8TQmcknKrdu1oxWux', + decimal: 8, + mint: 'hnt', + iconPath: 'assets/images/hnt_icon.png', + ), + SPLToken( + name: 'Pyth Network', + symbol: 'PYTH', + mintAddress: 'HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3', + decimal: 6, + mint: 'pyth', + ), + SPLToken( + name: 'Raydium', + symbol: 'RAY', + mintAddress: '4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R', + decimal: 6, + mint: 'ray', + iconPath: 'assets/images/ray_icon.png', + ), + SPLToken( + name: 'GMT', + symbol: 'GMT', + mintAddress: '7i5KKsX2weiTkry7jA4ZwSuXGhs5eJBEjY8vVxR4pfRx', + decimal: 6, + mint: 'ray', + iconPath: 'assets/images/gmt_icon.png', + ), + SPLToken( + name: 'AvocadoCoin', + symbol: 'AVDO', + mintAddress: 'EE5L8cMU4itTsCSuor7NLK6RZx6JhsBe8GGV3oaAHm3P', + decimal: 8, + mint: 'avdo', + iconPath: 'assets/images/avdo_icon.png', + ), + ]; + + List get initialSPLTokens => _defaultTokens.map((token) { + String? iconPath; + if (token.iconPath != null) return token; + + try { + iconPath = CryptoCurrency.all + .firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase()) + .iconPath; + } catch (_) {} + + return SPLToken.copyWith(token, iconPath, 'SOL'); + }).toList(); +} diff --git a/cw_solana/lib/file.dart b/cw_solana/lib/file.dart new file mode 100644 index 000000000..8fd236ec3 --- /dev/null +++ b/cw_solana/lib/file.dart @@ -0,0 +1,39 @@ +import 'dart:io'; +import 'package:cw_core/key.dart'; +import 'package:encrypt/encrypt.dart' as encrypt; + +Future write( + {required String path, + required String password, + required String data}) async { + final keys = extractKeys(password); + final key = encrypt.Key.fromBase64(keys.first); + final iv = encrypt.IV.fromBase64(keys.last); + final encrypted = await encode(key: key, iv: iv, data: data); + final f = File(path); + f.writeAsStringSync(encrypted); +} + +Future writeData( + {required String path, + required String password, + required String data}) async { + final keys = extractKeys(password); + final key = encrypt.Key.fromBase64(keys.first); + final iv = encrypt.IV.fromBase64(keys.last); + final encrypted = await encode(key: key, iv: iv, data: data); + final f = File(path); + f.writeAsStringSync(encrypted); +} + +Future read({required String path, required String password}) async { + final file = File(path); + + if (!file.existsSync()) { + file.createSync(); + } + + final encrypted = file.readAsStringSync(); + + return decode(password: password, data: encrypted); +} diff --git a/cw_solana/lib/pending_solana_transaction.dart b/cw_solana/lib/pending_solana_transaction.dart new file mode 100644 index 000000000..38347ed13 --- /dev/null +++ b/cw_solana/lib/pending_solana_transaction.dart @@ -0,0 +1,43 @@ +import 'package:cw_core/pending_transaction.dart'; +import 'package:solana/encoder.dart'; + +class PendingSolanaTransaction with PendingTransaction { + final double amount; + final SignedTx signedTransaction; + final String destinationAddress; + final Function sendTransaction; + final double fee; + + PendingSolanaTransaction({ + required this.fee, + required this.amount, + required this.signedTransaction, + required this.destinationAddress, + required this.sendTransaction, + }); + + @override + String get amountFormatted { + String stringifiedAmount = amount.toString(); + + if (stringifiedAmount.toString().length >= 6) { + stringifiedAmount = stringifiedAmount.substring(0, 6); + } + + return stringifiedAmount; + } + + @override + Future commit() async { + return await sendTransaction(); + } + + @override + String get feeFormatted => fee.toString(); + + @override + String get hex => signedTransaction.encode(); + + @override + String get id => ''; +} diff --git a/cw_solana/lib/solana_balance.dart b/cw_solana/lib/solana_balance.dart new file mode 100644 index 000000000..b1f0ef153 --- /dev/null +++ b/cw_solana/lib/solana_balance.dart @@ -0,0 +1,39 @@ +import 'dart:convert'; + +import 'package:cw_core/balance.dart'; + +class SolanaBalance extends Balance { + SolanaBalance(this.balance) : super(balance.toInt(), balance.toInt()); + + final double balance; + + @override + String get formattedAdditionalBalance => _balanceFormatted(); + + @override + String get formattedAvailableBalance => _balanceFormatted(); + + String _balanceFormatted() { + String stringBalance = balance.toString(); + if (stringBalance.toString().length >= 6) { + stringBalance = stringBalance.substring(0, 6); + } + return stringBalance; + } + + static SolanaBalance? fromJSON(String? jsonSource) { + if (jsonSource == null) { + return null; + } + + final decoded = json.decode(jsonSource) as Map; + + try { + return SolanaBalance(decoded['balance']); + } catch (e) { + return SolanaBalance(0.0); + } + } + + String toJSON() => json.encode({'balance': balance.toString()}); +} diff --git a/cw_solana/lib/solana_client.dart b/cw_solana/lib/solana_client.dart new file mode 100644 index 000000000..ececc56ba --- /dev/null +++ b/cw_solana/lib/solana_client.dart @@ -0,0 +1,477 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:math'; + +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/node.dart'; +import 'package:cw_solana/pending_solana_transaction.dart'; +import 'package:cw_solana/solana_balance.dart'; +import 'package:cw_solana/solana_transaction_model.dart'; +import 'package:http/http.dart' as http; +import 'package:solana/dto.dart'; +import 'package:solana/encoder.dart'; +import 'package:solana/solana.dart'; +import '.secrets.g.dart' as secrets; + +class SolanaWalletClient { + final httpClient = http.Client(); + SolanaClient? _client; + + bool connect(Node node) { + try { + Uri? rpcUri; + String webSocketUrl; + bool isModifiedNodeUri = false; + + if (node.uriRaw == 'rpc.ankr.com') { + isModifiedNodeUri = true; + String ankrApiKey = secrets.ankrApiKey; + + rpcUri = Uri.https(node.uriRaw, '/solana/$ankrApiKey'); + webSocketUrl = 'wss://${node.uriRaw}/solana/ws/$ankrApiKey'; + } else { + webSocketUrl = 'wss://${node.uriRaw}'; + } + + _client = SolanaClient( + rpcUrl: isModifiedNodeUri ? rpcUri! : node.uri, + websocketUrl: Uri.parse(webSocketUrl), + timeout: const Duration(minutes: 2), + ); + return true; + } catch (e) { + return false; + } + } + + Future getBalance(String address) async { + try { + final balance = await _client!.rpcClient.getBalance(address); + + final solBalance = balance.value / lamportsPerSol; + + return solBalance; + } catch (_) { + return 0.0; + } + } + + Future getSPLTokenAccounts(String mintAddress, String publicKey) async { + try { + final tokenAccounts = await _client!.rpcClient.getTokenAccountsByOwner( + publicKey, + TokenAccountsFilter.byMint(mintAddress), + commitment: Commitment.confirmed, + encoding: Encoding.jsonParsed, + ); + return tokenAccounts; + } catch (e) { + return null; + } + } + + Future getSplTokenBalance(String mintAddress, String publicKey) async { + // Fetch the token accounts (a token can have multiple accounts for various uses) + final tokenAccounts = await getSPLTokenAccounts(mintAddress, publicKey); + + // Handle scenario where there is no token account + if (tokenAccounts == null || tokenAccounts.value.isEmpty) { + return null; + } + + // Sum the balances of all accounts with the specified mint address + double totalBalance = 0.0; + + for (var programAccount in tokenAccounts.value) { + final tokenAmountResult = + await _client!.rpcClient.getTokenAccountBalance(programAccount.pubkey); + + final balance = tokenAmountResult.value.uiAmountString; + + final balanceAsDouble = double.tryParse(balance ?? '0.0') ?? 0.0; + + totalBalance += balanceAsDouble; + } + + return SolanaBalance(totalBalance); + } + + Future getGasForMessage(String message) async { + try { + final gasPrice = await _client!.rpcClient.getFeeForMessage(message) ?? 0; + final fee = gasPrice / lamportsPerSol; + return fee; + } catch (_) { + return 0; + } + } + + /// Load the Address's transactions into the account + Future> fetchTransactions( + Ed25519HDPublicKey publicKey, { + String? splTokenSymbol, + int? splTokenDecimal, + }) async { + List transactions = []; + + try { + final response = await _client!.rpcClient.getTransactionsList( + publicKey, + commitment: Commitment.confirmed, + limit: 1000, + ); + + for (final tx in response) { + if (tx.transaction is ParsedTransaction) { + final parsedTx = (tx.transaction as ParsedTransaction); + final message = parsedTx.message; + + final fee = (tx.meta?.fee ?? 0) / lamportsPerSol; + + for (final instruction in message.instructions) { + if (instruction is ParsedInstruction) { + instruction.map( + system: (systemData) { + systemData.parsed.map( + transfer: (transferData) { + ParsedSystemTransferInformation transfer = transferData.info; + bool isOutgoingTx = transfer.source == publicKey.toBase58(); + + double amount = transfer.lamports.toDouble() / lamportsPerSol; + + transactions.add( + SolanaTransactionModel( + id: parsedTx.signatures.first, + from: transfer.source, + to: transfer.destination, + amount: amount, + isOutgoingTx: isOutgoingTx, + blockTimeInInt: tx.blockTime!, + fee: fee, + programId: SystemProgram.programId, + tokenSymbol: 'SOL', + ), + ); + }, + transferChecked: (_) {}, + unsupported: (_) {}, + ); + }, + splToken: (splTokenData) { + if (splTokenSymbol != null) { + splTokenData.parsed.map( + transfer: (transferData) { + SplTokenTransferInfo transfer = transferData.info; + bool isOutgoingTx = transfer.source == publicKey.toBase58(); + + double amount = (double.tryParse(transfer.amount) ?? 0.0) / + pow(10, splTokenDecimal ?? 9); + + transactions.add( + SolanaTransactionModel( + id: parsedTx.signatures.first, + fee: fee, + from: transfer.source, + to: transfer.destination, + amount: amount, + isOutgoingTx: isOutgoingTx, + programId: TokenProgram.programId, + blockTimeInInt: tx.blockTime!, + tokenSymbol: splTokenSymbol, + ), + ); + }, + transferChecked: (transferCheckedData) { + SplTokenTransferCheckedInfo transfer = transferCheckedData.info; + bool isOutgoingTx = transfer.source == publicKey.toBase58(); + double amount = + double.tryParse(transfer.tokenAmount.uiAmountString ?? '0.0') ?? 0.0; + + transactions.add( + SolanaTransactionModel( + id: parsedTx.signatures.first, + fee: fee, + from: transfer.source, + to: transfer.destination, + amount: amount, + isOutgoingTx: isOutgoingTx, + programId: TokenProgram.programId, + blockTimeInInt: tx.blockTime!, + tokenSymbol: splTokenSymbol, + ), + ); + }, + generic: (genericData) {}, + ); + } + }, + memo: (_) {}, + unsupported: (a) {}, + ); + } + } + } + } + + return transactions; + } catch (err) { + return []; + } + } + + Future> getSPLTokenTransfers( + String address, + String splTokenSymbol, + int splTokenDecimal, + Ed25519HDKeyPair ownerKeypair, + ) async { + final tokenMint = Ed25519HDPublicKey.fromBase58(address); + + ProgramAccount? associatedTokenAccount; + + try { + associatedTokenAccount = await _client!.getAssociatedTokenAccount( + mint: tokenMint, + owner: ownerKeypair.publicKey, + commitment: Commitment.confirmed, + ); + } catch (_) {} + + if (associatedTokenAccount == null) return []; + + final accountPublicKey = Ed25519HDPublicKey.fromBase58(associatedTokenAccount.pubkey); + + final tokenTransactions = await fetchTransactions( + accountPublicKey, + splTokenSymbol: splTokenSymbol, + splTokenDecimal: splTokenDecimal, + ); + + return tokenTransactions; + } + + void stop() {} + + SolanaClient? get getSolanaClient => _client; + + Future signSolanaTransaction({ + required String tokenTitle, + required int tokenDecimals, + String? tokenMint, + required double inputAmount, + required String destinationAddress, + required Ed25519HDKeyPair ownerKeypair, + List references = const [], + }) async { + const commitment = Commitment.finalized; + + final latestBlockhash = + await _client!.rpcClient.getLatestBlockhash(commitment: commitment).value; + + final recentBlockhash = RecentBlockhash( + blockhash: latestBlockhash.blockhash, + feeCalculator: const FeeCalculator( + lamportsPerSignature: 500, + ), + ); + + if (tokenTitle == CryptoCurrency.sol.title) { + final pendingNativeTokenTransaction = await _signNativeTokenTransaction( + tokenTitle: tokenTitle, + tokenDecimals: tokenDecimals, + inputAmount: inputAmount, + destinationAddress: destinationAddress, + ownerKeypair: ownerKeypair, + recentBlockhash: recentBlockhash, + commitment: commitment, + ); + return pendingNativeTokenTransaction; + } else { + final pendingSPLTokenTransaction = _signSPLTokenTransaction( + tokenTitle: tokenTitle, + tokenDecimals: tokenDecimals, + tokenMint: tokenMint!, + inputAmount: inputAmount, + destinationAddress: destinationAddress, + ownerKeypair: ownerKeypair, + recentBlockhash: recentBlockhash, + commitment: commitment, + ); + return pendingSPLTokenTransaction; + } + } + + Future _signNativeTokenTransaction({ + required String tokenTitle, + required int tokenDecimals, + required double inputAmount, + required String destinationAddress, + required Ed25519HDKeyPair ownerKeypair, + required RecentBlockhash recentBlockhash, + required Commitment commitment, + }) async { + // Convert SOL to lamport + int lamports = (inputAmount * lamportsPerSol).toInt(); + + final instructions = [ + SystemInstruction.transfer( + fundingAccount: ownerKeypair.publicKey, + recipientAccount: Ed25519HDPublicKey.fromBase58(destinationAddress), + lamports: lamports, + ), + ]; + + final message = Message(instructions: instructions); + final signers = [ownerKeypair]; + + final signedTx = await _signTransactionInternal( + message: message, + signers: signers, + commitment: commitment, + recentBlockhash: recentBlockhash, + ); + + final fee = await _getFeeFromCompiledMessage( + message, + recentBlockhash, + signers.first.publicKey, + ); + + sendTx() async => await sendTransaction( + signedTransaction: signedTx, + commitment: commitment, + ); + + final pendingTransaction = PendingSolanaTransaction( + amount: inputAmount, + signedTransaction: signedTx, + destinationAddress: destinationAddress, + sendTransaction: sendTx, + fee: fee, + ); + + return pendingTransaction; + } + + Future _signSPLTokenTransaction({ + required String tokenTitle, + required int tokenDecimals, + required String tokenMint, + required double inputAmount, + required String destinationAddress, + required Ed25519HDKeyPair ownerKeypair, + required RecentBlockhash recentBlockhash, + required Commitment commitment, + }) async { + final destinationOwner = Ed25519HDPublicKey.fromBase58(destinationAddress); + final mint = Ed25519HDPublicKey.fromBase58(tokenMint); + + ProgramAccount? associatedRecipientAccount; + ProgramAccount? associatedSenderAccount; + + associatedRecipientAccount = await _client!.getAssociatedTokenAccount( + mint: mint, + owner: destinationOwner, + commitment: commitment, + ); + + associatedSenderAccount = await _client!.getAssociatedTokenAccount( + owner: ownerKeypair.publicKey, + mint: mint, + commitment: commitment, + ); + + // Throw an appropriate exception if the sender has no associated + // token account + if (associatedSenderAccount == null) { + throw NoAssociatedTokenAccountException(ownerKeypair.address, mint.toBase58()); + } + + try { + associatedRecipientAccount ??= await _client!.createAssociatedTokenAccount( + mint: mint, + owner: destinationOwner, + funder: ownerKeypair, + ); + } catch (e) { + throw Exception( + 'Error while creating an associated token account for the recipient: ${e.toString()}', + ); + } + + // Input by the user + final amount = (inputAmount * pow(10, tokenDecimals)).toInt(); + + final instruction = TokenInstruction.transfer( + source: Ed25519HDPublicKey.fromBase58(associatedSenderAccount.pubkey), + destination: Ed25519HDPublicKey.fromBase58(associatedRecipientAccount.pubkey), + owner: ownerKeypair.publicKey, + amount: amount, + ); + + final message = Message(instructions: [instruction]); + final signers = [ownerKeypair]; + + final signedTx = await _signTransactionInternal( + message: message, + signers: signers, + commitment: commitment, + recentBlockhash: recentBlockhash, + ); + + final fee = await _getFeeFromCompiledMessage( + message, + recentBlockhash, + signers.first.publicKey, + ); + + sendTx() async => await sendTransaction( + signedTransaction: signedTx, + commitment: commitment, + ); + + final pendingTransaction = PendingSolanaTransaction( + amount: inputAmount, + signedTransaction: signedTx, + destinationAddress: destinationAddress, + sendTransaction: sendTx, + fee: fee, + ); + return pendingTransaction; + } + + Future _getFeeFromCompiledMessage( + Message message, RecentBlockhash recentBlockhash, Ed25519HDPublicKey feePayer) async { + final compile = message.compile( + recentBlockhash: recentBlockhash.blockhash, + feePayer: feePayer, + ); + + final base64Message = base64Encode(compile.toByteArray().toList()); + + final fee = await getGasForMessage(base64Message); + return fee; + } + + Future _signTransactionInternal({ + required Message message, + required List signers, + required Commitment commitment, + required RecentBlockhash recentBlockhash, + }) async { + final signedTx = await signTransaction(recentBlockhash, message, signers); + + return signedTx; + } + + Future sendTransaction({ + required SignedTx signedTransaction, + required Commitment commitment, + }) async { + final signature = await _client!.rpcClient.sendTransaction(signedTransaction.encode()); + + _client!.waitForSignatureStatus(signature, status: commitment); + + return signature; + } +} diff --git a/cw_solana/lib/solana_exceptions.dart b/cw_solana/lib/solana_exceptions.dart new file mode 100644 index 000000000..7409b0500 --- /dev/null +++ b/cw_solana/lib/solana_exceptions.dart @@ -0,0 +1,21 @@ +import 'package:cw_core/crypto_currency.dart'; + +class SolanaTransactionCreationException implements Exception { + final String exceptionMessage; + + SolanaTransactionCreationException(CryptoCurrency currency) + : exceptionMessage = 'Error creating ${currency.title} transaction.'; + + @override + String toString() => exceptionMessage; +} + +class SolanaTransactionWrongBalanceException implements Exception { + final String exceptionMessage; + + SolanaTransactionWrongBalanceException(CryptoCurrency currency) + : exceptionMessage = 'Wrong balance. Not enough ${currency.title} on your balance.'; + + @override + String toString() => exceptionMessage; +} diff --git a/cw_solana/lib/solana_mnemonics.dart b/cw_solana/lib/solana_mnemonics.dart new file mode 100644 index 000000000..21cbb613a --- /dev/null +++ b/cw_solana/lib/solana_mnemonics.dart @@ -0,0 +1,2058 @@ +class SolanaMnemonicIsIncorrectException implements Exception { + @override + String toString() => + 'Solana mnemonic has incorrect format. Mnemonic should contain 12 or 24 words separated by space.'; +} + +class SolanaMnemonics { + static const englishWordlist = [ + 'abandon', + 'ability', + 'able', + 'about', + 'above', + 'absent', + 'absorb', + 'abstract', + 'absurd', + 'abuse', + 'access', + 'accident', + 'account', + 'accuse', + 'achieve', + 'acid', + 'acoustic', + 'acquire', + 'across', + 'act', + 'action', + 'actor', + 'actress', + 'actual', + 'adapt', + 'add', + 'addict', + 'address', + 'adjust', + 'admit', + 'adult', + 'advance', + 'advice', + 'aerobic', + 'affair', + 'afford', + 'afraid', + 'again', + 'age', + 'agent', + 'agree', + 'ahead', + 'aim', + 'air', + 'airport', + 'aisle', + 'alarm', + 'album', + 'alcohol', + 'alert', + 'alien', + 'all', + 'alley', + 'allow', + 'almost', + 'alone', + 'alpha', + 'already', + 'also', + 'alter', + 'always', + 'amateur', + 'amazing', + 'among', + 'amount', + 'amused', + 'analyst', + 'anchor', + 'ancient', + 'anger', + 'angle', + 'angry', + 'animal', + 'ankle', + 'announce', + 'annual', + 'another', + 'answer', + 'antenna', + 'antique', + 'anxiety', + 'any', + 'apart', + 'apology', + 'appear', + 'apple', + 'approve', + 'april', + 'arch', + 'arctic', + 'area', + 'arena', + 'argue', + 'arm', + 'armed', + 'armor', + 'army', + 'around', + 'arrange', + 'arrest', + 'arrive', + 'arrow', + 'art', + 'artefact', + 'artist', + 'artwork', + 'ask', + 'aspect', + 'assault', + 'asset', + 'assist', + 'assume', + 'asthma', + 'athlete', + 'atom', + 'attack', + 'attend', + 'attitude', + 'attract', + 'auction', + 'audit', + 'august', + 'aunt', + 'author', + 'auto', + 'autumn', + 'average', + 'avocado', + 'avoid', + 'awake', + 'aware', + 'away', + 'awesome', + 'awful', + 'awkward', + 'axis', + 'baby', + 'bachelor', + 'bacon', + 'badge', + 'bag', + 'balance', + 'balcony', + 'ball', + 'bamboo', + 'banana', + 'banner', + 'bar', + 'barely', + 'bargain', + 'barrel', + 'base', + 'basic', + 'basket', + 'battle', + 'beach', + 'bean', + 'beauty', + 'because', + 'become', + 'beef', + 'before', + 'begin', + 'behave', + 'behind', + 'believe', + 'below', + 'belt', + 'bench', + 'benefit', + 'best', + 'betray', + 'better', + 'between', + 'beyond', + 'bicycle', + 'bid', + 'bike', + 'bind', + 'biology', + 'bird', + 'birth', + 'bitter', + 'black', + 'blade', + 'blame', + 'blanket', + 'blast', + 'bleak', + 'bless', + 'blind', + 'blood', + 'blossom', + 'blouse', + 'blue', + 'blur', + 'blush', + 'board', + 'boat', + 'body', + 'boil', + 'bomb', + 'bone', + 'bonus', + 'book', + 'boost', + 'border', + 'boring', + 'borrow', + 'boss', + 'bottom', + 'bounce', + 'box', + 'boy', + 'bracket', + 'brain', + 'brand', + 'brass', + 'brave', + 'bread', + 'breeze', + 'brick', + 'bridge', + 'brief', + 'bright', + 'bring', + 'brisk', + 'broccoli', + 'broken', + 'bronze', + 'broom', + 'brother', + 'brown', + 'brush', + 'bubble', + 'buddy', + 'budget', + 'buffalo', + 'build', + 'bulb', + 'bulk', + 'bullet', + 'bundle', + 'bunker', + 'burden', + 'burger', + 'burst', + 'bus', + 'business', + 'busy', + 'butter', + 'buyer', + 'buzz', + 'cabbage', + 'cabin', + 'cable', + 'cactus', + 'cage', + 'cake', + 'call', + 'calm', + 'camera', + 'camp', + 'can', + 'canal', + 'cancel', + 'candy', + 'cannon', + 'canoe', + 'canvas', + 'canyon', + 'capable', + 'capital', + 'captain', + 'car', + 'carbon', + 'card', + 'cargo', + 'carpet', + 'carry', + 'cart', + 'case', + 'cash', + 'casino', + 'castle', + 'casual', + 'cat', + 'catalog', + 'catch', + 'category', + 'cattle', + 'caught', + 'cause', + 'caution', + 'cave', + 'ceiling', + 'celery', + 'cement', + 'census', + 'century', + 'cereal', + 'certain', + 'chair', + 'chalk', + 'champion', + 'change', + 'chaos', + 'chapter', + 'charge', + 'chase', + 'chat', + 'cheap', + 'check', + 'cheese', + 'chef', + 'cherry', + 'chest', + 'chicken', + 'chief', + 'child', + 'chimney', + 'choice', + 'choose', + 'chronic', + 'chuckle', + 'chunk', + 'churn', + 'cigar', + 'cinnamon', + 'circle', + 'citizen', + 'city', + 'civil', + 'claim', + 'clap', + 'clarify', + 'claw', + 'clay', + 'clean', + 'clerk', + 'clever', + 'click', + 'client', + 'cliff', + 'climb', + 'clinic', + 'clip', + 'clock', + 'clog', + 'close', + 'cloth', + 'cloud', + 'clown', + 'club', + 'clump', + 'cluster', + 'clutch', + 'coach', + 'coast', + 'coconut', + 'code', + 'coffee', + 'coil', + 'coin', + 'collect', + 'color', + 'column', + 'combine', + 'come', + 'comfort', + 'comic', + 'common', + 'company', + 'concert', + 'conduct', + 'confirm', + 'congress', + 'connect', + 'consider', + 'control', + 'convince', + 'cook', + 'cool', + 'copper', + 'copy', + 'coral', + 'core', + 'corn', + 'correct', + 'cost', + 'cotton', + 'couch', + 'country', + 'couple', + 'course', + 'cousin', + 'cover', + 'coyote', + 'crack', + 'cradle', + 'craft', + 'cram', + 'crane', + 'crash', + 'crater', + 'crawl', + 'crazy', + 'cream', + 'credit', + 'creek', + 'crew', + 'cricket', + 'crime', + 'crisp', + 'critic', + 'crop', + 'cross', + 'crouch', + 'crowd', + 'crucial', + 'cruel', + 'cruise', + 'crumble', + 'crunch', + 'crush', + 'cry', + 'crystal', + 'cube', + 'culture', + 'cup', + 'cupboard', + 'curious', + 'current', + 'curtain', + 'curve', + 'cushion', + 'custom', + 'cute', + 'cycle', + 'dad', + 'damage', + 'damp', + 'dance', + 'danger', + 'daring', + 'dash', + 'daughter', + 'dawn', + 'day', + 'deal', + 'debate', + 'debris', + 'decade', + 'december', + 'decide', + 'decline', + 'decorate', + 'decrease', + 'deer', + 'defense', + 'define', + 'defy', + 'degree', + 'delay', + 'deliver', + 'demand', + 'demise', + 'denial', + 'dentist', + 'deny', + 'depart', + 'depend', + 'deposit', + 'depth', + 'deputy', + 'derive', + 'describe', + 'desert', + 'design', + 'desk', + 'despair', + 'destroy', + 'detail', + 'detect', + 'develop', + 'device', + 'devote', + 'diagram', + 'dial', + 'diamond', + 'diary', + 'dice', + 'diesel', + 'diet', + 'differ', + 'digital', + 'dignity', + 'dilemma', + 'dinner', + 'dinosaur', + 'direct', + 'dirt', + 'disagree', + 'discover', + 'disease', + 'dish', + 'dismiss', + 'disorder', + 'display', + 'distance', + 'divert', + 'divide', + 'divorce', + 'dizzy', + 'doctor', + 'document', + 'dog', + 'doll', + 'dolphin', + 'domain', + 'donate', + 'donkey', + 'donor', + 'door', + 'dose', + 'double', + 'dove', + 'draft', + 'dragon', + 'drama', + 'drastic', + 'draw', + 'dream', + 'dress', + 'drift', + 'drill', + 'drink', + 'drip', + 'drive', + 'drop', + 'drum', + 'dry', + 'duck', + 'dumb', + 'dune', + 'during', + 'dust', + 'dutch', + 'duty', + 'dwarf', + 'dynamic', + 'eager', + 'eagle', + 'early', + 'earn', + 'earth', + 'easily', + 'east', + 'easy', + 'echo', + 'ecology', + 'economy', + 'edge', + 'edit', + 'educate', + 'effort', + 'egg', + 'eight', + 'either', + 'elbow', + 'elder', + 'electric', + 'elegant', + 'element', + 'elephant', + 'elevator', + 'elite', + 'else', + 'embark', + 'embody', + 'embrace', + 'emerge', + 'emotion', + 'employ', + 'empower', + 'empty', + 'enable', + 'enact', + 'end', + 'endless', + 'endorse', + 'enemy', + 'energy', + 'enforce', + 'engage', + 'engine', + 'enhance', + 'enjoy', + 'enlist', + 'enough', + 'enrich', + 'enroll', + 'ensure', + 'enter', + 'entire', + 'entry', + 'envelope', + 'episode', + 'equal', + 'equip', + 'era', + 'erase', + 'erode', + 'erosion', + 'error', + 'erupt', + 'escape', + 'essay', + 'essence', + 'estate', + 'eternal', + 'ethics', + 'evidence', + 'evil', + 'evoke', + 'evolve', + 'exact', + 'example', + 'excess', + 'exchange', + 'excite', + 'exclude', + 'excuse', + 'execute', + 'exercise', + 'exhaust', + 'exhibit', + 'exile', + 'exist', + 'exit', + 'exotic', + 'expand', + 'expect', + 'expire', + 'explain', + 'expose', + 'express', + 'extend', + 'extra', + 'eye', + 'eyebrow', + 'fabric', + 'face', + 'faculty', + 'fade', + 'faint', + 'faith', + 'fall', + 'false', + 'fame', + 'family', + 'famous', + 'fan', + 'fancy', + 'fantasy', + 'farm', + 'fashion', + 'fat', + 'fatal', + 'father', + 'fatigue', + 'fault', + 'favorite', + 'feature', + 'february', + 'federal', + 'fee', + 'feed', + 'feel', + 'female', + 'fence', + 'festival', + 'fetch', + 'fever', + 'few', + 'fiber', + 'fiction', + 'field', + 'figure', + 'file', + 'film', + 'filter', + 'final', + 'find', + 'fine', + 'finger', + 'finish', + 'fire', + 'firm', + 'first', + 'fiscal', + 'fish', + 'fit', + 'fitness', + 'fix', + 'flag', + 'flame', + 'flash', + 'flat', + 'flavor', + 'flee', + 'flight', + 'flip', + 'float', + 'flock', + 'floor', + 'flower', + 'fluid', + 'flush', + 'fly', + 'foam', + 'focus', + 'fog', + 'foil', + 'fold', + 'follow', + 'food', + 'foot', + 'force', + 'forest', + 'forget', + 'fork', + 'fortune', + 'forum', + 'forward', + 'fossil', + 'foster', + 'found', + 'fox', + 'fragile', + 'frame', + 'frequent', + 'fresh', + 'friend', + 'fringe', + 'frog', + 'front', + 'frost', + 'frown', + 'frozen', + 'fruit', + 'fuel', + 'fun', + 'funny', + 'furnace', + 'fury', + 'future', + 'gadget', + 'gain', + 'galaxy', + 'gallery', + 'game', + 'gap', + 'garage', + 'garbage', + 'garden', + 'garlic', + 'garment', + 'gas', + 'gasp', + 'gate', + 'gather', + 'gauge', + 'gaze', + 'general', + 'genius', + 'genre', + 'gentle', + 'genuine', + 'gesture', + 'ghost', + 'giant', + 'gift', + 'giggle', + 'ginger', + 'giraffe', + 'girl', + 'give', + 'glad', + 'glance', + 'glare', + 'glass', + 'glide', + 'glimpse', + 'globe', + 'gloom', + 'glory', + 'glove', + 'glow', + 'glue', + 'goat', + 'goddess', + 'gold', + 'good', + 'goose', + 'gorilla', + 'gospel', + 'gossip', + 'govern', + 'gown', + 'grab', + 'grace', + 'grain', + 'grant', + 'grape', + 'grass', + 'gravity', + 'great', + 'green', + 'grid', + 'grief', + 'grit', + 'grocery', + 'group', + 'grow', + 'grunt', + 'guard', + 'guess', + 'guide', + 'guilt', + 'guitar', + 'gun', + 'gym', + 'habit', + 'hair', + 'half', + 'hammer', + 'hamster', + 'hand', + 'happy', + 'harbor', + 'hard', + 'harsh', + 'harvest', + 'hat', + 'have', + 'hawk', + 'hazard', + 'head', + 'health', + 'heart', + 'heavy', + 'hedgehog', + 'height', + 'hello', + 'helmet', + 'help', + 'hen', + 'hero', + 'hidden', + 'high', + 'hill', + 'hint', + 'hip', + 'hire', + 'history', + 'hobby', + 'hockey', + 'hold', + 'hole', + 'holiday', + 'hollow', + 'home', + 'honey', + 'hood', + 'hope', + 'horn', + 'horror', + 'horse', + 'hospital', + 'host', + 'hotel', + 'hour', + 'hover', + 'hub', + 'huge', + 'human', + 'humble', + 'humor', + 'hundred', + 'hungry', + 'hunt', + 'hurdle', + 'hurry', + 'hurt', + 'husband', + 'hybrid', + 'ice', + 'icon', + 'idea', + 'identify', + 'idle', + 'ignore', + 'ill', + 'illegal', + 'illness', + 'image', + 'imitate', + 'immense', + 'immune', + 'impact', + 'impose', + 'improve', + 'impulse', + 'inch', + 'include', + 'income', + 'increase', + 'index', + 'indicate', + 'indoor', + 'industry', + 'infant', + 'inflict', + 'inform', + 'inhale', + 'inherit', + 'initial', + 'inject', + 'injury', + 'inmate', + 'inner', + 'innocent', + 'input', + 'inquiry', + 'insane', + 'insect', + 'inside', + 'inspire', + 'install', + 'intact', + 'interest', + 'into', + 'invest', + 'invite', + 'involve', + 'iron', + 'island', + 'isolate', + 'issue', + 'item', + 'ivory', + 'jacket', + 'jaguar', + 'jar', + 'jazz', + 'jealous', + 'jeans', + 'jelly', + 'jewel', + 'job', + 'join', + 'joke', + 'journey', + 'joy', + 'judge', + 'juice', + 'jump', + 'jungle', + 'junior', + 'junk', + 'just', + 'kangaroo', + 'keen', + 'keep', + 'ketchup', + 'key', + 'kick', + 'kid', + 'kidney', + 'kind', + 'kingdom', + 'kiss', + 'kit', + 'kitchen', + 'kite', + 'kitten', + 'kiwi', + 'knee', + 'knife', + 'knock', + 'know', + 'lab', + 'label', + 'labor', + 'ladder', + 'lady', + 'lake', + 'lamp', + 'language', + 'laptop', + 'large', + 'later', + 'latin', + 'laugh', + 'laundry', + 'lava', + 'law', + 'lawn', + 'lawsuit', + 'layer', + 'lazy', + 'leader', + 'leaf', + 'learn', + 'leave', + 'lecture', + 'left', + 'leg', + 'legal', + 'legend', + 'leisure', + 'lemon', + 'lend', + 'length', + 'lens', + 'leopard', + 'lesson', + 'letter', + 'level', + 'liar', + 'liberty', + 'library', + 'license', + 'life', + 'lift', + 'light', + 'like', + 'limb', + 'limit', + 'link', + 'lion', + 'liquid', + 'list', + 'little', + 'live', + 'lizard', + 'load', + 'loan', + 'lobster', + 'local', + 'lock', + 'logic', + 'lonely', + 'long', + 'loop', + 'lottery', + 'loud', + 'lounge', + 'love', + 'loyal', + 'lucky', + 'luggage', + 'lumber', + 'lunar', + 'lunch', + 'luxury', + 'lyrics', + 'machine', + 'mad', + 'magic', + 'magnet', + 'maid', + 'mail', + 'main', + 'major', + 'make', + 'mammal', + 'man', + 'manage', + 'mandate', + 'mango', + 'mansion', + 'manual', + 'maple', + 'marble', + 'march', + 'margin', + 'marine', + 'market', + 'marriage', + 'mask', + 'mass', + 'master', + 'match', + 'material', + 'math', + 'matrix', + 'matter', + 'maximum', + 'maze', + 'meadow', + 'mean', + 'measure', + 'meat', + 'mechanic', + 'medal', + 'media', + 'melody', + 'melt', + 'member', + 'memory', + 'mention', + 'menu', + 'mercy', + 'merge', + 'merit', + 'merry', + 'mesh', + 'message', + 'metal', + 'method', + 'middle', + 'midnight', + 'milk', + 'million', + 'mimic', + 'mind', + 'minimum', + 'minor', + 'minute', + 'miracle', + 'mirror', + 'misery', + 'miss', + 'mistake', + 'mix', + 'mixed', + 'mixture', + 'mobile', + 'model', + 'modify', + 'mom', + 'moment', + 'monitor', + 'monkey', + 'monster', + 'month', + 'moon', + 'moral', + 'more', + 'morning', + 'mosquito', + 'mother', + 'motion', + 'motor', + 'mountain', + 'mouse', + 'move', + 'movie', + 'much', + 'muffin', + 'mule', + 'multiply', + 'muscle', + 'museum', + 'mushroom', + 'music', + 'must', + 'mutual', + 'myself', + 'mystery', + 'myth', + 'naive', + 'name', + 'napkin', + 'narrow', + 'nasty', + 'nation', + 'nature', + 'near', + 'neck', + 'need', + 'negative', + 'neglect', + 'neither', + 'nephew', + 'nerve', + 'nest', + 'net', + 'network', + 'neutral', + 'never', + 'news', + 'next', + 'nice', + 'night', + 'noble', + 'noise', + 'nominee', + 'noodle', + 'normal', + 'north', + 'nose', + 'notable', + 'note', + 'nothing', + 'notice', + 'novel', + 'now', + 'nuclear', + 'number', + 'nurse', + 'nut', + 'oak', + 'obey', + 'object', + 'oblige', + 'obscure', + 'observe', + 'obtain', + 'obvious', + 'occur', + 'ocean', + 'october', + 'odor', + 'off', + 'offer', + 'office', + 'often', + 'oil', + 'okay', + 'old', + 'olive', + 'olympic', + 'omit', + 'once', + 'one', + 'onion', + 'online', + 'only', + 'open', + 'opera', + 'opinion', + 'oppose', + 'option', + 'orange', + 'orbit', + 'orchard', + 'order', + 'ordinary', + 'organ', + 'orient', + 'original', + 'orphan', + 'ostrich', + 'other', + 'outdoor', + 'outer', + 'output', + 'outside', + 'oval', + 'oven', + 'over', + 'own', + 'owner', + 'oxygen', + 'oyster', + 'ozone', + 'pact', + 'paddle', + 'page', + 'pair', + 'palace', + 'palm', + 'panda', + 'panel', + 'panic', + 'panther', + 'paper', + 'parade', + 'parent', + 'park', + 'parrot', + 'party', + 'pass', + 'patch', + 'path', + 'patient', + 'patrol', + 'pattern', + 'pause', + 'pave', + 'payment', + 'peace', + 'peanut', + 'pear', + 'peasant', + 'pelican', + 'pen', + 'penalty', + 'pencil', + 'people', + 'pepper', + 'perfect', + 'permit', + 'person', + 'pet', + 'phone', + 'photo', + 'phrase', + 'physical', + 'piano', + 'picnic', + 'picture', + 'piece', + 'pig', + 'pigeon', + 'pill', + 'pilot', + 'pink', + 'pioneer', + 'pipe', + 'pistol', + 'pitch', + 'pizza', + 'place', + 'planet', + 'plastic', + 'plate', + 'play', + 'please', + 'pledge', + 'pluck', + 'plug', + 'plunge', + 'poem', + 'poet', + 'point', + 'polar', + 'pole', + 'police', + 'pond', + 'pony', + 'pool', + 'popular', + 'portion', + 'position', + 'possible', + 'post', + 'potato', + 'pottery', + 'poverty', + 'powder', + 'power', + 'practice', + 'praise', + 'predict', + 'prefer', + 'prepare', + 'present', + 'pretty', + 'prevent', + 'price', + 'pride', + 'primary', + 'print', + 'priority', + 'prison', + 'private', + 'prize', + 'problem', + 'process', + 'produce', + 'profit', + 'program', + 'project', + 'promote', + 'proof', + 'property', + 'prosper', + 'protect', + 'proud', + 'provide', + 'public', + 'pudding', + 'pull', + 'pulp', + 'pulse', + 'pumpkin', + 'punch', + 'pupil', + 'puppy', + 'purchase', + 'purity', + 'purpose', + 'purse', + 'push', + 'put', + 'puzzle', + 'pyramid', + 'quality', + 'quantum', + 'quarter', + 'question', + 'quick', + 'quit', + 'quiz', + 'quote', + 'rabbit', + 'raccoon', + 'race', + 'rack', + 'radar', + 'radio', + 'rail', + 'rain', + 'raise', + 'rally', + 'ramp', + 'ranch', + 'random', + 'range', + 'rapid', + 'rare', + 'rate', + 'rather', + 'raven', + 'raw', + 'razor', + 'ready', + 'real', + 'reason', + 'rebel', + 'rebuild', + 'recall', + 'receive', + 'recipe', + 'record', + 'recycle', + 'reduce', + 'reflect', + 'reform', + 'refuse', + 'region', + 'regret', + 'regular', + 'reject', + 'relax', + 'release', + 'relief', + 'rely', + 'remain', + 'remember', + 'remind', + 'remove', + 'render', + 'renew', + 'rent', + 'reopen', + 'repair', + 'repeat', + 'replace', + 'report', + 'require', + 'rescue', + 'resemble', + 'resist', + 'resource', + 'response', + 'result', + 'retire', + 'retreat', + 'return', + 'reunion', + 'reveal', + 'review', + 'reward', + 'rhythm', + 'rib', + 'ribbon', + 'rice', + 'rich', + 'ride', + 'ridge', + 'rifle', + 'right', + 'rigid', + 'ring', + 'riot', + 'ripple', + 'risk', + 'ritual', + 'rival', + 'river', + 'road', + 'roast', + 'robot', + 'robust', + 'rocket', + 'romance', + 'roof', + 'rookie', + 'room', + 'rose', + 'rotate', + 'rough', + 'round', + 'route', + 'royal', + 'rubber', + 'rude', + 'rug', + 'rule', + 'run', + 'runway', + 'rural', + 'sad', + 'saddle', + 'sadness', + 'safe', + 'sail', + 'salad', + 'salmon', + 'salon', + 'salt', + 'salute', + 'same', + 'sample', + 'sand', + 'satisfy', + 'satoshi', + 'sauce', + 'sausage', + 'save', + 'say', + 'scale', + 'scan', + 'scare', + 'scatter', + 'scene', + 'scheme', + 'school', + 'science', + 'scissors', + 'scorpion', + 'scout', + 'scrap', + 'screen', + 'script', + 'scrub', + 'sea', + 'search', + 'season', + 'seat', + 'second', + 'secret', + 'section', + 'security', + 'seed', + 'seek', + 'segment', + 'select', + 'sell', + 'seminar', + 'senior', + 'sense', + 'sentence', + 'series', + 'service', + 'session', + 'settle', + 'setup', + 'seven', + 'shadow', + 'shaft', + 'shallow', + 'share', + 'shed', + 'shell', + 'sheriff', + 'shield', + 'shift', + 'shine', + 'ship', + 'shiver', + 'shock', + 'shoe', + 'shoot', + 'shop', + 'short', + 'shoulder', + 'shove', + 'shrimp', + 'shrug', + 'shuffle', + 'shy', + 'sibling', + 'sick', + 'side', + 'siege', + 'sight', + 'sign', + 'silent', + 'silk', + 'silly', + 'silver', + 'similar', + 'simple', + 'since', + 'sing', + 'siren', + 'sister', + 'situate', + 'six', + 'size', + 'skate', + 'sketch', + 'ski', + 'skill', + 'skin', + 'skirt', + 'skull', + 'slab', + 'slam', + 'sleep', + 'slender', + 'slice', + 'slide', + 'slight', + 'slim', + 'slogan', + 'slot', + 'slow', + 'slush', + 'small', + 'smart', + 'smile', + 'smoke', + 'smooth', + 'snack', + 'snake', + 'snap', + 'sniff', + 'snow', + 'soap', + 'soccer', + 'social', + 'sock', + 'soda', + 'soft', + 'solar', + 'soldier', + 'solid', + 'solution', + 'solve', + 'someone', + 'song', + 'soon', + 'sorry', + 'sort', + 'soul', + 'sound', + 'soup', + 'source', + 'south', + 'space', + 'spare', + 'spatial', + 'spawn', + 'speak', + 'special', + 'speed', + 'spell', + 'spend', + 'sphere', + 'spice', + 'spider', + 'spike', + 'spin', + 'spirit', + 'split', + 'spoil', + 'sponsor', + 'spoon', + 'sport', + 'spot', + 'spray', + 'spread', + 'spring', + 'spy', + 'square', + 'squeeze', + 'squirrel', + 'stable', + 'stadium', + 'staff', + 'stage', + 'stairs', + 'stamp', + 'stand', + 'start', + 'state', + 'stay', + 'steak', + 'steel', + 'stem', + 'step', + 'stereo', + 'stick', + 'still', + 'sting', + 'stock', + 'stomach', + 'stone', + 'stool', + 'story', + 'stove', + 'strategy', + 'street', + 'strike', + 'strong', + 'struggle', + 'student', + 'stuff', + 'stumble', + 'style', + 'subject', + 'submit', + 'subway', + 'success', + 'such', + 'sudden', + 'suffer', + 'sugar', + 'suggest', + 'suit', + 'summer', + 'sun', + 'sunny', + 'sunset', + 'super', + 'supply', + 'supreme', + 'sure', + 'surface', + 'surge', + 'surprise', + 'surround', + 'survey', + 'suspect', + 'sustain', + 'swallow', + 'swamp', + 'swap', + 'swarm', + 'swear', + 'sweet', + 'swift', + 'swim', + 'swing', + 'switch', + 'sword', + 'symbol', + 'symptom', + 'syrup', + 'system', + 'table', + 'tackle', + 'tag', + 'tail', + 'talent', + 'talk', + 'tank', + 'tape', + 'target', + 'task', + 'taste', + 'tattoo', + 'taxi', + 'teach', + 'team', + 'tell', + 'ten', + 'tenant', + 'tennis', + 'tent', + 'term', + 'test', + 'text', + 'thank', + 'that', + 'theme', + 'then', + 'theory', + 'there', + 'they', + 'thing', + 'this', + 'thought', + 'three', + 'thrive', + 'throw', + 'thumb', + 'thunder', + 'ticket', + 'tide', + 'tiger', + 'tilt', + 'timber', + 'time', + 'tiny', + 'tip', + 'tired', + 'tissue', + 'title', + 'toast', + 'tobacco', + 'today', + 'toddler', + 'toe', + 'together', + 'toilet', + 'token', + 'tomato', + 'tomorrow', + 'tone', + 'tongue', + 'tonight', + 'tool', + 'tooth', + 'top', + 'topic', + 'topple', + 'torch', + 'tornado', + 'tortoise', + 'toss', + 'total', + 'tourist', + 'toward', + 'tower', + 'town', + 'toy', + 'track', + 'trade', + 'traffic', + 'tragic', + 'train', + 'transfer', + 'trap', + 'trash', + 'travel', + 'tray', + 'treat', + 'tree', + 'trend', + 'trial', + 'tribe', + 'trick', + 'trigger', + 'trim', + 'trip', + 'trophy', + 'trouble', + 'truck', + 'true', + 'truly', + 'trumpet', + 'trust', + 'truth', + 'try', + 'tube', + 'tuition', + 'tumble', + 'tuna', + 'tunnel', + 'turkey', + 'turn', + 'turtle', + 'twelve', + 'twenty', + 'twice', + 'twin', + 'twist', + 'two', + 'type', + 'typical', + 'ugly', + 'umbrella', + 'unable', + 'unaware', + 'uncle', + 'uncover', + 'under', + 'undo', + 'unfair', + 'unfold', + 'unhappy', + 'uniform', + 'unique', + 'unit', + 'universe', + 'unknown', + 'unlock', + 'until', + 'unusual', + 'unveil', + 'update', + 'upgrade', + 'uphold', + 'upon', + 'upper', + 'upset', + 'urban', + 'urge', + 'usage', + 'use', + 'used', + 'useful', + 'useless', + 'usual', + 'utility', + 'vacant', + 'vacuum', + 'vague', + 'valid', + 'valley', + 'valve', + 'van', + 'vanish', + 'vapor', + 'various', + 'vast', + 'vault', + 'vehicle', + 'velvet', + 'vendor', + 'venture', + 'venue', + 'verb', + 'verify', + 'version', + 'very', + 'vessel', + 'veteran', + 'viable', + 'vibrant', + 'vicious', + 'victory', + 'video', + 'view', + 'village', + 'vintage', + 'violin', + 'virtual', + 'virus', + 'visa', + 'visit', + 'visual', + 'vital', + 'vivid', + 'vocal', + 'voice', + 'void', + 'volcano', + 'volume', + 'vote', + 'voyage', + 'wage', + 'wagon', + 'wait', + 'walk', + 'wall', + 'walnut', + 'want', + 'warfare', + 'warm', + 'warrior', + 'wash', + 'wasp', + 'waste', + 'water', + 'wave', + 'way', + 'wealth', + 'weapon', + 'wear', + 'weasel', + 'weather', + 'web', + 'wedding', + 'weekend', + 'weird', + 'welcome', + 'west', + 'wet', + 'whale', + 'what', + 'wheat', + 'wheel', + 'when', + 'where', + 'whip', + 'whisper', + 'wide', + 'width', + 'wife', + 'wild', + 'will', + 'win', + 'window', + 'wine', + 'wing', + 'wink', + 'winner', + 'winter', + 'wire', + 'wisdom', + 'wise', + 'wish', + 'witness', + 'wolf', + 'woman', + 'wonder', + 'wood', + 'wool', + 'word', + 'work', + 'world', + 'worry', + 'worth', + 'wrap', + 'wreck', + 'wrestle', + 'wrist', + 'write', + 'wrong', + 'yard', + 'year', + 'yellow', + 'you', + 'young', + 'youth', + 'zebra', + 'zero', + 'zone', + 'zoo' + ]; +} diff --git a/cw_solana/lib/solana_transaction_credentials.dart b/cw_solana/lib/solana_transaction_credentials.dart new file mode 100644 index 000000000..bd0c97f0b --- /dev/null +++ b/cw_solana/lib/solana_transaction_credentials.dart @@ -0,0 +1,12 @@ +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/output_info.dart'; + +class SolanaTransactionCredentials { + SolanaTransactionCredentials( + this.outputs, { + required this.currency, + }); + + final List outputs; + final CryptoCurrency currency; +} diff --git a/cw_solana/lib/solana_transaction_history.dart b/cw_solana/lib/solana_transaction_history.dart new file mode 100644 index 000000000..c03de19ad --- /dev/null +++ b/cw_solana/lib/solana_transaction_history.dart @@ -0,0 +1,78 @@ +import 'dart:convert'; +import 'dart:core'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_solana/file.dart'; +import 'package:cw_solana/solana_transaction_info.dart'; +import 'package:mobx/mobx.dart'; +import 'package:cw_core/transaction_history.dart'; + +part 'solana_transaction_history.g.dart'; + +const transactionsHistoryFileName = 'solana_transactions.json'; + +class SolanaTransactionHistory = SolanaTransactionHistoryBase with _$SolanaTransactionHistory; + +abstract class SolanaTransactionHistoryBase extends TransactionHistoryBase + with Store { + SolanaTransactionHistoryBase({required this.walletInfo, required String password}) + : _password = password { + transactions = ObservableMap(); + } + + final WalletInfo walletInfo; + String _password; + + Future init() async => await _load(); + + @override + Future save() async { + try { + final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type); + final path = '$dirPath/$transactionsHistoryFileName'; + final transactionMaps = transactions.map((key, value) => MapEntry(key, value.toJson())); + final data = json.encode({'transactions': transactionMaps}); + await writeData(path: path, password: _password, data: data); + } catch (e, s) { + print('Error while saving solana transaction history: ${e.toString()}'); + print(s); + } + } + + @override + void addOne(SolanaTransactionInfo transaction) => transactions[transaction.id] = transaction; + + @override + void addMany(Map transactions) => + this.transactions.addAll(transactions); + + Future> _read() async { + final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type); + final path = '$dirPath/$transactionsHistoryFileName'; + final content = await read(path: path, password: _password); + if (content.isEmpty) { + return {}; + } + return json.decode(content) as Map; + } + + Future _load() async { + try { + final content = await _read(); + final txs = content['transactions'] as Map? ?? {}; + + txs.entries.forEach((entry) { + final val = entry.value; + + if (val is Map) { + final tx = SolanaTransactionInfo.fromJson(val); + _update(tx); + } + }); + } catch (e) { + print(e); + } + } + + void _update(SolanaTransactionInfo transaction) => transactions[transaction.id] = transaction; +} diff --git a/cw_solana/lib/solana_transaction_info.dart b/cw_solana/lib/solana_transaction_info.dart new file mode 100644 index 000000000..1b7610e34 --- /dev/null +++ b/cw_solana/lib/solana_transaction_info.dart @@ -0,0 +1,78 @@ +import 'package:cw_core/format_amount.dart'; +import 'package:cw_core/transaction_direction.dart'; +import 'package:cw_core/transaction_info.dart'; + +class SolanaTransactionInfo extends TransactionInfo { + SolanaTransactionInfo({ + required this.id, + required this.blockTime, + required this.to, + required this.from, + required this.direction, + required this.solAmount, + this.tokenSymbol = "SOL", + required this.isPending, + required this.txFee, + }) : amount = solAmount.toInt(); + + final String id; + final String? to; + final String? from; + final int amount; + final bool isPending; + final double solAmount; + final String tokenSymbol; + final DateTime blockTime; + final double txFee; + final TransactionDirection direction; + + String? _fiatAmount; + + @override + DateTime get date => blockTime; + + @override + String amountFormatted() { + String stringBalance = solAmount.toString(); + + if (stringBalance.toString().length >= 6) { + stringBalance = stringBalance.substring(0, 6); + } + return '$stringBalance $tokenSymbol'; + } + + @override + String fiatAmount() => _fiatAmount ?? ''; + + @override + void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount); + + @override + String feeFormatted() => '${txFee.toString()} SOL'; + + factory SolanaTransactionInfo.fromJson(Map data) { + return SolanaTransactionInfo( + id: data['id'] as String, + solAmount: data['solAmount'], + direction: parseTransactionDirectionFromInt(data['direction'] as int), + blockTime: DateTime.fromMillisecondsSinceEpoch(data['blockTime'] as int), + isPending: data['isPending'] as bool, + tokenSymbol: data['tokenSymbol'] as String, + to: data['to'], + from: data['from'], + txFee: data['txFee'], + ); + } + + Map toJson() => { + 'id': id, + 'solAmount': solAmount, + 'direction': direction.index, + 'blockTime': blockTime.millisecondsSinceEpoch, + 'isPending': isPending, + 'tokenSymbol': tokenSymbol, + 'to': to, + 'from': from, + 'txFee': txFee, + }; +} diff --git a/cw_solana/lib/solana_transaction_model.dart b/cw_solana/lib/solana_transaction_model.dart new file mode 100644 index 000000000..c16c49258 --- /dev/null +++ b/cw_solana/lib/solana_transaction_model.dart @@ -0,0 +1,47 @@ +class SolanaTransactionModel { + final String id; + + final String from; + + final String to; + + final double amount; + + // If this is an outgoing transaction + final bool isOutgoingTx; + + // The Program ID of this transaction, e.g, System Program, Token Program... + final String programId; + + // The DateTime from the UNIX timestamp of the block where the transaction was included + final DateTime blockTime; + + // The Transaction fee + final double fee; + + // The token symbol + final String tokenSymbol; + + SolanaTransactionModel({ + required this.id, + required this.to, + required this.from, + required this.amount, + required this.programId, + required int blockTimeInInt, + this.isOutgoingTx = false, + required this.tokenSymbol, + required this.fee, + }) : blockTime = DateTime.fromMillisecondsSinceEpoch(blockTimeInInt * 1000); + + factory SolanaTransactionModel.fromJson(Map json) => SolanaTransactionModel( + id: json['id'], + blockTimeInInt: int.parse(json["timeStamp"]) * 1000, + from: json["from"], + to: json["to"], + amount: double.parse(json["value"]), + programId: json["programId"], + fee: json['fee'], + tokenSymbol: json['tokenSymbol'], + ); +} diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart new file mode 100644 index 000000000..f901a64be --- /dev/null +++ b/cw_solana/lib/solana_wallet.dart @@ -0,0 +1,510 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; +import 'package:cw_core/cake_hive.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/node.dart'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/pending_transaction.dart'; +import 'package:cw_core/sync_status.dart'; +import 'package:cw_core/transaction_direction.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/wallet_addresses.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_solana/default_spl_tokens.dart'; +import 'package:cw_solana/file.dart'; +import 'package:cw_solana/solana_balance.dart'; +import 'package:cw_solana/solana_client.dart'; +import 'package:cw_solana/solana_exceptions.dart'; +import 'package:cw_solana/solana_transaction_credentials.dart'; +import 'package:cw_solana/solana_transaction_history.dart'; +import 'package:cw_solana/solana_transaction_info.dart'; +import 'package:cw_solana/solana_transaction_model.dart'; +import 'package:cw_solana/solana_wallet_addresses.dart'; +import 'package:cw_solana/spl_token.dart'; +import 'package:hex/hex.dart'; +import 'package:hive/hive.dart'; +import 'package:mobx/mobx.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:solana/metaplex.dart' as metaplex; +import 'package:solana/solana.dart'; +import 'package:web3dart/crypto.dart'; + +part 'solana_wallet.g.dart'; + +class SolanaWallet = SolanaWalletBase with _$SolanaWallet; + +abstract class SolanaWalletBase + extends WalletBase with Store { + SolanaWalletBase({ + required WalletInfo walletInfo, + String? mnemonic, + String? privateKey, + required String password, + SolanaBalance? initialBalance, + }) : syncStatus = const NotConnectedSyncStatus(), + _password = password, + _mnemonic = mnemonic, + _hexPrivateKey = privateKey, + _client = SolanaWalletClient(), + walletAddresses = SolanaWalletAddresses(walletInfo), + balance = ObservableMap.of( + {CryptoCurrency.sol: initialBalance ?? SolanaBalance(BigInt.zero.toDouble())}), + super(walletInfo) { + this.walletInfo = walletInfo; + transactionHistory = SolanaTransactionHistory(walletInfo: walletInfo, password: password); + + if (!CakeHive.isAdapterRegistered(SPLToken.typeId)) { + CakeHive.registerAdapter(SPLTokenAdapter()); + } + + _sharedPrefs.complete(SharedPreferences.getInstance()); + } + + final String _password; + final String? _mnemonic; + final String? _hexPrivateKey; + + // The Solana WalletPair + Ed25519HDKeyPair? _walletKeyPair; + + Ed25519HDKeyPair? get walletKeyPair => _walletKeyPair; + + // To access the privateKey bytes. + Ed25519HDKeyPairData? _keyPairData; + + late SolanaWalletClient _client; + + Timer? _transactionsUpdateTimer; + + late final Box splTokensBox; + + @override + WalletAddresses walletAddresses; + + @override + @observable + SyncStatus syncStatus; + + @override + @observable + late ObservableMap balance; + + Completer _sharedPrefs = Completer(); + + @override + Ed25519HDKeyPairData get keys { + if (_keyPairData == null) { + return Ed25519HDKeyPairData([], publicKey: const Ed25519HDPublicKey([])); + } + + return _keyPairData!; + } + + @override + String? get seed => _mnemonic; + + @override + String get privateKey => HEX.encode(_keyPairData!.bytes); + + Future init() async { + final boxName = "${walletInfo.name.replaceAll(" ", "_")}_${SPLToken.boxName}"; + + splTokensBox = await CakeHive.openBox(boxName); + + // Create WalletPair using either the mnemonic or the privateKey + _walletKeyPair = await getWalletPair( + mnemonic: _mnemonic, + privateKey: _hexPrivateKey, + ); + + // Extract the keyPairData containing both the privateKey bytes and the publicKey hex. + _keyPairData = await _walletKeyPair!.extract(); + + walletInfo.address = _walletKeyPair!.address; + + await walletAddresses.init(); + await transactionHistory.init(); + await save(); + } + + Future getWalletPair({String? mnemonic, String? privateKey}) async { + assert(mnemonic != null || privateKey != null); + + if (privateKey != null) { + final privateKeyBytes = hexToBytes(privateKey); + return await Wallet.fromPrivateKeyBytes(privateKey: privateKeyBytes); + } + + return Wallet.fromMnemonic(mnemonic!, account: 0, change: 0); + } + + @override + int calculateEstimatedFee(TransactionPriority priority, int? amount) => 0; + + @override + Future changePassword(String password) => throw UnimplementedError("changePassword"); + + @override + void close() { + _client.stop(); + _transactionsUpdateTimer?.cancel(); + } + + @action + @override + Future connectToNode({required Node node}) async { + try { + syncStatus = ConnectingSyncStatus(); + + final isConnected = _client.connect(node); + + if (!isConnected) { + throw Exception("Solana Node connection failed"); + } + + try { + await Future.wait([ + _updateBalance(), + _updateNativeSOLTransactions(), + _updateSPLTokenTransactions(), + ]); + } catch (e) { + log(e.toString()); + } + + _setTransactionUpdateTimer(); + + syncStatus = ConnectedSyncStatus(); + } catch (e) { + syncStatus = FailedSyncStatus(); + } + } + + @override + Future createTransaction(Object credentials) async { + final solCredentials = credentials as SolanaTransactionCredentials; + + final outputs = solCredentials.outputs; + + final hasMultiDestination = outputs.length > 1; + + await _updateBalance(); + + final CryptoCurrency transactionCurrency = + balance.keys.firstWhere((element) => element.title == solCredentials.currency.title); + + final walletBalanceForCurrency = balance[transactionCurrency]!.balance; + + double totalAmount = 0.0; + + if (hasMultiDestination) { + if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) { + throw SolanaTransactionWrongBalanceException(transactionCurrency); + } + + final totalAmountFromCredentials = + outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0)); + + totalAmount = totalAmountFromCredentials.toDouble(); + + if (walletBalanceForCurrency < totalAmount) { + throw SolanaTransactionWrongBalanceException(transactionCurrency); + } + } else { + final output = outputs.first; + + final totalOriginalAmount = double.parse(output.cryptoAmount ?? '0.0'); + + totalAmount = output.sendAll ? walletBalanceForCurrency : totalOriginalAmount; + + if (walletBalanceForCurrency < totalAmount) { + throw SolanaTransactionWrongBalanceException(transactionCurrency); + } + } + + String? tokenMint; + // Token Mint is only needed for transactions that are not native tokens(non-SOL transactions) + if (transactionCurrency.title != CryptoCurrency.sol.title) { + tokenMint = (transactionCurrency as SPLToken).mintAddress; + } + + final pendingSolanaTransaction = await _client.signSolanaTransaction( + tokenMint: tokenMint, + tokenTitle: transactionCurrency.title, + inputAmount: totalAmount, + ownerKeypair: _walletKeyPair!, + tokenDecimals: transactionCurrency.decimals, + destinationAddress: solCredentials.outputs.first.isParsedAddress + ? solCredentials.outputs.first.extractedAddress! + : solCredentials.outputs.first.address, + ); + + return pendingSolanaTransaction; + } + + @override + Future> fetchTransactions() async => {}; + + /// Fetches the native SOL transactions linked to the wallet Public Key + Future _updateNativeSOLTransactions() async { + final address = Ed25519HDPublicKey.fromBase58(_walletKeyPair!.address); + + final transactions = await _client.fetchTransactions(address); + + final Map result = {}; + + for (var transactionModel in transactions) { + result[transactionModel.id] = SolanaTransactionInfo( + id: transactionModel.id, + to: transactionModel.to, + from: transactionModel.from, + blockTime: transactionModel.blockTime, + direction: transactionModel.isOutgoingTx + ? TransactionDirection.outgoing + : TransactionDirection.incoming, + solAmount: transactionModel.amount, + isPending: false, + txFee: transactionModel.fee, + tokenSymbol: transactionModel.tokenSymbol, + ); + } + + transactionHistory.addMany(result); + + await transactionHistory.save(); + } + + /// Fetches the SPL Tokens transactions linked to the token account Public Key + Future _updateSPLTokenTransactions() async { + List splTokenTransactions = []; + + for (var token in balance.keys) { + if (token is SPLToken) { + final tokenTxs = await _client.getSPLTokenTransfers( + token.mintAddress, + token.symbol, + token.decimal, + _walletKeyPair!, + ); + + splTokenTransactions.addAll(tokenTxs); + } + } + + final Map result = {}; + + for (var transactionModel in splTokenTransactions) { + result[transactionModel.id] = SolanaTransactionInfo( + id: transactionModel.id, + to: transactionModel.to, + from: transactionModel.from, + blockTime: transactionModel.blockTime, + direction: transactionModel.isOutgoingTx + ? TransactionDirection.outgoing + : TransactionDirection.incoming, + solAmount: transactionModel.amount, + isPending: false, + txFee: transactionModel.fee, + tokenSymbol: transactionModel.tokenSymbol, + ); + } + + transactionHistory.addMany(result); + + await transactionHistory.save(); + } + + @override + Future rescan({required int height}) => throw UnimplementedError("rescan"); + + @override + Future save() async { + await walletAddresses.updateAddressesInBox(); + final path = await makePath(); + await write(path: path, password: _password, data: toJSON()); + await transactionHistory.save(); + } + + @action + @override + Future startSync() async { + try { + syncStatus = AttemptingSyncStatus(); + + await Future.wait([ + _updateBalance(), + _updateNativeSOLTransactions(), + _updateSPLTokenTransactions(), + ]); + + syncStatus = SyncedSyncStatus(); + } catch (e) { + syncStatus = FailedSyncStatus(); + } + } + + Future makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); + + String toJSON() => json.encode({ + 'mnemonic': _mnemonic, + 'private_key': privateKey, + 'balance': balance[currency]!.toJSON(), + }); + + static Future open({ + required String name, + required String password, + required WalletInfo walletInfo, + }) async { + final path = await pathForWallet(name: name, type: walletInfo.type); + final jsonSource = await read(path: path, password: password); + final data = json.decode(jsonSource) as Map; + final mnemonic = data['mnemonic'] as String?; + final privateKey = data['private_key'] as String?; + final balance = SolanaBalance.fromJSON(data['balance'] as String) ?? SolanaBalance(0.0); + + return SolanaWallet( + walletInfo: walletInfo, + password: password, + mnemonic: mnemonic, + privateKey: privateKey, + initialBalance: balance, + ); + } + + Future _updateBalance() async { + balance[currency] = await _fetchSOLBalance(); + await _fetchSPLTokensBalances(); + await save(); + } + + Future _fetchSOLBalance() async { + final balance = await _client.getBalance(_walletKeyPair!.address); + + return SolanaBalance(balance); + } + + Future _fetchSPLTokensBalances() async { + for (var token in splTokensBox.values) { + if (token.enabled) { + try { + final tokenBalance = + await _client.getSplTokenBalance(token.mintAddress, _walletKeyPair!.address) ?? + balance[token] ?? + SolanaBalance(0.0); + balance[token] = tokenBalance; + } catch (e) { + print('Error fetching spl token (${token.symbol}) balance ${e.toString()}'); + } + } else { + balance.remove(token); + } + } + } + + @override + Future? updateBalance() async => await _updateBalance(); + + List get splTokenCurrencies => splTokensBox.values.toList(); + + void addInitialTokens() { + final initialSPLTokens = DefaultSPLTokens().initialSPLTokens; + + for (var token in initialSPLTokens) { + splTokensBox.put(token.mintAddress, token); + } + } + + Future addSPLToken(SPLToken token) async { + await splTokensBox.put(token.mintAddress, token); + + if (token.enabled) { + final tokenBalance = + await _client.getSplTokenBalance(token.mintAddress, _walletKeyPair!.address) ?? + balance[token] ?? + SolanaBalance(0.0); + + balance[token] = tokenBalance; + } else { + balance.remove(token); + } + } + + Future deleteSPLToken(SPLToken token) async { + await token.delete(); + + balance.remove(token); + _updateBalance(); + } + + Future getSPLToken(String mintAddress) async { + // Convert SPL token mint address to public key + final mintPublicKey = Ed25519HDPublicKey.fromBase58(mintAddress); + + // Fetch token's metadata account + final token = await solanaClient!.rpcClient.getMetadata(mint: mintPublicKey); + + if (token == null) { + return null; + } + + return SPLToken.fromMetadata( + name: token.name, + mint: token.mint, + symbol: token.symbol, + mintAddress: mintAddress, + ); + } + + @override + Future renameWalletFiles(String newWalletName) async { + final currentWalletPath = await pathForWallet(name: walletInfo.name, type: type); + final currentWalletFile = File(currentWalletPath); + + final currentDirPath = await pathForWalletDir(name: walletInfo.name, type: type); + final currentTransactionsFile = File('$currentDirPath/$transactionsHistoryFileName'); + + // Copies current wallet files into new wallet name's dir and files + if (currentWalletFile.existsSync()) { + final newWalletPath = await pathForWallet(name: newWalletName, type: type); + await currentWalletFile.copy(newWalletPath); + } + if (currentTransactionsFile.existsSync()) { + final newDirPath = await pathForWalletDir(name: newWalletName, type: type); + await currentTransactionsFile.copy('$newDirPath/$transactionsHistoryFileName'); + } + + // Delete old name's dir and files + await Directory(currentDirPath).delete(recursive: true); + } + + void _setTransactionUpdateTimer() { + if (_transactionsUpdateTimer?.isActive ?? false) { + _transactionsUpdateTimer!.cancel(); + } + + _transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 20), (_) { + _updateSPLTokenTransactions(); + _updateNativeSOLTransactions(); + _updateBalance(); + }); + } + + Future signSolanaMessage(String message) async { + // Convert the message to bytes + final messageBytes = utf8.encode(message); + + // Sign the message bytes with the wallet's private key + final signature = await _walletKeyPair!.sign(messageBytes); + + // Convert the signature to a hexadecimal string + final hex = bytesToHex(signature.bytes); + + return hex; + } + + SolanaClient? get solanaClient => _client.getSolanaClient; +} diff --git a/cw_solana/lib/solana_wallet_addresses.dart b/cw_solana/lib/solana_wallet_addresses.dart new file mode 100644 index 000000000..97a76fb99 --- /dev/null +++ b/cw_solana/lib/solana_wallet_addresses.dart @@ -0,0 +1,33 @@ +import 'package:cw_core/wallet_addresses.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:mobx/mobx.dart'; + +part 'solana_wallet_addresses.g.dart'; + +class SolanaWalletAddresses = SolanaWalletAddressesBase with _$SolanaWalletAddresses; + +abstract class SolanaWalletAddressesBase extends WalletAddresses with Store { + SolanaWalletAddressesBase(WalletInfo walletInfo) + : address = '', + super(walletInfo); + + @override + String address; + + @override + Future init() async { + address = walletInfo.address; + await updateAddressesInBox(); + } + + @override + Future updateAddressesInBox() async { + try { + addressesMap.clear(); + addressesMap[address] = ''; + await saveAddressesInBox(); + } catch (e) { + print(e.toString()); + } + } +} diff --git a/cw_solana/lib/solana_wallet_creation_credentials.dart b/cw_solana/lib/solana_wallet_creation_credentials.dart new file mode 100644 index 000000000..881c30abd --- /dev/null +++ b/cw_solana/lib/solana_wallet_creation_credentials.dart @@ -0,0 +1,29 @@ +import 'package:cw_core/wallet_credentials.dart'; +import 'package:cw_core/wallet_info.dart'; + +class SolanaNewWalletCredentials extends WalletCredentials { + SolanaNewWalletCredentials({required String name, WalletInfo? walletInfo}) + : super(name: name, walletInfo: walletInfo); +} + +class SolanaRestoreWalletFromSeedCredentials extends WalletCredentials { + SolanaRestoreWalletFromSeedCredentials( + {required String name, + required String password, + required this.mnemonic, + WalletInfo? walletInfo}) + : super(name: name, password: password, walletInfo: walletInfo); + + final String mnemonic; +} + +class SolanaRestoreWalletFromPrivateKey extends WalletCredentials { + SolanaRestoreWalletFromPrivateKey( + {required String name, + required String password, + required this.privateKey, + WalletInfo? walletInfo}) + : super(name: name, password: password, walletInfo: walletInfo); + + final String privateKey; +} diff --git a/cw_solana/lib/solana_wallet_service.dart b/cw_solana/lib/solana_wallet_service.dart new file mode 100644 index 000000000..8abf1ffbb --- /dev/null +++ b/cw_solana/lib/solana_wallet_service.dart @@ -0,0 +1,118 @@ +import 'dart:io'; + +import 'package:bip39/bip39.dart' as bip39; +import 'package:collection/collection.dart'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/wallet_base.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_solana/solana_mnemonics.dart'; +import 'package:cw_solana/solana_wallet.dart'; +import 'package:cw_solana/solana_wallet_creation_credentials.dart'; +import 'package:hive/hive.dart'; + +class SolanaWalletService extends WalletService { + SolanaWalletService(this.walletInfoSource); + + final Box walletInfoSource; + + @override + Future create(SolanaNewWalletCredentials credentials) async { + final strength = credentials.seedPhraseLength == 24 ? 256 : 128; + + final mnemonic = bip39.generateMnemonic(strength: strength); + + final wallet = SolanaWallet( + walletInfo: credentials.walletInfo!, + mnemonic: mnemonic, + password: credentials.password!, + ); + + await wallet.init(); + wallet.addInitialTokens(); + return wallet; + } + + @override + WalletType getType() => WalletType.solana; + + @override + Future isWalletExit(String name) async => + File(await pathForWallet(name: name, type: getType())).existsSync(); + + @override + Future openWallet(String name, String password) async { + final walletInfo = + walletInfoSource.values.firstWhere((info) => info.id == WalletBase.idFor(name, getType())); + final wallet = await SolanaWalletBase.open( + name: name, + password: password, + walletInfo: walletInfo, + ); + + await wallet.init(); + await wallet.save(); + + return wallet; + } + + @override + Future remove(String wallet) async { + File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true); + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; + await walletInfoSource.delete(walletInfo.key); + } + + @override + Future restoreFromKeys(SolanaRestoreWalletFromPrivateKey credentials) async { + final wallet = SolanaWallet( + password: credentials.password!, + privateKey: credentials.privateKey, + walletInfo: credentials.walletInfo!, + ); + + await wallet.init(); + wallet.addInitialTokens(); + await wallet.save(); + + return wallet; + } + + @override + Future restoreFromSeed(SolanaRestoreWalletFromSeedCredentials credentials) async { + if (!bip39.validateMnemonic(credentials.mnemonic)) { + throw SolanaMnemonicIsIncorrectException(); + } + + final wallet = SolanaWallet( + password: credentials.password!, + mnemonic: credentials.mnemonic, + walletInfo: credentials.walletInfo!, + ); + + await wallet.init(); + wallet.addInitialTokens(); + await wallet.save(); + + return wallet; + } + + @override + Future rename(String currentName, String password, String newName) async { + final currentWalletInfo = walletInfoSource.values + .firstWhere((info) => info.id == WalletBase.idFor(currentName, getType())); + final currentWallet = await SolanaWalletBase.open( + password: password, name: currentName, walletInfo: currentWalletInfo); + + await currentWallet.renameWalletFiles(newName); + + final newWalletInfo = currentWalletInfo; + newWalletInfo.id = WalletBase.idFor(newName, getType()); + newWalletInfo.name = newName; + + await walletInfoSource.put(currentWalletInfo.key, newWalletInfo); + } +} diff --git a/cw_solana/lib/spl_token.dart b/cw_solana/lib/spl_token.dart new file mode 100644 index 000000000..0413990b1 --- /dev/null +++ b/cw_solana/lib/spl_token.dart @@ -0,0 +1,146 @@ +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/hive_type_ids.dart'; +import 'package:hive/hive.dart'; +import 'package:solana/metaplex.dart'; + +part 'spl_token.g.dart'; + +@HiveType(typeId: SPLToken.typeId) +class SPLToken extends CryptoCurrency with HiveObjectMixin { + @HiveField(0) + final String name; + + @HiveField(1) + final String symbol; + + @HiveField(2) + final String mintAddress; + + @HiveField(3) + final int decimal; + + @HiveField(4, defaultValue: false) + bool _enabled; + + @HiveField(5) + final String mint; + + @HiveField(6) + final String? iconPath; + + @HiveField(7) + final String? tag; + + SPLToken({ + required this.name, + required this.symbol, + required this.mintAddress, + required this.decimal, + required this.mint, + this.iconPath, + this.tag = 'SOL', + bool enabled = false, + }) : _enabled = enabled, + super( + name: mint.toLowerCase(), + title: symbol.toUpperCase(), + fullName: name, + tag: tag, + iconPath: iconPath, + decimals: decimal, + ); + + factory SPLToken.fromMetadata({ + required String name, + required String mint, + required String symbol, + required String mintAddress, + }) { + return SPLToken( + name: name, + symbol: symbol, + mintAddress: mintAddress, + decimal: 0, + mint: mint, + iconPath: '', + ); + } + + factory SPLToken.cryptoCurrency({ + required String name, + required String symbol, + required int decimals, + required String iconPath, + required String mint, + }) { + return SPLToken( + name: name, + symbol: symbol, + decimal: decimals, + mint: mint, + iconPath: iconPath, + mintAddress: '', + ); + } + + bool get enabled => _enabled; + + set enabled(bool value) => _enabled = value; + + SPLToken.copyWith(SPLToken other, String? icon, String? tag) + : name = other.name, + symbol = other.symbol, + mintAddress = other.mintAddress, + decimal = other.decimal, + _enabled = other.enabled, + mint = other.mint, + tag = other.tag, + iconPath = icon, + super( + title: other.symbol.toUpperCase(), + name: other.symbol.toLowerCase(), + decimals: other.decimal, + fullName: other.name, + tag: other.tag, + iconPath: icon, + ); + + static const typeId = SPL_TOKEN_TYPE_ID; + static const boxName = 'SPLTokens'; + + @override + bool operator ==(other) => + (other is SPLToken && other.mintAddress == mintAddress) || + (other is CryptoCurrency && other.title == title); + + @override + int get hashCode => mintAddress.hashCode; +} + +class NFT extends SPLToken { + final ImageInfo? imageInfo; + + NFT( + String mint, + String name, + String symbol, + String mintAddress, + int decimal, + String iconPath, + this.imageInfo, + ) : super( + name: name, + symbol: symbol, + mintAddress: mintAddress, + decimal: decimal, + mint: mint, + iconPath: iconPath, + ); +} + +class ImageInfo { + final String uri; + final OffChainMetadata? data; + + const ImageInfo(this.uri, this.data); +} diff --git a/cw_solana/pubspec.yaml b/cw_solana/pubspec.yaml new file mode 100644 index 000000000..c98b7492e --- /dev/null +++ b/cw_solana/pubspec.yaml @@ -0,0 +1,37 @@ +name: cw_solana +description: A new Flutter package project. +version: 0.0.1 +publish_to: none +homepage: https://cakewallet.com + +environment: + sdk: '>=3.0.6 <4.0.0' + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + solana: ^0.30.1 + cw_core: + path: ../cw_core + http: ^1.1.0 + hive: ^2.2.3 + bip39: ^1.0.6 + mobx: ^2.3.0+1 + shared_preferences: ^2.0.15 + web3dart: ^2.7.1 + bip32: ^2.0.0 + hex: ^0.2.0 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.0 + build_runner: ^2.1.11 + mobx_codegen: ^2.0.7 + hive_generator: ^1.1.3 + +flutter: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg \ No newline at end of file diff --git a/cw_solana/test/cw_solana_test.dart b/cw_solana/test/cw_solana_test.dart new file mode 100644 index 000000000..42a5d8bdf --- /dev/null +++ b/cw_solana/test/cw_solana_test.dart @@ -0,0 +1,12 @@ +import 'package:flutter_test/flutter_test.dart'; + +import 'package:cw_solana/cw_solana.dart'; + +void main() { + test('adds one to input values', () { + final calculator = Calculator(); + expect(calculator.addOne(2), 3); + expect(calculator.addOne(-7), -6); + expect(calculator.addOne(0), 1); + }); +} diff --git a/ios/Runner/InfoBase.plist b/ios/Runner/InfoBase.plist index 2292d0b66..a7f208870 100644 --- a/ios/Runner/InfoBase.plist +++ b/ios/Runner/InfoBase.plist @@ -180,6 +180,16 @@ polygon-wallet + + CFBundleTypeRole + Viewer + CFBundleURLName + solana-wallet + CFBundleURLSchemes + + solana-wallet + + CFBundleVersion $(CURRENT_PROJECT_VERSION) diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 2ae9e3297..21f3c3557 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -1,6 +1,7 @@ import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/core/validator.dart'; +import 'package:cake_wallet/solana/solana.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/erc20_token.dart'; @@ -8,9 +9,7 @@ class AddressValidator extends TextValidator { AddressValidator({required CryptoCurrency type}) : super( errorMessage: S.current.error_text_address, - useAdditionalValidation: type == CryptoCurrency.btc - ? bitcoin.Address.validateAddress - : null, + useAdditionalValidation: type == CryptoCurrency.btc ? bitcoin.Address.validateAddress : null, pattern: getPattern(type), length: getLength(type)); @@ -130,6 +129,12 @@ class AddressValidator extends TextValidator { if (type is Erc20Token) { return [42]; } + + if (solana != null) { + final length = solana!.getValidationLength(type); + if (length != null) return length; + } + switch (type) { case CryptoCurrency.xmr: return null; @@ -192,11 +197,11 @@ class AddressValidator extends TextValidator { case CryptoCurrency.sc: return [76]; case CryptoCurrency.sol: + case CryptoCurrency.usdtSol: + case CryptoCurrency.usdcsol: return [32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44]; case CryptoCurrency.trx: return [34]; - case CryptoCurrency.usdcsol: - return [32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44]; case CryptoCurrency.usdt: return [34]; case CryptoCurrency.usdttrc20: @@ -286,6 +291,8 @@ class AddressValidator extends TextValidator { '|bitcoincash:q[0-9a-zA-Z]{42}([^0-9a-zA-Z]|\$)' '|([^0-9a-zA-Z]|^)q[0-9a-zA-Z]{41}([^0-9a-zA-Z]|\$)' '|([^0-9a-zA-Z]|^)q[0-9a-zA-Z]{42}([^0-9a-zA-Z]|\$)'; + case CryptoCurrency.sol: + return '([^0-9a-zA-Z]|^)[1-9A-HJ-NP-Za-km-z]{43,44}([^0-9a-zA-Z]|\$)'; default: return null; } diff --git a/lib/core/seed_validator.dart b/lib/core/seed_validator.dart index 8f65159e1..6d04055ba 100644 --- a/lib/core/seed_validator.dart +++ b/lib/core/seed_validator.dart @@ -4,6 +4,7 @@ import 'package:cake_wallet/haven/haven.dart'; import 'package:cake_wallet/core/validator.dart'; import 'package:cake_wallet/entities/mnemonic_item.dart'; import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cake_wallet/solana/solana.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/nano/nano.dart'; @@ -37,6 +38,8 @@ class SeedValidator extends Validator { return nano!.getNanoWordList(language); case WalletType.polygon: return polygon!.getPolygonWordList(language); + case WalletType.solana: + return solana!.getSolanaWordList(language); default: return []; } diff --git a/lib/core/wallet_connect/chain_service.dart b/lib/core/wallet_connect/chain_service/chain_service.dart similarity index 100% rename from lib/core/wallet_connect/chain_service.dart rename to lib/core/wallet_connect/chain_service/chain_service.dart diff --git a/lib/core/wallet_connect/evm_chain_id.dart b/lib/core/wallet_connect/chain_service/eth/evm_chain_id.dart similarity index 86% rename from lib/core/wallet_connect/evm_chain_id.dart rename to lib/core/wallet_connect/chain_service/eth/evm_chain_id.dart index b71fb562e..0be21b1b2 100644 --- a/lib/core/wallet_connect/evm_chain_id.dart +++ b/lib/core/wallet_connect/chain_service/eth/evm_chain_id.dart @@ -1,4 +1,4 @@ -import 'package:cake_wallet/core/wallet_connect/evm_chain_service.dart'; +import 'package:cake_wallet/core/wallet_connect/chain_service/eth/evm_chain_service.dart'; enum EVMChainId { ethereum, diff --git a/lib/core/wallet_connect/evm_chain_service.dart b/lib/core/wallet_connect/chain_service/eth/evm_chain_service.dart similarity index 98% rename from lib/core/wallet_connect/evm_chain_service.dart rename to lib/core/wallet_connect/chain_service/eth/evm_chain_service.dart index 74bff7479..6f3c8fa98 100644 --- a/lib/core/wallet_connect/evm_chain_service.dart +++ b/lib/core/wallet_connect/chain_service/eth/evm_chain_service.dart @@ -3,7 +3,7 @@ import 'dart:developer'; import 'dart:typed_data'; import 'package:cake_wallet/core/wallet_connect/eth_transaction_model.dart'; -import 'package:cake_wallet/core/wallet_connect/evm_chain_id.dart'; +import 'package:cake_wallet/core/wallet_connect/chain_service/eth/evm_chain_id.dart'; import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; @@ -20,8 +20,8 @@ import 'package:eth_sig_util/util/utils.dart'; import 'package:http/http.dart' as http; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; import 'package:web3dart/web3dart.dart'; -import 'chain_service.dart'; -import 'wallet_connect_key_service.dart'; +import '../chain_service.dart'; +import '../../wallet_connect_key_service.dart'; class EvmChainServiceImpl implements ChainService { final AppStore appStore; diff --git a/lib/core/wallet_connect/chain_service/solana/entities/solana_sign_message.dart b/lib/core/wallet_connect/chain_service/solana/entities/solana_sign_message.dart new file mode 100644 index 000000000..e462adbb5 --- /dev/null +++ b/lib/core/wallet_connect/chain_service/solana/entities/solana_sign_message.dart @@ -0,0 +1,28 @@ +class SolanaSignMessage { + final String pubkey; + final String message; + + SolanaSignMessage({ + required this.pubkey, + required this.message, + }); + + factory SolanaSignMessage.fromJson(Map json) { + return SolanaSignMessage( + pubkey: json['pubkey'] as String, + message: json['message'] as String, + ); + } + + Map toJson() { + return { + 'pubkey': pubkey, + 'message': message, + }; + } + + @override + String toString() { + return 'SolanaSignMessage(pubkey: $pubkey, message: $message)'; + } +} diff --git a/lib/core/wallet_connect/chain_service/solana/entities/solana_sign_transaction.dart b/lib/core/wallet_connect/chain_service/solana/entities/solana_sign_transaction.dart new file mode 100644 index 000000000..2cdf4697e --- /dev/null +++ b/lib/core/wallet_connect/chain_service/solana/entities/solana_sign_transaction.dart @@ -0,0 +1,106 @@ +class SolanaSignTransaction { + final String? feePayer; + final String? recentBlockhash; + final String transaction; + final List? instructions; + + SolanaSignTransaction({ + required this.feePayer, + required this.recentBlockhash, + required this.instructions, + required this.transaction, + }); + + factory SolanaSignTransaction.fromJson(Map json) { + return SolanaSignTransaction( + feePayer:json['feePayer'] !=null ? json['feePayer'] as String: null, + recentBlockhash: json['recentBlockhash']!=null? json['recentBlockhash'] as String: null, + instructions:json['instructions']!=null? (json['instructions'] as List) + .map((e) => SolanaInstruction.fromJson(e as Map)) + .toList(): null, + transaction: json['transaction'] as String, + ); + } + + Map toJson() { + return { + 'feePayer': feePayer, + 'recentBlockhash': recentBlockhash, + 'instructions': instructions, + 'transaction': transaction, + }; + } + + @override + String toString() { + return 'SolanaSignTransaction(feePayer: $feePayer, recentBlockhash: $recentBlockhash, instructions: $instructions, transaction: $transaction)'; + } +} + +class SolanaInstruction { + final String programId; + final List keys; + final List data; + + SolanaInstruction({ + required this.programId, + required this.keys, + required this.data, + }); + + factory SolanaInstruction.fromJson(Map json) { + return SolanaInstruction( + programId: json['programId'] as String, + keys: (json['keys'] as List) + .map((e) => SolanaKeyMetadata.fromJson(e as Map)) + .toList(), + data: (json['data'] as List).map((e) => e as int).toList(), + ); + } + + Map toJson() { + return { + 'programId': programId, + 'keys': keys, + 'data': data, + }; + } + + @override + String toString() { + return 'SolanaInstruction(programId: $programId, keys: $keys, data: $data)'; + } +} + +class SolanaKeyMetadata { + final String pubkey; + final bool isSigner; + final bool isWritable; + + SolanaKeyMetadata({ + required this.pubkey, + required this.isSigner, + required this.isWritable, + }); + + factory SolanaKeyMetadata.fromJson(Map json) { + return SolanaKeyMetadata( + pubkey: json['pubkey'] as String, + isSigner: json['isSigner'] as bool, + isWritable: json['isWritable'] as bool, + ); + } + + Map toJson() { + return { + 'pubkey': pubkey, + 'isSigner': isSigner, + 'isWritable': isWritable, + }; + } + + @override + String toString() { + return 'SolanaKeyMetadata(pubkey: $pubkey, isSigner: $isSigner, isWritable: $isWritable)'; + } +} diff --git a/lib/core/wallet_connect/chain_service/solana/solana_chain_id.dart b/lib/core/wallet_connect/chain_service/solana/solana_chain_id.dart new file mode 100644 index 000000000..bdc8a7d20 --- /dev/null +++ b/lib/core/wallet_connect/chain_service/solana/solana_chain_id.dart @@ -0,0 +1,27 @@ +import 'solana_chain_service.dart'; + +enum SolanaChainId { + mainnet, + testnet, + devnet, +} + +extension SolanaChainIdX on SolanaChainId { + String chain() { + String name = ''; + + switch (this) { + case SolanaChainId.mainnet: + name = '4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ'; + break; + case SolanaChainId.testnet: + name = '8E9rvCKLFQia2Y35HXjjpWzj8weVo44K'; + break; + case SolanaChainId.devnet: + name = ''; + break; + } + + return '${SolanaChainServiceImpl.namespace}:$name'; + } +} diff --git a/lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart b/lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart new file mode 100644 index 000000000..f5c696be6 --- /dev/null +++ b/lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart @@ -0,0 +1,177 @@ +import 'dart:developer'; + +import 'package:cake_wallet/core/wallet_connect/chain_service/solana/entities/solana_sign_message.dart'; +import 'package:cake_wallet/core/wallet_connect/chain_service/solana/solana_chain_id.dart'; +import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_widget.dart'; +import 'package:cake_wallet/core/wallet_connect/models/connection_model.dart'; +import 'package:cake_wallet/src/screens/wallet_connect/widgets/connection_widget.dart'; +import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/web3_request_modal.dart'; +import 'package:solana/base58.dart'; +import 'package:solana/solana.dart'; +import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; +import '../chain_service.dart'; +import '../../wallet_connect_key_service.dart'; +import 'entities/solana_sign_transaction.dart'; + +class SolanaChainServiceImpl implements ChainService { + final BottomSheetService bottomSheetService; + final Web3Wallet wallet; + final WalletConnectKeyService wcKeyService; + + static const namespace = 'solana'; + static const solSignTransaction = 'solana_signTransaction'; + static const solSignMessage = 'solana_signMessage'; + + final SolanaChainId reference; + + final SolanaClient solanaClient; + + final Ed25519HDKeyPair? ownerKeyPair; + + SolanaChainServiceImpl({ + required this.reference, + required this.wcKeyService, + required this.bottomSheetService, + required this.wallet, + required this.ownerKeyPair, + required String webSocketUrl, + required Uri rpcUrl, + SolanaClient? solanaClient, + }) : solanaClient = solanaClient ?? + SolanaClient( + rpcUrl: rpcUrl, + websocketUrl: Uri.parse(webSocketUrl), + timeout: const Duration(minutes: 2), + ) { + for (final String event in getEvents()) { + wallet.registerEventEmitter(chainId: getChainId(), event: event); + } + wallet.registerRequestHandler( + chainId: getChainId(), + method: solSignTransaction, + handler: solanaSignTransaction, + ); + wallet.registerRequestHandler( + chainId: getChainId(), + method: solSignMessage, + handler: solanaSignMessage, + ); + } + + @override + String getNamespace() { + return namespace; + } + + @override + String getChainId() { + return reference.chain(); + } + + @override + List getEvents() { + return ['']; + } + + Future requestAuthorization(String? text) async { + // Show the bottom sheet + final bool? isApproved = await bottomSheetService.queueBottomSheet( + widget: Web3RequestModal( + child: ConnectionWidget( + title: S.current.signTransaction, + info: [ + ConnectionModel( + text: text, + ), + ], + ), + ), + ) as bool?; + + if (isApproved != null && isApproved == false) { + return 'User rejected signature'; + } + + return null; + } + + Future solanaSignTransaction(String topic, dynamic parameters) async { + log('received solana sign transaction request $parameters'); + + final solanaSignTx = + SolanaSignTransaction.fromJson(parameters as Map); + + final String? authError = await requestAuthorization('Confirm request to sign transaction?'); + + if (authError != null) { + return authError; + } + + try { + final message = + await solanaClient.rpcClient.getMessageFromEncodedTx(solanaSignTx.transaction); + + final sign = await ownerKeyPair?.signMessage( + message: message, + recentBlockhash: solanaSignTx.recentBlockhash ?? '', + ); + + if (sign == null) { + return ''; + } + + String signature = sign.signatures.first.toBase58(); + + print(signature); + print(signature.runtimeType); + + bottomSheetService.queueBottomSheet( + isModalDismissible: true, + widget: BottomSheetMessageDisplayWidget( + message: S.current.awaitDAppProcessing, + isError: false, + ), + ); + + return signature; + } catch (e) { + log('An error has occurred while signing transaction: ${e.toString()}'); + bottomSheetService.queueBottomSheet( + isModalDismissible: true, + widget: BottomSheetMessageDisplayWidget( + message: '${S.current.errorSigningTransaction}: ${e.toString()}', + ), + ); + return 'Failed'; + } + } + + Future solanaSignMessage(String topic, dynamic parameters) async { + log('received solana sign message request: $parameters'); + + final solanaSignMessage = SolanaSignMessage.fromJson(parameters as Map); + + final String? authError = await requestAuthorization('Confirm request to sign message?'); + + if (authError != null) { + return authError; + } + Signature? sign; + + try { + sign = await ownerKeyPair?.sign(base58decode(solanaSignMessage.message)); + } catch (e) { + print(e); + } + + if (sign == null) { + return ''; + } + + String signature = sign.toBase58(); + + return signature; + } +} diff --git a/lib/core/wallet_connect/wallet_connect_key_service.dart b/lib/core/wallet_connect/wallet_connect_key_service.dart index 33d721073..f05adad97 100644 --- a/lib/core/wallet_connect/wallet_connect_key_service.dart +++ b/lib/core/wallet_connect/wallet_connect_key_service.dart @@ -2,6 +2,7 @@ import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart'; import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; +import 'package:cake_wallet/solana/solana.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; @@ -13,7 +14,6 @@ abstract class WalletConnectKeyService { /// If the chain is not found, returns an empty list. /// - [chain]: The chain to get the keys for. List getKeysForChain(WalletBase wallet); - } class KeyServiceImpl implements WalletConnectKeyService { @@ -23,6 +23,8 @@ class KeyServiceImpl implements WalletConnectKeyService { return ethereum!.getPrivateKey(wallet); case WalletType.polygon: return polygon!.getPrivateKey(wallet); + case WalletType.solana: + return solana!.getPrivateKey(wallet); default: return ''; } @@ -34,6 +36,8 @@ class KeyServiceImpl implements WalletConnectKeyService { return ethereum!.getPublicKey(wallet); case WalletType.polygon: return polygon!.getPublicKey(wallet); + case WalletType.solana: + return solana!.getPublicKey(wallet); default: return ''; } @@ -53,6 +57,14 @@ class KeyServiceImpl implements WalletConnectKeyService { privateKey: _getPrivateKeyForWallet(wallet), publicKey: _getPublicKeyForWallet(wallet), ), + ChainKeyModel( + chains: [ + 'solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ', // main-net + 'solana:8E9rvCKLFQia2Y35HXjjpWzj8weVo44K', // test-net + ], + privateKey: _getPrivateKeyForWallet(wallet), + publicKey: _getPublicKeyForWallet(wallet), + ), ]; return keys; } diff --git a/lib/core/wallet_connect/web3wallet_service.dart b/lib/core/wallet_connect/web3wallet_service.dart index ee560a0e0..4c71abe48 100644 --- a/lib/core/wallet_connect/web3wallet_service.dart +++ b/lib/core/wallet_connect/web3wallet_service.dart @@ -2,23 +2,27 @@ import 'dart:async'; import 'dart:developer'; import 'dart:typed_data'; -import 'package:cake_wallet/core/wallet_connect/evm_chain_id.dart'; -import 'package:cake_wallet/core/wallet_connect/evm_chain_service.dart'; +import 'package:cake_wallet/core/wallet_connect/chain_service/eth/evm_chain_id.dart'; +import 'package:cake_wallet/core/wallet_connect/chain_service/eth/evm_chain_service.dart'; import 'package:cake_wallet/core/wallet_connect/wallet_connect_key_service.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/core/wallet_connect/models/auth_request_model.dart'; import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart'; import 'package:cake_wallet/core/wallet_connect/models/session_request_model.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; +import 'package:cake_wallet/solana/solana.dart'; import 'package:cake_wallet/src/screens/wallet_connect/widgets/connection_request_widget.dart'; import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_widget.dart'; import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/web3_request_modal.dart'; import 'package:cake_wallet/store/app_store.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:eth_sig_util/eth_sig_util.dart'; import 'package:flutter/material.dart'; import 'package:mobx/mobx.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; +import 'chain_service/solana/solana_chain_id.dart'; +import 'chain_service/solana/solana_chain_service.dart'; import 'wc_bottom_sheet_service.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; @@ -114,14 +118,34 @@ abstract class Web3WalletServiceBase with Store { final newAuthRequests = _web3Wallet.completeRequests.getAll(); auth.addAll(newAuthRequests); - for (final cId in EVMChainId.values) { - EvmChainServiceImpl( - reference: cId, - appStore: appStore, - wcKeyService: walletKeyService, - bottomSheetService: _bottomSheetHandler, - wallet: _web3Wallet, - ); + if (isEVMCompatibleChain(appStore.wallet!.type)) { + for (final cId in EVMChainId.values) { + EvmChainServiceImpl( + reference: cId, + appStore: appStore, + wcKeyService: walletKeyService, + bottomSheetService: _bottomSheetHandler, + wallet: _web3Wallet, + ); + } + } + + if (appStore.wallet!.type == WalletType.solana) { + for (final cId in SolanaChainId.values) { + final node = appStore.settingsStore.getCurrentNode(appStore.wallet!.type); + final rpcUri = node.uri; + final webSocketUri = 'wss://${node.uriRaw}/ws${node.uri.path}'; + + SolanaChainServiceImpl( + reference: cId, + rpcUrl: rpcUri, + webSocketUrl: webSocketUri, + wcKeyService: walletKeyService, + bottomSheetService: _bottomSheetHandler, + wallet: _web3Wallet, + ownerKeyPair: solana!.getWalletKeyPair(appStore.wallet!), + ); + } } } diff --git a/lib/di.dart b/lib/di.dart index 05019a562..4a005a4de 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -21,6 +21,7 @@ import 'package:cake_wallet/ionia/ionia_gift_card.dart'; import 'package:cake_wallet/ionia/ionia_tip.dart'; import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/solana/solana.dart'; import 'package:cake_wallet/src/screens/anonpay_details/anonpay_details_page.dart'; import 'package:cake_wallet/src/screens/buy/buy_options_page.dart'; import 'package:cake_wallet/src/screens/buy/webview_page.dart'; @@ -863,6 +864,8 @@ Future setup({ return nano!.createNanoWalletService(_walletInfoSource); case WalletType.polygon: return polygon!.createPolygonWalletService(_walletInfoSource); + case WalletType.solana: + return solana!.createSolanaWalletService(_walletInfoSource); default: throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService'); } @@ -1174,7 +1177,7 @@ Future setup({ getIt.registerFactoryParam>( (homeSettingsViewModel, arguments) => EditTokenPage( homeSettingsViewModel: homeSettingsViewModel, - erc20token: arguments['token'] as Erc20Token?, + token: arguments['token'] as CryptoCurrency?, initialContractAddress: arguments['contractAddress'] as String?, ), ); diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 68e76d423..019276227 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -30,6 +30,7 @@ const polygonDefaultNodeUri = 'polygon-bor.publicnode.com'; const cakeWalletBitcoinCashDefaultNodeUri = 'bitcoincash.stackwallet.com:50002'; const nanoDefaultNodeUri = 'rpc.nano.to'; const nanoDefaultPowNodeUri = 'rpc.nano.to'; +const solanaDefaultNodeUri = 'rpc.ankr.com'; Future defaultSettingsMigration( {required int version, @@ -186,10 +187,15 @@ Future defaultSettingsMigration( await rewriteSecureStoragePin(secureStorage: secureStorage); break; case 26: - /// commented out as it was a probable cause for some users to have white screen issues - /// maybe due to multiple access on Secure Storage at once - /// or long await time on start of the app - // await insecureStorageMigration(secureStorage: secureStorage, sharedPreferences: sharedPreferences); + + /// commented out as it was a probable cause for some users to have white screen issues + /// maybe due to multiple access on Secure Storage at once + /// or long await time on start of the app + // await insecureStorageMigration(secureStorage: secureStorage, sharedPreferences: sharedPreferences); + case 27: + await addSolanaNodeList(nodes: nodes); + await changeSolanaCurrentNodeToDefault( + sharedPreferences: sharedPreferences, nodes: nodes); break; default: break; @@ -384,6 +390,11 @@ Node getMoneroDefaultNode({required Box nodes}) { } } +Node? getSolanaDefaultNode({required Box nodes}) { + return nodes.values.firstWhereOrNull((Node node) => node.uriRaw == solanaDefaultNodeUri) ?? + nodes.values.firstWhereOrNull((node) => node.type == WalletType.solana); +} + Future insecureStorageMigration({ required SharedPreferences sharedPreferences, required FlutterSecureStorage secureStorage, @@ -673,6 +684,7 @@ Future checkCurrentNodes( final currentNanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey); final currentBitcoinCashNodeId = sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); + final currentSolanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey); final currentMoneroNode = nodeSource.values.firstWhereOrNull((node) => node.key == currentMoneroNodeId); final currentBitcoinElectrumServer = @@ -691,6 +703,8 @@ Future checkCurrentNodes( powNodeSource.values.firstWhereOrNull((node) => node.key == currentNanoPowNodeId); final currentBitcoinCashNodeServer = nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinCashNodeId); + final currentSolanaNodeServer = + nodeSource.values.firstWhereOrNull((node) => node.key == currentSolanaNodeId); if (currentMoneroNode == null) { final newCakeWalletNode = Node(uri: newCakeWalletMoneroUri, type: WalletType.monero); await nodeSource.add(newCakeWalletNode); @@ -750,6 +764,12 @@ Future checkCurrentNodes( await nodeSource.add(node); await sharedPreferences.setInt(PreferencesKey.currentPolygonNodeIdKey, node.key as int); } + + if (currentSolanaNodeServer == null) { + final node = Node(uri: solanaDefaultNodeUri, type: WalletType.solana); + await nodeSource.add(node); + await sharedPreferences.setInt(PreferencesKey.currentSolanaNodeIdKey, node.key as int); + } } Future resetBitcoinElectrumServer( @@ -861,3 +881,20 @@ Future changePolygonCurrentNodeToDefault( await sharedPreferences.setInt(PreferencesKey.currentPolygonNodeIdKey, nodeId); } + +Future addSolanaNodeList({required Box nodes}) async { + final nodeList = await loadDefaultSolanaNodes(); + for (var node in nodeList) { + if (nodes.values.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) { + await nodes.add(node); + } + } +} + +Future changeSolanaCurrentNodeToDefault( + {required SharedPreferences sharedPreferences, required Box nodes}) async { + final node = getSolanaDefaultNode(nodes: nodes); + final nodeId = node?.key as int? ?? 0; + + await sharedPreferences.setInt(PreferencesKey.currentSolanaNodeIdKey, nodeId); +} diff --git a/lib/entities/node_list.dart b/lib/entities/node_list.dart index aaac8a5c2..3c82a3f6c 100644 --- a/lib/entities/node_list.dart +++ b/lib/entities/node_list.dart @@ -149,6 +149,23 @@ Future> loadDefaultPolygonNodes() async { return nodes; } +Future> loadDefaultSolanaNodes() async { + final nodesRaw = await rootBundle.loadString('assets/solana_node_list.yml'); + final loadedNodes = loadYaml(nodesRaw) as YamlList; + final nodes = []; + + for (final raw in loadedNodes) { + if (raw is Map) { + final node = Node.fromMap(Map.from(raw)); + + node.type = WalletType.solana; + nodes.add(node); + } + } + + return nodes; +} + Future resetToDefault(Box nodeSource) async { final moneroNodes = await loadDefaultNodes(); final bitcoinElectrumServerList = await loadBitcoinElectrumServerList(); @@ -158,6 +175,7 @@ Future resetToDefault(Box nodeSource) async { final ethereumNodes = await loadDefaultEthereumNodes(); final nanoNodes = await loadDefaultNanoNodes(); final polygonNodes = await loadDefaultPolygonNodes(); + final solanaNodes = await loadDefaultSolanaNodes(); final nodes = moneroNodes + bitcoinElectrumServerList + @@ -166,7 +184,8 @@ Future resetToDefault(Box nodeSource) async { ethereumNodes + bitcoinCashElectrumServerList + nanoNodes + - polygonNodes; + polygonNodes + + solanaNodes; await nodeSource.clear(); await nodeSource.addAll(nodes); diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 75e61b5e8..7adb2df7f 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -13,6 +13,7 @@ class PreferencesKey { static const currentBananoPowNodeIdKey = 'current_node_id_banano_pow'; static const currentFiatCurrencyKey = 'current_fiat_currency'; static const currentBitcoinCashNodeIdKey = 'current_node_id_bch'; + static const currentSolanaNodeIdKey = 'current_node_id_sol'; static const currentTransactionPriorityKeyLegacy = 'current_fee_priority'; static const currentBalanceDisplayModeKey = 'current_balance_display_mode'; static const shouldSaveRecipientAddressKey = 'save_recipient_address'; diff --git a/lib/entities/priority_for_wallet_type.dart b/lib/entities/priority_for_wallet_type.dart index 70b072c55..5fc0b5566 100644 --- a/lib/entities/priority_for_wallet_type.dart +++ b/lib/entities/priority_for_wallet_type.dart @@ -21,12 +21,13 @@ List priorityForWalletType(WalletType type) { return ethereum!.getTransactionPriorities(); case WalletType.bitcoinCash: return bitcoinCash!.getTransactionPriorities(); - // no such thing for nano/banano: - case WalletType.nano: - case WalletType.banano: - return []; case WalletType.polygon: return polygon!.getTransactionPriorities(); + // no such thing for nano/banano/solana: + case WalletType.nano: + case WalletType.banano: + case WalletType.solana: + return []; default: return []; } diff --git a/lib/entities/provider_types.dart b/lib/entities/provider_types.dart index ed688590c..9a4b68dd7 100644 --- a/lib/entities/provider_types.dart +++ b/lib/entities/provider_types.dart @@ -67,6 +67,8 @@ class ProvidersHelper { return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood]; case WalletType.polygon: return [ProviderType.askEachTime, ProviderType.dfx]; + case WalletType.solana: + return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood]; case WalletType.none: case WalletType.haven: return []; @@ -88,6 +90,13 @@ class ProvidersHelper { return [ProviderType.askEachTime, ProviderType.moonpaySell]; case WalletType.polygon: return [ProviderType.askEachTime, ProviderType.dfx]; + case WalletType.solana: + return [ + ProviderType.askEachTime, + ProviderType.onramper, + ProviderType.robinhood, + ProviderType.moonpaySell, + ]; case WalletType.monero: case WalletType.nano: case WalletType.banano: diff --git a/lib/ethereum/cw_ethereum.dart b/lib/ethereum/cw_ethereum.dart index d7c174e1a..6e658788e 100644 --- a/lib/ethereum/cw_ethereum.dart +++ b/lib/ethereum/cw_ethereum.dart @@ -119,12 +119,13 @@ class CWEthereum extends Ethereum { } @override - Future addErc20Token(WalletBase wallet, Erc20Token token) async => - await (wallet as EthereumWallet).addErc20Token(token); + Future addErc20Token(WalletBase wallet, CryptoCurrency token) async { + await (wallet as EthereumWallet).addErc20Token(token as Erc20Token); + } @override - Future deleteErc20Token(WalletBase wallet, Erc20Token token) async => - await (wallet as EthereumWallet).deleteErc20Token(token); + Future deleteErc20Token(WalletBase wallet, CryptoCurrency token) async => + await (wallet as EthereumWallet).deleteErc20Token(token as Erc20Token); @override Future getErc20Token(WalletBase wallet, String contractAddress) async { @@ -153,4 +154,6 @@ class CWEthereum extends Ethereum { Web3Client? getWeb3Client(WalletBase wallet) { return (wallet as EthereumWallet).getWeb3Client(); } + + String getTokenAddress(CryptoCurrency asset) => (asset as Erc20Token).contractAddress; } diff --git a/lib/main.dart b/lib/main.dart index 306b109a0..0c8a4c094 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -163,11 +163,11 @@ Future initializeAppConfigs() async { transactionDescriptions: transactionDescriptions, secureStorage: secureStorage, anonpayInvoiceInfo: anonpayInvoiceInfo, - initialMigrationVersion: 26); + initialMigrationVersion: 27); } Future initialSetup( - {required SharedPreferences sharedPreferences, + {required SharedPreferences sharedPreferences, required Box nodes, required Box powNodes, required Box walletInfoSource, diff --git a/lib/polygon/cw_polygon.dart b/lib/polygon/cw_polygon.dart index 6e5fbe2c6..0ee7457eb 100644 --- a/lib/polygon/cw_polygon.dart +++ b/lib/polygon/cw_polygon.dart @@ -119,12 +119,12 @@ class CWPolygon extends Polygon { } @override - Future addErc20Token(WalletBase wallet, Erc20Token token) async => - await (wallet as PolygonWallet).addErc20Token(token); + Future addErc20Token(WalletBase wallet, CryptoCurrency token) async => + await (wallet as PolygonWallet).addErc20Token(token as Erc20Token); @override - Future deleteErc20Token(WalletBase wallet, Erc20Token token) async => - await (wallet as PolygonWallet).deleteErc20Token(token); + Future deleteErc20Token(WalletBase wallet, CryptoCurrency token) async => + await (wallet as PolygonWallet).deleteErc20Token(token as Erc20Token); @override Future getErc20Token(WalletBase wallet, String contractAddress) async { @@ -153,4 +153,6 @@ class CWPolygon extends Polygon { Web3Client? getWeb3Client(WalletBase wallet) { return (wallet as PolygonWallet).getWeb3Client(); } + + String getTokenAddress(CryptoCurrency asset) => (asset as Erc20Token).contractAddress; } diff --git a/lib/reactions/fiat_rate_update.dart b/lib/reactions/fiat_rate_update.dart index 2b757ad44..fb1d4cd1a 100644 --- a/lib/reactions/fiat_rate_update.dart +++ b/lib/reactions/fiat_rate_update.dart @@ -4,9 +4,11 @@ import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/update_haven_rate.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cake_wallet/solana/solana.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/erc20_token.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; @@ -35,7 +37,7 @@ Future startFiatRateUpdate( torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly); } - Iterable? currencies; + Iterable? currencies; if (appStore.wallet!.type == WalletType.ethereum) { currencies = ethereum!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled); @@ -46,6 +48,12 @@ Future startFiatRateUpdate( polygon!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled); } + if (appStore.wallet!.type == WalletType.solana) { + currencies = + solana!.getSPLTokenCurrencies(appStore.wallet!).where((element) => element.enabled); + } + + if (currencies != null) { for (final currency in currencies) { () async { diff --git a/lib/reactions/on_current_wallet_change.dart b/lib/reactions/on_current_wallet_change.dart index ade9927ff..a2f2491f1 100644 --- a/lib/reactions/on_current_wallet_change.dart +++ b/lib/reactions/on_current_wallet_change.dart @@ -3,6 +3,8 @@ import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/update_haven_rate.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cake_wallet/solana/solana.dart'; +import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/erc20_token.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/balance.dart'; @@ -109,7 +111,7 @@ void startCurrentWalletChangeReaction( fiat: settingsStore.fiatCurrency, torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly); - Iterable? currencies; + Iterable? currencies; if (wallet.type == WalletType.ethereum) { currencies = ethereum!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled); @@ -118,7 +120,11 @@ void startCurrentWalletChangeReaction( currencies = polygon!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled); } - + if (wallet.type == WalletType.solana) { + currencies = + solana!.getSPLTokenCurrencies(appStore.wallet!).where((element) => element.enabled); + } + if (currencies != null) { for (final currency in currencies) { () async { diff --git a/lib/reactions/wallet_connect.dart b/lib/reactions/wallet_connect.dart index 4f5923e26..f4487123e 100644 --- a/lib/reactions/wallet_connect.dart +++ b/lib/reactions/wallet_connect.dart @@ -1,4 +1,5 @@ -import 'package:cake_wallet/core/wallet_connect/evm_chain_id.dart'; +import 'package:cake_wallet/core/wallet_connect/chain_service/eth/evm_chain_id.dart'; +import 'package:cake_wallet/core/wallet_connect/chain_service/solana/solana_chain_id.dart'; import 'package:cw_core/wallet_type.dart'; bool isEVMCompatibleChain(WalletType walletType) { @@ -11,12 +12,24 @@ bool isEVMCompatibleChain(WalletType walletType) { } } +bool isWalletConnectCompatibleChain(WalletType walletType) { + switch (walletType) { + case WalletType.polygon: + case WalletType.ethereum: + return true; + default: + return false; + } +} + String getChainNameSpaceAndIdBasedOnWalletType(WalletType walletType) { switch (walletType) { case WalletType.ethereum: return EVMChainId.ethereum.chain(); case WalletType.polygon: return EVMChainId.polygon.chain(); + case WalletType.solana: + return SolanaChainId.mainnet.chain(); default: return ''; } @@ -40,6 +53,8 @@ String getChainNameBasedOnWalletType(WalletType walletType) { return 'eth'; case WalletType.polygon: return 'polygon'; + case WalletType.solana: + return 'solana'; default: return ''; } @@ -51,6 +66,8 @@ String getTokenNameBasedOnWalletType(WalletType walletType) { return 'ETH'; case WalletType.polygon: return 'MATIC'; + case WalletType.solana: + return 'SOL'; default: return ''; } diff --git a/lib/solana/cw_solana.dart b/lib/solana/cw_solana.dart new file mode 100644 index 000000000..a86d6b0c6 --- /dev/null +++ b/lib/solana/cw_solana.dart @@ -0,0 +1,118 @@ +part of 'solana.dart'; + +class CWSolana extends Solana { + @override + List getSolanaWordList(String language) => SolanaMnemonics.englishWordlist; + + WalletService createSolanaWalletService(Box walletInfoSource) => + SolanaWalletService(walletInfoSource); + + @override + WalletCredentials createSolanaNewWalletCredentials({ + required String name, + WalletInfo? walletInfo, + }) => + SolanaNewWalletCredentials(name: name, walletInfo: walletInfo); + + @override + WalletCredentials createSolanaRestoreWalletFromSeedCredentials({ + required String name, + required String mnemonic, + required String password, + }) => + SolanaRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic); + + @override + WalletCredentials createSolanaRestoreWalletFromPrivateKey({ + required String name, + required String privateKey, + required String password, + }) => + SolanaRestoreWalletFromPrivateKey(name: name, password: password, privateKey: privateKey); + + @override + String getAddress(WalletBase wallet) => (wallet as SolanaWallet).walletAddresses.address; + + @override + String getPrivateKey(WalletBase wallet) => (wallet as SolanaWallet).privateKey; + + @override + String getPublicKey(WalletBase wallet) => (wallet as SolanaWallet).keys.publicKey.toBase58(); + + @override + Ed25519HDKeyPair? getWalletKeyPair(WalletBase wallet) => (wallet as SolanaWallet).walletKeyPair; + + Object createSolanaTransactionCredentials( + List outputs, { + required CryptoCurrency currency, + }) => + SolanaTransactionCredentials( + outputs + .map((out) => OutputInfo( + fiatAmount: out.fiatAmount, + cryptoAmount: out.cryptoAmount, + address: out.address, + note: out.note, + sendAll: out.sendAll, + extractedAddress: out.extractedAddress, + isParsedAddress: out.isParsedAddress, + formattedCryptoAmount: out.formattedCryptoAmount)) + .toList(), + currency: currency, + ); + + Object createSolanaTransactionCredentialsRaw( + List outputs, { + required CryptoCurrency currency, + }) => + SolanaTransactionCredentials(outputs, currency: currency); + + @override + List getSPLTokenCurrencies(WalletBase wallet) { + final solanaWallet = wallet as SolanaWallet; + return solanaWallet.splTokenCurrencies; + } + + @override + Future addSPLToken(WalletBase wallet, CryptoCurrency token) async => + await (wallet as SolanaWallet).addSPLToken(token as SPLToken); + + @override + Future deleteSPLToken(WalletBase wallet, CryptoCurrency token) async => + await (wallet as SolanaWallet).deleteSPLToken(token as SPLToken); + + @override + Future getSPLToken(WalletBase wallet, String mintAddress) async { + final solanaWallet = wallet as SolanaWallet; + return await solanaWallet.getSPLToken(mintAddress); + } + + @override + CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) { + transaction as SolanaTransactionInfo; + if (transaction.tokenSymbol == CryptoCurrency.sol.title) { + return CryptoCurrency.sol; + } + + wallet as SolanaWallet; + return wallet.splTokenCurrencies + .firstWhere((element) => transaction.tokenSymbol == element.symbol); + } + + @override + double getTransactionAmountRaw(TransactionInfo transactionInfo) { + return (transactionInfo as SolanaTransactionInfo).solAmount.toDouble(); + } + + @override + String getTokenAddress(CryptoCurrency asset) => (asset as SPLToken).mintAddress; + + @override + List? getValidationLength(CryptoCurrency type) { + if (type is SPLToken) { + return [44]; + } + + return null; + } +} diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart index a81a3f6e4..17a22a88f 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart @@ -37,6 +37,7 @@ class _DesktopWalletSelectionDropDownState extends State Image.asset( @@ -153,6 +154,8 @@ class _DesktopWalletSelectionDropDownState extends State { void initState() { super.initState(); - if (widget.erc20token != null) { - _contractAddressController.text = widget.erc20token!.contractAddress; - _tokenNameController.text = widget.erc20token!.name; - _tokenSymbolController.text = widget.erc20token!.symbol; - _tokenDecimalController.text = widget.erc20token!.decimal.toString(); + String? address; + + if (widget.token != null) { + address = widget.homeSettingsViewModel.getTokenAddressBasedOnWallet(widget.token!); + + _contractAddressController.text = address ?? ''; + _tokenNameController.text = widget.token!.name; + _tokenSymbolController.text = widget.token!.title; + _tokenDecimalController.text = widget.token!.decimals.toString(); } if (widget.initialContractAddress != null) { @@ -91,7 +96,7 @@ class _EditTokenPageBodyState extends State { } final contractAddress = _contractAddressController.text; - if (contractAddress.isNotEmpty && contractAddress != widget.erc20token?.contractAddress) { + if (contractAddress.isNotEmpty && contractAddress != address) { setState(() { _showDisclaimer = true; }); @@ -139,7 +144,9 @@ class _EditTokenPageBodyState extends State { style: TextStyle( fontSize: 14, fontWeight: FontWeight.normal, - color: Theme.of(context).extension()!.detailsTitlesColor, + color: Theme.of(context) + .extension()! + .detailsTitlesColor, ), ), ), @@ -172,12 +179,12 @@ class _EditTokenPageBodyState extends State { Expanded( child: PrimaryButton( onPressed: () async { - if (widget.erc20token != null) { - await widget.homeSettingsViewModel.deleteErc20Token(widget.erc20token!); + if (widget.token != null) { + await widget.homeSettingsViewModel.deleteToken(widget.token!); } Navigator.pop(context); }, - text: widget.erc20token != null ? S.of(context).delete : S.of(context).cancel, + text: widget.token != null ? S.of(context).delete : S.of(context).cancel, color: Colors.red, textColor: Colors.white, ), @@ -188,7 +195,7 @@ class _EditTokenPageBodyState extends State { onPressed: () async { if (_formKey.currentState!.validate() && (!_showDisclaimer || _disclaimerChecked)) { - await widget.homeSettingsViewModel.addErc20Token(Erc20Token( + await widget.homeSettingsViewModel.addToken(Erc20Token( name: _tokenNameController.text, symbol: _tokenSymbolController.text, contractAddress: _contractAddressController.text, @@ -214,14 +221,13 @@ class _EditTokenPageBodyState extends State { void _getTokenInfo() async { if (_contractAddressController.text.isNotEmpty) { - final token = - await widget.homeSettingsViewModel.getErc20Token(_contractAddressController.text); + final token = await widget.homeSettingsViewModel.getToken(_contractAddressController.text); if (token != null) { if (_tokenNameController.text.isEmpty) _tokenNameController.text = token.name; - if (_tokenSymbolController.text.isEmpty) _tokenSymbolController.text = token.symbol; + if (_tokenSymbolController.text.isEmpty) _tokenSymbolController.text = token.title; if (_tokenDecimalController.text.isEmpty) - _tokenDecimalController.text = token.decimal.toString(); + _tokenDecimalController.text = token.decimals.toString(); } } } diff --git a/lib/src/screens/dashboard/home_settings_page.dart b/lib/src/screens/dashboard/home_settings_page.dart index 618ba49ff..e841423c1 100644 --- a/lib/src/screens/dashboard/home_settings_page.dart +++ b/lib/src/screens/dashboard/home_settings_page.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/entities/sort_balance_types.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart'; import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart'; import 'package:cake_wallet/themes/extensions/address_theme.dart'; @@ -117,7 +118,7 @@ class HomeSettingsPage extends BasePage { return SettingsSwitcherCell( title: "${token.name} " - "(${token.symbol})", + "(${token.title})", value: token.enabled, onValueChange: (_, bool value) { _homeSettingsViewModel.changeTokenAvailability(token, value); @@ -128,20 +129,16 @@ class HomeSettingsPage extends BasePage { 'token': token, }); }, - leading: token.iconPath != null - ? Container( - child: Image.asset( - token.iconPath!, - height: 30.0, - width: 30.0, - ), - ) - : Container( + leading: CakeImageWidget( + imageUrl: token.iconPath, + height: 40, + width: 40, + displayOnError: Container( height: 30.0, width: 30.0, child: Center( child: Text( - token.symbol.substring(0, min(token.symbol.length, 2)), + token.title.substring(0, min(token.title.length, 2)), style: TextStyle(fontSize: 11), ), ), @@ -149,7 +146,8 @@ class HomeSettingsPage extends BasePage { shape: BoxShape.circle, color: Colors.grey.shade400, ), - ), + ), + ), decoration: BoxDecoration( color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(30), diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart index 453adccf5..bb3ec70dc 100644 --- a/lib/src/screens/dashboard/pages/balance_page.dart +++ b/lib/src/screens/dashboard/pages/balance_page.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/dashboard/pages/nft_listing_page.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/home_screen_account_widget.dart'; +import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart'; import 'package:cake_wallet/src/widgets/introducing_card.dart'; import 'package:cake_wallet/store/settings_store.dart'; @@ -333,15 +334,11 @@ class BalanceRowWidget extends StatelessWidget { child: Center( child: Column( children: [ - currency.iconPath != null - ? Container( - child: Image.asset( - currency.iconPath!, - height: 40.0, - width: 40.0, - ), - ) - : Container( + CakeImageWidget( + imageUrl: currency.iconPath, + height: 40, + width: 40, + displayOnError: Container( height: 30.0, width: 30.0, child: Center( @@ -355,6 +352,7 @@ class BalanceRowWidget extends StatelessWidget { color: Colors.grey.shade400, ), ), + ), const SizedBox(height: 10), Text( currency.title, diff --git a/lib/src/screens/dashboard/pages/nft_details_page.dart b/lib/src/screens/dashboard/pages/nft_details_page.dart index bb642fd4b..15d2a2b5c 100644 --- a/lib/src/screens/dashboard/pages/nft_details_page.dart +++ b/lib/src/screens/dashboard/pages/nft_details_page.dart @@ -2,7 +2,7 @@ import 'package:cake_wallet/entities/wallet_nft_response.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/menu_widget.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/nft_image_tile_widget.dart'; +import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:cake_wallet/src/widgets/gradient_background.dart'; import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; @@ -94,7 +94,7 @@ class NFTDetailsPage extends BasePage { .syncedBackgroundColor, ), - child: NFTImageWidget( + child: CakeImageWidget( imageUrl: nftAsset.normalizedMetadata?.imageUrl, ), ), diff --git a/lib/src/screens/dashboard/widgets/menu_widget.dart b/lib/src/screens/dashboard/widgets/menu_widget.dart index ed9b823ad..acd666025 100644 --- a/lib/src/screens/dashboard/widgets/menu_widget.dart +++ b/lib/src/screens/dashboard/widgets/menu_widget.dart @@ -18,23 +18,23 @@ class MenuWidget extends StatefulWidget { class MenuWidgetState extends State { MenuWidgetState() - : this.menuWidth = 0, - this.screenWidth = 0, - this.screenHeight = 0, - this.headerHeight = 120, - this.tileHeight = 60, - this.fromTopEdge = 50, - this.fromBottomEdge = 25, - this.moneroIcon = Image.asset('assets/images/monero_menu.png'), - this.bitcoinIcon = Image.asset('assets/images/bitcoin_menu.png'), - this.litecoinIcon = Image.asset('assets/images/litecoin_menu.png'), - this.havenIcon = Image.asset('assets/images/haven_menu.png'), - this.ethereumIcon = Image.asset('assets/images/eth_icon.png'), - this.nanoIcon = Image.asset('assets/images/nano_icon.png'), - this.bananoIcon = Image.asset('assets/images/nano_icon.png'), + : this.menuWidth = 0, + this.screenWidth = 0, + this.screenHeight = 0, + this.headerHeight = 120, + this.tileHeight = 60, + this.fromTopEdge = 50, + this.fromBottomEdge = 25, + this.moneroIcon = Image.asset('assets/images/monero_menu.png'), + this.bitcoinIcon = Image.asset('assets/images/bitcoin_menu.png'), + this.litecoinIcon = Image.asset('assets/images/litecoin_menu.png'), + this.havenIcon = Image.asset('assets/images/haven_menu.png'), + this.ethereumIcon = Image.asset('assets/images/eth_icon.png'), + this.nanoIcon = Image.asset('assets/images/nano_icon.png'), + this.bananoIcon = Image.asset('assets/images/nano_icon.png'), this.bitcoinCashIcon = Image.asset('assets/images/bch_icon.png'), - this.polygonIcon = Image.asset('assets/images/matic_icon.png'); - + this.polygonIcon = Image.asset('assets/images/matic_icon.png'), + this.solanaIcon = Image.asset('assets/images/sol_icon.png'); final largeScreen = 731; @@ -56,7 +56,7 @@ class MenuWidgetState extends State { Image nanoIcon; Image bananoIcon; Image polygonIcon; - + Image solanaIcon; @override void initState() { @@ -224,6 +224,8 @@ class MenuWidgetState extends State { return bananoIcon; case WalletType.polygon: return polygonIcon; + case WalletType.solana: + return solanaIcon; default: throw Exception('No icon for ${type.toString()}'); } diff --git a/lib/src/screens/dashboard/widgets/nft_tile_widget.dart b/lib/src/screens/dashboard/widgets/nft_tile_widget.dart index e7391b970..4c4d214e7 100644 --- a/lib/src/screens/dashboard/widgets/nft_tile_widget.dart +++ b/lib/src/screens/dashboard/widgets/nft_tile_widget.dart @@ -1,9 +1,8 @@ import 'package:cake_wallet/entities/wallet_nft_response.dart'; import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/nft_image_tile_widget.dart'; +import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class NFTTileWidget extends StatelessWidget { @@ -38,7 +37,7 @@ class NFTTileWidget extends StatelessWidget { ), color: Theme.of(context).extension()!.syncedBackgroundColor, ), - child: NFTImageWidget( + child: CakeImageWidget( imageUrl: nftAsset.normalizedMetadata?.imageUrl, ), ), diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 3746118d8..5870b1c4d 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -14,6 +14,7 @@ import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/utils/request_review_handler.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/view_model/send/output.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:mobx/mobx.dart'; @@ -439,10 +440,17 @@ class SendPage extends BasePage { } if (state is TransactionCommitted) { + String alertContent; + if (sendViewModel.walletType == WalletType.solana) { + alertContent = + '${S.of(_dialogContext).send_success(sendViewModel.selectedCryptoCurrency.toString())}. ${S.of(_dialogContext).waitFewSecondForTxUpdate}'; + } else { + alertContent = S.of(_dialogContext).send_success( + sendViewModel.selectedCryptoCurrency.toString()); + } return AlertWithOneAction( alertTitle: '', - alertContent: S.of(_dialogContext).send_success( - sendViewModel.selectedCryptoCurrency.toString()), + alertContent: alertContent, buttonText: S.of(_dialogContext).ok, buttonAction: () { Navigator.of(_dialogContext).pop(); diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 5f15c9c4d..6bd2d81e9 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -321,7 +321,7 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin Navigator.of(context).pushNamed(Routes.walletConnectConnectionsListing), ), diff --git a/lib/src/screens/settings/other_settings_page.dart b/lib/src/screens/settings/other_settings_page.dart index c88804147..fcf683050 100644 --- a/lib/src/screens/settings/other_settings_page.dart +++ b/lib/src/screens/settings/other_settings_page.dart @@ -26,7 +26,7 @@ class OtherSettingsPage extends BasePage { padding: EdgeInsets.only(top: 10), child: Column( children: [ - if (!_otherSettingsViewModel.changeRepresentativeEnabled) + if (_otherSettingsViewModel.displayTransactionPriority) SettingsPickerCell( title: S.current.settings_fee_priority, items: priorityForWalletType(_otherSettingsViewModel.walletType), diff --git a/lib/src/screens/wallet_connect/widgets/pairing_item_widget.dart b/lib/src/screens/wallet_connect/widgets/pairing_item_widget.dart index 063de8ec3..0d425f904 100644 --- a/lib/src/screens/wallet_connect/widgets/pairing_item_widget.dart +++ b/lib/src/screens/wallet_connect/widgets/pairing_item_widget.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/themes/extensions/receive_page_theme.dart'; import 'package:flutter/material.dart'; @@ -26,12 +27,11 @@ class PairingItemWidget extends StatelessWidget { '$year-${month.toString().padLeft(2, '0')}-${day.toString().padLeft(2, '0')}'; return ListTile( - leading: CircleAvatar( - backgroundImage: (metadata.icons.isNotEmpty - ? NetworkImage(metadata.icons[0]) - : const AssetImage( - 'assets/images/default_icon.png', - )) as ImageProvider, + leading: CakeImageWidget( + imageUrl: metadata.icons.isNotEmpty ? metadata.icons[0]: null, + displayOnError: CircleAvatar( + backgroundImage: AssetImage('assets/images/default_icon.png'), + ), ), title: Text( metadata.name, diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index 717bb0a94..b57473cba 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -103,6 +103,7 @@ class WalletListBodyState extends State { final bitcoinCashIcon = Image.asset('assets/images/bch_icon.png', height: 24, width: 24); final nanoIcon = Image.asset('assets/images/nano_icon.png', height: 24, width: 24); final polygonIcon = Image.asset('assets/images/matic_icon.png', height: 24, width: 24); + final solanaIcon = Image.asset('assets/images/sol_icon.png', height: 24, width: 24); final scrollController = ScrollController(); final double tileHeight = 60; Flushbar? _progressBar; @@ -313,6 +314,8 @@ class WalletListBodyState extends State { return nanoIcon; case WalletType.polygon: return polygonIcon; + case WalletType.solana: + return solanaIcon; default: return nonWalletTypeIcon; } diff --git a/lib/src/screens/dashboard/widgets/nft_image_tile_widget.dart b/lib/src/widgets/cake_image_widget.dart similarity index 51% rename from lib/src/screens/dashboard/widgets/nft_image_tile_widget.dart rename to lib/src/widgets/cake_image_widget.dart index d34ff02cb..14c62ad34 100644 --- a/lib/src/screens/dashboard/widgets/nft_image_tile_widget.dart +++ b/lib/src/widgets/cake_image_widget.dart @@ -2,25 +2,45 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -class NFTImageWidget extends StatelessWidget { - const NFTImageWidget({ +class CakeImageWidget extends StatelessWidget { + CakeImageWidget({ required this.imageUrl, - }); + Widget? displayOnError, + this.height, + this.width, + }) : _displayOnError = displayOnError ?? Icon(Icons.error); final String? imageUrl; + final double? height; + final double? width; + final Widget? _displayOnError; @override Widget build(BuildContext context) { try { - if (imageUrl == null) return Icon(Icons.error); + if (imageUrl == null) return _displayOnError!; + + if (imageUrl!.contains('assets/images')) { + return Image.asset( + imageUrl!, + height: height, + width: width, + ); + } if (imageUrl!.contains('.svg')) { - return SvgPicture.network(imageUrl!); + return SvgPicture.network( + imageUrl!, + height: height, + width: width, + ); } return Image.network( imageUrl!, fit: BoxFit.cover, + height: height, + width: width, loadingBuilder: (BuildContext _, Widget child, ImageChunkEvent? loadingProgress) { if (loadingProgress == null) { return child; @@ -31,7 +51,7 @@ class NFTImageWidget extends StatelessWidget { errorBuilder: (_, __, ___) => Icon(Icons.error), ); } catch (_) { - return Icon(Icons.error); + return _displayOnError!; } } } diff --git a/lib/store/app_store.dart b/lib/store/app_store.dart index a5a2b95e0..7d61abfc5 100644 --- a/lib/store/app_store.dart +++ b/lib/store/app_store.dart @@ -41,7 +41,7 @@ abstract class AppStoreBase with Store { this.wallet = wallet; this.wallet!.setExceptionHandler(ExceptionHandler.onError); - if (isEVMCompatibleChain(wallet.type)) { + if (isWalletConnectCompatibleChain(wallet.type)) { await getIt.get().onDispose(); getIt.get().create(); await getIt.get().init(); diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 253adf3ea..672b29269 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -838,6 +838,7 @@ abstract class SettingsStoreBase with Store { final polygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey); final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); final nanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey); + final solanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey); final moneroNode = nodeSource.get(nodeId); final bitcoinElectrumServer = nodeSource.get(bitcoinElectrumServerId); final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId); @@ -847,6 +848,7 @@ abstract class SettingsStoreBase with Store { final bitcoinCashElectrumServer = nodeSource.get(bitcoinCashElectrumServerId); final nanoNode = nodeSource.get(nanoNodeId); final nanoPowNode = powNodeSource.get(nanoPowNodeId); + final solanaNode = nodeSource.get(solanaNodeId); final packageInfo = await PackageInfo.fromPlatform(); final deviceName = await _getDeviceName() ?? ''; final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true; @@ -903,6 +905,10 @@ abstract class SettingsStoreBase with Store { powNodes[WalletType.nano] = nanoPowNode; } + if (solanaNode != null) { + nodes[WalletType.solana] = solanaNode; + } + final savedSyncMode = SyncMode.all.firstWhere((element) { return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 0); }); @@ -1190,6 +1196,7 @@ abstract class SettingsStoreBase with Store { final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey); final polygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey); final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); + final solanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey); final moneroNode = nodeSource.get(nodeId); final bitcoinElectrumServer = nodeSource.get(bitcoinElectrumServerId); final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId); @@ -1198,7 +1205,7 @@ abstract class SettingsStoreBase with Store { final polygonNode = nodeSource.get(polygonNodeId); final bitcoinCashNode = nodeSource.get(bitcoinCashElectrumServerId); final nanoNode = nodeSource.get(nanoNodeId); - + final solanaNode = nodeSource.get(solanaNodeId); if (moneroNode != null) { nodes[WalletType.monero] = moneroNode; } @@ -1231,6 +1238,10 @@ abstract class SettingsStoreBase with Store { nodes[WalletType.nano] = nanoNode; } + if (solanaNode != null) { + nodes[WalletType.solana] = solanaNode; + } + // MIGRATED: useTOTP2FA = await SecureKey.getBool( @@ -1358,6 +1369,9 @@ abstract class SettingsStoreBase with Store { case WalletType.polygon: await _sharedPreferences.setInt(PreferencesKey.currentPolygonNodeIdKey, node.key as int); break; + case WalletType.solana: + await _sharedPreferences.setInt(PreferencesKey.currentSolanaNodeIdKey, node.key as int); + break; default: break; } diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart index 75d7a9eb4..14033b368 100644 --- a/lib/view_model/advanced_privacy_settings_view_model.dart +++ b/lib/view_model/advanced_privacy_settings_view_model.dart @@ -28,7 +28,10 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { final SettingsStore _settingsStore; bool get hasSeedPhraseLengthOption => - type == WalletType.bitcoinCash || type == WalletType.ethereum; + type == WalletType.bitcoinCash || + type == WalletType.ethereum || + type == WalletType.polygon || + type == WalletType.solana; bool get hasSeedTypeOption => type == WalletType.monero; diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index e2c0382b0..eee53516e 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -18,15 +18,15 @@ import 'package:mobx/mobx.dart'; part 'balance_view_model.g.dart'; class BalanceRecord { - const BalanceRecord({ - required this.availableBalance, - required this.additionalBalance, - required this.frozenBalance, - required this.fiatAvailableBalance, - required this.fiatAdditionalBalance, - required this.fiatFrozenBalance, - required this.asset, - required this.formattedAssetTitle}); + const BalanceRecord( + {required this.availableBalance, + required this.additionalBalance, + required this.frozenBalance, + required this.fiatAvailableBalance, + required this.fiatAdditionalBalance, + required this.fiatFrozenBalance, + required this.asset, + required this.formattedAssetTitle}); final String fiatAdditionalBalance; final String fiatAvailableBalance; final String fiatFrozenBalance; @@ -41,12 +41,10 @@ class BalanceViewModel = BalanceViewModelBase with _$BalanceViewModel; abstract class BalanceViewModelBase with Store { BalanceViewModelBase( - {required this.appStore, - required this.settingsStore, - required this.fiatConvertationStore}) - : isReversing = false, - isShowCard = appStore.wallet!.walletInfo.isShowIntroCakePayCard, - wallet = appStore.wallet! { + {required this.appStore, required this.settingsStore, required this.fiatConvertationStore}) + : isReversing = false, + isShowCard = appStore.wallet!.walletInfo.isShowIntroCakePayCard, + wallet = appStore.wallet! { reaction((_) => appStore.wallet, _onWalletChange); } @@ -60,8 +58,7 @@ abstract class BalanceViewModelBase with Store { bool isReversing; @observable - WalletBase, TransactionInfo> - wallet; + WalletBase, TransactionInfo> wallet; @computed double get price { @@ -82,7 +79,8 @@ abstract class BalanceViewModelBase with Store { bool get isFiatDisabled => settingsStore.fiatApiMode == FiatApiMode.disabled; @computed - bool get isHomeScreenSettingsEnabled => isEVMCompatibleChain(wallet.type); + bool get isHomeScreenSettingsEnabled => + isEVMCompatibleChain(wallet.type) || wallet.type == WalletType.solana; @computed bool get hasAccounts => wallet.type == WalletType.monero; @@ -97,7 +95,7 @@ abstract class BalanceViewModelBase with Store { String get asset { final typeFormatted = walletTypeToString(appStore.wallet!.type); - switch(wallet.type) { + switch (wallet.type) { case WalletType.haven: return '$typeFormatted Assets'; default: @@ -120,13 +118,14 @@ abstract class BalanceViewModelBase with Store { @computed String get availableBalanceLabel { - switch(wallet.type) { + switch (wallet.type) { case WalletType.monero: case WalletType.haven: case WalletType.ethereum: case WalletType.polygon: case WalletType.nano: case WalletType.banano: + case WalletType.solana: return S.current.xmr_available_balance; default: return S.current.confirmed; @@ -135,11 +134,12 @@ abstract class BalanceViewModelBase with Store { @computed String get additionalBalanceLabel { - switch(wallet.type) { + switch (wallet.type) { case WalletType.monero: case WalletType.haven: case WalletType.ethereum: case WalletType.polygon: + case WalletType.solana: return S.current.xmr_full_balance; case WalletType.nano: case WalletType.banano: @@ -228,15 +228,17 @@ abstract class BalanceViewModelBase with Store { Map get balances { return wallet.balance.map((key, value) { if (displayMode == BalanceDisplayMode.hiddenBalance) { - return MapEntry(key, BalanceRecord( - availableBalance: '---', - additionalBalance: '---', - frozenBalance: '---', - fiatAdditionalBalance: isFiatDisabled ? '' : '---', - fiatAvailableBalance: isFiatDisabled ? '' : '---', - fiatFrozenBalance: isFiatDisabled ? '' : '---', - asset: key, - formattedAssetTitle: _formatterAsset(key))); + return MapEntry( + key, + BalanceRecord( + availableBalance: '---', + additionalBalance: '---', + frozenBalance: '---', + fiatAdditionalBalance: isFiatDisabled ? '' : '---', + fiatAvailableBalance: isFiatDisabled ? '' : '---', + fiatFrozenBalance: isFiatDisabled ? '' : '---', + asset: key, + formattedAssetTitle: _formatterAsset(key))); } final fiatCurrency = settingsStore.fiatCurrency; final price = fiatConvertationStore.prices[key] ?? 0; @@ -245,25 +247,23 @@ abstract class BalanceViewModelBase with Store { // throw Exception('Price is null for: $key'); // } - final additionalFiatBalance = isFiatDisabled ? '' : (fiatCurrency.toString() - + ' ' - + _getFiatBalance( - price: price, - cryptoAmount: value.formattedAdditionalBalance)); + final additionalFiatBalance = isFiatDisabled + ? '' + : (fiatCurrency.toString() + + ' ' + + _getFiatBalance(price: price, cryptoAmount: value.formattedAdditionalBalance)); - final availableFiatBalance = isFiatDisabled ? '' : (fiatCurrency.toString() - + ' ' - + _getFiatBalance( - price: price, - cryptoAmount: value.formattedAvailableBalance)); - - - final frozenFiatBalance = isFiatDisabled ? '' : (fiatCurrency.toString() - + ' ' - + _getFiatBalance( - price: price, - cryptoAmount: getFormattedFrozenBalance(value))); + final availableFiatBalance = isFiatDisabled + ? '' + : (fiatCurrency.toString() + + ' ' + + _getFiatBalance(price: price, cryptoAmount: value.formattedAvailableBalance)); + final frozenFiatBalance = isFiatDisabled + ? '' + : (fiatCurrency.toString() + + ' ' + + _getFiatBalance(price: price, cryptoAmount: getFormattedFrozenBalance(value))); return MapEntry( key, @@ -276,12 +276,22 @@ abstract class BalanceViewModelBase with Store { fiatFrozenBalance: frozenFiatBalance, asset: key, formattedAssetTitle: _formatterAsset(key))); - }); + }); } @computed - bool get hasAdditionalBalance => !isEVMCompatibleChain(wallet.type); - + bool get hasAdditionalBalance => _hasAdditionBalanceForWalletType(wallet.type); + + bool _hasAdditionBalanceForWalletType(WalletType type) { + switch (type) { + case WalletType.ethereum: + case WalletType.polygon: + case WalletType.solana: + return false; + default: + return true; + } + } @computed List get formattedBalances { @@ -358,9 +368,7 @@ abstract class BalanceViewModelBase with Store { @action void _onWalletChange( - WalletBase, - TransactionInfo>? - wallet) { + WalletBase, TransactionInfo>? wallet) { if (wallet == null) { return; } @@ -371,7 +379,7 @@ abstract class BalanceViewModelBase with Store { } @action - Future disableIntroCakePayCard () async { + Future disableIntroCakePayCard() async { const cardDisplayStatus = false; wallet.walletInfo.showIntroCakePayCard = cardDisplayStatus; await wallet.walletInfo.save(); @@ -401,6 +409,6 @@ abstract class BalanceViewModelBase with Store { } } - String getFormattedFrozenBalance(Balance walletBalance) => walletBalance.formattedUnAvailableBalance; + String getFormattedFrozenBalance(Balance walletBalance) => + walletBalance.formattedUnAvailableBalance; } - diff --git a/lib/view_model/dashboard/home_settings_view_model.dart b/lib/view_model/dashboard/home_settings_view_model.dart index fc2c27a7c..6d31a5af8 100644 --- a/lib/view_model/dashboard/home_settings_view_model.dart +++ b/lib/view_model/dashboard/home_settings_view_model.dart @@ -3,6 +3,7 @@ import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/sort_balance_types.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cake_wallet/solana/solana.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; import 'package:cw_core/crypto_currency.dart'; @@ -16,14 +17,14 @@ class HomeSettingsViewModel = HomeSettingsViewModelBase with _$HomeSettingsViewM abstract class HomeSettingsViewModelBase with Store { HomeSettingsViewModelBase(this._settingsStore, this._balanceViewModel) - : tokens = ObservableSet() { + : tokens = ObservableSet() { _updateTokensList(); } final SettingsStore _settingsStore; final BalanceViewModel _balanceViewModel; - final ObservableSet tokens; + final ObservableSet tokens; @observable String searchText = ''; @@ -43,7 +44,7 @@ abstract class HomeSettingsViewModelBase with Store { @action void setPinNativeToken(bool value) => _settingsStore.pinNativeTokenAtTop = value; - Future addErc20Token(Erc20Token token) async { + Future addToken(CryptoCurrency token) async { if (_balanceViewModel.wallet.type == WalletType.ethereum) { await ethereum!.addErc20Token(_balanceViewModel.wallet, token); } @@ -52,23 +53,31 @@ abstract class HomeSettingsViewModelBase with Store { await polygon!.addErc20Token(_balanceViewModel.wallet, token); } + if (_balanceViewModel.wallet.type == WalletType.solana) { + await solana!.addSPLToken(_balanceViewModel.wallet, token); + } + _updateTokensList(); _updateFiatPrices(token); } - Future deleteErc20Token(Erc20Token token) async { + Future deleteToken(CryptoCurrency token) async { if (_balanceViewModel.wallet.type == WalletType.ethereum) { - await ethereum!.deleteErc20Token(_balanceViewModel.wallet, token); + await ethereum!.deleteErc20Token(_balanceViewModel.wallet, token as Erc20Token); } if (_balanceViewModel.wallet.type == WalletType.polygon) { - await polygon!.deleteErc20Token(_balanceViewModel.wallet, token); + await polygon!.deleteErc20Token(_balanceViewModel.wallet, token as Erc20Token); + } + + if (_balanceViewModel.wallet.type == WalletType.solana) { + await solana!.deleteSPLToken(_balanceViewModel.wallet, token); } _updateTokensList(); } - Future getErc20Token(String contractAddress) async { + Future getToken(String contractAddress) async { if (_balanceViewModel.wallet.type == WalletType.ethereum) { return await ethereum!.getErc20Token(_balanceViewModel.wallet, contractAddress); } @@ -77,12 +86,16 @@ abstract class HomeSettingsViewModelBase with Store { return await polygon!.getErc20Token(_balanceViewModel.wallet, contractAddress); } + if (_balanceViewModel.wallet.type == WalletType.solana) { + return await solana!.getSPLToken(_balanceViewModel.wallet, contractAddress); + } + return null; } CryptoCurrency get nativeToken => _balanceViewModel.wallet.currency; - void _updateFiatPrices(Erc20Token token) async { + void _updateFiatPrices(CryptoCurrency token) async { try { _balanceViewModel.fiatConvertationStore.prices[token] = await FiatConversionService.fetchPrice( @@ -92,20 +105,27 @@ abstract class HomeSettingsViewModelBase with Store { } catch (_) {} } - void changeTokenAvailability(Erc20Token token, bool value) async { + void changeTokenAvailability(CryptoCurrency token, bool value) async { token.enabled = value; + if (_balanceViewModel.wallet.type == WalletType.ethereum) { - ethereum!.addErc20Token(_balanceViewModel.wallet, token); + ethereum!.addErc20Token(_balanceViewModel.wallet, token as Erc20Token); } + if (_balanceViewModel.wallet.type == WalletType.polygon) { - polygon!.addErc20Token(_balanceViewModel.wallet, token); + polygon!.addErc20Token(_balanceViewModel.wallet, token as Erc20Token); } + + if (_balanceViewModel.wallet.type == WalletType.solana) { + solana!.addSPLToken(_balanceViewModel.wallet, token); + } + _refreshTokensList(); } @action void _updateTokensList() { - int _sortFunc(Erc20Token e1, Erc20Token e2) { + int _sortFunc(CryptoCurrency e1, CryptoCurrency e2) { int index1 = _balanceViewModel.formattedBalances.indexWhere((element) => element.asset == e1); int index2 = _balanceViewModel.formattedBalances.indexWhere((element) => element.asset == e2); @@ -138,6 +158,14 @@ abstract class HomeSettingsViewModelBase with Store { .toList() ..sort(_sortFunc)); } + + if (_balanceViewModel.wallet.type == WalletType.solana) { + tokens.addAll(solana! + .getSPLTokenCurrencies(_balanceViewModel.wallet) + .where((element) => _matchesSearchText(element)) + .toList() + ..sort(_sortFunc)); + } } @action @@ -153,10 +181,32 @@ abstract class HomeSettingsViewModelBase with Store { _updateTokensList(); } - bool _matchesSearchText(Erc20Token asset) { + bool _matchesSearchText(CryptoCurrency asset) { + final address = getTokenAddressBasedOnWallet(asset); + + // The homes settings would only be displayed for either of Ethereum, Polygon or Solana Wallets. + if (address == null) return false; + return searchText.isEmpty || asset.fullName!.toLowerCase().contains(searchText.toLowerCase()) || asset.title.toLowerCase().contains(searchText.toLowerCase()) || - asset.contractAddress == searchText; + address == searchText; + } + + String? getTokenAddressBasedOnWallet(CryptoCurrency asset) { + if (_balanceViewModel.wallet.type == WalletType.solana) { + return solana!.getTokenAddress(asset); + } + + if (_balanceViewModel.wallet.type == WalletType.ethereum) { + return ethereum!.getTokenAddress(asset); + } + + if (_balanceViewModel.wallet.type == WalletType.polygon) { + return polygon!.getTokenAddress(asset); + } + + // We return null if it's neither Polygin, Ethereum or Solana wallet (which is actually impossible because we only display home settings for either of these three wallets). + return null; } } diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart index d8c4776b7..99de14a18 100644 --- a/lib/view_model/dashboard/transaction_list_item.dart +++ b/lib/view_model/dashboard/transaction_list_item.dart @@ -4,6 +4,7 @@ import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cake_wallet/solana/solana.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cake_wallet/store/settings_store.dart'; @@ -105,6 +106,14 @@ class TransactionListItem extends ActionListItem with Keyable { nano!.getTransactionAmountRaw(transaction).toString(), nanoUtil!.rawPerNano)), price: price); break; + case WalletType.solana: + final asset = solana!.assetOfTransaction(balanceViewModel.wallet, transaction); + final price = balanceViewModel.fiatConvertationStore.prices[asset]; + amount = calculateFiatAmountRaw( + cryptoAmount: solana!.getTransactionAmountRaw(transaction), + price: price, + ); + break; default: break; } diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index afe617803..1540ebef3 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -625,6 +625,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with depositCurrency = CryptoCurrency.maticpoly; receiveCurrency = CryptoCurrency.xmr; break; + case WalletType.solana: + depositCurrency = CryptoCurrency.sol; + receiveCurrency = CryptoCurrency.xmr; + break; default: break; } diff --git a/lib/view_model/node_list/node_list_view_model.dart b/lib/view_model/node_list/node_list_view_model.dart index 0cd4d7491..5526cc6d2 100644 --- a/lib/view_model/node_list/node_list_view_model.dart +++ b/lib/view_model/node_list/node_list_view_model.dart @@ -75,6 +75,9 @@ abstract class NodeListViewModelBase with Store { case WalletType.polygon: node = getPolygonDefaultNode(nodes: _nodeSource)!; break; + case WalletType.solana: + node = getSolanaDefaultNode(nodes: _nodeSource)!; + break; default: throw Exception('Unexpected wallet type: ${_appStore.wallet!.type}'); } diff --git a/lib/view_model/restore/restore_from_qr_vm.dart b/lib/view_model/restore/restore_from_qr_vm.dart index c8637c4be..31f0bfdd2 100644 --- a/lib/view_model/restore/restore_from_qr_vm.dart +++ b/lib/view_model/restore/restore_from_qr_vm.dart @@ -3,6 +3,7 @@ import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cake_wallet/solana/solana.dart'; import 'package:cake_wallet/view_model/restore/restore_mode.dart'; import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; import 'package:hive/hive.dart'; @@ -75,6 +76,9 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store case WalletType.polygon: return polygon!.createPolygonRestoreWalletFromPrivateKey( name: name, password: password, privateKey: restoreWallet.privateKey!); + case WalletType.solana: + return solana!.createSolanaRestoreWalletFromPrivateKey( + name: name, password: password, privateKey: restoreWallet.privateKey!); default: throw Exception('Unexpected type: ${restoreWallet.type.toString()}'); } @@ -102,6 +106,9 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store case WalletType.polygon: return polygon!.createPolygonRestoreWalletFromSeedCredentials( name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); + case WalletType.solana: + return solana!.createSolanaRestoreWalletFromSeedCredentials( + name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); default: throw Exception('Unexpected type: ${type.toString()}'); } diff --git a/lib/view_model/restore/wallet_restore_from_qr_code.dart b/lib/view_model/restore/wallet_restore_from_qr_code.dart index bfc9b7980..925c08cca 100644 --- a/lib/view_model/restore/wallet_restore_from_qr_code.dart +++ b/lib/view_model/restore/wallet_restore_from_qr_code.dart @@ -32,6 +32,7 @@ class WalletRestoreFromQRCode { 'bitcoincash': WalletType.bitcoinCash, 'bitcoincash-wallet': WalletType.bitcoinCash, 'bitcoincash_wallet': WalletType.bitcoinCash, + 'solana-wallet': WalletType.solana, }; static bool _containsAssetSpecifier(String code) => _extractWalletType(code) != null; @@ -175,6 +176,14 @@ class WalletRestoreFromQRCode { return WalletRestoreMode.seed; } + if (type == WalletType.solana && credentials.containsKey('private_key')) { + final privateKey = credentials['private_key'] as String; + if (privateKey.isEmpty) { + throw Exception('Unexpected restore mode: private_key'); + } + return WalletRestoreMode.keys; + } + throw Exception('Unexpected restore mode: restore params are invalid'); } } diff --git a/lib/view_model/send/output.dart b/lib/view_model/send/output.dart index e40000139..cc39aca8b 100644 --- a/lib/view_model/send/output.dart +++ b/lib/view_model/send/output.dart @@ -148,9 +148,8 @@ abstract class OutputBase with Store { @computed String get estimatedFeeFiatAmount { try { - final currency = isEVMCompatibleChain(_wallet.type) - ? _wallet.currency - : cryptoCurrencyHandler(); + final currency = + isEVMCompatibleChain(_wallet.type) ? _wallet.currency : cryptoCurrencyHandler(); final fiat = calculateFiatAmountRaw( price: _fiatConversationStore.prices[currency]!, cryptoAmount: estimatedFee); return fiat; @@ -220,7 +219,6 @@ abstract class OutputBase with Store { final crypto = double.parse(fiatAmount.replaceAll(',', '.')) / _fiatConversationStore.prices[cryptoCurrencyHandler()]!; final cryptoAmountTmp = _cryptoNumberFormat.format(crypto); - if (cryptoAmount != cryptoAmountTmp) { cryptoAmount = cryptoAmountTmp; } @@ -252,6 +250,9 @@ abstract class OutputBase with Store { case WalletType.polygon: maximumFractionDigits = 12; break; + case WalletType.solana: + maximumFractionDigits = 12; + break; default: break; } diff --git a/lib/view_model/send/send_template_view_model.dart b/lib/view_model/send/send_template_view_model.dart index 007c4b8c0..f79fbddc7 100644 --- a/lib/view_model/send/send_template_view_model.dart +++ b/lib/view_model/send/send_template_view_model.dart @@ -52,7 +52,8 @@ abstract class SendTemplateViewModelBase with Store { bool get hasMultiRecipient => _wallet.type != WalletType.haven && _wallet.type != WalletType.ethereum && - _wallet.type != WalletType.polygon; + _wallet.type != WalletType.polygon && + _wallet.type != WalletType.solana; @computed CryptoCurrency get cryptoCurrency => _wallet.currency; diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 885e2efe0..772150368 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -7,6 +7,7 @@ import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/entities/wallet_contact.dart'; import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; +import 'package:cake_wallet/solana/solana.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; @@ -44,7 +45,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor void onWalletChange(wallet) { currencies = wallet.balance.keys.toList(); selectedCryptoCurrency = wallet.currency; - hasMultipleTokens = isEVMCompatibleChain(wallet.type); + hasMultipleTokens = isEVMCompatibleChain(wallet.type) || wallet.type == WalletType.solana; } SendViewModelBase( @@ -57,7 +58,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor ) : state = InitialExecutionState(), currencies = appStore.wallet!.balance.keys.toList(), selectedCryptoCurrency = appStore.wallet!.currency, - hasMultipleTokens = isEVMCompatibleChain(appStore.wallet!.type), + hasMultipleTokens = isEVMCompatibleChain(appStore.wallet!.type) || + appStore.wallet!.type == WalletType.solana, outputs = ObservableList(), _settingsStore = appStore.settingsStore, fiatFromSettings = appStore.settingsStore.fiatCurrency, @@ -100,6 +102,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor @computed bool get isBatchSending => outputs.length > 1; + bool get shouldDisplaySendALL => walletType != WalletType.solana; + @computed String get pendingTransactionFiatAmount { if (pendingTransaction == null) { @@ -297,6 +301,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor pendingTransaction = await wallet.createTransaction(_credentials()); state = ExecutedSuccessfullyState(); } catch (e) { + print('Failed with ${e.toString()}'); state = FailureState(e.toString()); } } @@ -351,7 +356,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor Object _credentials() { final priority = _settingsStore.priority[wallet.type]; - if (priority == null && wallet.type != WalletType.nano) { + if (priority == null && wallet.type != WalletType.nano && wallet.type != WalletType.solana) { throw Exception('Priority is null for wallet type: ${wallet.type}'); } @@ -377,6 +382,9 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor case WalletType.polygon: return polygon!.createPolygonTransactionCredentials(outputs, priority: priority!, currency: selectedCryptoCurrency); + case WalletType.solana: + return solana! + .createSolanaTransactionCredentials(outputs, currency: selectedCryptoCurrency); default: throw Exception('Unexpected wallet type: ${wallet.type}'); } diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart index e44eb8fc7..263532d29 100644 --- a/lib/view_model/settings/other_settings_view_model.dart +++ b/lib/view_model/settings/other_settings_view_model.dart @@ -14,15 +14,14 @@ import 'package:package_info/package_info.dart'; part 'other_settings_view_model.g.dart'; -class OtherSettingsViewModel = OtherSettingsViewModelBase - with _$OtherSettingsViewModel; +class OtherSettingsViewModel = OtherSettingsViewModelBase with _$OtherSettingsViewModel; abstract class OtherSettingsViewModelBase with Store { OtherSettingsViewModelBase(this._settingsStore, this._wallet) : walletType = _wallet.type, currentVersion = '' { - PackageInfo.fromPlatform().then( - (PackageInfo packageInfo) => currentVersion = packageInfo.version); + PackageInfo.fromPlatform() + .then((PackageInfo packageInfo) => currentVersion = packageInfo.version); final priority = _settingsStore.priority[_wallet.type]; final priorities = priorityForWalletType(_wallet.type); @@ -33,8 +32,7 @@ abstract class OtherSettingsViewModelBase with Store { } final WalletType walletType; - final WalletBase, - TransactionInfo> _wallet; + final WalletBase, TransactionInfo> _wallet; @observable String currentVersion; @@ -57,12 +55,14 @@ abstract class OtherSettingsViewModelBase with Store { _wallet.type == WalletType.nano || _wallet.type == WalletType.banano; @computed - bool get isEnabledBuyAction => - !_settingsStore.disableBuy && _wallet.type != WalletType.haven; + bool get displayTransactionPriority => + !(changeRepresentativeEnabled || _wallet.type == WalletType.solana); @computed - bool get isEnabledSellAction => - !_settingsStore.disableSell && _wallet.type != WalletType.haven; + bool get isEnabledBuyAction => !_settingsStore.disableBuy && _wallet.type != WalletType.haven; + + @computed + bool get isEnabledSellAction => !_settingsStore.disableSell && _wallet.type != WalletType.haven; List get availableBuyProvidersTypes { return ProvidersHelper.getAvailableBuyProviderTypes(walletType); @@ -72,12 +72,10 @@ abstract class OtherSettingsViewModelBase with Store { ProvidersHelper.getAvailableSellProviderTypes(walletType); ProviderType get buyProviderType => - _settingsStore.defaultBuyProviders[walletType] ?? - ProviderType.askEachTime; + _settingsStore.defaultBuyProviders[walletType] ?? ProviderType.askEachTime; ProviderType get sellProviderType => - _settingsStore.defaultSellProviders[walletType] ?? - ProviderType.askEachTime; + _settingsStore.defaultSellProviders[walletType] ?? ProviderType.askEachTime; String getDisplayPriority(dynamic priority) { final _priority = priority as TransactionPriority; @@ -114,7 +112,6 @@ abstract class OtherSettingsViewModelBase with Store { _settingsStore.defaultBuyProviders[walletType] = buyProviderType; @action - ProviderType onSellProviderTypeSelected( - ProviderType sellProviderType) => + ProviderType onSellProviderTypeSelected(ProviderType sellProviderType) => _settingsStore.defaultSellProviders[walletType] = sellProviderType; } diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index a3bf281ca..04eaf25e4 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -54,6 +54,9 @@ abstract class TransactionDetailsViewModelBase with Store { case WalletType.polygon: _addPolygonListItems(tx, dateFormat); break; + case WalletType.solana: + _addSolanaListItems(tx, dateFormat); + break; default: break; } @@ -131,6 +134,8 @@ abstract class TransactionDetailsViewModelBase with Store { return 'https://bananolooker.com/block/${txId}'; case WalletType.polygon: return 'https://polygonscan.com/tx/${txId}'; + case WalletType.solana: + return 'https://solscan.io/tx/${txId}'; default: return ''; } @@ -155,6 +160,8 @@ abstract class TransactionDetailsViewModelBase with Store { return S.current.view_transaction_on + 'bananolooker.com'; case WalletType.polygon: return S.current.view_transaction_on + 'polygonscan.com'; + case WalletType.solana: + return S.current.view_transaction_on + 'solscan.io'; default: return ''; } @@ -281,4 +288,21 @@ abstract class TransactionDetailsViewModelBase with Store { items.addAll(_items); } + + void _addSolanaListItems(TransactionInfo tx, DateFormat dateFormat) { + final _items = [ + StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.id), + StandartListItem( + title: S.current.transaction_details_date, value: dateFormat.format(tx.date)), + StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()), + if (tx.feeFormatted()?.isNotEmpty ?? false) + StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!), + if (showRecipientAddress && tx.to != null) + StandartListItem(title: S.current.transaction_details_recipient_address, value: tx.to!), + if (tx.from != null) + StandartListItem(title: S.current.transaction_details_source_address, value: tx.from!), + ]; + + items.addAll(_items); + } } diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index 9270d1d44..bde535a23 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -7,6 +7,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/haven/haven.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cake_wallet/solana/solana.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; import 'package:cake_wallet/store/settings_store.dart'; @@ -159,6 +160,21 @@ class PolygonURI extends PaymentURI { } } +class SolanaURI extends PaymentURI { + SolanaURI({required String amount, required String address}) + : super(amount: amount, address: address); + + @override + String toString() { + var base = 'solana:' + address; + if (amount.isNotEmpty) { + base += '?amount=${amount.replaceAll(',', '.')}'; + } + + return base; + } +} + abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewModel with Store { WalletAddressListViewModelBase({ required AppStore appStore, @@ -257,6 +273,10 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo return PolygonURI(amount: amount, address: address.address); } + if (wallet.type == WalletType.solana) { + return SolanaURI(amount: amount, address: address.address); + } + throw Exception('Unexpected type: ${type.toString()}'); } @@ -326,6 +346,12 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo addressList.add(WalletAddressListItem(isPrimary: true, name: null, address: primaryAddress)); } + if (wallet.type == WalletType.solana) { + final primaryAddress = solana!.getAddress(wallet); + + addressList.add(WalletAddressListItem(isPrimary: true, name: null, address: primaryAddress)); + } + if (searchText.isNotEmpty) { return ObservableList.of(addressList.where((item) { if (item is WalletAddressListItem) { diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart index f931fec19..a84f1a4c4 100644 --- a/lib/view_model/wallet_keys_view_model.dart +++ b/lib/view_model/wallet_keys_view_model.dart @@ -110,7 +110,8 @@ abstract class WalletKeysViewModelBase with Store { ]); } - if (isEVMCompatibleChain(_appStore.wallet!.type)) { + if (isEVMCompatibleChain(_appStore.wallet!.type) || + _appStore.wallet!.type == WalletType.solana) { items.addAll([ if (_appStore.wallet!.privateKey != null) StandartListItem(title: S.current.private_key, value: _appStore.wallet!.privateKey!), @@ -165,6 +166,8 @@ abstract class WalletKeysViewModelBase with Store { return 'banano-wallet'; case WalletType.polygon: return 'polygon-wallet'; + case WalletType.solana: + return 'solana-wallet'; default: throw Exception('Unexpected wallet type: ${_appStore.wallet!.toString()}'); } diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart index d4a0c4c00..6f3e0280e 100644 --- a/lib/view_model/wallet_new_vm.dart +++ b/lib/view_model/wallet_new_vm.dart @@ -1,5 +1,6 @@ import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; +import 'package:cake_wallet/solana/solana.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/monero/monero.dart'; @@ -36,19 +37,21 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { bool get hasLanguageSelector => type == WalletType.monero || type == WalletType.haven; int get seedPhraseWordsLength { - switch (type) { - case WalletType.monero: - if(advancedPrivacySettingsViewModel.isPolySeed) { - return 16; - } - return 25; - case WalletType.ethereum: - case WalletType.bitcoinCash: - return advancedPrivacySettingsViewModel.seedPhraseLength.value; - default: - return 24; - } + switch (type) { + case WalletType.monero: + if (advancedPrivacySettingsViewModel.isPolySeed) { + return 16; + } + return 25; + case WalletType.solana: + case WalletType.polygon: + case WalletType.ethereum: + case WalletType.bitcoinCash: + return advancedPrivacySettingsViewModel.seedPhraseLength.value; + default: + return 24; } + } bool get hasSeedType => type == WalletType.monero; @@ -64,8 +67,8 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { case WalletType.litecoin: return bitcoin!.createBitcoinNewWalletCredentials(name: name); case WalletType.haven: - return haven!.createHavenNewWalletCredentials( - name: name, language: options!.first as String); + return haven! + .createHavenNewWalletCredentials(name: name, language: options!.first as String); case WalletType.ethereum: return ethereum!.createEthereumNewWalletCredentials(name: name); case WalletType.bitcoinCash: @@ -74,6 +77,8 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { return nano!.createNanoNewWalletCredentials(name: name); case WalletType.polygon: return polygon!.createPolygonNewWalletCredentials(name: name); + case WalletType.solana: + return solana!.createSolanaNewWalletCredentials(name: name); default: throw Exception('Unexpected type: ${type.toString()}'); } diff --git a/lib/view_model/wallet_restore_view_model.dart b/lib/view_model/wallet_restore_view_model.dart index 8d1e3b223..98dce3d92 100644 --- a/lib/view_model/wallet_restore_view_model.dart +++ b/lib/view_model/wallet_restore_view_model.dart @@ -4,6 +4,7 @@ import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cake_wallet/solana/solana.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/store/app_store.dart'; @@ -28,11 +29,11 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { {required WalletType type}) : hasSeedLanguageSelector = type == WalletType.monero || type == WalletType.haven, hasBlockchainHeightLanguageSelector = type == WalletType.monero || type == WalletType.haven, - hasRestoreFromPrivateKey = - type == WalletType.ethereum || + hasRestoreFromPrivateKey = type == WalletType.ethereum || type == WalletType.polygon || type == WalletType.nano || - type == WalletType.banano, + type == WalletType.banano || + type == WalletType.solana, isButtonEnabled = false, mode = WalletRestoreMode.seed, super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: true) { @@ -45,6 +46,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { break; case WalletType.nano: case WalletType.banano: + case WalletType.solana: availableModes = [WalletRestoreMode.seed, WalletRestoreMode.keys]; break; default: @@ -98,22 +100,21 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { name: name, height: height, mnemonic: seed, password: password); case WalletType.ethereum: return ethereum!.createEthereumRestoreWalletFromSeedCredentials( - name: name, - mnemonic: seed, - password: password); + name: name, mnemonic: seed, password: password); case WalletType.bitcoinCash: return bitcoinCash!.createBitcoinCashRestoreWalletFromSeedCredentials( - name: name, - mnemonic: seed, - password: password); + name: name, mnemonic: seed, password: password); case WalletType.nano: return nano!.createNanoRestoreWalletFromSeedCredentials( + name: name, mnemonic: seed, password: password, derivationType: derivationType); + case WalletType.polygon: + return polygon!.createPolygonRestoreWalletFromSeedCredentials( name: name, mnemonic: seed, password: password, - derivationType: derivationType); - case WalletType.polygon: - return polygon!.createPolygonRestoreWalletFromSeedCredentials( + ); + case WalletType.solana: + return solana!.createSolanaRestoreWalletFromSeedCredentials( name: name, mnemonic: seed, password: password, @@ -160,16 +161,22 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { case WalletType.nano: return nano!.createNanoRestoreWalletFromKeysCredentials( - name: name, - password: password, - seedKey: options['private_key'] as String, - derivationType: options["derivationType"] as DerivationType); + name: name, + password: password, + seedKey: options['private_key'] as String, + derivationType: options["derivationType"] as DerivationType); case WalletType.polygon: return polygon!.createPolygonRestoreWalletFromPrivateKey( name: name, password: password, privateKey: options['private_key'] as String, ); + case WalletType.solana: + return solana!.createSolanaRestoreWalletFromPrivateKey( + name: name, + password: password, + privateKey: options['private_key'] as String, + ); default: break; } @@ -187,10 +194,8 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { switch (type) { case WalletType.nano: - return nanoUtil!.compareDerivationMethods( - mnemonic: mnemonic, - privateKey: seedKey, - node: node); + return nanoUtil! + .compareDerivationMethods(mnemonic: mnemonic, privateKey: seedKey, node: node); default: break; } diff --git a/model_generator.sh b/model_generator.sh index a2b016bb0..8a6098621 100755 --- a/model_generator.sh +++ b/model_generator.sh @@ -5,6 +5,7 @@ cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_solana && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_ethereum && flutter pub get && cd .. cd cw_polygon && flutter pub get && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs diff --git a/pubspec_base.yaml b/pubspec_base.yaml index f38482ec3..758287601 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -106,6 +106,7 @@ dependencies: flutter_svg: ^2.0.9 polyseed: ^0.0.2 nostr_tools: ^1.0.9 + solana: ^0.30.1 dev_dependencies: flutter_test: @@ -152,6 +153,7 @@ flutter: - assets/nano_node_list.yml - assets/nano_pow_node_list.yml - assets/polygon_node_list.yml + - assets/solana_node_list.yml - assets/text/ - assets/faq/ - assets/animation/ diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 553262f79..3e3f595be 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -778,5 +778,6 @@ "you_pay": "انت تدفع", "you_will_get": "حول الى", "you_will_send": "تحويل من", - "yy": "YY" -} \ No newline at end of file + "yy": "YY", + "waitFewSecondForTxUpdate": "ﺕﻼﻣﺎﻌﻤﻟﺍ ﻞﺠﺳ ﻲﻓ ﺔﻠﻣﺎﻌﻤﻟﺍ ﺲﻜﻌﻨﺗ ﻰﺘﺣ ﻥﺍﻮﺛ ﻊﻀﺒﻟ ﺭﺎﻈﺘﻧﻻﺍ ﻰﺟﺮﻳ" +} diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 8d89f463b..9d64e36ae 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -778,5 +778,6 @@ "you_pay": "Вие плащате", "you_will_get": "Обръщане в", "you_will_send": "Обръщане от", - "yy": "гг" -} \ No newline at end of file + "yy": "гг", + "waitFewSecondForTxUpdate": "Моля, изчакайте няколко секунди, докато транзакцията се отрази в историята на транзакциите" +} diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index e81eab570..8665efc2c 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -778,5 +778,6 @@ "you_pay": "Zaplatíte", "you_will_get": "Směnit na", "you_will_send": "Směnit z", - "yy": "YY" -} \ No newline at end of file + "yy": "YY", + "waitFewSecondForTxUpdate": "Počkejte několik sekund, než se transakce projeví v historii transakcí" +} diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 3ca972af4..28e3d4996 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -781,5 +781,6 @@ "you_pay": "Sie bezahlen", "you_will_get": "Konvertieren zu", "you_will_send": "Konvertieren von", - "yy": "YY" -} \ No newline at end of file + "yy": "YY", + "waitFewSecondForTxUpdate": "Bitte warten Sie einige Sekunden, bis die Transaktion im Transaktionsverlauf angezeigt wird" +} diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 2db7602c1..aae06f6b0 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -778,5 +778,6 @@ "you_pay": "You Pay", "you_will_get": "Convert to", "you_will_send": "Convert from", - "yy": "YY" -} \ No newline at end of file + "yy": "YY", + "waitFewSecondForTxUpdate": "Kindly wait for a few seconds for transaction to reflect in transactions history" +} diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 5ca5ff4d3..d9e786467 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -779,5 +779,6 @@ "you_pay": "Tú pagas", "you_will_get": "Convertir a", "you_will_send": "Convertir de", - "yy": "YY" -} \ No newline at end of file + "yy": "YY", + "waitFewSecondForTxUpdate": "Espere unos segundos para que la transacción se refleje en el historial de transacciones." +} diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index aee967d21..8b4fc10d1 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -778,5 +778,6 @@ "you_pay": "Vous payez", "you_will_get": "Convertir vers", "you_will_send": "Convertir depuis", - "yy": "AA" -} \ No newline at end of file + "yy": "AA", + "waitFewSecondForTxUpdate": "Veuillez attendre quelques secondes pour que la transaction soit reflétée dans l'historique des transactions." +} diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index dfffa8a8b..6d1a5db0c 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -780,5 +780,6 @@ "you_pay": "Ka Bayar", "you_will_get": "Maida zuwa", "you_will_send": "Maida daga", - "yy": "YY" -} \ No newline at end of file + "yy": "YY", + "waitFewSecondForTxUpdate": "Da fatan za a jira ƴan daƙiƙa don ciniki don yin tunani a tarihin ma'amala" +} diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index e67b00726..eaeffab92 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -780,5 +780,6 @@ "you_pay": "आप भुगतान करते हैं", "you_will_get": "में बदलें", "you_will_send": "से रूपांतरित करें", - "yy": "वाईवाई" -} \ No newline at end of file + "yy": "वाईवाई", + "waitFewSecondForTxUpdate": "लेन-देन इतिहास में लेन-देन प्रतिबिंबित होने के लिए कृपया कुछ सेकंड प्रतीक्षा करें" +} diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index c2fee8420..a915030f4 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -778,5 +778,6 @@ "you_pay": "Vi plaćate", "you_will_get": "Razmijeni u", "you_will_send": "Razmijeni iz", - "yy": "GG" -} \ No newline at end of file + "yy": "GG", + "waitFewSecondForTxUpdate": "Pričekajte nekoliko sekundi da se transakcija prikaže u povijesti transakcija" +} diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 28a7df3c9..ed53b7e62 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -781,5 +781,6 @@ "you_pay": "Anda Membayar", "you_will_get": "Konversi ke", "you_will_send": "Konversi dari", - "yy": "YY" -} \ No newline at end of file + "yy": "YY", + "waitFewSecondForTxUpdate": "Mohon tunggu beberapa detik hingga transaksi terlihat di riwayat transaksi" +} diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 42f0b8d86..d83619855 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -781,5 +781,6 @@ "you_pay": "Tu paghi", "you_will_get": "Converti a", "you_will_send": "Conveti da", - "yy": "YY" -} \ No newline at end of file + "yy": "YY", + "waitFewSecondForTxUpdate": "Attendi qualche secondo affinché la transazione venga riflessa nella cronologia delle transazioni" +} diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index f4b014909..e04d8c000 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -779,5 +779,6 @@ "you_pay": "あなたが支払う", "you_will_get": "に変換", "you_will_send": "から変換", - "yy": "YY" -} \ No newline at end of file + "yy": "YY", + "waitFewSecondForTxUpdate": "取引履歴に取引が反映されるまで数秒お待ちください。" +} diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 7af7376ce..cfd3df6c9 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -780,5 +780,6 @@ "you_will_get": "로 변환하다", "you_will_send": "다음에서 변환", "YY": "YY", - "yy": "YY" -} \ No newline at end of file + "yy": "YY", + "waitFewSecondForTxUpdate": "거래 내역에 거래가 반영될 때까지 몇 초 정도 기다려 주세요." +} diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 6cba70ab2..281bb6cea 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -778,5 +778,6 @@ "you_pay": "သင်ပေးချေပါ။", "you_will_get": "သို့ပြောင်းပါ။", "you_will_send": "မှပြောင်းပါ။", - "yy": "YY" -} \ No newline at end of file + "yy": "YY", + "waitFewSecondForTxUpdate": "ငွေပေးငွေယူ မှတ်တမ်းတွင် ရောင်ပြန်ဟပ်ရန် စက္ကန့်အနည်းငယ်စောင့်ပါ။" +} diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 19451da27..19573b116 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -779,5 +779,6 @@ "you_pay": "U betaalt", "you_will_get": "Converteren naar", "you_will_send": "Converteren van", - "yy": "JJ" -} \ No newline at end of file + "yy": "JJ", + "waitFewSecondForTxUpdate": "Wacht een paar seconden totdat de transactie wordt weergegeven in de transactiegeschiedenis" +} diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 74aafd014..33fd1408a 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -778,5 +778,6 @@ "you_pay": "Płacisz", "you_will_get": "Konwertuj na", "you_will_send": "Konwertuj z", - "yy": "RR" -} \ No newline at end of file + "yy": "RR", + "waitFewSecondForTxUpdate": "Poczekaj kilka sekund, aż transakcja zostanie odzwierciedlona w historii transakcji" +} diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 53d93fe75..649551d01 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -781,5 +781,6 @@ "you_pay": "Você paga", "you_will_get": "Converter para", "you_will_send": "Converter de", - "yy": "aa" -} \ No newline at end of file + "yy": "aa", + "waitFewSecondForTxUpdate": "Aguarde alguns segundos para que a transação seja refletida no histórico de transações" +} diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 89a25db06..16c294ef7 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -779,5 +779,6 @@ "you_pay": "Вы платите", "you_will_get": "Конвертировать в", "you_will_send": "Конвертировать из", - "yy": "ГГ" -} \ No newline at end of file + "yy": "ГГ", + "waitFewSecondForTxUpdate": "Пожалуйста, подождите несколько секунд, чтобы транзакция отразилась в истории транзакций." +} diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index ef8992329..dc72090d4 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -778,5 +778,6 @@ "you_pay": "คุณจ่าย", "you_will_get": "แปลงเป็น", "you_will_send": "แปลงจาก", - "yy": "ปี" -} \ No newline at end of file + "yy": "ปี", + "waitFewSecondForTxUpdate": "กรุณารอสักครู่เพื่อให้ธุรกรรมปรากฏในประวัติการทำธุรกรรม" +} diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 55b6adb51..4090a4669 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -778,5 +778,6 @@ "you_pay": "Magbabayad ka", "you_will_get": "Mag -convert sa", "you_will_send": "I -convert mula sa", - "yy": "YY" -} \ No newline at end of file + "yy": "YY", + "waitFewSecondForTxUpdate": "Mangyaring maghintay ng ilang segundo para makita ang transaksyon sa history ng mga transaksyon" +} diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index e6cab5027..39eab9f86 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -778,5 +778,6 @@ "you_pay": "Şu kadar ödeyeceksin: ", "you_will_get": "Biçimine dönüştür:", "you_will_send": "Biçiminden dönüştür:", - "yy": "YY" -} \ No newline at end of file + "yy": "YY", + "waitFewSecondForTxUpdate": "İşlemin işlem geçmişine yansıması için lütfen birkaç saniye bekleyin" +} diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index e81d97021..b655a902d 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -779,5 +779,6 @@ "you_pay": "Ви платите", "you_will_get": "Конвертувати в", "you_will_send": "Конвертувати з", - "yy": "YY" -} \ No newline at end of file + "yy": "YY", + "waitFewSecondForTxUpdate": "Будь ласка, зачекайте кілька секунд, поки транзакція відобразиться в історії транзакцій" +} diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 465fac003..0dcd31069 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -780,5 +780,6 @@ "you_pay": "تم ادا کرو", "you_will_get": "میں تبدیل کریں۔", "you_will_send": "سے تبدیل کریں۔", - "yy": "YY" -} \ No newline at end of file + "yy": "YY", + "waitFewSecondForTxUpdate": "۔ﮟﯾﺮﮐ ﺭﺎﻈﺘﻧﺍ ﺎﮐ ﮉﻨﮑﯿﺳ ﺪﻨﭼ ﻡﺮﮐ ﮦﺍﺮﺑ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﯽﺳﺎﮑﻋ ﯽﮐ ﻦﯾﺩ ﻦﯿﻟ ﮟﯿﻣ ﺦﯾﺭﺎﺗ ﯽﮐ ﻦ" +} diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index c88f488cd..af21c001b 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -779,5 +779,6 @@ "you_pay": "Ẹ sàn", "you_will_get": "Ṣe pàṣípààrọ̀ sí", "you_will_send": "Ṣe pàṣípààrọ̀ láti", - "yy": "Ọd" -} \ No newline at end of file + "yy": "Ọd", + "waitFewSecondForTxUpdate": "Fi inurere duro fun awọn iṣeju diẹ fun idunadura lati ṣe afihan ninu itan-akọọlẹ iṣowo" +} diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 7e05d4471..6c245d30f 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -778,5 +778,6 @@ "you_pay": "你付钱", "you_will_get": "转换到", "you_will_send": "转换自", - "yy": "YY" -} \ No newline at end of file + "yy": "YY", + "waitFewSecondForTxUpdate": "请等待几秒钟,交易才会反映在交易历史记录中" +} diff --git a/scripts/android/pubspec_gen.sh b/scripts/android/pubspec_gen.sh index 4b89c4afa..d238052fe 100755 --- a/scripts/android/pubspec_gen.sh +++ b/scripts/android/pubspec_gen.sh @@ -10,7 +10,7 @@ case $APP_ANDROID_TYPE in CONFIG_ARGS="--monero" ;; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --haven --ethereum --polygon --nano --bitcoinCash" + CONFIG_ARGS="--monero --bitcoin --haven --ethereum --polygon --nano --bitcoinCash --solana" ;; $HAVEN) CONFIG_ARGS="--haven" diff --git a/scripts/ios/app_config.sh b/scripts/ios/app_config.sh index 81752a015..9f59d6632 100755 --- a/scripts/ios/app_config.sh +++ b/scripts/ios/app_config.sh @@ -28,7 +28,7 @@ case $APP_IOS_TYPE in CONFIG_ARGS="--monero" ;; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --haven --ethereum --polygon --nano --bitcoinCash" + CONFIG_ARGS="--monero --bitcoin --haven --ethereum --polygon --nano --bitcoinCash --solana" ;; $HAVEN) diff --git a/scripts/macos/app_config.sh b/scripts/macos/app_config.sh index cda367b9c..bd1417c4b 100755 --- a/scripts/macos/app_config.sh +++ b/scripts/macos/app_config.sh @@ -31,7 +31,7 @@ case $APP_MACOS_TYPE in $MONERO_COM) CONFIG_ARGS="--monero";; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash";; #--haven + CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana";; #--haven esac cp -rf pubspec_description.yaml pubspec.yaml diff --git a/tool/configure.dart b/tool/configure.dart index 408a6f6b1..bd2e4227c 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -7,6 +7,7 @@ const ethereumOutputPath = 'lib/ethereum/ethereum.dart'; const bitcoinCashOutputPath = 'lib/bitcoin_cash/bitcoin_cash.dart'; const nanoOutputPath = 'lib/nano/nano.dart'; const polygonOutputPath = 'lib/polygon/polygon.dart'; +const solanaOutputPath = 'lib/solana/solana.dart'; const walletTypesPath = 'lib/wallet_types.g.dart'; const pubspecDefaultPath = 'pubspec_default.yaml'; const pubspecOutputPath = 'pubspec.yaml'; @@ -21,6 +22,7 @@ Future main(List args) async { final hasNano = args.contains('${prefix}nano'); final hasBanano = args.contains('${prefix}banano'); final hasPolygon = args.contains('${prefix}polygon'); + final hasSolana = args.contains('${prefix}solana'); await generateBitcoin(hasBitcoin); await generateMonero(hasMonero); @@ -29,6 +31,7 @@ Future main(List args) async { await generateBitcoinCash(hasBitcoinCash); await generateNano(hasNano); await generatePolygon(hasPolygon); + await generateSolana(hasSolana); // await generateBanano(hasEthereum); await generatePubspec( @@ -40,6 +43,7 @@ Future main(List args) async { hasBanano: hasBanano, hasBitcoinCash: hasBitcoinCash, hasPolygon: hasPolygon, + hasSolana: hasSolana, ); await generateWalletTypes( hasMonero: hasMonero, @@ -50,6 +54,7 @@ Future main(List args) async { hasBanano: hasBanano, hasBitcoinCash: hasBitcoinCash, hasPolygon: hasPolygon, + hasSolana: hasSolana, ); } @@ -577,13 +582,14 @@ abstract class Ethereum { int formatterEthereumParseAmount(String amount); double formatterEthereumAmountToDouble({TransactionInfo? transaction, BigInt? amount, int exponent = 18}); List getERC20Currencies(WalletBase wallet); - Future addErc20Token(WalletBase wallet, Erc20Token token); - Future deleteErc20Token(WalletBase wallet, Erc20Token token); + Future addErc20Token(WalletBase wallet, CryptoCurrency token); + Future deleteErc20Token(WalletBase wallet, CryptoCurrency token); Future getErc20Token(WalletBase wallet, String contractAddress); CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction); void updateEtherscanUsageState(WalletBase wallet, bool isEnabled); Web3Client? getWeb3Client(WalletBase wallet); + String getTokenAddress(CryptoCurrency asset); } """; @@ -669,13 +675,14 @@ abstract class Polygon { int formatterPolygonParseAmount(String amount); double formatterPolygonAmountToDouble({TransactionInfo? transaction, BigInt? amount, int exponent = 18}); List getERC20Currencies(WalletBase wallet); - Future addErc20Token(WalletBase wallet, Erc20Token token); - Future deleteErc20Token(WalletBase wallet, Erc20Token token); + Future addErc20Token(WalletBase wallet, CryptoCurrency token); + Future deleteErc20Token(WalletBase wallet, CryptoCurrency token); Future getErc20Token(WalletBase wallet, String contractAddress); CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction); void updatePolygonScanUsageState(WalletBase wallet, bool isEnabled); Web3Client? getWeb3Client(WalletBase wallet); + String getTokenAddress(CryptoCurrency asset); } """; @@ -885,6 +892,86 @@ abstract class NanoUtil { await outputFile.writeAsString(output); } +Future generateSolana(bool hasImplementation) async { + final outputFile = File(solanaOutputPath); + const solanaCommonHeaders = """ +import 'package:cake_wallet/view_model/send/output.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/output_info.dart'; +import 'package:cw_core/transaction_info.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_credentials.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_service.dart'; +import 'package:hive/hive.dart'; + +"""; + const solanaCWHeaders = """ +import 'package:cw_solana/spl_token.dart'; +import 'package:cw_solana/solana_wallet.dart'; +import 'package:cw_solana/solana_mnemonics.dart'; +import 'package:cw_solana/solana_wallet_service.dart'; +import 'package:cw_solana/solana_transaction_info.dart'; +import 'package:cw_solana/solana_transaction_credentials.dart'; +import 'package:cw_solana/solana_wallet_creation_credentials.dart'; +import 'package:solana/solana.dart'; +"""; + const solanaCwPart = "part 'cw_solana.dart';"; + const solanaContent = """ +abstract class Solana { + List getSolanaWordList(String language); + WalletService createSolanaWalletService(Box walletInfoSource); + WalletCredentials createSolanaNewWalletCredentials( + {required String name, WalletInfo? walletInfo}); + WalletCredentials createSolanaRestoreWalletFromSeedCredentials( + {required String name, required String mnemonic, required String password}); + WalletCredentials createSolanaRestoreWalletFromPrivateKey( + {required String name, required String privateKey, required String password}); + + String getAddress(WalletBase wallet); + String getPrivateKey(WalletBase wallet); + String getPublicKey(WalletBase wallet); + Ed25519HDKeyPair? getWalletKeyPair(WalletBase wallet); + + Object createSolanaTransactionCredentials( + List outputs, { + required CryptoCurrency currency, + }); + + Object createSolanaTransactionCredentialsRaw( + List outputs, { + required CryptoCurrency currency, + }); + List getSPLTokenCurrencies(WalletBase wallet); + Future addSPLToken(WalletBase wallet, CryptoCurrency token); + Future deleteSPLToken(WalletBase wallet, CryptoCurrency token); + Future getSPLToken(WalletBase wallet, String contractAddress); + + CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction); + double getTransactionAmountRaw(TransactionInfo transactionInfo); + String getTokenAddress(CryptoCurrency asset); + List? getValidationLength(CryptoCurrency type); +} + + """; + + const solanaEmptyDefinition = 'Solana? solana;\n'; + const solanaCWDefinition = 'Solana? solana = CWSolana();\n'; + + final output = '$solanaCommonHeaders\n' + + (hasImplementation ? '$solanaCWHeaders\n' : '\n') + + (hasImplementation ? '$solanaCwPart\n\n' : '\n') + + (hasImplementation ? solanaCWDefinition : solanaEmptyDefinition) + + '\n' + + solanaContent; + + if (outputFile.existsSync()) { + await outputFile.delete(); + } + + await outputFile.writeAsString(output); +} + Future generatePubspec( {required bool hasMonero, required bool hasBitcoin, @@ -893,7 +980,8 @@ Future generatePubspec( required bool hasNano, required bool hasBanano, required bool hasBitcoinCash, - required bool hasPolygon}) async { + required bool hasPolygon, + required bool hasSolana}) async { const cwCore = """ cw_core: path: ./cw_core @@ -934,6 +1022,10 @@ Future generatePubspec( cw_polygon: path: ./cw_polygon """; + const cwSolana = """ + cw_solana: + path: ./cw_solana + """; const cwEVM = """ cw_evm: path: ./cw_evm @@ -972,6 +1064,10 @@ Future generatePubspec( output += '\n$cwPolygon'; } + if (hasSolana) { + output += '\n$cwSolana'; + } + if (hasHaven && !hasMonero) { output += '\n$cwSharedExternal\n$cwHaven'; } else if (hasHaven) { @@ -1002,7 +1098,8 @@ Future generateWalletTypes( required bool hasNano, required bool hasBanano, required bool hasBitcoinCash, - required bool hasPolygon}) async { + required bool hasPolygon, + required bool hasSolana}) async { final walletTypesFile = File(walletTypesPath); if (walletTypesFile.existsSync()) { @@ -1037,6 +1134,10 @@ Future generateWalletTypes( outputContent += '\tWalletType.polygon,\n'; } + if (hasSolana) { + outputContent += '\tWalletType.solana,\n'; + } + if (hasNano) { outputContent += '\tWalletType.nano,\n'; } diff --git a/tool/generate_secrets_config.dart b/tool/generate_secrets_config.dart index 58e7b8839..8745c2933 100644 --- a/tool/generate_secrets_config.dart +++ b/tool/generate_secrets_config.dart @@ -5,6 +5,7 @@ import 'utils/utils.dart'; const configPath = 'tool/.secrets-config.json'; const evmChainsConfigPath = 'tool/.evm-secrets-config.json'; +const solanaConfigPath = 'tool/.solana-secrets-config.json'; Future main(List args) async => generateSecretsConfig(args); @@ -18,8 +19,10 @@ Future generateSecretsConfig(List args) async { final configFile = File(configPath); final evmChainsConfigFile = File(evmChainsConfigPath); - final secrets = {}; + final solanaConfigFile = File(solanaConfigPath); + final secrets = {}; + secrets.addAll(extraInfo); secrets.removeWhere((key, dynamic value) { if (key.contains('--')) { @@ -49,6 +52,7 @@ Future generateSecretsConfig(List args) async { await configFile.writeAsString(secretsJson); secrets.clear(); + SecretKey.evmChainsSecrets.forEach((sec) { if (secrets[sec.name] != null) { return; @@ -60,4 +64,18 @@ Future generateSecretsConfig(List args) async { secretsJson = JsonEncoder.withIndent(' ').convert(secrets); await evmChainsConfigFile.writeAsString(secretsJson); + + secrets.clear(); + + SecretKey.solanaSecrets.forEach((sec) { + if (secrets[sec.name] != null) { + return; + } + + secrets[sec.name] = sec.generate(); + }); + + secretsJson = JsonEncoder.withIndent(' ').convert(secrets); + + await solanaConfigFile.writeAsString(secretsJson); } diff --git a/tool/import_secrets_config.dart b/tool/import_secrets_config.dart index 83e345f78..02061669b 100644 --- a/tool/import_secrets_config.dart +++ b/tool/import_secrets_config.dart @@ -8,6 +8,8 @@ const outputPath = 'lib/.secrets.g.dart'; const evmChainsConfigPath = 'tool/.evm-secrets-config.json'; const evmChainsOutputPath = 'cw_evm/lib/.secrets.g.dart'; +const solanaConfigPath = 'tool/.solana-secrets-config.json'; +const solanaOutputPath = 'cw_solana/lib/.secrets.g.dart'; Future main(List args) async => importSecretsConfig(); Future importSecretsConfig() async { @@ -21,6 +23,12 @@ Future importSecretsConfig() async { final evmChainsOutput = evmChainsInput.keys .fold('', (String acc, String val) => acc + generateConst(val, evmChainsInput)); + final solanaOutputFile = File(solanaOutputPath); + final solanaInput = + json.decode(File(solanaConfigPath).readAsStringSync()) as Map; + final solanaOutput = + solanaInput.keys.fold('', (String acc, String val) => acc + generateConst(val, solanaInput)); + if (outputFile.existsSync()) { await outputFile.delete(); } @@ -32,4 +40,10 @@ Future importSecretsConfig() async { } await evmChainsOutputFile.writeAsString(evmChainsOutput); + + if (solanaOutputFile.existsSync()) { + await solanaOutputFile.delete(); + } + + await solanaOutputFile.writeAsString(solanaOutput); } diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index f991c43cf..38b5129af 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -44,6 +44,10 @@ class SecretKey { SecretKey('polygonScanApiKey', () => ''), ]; + static final solanaSecrets = [ + SecretKey('ankrApiKey', () => ''), + ]; + final String name; final String Function() generate; } From a3a35f05e1d7347b1937caa08895833430c57fa5 Mon Sep 17 00:00:00 2001 From: Rafael <76502841+rafael-xmr@users.noreply.github.com> Date: Fri, 23 Feb 2024 13:13:30 -0300 Subject: [PATCH 118/241] Btc address types (#1263) * inital migration changes * feat: rest of changes * minor fix [skip ci] * fix: P2wshAddress & wallet address index * fix: address review comments * fix: address type restore * feat: add testnet * Fix review comments Remove bitcoin_base from cw_core * Fix address not matching selected type on start * remove un-necessary parameter [skip ci] * Remove bitcoin specific code from main lib Fix possible runtime exception from list wrong access * Minor fix * fix: fixes for Testnet * fix: bitcoin receive option dependency breaks monerocom * Fix issues when building Monero.com * feat: Transaction Builder changes * fix: discover addresses, testnet restoring, duplicate unspent coins, and taproot address vs schnorr sig tweak * fix: remove print * feat: improve error when failed broadcast response * feat: create fish shell env script * fix: unmodifiable maps * fix: build * fix: build * fix: computed observable side effect bug * feat: add nix script for android build_all * fix: wrong keypairs used for signing * fix: wrong addresses when using fromScriptPubKey scripts * fix(actual commit): testnet tx expanded + wrong addresses when using fromScriptPubKey scripts (update bitcoin_base deps) * fix: self-send [skip ci] * fix: p2wsh * fix: testnet fees * New versions * Update macos build number Minor UI fix * fix: use new bitcoin_base ref, fix tx list wrong hex value & refactor hidden vs hd use - if always use sideHd for isHidden, it is easier to simplify the functions instead of passing both which can be error prone - (ps: now this could probably be changed, for example from isHidden to isChange since with address list we now see "hidden" addresses) * Fix if condition to handle litecoin case * fix: self-send, change address was always making direction incoming * refactor: improve estimation function, add more inputs if balance missing * fix: new bitcoin_base update, fixes script issues * Update evm chain wallet service arguments * Fix translation [skip ci] * Fix translation [skip ci] * Update strings_fr.arb [skip ci] * fix: async isChange function not being awaited, refactor to reduce looping into a single place * fix: _address vs address, missing p2sh * fix: minor mistake in storing p2sh page type [skip ci] * refactor: use already matched addresses property * feat: improved perfomance for fetching transaction histories * feat: continue perfomance change, improve address discovery only to last address by type with history * fix: make sure transaction list is sorted by date * refactor: isTestnet only for bitcoin * fix: walletInfo type null case * fix: deprecated p2pk * refactor: make condition more readable * refactor: remove unnecessary Str variant * refactor: make condition more readable * fix: infinite loop possible * Revert removing isTestnet from other wallets [skip ci] * refactor: rename addresses when matched by receive type * Make the beta build [skip ci] Remove app_env.fish --------- Co-authored-by: OmarHatem --- assets/text/Release_Notes.txt | 8 +- cw_bitcoin/lib/address_from_output.dart | 36 +- cw_bitcoin/lib/address_to_output_script.dart | 24 +- cw_bitcoin/lib/bitcoin_address_record.dart | 56 +- .../lib/bitcoin_receive_page_option.dart | 42 ++ cw_bitcoin/lib/bitcoin_unspent.dart | 7 +- cw_bitcoin/lib/bitcoin_wallet.dart | 103 +-- cw_bitcoin/lib/bitcoin_wallet_addresses.dart | 48 +- cw_bitcoin/lib/bitcoin_wallet_service.dart | 35 +- cw_bitcoin/lib/electrum.dart | 133 ++-- cw_bitcoin/lib/electrum_transaction_info.dart | 83 ++- cw_bitcoin/lib/electrum_wallet.dart | 661 +++++++++++------- cw_bitcoin/lib/electrum_wallet_addresses.dart | 299 ++++---- cw_bitcoin/lib/electrum_wallet_snapshot.dart | 49 +- cw_bitcoin/lib/litecoin_wallet.dart | 106 +-- cw_bitcoin/lib/litecoin_wallet_addresses.dart | 43 +- cw_bitcoin/lib/litecoin_wallet_service.dart | 6 +- .../lib/pending_bitcoin_transaction.dart | 21 +- cw_bitcoin/lib/script_hash.dart | 7 +- cw_bitcoin/lib/utils.dart | 64 +- cw_bitcoin/pubspec.lock | 183 ++--- cw_bitcoin/pubspec.yaml | 5 + .../lib/src/bitcoin_cash_wallet.dart | 108 +-- .../src/bitcoin_cash_wallet_addresses.dart | 34 +- .../lib/src/bitcoin_cash_wallet_service.dart | 50 +- cw_bitcoin_cash/pubspec.yaml | 5 +- cw_core/lib/enumerate.dart | 13 + cw_core/lib/receive_page_option.dart | 21 + cw_core/lib/wallet_base.dart | 2 + cw_core/lib/wallet_info.dart | 6 + cw_core/lib/wallet_service.dart | 6 +- cw_core/pubspec.lock | 186 ++--- cw_ethereum/lib/ethereum_wallet_service.dart | 10 +- cw_evm/lib/evm_chain_wallet_service.dart | 6 +- cw_haven/lib/haven_wallet_service.dart | 6 +- cw_monero/lib/monero_wallet_service.dart | 8 +- cw_nano/lib/nano_wallet_service.dart | 6 +- cw_polygon/lib/polygon_wallet_service.dart | 12 +- lib/bitcoin/cw_bitcoin.dart | 352 +++++----- lib/core/address_validator.dart | 23 +- lib/core/wallet_creation_service.dart | 13 +- lib/di.dart | 2 +- lib/entities/default_settings_migration.dart | 21 +- lib/entities/receive_page_option.dart | 23 - lib/router.dart | 14 +- .../screens/dashboard/pages/address_page.dart | 28 +- .../advanced_privacy_settings_page.dart | 39 +- .../screens/new_wallet/new_wallet_page.dart | 14 +- .../screens/receive/anonpay_invoice_page.dart | 2 +- .../screens/receive/anonpay_receive_page.dart | 2 +- .../screens/restore/wallet_restore_page.dart | 8 +- .../anon_invoice_page_view_model.dart | 2 +- .../dashboard/dashboard_view_model.dart | 24 +- .../dashboard/receive_option_view_model.dart | 18 +- .../node_create_or_edit_view_model.dart | 2 + .../node_list/node_list_view_model.dart | 6 +- .../transaction_details_view_model.dart | 2 +- .../wallet_address_list_view_model.dart | 18 +- lib/view_model/wallet_creation_vm.dart | 11 + lib/view_model/wallet_new_vm.dart | 2 +- lib/view_model/wallet_restore_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_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 1 + res/values/strings_my.arb | 1 + res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_th.arb | 1 + res/values/strings_tl.arb | 1 + res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + scripts/android/app_env.sh | 4 +- scripts/android/shell.nix | 16 + scripts/ios/app_env.sh | 4 +- tool/configure.dart | 6 + 91 files changed, 1851 insertions(+), 1333 deletions(-) create mode 100644 cw_bitcoin/lib/bitcoin_receive_page_option.dart create mode 100644 cw_core/lib/enumerate.dart create mode 100644 cw_core/lib/receive_page_option.dart delete mode 100644 lib/entities/receive_page_option.dart create mode 100644 scripts/android/shell.nix diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 2f5130bea..ac032e354 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,5 +1,3 @@ -Bitcoin transactions fixes and enhancements -EVM wallets enhancements (Ethereum and Polygon) -Improve wallet recovery and error tolerance -Enhance Background sync for Monero wallets -Bug fixes \ No newline at end of file +Support ALL Bitcoin address types (Legacy, Segwit (both variants), Taproot) +Enhance Sending/Receiving flow for Bitcoin +Improve fee calculations in Bitcoin \ No newline at end of file diff --git a/cw_bitcoin/lib/address_from_output.dart b/cw_bitcoin/lib/address_from_output.dart index d06ffe402..73bc101c4 100644 --- a/cw_bitcoin/lib/address_from_output.dart +++ b/cw_bitcoin/lib/address_from_output.dart @@ -1,23 +1,23 @@ -import 'dart:typed_data'; -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData; +import 'package:bitcoin_base/bitcoin_base.dart'; -String addressFromOutput(Uint8List script, bitcoin.NetworkType networkType) { +String addressFromOutputScript(Script script, BasedUtxoNetwork network) { try { - return bitcoin.P2PKH( - data: PaymentData(output: script), - network: networkType) - .data - .address!; + switch (script.getAddressType()) { + case P2pkhAddressType.p2pkh: + return P2pkhAddress.fromScriptPubkey(script: script).toAddress(network); + case P2shAddressType.p2pkInP2sh: + return P2shAddress.fromScriptPubkey(script: script).toAddress(network); + case SegwitAddresType.p2wpkh: + return P2wpkhAddress.fromScriptPubkey(script: script).toAddress(network); + case P2shAddressType.p2pkhInP2sh: + return P2shAddress.fromScriptPubkey(script: script).toAddress(network); + case SegwitAddresType.p2wsh: + return P2wshAddress.fromScriptPubkey(script: script).toAddress(network); + case SegwitAddresType.p2tr: + return P2trAddress.fromScriptPubkey(script: script).toAddress(network); + default: + } } catch (_) {} - try { - return bitcoin.P2WPKH( - data: PaymentData(output: script), - network: networkType) - .data - .address!; - } catch(_) {} - return ''; -} \ No newline at end of file +} diff --git a/cw_bitcoin/lib/address_to_output_script.dart b/cw_bitcoin/lib/address_to_output_script.dart index 01c7b67a5..6ae50132b 100644 --- a/cw_bitcoin/lib/address_to_output_script.dart +++ b/cw_bitcoin/lib/address_to_output_script.dart @@ -1,27 +1,9 @@ import 'dart:typed_data'; -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:bs58check/bs58check.dart' as bs58check; -import 'package:bitcoin_flutter/src/utils/constants/op.dart'; -import 'package:bitcoin_flutter/src/utils/script.dart' as bscript; -import 'package:bitcoin_flutter/src/address.dart'; +import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin; -Uint8List p2shAddressToOutputScript(String address) { - final decodeBase58 = bs58check.decode(address); - final hash = decodeBase58.sublist(1); - return bscript.compile([OPS['OP_HASH160'], hash, OPS['OP_EQUAL']]); -} - -Uint8List addressToOutputScript( - String address, bitcoin.NetworkType networkType) { +List addressToOutputScript(String address, bitcoin.BasedUtxoNetwork network) { try { - // FIXME: improve validation for p2sh addresses - // 3 for bitcoin - // m for litecoin - if (address.startsWith('3') || address.toLowerCase().startsWith('m')) { - return p2shAddressToOutputScript(address); - } - - return Address.addressToOutputScript(address, networkType); + return bitcoin.addressToOutputScript(address: address, network: network); } catch (err) { print(err); return Uint8List(0); diff --git a/cw_bitcoin/lib/bitcoin_address_record.dart b/cw_bitcoin/lib/bitcoin_address_record.dart index 676edb4a5..d8d908230 100644 --- a/cw_bitcoin/lib/bitcoin_address_record.dart +++ b/cw_bitcoin/lib/bitcoin_address_record.dart @@ -1,6 +1,9 @@ import 'dart:convert'; import 'package:bitbox/bitbox.dart' as bitbox; +import 'package:bitcoin_base/bitcoin_base.dart'; +import 'package:cw_bitcoin/script_hash.dart' as sh; + class BitcoinAddressRecord { BitcoinAddressRecord( this.address, { @@ -10,23 +13,41 @@ class BitcoinAddressRecord { int balance = 0, String name = '', bool isUsed = false, + required this.type, + String? scriptHash, + required this.network, }) : _txCount = txCount, _balance = balance, _name = name, - _isUsed = isUsed; + _isUsed = isUsed, + scriptHash = + scriptHash ?? (network != null ? sh.scriptHash(address, network: network) : null); - factory BitcoinAddressRecord.fromJSON(String jsonSource) { + factory BitcoinAddressRecord.fromJSON(String jsonSource, BasedUtxoNetwork? network) { final decoded = json.decode(jsonSource) as Map; - return BitcoinAddressRecord(decoded['address'] as String, - index: decoded['index'] as int, - isHidden: decoded['isHidden'] as bool? ?? false, - isUsed: decoded['isUsed'] as bool? ?? false, - txCount: decoded['txCount'] as int? ?? 0, - name: decoded['name'] as String? ?? '', - balance: decoded['balance'] as int? ?? 0); + return BitcoinAddressRecord( + decoded['address'] as String, + index: decoded['index'] as int, + isHidden: decoded['isHidden'] as bool? ?? false, + isUsed: decoded['isUsed'] as bool? ?? false, + txCount: decoded['txCount'] as int? ?? 0, + name: decoded['name'] as String? ?? '', + balance: decoded['balance'] as int? ?? 0, + type: decoded['type'] != null && decoded['type'] != '' + ? BitcoinAddressType.values + .firstWhere((type) => type.toString() == decoded['type'] as String) + : SegwitAddresType.p2wpkh, + scriptHash: decoded['scriptHash'] as String?, + network: (decoded['network'] as String?) == null + ? network + : BasedUtxoNetwork.fromName(decoded['network'] as String), + ); } + @override + bool operator ==(Object o) => o is BitcoinAddressRecord && address == o.address; + final String address; bool isHidden; final int index; @@ -34,6 +55,8 @@ class BitcoinAddressRecord { int _balance; String _name; bool _isUsed; + String? scriptHash; + BasedUtxoNetwork? network; int get txCount => _txCount; @@ -50,21 +73,28 @@ class BitcoinAddressRecord { void setAsUsed() => _isUsed = true; void setNewName(String label) => _name = label; - @override - bool operator ==(Object o) => o is BitcoinAddressRecord && address == o.address; - @override int get hashCode => address.hashCode; String get cashAddr => bitbox.Address.toCashAddress(address); + BitcoinAddressType type; + + String updateScriptHash(BasedUtxoNetwork network) { + scriptHash = sh.scriptHash(address, network: network); + return scriptHash!; + } + String toJSON() => json.encode({ 'address': address, 'index': index, 'isHidden': isHidden, + 'isUsed': isUsed, 'txCount': txCount, 'name': name, - 'isUsed': isUsed, 'balance': balance, + 'type': type.toString(), + 'scriptHash': scriptHash, + 'network': network?.value, }); } diff --git a/cw_bitcoin/lib/bitcoin_receive_page_option.dart b/cw_bitcoin/lib/bitcoin_receive_page_option.dart new file mode 100644 index 000000000..2e246f532 --- /dev/null +++ b/cw_bitcoin/lib/bitcoin_receive_page_option.dart @@ -0,0 +1,42 @@ +import 'package:bitcoin_base/bitcoin_base.dart'; +import 'package:cw_core/receive_page_option.dart'; + +class BitcoinReceivePageOption implements ReceivePageOption { + static const p2wpkh = BitcoinReceivePageOption._('Segwit (P2WPKH)'); + static const p2sh = BitcoinReceivePageOption._('Segwit-Compatible (P2SH)'); + static const p2tr = BitcoinReceivePageOption._('Taproot (P2TR)'); + static const p2wsh = BitcoinReceivePageOption._('Segwit (P2WSH)'); + static const p2pkh = BitcoinReceivePageOption._('Legacy (P2PKH)'); + + const BitcoinReceivePageOption._(this.value); + + final String value; + + String toString() { + return value; + } + + static const all = [ + BitcoinReceivePageOption.p2wpkh, + BitcoinReceivePageOption.p2sh, + BitcoinReceivePageOption.p2tr, + BitcoinReceivePageOption.p2wsh, + BitcoinReceivePageOption.p2pkh + ]; + + factory BitcoinReceivePageOption.fromType(BitcoinAddressType type) { + switch (type) { + case SegwitAddresType.p2tr: + return BitcoinReceivePageOption.p2tr; + case SegwitAddresType.p2wsh: + return BitcoinReceivePageOption.p2wsh; + case P2pkhAddressType.p2pkh: + return BitcoinReceivePageOption.p2pkh; + case P2shAddressType.p2wpkhInP2sh: + return BitcoinReceivePageOption.p2sh; + case SegwitAddresType.p2wpkh: + default: + return BitcoinReceivePageOption.p2wpkh; + } + } +} diff --git a/cw_bitcoin/lib/bitcoin_unspent.dart b/cw_bitcoin/lib/bitcoin_unspent.dart index 9c198c27c..52edea091 100644 --- a/cw_bitcoin/lib/bitcoin_unspent.dart +++ b/cw_bitcoin/lib/bitcoin_unspent.dart @@ -6,10 +6,9 @@ class BitcoinUnspent extends Unspent { : bitcoinAddressRecord = addressRecord, super(addressRecord.address, hash, value, vout, null); - factory BitcoinUnspent.fromJSON( - BitcoinAddressRecord address, Map json) => - BitcoinUnspent(address, json['tx_hash'] as String, json['value'] as int, - json['tx_pos'] as int); + factory BitcoinUnspent.fromJSON(BitcoinAddressRecord address, Map json) => + BitcoinUnspent( + address, json['tx_hash'] as String, json['value'] as int, json['tx_pos'] as int); final BitcoinAddressRecord bitcoinAddressRecord; } diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 9cdb78f2d..3b3e9c636 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -1,3 +1,4 @@ +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/unspent_coins_info.dart'; @@ -17,36 +18,42 @@ part 'bitcoin_wallet.g.dart'; class BitcoinWallet = BitcoinWalletBase with _$BitcoinWallet; abstract class BitcoinWalletBase extends ElectrumWallet with Store { - BitcoinWalletBase( - {required String mnemonic, - required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - required Uint8List seedBytes, - List? initialAddresses, - ElectrumBalance? initialBalance, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) - : super( + BitcoinWalletBase({ + required String mnemonic, + required String password, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required Uint8List seedBytes, + String? addressPageType, + BasedUtxoNetwork? networkParam, + List? initialAddresses, + ElectrumBalance? initialBalance, + Map? initialRegularAddressIndex, + Map? initialChangeAddressIndex, + }) : super( mnemonic: mnemonic, password: password, walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfo, - networkType: bitcoin.bitcoin, + networkType: networkParam == null + ? bitcoin.bitcoin + : networkParam == BitcoinNetwork.mainnet + ? bitcoin.bitcoin + : bitcoin.testnet, initialAddresses: initialAddresses, initialBalance: initialBalance, seedBytes: seedBytes, currency: CryptoCurrency.btc) { walletAddresses = BitcoinWalletAddresses( - walletInfo, - electrumClient: electrumClient, - initialAddresses: initialAddresses, - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex, - mainHd: hd, - sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType) - .derivePath("m/0'/1"), - networkType: networkType); + walletInfo, + electrumClient: electrumClient, + initialAddresses: initialAddresses, + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + mainHd: hd, + sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"), + network: networkParam ?? network, + ); autorun((_) { this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress; }); @@ -57,21 +64,26 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required String password, required WalletInfo walletInfo, required Box unspentCoinsInfo, + String? addressPageType, + BasedUtxoNetwork? network, List? initialAddresses, ElectrumBalance? initialBalance, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0 + Map? initialRegularAddressIndex, + Map? initialChangeAddressIndex, }) async { return BitcoinWallet( - mnemonic: mnemonic, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - initialAddresses: initialAddresses, - initialBalance: initialBalance, - seedBytes: await mnemonicToSeedBytes(mnemonic), - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex); + mnemonic: mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: initialAddresses, + initialBalance: initialBalance, + seedBytes: await mnemonicToSeedBytes(mnemonic), + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + addressPageType: addressPageType, + networkParam: network, + ); } static Future open({ @@ -80,16 +92,21 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required Box unspentCoinsInfo, required String password, }) async { - final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password); + final snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password, + walletInfo.network != null ? BasedUtxoNetwork.fromName(walletInfo.network!) : null); + return BitcoinWallet( - mnemonic: snp.mnemonic, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - initialAddresses: snp.addresses, - initialBalance: snp.balance, - seedBytes: await mnemonicToSeedBytes(snp.mnemonic), - initialRegularAddressIndex: snp.regularAddressIndex, - initialChangeAddressIndex: snp.changeAddressIndex); + mnemonic: snp.mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: snp.addresses, + initialBalance: snp.balance, + seedBytes: await mnemonicToSeedBytes(snp.mnemonic), + initialRegularAddressIndex: snp.regularAddressIndex, + initialChangeAddressIndex: snp.changeAddressIndex, + addressPageType: snp.addressPageType, + networkParam: snp.network, + ); } -} \ No newline at end of file +} diff --git a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart index 36d37127d..f12577492 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart @@ -1,6 +1,5 @@ -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:cw_bitcoin/bitcoin_address_record.dart'; -import 'package:cw_bitcoin/electrum.dart'; +import 'package:bitcoin_base/bitcoin_base.dart'; +import 'package:bitcoin_flutter/bitcoin_flutter.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:cw_bitcoin/utils.dart'; import 'package:cw_core/wallet_info.dart'; @@ -11,24 +10,31 @@ part 'bitcoin_wallet_addresses.g.dart'; class BitcoinWalletAddresses = BitcoinWalletAddressesBase with _$BitcoinWalletAddresses; abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with Store { - BitcoinWalletAddressesBase(WalletInfo walletInfo, - {required bitcoin.HDWallet mainHd, - required bitcoin.HDWallet sideHd, - required bitcoin.NetworkType networkType, - required ElectrumClient electrumClient, - List? initialAddresses, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) - : super(walletInfo, - initialAddresses: initialAddresses, - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex, - mainHd: mainHd, - sideHd: sideHd, - electrumClient: electrumClient, - networkType: networkType); + BitcoinWalletAddressesBase( + WalletInfo walletInfo, { + required super.mainHd, + required super.sideHd, + required super.network, + required super.electrumClient, + super.initialAddresses, + super.initialRegularAddressIndex, + super.initialChangeAddressIndex, + }) : super(walletInfo); @override - String getAddress({required int index, required bitcoin.HDWallet hd}) => - generateP2WPKHAddress(hd: hd, index: index, networkType: networkType); + String getAddress({required int index, required HDWallet hd, BitcoinAddressType? addressType}) { + if (addressType == P2pkhAddressType.p2pkh) + return generateP2PKHAddress(hd: hd, index: index, network: network); + + if (addressType == SegwitAddresType.p2tr) + return generateP2TRAddress(hd: hd, index: index, network: network); + + if (addressType == SegwitAddresType.p2wsh) + return generateP2WSHAddress(hd: hd, index: index, network: network); + + if (addressType == P2shAddressType.p2wpkhInP2sh) + return generateP2SHAddress(hd: hd, index: index, network: network); + + return generateP2WPKHAddress(hd: hd, index: index, network: network); + } } diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index 736ec1044..2b8c489d2 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -1,4 +1,5 @@ import 'dart:io'; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic_is_incorrect_exception.dart'; import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart'; @@ -23,12 +24,17 @@ class BitcoinWalletService extends WalletService WalletType.bitcoin; @override - Future create(BitcoinNewWalletCredentials credentials) async { + Future create(BitcoinNewWalletCredentials credentials, {bool? isTestnet}) async { + final network = isTestnet == true ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet; + credentials.walletInfo?.network = network.value; + final wallet = await BitcoinWalletBase.create( - mnemonic: await generateMnemonic(), - password: credentials.password!, - walletInfo: credentials.walletInfo!, - unspentCoinsInfo: unspentCoinsInfoSource); + mnemonic: await generateMnemonic(), + password: credentials.password!, + walletInfo: credentials.walletInfo!, + unspentCoinsInfo: unspentCoinsInfoSource, + network: network, + ); await wallet.save(); await wallet.init(); return wallet; @@ -92,20 +98,27 @@ class BitcoinWalletService extends WalletService restoreFromKeys(BitcoinRestoreWalletFromWIFCredentials credentials) async => + Future restoreFromKeys(BitcoinRestoreWalletFromWIFCredentials credentials, + {bool? isTestnet}) async => throw UnimplementedError(); @override - Future restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials, + {bool? isTestnet}) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinMnemonicIsIncorrectException(); } + final network = isTestnet == true ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet; + credentials.walletInfo?.network = network.value; + final wallet = await BitcoinWalletBase.create( - password: credentials.password!, - mnemonic: credentials.mnemonic, - walletInfo: credentials.walletInfo!, - unspentCoinsInfo: unspentCoinsInfoSource); + password: credentials.password!, + mnemonic: credentials.mnemonic, + walletInfo: credentials.walletInfo!, + unspentCoinsInfo: unspentCoinsInfoSource, + network: network, + ); await wallet.save(); await wallet.init(); return wallet; diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index a05c251fe..51a53e285 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -2,12 +2,12 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; -import 'package:bitcoin_flutter/bitcoin_flutter.dart'; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/script_hash.dart'; import 'package:flutter/foundation.dart'; import 'package:rxdart/rxdart.dart'; -import 'package:collection/collection.dart'; +import 'package:http/http.dart' as http; String jsonrpcparams(List params) { final _params = params?.map((val) => '"${val.toString()}"')?.join(','); @@ -22,10 +22,7 @@ String jsonrpc( '{"jsonrpc": "$version", "method": "$method", "id": "$id", "params": ${json.encode(params)}}\n'; class SocketTask { - SocketTask({ - required this.isSubscription, - this.completer, - this.subject}); + SocketTask({required this.isSubscription, this.completer, this.subject}); final Completer? completer; final BehaviorSubject? subject; @@ -51,8 +48,7 @@ class ElectrumClient { Timer? _aliveTimer; String unterminatedString; - Future connectToUri(Uri uri) async => - await connect(host: uri.host, port: uri.port); + Future connectToUri(Uri uri) async => await connect(host: uri.host, port: uri.port); Future connect({required String host, required int port}) async { try { @@ -104,21 +100,20 @@ class ElectrumClient { } if (isJSONStringCorrect(unterminatedString)) { - final response = - json.decode(unterminatedString) as Map; + final response = json.decode(unterminatedString) as Map; _handleResponse(response); unterminatedString = ''; } } on TypeError catch (e) { - if (!e.toString().contains('Map') && !e.toString().contains('Map')) { + if (!e.toString().contains('Map') && + !e.toString().contains('Map')) { return; } unterminatedString += message; if (isJSONStringCorrect(unterminatedString)) { - final response = - json.decode(unterminatedString) as Map; + final response = json.decode(unterminatedString) as Map; _handleResponse(response); // unterminatedString = null; unterminatedString = ''; @@ -142,8 +137,7 @@ class ElectrumClient { } } - Future> version() => - call(method: 'server.version').then((dynamic result) { + Future> version() => call(method: 'server.version').then((dynamic result) { if (result is List) { return result.map((dynamic val) => val.toString()).toList(); } @@ -178,11 +172,10 @@ class ElectrumClient { }); Future>> getListUnspentWithAddress( - String address, NetworkType networkType) => + String address, BasedUtxoNetwork network) => call( - method: 'blockchain.scripthash.listunspent', - params: [scriptHash(address, networkType: networkType)]) - .then((dynamic result) { + method: 'blockchain.scripthash.listunspent', + params: [scriptHash(address, network: network)]).then((dynamic result) { if (result is List) { return result.map((dynamic val) { if (val is Map) { @@ -229,8 +222,7 @@ class ElectrumClient { return []; }); - Future> getTransactionRaw( - {required String hash}) async => + Future> getTransactionRaw({required String hash}) async => callWithTimeout(method: 'blockchain.transaction.get', params: [hash, true], timeout: 10000) .then((dynamic result) { if (result is Map) { @@ -240,8 +232,7 @@ class ElectrumClient { return {}; }); - Future getTransactionHex( - {required String hash}) async => + Future getTransactionHex({required String hash}) async => callWithTimeout(method: 'blockchain.transaction.get', params: [hash, false], timeout: 10000) .then((dynamic result) { if (result is String) { @@ -252,29 +243,40 @@ class ElectrumClient { }); Future broadcastTransaction( - {required String transactionRaw}) async => - call(method: 'blockchain.transaction.broadcast', params: [transactionRaw]) - .then((dynamic result) { - if (result is String) { - return result; + {required String transactionRaw, BasedUtxoNetwork? network}) async { + if (network == BitcoinNetwork.testnet) { + return http + .post(Uri(scheme: 'https', host: 'blockstream.info', path: '/testnet/api/tx'), + headers: {'Content-Type': 'application/json; charset=utf-8'}, + body: transactionRaw) + .then((http.Response response) { + if (response.statusCode == 200) { + return response.body; } - return ''; + throw Exception('Failed to broadcast transaction: ${response.body}'); }); + } - Future> getMerkle( - {required String hash, required int height}) async => - await call( - method: 'blockchain.transaction.get_merkle', - params: [hash, height]) as Map; + return call(method: 'blockchain.transaction.broadcast', params: [transactionRaw]) + .then((dynamic result) { + if (result is String) { + return result; + } - Future> getHeader({required int height}) async => - await call(method: 'blockchain.block.get_header', params: [height]) + return ''; + }); + } + + Future> getMerkle({required String hash, required int height}) async => + await call(method: 'blockchain.transaction.get_merkle', params: [hash, height]) as Map; + Future> getHeader({required int height}) async => + await call(method: 'blockchain.block.get_header', params: [height]) as Map; + Future estimatefee({required int p}) => - call(method: 'blockchain.estimatefee', params: [p]) - .then((dynamic result) { + call(method: 'blockchain.estimatefee', params: [p]).then((dynamic result) { if (result is double) { return result; } @@ -314,20 +316,17 @@ class ElectrumClient { return []; }); - Future> feeRates() async { + Future> feeRates({BasedUtxoNetwork? network}) async { + if (network == BitcoinNetwork.testnet) { + return [1, 1, 1]; + } try { final topDoubleString = await estimatefee(p: 1); final middleDoubleString = await estimatefee(p: 5); final bottomDoubleString = await estimatefee(p: 100); - final top = - (stringDoubleToBitcoinAmount(topDoubleString.toString()) / 1000) - .round(); - final middle = - (stringDoubleToBitcoinAmount(middleDoubleString.toString()) / 1000) - .round(); - final bottom = - (stringDoubleToBitcoinAmount(bottomDoubleString.toString()) / 1000) - .round(); + final top = (stringDoubleToBitcoinAmount(topDoubleString.toString()) / 1000).round(); + final middle = (stringDoubleToBitcoinAmount(middleDoubleString.toString()) / 1000).round(); + final bottom = (stringDoubleToBitcoinAmount(bottomDoubleString.toString()) / 1000).round(); return [bottom, middle, top]; } catch (_) { @@ -335,6 +334,21 @@ class ElectrumClient { } } + // https://electrumx.readthedocs.io/en/latest/protocol-methods.html#blockchain-headers-subscribe + // example response: + // { + // "height": 520481, + // "hex": "00000020890208a0ae3a3892aa047c5468725846577cfcd9b512b50000000000000000005dc2b02f2d297a9064ee103036c14d678f9afc7e3d9409cf53fd58b82e938e8ecbeca05a2d2103188ce804c4" + // } + Future getCurrentBlockChainTip() => + call(method: 'blockchain.headers.subscribe').then((result) { + if (result is Map) { + return result["height"] as int; + } + + return null; + }); + BehaviorSubject? scripthashUpdate(String scripthash) { _id += 1; return subscribe( @@ -344,16 +358,14 @@ class ElectrumClient { } BehaviorSubject? subscribe( - {required String id, - required String method, - List params = const []}) { + {required String id, required String method, List params = const []}) { try { final subscription = BehaviorSubject(); _regisrySubscription(id, subscription); socket!.write(jsonrpc(method: method, id: _id, params: params)); return subscription; - } catch(e) { + } catch (e) { print(e.toString()); return null; } @@ -370,9 +382,7 @@ class ElectrumClient { } Future callWithTimeout( - {required String method, - List params = const [], - int timeout = 4000}) async { + {required String method, List params = const [], int timeout = 4000}) async { try { final completer = Completer(); _id += 1; @@ -386,7 +396,7 @@ class ElectrumClient { }); return completer.future; - } catch(e) { + } catch (e) { print(e.toString()); } } @@ -397,8 +407,8 @@ class ElectrumClient { onConnectionStatusChange = null; } - void _registryTask(int id, Completer completer) => _tasks[id.toString()] = - SocketTask(completer: completer, isSubscription: false); + void _registryTask(int id, Completer completer) => + _tasks[id.toString()] = SocketTask(completer: completer, isSubscription: false); void _regisrySubscription(String id, BehaviorSubject subject) => _tasks[id] = SocketTask(subject: subject, isSubscription: true); @@ -419,8 +429,7 @@ class ElectrumClient { } } - void _methodHandler( - {required String method, required Map request}) { + void _methodHandler({required String method, required Map request}) { switch (method) { case 'blockchain.scripthash.subscribe': final params = request['params'] as List; @@ -451,8 +460,8 @@ class ElectrumClient { _methodHandler(method: method, request: response); return; } - - if (id != null){ + + if (id != null) { _finish(id, result); } } diff --git a/cw_bitcoin/lib/electrum_transaction_info.dart b/cw_bitcoin/lib/electrum_transaction_info.dart index bf5ec2c4f..cfea0e089 100644 --- a/cw_bitcoin/lib/electrum_transaction_info.dart +++ b/cw_bitcoin/lib/electrum_transaction_info.dart @@ -1,3 +1,4 @@ +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData; import 'package:cw_bitcoin/address_from_output.dart'; @@ -10,13 +11,12 @@ import 'package:cw_core/wallet_type.dart'; class ElectrumTransactionBundle { ElectrumTransactionBundle(this.originalTransaction, - {required this.ins, - required this.confirmations, - this.time}); - final bitcoin.Transaction originalTransaction; - final List ins; + {required this.ins, required this.confirmations, this.time, required this.height}); + final BtcTransaction originalTransaction; + final List ins; final int? time; final int confirmations; + final int height; } class ElectrumTransactionInfo extends TransactionInfo { @@ -39,8 +39,7 @@ class ElectrumTransactionInfo extends TransactionInfo { this.confirmations = confirmations; } - factory ElectrumTransactionInfo.fromElectrumVerbose( - Map obj, WalletType type, + factory ElectrumTransactionInfo.fromElectrumVerbose(Map obj, WalletType type, {required List addresses, required int height}) { final addressesSet = addresses.map((addr) => addr.address).toSet(); final id = obj['txid'] as String; @@ -58,10 +57,8 @@ class ElectrumTransactionInfo extends TransactionInfo { for (dynamic vin in vins) { final vout = vin['vout'] as int; final out = vin['tx']['vout'][vout] as Map; - final outAddresses = - (out['scriptPubKey']['addresses'] as List?)?.toSet(); - inputsAmount += - stringDoubleToBitcoinAmount((out['value'] as double? ?? 0).toString()); + final outAddresses = (out['scriptPubKey']['addresses'] as List?)?.toSet(); + inputsAmount += stringDoubleToBitcoinAmount((out['value'] as double? ?? 0).toString()); if (outAddresses?.intersection(addressesSet).isNotEmpty ?? false) { direction = TransactionDirection.outgoing; @@ -69,11 +66,9 @@ class ElectrumTransactionInfo extends TransactionInfo { } for (dynamic out in vout) { - final outAddresses = - out['scriptPubKey']['addresses'] as List? ?? []; + final outAddresses = out['scriptPubKey']['addresses'] as List? ?? []; final ntrs = outAddresses.toSet().intersection(addressesSet); - final value = stringDoubleToBitcoinAmount( - (out['value'] as double? ?? 0.0).toString()); + final value = stringDoubleToBitcoinAmount((out['value'] as double? ?? 0.0).toString()); totalOutAmount += value; if ((direction == TransactionDirection.incoming && ntrs.isNotEmpty) || @@ -96,44 +91,50 @@ class ElectrumTransactionInfo extends TransactionInfo { } factory ElectrumTransactionInfo.fromElectrumBundle( - ElectrumTransactionBundle bundle, - WalletType type, - bitcoin.NetworkType networkType, - {required Set addresses, - required int height}) { + ElectrumTransactionBundle bundle, WalletType type, BasedUtxoNetwork network, + {required Set addresses, required int height}) { final date = bundle.time != null - ? DateTime.fromMillisecondsSinceEpoch(bundle.time! * 1000) - : DateTime.now(); + ? DateTime.fromMillisecondsSinceEpoch(bundle.time! * 1000) + : DateTime.now(); var direction = TransactionDirection.incoming; var amount = 0; var inputAmount = 0; var totalOutAmount = 0; - for (var i = 0; i < bundle.originalTransaction.ins.length; i++) { - final input = bundle.originalTransaction.ins[i]; + for (var i = 0; i < bundle.originalTransaction.inputs.length; i++) { + final input = bundle.originalTransaction.inputs[i]; final inputTransaction = bundle.ins[i]; - final vout = input.index; - final outTransaction = inputTransaction.outs[vout!]; - final address = addressFromOutput(outTransaction.script!, networkType); - inputAmount += outTransaction.value!; - if (addresses.contains(address)) { + final outTransaction = inputTransaction.outputs[input.txIndex]; + inputAmount += outTransaction.amount.toInt(); + if (addresses.contains(addressFromOutputScript(outTransaction.scriptPubKey, network))) { direction = TransactionDirection.outgoing; } } - for (final out in bundle.originalTransaction.outs) { - totalOutAmount += out.value!; - final address = addressFromOutput(out.script!, networkType); - final addressExists = addresses.contains(address); + final receivedAmounts = []; + for (final out in bundle.originalTransaction.outputs) { + totalOutAmount += out.amount.toInt(); + final addressExists = addresses.contains(addressFromOutputScript(out.scriptPubKey, network)); + + if (addressExists) { + receivedAmounts.add(out.amount.toInt()); + } + if ((direction == TransactionDirection.incoming && addressExists) || (direction == TransactionDirection.outgoing && !addressExists)) { - amount += out.value!; + amount += out.amount.toInt(); } } + if (receivedAmounts.length == bundle.originalTransaction.outputs.length) { + // Self-send + direction = TransactionDirection.incoming; + amount = receivedAmounts.reduce((a, b) => a + b); + } + final fee = inputAmount - totalOutAmount; return ElectrumTransactionInfo(type, - id: bundle.originalTransaction.getId(), + id: bundle.originalTransaction.txId(), height: height, isPending: bundle.confirmations == 0, fee: fee, @@ -152,8 +153,8 @@ class ElectrumTransactionInfo extends TransactionInfo { if (addresses != null) { tx.outs.forEach((out) { try { - final p2pkh = bitcoin.P2PKH( - data: PaymentData(output: out.script), network: bitcoin.bitcoin); + final p2pkh = + bitcoin.P2PKH(data: PaymentData(output: out.script), network: bitcoin.bitcoin); exist = addresses.contains(p2pkh.data.address); if (exist) { @@ -163,9 +164,8 @@ class ElectrumTransactionInfo extends TransactionInfo { }); } - final date = timestamp != null - ? DateTime.fromMillisecondsSinceEpoch(timestamp * 1000) - : DateTime.now(); + final date = + timestamp != null ? DateTime.fromMillisecondsSinceEpoch(timestamp * 1000) : DateTime.now(); return ElectrumTransactionInfo(type, id: tx.getId(), @@ -178,8 +178,7 @@ class ElectrumTransactionInfo extends TransactionInfo { confirmations: confirmations); } - factory ElectrumTransactionInfo.fromJson( - Map data, WalletType type) { + factory ElectrumTransactionInfo.fromJson(Map data, WalletType type) { return ElectrumTransactionInfo(type, id: data['id'] as String, height: data['height'] as int, diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 8a41c1733..873fe2977 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -3,9 +3,10 @@ import 'dart:convert'; import 'dart:io'; import 'dart:math'; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin_base; import 'package:collection/collection.dart'; -import 'package:cw_bitcoin/address_to_output_script.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_bitcoin/bitcoin_transaction_no_inputs_exception.dart'; @@ -18,6 +19,7 @@ import 'package:cw_bitcoin/electrum_balance.dart'; import 'package:cw_bitcoin/electrum_transaction_history.dart'; import 'package:cw_bitcoin/electrum_transaction_info.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; +import 'package:cw_bitcoin/litecoin_network.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/script_hash.dart'; import 'package:cw_bitcoin/utils.dart'; @@ -37,6 +39,7 @@ import 'package:hex/hex.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:rxdart/subjects.dart'; +import 'package:http/http.dart' as http; part 'electrum_wallet.g.dart'; @@ -73,6 +76,12 @@ abstract class ElectrumWalletBase } : {}), this.unspentCoinsInfo = unspentCoinsInfo, + this.network = networkType == bitcoin.bitcoin + ? BitcoinNetwork.mainnet + : networkType == litecoinNetwork + ? LitecoinNetwork.mainnet + : BitcoinNetwork.testnet, + this.isTestnet = networkType == bitcoin.testnet, super(walletInfo) { this.electrumClient = electrumClient ?? ElectrumClient(); this.walletInfo = walletInfo; @@ -106,13 +115,13 @@ abstract class ElectrumWalletBase @observable SyncStatus syncStatus; - List get scriptHashes => walletAddresses.addresses - .map((addr) => scriptHash(addr.address, networkType: networkType)) + List get scriptHashes => walletAddresses.addressesByReceiveType + .map((addr) => scriptHash(addr.address, network: network)) .toList(); - List get publicScriptHashes => walletAddresses.addresses + List get publicScriptHashes => walletAddresses.allAddresses .where((addr) => !addr.isHidden) - .map((addr) => scriptHash(addr.address, networkType: networkType)) + .map((addr) => scriptHash(addr.address, network: network)) .toList(); String get xpub => hd.base58!; @@ -121,6 +130,10 @@ abstract class ElectrumWalletBase String get seed => mnemonic; bitcoin.NetworkType networkType; + BasedUtxoNetwork network; + + @override + bool? isTestnet; @override BitcoinWalletKeys get keys => @@ -145,12 +158,11 @@ abstract class ElectrumWalletBase Future startSync() async { try { syncStatus = AttemptingSyncStatus(); - await walletAddresses.discoverAddresses(); await updateTransactions(); _subscribeForUpdates(); await updateUnspent(); await updateBalance(); - _feeRates = await electrumClient.feeRates(); + _feeRates = await electrumClient.feeRates(network: network); Timer.periodic( const Duration(minutes: 1), (timer) async => _feeRates = await electrumClient.feeRates()); @@ -181,183 +193,206 @@ abstract class ElectrumWalletBase } } - @override - Future createTransaction(Object credentials) async { - const minAmount = 546; - final transactionCredentials = credentials as BitcoinTransactionCredentials; - final inputs = []; - final outputs = transactionCredentials.outputs; - final hasMultiDestination = outputs.length > 1; + Future _estimateTxFeeAndInputsToUse( + int credentialsAmount, + bool sendAll, + List outputAddresses, + List outputs, + BitcoinTransactionCredentials transactionCredentials, + {int? inputsCount}) async { + final utxos = []; + List privateKeys = []; + + var leftAmount = credentialsAmount; var allInputsAmount = 0; - if (unspentCoins.isEmpty) { - await updateUnspent(); - } + for (int i = 0; i < unspentCoins.length; i++) { + final utx = unspentCoins[i]; - for (final utx in unspentCoins) { if (utx.isSending) { allInputsAmount += utx.value; - inputs.add(utx); - } - } - - if (inputs.isEmpty) { - throw BitcoinTransactionNoInputsException(); - } - - final allAmountFee = transactionCredentials.feeRate != null - ? feeAmountWithFeeRate(transactionCredentials.feeRate!, inputs.length, outputs.length) - : feeAmountForPriority(transactionCredentials.priority!, inputs.length, outputs.length); - - final allAmount = allInputsAmount - allAmountFee; - - var credentialsAmount = 0; - var amount = 0; - var fee = 0; - - if (hasMultiDestination) { - if (outputs.any((item) => item.sendAll || item.formattedCryptoAmount! <= 0)) { - throw BitcoinTransactionWrongBalanceException(currency); - } - - credentialsAmount = outputs.fold(0, (acc, value) => acc + value.formattedCryptoAmount!); - - if (allAmount - credentialsAmount < minAmount) { - throw BitcoinTransactionWrongBalanceException(currency); - } - - amount = credentialsAmount; - - if (transactionCredentials.feeRate != null) { - fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate!, amount, - outputsCount: outputs.length + 1); - } else { - fee = calculateEstimatedFee(transactionCredentials.priority, amount, - outputsCount: outputs.length + 1); - } - } else { - final output = outputs.first; - credentialsAmount = !output.sendAll ? output.formattedCryptoAmount! : 0; - - if (credentialsAmount > allAmount) { - throw BitcoinTransactionWrongBalanceException(currency); - } - - amount = output.sendAll || allAmount - credentialsAmount < minAmount - ? allAmount - : credentialsAmount; - - if (output.sendAll || amount == allAmount) { - fee = allAmountFee; - } else if (transactionCredentials.feeRate != null) { - fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate!, amount); - } else { - fee = calculateEstimatedFee(transactionCredentials.priority, amount); - } - } - - if (fee == 0) { - throw BitcoinTransactionWrongBalanceException(currency); - } - - final totalAmount = amount + fee; - - if (totalAmount > balance[currency]!.confirmed || totalAmount > allInputsAmount) { - throw BitcoinTransactionWrongBalanceException(currency); - } - - final txb = bitcoin.TransactionBuilder(network: networkType); - final changeAddress = await walletAddresses.getChangeAddress(); - var leftAmount = totalAmount; - var totalInputAmount = 0; - - inputs.clear(); - - for (final utx in unspentCoins) { - if (utx.isSending) { leftAmount = leftAmount - utx.value; - totalInputAmount += utx.value; - inputs.add(utx); - if (leftAmount <= 0) { + final address = _addressTypeFromStr(utx.address, network); + final privkey = generateECPrivate( + hd: utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, + index: utx.bitcoinAddressRecord.index, + network: network); + + privateKeys.add(privkey); + + utxos.add( + UtxoWithAddress( + utxo: BitcoinUtxo( + txHash: utx.hash, + value: BigInt.from(utx.value), + vout: utx.vout, + scriptType: _getScriptType(address), + ), + ownerDetails: + UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: address), + ), + ); + + bool amountIsAcquired = !sendAll && leftAmount <= 0; + if ((inputsCount == null && amountIsAcquired) || inputsCount == i + 1) { break; } } } - if (inputs.isEmpty) { + if (utxos.isEmpty) { throw BitcoinTransactionNoInputsException(); } - if (amount <= 0 || totalInputAmount < totalAmount) { + var changeValue = allInputsAmount - credentialsAmount; + + if (!sendAll) { + if (changeValue > 0) { + final changeAddress = await walletAddresses.getChangeAddress(); + final address = _addressTypeFromStr(changeAddress, network); + outputAddresses.add(address); + outputs.add(BitcoinOutput(address: address, value: BigInt.from(changeValue))); + } + } + + final estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize( + utxos: utxos, outputs: outputs, network: network); + + final fee = transactionCredentials.feeRate != null + ? feeAmountWithFeeRate(transactionCredentials.feeRate!, 0, 0, size: estimatedSize) + : feeAmountForPriority(transactionCredentials.priority!, 0, 0, size: estimatedSize); + + if (fee == 0) { throw BitcoinTransactionWrongBalanceException(currency); } - txb.setVersion(1); - inputs.forEach((input) { - if (input.isP2wpkh) { - final p2wpkh = bitcoin - .P2WPKH( - data: generatePaymentData( - hd: input.bitcoinAddressRecord.isHidden - ? walletAddresses.sideHd - : walletAddresses.mainHd, - index: input.bitcoinAddressRecord.index), - network: networkType) - .data; + var amount = credentialsAmount; - txb.addInput(input.hash, input.vout, null, p2wpkh.output); - } else { - txb.addInput(input.hash, input.vout); + final lastOutput = outputs.last; + if (!sendAll) { + if (changeValue > fee) { + // Here, lastOutput is change, deduct the fee from it + outputs[outputs.length - 1] = + BitcoinOutput(address: lastOutput.address, value: lastOutput.value - BigInt.from(fee)); } - }); - - outputs.forEach((item) { - final outputAmount = hasMultiDestination ? item.formattedCryptoAmount : amount; - final outputAddress = item.isParsedAddress ? item.extractedAddress! : item.address; - txb.addOutput(addressToOutputScript(outputAddress, networkType), outputAmount!); - }); - - final estimatedSize = estimatedTransactionSize(inputs.length, outputs.length + 1); - var feeAmount = 0; - - if (transactionCredentials.feeRate != null) { - feeAmount = transactionCredentials.feeRate! * estimatedSize; } else { - feeAmount = feeRate(transactionCredentials.priority!) * estimatedSize; + // Here, if sendAll, the output amount equals to the input value - fee to fully spend every input on the transaction and have no amount for change + amount = allInputsAmount - fee; + outputs[outputs.length - 1] = + BitcoinOutput(address: lastOutput.address, value: BigInt.from(amount)); } - final changeValue = totalInputAmount - amount - feeAmount; + final totalAmount = amount + fee; - if (changeValue > minAmount) { - txb.addOutput(changeAddress, changeValue); + if (totalAmount > balance[currency]!.confirmed) { + throw BitcoinTransactionWrongBalanceException(currency); } - for (var i = 0; i < inputs.length; i++) { - final input = inputs[i]; - final keyPair = generateKeyPair( - hd: input.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, - index: input.bitcoinAddressRecord.index, - network: networkType); - final witnessValue = input.isP2wpkh ? input.value : null; + if (totalAmount > allInputsAmount) { + if (unspentCoins.where((utx) => utx.isSending).length == utxos.length) { + throw BitcoinTransactionWrongBalanceException(currency); + } else { + if (changeValue > fee) { + outputAddresses.removeLast(); + outputs.removeLast(); + } - txb.sign(vin: i, keyPair: keyPair, witnessValue: witnessValue); + return _estimateTxFeeAndInputsToUse( + credentialsAmount, sendAll, outputAddresses, outputs, transactionCredentials, + inputsCount: utxos.length + 1); + } } - return PendingBitcoinTransaction(txb.build(), type, - electrumClient: electrumClient, amount: amount, fee: fee) - ..addListener((transaction) async { - transactionHistory.addOne(transaction); - await updateBalance(); + return EstimatedTxResult(utxos: utxos, privateKeys: privateKeys, fee: fee, amount: amount); + } + + @override + Future createTransaction(Object credentials) async { + try { + final outputs = []; + final outputAddresses = []; + final transactionCredentials = credentials as BitcoinTransactionCredentials; + final hasMultiDestination = transactionCredentials.outputs.length > 1; + final sendAll = !hasMultiDestination && transactionCredentials.outputs.first.sendAll; + + var credentialsAmount = 0; + + for (final out in transactionCredentials.outputs) { + final outputAddress = out.isParsedAddress ? out.extractedAddress! : out.address; + final address = _addressTypeFromStr(outputAddress, network); + + outputAddresses.add(address); + + if (hasMultiDestination) { + if (out.sendAll || out.formattedCryptoAmount! <= 0) { + throw BitcoinTransactionWrongBalanceException(currency); + } + + final outputAmount = out.formattedCryptoAmount!; + credentialsAmount += outputAmount; + + outputs.add(BitcoinOutput(address: address, value: BigInt.from(outputAmount))); + } else { + if (!sendAll) { + final outputAmount = out.formattedCryptoAmount!; + credentialsAmount += outputAmount; + outputs.add(BitcoinOutput(address: address, value: BigInt.from(outputAmount))); + } else { + // The value will be changed after estimating the Tx size and deducting the fee from the total + outputs.add(BitcoinOutput(address: address, value: BigInt.from(0))); + } + } + } + + final estimatedTx = await _estimateTxFeeAndInputsToUse( + credentialsAmount, sendAll, outputAddresses, outputs, transactionCredentials); + + final txb = BitcoinTransactionBuilder( + utxos: estimatedTx.utxos, + outputs: outputs, + fee: BigInt.from(estimatedTx.fee), + network: network); + + final transaction = txb.buildTransaction((txDigest, utxo, publicKey, sighash) { + final key = estimatedTx.privateKeys + .firstWhereOrNull((element) => element.getPublic().toHex() == publicKey); + + if (key == null) { + throw Exception("Cannot find private key"); + } + + if (utxo.utxo.isP2tr()) { + return key.signTapRoot(txDigest, sighash: sighash); + } else { + return key.signInput(txDigest, sigHash: sighash); + } }); + + return PendingBitcoinTransaction(transaction, type, + electrumClient: electrumClient, + amount: estimatedTx.amount, + fee: estimatedTx.fee, + network: network) + ..addListener((transaction) async { + transactionHistory.addOne(transaction); + await updateBalance(); + }); + } catch (e) { + throw e; + } } String toJSON() => json.encode({ 'mnemonic': mnemonic, - 'account_index': walletAddresses.currentReceiveAddressIndex.toString(), - 'change_address_index': walletAddresses.currentChangeAddressIndex.toString(), - 'addresses': walletAddresses.addresses.map((addr) => addr.toJSON()).toList(), - 'balance': balance[currency]?.toJSON() + 'account_index': walletAddresses.currentReceiveAddressIndexByType, + 'change_address_index': walletAddresses.currentChangeAddressIndexByType, + 'addresses': walletAddresses.allAddresses.map((addr) => addr.toJSON()).toList(), + 'address_page_type': walletInfo.addressPageType == null + ? SegwitAddresType.p2wpkh.toString() + : walletInfo.addressPageType.toString(), + 'balance': balance[currency]?.toJSON(), + 'network_type': network == BitcoinNetwork.testnet ? 'testnet' : 'mainnet', }); int feeRate(TransactionPriority priority) { @@ -372,24 +407,29 @@ abstract class ElectrumWalletBase } } - int feeAmountForPriority( - BitcoinTransactionPriority priority, int inputsCount, int outputsCount) => - feeRate(priority) * estimatedTransactionSize(inputsCount, outputsCount); + int feeAmountForPriority(BitcoinTransactionPriority priority, int inputsCount, int outputsCount, + {int? size}) => + feeRate(priority) * (size ?? estimatedTransactionSize(inputsCount, outputsCount)); - int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount) => - feeRate * estimatedTransactionSize(inputsCount, outputsCount); + int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount, {int? size}) => + feeRate * (size ?? estimatedTransactionSize(inputsCount, outputsCount)); @override - int calculateEstimatedFee(TransactionPriority? priority, int? amount, {int? outputsCount}) { + int calculateEstimatedFee(TransactionPriority? priority, int? amount, + {int? outputsCount, int? size}) { if (priority is BitcoinTransactionPriority) { return calculateEstimatedFeeWithFeeRate(feeRate(priority), amount, - outputsCount: outputsCount); + outputsCount: outputsCount, size: size); } return 0; } - int calculateEstimatedFeeWithFeeRate(int feeRate, int? amount, {int? outputsCount}) { + int calculateEstimatedFeeWithFeeRate(int feeRate, int? amount, {int? outputsCount, int? size}) { + if (size != null) { + return feeAmountWithFeeRate(feeRate, 0, 0, size: size); + } + int inputsCount = 0; if (amount != null) { @@ -457,9 +497,6 @@ abstract class ElectrumWalletBase await transactionHistory.changePassword(password); } - bitcoin.ECPair keyPairFor({required int index}) => - generateKeyPair(hd: hd, index: index, network: networkType); - @override Future rescan({required int height}) async => throw UnimplementedError(); @@ -473,20 +510,23 @@ abstract class ElectrumWalletBase Future makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); Future updateUnspent() async { - final unspent = await Future.wait(walletAddresses.addresses.map((address) => electrumClient - .getListUnspentWithAddress(address.address, networkType) - .then((unspent) => unspent.map((unspent) { + List updatedUnspentCoins = []; + + final addressesSet = walletAddresses.allAddresses.map((addr) => addr.address).toSet(); + + await Future.wait(walletAddresses.allAddresses.map((address) => electrumClient + .getListUnspentWithAddress(address.address, network) + .then((unspent) => Future.forEach>(unspent, (unspent) async { try { - return BitcoinUnspent.fromJSON(address, unspent); - } catch (_) { - return null; - } - }).whereNotNull()))); - unspentCoins = unspent.expand((e) => e).toList(); - unspentCoins.forEach((coin) async { - final tx = await fetchTransactionInfo(hash: coin.hash, height: 0); - coin.isChange = tx?.direction == TransactionDirection.outgoing; - }); + final coin = BitcoinUnspent.fromJSON(address, unspent); + final tx = await fetchTransactionInfo( + hash: coin.hash, height: 0, myAddresses: addressesSet); + coin.isChange = tx?.direction == TransactionDirection.outgoing; + updatedUnspentCoins.add(coin); + } catch (_) {} + })))); + + unspentCoins = updatedUnspentCoins; if (unspentCoinsInfo.isEmpty) { unspentCoins.forEach((coin) => _addCoinInfo(coin)); @@ -495,8 +535,10 @@ abstract class ElectrumWalletBase if (unspentCoins.isNotEmpty) { unspentCoins.forEach((coin) { - final coinInfoList = unspentCoinsInfo.values - .where((element) => element.walletId.contains(id) && element.hash.contains(coin.hash)); + final coinInfoList = unspentCoinsInfo.values.where((element) => + element.walletId.contains(id) && + element.hash.contains(coin.hash) && + element.vout == coin.vout); if (coinInfoList.isNotEmpty) { final coinInfo = coinInfoList.first; @@ -537,7 +579,8 @@ abstract class ElectrumWalletBase if (currentWalletUnspentCoins.isNotEmpty) { currentWalletUnspentCoins.forEach((element) { - final existUnspentCoins = unspentCoins.where((coin) => element.hash.contains(coin.hash)); + final existUnspentCoins = unspentCoins + .where((coin) => element.hash.contains(coin.hash) && element.vout == coin.vout); if (existUnspentCoins.isEmpty) { keys.add(element.key); @@ -555,92 +598,152 @@ abstract class ElectrumWalletBase Future getTransactionExpanded( {required String hash, required int height}) async { - final verboseTransaction = await electrumClient.getTransactionRaw(hash: hash); - final transactionHex = verboseTransaction['hex'] as String; - final original = bitcoin.Transaction.fromHex(transactionHex); - final ins = []; - final time = verboseTransaction['time'] as int?; - final confirmations = verboseTransaction['confirmations'] as int? ?? 0; + String transactionHex; + int? time; + int confirmations = 0; + if (network == BitcoinNetwork.testnet) { + // Testnet public electrum server does not support verbose transaction fetching + transactionHex = await electrumClient.getTransactionHex(hash: hash); - for (final vin in original.ins) { - final id = HEX.encode(vin.hash!.reversed.toList()); - final txHex = await electrumClient.getTransactionHex(hash: id); - final tx = bitcoin.Transaction.fromHex(txHex); - ins.add(tx); + final status = json.decode( + (await http.get(Uri.parse("https://blockstream.info/testnet/api/tx/$hash/status"))).body); + + time = status["block_time"] as int?; + final tip = await electrumClient.getCurrentBlockChainTip() ?? 0; + confirmations = tip - (status["block_height"] as int? ?? 0); + } else { + final verboseTransaction = await electrumClient.getTransactionRaw(hash: hash); + + transactionHex = verboseTransaction['hex'] as String; + time = verboseTransaction['time'] as int?; + confirmations = verboseTransaction['confirmations'] as int? ?? 0; } - return ElectrumTransactionBundle(original, ins: ins, time: time, confirmations: confirmations); + final original = bitcoin_base.BtcTransaction.fromRaw(transactionHex); + final ins = []; + + for (final vin in original.inputs) { + try { + final id = HEX.encode(HEX.decode(vin.txId).reversed.toList()); + final txHex = await electrumClient.getTransactionHex(hash: id); + final tx = bitcoin_base.BtcTransaction.fromRaw(txHex); + ins.add(tx); + } catch (_) { + ins.add(bitcoin_base.BtcTransaction.fromRaw( + await electrumClient.getTransactionHex(hash: vin.txId), + )); + } + } + + return ElectrumTransactionBundle(original, + ins: ins, time: time, confirmations: confirmations, height: height); } Future fetchTransactionInfo( - {required String hash, required int height}) async { + {required String hash, + required int height, + required Set myAddresses, + bool? retryOnFailure}) async { try { - final tx = await getTransactionExpanded(hash: hash, height: height); - final addresses = walletAddresses.addresses.map((addr) => addr.address).toSet(); - return ElectrumTransactionInfo.fromElectrumBundle(tx, walletInfo.type, networkType, - addresses: addresses, height: height); - } catch (_) { + return ElectrumTransactionInfo.fromElectrumBundle( + await getTransactionExpanded(hash: hash, height: height), walletInfo.type, network, + addresses: myAddresses, height: height); + } catch (e) { + if (e is FormatException && retryOnFailure == true) { + await Future.delayed(const Duration(seconds: 2)); + return fetchTransactionInfo(hash: hash, height: height, myAddresses: myAddresses); + } return null; } } @override Future> fetchTransactions() async { - final addressHashes = {}; - final normalizedHistories = >[]; - final newTxCounts = {}; - - walletAddresses.addresses.forEach((addressRecord) { - final sh = scriptHash(addressRecord.address, networkType: networkType); - addressHashes[sh] = addressRecord; - newTxCounts[sh] = 0; - }); - try { - final histories = addressHashes.keys.map((scriptHash) => - electrumClient.getHistory(scriptHash).then((history) => {scriptHash: history})); - final historyResults = await Future.wait(histories); + final Map historiesWithDetails = {}; + final addressesSet = walletAddresses.allAddresses.map((addr) => addr.address).toSet(); + final currentHeight = await electrumClient.getCurrentBlockChainTip() ?? 0; - historyResults.forEach((history) { - history.entries.forEach((historyItem) { - if (historyItem.value.isNotEmpty) { - final address = addressHashes[historyItem.key]; - address?.setAsUsed(); - newTxCounts[historyItem.key] = historyItem.value.length; - normalizedHistories.addAll(historyItem.value); + await Future.wait(ADDRESS_TYPES.map((type) { + final addressesByType = walletAddresses.allAddresses.where((addr) => addr.type == type); + + return Future.wait(addressesByType.map((addressRecord) async { + final history = await _fetchAddressHistory(addressRecord, addressesSet, currentHeight); + + if (history.isNotEmpty) { + addressRecord.txCount = history.length; + historiesWithDetails.addAll(history); + + final matchedAddresses = + addressesByType.where((addr) => addr.isHidden == addressRecord.isHidden); + + final isLastUsedAddress = + history.isNotEmpty && addressRecord.address == matchedAddresses.last.address; + + if (isLastUsedAddress) { + await walletAddresses.discoverAddresses( + matchedAddresses.toList(), + addressRecord.isHidden, + (address, addressesSet) => + _fetchAddressHistory(address, addressesSet, currentHeight) + .then((history) => history.isNotEmpty ? address.address : null), + type: type); + } } - }); - }); - - for (var sh in addressHashes.keys) { - var balanceData = await electrumClient.getBalance(sh); - var addressRecord = addressHashes[sh]; - if (addressRecord != null) { - addressRecord.balance = balanceData['confirmed'] as int? ?? 0; - } - } - - addressHashes.forEach((sh, addressRecord) { - addressRecord.txCount = newTxCounts[sh] ?? 0; - }); - - final historiesWithDetails = await Future.wait(normalizedHistories.map((transaction) { - try { - return fetchTransactionInfo( - hash: transaction['tx_hash'] as String, height: transaction['height'] as int); - } catch (_) { - return Future.value(null); - } + })); })); - return historiesWithDetails.fold>( - {}, (acc, tx) { - if (tx == null) { - return acc; - } - acc[tx.id] = acc[tx.id]?.updated(tx) ?? tx; - return acc; - }); + return historiesWithDetails; + } catch (e) { + print(e.toString()); + return {}; + } + } + + Future> _fetchAddressHistory( + BitcoinAddressRecord addressRecord, Set addressesSet, int currentHeight) async { + try { + final Map historiesWithDetails = {}; + + final history = await electrumClient + .getHistory(addressRecord.scriptHash ?? addressRecord.updateScriptHash(network)); + + if (history.isNotEmpty) { + addressRecord.setAsUsed(); + + await Future.wait(history.map((transaction) async { + final txid = transaction['tx_hash'] as String; + final height = transaction['height'] as int; + final storedTx = transactionHistory.transactions[txid]; + + if (storedTx != null) { + if (height > 0) { + storedTx.height = height; + // the tx's block itself is the first confirmation so add 1 + storedTx.confirmations = currentHeight - height + 1; + storedTx.isPending = storedTx.confirmations == 0; + } + + historiesWithDetails[txid] = storedTx; + } else { + final tx = await fetchTransactionInfo( + hash: txid, height: height, myAddresses: addressesSet, retryOnFailure: true); + + if (tx != null) { + historiesWithDetails[txid] = tx; + + // Got a new transaction fetched, add it to the transaction history + // instead of waiting all to finish, and next time it will be faster + transactionHistory.addOne(tx); + await transactionHistory.save(); + } + } + + return Future.value(null); + })); + } + + return historiesWithDetails; } catch (e) { print(e.toString()); return {}; @@ -654,10 +757,8 @@ abstract class ElectrumWalletBase } _isTransactionUpdating = true; - final transactions = await fetchTransactions(); - transactionHistory.addMany(transactions); + await fetchTransactions(); walletAddresses.updateReceiveAddresses(); - await transactionHistory.save(); _isTransactionUpdating = false; } catch (e, stacktrace) { print(stacktrace); @@ -688,11 +789,11 @@ abstract class ElectrumWalletBase } Future _fetchBalances() async { - final addresses = walletAddresses.addresses.toList(); + final addresses = walletAddresses.allAddresses.toList(); final balanceFutures = >>[]; for (var i = 0; i < addresses.length; i++) { final addressRecord = addresses[i]; - final sh = scriptHash(addressRecord.address, networkType: networkType); + final sh = scriptHash(addressRecord.address, network: network); final balanceFuture = electrumClient.getBalance(sh); balanceFutures.add(balanceFuture); } @@ -701,6 +802,7 @@ abstract class ElectrumWalletBase unspentCoinsInfo.values.forEach((info) { unspentCoins.forEach((element) { if (element.hash == info.hash && + element.vout == info.vout && info.isFrozen && element.bitcoinAddressRecord.address == info.address && element.value == info.value) { @@ -738,10 +840,10 @@ abstract class ElectrumWalletBase String getChangeAddress() { const minCountOfHiddenAddresses = 5; final random = Random(); - var addresses = walletAddresses.addresses.where((addr) => addr.isHidden).toList(); + var addresses = walletAddresses.allAddresses.where((addr) => addr.isHidden).toList(); if (addresses.length < minCountOfHiddenAddresses) { - addresses = walletAddresses.addresses.toList(); + addresses = walletAddresses.allAddresses.toList(); } return addresses[random.nextInt(addresses.length)].address; @@ -753,9 +855,62 @@ abstract class ElectrumWalletBase @override String signMessage(String message, {String? address = null}) { final index = address != null - ? walletAddresses.addresses.firstWhere((element) => element.address == address).index + ? walletAddresses.allAddresses.firstWhere((element) => element.address == address).index : null; final HD = index == null ? hd : hd.derive(index); return base64Encode(HD.signMessage(message)); } } + +class EstimateTxParams { + EstimateTxParams( + {required this.amount, + required this.feeRate, + required this.priority, + required this.outputsCount, + required this.size}); + + final int amount; + final int feeRate; + final TransactionPriority priority; + final int outputsCount; + final int size; +} + +class EstimatedTxResult { + EstimatedTxResult( + {required this.utxos, required this.privateKeys, required this.fee, required this.amount}); + + final List utxos; + final List privateKeys; + final int fee; + final int amount; +} + +BitcoinBaseAddress _addressTypeFromStr(String address, BasedUtxoNetwork network) { + if (P2pkhAddress.regex.hasMatch(address)) { + return P2pkhAddress.fromAddress(address: address, network: network); + } else if (P2shAddress.regex.hasMatch(address)) { + return P2shAddress.fromAddress(address: address, network: network); + } else if (P2wshAddress.regex.hasMatch(address)) { + return P2wshAddress.fromAddress(address: address, network: network); + } else if (P2trAddress.regex.hasMatch(address)) { + return P2trAddress.fromAddress(address: address, network: network); + } else { + return P2wpkhAddress.fromAddress(address: address, network: network); + } +} + +BitcoinAddressType _getScriptType(BitcoinBaseAddress type) { + if (type is P2pkhAddress) { + return P2pkhAddressType.p2pkh; + } else if (type is P2shAddress) { + return P2shAddressType.p2wpkhInP2sh; + } else if (type is P2wshAddress) { + return SegwitAddresType.p2wsh; + } else if (type is P2trAddress) { + return SegwitAddresType.p2tr; + } else { + return SegwitAddresType.p2wpkh; + } +} diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 850d58f40..5880f5a19 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -1,8 +1,8 @@ -import 'package:bitbox/bitbox.dart' as bitbox; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:bitbox/bitbox.dart' as bitbox; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum.dart'; -import 'package:cw_bitcoin/script_hash.dart'; import 'package:cw_core/wallet_addresses.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; @@ -12,25 +12,41 @@ part 'electrum_wallet_addresses.g.dart'; class ElectrumWalletAddresses = ElectrumWalletAddressesBase with _$ElectrumWalletAddresses; +const List ADDRESS_TYPES = [ + SegwitAddresType.p2wpkh, + P2pkhAddressType.p2pkh, + SegwitAddresType.p2tr, + SegwitAddresType.p2wsh, + P2shAddressType.p2wpkhInP2sh, +]; + abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { - ElectrumWalletAddressesBase(WalletInfo walletInfo, - {required this.mainHd, - required this.sideHd, - required this.electrumClient, - required this.networkType, - List? initialAddresses, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) - : addresses = ObservableList.of((initialAddresses ?? []).toSet()), + ElectrumWalletAddressesBase( + WalletInfo walletInfo, { + required this.mainHd, + required this.sideHd, + required this.electrumClient, + required this.network, + List? initialAddresses, + Map? initialRegularAddressIndex, + Map? initialChangeAddressIndex, + }) : _addresses = ObservableList.of((initialAddresses ?? []).toSet()), + addressesByReceiveType = + ObservableList.of(([]).toSet()), receiveAddresses = ObservableList.of((initialAddresses ?? []) .where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed) .toSet()), changeAddresses = ObservableList.of((initialAddresses ?? []) .where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed) .toSet()), - currentReceiveAddressIndex = initialRegularAddressIndex, - currentChangeAddressIndex = initialChangeAddressIndex, - super(walletInfo); + currentReceiveAddressIndexByType = initialRegularAddressIndex ?? {}, + currentChangeAddressIndexByType = initialChangeAddressIndex ?? {}, + _addressPageType = walletInfo.addressPageType != null + ? BitcoinAddressType.fromValue(walletInfo.addressPageType!) + : SegwitAddresType.p2wpkh, + super(walletInfo) { + updateAddressesByMatch(); + } static const defaultReceiveAddressesCount = 22; static const defaultChangeAddressesCount = 17; @@ -40,37 +56,48 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { static String toLegacy(String address) => bitbox.Address.toLegacyAddress(address); - final ObservableList addresses; + final ObservableList _addresses; + // Matched by addressPageType + late ObservableList addressesByReceiveType; final ObservableList receiveAddresses; final ObservableList changeAddresses; final ElectrumClient electrumClient; - final bitcoin.NetworkType networkType; + final BasedUtxoNetwork network; final bitcoin.HDWallet mainHd; final bitcoin.HDWallet sideHd; + @observable + BitcoinAddressType _addressPageType = SegwitAddresType.p2wpkh; + + @computed + BitcoinAddressType get addressPageType => _addressPageType; + + @computed + List get allAddresses => _addresses; + @override @computed String get address { - if (isEnabledAutoGenerateSubaddress) { - if (receiveAddresses.isEmpty) { - final newAddress = generateNewAddress(hd: mainHd).address; - return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(newAddress) : newAddress; - } - final receiveAddress = receiveAddresses.first.address; + String receiveAddress; - return walletInfo.type == WalletType.bitcoinCash - ? toCashAddr(receiveAddress) - : receiveAddress; + final typeMatchingReceiveAddresses = receiveAddresses.where(_isAddressPageTypeMatch); + + if ((isEnabledAutoGenerateSubaddress && receiveAddresses.isEmpty) || + typeMatchingReceiveAddresses.isEmpty) { + receiveAddress = generateNewAddress().address; } else { - final receiveAddress = (receiveAddresses.first.address != addresses.first.address && - previousAddressRecord != null) - ? previousAddressRecord!.address - : addresses.first.address; + final previousAddressMatchesType = + previousAddressRecord != null && previousAddressRecord!.type == addressPageType; - return walletInfo.type == WalletType.bitcoinCash - ? toCashAddr(receiveAddress) - : receiveAddress; + if (previousAddressMatchesType && + typeMatchingReceiveAddresses.first.address != addressesByReceiveType.first.address) { + receiveAddress = previousAddressRecord!.address; + } else { + receiveAddress = typeMatchingReceiveAddresses.first.address; + } } + + return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(receiveAddress) : receiveAddress; } @observable @@ -81,7 +108,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { if (addr.startsWith('bitcoincash:')) { addr = toLegacy(addr); } - final addressRecord = addresses.firstWhere((addressRecord) => addressRecord.address == addr); + final addressRecord = _addresses.firstWhere((addressRecord) => addressRecord.address == addr); previousAddressRecord = addressRecord; receiveAddresses.remove(addressRecord); @@ -89,16 +116,29 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } @override - String get primaryAddress => getAddress(index: 0, hd: mainHd); + String get primaryAddress => getAddress(index: 0, hd: mainHd, addressType: addressPageType); - int currentReceiveAddressIndex; - int currentChangeAddressIndex; + Map currentReceiveAddressIndexByType; + + int get currentReceiveAddressIndex => + currentReceiveAddressIndexByType[_addressPageType.toString()] ?? 0; + + void set currentReceiveAddressIndex(int index) => + currentReceiveAddressIndexByType[_addressPageType.toString()] = index; + + Map currentChangeAddressIndexByType; + + int get currentChangeAddressIndex => + currentChangeAddressIndexByType[_addressPageType.toString()] ?? 0; + + void set currentChangeAddressIndex(int index) => + currentChangeAddressIndexByType[_addressPageType.toString()] = index; @observable BitcoinAddressRecord? previousAddressRecord; @computed - int get totalCountOfReceiveAddresses => addresses.fold(0, (acc, addressRecord) { + int get totalCountOfReceiveAddresses => addressesByReceiveType.fold(0, (acc, addressRecord) { if (!addressRecord.isHidden) { return acc + 1; } @@ -106,22 +146,21 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { }); @computed - int get totalCountOfChangeAddresses => addresses.fold(0, (acc, addressRecord) { + int get totalCountOfChangeAddresses => addressesByReceiveType.fold(0, (acc, addressRecord) { if (addressRecord.isHidden) { return acc + 1; } return acc; }); - Future discoverAddresses() async { - await _discoverAddresses(mainHd, false); - await _discoverAddresses(sideHd, true); - await updateAddressesInBox(); - } - @override Future init() async { await _generateInitialAddresses(); + await _generateInitialAddresses(type: P2pkhAddressType.p2pkh); + await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh); + await _generateInitialAddresses(type: SegwitAddresType.p2tr); + await _generateInitialAddresses(type: SegwitAddresType.p2wsh); + updateAddressesByMatch(); updateReceiveAddresses(); updateChangeAddresses(); await updateAddressesInBox(); @@ -141,10 +180,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { if (changeAddresses.isEmpty) { final newAddresses = await _createNewAddresses(gap, - hd: sideHd, startIndex: totalCountOfChangeAddresses > 0 ? totalCountOfChangeAddresses - 1 : 0, isHidden: true); - _addAddresses(newAddresses); + addAddresses(newAddresses); } if (currentChangeAddressIndex >= changeAddresses.length) { @@ -157,19 +195,26 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { return address; } - BitcoinAddressRecord generateNewAddress({bitcoin.HDWallet? hd, String? label}) { - final isHidden = hd == sideHd; + BitcoinAddressRecord generateNewAddress({String label = ''}) { + final newAddressIndex = addressesByReceiveType.fold( + 0, (int acc, addressRecord) => addressRecord.isHidden == false ? acc + 1 : acc); - final newAddressIndex = addresses.fold( - 0, (int acc, addressRecord) => isHidden == addressRecord.isHidden ? acc + 1 : acc); - - final address = BitcoinAddressRecord(getAddress(index: newAddressIndex, hd: hd ?? sideHd), - index: newAddressIndex, isHidden: isHidden, name: label ?? ''); - addresses.add(address); + final address = BitcoinAddressRecord( + getAddress(index: newAddressIndex, hd: mainHd, addressType: addressPageType), + index: newAddressIndex, + isHidden: false, + name: label, + type: addressPageType, + network: network, + ); + _addresses.add(address); + updateAddressesByMatch(); return address; } - String getAddress({required int index, required bitcoin.HDWallet hd}) => ''; + String getAddress( + {required int index, required bitcoin.HDWallet hd, BitcoinAddressType? addressType}) => + ''; @override Future updateAddressesInBox() async { @@ -187,126 +232,138 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { if (address.startsWith('bitcoincash:')) { address = toLegacy(address); } - final addressRecord = addresses.firstWhere((addressRecord) => addressRecord.address == address); + final addressRecord = + _addresses.firstWhere((addressRecord) => addressRecord.address == address); addressRecord.setNewName(label); - final index = addresses.indexOf(addressRecord); - addresses.remove(addressRecord); - addresses.insert(index, addressRecord); + final index = _addresses.indexOf(addressRecord); + _addresses.remove(addressRecord); + _addresses.insert(index, addressRecord); + } + + @action + void updateAddressesByMatch() { + addressesByReceiveType.clear(); + addressesByReceiveType.addAll(_addresses.where(_isAddressPageTypeMatch).toList()); } @action void updateReceiveAddresses() { receiveAddresses.removeRange(0, receiveAddresses.length); final newAddresses = - addresses.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed); + _addresses.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed); receiveAddresses.addAll(newAddresses); } @action void updateChangeAddresses() { changeAddresses.removeRange(0, changeAddresses.length); - final newAddresses = - addresses.where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed); + final newAddresses = _addresses.where((addressRecord) => + addressRecord.isHidden && + !addressRecord.isUsed && + // TODO: feature to change change address type. For now fixed to p2wpkh, the cheapest type + addressRecord.type == SegwitAddresType.p2wpkh); changeAddresses.addAll(newAddresses); } - Future _discoverAddresses(bitcoin.HDWallet hd, bool isHidden) async { - var hasAddrUse = true; - List addrs; - - if (addresses.isNotEmpty) { - - - if(!isHidden) { - final receiveAddressesList = addresses.where((addr) => !addr.isHidden).toList(); - validateSideHdAddresses(receiveAddressesList); - } - - addrs = addresses.where((addr) => addr.isHidden == isHidden).toList(); - } else { - addrs = await _createNewAddresses( - isHidden ? defaultChangeAddressesCount : defaultReceiveAddressesCount, - startIndex: 0, - hd: hd, - isHidden: isHidden); + @action + Future discoverAddresses(List addressList, bool isHidden, + Future Function(BitcoinAddressRecord, Set) getAddressHistory, + {BitcoinAddressType type = SegwitAddresType.p2wpkh}) async { + if (!isHidden) { + _validateSideHdAddresses(addressList.toList()); } - while (hasAddrUse) { - final addr = addrs.last.address; - hasAddrUse = await _hasAddressUsed(addr); + final newAddresses = await _createNewAddresses(gap, + startIndex: addressList.length, isHidden: isHidden, type: type); + addAddresses(newAddresses); - if (!hasAddrUse) { - break; - } + final addressesWithHistory = await Future.wait(newAddresses + .map((addr) => getAddressHistory(addr, _addresses.map((e) => e.address).toSet()))); + final isLastAddressUsed = addressesWithHistory.last == addressList.last.address; - final start = addrs.length; - final count = start + gap; - final batch = await _createNewAddresses(count, startIndex: start, hd: hd, isHidden: isHidden); - addrs.addAll(batch); - } - - if (addresses.length < addrs.length) { - _addAddresses(addrs); + if (isLastAddressUsed) { + discoverAddresses(addressList, isHidden, getAddressHistory, type: type); } } - Future _generateInitialAddresses() async { + Future _generateInitialAddresses( + {BitcoinAddressType type = SegwitAddresType.p2wpkh}) async { var countOfReceiveAddresses = 0; var countOfHiddenAddresses = 0; - addresses.forEach((addr) { - if (addr.isHidden) { - countOfHiddenAddresses += 1; - return; - } + _addresses.forEach((addr) { + if (addr.type == type) { + if (addr.isHidden) { + countOfHiddenAddresses += 1; + return; + } - countOfReceiveAddresses += 1; + countOfReceiveAddresses += 1; + } }); if (countOfReceiveAddresses < defaultReceiveAddressesCount) { final addressesCount = defaultReceiveAddressesCount - countOfReceiveAddresses; final newAddresses = await _createNewAddresses(addressesCount, - startIndex: countOfReceiveAddresses, hd: mainHd, isHidden: false); - addresses.addAll(newAddresses); + startIndex: countOfReceiveAddresses, isHidden: false, type: type); + addAddresses(newAddresses); } if (countOfHiddenAddresses < defaultChangeAddressesCount) { final addressesCount = defaultChangeAddressesCount - countOfHiddenAddresses; final newAddresses = await _createNewAddresses(addressesCount, - startIndex: countOfHiddenAddresses, hd: sideHd, isHidden: true); - addresses.addAll(newAddresses); + startIndex: countOfHiddenAddresses, isHidden: true, type: type); + addAddresses(newAddresses); } } Future> _createNewAddresses(int count, - {required bitcoin.HDWallet hd, int startIndex = 0, bool isHidden = false}) async { + {int startIndex = 0, bool isHidden = false, BitcoinAddressType? type}) async { final list = []; for (var i = startIndex; i < count + startIndex; i++) { - final address = - BitcoinAddressRecord(getAddress(index: i, hd: hd), index: i, isHidden: isHidden); + final address = BitcoinAddressRecord( + getAddress(index: i, hd: _getHd(isHidden), addressType: type ?? addressPageType), + index: i, + isHidden: isHidden, + type: type ?? addressPageType, + network: network, + ); list.add(address); } return list; } - void _addAddresses(Iterable addresses) { - final addressesSet = this.addresses.toSet(); + @action + void addAddresses(Iterable addresses) { + final addressesSet = this._addresses.toSet(); addressesSet.addAll(addresses); - this.addresses.removeRange(0, this.addresses.length); - this.addresses.addAll(addressesSet); + this._addresses.clear(); + this._addresses.addAll(addressesSet); + updateAddressesByMatch(); } - Future _hasAddressUsed(String address) async { - final sh = scriptHash(address, networkType: networkType); - final transactionHistory = await electrumClient.getHistory(sh); - return transactionHistory.isNotEmpty; - } - - void validateSideHdAddresses(List addrWithTransactions) { + void _validateSideHdAddresses(List addrWithTransactions) { addrWithTransactions.forEach((element) { - if (element.address != getAddress(index: element.index, hd: mainHd)) element.isHidden = true; + if (element.address != + getAddress(index: element.index, hd: mainHd, addressType: element.type)) + element.isHidden = true; }); } + + @action + Future setAddressType(BitcoinAddressType type) async { + _addressPageType = type; + updateAddressesByMatch(); + walletInfo.addressPageType = addressPageType.toString(); + await walletInfo.save(); + } + + bool _isAddressPageTypeMatch(BitcoinAddressRecord addressRecord) { + return _isAddressByType(addressRecord, addressPageType); + } + + bitcoin.HDWallet _getHd(bool isHidden) => isHidden ? sideHd : mainHd; + bool _isAddressByType(BitcoinAddressRecord addr, BitcoinAddressType type) => addr.type == type; } diff --git a/cw_bitcoin/lib/electrum_wallet_snapshot.dart b/cw_bitcoin/lib/electrum_wallet_snapshot.dart index 86d3e2fed..98c3753db 100644 --- a/cw_bitcoin/lib/electrum_wallet_snapshot.dart +++ b/cw_bitcoin/lib/electrum_wallet_snapshot.dart @@ -1,12 +1,13 @@ import 'dart:convert'; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum_balance.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/utils/file.dart'; import 'package:cw_core/wallet_type.dart'; -class ElectrumWallletSnapshot { - ElectrumWallletSnapshot({ +class ElectrumWalletSnapshot { + ElectrumWalletSnapshot({ required this.name, required this.type, required this.password, @@ -14,19 +15,24 @@ class ElectrumWallletSnapshot { required this.addresses, required this.balance, required this.regularAddressIndex, - required this.changeAddressIndex}); + required this.changeAddressIndex, + required this.addressPageType, + required this.network, + }); final String name; final String password; final WalletType type; + final String addressPageType; + final BasedUtxoNetwork network; String mnemonic; List addresses; ElectrumBalance balance; - int regularAddressIndex; - int changeAddressIndex; + Map regularAddressIndex; + Map changeAddressIndex; - static Future load(String name, WalletType type, String password) async { + static Future load(String name, WalletType type, String password, BasedUtxoNetwork? network) async { final path = await pathForWallet(name: name, type: type); final jsonSource = await read(path: path, password: password); final data = json.decode(jsonSource) as Map; @@ -34,26 +40,39 @@ class ElectrumWallletSnapshot { final mnemonic = data['mnemonic'] as String; final addresses = addressesTmp .whereType() - .map((addr) => BitcoinAddressRecord.fromJSON(addr)) + .map((addr) => BitcoinAddressRecord.fromJSON(addr, network)) .toList(); final balance = ElectrumBalance.fromJSON(data['balance'] as String) ?? ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0); - var regularAddressIndex = 0; - var changeAddressIndex = 0; + var regularAddressIndexByType = {SegwitAddresType.p2wpkh.toString(): 0}; + var changeAddressIndexByType = {SegwitAddresType.p2wpkh.toString(): 0}; try { - regularAddressIndex = int.parse(data['account_index'] as String? ?? '0'); - changeAddressIndex = int.parse(data['change_address_index'] as String? ?? '0'); - } catch (_) {} + regularAddressIndexByType = { + SegwitAddresType.p2wpkh.toString(): int.parse(data['account_index'] as String? ?? '0') + }; + changeAddressIndexByType = { + SegwitAddresType.p2wpkh.toString(): + int.parse(data['change_address_index'] as String? ?? '0') + }; + } catch (_) { + try { + regularAddressIndexByType = data["account_index"] as Map? ?? {}; + changeAddressIndexByType = data["change_address_index"] as Map? ?? {}; + } catch (_) {} + } - return ElectrumWallletSnapshot( + return ElectrumWalletSnapshot( name: name, type: type, password: password, mnemonic: mnemonic, addresses: addresses, balance: balance, - regularAddressIndex: regularAddressIndex, - changeAddressIndex: changeAddressIndex); + regularAddressIndex: regularAddressIndexByType, + changeAddressIndex: changeAddressIndexByType, + addressPageType: data['address_page_type'] as String? ?? SegwitAddresType.p2wpkh.toString(), + network: data['network_type'] == 'testnet' ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet, + ); } } diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 222e95acc..d2379d5a5 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -1,3 +1,4 @@ +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; import 'package:cw_core/crypto_currency.dart'; @@ -20,17 +21,18 @@ part 'litecoin_wallet.g.dart'; class LitecoinWallet = LitecoinWalletBase with _$LitecoinWallet; abstract class LitecoinWalletBase extends ElectrumWallet with Store { - LitecoinWalletBase( - {required String mnemonic, - required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - required Uint8List seedBytes, - List? initialAddresses, - ElectrumBalance? initialBalance, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) - : super( + LitecoinWalletBase({ + required String mnemonic, + required String password, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required Uint8List seedBytes, + String? addressPageType, + List? initialAddresses, + ElectrumBalance? initialBalance, + Map? initialRegularAddressIndex, + Map? initialChangeAddressIndex, + }) : super( mnemonic: mnemonic, password: password, walletInfo: walletInfo, @@ -41,41 +43,42 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { seedBytes: seedBytes, currency: CryptoCurrency.ltc) { walletAddresses = LitecoinWalletAddresses( - walletInfo, - electrumClient: electrumClient, - initialAddresses: initialAddresses, - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex, - mainHd: hd, - sideHd: bitcoin.HDWallet - .fromSeed(seedBytes, network: networkType) - .derivePath("m/0'/1"), - networkType: networkType,); + walletInfo, + electrumClient: electrumClient, + initialAddresses: initialAddresses, + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + mainHd: hd, + sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"), + network: network, + ); autorun((_) { this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress; }); } - static Future create({ - required String mnemonic, - required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - List? initialAddresses, - ElectrumBalance? initialBalance, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0 - }) async { + static Future create( + {required String mnemonic, + required String password, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + String? addressPageType, + List? initialAddresses, + ElectrumBalance? initialBalance, + Map? initialRegularAddressIndex, + Map? initialChangeAddressIndex}) async { return LitecoinWallet( - mnemonic: mnemonic, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - initialAddresses: initialAddresses, - initialBalance: initialBalance, - seedBytes: await mnemonicToSeedBytes(mnemonic), - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex); + mnemonic: mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: initialAddresses, + initialBalance: initialBalance, + seedBytes: await mnemonicToSeedBytes(mnemonic), + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + addressPageType: addressPageType, + ); } static Future open({ @@ -84,17 +87,20 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { required Box unspentCoinsInfo, required String password, }) async { - final snp = await ElectrumWallletSnapshot.load (name, walletInfo.type, password); + final snp = + await ElectrumWalletSnapshot.load(name, walletInfo.type, password, LitecoinNetwork.mainnet); return LitecoinWallet( - mnemonic: snp.mnemonic, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - initialAddresses: snp.addresses, - initialBalance: snp.balance, - seedBytes: await mnemonicToSeedBytes(snp.mnemonic), - initialRegularAddressIndex: snp.regularAddressIndex, - initialChangeAddressIndex: snp.changeAddressIndex); + mnemonic: snp.mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: snp.addresses, + initialBalance: snp.balance, + seedBytes: await mnemonicToSeedBytes(snp.mnemonic), + initialRegularAddressIndex: snp.regularAddressIndex, + initialChangeAddressIndex: snp.changeAddressIndex, + addressPageType: snp.addressPageType, + ); } @override diff --git a/cw_bitcoin/lib/litecoin_wallet_addresses.dart b/cw_bitcoin/lib/litecoin_wallet_addresses.dart index a317fa9f2..993d17933 100644 --- a/cw_bitcoin/lib/litecoin_wallet_addresses.dart +++ b/cw_bitcoin/lib/litecoin_wallet_addresses.dart @@ -1,39 +1,28 @@ +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/utils.dart'; -import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:cw_core/wallet_info.dart'; -import 'package:flutter/foundation.dart'; import 'package:mobx/mobx.dart'; part 'litecoin_wallet_addresses.g.dart'; -class LitecoinWalletAddresses = LitecoinWalletAddressesBase - with _$LitecoinWalletAddresses; +class LitecoinWalletAddresses = LitecoinWalletAddressesBase with _$LitecoinWalletAddresses; -abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses - with Store { +abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with Store { LitecoinWalletAddressesBase( - WalletInfo walletInfo, - {required bitcoin.HDWallet mainHd, - required bitcoin.HDWallet sideHd, - required bitcoin.NetworkType networkType, - required ElectrumClient electrumClient, - List? initialAddresses, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) - : super( - walletInfo, - initialAddresses: initialAddresses, - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex, - mainHd: mainHd, - sideHd: sideHd, - electrumClient: electrumClient, - networkType: networkType); + WalletInfo walletInfo, { + required super.mainHd, + required super.sideHd, + required super.network, + required super.electrumClient, + super.initialAddresses, + super.initialRegularAddressIndex, + super.initialChangeAddressIndex, + }) : super(walletInfo); @override - String getAddress({required int index, required bitcoin.HDWallet hd}) => - generateP2WPKHAddress(hd: hd, index: index, networkType: networkType); -} \ No newline at end of file + String getAddress( + {required int index, required bitcoin.HDWallet hd, BitcoinAddressType? addressType}) => + generateP2WPKHAddress(hd: hd, index: index, network: network); +} diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index 69d1dfc7e..3d7462fa1 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -25,7 +25,7 @@ class LitecoinWalletService extends WalletService< WalletType getType() => WalletType.litecoin; @override - Future create(BitcoinNewWalletCredentials credentials) async { + Future create(BitcoinNewWalletCredentials credentials, {bool? isTestnet}) async { final wallet = await LitecoinWalletBase.create( mnemonic: await generateMnemonic(), password: credentials.password!, @@ -94,12 +94,12 @@ class LitecoinWalletService extends WalletService< @override Future restoreFromKeys( - BitcoinRestoreWalletFromWIFCredentials credentials) async => + BitcoinRestoreWalletFromWIFCredentials credentials, {bool? isTestnet}) async => throw UnimplementedError(); @override Future restoreFromSeed( - BitcoinRestoreWalletFromSeedCredentials credentials) async { + BitcoinRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinMnemonicIsIncorrectException(); } diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart index e2dc10bfb..fa413febd 100644 --- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart +++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart @@ -1,5 +1,5 @@ import 'package:cw_bitcoin/bitcoin_commit_transaction_exception.dart'; -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_core/pending_transaction.dart'; import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/bitcoin_amount_format.dart'; @@ -9,22 +9,21 @@ import 'package:cw_core/wallet_type.dart'; class PendingBitcoinTransaction with PendingTransaction { PendingBitcoinTransaction(this._tx, this.type, - {required this.electrumClient, - required this.amount, - required this.fee}) + {required this.electrumClient, required this.amount, required this.fee, this.network}) : _listeners = []; final WalletType type; - final bitcoin.Transaction _tx; + final BtcTransaction _tx; final ElectrumClient electrumClient; final int amount; final int fee; + final BasedUtxoNetwork? network; @override - String get id => _tx.getId(); + String get id => _tx.txId(); @override - String get hex => _tx.toHex(); + String get hex => _tx.serialize(); @override String get amountFormatted => bitcoinAmountToString(amount: amount); @@ -36,18 +35,16 @@ class PendingBitcoinTransaction with PendingTransaction { @override Future commit() async { - final result = - await electrumClient.broadcastTransaction(transactionRaw: _tx.toHex()); + final result = await electrumClient.broadcastTransaction(transactionRaw: hex, network: network); if (result.isEmpty) { throw BitcoinCommitTransactionException(); } - _listeners?.forEach((listener) => listener(transactionInfo())); + _listeners.forEach((listener) => listener(transactionInfo())); } - void addListener( - void Function(ElectrumTransactionInfo transaction) listener) => + void addListener(void Function(ElectrumTransactionInfo transaction) listener) => _listeners.add(listener); ElectrumTransactionInfo transactionInfo() => ElectrumTransactionInfo(type, diff --git a/cw_bitcoin/lib/script_hash.dart b/cw_bitcoin/lib/script_hash.dart index 76a1bfcf0..620d3d28a 100644 --- a/cw_bitcoin/lib/script_hash.dart +++ b/cw_bitcoin/lib/script_hash.dart @@ -1,9 +1,8 @@ -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:crypto/crypto.dart'; -String scriptHash(String address, {required bitcoin.NetworkType networkType}) { - final outputScript = - bitcoin.Address.addressToOutputScript(address, networkType); +String scriptHash(String address, {required BasedUtxoNetwork network}) { + final outputScript = addressToOutputScript(address: address, network: network); final parts = sha256.convert(outputScript).toString().split(''); var res = ''; diff --git a/cw_bitcoin/lib/utils.dart b/cw_bitcoin/lib/utils.dart index 0d5a413b3..b156ccba3 100644 --- a/cw_bitcoin/lib/utils.dart +++ b/cw_bitcoin/lib/utils.dart @@ -1,55 +1,33 @@ import 'dart:typed_data'; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:flutter/foundation.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData; import 'package:hex/hex.dart'; -bitcoin.PaymentData generatePaymentData( - {required bitcoin.HDWallet hd, required int index}) => - PaymentData( - pubkey: Uint8List.fromList(HEX.decode(hd.derive(index).pubKey!))); +bitcoin.PaymentData generatePaymentData({required bitcoin.HDWallet hd, required int index}) => + PaymentData(pubkey: Uint8List.fromList(HEX.decode(hd.derive(index).pubKey!))); -bitcoin.ECPair generateKeyPair( - {required bitcoin.HDWallet hd, - required int index, - required bitcoin.NetworkType network}) => - bitcoin.ECPair.fromWIF(hd.derive(index).wif!, network: network); +ECPrivate generateECPrivate( + {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => + ECPrivate.fromWif(hd.derive(index).wif!, netVersion: network.wifNetVer); String generateP2WPKHAddress( - {required bitcoin.HDWallet hd, - required int index, - required bitcoin.NetworkType networkType}) => - bitcoin - .P2WPKH( - data: PaymentData( - pubkey: - Uint8List.fromList(HEX.decode(hd.derive(index).pubKey!))), - network: networkType) - .data - .address!; + {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => + ECPublic.fromHex(hd.derive(index).pubKey!).toP2wpkhAddress().toAddress(network); -String generateP2WPKHAddressByPath( - {required bitcoin.HDWallet hd, - required String path, - required bitcoin.NetworkType networkType}) => - bitcoin - .P2WPKH( - data: PaymentData( - pubkey: - Uint8List.fromList(HEX.decode(hd.derivePath(path).pubKey!))), - network: networkType) - .data - .address!; +String generateP2SHAddress( + {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => + ECPublic.fromHex(hd.derive(index).pubKey!).toP2wpkhInP2sh().toAddress(network); + +String generateP2WSHAddress( + {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => + ECPublic.fromHex(hd.derive(index).pubKey!).toP2wshAddress().toAddress(network); String generateP2PKHAddress( - {required bitcoin.HDWallet hd, - required int index, - required bitcoin.NetworkType networkType}) => - bitcoin - .P2PKH( - data: PaymentData( - pubkey: - Uint8List.fromList(HEX.decode(hd.derive(index).pubKey!))), - network: networkType) - .data - .address!; + {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => + ECPublic.fromHex(hd.derive(index).pubKey!).toP2pkhAddress().toAddress(network); + +String generateP2TRAddress( + {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => + ECPublic.fromHex(hd.derive(index).pubKey!).toTaprootAddress().toAddress(network); diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 3344cb807..25e6f269d 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -21,18 +21,18 @@ packages: dependency: transitive description: name: args - sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.2" asn1lib: dependency: transitive description: name: asn1lib - sha256: ab96a1cb3beeccf8145c52e449233fe68364c9641623acd3adad66f8184f1039 + sha256: c9c85fedbe2188b95133cbe960e16f5f448860f7133330e272edbbca5893ddc6 url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.5.2" async: dependency: transitive description: @@ -75,6 +75,15 @@ packages: url: "https://github.com/cake-tech/bitbox-flutter.git" source: git version: "1.0.1" + bitcoin_base: + dependency: "direct main" + description: + path: "." + ref: cake-update-v1 + resolved-ref: "9611e9db77e92a8434e918cdfb620068f6fcb1aa" + url: "https://github.com/cake-tech/bitcoin_base.git" + source: git + version: "4.0.0" bitcoin_flutter: dependency: "direct main" description: @@ -84,6 +93,14 @@ packages: url: "https://github.com/cake-tech/bitcoin_flutter.git" source: git version: "2.1.0" + blockchain_utils: + dependency: "direct main" + description: + name: blockchain_utils + sha256: "9701dfaa74caad4daae1785f1ec4445cf7fb94e45620bc3a4aca1b9b281dc6c9" + url: "https://pub.dev" + source: hosted + version: "1.6.0" boolean_selector: dependency: transitive description: @@ -104,10 +121,10 @@ packages: dependency: transitive description: name: build - sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.1" build_config: dependency: transitive description: @@ -120,10 +137,10 @@ packages: dependency: transitive description: name: build_daemon - sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "4.0.1" build_resolvers: dependency: "direct dev" description: @@ -136,18 +153,18 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.8" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" + sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41" url: "https://pub.dev" source: hosted - version: "7.2.7" + version: "7.2.10" built_collection: dependency: transitive description: @@ -160,10 +177,10 @@ packages: dependency: transitive description: name: built_value - sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" + sha256: a3ec2e0f967bc47f69f95009bb93db936288d61d5343b9436e378b28a2f830c6 url: "https://pub.dev" source: hosted - version: "8.4.3" + version: "8.9.0" characters: dependency: transitive description: @@ -176,10 +193,10 @@ packages: dependency: transitive description: name: checked_yaml - sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.0.3" clock: dependency: transitive description: @@ -192,10 +209,10 @@ packages: dependency: transitive description: name: code_builder - sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.10.0" collection: dependency: transitive description: @@ -216,18 +233,18 @@ packages: dependency: transitive description: name: crypto - sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" cryptography: dependency: "direct main" description: name: cryptography - sha256: e0e37f79665cd5c86e8897f9abe1accfe813c0cc5299dab22256e22fddc1fef8 + sha256: df156c5109286340817d21fa7b62f9140f17915077127dd70f8bd7a2a0997a35 url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.5.0" cw_core: dependency: "direct main" description: @@ -247,10 +264,10 @@ packages: dependency: transitive description: name: encrypt - sha256: "4fd4e4fdc21b9d7d4141823e1e6515cd94e7b8d84749504c232999fba25d9bbb" + sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2" url: "https://pub.dev" source: hosted - version: "5.0.1" + version: "5.0.3" fake_async: dependency: transitive description: @@ -263,10 +280,10 @@ packages: dependency: transitive description: name: ffi - sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.0" file: dependency: transitive description: @@ -292,10 +309,10 @@ packages: dependency: "direct main" description: name: flutter_mobx - sha256: "0da4add0016387a7bf309a0d0c41d36c6b3ae25ed7a176409267f166509e723e" + sha256: "4a5d062ff85ed3759f4aac6410ff0ffae32e324b2e71ca722ae1b37b32e865f4" url: "https://pub.dev" source: hosted - version: "2.0.6+5" + version: "2.2.0+2" flutter_test: dependency: "direct dev" description: flutter @@ -313,18 +330,18 @@ packages: dependency: transitive description: name: glob - sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" graphs: dependency: transitive description: name: graphs - sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2 + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.1" hex: dependency: transitive description: @@ -401,18 +418,18 @@ packages: dependency: transitive description: name: json_annotation - sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 url: "https://pub.dev" source: hosted - version: "4.8.0" + version: "4.8.1" logging: dependency: transitive description: name: logging - sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" matcher: dependency: transitive description: @@ -449,18 +466,26 @@ packages: dependency: "direct main" description: name: mobx - sha256: f1862bd92c6a903fab67338f27e2f731117c3cb9ea37cee1a487f9e4e0de314a + sha256: "74ee54012dc7c1b3276eaa960a600a7418ef5f9997565deb8fca1fd88fb36b78" url: "https://pub.dev" source: hosted - version: "2.1.3+1" + version: "2.3.0+1" mobx_codegen: dependency: "direct dev" description: name: mobx_codegen - sha256: "86122e410d8ea24dda0c69adb5c2a6ccadd5ce02ad46e144764e0d0184a06181" + sha256: d4beb9cea4b7b014321235f8fdc7c2193ee0fe1d1198e9da7403f8bc85c4407c url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" package_config: dependency: transitive description: @@ -481,26 +506,26 @@ packages: dependency: "direct main" description: name: path_provider - sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 + sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" path_provider_linux: dependency: transitive description: @@ -513,10 +538,10 @@ packages: dependency: transitive description: name: path_provider_platform_interface - sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_windows: dependency: transitive description: @@ -529,26 +554,26 @@ packages: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.4" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.8" pointycastle: dependency: transitive description: name: pointycastle - sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 + sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" url: "https://pub.dev" source: hosted - version: "3.6.2" + version: "3.7.4" pool: dependency: transitive description: @@ -557,30 +582,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" - process: + provider: dependency: transitive description: - name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + name: provider + sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" url: "https://pub.dev" source: hosted - version: "4.2.4" + version: "6.1.1" pub_semver: dependency: transitive description: name: pub_semver - sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" pubspec_parse: dependency: transitive description: name: pubspec_parse - sha256: "75f6614d6dde2dc68948dffbaa4fe5dae32cd700eb9fb763fe11dfb45a3c4d0a" + sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.3" rxdart: dependency: "direct main" description: @@ -593,18 +618,18 @@ packages: dependency: transitive description: name: shelf - sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" sky_engine: dependency: transitive description: flutter @@ -702,10 +727,10 @@ packages: dependency: transitive description: name: typed_data - sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" unorm_dart: dependency: "direct main" description: @@ -726,42 +751,42 @@ packages: dependency: transitive description: name: watcher - sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.0" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.4.0" win32: dependency: transitive description: name: win32 - sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 + sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "5.0.9" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d url: "https://pub.dev" source: hosted - version: "0.2.0+3" + version: "1.0.4" yaml: dependency: transitive description: name: yaml - sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.7.0" + flutter: ">=3.10.0" diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index a50ff68ad..847b77773 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -30,6 +30,11 @@ dependencies: rxdart: ^0.27.5 unorm_dart: ^0.2.0 cryptography: ^2.0.5 + bitcoin_base: + git: + url: https://github.com/cake-tech/bitcoin_base.git + ref: cake-update-v1 + blockchain_utils: ^1.6.0 dev_dependencies: flutter_test: diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index 1b87e2231..3c40cf9e9 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -28,17 +28,18 @@ part 'bitcoin_cash_wallet.g.dart'; class BitcoinCashWallet = BitcoinCashWalletBase with _$BitcoinCashWallet; abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { - BitcoinCashWalletBase( - {required String mnemonic, - required String password, - required WalletInfo walletInfo, - required Box unspentCoinsInfo, - required Uint8List seedBytes, - List? initialAddresses, - ElectrumBalance? initialBalance, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) - : super( + BitcoinCashWalletBase({ + required String mnemonic, + required String password, + required WalletInfo walletInfo, + required Box unspentCoinsInfo, + required Uint8List seedBytes, + String? addressPageType, + List? initialAddresses, + ElectrumBalance? initialBalance, + Map? initialRegularAddressIndex, + Map? initialChangeAddressIndex, + }) : super( mnemonic: mnemonic, password: password, walletInfo: walletInfo, @@ -48,40 +49,43 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { initialBalance: initialBalance, seedBytes: seedBytes, currency: CryptoCurrency.bch) { - walletAddresses = BitcoinCashWalletAddresses(walletInfo, - electrumClient: electrumClient, - initialAddresses: initialAddresses, - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex, - mainHd: hd, - sideHd: bitcoin.HDWallet.fromSeed(seedBytes) - .derivePath("m/44'/145'/0'/1"), - networkType: networkType); + walletAddresses = BitcoinCashWalletAddresses( + walletInfo, + electrumClient: electrumClient, + initialAddresses: initialAddresses, + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + mainHd: hd, + sideHd: bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/1"), + network: network, + ); autorun((_) { this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress; }); } - static Future create( {required String mnemonic, required String password, required WalletInfo walletInfo, required Box unspentCoinsInfo, + String? addressPageType, List? initialAddresses, ElectrumBalance? initialBalance, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) async { + Map? initialRegularAddressIndex, + Map? initialChangeAddressIndex}) async { return BitcoinCashWallet( - mnemonic: mnemonic, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - initialAddresses: initialAddresses, - initialBalance: initialBalance, - seedBytes: await Mnemonic.toSeed(mnemonic), - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex); + mnemonic: mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: initialAddresses, + initialBalance: initialBalance, + seedBytes: await Mnemonic.toSeed(mnemonic), + initialRegularAddressIndex: initialRegularAddressIndex, + initialChangeAddressIndex: initialChangeAddressIndex, + addressPageType: addressPageType, + ); } static Future open({ @@ -90,17 +94,20 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { required Box unspentCoinsInfo, required String password, }) async { - final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password); + final snp = await ElectrumWalletSnapshot.load( + name, walletInfo.type, password, BitcoinCashNetwork.mainnet); return BitcoinCashWallet( - mnemonic: snp.mnemonic, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - initialAddresses: snp.addresses, - initialBalance: snp.balance, - seedBytes: await Mnemonic.toSeed(snp.mnemonic), - initialRegularAddressIndex: snp.regularAddressIndex, - initialChangeAddressIndex: snp.changeAddressIndex); + mnemonic: snp.mnemonic, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + initialAddresses: snp.addresses, + initialBalance: snp.balance, + seedBytes: await Mnemonic.toSeed(snp.mnemonic), + initialRegularAddressIndex: snp.regularAddressIndex, + initialChangeAddressIndex: snp.changeAddressIndex, + addressPageType: snp.addressPageType, + ); } @override @@ -270,20 +277,18 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { electrumClient: electrumClient, amount: amount, fee: fee); } - bitbox.ECPair generateKeyPair( - {required bitcoin.HDWallet hd, - required int index}) => + bitbox.ECPair generateKeyPair({required bitcoin.HDWallet hd, required int index}) => bitbox.ECPair.fromWIF(hd.derive(index).wif!); @override - int feeAmountForPriority( - BitcoinTransactionPriority priority, int inputsCount, int outputsCount) => + int feeAmountForPriority(BitcoinTransactionPriority priority, int inputsCount, int outputsCount, + {int? size}) => feeRate(priority) * bitbox.BitcoinCash.getByteCount(inputsCount, outputsCount); - int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount) => + int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount, {int? size}) => feeRate * bitbox.BitcoinCash.getByteCount(inputsCount, outputsCount); - int calculateEstimatedFeeWithFeeRate(int feeRate, int? amount, {int? outputsCount}) { + int calculateEstimatedFeeWithFeeRate(int feeRate, int? amount, {int? outputsCount, int? size}) { int inputsCount = 0; int totalValue = 0; @@ -323,9 +328,10 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { @override String signMessage(String message, {String? address = null}) { final index = address != null - ? walletAddresses.addresses + ? walletAddresses.allAddresses .firstWhere((element) => element.address == AddressUtils.toLegacyAddress(address)) - .index : null; + .index + : null; final HD = index == null ? hd : hd.derive(index); return base64Encode(HD.signMessage(message)); } diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart index 1709c4d8f..8291ce2a5 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart @@ -1,6 +1,5 @@ +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:cw_bitcoin/bitcoin_address_record.dart'; -import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:cw_bitcoin/utils.dart'; import 'package:cw_core/wallet_info.dart'; @@ -11,24 +10,19 @@ part 'bitcoin_cash_wallet_addresses.g.dart'; class BitcoinCashWalletAddresses = BitcoinCashWalletAddressesBase with _$BitcoinCashWalletAddresses; abstract class BitcoinCashWalletAddressesBase extends ElectrumWalletAddresses with Store { - BitcoinCashWalletAddressesBase(WalletInfo walletInfo, - {required bitcoin.HDWallet mainHd, - required bitcoin.HDWallet sideHd, - required bitcoin.NetworkType networkType, - required ElectrumClient electrumClient, - List? initialAddresses, - int initialRegularAddressIndex = 0, - int initialChangeAddressIndex = 0}) - : super(walletInfo, - initialAddresses: initialAddresses, - initialRegularAddressIndex: initialRegularAddressIndex, - initialChangeAddressIndex: initialChangeAddressIndex, - mainHd: mainHd, - sideHd: sideHd, - electrumClient: electrumClient, - networkType: networkType); + BitcoinCashWalletAddressesBase( + WalletInfo walletInfo, { + required super.mainHd, + required super.sideHd, + required super.network, + required super.electrumClient, + super.initialAddresses, + super.initialRegularAddressIndex, + super.initialChangeAddressIndex, + }) : super(walletInfo); @override - String getAddress({required int index, required bitcoin.HDWallet hd}) => - generateP2PKHAddress(hd: hd, index: index, networkType: networkType); + String getAddress( + {required int index, required bitcoin.HDWallet hd, BitcoinAddressType? addressType}) => + generateP2PKHAddress(hd: hd, index: index, network: network); } diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart index f66e38ca7..df8e841f8 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart @@ -2,10 +2,7 @@ import 'dart:io'; import 'package:bip39/bip39.dart'; import 'package:cw_bitcoin_cash/cw_bitcoin_cash.dart'; -import 'package:cw_core/balance.dart'; import 'package:cw_core/pathForWallet.dart'; -import 'package:cw_core/transaction_history.dart'; -import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_info.dart'; @@ -15,8 +12,7 @@ import 'package:collection/collection.dart'; import 'package:hive/hive.dart'; class BitcoinCashWalletService extends WalletService { + BitcoinCashRestoreWalletFromSeedCredentials, BitcoinCashRestoreWalletFromWIFCredentials> { BitcoinCashWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); final Box walletInfoSource; @@ -30,13 +26,9 @@ class BitcoinCashWalletService extends WalletService create( - credentials) async { - final strength = (credentials.seedPhraseLength == 12) - ? 128 - : (credentials.seedPhraseLength == 24) - ? 256 - : 128; + Future create(credentials, {bool? isTestnet}) async { + final strength = credentials.seedPhraseLength == 24 ? 256 : 128; + final wallet = await BitcoinCashWalletBase.create( mnemonic: await Mnemonic.generate(strength: strength), password: credentials.password!, @@ -49,21 +41,25 @@ class BitcoinCashWalletService extends WalletService openWallet(String name, String password) async { - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(name, getType()))!; + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!; try { final wallet = await BitcoinCashWalletBase.open( - password: password, name: name, walletInfo: walletInfo, + password: password, + name: name, + walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); saveBackup(name); return wallet; - } catch(_) { + } catch (_) { await restoreWalletFilesFromBackup(name); final wallet = await BitcoinCashWalletBase.open( - password: password, name: name, walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfoSource); + password: password, + name: name, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); return wallet; } @@ -71,17 +67,16 @@ class BitcoinCashWalletService extends WalletService remove(String wallet) async { - File(await pathForWalletDir(name: wallet, type: getType())) - .delete(recursive: true); - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(wallet, getType()))!; + File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true); + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; await walletInfoSource.delete(walletInfo.key); } @override Future rename(String currentName, String password, String newName) async { - final currentWalletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(currentName, getType()))!; + final currentWalletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!; final currentWallet = await BitcoinCashWalletBase.open( password: password, name: currentName, @@ -99,15 +94,14 @@ class BitcoinCashWalletService extends WalletService - restoreFromKeys(credentials) { + Future restoreFromKeys(credentials, {bool? isTestnet}) { // TODO: implement restoreFromKeys throw UnimplementedError('restoreFromKeys() is not implemented'); } @override - Future restoreFromSeed( - BitcoinCashRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(BitcoinCashRestoreWalletFromSeedCredentials credentials, + {bool? isTestnet}) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinCashMnemonicIsIncorrectException(); } diff --git a/cw_bitcoin_cash/pubspec.yaml b/cw_bitcoin_cash/pubspec.yaml index 49a5efb15..9c098c0ff 100644 --- a/cw_bitcoin_cash/pubspec.yaml +++ b/cw_bitcoin_cash/pubspec.yaml @@ -29,7 +29,10 @@ dependencies: git: url: https://github.com/cake-tech/bitbox-flutter.git ref: master - bitcoin_base: ^3.0.1 + bitcoin_base: + git: + url: https://github.com/cake-tech/bitcoin_base.git + ref: cake-update-v1 diff --git a/cw_core/lib/enumerate.dart b/cw_core/lib/enumerate.dart new file mode 100644 index 000000000..d92347e91 --- /dev/null +++ b/cw_core/lib/enumerate.dart @@ -0,0 +1,13 @@ +abstract class Enumerate { + String get value; + + @override + operator ==(other) { + if (identical(other, this)) return true; + if (other is! Enumerate) return false; + return other.runtimeType == runtimeType && value == other.value; + } + + @override + int get hashCode => value.hashCode; +} diff --git a/cw_core/lib/receive_page_option.dart b/cw_core/lib/receive_page_option.dart new file mode 100644 index 000000000..786d07bc5 --- /dev/null +++ b/cw_core/lib/receive_page_option.dart @@ -0,0 +1,21 @@ +import 'package:cw_core/enumerate.dart'; + +class ReceivePageOption implements Enumerate { + static const mainnet = ReceivePageOption._('mainnet'); + static const anonPayInvoice = ReceivePageOption._('anonPayInvoice'); + static const anonPayDonationLink = ReceivePageOption._('anonPayDonationLink'); + + const ReceivePageOption._(this.value); + + final String value; + + String toString() { + return value; + } +} + +const ReceivePageOptions = [ + ReceivePageOption.mainnet, + ReceivePageOption.anonPayInvoice, + ReceivePageOption.anonPayDonationLink +]; diff --git a/cw_core/lib/wallet_base.dart b/cw_core/lib/wallet_base.dart index 09b423c14..49f1bdc94 100644 --- a/cw_core/lib/wallet_base.dart +++ b/cw_core/lib/wallet_base.dart @@ -88,4 +88,6 @@ abstract class WalletBase renameWalletFiles(String newWalletName); String signMessage(String message, {String? address = null}) => throw UnimplementedError(); + + bool? isTestnet; } diff --git a/cw_core/lib/wallet_info.dart b/cw_core/lib/wallet_info.dart index c4ccea00a..2a44175a7 100644 --- a/cw_core/lib/wallet_info.dart +++ b/cw_core/lib/wallet_info.dart @@ -148,6 +148,12 @@ class WalletInfo extends HiveObject { @HiveField(17) String? derivationPath; + @HiveField(18) + String? addressPageType; + + @HiveField(19) + String? network; + String get yatLastUsedAddress => yatLastUsedAddressRaw ?? ''; set yatLastUsedAddress(String address) { diff --git a/cw_core/lib/wallet_service.dart b/cw_core/lib/wallet_service.dart index 3b4908386..22981b9db 100644 --- a/cw_core/lib/wallet_service.dart +++ b/cw_core/lib/wallet_service.dart @@ -9,11 +9,11 @@ abstract class WalletService { WalletType getType(); - Future create(N credentials); + Future create(N credentials, {bool? isTestnet}); - Future restoreFromSeed(RFS credentials); + Future restoreFromSeed(RFS credentials, {bool? isTestnet}); - Future restoreFromKeys(RFK credentials); + Future restoreFromKeys(RFK credentials, {bool? isTestnet}); Future openWallet(String name, String password); diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock index aacbd9ddd..678e57b54 100644 --- a/cw_core/pubspec.lock +++ b/cw_core/pubspec.lock @@ -5,34 +5,34 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "4897882604d919befd350648c7f91926a9d5de99e67b455bf0917cc2362f4bb8" + sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 url: "https://pub.dev" source: hosted - version: "47.0.0" + version: "64.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: "690e335554a8385bc9d787117d9eb52c0c03ee207a607e593de3c9d71b1cfe80" + sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" url: "https://pub.dev" source: hosted - version: "4.7.0" + version: "6.2.0" args: dependency: transitive description: name: args - sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.2" asn1lib: dependency: transitive description: name: asn1lib - sha256: ab96a1cb3beeccf8145c52e449233fe68364c9641623acd3adad66f8184f1039 + sha256: "21afe4333076c02877d14f4a89df111e658a6d466cbfc802eb705eb91bd5adfd" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.5.0" async: dependency: transitive description: @@ -53,10 +53,10 @@ packages: dependency: transitive description: name: build - sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.1" build_config: dependency: transitive description: @@ -69,34 +69,34 @@ packages: dependency: transitive description: name: build_daemon - sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "4.0.1" build_resolvers: dependency: "direct dev" description: name: build_resolvers - sha256: "687cf90a3951affac1bd5f9ecb5e3e90b60487f3d9cdc359bb310f8876bb02a6" + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" url: "https://pub.dev" source: hosted - version: "2.0.10" + version: "2.4.2" build_runner: dependency: "direct dev" description: name: build_runner - sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.8" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" + sha256: c9e32d21dd6626b5c163d48b037ce906bbe428bc23ab77bcd77bb21e593b6185 url: "https://pub.dev" source: hosted - version: "7.2.7" + version: "7.2.11" built_collection: dependency: transitive description: @@ -109,10 +109,10 @@ packages: dependency: transitive description: name: built_value - sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" + sha256: c9aabae0718ec394e5bc3c7272e6bb0dc0b32201a08fe185ec1d8401d3e39309 url: "https://pub.dev" source: hosted - version: "8.4.3" + version: "8.8.1" characters: dependency: transitive description: @@ -125,10 +125,10 @@ packages: dependency: transitive description: name: checked_yaml - sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.0.3" clock: dependency: transitive description: @@ -141,10 +141,10 @@ packages: dependency: transitive description: name: code_builder - sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.10.0" collection: dependency: transitive description: @@ -165,26 +165,26 @@ packages: dependency: transitive description: name: crypto - sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" dart_style: dependency: transitive description: name: dart_style - sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" + sha256: "40ae61a5d43feea6d24bd22c0537a6629db858963b99b4bc1c3db80676f32368" url: "https://pub.dev" source: hosted - version: "2.2.4" + version: "2.3.4" encrypt: dependency: "direct main" description: name: encrypt - sha256: "4fd4e4fdc21b9d7d4141823e1e6515cd94e7b8d84749504c232999fba25d9bbb" + sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2" url: "https://pub.dev" source: hosted - version: "5.0.1" + version: "5.0.3" fake_async: dependency: transitive description: @@ -197,10 +197,10 @@ packages: dependency: transitive description: name: ffi - sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.0" file: dependency: "direct main" description: @@ -226,10 +226,10 @@ packages: dependency: "direct main" description: name: flutter_mobx - sha256: "0da4add0016387a7bf309a0d0c41d36c6b3ae25ed7a176409267f166509e723e" + sha256: "4a5d062ff85ed3759f4aac6410ff0ffae32e324b2e71ca722ae1b37b32e865f4" url: "https://pub.dev" source: hosted - version: "2.0.6+5" + version: "2.2.0+2" flutter_test: dependency: "direct dev" description: flutter @@ -247,18 +247,18 @@ packages: dependency: transitive description: name: glob - sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" graphs: dependency: transitive description: name: graphs - sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2 + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.1" hive: dependency: transitive description: @@ -327,18 +327,18 @@ packages: dependency: transitive description: name: json_annotation - sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 url: "https://pub.dev" source: hosted - version: "4.8.0" + version: "4.8.1" logging: dependency: transitive description: name: logging - sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" matcher: dependency: transitive description: @@ -375,18 +375,26 @@ packages: dependency: "direct main" description: name: mobx - sha256: f1862bd92c6a903fab67338f27e2f731117c3cb9ea37cee1a487f9e4e0de314a + sha256: "74ee54012dc7c1b3276eaa960a600a7418ef5f9997565deb8fca1fd88fb36b78" url: "https://pub.dev" source: hosted - version: "2.1.3+1" + version: "2.3.0+1" mobx_codegen: dependency: "direct dev" description: name: mobx_codegen - sha256: "86122e410d8ea24dda0c69adb5c2a6ccadd5ce02ad46e144764e0d0184a06181" + sha256: b26c7f9c20b38f0ea572c1ed3f29d8e027cb265538bbd1aed3ec198642cfca42 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.6.0+1" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" package_config: dependency: transitive description: @@ -407,26 +415,26 @@ packages: dependency: "direct main" description: name: path_provider - sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 + sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" path_provider_linux: dependency: transitive description: @@ -439,10 +447,10 @@ packages: dependency: transitive description: name: path_provider_platform_interface - sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_windows: dependency: transitive description: @@ -455,26 +463,26 @@ packages: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.4" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.8" pointycastle: dependency: transitive description: name: pointycastle - sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 + sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" url: "https://pub.dev" source: hosted - version: "3.6.2" + version: "3.7.4" pool: dependency: transitive description: @@ -483,46 +491,46 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" - process: + provider: dependency: transitive description: - name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + name: provider + sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" url: "https://pub.dev" source: hosted - version: "4.2.4" + version: "6.1.1" pub_semver: dependency: transitive description: name: pub_semver - sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" pubspec_parse: dependency: transitive description: name: pubspec_parse - sha256: "75f6614d6dde2dc68948dffbaa4fe5dae32cd700eb9fb763fe11dfb45a3c4d0a" + sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.3" shelf: dependency: transitive description: name: shelf - sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" sky_engine: dependency: transitive description: flutter @@ -540,18 +548,18 @@ packages: dependency: transitive description: name: source_gen - sha256: "2d79738b6bbf38a43920e2b8d189e9a3ce6cc201f4b8fc76be5e4fe377b1c38d" + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" url: "https://pub.dev" source: hosted - version: "1.2.6" + version: "1.5.0" source_helper: dependency: transitive description: name: source_helper - sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f" + sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" url: "https://pub.dev" source: hosted - version: "1.3.3" + version: "1.3.4" source_span: dependency: transitive description: @@ -620,10 +628,10 @@ packages: dependency: transitive description: name: typed_data - sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" vector_math: dependency: transitive description: @@ -636,42 +644,42 @@ packages: dependency: transitive description: name: watcher - sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.0" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.4.0" win32: dependency: transitive description: name: win32 - sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 + sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "5.0.9" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d url: "https://pub.dev" source: hosted - version: "0.2.0+3" + version: "1.0.4" yaml: dependency: transitive description: name: yaml - sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.7.0" + flutter: ">=3.10.0" diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index 5e8c22718..53c8bfea9 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -16,7 +16,7 @@ class EthereumWalletService extends EVMChainWalletService { WalletType getType() => WalletType.ethereum; @override - Future create(EVMChainNewWalletCredentials credentials) async { + Future create(EVMChainNewWalletCredentials credentials, {bool? isTestnet}) async { final strength = credentials.seedPhraseLength == 24 ? 256 : 128; final mnemonic = bip39.generateMnemonic(strength: strength); @@ -52,7 +52,6 @@ class EthereumWalletService extends EVMChainWalletService { saveBackup(name); return wallet; } catch (_) { - await restoreWalletFilesFromBackup(name); final wallet = await EthereumWallet.open( @@ -84,7 +83,8 @@ class EthereumWalletService extends EVMChainWalletService { } @override - Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials) async { + Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials, + {bool? isTestnet}) async { final wallet = EthereumWallet( password: credentials.password!, privateKey: credentials.privateKey, @@ -100,8 +100,8 @@ class EthereumWalletService extends EVMChainWalletService { } @override - Future restoreFromSeed( - EVMChainRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(EVMChainRestoreWalletFromSeedCredentials credentials, + {bool? isTestnet}) async { if (!bip39.validateMnemonic(credentials.mnemonic)) { throw EthereumMnemonicIsIncorrectException(); } diff --git a/cw_evm/lib/evm_chain_wallet_service.dart b/cw_evm/lib/evm_chain_wallet_service.dart index 988a38684..d77a3a81a 100644 --- a/cw_evm/lib/evm_chain_wallet_service.dart +++ b/cw_evm/lib/evm_chain_wallet_service.dart @@ -22,7 +22,7 @@ abstract class EVMChainWalletService extends WalletSer WalletType getType(); @override - Future create(EVMChainNewWalletCredentials credentials); + Future create(EVMChainNewWalletCredentials credentials, {bool? isTestnet}); @override Future openWallet(String name, String password); @@ -31,10 +31,10 @@ abstract class EVMChainWalletService extends WalletSer Future rename(String currentName, String password, String newName); @override - Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials); + Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials, {bool? isTestnet}); @override - Future restoreFromSeed(EVMChainRestoreWalletFromSeedCredentials credentials); + Future restoreFromSeed(EVMChainRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}); @override Future isWalletExit(String name) async => diff --git a/cw_haven/lib/haven_wallet_service.dart b/cw_haven/lib/haven_wallet_service.dart index dd7713e08..d4808c2d6 100644 --- a/cw_haven/lib/haven_wallet_service.dart +++ b/cw_haven/lib/haven_wallet_service.dart @@ -68,7 +68,7 @@ class HavenWalletService extends WalletService< WalletType getType() => WalletType.haven; @override - Future create(HavenNewWalletCredentials credentials) async { + Future create(HavenNewWalletCredentials credentials, {bool? isTestnet}) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await haven_wallet_manager.createWallet( @@ -174,7 +174,7 @@ class HavenWalletService extends WalletService< @override Future restoreFromKeys( - HavenRestoreWalletFromKeysCredentials credentials) async { + HavenRestoreWalletFromKeysCredentials credentials, {bool? isTestnet}) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await haven_wallet_manager.restoreFromKeys( @@ -198,7 +198,7 @@ class HavenWalletService extends WalletService< @override Future restoreFromSeed( - HavenRestoreWalletFromSeedCredentials credentials) async { + HavenRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await haven_wallet_manager.restoreFromSeed( diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 3dea7fc0e..1f33dbb3d 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -68,7 +68,7 @@ class MoneroWalletService extends WalletService WalletType.monero; @override - Future create(MoneroNewWalletCredentials credentials) async { + Future create(MoneroNewWalletCredentials credentials, {bool? isTestnet}) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); @@ -203,7 +203,8 @@ class MoneroWalletService extends WalletService restoreFromKeys(MoneroRestoreWalletFromKeysCredentials credentials) async { + Future restoreFromKeys(MoneroRestoreWalletFromKeysCredentials credentials, + {bool? isTestnet}) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await monero_wallet_manager.restoreFromKeys( @@ -227,7 +228,8 @@ class MoneroWalletService extends WalletService restoreFromSeed(MoneroRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(MoneroRestoreWalletFromSeedCredentials credentials, + {bool? isTestnet}) async { // Restore from Polyseed if (Polyseed.isValidSeed(credentials.mnemonic)) { return restoreFromPolyseed(credentials); diff --git a/cw_nano/lib/nano_wallet_service.dart b/cw_nano/lib/nano_wallet_service.dart index a76f0393d..7ab502d49 100644 --- a/cw_nano/lib/nano_wallet_service.dart +++ b/cw_nano/lib/nano_wallet_service.dart @@ -26,7 +26,7 @@ class NanoWalletService extends WalletService WalletType.nano; @override - Future create(NanoNewWalletCredentials credentials) async { + Future create(NanoNewWalletCredentials credentials, {bool? isTestnet}) async { // nano standard: DerivationType derivationType = DerivationType.nano; String seedKey = NanoSeeds.generateSeed(); @@ -79,7 +79,7 @@ class NanoWalletService extends WalletService restoreFromKeys(NanoRestoreWalletFromKeysCredentials credentials) async { + Future restoreFromKeys(NanoRestoreWalletFromKeysCredentials credentials, {bool? isTestnet}) async { if (credentials.seedKey.contains(' ')) { throw Exception("Invalid key!"); } else { @@ -113,7 +113,7 @@ class NanoWalletService extends WalletService restoreFromSeed(NanoRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(NanoRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { if (credentials.mnemonic.contains(' ')) { if (!bip39.validateMnemonic(credentials.mnemonic)) { throw nm.NanoMnemonicIsIncorrectException(); diff --git a/cw_polygon/lib/polygon_wallet_service.dart b/cw_polygon/lib/polygon_wallet_service.dart index 0199a1552..59e14abbf 100644 --- a/cw_polygon/lib/polygon_wallet_service.dart +++ b/cw_polygon/lib/polygon_wallet_service.dart @@ -19,7 +19,7 @@ class PolygonWalletService extends EVMChainWalletService { WalletType getType() => WalletType.polygon; @override - Future create(EVMChainNewWalletCredentials credentials) async { + Future create(EVMChainNewWalletCredentials credentials, {bool? isTestnet}) async { final strength = credentials.seedPhraseLength == 24 ? 256 : 128; final mnemonic = bip39.generateMnemonic(strength: strength); @@ -62,7 +62,7 @@ class PolygonWalletService extends EVMChainWalletService { password: password, walletInfo: walletInfo, ); - + await wallet.init(); await wallet.save(); return wallet; @@ -70,8 +70,8 @@ class PolygonWalletService extends EVMChainWalletService { } @override - Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials) async { - + Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials, + {bool? isTestnet}) async { final wallet = PolygonWallet( password: credentials.password!, privateKey: credentials.privateKey, @@ -87,8 +87,8 @@ class PolygonWalletService extends EVMChainWalletService { } @override - Future restoreFromSeed( - EVMChainRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(EVMChainRestoreWalletFromSeedCredentials credentials, + {bool? isTestnet}) async { if (!bip39.validateMnemonic(credentials.mnemonic)) { throw PolygonMnemonicIsIncorrectException(); } diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 688825013..f9c20d45e 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -1,181 +1,191 @@ part of 'bitcoin.dart'; class CWBitcoin extends Bitcoin { - @override - TransactionPriority getMediumTransactionPriority() => BitcoinTransactionPriority.medium; - - @override - WalletCredentials createBitcoinRestoreWalletFromSeedCredentials({ - required String name, - required String mnemonic, - required String password}) - => BitcoinRestoreWalletFromSeedCredentials(name: name, mnemonic: mnemonic, password: password); - - @override - WalletCredentials createBitcoinRestoreWalletFromWIFCredentials({ - required String name, - required String password, - required String wif, - WalletInfo? walletInfo}) - => BitcoinRestoreWalletFromWIFCredentials(name: name, password: password, wif: wif, walletInfo: walletInfo); - - @override - WalletCredentials createBitcoinNewWalletCredentials({ - required String name, - WalletInfo? walletInfo}) - => BitcoinNewWalletCredentials(name: name, walletInfo: walletInfo); - - @override - List getWordList() => wordlist; - - @override - Map getWalletKeys(Object wallet) { - final bitcoinWallet = wallet as ElectrumWallet; - final keys = bitcoinWallet.keys; - - return { - 'wif': keys.wif, - 'privateKey': keys.privateKey, - 'publicKey': keys.publicKey - }; - } - - @override - List getTransactionPriorities() - => BitcoinTransactionPriority.all; - - @override - List getLitecoinTransactionPriorities() - => LitecoinTransactionPriority.all; - - @override - TransactionPriority deserializeBitcoinTransactionPriority(int raw) - => BitcoinTransactionPriority.deserialize(raw: raw); - - @override - TransactionPriority deserializeLitecoinTransactionPriority(int raw) - => LitecoinTransactionPriority.deserialize(raw: raw); - - @override - int getFeeRate(Object wallet, TransactionPriority priority) { - final bitcoinWallet = wallet as ElectrumWallet; - return bitcoinWallet.feeRate(priority); - } - - @override - Future generateNewAddress(Object wallet, String label) async { - final bitcoinWallet = wallet as ElectrumWallet; - await bitcoinWallet.walletAddresses.generateNewAddress(label: label, hd: bitcoinWallet.hd); - await wallet.save(); - } - - @override - Future updateAddress(Object wallet,String address, String label) async { - final bitcoinWallet = wallet as ElectrumWallet; - bitcoinWallet.walletAddresses.updateAddress(address, label); - await wallet.save(); - } - - @override - Object createBitcoinTransactionCredentials(List outputs, {required TransactionPriority priority, int? feeRate}) - => BitcoinTransactionCredentials( - outputs.map((out) => OutputInfo( - fiatAmount: out.fiatAmount, - cryptoAmount: out.cryptoAmount, - address: out.address, - note: out.note, - sendAll: out.sendAll, - extractedAddress: out.extractedAddress, - isParsedAddress: out.isParsedAddress, - formattedCryptoAmount: out.formattedCryptoAmount)) - .toList(), - priority: priority as BitcoinTransactionPriority, - feeRate: feeRate); - - @override - Object createBitcoinTransactionCredentialsRaw(List outputs, {TransactionPriority? priority, required int feeRate}) - => BitcoinTransactionCredentials( - outputs, - priority: priority != null ? priority as BitcoinTransactionPriority : null, - feeRate: feeRate); - - @override - List getAddresses(Object wallet) { - final bitcoinWallet = wallet as ElectrumWallet; - return bitcoinWallet.walletAddresses.addresses - .map((BitcoinAddressRecord addr) => addr.address) - .toList(); - } - - @override - @computed - List getSubAddresses(Object wallet) { - final electrumWallet = wallet as ElectrumWallet; - return electrumWallet.walletAddresses.addresses - .map((BitcoinAddressRecord addr) => ElectrumSubAddress( - id: addr.index, - name: addr.name, - address: electrumWallet.type == WalletType.bitcoinCash ? addr.cashAddr : addr.address, - txCount: addr.txCount, - balance: addr.balance, - isChange: addr.isHidden)) - .toList(); - } - - @override - String getAddress(Object wallet) { - final bitcoinWallet = wallet as ElectrumWallet; - return bitcoinWallet.walletAddresses.address; - } - - @override - String formatterBitcoinAmountToString({required int amount}) - => bitcoinAmountToString(amount: amount); - - @override - double formatterBitcoinAmountToDouble({required int amount}) - => bitcoinAmountToDouble(amount: amount); - - @override - int formatterStringDoubleToBitcoinAmount(String amount) - => stringDoubleToBitcoinAmount(amount); + @override + TransactionPriority getMediumTransactionPriority() => BitcoinTransactionPriority.medium; @override - String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate) - => (priority as BitcoinTransactionPriority).labelWithRate(rate); - - @override - List getUnspents(Object wallet) { - final bitcoinWallet = wallet as ElectrumWallet; - return bitcoinWallet.unspentCoins; - } - - Future updateUnspents(Object wallet) async { - final bitcoinWallet = wallet as ElectrumWallet; - await bitcoinWallet.updateUnspent(); - } - - WalletService createBitcoinWalletService(Box walletInfoSource, Box unspentCoinSource) { - return BitcoinWalletService(walletInfoSource, unspentCoinSource); - } - - WalletService createLitecoinWalletService(Box walletInfoSource, Box unspentCoinSource) { - return LitecoinWalletService(walletInfoSource, unspentCoinSource); - } - - @override - TransactionPriority getBitcoinTransactionPriorityMedium() - => BitcoinTransactionPriority.medium; + WalletCredentials createBitcoinRestoreWalletFromSeedCredentials( + {required String name, required String mnemonic, required String password}) => + BitcoinRestoreWalletFromSeedCredentials(name: name, mnemonic: mnemonic, password: password); @override - TransactionPriority getLitecoinTransactionPriorityMedium() - => LitecoinTransactionPriority.medium; + WalletCredentials createBitcoinRestoreWalletFromWIFCredentials( + {required String name, + required String password, + required String wif, + WalletInfo? walletInfo}) => + BitcoinRestoreWalletFromWIFCredentials( + name: name, password: password, wif: wif, walletInfo: walletInfo); @override - TransactionPriority getBitcoinTransactionPrioritySlow() - => BitcoinTransactionPriority.slow; - + WalletCredentials createBitcoinNewWalletCredentials( + {required String name, WalletInfo? walletInfo}) => + BitcoinNewWalletCredentials(name: name, walletInfo: walletInfo); + @override - TransactionPriority getLitecoinTransactionPrioritySlow() - => LitecoinTransactionPriority.slow; -} \ No newline at end of file + List getWordList() => wordlist; + + @override + Map getWalletKeys(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + final keys = bitcoinWallet.keys; + + return { + 'wif': keys.wif, + 'privateKey': keys.privateKey, + 'publicKey': keys.publicKey + }; + } + + @override + List getTransactionPriorities() => BitcoinTransactionPriority.all; + + @override + List getLitecoinTransactionPriorities() => LitecoinTransactionPriority.all; + + @override + TransactionPriority deserializeBitcoinTransactionPriority(int raw) => + BitcoinTransactionPriority.deserialize(raw: raw); + + @override + TransactionPriority deserializeLitecoinTransactionPriority(int raw) => + LitecoinTransactionPriority.deserialize(raw: raw); + + @override + int getFeeRate(Object wallet, TransactionPriority priority) { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.feeRate(priority); + } + + @override + Future generateNewAddress(Object wallet, String label) async { + final bitcoinWallet = wallet as ElectrumWallet; + await bitcoinWallet.walletAddresses.generateNewAddress(label: label); + await wallet.save(); + } + + @override + Future updateAddress(Object wallet, String address, String label) async { + final bitcoinWallet = wallet as ElectrumWallet; + bitcoinWallet.walletAddresses.updateAddress(address, label); + await wallet.save(); + } + + @override + Object createBitcoinTransactionCredentials(List outputs, + {required TransactionPriority priority, int? feeRate}) => + BitcoinTransactionCredentials( + outputs + .map((out) => OutputInfo( + fiatAmount: out.fiatAmount, + cryptoAmount: out.cryptoAmount, + address: out.address, + note: out.note, + sendAll: out.sendAll, + extractedAddress: out.extractedAddress, + isParsedAddress: out.isParsedAddress, + formattedCryptoAmount: out.formattedCryptoAmount)) + .toList(), + priority: priority as BitcoinTransactionPriority, + feeRate: feeRate); + + @override + Object createBitcoinTransactionCredentialsRaw(List outputs, + {TransactionPriority? priority, required int feeRate}) => + BitcoinTransactionCredentials(outputs, + priority: priority != null ? priority as BitcoinTransactionPriority : null, + feeRate: feeRate); + + @override + List getAddresses(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.walletAddresses.addressesByReceiveType + .map((BitcoinAddressRecord addr) => addr.address) + .toList(); + } + + @override + @computed + List getSubAddresses(Object wallet) { + final electrumWallet = wallet as ElectrumWallet; + return electrumWallet.walletAddresses.addressesByReceiveType + .map((BitcoinAddressRecord addr) => ElectrumSubAddress( + id: addr.index, + name: addr.name, + address: electrumWallet.type == WalletType.bitcoinCash ? addr.cashAddr : addr.address, + txCount: addr.txCount, + balance: addr.balance, + isChange: addr.isHidden)) + .toList(); + } + + @override + String getAddress(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.walletAddresses.address; + } + + @override + String formatterBitcoinAmountToString({required int amount}) => + bitcoinAmountToString(amount: amount); + + @override + double formatterBitcoinAmountToDouble({required int amount}) => + bitcoinAmountToDouble(amount: amount); + + @override + int formatterStringDoubleToBitcoinAmount(String amount) => stringDoubleToBitcoinAmount(amount); + + @override + String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate) => + (priority as BitcoinTransactionPriority).labelWithRate(rate); + + @override + List getUnspents(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.unspentCoins; + } + + Future updateUnspents(Object wallet) async { + final bitcoinWallet = wallet as ElectrumWallet; + await bitcoinWallet.updateUnspent(); + } + + WalletService createBitcoinWalletService( + Box walletInfoSource, Box unspentCoinSource) { + return BitcoinWalletService(walletInfoSource, unspentCoinSource); + } + + WalletService createLitecoinWalletService( + Box walletInfoSource, Box unspentCoinSource) { + return LitecoinWalletService(walletInfoSource, unspentCoinSource); + } + + @override + TransactionPriority getBitcoinTransactionPriorityMedium() => BitcoinTransactionPriority.medium; + + @override + TransactionPriority getLitecoinTransactionPriorityMedium() => LitecoinTransactionPriority.medium; + + @override + TransactionPriority getBitcoinTransactionPrioritySlow() => BitcoinTransactionPriority.slow; + + @override + TransactionPriority getLitecoinTransactionPrioritySlow() => LitecoinTransactionPriority.slow; + + @override + Future setAddressType(Object wallet, dynamic option) async { + final bitcoinWallet = wallet as ElectrumWallet; + await bitcoinWallet.walletAddresses.setAddressType(option as BitcoinAddressType); + } + + @override + BitcoinReceivePageOption getSelectedAddressType(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + return BitcoinReceivePageOption.fromType(bitcoinWallet.walletAddresses.addressPageType); + } + + @override + List getBitcoinReceivePageOptions() => BitcoinReceivePageOption.all; +} diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 21f3c3557..432471655 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -1,4 +1,4 @@ -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/core/validator.dart'; import 'package:cake_wallet/solana/solana.dart'; @@ -9,7 +9,9 @@ class AddressValidator extends TextValidator { AddressValidator({required CryptoCurrency type}) : super( errorMessage: S.current.error_text_address, - useAdditionalValidation: type == CryptoCurrency.btc ? bitcoin.Address.validateAddress : null, + useAdditionalValidation: type == CryptoCurrency.btc + ? (String txt) => validateAddress(address: txt, network: BitcoinNetwork.mainnet) + : null, pattern: getPattern(type), length: getLength(type)); @@ -24,7 +26,7 @@ class AddressValidator extends TextValidator { return '^[0-9a-zA-Z]{59}\$|^[0-9a-zA-Z]{92}\$|^[0-9a-zA-Z]{104}\$' '|^[0-9a-zA-Z]{105}\$|^addr1[0-9a-zA-Z]{98}\$'; case CryptoCurrency.btc: - return '^3[0-9a-zA-Z]{32}\$|^3[0-9a-zA-Z]{33}\$|^bc1[0-9a-zA-Z]{59}\$'; + return '^${P2pkhAddress.regex.pattern}\$|^${P2shAddress.regex.pattern}\$|^${P2wpkhAddress.regex.pattern}\$|${P2trAddress.regex.pattern}\$|^${P2wshAddress.regex.pattern}\$'; case CryptoCurrency.nano: return '[0-9a-zA-Z_]'; case CryptoCurrency.banano: @@ -89,7 +91,7 @@ class AddressValidator extends TextValidator { case CryptoCurrency.dai: case CryptoCurrency.dash: case CryptoCurrency.eos: - return '[0-9a-zA-Z]'; + return '[0-9a-zA-Z]'; case CryptoCurrency.bch: return '^(?!bitcoincash:)[0-9a-zA-Z]*\$|^(?!bitcoincash:)q|p[0-9a-zA-Z]{41}\$|^(?!bitcoincash:)q|p[0-9a-zA-Z]{42}\$|^bitcoincash:q|p[0-9a-zA-Z]{41}\$|^bitcoincash:q|p[0-9a-zA-Z]{42}\$'; case CryptoCurrency.bnb: @@ -268,12 +270,11 @@ class AddressValidator extends TextValidator { '|([^0-9a-zA-Z]|^)8[0-9a-zA-Z]{94}([^0-9a-zA-Z]|\$)' '|([^0-9a-zA-Z]|^)[0-9a-zA-Z]{106}([^0-9a-zA-Z]|\$)'; case CryptoCurrency.btc: - return '([^0-9a-zA-Z]|^)1[0-9a-zA-Z]{32}([^0-9a-zA-Z]|\$)' - '|([^0-9a-zA-Z]|^)1[0-9a-zA-Z]{33}([^0-9a-zA-Z]|\$)' - '|([^0-9a-zA-Z]|^)3[0-9a-zA-Z]{32}([^0-9a-zA-Z]|\$)' - '|([^0-9a-zA-Z]|^)3[0-9a-zA-Z]{33}([^0-9a-zA-Z]|\$)' - '|([^0-9a-zA-Z]|^)bc1[0-9a-zA-Z]{39}([^0-9a-zA-Z]|\$)' - '|([^0-9a-zA-Z]|^)bc1[0-9a-zA-Z]{59}([^0-9a-zA-Z]|\$)'; + return '([^0-9a-zA-Z]|^)${P2pkhAddress.regex.pattern}|\$)' + '([^0-9a-zA-Z]|^)${P2shAddress.regex.pattern}|\$)' + '([^0-9a-zA-Z]|^)${P2wpkhAddress.regex.pattern}|\$)' + '([^0-9a-zA-Z]|^)${P2wshAddress.regex.pattern}|\$)' + '([^0-9a-zA-Z]|^)${P2trAddress.regex.pattern}|\$)'; case CryptoCurrency.ltc: return '([^0-9a-zA-Z]|^)^L[a-zA-Z0-9]{26,33}([^0-9a-zA-Z]|\$)' '|([^0-9a-zA-Z]|^)[LM][a-km-zA-HJ-NP-Z1-9]{26,33}([^0-9a-zA-Z]|\$)' @@ -297,4 +298,4 @@ class AddressValidator extends TextValidator { return null; } } -} \ No newline at end of file +} diff --git a/lib/core/wallet_creation_service.dart b/lib/core/wallet_creation_service.dart index 8548f079f..31a893ad6 100644 --- a/lib/core/wallet_creation_service.dart +++ b/lib/core/wallet_creation_service.dart @@ -2,7 +2,6 @@ import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:hive/hive.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -55,7 +54,7 @@ class WalletCreationService { } } - Future create(WalletCredentials credentials) async { + Future create(WalletCredentials credentials, {bool? isTestnet}) async { checkIfExists(credentials.name); final password = generateWalletPassword(); credentials.password = password; @@ -63,7 +62,7 @@ class WalletCreationService { credentials.seedPhraseLength = settingsStore.seedPhraseLength.value; } await keyService.saveWalletPassword(password: password, walletName: credentials.name); - final wallet = await _service!.create(credentials); + final wallet = await _service!.create(credentials, isTestnet: isTestnet); if (wallet.type == WalletType.monero) { await sharedPreferences.setBool( @@ -73,12 +72,12 @@ class WalletCreationService { return wallet; } - Future restoreFromKeys(WalletCredentials credentials) async { + Future restoreFromKeys(WalletCredentials credentials, {bool? isTestnet}) async { checkIfExists(credentials.name); final password = generateWalletPassword(); credentials.password = password; await keyService.saveWalletPassword(password: password, walletName: credentials.name); - final wallet = await _service!.restoreFromKeys(credentials); + final wallet = await _service!.restoreFromKeys(credentials, isTestnet: isTestnet); if (wallet.type == WalletType.monero) { await sharedPreferences.setBool( @@ -88,12 +87,12 @@ class WalletCreationService { return wallet; } - Future restoreFromSeed(WalletCredentials credentials) async { + Future restoreFromSeed(WalletCredentials credentials, {bool? isTestnet}) async { checkIfExists(credentials.name); final password = generateWalletPassword(); credentials.password = password; await keyService.saveWalletPassword(password: password, walletName: credentials.name); - final wallet = await _service!.restoreFromSeed(credentials); + final wallet = await _service!.restoreFromSeed(credentials, isTestnet: isTestnet); if (wallet.type == WalletType.monero) { await sharedPreferences.setBool( diff --git a/lib/di.dart b/lib/di.dart index 4a005a4de..473eaed00 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -13,7 +13,7 @@ import 'package:cake_wallet/core/yat_service.dart'; import 'package:cake_wallet/entities/background_tasks.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/parse_address_from_domain.dart'; -import 'package:cake_wallet/entities/receive_page_option.dart'; +import 'package:cw_core/receive_page_option.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/ionia/ionia_anypay.dart'; diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 019276227..fb3e9e80c 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -23,6 +23,10 @@ import 'package:collection/collection.dart'; const newCakeWalletMoneroUri = 'xmr-node.cakewallet.com:18081'; const cakeWalletBitcoinElectrumUri = 'electrum.cakewallet.com:50002'; +const publicBitcoinTestnetElectrumAddress = 'electrum.blockstream.info'; +const publicBitcoinTestnetElectrumPort = '60002'; +const publicBitcoinTestnetElectrumUri = + '$publicBitcoinTestnetElectrumAddress:$publicBitcoinTestnetElectrumPort'; const cakeWalletLitecoinElectrumUri = 'ltc-electrum.cakewallet.com:50002'; const havenDefaultNodeUri = 'nodes.havenprotocol.org:443'; const ethereumDefaultNodeUri = 'ethereum.publicnode.com'; @@ -334,6 +338,12 @@ Node? getBitcoinDefaultElectrumServer({required Box nodes}) { nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoin); } +Node? getBitcoinTestnetDefaultElectrumServer({required Box nodes}) { + return nodes.values + .firstWhereOrNull((Node node) => node.uriRaw == publicBitcoinTestnetElectrumUri) ?? + nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoin); +} + Node? getLitecoinDefaultElectrumServer({required Box nodes}) { return nodes.values .firstWhereOrNull((Node node) => node.uriRaw == cakeWalletLitecoinElectrumUri) ?? @@ -503,8 +513,15 @@ Future rewriteSecureStoragePin({required FlutterSecureStorage secureStorag } Future changeBitcoinCurrentElectrumServerToDefault( - {required SharedPreferences sharedPreferences, required Box nodes}) async { - final server = getBitcoinDefaultElectrumServer(nodes: nodes); + {required SharedPreferences sharedPreferences, + required Box nodes, + bool? isTestnet}) async { + Node? server; + if (isTestnet == true) { + server = getBitcoinTestnetDefaultElectrumServer(nodes: nodes); + } else { + server = getBitcoinDefaultElectrumServer(nodes: nodes); + } final serverId = server?.key as int? ?? 0; await sharedPreferences.setInt(PreferencesKey.currentBitcoinElectrumSererIdKey, serverId); diff --git a/lib/entities/receive_page_option.dart b/lib/entities/receive_page_option.dart deleted file mode 100644 index 3ee9abe96..000000000 --- a/lib/entities/receive_page_option.dart +++ /dev/null @@ -1,23 +0,0 @@ - -enum ReceivePageOption { - mainnet, - anonPayInvoice, - anonPayDonationLink; - - @override - String toString() { - String label = ''; - switch (this) { - case ReceivePageOption.mainnet: - label = 'Mainnet'; - break; - case ReceivePageOption.anonPayInvoice: - label = 'Trocador AnonPay Invoice'; - break; - case ReceivePageOption.anonPayDonationLink: - label = 'Trocador AnonPay Donation Link'; - break; - } - return label; - } -} diff --git a/lib/router.dart b/lib/router.dart index b7b7c9a8e..ef7b7f31e 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -532,13 +532,19 @@ Route createRoute(RouteSettings settings) { builder: (_) => getIt.get(param1: title, param2: url)); case Routes.advancedPrivacySettings: - final type = settings.arguments as WalletType; + final args = settings.arguments as Map; + final type = args['type'] as WalletType; + final useTestnet = args['useTestnet'] as bool; + final toggleTestnet = args['toggleTestnet'] as Function(bool? val); return CupertinoPageRoute( builder: (_) => AdvancedPrivacySettingsPage( - getIt.get(param1: type), - getIt.get(param1: type, param2: false), - getIt.get())); + useTestnet, + toggleTestnet, + getIt.get(param1: type), + getIt.get(param1: type, param2: false), + getIt.get(), + )); case Routes.anonPayInvoicePage: final args = settings.arguments as List; diff --git a/lib/src/screens/dashboard/pages/address_page.dart b/lib/src/screens/dashboard/pages/address_page.dart index b4460edc9..7b7c84c28 100644 --- a/lib/src/screens/dashboard/pages/address_page.dart +++ b/lib/src/screens/dashboard/pages/address_page.dart @@ -5,7 +5,8 @@ import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/monero_accounts/monero_account_list_page.dart'; import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; -import 'package:cake_wallet/entities/receive_page_option.dart'; +import 'package:cw_core/receive_page_option.dart'; +import 'package:cw_bitcoin/bitcoin_receive_page_option.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/present_receive_option_picker.dart'; import 'package:cake_wallet/src/widgets/gradient_background.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; @@ -27,6 +28,7 @@ import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:bitcoin_base/bitcoin_base.dart'; class AddressPage extends BasePage { AddressPage({ @@ -69,7 +71,7 @@ class AddressPage extends BasePage { size: 16, ); final _closeButton = - currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage; + currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage; bool isMobileView = responsiveLayoutUtil.shouldRenderMobileUI; @@ -163,11 +165,10 @@ class AddressPage extends BasePage { return SelectButton( text: addressListViewModel.buttonTitle, onTap: () async => dashboardViewModel.isAutoGenerateSubaddressesEnabled && - (WalletType.monero == addressListViewModel.wallet.type || - WalletType.haven == addressListViewModel.wallet.type) + (WalletType.monero == addressListViewModel.wallet.type || + WalletType.haven == addressListViewModel.wallet.type) ? await showPopUp( - context: context, - builder: (_) => getIt.get()) + context: context, builder: (_) => getIt.get()) : Navigator.of(context).pushNamed(Routes.receive), textColor: Theme.of(context).extension()!.textColor, color: Theme.of(context).extension()!.syncedBackgroundColor, @@ -229,6 +230,21 @@ class AddressPage extends BasePage { ); } break; + case BitcoinReceivePageOption.p2pkh: + addressListViewModel.setAddressType(P2pkhAddressType.p2pkh); + break; + case BitcoinReceivePageOption.p2sh: + addressListViewModel.setAddressType(P2shAddressType.p2wpkhInP2sh); + break; + case BitcoinReceivePageOption.p2wpkh: + addressListViewModel.setAddressType(SegwitAddresType.p2wpkh); + break; + case BitcoinReceivePageOption.p2tr: + addressListViewModel.setAddressType(SegwitAddresType.p2tr); + break; + case BitcoinReceivePageOption.p2wsh: + addressListViewModel.setAddressType(SegwitAddresType.p2wsh); + break; default: } }); diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index a4bd6c7b9..26478345e 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/entities/default_settings_migration.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/seed_phrase_length.dart'; @@ -11,6 +12,7 @@ import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model. import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; import 'package:cake_wallet/view_model/seed_type_view_model.dart'; import 'package:cake_wallet/view_model/settings/choices_list_item.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -19,7 +21,7 @@ import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; class AdvancedPrivacySettingsPage extends BasePage { - AdvancedPrivacySettingsPage( + AdvancedPrivacySettingsPage(this.useTestnet, this.toggleUseTestnet, this.advancedPrivacySettingsViewModel, this.nodeViewModel, this.seedTypeViewModel); final AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel; @@ -29,13 +31,16 @@ class AdvancedPrivacySettingsPage extends BasePage { @override String get title => S.current.privacy_settings; + final bool useTestnet; + final Function(bool? val) toggleUseTestnet; + @override - Widget body(BuildContext context) => AdvancedPrivacySettingsBody( + Widget body(BuildContext context) => AdvancedPrivacySettingsBody(useTestnet, toggleUseTestnet, advancedPrivacySettingsViewModel, nodeViewModel, seedTypeViewModel); } class AdvancedPrivacySettingsBody extends StatefulWidget { - const AdvancedPrivacySettingsBody( + const AdvancedPrivacySettingsBody(this.useTestnet, this.toggleUseTestnet, this.privacySettingsViewModel, this.nodeViewModel, this.seedTypeViewModel, {Key? key}) : super(key: key); @@ -44,6 +49,9 @@ class AdvancedPrivacySettingsBody extends StatefulWidget { final NodeCreateOrEditViewModel nodeViewModel; final SeedTypeViewModel seedTypeViewModel; + final bool useTestnet; + final Function(bool? val) toggleUseTestnet; + @override _AdvancedPrivacySettingsBodyState createState() => _AdvancedPrivacySettingsBodyState(); } @@ -52,9 +60,14 @@ class _AdvancedPrivacySettingsBodyState extends State(); + bool? testnetValue; @override Widget build(BuildContext context) { + if (testnetValue == null && widget.useTestnet != null) { + testnetValue = widget.useTestnet; + } + return Container( padding: EdgeInsets.only(top: 24), child: ScrollableWithBottomSection( @@ -125,6 +138,19 @@ class _AdvancedPrivacySettingsBodyState extends State WalletNameForm( - _walletNewVM, currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage, _seedTypeViewModel); + _walletNewVM, + currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage, + _seedTypeViewModel); } class WalletNameForm extends StatefulWidget { @@ -187,7 +189,6 @@ class _WalletNameFormState extends State { ), ), ), - if (_walletNewVM.hasLanguageSelector) ...[ if (_walletNewVM.hasSeedType) ...[ Observer( @@ -222,7 +223,7 @@ class _WalletNameFormState extends State { ), ), ) - ] + ], ], ), ), @@ -245,8 +246,11 @@ class _WalletNameFormState extends State { const SizedBox(height: 25), GestureDetector( onTap: () { - Navigator.of(context) - .pushNamed(Routes.advancedPrivacySettings, arguments: _walletNewVM.type); + Navigator.of(context).pushNamed(Routes.advancedPrivacySettings, arguments: { + "type": _walletNewVM.type, + "useTestnet": _walletNewVM.useTestnet, + "toggleTestnet": _walletNewVM.toggleUseTestnet + }); }, child: Text(S.of(context).advanced_settings), ), diff --git a/lib/src/screens/receive/anonpay_invoice_page.dart b/lib/src/screens/receive/anonpay_invoice_page.dart index fc835c72d..f33cdcc5b 100644 --- a/lib/src/screens/receive/anonpay_invoice_page.dart +++ b/lib/src/screens/receive/anonpay_invoice_page.dart @@ -4,7 +4,7 @@ import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart'; import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; -import 'package:cake_wallet/entities/receive_page_option.dart'; +import 'package:cw_core/receive_page_option.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/present_receive_option_picker.dart'; import 'package:cake_wallet/src/screens/receive/widgets/anonpay_input_form.dart'; diff --git a/lib/src/screens/receive/anonpay_receive_page.dart b/lib/src/screens/receive/anonpay_receive_page.dart index b602abde6..7d71e3a22 100644 --- a/lib/src/screens/receive/anonpay_receive_page.dart +++ b/lib/src/screens/receive/anonpay_receive_page.dart @@ -1,7 +1,7 @@ import 'package:cake_wallet/anonpay/anonpay_info_base.dart'; import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart'; import 'package:cake_wallet/entities/qr_view_data.dart'; -import 'package:cake_wallet/entities/receive_page_option.dart'; +import 'package:cw_core/receive_page_option.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index 899aacd19..fe5ac8487 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -210,8 +210,12 @@ class WalletRestorePage extends BasePage { const SizedBox(height: 25), GestureDetector( onTap: () { - Navigator.of(context).pushNamed(Routes.advancedPrivacySettings, - arguments: walletRestoreViewModel.type); + Navigator.of(context) + .pushNamed(Routes.advancedPrivacySettings, arguments: { + 'type': walletRestoreViewModel.type, + 'useTestnet': walletRestoreViewModel.useTestnet, + 'toggleTestnet': walletRestoreViewModel.toggleUseTestnet + }); }, child: Text(S.of(context).advanced_settings), ), diff --git a/lib/view_model/anon_invoice_page_view_model.dart b/lib/view_model/anon_invoice_page_view_model.dart index 53e8473a0..187eea375 100644 --- a/lib/view_model/anon_invoice_page_view_model.dart +++ b/lib/view_model/anon_invoice_page_view_model.dart @@ -4,7 +4,7 @@ import 'package:cake_wallet/anonpay/anonpay_request.dart'; import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; -import 'package:cake_wallet/entities/receive_page_option.dart'; +import 'package:cw_core/receive_page_option.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/currency.dart'; diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index a794c2262..da5eb0373 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -148,17 +148,21 @@ abstract class DashboardViewModelBase with Store { monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id) .toList(); - transactions = ObservableList.of(_accountTransactions.map((transaction) => - TransactionListItem( - transaction: transaction, - balanceViewModel: balanceViewModel, - settingsStore: appStore.settingsStore))); + final sortedTransactions = [..._accountTransactions]; + sortedTransactions.sort((a, b) => a.date.compareTo(b.date)); + + transactions = ObservableList.of(sortedTransactions.map((transaction) => TransactionListItem( + transaction: transaction, + balanceViewModel: balanceViewModel, + settingsStore: appStore.settingsStore))); } else { - transactions = ObservableList.of(wallet.transactionHistory.transactions.values.map( - (transaction) => TransactionListItem( - transaction: transaction, - balanceViewModel: balanceViewModel, - settingsStore: appStore.settingsStore))); + final sortedTransactions = [...wallet.transactionHistory.transactions.values]; + sortedTransactions.sort((a, b) => a.date.compareTo(b.date)); + + transactions = ObservableList.of(sortedTransactions.map((transaction) => TransactionListItem( + transaction: transaction, + balanceViewModel: balanceViewModel, + settingsStore: appStore.settingsStore))); } // TODO: nano sub-account generation is disabled: diff --git a/lib/view_model/dashboard/receive_option_view_model.dart b/lib/view_model/dashboard/receive_option_view_model.dart index 0eaa2a5f0..1e4726eee 100644 --- a/lib/view_model/dashboard/receive_option_view_model.dart +++ b/lib/view_model/dashboard/receive_option_view_model.dart @@ -1,4 +1,5 @@ -import 'package:cake_wallet/entities/receive_page_option.dart'; +import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cw_core/receive_page_option.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; @@ -9,11 +10,20 @@ class ReceiveOptionViewModel = ReceiveOptionViewModelBase with _$ReceiveOptionVi abstract class ReceiveOptionViewModelBase with Store { ReceiveOptionViewModelBase(this._wallet, this.initialPageOption) - : selectedReceiveOption = initialPageOption ?? ReceivePageOption.mainnet, + : selectedReceiveOption = initialPageOption ?? + (_wallet.type == WalletType.bitcoin + ? bitcoin!.getSelectedAddressType(_wallet) + : ReceivePageOption.mainnet), _options = [] { final walletType = _wallet.type; - _options = - walletType == WalletType.haven ? [ReceivePageOption.mainnet] : ReceivePageOption.values; + _options = walletType == WalletType.haven + ? [ReceivePageOption.mainnet] + : walletType == WalletType.bitcoin + ? [ + ...bitcoin!.getBitcoinReceivePageOptions(), + ...ReceivePageOptions.where((element) => element != ReceivePageOption.mainnet) + ] + : ReceivePageOptions; } final WalletBase _wallet; diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart index 0fb9a83c6..e323268a0 100644 --- a/lib/view_model/node_list/node_create_or_edit_view_model.dart +++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart @@ -65,6 +65,8 @@ abstract class NodeCreateOrEditViewModelBase with Store { bool get hasAuthCredentials => _walletType == WalletType.monero || _walletType == WalletType.haven; + bool get hasTestnetSupport => _walletType == WalletType.bitcoin; + String get uri { var uri = address; diff --git a/lib/view_model/node_list/node_list_view_model.dart b/lib/view_model/node_list/node_list_view_model.dart index 5526cc6d2..9c2d2611e 100644 --- a/lib/view_model/node_list/node_list_view_model.dart +++ b/lib/view_model/node_list/node_list_view_model.dart @@ -52,7 +52,11 @@ abstract class NodeListViewModelBase with Store { switch (_appStore.wallet!.type) { case WalletType.bitcoin: - node = getBitcoinDefaultElectrumServer(nodes: _nodeSource)!; + if (_appStore.wallet!.isTestnet == true) { + node = getBitcoinTestnetDefaultElectrumServer(nodes: _nodeSource)!; + } else { + node = getBitcoinDefaultElectrumServer(nodes: _nodeSource)!; + } break; case WalletType.monero: node = getMoneroDefaultNode(nodes: _nodeSource); diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index 04eaf25e4..1b1ceb814 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -119,7 +119,7 @@ abstract class TransactionDetailsViewModelBase with Store { case WalletType.monero: return 'https://monero.com/tx/${txId}'; case WalletType.bitcoin: - return 'https://mempool.space/tx/${txId}'; + return 'https://mempool.space/${wallet.isTestnet == true ? "testnet/" : ""}tx/${txId}'; case WalletType.litecoin: return 'https://blockchair.com/litecoin/transaction/${txId}'; case WalletType.bitcoinCash: diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index bde535a23..a2aab5251 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -388,9 +388,6 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin; - // wallet.type == WalletType.nano || - // wallet.type == WalletType.banano; TODO: nano accounts are disabled for now - @computed bool get isElectrumWallet => wallet.type == WalletType.bitcoin || @@ -409,16 +406,17 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo void setAddress(WalletAddressListItem address) => wallet.walletAddresses.address = address.address; + @action + Future setAddressType(dynamic option) async { + if (wallet.type == WalletType.bitcoin) { + await bitcoin!.setAddressType(wallet, option); + } + } + void _init() { _baseItems = []; - if (wallet.type == WalletType.monero || - wallet.type == - WalletType - .haven /*|| - wallet.type == WalletType.nano || - wallet.type == WalletType.banano*/ - ) { + if (wallet.type == WalletType.monero || wallet.type == WalletType.haven) { _baseItems.add(WalletAccountListHeader()); } diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index 45306905c..4a1e054d6 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -23,6 +23,12 @@ abstract class WalletCreationVMBase with Store { : state = InitialExecutionState(), name = ''; + @observable + bool _useTestnet = false; + + @computed + bool get useTestnet => _useTestnet; + @observable String name; @@ -94,4 +100,9 @@ abstract class WalletCreationVMBase with Store { Future processFromRestoredWallet( WalletCredentials credentials, RestoredWallet restoreWallet) => throw UnimplementedError(); + + @action + void toggleUseTestnet(bool? value) { + _useTestnet = value ?? !_useTestnet; + } } diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart index 6f3e0280e..8b19108ec 100644 --- a/lib/view_model/wallet_new_vm.dart +++ b/lib/view_model/wallet_new_vm.dart @@ -87,6 +87,6 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { @override Future process(WalletCredentials credentials) async { walletCreationService.changeWalletType(type: type); - return walletCreationService.create(credentials); + return walletCreationService.create(credentials, isTestnet: useTestnet); } } diff --git a/lib/view_model/wallet_restore_view_model.dart b/lib/view_model/wallet_restore_view_model.dart index 98dce3d92..93ca813d6 100644 --- a/lib/view_model/wallet_restore_view_model.dart +++ b/lib/view_model/wallet_restore_view_model.dart @@ -207,9 +207,9 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { @override Future process(WalletCredentials credentials) async { if (mode == WalletRestoreMode.keys) { - return walletCreationService.restoreFromKeys(credentials); + return walletCreationService.restoreFromKeys(credentials, isTestnet: useTestnet); } - return walletCreationService.restoreFromSeed(credentials); + return walletCreationService.restoreFromSeed(credentials, isTestnet: useTestnet); } } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 3e3f595be..9e822c474 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -719,6 +719,7 @@ "use_card_info_two": "يتم تحويل الأموال إلى الدولار الأمريكي عند الاحتفاظ بها في الحساب المدفوع مسبقًا ، وليس بالعملات الرقمية.", "use_ssl": "استخدم SSL", "use_suggested": "استخدام المقترح", + "use_testnet": "استخدم testnet", "variable_pair_not_supported": "هذا الزوج المتغير غير مدعوم في التبادلات المحددة", "verification": "تَحَقّق", "verify_with_2fa": "تحقق مع Cake 2FA", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 9d64e36ae..8dbdf4b98 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -719,6 +719,7 @@ "use_card_info_two": "Средствата се обръщат в USD, когато биват запазени в предплатената карта, а не в дигитална валута.", "use_ssl": "Използване на SSL", "use_suggested": "Използване на предложеното", + "use_testnet": "Използвайте TestNet", "variable_pair_not_supported": "Този variable pair не се поддържа от избраната борса", "verification": "Потвърждаване", "verify_with_2fa": "Проверете с Cake 2FA", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 8665efc2c..ff22febf0 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -719,6 +719,7 @@ "use_card_info_two": "Prostředky jsou převedeny na USD, když jsou drženy na předplaceném účtu, nikoliv na digitální měnu.", "use_ssl": "Použít SSL", "use_suggested": "Použít doporučený", + "use_testnet": "Použijte testNet", "variable_pair_not_supported": "Tento pár s tržním kurzem není ve zvolené směnárně podporován", "verification": "Ověření", "verify_with_2fa": "Ověřte pomocí Cake 2FA", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 28e3d4996..366d7d529 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -721,6 +721,7 @@ "use_card_info_two": "Guthaben werden auf dem Prepaid-Konto in USD umgerechnet, nicht in digitale Währung.", "use_ssl": "SSL verwenden", "use_suggested": "Vorgeschlagen verwenden", + "use_testnet": "TESTNET verwenden", "variable_pair_not_supported": "Dieses Variablenpaar wird von den ausgewählten Börsen nicht unterstützt", "verification": "Verifizierung", "verify_with_2fa": "Verifizieren Sie mit Cake 2FA", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index aae06f6b0..b7aecc739 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -719,6 +719,7 @@ "use_card_info_two": "Funds are converted to USD when they're held in the prepaid account, not in digital currencies.", "use_ssl": "Use SSL", "use_suggested": "Use Suggested", + "use_testnet": "Use Testnet", "variable_pair_not_supported": "This variable pair is not supported with the selected exchanges", "verification": "Verification", "verify_with_2fa": "Verify with Cake 2FA", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index d9e786467..832d66b5b 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -720,6 +720,7 @@ "use_card_info_two": "Los fondos se convierten a USD cuando se mantienen en la cuenta prepaga, no en monedas digitales.", "use_ssl": "Utilice SSL", "use_suggested": "Usar sugerido", + "use_testnet": "Use TestNet", "variable_pair_not_supported": "Este par de variables no es compatible con los intercambios seleccionados", "verification": "Verificación", "verify_with_2fa": "Verificar con Cake 2FA", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 8b4fc10d1..80b44d6ed 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -719,6 +719,7 @@ "use_card_info_two": "Les fonds sont convertis en USD lorsqu'ils sont détenus sur le compte prépayé, et non en devises numériques.", "use_ssl": "Utiliser SSL", "use_suggested": "Suivre la suggestion", + "use_testnet": "Utiliser TestNet", "variable_pair_not_supported": "Cette paire variable n'est pas prise en charge avec les échanges sélectionnés", "verification": "Vérification", "verify_with_2fa": "Vérifier avec Cake 2FA", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 6d1a5db0c..e1b77f346 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -721,6 +721,7 @@ "use_card_info_two": "Ana canza kuɗi zuwa dalar Amurka lokacin da ake riƙe su a cikin asusun da aka riga aka biya, ba cikin agogon dijital ba.", "use_ssl": "Yi amfani da SSL", "use_suggested": "Amfani da Shawarwari", + "use_testnet": "Amfani da gwaji", "variable_pair_not_supported": "Ba a samun goyan bayan wannan m biyu tare da zaɓaɓɓun musayar", "verification": "tabbatar", "verify_with_2fa": "Tabbatar da Cake 2FA", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index eaeffab92..555e1fff5 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -721,6 +721,7 @@ "use_card_info_two": "डिजिटल मुद्राओं में नहीं, प्रीपेड खाते में रखे जाने पर निधियों को यूएसडी में बदल दिया जाता है।", "use_ssl": "उपयोग SSL", "use_suggested": "सुझाए गए का प्रयोग करें", + "use_testnet": "टेस्टनेट का उपयोग करें", "variable_pair_not_supported": "यह परिवर्तनीय जोड़ी चयनित एक्सचेंजों के साथ समर्थित नहीं है", "verification": "सत्यापन", "verify_with_2fa": "केक 2FA के साथ सत्यापित करें", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index a915030f4..2b2e80198 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -719,6 +719,7 @@ "use_card_info_two": "Sredstva se pretvaraju u USD kada se drže na prepaid računu, a ne u digitalnim valutama.", "use_ssl": "Koristi SSL", "use_suggested": "Koristite predloženo", + "use_testnet": "Koristite TestNet", "variable_pair_not_supported": "Ovaj par varijabli nije podržan s odabranim burzama", "verification": "Potvrda", "verify_with_2fa": "Provjerite s Cake 2FA", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index ed53b7e62..10af2f8ad 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -722,6 +722,7 @@ "use_card_info_two": "Dana dikonversi ke USD ketika disimpan dalam akun pra-bayar, bukan dalam mata uang digital.", "use_ssl": "Gunakan SSL", "use_suggested": "Gunakan yang Disarankan", + "use_testnet": "Gunakan TestNet", "variable_pair_not_supported": "Pasangan variabel ini tidak didukung dengan bursa yang dipilih", "verification": "Verifikasi", "verify_with_2fa": "Verifikasi dengan Cake 2FA", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index d83619855..a4093f077 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -721,6 +721,7 @@ "use_card_info_two": "I fondi vengono convertiti in USD quando sono detenuti nel conto prepagato, non in valute digitali.", "use_ssl": "Usa SSL", "use_suggested": "Usa suggerito", + "use_testnet": "Usa TestNet", "variable_pair_not_supported": "Questa coppia di variabili non è supportata con gli scambi selezionati", "verification": "Verifica", "verify_with_2fa": "Verifica con Cake 2FA", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index e04d8c000..001e26f65 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -720,6 +720,7 @@ "use_card_info_two": "デジタル通貨ではなく、プリペイドアカウントで保持されている場合、資金は米ドルに変換されます。", "use_ssl": "SSLを使用する", "use_suggested": "推奨を使用", + "use_testnet": "テストネットを使用します", "variable_pair_not_supported": "この変数ペアは、選択した取引所ではサポートされていません", "verification": "検証", "verify_with_2fa": "Cake 2FA で検証する", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index cfd3df6c9..bc708b246 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -720,6 +720,7 @@ "use_card_info_two": "디지털 화폐가 아닌 선불 계정에 보유하면 자금이 USD로 변환됩니다.", "use_ssl": "SSL 사용", "use_suggested": "추천 사용", + "use_testnet": "TestNet을 사용하십시오", "variable_pair_not_supported": "이 변수 쌍은 선택한 교환에서 지원되지 않습니다.", "verification": "검증", "verify_with_2fa": "케이크 2FA로 확인", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 281bb6cea..56cdb802d 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -719,6 +719,7 @@ "use_card_info_two": "ဒစ်ဂျစ်တယ်ငွေကြေးများဖြင့်မဟုတ်ဘဲ ကြိုတင်ငွေပေးချေသည့်အကောင့်တွင် သိမ်းထားသည့်အခါ ရန်ပုံငွေများကို USD သို့ ပြောင်းလဲပါသည်။", "use_ssl": "SSL ကိုသုံးပါ။", "use_suggested": "အကြံပြုထားသည်ကို အသုံးပြုပါ။", + "use_testnet": "testnet ကိုသုံးပါ", "variable_pair_not_supported": "ရွေးချယ်ထားသော ဖလှယ်မှုများဖြင့် ဤပြောင်းလဲနိုင်သောအတွဲကို ပံ့ပိုးမထားပါ။", "verification": "စိစစ်ခြင်း။", "verify_with_2fa": "Cake 2FA ဖြင့် စစ်ဆေးပါ။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 19573b116..3ab2c06e6 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -719,6 +719,7 @@ "use_card_info_two": "Tegoeden worden omgezet naar USD wanneer ze op de prepaid-rekening staan, niet in digitale valuta.", "use_ssl": "Gebruik SSL", "use_suggested": "Gebruik aanbevolen", + "use_testnet": "Gebruik testnet", "variable_pair_not_supported": "Dit variabelenpaar wordt niet ondersteund met de geselecteerde uitwisselingen", "verification": "Verificatie", "verify_with_2fa": "Controleer met Cake 2FA", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 33fd1408a..855fb6680 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -719,6 +719,7 @@ "use_card_info_two": "Środki są przeliczane na USD, gdy są przechowywane na koncie przedpłaconym, a nie w walutach cyfrowych.", "use_ssl": "Użyj SSL", "use_suggested": "Użyj sugerowane", + "use_testnet": "Użyj testne", "variable_pair_not_supported": "Ta para zmiennych nie jest obsługiwana na wybranych giełdach", "verification": "Weryfikacja", "verify_with_2fa": "Sprawdź za pomocą Cake 2FA", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 649551d01..df3f0cdd1 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -721,6 +721,7 @@ "use_card_info_two": "Os fundos são convertidos para USD quando mantidos na conta pré-paga, não em moedas digitais.", "use_ssl": "Use SSL", "use_suggested": "Uso sugerido", + "use_testnet": "Use testNet", "variable_pair_not_supported": "Este par de variáveis não é compatível com as trocas selecionadas", "verification": "Verificação", "verify_with_2fa": "Verificar com Cake 2FA", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 16c294ef7..ebd444461 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -720,6 +720,7 @@ "use_card_info_two": "Средства конвертируются в доллары США, когда они хранятся на предоплаченном счете, а не в цифровых валютах.", "use_ssl": "Использовать SSL", "use_suggested": "Использовать предложенный", + "use_testnet": "Используйте Testnet", "variable_pair_not_supported": "Эта пара переменных не поддерживается выбранными биржами.", "verification": "Проверка", "verify_with_2fa": "Подтвердить с помощью Cake 2FA", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index dc72090d4..5e04f780f 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -719,6 +719,7 @@ "use_card_info_two": "เงินจะถูกแปลงค่าเป็นดอลลาร์สหรัฐเมื่อถือไว้ในบัญชีสำรองเงิน ไม่ใช่สกุลเงินดิจิตอล", "use_ssl": "ใช้ SSL", "use_suggested": "ใช้ที่แนะนำ", + "use_testnet": "ใช้ testnet", "variable_pair_not_supported": "คู่ความสัมพันธ์ที่เปลี่ยนแปลงได้นี้ไม่สนับสนุนกับหุ้นที่เลือก", "verification": "การตรวจสอบ", "verify_with_2fa": "ตรวจสอบกับ Cake 2FA", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 4090a4669..6be45a997 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -719,6 +719,7 @@ "use_card_info_two": "Ang mga pondo ay na -convert sa USD kapag gaganapin sila sa prepaid account, hindi sa mga digital na pera.", "use_ssl": "Gumamit ng SSL", "use_suggested": "Gumamit ng iminungkahing", + "use_testnet": "Gumamit ng testnet", "variable_pair_not_supported": "Ang variable na pares na ito ay hindi suportado sa mga napiling palitan", "verification": "Pag -verify", "verify_with_2fa": "Mag -verify sa cake 2FA", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 39eab9f86..60773f37d 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -719,6 +719,7 @@ "use_card_info_two": "Paralar, dijital para birimlerinde değil, ön ödemeli hesapta tutulduğunda USD'ye dönüştürülür.", "use_ssl": "SSL kullan", "use_suggested": "Önerileni Kullan", + "use_testnet": "TestNet kullanın", "variable_pair_not_supported": "Bu değişken paritesi seçilen borsalarda desteklenmemekte", "verification": "Doğrulama", "verify_with_2fa": "Cake 2FA ile Doğrulayın", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index b655a902d..ae4efdd8f 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -720,6 +720,7 @@ "use_card_info_two": "Кошти конвертуються в долари США, якщо вони зберігаються на передплаченому рахунку, а не в цифрових валютах.", "use_ssl": "Використати SSL", "use_suggested": "Використати запропоноване", + "use_testnet": "Використовуйте тестову мережу", "variable_pair_not_supported": "Ця пара змінних не підтримується вибраними біржами", "verification": "Перевірка", "verify_with_2fa": "Перевірте за допомогою Cake 2FA", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 0dcd31069..929f7de2e 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -721,6 +721,7 @@ "use_card_info_two": "رقوم کو امریکی ڈالر میں تبدیل کیا جاتا ہے جب پری پیڈ اکاؤنٹ میں رکھا جاتا ہے، ڈیجیٹل کرنسیوں میں نہیں۔", "use_ssl": "SSL استعمال کریں۔", "use_suggested": "تجویز کردہ استعمال کریں۔", + "use_testnet": "ٹیسٹ نیٹ استعمال کریں", "variable_pair_not_supported": "یہ متغیر جوڑا منتخب ایکسچینجز کے ساتھ تعاون یافتہ نہیں ہے۔", "verification": "تصدیق", "verify_with_2fa": "کیک 2FA سے تصدیق کریں۔", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index af21c001b..9813cc976 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -720,6 +720,7 @@ "use_card_info_two": "A pààrọ̀ owó sí owó Amẹ́ríkà tó bá wà nínú àkanti t'á ti fikún tẹ́lẹ̀tẹ́lẹ̀. A kò kó owó náà nínú owó ayélujára.", "use_ssl": "Lo SSL", "use_suggested": "Lo àbá", + "use_testnet": "Lo tele", "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_with_2fa": "Ṣeẹda pẹlu Cake 2FA", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 6c245d30f..3a2104ecc 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -719,6 +719,7 @@ "use_card_info_two": "预付账户中的资金转换为美元,不是数字货币。", "use_ssl": "使用SSL", "use_suggested": "使用建议", + "use_testnet": "使用TestNet", "variable_pair_not_supported": "所选交易所不支持此变量对", "verification": "验证", "verify_with_2fa": "用 Cake 2FA 验证", diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index f659239e7..9251ec31a 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -22,8 +22,8 @@ MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.13.3" -CAKEWALLET_BUILD_NUMBER=192 +CAKEWALLET_VERSION="4.14.0" +CAKEWALLET_BUILD_NUMBER=193 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/android/shell.nix b/scripts/android/shell.nix new file mode 100644 index 000000000..b89da09c0 --- /dev/null +++ b/scripts/android/shell.nix @@ -0,0 +1,16 @@ +{ pkgs ? import {} }: + +pkgs.mkShell { + buildInputs = [ + pkgs.curl + pkgs.unzip + pkgs.automake + pkgs.file + pkgs.pkg-config + pkgs.git + pkgs.libtool + pkgs.ncurses5 + pkgs.openjdk8 + pkgs.clang + ]; +} diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index bb4ca77f8..47d80013c 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -18,8 +18,8 @@ MONERO_COM_BUILD_NUMBER=73 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.13.3" -CAKEWALLET_BUILD_NUMBER=212 +CAKEWALLET_VERSION="4.14.0" +CAKEWALLET_BUILD_NUMBER=213 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/tool/configure.dart b/tool/configure.dart index bd2e4227c..3a69e86b1 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -72,6 +72,7 @@ import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart';"""; const bitcoinCWHeaders = """ +import 'package:cw_bitcoin/bitcoin_receive_page_option.dart'; import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; @@ -82,6 +83,7 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_bitcoin/litecoin_wallet_service.dart'; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:mobx/mobx.dart'; """; const bitcoinCwPart = "part 'cw_bitcoin.dart';"; @@ -139,6 +141,10 @@ abstract class Bitcoin { TransactionPriority getLitecoinTransactionPriorityMedium(); TransactionPriority getBitcoinTransactionPrioritySlow(); TransactionPriority getLitecoinTransactionPrioritySlow(); + + Future setAddressType(Object wallet, dynamic option); + BitcoinReceivePageOption getSelectedAddressType(Object wallet); + List getBitcoinReceivePageOptions(); } """; From cbc0c3afd6bcb5999bc0928d9aa209e34d674849 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Fri, 23 Feb 2024 19:09:24 +0200 Subject: [PATCH 119/241] Generic fixes (#1304) * fix mobx no element error * fix mobx issue * Remove unused code * Enhance error handling for monero sync failure case * Separate litecoin mnemonic exception from bitcoin * - Enable onramper for polygon - Add Kaspa validation * Set null as the default length of address validation * Modify EVM fee text [skip ci] * Add seed length option to polygon * Add digibyte * Update configure_cake_wallet.sh and fix conflicts * Pin bottom section * Fix Solana missing isTestnet param --- .gitignore | 1 + assets/images/digibyte.png | Bin 0 -> 6008 bytes configure_cake_wallet.sh | 1 + cw_bitcoin/lib/bitcoin_wallet_service.dart | 2 +- cw_bitcoin/lib/litecoin_wallet_service.dart | 4 +- ...t => mnemonic_is_incorrect_exception.dart} | 6 +++ cw_core/lib/crypto_currency.dart | 9 ++-- cw_evm/lib/evm_chain_wallet_addresses.dart | 1 + cw_monero/lib/monero_wallet.dart | 20 ++++---- cw_solana/lib/default_spl_tokens.dart | 2 - cw_solana/lib/solana_wallet_service.dart | 8 ++-- lib/bitcoin_cash/cw_bitcoin_cash.dart | 6 --- lib/core/address_validator.dart | 4 +- lib/entities/provider_types.dart | 4 +- lib/src/screens/send/send_page.dart | 5 +- .../scollable_with_bottom_section.dart | 43 +++++++----------- .../advanced_privacy_settings_view_model.dart | 24 ++++++++-- .../unspent_coins_list_view_model.dart | 6 ++- lib/view_model/wallet_keys_view_model.dart | 4 +- tool/configure.dart | 4 -- 20 files changed, 84 insertions(+), 70 deletions(-) create mode 100644 assets/images/digibyte.png rename cw_bitcoin/lib/{bitcoin_mnemonic_is_incorrect_exception.dart => mnemonic_is_incorrect_exception.dart} (50%) diff --git a/.gitignore b/.gitignore index 25edfcfb0..6f2d0a182 100644 --- a/.gitignore +++ b/.gitignore @@ -86,6 +86,7 @@ cw_monero/cw_monero/android/.cxx/ **/*.g.dart android/key.properties +android/app/key.jks **/tool/.secrets-prod.json **/tool/.secrets-test.json diff --git a/assets/images/digibyte.png b/assets/images/digibyte.png new file mode 100644 index 0000000000000000000000000000000000000000..0045c68521f06503057c4168c7ec3bc3a6b48905 GIT binary patch literal 6008 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 literal 0 HcmV?d00001 diff --git a/configure_cake_wallet.sh b/configure_cake_wallet.sh index 5009cd9e3..cc55e8fcc 100755 --- a/configure_cake_wallet.sh +++ b/configure_cake_wallet.sh @@ -30,6 +30,7 @@ cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_solana && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_ethereum && flutter pub get && cd .. cd cw_polygon && flutter pub get && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index 2b8c489d2..38e769d15 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -1,7 +1,7 @@ import 'dart:io'; import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; -import 'package:cw_bitcoin/bitcoin_mnemonic_is_incorrect_exception.dart'; +import 'package:cw_bitcoin/mnemonic_is_incorrect_exception.dart'; import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_base.dart'; diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index 3d7462fa1..ee3b0e628 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -2,7 +2,7 @@ import 'dart:io'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:hive/hive.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; -import 'package:cw_bitcoin/bitcoin_mnemonic_is_incorrect_exception.dart'; +import 'package:cw_bitcoin/mnemonic_is_incorrect_exception.dart'; import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart'; import 'package:cw_bitcoin/litecoin_wallet.dart'; import 'package:cw_core/wallet_service.dart'; @@ -101,7 +101,7 @@ class LitecoinWalletService extends WalletService< Future restoreFromSeed( BitcoinRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { if (!validateMnemonic(credentials.mnemonic)) { - throw BitcoinMnemonicIsIncorrectException(); + throw LitecoinMnemonicIsIncorrectException(); } final wallet = await LitecoinWalletBase.create( diff --git a/cw_bitcoin/lib/bitcoin_mnemonic_is_incorrect_exception.dart b/cw_bitcoin/lib/mnemonic_is_incorrect_exception.dart similarity index 50% rename from cw_bitcoin/lib/bitcoin_mnemonic_is_incorrect_exception.dart rename to cw_bitcoin/lib/mnemonic_is_incorrect_exception.dart index 8d0583ce5..779bd3ea2 100644 --- a/cw_bitcoin/lib/bitcoin_mnemonic_is_incorrect_exception.dart +++ b/cw_bitcoin/lib/mnemonic_is_incorrect_exception.dart @@ -3,3 +3,9 @@ class BitcoinMnemonicIsIncorrectException implements Exception { String toString() => 'Bitcoin mnemonic has incorrect format. Mnemonic should contain 12 or 24 words separated by space.'; } + +class LitecoinMnemonicIsIncorrectException implements Exception { + @override + String toString() => + 'Litecoin mnemonic has incorrect format. Mnemonic should contain 24 words separated by space.'; +} diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index 62c0ad437..67581ecb8 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -9,7 +9,8 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen required this.decimals, this.fullName, this.iconPath, - this.tag, this.enabled = false, + this.tag, + this.enabled = false, }) : super(title: title, raw: raw); @@ -100,6 +101,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen CryptoCurrency.usdtPoly, CryptoCurrency.usdcEPoly, CryptoCurrency.kaspa, + CryptoCurrency.digibyte, ]; static const havenCurrencies = [ @@ -211,8 +213,9 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen static const banano = CryptoCurrency(title: 'BAN', fullName: 'Banano', raw: 86, name: 'banano', iconPath: 'assets/images/nano_icon.png', decimals: 29); static const usdtPoly = CryptoCurrency(title: 'USDT', tag: 'POLY', fullName: 'Tether USD (PoS)', raw: 87, name: 'usdtpoly', iconPath: 'assets/images/usdt_icon.png', decimals: 6); static const usdcEPoly = CryptoCurrency(title: 'USDC.E', tag: 'POLY', fullName: 'USD Coin (PoS)', raw: 88, name: 'usdcepoly', iconPath: 'assets/images/usdc_icon.png', decimals: 6); - static const kaspa = CryptoCurrency(title: 'KAS', fullName: 'Kaspa', raw: 89, name: 'kaspa', iconPath: 'assets/images/kaspa_icon.png', decimals: 8); - static const usdtSol = CryptoCurrency(title: 'USDT', tag: 'SOL', fullName: 'USDT Tether', raw: 90, name: 'usdtsol', iconPath: 'assets/images/usdt_icon.png', decimals: 6); + static const kaspa = CryptoCurrency(title: 'KAS', fullName: 'Kaspa', raw: 89, name: 'kas', iconPath: 'assets/images/kaspa_icon.png', decimals: 8); + static const digibyte = CryptoCurrency(title: 'DGB', fullName: 'DigiByte', raw: 90, name: 'dgb', iconPath: 'assets/images/digibyte.png', decimals: 8); + static const usdtSol = CryptoCurrency(title: 'USDT', tag: 'SOL', fullName: 'USDT Tether', raw: 90, name: 'usdtsol', iconPath: 'assets/images/usdt_icon.png', decimals: 6); static final Map _rawCurrencyMap = diff --git a/cw_evm/lib/evm_chain_wallet_addresses.dart b/cw_evm/lib/evm_chain_wallet_addresses.dart index d5d39f21d..4615d79ed 100644 --- a/cw_evm/lib/evm_chain_wallet_addresses.dart +++ b/cw_evm/lib/evm_chain_wallet_addresses.dart @@ -14,6 +14,7 @@ abstract class EVMChainWalletAddressesBase extends WalletAddresses with Store { super(walletInfo); @override + @observable String address; @override diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 1a34e4bd6..ab4bfb0b0 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -576,15 +576,19 @@ abstract class MoneroWalletBase return; } - final height = _getHeightByDate(walletInfo.date); - - if (height > MIN_RESTORE_HEIGHT) { - monero_wallet.setRecoveringFromSeed(isRecovery: true); - monero_wallet.setRefreshFromBlockHeight(height: height); - return; + int height = 0; + try { + height = _getHeightByDate(walletInfo.date); + } catch (e, s) { + onError?.call(FlutterErrorDetails( + exception: e, + stack: s, + library: this.runtimeType.toString(), + )); } - throw Exception("height isn't > $MIN_RESTORE_HEIGHT!"); + monero_wallet.setRecoveringFromSeed(isRecovery: true); + monero_wallet.setRefreshFromBlockHeight(height: height); } int _getHeightDistance(DateTime date) { @@ -600,7 +604,7 @@ abstract class MoneroWalletBase final heightDistance = _getHeightDistance(date); if (nodeHeight <= 0) { - // the node returned 0 (an error state), so lets just restore from cache: + // the node returned 0 (an error state) throw Exception("nodeHeight is <= 0!"); } diff --git a/cw_solana/lib/default_spl_tokens.dart b/cw_solana/lib/default_spl_tokens.dart index f96d62d86..7acad78e0 100644 --- a/cw_solana/lib/default_spl_tokens.dart +++ b/cw_solana/lib/default_spl_tokens.dart @@ -25,7 +25,6 @@ class DefaultSPLTokens { mintAddress: '2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk', decimal: 6, mint: 'soEth', - enabled: true, iconPath: 'assets/images/eth_icon.png', ), SPLToken( @@ -34,7 +33,6 @@ class DefaultSPLTokens { mintAddress: 'So11111111111111111111111111111111111111112', decimal: 9, mint: 'WSOL', - enabled: true, iconPath: 'assets/images/sol_icon.png', ), SPLToken( diff --git a/cw_solana/lib/solana_wallet_service.dart b/cw_solana/lib/solana_wallet_service.dart index 8abf1ffbb..b3ff22e7e 100644 --- a/cw_solana/lib/solana_wallet_service.dart +++ b/cw_solana/lib/solana_wallet_service.dart @@ -19,7 +19,7 @@ class SolanaWalletService extends WalletService walletInfoSource; @override - Future create(SolanaNewWalletCredentials credentials) async { + Future create(SolanaNewWalletCredentials credentials, {bool? isTestnet}) async { final strength = credentials.seedPhraseLength == 24 ? 256 : 128; final mnemonic = bip39.generateMnemonic(strength: strength); @@ -67,7 +67,8 @@ class SolanaWalletService extends WalletService restoreFromKeys(SolanaRestoreWalletFromPrivateKey credentials) async { + Future restoreFromKeys(SolanaRestoreWalletFromPrivateKey credentials, + {bool? isTestnet}) async { final wallet = SolanaWallet( password: credentials.password!, privateKey: credentials.privateKey, @@ -82,7 +83,8 @@ class SolanaWalletService extends WalletService restoreFromSeed(SolanaRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(SolanaRestoreWalletFromSeedCredentials credentials, + {bool? isTestnet}) async { if (!bip39.validateMnemonic(credentials.mnemonic)) { throw SolanaMnemonicIsIncorrectException(); } diff --git a/lib/bitcoin_cash/cw_bitcoin_cash.dart b/lib/bitcoin_cash/cw_bitcoin_cash.dart index 7dbb8614f..6e169209f 100644 --- a/lib/bitcoin_cash/cw_bitcoin_cash.dart +++ b/lib/bitcoin_cash/cw_bitcoin_cash.dart @@ -1,12 +1,6 @@ part of 'bitcoin_cash.dart'; class CWBitcoinCash extends BitcoinCash { - @override - String getMnemonic(int? strength) => Mnemonic.generate(); - - @override - Uint8List getSeedFromMnemonic(String seed) => Mnemonic.toSeed(seed); - @override String getCashAddrFormat(String address) => AddressUtils.getCashAddrFormat(address); diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 432471655..853762a1c 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -257,9 +257,9 @@ class AddressValidator extends TextValidator { case CryptoCurrency.near: return [64]; case CryptoCurrency.btcln: - return null; + case CryptoCurrency.kaspa: default: - return []; + return null; } } diff --git a/lib/entities/provider_types.dart b/lib/entities/provider_types.dart index 9a4b68dd7..f9c2f1a82 100644 --- a/lib/entities/provider_types.dart +++ b/lib/entities/provider_types.dart @@ -66,7 +66,7 @@ class ProvidersHelper { case WalletType.bitcoinCash: return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood]; case WalletType.polygon: - return [ProviderType.askEachTime, ProviderType.dfx]; + return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.dfx]; case WalletType.solana: return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood]; case WalletType.none: @@ -89,7 +89,7 @@ class ProvidersHelper { case WalletType.bitcoinCash: return [ProviderType.askEachTime, ProviderType.moonpaySell]; case WalletType.polygon: - return [ProviderType.askEachTime, ProviderType.dfx]; + return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.dfx]; case WalletType.solana: return [ ProviderType.askEachTime, diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 5870b1c4d..a3b7eaf85 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/entities/template.dart'; +import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.dart'; import 'package:cake_wallet/src/screens/send/widgets/send_card.dart'; import 'package:cake_wallet/src/widgets/add_template_button.dart'; @@ -420,7 +421,9 @@ class SendPage extends BasePage { amount: S.of(_dialogContext).send_amount, amountValue: sendViewModel.pendingTransaction!.amountFormatted, fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted, - fee: S.of(_dialogContext).send_fee, + fee: isEVMCompatibleChain(sendViewModel.walletType) + ? S.of(_dialogContext).send_estimated_fee + : S.of(_dialogContext).send_fee, feeValue: sendViewModel.pendingTransaction!.feeFormatted, feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted, outputs: sendViewModel.outputs, diff --git a/lib/src/widgets/scollable_with_bottom_section.dart b/lib/src/widgets/scollable_with_bottom_section.dart index 53f56716c..2487e6130 100644 --- a/lib/src/widgets/scollable_with_bottom_section.dart +++ b/lib/src/widgets/scollable_with_bottom_section.dart @@ -14,37 +14,28 @@ class ScrollableWithBottomSection extends StatefulWidget { final EdgeInsets? bottomSectionPadding; @override - ScrollableWithBottomSectionState createState() => - ScrollableWithBottomSectionState(); + ScrollableWithBottomSectionState createState() => ScrollableWithBottomSectionState(); } -class ScrollableWithBottomSectionState - extends State { +class ScrollableWithBottomSectionState extends State { @override Widget build(BuildContext context) { - return LayoutBuilder(builder: (context, constraints) { - return SingleChildScrollView( - // physics: - // const AlwaysScrollableScrollPhysics(), // const NeverScrollableScrollPhysics(), // - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.heightConstraints().maxHeight), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: widget.contentPadding ?? - EdgeInsets.only(left: 20, right: 20), - child: widget.content, - ), - Padding( - padding: widget.bottomSectionPadding ?? - EdgeInsets.only(bottom: 20, right: 20, left: 20), - child: widget.bottomSection) - ], + return Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: widget.contentPadding ?? EdgeInsets.only(left: 20, right: 20), + child: widget.content, + ), ), ), - ); - }); + Padding( + padding: widget.bottomSectionPadding?.copyWith(top: 10) ?? + EdgeInsets.only(top: 10, bottom: 20, right: 20, left: 20), + child: widget.bottomSection, + ), + ], + ); } } diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart index 14033b368..b78d831a4 100644 --- a/lib/view_model/advanced_privacy_settings_view_model.dart +++ b/lib/view_model/advanced_privacy_settings_view_model.dart @@ -27,11 +27,25 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { final SettingsStore _settingsStore; - bool get hasSeedPhraseLengthOption => - type == WalletType.bitcoinCash || - type == WalletType.ethereum || - type == WalletType.polygon || - type == WalletType.solana; + bool get hasSeedPhraseLengthOption { + // convert to switch case so that it give a syntax error when adding a new wallet type + // thus we don't forget about it + switch (type) { + case WalletType.ethereum: + case WalletType.bitcoinCash: + case WalletType.polygon: + case WalletType.solana: + return true; + case WalletType.monero: + case WalletType.none: + case WalletType.bitcoin: + case WalletType.litecoin: + case WalletType.haven: + case WalletType.nano: + case WalletType.banano: + return false; + } + } bool get hasSeedTypeOption => type == WalletType.monero; diff --git a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart index 6380bb07e..3b90aff41 100644 --- a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart +++ b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart @@ -15,7 +15,8 @@ class UnspentCoinsListViewModel = UnspentCoinsListViewModelBase with _$UnspentCo abstract class UnspentCoinsListViewModelBase with Store { UnspentCoinsListViewModelBase( {required this.wallet, required Box unspentCoinsInfo}) - : _unspentCoinsInfo = unspentCoinsInfo { + : _unspentCoinsInfo = unspentCoinsInfo, + _items = ObservableList() { _updateUnspentCoinsInfo(); _updateUnspents(); } @@ -23,7 +24,8 @@ abstract class UnspentCoinsListViewModelBase with Store { WalletBase wallet; final Box _unspentCoinsInfo; - final ObservableList _items = ObservableList(); + @observable + ObservableList _items; @computed ObservableList get items => _items; diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart index a84f1a4c4..d88316a04 100644 --- a/lib/view_model/wallet_keys_view_model.dart +++ b/lib/view_model/wallet_keys_view_model.dart @@ -20,9 +20,7 @@ abstract class WalletKeysViewModelBase with Store { WalletKeysViewModelBase(this._appStore) : title = _appStore.wallet!.type == WalletType.bitcoin || _appStore.wallet!.type == WalletType.litecoin || - _appStore.wallet!.type == WalletType.bitcoinCash || - _appStore.wallet!.type == WalletType.ethereum || - _appStore.wallet!.type == WalletType.polygon + _appStore.wallet!.type == WalletType.bitcoinCash ? S.current.wallet_seed : S.current.wallet_keys, _restoreHeight = _appStore.wallet!.walletInfo.restoreHeight, diff --git a/tool/configure.dart b/tool/configure.dart index 3a69e86b1..fb1647e13 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -729,10 +729,6 @@ import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; const bitcoinCashCwPart = "part 'cw_bitcoin_cash.dart';"; const bitcoinCashContent = """ abstract class BitcoinCash { - String getMnemonic(int? strength); - - Uint8List getSeedFromMnemonic(String seed); - String getCashAddrFormat(String address); WalletService createBitcoinCashWalletService( From 52983edf91fb9b11fe9ed1ac69fbe40301d10ece Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 23 Feb 2024 13:49:21 -0500 Subject: [PATCH 120/241] UI Enhancements (#1308) * Center the account text on the balance page * Modify dashboard button spacing * Change default theme to Dark theme * Remove legacyTheme and modify theme order * Add condition for Monero.com wallet default theme * Add locale for new themes * Add new themes * Update padding * Fixes * Update settings_store.dart --------- Co-authored-by: Omar Hatem --- lib/core/backup_service.dart | 2 -- lib/entities/preferences_key.dart | 1 - lib/palette.dart | 3 +++ lib/src/screens/dashboard/dashboard_page.dart | 2 +- .../widgets/home_screen_account_widget.dart | 4 ++-- lib/store/settings_store.dart | 11 +++------ lib/themes/monero_dark_theme.dart | 4 ++-- lib/themes/purple_dark_theme.dart | 13 +++++++++++ lib/themes/red_dark_theme.dart | 13 +++++++++++ lib/themes/red_light_theme.dart | 13 +++++++++++ lib/themes/theme_list.dart | 23 +++++++++++++++---- res/values/strings_ar.arb | 3 +++ res/values/strings_bg.arb | 3 +++ res/values/strings_cs.arb | 3 +++ res/values/strings_de.arb | 3 +++ res/values/strings_en.arb | 3 +++ res/values/strings_es.arb | 3 +++ res/values/strings_fr.arb | 3 +++ res/values/strings_ha.arb | 3 +++ res/values/strings_hi.arb | 3 +++ res/values/strings_hr.arb | 3 +++ res/values/strings_id.arb | 3 +++ res/values/strings_it.arb | 3 +++ res/values/strings_ja.arb | 3 +++ res/values/strings_ko.arb | 3 +++ res/values/strings_my.arb | 3 +++ res/values/strings_nl.arb | 3 +++ res/values/strings_pl.arb | 3 +++ res/values/strings_pt.arb | 3 +++ res/values/strings_ru.arb | 3 +++ res/values/strings_th.arb | 3 +++ res/values/strings_tl.arb | 3 +++ res/values/strings_tr.arb | 3 +++ res/values/strings_uk.arb | 3 +++ res/values/strings_ur.arb | 3 +++ res/values/strings_yo.arb | 3 +++ res/values/strings_zh.arb | 3 +++ 37 files changed, 147 insertions(+), 20 deletions(-) create mode 100644 lib/themes/purple_dark_theme.dart create mode 100644 lib/themes/red_dark_theme.dart create mode 100644 lib/themes/red_light_theme.dart diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 9b5c4c8db..2ec5f293d 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -464,8 +464,6 @@ class BackupService { PreferencesKey.disableSellKey: _sharedPreferences.getBool(PreferencesKey.disableSellKey), PreferencesKey.defaultBuyProvider: _sharedPreferences.getInt(PreferencesKey.defaultBuyProvider), - PreferencesKey.isDarkThemeLegacy: - _sharedPreferences.getBool(PreferencesKey.isDarkThemeLegacy), PreferencesKey.currentPinLength: _sharedPreferences.getInt(PreferencesKey.currentPinLength), PreferencesKey.currentTransactionPriorityKeyLegacy: _sharedPreferences.getInt(PreferencesKey.currentTransactionPriorityKeyLegacy), diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 7adb2df7f..0dd251aaa 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -28,7 +28,6 @@ class PreferencesKey { static const disableExchangeKey = 'disable_exchange'; static const exchangeStatusKey = 'exchange_status'; static const currentTheme = 'current_theme'; - static const isDarkThemeLegacy = 'dark_theme'; static const displayActionListModeKey = 'display_list_mode'; static const currentPinLength = 'current_pin_length'; static const currentLanguageCode = 'language_code'; diff --git a/lib/palette.dart b/lib/palette.dart index 46e2e8165..58cbeb697 100644 --- a/lib/palette.dart +++ b/lib/palette.dart @@ -23,6 +23,7 @@ class Palette { static const Color cornflower = Color.fromRGBO(85, 147, 240, 1.0); static const Color royalBlue = Color.fromRGBO(43, 114, 221, 1.0); static const Color lightRed = Color.fromRGBO(227, 87, 87, 1.0); + static const Color veryLightRed = Color.fromRGBO(239, 156, 156, 1.0); static const Color persianRed = Color.fromRGBO(206, 55, 55, 1.0); static const Color blueCraiola = Color.fromRGBO(69, 110, 255, 1.0); static const Color blueGreyCraiola = Color.fromRGBO(106, 177, 207, 1.0); @@ -97,4 +98,6 @@ class PaletteDark { static const Color matrixGreen = Color.fromRGBO(18, 229, 90, 1.0); static const Color moneroOrange = Color.fromRGBO(255, 102, 0, 1.0); static const Color moneroCard = Color.fromRGBO(20, 21, 24, 1.0); + static const Color red = Color.fromRGBO(190, 30, 30, 1.0); + static const Color darkPurple = Color.fromRGBO(117, 36, 204, 1.0); } diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index 356c69c00..61e7d6176 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -224,7 +224,7 @@ class _DashboardPageView extends BasePage { .syncedBackgroundColor, ), child: Container( - padding: EdgeInsets.only(left: 32, right: 32), + padding: EdgeInsets.only(left: 24, right: 32), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: MainActions.all diff --git a/lib/src/screens/dashboard/widgets/home_screen_account_widget.dart b/lib/src/screens/dashboard/widgets/home_screen_account_widget.dart index fa036978f..df20c5c43 100644 --- a/lib/src/screens/dashboard/widgets/home_screen_account_widget.dart +++ b/lib/src/screens/dashboard/widgets/home_screen_account_widget.dart @@ -19,8 +19,8 @@ class HomeScreenAccountWidget extends StatelessWidget { builder: (_) => getIt.get()); }, behavior: HitTestBehavior.opaque, - child: Container( - height: 100.0, + child: Padding( + padding: EdgeInsets.only(top: 25, bottom: 25, left: 25, right: 0), child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 672b29269..488049656 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -19,6 +19,7 @@ import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; import 'package:cake_wallet/view_model/settings/sync_mode.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; +import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/themes/theme_list.dart'; @@ -789,12 +790,9 @@ abstract class SettingsStoreBase with Store { final exchangeStatus = ExchangeApiMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.exchangeStatusKey) ?? ExchangeApiMode.enabled.raw); - final legacyTheme = (sharedPreferences.getBool(PreferencesKey.isDarkThemeLegacy) ?? false) - ? ThemeType.dark.index - : ThemeType.bright.index; final savedTheme = initialTheme ?? ThemeList.deserialize( - raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? legacyTheme); + raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? (isMoneroOnly ? ThemeList.moneroDarkTheme.raw : ThemeList.darkTheme.raw)); final actionListDisplayMode = ObservableList(); actionListDisplayMode.addAll(deserializeActionlistDisplayModes( sharedPreferences.getInt(PreferencesKey.displayActionListModeKey) ?? defaultActionsMode)); @@ -1152,11 +1150,8 @@ abstract class SettingsStoreBase with Store { exchangeStatus = ExchangeApiMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.exchangeStatusKey) ?? ExchangeApiMode.enabled.raw); - final legacyTheme = (sharedPreferences.getBool(PreferencesKey.isDarkThemeLegacy) ?? false) - ? ThemeType.dark.index - : ThemeType.bright.index; currentTheme = ThemeList.deserialize( - raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? legacyTheme); + raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? (isMoneroOnly ? ThemeList.moneroDarkTheme.raw : ThemeList.darkTheme.raw)); actionlistDisplayMode = ObservableList(); actionlistDisplayMode.addAll(deserializeActionlistDisplayModes( sharedPreferences.getInt(PreferencesKey.displayActionListModeKey) ?? defaultActionsMode)); diff --git a/lib/themes/monero_dark_theme.dart b/lib/themes/monero_dark_theme.dart index 4931d74bc..1478ba8c5 100644 --- a/lib/themes/monero_dark_theme.dart +++ b/lib/themes/monero_dark_theme.dart @@ -95,12 +95,12 @@ class MoneroDarkTheme extends DarkTheme { @override CakeMenuTheme get menuTheme => super.menuTheme.copyWith( - headerFirstGradientColor: containerColor, + headerFirstGradientColor: primaryColor, headerSecondGradientColor: containerColor, backgroundColor: containerColor, subnameTextColor: Colors.grey, dividerColor: colorScheme.secondaryContainer, - iconColor: colorScheme.secondaryContainer, + iconColor: Colors.white, settingActionsIconColor: colorScheme.secondaryContainer); @override diff --git a/lib/themes/purple_dark_theme.dart b/lib/themes/purple_dark_theme.dart new file mode 100644 index 000000000..04365de38 --- /dev/null +++ b/lib/themes/purple_dark_theme.dart @@ -0,0 +1,13 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/themes/monero_dark_theme.dart'; +import 'package:flutter/material.dart'; + +class PurpleDarkTheme extends MoneroDarkTheme { + PurpleDarkTheme({required int raw}) : super(raw: raw); + + @override + String get title => S.current.purple_dark_theme; + @override + Color get primaryColor => PaletteDark.darkPurple; +} \ No newline at end of file diff --git a/lib/themes/red_dark_theme.dart b/lib/themes/red_dark_theme.dart new file mode 100644 index 000000000..d378fc66a --- /dev/null +++ b/lib/themes/red_dark_theme.dart @@ -0,0 +1,13 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/themes/monero_dark_theme.dart'; +import 'package:flutter/material.dart'; + +class RedDarkTheme extends MoneroDarkTheme { + RedDarkTheme({required int raw}) : super(raw: raw); + + @override + String get title => S.current.red_dark_theme; + @override + Color get primaryColor => PaletteDark.red; +} \ No newline at end of file diff --git a/lib/themes/red_light_theme.dart b/lib/themes/red_light_theme.dart new file mode 100644 index 000000000..47a995a11 --- /dev/null +++ b/lib/themes/red_light_theme.dart @@ -0,0 +1,13 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/themes/monero_light_theme.dart'; +import 'package:flutter/material.dart'; + +class RedLightTheme extends MoneroLightTheme { + RedLightTheme({required int raw}) : super(raw: raw); + + @override + String get title => S.current.red_light_theme; + @override + Color get primaryColor => Palette.darkRed; +} \ No newline at end of file diff --git a/lib/themes/theme_list.dart b/lib/themes/theme_list.dart index cb65dc2b9..6d0d44225 100644 --- a/lib/themes/theme_list.dart +++ b/lib/themes/theme_list.dart @@ -3,23 +3,29 @@ import 'package:cake_wallet/themes/dark_theme.dart'; import 'package:cake_wallet/themes/light_theme.dart'; import 'package:cake_wallet/themes/monero_light_theme.dart'; import 'package:cake_wallet/themes/monero_dark_theme.dart'; +import 'package:cake_wallet/themes/purple_dark_theme.dart'; import 'package:cake_wallet/themes/matrix_green_theme.dart'; import 'package:cake_wallet/themes/bitcoin_dark_theme.dart'; import 'package:cake_wallet/themes/bitcoin_light_theme.dart'; import 'package:cake_wallet/themes/high_contrast_theme.dart'; +import 'package:cake_wallet/themes/red_dark_theme.dart'; +import 'package:cake_wallet/themes/red_light_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; class ThemeList { static final all = [ - brightTheme, - lightTheme, darkTheme, + lightTheme, + brightTheme, moneroDarkTheme, moneroLightTheme, - matrixGreenTheme, + purpleDarkTheme, bitcoinDarkTheme, bitcoinLightTheme, - highContrastTheme + matrixGreenTheme, + redDarkTheme, + redLightTheme, + highContrastTheme, ]; static final lightTheme = LightTheme(raw: 0); @@ -31,6 +37,9 @@ class ThemeList { static final bitcoinDarkTheme = BitcoinDarkTheme(raw: 6); static final bitcoinLightTheme = BitcoinLightTheme(raw: 7); static final highContrastTheme = HighContrastTheme(raw: 8); + static final redLightTheme = RedLightTheme(raw: 9); + static final redDarkTheme = RedDarkTheme(raw: 10); + static final purpleDarkTheme = PurpleDarkTheme(raw: 11); static ThemeBase deserialize({required int raw}) { switch (raw) { @@ -52,6 +61,12 @@ class ThemeList { return bitcoinLightTheme; case 8: return highContrastTheme; + case 9: + return redLightTheme; + case 10: + return redDarkTheme; + case 11: + return purpleDarkTheme; default: throw Exception( 'Unexpected token raw: $raw for deserialization of ThemeBase'); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 9e822c474..af92cead4 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -429,6 +429,7 @@ "provider_error": "خطأ ${provider}", "public_key": "مفتاح عمومي", "purchase_gift_card": "شراء بطاقة هدايا", + "purple_dark_theme": "موضوع الظلام الأرجواني", "qr_fullscreen": "انقر لفتح ال QR بملء الشاشة", "qr_payment_amount": "يحتوي هذا ال QR على مبلغ الدفع. هل تريد تغير المبلغ فوق القيمة الحالية؟", "question_to_disable_2fa": "هل أنت متأكد أنك تريد تعطيل Cake 2FA؟ لن تكون هناك حاجة إلى رمز 2FA للوصول إلى المحفظة ووظائف معينة.", @@ -440,6 +441,8 @@ "reconnect": "أعد الاتصال", "reconnect_alert_text": "هل أنت متأكد من رغبتك في إعادة الاتصال؟", "reconnection": "إعادة الاتصال", + "red_dark_theme": "موضوع الظلام الأحمر", + "red_light_theme": "موضوع الضوء الأحمر", "redeemed": "استردت", "refund_address": "عنوان إعادة المال", "reject": "ﺾﻓﺮﻳ", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 8dbdf4b98..9f46ac2f4 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -429,6 +429,7 @@ "provider_error": "Грешка на ${provider} ", "public_key": "Публичен ключ", "purchase_gift_card": "Купуване на Gift Card", + "purple_dark_theme": "Лилава тъмна тема", "qr_fullscreen": "Натиснете, за да отворите QR кода на цял екран", "qr_payment_amount": "Този QR код съдържа сума за плащане. Искате ли да промените стойността?", "question_to_disable_2fa": "Сигурни ли сте, че искате да деактивирате Cake 2FA? Вече няма да е необходим 2FA код за достъп до портфейла и определени функции.", @@ -440,6 +441,8 @@ "reconnect": "Reconnect", "reconnect_alert_text": "Сигурни ли сте, че искате да се свържете отново?", "reconnection": "Свързване отново", + "red_dark_theme": "Червена тъмна тема", + "red_light_theme": "Тема на червената светлина", "redeemed": "Използвани", "refund_address": "Refund address", "reject": "Отхвърляне", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index ff22febf0..f47c7acb3 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -429,6 +429,7 @@ "provider_error": "${provider} chyba", "public_key": "Veřejný klíč", "purchase_gift_card": "Objednat dárkovou kartu", + "purple_dark_theme": "Fialové temné téma", "qr_fullscreen": "Poklepáním otevřete QR kód na celé obrazovce", "qr_payment_amount": "Tento QR kód obsahuje i částku. Chcete přepsat současnou hodnotu?", "question_to_disable_2fa": "Opravdu chcete deaktivovat Cake 2FA? Pro přístup k peněžence a některým funkcím již nebude potřeba kód 2FA.", @@ -440,6 +441,8 @@ "reconnect": "Znovu připojit", "reconnect_alert_text": "Opravdu se chcete znovu připojit?", "reconnection": "Znovu připojit", + "red_dark_theme": "Červené temné téma", + "red_light_theme": "Téma červeného světla", "redeemed": "Uplatněné", "refund_address": "Adresa pro vrácení", "reject": "Odmítnout", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 366d7d529..338112022 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -430,6 +430,7 @@ "provider_error": "${provider}-Fehler", "public_key": "Öffentlicher Schlüssel", "purchase_gift_card": "Geschenkkarte kaufen", + "purple_dark_theme": "Lila dunkle Thema", "qr_fullscreen": "Tippen Sie hier, um den QR-Code im Vollbildmodus zu öffnen", "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", "question_to_disable_2fa": "Sind Sie sicher, dass Sie Cake 2FA deaktivieren möchten? Für den Zugriff auf die Wallet und bestimmte Funktionen wird kein 2FA-Code mehr benötigt.", @@ -441,6 +442,8 @@ "reconnect": "Erneut verbinden", "reconnect_alert_text": "Sind Sie sicher, dass Sie sich neu verbinden möchten?", "reconnection": "Neu verbinden", + "red_dark_theme": "Red Dark Thema", + "red_light_theme": "Rotlichtthema", "redeemed": "Versilbert", "refund_address": "Rückerstattungsadresse", "reject": "Ablehnen", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index b7aecc739..86dc6518d 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -429,6 +429,7 @@ "provider_error": "${provider} error", "public_key": "Public key", "purchase_gift_card": "Purchase Gift Card", + "purple_dark_theme": "Purple Dark Theme", "qr_fullscreen": "Tap to open full screen QR code", "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", "question_to_disable_2fa": "Are you sure that you want to disable Cake 2FA? A 2FA code will no longer be needed to access the wallet and certain functions.", @@ -440,6 +441,8 @@ "reconnect": "Reconnect", "reconnect_alert_text": "Are you sure you want to reconnect?", "reconnection": "Reconnection", + "red_dark_theme": "Red Dark Theme", + "red_light_theme": "Red Light Theme", "redeemed": "Redeemed", "refund_address": "Refund address", "reject": "Reject", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 832d66b5b..09ad9948b 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -430,6 +430,7 @@ "provider_error": "${provider} error", "public_key": "Clave pública", "purchase_gift_card": "Comprar tarjeta de regalo", + "purple_dark_theme": "Tema morado oscuro", "qr_fullscreen": "Toque para abrir el código QR en pantalla completa", "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", "question_to_disable_2fa": "¿Está seguro de que desea deshabilitar Cake 2FA? Ya no se necesitará un código 2FA para acceder a la billetera y a ciertas funciones.", @@ -441,6 +442,8 @@ "reconnect": "Volver a conectar", "reconnect_alert_text": "¿Estás seguro de reconectar?", "reconnection": "Reconexión", + "red_dark_theme": "Tema rojo oscuro", + "red_light_theme": "Tema de la luz roja", "redeemed": "Redimido", "refund_address": "Dirección de reembolso", "reject": "Rechazar", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 80b44d6ed..e552dfafa 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -429,6 +429,7 @@ "provider_error": "Erreur de ${provider}", "public_key": "Clef publique", "purchase_gift_card": "Acheter une carte-cadeau", + "purple_dark_theme": "THÈME PURPLE DARK", "qr_fullscreen": "Appuyez pour ouvrir le QR code en mode plein écran", "qr_payment_amount": "Ce QR code contient un montant de paiement. Voulez-vous remplacer la valeur actuelle ?", "question_to_disable_2fa": "Êtes-vous sûr de vouloir désactiver Cake 2FA ? Un code 2FA ne sera plus nécessaire pour accéder au portefeuille (wallet) et à certaines fonctions.", @@ -440,6 +441,8 @@ "reconnect": "Reconnecter", "reconnect_alert_text": "Êtes vous certain de vouloir vous reconnecter ?", "reconnection": "Reconnexion", + "red_dark_theme": "Thème rouge noir", + "red_light_theme": "Thème de la lumière rouge", "redeemed": "Converties", "refund_address": "Adresse de Remboursement", "reject": "Rejeter", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index e1b77f346..40f6b2857 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -431,6 +431,7 @@ "provider_error": "${provider} kuskure", "public_key": "Maɓallin jama'a", "purchase_gift_card": "Katin Kyautar Sayi", + "purple_dark_theme": "M duhu jigo", "qr_fullscreen": "Matsa don buɗe lambar QR na cikakken allo", "qr_payment_amount": "Wannan QR code yana da adadin kuɗi. Kuna so ku overwrite wannan adadi?", "question_to_disable_2fa": "Ka tabbata cewa kana son kashe cake 2fa? Ba za a sake buƙatar lambar 2FA ba don samun damar yin walat da takamaiman ayyuka.", @@ -442,6 +443,8 @@ "reconnect": "Sake haɗawa", "reconnect_alert_text": "Shin kun tabbata kuna son sake haɗawa?", "reconnection": "Sake haɗawa", + "red_dark_theme": "Ja duhu taken", + "red_light_theme": "Ja mai haske", "redeemed": "An fanshi", "refund_address": "Adireshin maidowa", "reject": "Ƙi", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 555e1fff5..d35a5f716 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -430,6 +430,7 @@ "provider_error": "${provider} त्रुटि", "public_key": "सार्वजनिक कुंजी", "purchase_gift_card": "गिफ्ट कार्ड खरीदें", + "purple_dark_theme": "पर्पल डार्क थीम", "qr_fullscreen": "फ़ुल स्क्रीन क्यूआर कोड खोलने के लिए टैप करें", "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", "question_to_disable_2fa": "क्या आप सुनिश्चित हैं कि आप Cake 2FA को अक्षम करना चाहते हैं? वॉलेट और कुछ कार्यों तक पहुँचने के लिए अब 2FA कोड की आवश्यकता नहीं होगी।", @@ -442,6 +443,8 @@ "reconnect": "रिकनेक्ट", "reconnect_alert_text": "क्या आप पुन: कनेक्ट होना सुनिश्चित करते हैं?", "reconnection": "पुनर्संयोजन", + "red_dark_theme": "लाल डार्क थीम", + "red_light_theme": "लाल प्रकाश थीम", "redeemed": "रिडीम किया गया", "refund_address": "वापसी का पता", "reject": "अस्वीकार करना", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 2b2e80198..c41310441 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -429,6 +429,7 @@ "provider_error": "${provider} greška", "public_key": "Javni ključ", "purchase_gift_card": "Kupnja darovne kartice", + "purple_dark_theme": "Ljubičasta tamna tema", "qr_fullscreen": "Dodirnite za otvaranje QR koda preko cijelog zaslona", "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", "question_to_disable_2fa": "Jeste li sigurni da želite onemogućiti Cake 2FA? 2FA kod više neće biti potreban za pristup novčaniku i određenim funkcijama.", @@ -440,6 +441,8 @@ "reconnect": "Ponovno povezivanje", "reconnect_alert_text": "Jeste li sigurni da se želite ponovno povezati?", "reconnection": "Ponovno povezivanje", + "red_dark_theme": "Crvena tamna tema", + "red_light_theme": "Tema crvenog svjetla", "redeemed": "otkupljeno", "refund_address": "Adresa za povrat", "reject": "Odbiti", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 10af2f8ad..a9b9b50b3 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -431,6 +431,7 @@ "provider_error": "${provider} error", "public_key": "Kunci publik", "purchase_gift_card": "Beli Kartu Hadiah", + "purple_dark_theme": "Tema gelap ungu", "qr_fullscreen": "Tap untuk membuka layar QR code penuh", "qr_payment_amount": "QR code ini berisi jumlah pembayaran. Apakah Anda ingin menimpa nilai saat ini?", "question_to_disable_2fa": "Apakah Anda yakin ingin menonaktifkan Cake 2FA? Kode 2FA tidak lagi diperlukan untuk mengakses dompet dan fungsi tertentu.", @@ -442,6 +443,8 @@ "reconnect": "Sambungkan kembali", "reconnect_alert_text": "Apakah Anda yakin ingin menyambungkan kembali?", "reconnection": "Koneksi kembali", + "red_dark_theme": "Tema gelap merah", + "red_light_theme": "Tema lampu merah", "redeemed": "Ditukar", "refund_address": "Alamat pengembalian", "reject": "Menolak", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index a4093f077..9682e3d7f 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -431,6 +431,7 @@ "provider_error": "${provider} errore", "public_key": "Chiave pubblica", "purchase_gift_card": "Acquista carta regalo", + "purple_dark_theme": "Tema oscuro viola", "qr_fullscreen": "Tocca per aprire il codice QR a schermo intero", "qr_payment_amount": "Questo codice QR contiene l'ammontare del pagamento. Vuoi sovrascrivere il varlore attuale?", "question_to_disable_2fa": "Sei sicuro di voler disabilitare Cake 2FA? Non sarà più necessario un codice 2FA per accedere al portafoglio e ad alcune funzioni.", @@ -442,6 +443,8 @@ "reconnect": "Riconnetti", "reconnect_alert_text": "Sei sicuro di volerti riconnettere?", "reconnection": "Riconnessione", + "red_dark_theme": "Red Dark Theme", + "red_light_theme": "Tema della luce rossa", "redeemed": "Redento", "refund_address": "Indirizzo di rimborso", "reject": "Rifiutare", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 001e26f65..0f4513eee 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -430,6 +430,7 @@ "provider_error": "${provider} エラー", "public_key": "公開鍵", "purchase_gift_card": "ギフトカードを購入", + "purple_dark_theme": "紫色の暗いテーマ", "qr_fullscreen": "タップして全画面QRコードを開く", "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", "question_to_disable_2fa": "Cake 2FA を無効にしてもよろしいですか?ウォレットと特定の機能にアクセスするために 2FA コードは必要なくなります。", @@ -441,6 +442,8 @@ "reconnect": "再接続", "reconnect_alert_text": "再接続しますか?", "reconnection": "再接続", + "red_dark_theme": "赤い暗いテーマ", + "red_light_theme": "赤色光のテーマ", "redeemed": "償還", "refund_address": "払い戻し住所", "reject": "拒否する", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index bc708b246..2dd80cf5c 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -430,6 +430,7 @@ "provider_error": "${provider} 오류", "public_key": "공개 키", "purchase_gift_card": "기프트 카드 구매", + "purple_dark_theme": "보라색 어두운 테마", "qr_fullscreen": "전체 화면 QR 코드를 열려면 탭하세요.", "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", "question_to_disable_2fa": "Cake 2FA를 비활성화하시겠습니까? 지갑 및 특정 기능에 액세스하는 데 더 이상 2FA 코드가 필요하지 않습니다.", @@ -441,6 +442,8 @@ "reconnect": "다시 연결", "reconnect_alert_text": "다시 연결 하시겠습니까?", "reconnection": "재 연결", + "red_dark_theme": "빨간 어두운 테마", + "red_light_theme": "빨간불 테마", "redeemed": "구함", "refund_address": "환불 주소", "reject": "거부하다", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 56cdb802d..1bc338dcb 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -429,6 +429,7 @@ "provider_error": "${provider} အမှား", "public_key": "အများသူငှာသော့", "purchase_gift_card": "လက်ဆောင်ကတ်ဝယ်ပါ။", + "purple_dark_theme": "ခရမ်းရောင် Drwing Theme", "qr_fullscreen": "မျက်နှာပြင်အပြည့် QR ကုဒ်ကိုဖွင့်ရန် တို့ပါ။", "qr_payment_amount": "ဤ QR ကုဒ်တွင် ငွေပေးချေမှုပမာဏတစ်ခုပါရှိသည်။ လက်ရှိတန်ဖိုးကို ထပ်ရေးလိုပါသလား။", "question_to_disable_2fa": "Cake 2FA ကို ပိတ်လိုသည်မှာ သေချာပါသလား။ ပိုက်ဆံအိတ်နှင့် အချို့သောလုပ်ဆောင်ချက်များကို အသုံးပြုရန်အတွက် 2FA ကုဒ်တစ်ခု မလိုအပ်တော့ပါ။", @@ -440,6 +441,8 @@ "reconnect": "ပြန်လည်ချိတ်ဆက်ပါ။", "reconnect_alert_text": "ပြန်လည်ချိတ်ဆက်လိုသည်မှာ သေချာပါသလား။ ?", "reconnection": "ပြန်လည်ချိတ်ဆက်မှု", + "red_dark_theme": "အနီရောင်မှောင်မိုက်ဆောင်ပုဒ်", + "red_light_theme": "အနီရောင်အလင်းအကြောင်းအရာ", "redeemed": "ရွေးနှုတ်ခဲ့သည်။", "refund_address": "ပြန်အမ်းငွေလိပ်စာ", "reject": "ငြင်းပယ်ပါ။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 3ab2c06e6..56175b636 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -429,6 +429,7 @@ "provider_error": "${provider} fout", "public_key": "Publieke sleutel", "purchase_gift_card": "Cadeaubon kopen", + "purple_dark_theme": "Paars donker thema", "qr_fullscreen": "Tik om de QR-code op volledig scherm te openen", "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", "question_to_disable_2fa": "Weet je zeker dat je Cake 2FA wilt uitschakelen? Er is geen 2FA-code meer nodig om toegang te krijgen tot de portemonnee en bepaalde functies.", @@ -440,6 +441,8 @@ "reconnect": "Sluit", "reconnect_alert_text": "Weet u zeker dat u opnieuw verbinding wilt maken?", "reconnection": "Reconnection", + "red_dark_theme": "Rood donker thema", + "red_light_theme": "Rood licht thema", "redeemed": "Verzilverd", "refund_address": "Adres voor terugbetaling", "reject": "Afwijzen", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 855fb6680..cbd1a7171 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -429,6 +429,7 @@ "provider_error": "${provider} pomyłka", "public_key": "Klucz publiczny", "purchase_gift_card": "Kup kartę podarunkową", + "purple_dark_theme": "Purple Dark Temat", "qr_fullscreen": "Dotknij, aby otworzyć pełnoekranowy kod QR", "qr_payment_amount": "Ten kod QR zawiera kwotę do zapłaty. Czy chcesz nadpisać obecną wartość?", "question_to_disable_2fa": "Czy na pewno chcesz wyłączyć Cake 2FA? Kod 2FA nie będzie już potrzebny do uzyskania dostępu do portfela i niektórych funkcji.", @@ -440,6 +441,8 @@ "reconnect": "Połącz ponownie", "reconnect_alert_text": "Czy na pewno ponownie się ponownie połączysz?", "reconnection": "Ponowne łączenie", + "red_dark_theme": "Czerwony Mroczny motyw", + "red_light_theme": "Motyw czerwony światło", "redeemed": "wykupione", "refund_address": "Adres do zwrotu", "reject": "Odrzucić", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index df3f0cdd1..7520f9327 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -431,6 +431,7 @@ "provider_error": "${provider} erro", "public_key": "Chave pública", "purchase_gift_card": "Comprar vale-presente", + "purple_dark_theme": "Tema escuro roxo", "qr_fullscreen": "Toque para abrir o código QR em tela cheia", "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", "question_to_disable_2fa": "Tem certeza de que deseja desativar o Cake 2FA? Um código 2FA não será mais necessário para acessar a carteira e certas funções.", @@ -442,6 +443,8 @@ "reconnect": "Reconectar", "reconnect_alert_text": "Você tem certeza de que deseja reconectar?", "reconnection": "Reconectar", + "red_dark_theme": "Tema escuro vermelho", + "red_light_theme": "Tema da luz vermelha", "redeemed": "Resgatado", "refund_address": "Endereço de reembolso", "reject": "Rejeitar", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index ebd444461..ee31e003a 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -430,6 +430,7 @@ "provider_error": "${provider} ошибка", "public_key": "Публичный ключ", "purchase_gift_card": "Купить подарочную карту", + "purple_dark_theme": "Пурпурная темная тема", "qr_fullscreen": "Нажмите, чтобы открыть полноэкранный QR-код", "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", "question_to_disable_2fa": "Вы уверены, что хотите отключить Cake 2FA? Код 2FA больше не потребуется для доступа к кошельку и некоторым функциям.", @@ -441,6 +442,8 @@ "reconnect": "Переподключиться", "reconnect_alert_text": "Вы хотите переподключиться?", "reconnection": "Переподключение", + "red_dark_theme": "Красная темная тема", + "red_light_theme": "Тема красного света", "redeemed": "искуплен", "refund_address": "Адрес возврата", "reject": "Отклонять", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 5e04f780f..3fddae170 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -429,6 +429,7 @@ "provider_error": "ข้อผิดพลาด ${provider}", "public_key": "คีย์สาธารณะ", "purchase_gift_card": "ซื้อบัตรของขวัญ", + "purple_dark_theme": "ธีมสีม่วงเข้ม", "qr_fullscreen": "แตะเพื่อเปิดหน้าจอ QR code แบบเต็มจอ", "qr_payment_amount": "QR code นี้มีจำนวนการชำระเงิน คุณต้องการเขียนทับค่าปัจจุบันหรือไม่?", "question_to_disable_2fa": "คุณแน่ใจหรือไม่ว่าต้องการปิดการใช้งาน Cake 2FA ไม่จำเป็นต้องใช้รหัส 2FA ในการเข้าถึงกระเป๋าเงินและฟังก์ชั่นบางอย่างอีกต่อไป", @@ -440,6 +441,8 @@ "reconnect": "เชื่อมต่อใหม่", "reconnect_alert_text": "คุณแน่ใจหรือไม่ว่าต้องการเชื่อมต่อใหม่?", "reconnection": "เชื่อมต่อใหม่", + "red_dark_theme": "ธีมสีแดงเข้ม", + "red_light_theme": "ธีมแสงสีแดง", "redeemed": "แลกของขวัญ", "refund_address": "ที่อยู่สำหรับส่งคืน", "reject": "ปฏิเสธ", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 6be45a997..6dc6d793a 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -429,6 +429,7 @@ "provider_error": "${provider} error", "public_key": "Pampublikong susi", "purchase_gift_card": "Bumili ng Gift Card", + "purple_dark_theme": "Purple Madilim na Tema", "qr_fullscreen": "Tapikin upang buksan ang buong screen QR code", "qr_payment_amount": "Ang QR code na ito ay naglalaman ng isang halaga ng pagbabayad. Nais mo bang i -overwrite ang kasalukuyang halaga?", "question_to_disable_2fa": "Sigurado ka bang nais mong huwag paganahin ang cake 2fa? Ang isang 2FA code ay hindi na kinakailangan upang ma -access ang pitaka at ilang mga pag -andar.", @@ -440,6 +441,8 @@ "reconnect": "Kumonekta muli", "reconnect_alert_text": "Sigurado ka bang nais mong muling kumonekta?", "reconnection": "Pag -ugnay muli", + "red_dark_theme": "Red Madilim na Tema", + "red_light_theme": "Red light tema", "redeemed": "Tinubos", "refund_address": "Refund address", "reject": "Tanggihan", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 60773f37d..585ef495a 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -429,6 +429,7 @@ "provider_error": "${provider} hatası", "public_key": "Genel Anahtar", "purchase_gift_card": "Hediye Kartı Satın Al", + "purple_dark_theme": "Mor karanlık tema", "qr_fullscreen": "QR kodunu tam ekranda açmak için dokun", "qr_payment_amount": "Bu QR kodu ödeme tutarını içeriyor. Geçerli miktarın üzerine yazmak istediğine emin misin?", "question_to_disable_2fa": "Cake 2FA'yı devre dışı bırakmak istediğinizden emin misiniz? M-cüzdana ve belirli işlevlere erişmek için artık 2FA koduna gerek kalmayacak.", @@ -440,6 +441,8 @@ "reconnect": "Yeniden Bağlan", "reconnect_alert_text": "Yeniden bağlanmak istediğinden emin misin?", "reconnection": "Yeniden bağlantı", + "red_dark_theme": "Kırmızı Karanlık Tema", + "red_light_theme": "Kırmızı Işık Teması", "redeemed": "Kullanılmış", "refund_address": "İade adresi", "reject": "Reddetmek", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index ae4efdd8f..a22fa8fb1 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -429,6 +429,7 @@ "provider_error": "${provider} помилка", "public_key": "Публічний ключ", "purchase_gift_card": "Придбати подарункову картку", + "purple_dark_theme": "Фіолетова темна тема", "qr_fullscreen": "Торкніться, щоб відкрити QR-код на весь екран", "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", "question_to_disable_2fa": "Ви впевнені, що хочете вимкнути Cake 2FA? Код 2FA більше не потрібен для доступу до гаманця та певних функцій.", @@ -440,6 +441,8 @@ "reconnect": "Перепідключитися", "reconnect_alert_text": "Ви хочете перепідключитися?", "reconnection": "Перепідключення", + "red_dark_theme": "Червона темна тема", + "red_light_theme": "Тема червоного світла", "redeeded": "Викуплено", "redeemed": "Викуплений", "refund_address": "Адреса повернення коштів", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 929f7de2e..35e17feac 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -431,6 +431,7 @@ "provider_error": "${provider} خرابی۔", "public_key": "عوامی کلید", "purchase_gift_card": "گفٹ کارڈ خریدیں۔", + "purple_dark_theme": "ارغوانی ڈارک تھیم", "qr_fullscreen": "فل سکرین QR کوڈ کھولنے کے لیے تھپتھپائیں۔", "qr_payment_amount": "اس QR کوڈ میں ادائیگی کی رقم شامل ہے۔ کیا آپ موجودہ قدر کو اوور رائٹ کرنا چاہتے ہیں؟", "question_to_disable_2fa": "کیا آپ واقعی کیک 2FA کو غیر فعال کرنا چاہتے ہیں؟ بٹوے اور بعض افعال تک رسائی کے لیے اب 2FA کوڈ کی ضرورت نہیں ہوگی۔", @@ -442,6 +443,8 @@ "reconnect": "دوبارہ جڑیں۔", "reconnect_alert_text": "کیا آپ واقعی دوبارہ جڑنا چاہتے ہیں؟", "reconnection": "دوبارہ رابطہ", + "red_dark_theme": "ریڈ ڈارک تھیم", + "red_light_theme": "ریڈ لائٹ تھیم", "redeemed": "چھڑایا", "refund_address": "رقم کی واپسی کا پتہ", "reject": "ﺎﻧﺮﮐ ﺩﺭ", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 9813cc976..0f141ebdf 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -430,6 +430,7 @@ "provider_error": "Àṣìṣe ${provider}", "public_key": "Kọ́kọ́rọ́ tó kò àdáni", "purchase_gift_card": "Ra káàdì ìrajà t'á lò nínú irú kan ìtajà", + "purple_dark_theme": "Akọle dudu dudu", "qr_fullscreen": "Àmì ìlujá túbọ̀ máa tóbi tí o bá tẹ̀", "qr_payment_amount": "Iye owó t'á ránṣé wà nínú àmì ìlujá yìí. Ṣé ẹ fẹ́ pààrọ̀ ẹ̀?", "question_to_disable_2fa": "Ṣe o wa daadaa pe o fẹ ko 2FA Cake? Ko si itumọ ti a yoo nilo lati ranse si iwe iwe naa ati eyikeyi iṣẹ ti o ni.", @@ -441,6 +442,8 @@ "reconnect": "Ṣe àtúnse", "reconnect_alert_text": "Ṣó dá ẹ lójú pé ẹ fẹ́ ṣe àtúnse?", "reconnection": "Àtúnṣe", + "red_dark_theme": "Akọle dudu pupa", + "red_light_theme": "Akori ina pupa", "redeemed": "Ó lílò", "refund_address": "Àdírẹ́sì t'ẹ́ gba owó sí", "reject": "Kọ", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 3a2104ecc..ffea168a9 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -429,6 +429,7 @@ "provider_error": "${provider} 错误", "public_key": "公钥", "purchase_gift_card": "购买礼品卡", + "purple_dark_theme": "紫色的黑暗主题", "qr_fullscreen": "点击打开全屏二维码", "qr_payment_amount": "This QR code contains a payment amount. Do you want to overwrite the current value?", "question_to_disable_2fa": "您确定要禁用 Cake 2FA 吗?访问钱包和某些功能将不再需要 2FA 代码。", @@ -440,6 +441,8 @@ "reconnect": "重新连接", "reconnect_alert_text": "您确定要重新连接吗?", "reconnection": "重新连接", + "red_dark_theme": "红色的黑暗主题", + "red_light_theme": "红灯主题", "redeemed": "赎回", "refund_address": "退款地址", "reject": "拒绝", From 948669b5c2fc3464f548e7c725f2a7c1e8936c89 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 23 Feb 2024 15:00:16 -0500 Subject: [PATCH 121/241] Fix colors (#1311) * Fix colors * Update colors * oops --- lib/palette.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/palette.dart b/lib/palette.dart index 58cbeb697..6681888c8 100644 --- a/lib/palette.dart +++ b/lib/palette.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; class Palette { static const Color green = Color.fromRGBO(39, 206, 80, 1.0); static const Color red = Color.fromRGBO(255, 51, 51, 1.0); - static const Color darkRed = Color.fromRGBO(204, 38, 38, 1.0); + static const Color darkRed = Color.fromRGBO(205, 0, 0, 1.0); static const Color blueAlice = Color.fromRGBO(229, 247, 255, 1.0); static const Color lightBlue = Color.fromRGBO(172, 203, 238, 1.0); static const Color lavender = Color.fromRGBO(237, 245, 252, 1.0); @@ -98,6 +98,6 @@ class PaletteDark { static const Color matrixGreen = Color.fromRGBO(18, 229, 90, 1.0); static const Color moneroOrange = Color.fromRGBO(255, 102, 0, 1.0); static const Color moneroCard = Color.fromRGBO(20, 21, 24, 1.0); - static const Color red = Color.fromRGBO(190, 30, 30, 1.0); - static const Color darkPurple = Color.fromRGBO(117, 36, 204, 1.0); + static const Color red = Color.fromRGBO(195, 0, 0, 1.0); + static const Color darkPurple = Color.fromRGBO(109, 14, 210, 1.0); } From 5b1f17c1fbcfbf3b4989421779acbfafb5269f05 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Fri, 23 Feb 2024 16:50:17 -0800 Subject: [PATCH 122/241] fix (#1232) --- macos/Podfile | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/macos/Podfile b/macos/Podfile index fe5678c70..16db2b54c 100644 --- a/macos/Podfile +++ b/macos/Podfile @@ -41,4 +41,20 @@ post_install do |installer| config.build_settings['MACOSX_DEPLOYMENT_TARGET'] = '12.0' end end + + installer.aggregate_targets.each do |target| + target.xcconfigs.each do |variant, xcconfig| + xcconfig_path = target.client_root + target.xcconfig_relative_path(variant) + IO.write(xcconfig_path, IO.read(xcconfig_path).gsub("DT_TOOLCHAIN_DIR", "TOOLCHAIN_DIR")) + end + end + + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + if config.base_configuration_reference.is_a? Xcodeproj::Project::Object::PBXFileReference + xcconfig_path = config.base_configuration_reference.real_path + IO.write(xcconfig_path, IO.read(xcconfig_path).gsub("DT_TOOLCHAIN_DIR", "TOOLCHAIN_DIR")) + end + end + end end From 2549b0fa0a7171846e7dd872a54dc2e41075e6f6 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Tue, 27 Feb 2024 21:15:18 -0500 Subject: [PATCH 123/241] Replace purple with "Cake Dark Blue" theme and make it default (#1314) --- lib/palette.dart | 2 ++ lib/store/settings_store.dart | 4 ++-- lib/themes/cake_dark_theme.dart | 24 ++++++++++++++++++++++++ lib/themes/purple_dark_theme.dart | 13 ------------- lib/themes/theme_list.dart | 10 +++++----- res/values/strings_ar.arb | 7 ++++--- res/values/strings_bg.arb | 7 ++++--- res/values/strings_cs.arb | 7 ++++--- res/values/strings_de.arb | 9 +++++---- res/values/strings_en.arb | 7 ++++--- res/values/strings_es.arb | 7 ++++--- res/values/strings_fr.arb | 7 ++++--- res/values/strings_ha.arb | 7 ++++--- res/values/strings_hi.arb | 7 ++++--- res/values/strings_hr.arb | 7 ++++--- res/values/strings_id.arb | 7 ++++--- res/values/strings_it.arb | 7 ++++--- res/values/strings_ja.arb | 7 ++++--- res/values/strings_ko.arb | 9 +++++---- res/values/strings_my.arb | 7 ++++--- res/values/strings_nl.arb | 7 ++++--- res/values/strings_pl.arb | 7 ++++--- res/values/strings_pt.arb | 7 ++++--- res/values/strings_ru.arb | 7 ++++--- res/values/strings_th.arb | 7 ++++--- res/values/strings_tl.arb | 7 ++++--- res/values/strings_tr.arb | 7 ++++--- res/values/strings_uk.arb | 7 ++++--- res/values/strings_ur.arb | 7 ++++--- res/values/strings_yo.arb | 7 ++++--- res/values/strings_zh.arb | 7 ++++--- 31 files changed, 139 insertions(+), 100 deletions(-) create mode 100644 lib/themes/cake_dark_theme.dart delete mode 100644 lib/themes/purple_dark_theme.dart diff --git a/lib/palette.dart b/lib/palette.dart index 6681888c8..eb0ff50e9 100644 --- a/lib/palette.dart +++ b/lib/palette.dart @@ -100,4 +100,6 @@ class PaletteDark { static const Color moneroCard = Color.fromRGBO(20, 21, 24, 1.0); static const Color red = Color.fromRGBO(195, 0, 0, 1.0); static const Color darkPurple = Color.fromRGBO(109, 14, 210, 1.0); + static const Color cakeBlue = Color.fromRGBO(0, 184, 250, 1.0); + static const Color darkBlue = Color.fromRGBO(0, 123, 168, 1.0); } diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 488049656..fe6c98826 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -792,7 +792,7 @@ abstract class SettingsStoreBase with Store { ExchangeApiMode.enabled.raw); final savedTheme = initialTheme ?? ThemeList.deserialize( - raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? (isMoneroOnly ? ThemeList.moneroDarkTheme.raw : ThemeList.darkTheme.raw)); + raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? (isMoneroOnly ? ThemeList.moneroDarkTheme.raw : ThemeList.cakeDarkTheme.raw)); final actionListDisplayMode = ObservableList(); actionListDisplayMode.addAll(deserializeActionlistDisplayModes( sharedPreferences.getInt(PreferencesKey.displayActionListModeKey) ?? defaultActionsMode)); @@ -1151,7 +1151,7 @@ abstract class SettingsStoreBase with Store { raw: sharedPreferences.getInt(PreferencesKey.exchangeStatusKey) ?? ExchangeApiMode.enabled.raw); currentTheme = ThemeList.deserialize( - raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? (isMoneroOnly ? ThemeList.moneroDarkTheme.raw : ThemeList.darkTheme.raw)); + raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? (isMoneroOnly ? ThemeList.moneroDarkTheme.raw : ThemeList.cakeDarkTheme.raw)); actionlistDisplayMode = ObservableList(); actionlistDisplayMode.addAll(deserializeActionlistDisplayModes( sharedPreferences.getInt(PreferencesKey.displayActionListModeKey) ?? defaultActionsMode)); diff --git a/lib/themes/cake_dark_theme.dart b/lib/themes/cake_dark_theme.dart new file mode 100644 index 000000000..262ee1d64 --- /dev/null +++ b/lib/themes/cake_dark_theme.dart @@ -0,0 +1,24 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/themes/monero_dark_theme.dart'; +import 'package:flutter/material.dart'; +import 'package:cake_wallet/themes/extensions/menu_theme.dart'; + +class CakeDarkTheme extends MoneroDarkTheme { + CakeDarkTheme({required int raw}) : super(raw: raw); + + @override + String get title => S.current.cake_dark_theme; + @override + Color get primaryColor => PaletteDark.cakeBlue; + + @override + CakeMenuTheme get menuTheme => super.menuTheme.copyWith( + headerFirstGradientColor: PaletteDark.darkBlue, + headerSecondGradientColor: containerColor, + backgroundColor: containerColor, + subnameTextColor: Colors.grey, + dividerColor: colorScheme.secondaryContainer, + iconColor: Colors.white, + settingActionsIconColor: colorScheme.secondaryContainer); +} \ No newline at end of file diff --git a/lib/themes/purple_dark_theme.dart b/lib/themes/purple_dark_theme.dart deleted file mode 100644 index 04365de38..000000000 --- a/lib/themes/purple_dark_theme.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/palette.dart'; -import 'package:cake_wallet/themes/monero_dark_theme.dart'; -import 'package:flutter/material.dart'; - -class PurpleDarkTheme extends MoneroDarkTheme { - PurpleDarkTheme({required int raw}) : super(raw: raw); - - @override - String get title => S.current.purple_dark_theme; - @override - Color get primaryColor => PaletteDark.darkPurple; -} \ No newline at end of file diff --git a/lib/themes/theme_list.dart b/lib/themes/theme_list.dart index 6d0d44225..3ca7346b3 100644 --- a/lib/themes/theme_list.dart +++ b/lib/themes/theme_list.dart @@ -3,7 +3,7 @@ import 'package:cake_wallet/themes/dark_theme.dart'; import 'package:cake_wallet/themes/light_theme.dart'; import 'package:cake_wallet/themes/monero_light_theme.dart'; import 'package:cake_wallet/themes/monero_dark_theme.dart'; -import 'package:cake_wallet/themes/purple_dark_theme.dart'; +import 'package:cake_wallet/themes/cake_dark_theme.dart'; import 'package:cake_wallet/themes/matrix_green_theme.dart'; import 'package:cake_wallet/themes/bitcoin_dark_theme.dart'; import 'package:cake_wallet/themes/bitcoin_light_theme.dart'; @@ -14,12 +14,12 @@ import 'package:cake_wallet/themes/theme_base.dart'; class ThemeList { static final all = [ + cakeDarkTheme, darkTheme, lightTheme, - brightTheme, moneroDarkTheme, moneroLightTheme, - purpleDarkTheme, + brightTheme, bitcoinDarkTheme, bitcoinLightTheme, matrixGreenTheme, @@ -39,7 +39,7 @@ class ThemeList { static final highContrastTheme = HighContrastTheme(raw: 8); static final redLightTheme = RedLightTheme(raw: 9); static final redDarkTheme = RedDarkTheme(raw: 10); - static final purpleDarkTheme = PurpleDarkTheme(raw: 11); + static final cakeDarkTheme = CakeDarkTheme(raw: 11); static ThemeBase deserialize({required int raw}) { switch (raw) { @@ -66,7 +66,7 @@ class ThemeList { case 10: return redDarkTheme; case 11: - return purpleDarkTheme; + return cakeDarkTheme; default: throw Exception( 'Unexpected token raw: $raw for deserialization of ThemeBase'); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index af92cead4..a5ea72ce7 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -84,6 +84,7 @@ "buy_with": "اشتر بواسطة", "by_cake_pay": "عن طريق Cake Pay", "cake_2fa_preset": " كعكة 2FA مسبقا", + "cake_dark_theme": "موضوع الكعكة الظلام", "cake_pay_account_note": "قم بالتسجيل باستخدام عنوان بريد إلكتروني فقط لمشاهدة البطاقات وشرائها. حتى أن بعضها متوفر بسعر مخفض!", "cake_pay_learn_more": "شراء واسترداد بطاقات الهدايا على الفور في التطبيق!\nاسحب من اليسار إلى اليمين لمعرفة المزيد.", "cake_pay_subtitle": "شراء بطاقات هدايا مخفضة السعر (الولايات المتحدة فقط)", @@ -732,6 +733,7 @@ "view_key_private": "مفتاح العرض (خاص)", "view_key_public": "مفتاح العرض (عام)", "view_transaction_on": "عرض العملية على", + "waitFewSecondForTxUpdate": "ﺕﻼﻣﺎﻌﻤﻟﺍ ﻞﺠﺳ ﻲﻓ ﺔﻠﻣﺎﻌﻤﻟﺍ ﺲﻜﻌﻨﺗ ﻰﺘﺣ ﻥﺍﻮﺛ ﻊﻀﺒﻟ ﺭﺎﻈﺘﻧﻻﺍ ﻰﺟﺮﻳ", "wallet_keys": "سييد المحفظة / المفاتيح", "wallet_list_create_new_wallet": "إنشاء محفظة جديدة", "wallet_list_edit_wallet": "تحرير المحفظة", @@ -782,6 +784,5 @@ "you_pay": "انت تدفع", "you_will_get": "حول الى", "you_will_send": "تحويل من", - "yy": "YY", - "waitFewSecondForTxUpdate": "ﺕﻼﻣﺎﻌﻤﻟﺍ ﻞﺠﺳ ﻲﻓ ﺔﻠﻣﺎﻌﻤﻟﺍ ﺲﻜﻌﻨﺗ ﻰﺘﺣ ﻥﺍﻮﺛ ﻊﻀﺒﻟ ﺭﺎﻈﺘﻧﻻﺍ ﻰﺟﺮﻳ" -} + "yy": "YY" +} \ No newline at end of file diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 9f46ac2f4..a42460619 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -84,6 +84,7 @@ "buy_with": "Купуване чрез", "by_cake_pay": "от Cake Pay", "cake_2fa_preset": "Торта 2FA Preset", + "cake_dark_theme": "Торта тъмна тема", "cake_pay_account_note": "Регистрайте се само с един имейл, за да виждате и купувате карти. За някои има дори и отстъпка!", "cake_pay_learn_more": "Купете и използвайте гифткарти директно в приложението!\nПлъзнете отляво надясно, за да научите още.", "cake_pay_subtitle": "Купете гифткарти на намалени цени (само за САЩ)", @@ -732,6 +733,7 @@ "view_key_private": "View key (таен)", "view_key_public": "View key (публичен)", "view_transaction_on": "Вижте транзакция на ", + "waitFewSecondForTxUpdate": "Моля, изчакайте няколко секунди, докато транзакцията се отрази в историята на транзакциите", "wallet_keys": "Seed/keys на портфейла", "wallet_list_create_new_wallet": "Създаване на нов портфейл", "wallet_list_edit_wallet": "Редактиране на портфейла", @@ -782,6 +784,5 @@ "you_pay": "Вие плащате", "you_will_get": "Обръщане в", "you_will_send": "Обръщане от", - "yy": "гг", - "waitFewSecondForTxUpdate": "Моля, изчакайте няколко секунди, докато транзакцията се отрази в историята на транзакциите" -} + "yy": "гг" +} \ No newline at end of file diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index f47c7acb3..8970d394a 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -84,6 +84,7 @@ "buy_with": "Nakoupit pomocí", "by_cake_pay": "od Cake Pay", "cake_2fa_preset": "Předvolba Cake 2FA", + "cake_dark_theme": "Dort tmavé téma", "cake_pay_account_note": "Přihlaste se svou e-mailovou adresou pro zobrazení a nákup karet. Některé jsou dostupné ve slevě!", "cake_pay_learn_more": "Okamžitý nákup a uplatnění dárkových karet v aplikaci!\nPřejeďte prstem zleva doprava pro další informace.", "cake_pay_subtitle": "Kupte si zlevněné dárkové karty (pouze USA)", @@ -732,6 +733,7 @@ "view_key_private": "Klíč pro zobrazení (soukromý)", "view_key_public": "Klíč pro zobrazení (veřejný)", "view_transaction_on": "Zobrazit transakci na ", + "waitFewSecondForTxUpdate": "Počkejte několik sekund, než se transakce projeví v historii transakcí", "wallet_keys": "Seed/klíče peněženky", "wallet_list_create_new_wallet": "Vytvořit novou peněženku", "wallet_list_edit_wallet": "Upravit peněženku", @@ -782,6 +784,5 @@ "you_pay": "Zaplatíte", "you_will_get": "Směnit na", "you_will_send": "Směnit z", - "yy": "YY", - "waitFewSecondForTxUpdate": "Počkejte několik sekund, než se transakce projeví v historii transakcí" -} + "yy": "YY" +} \ No newline at end of file diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 338112022..93d421061 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -84,6 +84,7 @@ "buy_with": "Kaufen mit", "by_cake_pay": "von Cake Pay", "cake_2fa_preset": "Kuchen 2FA-Voreinstellung", + "cake_dark_theme": "Cake Dark Thema", "cake_pay_account_note": "Melden Sie sich nur mit einer E-Mail-Adresse an, um Karten anzuzeigen und zu kaufen. Einige sind sogar mit Rabatt erhältlich!", "cake_pay_learn_more": "Kaufen und lösen Sie Geschenkkarten sofort in der App ein!\nWischen Sie von links nach rechts, um mehr zu erfahren.", "cake_pay_subtitle": "Kaufen Sie ermäßigte Geschenkkarten (nur USA)", @@ -409,8 +410,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", @@ -734,6 +735,7 @@ "view_key_private": "View Key (geheim)", "view_key_public": "View Key (öffentlich)", "view_transaction_on": "Anzeigen der Transaktion auf ", + "waitFewSecondForTxUpdate": "Bitte warten Sie einige Sekunden, bis die Transaktion im Transaktionsverlauf angezeigt wird", "waiting_payment_confirmation": "Warte auf Zahlungsbestätigung", "wallet_keys": "Wallet-Seed/-Schlüssel", "wallet_list_create_new_wallet": "Neue Wallet erstellen", @@ -785,6 +787,5 @@ "you_pay": "Sie bezahlen", "you_will_get": "Konvertieren zu", "you_will_send": "Konvertieren von", - "yy": "YY", - "waitFewSecondForTxUpdate": "Bitte warten Sie einige Sekunden, bis die Transaktion im Transaktionsverlauf angezeigt wird" -} + "yy": "YY" +} \ No newline at end of file diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 86dc6518d..4ccade317 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -84,6 +84,7 @@ "buy_with": "Buy with", "by_cake_pay": "by Cake Pay", "cake_2fa_preset": "Cake 2FA Preset", + "cake_dark_theme": "Cake Dark Theme", "cake_pay_account_note": "Sign up with just an email address to see and purchase cards. Some are even available at a discount!", "cake_pay_learn_more": "Instantly purchase and redeem gift cards in the app!\nSwipe left to right to learn more.", "cake_pay_subtitle": "Buy discounted gift cards (USA only)", @@ -732,6 +733,7 @@ "view_key_private": "View key (private)", "view_key_public": "View key (public)", "view_transaction_on": "View Transaction on ", + "waitFewSecondForTxUpdate": "Kindly wait for a few seconds for transaction to reflect in transactions history", "wallet_keys": "Wallet seed/keys", "wallet_list_create_new_wallet": "Create New Wallet", "wallet_list_edit_wallet": "Edit wallet", @@ -782,6 +784,5 @@ "you_pay": "You Pay", "you_will_get": "Convert to", "you_will_send": "Convert from", - "yy": "YY", - "waitFewSecondForTxUpdate": "Kindly wait for a few seconds for transaction to reflect in transactions history" -} + "yy": "YY" +} \ No newline at end of file diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 09ad9948b..611f3bd35 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -84,6 +84,7 @@ "buy_with": "Compra con", "by_cake_pay": "por Cake Pay", "cake_2fa_preset": "Pastel 2FA preestablecido", + "cake_dark_theme": "Tema oscuro del pastel", "cake_pay_account_note": "Regístrese con solo una dirección de correo electrónico para ver y comprar tarjetas. ¡Algunas incluso están disponibles con descuento!", "cake_pay_learn_more": "¡Compre y canjee tarjetas de regalo al instante en la aplicación!\nDeslice el dedo de izquierda a derecha para obtener más información.", "cake_pay_subtitle": "Compre tarjetas de regalo con descuento (solo EE. UU.)", @@ -733,6 +734,7 @@ "view_key_private": "View clave (privado)", "view_key_public": "View clave (público)", "view_transaction_on": "View Transaction on ", + "waitFewSecondForTxUpdate": "Espere unos segundos para que la transacción se refleje en el historial de transacciones.", "wallet_keys": "Billetera semilla/claves", "wallet_list_create_new_wallet": "Crear nueva billetera", "wallet_list_edit_wallet": "Editar billetera", @@ -783,6 +785,5 @@ "you_pay": "Tú pagas", "you_will_get": "Convertir a", "you_will_send": "Convertir de", - "yy": "YY", - "waitFewSecondForTxUpdate": "Espere unos segundos para que la transacción se refleje en el historial de transacciones." -} + "yy": "YY" +} \ No newline at end of file diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index e552dfafa..f00a85310 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -84,6 +84,7 @@ "buy_with": "Acheter avec", "by_cake_pay": "par Cake Pay", "cake_2fa_preset": "Cake 2FA prédéfini", + "cake_dark_theme": "Thème sombre du gâteau", "cake_pay_account_note": "Inscrivez-vous avec juste une adresse e-mail pour voir et acheter des cartes. Certaines sont même disponibles à prix réduit !", "cake_pay_learn_more": "Achetez et utilisez instantanément des cartes-cadeaux dans l'application !\nBalayer de gauche à droite pour en savoir plus.", "cake_pay_subtitle": "Achetez des cartes-cadeaux à prix réduit (États-Unis uniquement)", @@ -732,6 +733,7 @@ "view_key_private": "Clef d'audit (view key) (privée)", "view_key_public": "Clef d'audit (view key) (publique)", "view_transaction_on": "Voir la Transaction sur ", + "waitFewSecondForTxUpdate": "Veuillez attendre quelques secondes pour que la transaction soit reflétée dans l'historique des transactions.", "wallet_keys": "Phrase secrète (seed)/Clefs du portefeuille (wallet)", "wallet_list_create_new_wallet": "Créer un Nouveau Portefeuille (Wallet)", "wallet_list_edit_wallet": "Modifier le portefeuille", @@ -782,6 +784,5 @@ "you_pay": "Vous payez", "you_will_get": "Convertir vers", "you_will_send": "Convertir depuis", - "yy": "AA", - "waitFewSecondForTxUpdate": "Veuillez attendre quelques secondes pour que la transaction soit reflétée dans l'historique des transactions." -} + "yy": "AA" +} \ No newline at end of file diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 40f6b2857..ab314af7f 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -84,6 +84,7 @@ "buy_with": "Saya da", "by_cake_pay": "da Cake Pay", "cake_2fa_preset": "Cake 2FA saiti", + "cake_dark_theme": "Cake Dark Jigo", "cake_pay_account_note": "Yi rajista tare da adireshin imel kawai don gani da siyan katunan. Wasu ma suna samuwa a rangwame!", "cake_pay_learn_more": "Nan take siya ku kwaso katunan kyaututtuka a cikin app!\nTake hagu zuwa dama don ƙarin koyo.", "cake_pay_subtitle": "Sayi katunan kyauta masu rahusa (Amurka kawai)", @@ -734,6 +735,7 @@ "view_key_private": "Duba maɓallin (maɓallin kalmar sirri)", "view_key_public": "Maɓallin Duba (maɓallin jama'a)", "view_transaction_on": "Dubo aikace-aikacen akan", + "waitFewSecondForTxUpdate": "Da fatan za a jira ƴan daƙiƙa don ciniki don yin tunani a tarihin ma'amala", "wallet_keys": "Iri/maɓalli na walat", "wallet_list_create_new_wallet": "Ƙirƙiri Sabon Wallet", "wallet_list_edit_wallet": "Gyara walat", @@ -784,6 +786,5 @@ "you_pay": "Ka Bayar", "you_will_get": "Maida zuwa", "you_will_send": "Maida daga", - "yy": "YY", - "waitFewSecondForTxUpdate": "Da fatan za a jira ƴan daƙiƙa don ciniki don yin tunani a tarihin ma'amala" -} + "yy": "YY" +} \ No newline at end of file diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index d35a5f716..da7d97c46 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -84,6 +84,7 @@ "buy_with": "के साथ खरीदें", "by_cake_pay": "केकपे द्वारा", "cake_2fa_preset": "केक 2एफए प्रीसेट", + "cake_dark_theme": "केक डार्क थीम", "cake_pay_account_note": "कार्ड देखने और खरीदने के लिए केवल एक ईमेल पते के साथ साइन अप करें। कुछ छूट पर भी उपलब्ध हैं!", "cake_pay_learn_more": "ऐप में उपहार कार्ड तुरंत खरीदें और रिडीम करें!\nअधिक जानने के लिए बाएं से दाएं स्वाइप करें।", "cake_pay_subtitle": "रियायती उपहार कार्ड खरीदें (केवल यूएसए)", @@ -734,6 +735,7 @@ "view_key_private": "कुंजी देखें(निजी)", "view_key_public": "कुंजी देखें (जनता)", "view_transaction_on": "View Transaction on ", + "waitFewSecondForTxUpdate": "लेन-देन इतिहास में लेन-देन प्रतिबिंबित होने के लिए कृपया कुछ सेकंड प्रतीक्षा करें", "wallet_keys": "बटुआ बीज / चाबियाँ", "wallet_list_create_new_wallet": "नया बटुआ बनाएँ", "wallet_list_edit_wallet": "बटुआ संपादित करें", @@ -784,6 +786,5 @@ "you_pay": "आप भुगतान करते हैं", "you_will_get": "में बदलें", "you_will_send": "से रूपांतरित करें", - "yy": "वाईवाई", - "waitFewSecondForTxUpdate": "लेन-देन इतिहास में लेन-देन प्रतिबिंबित होने के लिए कृपया कुछ सेकंड प्रतीक्षा करें" -} + "yy": "वाईवाई" +} \ No newline at end of file diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index c41310441..22b486a1c 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -84,6 +84,7 @@ "buy_with": "Kupite s", "by_cake_pay": "od Cake Paya", "cake_2fa_preset": "Cake 2FA Preset", + "cake_dark_theme": "TOKA DARKA TEMA", "cake_pay_account_note": "Prijavite se samo s adresom e-pošte da biste vidjeli i kupili kartice. Neke su čak dostupne uz popust!", "cake_pay_learn_more": "Azonnal vásárolhat és válthat be ajándékutalványokat az alkalmazásban!\nTovábbi információért csúsztassa balról jobbra az ujját.", "cake_pay_subtitle": "Kupite darovne kartice s popustom (samo SAD)", @@ -732,6 +733,7 @@ "view_key_private": "View key (privatni)", "view_key_public": "View key (javni)", "view_transaction_on": "View Transaction on ", + "waitFewSecondForTxUpdate": "Pričekajte nekoliko sekundi da se transakcija prikaže u povijesti transakcija", "wallet_keys": "Pristupni izraz/ključ novčanika", "wallet_list_create_new_wallet": "Izradi novi novčanik", "wallet_list_edit_wallet": "Uredi novčanik", @@ -782,6 +784,5 @@ "you_pay": "Vi plaćate", "you_will_get": "Razmijeni u", "you_will_send": "Razmijeni iz", - "yy": "GG", - "waitFewSecondForTxUpdate": "Pričekajte nekoliko sekundi da se transakcija prikaže u povijesti transakcija" -} + "yy": "GG" +} \ No newline at end of file diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index a9b9b50b3..a2f3ed017 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -84,6 +84,7 @@ "buy_with": "Beli dengan", "by_cake_pay": "oleh Cake Pay", "cake_2fa_preset": "Preset Kue 2FA", + "cake_dark_theme": "Tema Kue Gelap", "cake_pay_account_note": "Daftar hanya dengan alamat email untuk melihat dan membeli kartu. Beberapa di antaranya bahkan tersedia dengan diskon!", "cake_pay_learn_more": "Beli dan tukar kartu hadiah secara instan di aplikasi!\nGeser ke kanan untuk informasi lebih lanjut.", "cake_pay_subtitle": "Beli kartu hadiah dengan harga diskon (hanya USA)", @@ -735,6 +736,7 @@ "view_key_private": "Kunci tampilan (privat)", "view_key_public": "Kunci tampilan (publik)", "view_transaction_on": "Lihat Transaksi di ", + "waitFewSecondForTxUpdate": "Mohon tunggu beberapa detik hingga transaksi terlihat di riwayat transaksi", "wallet_keys": "Seed/kunci dompet", "wallet_list_create_new_wallet": "Buat Dompet Baru", "wallet_list_edit_wallet": "Edit dompet", @@ -785,6 +787,5 @@ "you_pay": "Anda Membayar", "you_will_get": "Konversi ke", "you_will_send": "Konversi dari", - "yy": "YY", - "waitFewSecondForTxUpdate": "Mohon tunggu beberapa detik hingga transaksi terlihat di riwayat transaksi" -} + "yy": "YY" +} \ No newline at end of file diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 9682e3d7f..015b63d47 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -84,6 +84,7 @@ "buy_with": "Acquista con", "by_cake_pay": "da Cake Pay", "cake_2fa_preset": "Torta 2FA Preset", + "cake_dark_theme": "Tema oscuro della torta", "cake_pay_account_note": "Iscriviti con solo un indirizzo email per vedere e acquistare le carte. Alcune sono anche disponibili con uno sconto!", "cake_pay_learn_more": "Acquista e riscatta istantaneamente carte regalo nell'app!\nScorri da sinistra a destra per saperne di più.", "cake_pay_subtitle": "Acquista buoni regalo scontati (solo USA)", @@ -734,6 +735,7 @@ "view_key_private": "Chiave di visualizzazione (privata)", "view_key_public": "Chiave di visualizzazione (pubblica)", "view_transaction_on": "View Transaction on ", + "waitFewSecondForTxUpdate": "Attendi qualche secondo affinché la transazione venga riflessa nella cronologia delle transazioni", "waiting_payment_confirmation": "In attesa di conferma del pagamento", "wallet_keys": "Seme Portafoglio /chiavi", "wallet_list_create_new_wallet": "Crea Nuovo Portafoglio", @@ -785,6 +787,5 @@ "you_pay": "Tu paghi", "you_will_get": "Converti a", "you_will_send": "Conveti da", - "yy": "YY", - "waitFewSecondForTxUpdate": "Attendi qualche secondo affinché la transazione venga riflessa nella cronologia delle transazioni" -} + "yy": "YY" +} \ No newline at end of file diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 0f4513eee..36ec1932b 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -84,6 +84,7 @@ "buy_with": "で購入", "by_cake_pay": "by Cake Pay", "cake_2fa_preset": "ケーキ 2FA プリセット", + "cake_dark_theme": "ケーキ暗いテーマ", "cake_pay_account_note": "メールアドレスだけでサインアップして、カードを表示して購入できます。割引価格で利用できるカードもあります!", "cake_pay_learn_more": "アプリですぐにギフトカードを購入して引き換えましょう!\n左から右にスワイプして詳細をご覧ください。", "cake_pay_subtitle": "割引ギフトカードを購入する (米国のみ)", @@ -733,6 +734,7 @@ "view_key_private": "ビューキー (プライベート)", "view_key_public": "ビューキー (パブリック)", "view_transaction_on": "View Transaction on ", + "waitFewSecondForTxUpdate": "取引履歴に取引が反映されるまで数秒お待ちください。", "wallet_keys": "ウォレットシード/キー", "wallet_list_create_new_wallet": "新しいウォレットを作成", "wallet_list_edit_wallet": "ウォレットを編集する", @@ -783,6 +785,5 @@ "you_pay": "あなたが支払う", "you_will_get": "に変換", "you_will_send": "から変換", - "yy": "YY", - "waitFewSecondForTxUpdate": "取引履歴に取引が反映されるまで数秒お待ちください。" -} + "yy": "YY" +} \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 2dd80cf5c..b51f42e8f 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -84,6 +84,7 @@ "buy_with": "구매", "by_cake_pay": "Cake Pay로", "cake_2fa_preset": "케이크 2FA 프리셋", + "cake_dark_theme": "케이크 다크 테마", "cake_pay_account_note": "이메일 주소로 가입하면 카드를 보고 구매할 수 있습니다. 일부는 할인된 가격으로 사용 가능합니다!", "cake_pay_learn_more": "앱에서 즉시 기프트 카드를 구매하고 사용하세요!\n자세히 알아보려면 왼쪽에서 오른쪽으로 스와이프하세요.", "cake_pay_subtitle": "할인된 기프트 카드 구매(미국만 해당)", @@ -409,8 +410,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": "다른 노드에 연결을 시도하십시오", @@ -733,6 +734,7 @@ "view_key_private": "키보기(은밀한)", "view_key_public": "키보기 (공공의)", "view_transaction_on": "View Transaction on ", + "waitFewSecondForTxUpdate": "거래 내역에 거래가 반영될 때까지 몇 초 정도 기다려 주세요.", "wallet_keys": "지갑 시드 / 키", "wallet_list_create_new_wallet": "새 월렛 만들기", "wallet_list_edit_wallet": "지갑 수정", @@ -784,6 +786,5 @@ "you_will_get": "로 변환하다", "you_will_send": "다음에서 변환", "YY": "YY", - "yy": "YY", - "waitFewSecondForTxUpdate": "거래 내역에 거래가 반영될 때까지 몇 초 정도 기다려 주세요." -} + "yy": "YY" +} \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 1bc338dcb..fe719a82b 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -84,6 +84,7 @@ "buy_with": "အတူဝယ်ပါ။", "by_cake_pay": "Cake Pay ဖြင့်", "cake_2fa_preset": "ကိတ်မုန့် 2FA ကြိုတင်သတ်မှတ်", + "cake_dark_theme": "ကိတ်မုန့် Dark Theme", "cake_pay_account_note": "ကတ်များကြည့်ရှုဝယ်ယူရန် အီးမေးလ်လိပ်စာတစ်ခုဖြင့် စာရင်းသွင်းပါ။ အချို့ကို လျှော့ဈေးဖြင့်ပင် ရနိုင်သည်။", "cake_pay_learn_more": "အက်ပ်ရှိ လက်ဆောင်ကတ်များကို ချက်ချင်းဝယ်ယူပြီး ကူပွန်ဖြင့် လဲလှယ်ပါ။\nပိုမိုလေ့လာရန် ဘယ်မှညာသို့ ပွတ်ဆွဲပါ။", "cake_pay_subtitle": "လျှော့စျေးလက်ဆောင်ကတ်များဝယ်ပါ (USA သာ)", @@ -732,6 +733,7 @@ "view_key_private": "သော့ကိုကြည့်ရန် (သီးသန့်)", "view_key_public": "သော့ကိုကြည့်ရန် (အများပြည်သူ)", "view_transaction_on": "ငွေလွှဲခြင်းကို ဖွင့်ကြည့်ပါ။", + "waitFewSecondForTxUpdate": "ငွေပေးငွေယူ မှတ်တမ်းတွင် ရောင်ပြန်ဟပ်ရန် စက္ကန့်အနည်းငယ်စောင့်ပါ။", "wallet_keys": "ပိုက်ဆံအိတ် အစေ့/သော့များ", "wallet_list_create_new_wallet": "Wallet အသစ်ဖန်တီးပါ။", "wallet_list_edit_wallet": "ပိုက်ဆံအိတ်ကို တည်းဖြတ်ပါ။", @@ -782,6 +784,5 @@ "you_pay": "သင်ပေးချေပါ။", "you_will_get": "သို့ပြောင်းပါ။", "you_will_send": "မှပြောင်းပါ။", - "yy": "YY", - "waitFewSecondForTxUpdate": "ငွေပေးငွေယူ မှတ်တမ်းတွင် ရောင်ပြန်ဟပ်ရန် စက္ကန့်အနည်းငယ်စောင့်ပါ။" -} + "yy": "YY" +} \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 56175b636..ed5054abe 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -84,6 +84,7 @@ "buy_with": "Koop met", "by_cake_pay": "door Cake Pay", "cake_2fa_preset": "Taart 2FA Voorinstelling", + "cake_dark_theme": "Cake Dark Theme", "cake_pay_account_note": "Meld u aan met alleen een e-mailadres om kaarten te bekijken en te kopen. Sommige zijn zelfs met korting verkrijgbaar!", "cake_pay_learn_more": "Koop en wissel cadeaubonnen direct in de app in!\nSwipe van links naar rechts voor meer informatie.", "cake_pay_subtitle": "Koop cadeaubonnen met korting (alleen VS)", @@ -732,6 +733,7 @@ "view_key_private": "Bekijk sleutel (privaat)", "view_key_public": "Bekijk sleutel (openbaar)", "view_transaction_on": "View Transaction on ", + "waitFewSecondForTxUpdate": "Wacht een paar seconden totdat de transactie wordt weergegeven in de transactiegeschiedenis", "waiting_payment_confirmation": "In afwachting van betalingsbevestiging", "wallet_keys": "Portemonnee zaad/sleutels", "wallet_list_create_new_wallet": "Maak een nieuwe portemonnee", @@ -783,6 +785,5 @@ "you_pay": "U betaalt", "you_will_get": "Converteren naar", "you_will_send": "Converteren van", - "yy": "JJ", - "waitFewSecondForTxUpdate": "Wacht een paar seconden totdat de transactie wordt weergegeven in de transactiegeschiedenis" -} + "yy": "JJ" +} \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index cbd1a7171..aa567799e 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -84,6 +84,7 @@ "buy_with": "Kup za pomocą", "by_cake_pay": "przez Cake Pay", "cake_2fa_preset": "Ciasto 2FA Preset", + "cake_dark_theme": "Cake Dark Temat", "cake_pay_account_note": "Zarejestruj się, używając tylko adresu e-mail, aby przeglądać i kupować karty. Niektóre są nawet dostępne ze zniżką!", "cake_pay_learn_more": "Kupuj i wykorzystuj karty podarunkowe od razu w aplikacji!\nPrzesuń od lewej do prawej, aby dowiedzieć się więcej.", "cake_pay_subtitle": "Kup karty upominkowe ze zniżką (tylko USA)", @@ -732,6 +733,7 @@ "view_key_private": "Prywatny Klucz Wglądu", "view_key_public": "Publiczny Klucz Wglądu", "view_transaction_on": "Zobacz transakcje na ", + "waitFewSecondForTxUpdate": "Poczekaj kilka sekund, aż transakcja zostanie odzwierciedlona w historii transakcji", "wallet_keys": "Klucze portfela", "wallet_list_create_new_wallet": "Utwórz nowy portfel", "wallet_list_edit_wallet": "Edytuj portfel", @@ -782,6 +784,5 @@ "you_pay": "Płacisz", "you_will_get": "Konwertuj na", "you_will_send": "Konwertuj z", - "yy": "RR", - "waitFewSecondForTxUpdate": "Poczekaj kilka sekund, aż transakcja zostanie odzwierciedlona w historii transakcji" -} + "yy": "RR" +} \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 7520f9327..b0aa7cab5 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -84,6 +84,7 @@ "buy_with": "Compre com", "by_cake_pay": "por Cake Pay", "cake_2fa_preset": "Predefinição de bolo 2FA", + "cake_dark_theme": "Bolo tema escuro", "cake_pay_account_note": "Inscreva-se com apenas um endereço de e-mail para ver e comprar cartões. Alguns estão até com desconto!", "cake_pay_learn_more": "Compre e resgate vales-presente instantaneamente no app!\nDeslize da esquerda para a direita para saber mais.", "cake_pay_subtitle": "Compre vales-presente com desconto (somente nos EUA)", @@ -734,6 +735,7 @@ "view_key_private": "Chave de visualização (privada)", "view_key_public": "Chave de visualização (pública)", "view_transaction_on": "View Transaction on ", + "waitFewSecondForTxUpdate": "Aguarde alguns segundos para que a transação seja refletida no histórico de transações", "waiting_payment_confirmation": "Aguardando confirmação de pagamento", "wallet_keys": "Semente/chaves da carteira", "wallet_list_create_new_wallet": "Criar nova carteira", @@ -785,6 +787,5 @@ "you_pay": "Você paga", "you_will_get": "Converter para", "you_will_send": "Converter de", - "yy": "aa", - "waitFewSecondForTxUpdate": "Aguarde alguns segundos para que a transação seja refletida no histórico de transações" -} + "yy": "aa" +} \ No newline at end of file diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index ee31e003a..bfb7b62d7 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -84,6 +84,7 @@ "buy_with": "Купить с помощью", "by_cake_pay": "от Cake Pay", "cake_2fa_preset": "Торт 2FA Preset", + "cake_dark_theme": "Тейт темная тема", "cake_pay_account_note": "Зарегистрируйтесь, указав только адрес электронной почты, чтобы просматривать и покупать карты. Некоторые даже доступны со скидкой!", "cake_pay_learn_more": "Мгновенно покупайте и используйте подарочные карты в приложении!\nПроведите по экрану слева направо, чтобы узнать больше.", "cake_pay_subtitle": "Покупайте подарочные карты со скидкой (только для США)", @@ -733,6 +734,7 @@ "view_key_private": "Приватный ключ просмотра", "view_key_public": "Публичный ключ просмотра", "view_transaction_on": "View Transaction on ", + "waitFewSecondForTxUpdate": "Пожалуйста, подождите несколько секунд, чтобы транзакция отразилась в истории транзакций.", "wallet_keys": "Мнемоническая фраза/ключи кошелька", "wallet_list_create_new_wallet": "Создать новый кошелёк", "wallet_list_edit_wallet": "Изменить кошелек", @@ -783,6 +785,5 @@ "you_pay": "Вы платите", "you_will_get": "Конвертировать в", "you_will_send": "Конвертировать из", - "yy": "ГГ", - "waitFewSecondForTxUpdate": "Пожалуйста, подождите несколько секунд, чтобы транзакция отразилась в истории транзакций." -} + "yy": "ГГ" +} \ No newline at end of file diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 3fddae170..5da17828f 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -84,6 +84,7 @@ "buy_with": "ซื้อด้วย", "by_cake_pay": "โดย Cake Pay", "cake_2fa_preset": "เค้ก 2FA ที่ตั้งไว้ล่วงหน้า", + "cake_dark_theme": "ธีมเค้กมืด", "cake_pay_account_note": "ลงทะเบียนด้วยอีเมลเพียงอย่างเดียวเพื่อดูและซื้อบัตร บางบัตรอาจมีส่วนลด!", "cake_pay_learn_more": "ซื้อและเบิกบัตรของขวัญในแอพพลิเคชันทันที!\nกระแทกขวาไปซ้ายเพื่อเรียนรู้เพิ่มเติม", "cake_pay_subtitle": "ซื้อบัตรของขวัญราคาถูก (สำหรับสหรัฐอเมริกาเท่านั้น)", @@ -732,6 +733,7 @@ "view_key_private": "คีย์มุมมอง (ส่วนตัว)", "view_key_public": "คีย์มุมมอง (สาธารณะ)", "view_transaction_on": "ดูการทำธุรกรรมบน ", + "waitFewSecondForTxUpdate": "กรุณารอสักครู่เพื่อให้ธุรกรรมปรากฏในประวัติการทำธุรกรรม", "wallet_keys": "ซีดของกระเป๋า/คีย์", "wallet_list_create_new_wallet": "สร้างกระเป๋าใหม่", "wallet_list_edit_wallet": "แก้ไขกระเป๋าสตางค์", @@ -782,6 +784,5 @@ "you_pay": "คุณจ่าย", "you_will_get": "แปลงเป็น", "you_will_send": "แปลงจาก", - "yy": "ปี", - "waitFewSecondForTxUpdate": "กรุณารอสักครู่เพื่อให้ธุรกรรมปรากฏในประวัติการทำธุรกรรม" -} + "yy": "ปี" +} \ No newline at end of file diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 6dc6d793a..e0a0b1eae 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -84,6 +84,7 @@ "buy_with": "Bumili ka", "by_cake_pay": "sa pamamagitan ng cake pay", "cake_2fa_preset": "Cake 2fa preset", + "cake_dark_theme": "Cake madilim na tema", "cake_pay_account_note": "Mag -sign up na may isang email address lamang upang makita at bumili ng mga kard. Ang ilan ay magagamit kahit sa isang diskwento!", "cake_pay_learn_more": "Agad na bumili at tubusin ang mga kard ng regalo sa app!\nMag -swipe pakaliwa sa kanan upang matuto nang higit pa.", "cake_pay_subtitle": "Bumili ng mga diskwento na gift card (USA lamang)", @@ -732,6 +733,7 @@ "view_key_private": "Tingnan ang Key (Pribado)", "view_key_public": "Tingnan ang Key (Publiko)", "view_transaction_on": "Tingnan ang transaksyon sa", + "waitFewSecondForTxUpdate": "Mangyaring maghintay ng ilang segundo para makita ang transaksyon sa history ng mga transaksyon", "wallet_keys": "Mga buto/susi ng pitaka", "wallet_list_create_new_wallet": "Lumikha ng bagong pitaka", "wallet_list_edit_wallet": "I -edit ang Wallet", @@ -782,6 +784,5 @@ "you_pay": "Magbabayad ka", "you_will_get": "Mag -convert sa", "you_will_send": "I -convert mula sa", - "yy": "YY", - "waitFewSecondForTxUpdate": "Mangyaring maghintay ng ilang segundo para makita ang transaksyon sa history ng mga transaksyon" -} + "yy": "YY" +} \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 585ef495a..c4d64305e 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -84,6 +84,7 @@ "buy_with": "Şunun ile al: ", "by_cake_pay": "Cake Pay tarafından", "cake_2fa_preset": "Kek 2FA Ön Ayarı", + "cake_dark_theme": "Kek Koyu Tema", "cake_pay_account_note": "Kartları görmek ve satın almak için sadece bir e-posta adresiyle kaydolun. Hatta bazıları indirimli olarak bile mevcut!", "cake_pay_learn_more": "Uygulamada anında hediye kartları satın alın ve harcayın!\nDaha fazla öğrenmek için soldan sağa kaydır.", "cake_pay_subtitle": "İndirimli hediye kartları satın alın (yalnızca ABD)", @@ -732,6 +733,7 @@ "view_key_private": "İzleme anahtarı (özel)", "view_key_public": "İzleme anahtarı (genel)", "view_transaction_on": "İşlemi şurada görüntüle ", + "waitFewSecondForTxUpdate": "İşlemin işlem geçmişine yansıması için lütfen birkaç saniye bekleyin", "wallet_keys": "Cüzdan tohumu/anahtarları", "wallet_list_create_new_wallet": "Yeni Cüzdan Oluştur", "wallet_list_edit_wallet": "Cüzdanı düzenle", @@ -782,6 +784,5 @@ "you_pay": "Şu kadar ödeyeceksin: ", "you_will_get": "Biçimine dönüştür:", "you_will_send": "Biçiminden dönüştür:", - "yy": "YY", - "waitFewSecondForTxUpdate": "İşlemin işlem geçmişine yansıması için lütfen birkaç saniye bekleyin" -} + "yy": "YY" +} \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index a22fa8fb1..59371cdbe 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -84,6 +84,7 @@ "buy_with": "Купити за допомогою", "by_cake_pay": "від Cake Pay", "cake_2fa_preset": "Торт 2FA Preset", + "cake_dark_theme": "Темна тема торта", "cake_pay_account_note": "Зареєструйтеся, використовуючи лише адресу електронної пошти, щоб переглядати та купувати картки. Деякі навіть доступні зі знижкою!", "cake_pay_learn_more": "Миттєво купуйте та активуйте подарункові картки в додатку!\nПроведіть пальцем зліва направо, щоб дізнатися більше.", "cake_pay_subtitle": "Купуйте подарункові картки зі знижкою (тільки для США)", @@ -733,6 +734,7 @@ "view_key_private": "Приватний ключ перегляду", "view_key_public": "Публічний ключ перегляду", "view_transaction_on": "View Transaction on ", + "waitFewSecondForTxUpdate": "Будь ласка, зачекайте кілька секунд, поки транзакція відобразиться в історії транзакцій", "wallet_keys": "Мнемонічна фраза/ключі гаманця", "wallet_list_create_new_wallet": "Створити новий гаманець", "wallet_list_edit_wallet": "Редагувати гаманець", @@ -783,6 +785,5 @@ "you_pay": "Ви платите", "you_will_get": "Конвертувати в", "you_will_send": "Конвертувати з", - "yy": "YY", - "waitFewSecondForTxUpdate": "Будь ласка, зачекайте кілька секунд, поки транзакція відобразиться в історії транзакцій" -} + "yy": "YY" +} \ No newline at end of file diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 35e17feac..73b758561 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -84,6 +84,7 @@ "buy_with": "کے ساتھ خریدیں۔", "by_cake_pay": "Cake پے کے ذریعے", "cake_2fa_preset": "کیک 2FA پیش سیٹ", + "cake_dark_theme": "کیک ڈارک تھیم", "cake_pay_account_note": "کارڈز دیکھنے اور خریدنے کے لیے صرف ایک ای میل ایڈریس کے ساتھ سائن اپ کریں۔ کچھ رعایت پر بھی دستیاب ہیں!", "cake_pay_learn_more": "ایپ میں فوری طور پر گفٹ کارڈز خریدیں اور بھنائیں!\\nمزید جاننے کے لیے بائیں سے دائیں سوائپ کریں۔", "cake_pay_subtitle": "رعایتی گفٹ کارڈز خریدیں (صرف امریکہ)", @@ -734,6 +735,7 @@ "view_key_private": "کلید دیکھیں (نجی)", "view_key_public": "کلید دیکھیں (عوامی)", "view_transaction_on": "لین دین دیکھیں آن", + "waitFewSecondForTxUpdate": "۔ﮟﯾﺮﮐ ﺭﺎﻈﺘﻧﺍ ﺎﮐ ﮉﻨﮑﯿﺳ ﺪﻨﭼ ﻡﺮﮐ ﮦﺍﺮﺑ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﯽﺳﺎﮑﻋ ﯽﮐ ﻦﯾﺩ ﻦﯿﻟ ﮟﯿﻣ ﺦﯾﺭﺎﺗ ﯽﮐ ﻦ", "wallet_keys": "بٹوے کے بیج / چابیاں", "wallet_list_create_new_wallet": "نیا والیٹ بنائیں", "wallet_list_edit_wallet": "بٹوے میں ترمیم کریں۔", @@ -784,6 +786,5 @@ "you_pay": "تم ادا کرو", "you_will_get": "میں تبدیل کریں۔", "you_will_send": "سے تبدیل کریں۔", - "yy": "YY", - "waitFewSecondForTxUpdate": "۔ﮟﯾﺮﮐ ﺭﺎﻈﺘﻧﺍ ﺎﮐ ﮉﻨﮑﯿﺳ ﺪﻨﭼ ﻡﺮﮐ ﮦﺍﺮﺑ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﯽﺳﺎﮑﻋ ﯽﮐ ﻦﯾﺩ ﻦﯿﻟ ﮟﯿﻣ ﺦﯾﺭﺎﺗ ﯽﮐ ﻦ" -} + "yy": "YY" +} \ No newline at end of file diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 0f141ebdf..4ccf10ff6 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -84,6 +84,7 @@ "buy_with": "Rà pẹ̀lú", "by_cake_pay": "láti ọwọ́ Cake Pay", "cake_2fa_preset": "Cake 2FA Tito", + "cake_dark_theme": "Akara oyinbo dudu koko", "cake_pay_account_note": "Ẹ fi àdírẹ́sì ímeèlì nìkan forúkọ sílẹ̀ k'ẹ́ rí àti ra àwọn káàdì. Ẹ lè fi owó tó kéré jù ra àwọn káàdì kan!", "cake_pay_learn_more": "Láìpẹ́ ra àti lo àwọn káàdí ìrajà t'á lò nínú irú kan ìtajà nínú áàpù!\nẸ tẹ̀ òsì de ọ̀tún láti kọ́ jù.", "cake_pay_subtitle": "Ra àwọn káàdì ìrajà t'á lò nínú ìtajà kan fún owó tí kò pọ̀ (USA nìkan)", @@ -733,6 +734,7 @@ "view_key_private": "Kọ́kọ́rọ́ ìwò (àdáni)", "view_key_public": "Kọ́kọ́rọ́ ìwò (kò àdáni)", "view_transaction_on": "Wo pàṣípààrọ̀ lórí ", + "waitFewSecondForTxUpdate": "Fi inurere duro fun awọn iṣeju diẹ fun idunadura lati ṣe afihan ninu itan-akọọlẹ iṣowo", "wallet_keys": "Hóró/kọ́kọ́rọ́ àpamọ́wọ́", "wallet_list_create_new_wallet": "Ṣe àpamọ́wọ́ títun", "wallet_list_edit_wallet": "Ṣatunkọ apamọwọ", @@ -783,6 +785,5 @@ "you_pay": "Ẹ sàn", "you_will_get": "Ṣe pàṣípààrọ̀ sí", "you_will_send": "Ṣe pàṣípààrọ̀ láti", - "yy": "Ọd", - "waitFewSecondForTxUpdate": "Fi inurere duro fun awọn iṣeju diẹ fun idunadura lati ṣe afihan ninu itan-akọọlẹ iṣowo" -} + "yy": "Ọd" +} \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index ffea168a9..3cff27996 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -84,6 +84,7 @@ "buy_with": "一起购买", "by_cake_pay": "通过 Cake Pay", "cake_2fa_preset": "蛋糕 2FA 预设", + "cake_dark_theme": "蛋糕黑暗主题", "cake_pay_account_note": "只需使用電子郵件地址註冊即可查看和購買卡片。有些甚至可以打折!", "cake_pay_learn_more": "立即在应用中购买和兑换礼品卡!\n从左向右滑动以了解详情。", "cake_pay_subtitle": "购买打折礼品卡(仅限美国)", @@ -732,6 +733,7 @@ "view_key_private": "View 密钥(私钥)", "view_key_public": "View 密钥(公钥)", "view_transaction_on": "View Transaction on ", + "waitFewSecondForTxUpdate": "请等待几秒钟,交易才会反映在交易历史记录中", "wallet_keys": "钱包种子/密钥", "wallet_list_create_new_wallet": "创建新钱包", "wallet_list_edit_wallet": "编辑钱包", @@ -782,6 +784,5 @@ "you_pay": "你付钱", "you_will_get": "转换到", "you_will_send": "转换自", - "yy": "YY", - "waitFewSecondForTxUpdate": "请等待几秒钟,交易才会反映在交易历史记录中" -} + "yy": "YY" +} \ No newline at end of file From 10fd32fb2e167c57f34bb74c84c908188f631561 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 1 Mar 2024 21:38:48 +0200 Subject: [PATCH 124/241] Cw 586 display user twitter image in birdpay (#1315) * Update address_validator.dart * add twitter profile image * mastodon profile image * fix data types --- lib/core/address_validator.dart | 10 +- lib/entities/parse_address_from_domain.dart | 27 +++- lib/entities/parsed_address.dart | 67 +++++--- lib/mastodon/mastodon_user.dart | 5 +- .../widgets/extract_address_from_parsed.dart | 8 + lib/src/widgets/alert_with_one_action.dart | 12 +- lib/src/widgets/base_alert_dialog.dart | 148 ++++++++++++------ lib/twitter/twitter_api.dart | 2 +- lib/twitter/twitter_user.dart | 7 +- 9 files changed, 200 insertions(+), 86 deletions(-) diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 853762a1c..84fcb9e2e 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -270,11 +270,11 @@ class AddressValidator extends TextValidator { '|([^0-9a-zA-Z]|^)8[0-9a-zA-Z]{94}([^0-9a-zA-Z]|\$)' '|([^0-9a-zA-Z]|^)[0-9a-zA-Z]{106}([^0-9a-zA-Z]|\$)'; case CryptoCurrency.btc: - return '([^0-9a-zA-Z]|^)${P2pkhAddress.regex.pattern}|\$)' - '([^0-9a-zA-Z]|^)${P2shAddress.regex.pattern}|\$)' - '([^0-9a-zA-Z]|^)${P2wpkhAddress.regex.pattern}|\$)' - '([^0-9a-zA-Z]|^)${P2wshAddress.regex.pattern}|\$)' - '([^0-9a-zA-Z]|^)${P2trAddress.regex.pattern}|\$)'; + return '([^0-9a-zA-Z]|^)([1mn][a-km-zA-HJ-NP-Z1-9]{25,34})([^0-9a-zA-Z]|\$)' //P2pkhAddress type + '|([^0-9a-zA-Z]|^)([23][a-km-zA-HJ-NP-Z1-9]{25,34})([^0-9a-zA-Z]|\$)' //P2shAddress type + '|([^0-9a-zA-Z]|^)((bc|tb)1q[ac-hj-np-z02-9]{25,39})([^0-9a-zA-Z]|\$)' //P2wpkhAddress type + '|([^0-9a-zA-Z]|^)((bc|tb)1q[ac-hj-np-z02-9]{40,80})([^0-9a-zA-Z]|\$)' //P2wshAddress type + '|([^0-9a-zA-Z]|^)((bc|tb)1p([ac-hj-np-z02-9]{39}|[ac-hj-np-z02-9]{59}|[ac-hj-np-z02-9]{8,89}))([^0-9a-zA-Z]|\$)'; //P2trAddress type case CryptoCurrency.ltc: return '([^0-9a-zA-Z]|^)^L[a-zA-Z0-9]{26,33}([^0-9a-zA-Z]|\$)' '|([^0-9a-zA-Z]|^)[LM][a-km-zA-HJ-NP-Z1-9]{26,33}([^0-9a-zA-Z]|\$)' diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart index 52bcc495b..3ebc08c55 100644 --- a/lib/entities/parse_address_from_domain.dart +++ b/lib/entities/parse_address_from_domain.dart @@ -69,16 +69,20 @@ class AddressResolver { } - Future resolve(BuildContext context, String text, String ticker) async { + Future resolve(BuildContext context, String text, String ticker) async { try { if (text.startsWith('@') && !text.substring(1).contains('@')) { - if(settingsStore.lookupsTwitter) { + if (settingsStore.lookupsTwitter) { final formattedName = text.substring(1); final twitterUser = await TwitterApi.lookupUserByName(userName: formattedName); final addressFromBio = extractAddressByType( raw: twitterUser.description, type: CryptoCurrency.fromString(ticker)); if (addressFromBio != null) { - return ParsedAddress.fetchTwitterAddress(address: addressFromBio, name: text); + return ParsedAddress.fetchTwitterAddress( + address: addressFromBio, + name: text, + profileImageUrl: twitterUser.profileImageUrl, + profileName: twitterUser.name); } final pinnedTweet = twitterUser.pinnedTweet?.text; @@ -86,7 +90,11 @@ class AddressResolver { final addressFromPinnedTweet = extractAddressByType(raw: pinnedTweet, type: CryptoCurrency.fromString(ticker)); if (addressFromPinnedTweet != null) { - return ParsedAddress.fetchTwitterAddress(address: addressFromPinnedTweet, name: text); + return ParsedAddress.fetchTwitterAddress( + address: addressFromPinnedTweet, + name: text, + profileImageUrl: twitterUser.profileImageUrl, + profileName: twitterUser.name); } } } @@ -107,7 +115,11 @@ class AddressResolver { extractAddressByType(raw: mastodonUser.note, type: CryptoCurrency.fromString(ticker)); if (addressFromBio != null) { - return ParsedAddress.fetchMastodonAddress(address: addressFromBio, name: text); + return ParsedAddress.fetchMastodonAddress( + address: addressFromBio, + name: text, + profileImageUrl: mastodonUser.profileImageUrl, + profileName: mastodonUser.username); } else { final pinnedPosts = await MastodonAPI.getPinnedPosts(userId: mastodonUser.id, apiHost: hostName); @@ -119,7 +131,10 @@ class AddressResolver { if (addressFromPinnedPost != null) { return ParsedAddress.fetchMastodonAddress( - address: addressFromPinnedPost, name: text); + address: addressFromPinnedPost, + name: text, + profileImageUrl: mastodonUser.profileImageUrl, + profileName: mastodonUser.username); } } } diff --git a/lib/entities/parsed_address.dart b/lib/entities/parsed_address.dart index d414a827d..d87deb9e8 100644 --- a/lib/entities/parsed_address.dart +++ b/lib/entities/parsed_address.dart @@ -1,7 +1,6 @@ import 'package:cake_wallet/entities/openalias_record.dart'; import 'package:cake_wallet/entities/yat_record.dart'; - enum ParseFrom { unstoppableDomains, openAlias, @@ -20,36 +19,37 @@ class ParsedAddress { required this.addresses, this.name = '', this.description = '', + this.profileImageUrl = '', + this.profileName = '', this.parseFrom = ParseFrom.notParsed, }); factory ParsedAddress.fetchEmojiAddress({ List? addresses, required String name, - }){ - if (addresses?.isEmpty ?? true) { - return ParsedAddress( - addresses: [name], parseFrom: ParseFrom.yatRecord); - } - return ParsedAddress( - addresses: addresses!.map((e) => e.address).toList(), - name: name, - parseFrom: ParseFrom.yatRecord, - ); + }) { + if (addresses?.isEmpty ?? true) { + return ParsedAddress(addresses: [name], parseFrom: ParseFrom.yatRecord); + } + return ParsedAddress( + addresses: addresses!.map((e) => e.address).toList(), + name: name, + parseFrom: ParseFrom.yatRecord, + ); } factory ParsedAddress.fetchUnstoppableDomainAddress({ String? address, required String name, - }){ - if (address?.isEmpty ?? true) { - return ParsedAddress(addresses: [name]); - } - return ParsedAddress( - addresses: [address!], - name: name, - parseFrom: ParseFrom.unstoppableDomains, - ); + }) { + if (address?.isEmpty ?? true) { + return ParsedAddress(addresses: [name]); + } + return ParsedAddress( + addresses: [address!], + name: name, + parseFrom: ParseFrom.unstoppableDomains, + ); } factory ParsedAddress.fetchOpenAliasAddress( @@ -65,7 +65,7 @@ class ParsedAddress { ); } - factory ParsedAddress.fetchFioAddress({required String address, required String name}){ + factory ParsedAddress.fetchFioAddress({required String address, required String name}) { return ParsedAddress( addresses: [address], name: name, @@ -73,23 +73,37 @@ class ParsedAddress { ); } - factory ParsedAddress.fetchTwitterAddress({required String address, required String name}){ + factory ParsedAddress.fetchTwitterAddress( + {required String address, + required String name, + required String profileImageUrl, + required String profileName, + String? description}) { return ParsedAddress( addresses: [address], name: name, + description: description ?? '', + profileImageUrl: profileImageUrl, + profileName: profileName, parseFrom: ParseFrom.twitter, ); } - factory ParsedAddress.fetchMastodonAddress({required String address, required String name}){ + factory ParsedAddress.fetchMastodonAddress( + {required String address, + required String name, + required String profileImageUrl, + required String profileName}) { return ParsedAddress( addresses: [address], name: name, - parseFrom: ParseFrom.mastodon + parseFrom: ParseFrom.mastodon, + profileImageUrl: profileImageUrl, + profileName: profileName, ); } - factory ParsedAddress.fetchContactAddress({required String address, required String name}){ + factory ParsedAddress.fetchContactAddress({required String address, required String name}) { return ParsedAddress( addresses: [address], name: name, @@ -116,6 +130,7 @@ class ParsedAddress { final List addresses; final String name; final String description; + final String profileImageUrl; + final String profileName; final ParseFrom parseFrom; - } diff --git a/lib/mastodon/mastodon_user.dart b/lib/mastodon/mastodon_user.dart index f5a29f298..1832c083e 100644 --- a/lib/mastodon/mastodon_user.dart +++ b/lib/mastodon/mastodon_user.dart @@ -1,12 +1,14 @@ class MastodonUser { String id; String username; + String profileImageUrl; String acct; String note; MastodonUser({ required this.id, required this.username, + required this.profileImageUrl, required this.acct, required this.note, }); @@ -14,9 +16,10 @@ class MastodonUser { factory MastodonUser.fromJson(Map json) { return MastodonUser( id: json['id'] as String, - username: json['username'] as String, + username: json['username'] as String? ?? '', acct: json['acct'] as String, note: json['note'] as String, + profileImageUrl: json['avatar'] as String? ?? '' ); } } diff --git a/lib/src/screens/send/widgets/extract_address_from_parsed.dart b/lib/src/screens/send/widgets/extract_address_from_parsed.dart index bb09d4ca3..42e646d58 100644 --- a/lib/src/screens/send/widgets/extract_address_from_parsed.dart +++ b/lib/src/screens/send/widgets/extract_address_from_parsed.dart @@ -11,6 +11,8 @@ Future extractAddressFromParsed( var title = ''; var content = ''; var address = ''; + var profileImageUrl = ''; + var profileName = ''; switch (parsedAddress.parseFrom) { case ParseFrom.unstoppableDomains: @@ -37,11 +39,15 @@ Future extractAddressFromParsed( title = S.of(context).address_detected; content = S.of(context).extracted_address_content('${parsedAddress.name} (Twitter)'); address = parsedAddress.addresses.first; + profileImageUrl = parsedAddress.profileImageUrl; + profileName = parsedAddress.profileName; break; case ParseFrom.mastodon: title = S.of(context).address_detected; content = S.of(context).extracted_address_content('${parsedAddress.name} (Mastodon)'); address = parsedAddress.addresses.first; + profileImageUrl = parsedAddress.profileImageUrl; + profileName = parsedAddress.profileName; break; case ParseFrom.nostr: title = S.of(context).address_detected; @@ -95,6 +101,8 @@ Future extractAddressFromParsed( return AlertWithOneAction( alertTitle: title, + headerTitleText: profileName.isEmpty ? null : profileName, + headerImageProfileUrl: profileImageUrl.isEmpty ? null : profileImageUrl, alertContent: content, buttonText: S.of(context).ok, buttonAction: () => Navigator.of(context).pop()); diff --git a/lib/src/widgets/alert_with_one_action.dart b/lib/src/widgets/alert_with_one_action.dart index c06114f5b..7ad0ac1af 100644 --- a/lib/src/widgets/alert_with_one_action.dart +++ b/lib/src/widgets/alert_with_one_action.dart @@ -7,7 +7,9 @@ class AlertWithOneAction extends BaseAlertDialog { required this.alertContent, required this.buttonText, required this.buttonAction, - this.alertBarrierDismissible = true + this.alertBarrierDismissible = true, + this.headerTitleText, + this.headerImageProfileUrl }); final String alertTitle; @@ -15,6 +17,8 @@ class AlertWithOneAction extends BaseAlertDialog { final String buttonText; final VoidCallback buttonAction; final bool alertBarrierDismissible; + final String? headerTitleText; + final String? headerImageProfileUrl; @override String get titleText => alertTitle; @@ -25,6 +29,12 @@ class AlertWithOneAction extends BaseAlertDialog { @override bool get barrierDismissible => alertBarrierDismissible; + @override + String? get headerImageUrl => headerImageProfileUrl; + + @override + String? get headerText => headerTitleText; + @override Widget actionButtons(BuildContext context) { return Container( diff --git a/lib/src/widgets/base_alert_dialog.dart b/lib/src/widgets/base_alert_dialog.dart index 02a1f6ad0..e9ef522df 100644 --- a/lib/src/widgets/base_alert_dialog.dart +++ b/lib/src/widgets/base_alert_dialog.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/src/screens/receive/widgets/header_tile.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'dart:ui'; import 'package:cake_wallet/src/widgets/section_divider.dart'; @@ -5,19 +6,34 @@ import 'package:cake_wallet/themes/extensions/alert_theme.dart'; import 'package:flutter/material.dart'; class BaseAlertDialog extends StatelessWidget { + String? get headerText => ''; + String get titleText => ''; + String get contentText => ''; + String get leftActionButtonText => ''; + String get rightActionButtonText => ''; + bool get isDividerExists => false; + VoidCallback get actionLeft => () {}; + VoidCallback get actionRight => () {}; + bool get barrierDismissible => true; + Color? get leftActionButtonTextColor => null; + Color? get rightActionButtonTextColor => null; + Color? get leftActionButtonColor => null; + Color? get rightActionButtonColor => null; + String? get headerImageUrl => null; + Widget title(BuildContext context) { return Text( titleText, @@ -32,6 +48,23 @@ class BaseAlertDialog extends StatelessWidget { ); } + Widget headerTitle(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(top: 10.0), + child: Text( + headerText!, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 25, + fontFamily: 'Lato', + fontWeight: FontWeight.w600, + color: Theme.of(context).extension()!.titleColor, + decoration: TextDecoration.none, + ), + ), + ); + } + Widget content(BuildContext context) { return Text( contentText, @@ -48,17 +81,17 @@ class BaseAlertDialog extends StatelessWidget { Widget actionButtons(BuildContext context) { return Container( - height: 60, - child: Row( - mainAxisSize: MainAxisSize.max, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ + height: 60, + child: Row( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ Expanded( child: TextButton( onPressed: actionLeft, style: TextButton.styleFrom( - backgroundColor: leftActionButtonColor ?? - Theme.of(context).dialogBackgroundColor, + backgroundColor: + leftActionButtonColor ?? Theme.of(context).dialogBackgroundColor, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.zero))), child: Text( @@ -79,8 +112,8 @@ class BaseAlertDialog extends StatelessWidget { child: TextButton( onPressed: actionRight, style: TextButton.styleFrom( - backgroundColor: rightActionButtonColor ?? - Theme.of(context).dialogBackgroundColor, + backgroundColor: + rightActionButtonColor ?? Theme.of(context).dialogBackgroundColor, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.zero))), child: Text( @@ -90,8 +123,7 @@ class BaseAlertDialog extends StatelessWidget { fontSize: 15, fontFamily: 'Lato', fontWeight: FontWeight.w600, - color: rightActionButtonTextColor ?? - Theme.of(context).primaryColor, + color: rightActionButtonTextColor ?? Theme.of(context).primaryColor, decoration: TextDecoration.none, ), )), @@ -100,6 +132,24 @@ class BaseAlertDialog extends StatelessWidget { )); } + Widget headerImage(BuildContext context, String imageUrl) { + return Positioned( + top: -50, + left: 0, + right: 0, + child: CircleAvatar( + radius: 50, + backgroundColor: Colors.white, + child: ClipOval( + child: Image.network( + imageUrl, + fit: BoxFit.cover, + ), + ), + ), + ); + } + @override Widget build(BuildContext context) { return GestureDetector( @@ -109,43 +159,51 @@ class BaseAlertDialog extends StatelessWidget { child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 3.0, sigmaY: 3.0), child: Container( - decoration: BoxDecoration( - color: - Theme.of(context).extension()!.backdropColor), + decoration: + BoxDecoration(color: Theme.of(context).extension()!.backdropColor), child: Center( child: GestureDetector( onTap: () => null, - child: ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(30)), - child: Container( - width: 300, - color: Theme.of(context).dialogBackgroundColor, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Padding( - padding: EdgeInsets.fromLTRB(24, 20, 24, 0), - child: title(context), - ), - isDividerExists - ? Padding( - padding: EdgeInsets.only(top: 16, bottom: 8), - child: const HorizontalSectionDivider(), - ) - : Offstage(), - Padding( - padding: EdgeInsets.fromLTRB(24, 8, 24, 32), - child: content(context), - ) - ], - ), - const HorizontalSectionDivider(), - actionButtons(context) - ], - ), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + color: Theme.of(context).dialogBackgroundColor), + width: 300, + child: Stack( + clipBehavior: Clip.none, + children: [ + if (headerImageUrl != null) headerImage(context, headerImageUrl!), + Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (headerImageUrl != null) const SizedBox(height: 50), + Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + if (headerText != null) headerTitle(context), + Padding( + padding: EdgeInsets.fromLTRB(24, 20, 24, 0), + child: title(context), + ), + isDividerExists + ? Padding( + padding: EdgeInsets.only(top: 16, bottom: 8), + child: const HorizontalSectionDivider(), + ) + : Offstage(), + Padding( + padding: EdgeInsets.fromLTRB(24, 8, 24, 32), + child: content(context), + ) + ], + ), + const HorizontalSectionDivider(), + ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(30)), + child: actionButtons(context)) + ], + ), + ], ), ), ), diff --git a/lib/twitter/twitter_api.dart b/lib/twitter/twitter_api.dart index 24121c9c0..bf6298dae 100644 --- a/lib/twitter/twitter_api.dart +++ b/lib/twitter/twitter_api.dart @@ -12,7 +12,7 @@ class TwitterApi { static Future lookupUserByName({required String userName}) async { final queryParams = { - 'user.fields': 'description', + 'user.fields': 'description,profile_image_url', 'expansions': 'pinned_tweet_id', 'tweet.fields': 'note_tweet' }; diff --git a/lib/twitter/twitter_user.dart b/lib/twitter/twitter_user.dart index c0eb5431c..01db25684 100644 --- a/lib/twitter/twitter_user.dart +++ b/lib/twitter/twitter_user.dart @@ -4,20 +4,25 @@ class TwitterUser { required this.username, required this.name, required this.description, + required this.profileImageUrl, this.pinnedTweet}); final String id; final String username; final String name; final String description; + final String profileImageUrl; final Tweet? pinnedTweet; factory TwitterUser.fromJson(Map json, [Tweet? pinnedTweet]) { + final profileImageUrl = json['data']['profile_image_url'] as String? ?? ''; + final scaledProfileImageUrl = profileImageUrl.replaceFirst('normal', '200x200'); return TwitterUser( id: json['data']['id'] as String, - username: json['data']['username'] as String, + username: json['data']['username'] as String? ?? '', name: json['data']['name'] as String, description: json['data']['description'] as String? ?? '', + profileImageUrl: scaledProfileImageUrl, pinnedTweet: pinnedTweet, ); } From c7deeaea9b65330c5fe9894da3ee4f4ab9cd9d11 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Mon, 4 Mar 2024 19:32:10 +0200 Subject: [PATCH 125/241] New versions (#1312) * New versions Fix issues with Monero.com * Add sending for Solana tokens exchanges * Add default keyword for P2WPKH [skip ci] * chore: Switch solana commitment to confirmed to reduced blockhash expiration (#1313) * Modify test workflow to send arm64-v8a build only * Fix workflow build path * Remove unnecessary reverse of txId * Show case sensitive evm wallet address * Revert default Cake Theme add custom package id for test builds * Fix workflow script * Fix workflow * hash branch name * hash branch name * Update versions * Add user image to Nostr Add fetching address from text for tokens * Fix test app package id * fix: Solana message improvement (#1316) --------- Co-authored-by: Adegoke David <64401859+Blazebrain@users.noreply.github.com> --- .github/workflows/pr_test_build.yml | 28 +++++++--------- assets/text/Monerocom_Release_Notes.txt | 5 ++- assets/text/Release_Notes.txt | 5 ++- .../lib/bitcoin_receive_page_option.dart | 4 +-- cw_bitcoin/lib/electrum_wallet.dart | 14 ++------ cw_core/lib/crypto_currency.dart | 12 ++++++- cw_evm/lib/evm_chain_wallet.dart | 2 +- cw_solana/lib/solana_client.dart | 11 ++++--- ios/Podfile | 4 +-- ios/Podfile.lock | 24 +++++++------- ios/Runner.xcodeproj/project.pbxproj | 11 ++----- lib/bitcoin/cw_bitcoin.dart | 21 ++++++++++-- lib/core/address_validator.dart | 10 ++++++ lib/entities/parse_address_from_domain.dart | 33 +++++++++++-------- lib/entities/parsed_address.dart | 8 ++++- .../screens/dashboard/pages/address_page.dart | 21 +++--------- .../widgets/extract_address_from_parsed.dart | 2 ++ lib/src/widgets/base_alert_dialog.dart | 1 - lib/store/settings_store.dart | 12 +++++-- lib/twitter/twitter_api.dart | 31 ++++++++++------- .../exchange/exchange_trade_view_model.dart | 7 +++- macos/Flutter/GeneratedPluginRegistrant.swift | 2 +- macos/Podfile.lock | 14 ++++---- pubspec_base.yaml | 6 +++- scripts/android/app_env.sh | 6 ++-- scripts/ios/app_env.sh | 6 ++-- scripts/macos/app_env.sh | 8 ++--- tool/configure.dart | 16 +++++---- 28 files changed, 186 insertions(+), 138 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index b5fe24f18..4df215e13 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -104,17 +104,7 @@ jobs: - name: Build generated code run: | cd /opt/android/cake_wallet - cd cw_core && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. - cd cw_evm && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. - cd cw_monero && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. - cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. - cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. - cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. - cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. - cd cw_solana && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. - cd cw_ethereum && flutter pub get && cd .. - cd cw_polygon && flutter pub get && cd .. - flutter packages pub run build_runner build --delete-conflicting-outputs + ./model_generator.sh - name: Add secrets run: | @@ -159,12 +149,16 @@ jobs: echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> cw_solana/lib/.secrets.g.dart - name: Rename app - run: echo -e "id=com.cakewallet.test\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties + run: | + hash=`sha512sum <<<"${{ env.BRANCH_NAME }}"` + substring=${hash:0:15} + echo substring + echo -e "id=com.cakewallet.test_$(substring)\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties - name: Build run: | cd /opt/android/cake_wallet - flutter build apk --release + flutter build apk --release --split-per-abi # - name: Push to App Center # run: | @@ -181,21 +175,21 @@ jobs: - name: Rename apk file run: | - cd /opt/android/cake_wallet/build/app/outputs/apk/release + cd /opt/android/cake_wallet/build/app/outputs/flutter-apk mkdir test-apk - cp app-release.apk test-apk/${{env.BRANCH_NAME}}.apk + cp app-arm64-v8a-release.apk test-apk/${{env.BRANCH_NAME}}.apk - name: Upload Artifact uses: kittaakos/upload-artifact-as-is@v0 with: - path: /opt/android/cake_wallet/build/app/outputs/apk/release/test-apk/ + 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/apk/release/app-release.apk + 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 diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 7cf786332..732e58a18 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,3 +1,2 @@ -Improve wallet recovery and error tolerance -Enhance Background sync for Monero wallets -Bug fixes \ No newline at end of file +New themes +Bug fixes and enhancements \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index ac032e354..1c2ec154c 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,3 +1,6 @@ +Add Solana wallet Support ALL Bitcoin address types (Legacy, Segwit (both variants), Taproot) Enhance Sending/Receiving flow for Bitcoin -Improve fee calculations in Bitcoin \ No newline at end of file +Improve fee calculations in Bitcoin +New themes +Bug fixes and enhancements \ No newline at end of file diff --git a/cw_bitcoin/lib/bitcoin_receive_page_option.dart b/cw_bitcoin/lib/bitcoin_receive_page_option.dart index 2e246f532..2d2339a41 100644 --- a/cw_bitcoin/lib/bitcoin_receive_page_option.dart +++ b/cw_bitcoin/lib/bitcoin_receive_page_option.dart @@ -2,7 +2,7 @@ import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_core/receive_page_option.dart'; class BitcoinReceivePageOption implements ReceivePageOption { - static const p2wpkh = BitcoinReceivePageOption._('Segwit (P2WPKH)'); + static const p2wpkh = BitcoinReceivePageOption._('Segwit (P2WPKH) (Default)'); static const p2sh = BitcoinReceivePageOption._('Segwit-Compatible (P2SH)'); static const p2tr = BitcoinReceivePageOption._('Taproot (P2TR)'); static const p2wsh = BitcoinReceivePageOption._('Segwit (P2WSH)'); @@ -18,9 +18,9 @@ class BitcoinReceivePageOption implements ReceivePageOption { static const all = [ BitcoinReceivePageOption.p2wpkh, - BitcoinReceivePageOption.p2sh, BitcoinReceivePageOption.p2tr, BitcoinReceivePageOption.p2wsh, + BitcoinReceivePageOption.p2sh, BitcoinReceivePageOption.p2pkh ]; diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 873fe2977..c3f40a235 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -35,7 +35,6 @@ import 'package:cw_core/utils/file.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:flutter/foundation.dart'; -import 'package:hex/hex.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:rxdart/subjects.dart'; @@ -623,16 +622,9 @@ abstract class ElectrumWalletBase final ins = []; for (final vin in original.inputs) { - try { - final id = HEX.encode(HEX.decode(vin.txId).reversed.toList()); - final txHex = await electrumClient.getTransactionHex(hash: id); - final tx = bitcoin_base.BtcTransaction.fromRaw(txHex); - ins.add(tx); - } catch (_) { - ins.add(bitcoin_base.BtcTransaction.fromRaw( - await electrumClient.getTransactionHex(hash: vin.txId), - )); - } + final txHex = await electrumClient.getTransactionHex(hash: vin.txId); + final tx = bitcoin_base.BtcTransaction.fromRaw(txHex); + ins.add(tx); } return ElectrumTransactionBundle(original, diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index 67581ecb8..ce509015c 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -102,6 +102,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen CryptoCurrency.usdcEPoly, CryptoCurrency.kaspa, CryptoCurrency.digibyte, + CryptoCurrency.usdtSol, ]; static const havenCurrencies = [ @@ -246,7 +247,16 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen return CryptoCurrency._rawCurrencyMap[raw]!; } - static CryptoCurrency fromString(String name) { + // TODO: refactor this + static CryptoCurrency fromString(String name, {CryptoCurrency? walletCurrency}) { + try { + return CryptoCurrency.all.firstWhere((element) => + element.title.toLowerCase() == name && + (element.tag == null || + element.tag == walletCurrency?.title || + element.tag == walletCurrency?.tag)); + } catch (_) {} + if (CryptoCurrency._nameCurrencyMap[name.toLowerCase()] == null) { final s = 'Unexpected token: $name for CryptoCurrency fromString'; throw ArgumentError.value(name, 'name', s); diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart index ea19a8557..0fb282960 100644 --- a/cw_evm/lib/evm_chain_wallet.dart +++ b/cw_evm/lib/evm_chain_wallet.dart @@ -146,7 +146,7 @@ abstract class EVMChainWalletBase privateKey: _hexPrivateKey, password: _password, ); - walletAddresses.address = _evmChainPrivateKey.address.toString(); + walletAddresses.address = _evmChainPrivateKey.address.hexEip55; await save(); } diff --git a/cw_solana/lib/solana_client.dart b/cw_solana/lib/solana_client.dart index ececc56ba..ea4a9161a 100644 --- a/cw_solana/lib/solana_client.dart +++ b/cw_solana/lib/solana_client.dart @@ -263,7 +263,7 @@ class SolanaWalletClient { required Ed25519HDKeyPair ownerKeypair, List references = const [], }) async { - const commitment = Commitment.finalized; + const commitment = Commitment.confirmed; final latestBlockhash = await _client!.rpcClient.getLatestBlockhash(commitment: commitment).value; @@ -394,9 +394,7 @@ class SolanaWalletClient { funder: ownerKeypair, ); } catch (e) { - throw Exception( - 'Error while creating an associated token account for the recipient: ${e.toString()}', - ); + throw Exception('Insufficient lamports balance to complete this transaction'); } // Input by the user @@ -468,7 +466,10 @@ class SolanaWalletClient { required SignedTx signedTransaction, required Commitment commitment, }) async { - final signature = await _client!.rpcClient.sendTransaction(signedTransaction.encode()); + final signature = await _client!.rpcClient.sendTransaction( + signedTransaction.encode(), + preflightCommitment: commitment, + ); _client!.waitForSignatureStatus(signature, status: commitment); diff --git a/ios/Podfile b/ios/Podfile index 027d48ceb..00b5fd2df 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '11.0' +platform :ios, '12.0' source 'https://github.com/CocoaPods/Specs.git' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. @@ -44,7 +44,7 @@ post_install do |installer| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0' config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ '$(inherited)', diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 2545e90ce..4f3aea7ec 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -7,7 +7,7 @@ PODS: - connectivity_plus (0.0.1): - Flutter - ReachabilitySwift - - CryptoSwift (1.7.1) + - CryptoSwift (1.8.1) - cw_haven (0.0.1): - cw_haven/Boost (= 0.0.1) - cw_haven/Haven (= 0.0.1) @@ -132,9 +132,9 @@ PODS: - permission_handler_apple (9.1.1): - Flutter - ReachabilitySwift (5.0.0) - - SDWebImage (5.16.0): - - SDWebImage/Core (= 5.16.0) - - SDWebImage/Core (5.16.0) + - SDWebImage (5.18.11): + - SDWebImage/Core (= 5.18.11) + - SDWebImage/Core (5.18.11) - sensitive_clipboard (0.0.1): - Flutter - share_plus (0.0.1): @@ -142,9 +142,9 @@ PODS: - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS - - SwiftProtobuf (1.22.0) + - SwiftProtobuf (1.25.2) - SwiftyGif (5.4.4) - - Toast (4.0.0) + - Toast (4.1.0) - uni_links (0.0.1): - Flutter - UnstoppableDomainsResolution (4.0.0): @@ -262,8 +262,8 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0 BigInt: f668a80089607f521586bbe29513d708491ef2f7 - connectivity_plus: 413a8857dd5d9f1c399a39130850d02fe0feaf7e - CryptoSwift: d3d18dc357932f7e6d580689e065cf1f176007c1 + connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d + CryptoSwift: b9c701d6f5011df23794dbf7f2e480a77835d83d cw_haven: b3e54e1fbe7b8e6fda57a93206bc38f8e89b898a cw_monero: 4cf3b96f2da8e95e2ef7d6703dd4d2c509127b7d cw_shared_external: 2972d872b8917603478117c9957dfca611845a92 @@ -287,19 +287,19 @@ SPEC CHECKSUMS: path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 - SDWebImage: 2aea163b50bfcb569a2726b6a754c54a4506fcf6 + SDWebImage: a3ba0b8faac7228c3c8eadd1a55c9c9fe5e16457 sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986 share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 - SwiftProtobuf: 40bd808372cb8706108f22d28f8ab4a6b9bc6989 + SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1 SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f - Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 + Toast: ec33c32b8688982cecc6348adeae667c1b9938da uni_links: d97da20c7701486ba192624d99bffaaffcfc298a UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841 url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812 wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47 workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6 -PODFILE CHECKSUM: 09df1114e7c360f55770d35a79356bf5446e0100 +PODFILE CHECKSUM: fcb1b8418441a35b438585c9dd8374e722e6c6ca COCOAPODS: 1.12.1 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 1da5bc4bc..7a8b99b49 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -377,7 +377,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -523,7 +523,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -561,7 +561,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -607,9 +607,4 @@ /* End XCConfigurationList section */ }; rootObject = 97C146E61CF9000F007C117D /* Project object */; - SystemCapabilities = { - com.apple.BackgroundModes = { - enabled = 1; - }; - }; } diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index f9c20d45e..b36421608 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -181,11 +181,28 @@ class CWBitcoin extends Bitcoin { } @override - BitcoinReceivePageOption getSelectedAddressType(Object wallet) { + ReceivePageOption getSelectedAddressType(Object wallet) { final bitcoinWallet = wallet as ElectrumWallet; return BitcoinReceivePageOption.fromType(bitcoinWallet.walletAddresses.addressPageType); } @override - List getBitcoinReceivePageOptions() => BitcoinReceivePageOption.all; + List getBitcoinReceivePageOptions() => BitcoinReceivePageOption.all; + + @override + BitcoinAddressType getBitcoinAddressType(ReceivePageOption option) { + switch (option) { + case BitcoinReceivePageOption.p2pkh: + return P2pkhAddressType.p2pkh; + case BitcoinReceivePageOption.p2sh: + return P2shAddressType.p2wpkhInP2sh; + case BitcoinReceivePageOption.p2tr: + return SegwitAddresType.p2tr; + case BitcoinReceivePageOption.p2wsh: + return SegwitAddresType.p2wsh; + case BitcoinReceivePageOption.p2wpkh: + default: + return SegwitAddresType.p2wpkh; + } + } } diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 84fcb9e2e..ad2c761a3 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -295,6 +295,16 @@ class AddressValidator extends TextValidator { case CryptoCurrency.sol: return '([^0-9a-zA-Z]|^)[1-9A-HJ-NP-Za-km-z]{43,44}([^0-9a-zA-Z]|\$)'; default: + if (type.tag == CryptoCurrency.eth.title) { + return '0x[0-9a-zA-Z]{42}'; + } + if (type.tag == CryptoCurrency.maticpoly.tag) { + return '0x[0-9a-zA-Z]{42}'; + } + if (type.tag == CryptoCurrency.sol.title) { + return '([^0-9a-zA-Z]|^)[1-9A-HJ-NP-Za-km-z]{43,44}([^0-9a-zA-Z]|\$)'; + } + return null; } } diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart index 3ebc08c55..bab0ef51d 100644 --- a/lib/entities/parse_address_from_domain.dart +++ b/lib/entities/parse_address_from_domain.dart @@ -51,7 +51,8 @@ class AddressResolver { } final match = RegExp(addressPattern).firstMatch(raw); - return match?.group(0)?.replaceAllMapped(RegExp('[^0-9a-zA-Z]|bitcoincash:|nano_'), (Match match) { + return match?.group(0)?.replaceAllMapped(RegExp('[^0-9a-zA-Z]|bitcoincash:|nano_'), + (Match match) { String group = match.group(0)!; if (group.startsWith('bitcoincash:') || group.startsWith('nano_')) { return group; @@ -68,7 +69,7 @@ class AddressResolver { return emailRegex.hasMatch(address); } - + // TODO: refactor this to take Crypto currency instead of ticker, or at least pass in the tag as well Future resolve(BuildContext context, String text, String ticker) async { try { if (text.startsWith('@') && !text.substring(1).contains('@')) { @@ -76,7 +77,8 @@ class AddressResolver { final formattedName = text.substring(1); final twitterUser = await TwitterApi.lookupUserByName(userName: formattedName); final addressFromBio = extractAddressByType( - raw: twitterUser.description, type: CryptoCurrency.fromString(ticker)); + raw: twitterUser.description, + type: CryptoCurrency.fromString(ticker, walletCurrency: wallet.currency)); if (addressFromBio != null) { return ParsedAddress.fetchTwitterAddress( address: addressFromBio, @@ -87,8 +89,9 @@ class AddressResolver { final pinnedTweet = twitterUser.pinnedTweet?.text; if (pinnedTweet != null) { - final addressFromPinnedTweet = - extractAddressByType(raw: pinnedTweet, type: CryptoCurrency.fromString(ticker)); + final addressFromPinnedTweet = extractAddressByType( + raw: pinnedTweet, + type: CryptoCurrency.fromString(ticker, walletCurrency: wallet.currency)); if (addressFromPinnedTweet != null) { return ParsedAddress.fetchTwitterAddress( address: addressFromPinnedTweet, @@ -108,11 +111,11 @@ class AddressResolver { final userName = subText.substring(0, hostNameIndex); final mastodonUser = - await MastodonAPI.lookupUserByUserName(userName: userName, apiHost: hostName); + await MastodonAPI.lookupUserByUserName(userName: userName, apiHost: hostName); if (mastodonUser != null) { - String? addressFromBio = - extractAddressByType(raw: mastodonUser.note, type: CryptoCurrency.fromString(ticker)); + String? addressFromBio = extractAddressByType( + raw: mastodonUser.note, type: CryptoCurrency.fromString(ticker)); if (addressFromBio != null) { return ParsedAddress.fetchMastodonAddress( @@ -122,7 +125,7 @@ class AddressResolver { profileName: mastodonUser.username); } else { final pinnedPosts = - await MastodonAPI.getPinnedPosts(userId: mastodonUser.id, apiHost: hostName); + await MastodonAPI.getPinnedPosts(userId: mastodonUser.id, apiHost: hostName); if (pinnedPosts.isNotEmpty) { final userPinnedPostsText = pinnedPosts.map((item) => item.content).join('\n'); @@ -150,7 +153,7 @@ class AddressResolver { } } if (text.hasOnlyEmojis) { - if(settingsStore.lookupsYatService) { + if (settingsStore.lookupsYatService) { if (walletType != WalletType.haven) { final addresses = await yatService.fetchYatAddress(text, ticker); return ParsedAddress.fetchEmojiAddress(addresses: addresses, name: text); @@ -166,7 +169,7 @@ class AddressResolver { } if (unstoppableDomains.any((domain) => name.trim() == domain)) { - if(settingsStore.lookupsUnstoppableDomains) { + if (settingsStore.lookupsUnstoppableDomains) { final address = await fetchUnstoppableDomainAddress(text, ticker); return ParsedAddress.fetchUnstoppableDomainAddress(address: address, name: text); } @@ -182,7 +185,7 @@ class AddressResolver { } if (formattedName.contains(".")) { - if(settingsStore.lookupsOpenAlias) { + if (settingsStore.lookupsOpenAlias) { final txtRecord = await OpenaliasRecord.lookupOpenAliasRecord(formattedName); if (txtRecord != null) { final record = await OpenaliasRecord.fetchAddressAndName( @@ -201,7 +204,11 @@ class AddressResolver { String? addressFromBio = extractAddressByType( raw: nostrUserData.about, type: CryptoCurrency.fromString(ticker)); if (addressFromBio != null) { - return ParsedAddress.nostrAddress(address: addressFromBio, name: text); + return ParsedAddress.nostrAddress( + address: addressFromBio, + name: text, + profileImageUrl: nostrUserData.picture, + profileName: nostrUserData.name); } } } diff --git a/lib/entities/parsed_address.dart b/lib/entities/parsed_address.dart index d87deb9e8..fc8ab2440 100644 --- a/lib/entities/parsed_address.dart +++ b/lib/entities/parsed_address.dart @@ -119,11 +119,17 @@ class ParsedAddress { ); } - factory ParsedAddress.nostrAddress({required String address, required String name}) { + factory ParsedAddress.nostrAddress( + {required String address, + required String name, + required String profileImageUrl, + required String profileName}) { return ParsedAddress( addresses: [address], name: name, parseFrom: ParseFrom.nostr, + profileImageUrl: profileImageUrl, + profileName: profileName, ); } diff --git a/lib/src/screens/dashboard/pages/address_page.dart b/lib/src/screens/dashboard/pages/address_page.dart index 7b7c84c28..0d7c4f11c 100644 --- a/lib/src/screens/dashboard/pages/address_page.dart +++ b/lib/src/screens/dashboard/pages/address_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart'; import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/di.dart'; @@ -6,7 +7,6 @@ import 'package:cake_wallet/src/screens/monero_accounts/monero_account_list_page import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cw_core/receive_page_option.dart'; -import 'package:cw_bitcoin/bitcoin_receive_page_option.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/present_receive_option_picker.dart'; import 'package:cake_wallet/src/widgets/gradient_background.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; @@ -28,7 +28,6 @@ import 'package:keyboard_actions/keyboard_actions.dart'; import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; -import 'package:bitcoin_base/bitcoin_base.dart'; class AddressPage extends BasePage { AddressPage({ @@ -230,22 +229,10 @@ class AddressPage extends BasePage { ); } break; - case BitcoinReceivePageOption.p2pkh: - addressListViewModel.setAddressType(P2pkhAddressType.p2pkh); - break; - case BitcoinReceivePageOption.p2sh: - addressListViewModel.setAddressType(P2shAddressType.p2wpkhInP2sh); - break; - case BitcoinReceivePageOption.p2wpkh: - addressListViewModel.setAddressType(SegwitAddresType.p2wpkh); - break; - case BitcoinReceivePageOption.p2tr: - addressListViewModel.setAddressType(SegwitAddresType.p2tr); - break; - case BitcoinReceivePageOption.p2wsh: - addressListViewModel.setAddressType(SegwitAddresType.p2wsh); - break; default: + if (addressListViewModel.type == WalletType.bitcoin) { + addressListViewModel.setAddressType(bitcoin!.getBitcoinAddressType(option)); + } } }); diff --git a/lib/src/screens/send/widgets/extract_address_from_parsed.dart b/lib/src/screens/send/widgets/extract_address_from_parsed.dart index 42e646d58..eb997c11b 100644 --- a/lib/src/screens/send/widgets/extract_address_from_parsed.dart +++ b/lib/src/screens/send/widgets/extract_address_from_parsed.dart @@ -53,6 +53,8 @@ Future extractAddressFromParsed( title = S.of(context).address_detected; content = S.of(context).extracted_address_content('${parsedAddress.name} (Nostr NIP-05)'); address = parsedAddress.addresses.first; + profileImageUrl = parsedAddress.profileImageUrl; + profileName = parsedAddress.profileName; break; case ParseFrom.yatRecord: if (parsedAddress.name.isEmpty) { diff --git a/lib/src/widgets/base_alert_dialog.dart b/lib/src/widgets/base_alert_dialog.dart index e9ef522df..b251e4b45 100644 --- a/lib/src/widgets/base_alert_dialog.dart +++ b/lib/src/widgets/base_alert_dialog.dart @@ -1,4 +1,3 @@ -import 'package:cake_wallet/src/screens/receive/widgets/header_tile.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'dart:ui'; import 'package:cake_wallet/src/widgets/section_divider.dart'; diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index fe6c98826..6c91d73f3 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -790,9 +790,16 @@ abstract class SettingsStoreBase with Store { final exchangeStatus = ExchangeApiMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.exchangeStatusKey) ?? ExchangeApiMode.enabled.raw); + final bool isNewInstall = sharedPreferences.getBool(PreferencesKey.isNewInstall) ?? true; + final int defaultTheme; + if (isNewInstall) { + defaultTheme = isMoneroOnly ? ThemeList.moneroDarkTheme.raw : ThemeList.brightTheme.raw; + } else { + defaultTheme = ThemeType.bright.index; + } final savedTheme = initialTheme ?? ThemeList.deserialize( - raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? (isMoneroOnly ? ThemeList.moneroDarkTheme.raw : ThemeList.cakeDarkTheme.raw)); + raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? defaultTheme); final actionListDisplayMode = ObservableList(); actionListDisplayMode.addAll(deserializeActionlistDisplayModes( sharedPreferences.getInt(PreferencesKey.displayActionListModeKey) ?? defaultActionsMode)); @@ -1151,7 +1158,8 @@ abstract class SettingsStoreBase with Store { raw: sharedPreferences.getInt(PreferencesKey.exchangeStatusKey) ?? ExchangeApiMode.enabled.raw); currentTheme = ThemeList.deserialize( - raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? (isMoneroOnly ? ThemeList.moneroDarkTheme.raw : ThemeList.cakeDarkTheme.raw)); + raw: sharedPreferences.getInt(PreferencesKey.currentTheme) ?? + (isMoneroOnly ? ThemeList.moneroDarkTheme.raw : ThemeList.brightTheme.raw)); actionlistDisplayMode = ObservableList(); actionlistDisplayMode.addAll(deserializeActionlistDisplayModes( sharedPreferences.getInt(PreferencesKey.displayActionListModeKey) ?? defaultActionsMode)); diff --git a/lib/twitter/twitter_api.dart b/lib/twitter/twitter_api.dart index bf6298dae..5acb00e2a 100644 --- a/lib/twitter/twitter_api.dart +++ b/lib/twitter/twitter_api.dart @@ -32,7 +32,10 @@ class TwitterApi { } final Map responseJSON = jsonDecode(response.body) as Map; - if (responseJSON['errors'] != null) { + if (responseJSON['errors'] != null && + !responseJSON['errors'][0]['detail'] + .toString() + .contains("Could not find tweet with pinned_tweet_id")) { throw Exception(responseJSON['errors'][0]['detail']); } @@ -40,20 +43,24 @@ class TwitterApi { } static Tweet? _getPinnedTweet(Map responseJSON) { - final tweetId = responseJSON['data']['pinned_tweet_id'] as String?; - if (tweetId == null || responseJSON['includes'] == null) return null; + try { + final tweetId = responseJSON['data']['pinned_tweet_id'] as String?; + if (tweetId == null || responseJSON['includes'] == null) return null; - final tweetIncludes = List.from(responseJSON['includes']['tweets'] as List); - final pinnedTweetData = tweetIncludes.firstWhere( - (tweet) => tweet['id'] == tweetId, - orElse: () => null, - ) as Map?; + final tweetIncludes = List.from(responseJSON['includes']['tweets'] as List); + final pinnedTweetData = tweetIncludes.firstWhere( + (tweet) => tweet['id'] == tweetId, + orElse: () => null, + ) as Map?; - if (pinnedTweetData == null) return null; + if (pinnedTweetData == null) return null; - final pinnedTweetText = - (pinnedTweetData['note_tweet']?['text'] ?? pinnedTweetData['text']) as String; + final pinnedTweetText = + (pinnedTweetData['note_tweet']?['text'] ?? pinnedTweetData['text']) as String; - return Tweet(id: tweetId, text: pinnedTweetText); + return Tweet(id: tweetId, text: pinnedTweetText); + } catch (e) { + return null; + } } } diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index 93877a525..0d40ae240 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -162,9 +162,14 @@ abstract class ExchangeTradeViewModelBase with Store { wallet.currency == CryptoCurrency.maticpoly && tradesStore.trade!.from.tag == CryptoCurrency.maticpoly.tag; + bool _isSplToken() => + wallet.currency == CryptoCurrency.sol && + tradesStore.trade!.from.tag == CryptoCurrency.sol.title; + return tradesStore.trade!.from == wallet.currency || tradesStore.trade!.provider == ExchangeProviderDescription.xmrto || _isEthToken() || - _isPolygonToken(); + _isPolygonToken() || + _isSplToken(); } } diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 05996a674..75a78404f 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,7 +5,7 @@ import FlutterMacOS import Foundation -import connectivity_plus_macos +import connectivity_plus import cw_monero import device_info_plus import devicelocale diff --git a/macos/Podfile.lock b/macos/Podfile.lock index fcbe1d733..106a8a652 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - connectivity_plus_macos (0.0.1): + - connectivity_plus (0.0.1): - FlutterMacOS - ReachabilitySwift - cw_monero (0.0.1): @@ -51,7 +51,7 @@ PODS: - FlutterMacOS DEPENDENCIES: - - connectivity_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus_macos/macos`) + - connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`) - cw_monero (from `Flutter/ephemeral/.symlinks/plugins/cw_monero/macos`) - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`) @@ -73,8 +73,8 @@ SPEC REPOS: - ReachabilitySwift EXTERNAL SOURCES: - connectivity_plus_macos: - :path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus_macos/macos + connectivity_plus: + :path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos cw_monero: :path: Flutter/ephemeral/.symlinks/plugins/cw_monero/macos device_info_plus: @@ -105,8 +105,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos SPEC CHECKSUMS: - connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308 - cw_monero: f8b7f104508efba2591548e76b5c058d05cba3f0 + connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747 + cw_monero: ec03de55a19c4a2b174ea687e0f4202edc716fa4 device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225 flutter_inappwebview_macos: 9600c9df9fdb346aaa8933812009f8d94304203d @@ -123,6 +123,6 @@ SPEC CHECKSUMS: url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269 -PODFILE CHECKSUM: 5107934592df7813b33d744aebc8ddc6b5a5445f +PODFILE CHECKSUM: 65ec1541137fb5b35d00490dec1bb48d4d9586bb COCOAPODS: 1.12.1 diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 758287601..d4bf981cd 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -55,7 +55,7 @@ dependencies: basic_utils: ^5.6.1 get_it: ^7.2.0 # connectivity: ^3.0.3 - connectivity_plus: ^2.3.5 + connectivity_plus: ^5.0.2 keyboard_actions: ^4.0.1 another_flushbar: ^1.12.29 archive: ^3.3.0 @@ -107,6 +107,10 @@ dependencies: polyseed: ^0.0.2 nostr_tools: ^1.0.9 solana: ^0.30.1 + bitcoin_base: + git: + url: https://github.com/cake-tech/bitcoin_base.git + ref: cake-update-v1 dev_dependencies: flutter_test: diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 9251ec31a..fa3701fa7 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.10.3" -MONERO_COM_BUILD_NUMBER=75 +MONERO_COM_VERSION="1.11.0" +MONERO_COM_BUILD_NUMBER=77 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="4.14.0" -CAKEWALLET_BUILD_NUMBER=193 +CAKEWALLET_BUILD_NUMBER=196 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 47d80013c..31f0b9548 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.10.3" -MONERO_COM_BUILD_NUMBER=73 +MONERO_COM_VERSION="1.11.0" +MONERO_COM_BUILD_NUMBER=75 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="4.14.0" -CAKEWALLET_BUILD_NUMBER=213 +CAKEWALLET_BUILD_NUMBER=215 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 49edd9acb..4dec47f40 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -16,13 +16,13 @@ if [ -n "$1" ]; then fi MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.0.3" -MONERO_COM_BUILD_NUMBER=5 +MONERO_COM_VERSION="1.1.0" +MONERO_COM_BUILD_NUMBER=7 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.6.3" -CAKEWALLET_BUILD_NUMBER=53 +CAKEWALLET_VERSION="1.7.0" +CAKEWALLET_BUILD_NUMBER=55 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then diff --git a/tool/configure.dart b/tool/configure.dart index fb1647e13..3c1587a98 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -61,6 +61,7 @@ Future main(List args) async { Future generateBitcoin(bool hasImplementation) async { final outputFile = File(bitcoinOutputPath); const bitcoinCommonHeaders = """ +import 'package:cw_core/receive_page_option.dart'; import 'package:cw_core/unspent_transaction_output.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; @@ -70,7 +71,8 @@ import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:hive/hive.dart';"""; +import 'package:hive/hive.dart'; +import 'package:bitcoin_base/bitcoin_base.dart';"""; const bitcoinCWHeaders = """ import 'package:cw_bitcoin/bitcoin_receive_page_option.dart'; import 'package:cw_bitcoin/electrum_wallet.dart'; @@ -83,7 +85,6 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_bitcoin/litecoin_wallet_service.dart'; -import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:mobx/mobx.dart'; """; const bitcoinCwPart = "part 'cw_bitcoin.dart';"; @@ -143,8 +144,9 @@ abstract class Bitcoin { TransactionPriority getLitecoinTransactionPrioritySlow(); Future setAddressType(Object wallet, dynamic option); - BitcoinReceivePageOption getSelectedAddressType(Object wallet); - List getBitcoinReceivePageOptions(); + ReceivePageOption getSelectedAddressType(Object wallet); + List getBitcoinReceivePageOptions(); + BitcoinAddressType getBitcoinAddressType(ReceivePageOption option); } """; @@ -906,6 +908,7 @@ import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:hive/hive.dart'; +import 'package:solana/solana.dart'; """; const solanaCWHeaders = """ @@ -916,7 +919,6 @@ import 'package:cw_solana/solana_wallet_service.dart'; import 'package:cw_solana/solana_transaction_info.dart'; import 'package:cw_solana/solana_transaction_credentials.dart'; import 'package:cw_solana/solana_wallet_creation_credentials.dart'; -import 'package:solana/solana.dart'; """; const solanaCwPart = "part 'cw_solana.dart';"; const solanaContent = """ @@ -944,10 +946,10 @@ abstract class Solana { List outputs, { required CryptoCurrency currency, }); - List getSPLTokenCurrencies(WalletBase wallet); + List getSPLTokenCurrencies(WalletBase wallet); Future addSPLToken(WalletBase wallet, CryptoCurrency token); Future deleteSPLToken(WalletBase wallet, CryptoCurrency token); - Future getSPLToken(WalletBase wallet, String contractAddress); + Future getSPLToken(WalletBase wallet, String contractAddress); CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction); double getTransactionAmountRaw(TransactionInfo transactionInfo); From 64143646026576b05f57795cb92cb99b95438644 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Sun, 10 Mar 2024 04:02:30 +0200 Subject: [PATCH 126/241] Generic fixes (#1320) * New price API * Fix test app package id * Fix workflow * change environment variable to use pr number [skip ci] * Fix un-needed padding * Fix raw value for usdtSol * Remove duplicate fetching for balance and transactions at start [skip ci] * Fix address validation of spl tokens * Add Service Status * Update lib/src/widgets/service_status_tile.dart Co-authored-by: Konstantin Ullrich * Update lib/src/widgets/services_updates_widget.dart Co-authored-by: Konstantin Ullrich * Update monero version * update sodium script * Change automatic priority fee rate --------- Co-authored-by: Konstantin Ullrich --- .github/workflows/pr_test_build.yml | 6 +- assets/images/notification_icon.png | Bin 0 -> 471 bytes assets/images/status_website_image.png | Bin 0 -> 546 bytes cw_core/lib/crypto_currency.dart | 2 +- cw_monero/lib/monero_wallet.dart | 11 +- cw_solana/lib/solana_wallet.dart | 10 -- lib/di.dart | 1 + lib/entities/preferences_key.dart | 1 + lib/entities/service_status.dart | 41 ++++++ lib/solana/cw_solana.dart | 2 +- lib/src/screens/dashboard/dashboard_page.dart | 4 + lib/src/widgets/base_alert_dialog.dart | 2 +- lib/src/widgets/service_status_tile.dart | 71 +++++++++++ lib/src/widgets/services_updates_widget.dart | 120 ++++++++++++++++++ .../dashboard/dashboard_view_model.dart | 29 ++++- lib/view_model/send/send_view_model.dart | 3 +- scripts/android/build_monero.sh | 2 +- scripts/ios/build_monero.sh | 2 +- scripts/ios/build_sodium.sh | 9 +- scripts/macos/build_monero.sh | 2 +- 20 files changed, 285 insertions(+), 33 deletions(-) create mode 100644 assets/images/notification_icon.png create mode 100644 assets/images/status_website_image.png create mode 100644 lib/entities/service_status.dart create mode 100644 lib/src/widgets/service_status_tile.dart create mode 100644 lib/src/widgets/services_updates_widget.dart diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 4df215e13..282941365 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -16,6 +16,7 @@ jobs: env: STORE_PASS: test@cake_wallet KEY_PASS: test@cake_wallet + PR_NUMBER: ${{ github.event.number }} steps: - name: is pr @@ -150,10 +151,7 @@ jobs: - name: Rename app run: | - hash=`sha512sum <<<"${{ env.BRANCH_NAME }}"` - substring=${hash:0:15} - echo substring - echo -e "id=com.cakewallet.test_$(substring)\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties + echo -e "id=com.cakewallet.test_${{ env.PR_NUMBER }}\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties - name: Build run: | diff --git a/assets/images/notification_icon.png b/assets/images/notification_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d60211a0bef9014482e22ba784b9846f173611 GIT binary patch literal 471 zcmV;|0Vw{7P)X1^@s6+90*i00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP zgD?zKav8uIlul4a@CMBW$p*~^p%XNj06Ib^XgdMjpxppE0ez+KJ0HQuKy>#fu;rJK zB_T2(UDss_xwU}w1!#b8eU=5X=@I8pTi~8cHP(KiKY(_%T7Ag`*$k{HNlRyEs0ZK( z7`z+k3OGBPWWnJbQ<4St^)4!=ESp07lzIp@hhztgXi_wE@Sb8=0)s1k~NS4KQcpDj&Hy|M7~ri;BjzAyHYDf76?<5_t)2KX|r%p zX(w+(o{Kr9=$*IhlkzG^ZZ@(|Seh3n{f&4-q&u*#Z~SWclu+Kr33YrN`Sm(MpMlml zh&IFkp>gwt=T2jzppF@k(0YVrQYzhK4D4C&_gC}MR3BoT{+~#5_3Ar=+5t*%=>_>8 z6B+I9xHcNKn~eET9=-cG@!2r?v;r8*qt__Tu8>q=)F$BzZI?JI{s8Bgz0#>m@Ff5M N002ovPDHLkV1nYWz)t`G literal 0 HcmV?d00001 diff --git a/assets/images/status_website_image.png b/assets/images/status_website_image.png new file mode 100644 index 0000000000000000000000000000000000000000..017bb64e19d8aa32b5e608d206f03197cb8e1fc1 GIT binary patch literal 546 zcmV+-0^R+IP)OXT=e`fhj;+j$j2m8{h;!Dx@M*2#xUsNeeb`0^J|+>>^}Xr9OT^pfdc;f>M@O0SK`RC^v=2iEJcsTguxnF~Hh>Y_^t} zsfhQ&SIcA&$3lU<9a$bpxX9cytpyX@C}9!g_;cG~CEWrgb^@t1M>T`6r2`~O+!GGo zO)F4x6ThTK!+=1o86IeV1R*KP5~$5B4F%F%Ao%Ib%&GxmdoQ(v?!bV#TA~iBHb-rc z=pmr9p7n-l$XR{lBO_S`gt08e@R3-vDqEO$x;Lk=2? zQV_9lBAIj1@PrVe-pROG%cLi9rg4jp`v)TpsIE)~90DeCM9-BjPlBfVKM@{i0f}p|Q_*s-V$mJO=*V97)Lmf`n;W07` zJOU9KIptvWa$>`d)R$i kTs93N*?qe2`|uC@0_}R?UQ~Njs{jB107*qoM6N<$f`XUbW&i*H literal 0 HcmV?d00001 diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index ce509015c..9cebce10a 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -216,7 +216,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen static const usdcEPoly = CryptoCurrency(title: 'USDC.E', tag: 'POLY', fullName: 'USD Coin (PoS)', raw: 88, name: 'usdcepoly', iconPath: 'assets/images/usdc_icon.png', decimals: 6); static const kaspa = CryptoCurrency(title: 'KAS', fullName: 'Kaspa', raw: 89, name: 'kas', iconPath: 'assets/images/kaspa_icon.png', decimals: 8); static const digibyte = CryptoCurrency(title: 'DGB', fullName: 'DigiByte', raw: 90, name: 'dgb', iconPath: 'assets/images/digibyte.png', decimals: 8); - static const usdtSol = CryptoCurrency(title: 'USDT', tag: 'SOL', fullName: 'USDT Tether', raw: 90, name: 'usdtsol', iconPath: 'assets/images/usdt_icon.png', decimals: 6); + static const usdtSol = CryptoCurrency(title: 'USDT', tag: 'SOL', fullName: 'USDT Tether', raw: 91, name: 'usdtsol', iconPath: 'assets/images/usdt_icon.png', decimals: 6); static final Map _rawCurrencyMap = diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index ab4bfb0b0..58f63d7ce 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -183,13 +183,8 @@ abstract class MoneroWalletBase // try to use the date instead: try { _setHeightFromDate(); - } catch (e, s) { + } catch (_) { // we still couldn't get a valid sync height :/ - onError?.call(FlutterErrorDetails( - exception: e, - stack: s, - library: this.runtimeType.toString(), - )); } } } @@ -287,7 +282,9 @@ abstract class MoneroWalletBase pendingTransactionDescription = await transaction_history.createTransaction( address: address!, amount: amount, - priorityRaw: _credentials.priority.serialize(), + priorityRaw: _credentials.priority == MoneroTransactionPriority.automatic + ? MoneroTransactionPriority.medium.serialize() + : _credentials.priority.serialize(), accountIndex: walletAddresses.account!.id, preferredInputs: inputs); } diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart index f901a64be..3476d76cd 100644 --- a/cw_solana/lib/solana_wallet.dart +++ b/cw_solana/lib/solana_wallet.dart @@ -165,16 +165,6 @@ abstract class SolanaWalletBase throw Exception("Solana Node connection failed"); } - try { - await Future.wait([ - _updateBalance(), - _updateNativeSOLTransactions(), - _updateSPLTokenTransactions(), - ]); - } catch (e) { - log(e.toString()); - } - _setTransactionUpdateTimer(); syncStatus = ConnectedSyncStatus(); diff --git a/lib/di.dart b/lib/di.dart index 473eaed00..782c0f1f4 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -384,6 +384,7 @@ Future setup({ yatStore: getIt.get(), ordersStore: getIt.get(), anonpayTransactionsStore: getIt.get(), + sharedPreferences: getIt.get(), keyService: getIt.get())); getIt.registerFactory( diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 0dd251aaa..1808be97c 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -72,4 +72,5 @@ class PreferencesKey { static const lastSeenAppVersion = 'last_seen_app_version'; static const shouldShowMarketPlaceInDashboard = 'should_show_marketplace_in_dashboard'; static const isNewInstall = 'is_new_install'; + static const serviceStatusShaKey = 'service_status_sha_key'; } diff --git a/lib/entities/service_status.dart b/lib/entities/service_status.dart new file mode 100644 index 000000000..392c8072d --- /dev/null +++ b/lib/entities/service_status.dart @@ -0,0 +1,41 @@ +class ServiceStatus { + final String title; + final String description; + final String? image; + final String? status; + final DateTime date; + + ServiceStatus( + {required this.title, + required this.description, + required this.date, + this.image, + this.status}); + + factory ServiceStatus.fromJson(Map json) => ServiceStatus( + title: json['title'] as String? ?? '', + description: json['description'] as String? ?? '', + date: DateTime.tryParse(json['date'] as String? ?? '') ?? DateTime.now(), + image: json['image'] as String?, + status: json['status'] as String?, + ); +} + +class ServicesResponse { + final List servicesStatus; + final bool hasUpdates; + final String currentSha; + + ServicesResponse(this.servicesStatus, this.hasUpdates, this.currentSha); + + factory ServicesResponse.fromJson( + Map json, bool hasUpdates, String currentSha) { + return ServicesResponse( + (json['notices'] as List? ?? []) + .map((e) => ServiceStatus.fromJson(e as Map)) + .toList(), + hasUpdates, + currentSha, + ); + } +} diff --git a/lib/solana/cw_solana.dart b/lib/solana/cw_solana.dart index a86d6b0c6..9f9d81e5f 100644 --- a/lib/solana/cw_solana.dart +++ b/lib/solana/cw_solana.dart @@ -110,7 +110,7 @@ class CWSolana extends Solana { @override List? getValidationLength(CryptoCurrency type) { if (type is SPLToken) { - return [44]; + return [32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44]; } return null; diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index 61e7d6176..3806dff91 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -7,6 +7,7 @@ import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sideba import 'package:cake_wallet/src/screens/dashboard/pages/market_place_page.dart'; import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/bottom_sheet_listener.dart'; import 'package:cake_wallet/src/widgets/gradient_background.dart'; +import 'package:cake_wallet/src/widgets/services_updates_widget.dart'; import 'package:cake_wallet/src/widgets/vulnerable_seeds_popup.dart'; import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; import 'package:cake_wallet/utils/device_info.dart'; @@ -101,6 +102,9 @@ class _DashboardPageView extends BasePage { @override Widget get endDrawer => MenuWidget(dashboardViewModel); + @override + Widget leading(BuildContext context) => ServicesUpdatesWidget(dashboardViewModel.getServicesStatus()); + @override Widget middle(BuildContext context) { return SyncIndicator( diff --git a/lib/src/widgets/base_alert_dialog.dart b/lib/src/widgets/base_alert_dialog.dart index b251e4b45..5c1111740 100644 --- a/lib/src/widgets/base_alert_dialog.dart +++ b/lib/src/widgets/base_alert_dialog.dart @@ -179,7 +179,7 @@ class BaseAlertDialog extends StatelessWidget { Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - if (headerText != null) headerTitle(context), + if (headerText?.isNotEmpty ?? false) headerTitle(context), Padding( padding: EdgeInsets.fromLTRB(24, 20, 24, 0), child: title(context), diff --git a/lib/src/widgets/service_status_tile.dart b/lib/src/widgets/service_status_tile.dart new file mode 100644 index 000000000..f2a079841 --- /dev/null +++ b/lib/src/widgets/service_status_tile.dart @@ -0,0 +1,71 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cake_wallet/entities/service_status.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + +class ServiceStatusTile extends StatelessWidget { + final ServiceStatus status; + + const ServiceStatusTile(this.status, {super.key}); + + @override + Widget build(BuildContext context) { + return ListTile( + contentPadding: const EdgeInsets.all(8), + title: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: AutoSizeText( + "${status.title}${status.status != null ? " - ${status.status}" : ""}", + style: TextStyle( + fontSize: 16, + fontFamily: 'Lato', + fontWeight: FontWeight.w800, + height: 1, + ), + maxLines: 1, + textAlign: TextAlign.start, + ), + ), + Text( + _getTimeString(status.date), + style: TextStyle(fontSize: 12), + ), + ], + ), + ), + leading: RotatedBox( + child: Icon( + Icons.info, + color: status.status == "resolved" ? Colors.green : Colors.red, + ), + quarterTurns: 2, + ), + subtitle: Row( + children: [ + Expanded(child: Text(status.description)), + if (status.image != null) + SizedBox( + height: 50, + width: 50, + child: Image.network(status.image!), + ), + ], + ), + ); + } + + String _getTimeString(DateTime date) { + int difference = DateTime.now().difference(date).inHours; + if (difference == 0) { + return "few minutes ago"; + } + if (difference < 24) { + return DateFormat('h:mm a').format(date); + } + return DateFormat('d-MM-yyyy').format(date); + } +} diff --git a/lib/src/widgets/services_updates_widget.dart b/lib/src/widgets/services_updates_widget.dart new file mode 100644 index 000000000..7a8614b75 --- /dev/null +++ b/lib/src/widgets/services_updates_widget.dart @@ -0,0 +1,120 @@ +import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/entities/preferences_key.dart'; +import 'package:cake_wallet/entities/service_status.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/src/widgets/service_status_tile.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class ServicesUpdatesWidget extends StatelessWidget { + final Future servicesResponse; + + const ServicesUpdatesWidget(this.servicesResponse, {super.key}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: FutureBuilder( + future: servicesResponse, + builder: (context, state) { + return InkWell( + onTap: state.hasData + ? () { + // save currentSha when the user see the status + getIt + .get() + .setString(PreferencesKey.serviceStatusShaKey, state.data!.currentSha); + + showModalBottomSheet( + context: context, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(50), + topRight: Radius.circular(50), + ), + ), + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context).size.height / 2, + minHeight: MediaQuery.of(context).size.height / 4, + ), + builder: (context) { + Widget body; + if (state.data!.servicesStatus.isEmpty) { + body = Center( + child: Text("Everything is up and running as expected"), + ); + } else { + body = SingleChildScrollView( + child: Column( + children: state.data!.servicesStatus + .map((status) => ServiceStatusTile(status)) + .toList()), + ); + } + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 20), + child: Stack( + children: [ + body, + Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: MediaQuery.of(context).size.width / 8), + child: PrimaryImageButton( + onPressed: () { + try { + launchUrl(Uri.parse("https://status.cakewallet.com/")); + } catch (_) {} + }, + image: Image.asset( + "assets/images/status_website_image.png", + color: Theme.of(context).brightness == Brightness.light + ? Colors.white + : null, + ), + text: "Status Website", + color: Theme.of(context) + .extension()! + .createNewWalletButtonBackgroundColor, + textColor: Theme.of(context) + .extension()! + .restoreWalletButtonTextColor, + ), + ), + ) + ], + ), + ); + }, + ); + } + : null, + child: Stack( + children: [ + Image.asset( + "assets/images/notification_icon.png", + color: Theme.of(context).extension()!.pageTitleTextColor, + ), + if (state.hasData && state.data!.hasUpdates) + Container( + height: 7, + width: 7, + margin: EdgeInsetsDirectional.only(start: 8), + decoration: BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), + ), + ], + ), + ); + }, + ), + ); + } +} diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index da5eb0373..a21a92cb4 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -4,8 +4,10 @@ import 'package:cake_wallet/buy/buy_provider.dart'; import 'package:cake_wallet/core/key_service.dart'; import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/balance_display_mode.dart'; +import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/provider_types.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; +import 'package:cake_wallet/entities/service_status.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/monero/monero.dart'; @@ -42,7 +44,8 @@ import 'package:cw_core/wallet_type.dart'; import 'package:eth_sig_util/util/utils.dart'; import 'package:flutter/services.dart'; import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/entities/provider_types.dart'; +import 'package:http/http.dart' as http; +import 'package:shared_preferences/shared_preferences.dart'; part 'dashboard_view_model.g.dart'; @@ -59,6 +62,7 @@ abstract class DashboardViewModelBase with Store { required this.yatStore, required this.ordersStore, required this.anonpayTransactionsStore, + required this.sharedPreferences, required this.keyService}) : hasSellAction = false, hasBuyAction = false, @@ -280,6 +284,7 @@ abstract class DashboardViewModelBase with Store { bool get hasRescan => wallet.type == WalletType.monero || wallet.type == WalletType.haven; final KeyService keyService; + final SharedPreferences sharedPreferences; BalanceViewModel balanceViewModel; @@ -497,4 +502,26 @@ abstract class DashboardViewModelBase with Store { return affectedWallets; } + + Future getServicesStatus() async { + try { + final res = await http.get(Uri.parse("https://service-api.cakewallet.com/v1/active-notices")); + + if (res.statusCode < 200 || res.statusCode >= 300) { + throw res.body; + } + + final oldSha = sharedPreferences.getString(PreferencesKey.serviceStatusShaKey); + + + final hash = await Cryptography.instance.sha256().hash(utf8.encode(res.body)); + final currentSha = bytesToHex(hash.bytes); + + final hasUpdates = oldSha != currentSha; + + return ServicesResponse.fromJson(json.decode(res.body) as Map, hasUpdates, currentSha); + } catch (_) { + return ServicesResponse([], false, ''); + } + } } diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 772150368..507ed14cc 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -427,9 +427,10 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor ) { if (walletType == WalletType.ethereum || walletType == WalletType.polygon || + walletType == WalletType.solana || walletType == WalletType.haven) { if (error.contains('gas required exceeds allowance') || - error.contains('insufficient funds for')) { + error.contains('insufficient funds')) { return S.current.do_not_have_enough_gas_asset(currency.toString()); } diff --git a/scripts/android/build_monero.sh b/scripts/android/build_monero.sh index e0010b351..7e9b58b6d 100755 --- a/scripts/android/build_monero.sh +++ b/scripts/android/build_monero.sh @@ -1,7 +1,7 @@ #!/bin/sh . ./config.sh -MONERO_BRANCH=release-v0.18.2.2-android +MONERO_BRANCH=release-v0.18.2.2-android_tx_priority_fix MONERO_SRC_DIR=${WORKDIR}/monero git clone https://github.com/cake-tech/monero.git ${MONERO_SRC_DIR} --branch ${MONERO_BRANCH} diff --git a/scripts/ios/build_monero.sh b/scripts/ios/build_monero.sh index 54dda546f..2c81576f1 100755 --- a/scripts/ios/build_monero.sh +++ b/scripts/ios/build_monero.sh @@ -4,7 +4,7 @@ MONERO_URL="https://github.com/cake-tech/monero.git" MONERO_DIR_PATH="${EXTERNAL_IOS_SOURCE_DIR}/monero" -MONERO_VERSION=release-v0.18.2.2 +MONERO_VERSION=release-v0.18.2.2_tx_priority_fix BUILD_TYPE=release PREFIX=${EXTERNAL_IOS_DIR} DEST_LIB_DIR=${EXTERNAL_IOS_LIB_DIR}/monero diff --git a/scripts/ios/build_sodium.sh b/scripts/ios/build_sodium.sh index 66f383fb4..5632719ad 100755 --- a/scripts/ios/build_sodium.sh +++ b/scripts/ios/build_sodium.sh @@ -8,9 +8,10 @@ SODIUM_URL="https://github.com/jedisct1/libsodium.git" echo "============================ SODIUM ============================" echo "Cloning SODIUM from - $SODIUM_URL" -git clone $SODIUM_URL $SODIUM_PATH --branch stable +git clone $SODIUM_URL $SODIUM_PATH cd $SODIUM_PATH -./dist-build/ios.sh +git checkout 443617d7507498f7477703f0b51cb596d4539262 +./dist-build/apple-xcframework.sh -mv ${SODIUM_PATH}/libsodium-ios/include/* $EXTERNAL_IOS_INCLUDE_DIR -mv ${SODIUM_PATH}/libsodium-ios/lib/* $EXTERNAL_IOS_LIB_DIR \ No newline at end of file +mv ${SODIUM_PATH}/libsodium-apple/ios/include/* $EXTERNAL_IOS_INCLUDE_DIR +mv ${SODIUM_PATH}/libsodium-apple/ios/lib/* $EXTERNAL_IOS_LIB_DIR \ No newline at end of file diff --git a/scripts/macos/build_monero.sh b/scripts/macos/build_monero.sh index c1ee0e5d3..2a1ae89a5 100755 --- a/scripts/macos/build_monero.sh +++ b/scripts/macos/build_monero.sh @@ -4,7 +4,7 @@ MONERO_URL="https://github.com/cake-tech/monero.git" MONERO_DIR_PATH="${EXTERNAL_MACOS_SOURCE_DIR}/monero" -MONERO_VERSION=release-v0.18.2.2 +MONERO_VERSION=release-v0.18.2.2_tx_priority_fix BUILD_TYPE=release PREFIX=${EXTERNAL_MACOS_DIR} DEST_LIB_DIR=${EXTERNAL_MACOS_LIB_DIR}/monero From 50b5ebc622fd5742f6e089dd6e25631e76fda237 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Thu, 14 Mar 2024 20:26:00 +0200 Subject: [PATCH 127/241] Monero update (#1325) * New price API * Fix test app package id * Fix workflow * change environment variable to use pr number [skip ci] * Fix un-needed padding * Fix raw value for usdtSol * Remove duplicate fetching for balance and transactions at start [skip ci] * Fix address validation of spl tokens * Add Service Status * Update lib/src/widgets/service_status_tile.dart Co-authored-by: Konstantin Ullrich * Update lib/src/widgets/services_updates_widget.dart Co-authored-by: Konstantin Ullrich * Update monero version * update sodium script * Change automatic priority fee rate * New versions [skip ci] * Update monero version * Temp remove split per abi * Specifically build monero.com * Revert monero dependencies trial fix * Update Monero Fix Monero Automatic Priority * Fix android script * Fix build_monero.sh android Add svg notification icon * trial 1 * trial 2 * trial 3 * trial 4 * Trial 5 * Trial * revert --------- Co-authored-by: Konstantin Ullrich --- assets/images/notification_icon.png | Bin 471 -> 0 bytes assets/images/notification_icon.svg | 69 ++++++++++++++++++ assets/text/Monerocom_Release_Notes.txt | 2 +- assets/text/Release_Notes.txt | 6 +- cw_core/lib/monero_transaction_priority.dart | 14 ++-- cw_monero/lib/monero_wallet.dart | 4 +- lib/entities/default_settings_migration.dart | 15 ++++ lib/main.dart | 2 +- .../desktop_sidebar/side_menu_item.dart | 32 ++++---- .../desktop_sidebar_wrapper.dart | 13 +++- lib/src/widgets/services_updates_widget.dart | 8 +- .../dashboard/dashboard_view_model.dart | 16 ++-- .../dashboard/desktop_sidebar_view_model.dart | 1 + scripts/android/app_env.sh | 8 +- scripts/android/build_monero.sh | 7 +- scripts/ios/app_env.sh | 8 +- scripts/ios/build_monero.sh | 3 +- scripts/macos/app_env.sh | 8 +- scripts/macos/build_monero.sh | 3 +- 19 files changed, 156 insertions(+), 63 deletions(-) delete mode 100644 assets/images/notification_icon.png create mode 100644 assets/images/notification_icon.svg diff --git a/assets/images/notification_icon.png b/assets/images/notification_icon.png deleted file mode 100644 index a6d60211a0bef9014482e22ba784b9846f173611..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 471 zcmV;|0Vw{7P)X1^@s6+90*i00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP zgD?zKav8uIlul4a@CMBW$p*~^p%XNj06Ib^XgdMjpxppE0ez+KJ0HQuKy>#fu;rJK zB_T2(UDss_xwU}w1!#b8eU=5X=@I8pTi~8cHP(KiKY(_%T7Ag`*$k{HNlRyEs0ZK( z7`z+k3OGBPWWnJbQ<4St^)4!=ESp07lzIp@hhztgXi_wE@Sb8=0)s1k~NS4KQcpDj&Hy|M7~ri;BjzAyHYDf76?<5_t)2KX|r%p zX(w+(o{Kr9=$*IhlkzG^ZZ@(|Seh3n{f&4-q&u*#Z~SWclu+Kr33YrN`Sm(MpMlml zh&IFkp>gwt=T2jzppF@k(0YVrQYzhK4D4C&_gC}MR3BoT{+~#5_3Ar=+5t*%=>_>8 z6B+I9xHcNKn~eET9=-cG@!2r?v;r8*qt__Tu8>q=)F$BzZI?JI{s8Bgz0#>m@Ff5M N002ovPDHLkV1nYWz)t`G diff --git a/assets/images/notification_icon.svg b/assets/images/notification_icon.svg new file mode 100644 index 000000000..099039e67 --- /dev/null +++ b/assets/images/notification_icon.svg @@ -0,0 +1,69 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 732e58a18..05f78b809 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,2 +1,2 @@ -New themes +In-App live status page for the app services Bug fixes and enhancements \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 1c2ec154c..05f78b809 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,6 +1,2 @@ -Add Solana wallet -Support ALL Bitcoin address types (Legacy, Segwit (both variants), Taproot) -Enhance Sending/Receiving flow for Bitcoin -Improve fee calculations in Bitcoin -New themes +In-App live status page for the app services Bug fixes and enhancements \ No newline at end of file diff --git a/cw_core/lib/monero_transaction_priority.dart b/cw_core/lib/monero_transaction_priority.dart index f5c00ecc7..81058f336 100644 --- a/cw_core/lib/monero_transaction_priority.dart +++ b/cw_core/lib/monero_transaction_priority.dart @@ -1,7 +1,4 @@ import 'package:cw_core/transaction_priority.dart'; -import 'package:cw_core/wallet_type.dart'; -//import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cw_core/enumerable_item.dart'; class MoneroTransactionPriority extends TransactionPriority { const MoneroTransactionPriority({required String title, required int raw}) @@ -12,21 +9,20 @@ class MoneroTransactionPriority extends TransactionPriority { MoneroTransactionPriority.automatic, MoneroTransactionPriority.medium, MoneroTransactionPriority.fast, - MoneroTransactionPriority.fastest + MoneroTransactionPriority.fastest, ]; - static const slow = MoneroTransactionPriority(title: 'Slow', raw: 0); - static const automatic = MoneroTransactionPriority(title: 'Automatic', raw: 1); + static const automatic = MoneroTransactionPriority(title: 'Automatic', raw: 0); + static const slow = MoneroTransactionPriority(title: 'Slow', raw: 1); static const medium = MoneroTransactionPriority(title: 'Medium', raw: 2); static const fast = MoneroTransactionPriority(title: 'Fast', raw: 3); static const fastest = MoneroTransactionPriority(title: 'Fastest', raw: 4); - static const standard = slow; static MoneroTransactionPriority deserialize({required int raw}) { switch (raw) { case 0: - return slow; - case 1: return automatic; + case 1: + return slow; case 2: return medium; case 3: diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 58f63d7ce..5644f6f2e 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -282,9 +282,7 @@ abstract class MoneroWalletBase pendingTransactionDescription = await transaction_history.createTransaction( address: address!, amount: amount, - priorityRaw: _credentials.priority == MoneroTransactionPriority.automatic - ? MoneroTransactionPriority.medium.serialize() - : _credentials.priority.serialize(), + priorityRaw: _credentials.priority.serialize(), accountIndex: walletAddresses.account!.id, preferredInputs: inputs); } diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index fb3e9e80c..0851d00f5 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -201,6 +201,9 @@ Future defaultSettingsMigration( await changeSolanaCurrentNodeToDefault( sharedPreferences: sharedPreferences, nodes: nodes); break; + case 28: + await _updateMoneroPriority(sharedPreferences); + break; default: break; } @@ -215,6 +218,18 @@ Future defaultSettingsMigration( await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version); } +Future _updateMoneroPriority(SharedPreferences sharedPreferences) async { + final currentPriority = + await sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority) ?? + monero!.getDefaultTransactionPriority().serialize(); + + // was set to automatic but automatic should be 0 + if (currentPriority == 1) { + sharedPreferences.setInt(PreferencesKey.moneroTransactionPriority, + monero!.getDefaultTransactionPriority().serialize()); // 0 + } +} + Future _validateWalletInfoBoxData(Box walletInfoSource) async { try { final root = await getApplicationDocumentsDirectory(); diff --git a/lib/main.dart b/lib/main.dart index 0c8a4c094..a87bcfdad 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -163,7 +163,7 @@ Future initializeAppConfigs() async { transactionDescriptions: transactionDescriptions, secureStorage: secureStorage, anonpayInvoiceInfo: anonpayInvoiceInfo, - initialMigrationVersion: 27); + initialMigrationVersion: 28); } Future initialSetup( diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart index 8119e9fd4..940ab54ca 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart @@ -7,13 +7,15 @@ class SideMenuItem extends StatelessWidget { required this.onTap, this.imagePath, this.icon, + this.widget, this.isSelected = false, - }) : assert((icon != null && imagePath == null) || (icon == null && imagePath != null)); + }) : assert(widget != null || icon != null || imagePath != null); final void Function() onTap; final String? imagePath; final IconData? icon; final bool isSelected; + final Widget? widget; Color _setColor(BuildContext context) { if (isSelected) { @@ -28,18 +30,7 @@ class SideMenuItem extends StatelessWidget { return InkWell( child: Padding( padding: EdgeInsets.all(20), - child: icon != null - ? Icon( - icon, - color: _setColor(context), - ) - : Image.asset( - imagePath ?? '', - fit: BoxFit.cover, - height: 30, - width: 30, - color: _setColor(context), - ), + child: widget ?? _getIcon(context), ), onTap: () => onTap.call(), highlightColor: Colors.transparent, @@ -48,4 +39,19 @@ class SideMenuItem extends StatelessWidget { splashColor: Colors.transparent, ); } + + Widget _getIcon(BuildContext context) { + return icon != null + ? Icon( + icon, + color: _setColor(context), + ) + : Image.asset( + imagePath ?? '', + fit: BoxFit.cover, + height: 30, + width: 30, + color: _setColor(context), + ); + } } diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart index f73570048..d0ddb19e6 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart @@ -9,6 +9,7 @@ import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sideba import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator.dart'; import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/bottom_sheet_listener.dart'; +import 'package:cake_wallet/src/widgets/services_updates_widget.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart'; import 'package:flutter/cupertino.dart'; @@ -105,12 +106,18 @@ class DesktopSidebarWrapper extends BasePage { ? selectedIconPath : unselectedIconPath, ), + SideMenuItem( + widget: ServicesUpdatesWidget(dashboardViewModel.getServicesStatus()), + isSelected: desktopSidebarViewModel.currentPage == SidebarItem.status, + onTap: () {}, + ), ], bottomItems: [ SideMenuItem( - imagePath: 'assets/images/support_icon.png', - isSelected: desktopSidebarViewModel.currentPage == SidebarItem.support, - onTap: () => desktopSidebarViewModel.onPageChange(SidebarItem.support)), + imagePath: 'assets/images/support_icon.png', + isSelected: desktopSidebarViewModel.currentPage == SidebarItem.support, + onTap: () => desktopSidebarViewModel.onPageChange(SidebarItem.support), + ), SideMenuItem( imagePath: 'assets/images/settings_outline.png', isSelected: desktopSidebarViewModel.currentPage == SidebarItem.settings, diff --git a/lib/src/widgets/services_updates_widget.dart b/lib/src/widgets/services_updates_widget.dart index 7a8614b75..9557ff6b9 100644 --- a/lib/src/widgets/services_updates_widget.dart +++ b/lib/src/widgets/services_updates_widget.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/src/widgets/service_status_tile.dart'; import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -96,15 +97,16 @@ class ServicesUpdatesWidget extends StatelessWidget { : null, child: Stack( children: [ - Image.asset( - "assets/images/notification_icon.png", + SvgPicture.asset( + "assets/images/notification_icon.svg", color: Theme.of(context).extension()!.pageTitleTextColor, + width: 30, ), if (state.hasData && state.data!.hasUpdates) Container( height: 7, width: 7, - margin: EdgeInsetsDirectional.only(start: 8), + margin: EdgeInsetsDirectional.only(start: 15), decoration: BoxDecoration( color: Colors.red, shape: BoxShape.circle, diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index a21a92cb4..b02c09f82 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -344,15 +344,13 @@ abstract class DashboardViewModelBase with Store { bool hasExchangeAction; @computed - bool get isEnabledBuyAction => - !settingsStore.disableBuy && availableBuyProviders.isNotEmpty; + bool get isEnabledBuyAction => !settingsStore.disableBuy && availableBuyProviders.isNotEmpty; @observable bool hasBuyAction; @computed - bool get isEnabledSellAction => - !settingsStore.disableSell && availableSellProviders.isNotEmpty; + bool get isEnabledSellAction => !settingsStore.disableSell && availableSellProviders.isNotEmpty; @observable bool hasSellAction; @@ -477,7 +475,8 @@ abstract class DashboardViewModelBase with Store { Future> checkAffectedWallets() async { // await load file - final vulnerableSeedsString = await rootBundle.loadString('assets/text/cakewallet_weak_bitcoin_seeds_hashed_sorted_version1.txt'); + final vulnerableSeedsString = await rootBundle + .loadString('assets/text/cakewallet_weak_bitcoin_seeds_hashed_sorted_version1.txt'); final vulnerableSeeds = vulnerableSeedsString.split("\n"); final walletInfoSource = await CakeHive.openBox(WalletInfo.boxName); @@ -513,13 +512,16 @@ abstract class DashboardViewModelBase with Store { final oldSha = sharedPreferences.getString(PreferencesKey.serviceStatusShaKey); - final hash = await Cryptography.instance.sha256().hash(utf8.encode(res.body)); final currentSha = bytesToHex(hash.bytes); final hasUpdates = oldSha != currentSha; - return ServicesResponse.fromJson(json.decode(res.body) as Map, hasUpdates, currentSha); + return ServicesResponse.fromJson( + json.decode(res.body) as Map, + hasUpdates, + currentSha, + ); } catch (_) { return ServicesResponse([], false, ''); } diff --git a/lib/view_model/dashboard/desktop_sidebar_view_model.dart b/lib/view_model/dashboard/desktop_sidebar_view_model.dart index 543b44b35..52a6dc49b 100644 --- a/lib/view_model/dashboard/desktop_sidebar_view_model.dart +++ b/lib/view_model/dashboard/desktop_sidebar_view_model.dart @@ -5,6 +5,7 @@ part 'desktop_sidebar_view_model.g.dart'; enum SidebarItem { dashboard, transactions, + status, support, settings, } diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index fa3701fa7..eb1aaaacc 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.11.0" -MONERO_COM_BUILD_NUMBER=77 +MONERO_COM_VERSION="1.11.1" +MONERO_COM_BUILD_NUMBER=78 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.14.0" -CAKEWALLET_BUILD_NUMBER=196 +CAKEWALLET_VERSION="4.14.1" +CAKEWALLET_BUILD_NUMBER=197 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/android/build_monero.sh b/scripts/android/build_monero.sh index 7e9b58b6d..fb596e452 100755 --- a/scripts/android/build_monero.sh +++ b/scripts/android/build_monero.sh @@ -1,13 +1,12 @@ #!/bin/sh . ./config.sh -MONERO_BRANCH=release-v0.18.2.2-android_tx_priority_fix +MONERO_BRANCH=release-v0.18.3.2-android MONERO_SRC_DIR=${WORKDIR}/monero git clone https://github.com/cake-tech/monero.git ${MONERO_SRC_DIR} --branch ${MONERO_BRANCH} cd $MONERO_SRC_DIR -git submodule init -git submodule update +git submodule update --init --force for arch in "aarch" "aarch64" "i686" "x86_64" do @@ -59,7 +58,7 @@ cd $MONERO_SRC_DIR rm -rf ./build/release mkdir -p ./build/release cd ./build/release -CC=${CLANG} CXX=${CXXLANG} cmake -D USE_DEVICE_TREZOR=OFF -D BUILD_GUI_DEPS=1 -D BUILD_TESTS=OFF -D ARCH=${ARCH} -D STATIC=ON -D BUILD_64=${BUILD_64} -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D INSTALL_VENDORED_LIBUNBOUND=ON -D BUILD_TAG=${TAG} -D CMAKE_SYSTEM_NAME="Android" -D CMAKE_ANDROID_STANDALONE_TOOLCHAIN="${ANDROID_STANDALONE_TOOLCHAIN_PATH}" -D CMAKE_ANDROID_ARCH_ABI=${ARCH_ABI} $FLAGS ../.. +CC=${CLANG} CXX=${CXXLANG} cmake -D USE_DEVICE_TREZOR=OFF -D BUILD_GUI_DEPS=1 -D BUILD_TESTS=OFF -D ARCH=${ARCH} -D STATIC=ON -D BUILD_64=${BUILD_64} -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D INSTALL_VENDORED_LIBUNBOUND=ON -D BUILD_TAG=${TAG} -D CMAKE_SYSTEM_NAME="Android" -D CMAKE_ANDROID_STANDALONE_TOOLCHAIN="${ANDROID_STANDALONE_TOOLCHAIN_PATH}" -D CMAKE_ANDROID_ARCH_ABI=${ARCH_ABI} -D MANUAL_SUBMODULES=1 $FLAGS ../.. make wallet_api -j$THREADS find . -path ./lib -prune -o -name '*.a' -exec cp '{}' lib \; diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 31f0b9548..1c778063d 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.11.0" -MONERO_COM_BUILD_NUMBER=75 +MONERO_COM_VERSION="1.11.1" +MONERO_COM_BUILD_NUMBER=76 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.14.0" -CAKEWALLET_BUILD_NUMBER=215 +CAKEWALLET_VERSION="4.14.1" +CAKEWALLET_BUILD_NUMBER=216 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/ios/build_monero.sh b/scripts/ios/build_monero.sh index 2c81576f1..6f06f22c1 100755 --- a/scripts/ios/build_monero.sh +++ b/scripts/ios/build_monero.sh @@ -4,7 +4,7 @@ MONERO_URL="https://github.com/cake-tech/monero.git" MONERO_DIR_PATH="${EXTERNAL_IOS_SOURCE_DIR}/monero" -MONERO_VERSION=release-v0.18.2.2_tx_priority_fix +MONERO_VERSION=release-v0.18.3.2 BUILD_TYPE=release PREFIX=${EXTERNAL_IOS_DIR} DEST_LIB_DIR=${EXTERNAL_IOS_LIB_DIR}/monero @@ -52,6 +52,7 @@ cmake -D IOS=ON \ -DUNBOUND_INCLUDE_DIR=${EXTERNAL_IOS_INCLUDE_DIR} \ -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} \ -DUSE_DEVICE_TREZOR=OFF \ + -DMANUAL_SUBMODULES=1 \ ../.. make wallet_api -j4 find . -path ./lib -prune -o -name '*.a' -exec cp '{}' lib \; diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 4dec47f40..4c84832e6 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -16,13 +16,13 @@ if [ -n "$1" ]; then fi MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.1.0" -MONERO_COM_BUILD_NUMBER=7 +MONERO_COM_VERSION="1.1.1" +MONERO_COM_BUILD_NUMBER=9 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.7.0" -CAKEWALLET_BUILD_NUMBER=55 +CAKEWALLET_VERSION="1.7.1" +CAKEWALLET_BUILD_NUMBER=56 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then diff --git a/scripts/macos/build_monero.sh b/scripts/macos/build_monero.sh index 2a1ae89a5..1af7ae0e3 100755 --- a/scripts/macos/build_monero.sh +++ b/scripts/macos/build_monero.sh @@ -4,7 +4,7 @@ MONERO_URL="https://github.com/cake-tech/monero.git" MONERO_DIR_PATH="${EXTERNAL_MACOS_SOURCE_DIR}/monero" -MONERO_VERSION=release-v0.18.2.2_tx_priority_fix +MONERO_VERSION=release-v0.18.3.2 BUILD_TYPE=release PREFIX=${EXTERNAL_MACOS_DIR} DEST_LIB_DIR=${EXTERNAL_MACOS_LIB_DIR}/monero @@ -46,6 +46,7 @@ cmake -DARCH=${ARCH} \ -DUNBOUND_INCLUDE_DIR=${EXTERNAL_MACOS_INCLUDE_DIR} \ -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} \ -DUSE_DEVICE_TREZOR=OFF \ + -DMANUAL_SUBMODULES=1 \ ../.. make wallet_api -j4 find . -path ./lib -prune -o -name '*.a' -exec cp '{}' lib \; From 27347779fa55232f9ceea6ee4e8c7466101b85a3 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Mon, 18 Mar 2024 17:45:11 +0200 Subject: [PATCH 128/241] New versions (#1334) * Enable Exolix Improve service updates indicator New versions * Add exolix Api token to limits api * Ignore reporting network issues * Change default bitcoin node --- assets/text/Monerocom_Release_Notes.txt | 2 ++ assets/text/Release_Notes.txt | 3 +++ cw_monero/lib/monero_wallet.dart | 8 +----- lib/entities/default_settings_migration.dart | 27 +++++++++++++++++++ .../provider/exolix_exchange_provider.dart | 1 + lib/main.dart | 2 +- lib/src/widgets/services_updates_widget.dart | 13 +++++++-- lib/utils/feature_flag.dart | 2 +- scripts/android/app_env.sh | 8 +++--- scripts/ios/app_env.sh | 8 +++--- scripts/macos/app_env.sh | 8 +++--- 11 files changed, 59 insertions(+), 23 deletions(-) diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 05f78b809..90fcd2a75 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,2 +1,4 @@ +Monero enhancements In-App live status page for the app services +Add Exolix exchange provider Bug fixes and enhancements \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 05f78b809..d8d4ed830 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,2 +1,5 @@ +Monero enhancements +Bitcoin support different address types (Taproot, Segwit P2WPKH/P2WSH, Legacy) In-App live status page for the app services +Add Exolix exchange provider Bug fixes and enhancements \ No newline at end of file diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 5644f6f2e..d00a54c8f 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -574,13 +574,7 @@ abstract class MoneroWalletBase int height = 0; try { height = _getHeightByDate(walletInfo.date); - } catch (e, s) { - onError?.call(FlutterErrorDetails( - exception: e, - stack: s, - library: this.runtimeType.toString(), - )); - } + } catch (_) {} monero_wallet.setRecoveringFromSeed(isRecovery: true); monero_wallet.setRefreshFromBlockHeight(height: height); diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 0851d00f5..8ce38e4c4 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -35,6 +35,7 @@ const cakeWalletBitcoinCashDefaultNodeUri = 'bitcoincash.stackwallet.com:50002'; const nanoDefaultNodeUri = 'rpc.nano.to'; const nanoDefaultPowNodeUri = 'rpc.nano.to'; const solanaDefaultNodeUri = 'rpc.ankr.com'; +const newCakeWalletBitcoinUri = 'btc-electrum.cakewallet.com:50002'; Future defaultSettingsMigration( {required int version, @@ -201,9 +202,15 @@ Future defaultSettingsMigration( await changeSolanaCurrentNodeToDefault( sharedPreferences: sharedPreferences, nodes: nodes); break; + case 28: await _updateMoneroPriority(sharedPreferences); break; + + case 29: + await changeDefaultBitcoinNode(nodes, sharedPreferences); + break; + default: break; } @@ -702,6 +709,26 @@ Future changeDefaultMoneroNode( } } +Future changeDefaultBitcoinNode( + Box nodeSource, SharedPreferences sharedPreferences) async { + const cakeWalletBitcoinNodeUriPattern = '.cakewallet.com'; + final currentBitcoinNodeId = + sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); + final currentBitcoinNode = + nodeSource.values.firstWhere((node) => node.key == currentBitcoinNodeId); + final needToReplaceCurrentBitcoinNode = + currentBitcoinNode.uri.toString().contains(cakeWalletBitcoinNodeUriPattern); + + final newCakeWalletBitcoinNode = Node(uri: newCakeWalletBitcoinUri, type: WalletType.bitcoin); + + await nodeSource.add(newCakeWalletBitcoinNode); + + if (needToReplaceCurrentBitcoinNode) { + await sharedPreferences.setInt( + PreferencesKey.currentBitcoinElectrumSererIdKey, newCakeWalletBitcoinNode.key as int); + } +} + Future checkCurrentNodes( Box nodeSource, Box powNodeSource, SharedPreferences sharedPreferences) async { final currentMoneroNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey); diff --git a/lib/exchange/provider/exolix_exchange_provider.dart b/lib/exchange/provider/exolix_exchange_provider.dart index eb40aff73..9374439f3 100644 --- a/lib/exchange/provider/exolix_exchange_provider.dart +++ b/lib/exchange/provider/exolix_exchange_provider.dart @@ -66,6 +66,7 @@ class ExolixExchangeProvider extends ExchangeProvider { final params = { 'rateType': _getRateType(isFixedRateMode), 'amount': '1', + 'apiToken': apiKey, }; if (isFixedRateMode) { params['coinFrom'] = _normalizeCurrency(to); diff --git a/lib/main.dart b/lib/main.dart index a87bcfdad..db505f15a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -163,7 +163,7 @@ Future initializeAppConfigs() async { transactionDescriptions: transactionDescriptions, secureStorage: secureStorage, anonpayInvoiceInfo: anonpayInvoiceInfo, - initialMigrationVersion: 28); + initialMigrationVersion: 29); } Future initialSetup( diff --git a/lib/src/widgets/services_updates_widget.dart b/lib/src/widgets/services_updates_widget.dart index 9557ff6b9..65dbe5e40 100644 --- a/lib/src/widgets/services_updates_widget.dart +++ b/lib/src/widgets/services_updates_widget.dart @@ -10,17 +10,24 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher.dart'; -class ServicesUpdatesWidget extends StatelessWidget { +class ServicesUpdatesWidget extends StatefulWidget { final Future servicesResponse; const ServicesUpdatesWidget(this.servicesResponse, {super.key}); + @override + State createState() => _ServicesUpdatesWidgetState(); +} + +class _ServicesUpdatesWidgetState extends State { + bool wasOpened = false; + @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(8.0), child: FutureBuilder( - future: servicesResponse, + future: widget.servicesResponse, builder: (context, state) { return InkWell( onTap: state.hasData @@ -30,6 +37,8 @@ class ServicesUpdatesWidget extends StatelessWidget { .get() .setString(PreferencesKey.serviceStatusShaKey, state.data!.currentSha); + setState(() => wasOpened = true); + showModalBottomSheet( context: context, shape: RoundedRectangleBorder( diff --git a/lib/utils/feature_flag.dart b/lib/utils/feature_flag.dart index 91a4c67ca..2a29bd949 100644 --- a/lib/utils/feature_flag.dart +++ b/lib/utils/feature_flag.dart @@ -1,5 +1,5 @@ class FeatureFlag { static const bool isCakePayEnabled = false; - static const bool isExolixEnabled = false; + static const bool isExolixEnabled = true; static const bool isInAppTorEnabled = false; } \ No newline at end of file diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index eb1aaaacc..02f874d77 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.11.1" -MONERO_COM_BUILD_NUMBER=78 +MONERO_COM_VERSION="1.12.0" +MONERO_COM_BUILD_NUMBER=79 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.14.1" -CAKEWALLET_BUILD_NUMBER=197 +CAKEWALLET_VERSION="4.15.0" +CAKEWALLET_BUILD_NUMBER=198 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 1c778063d..b65d3e7a6 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.11.1" -MONERO_COM_BUILD_NUMBER=76 +MONERO_COM_VERSION="1.12.0" +MONERO_COM_BUILD_NUMBER=77 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.14.1" -CAKEWALLET_BUILD_NUMBER=216 +CAKEWALLET_VERSION="4.15.0" +CAKEWALLET_BUILD_NUMBER=217 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 4c84832e6..19a1e6846 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -16,13 +16,13 @@ if [ -n "$1" ]; then fi MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.1.1" -MONERO_COM_BUILD_NUMBER=9 +MONERO_COM_VERSION="1.2.0" +MONERO_COM_BUILD_NUMBER=10 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.7.1" -CAKEWALLET_BUILD_NUMBER=56 +CAKEWALLET_VERSION="1.8.0" +CAKEWALLET_BUILD_NUMBER=57 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From 58b2dfb26cc32a1f445ad916b941fea2c910349f Mon Sep 17 00:00:00 2001 From: Serhii Date: Tue, 19 Mar 2024 21:55:34 +0200 Subject: [PATCH 129/241] Fix deep link handling issue (#1297) * Update root.dart * Revert "Update root.dart" This reverts commit 5808903aafa81c316eb8a32a462ee18392e08f2f. * Update root.dart * increase delay * fix with mobx reaction * lunchUri fix --- lib/src/screens/root/root.dart | 42 ++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index 5704c99ad..8a75b78bb 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/payment_request.dart'; +import 'package:cw_core/wallet_base.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; @@ -12,6 +13,7 @@ import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/authentication_store.dart'; import 'package:cake_wallet/entities/qr_scanner.dart'; import 'package:fluttertoast/fluttertoast.dart'; +import 'package:mobx/mobx.dart'; import 'package:uni_links/uni_links.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart'; @@ -49,6 +51,7 @@ class RootState extends State with WidgetsBindingObserver { bool _requestAuth; StreamSubscription? stream; + ReactionDisposer? _walletReactionDisposer; Uri? launchUri; @override @@ -72,6 +75,7 @@ class RootState extends State with WidgetsBindingObserver { @override void dispose() { stream?.cancel(); + _walletReactionDisposer?.call(); super.dispose(); } @@ -169,10 +173,20 @@ class RootState extends State with WidgetsBindingObserver { ); }); } else if (_isValidPaymentUri()) { - widget.navigatorKey.currentState?.pushNamed( - Routes.send, - arguments: PaymentRequest.fromUri(launchUri), - ); + if (widget.authenticationStore.state == AuthenticationState.uninitialized) { + launchUri = null; + } else { + if (widget.appStore.wallet == null) { + waitForWalletInstance(context, launchUri!); + launchUri = null; + } else { + widget.navigatorKey.currentState?.pushNamed( + Routes.send, + arguments: PaymentRequest.fromUri(launchUri), + ); + launchUri = null; + } + } launchUri = null; } else if (isWalletConnectLink) { if (isEVMCompatibleChain(widget.appStore.wallet!.type)) { @@ -233,4 +247,24 @@ class RootState extends State with WidgetsBindingObserver { fontSize: 16.0, ); } + + void waitForWalletInstance(BuildContext context, Uri tempLaunchUri) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (context.mounted) { + _walletReactionDisposer = reaction( + (_) => widget.appStore.wallet, + (WalletBase? wallet) { + if (wallet != null) { + widget.navigatorKey.currentState?.pushNamed( + Routes.send, + arguments: PaymentRequest.fromUri(tempLaunchUri), + ); + _walletReactionDisposer?.call(); + _walletReactionDisposer = null; + } + }, + ); + } + }); + } } From a0c0ede0998124bf68b89ab95366f63613ea37d0 Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 20 Mar 2024 00:44:00 +0200 Subject: [PATCH 130/241] Cw 588 show popup for adding to address book (#1326) * popup for adding to address book * update localization files --- lib/src/screens/send/send_page.dart | 58 ++++++++++++++----- .../contact_list/contact_view_model.dart | 4 +- lib/view_model/send/send_view_model.dart | 29 ++++++++++ res/values/strings_ar.arb | 1 + res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 1 + res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 1 + res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_th.arb | 1 + res/values/strings_tl.arb | 1 + res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + 29 files changed, 103 insertions(+), 18 deletions(-) diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index a3b7eaf85..a4c095739 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/core/auth_service.dart'; +import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/entities/template.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; @@ -48,6 +49,7 @@ class SendPage extends BasePage { final PaymentRequest? initialPaymentRequest; bool _effectsInstalled = false; + ContactRecord? newContactAddress; @override String get title => S.current.send; @@ -443,22 +445,50 @@ class SendPage extends BasePage { } if (state is TransactionCommitted) { - String alertContent; - if (sendViewModel.walletType == WalletType.solana) { - alertContent = - '${S.of(_dialogContext).send_success(sendViewModel.selectedCryptoCurrency.toString())}. ${S.of(_dialogContext).waitFewSecondForTxUpdate}'; + newContactAddress = + newContactAddress ?? sendViewModel.newContactAddress(); + + final successMessage = S.of(_dialogContext).send_success( + sendViewModel.selectedCryptoCurrency.toString()); + + final waitMessage = sendViewModel.walletType == WalletType.solana + ? '. ${S.of(_dialogContext).waitFewSecondForTxUpdate}' : ''; + + final newContactMessage = newContactAddress != null + ? '\n${S.of(context).add_contact_to_address_book}' : ''; + + final alertContent = + "$successMessage$waitMessage$newContactMessage"; + + if (newContactAddress != null) { + return AlertWithTwoActions( + alertTitle: '', + alertContent: alertContent, + rightButtonText: S.of(_dialogContext).add_contact, + leftButtonText: S.of(_dialogContext).ignor, + 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 { - alertContent = S.of(_dialogContext).send_success( - sendViewModel.selectedCryptoCurrency.toString()); + return AlertWithOneAction( + alertTitle: '', + alertContent: alertContent, + buttonText: S.of(_dialogContext).ok, + buttonAction: () { + Navigator.of(_dialogContext).pop(); + RequestReviewHandler.requestReview(); + }); } - return AlertWithOneAction( - alertTitle: '', - alertContent: alertContent, - buttonText: S.of(_dialogContext).ok, - buttonAction: () { - Navigator.of(_dialogContext).pop(); - RequestReviewHandler.requestReview(); - }); } return Offstage(); diff --git a/lib/view_model/contact_list/contact_view_model.dart b/lib/view_model/contact_list/contact_view_model.dart index 258348d3d..053cfe4c5 100644 --- a/lib/view_model/contact_list/contact_view_model.dart +++ b/lib/view_model/contact_list/contact_view_model.dart @@ -48,11 +48,11 @@ abstract class ContactViewModelBase with Store { currency = null; } - Future save() async { + Future save() async { try { state = IsExecutingState(); - if (_contact != null) { + if (_contact != null && _contact!.original.isInBox) { _contact?.name = name; _contact?.address = address; _contact?.type = currency!; diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 507ed14cc..7636c485a 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/entities/contact.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'; @@ -420,6 +421,34 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor } } + ContactRecord? newContactAddress () { + + final Set contactAddresses = + Set.from(contactListViewModel.contacts.map((contact) => contact.address)) + ..addAll(contactListViewModel.walletContacts.map((contact) => contact.address)); + + for (var output in outputs) { + String address; + if (output.isParsedAddress) { + address = output.parsedAddress.addresses.first; + } else { + address = output.address; + } + + if (address.isNotEmpty && !contactAddresses.contains(address)) { + + return ContactRecord( + contactListViewModel.contactSource, + Contact( + name: '', + address: address, + type: selectedCryptoCurrency, + )); + } + } + return null; + } + String translateErrorMessage( String error, WalletType walletType, diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index a5ea72ce7..900f59135 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "ﺎﻨﻫ ﺔﻄﺸﻨﻟﺍ ﺕﻻﺎﺼﺗﻻﺍ ﺮﻬﻈﺘﺳ", "add": "إضافة", "add_contact": "ﻝﺎﺼﺗﺍ ﺔﻬﺟ ﺔﻓﺎﺿﺇ", + "add_contact_to_address_book": "هل ترغب في إضافة جهة الاتصال هذه إلى دفتر العناوين الخاص بك؟", "add_custom_node": "إضافة عقدة مخصصة جديدة", "add_custom_redemption": "إضافة استرداد مخصص", "add_fund_to_card": "أضف أموالاً مدفوعة مسبقًا إلى البطاقات (حتى ${value})", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index a42460619..3e8cd148e 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Тук ще се появят активни връзки", "add": "Добави", "add_contact": "Добави контакт", + "add_contact_to_address_book": "Искате ли да добавите този контакт към вашата адресна книга?", "add_custom_node": "Добавяне на нов персонализиран Node", "add_custom_redemption": "Добавете персонализиран Redemption", "add_fund_to_card": "Добавете предплатени средства в картите (до ${value})", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 8970d394a..8a5213821 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Zde se zobrazí aktivní připojení", "add": "Přidat", "add_contact": "Přidat kontakt", + "add_contact_to_address_book": "Chcete přidat tento kontakt do svého adresáře?", "add_custom_node": "Přidat vlastní uzel", "add_custom_redemption": "Přidat vlastní uplatnění", "add_fund_to_card": "Všechny předplacené prostředky na kartě (až ${value})", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 93d421061..549f6f775 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Hier werden aktive Verbindungen angezeigt", "add": "Hinzufügen", "add_contact": "Kontakt hinzufügen", + "add_contact_to_address_book": "Möchten Sie diesen Kontakt zu Ihrem Adressbuch hinzufügen?", "add_custom_node": "Neuen benutzerdefinierten Knoten hinzufügen", "add_custom_redemption": "Benutzerdefinierte Einlösung hinzufügen", "add_fund_to_card": "Prepaid-Guthaben zu den Karten hinzufügen (bis zu ${value})", @@ -410,8 +411,8 @@ "placeholder_transactions": "Ihre Transaktionen werden hier angezeigt", "please_fill_totp": "Bitte geben Sie den 8-stelligen Code ein, der auf Ihrem anderen Gerät vorhanden ist", "please_make_selection": "Bitte treffen Sie unten eine Auswahl zum Erstellen oder Wiederherstellen Ihrer Wallet.", - "please_reference_document": "Bitte verweisen Sie auf die folgenden Dokumente, um weitere Informationen zu erhalten.", "Please_reference_document": "Weitere Informationen finden Sie in den Dokumenten unten.", + "please_reference_document": "Bitte verweisen Sie auf die folgenden Dokumente, um weitere Informationen zu erhalten.", "please_select": "Bitte auswählen:", "please_select_backup_file": "Bitte wählen Sie die Sicherungsdatei und geben Sie das Sicherungskennwort ein.", "please_try_to_connect_to_another_node": "Bitte versuchen Sie, sich mit einem anderen Knoten zu verbinden", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 4ccade317..9b1610da5 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Active connections will appear here", "add": "Add", "add_contact": "Add contact", + "add_contact_to_address_book": "Would you like to add this contact to your address book?", "add_custom_node": "Add New Custom Node", "add_custom_redemption": "Add Custom Redemption", "add_fund_to_card": "Add prepaid funds to the cards (up to ${value})", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 611f3bd35..4847f5521 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Las conexiones activas aparecerán aquí", "add": "Añadir", "add_contact": "Agregar contacto", + "add_contact_to_address_book": "¿Le gustaría agregar este contacto a su libreta de direcciones?", "add_custom_node": "Agregar nuevo nodo personalizado", "add_custom_redemption": "Agregar redención personalizada", "add_fund_to_card": "Agregar fondos prepagos a las tarjetas (hasta ${value})", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index f00a85310..d1390a5ca 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Les connexions actives apparaîtront ici", "add": "Ajouter", "add_contact": "Ajouter le contact", + "add_contact_to_address_book": "Souhaitez-vous ajouter ce contact à votre carnet d'adresses?", "add_custom_node": "Ajouter un nouveau nœud personnalisé", "add_custom_redemption": "Ajouter un remboursement personnalisé", "add_fund_to_card": "Ajouter des fonds prépayés aux cartes (jusqu'à ${value})", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index ab314af7f..e9bd604d2 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Haɗin kai mai aiki zai bayyana a nan", "add": "Ƙara", "add_contact": "Ƙara lamba", + "add_contact_to_address_book": "Kuna so ku ƙara wannan lamba zuwa littafin adireshinku?", "add_custom_node": "Ƙara Sabon Kulli na Custom", "add_custom_redemption": "Ƙara Ceto na Musamman", "add_fund_to_card": "Ƙara kuɗin da aka riga aka biya a katunan (har zuwa ${value})", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index da7d97c46..535fd0264 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "सक्रिय कनेक्शन यहां दिखाई देंगे", "add": "जोड़ना", "add_contact": "संपर्क जोड़ें", + "add_contact_to_address_book": "क्या आप इस संपर्क को अपनी एड्रेस बुक में जोड़ना चाहेंगे?", "add_custom_node": "नया कस्टम नोड जोड़ें", "add_custom_redemption": "कस्टम रिडेम्पशन जोड़ें", "add_fund_to_card": "कार्ड में प्रीपेड धनराशि जोड़ें (${value} तक)", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 22b486a1c..9a7cab450 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Ovdje će se pojaviti aktivne veze", "add": "Dodaj", "add_contact": "Dodaj kontakt", + "add_contact_to_address_book": "Želite li dodati ovaj kontakt u svoj adresar?", "add_custom_node": "Dodaj novi prilagođeni čvor", "add_custom_redemption": "Dodaj prilagođeni otkup", "add_fund_to_card": "Dodajte unaprijed uplaćena sredstva na kartice (do ${value})", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index a2f3ed017..f29298c4f 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Koneksi aktif akan muncul di sini", "add": "Menambahkan", "add_contact": "Tambah kontak", + "add_contact_to_address_book": "Apakah Anda ingin menambahkan kontak ini ke buku alamat Anda?", "add_custom_node": "Tambahkan Node Kustom Baru", "add_custom_redemption": "Tambahkan Tukar Kustom", "add_fund_to_card": "Tambahkan dana pra-bayar ke kartu (hingga ${value})", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 015b63d47..82dd6b976 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Le connessioni attive verranno visualizzate qui", "add": "Aggiungi", "add_contact": "Aggiungi contatto", + "add_contact_to_address_book": "Vorresti aggiungere questo contatto alla tua rubrica?", "add_custom_node": "Aggiungi nuovo nodo personalizzato", "add_custom_redemption": "Aggiungi riscatto personalizzato", "add_fund_to_card": "Aggiungi fondi prepagati alle carte (fino a ${value})", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 36ec1932b..95a7643b0 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "アクティブな接続がここに表示されます", "add": "加える", "add_contact": "連絡先を追加", + "add_contact_to_address_book": "この連絡先をアドレス帳に追加しますか?", "add_custom_node": "新しいカスタム ノードを追加", "add_custom_redemption": "カスタム引き換えを追加", "add_fund_to_card": "プリペイド資金をカードに追加します(最大 ${value})", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index b51f42e8f..e8b208c28 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "활성 연결이 여기에 표시됩니다", "add": "더하다", "add_contact": "주소록에 추가", + "add_contact_to_address_book": "이 연락처를 주소록에 추가 하시겠습니까?", "add_custom_node": "새 사용자 정의 노드 추가", "add_custom_redemption": "사용자 지정 상환 추가", "add_fund_to_card": "카드에 선불 금액 추가(최대 ${value})", @@ -410,8 +411,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": "다른 노드에 연결을 시도하십시오", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index fe719a82b..42ea07cb6 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "လက်ရှိချိတ်ဆက်မှုများ ဤနေရာတွင် ပေါ်လာပါမည်။", "add": "ထည့်ပါ။", "add_contact": "အဆက်အသွယ်ထည့်ပါ။", + "add_contact_to_address_book": "ဒီအဆက်အသွယ်ကိုမင်းရဲ့လိပ်စာစာအုပ်နဲ့ထပ်ထည့်ချင်ပါသလား။", "add_custom_node": "စိတ်ကြိုက် Node အသစ်ကို ထည့်ပါ။", "add_custom_redemption": "စိတ်ကြိုက်ရွေးယူမှုကို ထည့်ပါ။", "add_fund_to_card": "ကတ်များသို့ ကြိုတင်ငွေပေးငွေများ ထည့်ပါ (${value} အထိ)", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index ed5054abe..a00a12338 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Actieve verbindingen worden hier weergegeven", "add": "Toevoegen", "add_contact": "Contactpersoon toevoegen", + "add_contact_to_address_book": "Wilt u dit contact toevoegen aan uw adresboek?", "add_custom_node": "Voeg een nieuw aangepast knooppunt toe", "add_custom_redemption": "Voeg aangepaste inwisseling toe", "add_fund_to_card": "Voeg prepaid tegoed toe aan de kaarten (tot ${value})", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index aa567799e..1ad616bc9 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Tutaj pojawią się aktywne połączenia", "add": "Dodaj", "add_contact": "Dodaj kontakt", + "add_contact_to_address_book": "Czy chciałbyś dodać ten kontakt do swojej książki adresowej?", "add_custom_node": "Dodaj nowy węzeł niestandardowy", "add_custom_redemption": "Dodaj niestandardowe wykorzystanie", "add_fund_to_card": "Dodaj przedpłacone środki do kart (do ${value})", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index b0aa7cab5..c1b579186 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Conexões ativas aparecerão aqui", "add": "Adicionar", "add_contact": "Adicionar contato", + "add_contact_to_address_book": "Você gostaria de adicionar esse contato ao seu catálogo de endereços?", "add_custom_node": "Adicionar novo nó personalizado", "add_custom_redemption": "Adicionar resgate personalizado", "add_fund_to_card": "Adicionar fundos pré-pagos aos cartões (até ${value})", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index bfb7b62d7..f327f126a 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Здесь появятся активные подключения", "add": "Добавить", "add_contact": "Добавить контакт", + "add_contact_to_address_book": "Хотели бы вы добавить этот контакт в свою адресную книгу?", "add_custom_node": "Добавить новый пользовательский узел", "add_custom_redemption": "Добавить пользовательское погашение", "add_fund_to_card": "Добавить предоплаченные средства на карты (до ${value})", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 5da17828f..255b80df7 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "การเชื่อมต่อที่ใช้งานอยู่จะปรากฏที่นี่", "add": "เพิ่ม", "add_contact": "เพิ่มผู้ติดต่อ", + "add_contact_to_address_book": "คุณต้องการเพิ่มผู้ติดต่อนี้ในสมุดที่อยู่ของคุณหรือไม่?", "add_custom_node": "เพิ่มจุดโหนดแบบกำหนดเอง", "add_custom_redemption": "เพิ่มการรับคืนที่กำหนดเอง", "add_fund_to_card": "เพิ่มเงินสำรองไว้บนบัตร (ถึง ${value})", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index e0a0b1eae..1d7063881 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Lalabas dito ang mga aktibong koneksyon", "add": "Idagdag", "add_contact": "Magdagdag ng contact", + "add_contact_to_address_book": "Nais mo bang idagdag ang contact na ito sa iyong address book?", "add_custom_node": "Magdagdag ng bagong pasadyang node", "add_custom_redemption": "Magdagdag ng pasadyang pagtubos", "add_fund_to_card": "Magdagdag ng prepaid na pondo sa mga kard (hanggang sa ${value})", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index c4d64305e..99879d5ef 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Aktif bağlantılar burada görünecek", "add": "Ekle", "add_contact": "Kişi ekle", + "add_contact_to_address_book": "Bu kişiyi adres defterinize eklemek ister misiniz?", "add_custom_node": "Yeni Özel Düğüm Ekleme", "add_custom_redemption": "Özel Bozdurma Ekle", "add_fund_to_card": "Ön ödemeli kartlara para ekle (En fazla yüklenebilir tutar: ${value})", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 59371cdbe..63c59d475 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Тут з’являться активні підключення", "add": "Добавити", "add_contact": "Додати контакт", + "add_contact_to_address_book": "Хотіли б ви додати цей контакт до своєї адресної книги?", "add_custom_node": "Додати новий спеціальний вузол", "add_custom_redemption": "Додати спеціальне погашення", "add_fund_to_card": "Додайте передплачені кошти на картки (до ${value})", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 73b758561..08212c0b1 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "۔ﮯﮔ ﮞﻮﮨ ﺮﮨﺎﻇ ﮞﺎﮩﯾ ﺰﻨﺸﮑﻨﮐ ﻝﺎﻌﻓ", "add": "شامل کریں۔", "add_contact": "۔ﮟﯾﺮﮐ ﻞﻣﺎﺷ ﮧﻄﺑﺍﺭ", + "add_contact_to_address_book": "کیا آپ اس رابطہ کو اپنی ایڈریس بک میں شامل کرنا چاہیں گے؟", "add_custom_node": "نیا کسٹم نوڈ شامل کریں۔", "add_custom_redemption": "حسب ضرورت چھٹکارا شامل کریں۔", "add_fund_to_card": "کارڈز میں پری پیڈ فنڈز شامل کریں (${value} تک)", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 4ccf10ff6..f9b198843 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "Awọn asopọ ti nṣiṣe lọwọ yoo han nibi", "add": "Fikún", "add_contact": "Fi olubasọrọ kun", + "add_contact_to_address_book": "Ṣe o fẹ lati ṣafikun olubasọrọ yii si iwe adirẹsi rẹ?", "add_custom_node": "Fikún apẹka títun t'ẹ́ pààrọ̀", "add_custom_redemption": "Tẹ̀ iye owó t'ẹ́ fẹ́ ná", "add_fund_to_card": "Ẹ fikún owó sí àwọn káàdì (kò tóbi ju ${value})", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 3cff27996..8a61a6a4a 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -9,6 +9,7 @@ "activeConnectionsPrompt": "活动连接将出现在这里", "add": "添加", "add_contact": "增加联系人", + "add_contact_to_address_book": "您想将此联系人添加到您的通讯录中吗?", "add_custom_node": "添加新的自定义节点", "add_custom_redemption": "添加自定义兑换", "add_fund_to_card": "向卡中添加预付资金(最多 ${value})", From 5a7a0e01a735849435b56930a3efa998805db657 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Thu, 21 Mar 2024 04:51:57 +0200 Subject: [PATCH 131/241] Litcoin bitcoin cash fix (#1339) * Make address to output script a single entry point Fix network type for bitcoin cash * Add MoonPay to sell polygon * Normalize currency for moonpay widget * Minor fix * fix: litecoin & bch address types * fix: remove print * fix: network decode location * fix: missing place additional network type * fix: wrong initial address page type * fix: initial address generation * fix: btc exchange sending all, bch without change addresses * Minor fixes * Update app versions [skip ci] --------- Co-authored-by: Rafael Saes --- assets/text/Release_Notes.txt | 4 - cw_bitcoin/lib/address_to_output_script.dart | 3 + cw_bitcoin/lib/bitcoin_address_record.dart | 15 +- cw_bitcoin/lib/bitcoin_wallet.dart | 8 +- cw_bitcoin/lib/electrum_wallet.dart | 56 ++- cw_bitcoin/lib/electrum_wallet_addresses.dart | 41 +- cw_bitcoin/lib/electrum_wallet_snapshot.dart | 10 +- cw_bitcoin/lib/script_hash.dart | 7 +- cw_bitcoin/pubspec.lock | 10 +- cw_bitcoin/pubspec.yaml | 4 +- .../lib/src/bitcoin_cash_wallet.dart | 28 +- .../src/bitcoin_cash_wallet_addresses.dart | 1 + cw_bitcoin_cash/pubspec.yaml | 2 +- ios/Podfile.lock | 4 +- lib/bitcoin/cw_bitcoin.dart | 24 +- lib/buy/moonpay/moonpay_provider.dart | 10 +- lib/core/address_validator.dart | 2 +- lib/entities/provider_types.dart | 7 +- lib/src/screens/exchange/exchange_page.dart | 21 +- .../exchange/exchange_template_page.dart | 365 ++++++++---------- .../exchange/widgets/exchange_card.dart | 242 ++++++------ lib/src/screens/send/send_template_page.dart | 12 +- lib/src/screens/send/widgets/send_card.dart | 23 +- .../exchange/exchange_view_model.dart | 27 +- macos/Podfile.lock | 2 +- pubspec_base.yaml | 2 +- scripts/android/app_env.sh | 4 +- scripts/ios/app_env.sh | 4 +- scripts/macos/app_env.sh | 4 +- tool/configure.dart | 2 +- 30 files changed, 497 insertions(+), 447 deletions(-) diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index d8d4ed830..83e18c18e 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,5 +1 @@ -Monero enhancements -Bitcoin support different address types (Taproot, Segwit P2WPKH/P2WSH, Legacy) -In-App live status page for the app services -Add Exolix exchange provider Bug fixes and enhancements \ No newline at end of file diff --git a/cw_bitcoin/lib/address_to_output_script.dart b/cw_bitcoin/lib/address_to_output_script.dart index 6ae50132b..892f7a0d6 100644 --- a/cw_bitcoin/lib/address_to_output_script.dart +++ b/cw_bitcoin/lib/address_to_output_script.dart @@ -3,6 +3,9 @@ import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin; List addressToOutputScript(String address, bitcoin.BasedUtxoNetwork network) { try { + if (network == bitcoin.BitcoinCashNetwork.mainnet) { + return bitcoin.BitcoinCashAddress(address).baseAddress.toScriptPubKey().toBytes(); + } return bitcoin.addressToOutputScript(address: address, network: network); } catch (err) { print(err); diff --git a/cw_bitcoin/lib/bitcoin_address_record.dart b/cw_bitcoin/lib/bitcoin_address_record.dart index d8d908230..d1c3b6a61 100644 --- a/cw_bitcoin/lib/bitcoin_address_record.dart +++ b/cw_bitcoin/lib/bitcoin_address_record.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'package:bitbox/bitbox.dart' as bitbox; import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/script_hash.dart' as sh; @@ -20,10 +19,9 @@ class BitcoinAddressRecord { _balance = balance, _name = name, _isUsed = isUsed, - scriptHash = - scriptHash ?? (network != null ? sh.scriptHash(address, network: network) : null); + scriptHash = scriptHash ?? sh.scriptHash(address, network: network); - factory BitcoinAddressRecord.fromJSON(String jsonSource, BasedUtxoNetwork? network) { + factory BitcoinAddressRecord.fromJSON(String jsonSource, BasedUtxoNetwork network) { final decoded = json.decode(jsonSource) as Map; return BitcoinAddressRecord( @@ -39,9 +37,7 @@ class BitcoinAddressRecord { .firstWhere((type) => type.toString() == decoded['type'] as String) : SegwitAddresType.p2wpkh, scriptHash: decoded['scriptHash'] as String?, - network: (decoded['network'] as String?) == null - ? network - : BasedUtxoNetwork.fromName(decoded['network'] as String), + network: network, ); } @@ -56,7 +52,7 @@ class BitcoinAddressRecord { String _name; bool _isUsed; String? scriptHash; - BasedUtxoNetwork? network; + BasedUtxoNetwork network; int get txCount => _txCount; @@ -76,8 +72,6 @@ class BitcoinAddressRecord { @override int get hashCode => address.hashCode; - String get cashAddr => bitbox.Address.toCashAddress(address); - BitcoinAddressType type; String updateScriptHash(BasedUtxoNetwork network) { @@ -95,6 +89,5 @@ class BitcoinAddressRecord { 'balance': balance, 'type': type.toString(), 'scriptHash': scriptHash, - 'network': network?.value, }); } diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 3b3e9c636..bf59e8637 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -92,8 +92,10 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required Box unspentCoinsInfo, required String password, }) async { - final snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password, - walletInfo.network != null ? BasedUtxoNetwork.fromName(walletInfo.network!) : null); + final network = walletInfo.network != null + ? BasedUtxoNetwork.fromName(walletInfo.network!) + : BitcoinNetwork.mainnet; + final snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password, network); return BitcoinWallet( mnemonic: snp.mnemonic, @@ -106,7 +108,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialRegularAddressIndex: snp.regularAddressIndex, initialChangeAddressIndex: snp.changeAddressIndex, addressPageType: snp.addressPageType, - networkParam: snp.network, + networkParam: network, ); } } diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index c3f40a235..86fbd6dbe 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -75,11 +75,7 @@ abstract class ElectrumWalletBase } : {}), this.unspentCoinsInfo = unspentCoinsInfo, - this.network = networkType == bitcoin.bitcoin - ? BitcoinNetwork.mainnet - : networkType == litecoinNetwork - ? LitecoinNetwork.mainnet - : BitcoinNetwork.testnet, + this.network = _getNetwork(networkType, currency), this.isTestnet = networkType == bitcoin.testnet, super(walletInfo) { this.electrumClient = electrumClient ?? ElectrumClient(); @@ -192,12 +188,13 @@ abstract class ElectrumWalletBase } } - Future _estimateTxFeeAndInputsToUse( + Future estimateTxFeeAndInputsToUse( int credentialsAmount, bool sendAll, List outputAddresses, List outputs, - BitcoinTransactionCredentials transactionCredentials, + int? feeRate, + BitcoinTransactionPriority? priority, {int? inputsCount}) async { final utxos = []; List privateKeys = []; @@ -212,7 +209,7 @@ abstract class ElectrumWalletBase allInputsAmount += utx.value; leftAmount = leftAmount - utx.value; - final address = _addressTypeFromStr(utx.address, network); + final address = addressTypeFromStr(utx.address, network); final privkey = generateECPrivate( hd: utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, index: utx.bitcoinAddressRecord.index, @@ -249,7 +246,7 @@ abstract class ElectrumWalletBase if (!sendAll) { if (changeValue > 0) { final changeAddress = await walletAddresses.getChangeAddress(); - final address = _addressTypeFromStr(changeAddress, network); + final address = addressTypeFromStr(changeAddress, network); outputAddresses.add(address); outputs.add(BitcoinOutput(address: address, value: BigInt.from(changeValue))); } @@ -258,9 +255,9 @@ abstract class ElectrumWalletBase final estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize( utxos: utxos, outputs: outputs, network: network); - final fee = transactionCredentials.feeRate != null - ? feeAmountWithFeeRate(transactionCredentials.feeRate!, 0, 0, size: estimatedSize) - : feeAmountForPriority(transactionCredentials.priority!, 0, 0, size: estimatedSize); + int fee = feeRate != null + ? feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize) + : feeAmountForPriority(priority!, 0, 0, size: estimatedSize); if (fee == 0) { throw BitcoinTransactionWrongBalanceException(currency); @@ -297,8 +294,8 @@ abstract class ElectrumWalletBase outputs.removeLast(); } - return _estimateTxFeeAndInputsToUse( - credentialsAmount, sendAll, outputAddresses, outputs, transactionCredentials, + return estimateTxFeeAndInputsToUse( + credentialsAmount, sendAll, outputAddresses, outputs, feeRate, priority, inputsCount: utxos.length + 1); } } @@ -319,7 +316,7 @@ abstract class ElectrumWalletBase for (final out in transactionCredentials.outputs) { final outputAddress = out.isParsedAddress ? out.extractedAddress! : out.address; - final address = _addressTypeFromStr(outputAddress, network); + final address = addressTypeFromStr(outputAddress, network); outputAddresses.add(address); @@ -344,8 +341,14 @@ abstract class ElectrumWalletBase } } - final estimatedTx = await _estimateTxFeeAndInputsToUse( - credentialsAmount, sendAll, outputAddresses, outputs, transactionCredentials); + final estimatedTx = await estimateTxFeeAndInputsToUse( + credentialsAmount, + sendAll, + outputAddresses, + outputs, + transactionCredentials.feeRate, + transactionCredentials.priority, + ); final txb = BitcoinTransactionBuilder( utxos: estimatedTx.utxos, @@ -391,7 +394,6 @@ abstract class ElectrumWalletBase ? SegwitAddresType.p2wpkh.toString() : walletInfo.addressPageType.toString(), 'balance': balance[currency]?.toJSON(), - 'network_type': network == BitcoinNetwork.testnet ? 'testnet' : 'mainnet', }); int feeRate(TransactionPriority priority) { @@ -852,6 +854,22 @@ abstract class ElectrumWalletBase final HD = index == null ? hd : hd.derive(index); return base64Encode(HD.signMessage(message)); } + + static BasedUtxoNetwork _getNetwork(bitcoin.NetworkType networkType, CryptoCurrency? currency) { + if (networkType == bitcoin.bitcoin && currency == CryptoCurrency.bch) { + return BitcoinCashNetwork.mainnet; + } + + if (networkType == litecoinNetwork) { + return LitecoinNetwork.mainnet; + } + + if (networkType == bitcoin.testnet) { + return BitcoinNetwork.testnet; + } + + return BitcoinNetwork.mainnet; + } } class EstimateTxParams { @@ -879,7 +897,7 @@ class EstimatedTxResult { final int amount; } -BitcoinBaseAddress _addressTypeFromStr(String address, BasedUtxoNetwork network) { +BitcoinBaseAddress addressTypeFromStr(String address, BasedUtxoNetwork network) { if (P2pkhAddress.regex.hasMatch(address)) { return P2pkhAddress.fromAddress(address: address, network: network); } else if (P2shAddress.regex.hasMatch(address)) { diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 5880f5a19..828bda8af 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -1,6 +1,5 @@ import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; -import 'package:bitbox/bitbox.dart' as bitbox; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_core/wallet_addresses.dart'; @@ -30,6 +29,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { List? initialAddresses, Map? initialRegularAddressIndex, Map? initialChangeAddressIndex, + BitcoinAddressType? initialAddressPageType, }) : _addresses = ObservableList.of((initialAddresses ?? []).toSet()), addressesByReceiveType = ObservableList.of(([]).toSet()), @@ -41,9 +41,10 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { .toSet()), currentReceiveAddressIndexByType = initialRegularAddressIndex ?? {}, currentChangeAddressIndexByType = initialChangeAddressIndex ?? {}, - _addressPageType = walletInfo.addressPageType != null - ? BitcoinAddressType.fromValue(walletInfo.addressPageType!) - : SegwitAddresType.p2wpkh, + _addressPageType = initialAddressPageType ?? + (walletInfo.addressPageType != null + ? BitcoinAddressType.fromValue(walletInfo.addressPageType!) + : SegwitAddresType.p2wpkh), super(walletInfo) { updateAddressesByMatch(); } @@ -52,10 +53,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { static const defaultChangeAddressesCount = 17; static const gap = 20; - static String toCashAddr(String address) => bitbox.Address.toCashAddress(address); - - static String toLegacy(String address) => bitbox.Address.toLegacyAddress(address); - final ObservableList _addresses; // Matched by addressPageType late ObservableList addressesByReceiveType; @@ -67,7 +64,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { final bitcoin.HDWallet sideHd; @observable - BitcoinAddressType _addressPageType = SegwitAddresType.p2wpkh; + late BitcoinAddressType _addressPageType; @computed BitcoinAddressType get addressPageType => _addressPageType; @@ -97,7 +94,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { } } - return walletInfo.type == WalletType.bitcoinCash ? toCashAddr(receiveAddress) : receiveAddress; + return receiveAddress; } @observable @@ -105,9 +102,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @override set address(String addr) { - if (addr.startsWith('bitcoincash:')) { - addr = toLegacy(addr); - } final addressRecord = _addresses.firstWhere((addressRecord) => addressRecord.address == addr); previousAddressRecord = addressRecord; @@ -155,11 +149,17 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @override Future init() async { - await _generateInitialAddresses(); - await _generateInitialAddresses(type: P2pkhAddressType.p2pkh); - await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh); - await _generateInitialAddresses(type: SegwitAddresType.p2tr); - await _generateInitialAddresses(type: SegwitAddresType.p2wsh); + if (walletInfo.type == WalletType.bitcoinCash) { + await _generateInitialAddresses(type: P2pkhAddressType.p2pkh); + } else if (walletInfo.type == WalletType.litecoin) { + await _generateInitialAddresses(); + } else if (walletInfo.type == WalletType.bitcoin) { + await _generateInitialAddresses(); + await _generateInitialAddresses(type: P2pkhAddressType.p2pkh); + await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh); + await _generateInitialAddresses(type: SegwitAddresType.p2tr); + await _generateInitialAddresses(type: SegwitAddresType.p2wsh); + } updateAddressesByMatch(); updateReceiveAddresses(); updateChangeAddresses(); @@ -229,9 +229,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { @action void updateAddress(String address, String label) { - if (address.startsWith('bitcoincash:')) { - address = toLegacy(address); - } final addressRecord = _addresses.firstWhere((addressRecord) => addressRecord.address == address); addressRecord.setNewName(label); @@ -261,7 +258,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { addressRecord.isHidden && !addressRecord.isUsed && // TODO: feature to change change address type. For now fixed to p2wpkh, the cheapest type - addressRecord.type == SegwitAddresType.p2wpkh); + (walletInfo.type != WalletType.bitcoin || addressRecord.type == SegwitAddresType.p2wpkh)); changeAddresses.addAll(newAddresses); } diff --git a/cw_bitcoin/lib/electrum_wallet_snapshot.dart b/cw_bitcoin/lib/electrum_wallet_snapshot.dart index 98c3753db..6f76ab312 100644 --- a/cw_bitcoin/lib/electrum_wallet_snapshot.dart +++ b/cw_bitcoin/lib/electrum_wallet_snapshot.dart @@ -17,14 +17,12 @@ class ElectrumWalletSnapshot { required this.regularAddressIndex, required this.changeAddressIndex, required this.addressPageType, - required this.network, }); final String name; final String password; final WalletType type; - final String addressPageType; - final BasedUtxoNetwork network; + final String? addressPageType; String mnemonic; List addresses; @@ -32,7 +30,8 @@ class ElectrumWalletSnapshot { Map regularAddressIndex; Map changeAddressIndex; - static Future load(String name, WalletType type, String password, BasedUtxoNetwork? network) async { + static Future load( + String name, WalletType type, String password, BasedUtxoNetwork network) async { final path = await pathForWallet(name: name, type: type); final jsonSource = await read(path: path, password: password); final data = json.decode(jsonSource) as Map; @@ -71,8 +70,7 @@ class ElectrumWalletSnapshot { balance: balance, regularAddressIndex: regularAddressIndexByType, changeAddressIndex: changeAddressIndexByType, - addressPageType: data['address_page_type'] as String? ?? SegwitAddresType.p2wpkh.toString(), - network: data['network_type'] == 'testnet' ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet, + addressPageType: data['address_page_type'] as String?, ); } } diff --git a/cw_bitcoin/lib/script_hash.dart b/cw_bitcoin/lib/script_hash.dart index 620d3d28a..2130fcbbe 100644 --- a/cw_bitcoin/lib/script_hash.dart +++ b/cw_bitcoin/lib/script_hash.dart @@ -1,8 +1,9 @@ -import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:crypto/crypto.dart'; +import 'package:cw_bitcoin/address_to_output_script.dart'; +import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin; -String scriptHash(String address, {required BasedUtxoNetwork network}) { - final outputScript = addressToOutputScript(address: address, network: network); +String scriptHash(String address, {required bitcoin.BasedUtxoNetwork network}) { + final outputScript = addressToOutputScript(address, network); final parts = sha256.convert(outputScript).toString().split(''); var res = ''; diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 25e6f269d..b39dcae07 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -79,11 +79,11 @@ packages: dependency: "direct main" description: path: "." - ref: cake-update-v1 - resolved-ref: "9611e9db77e92a8434e918cdfb620068f6fcb1aa" + ref: cake-update-v2 + resolved-ref: "3fd81d238b990bb767fc7a4fdd5053a22a142e2e" url: "https://github.com/cake-tech/bitcoin_base.git" source: git - version: "4.0.0" + version: "4.2.0" bitcoin_flutter: dependency: "direct main" description: @@ -97,10 +97,10 @@ packages: dependency: "direct main" description: name: blockchain_utils - sha256: "9701dfaa74caad4daae1785f1ec4445cf7fb94e45620bc3a4aca1b9b281dc6c9" + sha256: "38ef5f4a22441ac4370aed9071dc71c460acffc37c79b344533f67d15f24c13c" url: "https://pub.dev" source: hosted - version: "1.6.0" + version: "2.1.1" boolean_selector: dependency: transitive description: diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index 847b77773..bcbb55e11 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -33,8 +33,8 @@ dependencies: bitcoin_base: git: url: https://github.com/cake-tech/bitcoin_base.git - ref: cake-update-v1 - blockchain_utils: ^1.6.0 + ref: cake-update-v2 + blockchain_utils: ^2.1.1 dev_dependencies: flutter_test: diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index 3c40cf9e9..f5835e728 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -34,7 +34,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { required WalletInfo walletInfo, required Box unspentCoinsInfo, required Uint8List seedBytes, - String? addressPageType, + BitcoinAddressType? addressPageType, List? initialAddresses, ElectrumBalance? initialBalance, Map? initialRegularAddressIndex, @@ -58,6 +58,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { mainHd: hd, sideHd: bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/1"), network: network, + initialAddressPageType: addressPageType, ); autorun((_) { this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress; @@ -84,7 +85,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { seedBytes: await Mnemonic.toSeed(mnemonic), initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex, - addressPageType: addressPageType, + addressPageType: P2pkhAddressType.p2pkh, ); } @@ -101,12 +102,31 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { password: password, walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfo, - initialAddresses: snp.addresses, + initialAddresses: snp.addresses.map((addr) { + try { + BitcoinCashAddress(addr.address); + return BitcoinAddressRecord( + addr.address, + index: addr.index, + isHidden: addr.isHidden, + type: P2pkhAddressType.p2pkh, + network: BitcoinCashNetwork.mainnet, + ); + } catch (_) { + return BitcoinAddressRecord( + AddressUtils.getCashAddrFormat(addr.address), + index: addr.index, + isHidden: addr.isHidden, + type: P2pkhAddressType.p2pkh, + network: BitcoinCashNetwork.mainnet, + ); + } + }).toList(), initialBalance: snp.balance, seedBytes: await Mnemonic.toSeed(snp.mnemonic), initialRegularAddressIndex: snp.regularAddressIndex, initialChangeAddressIndex: snp.changeAddressIndex, - addressPageType: snp.addressPageType, + addressPageType: P2pkhAddressType.p2pkh, ); } diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart index 8291ce2a5..3164651f3 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_addresses.dart @@ -19,6 +19,7 @@ abstract class BitcoinCashWalletAddressesBase extends ElectrumWalletAddresses wi super.initialAddresses, super.initialRegularAddressIndex, super.initialChangeAddressIndex, + super.initialAddressPageType, }) : super(walletInfo); @override diff --git a/cw_bitcoin_cash/pubspec.yaml b/cw_bitcoin_cash/pubspec.yaml index 9c098c0ff..7130b3c58 100644 --- a/cw_bitcoin_cash/pubspec.yaml +++ b/cw_bitcoin_cash/pubspec.yaml @@ -32,7 +32,7 @@ dependencies: bitcoin_base: git: url: https://github.com/cake-tech/bitcoin_base.git - ref: cake-update-v1 + ref: cake-update-v2 diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 4f3aea7ec..be72b992d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -277,7 +277,7 @@ SPEC CHECKSUMS: flutter_inappwebview_ios: 97215cf7d4677db55df76782dbd2930c5e1c1ea0 flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83 flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be - fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0 + fluttertoast: 48c57db1b71b0ce9e6bba9f31c940ff4b001293c in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d local_auth_ios: 1ba1475238daa33a6ffa2a29242558437be435ac MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb @@ -302,4 +302,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: fcb1b8418441a35b438585c9dd8374e722e6c6ca -COCOAPODS: 1.12.1 +COCOAPODS: 1.15.2 diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index b36421608..709dc9a04 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -113,13 +113,35 @@ class CWBitcoin extends Bitcoin { .map((BitcoinAddressRecord addr) => ElectrumSubAddress( id: addr.index, name: addr.name, - address: electrumWallet.type == WalletType.bitcoinCash ? addr.cashAddr : addr.address, + address: addr.address, txCount: addr.txCount, balance: addr.balance, isChange: addr.isHidden)) .toList(); } + @override + Future estimateFakeSendAllTxAmount(Object wallet, TransactionPriority priority) async { + final electrumWallet = wallet as ElectrumWallet; + final sk = ECPrivate.random(); + + final p2shAddr = sk.getPublic().toP2pkhInP2sh(); + final p2wpkhAddr = sk.getPublic().toP2wpkhAddress(); + final estimatedTx = await electrumWallet.estimateTxFeeAndInputsToUse( + 0, + true, + // Deposit address + change address + [p2shAddr, p2wpkhAddr], + [ + BitcoinOutput(address: p2shAddr, value: BigInt.zero), + BitcoinOutput(address: p2wpkhAddr, value: BigInt.zero) + ], + null, + priority as BitcoinTransactionPriority); + + return estimatedTx.amount; + } + @override String getAddress(Object wallet) { final bitcoinWallet = wallet as ElectrumWallet; diff --git a/lib/buy/moonpay/moonpay_provider.dart b/lib/buy/moonpay/moonpay_provider.dart index 0ccb73e1c..75ba45ce1 100644 --- a/lib/buy/moonpay/moonpay_provider.dart +++ b/lib/buy/moonpay/moonpay_provider.dart @@ -81,7 +81,7 @@ class MoonPaySellProvider extends BuyProvider { '', { 'apiKey': _apiKey, - 'defaultBaseCurrencyCode': currency.toString().toLowerCase(), + 'defaultBaseCurrencyCode': _normalizeCurrency(currency), 'refundWalletAddress': refundWalletAddress, }..addAll(customParams), ); @@ -134,6 +134,14 @@ class MoonPaySellProvider extends BuyProvider { ); } } + + String _normalizeCurrency(CryptoCurrency currency) { + if (currency == CryptoCurrency.maticpoly) { + return "MATIC_POLYGON"; + } + + return currency.toString().toLowerCase(); + } } class MoonPayBuyProvider extends BuyProvider { diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index ad2c761a3..967cf9bf0 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -274,7 +274,7 @@ class AddressValidator extends TextValidator { '|([^0-9a-zA-Z]|^)([23][a-km-zA-HJ-NP-Z1-9]{25,34})([^0-9a-zA-Z]|\$)' //P2shAddress type '|([^0-9a-zA-Z]|^)((bc|tb)1q[ac-hj-np-z02-9]{25,39})([^0-9a-zA-Z]|\$)' //P2wpkhAddress type '|([^0-9a-zA-Z]|^)((bc|tb)1q[ac-hj-np-z02-9]{40,80})([^0-9a-zA-Z]|\$)' //P2wshAddress type - '|([^0-9a-zA-Z]|^)((bc|tb)1p([ac-hj-np-z02-9]{39}|[ac-hj-np-z02-9]{59}|[ac-hj-np-z02-9]{8,89}))([^0-9a-zA-Z]|\$)'; //P2trAddress type + '|([^0-9a-zA-Z]|^)((bc|tb)1p([ac-hj-np-z02-9]{39}|[ac-hj-np-z02-9]{59}|[ac-hj-np-z02-9]{8,89}))([^0-9a-zA-Z]|\$)'; //P2trAddress type case CryptoCurrency.ltc: return '([^0-9a-zA-Z]|^)^L[a-zA-Z0-9]{26,33}([^0-9a-zA-Z]|\$)' '|([^0-9a-zA-Z]|^)[LM][a-km-zA-HJ-NP-Z1-9]{26,33}([^0-9a-zA-Z]|\$)' diff --git a/lib/entities/provider_types.dart b/lib/entities/provider_types.dart index f9c2f1a82..b7336c2a7 100644 --- a/lib/entities/provider_types.dart +++ b/lib/entities/provider_types.dart @@ -89,7 +89,12 @@ class ProvidersHelper { case WalletType.bitcoinCash: return [ProviderType.askEachTime, ProviderType.moonpaySell]; case WalletType.polygon: - return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.dfx]; + return [ + ProviderType.askEachTime, + ProviderType.onramper, + ProviderType.moonpaySell, + ProviderType.dfx, + ]; case WalletType.solana: return [ ProviderType.askEachTime, diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 94b51301c..61355df05 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -384,7 +384,7 @@ class ExchangePage extends BasePage { (CryptoCurrency currency) => _onCurrencyChange(currency, exchangeViewModel, depositKey)); reaction((_) => exchangeViewModel.depositAmount, (String amount) { - if (depositKey.currentState!.amountController.text != amount) { + if (depositKey.currentState!.amountController.text != amount && amount != S.of(context).all) { depositKey.currentState!.amountController.text = amount; } }); @@ -467,7 +467,9 @@ class ExchangePage extends BasePage { .addListener(() => exchangeViewModel.depositAddress = depositAddressController.text); depositAmountController.addListener(() { - if (depositAmountController.text != exchangeViewModel.depositAmount) { + if (depositAmountController.text != exchangeViewModel.depositAmount && + depositAmountController.text != S.of(context).all) { + exchangeViewModel.isSendAllEnabled = false; _depositAmountDebounce.run(() { exchangeViewModel.changeDepositAmount(amount: depositAmountController.text); exchangeViewModel.isReceiveAmountEntered = false; @@ -589,8 +591,9 @@ class ExchangePage extends BasePage { onDispose: disposeBestRateSync, hasAllAmount: exchangeViewModel.hasAllAmount, allAmount: exchangeViewModel.hasAllAmount - ? () => exchangeViewModel.calculateDepositAllAmount() + ? () => exchangeViewModel.enableSendAllAmount() : null, + isAllAmountEnabled: exchangeViewModel.isSendAllEnabled, amountFocusNode: _depositAmountFocus, addressFocusNode: _depositAddressFocus, key: depositKey, @@ -626,8 +629,10 @@ class ExchangePage extends BasePage { }, imageArrow: arrowBottomPurple, currencyButtonColor: Colors.transparent, - addressButtonsColor: Theme.of(context).extension()!.textFieldButtonColor, - borderColor: Theme.of(context).extension()!.textFieldBorderTopPanelColor, + addressButtonsColor: + Theme.of(context).extension()!.textFieldButtonColor, + borderColor: + Theme.of(context).extension()!.textFieldBorderTopPanelColor, currencyValueValidator: (value) { return !exchangeViewModel.isFixedRateMode ? AmountValidator( @@ -673,8 +678,10 @@ class ExchangePage extends BasePage { exchangeViewModel.changeReceiveCurrency(currency: currency), imageArrow: arrowBottomCakeGreen, currencyButtonColor: Colors.transparent, - addressButtonsColor: Theme.of(context).extension()!.textFieldButtonColor, - borderColor: Theme.of(context).extension()!.textFieldBorderBottomPanelColor, + addressButtonsColor: + Theme.of(context).extension()!.textFieldButtonColor, + borderColor: + Theme.of(context).extension()!.textFieldBorderBottomPanelColor, currencyValueValidator: (value) { return exchangeViewModel.isFixedRateMode ? AmountValidator( diff --git a/lib/src/screens/exchange/exchange_template_page.dart b/lib/src/screens/exchange/exchange_template_page.dart index 3a7456dd8..d24c91dad 100644 --- a/lib/src/screens/exchange/exchange_template_page.dart +++ b/lib/src/screens/exchange/exchange_template_page.dart @@ -56,17 +56,14 @@ class ExchangeTemplatePage extends BasePage { height: 8, ); - final depositWalletName = - exchangeViewModel.depositCurrency == CryptoCurrency.xmr + final depositWalletName = exchangeViewModel.depositCurrency == CryptoCurrency.xmr ? exchangeViewModel.wallet.name : null; - final receiveWalletName = - exchangeViewModel.receiveCurrency == CryptoCurrency.xmr + final receiveWalletName = exchangeViewModel.receiveCurrency == CryptoCurrency.xmr ? exchangeViewModel.wallet.name : null; - WidgetsBinding.instance - .addPostFrameCallback((_) => _setReactions(context, exchangeViewModel)); + WidgetsBinding.instance.addPostFrameCallback((_) => _setReactions(context, exchangeViewModel)); return KeyboardActions( disableScroll: true, @@ -76,128 +73,125 @@ class ExchangeTemplatePage extends BasePage { nextFocus: false, actions: [ KeyboardActionsItem( - focusNode: _depositAmountFocus, - toolbarButtons: [(_) => KeyboardDoneButton()]), + focusNode: _depositAmountFocus, toolbarButtons: [(_) => KeyboardDoneButton()]), KeyboardActionsItem( - focusNode: _receiveAmountFocus, - toolbarButtons: [(_) => KeyboardDoneButton()]) + focusNode: _receiveAmountFocus, toolbarButtons: [(_) => KeyboardDoneButton()]) ]), child: Container( - color: Theme.of(context).colorScheme.background, - child: Form( - key: _formKey, - child: ScrollableWithBottomSection( - contentPadding: EdgeInsets.only(bottom: 24), - content: Container( - padding: EdgeInsets.only(bottom: 32), - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(24), - bottomRight: Radius.circular(24) - ), - gradient: LinearGradient( - colors: [ - Theme.of(context).extension()!.firstGradientBottomPanelColor, - Theme.of(context).extension()!.secondGradientBottomPanelColor, - ], - stops: [0.35, 1.0], - begin: Alignment.topLeft, - end: Alignment.bottomRight), - ), - child: FocusTraversalGroup( - policy: OrderedTraversalPolicy(), - child: Column( - children: [ - Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(24), - bottomRight: Radius.circular(24) + color: Theme.of(context).colorScheme.background, + child: Form( + key: _formKey, + child: ScrollableWithBottomSection( + contentPadding: EdgeInsets.only(bottom: 24), + content: Container( + padding: EdgeInsets.only(bottom: 32), + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)), + gradient: LinearGradient(colors: [ + Theme.of(context) + .extension()! + .firstGradientBottomPanelColor, + Theme.of(context) + .extension()! + .secondGradientBottomPanelColor, + ], stops: [ + 0.35, + 1.0 + ], begin: Alignment.topLeft, end: Alignment.bottomRight), + ), + child: FocusTraversalGroup( + policy: OrderedTraversalPolicy(), + child: Column( + children: [ + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(24), + bottomRight: Radius.circular(24)), + gradient: LinearGradient(colors: [ + Theme.of(context) + .extension()! + .firstGradientTopPanelColor, + Theme.of(context) + .extension()! + .secondGradientTopPanelColor, + ], begin: Alignment.topLeft, end: Alignment.bottomRight), + ), + padding: EdgeInsets.fromLTRB(24, 100, 24, 32), + child: Observer( + builder: (_) => ExchangeCard( + amountFocusNode: _depositAmountFocus, + key: depositKey, + title: S.of(context).you_will_send, + initialCurrency: exchangeViewModel.depositCurrency, + initialWalletName: depositWalletName ?? '', + initialAddress: exchangeViewModel.depositCurrency == + exchangeViewModel.wallet.currency + ? exchangeViewModel.wallet.walletAddresses.address + : exchangeViewModel.depositAddress, + initialIsAmountEditable: true, + initialIsAddressEditable: exchangeViewModel.isDepositAddressEnabled, + isAmountEstimated: false, + hasRefundAddress: true, + isMoneroWallet: exchangeViewModel.isMoneroWallet, + currencies: CryptoCurrency.all, + onCurrencySelected: (currency) => + exchangeViewModel.changeDepositCurrency(currency: currency), + imageArrow: arrowBottomPurple, + currencyButtonColor: Colors.transparent, + addressButtonsColor: Theme.of(context) + .extension()! + .textFieldButtonColor, + borderColor: Theme.of(context) + .extension()! + .textFieldBorderBottomPanelColor, + currencyValueValidator: + AmountValidator(currency: exchangeViewModel.depositCurrency), + //addressTextFieldValidator: AddressValidator( + // type: exchangeViewModel.depositCurrency), + ), + ), ), - gradient: LinearGradient( - colors: [ - Theme.of(context).extension()!.firstGradientTopPanelColor, - Theme.of(context).extension()!.secondGradientTopPanelColor, - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight), - ), - padding: EdgeInsets.fromLTRB(24, 100, 24, 32), - child: Observer( - builder: (_) => ExchangeCard( - amountFocusNode: _depositAmountFocus, - key: depositKey, - title: S.of(context).you_will_send, - initialCurrency: - exchangeViewModel.depositCurrency, - initialWalletName: depositWalletName ?? '', - initialAddress: exchangeViewModel - .depositCurrency == - exchangeViewModel.wallet.currency - ? exchangeViewModel.wallet.walletAddresses.address - : exchangeViewModel.depositAddress, - initialIsAmountEditable: true, - initialIsAddressEditable: exchangeViewModel - .isDepositAddressEnabled, - isAmountEstimated: false, - hasRefundAddress: true, - isMoneroWallet: exchangeViewModel.isMoneroWallet, - currencies: CryptoCurrency.all, - onCurrencySelected: (currency) => - exchangeViewModel.changeDepositCurrency( - currency: currency), - imageArrow: arrowBottomPurple, - currencyButtonColor: Colors.transparent, - addressButtonsColor: - Theme.of(context).extension()!.textFieldButtonColor, - borderColor: Theme.of(context).extension()!.textFieldBorderBottomPanelColor, - currencyValueValidator: AmountValidator( - currency: exchangeViewModel.depositCurrency), - //addressTextFieldValidator: AddressValidator( - // type: exchangeViewModel.depositCurrency), - ), - ), + Padding( + padding: EdgeInsets.only(top: 29, left: 24, right: 24), + child: Observer( + builder: (_) => ExchangeCard( + amountFocusNode: _receiveAmountFocus, + key: receiveKey, + title: S.of(context).you_will_get, + initialCurrency: exchangeViewModel.receiveCurrency, + initialWalletName: receiveWalletName ?? '', + initialAddress: exchangeViewModel.receiveCurrency == + exchangeViewModel.wallet.currency + ? exchangeViewModel.wallet.walletAddresses.address + : exchangeViewModel.receiveAddress, + initialIsAmountEditable: false, + isAmountEstimated: true, + isMoneroWallet: exchangeViewModel.isMoneroWallet, + currencies: exchangeViewModel.receiveCurrencies, + onCurrencySelected: (currency) => exchangeViewModel + .changeReceiveCurrency(currency: currency), + imageArrow: arrowBottomCakeGreen, + currencyButtonColor: Colors.transparent, + addressButtonsColor: Theme.of(context) + .extension()! + .textFieldButtonColor, + borderColor: Theme.of(context) + .extension()! + .textFieldBorderBottomPanelColor, + currencyValueValidator: AmountValidator( + currency: exchangeViewModel.receiveCurrency), + //addressTextFieldValidator: AddressValidator( + // type: exchangeViewModel.receiveCurrency), + )), + ) + ], ), - Padding( - padding: EdgeInsets.only(top: 29, left: 24, right: 24), - child: Observer( - builder: (_) => ExchangeCard( - amountFocusNode: _receiveAmountFocus, - key: receiveKey, - title: S.of(context).you_will_get, - initialCurrency: - exchangeViewModel.receiveCurrency, - initialWalletName: receiveWalletName ?? '', - initialAddress: - exchangeViewModel.receiveCurrency == - exchangeViewModel.wallet.currency - ? exchangeViewModel.wallet.walletAddresses.address - : exchangeViewModel.receiveAddress, - initialIsAmountEditable: false, - isAmountEstimated: true, - isMoneroWallet: exchangeViewModel.isMoneroWallet, - currencies: exchangeViewModel.receiveCurrencies, - onCurrencySelected: (currency) => - exchangeViewModel.changeReceiveCurrency( - currency: currency), - imageArrow: arrowBottomCakeGreen, - currencyButtonColor: Colors.transparent, - addressButtonsColor: - Theme.of(context).extension()!.textFieldButtonColor, - borderColor: Theme.of(context).extension()!.textFieldBorderBottomPanelColor, - currencyValueValidator: AmountValidator( - currency: exchangeViewModel.receiveCurrency), - //addressTextFieldValidator: AddressValidator( - // type: exchangeViewModel.receiveCurrency), - )), - ) - ], + ), ), - ), - ), - bottomSectionPadding: - EdgeInsets.only(left: 24, right: 24, bottom: 24), - bottomSection: Column(children: [ + bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), + bottomSection: Column(children: [ Padding( padding: EdgeInsets.only(bottom: 15), child: Observer( @@ -217,36 +211,31 @@ class ExchangeTemplatePage extends BasePage { ), ), PrimaryButton( - onPressed: () { - if (_formKey.currentState != null && _formKey.currentState!.validate()) { - exchangeViewModel.addTemplate( - amount: exchangeViewModel.depositAmount, - depositCurrency: - exchangeViewModel.depositCurrency.name, - depositCurrencyTitle: exchangeViewModel - .depositCurrency.title + ' ${exchangeViewModel.depositCurrency.tag ?? ''}', - receiveCurrency: - exchangeViewModel.receiveCurrency.name, - receiveCurrencyTitle: exchangeViewModel - .receiveCurrency.title + ' ${exchangeViewModel.receiveCurrency.tag ?? ''}', - provider: exchangeViewModel.provider.toString(), - depositAddress: exchangeViewModel.depositAddress, - receiveAddress: exchangeViewModel.receiveAddress); - exchangeViewModel.updateTemplate(); - Navigator.of(context).pop(); - } - }, - text: S.of(context).save, - color: Theme.of(context).primaryColor, - textColor: Colors.white), - ]), - )) - ) - ); + onPressed: () { + if (_formKey.currentState != null && _formKey.currentState!.validate()) { + exchangeViewModel.addTemplate( + amount: exchangeViewModel.depositAmount, + depositCurrency: exchangeViewModel.depositCurrency.name, + depositCurrencyTitle: exchangeViewModel.depositCurrency.title + + ' ${exchangeViewModel.depositCurrency.tag ?? ''}', + receiveCurrency: exchangeViewModel.receiveCurrency.name, + receiveCurrencyTitle: exchangeViewModel.receiveCurrency.title + + ' ${exchangeViewModel.receiveCurrency.tag ?? ''}', + provider: exchangeViewModel.provider.toString(), + depositAddress: exchangeViewModel.depositAddress, + receiveAddress: exchangeViewModel.receiveAddress); + exchangeViewModel.updateTemplate(); + Navigator.of(context).pop(); + } + }, + text: S.of(context).save, + color: Theme.of(context).primaryColor, + textColor: Colors.white), + ]), + )))); } - void _setReactions( - BuildContext context, ExchangeViewModel exchangeViewModel) { + void _setReactions(BuildContext context, ExchangeViewModel exchangeViewModel) { if (_isReactionsSet) { return; } @@ -272,33 +261,27 @@ class ExchangeTemplatePage extends BasePage { // key.currentState.changeLimits(min: min, max: max); // } - _onCurrencyChange( - exchangeViewModel.receiveCurrency, exchangeViewModel, receiveKey); - _onCurrencyChange( - exchangeViewModel.depositCurrency, exchangeViewModel, depositKey); + _onCurrencyChange(exchangeViewModel.receiveCurrency, exchangeViewModel, receiveKey); + _onCurrencyChange(exchangeViewModel.depositCurrency, exchangeViewModel, depositKey); reaction( - (_) => exchangeViewModel.wallet.name, - (String _) => _onWalletNameChange( - exchangeViewModel, exchangeViewModel.receiveCurrency, receiveKey)); + (_) => exchangeViewModel.wallet.name, + (String _) => + _onWalletNameChange(exchangeViewModel, exchangeViewModel.receiveCurrency, receiveKey)); reaction( - (_) => exchangeViewModel.wallet.name, - (String _) => _onWalletNameChange( - exchangeViewModel, exchangeViewModel.depositCurrency, depositKey)); + (_) => exchangeViewModel.wallet.name, + (String _) => + _onWalletNameChange(exchangeViewModel, exchangeViewModel.depositCurrency, depositKey)); - reaction( - (_) => exchangeViewModel.receiveCurrency, - (CryptoCurrency currency) => - _onCurrencyChange(currency, exchangeViewModel, receiveKey)); + reaction((_) => exchangeViewModel.receiveCurrency, + (CryptoCurrency currency) => _onCurrencyChange(currency, exchangeViewModel, receiveKey)); - reaction( - (_) => exchangeViewModel.depositCurrency, - (CryptoCurrency currency) => - _onCurrencyChange(currency, exchangeViewModel, depositKey)); + reaction((_) => exchangeViewModel.depositCurrency, + (CryptoCurrency currency) => _onCurrencyChange(currency, exchangeViewModel, depositKey)); reaction((_) => exchangeViewModel.depositAmount, (String amount) { - if (depositKey.currentState!.amountController.text != amount) { + if (depositKey.currentState!.amountController.text != amount && amount != S.of(context).all) { depositKey.currentState!.amountController.text = amount; } }); @@ -309,10 +292,9 @@ class ExchangeTemplatePage extends BasePage { } }); - reaction((_) => exchangeViewModel.isDepositAddressEnabled, - (bool isEnabled) { - depositKey.currentState!.isAddressEditable(isEditable: isEnabled); - }); + reaction((_) => exchangeViewModel.isDepositAddressEnabled, (bool isEnabled) { + depositKey.currentState!.isAddressEditable(isEditable: isEnabled); + }); reaction((_) => exchangeViewModel.receiveAmount, (String amount) { if (receiveKey.currentState!.amountController.text != amount) { @@ -353,30 +335,28 @@ class ExchangeTemplatePage extends BasePage { receiveKey.currentState.changeLimits(min: null, max: null); });*/ - depositAddressController.addListener( - () => exchangeViewModel.depositAddress = depositAddressController.text); + depositAddressController + .addListener(() => exchangeViewModel.depositAddress = depositAddressController.text); depositAmountController.addListener(() { - if (depositAmountController.text != exchangeViewModel.depositAmount) { - exchangeViewModel.changeDepositAmount( - amount: depositAmountController.text); + if (depositAmountController.text != exchangeViewModel.depositAmount && + exchangeViewModel.depositAmount != S.of(context).all) { + exchangeViewModel.changeDepositAmount(amount: depositAmountController.text); exchangeViewModel.isReceiveAmountEntered = false; } }); - receiveAddressController.addListener( - () => exchangeViewModel.receiveAddress = receiveAddressController.text); + receiveAddressController + .addListener(() => exchangeViewModel.receiveAddress = receiveAddressController.text); receiveAmountController.addListener(() { if (receiveAmountController.text != exchangeViewModel.receiveAmount) { - exchangeViewModel.changeReceiveAmount( - amount: receiveAmountController.text); + exchangeViewModel.changeReceiveAmount(amount: receiveAmountController.text); exchangeViewModel.isReceiveAmountEntered = true; } }); - reaction((_) => exchangeViewModel.wallet.walletAddresses.address, - (String address) { + reaction((_) => exchangeViewModel.wallet.walletAddresses.address, (String address) { if (exchangeViewModel.depositCurrency == CryptoCurrency.xmr) { depositKey.currentState!.changeAddress(address: address); } @@ -389,29 +369,26 @@ class ExchangeTemplatePage extends BasePage { _isReactionsSet = true; } - void _onCurrencyChange(CryptoCurrency currency, - ExchangeViewModel exchangeViewModel, GlobalKey key) { + void _onCurrencyChange(CryptoCurrency currency, ExchangeViewModel exchangeViewModel, + GlobalKey key) { final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency; key.currentState!.changeSelectedCurrency(currency); - key.currentState!.changeWalletName( - isCurrentTypeWallet ? exchangeViewModel.wallet.name : ''); + key.currentState!.changeWalletName(isCurrentTypeWallet ? exchangeViewModel.wallet.name : ''); key.currentState!.changeAddress( - address: isCurrentTypeWallet - ? exchangeViewModel.wallet.walletAddresses.address : ''); + address: isCurrentTypeWallet ? exchangeViewModel.wallet.walletAddresses.address : ''); key.currentState!.changeAmount(amount: ''); } - void _onWalletNameChange(ExchangeViewModel exchangeViewModel, - CryptoCurrency currency, GlobalKey key) { + void _onWalletNameChange(ExchangeViewModel exchangeViewModel, CryptoCurrency currency, + GlobalKey key) { final isCurrentTypeWallet = currency == exchangeViewModel.wallet.currency; if (isCurrentTypeWallet) { key.currentState!.changeWalletName(exchangeViewModel.wallet.name); - key.currentState!.addressController.text = - exchangeViewModel.wallet.walletAddresses.address; + key.currentState!.addressController.text = exchangeViewModel.wallet.walletAddresses.address; } else if (key.currentState!.addressController.text == exchangeViewModel.wallet.walletAddresses.address) { key.currentState!.changeWalletName(''); diff --git a/lib/src/screens/exchange/widgets/exchange_card.dart b/lib/src/screens/exchange/widgets/exchange_card.dart index 706ace7de..d2e3c27d4 100644 --- a/lib/src/screens/exchange/widgets/exchange_card.dart +++ b/lib/src/screens/exchange/widgets/exchange_card.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/core/amount_validator.dart'; import 'package:cake_wallet/entities/contact_base.dart'; import 'package:cake_wallet/themes/extensions/qr_code_theme.dart'; import 'package:cake_wallet/routes.dart'; @@ -37,6 +38,7 @@ class ExchangeCard extends StatefulWidget { this.addressButtonsColor = Colors.transparent, this.borderColor = Colors.transparent, this.hasAllAmount = false, + this.isAllAmountEnabled = false, this.amountFocusNode, this.addressFocusNode, this.allAmount, @@ -62,9 +64,11 @@ class ExchangeCard extends StatefulWidget { final Color borderColor; final FormFieldValidator? currencyValueValidator; final FormFieldValidator? addressTextFieldValidator; + final FormFieldValidator allAmountValidator = AllAmountValidator(); final FocusNode? amountFocusNode; final FocusNode? addressFocusNode; final bool hasAllAmount; + final bool isAllAmountEnabled; final VoidCallback? allAmount; final void Function(BuildContext context)? onPushPasteButton; final void Function(BuildContext context)? onPushAddressBookButton; @@ -76,15 +80,15 @@ class ExchangeCard extends StatefulWidget { class ExchangeCardState extends State { ExchangeCardState() - : _title = '', - _min = '', - _max = '', - _isAmountEditable = false, - _isAddressEditable = false, - _walletName = '', - _selectedCurrency = CryptoCurrency.btc, - _isAmountEstimated = false, - _isMoneroWallet = false; + : _title = '', + _min = '', + _max = '', + _isAmountEditable = false, + _isAddressEditable = false, + _walletName = '', + _selectedCurrency = CryptoCurrency.btc, + _isAmountEstimated = false, + _isMoneroWallet = false; final addressController = TextEditingController(); final amountController = TextEditingController(); @@ -160,6 +164,12 @@ class ExchangeCardState extends State { @override Widget build(BuildContext context) { + if (widget.isAllAmountEnabled) { + WidgetsBinding.instance.addPostFrameCallback((_) { + amountController.text = S.of(context).all; + }); + } + final copyImage = Image.asset('assets/images/copy_content.png', height: 16, width: 16, @@ -168,8 +178,7 @@ class ExchangeCardState extends State { return Container( width: double.infinity, color: Colors.transparent, - child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: < - Widget>[ + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.start, children: [ @@ -202,40 +211,38 @@ class ExchangeCardState extends State { ), Text(_selectedCurrency.toString(), style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: 16, - color: Colors.white)) + fontWeight: FontWeight.w600, fontSize: 16, color: Colors.white)) ]), ), ), - _selectedCurrency.tag != null ? Padding( - padding: const EdgeInsets.only(right:3.0), - child: Container( - height: 32, - decoration: BoxDecoration( - color: widget.addressButtonsColor ?? - Theme.of(context).extension()!.textFieldButtonColor, - borderRadius: - BorderRadius.all(Radius.circular(6))), - child: Center( - child: Padding( - padding: const EdgeInsets.all(6.0), - child: Text(_selectedCurrency.tag!, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: Theme.of(context).extension()!.textFieldButtonIconColor)), + if (_selectedCurrency.tag != null) + Padding( + padding: const EdgeInsets.only(right: 3.0), + child: Container( + height: 32, + decoration: BoxDecoration( + color: widget.addressButtonsColor ?? + Theme.of(context).extension()!.textFieldButtonColor, + borderRadius: BorderRadius.all(Radius.circular(6))), + child: Center( + child: Padding( + padding: const EdgeInsets.all(6.0), + child: Text(_selectedCurrency.tag!, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: Theme.of(context) + .extension()! + .textFieldButtonIconColor)), + ), ), ), ), - ) : Container(), Padding( padding: const EdgeInsets.only(right: 4.0), child: Text(':', style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: 16, - color: Colors.white)), + fontWeight: FontWeight.w600, fontSize: 16, color: Colors.white)), ), Expanded( child: Row( @@ -249,26 +256,27 @@ class ExchangeCardState extends State { controller: amountController, enabled: _isAmountEditable, textAlign: TextAlign.left, - keyboardType: TextInputType.numberWithOptions( - signed: false, decimal: true), + keyboardType: + TextInputType.numberWithOptions(signed: false, decimal: true), inputFormatters: [ - FilteringTextInputFormatter.deny( - RegExp('[\\-|\\ ]')) + FilteringTextInputFormatter.deny(RegExp('[\\-|\\ ]')) ], hintText: '0.0000', borderColor: Colors.transparent, //widget.borderColor, textStyle: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Colors.white), + fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white), placeholderTextStyle: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, - color: Theme.of(context).extension()!.hintTextColor), - validator: _isAmountEditable - ? widget.currencyValueValidator - : null), + color: Theme.of(context) + .extension()! + .hintTextColor), + validator: widget.hasAllAmount + ? widget.allAmountValidator + : _isAmountEditable + ? widget.currencyValueValidator + : null), ), ), if (widget.hasAllAmount) @@ -276,9 +284,10 @@ class ExchangeCardState extends State { height: 32, width: 32, decoration: BoxDecoration( - color: Theme.of(context).extension()!.textFieldButtonColor, - borderRadius: - BorderRadius.all(Radius.circular(6))), + color: Theme.of(context) + .extension()! + .textFieldButtonColor, + borderRadius: BorderRadius.all(Radius.circular(6))), child: InkWell( onTap: () => widget.allAmount?.call(), child: Center( @@ -287,7 +296,9 @@ class ExchangeCardState extends State { style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, - color: Theme.of(context).extension()!.textFieldButtonIconColor)), + color: Theme.of(context) + .extension()! + .textFieldButtonIconColor)), ), ), ) @@ -296,39 +307,30 @@ class ExchangeCardState extends State { ), ], )), - Divider( - height: 1, - color: Theme.of(context).extension()!.textFieldHintColor), + Divider(height: 1, color: Theme.of(context).extension()!.textFieldHintColor), Padding( padding: EdgeInsets.only(top: 5), child: Container( height: 15, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - _min != null - ? Text( - S - .of(context) - .min_value(_min ?? '', _selectedCurrency.toString()), - style: TextStyle( - fontSize: 10, - height: 1.2, - color: Theme.of(context).extension()!.hintTextColor), - ) - : Offstage(), - _min != null ? SizedBox(width: 10) : Offstage(), - _max != null - ? Text( - S - .of(context) - .max_value(_max ?? '', _selectedCurrency.toString()), - style: TextStyle( - fontSize: 10, - height: 1.2, - color: Theme.of(context).extension()!.hintTextColor)) - : Offstage(), - ])), + child: Row(mainAxisAlignment: MainAxisAlignment.start, children: [ + _min != null + ? Text( + S.of(context).min_value(_min ?? '', _selectedCurrency.toString()), + style: TextStyle( + fontSize: 10, + height: 1.2, + color: Theme.of(context).extension()!.hintTextColor), + ) + : Offstage(), + _min != null ? SizedBox(width: 10) : Offstage(), + _max != null + ? Text(S.of(context).max_value(_max ?? '', _selectedCurrency.toString()), + style: TextStyle( + fontSize: 10, + height: 1.2, + color: Theme.of(context).extension()!.hintTextColor)) + : Offstage(), + ])), ), !_isAddressEditable && widget.hasRefundAddress ? Padding( @@ -343,7 +345,7 @@ class ExchangeCardState extends State { : Offstage(), _isAddressEditable ? FocusTraversalOrder( - order: NumericFocusOrder(2), + order: NumericFocusOrder(2), child: Padding( padding: EdgeInsets.only(top: 20), child: AddressTextField( @@ -352,27 +354,23 @@ class ExchangeCardState extends State { onURIScanned: (uri) { final paymentRequest = PaymentRequest.fromUri(uri); addressController.text = paymentRequest.address; - + if (amountController.text.isNotEmpty) { _showAmountPopup(context, paymentRequest); return; } widget.amountFocusNode?.requestFocus(); - amountController.text = paymentRequest.amount; + amountController.text = paymentRequest.amount; }, - placeholder: widget.hasRefundAddress - ? S.of(context).refund_address - : null, + placeholder: widget.hasRefundAddress ? S.of(context).refund_address : null, options: [ AddressTextFieldOption.paste, AddressTextFieldOption.qrCode, AddressTextFieldOption.addressBook, ], isBorderExist: false, - textStyle: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Colors.white), + textStyle: + TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white), hintStyle: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, @@ -381,27 +379,22 @@ class ExchangeCardState extends State { validator: widget.addressTextFieldValidator, onPushPasteButton: widget.onPushPasteButton, onPushAddressBookButton: widget.onPushAddressBookButton, - selectedCurrency: _selectedCurrency - ), - + selectedCurrency: _selectedCurrency), ), - ) + ) : Padding( padding: EdgeInsets.only(top: 10), child: Builder( builder: (context) => Stack(children: [ - FocusTraversalOrder( - order: NumericFocusOrder(3), - child: BaseTextFormField( - controller: addressController, - borderColor: Colors.transparent, - suffixIcon: - SizedBox(width: _isMoneroWallet ? 80 : 36), - textStyle: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Colors.white), - validator: widget.addressTextFieldValidator), + FocusTraversalOrder( + order: NumericFocusOrder(3), + child: BaseTextFormField( + controller: addressController, + borderColor: Colors.transparent, + suffixIcon: SizedBox(width: _isMoneroWallet ? 80 : 36), + textStyle: TextStyle( + fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white), + validator: widget.addressTextFieldValidator), ), Positioned( top: 2, @@ -421,33 +414,28 @@ class ExchangeCardState extends State { child: InkWell( onTap: () async { final contact = - await Navigator.of(context) - .pushNamed( + await Navigator.of(context).pushNamed( Routes.pickerAddressBook, arguments: widget.initialCurrency, ); - if (contact is ContactBase && - contact.address != null) { + if (contact is ContactBase) { setState(() => - addressController.text = - contact.address); - widget.onPushAddressBookButton - ?.call(context); + addressController.text = contact.address); + widget.onPushAddressBookButton?.call(context); } }, child: Container( padding: EdgeInsets.all(8), decoration: BoxDecoration( - color: widget - .addressButtonsColor, + color: widget.addressButtonsColor, borderRadius: - BorderRadius.all( - Radius.circular( - 6))), + BorderRadius.all(Radius.circular(6))), child: Image.asset( 'assets/images/open_book.png', - color: Theme.of(context).extension()!.textFieldButtonIconColor, + color: Theme.of(context) + .extension()! + .textFieldButtonIconColor, )), ), )), @@ -462,18 +450,13 @@ class ExchangeCardState extends State { label: S.of(context).copy_address, child: InkWell( onTap: () { - Clipboard.setData(ClipboardData( - text: addressController - .text)); + Clipboard.setData( + ClipboardData(text: addressController.text)); showBar( - context, - S - .of(context) - .copied_to_clipboard); + context, S.of(context).copied_to_clipboard); }, child: Container( - padding: EdgeInsets.fromLTRB( - 8, 8, 0, 8), + padding: EdgeInsets.fromLTRB(8, 8, 0, 8), color: Colors.transparent, child: copyImage), ), @@ -514,7 +497,6 @@ class ExchangeCardState extends State { Navigator.of(context).pop(); }, actionLeftButton: () => Navigator.of(dialogContext).pop()); - } - ); + }); } } diff --git a/lib/src/screens/send/send_template_page.dart b/lib/src/screens/send/send_template_page.dart index 205fd62e1..52458942c 100644 --- a/lib/src/screens/send/send_template_page.dart +++ b/lib/src/screens/send/send_template_page.dart @@ -1,7 +1,5 @@ import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; -import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart'; -import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/src/widgets/trail_button.dart'; import 'package:cake_wallet/view_model/send/template_view_model.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -11,7 +9,6 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/view_model/send/send_template_view_model.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/screens/send/widgets/prefix_currency_icon_widget.dart'; import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; import 'package:cake_wallet/src/screens/send/widgets/send_template_card.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart'; @@ -97,8 +94,13 @@ class SendTemplatePage extends BasePage { radius: 6.0, dotWidth: 6.0, dotHeight: 6.0, - dotColor: Theme.of(context).extension()!.indicatorDotColor, - activeDotColor: Theme.of(context).extension()!.indicatorDotTheme.activeIndicatorColor)) + dotColor: Theme.of(context) + .extension()! + .indicatorDotColor, + activeDotColor: Theme.of(context) + .extension()! + .indicatorDotTheme + .activeIndicatorColor)) : Offstage(); }, ), diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 6bd2d81e9..3f5714be9 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -80,15 +80,17 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin( - context: context, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: S.of(context).error, - alertContent: S.of(context).unmatched_currencies, - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop()); - }); + if (context.mounted) { + showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: S.of(context).error, + alertContent: S.of(context).unmatched_currencies, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop()); + }); + } }); } } @@ -321,7 +323,8 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin calculateDepositAllAmount() async { + if (wallet.type == WalletType.litecoin || wallet.type == WalletType.bitcoinCash) { final availableBalance = wallet.balance[wallet.currency]!.available; final priority = _settingsStore.priority[wallet.type]!; final fee = wallet.calculateEstimatedFee(priority, null); @@ -545,6 +553,13 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with final amount = availableBalance - fee; changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount)); + } else if (wallet.type == WalletType.bitcoin) { + final priority = _settingsStore.priority[wallet.type]!; + + final amount = await bitcoin!.estimateFakeSendAllTxAmount( + wallet, bitcoin!.deserializeBitcoinTransactionPriority(priority.raw)); + + changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount)); } } diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 106a8a652..b82513de2 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -125,4 +125,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 65ec1541137fb5b35d00490dec1bb48d4d9586bb -COCOAPODS: 1.12.1 +COCOAPODS: 1.15.2 diff --git a/pubspec_base.yaml b/pubspec_base.yaml index d4bf981cd..0293df1d1 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -110,7 +110,7 @@ dependencies: bitcoin_base: git: url: https://github.com/cake-tech/bitcoin_base.git - ref: cake-update-v1 + ref: cake-update-v2 dev_dependencies: flutter_test: diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 02f874d77..ec851a89b 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -22,8 +22,8 @@ MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.15.0" -CAKEWALLET_BUILD_NUMBER=198 +CAKEWALLET_VERSION="4.15.1" +CAKEWALLET_BUILD_NUMBER=199 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index b65d3e7a6..53bbf4022 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -18,8 +18,8 @@ MONERO_COM_BUILD_NUMBER=77 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.15.0" -CAKEWALLET_BUILD_NUMBER=217 +CAKEWALLET_VERSION="4.15.1" +CAKEWALLET_BUILD_NUMBER=218 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 19a1e6846..1e8022b7b 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -21,8 +21,8 @@ MONERO_COM_BUILD_NUMBER=10 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.8.0" -CAKEWALLET_BUILD_NUMBER=57 +CAKEWALLET_VERSION="1.8.1" +CAKEWALLET_BUILD_NUMBER=58 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then diff --git a/tool/configure.dart b/tool/configure.dart index 3c1587a98..962731d06 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -70,7 +70,6 @@ import 'package:cw_core/output_info.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cake_wallet/view_model/send/output.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; import 'package:bitcoin_base/bitcoin_base.dart';"""; const bitcoinCWHeaders = """ @@ -127,6 +126,7 @@ abstract class Bitcoin { List getAddresses(Object wallet); String getAddress(Object wallet); + Future estimateFakeSendAllTxAmount(Object wallet, TransactionPriority priority); List getSubAddresses(Object wallet); String formatterBitcoinAmountToString({required int amount}); From ecb4f32cdaafdd0c362027f641f6b6ff0e480324 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Thu, 21 Mar 2024 15:42:16 +0200 Subject: [PATCH 132/241] Fix Exchange field not taking numbers (#1341) --- lib/src/screens/exchange/exchange_page.dart | 2 +- lib/src/screens/exchange/widgets/exchange_card.dart | 4 +--- scripts/android/app_env.sh | 4 ++-- scripts/ios/app_env.sh | 4 ++-- scripts/macos/app_env.sh | 4 ++-- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 61355df05..1a5ab24e6 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -634,7 +634,7 @@ class ExchangePage extends BasePage { borderColor: Theme.of(context).extension()!.textFieldBorderTopPanelColor, currencyValueValidator: (value) { - return !exchangeViewModel.isFixedRateMode + return !exchangeViewModel.isFixedRateMode && value != S.of(context).all ? AmountValidator( isAutovalidate: true, currency: exchangeViewModel.depositCurrency, diff --git a/lib/src/screens/exchange/widgets/exchange_card.dart b/lib/src/screens/exchange/widgets/exchange_card.dart index d2e3c27d4..8fa809de9 100644 --- a/lib/src/screens/exchange/widgets/exchange_card.dart +++ b/lib/src/screens/exchange/widgets/exchange_card.dart @@ -272,9 +272,7 @@ class ExchangeCardState extends State { color: Theme.of(context) .extension()! .hintTextColor), - validator: widget.hasAllAmount - ? widget.allAmountValidator - : _isAmountEditable + validator: _isAmountEditable ? widget.currencyValueValidator : null), ), diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index ec851a89b..ed2b67de5 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -22,8 +22,8 @@ MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.15.1" -CAKEWALLET_BUILD_NUMBER=199 +CAKEWALLET_VERSION="4.15.2" +CAKEWALLET_BUILD_NUMBER=200 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 53bbf4022..53514b39b 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -18,8 +18,8 @@ MONERO_COM_BUILD_NUMBER=77 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.15.1" -CAKEWALLET_BUILD_NUMBER=218 +CAKEWALLET_VERSION="4.15.2" +CAKEWALLET_BUILD_NUMBER=219 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 1e8022b7b..1654a022a 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -21,8 +21,8 @@ MONERO_COM_BUILD_NUMBER=10 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.8.1" -CAKEWALLET_BUILD_NUMBER=58 +CAKEWALLET_VERSION="1.8.2" +CAKEWALLET_BUILD_NUMBER=59 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From af7fe0509969da18ae6f778210814bc020ca907e Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Thu, 21 Mar 2024 16:31:05 +0200 Subject: [PATCH 133/241] Generic fixes (#1342) * handle balance exceptions in estimating All exchange * Fix trades not showing --- cw_bitcoin/lib/electrum_wallet_addresses.dart | 4 ++- lib/bitcoin/cw_bitcoin.dart | 28 +++++++++++-------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 828bda8af..69d0a6385 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -220,7 +220,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { Future updateAddressesInBox() async { try { addressesMap.clear(); - addressesMap[address] = ''; + _addresses.forEach((addressRecord) { + addressesMap[addressRecord.address] = addressRecord.name; + }); await saveAddressesInBox(); } catch (e) { print(e.toString()); diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 709dc9a04..78423a8c3 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -127,19 +127,23 @@ class CWBitcoin extends Bitcoin { final p2shAddr = sk.getPublic().toP2pkhInP2sh(); final p2wpkhAddr = sk.getPublic().toP2wpkhAddress(); - final estimatedTx = await electrumWallet.estimateTxFeeAndInputsToUse( - 0, - true, - // Deposit address + change address - [p2shAddr, p2wpkhAddr], - [ - BitcoinOutput(address: p2shAddr, value: BigInt.zero), - BitcoinOutput(address: p2wpkhAddr, value: BigInt.zero) - ], - null, - priority as BitcoinTransactionPriority); + try { + final estimatedTx = await electrumWallet.estimateTxFeeAndInputsToUse( + 0, + true, + // Deposit address + change address + [p2shAddr, p2wpkhAddr], + [ + BitcoinOutput(address: p2shAddr, value: BigInt.zero), + BitcoinOutput(address: p2wpkhAddr, value: BigInt.zero) + ], + null, + priority as BitcoinTransactionPriority); - return estimatedTx.amount; + return estimatedTx.amount; + } catch (_) { + return 0; + } } @override From bca59ad5e486b6f0d9f6f572bc73f304b28199ae Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Mon, 25 Mar 2024 13:16:57 -0500 Subject: [PATCH 134/241] Remove moonpay secret use exchange-helper instead (#1343) * Remove moonpay secret use exchange-helper instead * Update lib/buy/moonpay/moonpay_provider.dart * remove web3dart dep from cw_solana * Apply new api for moonpay exchange helper * Add Robinhood as Polygon buy-provider --- .github/workflows/pr_test_build.yml | 2 +- cw_solana/lib/solana_wallet.dart | 6 +-- cw_solana/pubspec.yaml | 3 +- lib/buy/moonpay/moonpay_provider.dart | 52 +++++++++++++------ lib/buy/robinhood/robinhood_buy_provider.dart | 3 +- lib/entities/provider_types.dart | 11 +--- tool/utils/secret_key.dart | 2 +- 7 files changed, 44 insertions(+), 35 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 282941365..ddc8869f0 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -143,7 +143,7 @@ jobs: 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 robinhoodCIdApiSecret = '${{ secrets.ROBINHOOD_CID_CLIENT_SECRET }}';" >> 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 diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart index 3476d76cd..de4d70674 100644 --- a/cw_solana/lib/solana_wallet.dart +++ b/cw_solana/lib/solana_wallet.dart @@ -1,6 +1,5 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:developer'; import 'dart:io'; import 'package:cw_core/cake_hive.dart'; import 'package:cw_core/crypto_currency.dart'; @@ -30,7 +29,6 @@ import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:solana/metaplex.dart' as metaplex; import 'package:solana/solana.dart'; -import 'package:web3dart/crypto.dart'; part 'solana_wallet.g.dart'; @@ -134,7 +132,7 @@ abstract class SolanaWalletBase assert(mnemonic != null || privateKey != null); if (privateKey != null) { - final privateKeyBytes = hexToBytes(privateKey); + final privateKeyBytes = HEX.decode(privateKey); return await Wallet.fromPrivateKeyBytes(privateKey: privateKeyBytes); } @@ -491,7 +489,7 @@ abstract class SolanaWalletBase final signature = await _walletKeyPair!.sign(messageBytes); // Convert the signature to a hexadecimal string - final hex = bytesToHex(signature.bytes); + final hex = HEX.encode(signature.bytes); return hex; } diff --git a/cw_solana/pubspec.yaml b/cw_solana/pubspec.yaml index c98b7492e..7e24983bf 100644 --- a/cw_solana/pubspec.yaml +++ b/cw_solana/pubspec.yaml @@ -19,7 +19,6 @@ dependencies: bip39: ^1.0.6 mobx: ^2.3.0+1 shared_preferences: ^2.0.15 - web3dart: ^2.7.1 bip32: ^2.0.0 hex: ^0.2.0 @@ -34,4 +33,4 @@ dev_dependencies: flutter: # assets: # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg \ No newline at end of file + # - images/a_dot_ham.jpeg diff --git a/lib/buy/moonpay/moonpay_provider.dart b/lib/buy/moonpay/moonpay_provider.dart index 75ba45ce1..02bdedaec 100644 --- a/lib/buy/moonpay/moonpay_provider.dart +++ b/lib/buy/moonpay/moonpay_provider.dart @@ -1,4 +1,13 @@ import 'dart:convert'; + +import 'package:cake_wallet/.secrets.g.dart' as secrets; +import 'package:cake_wallet/buy/buy_amount.dart'; +import 'package:cake_wallet/buy/buy_exception.dart'; +import 'package:cake_wallet/buy/buy_provider.dart'; +import 'package:cake_wallet/buy/buy_provider_description.dart'; +import 'package:cake_wallet/buy/order.dart'; +import 'package:cake_wallet/exchange/trade_state.dart'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; @@ -6,19 +15,11 @@ import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:crypto/crypto.dart'; -import 'package:cake_wallet/buy/buy_exception.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:flutter/material.dart'; -import 'package:http/http.dart'; -import 'package:cake_wallet/buy/buy_amount.dart'; -import 'package:cake_wallet/buy/buy_provider.dart'; -import 'package:cake_wallet/buy/buy_provider_description.dart'; -import 'package:cake_wallet/buy/order.dart'; +import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:cake_wallet/exchange/trade_state.dart'; -import 'package:cake_wallet/.secrets.g.dart' as secrets; -import 'package:cw_core/crypto_currency.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; import 'package:url_launcher/url_launcher.dart'; class MoonPaySellProvider extends BuyProvider { @@ -34,6 +35,7 @@ class MoonPaySellProvider extends BuyProvider { static const _baseTestUrl = 'sell-sandbox.moonpay.com'; static const _baseProductUrl = 'sell.moonpay.com'; + static const _cIdBaseUrl = 'exchange-helper.cakewallet.com'; @override String get providerDescription => @@ -60,9 +62,29 @@ class MoonPaySellProvider extends BuyProvider { static String get _apiKey => secrets.moonPayApiKey; - static String get _secretKey => secrets.moonPaySecretKey; + static String get _exchangeHelperApiKey => secrets.exchangeHelperApiKey; final String baseUrl; + Future getMoonpaySignature(String query) async { + final uri = Uri.https(_cIdBaseUrl, "/api/moonpay"); + + final response = await post( + uri, + headers: { + 'Content-Type': 'application/json', + 'x-api-key': _exchangeHelperApiKey, + }, + body: json.encode({'query': query}), + ); + + if (response.statusCode == 200) { + return (jsonDecode(response.body) as Map)['signature'] as String; + } else { + throw Exception( + 'Provider currently unavailable. Status: ${response.statusCode} ${response.body}'); + } + } + Future requestMoonPayUrl({ required CryptoCurrency currency, required String refundWalletAddress, @@ -86,11 +108,7 @@ class MoonPaySellProvider extends BuyProvider { }..addAll(customParams), ); - final messageBytes = utf8.encode('?${originalUri.query}'); - final key = utf8.encode(_secretKey); - final hmac = Hmac(sha256, key); - final digest = hmac.convert(messageBytes); - final signature = base64.encode(digest.bytes); + final signature = await getMoonpaySignature('?${originalUri.query}'); if (isTestEnvironment) { return originalUri; diff --git a/lib/buy/robinhood/robinhood_buy_provider.dart b/lib/buy/robinhood/robinhood_buy_provider.dart index 47c3ab1ea..7610e51f3 100644 --- a/lib/buy/robinhood/robinhood_buy_provider.dart +++ b/lib/buy/robinhood/robinhood_buy_provider.dart @@ -32,11 +32,12 @@ class RobinhoodBuyProvider extends BuyProvider { String get _applicationId => secrets.robinhoodApplicationId; - String get _apiSecret => secrets.robinhoodCIdApiSecret; + String get _apiSecret => secrets.exchangeHelperApiKey; String getSignature(String message) { switch (wallet.type) { case WalletType.ethereum: + case WalletType.polygon: return wallet.signMessage(message); case WalletType.litecoin: case WalletType.bitcoin: diff --git a/lib/entities/provider_types.dart b/lib/entities/provider_types.dart index b7336c2a7..f3993e129 100644 --- a/lib/entities/provider_types.dart +++ b/lib/entities/provider_types.dart @@ -55,6 +55,7 @@ class ProvidersHelper { case WalletType.monero: return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.dfx]; case WalletType.bitcoin: + case WalletType.polygon: case WalletType.ethereum: return [ ProviderType.askEachTime, @@ -65,8 +66,6 @@ class ProvidersHelper { case WalletType.litecoin: case WalletType.bitcoinCash: return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood]; - case WalletType.polygon: - return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.dfx]; case WalletType.solana: return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood]; case WalletType.none: @@ -79,6 +78,7 @@ class ProvidersHelper { switch (walletType) { case WalletType.bitcoin: case WalletType.ethereum: + case WalletType.polygon: return [ ProviderType.askEachTime, ProviderType.onramper, @@ -88,13 +88,6 @@ class ProvidersHelper { case WalletType.litecoin: case WalletType.bitcoinCash: return [ProviderType.askEachTime, ProviderType.moonpaySell]; - case WalletType.polygon: - return [ - ProviderType.askEachTime, - ProviderType.onramper, - ProviderType.moonpaySell, - ProviderType.dfx, - ]; case WalletType.solana: return [ ProviderType.askEachTime, diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index 38b5129af..430de03b6 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -34,7 +34,7 @@ class SecretKey { SecretKey('chatwootWebsiteToken', () => ''), SecretKey('exolixApiKey', () => ''), SecretKey('robinhoodApplicationId', () => ''), - SecretKey('robinhoodCIdApiSecret', () => ''), + SecretKey('exchangeHelperApiKey', () => ''), SecretKey('walletConnectProjectId', () => ''), SecretKey('moralisApiKey', () => ''), ]; From 4520f583a6d66a8678b8f0c476dde8b9509a1fe0 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Mon, 25 Mar 2024 14:28:45 -0400 Subject: [PATCH 135/241] Add toggle for disabling service bulletin (#1347) * Add toggle for disabling service bulletin * Make the toggle functional * Fix + add toggle to Advanced Settings * Remove unused variable --------- Co-authored-by: Omar Hatem --- lib/entities/preferences_key.dart | 1 + lib/src/screens/dashboard/dashboard_page.dart | 11 ++++++++++- .../new_wallet/advanced_privacy_settings_page.dart | 6 ++++++ lib/src/screens/settings/privacy_page.dart | 6 ++++++ lib/store/settings_store.dart | 13 +++++++++++++ .../advanced_privacy_settings_view_model.dart | 6 ++++++ lib/view_model/dashboard/dashboard_view_model.dart | 3 +++ .../settings/privacy_settings_view_model.dart | 6 ++++++ res/values/strings_ar.arb | 1 + res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 3 ++- res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 1 + res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 1 + res/values/strings_my.arb | 1 + res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_th.arb | 1 + res/values/strings_tl.arb | 1 + res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + 34 files changed, 78 insertions(+), 2 deletions(-) diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 1808be97c..5c22455d2 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -20,6 +20,7 @@ class PreferencesKey { static const isAppSecureKey = 'is_app_secure'; static const disableBuyKey = 'disable_buy'; static const disableSellKey = 'disable_sell'; + static const disableBulletinKey = 'disable_bulletin'; static const defaultBuyProvider = 'default_buy_provider'; static const walletListOrder = 'wallet_list_order'; static const walletListAscending = 'wallet_list_ascending'; diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index 3806dff91..ed06f4704 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -103,7 +103,16 @@ class _DashboardPageView extends BasePage { Widget get endDrawer => MenuWidget(dashboardViewModel); @override - Widget leading(BuildContext context) => ServicesUpdatesWidget(dashboardViewModel.getServicesStatus()); + Widget leading(BuildContext context) { + return Observer( + builder: (context) { + if (dashboardViewModel.isEnabledBulletinAction) { + return ServicesUpdatesWidget(dashboardViewModel.getServicesStatus()); + } + return const SizedBox(); + }, + ); + } @override Widget middle(BuildContext context) { diff --git a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart index 26478345e..881d9f95a 100644 --- a/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart +++ b/lib/src/screens/new_wallet/advanced_privacy_settings_page.dart @@ -100,6 +100,12 @@ class _AdvancedPrivacySettingsBodyState extends State sharedPreferences.setBool(PreferencesKey.disableSellKey, disableSell)); + reaction( + (_) => disableBulletin, + (bool disableBulletin) => + sharedPreferences.setBool(PreferencesKey.disableBulletinKey, disableBulletin)); + reaction( (_) => walletListOrder, (WalletListOrderType walletListOrder) => @@ -553,6 +560,9 @@ abstract class SettingsStoreBase with Store { @observable bool disableSell; + @observable + bool disableBulletin; + @observable WalletListOrderType walletListOrder; @@ -777,6 +787,7 @@ abstract class SettingsStoreBase with Store { final isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? false; final disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? false; final disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? false; + final disableBulletin = sharedPreferences.getBool(PreferencesKey.disableBulletinKey) ?? false; final walletListOrder = WalletListOrderType.values[sharedPreferences.getInt(PreferencesKey.walletListOrder) ?? 0]; final walletListAscending = @@ -1029,6 +1040,7 @@ abstract class SettingsStoreBase with Store { initialAppSecure: isAppSecure, initialDisableBuy: disableBuy, initialDisableSell: disableSell, + initialDisableBulletin: disableBulletin, initialWalletListOrder: walletListOrder, initialWalletListAscending: walletListAscending, initialFiatMode: currentFiatApiMode, @@ -1147,6 +1159,7 @@ abstract class SettingsStoreBase with Store { isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? isAppSecure; disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? disableBuy; disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? disableSell; + disableBulletin = sharedPreferences.getBool(PreferencesKey.disableBulletinKey) ?? disableBulletin; walletListOrder = WalletListOrderType.values[sharedPreferences.getInt(PreferencesKey.walletListOrder) ?? 0]; walletListAscending = sharedPreferences.getBool(PreferencesKey.walletListAscending) ?? true; diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart index b78d831a4..a17ddff36 100644 --- a/lib/view_model/advanced_privacy_settings_view_model.dart +++ b/lib/view_model/advanced_privacy_settings_view_model.dart @@ -20,6 +20,9 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { @computed FiatApiMode get fiatApiMode => _settingsStore.fiatApiMode; + @computed + bool get disableBulletin => _settingsStore.disableBulletin; + @observable bool _addCustomNode = false; @@ -64,6 +67,9 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { @action void setExchangeApiMode(ExchangeApiMode value) => _settingsStore.exchangeStatus = value; + @action + void setDisableBulletin(bool value) => _settingsStore.disableBulletin = value; + @action void toggleAddCustomNode() => _addCustomNode = !_addCustomNode; diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index b02c09f82..9ee0647fc 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -355,6 +355,9 @@ abstract class DashboardViewModelBase with Store { @observable bool hasSellAction; + @computed + bool get isEnabledBulletinAction => !settingsStore.disableBulletin; + ReactionDisposer? _onMoneroAccountChangeReaction; ReactionDisposer? _onMoneroBalanceChangeReaction; diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart index 65375b3e7..831a45357 100644 --- a/lib/view_model/settings/privacy_settings_view_model.dart +++ b/lib/view_model/settings/privacy_settings_view_model.dart @@ -59,6 +59,9 @@ abstract class PrivacySettingsViewModelBase with Store { @computed bool get disableSell => _settingsStore.disableSell; + @computed + bool get disableBulletin => _settingsStore.disableBulletin; + @computed bool get useEtherscan => _settingsStore.useEtherscan; @@ -106,6 +109,9 @@ abstract class PrivacySettingsViewModelBase with Store { @action void setDisableSell(bool value) => _settingsStore.disableSell = value; + @action + void setDisableBulletin(bool value) => _settingsStore.disableBulletin = value; + @action void setLookupsTwitter(bool value) => _settingsStore.lookupsTwitter = value; diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 900f59135..66af15dfa 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -186,6 +186,7 @@ "digit_pin": "-رقم PIN", "digital_and_physical_card": " بطاقة ائتمان رقمية ومادية مسبقة الدفع", "disable": "إبطال", + "disable_bulletin": "تعطيل نشرة حالة الخدمة", "disable_buy": "تعطيل إجراء الشراء", "disable_cake_2fa": "تعطيل 2 عامل المصادقة", "disable_exchange": "تعطيل التبادل", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 3e8cd148e..061506b86 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -186,6 +186,7 @@ "digit_pin": "-цифрен PIN", "digital_and_physical_card": " дигитална или физическа предплатена дебитна карта", "disable": "Деактивиране", + "disable_bulletin": "Деактивирайте бюлетина за състоянието на услугата", "disable_buy": "Деактивирайте действието за покупка", "disable_cake_2fa": "Деактивирайте Cake 2FA", "disable_exchange": "Деактивиране на борса", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 8a5213821..2896c11a9 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -186,6 +186,7 @@ "digit_pin": "-číselný PIN", "digital_and_physical_card": " digitální a fyzické předplacené debetní karty,", "disable": "Zakázat", + "disable_bulletin": "Zakázat status servisního stavu", "disable_buy": "Zakázat akci nákupu", "disable_cake_2fa": "Zakázat Cake 2FA", "disable_exchange": "Zakázat směnárny", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 549f6f775..9dfa4f4db 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -186,6 +186,7 @@ "digit_pin": "-stellige PIN", "digital_and_physical_card": "digitale und physische Prepaid-Debitkarte", "disable": "Deaktivieren", + "disable_bulletin": "Deaktivieren Sie das Bulletin des Service Status", "disable_buy": "Kaufaktion deaktivieren", "disable_cake_2fa": "Cake 2FA deaktivieren", "disable_exchange": "Exchange deaktivieren", @@ -411,8 +412,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", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 9b1610da5..902cb062f 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -186,6 +186,7 @@ "digit_pin": "-digit PIN", "digital_and_physical_card": " digital and physical prepaid debit card", "disable": "Disable", + "disable_bulletin": "Disable service status bulletin", "disable_buy": "Disable buy action", "disable_cake_2fa": "Disable Cake 2FA", "disable_exchange": "Disable exchange", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 4847f5521..4b9a9d26b 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -186,6 +186,7 @@ "digit_pin": "-dígito PIN", "digital_and_physical_card": " tarjeta de débito prepago digital y física", "disable": "Desactivar", + "disable_bulletin": "Desactivar el boletín de estado del servicio", "disable_buy": "Desactivar acción de compra", "disable_cake_2fa": "Desactivar pastel 2FA", "disable_exchange": "Deshabilitar intercambio", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index d1390a5ca..384bb9585 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -186,6 +186,7 @@ "digit_pin": " chiffres", "digital_and_physical_card": "carte de débit prépayée numérique et physique", "disable": "Désactiver", + "disable_bulletin": "Désactiver le bulletin de statut de service", "disable_buy": "Désactiver l'action d'achat", "disable_cake_2fa": "Désactiver Cake 2FA", "disable_exchange": "Désactiver l'échange", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index e9bd604d2..7c0a7df12 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -186,6 +186,7 @@ "digit_pin": "-lambar PIN", "digital_and_physical_card": "katin zare kudi na dijital da na zahiri", "disable": "Kashe", + "disable_bulletin": "Musaki ma'aunin sabis na sabis", "disable_buy": "Kashe alama", "disable_cake_2fa": "Musaki Cake 2FA", "disable_exchange": "Kashe musanya", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 535fd0264..932fb25e7 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -186,6 +186,7 @@ "digit_pin": "-अंक पिन", "digital_and_physical_card": "डिजिटल और भौतिक प्रीपेड डेबिट कार्ड", "disable": "अक्षम करना", + "disable_bulletin": "सेवा स्थिति बुलेटिन अक्षम करें", "disable_buy": "खरीद कार्रवाई अक्षम करें", "disable_cake_2fa": "केक 2FA अक्षम करें", "disable_exchange": "एक्सचेंज अक्षम करें", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 9a7cab450..c8c9a00bd 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -186,6 +186,7 @@ "digit_pin": "-znamenkasti PIN", "digital_and_physical_card": "digitalna i fizička unaprijed plaćena debitna kartica", "disable": "Onemogući", + "disable_bulletin": "Onemogućite bilten o statusu usluge", "disable_buy": "Onemogući kupnju", "disable_cake_2fa": "Onemogući Cake 2FA", "disable_exchange": "Onemogući exchange", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index f29298c4f..2168de910 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -186,6 +186,7 @@ "digit_pin": "-digit PIN", "digital_and_physical_card": " kartu debit pra-bayar digital dan fisik", "disable": "Cacat", + "disable_bulletin": "Nonaktifkan Buletin Status Layanan", "disable_buy": "Nonaktifkan tindakan beli", "disable_cake_2fa": "Nonaktifkan Kue 2FA", "disable_exchange": "Nonaktifkan pertukaran", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 82dd6b976..2700203a0 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -187,6 +187,7 @@ "digit_pin": "-cifre PIN", "digital_and_physical_card": "carta di debito prepagata digitale e fisica", "disable": "disattivare", + "disable_bulletin": "Disabilita Bollettino dello stato del servizio", "disable_buy": "Disabilita l'azione di acquisto", "disable_cake_2fa": "Disabilita Cake 2FA", "disable_exchange": "Disabilita scambio", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 95a7643b0..443ce6658 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -186,6 +186,7 @@ "digit_pin": "桁ピン", "digital_and_physical_card": "デジタルおよび物理プリペイドデビットカード", "disable": "無効にする", + "disable_bulletin": "サービスステータス速報を無効にします", "disable_buy": "購入アクションを無効にする", "disable_cake_2fa": "Cake 2FA を無効にする", "disable_exchange": "交換を無効にする", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index e8b208c28..3affd803b 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -186,6 +186,7 @@ "digit_pin": "숫자 PIN", "digital_and_physical_card": " 디지털 및 실제 선불 직불 카드", "disable": "장애를 입히다", + "disable_bulletin": "서비스 상태 게시판을 비활성화합니다", "disable_buy": "구매 행동 비활성화", "disable_cake_2fa": "케이크 2FA 비활성화", "disable_exchange": "교환 비활성화", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 42ea07cb6..c52d65c06 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -186,6 +186,7 @@ "digit_pin": "-ဂဏန်း PIN", "digital_and_physical_card": " ဒစ်ဂျစ်တယ်နှင့် ရုပ်ပိုင်းဆိုင်ရာ ကြိုတင်ငွေပေးချေသော ဒက်ဘစ်ကတ်", "disable": "ပိတ်ပါ။", + "disable_bulletin": "ဝန်ဆောင်မှုအခြေအနေစာစောင်ကိုပိတ်ပါ", "disable_buy": "ဝယ်ယူမှု လုပ်ဆောင်ချက်ကို ပိတ်ပါ။", "disable_cake_2fa": "ကိတ်မုန့် 2FA ကို ပိတ်ပါ။", "disable_exchange": "လဲလှယ်မှုကို ပိတ်ပါ။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index a00a12338..fa7825809 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -186,6 +186,7 @@ "digit_pin": "-cijferige PIN", "digital_and_physical_card": "digitale en fysieke prepaid debetkaart", "disable": "Uitzetten", + "disable_bulletin": "Schakel servicestatus Bulletin uit", "disable_buy": "Koopactie uitschakelen", "disable_cake_2fa": "Taart 2FA uitschakelen", "disable_exchange": "Uitwisseling uitschakelen", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 1ad616bc9..16dc8696a 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -186,6 +186,7 @@ "digit_pin": "-znakowy PIN", "digital_and_physical_card": " cyfrowa i fizyczna przedpłacona karta debetowa", "disable": "Wyłączyć", + "disable_bulletin": "Wyłącz biuletyn statusu usługi", "disable_buy": "Wyłącz akcję kupna", "disable_cake_2fa": "Wyłącz Cake 2FA", "disable_exchange": "Wyłącz wymianę", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index c1b579186..8516ecf3f 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -186,6 +186,7 @@ "digit_pin": "dígitos", "digital_and_physical_card": "cartão de débito pré-pago digital e físico", "disable": "Desativar", + "disable_bulletin": "Desativar boletim de status de serviço", "disable_buy": "Desativar ação de compra", "disable_cake_2fa": "Desabilitar o Cake 2FA", "disable_exchange": "Desativar troca", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index f327f126a..2bff24414 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -186,6 +186,7 @@ "digit_pin": "-значный PIN", "digital_and_physical_card": "цифровая и физическая предоплаченная дебетовая карта", "disable": "Запрещать", + "disable_bulletin": "Отключить бюллетень статуса обслуживания", "disable_buy": "Отключить действие покупки", "disable_cake_2fa": "Отключить торт 2FA", "disable_exchange": "Отключить обмен", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 255b80df7..9c37ff8bb 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -186,6 +186,7 @@ "digit_pin": "-หลัก PIN", "digital_and_physical_card": "บัตรเดบิตดิจิตอลและบัตรพื้นฐาน", "disable": "ปิดการใช้งาน", + "disable_bulletin": "ปิดการใช้งาน Bulletin สถานะบริการ", "disable_buy": "ปิดการใช้งานการซื้อ", "disable_cake_2fa": "ปิดการใช้งานเค้ก 2FA", "disable_exchange": "ปิดใช้งานการแลกเปลี่ยน", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 1d7063881..d4be21741 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -186,6 +186,7 @@ "digit_pin": "-digit pin", "digital_and_physical_card": "Digital at Physical Prepaid Debit Card", "disable": "Huwag paganahin", + "disable_bulletin": "Huwag paganahin ang Bulletin ng Katayuan ng Serbisyo", "disable_buy": "Huwag paganahin ang pagkilos ng pagbili", "disable_cake_2fa": "Huwag paganahin ang cake 2FA", "disable_exchange": "Huwag paganahin ang palitan", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 99879d5ef..a6209ed33 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -186,6 +186,7 @@ "digit_pin": " haneli PIN", "digital_and_physical_card": " Dijital para birimleri ile para yükleyebileceğiniz ve ek bilgiye gerek olmayan", "disable": "Devre dışı bırakmak", + "disable_bulletin": "Hizmet Durumu Bültenini Devre Dışı Bırak", "disable_buy": "Satın alma işlemini devre dışı bırak", "disable_cake_2fa": "Cake 2FA'yı Devre Dışı Bırak", "disable_exchange": "Borsayı devre dışı bırak", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 63c59d475..3d60b9e8e 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -186,6 +186,7 @@ "digit_pin": "-значний PIN", "digital_and_physical_card": " цифрова та фізична передплачена дебетова картка", "disable": "Вимкнути", + "disable_bulletin": "Вимкнути статус послуги", "disable_buy": "Вимкнути дію покупки", "disable_cake_2fa": "Вимкнути Cake 2FA", "disable_exchange": "Вимкнути exchange", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 08212c0b1..e0e74e6de 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -186,6 +186,7 @@ "digit_pin": "-ہندسوں کا پن", "digital_and_physical_card": " ڈیجیٹل اور فزیکل پری پیڈ ڈیبٹ کارڈ", "disable": "غیر فعال کریں۔", + "disable_bulletin": "خدمت کی حیثیت کا بلیٹن کو غیر فعال کریں", "disable_buy": "خرید ایکشن کو غیر فعال کریں۔", "disable_cake_2fa": "کیک 2FA کو غیر فعال کریں۔", "disable_exchange": "تبادلے کو غیر فعال کریں۔", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index f9b198843..54df5dbf2 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -186,6 +186,7 @@ "digit_pin": "-díjíìtì òǹkà ìdánimọ̀ àdáni", "digital_and_physical_card": " káàdì ìrajà t'ara àti ti ayélujára", "disable": "Ko si", + "disable_bulletin": "Mu blogti ipo ipo ṣiṣẹ", "disable_buy": "Ko iṣọrọ ọja", "disable_cake_2fa": "Ko 2FA Cake sii", "disable_exchange": "Pa ilé pàṣípààrọ̀", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 8a61a6a4a..cb1f012fb 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -186,6 +186,7 @@ "digit_pin": "位 PIN", "digital_and_physical_card": "数字和物理预付借记卡", "disable": "停用", + "disable_bulletin": "禁用服务状态公告", "disable_buy": "禁用购买操作", "disable_cake_2fa": "禁用蛋糕 2FA", "disable_exchange": "禁用交换", From 6ae0f37b9c6ccb6376981e944eea1a7054eb270d Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Tue, 26 Mar 2024 11:37:52 +0100 Subject: [PATCH 136/241] CW-597-AuthService-Bug (#1346) * fix: AuthService keychain bug fix * fix: Fetch read implementation * fix: Simplify logic for retries * Minor enhancement --------- Co-authored-by: Omar Hatem --- lib/core/auth_service.dart | 7 +++++-- lib/core/key_service.dart | 3 ++- lib/core/secure_storage.dart | 27 +++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 lib/core/secure_storage.dart diff --git a/lib/core/auth_service.dart b/lib/core/auth_service.dart index a99aef31d..48610784c 100644 --- a/lib/core/auth_service.dart +++ b/lib/core/auth_service.dart @@ -1,5 +1,7 @@ +import 'dart:async'; import 'dart:io'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/core/totp_request_details.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; @@ -64,7 +66,7 @@ class AuthService with Store { Future authenticate(String pin) async { final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); - final encodedPin = await secureStorage.read(key: key); + final encodedPin = await readSecureStorage(secureStorage, key); final decodedPin = decodedPinCode(pin: encodedPin!); return decodedPin == pin; @@ -76,7 +78,8 @@ class AuthService with Store { } Future requireAuth() async { - final timestamp = int.tryParse(await secureStorage.read(key: SecureKey.lastAuthTimeMilliseconds) ?? '0'); + final timestamp = + int.tryParse(await secureStorage.read(key: SecureKey.lastAuthTimeMilliseconds) ?? '0'); final duration = _durationToRequireAuth(timestamp ?? 0); final requiredPinInterval = settingsStore.pinTimeOutDuration; diff --git a/lib/core/key_service.dart b/lib/core/key_service.dart index fce254ea2..f829c22b5 100644 --- a/lib/core/key_service.dart +++ b/lib/core/key_service.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cake_wallet/entities/encrypt.dart'; @@ -10,7 +11,7 @@ class KeyService { Future getWalletPassword({required String walletName}) async { final key = generateStoreKeyFor( key: SecretStoreKey.moneroWalletPassword, walletName: walletName); - final encodedPassword = await _secureStorage.read(key: key); + final encodedPassword = await readSecureStorage(_secureStorage, key); return decodeWalletPassword(password: encodedPassword!); } diff --git a/lib/core/secure_storage.dart b/lib/core/secure_storage.dart new file mode 100644 index 000000000..4d9334a10 --- /dev/null +++ b/lib/core/secure_storage.dart @@ -0,0 +1,27 @@ +import 'dart:async'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +// For now, we can create a utility function to handle this. +// +// However, we could look into abstracting the entire FlutterSecureStorage package +// so the app doesn't depend on the package directly but an absraction. +// It'll make these kind of modifications to read/write come from a single point. + +Future readSecureStorage(FlutterSecureStorage secureStorage, String key) async { + String? result; + const maxWait = Duration(seconds: 3); + const checkInterval = Duration(milliseconds: 200); + + DateTime start = DateTime.now(); + + while (result == null && DateTime.now().difference(start) < maxWait) { + result = await secureStorage.read(key: key); + + if (result != null) { + break; + } + + await Future.delayed(checkInterval); + } + + return result; +} From b9e803f3bd603a996e526cfd27db5d3c00f7b48f Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Tue, 26 Mar 2024 11:08:39 -0500 Subject: [PATCH 137/241] Fix pubspec generation on windows (#1351) --- tool/configure.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/configure.dart b/tool/configure.dart index 962731d06..99d1fe8ee 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -1037,7 +1037,7 @@ Future generatePubspec( final inputFile = File(pubspecOutputPath); final inputText = await inputFile.readAsString(); final inputLines = inputText.split('\n'); - final dependenciesIndex = inputLines.indexWhere((line) => line.toLowerCase() == 'dependencies:'); + final dependenciesIndex = inputLines.indexWhere((line) => line.toLowerCase().contains('dependencies:')); var output = cwCore; if (hasMonero) { From cdf081edfdab1b4e05e3a8e83e709e624784cafc Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 28 Mar 2024 14:41:11 +0200 Subject: [PATCH 138/241] Cw 537 integrate thor chain swaps (#1280) * thorChain btc to eth swap * eth to btc swap * update the UI * update localization * Update thorchain_exchange.provider.dart * minor fixes * minor fix * fix min amount bug * revert amount_converter changes * fetching thorChain traid info * resolve evm related merge conflicts * minor fix * Fix eth transaction hash for Thorchain Integration * add new status endpoint and refund address for eth * Adjust affiliate fee * Fix conflicts with main * review comments + transaction filter item * taproot addresses check * added 10 outputs check * Update thorchain_exchange.provider.dart * minor fixes * update thorchain title * fix fetching rate for thorchain * Revert "fix fetching rate for thorchain" This reverts commit 3aa1386ecfbca14271bf01a73b424de19c4fd484. * fix thorchain exchange rate --------- Co-authored-by: OmarHatem --- assets/images/thorchain.png | Bin 0 -> 5478 bytes cw_bitcoin/lib/electrum_wallet.dart | 39 ++- .../lib/pending_bitcoin_transaction.dart | 3 + .../lib/src/bitcoin_cash_wallet.dart | 5 +- cw_core/lib/output_info.dart | 4 +- cw_core/lib/pending_transaction.dart | 1 + cw_evm/lib/evm_chain_client.dart | 9 + cw_evm/lib/evm_chain_wallet.dart | 8 + cw_evm/lib/pending_evm_chain_transaction.dart | 10 +- cw_polygon/lib/polygon_client.dart | 2 + lib/bitcoin/cw_bitcoin.dart | 3 +- lib/ethereum/cw_ethereum.dart | 3 +- .../exchange_provider_description.dart | 4 + .../provider/thorchain_exchange.provider.dart | 248 ++++++++++++++++++ lib/exchange/trade.dart | 24 +- lib/exchange/trade_state.dart | 3 + .../dashboard/widgets/filter_tile.dart | 2 +- .../widgets/sync_indicator_icon.dart | 2 + .../screens/dashboard/widgets/trade_row.dart | 38 +-- lib/src/screens/exchange/exchange_page.dart | 15 +- lib/store/dashboard/trade_filter_store.dart | 39 ++- .../anonpay_details_view_model.dart | 2 +- .../dashboard/dashboard_view_model.dart | 5 + .../exchange/exchange_trade_view_model.dart | 13 +- .../exchange/exchange_view_model.dart | 29 +- lib/view_model/order_details_view_model.dart | 2 +- lib/view_model/send/output.dart | 3 + lib/view_model/send/send_view_model.dart | 10 +- lib/view_model/trade_details_view_model.dart | 58 ++-- 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_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_yo.arb | 2 + res/values/strings_zh.arb | 2 + 55 files changed, 534 insertions(+), 102 deletions(-) create mode 100644 assets/images/thorchain.png create mode 100644 lib/exchange/provider/thorchain_exchange.provider.dart diff --git a/assets/images/thorchain.png b/assets/images/thorchain.png new file mode 100644 index 0000000000000000000000000000000000000000..674b60f824c16848aaef27b347588ffeb8051deb GIT binary patch literal 5478 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 aYt7G+@%vUxf9L outputs, int? feeRate, BitcoinTransactionPriority? priority, - {int? inputsCount}) async { + {int? inputsCount, + String? memo}) async { final utxos = []; List privateKeys = []; @@ -253,7 +254,11 @@ abstract class ElectrumWalletBase } final estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize( - utxos: utxos, outputs: outputs, network: network); + utxos: utxos, + outputs: outputs, + network: network, + memo: memo, + ); int fee = feeRate != null ? feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize) @@ -300,7 +305,13 @@ abstract class ElectrumWalletBase } } - return EstimatedTxResult(utxos: utxos, privateKeys: privateKeys, fee: fee, amount: amount); + return EstimatedTxResult( + utxos: utxos, + privateKeys: privateKeys, + fee: fee, + amount: amount, + memo: memo, + ); } @override @@ -348,13 +359,17 @@ abstract class ElectrumWalletBase outputs, transactionCredentials.feeRate, transactionCredentials.priority, + memo: transactionCredentials.outputs.first.memo, ); final txb = BitcoinTransactionBuilder( - utxos: estimatedTx.utxos, - outputs: outputs, - fee: BigInt.from(estimatedTx.fee), - network: network); + utxos: estimatedTx.utxos, + outputs: outputs, + fee: BigInt.from(estimatedTx.fee), + network: network, + memo: estimatedTx.memo, + outputOrdering: BitcoinOrdering.none, + ); final transaction = txb.buildTransaction((txDigest, utxo, publicKey, sighash) { final key = estimatedTx.privateKeys @@ -888,13 +903,19 @@ class EstimateTxParams { } class EstimatedTxResult { - EstimatedTxResult( - {required this.utxos, required this.privateKeys, required this.fee, required this.amount}); + EstimatedTxResult({ + required this.utxos, + required this.privateKeys, + required this.fee, + required this.amount, + this.memo, + }); final List utxos; final List privateKeys; final int fee; final int amount; + final String? memo; } BitcoinBaseAddress addressTypeFromStr(String address, BasedUtxoNetwork network) { diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart index fa413febd..b45931133 100644 --- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart +++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart @@ -31,6 +31,9 @@ class PendingBitcoinTransaction with PendingTransaction { @override String get feeFormatted => bitcoinAmountToString(amount: fee); + @override + int? get outputCount => _tx.outputs.length; + final List _listeners; @override diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index f5835e728..40ddcfa57 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -140,6 +140,8 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { var allInputsAmount = 0; + final String? opReturnMemo = outputs.first.memo; + if (unspentCoins.isEmpty) await updateUnspent(); for (final utx in unspentCoins) { @@ -282,6 +284,8 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { txb.addOutput(changeAddress, changeValue); } + if (opReturnMemo != null) txb.addOutputData(opReturnMemo); + for (var i = 0; i < inputs.length; i++) { final input = inputs[i]; final keyPair = generateKeyPair( @@ -290,7 +294,6 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { txb.sign(i, keyPair, input.value); } - // Build the transaction final tx = txb.build(); return PendingBitcoinCashTransaction(tx, type, diff --git a/cw_core/lib/output_info.dart b/cw_core/lib/output_info.dart index e2b1201a8..9e3ac4ffc 100644 --- a/cw_core/lib/output_info.dart +++ b/cw_core/lib/output_info.dart @@ -7,7 +7,8 @@ class OutputInfo { this.formattedCryptoAmount, this.fiatAmount, this.note, - this.extractedAddress,}); + this.extractedAddress, + this.memo}); final String? fiatAmount; final String? cryptoAmount; @@ -17,4 +18,5 @@ class OutputInfo { final bool sendAll; final bool isParsedAddress; final int? formattedCryptoAmount; + final String? memo; } \ No newline at end of file diff --git a/cw_core/lib/pending_transaction.dart b/cw_core/lib/pending_transaction.dart index cc5686fc9..042b0ca2b 100644 --- a/cw_core/lib/pending_transaction.dart +++ b/cw_core/lib/pending_transaction.dart @@ -3,6 +3,7 @@ mixin PendingTransaction { String get amountFormatted; String get feeFormatted; String get hex; + int? get outputCount => null; Future commit(); } \ 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 de5b3874a..5e84ec796 100644 --- a/cw_evm/lib/evm_chain_client.dart +++ b/cw_evm/lib/evm_chain_client.dart @@ -14,6 +14,7 @@ import 'package:flutter/services.dart'; import 'package:http/http.dart'; import 'package:erc20/erc20.dart'; import 'package:web3dart/web3dart.dart'; +import 'package:hex/hex.dart' as hex; abstract class EVMChainClient { final httpClient = Client(); @@ -85,6 +86,7 @@ abstract class EVMChainClient { required CryptoCurrency currency, required int exponent, String? contractAddress, + String? data, }) async { assert(currency == CryptoCurrency.eth || currency == CryptoCurrency.maticpoly || @@ -100,6 +102,7 @@ abstract class EVMChainClient { to: EthereumAddress.fromHex(toAddress), maxPriorityFeePerGas: EtherAmount.fromInt(EtherUnit.gwei, priority.tip), amount: isEVMCompatibleChain ? EtherAmount.inWei(BigInt.parse(amount)) : EtherAmount.zero(), + data: data != null ? hexToBytes(data) : null, ); final signedTransaction = @@ -140,12 +143,14 @@ abstract class EVMChainClient { required EthereumAddress to, required EtherAmount amount, EtherAmount? maxPriorityFeePerGas, + Uint8List? data, }) { return Transaction( from: from, to: to, maxPriorityFeePerGas: maxPriorityFeePerGas, value: amount, + data: data, ); } @@ -222,6 +227,10 @@ abstract class EVMChainClient { } } + Uint8List hexToBytes(String hexString) { + return Uint8List.fromList(hex.HEX.decode(hexString.startsWith('0x') ? hexString.substring(2) : hexString)); + } + void stop() { _client?.dispose(); } diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart index 0fb282960..2d58e95ab 100644 --- a/cw_evm/lib/evm_chain_wallet.dart +++ b/cw_evm/lib/evm_chain_wallet.dart @@ -224,6 +224,13 @@ abstract class EVMChainWalletBase final outputs = _credentials.outputs; final hasMultiDestination = outputs.length > 1; + final String? opReturnMemo = outputs.first.memo; + + String? hexOpReturnMemo; + if (opReturnMemo != null) { + hexOpReturnMemo = '0x${opReturnMemo.codeUnits.map((char) => char.toRadixString(16).padLeft(2, '0')).join()}'; + } + final CryptoCurrency transactionCurrency = balance.keys.firstWhere((element) => element.title == _credentials.currency.title); @@ -279,6 +286,7 @@ abstract class EVMChainWalletBase exponent: exponent, contractAddress: transactionCurrency is Erc20Token ? transactionCurrency.contractAddress : null, + data: hexOpReturnMemo, ); return pendingEVMChainTransaction; diff --git a/cw_evm/lib/pending_evm_chain_transaction.dart b/cw_evm/lib/pending_evm_chain_transaction.dart index 8129de728..0b367da68 100644 --- a/cw_evm/lib/pending_evm_chain_transaction.dart +++ b/cw_evm/lib/pending_evm_chain_transaction.dart @@ -3,6 +3,7 @@ import 'dart:typed_data'; import 'package:cw_core/pending_transaction.dart'; import 'package:web3dart/crypto.dart'; +import 'package:hex/hex.dart' as Hex; class PendingEVMChainTransaction with PendingTransaction { final Function sendTransaction; @@ -38,5 +39,12 @@ class PendingEVMChainTransaction with PendingTransaction { String get hex => bytesToHex(signedTransaction, include0x: true); @override - String get id => ''; + String get id { + final String eip1559Hex = '0x02${hex.substring(2)}'; + final Uint8List bytes = Uint8List.fromList(Hex.HEX.decode(eip1559Hex.substring(2))); + + var txid = keccak256(bytes); + + return '0x${Hex.HEX.encode(txid)}'; + } } diff --git a/cw_polygon/lib/polygon_client.dart b/cw_polygon/lib/polygon_client.dart index 055b42f87..35fbe5072 100644 --- a/cw_polygon/lib/polygon_client.dart +++ b/cw_polygon/lib/polygon_client.dart @@ -13,6 +13,8 @@ class PolygonClient extends EVMChainClient { required EthereumAddress to, required EtherAmount amount, EtherAmount? maxPriorityFeePerGas, + Uint8List? data, + }) { return Transaction( from: from, diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 78423a8c3..4db51fbc2 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -85,7 +85,8 @@ class CWBitcoin extends Bitcoin { sendAll: out.sendAll, extractedAddress: out.extractedAddress, isParsedAddress: out.isParsedAddress, - formattedCryptoAmount: out.formattedCryptoAmount)) + formattedCryptoAmount: out.formattedCryptoAmount, + memo: out.memo)) .toList(), priority: priority as BitcoinTransactionPriority, feeRate: feeRate); diff --git a/lib/ethereum/cw_ethereum.dart b/lib/ethereum/cw_ethereum.dart index 6e658788e..52839d68a 100644 --- a/lib/ethereum/cw_ethereum.dart +++ b/lib/ethereum/cw_ethereum.dart @@ -76,7 +76,8 @@ class CWEthereum extends Ethereum { sendAll: out.sendAll, extractedAddress: out.extractedAddress, isParsedAddress: out.isParsedAddress, - formattedCryptoAmount: out.formattedCryptoAmount)) + formattedCryptoAmount: out.formattedCryptoAmount, + memo: out.memo)) .toList(), priority: priority as EVMChainTransactionPriority, currency: currency, diff --git a/lib/exchange/exchange_provider_description.dart b/lib/exchange/exchange_provider_description.dart index abfac3a6b..4d9691035 100644 --- a/lib/exchange/exchange_provider_description.dart +++ b/lib/exchange/exchange_provider_description.dart @@ -22,6 +22,8 @@ class ExchangeProviderDescription extends EnumerableItem with Serializable< ExchangeProviderDescription(title: 'Trocador', raw: 5, image: 'assets/images/trocador.png'); static const exolix = ExchangeProviderDescription(title: 'Exolix', raw: 6, image: 'assets/images/exolix.png'); + static const thorChain = + ExchangeProviderDescription(title: 'ThorChain' , raw: 8, image: 'assets/images/thorchain.png'); static const all = ExchangeProviderDescription(title: 'All trades', raw: 7, image: ''); @@ -41,6 +43,8 @@ class ExchangeProviderDescription extends EnumerableItem with Serializable< return trocador; case 6: return exolix; + case 8: + return thorChain; case 7: return all; default: diff --git a/lib/exchange/provider/thorchain_exchange.provider.dart b/lib/exchange/provider/thorchain_exchange.provider.dart new file mode 100644 index 000000000..2ab04b742 --- /dev/null +++ b/lib/exchange/provider/thorchain_exchange.provider.dart @@ -0,0 +1,248 @@ +import 'dart:convert'; + +import 'package:cake_wallet/exchange/exchange_provider_description.dart'; +import 'package:cake_wallet/exchange/limits.dart'; +import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; +import 'package:cake_wallet/exchange/trade.dart'; +import 'package:cake_wallet/exchange/trade_request.dart'; +import 'package:cake_wallet/exchange/trade_state.dart'; +import 'package:cake_wallet/exchange/utils/currency_pairs_utils.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:hive/hive.dart'; +import 'package:http/http.dart' as http; + +class ThorChainExchangeProvider extends ExchangeProvider { + ThorChainExchangeProvider({required this.tradesStore}) + : super(pairList: supportedPairs(_notSupported)); + + static final List _notSupported = [ + ...(CryptoCurrency.all + .where((element) => ![ + CryptoCurrency.btc, + CryptoCurrency.eth, + CryptoCurrency.ltc, + CryptoCurrency.bch, + CryptoCurrency.aave, + CryptoCurrency.dai, + CryptoCurrency.gusd, + CryptoCurrency.usdc, + CryptoCurrency.usdterc20, + CryptoCurrency.wbtc, + ].contains(element)) + .toList()) + ]; + + static final isRefundAddressSupported = [CryptoCurrency.eth]; + + static const _baseURL = 'thornode.ninerealms.com'; + static const _quotePath = '/thorchain/quote/swap'; + static const _txInfoPath = '/thorchain/tx/status/'; + static const _affiliateName = 'cakewallet'; + static const _affiliateBps = '175'; + + final Box tradesStore; + + @override + String get title => 'THORChain'; + + @override + bool get isAvailable => true; + + @override + bool get isEnabled => true; + + @override + bool get supportsFixedRate => false; + + @override + ExchangeProviderDescription get description => ExchangeProviderDescription.thorChain; + + @override + Future checkIsAvailable() async => true; + + @override + Future fetchRate( + {required CryptoCurrency from, + required CryptoCurrency to, + required double amount, + required bool isFixedRateMode, + required bool isReceiveAmount}) async { + try { + if (amount == 0) return 0.0; + + final params = { + 'from_asset': _normalizeCurrency(from), + 'to_asset': _normalizeCurrency(to), + 'amount': _doubleToThorChainString(amount), + 'affiliate': _affiliateName, + 'affiliate_bps': _affiliateBps + }; + + final responseJSON = await _getSwapQuote(params); + + final expectedAmountOut = responseJSON['expected_amount_out'] as String? ?? '0.0'; + + return _thorChainAmountToDouble(expectedAmountOut) / amount; + } catch (e) { + print(e.toString()); + return 0.0; + } + } + + @override + Future fetchLimits( + {required CryptoCurrency from, + required CryptoCurrency to, + required bool isFixedRateMode}) async { + final params = { + 'from_asset': _normalizeCurrency(from), + 'to_asset': _normalizeCurrency(to), + 'amount': _doubleToThorChainString(1), + 'affiliate': _affiliateName, + 'affiliate_bps': _affiliateBps + }; + + final responseJSON = await _getSwapQuote(params); + final minAmountIn = responseJSON['recommended_min_amount_in'] as String? ?? '0.0'; + + return Limits(min: _thorChainAmountToDouble(minAmountIn)); + } + + @override + Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { + String formattedToAddress = request.toAddress.startsWith('bitcoincash:') + ? request.toAddress.replaceFirst('bitcoincash:', '') + : request.toAddress; + + final formattedFromAmount = double.parse(request.fromAmount); + + final params = { + 'from_asset': _normalizeCurrency(request.fromCurrency), + 'to_asset': _normalizeCurrency(request.toCurrency), + 'amount': _doubleToThorChainString(formattedFromAmount), + 'destination': formattedToAddress, + 'affiliate': _affiliateName, + 'affiliate_bps': _affiliateBps, + 'refund_address': + isRefundAddressSupported.contains(request.fromCurrency) ? request.refundAddress : '', + }; + + final responseJSON = await _getSwapQuote(params); + + final inputAddress = responseJSON['inbound_address'] as String?; + final memo = responseJSON['memo'] as String?; + + return Trade( + id: '', + from: request.fromCurrency, + to: request.toCurrency, + provider: description, + inputAddress: inputAddress, + createdAt: DateTime.now(), + amount: request.fromAmount, + state: TradeState.notFound, + payoutAddress: request.toAddress, + memo: memo); + } + + @override + Future findTradeById({required String id}) async { + if (id.isEmpty) throw Exception('Trade id is empty'); + final formattedId = id.startsWith('0x') ? id.substring(2) : id; + final uri = Uri.https(_baseURL, '$_txInfoPath$formattedId'); + final response = await http.get(uri); + + if (response.statusCode == 404) { + throw Exception('Trade not found for id: $formattedId'); + } else if (response.statusCode != 200) { + throw Exception('Unexpected HTTP status: ${response.statusCode}'); + } + + final responseJSON = json.decode(response.body); + final Map stagesJson = responseJSON['stages'] as Map; + + final inboundObservedStarted = stagesJson['inbound_observed']?['started'] as bool? ?? true; + if (!inboundObservedStarted) { + throw Exception('Trade has not started for id: $formattedId'); + } + + final currentState = _updateStateBasedOnStages(stagesJson) ?? TradeState.notFound; + + final tx = responseJSON['tx']; + final String fromAddress = tx['from_address'] as String? ?? ''; + final String toAddress = tx['to_address'] as String? ?? ''; + final List coins = tx['coins'] as List; + final String? memo = tx['memo'] as String?; + + final parts = memo?.split(':') ?? []; + + final String toChain = parts.length > 1 ? parts[1].split('.')[0] : ''; + final String toAsset = parts.length > 1 && parts[1].split('.').length > 1 ? parts[1].split('.')[1].split('-')[0] : ''; + + final formattedToChain = CryptoCurrency.fromString(toChain); + final toAssetWithChain = CryptoCurrency.fromString(toAsset, walletCurrency:formattedToChain); + + final plannedOutTxs = responseJSON['planned_out_txs'] as List?; + final isRefund = plannedOutTxs?.any((tx) => tx['refund'] == true) ?? false; + + return Trade( + id: id, + from: CryptoCurrency.fromString(tx['chain'] as String? ?? ''), + to: toAssetWithChain, + provider: description, + inputAddress: fromAddress, + payoutAddress: toAddress, + amount: coins.first['amount'] as String? ?? '0.0', + state: currentState, + memo: memo, + isRefund: isRefund, + ); + } + + Future> _getSwapQuote(Map params) async { + Uri uri = Uri.https(_baseURL, _quotePath, params); + + final response = await http.get(uri); + + if (response.statusCode != 200) { + throw Exception('Unexpected HTTP status: ${response.statusCode}'); + } + + if (response.body.contains('error')) { + throw Exception('Unexpected response: ${response.body}'); + } + + return json.decode(response.body) as Map; + } + + String _normalizeCurrency(CryptoCurrency currency) { + final networkTitle = currency.tag == 'ETH' ? 'ETH' : currency.title; + return '$networkTitle.${currency.title}'; + } + + String _doubleToThorChainString(double amount) => (amount * 1e8).toInt().toString(); + + double _thorChainAmountToDouble(String amount) => double.parse(amount) / 1e8; + + TradeState? _updateStateBasedOnStages(Map stages) { + TradeState? currentState; + + if (stages['inbound_observed']['completed'] as bool? ?? false) { + currentState = TradeState.confirmation; + } + if (stages['inbound_confirmation_counted']['completed'] as bool? ?? false) { + currentState = TradeState.confirmed; + } + if (stages['inbound_finalised']['completed'] as bool? ?? false) { + currentState = TradeState.processing; + } + if (stages['swap_finalised']['completed'] as bool? ?? false) { + currentState = TradeState.traded; + } + if (stages['outbound_signed']['completed'] as bool? ?? false) { + currentState = TradeState.success; + } + + return currentState; + } +} diff --git a/lib/exchange/trade.dart b/lib/exchange/trade.dart index 4eb48c248..4bfb335b8 100644 --- a/lib/exchange/trade.dart +++ b/lib/exchange/trade.dart @@ -27,7 +27,10 @@ class Trade extends HiveObject { this.password, this.providerId, this.providerName, - this.fromWalletAddress + this.fromWalletAddress, + this.memo, + this.txId, + this.isRefund, }) { if (provider != null) providerRaw = provider.raw; @@ -105,6 +108,15 @@ class Trade extends HiveObject { @HiveField(17) String? fromWalletAddress; + @HiveField(18) + String? memo; + + @HiveField(19) + String? txId; + + @HiveField(20) + bool? isRefund; + static Trade fromMap(Map map) { return Trade( id: map['id'] as String, @@ -115,7 +127,10 @@ class Trade extends HiveObject { map['date'] != null ? DateTime.fromMillisecondsSinceEpoch(map['date'] as int) : null, amount: map['amount'] as String, walletId: map['wallet_id'] as String, - fromWalletAddress: map['from_wallet_address'] as String? + fromWalletAddress: map['from_wallet_address'] as String?, + memo: map['memo'] as String?, + txId: map['tx_id'] as String?, + isRefund: map['isRefund'] as bool? ); } @@ -128,7 +143,10 @@ class Trade extends HiveObject { 'date': createdAt != null ? createdAt!.millisecondsSinceEpoch : null, 'amount': amount, 'wallet_id': walletId, - 'from_wallet_address': fromWalletAddress + 'from_wallet_address': fromWalletAddress, + 'memo': memo, + 'tx_id': txId, + 'isRefund': isRefund }; } diff --git a/lib/exchange/trade_state.dart b/lib/exchange/trade_state.dart index ed56d9845..2c58a96f4 100644 --- a/lib/exchange/trade_state.dart +++ b/lib/exchange/trade_state.dart @@ -41,6 +41,8 @@ class TradeState extends EnumerableItem with Serializable { static const success = TradeState(raw: 'success', title: 'Success'); static TradeState deserialize({required String raw}) { switch (raw) { + case 'NOT_FOUND': + return notFound; case 'pending': return pending; case 'confirming': @@ -98,6 +100,7 @@ class TradeState extends EnumerableItem with Serializable { case 'sending': return sending; case 'success': + case 'done': return success; default: throw Exception('Unexpected token: $raw in TradeState deserialize'); diff --git a/lib/src/screens/dashboard/widgets/filter_tile.dart b/lib/src/screens/dashboard/widgets/filter_tile.dart index 3be96073a..d2f824806 100644 --- a/lib/src/screens/dashboard/widgets/filter_tile.dart +++ b/lib/src/screens/dashboard/widgets/filter_tile.dart @@ -9,7 +9,7 @@ class FilterTile extends StatelessWidget { Widget build(BuildContext context) { return Container( width: double.infinity, - padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 24.0), + padding: EdgeInsets.symmetric(vertical: 6.0, horizontal: 24.0), child: child, ); } diff --git a/lib/src/screens/dashboard/widgets/sync_indicator_icon.dart b/lib/src/screens/dashboard/widgets/sync_indicator_icon.dart index 11bde6dfa..21133a438 100644 --- a/lib/src/screens/dashboard/widgets/sync_indicator_icon.dart +++ b/lib/src/screens/dashboard/widgets/sync_indicator_icon.dart @@ -20,6 +20,7 @@ class SyncIndicatorIcon extends StatelessWidget { static const String created = 'created'; static const String fetching = 'fetching'; static const String finished = 'finished'; + static const String success = 'success'; @override Widget build(BuildContext context) { @@ -45,6 +46,7 @@ class SyncIndicatorIcon extends StatelessWidget { indicatorColor = Colors.red; break; case finished: + case success: indicatorColor = PaletteDark.brightGreen; break; default: diff --git a/lib/src/screens/dashboard/widgets/trade_row.dart b/lib/src/screens/dashboard/widgets/trade_row.dart index 7f570b98e..caccb8047 100644 --- a/lib/src/screens/dashboard/widgets/trade_row.dart +++ b/lib/src/screens/dashboard/widgets/trade_row.dart @@ -34,7 +34,9 @@ class TradeRow extends StatelessWidget { mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.center, children: [ - _getPoweredImage(provider)!, + ClipRRect( + borderRadius: BorderRadius.circular(50), + child: Image.asset(provider.image, width: 36, height: 36)), SizedBox(width: 12), Expanded( child: Column( @@ -69,38 +71,4 @@ class TradeRow extends StatelessWidget { ), )); } - - Widget? _getPoweredImage(ExchangeProviderDescription provider) { - Widget? image; - - switch (provider) { - case ExchangeProviderDescription.xmrto: - image = Image.asset('assets/images/xmrto.png', height: 36, width: 36); - break; - case ExchangeProviderDescription.changeNow: - image = Image.asset('assets/images/changenow.png', height: 36, width: 36); - break; - case ExchangeProviderDescription.morphToken: - image = Image.asset('assets/images/morph.png', height: 36, width: 36); - break; - case ExchangeProviderDescription.sideShift: - image = Image.asset('assets/images/sideshift.png', width: 36, height: 36); - break; - case ExchangeProviderDescription.simpleSwap: - image = Image.asset('assets/images/simpleSwap.png', width: 36, height: 36); - break; - case ExchangeProviderDescription.trocador: - image = ClipRRect( - borderRadius: BorderRadius.circular(50), - child: Image.asset('assets/images/trocador.png', width: 36, height: 36)); - break; - case ExchangeProviderDescription.exolix: - image = Image.asset('assets/images/exolix.png', width: 36, height: 36); - break; - default: - image = null; - } - - return image; - } } diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 1a5ab24e6..d8e5a6a4a 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/exchange/exchange_provider_description.dart'; +import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart'; import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/core/auth_service.dart'; @@ -60,7 +62,7 @@ class ExchangePage extends BasePage { final _receiveAmountFocus = FocusNode(); final _receiveAddressFocus = FocusNode(); final _receiveAmountDebounce = Debounce(Duration(milliseconds: 500)); - final _depositAmountDebounce = Debounce(Duration(milliseconds: 500)); + Debounce _depositAmountDebounce = Debounce(Duration(milliseconds: 500)); var _isReactionsSet = false; final arrowBottomPurple = Image.asset( @@ -431,7 +433,9 @@ class ExchangePage extends BasePage { } if (state is TradeIsCreatedSuccessfully) { exchangeViewModel.reset(); - Navigator.of(context).pushNamed(Routes.exchangeConfirm); + (exchangeViewModel.tradesStore.trade?.provider == ExchangeProviderDescription.thorChain) + ? Navigator.of(context).pushReplacementNamed(Routes.exchangeTrade) + : Navigator.of(context).pushReplacementNamed(Routes.exchangeConfirm); } }); @@ -470,6 +474,13 @@ class ExchangePage extends BasePage { if (depositAmountController.text != exchangeViewModel.depositAmount && depositAmountController.text != S.of(context).all) { exchangeViewModel.isSendAllEnabled = false; + final isThorChain = exchangeViewModel.selectedProviders + .any((provider) => provider is ThorChainExchangeProvider); + + _depositAmountDebounce = isThorChain + ? Debounce(Duration(milliseconds: 1000)) + : Debounce(Duration(milliseconds: 500)); + _depositAmountDebounce.run(() { exchangeViewModel.changeDepositAmount(amount: depositAmountController.text); exchangeViewModel.isReceiveAmountEntered = false; diff --git a/lib/store/dashboard/trade_filter_store.dart b/lib/store/dashboard/trade_filter_store.dart index 4e901aa5e..c05839578 100644 --- a/lib/store/dashboard/trade_filter_store.dart +++ b/lib/store/dashboard/trade_filter_store.dart @@ -3,18 +3,20 @@ import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:mobx/mobx.dart'; -part'trade_filter_store.g.dart'; +part 'trade_filter_store.g.dart'; class TradeFilterStore = TradeFilterStoreBase with _$TradeFilterStore; abstract class TradeFilterStoreBase with Store { - TradeFilterStoreBase() : displayXMRTO = true, + TradeFilterStoreBase() + : displayXMRTO = true, displayChangeNow = true, displaySideShift = true, displayMorphToken = true, displaySimpleSwap = true, displayTrocador = true, - displayExolix = true; + displayExolix = true, + displayThorChain = true; @observable bool displayXMRTO; @@ -37,8 +39,17 @@ abstract class TradeFilterStoreBase with Store { @observable bool displayExolix; + @observable + bool displayThorChain; + @computed - bool get displayAllTrades => displayChangeNow && displaySideShift && displaySimpleSwap && displayTrocador && displayExolix; + bool get displayAllTrades => + displayChangeNow && + displaySideShift && + displaySimpleSwap && + displayTrocador && + displayExolix && + displayThorChain; @action void toggleDisplayExchange(ExchangeProviderDescription provider) { @@ -64,6 +75,9 @@ abstract class TradeFilterStoreBase with Store { case ExchangeProviderDescription.exolix: displayExolix = !displayExolix; break; + case ExchangeProviderDescription.thorChain: + displayThorChain = !displayThorChain; + break; case ExchangeProviderDescription.all: if (displayAllTrades) { displayChangeNow = false; @@ -73,6 +87,7 @@ abstract class TradeFilterStoreBase with Store { displaySimpleSwap = false; displayTrocador = false; displayExolix = false; + displayThorChain = false; } else { displayChangeNow = true; displaySideShift = true; @@ -81,6 +96,7 @@ abstract class TradeFilterStoreBase with Store { displaySimpleSwap = true; displayTrocador = true; displayExolix = true; + displayThorChain = true; } break; } @@ -96,16 +112,13 @@ abstract class TradeFilterStoreBase with Store { ? _trades .where((item) => (displayXMRTO && item.trade.provider == ExchangeProviderDescription.xmrto) || - (displaySideShift && - item.trade.provider == ExchangeProviderDescription.sideShift) || - (displayChangeNow && - item.trade.provider == ExchangeProviderDescription.changeNow) || - (displayMorphToken && - item.trade.provider == ExchangeProviderDescription.morphToken) || - (displaySimpleSwap && - item.trade.provider == ExchangeProviderDescription.simpleSwap) || + (displaySideShift && item.trade.provider == ExchangeProviderDescription.sideShift) || + (displayChangeNow && item.trade.provider == ExchangeProviderDescription.changeNow) || + (displayMorphToken && item.trade.provider == ExchangeProviderDescription.morphToken) || + (displaySimpleSwap && item.trade.provider == ExchangeProviderDescription.simpleSwap) || (displayTrocador && item.trade.provider == ExchangeProviderDescription.trocador) || - (displayExolix && item.trade.provider == ExchangeProviderDescription.exolix)) + (displayExolix && item.trade.provider == ExchangeProviderDescription.exolix) || + (displayThorChain && item.trade.provider == ExchangeProviderDescription.thorChain)) .toList() : _trades; } diff --git a/lib/view_model/anonpay_details_view_model.dart b/lib/view_model/anonpay_details_view_model.dart index 6c528f495..fe4b9da3d 100644 --- a/lib/view_model/anonpay_details_view_model.dart +++ b/lib/view_model/anonpay_details_view_model.dart @@ -71,7 +71,7 @@ abstract class AnonpayDetailsViewModelBase with Store { ]); items.add(TrackTradeListItem( - title: 'Track', + title: S.current.track, value: invoiceDetail.clearnetStatusUrl, onTap: () => launchUrlString(invoiceDetail.clearnetStatusUrl))); } diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 9ee0647fc..66d179523 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -120,6 +120,11 @@ abstract class DashboardViewModelBase with Store { caption: ExchangeProviderDescription.exolix.title, onChanged: () => tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.exolix)), + FilterItem( + value: () => tradeFilterStore.displayThorChain, + caption: ExchangeProviderDescription.thorChain.title, + onChanged: () => + tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.thorChain)), ] }, subname = '', diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index 0d40ae240..3eb07460b 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; import 'package:cake_wallet/exchange/provider/exolix_exchange_provider.dart'; import 'package:cake_wallet/exchange/provider/sideshift_exchange_provider.dart'; import 'package:cake_wallet/exchange/provider/simpleswap_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart'; import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; import 'package:cake_wallet/exchange/trade.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -47,6 +48,9 @@ abstract class ExchangeTradeViewModelBase with Store { case ExchangeProviderDescription.exolix: _provider = ExolixExchangeProvider(); break; + case ExchangeProviderDescription.thorChain: + _provider = ThorChainExchangeProvider(tradesStore: trades); + break; } _updateItems(); @@ -100,8 +104,13 @@ abstract class ExchangeTradeViewModelBase with Store { final output = sendViewModel.outputs.first; output.address = trade.inputAddress ?? ''; output.setCryptoAmount(trade.amount); + if (_provider is ThorChainExchangeProvider) output.memo = trade.memo; sendViewModel.selectedCryptoCurrency = trade.from; - await sendViewModel.createTransaction(); + final pendingTransaction = await sendViewModel.createTransaction(provider: _provider); + if (_provider is ThorChainExchangeProvider) { + trade.id = pendingTransaction?.id ?? ''; + trades.add(trade); + } } @action @@ -127,6 +136,8 @@ abstract class ExchangeTradeViewModelBase with Store { tradesStore.trade!.from.tag != null ? '${tradesStore.trade!.from.tag}' + ' ' : ''; final tagTo = tradesStore.trade!.to.tag != null ? '${tradesStore.trade!.to.tag}' + ' ' : ''; items.clear(); + + if(trade.provider != ExchangeProviderDescription.thorChain) items.add(ExchangeTradeItem( title: "${trade.provider.title} ${S.current.id}", data: '${trade.id}', isCopied: true)); diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 1f86847f4..01ac8e942 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:collection'; import 'dart:convert'; +import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/core/wallet_change_listener_view_model.dart'; @@ -9,6 +10,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/wallet_contact.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; +import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/exchange/exchange_template.dart'; import 'package:cake_wallet/exchange/exchange_trade_state.dart'; import 'package:cake_wallet/exchange/limits.dart'; @@ -18,6 +20,7 @@ import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; import 'package:cake_wallet/exchange/provider/exolix_exchange_provider.dart'; import 'package:cake_wallet/exchange/provider/sideshift_exchange_provider.dart'; import 'package:cake_wallet/exchange/provider/simpleswap_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart'; import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; import 'package:cake_wallet/exchange/trade.dart'; import 'package:cake_wallet/exchange/trade_request.dart'; @@ -96,7 +99,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with /// if the provider is not in the user settings (user's first time or newly added provider) /// then use its default value decided by us - selectedProviders = ObservableList.of(providersForCurrentPair() + selectedProviders = ObservableList.of(providerList .where((element) => exchangeProvidersSelection[element.title] == null ? element.isEnabled : (exchangeProvidersSelection[element.title] as bool)) @@ -148,6 +151,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with SimpleSwapExchangeProvider(), TrocadorExchangeProvider( useTorOnly: _useTorOnly, providerStates: _settingsStore.trocadorProviderStates), + ThorChainExchangeProvider(tradesStore: trades), if (FeatureFlag.isExolixEnabled) ExolixExchangeProvider(), ]; @@ -496,8 +500,16 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with await provider.createTrade(request: request, isFixedRateMode: isFixedRateMode); trade.walletId = wallet.id; trade.fromWalletAddress = wallet.walletAddresses.address; + + if (!isCanCreateTrade(trade)) { + tradeState = TradeIsCreatedFailure( + title: S.current.trade_not_created, + error: S.current.thorchain_taproot_address_not_supported); + return; + } + tradesStore.setTrade(trade); - await trades.add(trade); + if (trade.provider != ExchangeProviderDescription.thorChain) await trades.add(trade); tradeState = TradeIsCreatedSuccessfully(trade: trade); /// return after the first successful trade @@ -749,4 +761,17 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with int get depositMaxDigits => depositCurrency.decimals; int get receiveMaxDigits => receiveCurrency.decimals; + + bool isCanCreateTrade(Trade trade) { + if (trade.provider == ExchangeProviderDescription.thorChain) { + final payoutAddress = trade.payoutAddress ?? ''; + final fromWalletAddress = trade.fromWalletAddress ?? ''; + final tapRootPattern = RegExp(P2trAddress.regex.pattern); + + if (tapRootPattern.hasMatch(payoutAddress) || tapRootPattern.hasMatch(fromWalletAddress)) { + return false; + } + } + return true; + } } diff --git a/lib/view_model/order_details_view_model.dart b/lib/view_model/order_details_view_model.dart index 9b00bbb46..384c0541d 100644 --- a/lib/view_model/order_details_view_model.dart +++ b/lib/view_model/order_details_view_model.dart @@ -99,7 +99,7 @@ abstract class OrderDetailsViewModelBase with Store { final buildURL = trackUrl + '${order.transferId}'; items.add( TrackTradeListItem( - title: 'Track', + title: S.current.track, value: buildURL, onTap: () { try { diff --git a/lib/view_model/send/output.dart b/lib/view_model/send/output.dart index cc39aca8b..c881284b3 100644 --- a/lib/view_model/send/output.dart +++ b/lib/view_model/send/output.dart @@ -66,6 +66,8 @@ abstract class OutputBase with Store { @observable String extractedAddress; + String? memo; + @computed bool get isParsedAddress => parsedAddress.parseFrom != ParseFrom.notParsed && parsedAddress.name.isNotEmpty; @@ -175,6 +177,7 @@ abstract class OutputBase with Store { fiatAmount = ''; address = ''; note = ''; + memo = null; resetParsedAddress(); } diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 7636c485a..451f2210d 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -2,6 +2,8 @@ import 'package:cake_wallet/entities/contact.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'; +import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart'; import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/core/wallet_change_listener_view_model.dart'; import 'package:cake_wallet/entities/contact_record.dart'; @@ -296,14 +298,20 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor } @action - Future createTransaction() async { + Future createTransaction({ExchangeProvider? provider}) async { try { state = IsExecutingState(); pendingTransaction = await wallet.createTransaction(_credentials()); + if (provider is ThorChainExchangeProvider) { + final outputCount = pendingTransaction?.outputCount ?? 0; + if (outputCount > 10) throw Exception("ThorChain does not support more than 10 outputs"); + } state = ExecutedSuccessfullyState(); + return pendingTransaction; } catch (e) { print('Failed with ${e.toString()}'); state = FailureState(e.toString()); + return null; } } diff --git a/lib/view_model/trade_details_view_model.dart b/lib/view_model/trade_details_view_model.dart index 45502fd74..1da322778 100644 --- a/lib/view_model/trade_details_view_model.dart +++ b/lib/view_model/trade_details_view_model.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/exchange/provider/exchange_provider.dart'; import 'package:cake_wallet/exchange/provider/exolix_exchange_provider.dart'; import 'package:cake_wallet/exchange/provider/sideshift_exchange_provider.dart'; import 'package:cake_wallet/exchange/provider/simpleswap_exchange_provider.dart'; +import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart'; import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; import 'package:cake_wallet/exchange/trade.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -52,6 +53,9 @@ abstract class TradeDetailsViewModelBase with Store { case ExchangeProviderDescription.exolix: _provider = ExolixExchangeProvider(); break; + case ExchangeProviderDescription.thorChain: + _provider = ThorChainExchangeProvider(tradesStore: trades); + break; } _updateItems(); @@ -62,6 +66,24 @@ abstract class TradeDetailsViewModelBase with Store { } } + static String? getTrackUrl(ExchangeProviderDescription provider, Trade trade) { + switch (provider) { + case ExchangeProviderDescription.changeNow: + return 'https://changenow.io/exchange/txs/${trade.id}'; + case ExchangeProviderDescription.sideShift: + return 'https://sideshift.ai/orders/${trade.id}'; + case ExchangeProviderDescription.simpleSwap: + return 'https://simpleswap.io/exchange?id=${trade.id}'; + case ExchangeProviderDescription.trocador: + return 'https://trocador.app/en/checkout/${trade.id}'; + case ExchangeProviderDescription.exolix: + return 'https://exolix.com/transaction/${trade.id}'; + case ExchangeProviderDescription.thorChain: + return 'https://track.ninerealms.com/${trade.id}'; + } + return null; + } + final Box trades; @observable @@ -125,46 +147,26 @@ abstract class TradeDetailsViewModelBase with Store { items.add(StandartListItem( title: S.current.trade_details_provider, value: trade.provider.toString())); - if (trade.provider == ExchangeProviderDescription.changeNow) { - final buildURL = 'https://changenow.io/exchange/txs/${trade.id.toString()}'; + final trackUrl = TradeDetailsViewModelBase.getTrackUrl(trade.provider, trade); + if (trackUrl != null) { items.add(TrackTradeListItem( - title: 'Track', - value: buildURL, - onTap: () { - _launchUrl(buildURL); - })); + title: S.current.track, value: trackUrl, onTap: () => _launchUrl(trackUrl))); } - if (trade.provider == ExchangeProviderDescription.sideShift) { - final buildURL = 'https://sideshift.ai/orders/${trade.id.toString()}'; - items.add( - TrackTradeListItem(title: 'Track', value: buildURL, onTap: () => _launchUrl(buildURL))); - } - - if (trade.provider == ExchangeProviderDescription.simpleSwap) { - final buildURL = 'https://simpleswap.io/exchange?id=${trade.id.toString()}'; - items.add( - TrackTradeListItem(title: 'Track', value: buildURL, onTap: () => _launchUrl(buildURL))); + if (trade.isRefund == true) { + items.add(StandartListItem( + title: 'Refund', value: trade.refundAddress ?? '')); } if (trade.provider == ExchangeProviderDescription.trocador) { - final buildURL = 'https://trocador.app/en/checkout/${trade.id.toString()}'; - items.add( - TrackTradeListItem(title: 'Track', value: buildURL, onTap: () => _launchUrl(buildURL))); - items.add(StandartListItem( title: '${trade.providerName} ${S.current.id.toUpperCase()}', value: trade.providerId ?? '')); - if (trade.password != null && trade.password!.isNotEmpty) + if (trade.password != null && trade.password!.isNotEmpty) { items.add(StandartListItem( title: '${trade.providerName} ${S.current.password}', value: trade.password ?? '')); - } - - if (trade.provider == ExchangeProviderDescription.exolix) { - final buildURL = 'https://exolix.com/transaction/${trade.id.toString()}'; - items.add( - TrackTradeListItem(title: 'Track', value: buildURL, onTap: () => _launchUrl(buildURL))); + } } } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 66af15dfa..44d55e0ed 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -643,6 +643,7 @@ "template_name": "اسم القالب", "third_intro_content": "يعيش Yats خارج Cake Wallet أيضًا. يمكن استبدال أي عنوان محفظة على وجه الأرض بـ Yat!", "third_intro_title": "يتماشي Yat بلطف مع الآخرين", + "thorchain_taproot_address_not_supported": "لا يدعم مزود Thorchain عناوين Taproot. يرجى تغيير العنوان أو تحديد مزود مختلف.", "time": "${minutes}د ${seconds}س", "tip": "بقشيش:", "today": "اليوم", @@ -660,6 +661,7 @@ "totp_code": "كود TOTP", "totp_secret_code": "كود TOTP السري", "totp_verification_success": "تم التحقق بنجاح!", + "track": " ﺭﺎﺴﻣ", "trade_details_copied": "تم نسخ ${title} إلى الحافظة", "trade_details_created_at": "أنشئت في", "trade_details_fetching": "جار الجلب", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 061506b86..1817b1807 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -643,6 +643,7 @@ "template_name": "Име на шаблон", "third_intro_content": "Yats също живее извън Cake Wallet. Всеки адрес на портфейл може да бъде заменен с Yat!", "third_intro_title": "Yat добре се сработва с други", + "thorchain_taproot_address_not_supported": "Доставчикът на Thorchain не поддържа адреси на TapRoot. Моля, променете адреса или изберете друг доставчик.", "time": "${minutes} мин ${seconds} сек", "tip": "Tip:", "today": "Днес", @@ -660,6 +661,7 @@ "totp_code": "TOTP код", "totp_secret_code": "TOTP таен код", "totp_verification_success": "Проверката е успешна!", + "track": "Писта", "trade_details_copied": "${title} копирано", "trade_details_created_at": "Създадено", "trade_details_fetching": "Обработка", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 2896c11a9..9bd416f45 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -643,6 +643,7 @@ "template_name": "Název šablony", "third_intro_content": "Yat existuje i mimo Cake Wallet. Jakákoliv adresa peněženky na světě může být nahrazena Yatem!", "third_intro_title": "Yat dobře spolupracuje s ostatními", + "thorchain_taproot_address_not_supported": "Poskytovatel Thorchain nepodporuje adresy Taproot. Změňte adresu nebo vyberte jiného poskytovatele.", "time": "${minutes}m ${seconds}s", "tip": "Spropitné:", "today": "Dnes", @@ -660,6 +661,7 @@ "totp_code": "Kód TOTP", "totp_secret_code": "Tajný kód TOTP", "totp_verification_success": "Ověření proběhlo úspěšně!", + "track": "Dráha", "trade_details_copied": "${title} zkopírováno do schránky", "trade_details_created_at": "Vytvořeno v", "trade_details_fetching": "Získávám", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 9dfa4f4db..109df5ef2 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -644,6 +644,7 @@ "template_name": "Vorlagenname", "third_intro_content": "Yats leben auch außerhalb von Cake Wallet. Jede Wallet-Adresse auf der Welt kann durch ein Yat ersetzt werden!", "third_intro_title": "Yat spielt gut mit anderen", + "thorchain_taproot_address_not_supported": "Der Thorchain -Anbieter unterstützt keine Taproot -Adressen. Bitte ändern Sie die Adresse oder wählen Sie einen anderen Anbieter aus.", "time": "${minutes}m ${seconds}s", "tip": "Hinweis:", "today": "Heute", @@ -661,6 +662,7 @@ "totp_code": "TOTP-Code", "totp_secret_code": "TOTP-Geheimcode", "totp_verification_success": "Verifizierung erfolgreich!", + "track": "Schiene", "trade_details_copied": "${title} in die Zwischenablage kopiert", "trade_details_created_at": "Erzeugt am", "trade_details_fetching": "Wird ermittelt", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 902cb062f..f9e67d475 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -643,6 +643,7 @@ "template_name": "Template Name", "third_intro_content": "Yats live outside of Cake Wallet, too. Any wallet address on earth can be replaced with a Yat!", "third_intro_title": "Yat plays nicely with others", + "thorchain_taproot_address_not_supported": "The ThorChain provider does not support Taproot addresses. Please change the address or select a different provider.", "time": "${minutes}m ${seconds}s", "tip": "Tip:", "today": "Today", @@ -660,6 +661,7 @@ "totp_code": "TOTP Code", "totp_secret_code": "TOTP Secret Code", "totp_verification_success": "Verification Successful!", + "track": "Track", "trade_details_copied": "${title} copied to Clipboard", "trade_details_created_at": "Created at", "trade_details_fetching": "Fetching", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 4b9a9d26b..f84f892dd 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -644,6 +644,7 @@ "template_name": "Nombre de la plantilla", "third_intro_content": "Los Yats también viven fuera de Cake Wallet. Cualquier dirección de billetera en la tierra se puede reemplazar con un Yat!", "third_intro_title": "Yat juega muy bien con otras", + "thorchain_taproot_address_not_supported": "El proveedor de Thorchain no admite las direcciones de Taproot. Cambie la dirección o seleccione un proveedor diferente.", "time": "${minutes}m ${seconds}s", "tip": "Consejo:", "today": "Hoy", @@ -661,6 +662,7 @@ "totp_code": "Código TOTP", "totp_secret_code": "Código secreto TOTP", "totp_verification_success": "¡Verificación exitosa!", + "track": "Pista", "trade_details_copied": "${title} Copiado al portapapeles", "trade_details_created_at": "Creado en", "trade_details_fetching": "Cargando", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 384bb9585..048b97f66 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -643,6 +643,7 @@ "template_name": "Nom du modèle", "third_intro_content": "Les Yats existent aussi en dehors de Cake Wallet. Toute adresse sur terre peut être remplacée par un Yat !", "third_intro_title": "Yat est universel", + "thorchain_taproot_address_not_supported": "Le fournisseur de Thorchain ne prend pas en charge les adresses de tapoot. Veuillez modifier l'adresse ou sélectionner un autre fournisseur.", "time": "${minutes}m ${seconds}s", "tip": "Pourboire :", "today": "Aujourd'hui", @@ -660,6 +661,7 @@ "totp_code": "Code TOTP", "totp_secret_code": "Secret TOTP", "totp_verification_success": "Vérification réussie !", + "track": "Piste", "trade_details_copied": "${title} copié vers le presse-papier", "trade_details_created_at": "Créé le", "trade_details_fetching": "Récupération", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 7c0a7df12..4eadc6333 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -645,6 +645,7 @@ "template_name": "Sunan Samfura", "third_intro_content": "Yats suna zaune a wajen Kek Wallet, kuma. Ana iya maye gurbin kowane adireshin walat a duniya da Yat!", "third_intro_title": "Yat yana wasa da kyau tare da wasu", + "thorchain_taproot_address_not_supported": "Mai ba da tallafi na ThorChain baya goyan bayan adreshin taproot. Da fatan za a canza adireshin ko zaɓi mai bayarwa daban.", "time": "${minutes}m ${seconds}s", "tip": "Tukwici:", "today": "Yau", @@ -662,6 +663,7 @@ "totp_code": "Lambar totp", "totp_secret_code": "Lambar sirri", "totp_verification_success": "Tabbatar cin nasara!", + "track": "Waƙa", "trade_details_copied": "${title} an kwafa zuwa cikin kwafin", "trade_details_created_at": "An ƙirƙira a", "trade_details_fetching": "Daukewa", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 932fb25e7..500df31f7 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -645,6 +645,7 @@ "template_name": "टेम्पलेट नाम", "third_intro_content": "Yats Cake Wallet के बाहर भी रहता है। धरती पर किसी भी वॉलेट पते को Yat से बदला जा सकता है!", "third_intro_title": "Yat दूसरों के साथ अच्छा खेलता है", + "thorchain_taproot_address_not_supported": "थोरचेन प्रदाता टैपरोट पते का समर्थन नहीं करता है। कृपया पता बदलें या एक अलग प्रदाता का चयन करें।", "time": "${minutes}m ${seconds}s", "tip": "टिप:", "today": "आज", @@ -662,6 +663,7 @@ "totp_code": "टीओटीपी कोड", "totp_secret_code": "टीओटीपी गुप्त कोड", "totp_verification_success": "सत्यापन सफल!", + "track": "रास्ता", "trade_details_copied": "${title} क्लिपबोर्ड पर नकल", "trade_details_created_at": "पर बनाया गया", "trade_details_fetching": "ला रहा है", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index c8c9a00bd..9a6f74adb 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -643,6 +643,7 @@ "template_name": "Naziv predloška", "third_intro_content": "Yats žive i izvan Cake Wallet -a. Bilo koja adresa novčanika na svijetu može se zamijeniti Yat!", "third_intro_title": "Yat se lijepo igra s drugima", + "thorchain_taproot_address_not_supported": "Thorchain pružatelj ne podržava Taproot adrese. Promijenite adresu ili odaberite drugog davatelja usluga.", "time": "${minutes}m ${seconds}s", "tip": "Savjet:", "today": "Danas", @@ -660,6 +661,7 @@ "totp_code": "TOTP kod", "totp_secret_code": "TOTP tajni kod", "totp_verification_success": "Provjera uspješna!", + "track": "Staza", "trade_details_copied": "${title} kopiran u međuspremnik", "trade_details_created_at": "Stvoreno u", "trade_details_fetching": "Dohvaćanje", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 2168de910..b0c4276c3 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -646,6 +646,7 @@ "template_name": "Nama Templat", "third_intro_content": "Yats hidup di luar Cake Wallet juga. Setiap alamat dompet di dunia dapat diganti dengan Yat!", "third_intro_title": "Yat bermain baik dengan yang lain", + "thorchain_taproot_address_not_supported": "Penyedia Thorchain tidak mendukung alamat Taproot. Harap ubah alamatnya atau pilih penyedia yang berbeda.", "time": "${minutes}m ${seconds}s", "tip": "Tip:", "today": "Hari ini", @@ -663,6 +664,7 @@ "totp_code": "Kode TOTP", "totp_secret_code": "Kode Rahasia TOTP", "totp_verification_success": "Verifikasi Berhasil!", + "track": "Melacak", "trade_details_copied": "${title} disalin ke Clipboard", "trade_details_created_at": "Dibuat pada", "trade_details_fetching": "Mengambil", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 2700203a0..b96acc951 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -645,6 +645,7 @@ "template_name": "Nome modello", "third_intro_content": "Yat può funzionare anche fuori da Cake Wallet. Qualsiasi indirizzo di portafoglio sulla terra può essere sostituito con uno Yat!", "third_intro_title": "Yat gioca bene con gli altri", + "thorchain_taproot_address_not_supported": "Il provider di Thorchain non supporta gli indirizzi di TapRoot. Si prega di modificare l'indirizzo o selezionare un fornitore diverso.", "time": "${minutes}m ${seconds}s", "tip": "Suggerimento:", "today": "Oggi", @@ -662,6 +663,7 @@ "totp_code": "Codice TOTP", "totp_secret_code": "TOTP codice segreto", "totp_verification_success": "Verifica riuscita!", + "track": "Traccia", "trade_details_copied": "${title} copiati negli Appunti", "trade_details_created_at": "Creato alle", "trade_details_fetching": "Recupero", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 443ce6658..9f8ddbe15 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -644,6 +644,7 @@ "template_name": "テンプレート名", "third_intro_content": "YatsはCakeWalletの外にも住んでいます。 地球上のどのウォレットアドレスもYatに置き換えることができます!", "third_intro_title": "Yatは他の人とうまく遊ぶ", + "thorchain_taproot_address_not_supported": "Thorchainプロバイダーは、TapRootアドレスをサポートしていません。アドレスを変更するか、別のプロバイダーを選択してください。", "time": "${minutes}m ${seconds}s", "tip": "ヒント: ", "today": "今日", @@ -661,6 +662,7 @@ "totp_code": "TOTP コード", "totp_secret_code": "TOTPシークレットコード", "totp_verification_success": "検証成功!", + "track": "追跡", "trade_details_copied": "${title} クリップボードにコピーしました", "trade_details_created_at": "で作成", "trade_details_fetching": "フェッチング", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 3affd803b..757dc6cb3 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -644,6 +644,7 @@ "template_name": "템플릿 이름", "third_intro_content": "Yats는 Cake Wallet 밖에서도 살고 있습니다. 지구상의 모든 지갑 주소는 Yat!", "third_intro_title": "Yat는 다른 사람들과 잘 놉니다.", + "thorchain_taproot_address_not_supported": "Thorchain 제공 업체는 Taproot 주소를 지원하지 않습니다. 주소를 변경하거나 다른 공급자를 선택하십시오.", "time": "${minutes}m ${seconds}s", "tip": "팁:", "today": "오늘", @@ -661,6 +662,7 @@ "totp_code": "TOTP 코드", "totp_secret_code": "TOTP 비밀 코드", "totp_verification_success": "확인 성공!", + "track": "길", "trade_details_copied": "${title} 클립 보드에 복사", "trade_details_created_at": "에 작성", "trade_details_fetching": "가져 오는 중", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index c52d65c06..5b622c234 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -643,6 +643,7 @@ "template_name": "နမူနာပုံစံ", "third_intro_content": "Yats သည် Cake Wallet အပြင်ဘက်တွင် နေထိုင်ပါသည်။ ကမ္ဘာပေါ်ရှိ မည်သည့်ပိုက်ဆံအိတ်လိပ်စာကို Yat ဖြင့် အစားထိုးနိုင်ပါသည်။", "third_intro_title": "Yat သည် အခြားသူများနှင့် ကောင်းစွာကစားသည်။", + "thorchain_taproot_address_not_supported": "Thorchain Provider သည် Taproot လိပ်စာများကိုမထောက်ခံပါ။ ကျေးဇူးပြု. လိပ်စာကိုပြောင်းပါသို့မဟုတ်အခြားပံ့ပိုးပေးသူကိုရွေးချယ်ပါ။", "time": "${minutes}m ${seconds}s", "tip": "အကြံပြုချက်-", "today": "ဒီနေ့", @@ -660,6 +661,7 @@ "totp_code": "TOTP ကုဒ်", "totp_secret_code": "TOTP လျှို့ဝှက်ကုဒ်", "totp_verification_success": "အတည်ပြုခြင်း အောင်မြင်ပါသည်။", + "track": "တစ်ပုဒ်", "trade_details_copied": "${title} ကို Clipboard သို့ ကူးယူထားသည်။", "trade_details_created_at": "တွင်ဖန်တီးခဲ့သည်။", "trade_details_fetching": "ခေါ်ယူခြင်း။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index fa7825809..121ade760 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -643,6 +643,7 @@ "template_name": "Sjabloonnaam", "third_intro_content": "Yats wonen ook buiten Cake Wallet. Elk portemonnee-adres op aarde kan worden vervangen door een Yat!", "third_intro_title": "Yat speelt leuk met anderen", + "thorchain_taproot_address_not_supported": "De Thorchain -provider ondersteunt geen Taprooot -adressen. Wijzig het adres of selecteer een andere provider.", "time": "${minutes}m ${seconds}s", "tip": "Tip:", "today": "Vandaag", @@ -660,6 +661,7 @@ "totp_code": "TOTP-code", "totp_secret_code": "TOTP-geheime code", "totp_verification_success": "Verificatie geslaagd!", + "track": "Spoor", "trade_details_copied": "${title} gekopieerd naar het klembord", "trade_details_created_at": "Gemaakt bij", "trade_details_fetching": "Ophalen", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 16dc8696a..88fbfb6e5 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -643,6 +643,7 @@ "template_name": "Nazwa szablonu", "third_intro_content": "Yats mieszkają również poza Cake Wallet. Każdy adres portfela na ziemi można zastąpić Yat!", "third_intro_title": "Yat ładnie bawi się z innymi", + "thorchain_taproot_address_not_supported": "Dostawca Thorchain nie obsługuje adresów TAPROOT. Zmień adres lub wybierz innego dostawcę.", "time": "${minutes}m ${seconds}s", "tip": "wskazówka:", "today": "Dzisiaj", @@ -660,6 +661,7 @@ "totp_code": "Kod TOTP", "totp_secret_code": "Tajny kod TOTP", "totp_verification_success": "Weryfikacja powiodła się!", + "track": "Ścieżka", "trade_details_copied": "${title} skopiowane do schowka", "trade_details_created_at": "Utworzono ", "trade_details_fetching": "Pobieranie", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 8516ecf3f..7487499ef 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -645,6 +645,7 @@ "template_name": "Nome do modelo", "third_intro_content": "Yats também mora fora da Cake Wallet. Qualquer endereço de carteira na Terra pode ser substituído por um Yat!", "third_intro_title": "Yat joga bem com os outros", + "thorchain_taproot_address_not_supported": "O provedor de Thorchain não suporta endereços de raiz de Tap. Altere o endereço ou selecione um provedor diferente.", "time": "${minutes}m ${seconds}s", "tip": "Dica:", "today": "Hoje", @@ -662,6 +663,7 @@ "totp_code": "Código TOTP", "totp_secret_code": "Código Secreto TOTP", "totp_verification_success": "Verificação bem-sucedida!", + "track": "Acompanhar", "trade_details_copied": "${title} copiados para a área de transferência", "trade_details_created_at": "Criada em", "trade_details_fetching": "Buscando", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 2bff24414..443daa588 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -644,6 +644,7 @@ "template_name": "Имя Шаблона", "third_intro_content": "Yat находятся за пределами Cake Wallet. Любой адрес кошелька на земле можно заменить на Yat!", "third_intro_title": "Yat хорошо взаимодействует с другими", + "thorchain_taproot_address_not_supported": "Поставщик Thorchain не поддерживает адреса taproot. Пожалуйста, измените адрес или выберите другого поставщика.", "time": "${minutes}мин ${seconds}сек", "tip": "Совет:", "today": "Сегодня", @@ -661,6 +662,7 @@ "totp_code": "TOTP-код", "totp_secret_code": "Секретный код ТОТП", "totp_verification_success": "Проверка прошла успешно!", + "track": "Отслеживать", "trade_details_copied": "${title} скопировано в буфер обмена", "trade_details_created_at": "Создано", "trade_details_fetching": "Получение", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 9c37ff8bb..dc864c39c 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -643,6 +643,7 @@ "template_name": "ชื่อแม่แบบ", "third_intro_content": "Yat อาศัยอยู่นอก Cake Wallet ด้วย ที่อยู่กระเป๋าใดๆ ทั่วโลกสามารถแทนด้วย Yat ได้อีกด้วย!", "third_intro_title": "Yat ปฏิบัติตนอย่างดีกับผู้อื่น", + "thorchain_taproot_address_not_supported": "ผู้ให้บริการ Thorchain ไม่รองรับที่อยู่ taproot โปรดเปลี่ยนที่อยู่หรือเลือกผู้ให้บริการอื่น", "time": "${minutes}m ${seconds}s", "tip": "เพิ่มค่าตอบแทน:", "today": "วันนี้", @@ -660,6 +661,7 @@ "totp_code": "รหัสทีโอพี", "totp_secret_code": "รหัสลับ TOTP", "totp_verification_success": "การยืนยันสำเร็จ!", + "track": "ติดตาม", "trade_details_copied": "${title} คัดลอกไปยัง Clipboard", "trade_details_created_at": "สร้างเมื่อ", "trade_details_fetching": "กำลังเรียกข้อมูล", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index d4be21741..4abd6472f 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -643,6 +643,7 @@ "template_name": "Pangalan ng Template", "third_intro_content": "Ang mga yats ay nakatira sa labas ng cake wallet, din. Ang anumang address ng pitaka sa mundo ay maaaring mapalitan ng isang yat!", "third_intro_title": "Si Yat ay mahusay na gumaganap sa iba", + "thorchain_taproot_address_not_supported": "Ang Tagabigay ng Thorchain ay hindi sumusuporta sa mga address ng taproot. Mangyaring baguhin ang address o pumili ng ibang provider.", "time": "${minutes} m ${seconds} s", "tip": "Tip:", "today": "Ngayon", @@ -660,6 +661,7 @@ "totp_code": "TOTP code", "totp_secret_code": "TOTP Secret Code", "totp_verification_success": "Matagumpay ang pagpapatunay!", + "track": "Subaybayan", "trade_details_copied": "${title} kinopya sa clipboard", "trade_details_created_at": "Nilikha sa", "trade_details_fetching": "Pagkuha", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index a6209ed33..c615864a7 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -643,6 +643,7 @@ "template_name": "şablon adı", "third_intro_content": "Yat'lar Cake Wallet'ın dışında da çalışabilir. Dünya üzerindeki herhangi bir cüzdan adresi Yat ile değiştirilebilir!", "third_intro_title": "Yat diğerleriyle iyi çalışır", + "thorchain_taproot_address_not_supported": "Thorchain sağlayıcısı Taproot adreslerini desteklemiyor. Lütfen adresi değiştirin veya farklı bir sağlayıcı seçin.", "time": "${minutes}d ${seconds}s", "tip": "Bahşiş:", "today": "Bugün", @@ -660,6 +661,7 @@ "totp_code": "TOTP Kodu", "totp_secret_code": "TOTP Gizli Kodu", "totp_verification_success": "Doğrulama Başarılı!", + "track": "İzlemek", "trade_details_copied": "${title} panoya kopyalandı", "trade_details_created_at": "'da oluşturuldu", "trade_details_fetching": "Getiriliyor", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 3d60b9e8e..0fe324d11 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -644,6 +644,7 @@ "template_name": "Назва шаблону", "third_intro_content": "Yat знаходиться за межами Cake Wallet. Будь-яку адресу гаманця на землі можна замінити на Yat!", "third_intro_title": "Yat добре взаємодіє з іншими", + "thorchain_taproot_address_not_supported": "Постачальник Thorchain не підтримує адреси Taproot. Будь ласка, змініть адресу або виберіть іншого постачальника.", "time": "${minutes}хв ${seconds}сек", "tip": "Порада:", "today": "Сьогодні", @@ -661,6 +662,7 @@ "totp_code": "Код TOTP", "totp_secret_code": "Секретний код TOTP", "totp_verification_success": "Перевірка успішна!", + "track": "Відслідковувати", "trade_details_copied": "${title} скопійовано в буфер обміну", "trade_details_created_at": "Створено", "trade_details_fetching": "Отримання", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index e0e74e6de..9de85a683 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -645,6 +645,7 @@ "template_name": "ٹیمپلیٹ کا نام", "third_intro_content": "Yats بھی Cake والیٹ سے باہر رہتے ہیں۔ زمین پر کسی بھی بٹوے کے پتے کو Yat سے تبدیل کیا جا سکتا ہے!", "third_intro_title": "Yat دوسروں کے ساتھ اچھی طرح کھیلتا ہے۔", + "thorchain_taproot_address_not_supported": "تھورچین فراہم کنندہ ٹیپروٹ پتے کی حمایت نہیں کرتا ہے۔ براہ کرم پتہ تبدیل کریں یا ایک مختلف فراہم کنندہ کو منتخب کریں۔", "time": "${minutes}m ${seconds}s", "tip": "ٹپ:", "today": "آج", @@ -662,6 +663,7 @@ "totp_code": "TOTP کوڈ", "totp_secret_code": "TOTP خفیہ کوڈ", "totp_verification_success": "توثیق کامیاب!", + "track": " ﮏﯾﺮﭨ", "trade_details_copied": "${title} کو کلپ بورڈ پر کاپی کیا گیا۔", "trade_details_created_at": "پر تخلیق کیا گیا۔", "trade_details_fetching": "لا رہا ہے۔", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 54df5dbf2..8d85f0d6e 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -644,6 +644,7 @@ "template_name": "Orukọ Awoṣe", "third_intro_content": "A sì lè lo Yats níta Cake Wallet. A lè rọ́pò Àdírẹ́sì kankan àpamọ́wọ́ fún Yat!", "third_intro_title": "Àlàáfíà ni Yat àti àwọn ìmíìn jọ wà", + "thorchain_taproot_address_not_supported": "Olupese Trockchain ko ṣe atilẹyin awọn adirẹsi Taproot. Jọwọ yi adirẹsi pada tabi yan olupese ti o yatọ.", "time": "${minutes}ìṣj ${seconds}ìṣs", "tip": "Owó àfikún:", "today": "Lénìí", @@ -661,6 +662,7 @@ "totp_code": "Koodu TOTP", "totp_secret_code": "Koodu iye TOTP", "totp_verification_success": "Ìbẹrẹ dọkita!", + "track": "Orin", "trade_details_copied": "Ti ṣeda ${title} sí àtẹ àkọsílẹ̀", "trade_details_created_at": "Ṣíṣe ní", "trade_details_fetching": "Ń mú wá", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index cb1f012fb..4087d96e8 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -643,6 +643,7 @@ "template_name": "模板名称", "third_intro_content": "Yats 也住在 Cake Wallet 之外。 地球上任何一個錢包地址都可以用一個Yat來代替!", "third_intro_title": "Yat 和別人玩得很好", + "thorchain_taproot_address_not_supported": "Thorchain提供商不支持Taproot地址。请更改地址或选择其他提供商。", "time": "${minutes}m ${seconds}s", "tip": "提示:", "today": "今天", @@ -660,6 +661,7 @@ "totp_code": "TOTP代码", "totp_secret_code": "TOTP密码", "totp_verification_success": "验证成功!", + "track": "追踪", "trade_details_copied": "${title} 复制到剪贴板", "trade_details_created_at": "创建于", "trade_details_fetching": "正在获取", From 78685b74f0c4040da4f5298b31ec4bcef2edcf7c Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Thu, 28 Mar 2024 06:30:41 -0700 Subject: [PATCH 139/241] Cw 521 moonpay buy (#1335) * save * save * moonpay fixes * fix for debug mode * code cleanup * another fix for debug mode * [skip ci] fixes * test build * code cleanup * fix buy page --- lib/buy/moonpay/moonpay_provider.dart | 235 ++++++++++--------- lib/di.dart | 8 +- lib/entities/provider_types.dart | 19 +- lib/src/screens/buy/buy_options_page.dart | 78 +++--- lib/src/screens/buy/buy_webview_page.dart | 2 +- lib/view_model/buy/buy_view_model.dart | 12 - lib/view_model/order_details_view_model.dart | 14 +- 7 files changed, 182 insertions(+), 186 deletions(-) diff --git a/lib/buy/moonpay/moonpay_provider.dart b/lib/buy/moonpay/moonpay_provider.dart index 02bdedaec..52a4f6187 100644 --- a/lib/buy/moonpay/moonpay_provider.dart +++ b/lib/buy/moonpay/moonpay_provider.dart @@ -22,20 +22,24 @@ import 'package:flutter/material.dart'; import 'package:http/http.dart'; import 'package:url_launcher/url_launcher.dart'; -class MoonPaySellProvider extends BuyProvider { - MoonPaySellProvider({ +class MoonPayProvider extends BuyProvider { + MoonPayProvider({ required SettingsStore settingsStore, required WalletBase wallet, bool isTestEnvironment = false, - }) : baseUrl = isTestEnvironment ? _baseTestUrl : _baseProductUrl, + }) : baseSellUrl = isTestEnvironment ? _baseSellTestUrl : _baseSellProductUrl, + baseBuyUrl = isTestEnvironment ? _baseBuyTestUrl : _baseBuyProductUrl, this._settingsStore = settingsStore, super(wallet: wallet, isTestEnvironment: isTestEnvironment); final SettingsStore _settingsStore; - static const _baseTestUrl = 'sell-sandbox.moonpay.com'; - static const _baseProductUrl = 'sell.moonpay.com'; + static const _baseSellTestUrl = 'sell-sandbox.moonpay.com'; + static const _baseSellProductUrl = 'sell.moonpay.com'; + static const _baseBuyTestUrl = 'buy-staging.moonpay.com'; + static const _baseBuyProductUrl = 'buy.moonpay.com'; static const _cIdBaseUrl = 'exchange-helper.cakewallet.com'; + static const _apiUrl = 'https://api.moonpay.com'; @override String get providerDescription => @@ -62,8 +66,14 @@ class MoonPaySellProvider extends BuyProvider { static String get _apiKey => secrets.moonPayApiKey; + final String baseBuyUrl; + final String baseSellUrl; + + String get currencyCode => walletTypeToCryptoCurrency(wallet.type).title.toLowerCase(); + + String get trackUrl => baseBuyUrl + '/transaction_receipt?transactionId='; + static String get _exchangeHelperApiKey => secrets.exchangeHelperApiKey; - final String baseUrl; Future getMoonpaySignature(String query) async { final uri = Uri.https(_cIdBaseUrl, "/api/moonpay"); @@ -85,147 +95,92 @@ class MoonPaySellProvider extends BuyProvider { } } - Future requestMoonPayUrl({ + Future requestSellMoonPayUrl({ required CryptoCurrency currency, required String refundWalletAddress, required SettingsStore settingsStore, }) async { - final customParams = { + final params = { 'theme': themeToMoonPayTheme(settingsStore.currentTheme), 'language': settingsStore.languageCode, 'colorCode': settingsStore.currentTheme.type == ThemeType.dark ? '#${Palette.blueCraiola.value.toRadixString(16).substring(2, 8)}' : '#${Palette.moderateSlateBlue.value.toRadixString(16).substring(2, 8)}', + 'defaultCurrencyCode': _normalizeCurrency(currency), + 'refundWalletAddress': refundWalletAddress, }; - final originalUri = Uri.https( - baseUrl, - '', - { - 'apiKey': _apiKey, - 'defaultBaseCurrencyCode': _normalizeCurrency(currency), - 'refundWalletAddress': refundWalletAddress, - }..addAll(customParams), - ); + if (_apiKey.isNotEmpty) { + params['apiKey'] = _apiKey; + } - final signature = await getMoonpaySignature('?${originalUri.query}'); + final originalUri = Uri.https( + baseSellUrl, + '', + params, + ); if (isTestEnvironment) { return originalUri; } + final signature = await getMoonpaySignature('?${originalUri.query}'); + final query = Map.from(originalUri.queryParameters); query['signature'] = signature; final signedUri = originalUri.replace(queryParameters: query); return signedUri; } - @override - Future launchProvider(BuildContext context, bool? isBuyAction) async { - try { - final uri = await requestMoonPayUrl( - currency: wallet.currency, - refundWalletAddress: wallet.walletAddresses.address, - settingsStore: _settingsStore, - ); - - if (await canLaunchUrl(uri)) { - if (DeviceInfo.instance.isMobile) { - Navigator.of(context).pushNamed(Routes.webViewPage, arguments: ['MoonPay', uri]); - } else { - await launchUrl(uri, mode: LaunchMode.externalApplication); - } - } else { - throw Exception('Could not launch URL'); - } - } catch (e) { - await showDialog( - context: context, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: 'MoonPay', - alertContent: 'The MoonPay service is currently unavailable: $e', - buttonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop(), - ); - }, - ); - } - } - - String _normalizeCurrency(CryptoCurrency currency) { - if (currency == CryptoCurrency.maticpoly) { - return "MATIC_POLYGON"; - } - - return currency.toString().toLowerCase(); - } -} - -class MoonPayBuyProvider extends BuyProvider { - MoonPayBuyProvider({required WalletBase wallet, bool isTestEnvironment = false}) - : baseUrl = isTestEnvironment ? _baseTestUrl : _baseProductUrl, - super(wallet: wallet, isTestEnvironment: isTestEnvironment); - - static const _baseTestUrl = 'https://buy-staging.moonpay.com'; - static const _baseProductUrl = 'https://buy.moonpay.com'; - static const _apiUrl = 'https://api.moonpay.com'; + // BUY: static const _currenciesSuffix = '/v3/currencies'; static const _quoteSuffix = '/buy_quote'; static const _transactionsSuffix = '/v1/transactions'; static const _ipAddressSuffix = '/v4/ip_address'; - static const _apiKey = secrets.moonPayApiKey; - static const _secretKey = secrets.moonPaySecretKey; - @override - String get title => 'MoonPay'; + Future requestBuyMoonPayUrl({ + required CryptoCurrency currency, + required SettingsStore settingsStore, + required String walletAddress, + String? amount, + }) async { + final params = { + 'theme': themeToMoonPayTheme(settingsStore.currentTheme), + 'language': settingsStore.languageCode, + 'colorCode': settingsStore.currentTheme.type == ThemeType.dark + ? '#${Palette.blueCraiola.value.toRadixString(16).substring(2, 8)}' + : '#${Palette.moderateSlateBlue.value.toRadixString(16).substring(2, 8)}', + 'defaultCurrencyCode': _normalizeCurrency(currency), + 'baseCurrencyCode': _normalizeCurrency(currency), + 'baseCurrencyAmount': amount ?? '0', + 'currencyCode': currencyCode, + 'walletAddress': walletAddress, + 'lockAmount': 'true', + 'showAllCurrencies': 'false', + 'showWalletAddressForm': 'false', + 'enabledPaymentMethods': + 'credit_debit_card,apple_pay,google_pay,samsung_pay,sepa_bank_transfer,gbp_bank_transfer,gbp_open_banking_payment', + }; - @override - String get providerDescription => - 'MoonPay offers a fast and simple way to buy and sell cryptocurrencies'; + if (_apiKey.isNotEmpty) { + params['apiKey'] = _apiKey; + } - @override - String get lightIcon => 'assets/images/moonpay_light.png'; + final originalUri = Uri.https( + baseBuyUrl, + '', + params, + ); - @override - String get darkIcon => 'assets/images/moonpay_dark.png'; + if (isTestEnvironment) { + return originalUri; + } - String get currencyCode => walletTypeToCryptoCurrency(wallet.type).title.toLowerCase(); - - String get trackUrl => baseUrl + '/transaction_receipt?transactionId='; - - String baseUrl; - - Future requestUrl(String amount, String sourceCurrency) async { - final enabledPaymentMethods = 'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay' - '%2Csepa_bank_transfer%2Cgbp_bank_transfer%2Cgbp_open_banking_payment'; - - final suffix = '?apiKey=' + - _apiKey + - '¤cyCode=' + - currencyCode + - '&enabledPaymentMethods=' + - enabledPaymentMethods + - '&walletAddress=' + - wallet.walletAddresses.address + - '&baseCurrencyCode=' + - sourceCurrency.toLowerCase() + - '&baseCurrencyAmount=' + - amount + - '&lockAmount=true' + - '&showAllCurrencies=false' + - '&showWalletAddressForm=false'; - - final originalUrl = baseUrl + suffix; - - final messageBytes = utf8.encode(suffix); - final key = utf8.encode(_secretKey); - final hmac = Hmac(sha256, key); - final digest = hmac.convert(messageBytes); - final signature = base64.encode(digest.bytes); - final urlWithSignature = originalUrl + '&signature=${Uri.encodeComponent(signature)}'; - - return isTestEnvironment ? originalUrl : urlWithSignature; + final signature = await getMoonpaySignature('?${originalUri.query}'); + final query = Map.from(originalUri.queryParameters); + query['signature'] = signature; + final signedUri = originalUri.replace(queryParameters: query); + return signedUri; } Future calculateAmount(String amount, String sourceCurrency) async { @@ -300,6 +255,52 @@ class MoonPayBuyProvider extends BuyProvider { } @override - Future launchProvider(BuildContext context, bool? isBuyAction) => - throw UnimplementedError(); + Future launchProvider(BuildContext context, bool? isBuyAction) async { + // try { + late final Uri uri; + if (isBuyAction ?? true) { + uri = await requestBuyMoonPayUrl( + currency: wallet.currency, + walletAddress: wallet.walletAddresses.address, + settingsStore: _settingsStore, + ); + } else { + uri = await requestSellMoonPayUrl( + currency: wallet.currency, + refundWalletAddress: wallet.walletAddresses.address, + settingsStore: _settingsStore, + ); + } + + if (await canLaunchUrl(uri)) { + if (DeviceInfo.instance.isMobile) { + Navigator.of(context).pushNamed(Routes.webViewPage, arguments: ['MoonPay', uri]); + } else { + await launchUrl(uri, mode: LaunchMode.externalApplication); + } + } else { + throw Exception('Could not launch URL'); + } + // } catch (e) { + // await showDialog( + // context: context, + // builder: (BuildContext context) { + // return AlertWithOneAction( + // alertTitle: 'MoonPay', + // alertContent: 'The MoonPay service is currently unavailable: $e', + // buttonText: S.of(context).ok, + // buttonAction: () => Navigator.of(context).pop(), + // ); + // }, + // ); + // } + } + + String _normalizeCurrency(CryptoCurrency currency) { + if (currency == CryptoCurrency.maticpoly) { + return "MATIC_POLYGON"; + } + + return currency.toString().toLowerCase(); + } } diff --git a/lib/di.dart b/lib/di.dart index 782c0f1f4..291555330 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -198,6 +198,7 @@ import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart'; import 'package:cake_wallet/view_model/wallet_restore_view_model.dart'; import 'package:cake_wallet/view_model/wallet_seed_view_model.dart'; import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:get_it/get_it.dart'; import 'package:hive/hive.dart'; @@ -806,8 +807,11 @@ Future setup({ getIt .registerFactory(() => DFXBuyProvider(wallet: getIt.get().wallet!)); - getIt.registerFactory(() => MoonPaySellProvider( - settingsStore: getIt.get().settingsStore, wallet: getIt.get().wallet!)); + getIt.registerFactory(() => MoonPayProvider( + settingsStore: getIt.get().settingsStore, + wallet: getIt.get().wallet!, + isTestEnvironment: kDebugMode, + )); getIt.registerFactory(() => OnRamperBuyProvider( getIt.get().settingsStore, diff --git a/lib/entities/provider_types.dart b/lib/entities/provider_types.dart index f3993e129..701781cc2 100644 --- a/lib/entities/provider_types.dart +++ b/lib/entities/provider_types.dart @@ -11,7 +11,7 @@ enum ProviderType { robinhood, dfx, onramper, - moonpaySell, + moonpay, } extension ProviderTypeName on ProviderType { @@ -25,7 +25,7 @@ extension ProviderTypeName on ProviderType { return 'DFX Connect'; case ProviderType.onramper: return 'Onramper'; - case ProviderType.moonpaySell: + case ProviderType.moonpay: return 'MoonPay'; } } @@ -40,7 +40,7 @@ extension ProviderTypeName on ProviderType { return 'dfx_connect_provider'; case ProviderType.onramper: return 'onramper_provider'; - case ProviderType.moonpaySell: + case ProviderType.moonpay: return 'moonpay_provider'; } } @@ -62,10 +62,11 @@ class ProvidersHelper { ProviderType.onramper, ProviderType.dfx, ProviderType.robinhood, + ProviderType.moonpay, ]; case WalletType.litecoin: case WalletType.bitcoinCash: - return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood]; + return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood, ProviderType.moonpay]; case WalletType.solana: return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood]; case WalletType.none: @@ -82,18 +83,18 @@ class ProvidersHelper { return [ ProviderType.askEachTime, ProviderType.onramper, - ProviderType.moonpaySell, + ProviderType.moonpay, ProviderType.dfx, ]; case WalletType.litecoin: case WalletType.bitcoinCash: - return [ProviderType.askEachTime, ProviderType.moonpaySell]; + return [ProviderType.askEachTime, ProviderType.moonpay]; case WalletType.solana: return [ ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood, - ProviderType.moonpaySell, + ProviderType.moonpay, ]; case WalletType.monero: case WalletType.nano: @@ -112,10 +113,10 @@ class ProvidersHelper { return getIt.get(); case ProviderType.onramper: return getIt.get(); + case ProviderType.moonpay: + return getIt.get(); case ProviderType.askEachTime: return null; - case ProviderType.moonpaySell: - return getIt.get(); } } } diff --git a/lib/src/screens/buy/buy_options_page.dart b/lib/src/screens/buy/buy_options_page.dart index 50f041d2e..38f3ed968 100644 --- a/lib/src/screens/buy/buy_options_page.dart +++ b/lib/src/screens/buy/buy_options_page.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/option_tile.dart'; +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/themes/extensions/option_tile_theme.dart'; import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; @@ -25,45 +26,46 @@ class BuySellOptionsPage extends BasePage { ? dashboardViewModel.availableBuyProviders : dashboardViewModel.availableSellProviders; - return Container( - child: Center( - child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: 330), - child: Column( - children: [ - ...availableProviders.map((provider) { - final icon = Image.asset( - isLightMode ? provider.lightIcon : provider.darkIcon, - height: 40, - width: 40, - ); + return ScrollableWithBottomSection( + content: Container( + child: Center( + child: ConstrainedBox( + constraints: BoxConstraints(maxWidth: 330), + child: Column( + children: [ + ...availableProviders.map((provider) { + final icon = Image.asset( + isLightMode ? provider.lightIcon : provider.darkIcon, + height: 40, + width: 40, + ); - return Padding( - padding: EdgeInsets.only(top: 24), - child: OptionTile( - image: icon, - title: provider.toString(), - description: provider.providerDescription, - onPressed: () => provider.launchProvider(context, isBuyAction), - ), - ); - }).toList(), - Spacer(), - Padding( - padding: EdgeInsets.fromLTRB(24, 24, 24, 32), - child: Text( - isBuyAction - ? S.of(context).select_buy_provider_notice - : S.of(context).select_sell_provider_notice, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.normal, - color: Theme.of(context).extension()!.detailsTitlesColor, - ), - ), - ), - ], + return Padding( + padding: EdgeInsets.only(top: 24), + child: OptionTile( + image: icon, + title: provider.toString(), + description: provider.providerDescription, + onPressed: () => provider.launchProvider(context, isBuyAction), + ), + ); + }).toList(), + ], + ), + ), + ), + ), + bottomSection: Padding( + padding: EdgeInsets.fromLTRB(24, 24, 24, 32), + child: Text( + isBuyAction + ? S.of(context).select_buy_provider_notice + : S.of(context).select_sell_provider_notice, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.normal, + color: Theme.of(context).extension()!.detailsTitlesColor, ), ), ), diff --git a/lib/src/screens/buy/buy_webview_page.dart b/lib/src/screens/buy/buy_webview_page.dart index 829bff3d9..ad6970861 100644 --- a/lib/src/screens/buy/buy_webview_page.dart +++ b/lib/src/screens/buy/buy_webview_page.dart @@ -60,7 +60,7 @@ class BuyWebViewPageBodyState extends State { _saveOrder(keyword: 'completed', splitSymbol: '/'); } - if (widget.buyViewModel.selectedProvider is MoonPayBuyProvider) { + if (widget.buyViewModel.selectedProvider is MoonPayProvider) { _saveOrder(keyword: 'transactionId', splitSymbol: '='); } } diff --git a/lib/view_model/buy/buy_view_model.dart b/lib/view_model/buy/buy_view_model.dart index d73396e1b..7c2591cbb 100644 --- a/lib/view_model/buy/buy_view_model.dart +++ b/lib/view_model/buy/buy_view_model.dart @@ -93,18 +93,6 @@ abstract class BuyViewModelBase with Store { _providerList.add(WyreBuyProvider(wallet: wallet)); } - var isMoonPayEnabled = false; - try { - isMoonPayEnabled = await MoonPayBuyProvider.onEnabled(); - } catch (e) { - isMoonPayEnabled = false; - print(e.toString()); - } - - if (isMoonPayEnabled) { - _providerList.add(MoonPayBuyProvider(wallet: wallet)); - } - items = _providerList.map((provider) => BuyItem(provider: provider, buyAmountViewModel: buyAmountViewModel)) .toList(); diff --git a/lib/view_model/order_details_view_model.dart b/lib/view_model/order_details_view_model.dart index 384c0541d..412f1b962 100644 --- a/lib/view_model/order_details_view_model.dart +++ b/lib/view_model/order_details_view_model.dart @@ -27,7 +27,7 @@ abstract class OrderDetailsViewModelBase with Store { _provider = WyreBuyProvider(wallet: wallet); break; case BuyProviderDescription.moonPay: - _provider = MoonPayBuyProvider(wallet: wallet); + // _provider = MoonPayProvider(wallet: wallet);// TODO: CW-521 break; } } @@ -50,9 +50,9 @@ abstract class OrderDetailsViewModelBase with Store { @action Future _updateOrder() async { try { - if (_provider != null && (_provider is MoonPayBuyProvider || _provider is WyreBuyProvider)) { - final updatedOrder = _provider is MoonPayBuyProvider - ? await (_provider as MoonPayBuyProvider).findOrderById(order.id) + if (_provider != null && (_provider is MoonPayProvider || _provider is WyreBuyProvider)) { + final updatedOrder = _provider is MoonPayProvider + ? await (_provider as MoonPayProvider).findOrderById(order.id) : await (_provider as WyreBuyProvider).findOrderById(order.id); updatedOrder.from = order.from; updatedOrder.to = order.to; @@ -89,10 +89,10 @@ abstract class OrderDetailsViewModelBase with Store { value: order.provider.title) ); - if (_provider != null && (_provider is MoonPayBuyProvider || _provider is WyreBuyProvider)) { + if (_provider != null && (_provider is MoonPayProvider || _provider is WyreBuyProvider)) { - final trackUrl = _provider is MoonPayBuyProvider - ? (_provider as MoonPayBuyProvider).trackUrl + final trackUrl = _provider is MoonPayProvider + ? (_provider as MoonPayProvider).trackUrl : (_provider as WyreBuyProvider).trackUrl; if (trackUrl.isNotEmpty ?? false) { From fd9018bcc4b48b094e0ac62781ac746b744013fc Mon Sep 17 00:00:00 2001 From: Rafael <76502841+rafael-xmr@users.noreply.github.com> Date: Fri, 29 Mar 2024 15:51:34 -0300 Subject: [PATCH 140/241] Cw 598 fixes for electrum based wallets (#1344) * fix: address book addresses, bch builder, exchange all fee estimation, bch coin control * feat: new error framework for Electrum messages * build: cw_bitcoin.dart * feat: error improvements, localization, fix exchange amount mismatch * chore: misc comment & print [skip ci] * feat: refactor & simplify sendAll vs regular tx estimation and creation - Since there were so many conditions inside a single function to alter its behavior if sendAll or not, it is easier and more readable to have separate sendAll and estimateTx functions that behave separately * fix: wrong LTC dust * feat: fee rate confirmation * fix: wrong createTrade value when isSendAll is enabled * fix bitcoin cash address parsing [skip ci] * fix: form no amount validator, address book with multiple entries, exchange all below min error * fix: improve string, fix sending with dust inputs at the top * fix: two change outputs when re-estimating * fix: sendAll with a little dust adds fees * chore: sanity check [skip ci] * fix: if the fee is higher than estimated * Minor enhancement [skip ci] --------- Co-authored-by: OmarHatem --- .../bitcoin_commit_transaction_exception.dart | 8 +- ...tcoin_transaction_no_inputs_exception.dart | 4 - ...n_transaction_wrong_balance_exception.dart | 10 - cw_bitcoin/lib/electrum.dart | 60 +-- cw_bitcoin/lib/electrum_wallet.dart | 383 +++++++++++++----- cw_bitcoin/lib/electrum_wallet_addresses.dart | 8 +- cw_bitcoin/lib/exceptions.dart | 27 ++ .../lib/pending_bitcoin_transaction.dart | 37 +- .../lib/src/bitcoin_cash_wallet.dart | 183 --------- .../src/pending_bitcoin_cash_transaction.dart | 38 +- cw_core/lib/exceptions.dart | 30 ++ cw_core/lib/pending_transaction.dart | 3 +- cw_core/lib/wallet_addresses.dart | 8 +- lib/bitcoin/cw_bitcoin.dart | 41 +- lib/core/amount_validator.dart | 4 + .../provider/changenow_exchange_provider.dart | 9 +- lib/exchange/provider/exchange_provider.dart | 3 +- .../provider/exolix_exchange_provider.dart | 9 +- .../provider/sideshift_exchange_provider.dart | 7 +- .../simpleswap_exchange_provider.dart | 7 +- .../provider/thorchain_exchange.provider.dart | 15 +- .../provider/trocador_exchange_provider.dart | 16 +- lib/exchange/trade.dart | 11 +- lib/src/screens/exchange/exchange_page.dart | 10 +- .../exchange_trade/exchange_trade_page.dart | 1 + lib/src/screens/send/send_page.dart | 1 + .../send/widgets/confirm_sending_alert.dart | 40 +- .../unspent_coins_list_page.dart | 5 +- .../contact_list/contact_list_view_model.dart | 2 + .../exchange/exchange_trade_view_model.dart | 11 +- .../exchange/exchange_view_model.dart | 42 +- lib/view_model/send/send_view_model.dart | 63 ++- .../unspent_coins_details_view_model.dart | 4 +- res/values/strings_ar.arb | 11 + res/values/strings_bg.arb | 11 + res/values/strings_cs.arb | 11 + res/values/strings_de.arb | 11 + res/values/strings_en.arb | 11 + res/values/strings_es.arb | 11 + res/values/strings_fr.arb | 11 + res/values/strings_ha.arb | 11 + res/values/strings_hi.arb | 11 + res/values/strings_hr.arb | 11 + res/values/strings_id.arb | 11 + res/values/strings_it.arb | 11 + res/values/strings_ja.arb | 13 +- res/values/strings_ko.arb | 13 +- res/values/strings_my.arb | 13 +- res/values/strings_nl.arb | 13 +- res/values/strings_pl.arb | 13 +- res/values/strings_pt.arb | 13 +- res/values/strings_ru.arb | 13 +- res/values/strings_th.arb | 13 +- res/values/strings_tl.arb | 13 +- res/values/strings_tr.arb | 13 +- res/values/strings_uk.arb | 13 +- res/values/strings_ur.arb | 13 +- res/values/strings_yo.arb | 13 +- res/values/strings_zh.arb | 13 +- tool/configure.dart | 1 + 60 files changed, 984 insertions(+), 431 deletions(-) delete mode 100644 cw_bitcoin/lib/bitcoin_transaction_no_inputs_exception.dart delete mode 100644 cw_bitcoin/lib/bitcoin_transaction_wrong_balance_exception.dart create mode 100644 cw_bitcoin/lib/exceptions.dart create mode 100644 cw_core/lib/exceptions.dart diff --git a/cw_bitcoin/lib/bitcoin_commit_transaction_exception.dart b/cw_bitcoin/lib/bitcoin_commit_transaction_exception.dart index 3e21bae81..7bf488f3f 100644 --- a/cw_bitcoin/lib/bitcoin_commit_transaction_exception.dart +++ b/cw_bitcoin/lib/bitcoin_commit_transaction_exception.dart @@ -1,4 +1,8 @@ class BitcoinCommitTransactionException implements Exception { + String errorMessage; + BitcoinCommitTransactionException(this.errorMessage); + @override - String toString() => 'Transaction commit is failed.'; -} \ No newline at end of file + String toString() => errorMessage; +} + diff --git a/cw_bitcoin/lib/bitcoin_transaction_no_inputs_exception.dart b/cw_bitcoin/lib/bitcoin_transaction_no_inputs_exception.dart deleted file mode 100644 index fac7e93c4..000000000 --- a/cw_bitcoin/lib/bitcoin_transaction_no_inputs_exception.dart +++ /dev/null @@ -1,4 +0,0 @@ -class BitcoinTransactionNoInputsException implements Exception { - @override - String toString() => 'Not enough inputs available. Please select more under Coin Control'; -} diff --git a/cw_bitcoin/lib/bitcoin_transaction_wrong_balance_exception.dart b/cw_bitcoin/lib/bitcoin_transaction_wrong_balance_exception.dart deleted file mode 100644 index 3f379bea0..000000000 --- a/cw_bitcoin/lib/bitcoin_transaction_wrong_balance_exception.dart +++ /dev/null @@ -1,10 +0,0 @@ -import 'package:cw_core/crypto_currency.dart'; - -class BitcoinTransactionWrongBalanceException implements Exception { - BitcoinTransactionWrongBalanceException(this.currency); - - final CryptoCurrency currency; - - @override - String toString() => 'You do not have enough ${currency.title} to send this amount.'; -} \ No newline at end of file diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart index 51a53e285..0553170cc 100644 --- a/cw_bitcoin/lib/electrum.dart +++ b/cw_bitcoin/lib/electrum.dart @@ -7,10 +7,9 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/script_hash.dart'; import 'package:flutter/foundation.dart'; import 'package:rxdart/rxdart.dart'; -import 'package:http/http.dart' as http; String jsonrpcparams(List params) { - final _params = params?.map((val) => '"${val.toString()}"')?.join(','); + final _params = params.map((val) => '"${val.toString()}"').join(','); return '[$_params]'; } @@ -34,6 +33,7 @@ class ElectrumClient { : _id = 0, _isConnected = false, _tasks = {}, + _errors = {}, unterminatedString = ''; static const connectionTimeout = Duration(seconds: 5); @@ -44,6 +44,7 @@ class ElectrumClient { void Function(bool)? onConnectionStatusChange; int _id; final Map _tasks; + final Map _errors; bool _isConnected; Timer? _aliveTimer; String unterminatedString; @@ -243,30 +244,20 @@ class ElectrumClient { }); Future broadcastTransaction( - {required String transactionRaw, BasedUtxoNetwork? network}) async { - if (network == BitcoinNetwork.testnet) { - return http - .post(Uri(scheme: 'https', host: 'blockstream.info', path: '/testnet/api/tx'), - headers: {'Content-Type': 'application/json; charset=utf-8'}, - body: transactionRaw) - .then((http.Response response) { - if (response.statusCode == 200) { - return response.body; + {required String transactionRaw, + BasedUtxoNetwork? network, + Function(int)? idCallback}) async => + call( + method: 'blockchain.transaction.broadcast', + params: [transactionRaw], + idCallback: idCallback) + .then((dynamic result) { + if (result is String) { + return result; } - throw Exception('Failed to broadcast transaction: ${response.body}'); + return ''; }); - } - - return call(method: 'blockchain.transaction.broadcast', params: [transactionRaw]) - .then((dynamic result) { - if (result is String) { - return result; - } - - return ''; - }); - } Future> getMerkle({required String hash, required int height}) async => await call(method: 'blockchain.transaction.get_merkle', params: [hash, height]) @@ -371,10 +362,12 @@ class ElectrumClient { } } - Future call({required String method, List params = const []}) async { + Future call( + {required String method, List params = const [], Function(int)? idCallback}) async { final completer = Completer(); _id += 1; final id = _id; + idCallback?.call(id); _registryTask(id, completer); socket!.write(jsonrpc(method: method, id: id, params: params)); @@ -456,6 +449,23 @@ class ElectrumClient { final id = response['id'] as String?; final result = response['result']; + try { + final error = response['error'] as Map?; + if (error != null) { + final errorMessage = error['message'] as String?; + if (errorMessage != null) { + _errors[id!] = errorMessage; + } + } + } catch (_) {} + + try { + final error = response['error'] as String?; + if (error != null) { + _errors[id!] = error; + } + } catch (_) {} + if (method is String) { _methodHandler(method: method, request: response); return; @@ -465,6 +475,8 @@ class ElectrumClient { _finish(id, result); } } + + String getErrorMessage(int id) => _errors[id.toString()] ?? ''; } // FIXME: move me diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index e8c81c493..ffd8b5d52 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -8,10 +8,9 @@ import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin_base; import 'package:collection/collection.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; +import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; -import 'package:cw_bitcoin/bitcoin_transaction_no_inputs_exception.dart'; import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; -import 'package:cw_bitcoin/bitcoin_transaction_wrong_balance_exception.dart'; import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_bitcoin/bitcoin_wallet_keys.dart'; import 'package:cw_bitcoin/electrum.dart'; @@ -19,6 +18,7 @@ import 'package:cw_bitcoin/electrum_balance.dart'; import 'package:cw_bitcoin/electrum_transaction_history.dart'; import 'package:cw_bitcoin/electrum_transaction_info.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; +import 'package:cw_bitcoin/exceptions.dart'; import 'package:cw_bitcoin/litecoin_network.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/script_hash.dart'; @@ -188,27 +188,27 @@ abstract class ElectrumWalletBase } } - Future estimateTxFeeAndInputsToUse( - int credentialsAmount, - bool sendAll, - List outputAddresses, - List outputs, - int? feeRate, - BitcoinTransactionPriority? priority, - {int? inputsCount, - String? memo}) async { + int _getDustAmount() { + return 546; + } + + bool _isBelowDust(int amount) => amount <= _getDustAmount() && network != BitcoinNetwork.testnet; + + Future estimateSendAllTx( + List outputs, + int feeRate, { + String? memo, + int credentialsAmount = 0, + }) async { final utxos = []; List privateKeys = []; - - var leftAmount = credentialsAmount; - var allInputsAmount = 0; + int allInputsAmount = 0; for (int i = 0; i < unspentCoins.length; i++) { final utx = unspentCoins[i]; if (utx.isSending) { allInputsAmount += utx.value; - leftAmount = leftAmount - utx.value; final address = addressTypeFromStr(utx.address, network); final privkey = generateECPrivate( @@ -226,15 +226,12 @@ abstract class ElectrumWalletBase vout: utx.vout, scriptType: _getScriptType(address), ), - ownerDetails: - UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: address), + ownerDetails: UtxoAddressDetails( + publicKey: privkey.getPublic().toHex(), + address: address, + ), ), ); - - bool amountIsAcquired = !sendAll && leftAmount <= 0; - if ((inputsCount == null && amountIsAcquired) || inputsCount == i + 1) { - break; - } } } @@ -242,66 +239,218 @@ abstract class ElectrumWalletBase throw BitcoinTransactionNoInputsException(); } - var changeValue = allInputsAmount - credentialsAmount; - - if (!sendAll) { - if (changeValue > 0) { - final changeAddress = await walletAddresses.getChangeAddress(); - final address = addressTypeFromStr(changeAddress, network); - outputAddresses.add(address); - outputs.add(BitcoinOutput(address: address, value: BigInt.from(changeValue))); - } + int estimatedSize; + if (network is BitcoinCashNetwork) { + estimatedSize = ForkedTransactionBuilder.estimateTransactionSize( + utxos: utxos, + outputs: outputs, + network: network as BitcoinCashNetwork, + memo: memo, + ); + } else { + estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize( + utxos: utxos, + outputs: outputs, + network: network, + memo: memo, + ); } - final estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize( - utxos: utxos, - outputs: outputs, - network: network, - memo: memo, - ); - - int fee = feeRate != null - ? feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize) - : feeAmountForPriority(priority!, 0, 0, size: estimatedSize); + int fee = feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize); if (fee == 0) { - throw BitcoinTransactionWrongBalanceException(currency); + throw BitcoinTransactionNoFeeException(); } - var amount = credentialsAmount; + // Here, when sending all, the output amount equals to the input value - fee to fully spend every input on the transaction and have no amount left for change + int amount = allInputsAmount - fee; - final lastOutput = outputs.last; - if (!sendAll) { - if (changeValue > fee) { - // Here, lastOutput is change, deduct the fee from it - outputs[outputs.length - 1] = - BitcoinOutput(address: lastOutput.address, value: lastOutput.value - BigInt.from(fee)); + // Attempting to send less than the dust limit + if (_isBelowDust(amount)) { + throw BitcoinTransactionNoDustException(); + } + + if (credentialsAmount > 0) { + final amountLeftForFee = amount - credentialsAmount; + if (amountLeftForFee > 0 && _isBelowDust(amountLeftForFee)) { + amount -= amountLeftForFee; + fee += amountLeftForFee; } + } + + outputs[outputs.length - 1] = + BitcoinOutput(address: outputs.last.address, value: BigInt.from(amount)); + + return EstimatedTxResult( + utxos: utxos, + privateKeys: privateKeys, + fee: fee, + amount: amount, + isSendAll: true, + hasChange: false, + memo: memo, + ); + } + + Future estimateTxForAmount( + int credentialsAmount, + List outputs, + int feeRate, { + int? inputsCount, + String? memo, + }) async { + final utxos = []; + List privateKeys = []; + int allInputsAmount = 0; + + int leftAmount = credentialsAmount; + final sendingCoins = unspentCoins.where((utx) => utx.isSending).toList(); + + for (int i = 0; i < sendingCoins.length; i++) { + final utx = sendingCoins[i]; + + allInputsAmount += utx.value; + leftAmount = leftAmount - utx.value; + + final address = addressTypeFromStr(utx.address, network); + final privkey = generateECPrivate( + hd: utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, + index: utx.bitcoinAddressRecord.index, + network: network); + + privateKeys.add(privkey); + + utxos.add( + UtxoWithAddress( + utxo: BitcoinUtxo( + txHash: utx.hash, + value: BigInt.from(utx.value), + vout: utx.vout, + scriptType: _getScriptType(address), + ), + ownerDetails: UtxoAddressDetails( + publicKey: privkey.getPublic().toHex(), + address: address, + ), + ), + ); + + bool amountIsAcquired = leftAmount <= 0; + if ((inputsCount == null && amountIsAcquired) || inputsCount == i + 1) { + break; + } + } + + if (utxos.isEmpty) { + throw BitcoinTransactionNoInputsException(); + } + + final spendingAllCoins = sendingCoins.length == utxos.length; + + // How much is being spent - how much is being sent + int amountLeftForChangeAndFee = allInputsAmount - credentialsAmount; + + if (amountLeftForChangeAndFee <= 0) { + throw BitcoinTransactionWrongBalanceException(); + } + + final changeAddress = await walletAddresses.getChangeAddress(); + final address = addressTypeFromStr(changeAddress, network); + outputs.add(BitcoinOutput( + address: address, + value: BigInt.from(amountLeftForChangeAndFee), + )); + + int estimatedSize; + if (network is BitcoinCashNetwork) { + estimatedSize = ForkedTransactionBuilder.estimateTransactionSize( + utxos: utxos, + outputs: outputs, + network: network as BitcoinCashNetwork, + memo: memo, + ); } else { - // Here, if sendAll, the output amount equals to the input value - fee to fully spend every input on the transaction and have no amount for change - amount = allInputsAmount - fee; + estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize( + utxos: utxos, + outputs: outputs, + network: network, + memo: memo, + ); + } + + int fee = feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize); + + if (fee == 0) { + throw BitcoinTransactionNoFeeException(); + } + + int amount = credentialsAmount; + final lastOutput = outputs.last; + final amountLeftForChange = amountLeftForChangeAndFee - fee; + + if (!_isBelowDust(amountLeftForChange)) { + // Here, lastOutput already is change, return the amount left without the fee to the user's address. outputs[outputs.length - 1] = - BitcoinOutput(address: lastOutput.address, value: BigInt.from(amount)); + BitcoinOutput(address: lastOutput.address, value: BigInt.from(amountLeftForChange)); + } else { + // If has change that is lower than dust, will end up with tx rejected by network rules, so estimate again without the added change + outputs.removeLast(); + + // Still has inputs to spend before failing + if (!spendingAllCoins) { + return estimateTxForAmount( + credentialsAmount, + outputs, + feeRate, + inputsCount: utxos.length + 1, + memo: memo, + ); + } + + final estimatedSendAll = await estimateSendAllTx( + outputs, + feeRate, + memo: memo, + ); + + if (estimatedSendAll.amount == credentialsAmount) { + return estimatedSendAll; + } + + // Estimate to user how much is needed to send to cover the fee + final maxAmountWithReturningChange = allInputsAmount - _getDustAmount() - fee - 1; + throw BitcoinTransactionNoDustOnChangeException( + bitcoinAmountToString(amount: maxAmountWithReturningChange), + bitcoinAmountToString(amount: estimatedSendAll.amount), + ); + } + + // Attempting to send less than the dust limit + if (_isBelowDust(amount)) { + throw BitcoinTransactionNoDustException(); } final totalAmount = amount + fee; if (totalAmount > balance[currency]!.confirmed) { - throw BitcoinTransactionWrongBalanceException(currency); + throw BitcoinTransactionWrongBalanceException(); } if (totalAmount > allInputsAmount) { - if (unspentCoins.where((utx) => utx.isSending).length == utxos.length) { - throw BitcoinTransactionWrongBalanceException(currency); + if (spendingAllCoins) { + throw BitcoinTransactionWrongBalanceException(); } else { - if (changeValue > fee) { - outputAddresses.removeLast(); + if (amountLeftForChangeAndFee > fee) { outputs.removeLast(); } - return estimateTxFeeAndInputsToUse( - credentialsAmount, sendAll, outputAddresses, outputs, feeRate, priority, - inputsCount: utxos.length + 1); + return estimateTxForAmount( + credentialsAmount, + outputs, + feeRate, + inputsCount: utxos.length + 1, + memo: memo, + ); } } @@ -310,6 +459,8 @@ abstract class ElectrumWalletBase privateKeys: privateKeys, fee: fee, amount: amount, + hasChange: true, + isSendAll: false, memo: memo, ); } @@ -318,58 +469,80 @@ abstract class ElectrumWalletBase Future createTransaction(Object credentials) async { try { final outputs = []; - final outputAddresses = []; final transactionCredentials = credentials as BitcoinTransactionCredentials; final hasMultiDestination = transactionCredentials.outputs.length > 1; final sendAll = !hasMultiDestination && transactionCredentials.outputs.first.sendAll; + final memo = transactionCredentials.outputs.first.memo; - var credentialsAmount = 0; + int credentialsAmount = 0; for (final out in transactionCredentials.outputs) { - final outputAddress = out.isParsedAddress ? out.extractedAddress! : out.address; - final address = addressTypeFromStr(outputAddress, network); + final outputAmount = out.formattedCryptoAmount!; - outputAddresses.add(address); + if (!sendAll && _isBelowDust(outputAmount)) { + throw BitcoinTransactionNoDustException(); + } if (hasMultiDestination) { - if (out.sendAll || out.formattedCryptoAmount! <= 0) { - throw BitcoinTransactionWrongBalanceException(currency); + if (out.sendAll) { + throw BitcoinTransactionWrongBalanceException(); } + } - final outputAmount = out.formattedCryptoAmount!; - credentialsAmount += outputAmount; + credentialsAmount += outputAmount; - outputs.add(BitcoinOutput(address: address, value: BigInt.from(outputAmount))); + final address = + addressTypeFromStr(out.isParsedAddress ? out.extractedAddress! : out.address, network); + + if (sendAll) { + // The value will be changed after estimating the Tx size and deducting the fee from the total to be sent + outputs.add(BitcoinOutput(address: address, value: BigInt.from(0))); } else { - if (!sendAll) { - final outputAmount = out.formattedCryptoAmount!; - credentialsAmount += outputAmount; - outputs.add(BitcoinOutput(address: address, value: BigInt.from(outputAmount))); - } else { - // The value will be changed after estimating the Tx size and deducting the fee from the total - outputs.add(BitcoinOutput(address: address, value: BigInt.from(0))); - } + outputs.add(BitcoinOutput(address: address, value: BigInt.from(outputAmount))); } } - final estimatedTx = await estimateTxFeeAndInputsToUse( - credentialsAmount, - sendAll, - outputAddresses, - outputs, - transactionCredentials.feeRate, - transactionCredentials.priority, - memo: transactionCredentials.outputs.first.memo, - ); + final feeRateInt = transactionCredentials.feeRate != null + ? transactionCredentials.feeRate! + : feeRate(transactionCredentials.priority!); - final txb = BitcoinTransactionBuilder( - utxos: estimatedTx.utxos, - outputs: outputs, - fee: BigInt.from(estimatedTx.fee), - network: network, - memo: estimatedTx.memo, - outputOrdering: BitcoinOrdering.none, - ); + EstimatedTxResult estimatedTx; + if (sendAll) { + estimatedTx = await estimateSendAllTx( + outputs, + feeRateInt, + memo: memo, + credentialsAmount: credentialsAmount, + ); + } else { + estimatedTx = await estimateTxForAmount( + credentialsAmount, + outputs, + feeRateInt, + memo: memo, + ); + } + + BasedBitcoinTransacationBuilder txb; + if (network is BitcoinCashNetwork) { + txb = ForkedTransactionBuilder( + utxos: estimatedTx.utxos, + outputs: outputs, + fee: BigInt.from(estimatedTx.fee), + network: network, + memo: estimatedTx.memo, + outputOrdering: BitcoinOrdering.none, + ); + } else { + txb = BitcoinTransactionBuilder( + utxos: estimatedTx.utxos, + outputs: outputs, + fee: BigInt.from(estimatedTx.fee), + network: network, + memo: estimatedTx.memo, + outputOrdering: BitcoinOrdering.none, + ); + } final transaction = txb.buildTransaction((txDigest, utxo, publicKey, sighash) { final key = estimatedTx.privateKeys @@ -390,7 +563,10 @@ abstract class ElectrumWalletBase electrumClient: electrumClient, amount: estimatedTx.amount, fee: estimatedTx.fee, - network: network) + feeRate: feeRateInt.toString(), + network: network, + hasChange: estimatedTx.hasChange, + isSendAll: estimatedTx.isSendAll) ..addListener((transaction) async { transactionHistory.addOne(transaction); await updateBalance(); @@ -423,7 +599,7 @@ abstract class ElectrumWalletBase } } - int feeAmountForPriority(BitcoinTransactionPriority priority, int inputsCount, int outputsCount, + int feeAmountForPriority(TransactionPriority priority, int inputsCount, int outputsCount, {int? size}) => feeRate(priority) * (size ?? estimatedTransactionSize(inputsCount, outputsCount)); @@ -908,6 +1084,8 @@ class EstimatedTxResult { required this.privateKeys, required this.fee, required this.amount, + required this.hasChange, + required this.isSendAll, this.memo, }); @@ -915,10 +1093,21 @@ class EstimatedTxResult { final List privateKeys; final int fee; final int amount; + final bool hasChange; + final bool isSendAll; final String? memo; } BitcoinBaseAddress addressTypeFromStr(String address, BasedUtxoNetwork network) { + if (network is BitcoinCashNetwork) { + if (!address.startsWith("bitcoincash:") && + (address.startsWith("q") || address.startsWith("p"))) { + address = "bitcoincash:$address"; + } + + return BitcoinCashAddress(address).baseAddress; + } + if (P2pkhAddress.regex.hasMatch(address)) { return P2pkhAddress.fromAddress(address: address, network: network); } else if (P2shAddress.regex.hasMatch(address)) { diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index 69d0a6385..ac2397561 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -77,7 +77,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { String get address { String receiveAddress; - final typeMatchingReceiveAddresses = receiveAddresses.where(_isAddressPageTypeMatch); + final typeMatchingReceiveAddresses = + receiveAddresses.where(_isAddressPageTypeMatch).where((addr) => !addr.isUsed); if ((isEnabledAutoGenerateSubaddress && receiveAddresses.isEmpty) || typeMatchingReceiveAddresses.isEmpty) { @@ -220,8 +221,11 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { Future updateAddressesInBox() async { try { addressesMap.clear(); + addressesMap[address] = ''; + + allAddressesMap.clear(); _addresses.forEach((addressRecord) { - addressesMap[addressRecord.address] = addressRecord.name; + allAddressesMap[addressRecord.address] = addressRecord.name; }); await saveAddressesInBox(); } catch (e) { diff --git a/cw_bitcoin/lib/exceptions.dart b/cw_bitcoin/lib/exceptions.dart new file mode 100644 index 000000000..4b03eb922 --- /dev/null +++ b/cw_bitcoin/lib/exceptions.dart @@ -0,0 +1,27 @@ +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/exceptions.dart'; + +class BitcoinTransactionWrongBalanceException extends TransactionWrongBalanceException { + BitcoinTransactionWrongBalanceException() : super(CryptoCurrency.btc); +} + +class BitcoinTransactionNoInputsException extends TransactionNoInputsException {} + +class BitcoinTransactionNoFeeException extends TransactionNoFeeException {} + +class BitcoinTransactionNoDustException extends TransactionNoDustException {} + +class BitcoinTransactionNoDustOnChangeException extends TransactionNoDustOnChangeException { + BitcoinTransactionNoDustOnChangeException(super.max, super.min); +} + +class BitcoinTransactionCommitFailed extends TransactionCommitFailed {} + +class BitcoinTransactionCommitFailedDustChange extends TransactionCommitFailedDustChange {} + +class BitcoinTransactionCommitFailedDustOutput extends TransactionCommitFailedDustOutput {} + +class BitcoinTransactionCommitFailedDustOutputSendAll + extends TransactionCommitFailedDustOutputSendAll {} + +class BitcoinTransactionCommitFailedVoutNegative extends TransactionCommitFailedVoutNegative {} diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart index b45931133..ada39a8f7 100644 --- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart +++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart @@ -1,4 +1,4 @@ -import 'package:cw_bitcoin/bitcoin_commit_transaction_exception.dart'; +import 'package:cw_bitcoin/exceptions.dart'; import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_core/pending_transaction.dart'; import 'package:cw_bitcoin/electrum.dart'; @@ -9,7 +9,13 @@ import 'package:cw_core/wallet_type.dart'; class PendingBitcoinTransaction with PendingTransaction { PendingBitcoinTransaction(this._tx, this.type, - {required this.electrumClient, required this.amount, required this.fee, this.network}) + {required this.electrumClient, + required this.amount, + required this.fee, + required this.feeRate, + this.network, + required this.hasChange, + required this.isSendAll}) : _listeners = []; final WalletType type; @@ -17,7 +23,10 @@ class PendingBitcoinTransaction with PendingTransaction { final ElectrumClient electrumClient; final int amount; final int fee; + final String feeRate; final BasedUtxoNetwork? network; + final bool hasChange; + final bool isSendAll; @override String get id => _tx.txId(); @@ -38,10 +47,30 @@ class PendingBitcoinTransaction with PendingTransaction { @override Future commit() async { - final result = await electrumClient.broadcastTransaction(transactionRaw: hex, network: network); + int? callId; + + final result = await electrumClient.broadcastTransaction( + transactionRaw: hex, network: network, idCallback: (id) => callId = id); if (result.isEmpty) { - throw BitcoinCommitTransactionException(); + if (callId != null) { + final error = electrumClient.getErrorMessage(callId!); + + if (error.contains("dust")) { + if (hasChange) { + throw BitcoinTransactionCommitFailedDustChange(); + } else if (!isSendAll) { + throw BitcoinTransactionCommitFailedDustOutput(); + } else { + throw BitcoinTransactionCommitFailedDustOutputSendAll(); + } + } + + if (error.contains("bad-txns-vout-negative")) { + throw BitcoinTransactionCommitFailedVoutNegative(); + } + } + throw BitcoinTransactionCommitFailed(); } _listeners.forEach((listener) => listener(transactionInfo())); diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index 40ddcfa57..1f04e5624 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -4,15 +4,10 @@ import 'package:bitbox/bitbox.dart' as bitbox; import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:cw_bitcoin/bitcoin_address_record.dart'; -import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; -import 'package:cw_bitcoin/bitcoin_transaction_no_inputs_exception.dart'; import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; -import 'package:cw_bitcoin/bitcoin_transaction_wrong_balance_exception.dart'; -import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_bitcoin/electrum_balance.dart'; import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:cw_bitcoin/electrum_wallet_snapshot.dart'; -import 'package:cw_bitcoin_cash/src/pending_bitcoin_cash_transaction.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/unspent_coins_info.dart'; @@ -130,187 +125,9 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { ); } - @override - Future createTransaction(Object credentials) async { - const minAmount = 546; - final transactionCredentials = credentials as BitcoinTransactionCredentials; - final inputs = []; - final outputs = transactionCredentials.outputs; - final hasMultiDestination = outputs.length > 1; - - var allInputsAmount = 0; - - final String? opReturnMemo = outputs.first.memo; - - if (unspentCoins.isEmpty) await updateUnspent(); - - for (final utx in unspentCoins) { - if (utx.isSending) { - allInputsAmount += utx.value; - inputs.add(utx); - } - } - - if (inputs.isEmpty) throw BitcoinTransactionNoInputsException(); - - final allAmountFee = transactionCredentials.feeRate != null - ? feeAmountWithFeeRate(transactionCredentials.feeRate!, inputs.length, outputs.length) - : feeAmountForPriority(transactionCredentials.priority!, inputs.length, outputs.length); - - final allAmount = allInputsAmount - allAmountFee; - - var credentialsAmount = 0; - var amount = 0; - var fee = 0; - - if (hasMultiDestination) { - if (outputs.any((item) => item.sendAll || item.formattedCryptoAmount! <= 0)) { - throw BitcoinTransactionWrongBalanceException(currency); - } - - credentialsAmount = outputs.fold(0, (acc, value) => acc + value.formattedCryptoAmount!); - - if (allAmount - credentialsAmount < minAmount) { - throw BitcoinTransactionWrongBalanceException(currency); - } - - amount = credentialsAmount; - - if (transactionCredentials.feeRate != null) { - fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate!, amount, - outputsCount: outputs.length + 1); - } else { - fee = calculateEstimatedFee(transactionCredentials.priority, amount, - outputsCount: outputs.length + 1); - } - } else { - final output = outputs.first; - credentialsAmount = !output.sendAll ? output.formattedCryptoAmount! : 0; - - if (credentialsAmount > allAmount) { - throw BitcoinTransactionWrongBalanceException(currency); - } - - amount = output.sendAll || allAmount - credentialsAmount < minAmount - ? allAmount - : credentialsAmount; - - if (output.sendAll || amount == allAmount) { - fee = allAmountFee; - } else if (transactionCredentials.feeRate != null) { - fee = calculateEstimatedFeeWithFeeRate(transactionCredentials.feeRate!, amount); - } else { - fee = calculateEstimatedFee(transactionCredentials.priority, amount); - } - } - - if (fee == 0) { - throw BitcoinTransactionWrongBalanceException(currency); - } - - final totalAmount = amount + fee; - - if (totalAmount > balance[currency]!.confirmed || totalAmount > allInputsAmount) { - throw BitcoinTransactionWrongBalanceException(currency); - } - final txb = bitbox.Bitbox.transactionBuilder(testnet: false); - - final changeAddress = await walletAddresses.getChangeAddress(); - var leftAmount = totalAmount; - var totalInputAmount = 0; - - inputs.clear(); - - for (final utx in unspentCoins) { - if (utx.isSending) { - leftAmount = leftAmount - utx.value; - totalInputAmount += utx.value; - inputs.add(utx); - - if (leftAmount <= 0) { - break; - } - } - } - - if (inputs.isEmpty) throw BitcoinTransactionNoInputsException(); - - if (amount <= 0 || totalInputAmount < totalAmount) { - throw BitcoinTransactionWrongBalanceException(currency); - } - - inputs.forEach((input) { - txb.addInput(input.hash, input.vout); - }); - - final String bchPrefix = "bitcoincash:"; - - outputs.forEach((item) { - final outputAmount = hasMultiDestination ? item.formattedCryptoAmount : amount; - String outputAddress = item.isParsedAddress ? item.extractedAddress! : item.address; - - if (!outputAddress.startsWith(bchPrefix)) { - outputAddress = "$bchPrefix$outputAddress"; - } - - bool isP2sh = outputAddress.startsWith("p", bchPrefix.length); - - if (isP2sh) { - final p2sh = P2shAddress.fromAddress( - address: outputAddress, - network: BitcoinCashNetwork.mainnet, - ); - - txb.addOutput(Uint8List.fromList(p2sh.toScriptPubKey().toBytes()), outputAmount!); - return; - } - - txb.addOutput(outputAddress, outputAmount!); - }); - - final estimatedSize = bitbox.BitcoinCash.getByteCount(inputs.length, outputs.length + 1); - - var feeAmount = 0; - - if (transactionCredentials.feeRate != null) { - feeAmount = transactionCredentials.feeRate! * estimatedSize; - } else { - feeAmount = feeRate(transactionCredentials.priority!) * estimatedSize; - } - - final changeValue = totalInputAmount - amount - feeAmount; - - if (changeValue > minAmount) { - txb.addOutput(changeAddress, changeValue); - } - - if (opReturnMemo != null) txb.addOutputData(opReturnMemo); - - for (var i = 0; i < inputs.length; i++) { - final input = inputs[i]; - final keyPair = generateKeyPair( - hd: input.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, - index: input.bitcoinAddressRecord.index); - txb.sign(i, keyPair, input.value); - } - - final tx = txb.build(); - - return PendingBitcoinCashTransaction(tx, type, - electrumClient: electrumClient, amount: amount, fee: fee); - } - bitbox.ECPair generateKeyPair({required bitcoin.HDWallet hd, required int index}) => bitbox.ECPair.fromWIF(hd.derive(index).wif!); - @override - int feeAmountForPriority(BitcoinTransactionPriority priority, int inputsCount, int outputsCount, - {int? size}) => - feeRate(priority) * bitbox.BitcoinCash.getByteCount(inputsCount, outputsCount); - - int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount, {int? size}) => - feeRate * bitbox.BitcoinCash.getByteCount(inputsCount, outputsCount); - int calculateEstimatedFeeWithFeeRate(int feeRate, int? amount, {int? outputsCount, int? size}) { int inputsCount = 0; int totalValue = 0; diff --git a/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart b/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart index d5ac36ce2..da4710a8b 100644 --- a/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart +++ b/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart @@ -1,4 +1,4 @@ -import 'package:cw_bitcoin/bitcoin_commit_transaction_exception.dart'; +import 'package:cw_bitcoin/exceptions.dart'; import 'package:bitbox/bitbox.dart' as bitbox; import 'package:cw_core/pending_transaction.dart'; import 'package:cw_bitcoin/electrum.dart'; @@ -11,7 +11,9 @@ class PendingBitcoinCashTransaction with PendingTransaction { PendingBitcoinCashTransaction(this._tx, this.type, {required this.electrumClient, required this.amount, - required this.fee}) + required this.fee, + required this.hasChange, + required this.isSendAll}) : _listeners = []; final WalletType type; @@ -19,6 +21,8 @@ class PendingBitcoinCashTransaction with PendingTransaction { final ElectrumClient electrumClient; final int amount; final int fee; + final bool hasChange; + final bool isSendAll; @override String get id => _tx.getId(); @@ -36,18 +40,36 @@ class PendingBitcoinCashTransaction with PendingTransaction { @override Future commit() async { - final result = - await electrumClient.broadcastTransaction(transactionRaw: _tx.toHex()); + int? callId; + + final result = await electrumClient.broadcastTransaction( + transactionRaw: hex, idCallback: (id) => callId = id); if (result.isEmpty) { - throw BitcoinCommitTransactionException(); + if (callId != null) { + final error = electrumClient.getErrorMessage(callId!); + + if (error.contains("dust")) { + if (hasChange) { + throw BitcoinTransactionCommitFailedDustChange(); + } else if (!isSendAll) { + throw BitcoinTransactionCommitFailedDustOutput(); + } else { + throw BitcoinTransactionCommitFailedDustOutputSendAll(); + } + } + + if (error.contains("bad-txns-vout-negative")) { + throw BitcoinTransactionCommitFailedVoutNegative(); + } + } + throw BitcoinTransactionCommitFailed(); } - _listeners?.forEach((listener) => listener(transactionInfo())); + _listeners.forEach((listener) => listener(transactionInfo())); } - void addListener( - void Function(ElectrumTransactionInfo transaction) listener) => + void addListener(void Function(ElectrumTransactionInfo transaction) listener) => _listeners.add(listener); ElectrumTransactionInfo transactionInfo() => ElectrumTransactionInfo(type, diff --git a/cw_core/lib/exceptions.dart b/cw_core/lib/exceptions.dart new file mode 100644 index 000000000..848ac40e6 --- /dev/null +++ b/cw_core/lib/exceptions.dart @@ -0,0 +1,30 @@ +import 'package:cw_core/crypto_currency.dart'; + +class TransactionWrongBalanceException implements Exception { + TransactionWrongBalanceException(this.currency); + + final CryptoCurrency currency; +} + +class TransactionNoInputsException implements Exception {} + +class TransactionNoFeeException implements Exception {} + +class TransactionNoDustException implements Exception {} + +class TransactionNoDustOnChangeException implements Exception { + TransactionNoDustOnChangeException(this.max, this.min); + + final String max; + final String min; +} + +class TransactionCommitFailed implements Exception {} + +class TransactionCommitFailedDustChange implements Exception {} + +class TransactionCommitFailedDustOutput implements Exception {} + +class TransactionCommitFailedDustOutputSendAll implements Exception {} + +class TransactionCommitFailedVoutNegative implements Exception {} diff --git a/cw_core/lib/pending_transaction.dart b/cw_core/lib/pending_transaction.dart index 042b0ca2b..642db9c2c 100644 --- a/cw_core/lib/pending_transaction.dart +++ b/cw_core/lib/pending_transaction.dart @@ -2,8 +2,9 @@ mixin PendingTransaction { String get id; String get amountFormatted; String get feeFormatted; + String? feeRate; String get hex; int? get outputCount => null; Future commit(); -} \ No newline at end of file +} diff --git a/cw_core/lib/wallet_addresses.dart b/cw_core/lib/wallet_addresses.dart index d8c84c80c..a2a2a50a3 100644 --- a/cw_core/lib/wallet_addresses.dart +++ b/cw_core/lib/wallet_addresses.dart @@ -3,8 +3,9 @@ import 'package:cw_core/wallet_info.dart'; abstract class WalletAddresses { WalletAddresses(this.walletInfo) - : addressesMap = {}, - addressInfos = {}; + : addressesMap = {}, + allAddressesMap = {}, + addressInfos = {}; final WalletInfo walletInfo; @@ -15,6 +16,7 @@ abstract class WalletAddresses { set address(String address); Map addressesMap; + Map allAddressesMap; Map> addressInfos; @@ -39,5 +41,5 @@ abstract class WalletAddresses { } } - bool containsAddress(String address) => addressesMap.containsKey(address); + bool containsAddress(String address) => allAddressesMap.containsKey(address); } diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 4db51fbc2..c9649a2e3 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -86,7 +86,7 @@ class CWBitcoin extends Bitcoin { extractedAddress: out.extractedAddress, isParsedAddress: out.isParsedAddress, formattedCryptoAmount: out.formattedCryptoAmount, - memo: out.memo)) + memo: out.memo)) .toList(), priority: priority as BitcoinTransactionPriority, feeRate: feeRate); @@ -123,23 +123,30 @@ class CWBitcoin extends Bitcoin { @override Future estimateFakeSendAllTxAmount(Object wallet, TransactionPriority priority) async { - final electrumWallet = wallet as ElectrumWallet; - final sk = ECPrivate.random(); - - final p2shAddr = sk.getPublic().toP2pkhInP2sh(); - final p2wpkhAddr = sk.getPublic().toP2wpkhAddress(); try { - final estimatedTx = await electrumWallet.estimateTxFeeAndInputsToUse( - 0, - true, - // Deposit address + change address - [p2shAddr, p2wpkhAddr], - [ - BitcoinOutput(address: p2shAddr, value: BigInt.zero), - BitcoinOutput(address: p2wpkhAddr, value: BigInt.zero) - ], - null, - priority as BitcoinTransactionPriority); + final sk = ECPrivate.random(); + final electrumWallet = wallet as ElectrumWallet; + + if (wallet.type == WalletType.bitcoinCash) { + final p2pkhAddr = sk.getPublic().toP2pkhAddress(); + final estimatedTx = await electrumWallet.estimateSendAllTx( + [BitcoinOutput(address: p2pkhAddr, value: BigInt.zero)], + getFeeRate(wallet, priority as BitcoinCashTransactionPriority), + ); + + return estimatedTx.amount; + } + + final p2shAddr = sk.getPublic().toP2pkhInP2sh(); + final estimatedTx = await electrumWallet.estimateSendAllTx( + [BitcoinOutput(address: p2shAddr, value: BigInt.zero)], + getFeeRate( + wallet, + wallet.type == WalletType.litecoin + ? priority as LitecoinTransactionPriority + : priority as BitcoinTransactionPriority, + ), + ); return estimatedTx.amount; } catch (_) { diff --git a/lib/core/amount_validator.dart b/lib/core/amount_validator.dart index fb5214d54..38983dfb2 100644 --- a/lib/core/amount_validator.dart +++ b/lib/core/amount_validator.dart @@ -34,6 +34,10 @@ class AmountValidator extends TextValidator { late final DecimalAmountValidator decimalAmountValidator; String? call(String? value) { + if (value == null || value.isEmpty) { + return S.current.error_text_amount; + } + //* Validate for Text(length, symbols, decimals etc) final textValidation = symbolsAmountValidator(value) ?? decimalAmountValidator(value); diff --git a/lib/exchange/provider/changenow_exchange_provider.dart b/lib/exchange/provider/changenow_exchange_provider.dart index c4a96bc5b..42f8634fb 100644 --- a/lib/exchange/provider/changenow_exchange_provider.dart +++ b/lib/exchange/provider/changenow_exchange_provider.dart @@ -133,7 +133,11 @@ class ChangeNowExchangeProvider extends ExchangeProvider { } @override - Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { + Future createTrade({ + required TradeRequest request, + required bool isFixedRateMode, + required bool isSendAll, + }) async { final distributionPath = await DistributionInfo.instance.getDistributionPath(); final formattedAppVersion = int.tryParse(_settingsStore.appVersion.replaceAll('.', '')) ?? 0; final payload = { @@ -202,7 +206,8 @@ class ChangeNowExchangeProvider extends ExchangeProvider { createdAt: DateTime.now(), amount: responseJSON['fromAmount']?.toString() ?? request.fromAmount, state: TradeState.created, - payoutAddress: payoutAddress); + payoutAddress: payoutAddress, + isSendAll: isSendAll); } @override diff --git a/lib/exchange/provider/exchange_provider.dart b/lib/exchange/provider/exchange_provider.dart index d1f69689d..a91a7ac9d 100644 --- a/lib/exchange/provider/exchange_provider.dart +++ b/lib/exchange/provider/exchange_provider.dart @@ -28,7 +28,8 @@ abstract class ExchangeProvider { Future fetchLimits( {required CryptoCurrency from, required CryptoCurrency to, required bool isFixedRateMode}); - Future createTrade({required TradeRequest request, required bool isFixedRateMode}); + Future createTrade( + {required TradeRequest request, required bool isFixedRateMode, required bool isSendAll}); Future findTradeById({required String id}); diff --git a/lib/exchange/provider/exolix_exchange_provider.dart b/lib/exchange/provider/exolix_exchange_provider.dart index 9374439f3..db11a8f58 100644 --- a/lib/exchange/provider/exolix_exchange_provider.dart +++ b/lib/exchange/provider/exolix_exchange_provider.dart @@ -130,7 +130,11 @@ class ExolixExchangeProvider extends ExchangeProvider { } @override - Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { + Future createTrade({ + required TradeRequest request, + required bool isFixedRateMode, + required bool isSendAll, + }) async { final headers = {'Content-Type': 'application/json'}; final body = { 'coinFrom': _normalizeCurrency(request.fromCurrency), @@ -180,7 +184,8 @@ class ExolixExchangeProvider extends ExchangeProvider { createdAt: DateTime.now(), amount: amount, state: TradeState.created, - payoutAddress: payoutAddress); + payoutAddress: payoutAddress, + isSendAll: isSendAll); } @override diff --git a/lib/exchange/provider/sideshift_exchange_provider.dart b/lib/exchange/provider/sideshift_exchange_provider.dart index 261aeedf3..1be4f8045 100644 --- a/lib/exchange/provider/sideshift_exchange_provider.dart +++ b/lib/exchange/provider/sideshift_exchange_provider.dart @@ -144,7 +144,11 @@ class SideShiftExchangeProvider extends ExchangeProvider { } @override - Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { + Future createTrade({ + required TradeRequest request, + required bool isFixedRateMode, + required bool isSendAll, + }) async { String url = ''; final body = { 'affiliateId': affiliateId, @@ -197,6 +201,7 @@ class SideShiftExchangeProvider extends ExchangeProvider { amount: depositAmount ?? request.fromAmount, payoutAddress: settleAddress, createdAt: DateTime.now(), + isSendAll: isSendAll, ); } diff --git a/lib/exchange/provider/simpleswap_exchange_provider.dart b/lib/exchange/provider/simpleswap_exchange_provider.dart index 5c162a995..df83cf491 100644 --- a/lib/exchange/provider/simpleswap_exchange_provider.dart +++ b/lib/exchange/provider/simpleswap_exchange_provider.dart @@ -117,7 +117,11 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { } @override - Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { + Future createTrade({ + required TradeRequest request, + required bool isFixedRateMode, + required bool isSendAll, + }) async { final headers = {'Content-Type': 'application/json'}; final params = {'api_key': apiKey}; final body = { @@ -162,6 +166,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider { amount: request.fromAmount, payoutAddress: payoutAddress, createdAt: DateTime.now(), + isSendAll: isSendAll, ); } diff --git a/lib/exchange/provider/thorchain_exchange.provider.dart b/lib/exchange/provider/thorchain_exchange.provider.dart index 2ab04b742..32dce7db8 100644 --- a/lib/exchange/provider/thorchain_exchange.provider.dart +++ b/lib/exchange/provider/thorchain_exchange.provider.dart @@ -109,7 +109,11 @@ class ThorChainExchangeProvider extends ExchangeProvider { } @override - Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { + Future createTrade({ + required TradeRequest request, + required bool isFixedRateMode, + required bool isSendAll, + }) async { String formattedToAddress = request.toAddress.startsWith('bitcoincash:') ? request.toAddress.replaceFirst('bitcoincash:', '') : request.toAddress; @@ -142,7 +146,8 @@ class ThorChainExchangeProvider extends ExchangeProvider { amount: request.fromAmount, state: TradeState.notFound, payoutAddress: request.toAddress, - memo: memo); + memo: memo, + isSendAll: isSendAll); } @override @@ -177,10 +182,12 @@ class ThorChainExchangeProvider extends ExchangeProvider { final parts = memo?.split(':') ?? []; final String toChain = parts.length > 1 ? parts[1].split('.')[0] : ''; - final String toAsset = parts.length > 1 && parts[1].split('.').length > 1 ? parts[1].split('.')[1].split('-')[0] : ''; + final String toAsset = parts.length > 1 && parts[1].split('.').length > 1 + ? parts[1].split('.')[1].split('-')[0] + : ''; final formattedToChain = CryptoCurrency.fromString(toChain); - final toAssetWithChain = CryptoCurrency.fromString(toAsset, walletCurrency:formattedToChain); + final toAssetWithChain = CryptoCurrency.fromString(toAsset, walletCurrency: formattedToChain); final plannedOutTxs = responseJSON['planned_out_txs'] as List?; final isRefund = plannedOutTxs?.any((tx) => tx['refund'] == true) ?? false; diff --git a/lib/exchange/provider/trocador_exchange_provider.dart b/lib/exchange/provider/trocador_exchange_provider.dart index faa4cc060..326573016 100644 --- a/lib/exchange/provider/trocador_exchange_provider.dart +++ b/lib/exchange/provider/trocador_exchange_provider.dart @@ -13,7 +13,8 @@ import 'package:http/http.dart'; class TrocadorExchangeProvider extends ExchangeProvider { TrocadorExchangeProvider({this.useTorOnly = false, this.providerStates = const {}}) - : _lastUsedRateId = '', _provider = [], + : _lastUsedRateId = '', + _provider = [], super(pairList: supportedPairs(_notSupported)); bool useTorOnly; @@ -23,7 +24,7 @@ class TrocadorExchangeProvider extends ExchangeProvider { 'Swapter', 'StealthEx', 'Simpleswap', - 'Swapuz' + 'Swapuz', 'ChangeNow', 'Changehero', 'FixedFloat', @@ -144,8 +145,11 @@ class TrocadorExchangeProvider extends ExchangeProvider { } @override - Future createTrade({required TradeRequest request, required bool isFixedRateMode}) async { - + Future createTrade({ + required TradeRequest request, + required bool isFixedRateMode, + required bool isSendAll, + }) async { final params = { 'api_key': apiKey, 'ticker_from': _normalizeCurrency(request.fromCurrency), @@ -172,7 +176,6 @@ class TrocadorExchangeProvider extends ExchangeProvider { params['id'] = _lastUsedRateId; } - String firstAvailableProvider = ''; for (var provider in _provider) { @@ -225,7 +228,8 @@ class TrocadorExchangeProvider extends ExchangeProvider { providerName: providerName, createdAt: DateTime.tryParse(date)?.toLocal(), amount: responseJSON['amount_from']?.toString() ?? request.fromAmount, - payoutAddress: payoutAddress); + payoutAddress: payoutAddress, + isSendAll: isSendAll); } @override diff --git a/lib/exchange/trade.dart b/lib/exchange/trade.dart index 4bfb335b8..6cc3fddbe 100644 --- a/lib/exchange/trade.dart +++ b/lib/exchange/trade.dart @@ -31,6 +31,7 @@ class Trade extends HiveObject { this.memo, this.txId, this.isRefund, + this.isSendAll, }) { if (provider != null) providerRaw = provider.raw; @@ -117,6 +118,9 @@ class Trade extends HiveObject { @HiveField(20) bool? isRefund; + @HiveField(21) + bool? isSendAll; + static Trade fromMap(Map map) { return Trade( id: map['id'] as String, @@ -130,8 +134,8 @@ class Trade extends HiveObject { fromWalletAddress: map['from_wallet_address'] as String?, memo: map['memo'] as String?, txId: map['tx_id'] as String?, - isRefund: map['isRefund'] as bool? - ); + isRefund: map['isRefund'] as bool?, + isSendAll: map['isSendAll'] as bool?); } Map toMap() { @@ -146,7 +150,8 @@ class Trade extends HiveObject { 'from_wallet_address': fromWalletAddress, 'memo': memo, 'tx_id': txId, - 'isRefund': isRefund + 'isRefund': isRefund, + 'isSendAll': isSendAll, }; } diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index d8e5a6a4a..d9e119038 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -186,7 +186,13 @@ class ExchangePage extends BasePage { StandardCheckbox( value: exchangeViewModel.isFixedRateMode, caption: S.of(context).fixed_rate, - onChanged: (value) => exchangeViewModel.isFixedRateMode = value, + onChanged: (value) { + if (value) { + exchangeViewModel.enableFixedRateMode(); + } else { + exchangeViewModel.isFixedRateMode = false; + } + }, ), ], )), @@ -528,7 +534,7 @@ class ExchangePage extends BasePage { _receiveAmountFocus.addListener(() { if (_receiveAmountFocus.hasFocus) { - exchangeViewModel.isFixedRateMode = true; + exchangeViewModel.enableFixedRateMode(); } // exchangeViewModel.changeReceiveAmount(amount: receiveAmountController.text); }); diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index c4dcae32c..4d3334f9f 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -262,6 +262,7 @@ class ExchangeTradeState extends State { fee: S.of(popupContext).send_fee, feeValue: widget.exchangeTradeViewModel.sendViewModel .pendingTransaction!.feeFormatted, + feeRate: widget.exchangeTradeViewModel.sendViewModel.pendingTransaction!.feeRate, rightButtonText: S.of(popupContext).send, leftButtonText: S.of(popupContext).cancel, actionRightButton: () async { diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index a4c095739..56b1b7af7 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -426,6 +426,7 @@ class SendPage extends BasePage { fee: isEVMCompatibleChain(sendViewModel.walletType) ? S.of(_dialogContext).send_estimated_fee : S.of(_dialogContext).send_fee, + feeRate: sendViewModel.pendingTransaction!.feeRate, feeValue: sendViewModel.pendingTransaction!.feeFormatted, feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted, outputs: sendViewModel.outputs, diff --git a/lib/src/screens/send/widgets/confirm_sending_alert.dart b/lib/src/screens/send/widgets/confirm_sending_alert.dart index 87d00ce0f..ce711ce8b 100644 --- a/lib/src/screens/send/widgets/confirm_sending_alert.dart +++ b/lib/src/screens/send/widgets/confirm_sending_alert.dart @@ -16,6 +16,7 @@ class ConfirmSendingAlert extends BaseAlertDialog { required this.amountValue, required this.fiatAmountValue, required this.fee, + this.feeRate, required this.feeValue, required this.feeFiatAmount, required this.outputs, @@ -36,6 +37,7 @@ class ConfirmSendingAlert extends BaseAlertDialog { final String amountValue; final String fiatAmountValue; final String fee; + final String? feeRate; final String feeValue; final String feeFiatAmount; final List outputs; @@ -90,6 +92,7 @@ class ConfirmSendingAlert extends BaseAlertDialog { amountValue: amountValue, fiatAmountValue: fiatAmountValue, fee: fee, + feeRate: feeRate, feeValue: feeValue, feeFiatAmount: feeFiatAmount, outputs: outputs); @@ -103,6 +106,7 @@ class ConfirmSendingAlertContent extends StatefulWidget { required this.amountValue, required this.fiatAmountValue, required this.fee, + this.feeRate, required this.feeValue, required this.feeFiatAmount, required this.outputs}); @@ -113,6 +117,7 @@ class ConfirmSendingAlertContent extends StatefulWidget { final String amountValue; final String fiatAmountValue; final String fee; + final String? feeRate; final String feeValue; final String feeFiatAmount; final List outputs; @@ -125,6 +130,7 @@ class ConfirmSendingAlertContent extends StatefulWidget { amountValue: amountValue, fiatAmountValue: fiatAmountValue, fee: fee, + feeRate: feeRate, feeValue: feeValue, feeFiatAmount: feeFiatAmount, outputs: outputs); @@ -138,6 +144,7 @@ class ConfirmSendingAlertContentState extends State required this.amountValue, required this.fiatAmountValue, required this.fee, + this.feeRate, required this.feeValue, required this.feeFiatAmount, required this.outputs}) @@ -153,6 +160,7 @@ class ConfirmSendingAlertContentState extends State final String amountValue; final String fiatAmountValue; final String fee; + final String? feeRate; final String feeValue; final String feeFiatAmount; final List outputs; @@ -183,7 +191,7 @@ class ConfirmSendingAlertContentState extends State return Stack(alignment: Alignment.center, clipBehavior: Clip.none, children: [ Container( - height: 200, + height: feeRate != null ? 250 : 200, child: SingleChildScrollView( controller: controller, child: Column( @@ -311,6 +319,36 @@ class ConfirmSendingAlertContentState extends State ) ], )), + if (feeRate != null && feeRate!.isNotEmpty) + Padding( + padding: EdgeInsets.only(top: 16), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + S.current.send_estimated_fee, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.normal, + fontFamily: 'Lato', + color: Theme.of(context).extension()!.titleColor, + decoration: TextDecoration.none, + ), + ), + Text( + "$feeRate sat/byte", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + fontFamily: 'Lato', + color: Theme.of(context).extension()!.titleColor, + decoration: TextDecoration.none, + ), + ) + ], + )), Padding( padding: EdgeInsets.only(top: 16), child: Column( 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 36cbda641..70ae7ce3f 100644 --- a/lib/src/screens/unspent_coins/unspent_coins_list_page.dart +++ b/lib/src/screens/unspent_coins/unspent_coins_list_page.dart @@ -46,9 +46,6 @@ class UnspentCoinsListFormState extends State { itemBuilder: (_, int index) { return Observer(builder: (_) { final item = unspentCoinsListViewModel.items[index]; - final address = unspentCoinsListViewModel.wallet.type == WalletType.bitcoinCash - ? bitcoinCash!.getCashAddrFormat(item.address) - : item.address; return GestureDetector( onTap: () => Navigator.of(context).pushNamed(Routes.unspentCoinsDetails, @@ -56,7 +53,7 @@ class UnspentCoinsListFormState extends State { child: UnspentCoinsListItem( note: item.note, amount: item.amount, - address: address, + address: item.address, isSending: item.isSending, isFrozen: item.isFrozen, isChange: item.isChange, diff --git a/lib/view_model/contact_list/contact_list_view_model.dart b/lib/view_model/contact_list/contact_list_view_model.dart index b53b67c43..6c3169be1 100644 --- a/lib/view_model/contact_list/contact_list_view_model.dart +++ b/lib/view_model/contact_list/contact_list_view_model.dart @@ -46,6 +46,8 @@ abstract class ContactListViewModelBase with Store { name, walletTypeToCryptoCurrency(info.type), )); + // Only one contact address per wallet + return; }); } else if (info.address != null) { walletContacts.add(WalletContact( diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index 3eb07460b..9bd9ef913 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -105,6 +105,7 @@ abstract class ExchangeTradeViewModelBase with Store { output.address = trade.inputAddress ?? ''; output.setCryptoAmount(trade.amount); if (_provider is ThorChainExchangeProvider) output.memo = trade.memo; + if (trade.isSendAll == true) output.sendAll = true; sendViewModel.selectedCryptoCurrency = trade.from; final pendingTransaction = await sendViewModel.createTransaction(provider: _provider); if (_provider is ThorChainExchangeProvider) { @@ -116,6 +117,8 @@ abstract class ExchangeTradeViewModelBase with Store { @action Future _updateTrade() async { try { + final agreedAmount = tradesStore.trade!.amount; + final isSendAll = tradesStore.trade!.isSendAll; final updatedTrade = await _provider!.findTradeById(id: trade.id); if (updatedTrade.createdAt == null && trade.createdAt != null) @@ -124,6 +127,8 @@ abstract class ExchangeTradeViewModelBase with Store { if (updatedTrade.amount.isEmpty) updatedTrade.amount = trade.amount; trade = updatedTrade; + trade.amount = agreedAmount; + trade.isSendAll = isSendAll; _updateItems(); } catch (e) { @@ -137,9 +142,9 @@ abstract class ExchangeTradeViewModelBase with Store { final tagTo = tradesStore.trade!.to.tag != null ? '${tradesStore.trade!.to.tag}' + ' ' : ''; items.clear(); - if(trade.provider != ExchangeProviderDescription.thorChain) - items.add(ExchangeTradeItem( - title: "${trade.provider.title} ${S.current.id}", data: '${trade.id}', isCopied: true)); + if (trade.provider != ExchangeProviderDescription.thorChain) + items.add(ExchangeTradeItem( + title: "${trade.provider.title} ${S.current.id}", data: '${trade.id}', isCopied: true)); if (trade.extraId != null) { final title = trade.from == CryptoCurrency.xrp diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 01ac8e942..eba347ac4 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -470,6 +470,18 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with @action Future createTrade() async { + if (isSendAllEnabled) { + await calculateDepositAllAmount(); + final amount = double.tryParse(depositAmount); + + if (limits.min != null && amount != null && amount < limits.min!) { + tradeState = TradeIsCreatedFailure( + title: S.current.trade_not_created, + error: S.current.amount_is_below_minimum_limit(limits.min!.toString())); + return; + } + } + try { for (var provider in _sortedAvailableProviders.values) { if (!(await provider.checkIsAvailable())) continue; @@ -496,8 +508,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with else { try { tradeState = TradeIsCreating(); - final trade = - await provider.createTrade(request: request, isFixedRateMode: isFixedRateMode); + final trade = await provider.createTrade( + request: request, + isFixedRateMode: isFixedRateMode, + isSendAll: isSendAllEnabled, + ); trade.walletId = wallet.id; trade.fromWalletAddress = wallet.walletAddresses.address; @@ -551,25 +566,24 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with @action void enableSendAllAmount() { isSendAllEnabled = true; + isFixedRateMode = false; calculateDepositAllAmount(); } + @action + void enableFixedRateMode() { + isSendAllEnabled = false; + isFixedRateMode = true; + } + @action Future calculateDepositAllAmount() async { - if (wallet.type == WalletType.litecoin || wallet.type == WalletType.bitcoinCash) { - final availableBalance = wallet.balance[wallet.currency]!.available; - final priority = _settingsStore.priority[wallet.type]!; - final fee = wallet.calculateEstimatedFee(priority, null); - - if (availableBalance < fee || availableBalance == 0) return; - - final amount = availableBalance - fee; - changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount)); - } else if (wallet.type == WalletType.bitcoin) { + if (wallet.type == WalletType.litecoin || + wallet.type == WalletType.bitcoin || + wallet.type == WalletType.bitcoinCash) { final priority = _settingsStore.priority[wallet.type]!; - final amount = await bitcoin!.estimateFakeSendAllTxAmount( - wallet, bitcoin!.deserializeBitcoinTransactionPriority(priority.raw)); + final amount = await bitcoin!.estimateFakeSendAllTxAmount(wallet, priority); changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount)); } diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 451f2210d..28f964a9c 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -14,6 +14,7 @@ import 'package:cake_wallet/solana/solana.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; +import 'package:cw_core/exceptions.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cake_wallet/view_model/send/send_template_view_model.dart'; @@ -309,9 +310,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor state = ExecutedSuccessfullyState(); return pendingTransaction; } catch (e) { - print('Failed with ${e.toString()}'); - state = FailureState(e.toString()); - return null; + state = FailureState(translateErrorMessage(e, wallet.type, wallet.currency)); } } @@ -353,8 +352,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor state = TransactionCommitted(); } catch (e) { - String translatedError = translateErrorMessage(e.toString(), wallet.type, wallet.currency); - state = FailureState(translatedError); + state = FailureState(translateErrorMessage(e, wallet.type, wallet.currency)); } } @@ -429,11 +427,10 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor } } - ContactRecord? newContactAddress () { - + ContactRecord? newContactAddress() { final Set contactAddresses = - Set.from(contactListViewModel.contacts.map((contact) => contact.address)) - ..addAll(contactListViewModel.walletContacts.map((contact) => contact.address)); + Set.from(contactListViewModel.contacts.map((contact) => contact.address)) + ..addAll(contactListViewModel.walletContacts.map((contact) => contact.address)); for (var output in outputs) { String address; @@ -444,7 +441,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor } if (address.isNotEmpty && !contactAddresses.contains(address)) { - return ContactRecord( contactListViewModel.contactSource, Contact( @@ -458,22 +454,59 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor } String translateErrorMessage( - String error, + Object error, WalletType walletType, CryptoCurrency currency, ) { + String errorMessage = error.toString(); + if (walletType == WalletType.ethereum || walletType == WalletType.polygon || walletType == WalletType.solana || walletType == WalletType.haven) { - if (error.contains('gas required exceeds allowance') || - error.contains('insufficient funds')) { + if (errorMessage.contains('gas required exceeds allowance') || + errorMessage.contains('insufficient funds')) { return S.current.do_not_have_enough_gas_asset(currency.toString()); } - return error; + return errorMessage; } - return error; + if (walletType == WalletType.bitcoin || + walletType == WalletType.litecoin || + walletType == WalletType.bitcoinCash) { + if (error is TransactionWrongBalanceException) { + return S.current.tx_wrong_balance_exception(currency.toString()); + } + if (error is TransactionNoInputsException) { + return S.current.tx_not_enough_inputs_exception; + } + if (error is TransactionNoFeeException) { + return S.current.tx_zero_fee_exception; + } + if (error is TransactionNoDustException) { + return S.current.tx_no_dust_exception; + } + if (error is TransactionCommitFailed) { + return S.current.tx_commit_failed; + } + if (error is TransactionCommitFailedDustChange) { + return S.current.tx_rejected_dust_change; + } + if (error is TransactionCommitFailedDustOutput) { + return S.current.tx_rejected_dust_output; + } + if (error is TransactionCommitFailedDustOutputSendAll) { + return S.current.tx_rejected_dust_output_send_all; + } + if (error is TransactionCommitFailedVoutNegative) { + return S.current.tx_rejected_vout_negative; + } + if (error is TransactionNoDustOnChangeException) { + return S.current.tx_commit_exception_no_dust_on_change(error.min, error.max); + } + } + + return errorMessage; } } diff --git a/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart b/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart index 4da43c241..fd142dd33 100644 --- a/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart +++ b/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart @@ -100,7 +100,5 @@ abstract class UnspentCoinsDetailsViewModelBase with Store { final WalletType _type; List items; - String get formattedAddress => WalletType.bitcoinCash == _type - ? bitcoinCash!.getCashAddrFormat(unspentCoinsItem.address) - : unspentCoinsItem.address; + String get formattedAddress => unspentCoinsItem.address; } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 44d55e0ed..d4d0d664d 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -43,6 +43,7 @@ "already_have_account": "لديك حساب؟", "always": "دائماً", "amount": "مقدار:", + "amount_is_below_minimum_limit": "سيكون رصيدك بعد الرسوم أقل من الحد الأدنى للمبلغ اللازم للتبادل (${min})", "amount_is_estimate": "المبلغ المستلم هو تقدير", "amount_is_guaranteed": "مبلغ الاستلام مضمون", "and": "و", @@ -712,6 +713,16 @@ "transactions": "المعاملات", "transactions_by_date": "المعاملات حسب التاريخ", "trusted": "موثوق به", + "tx_commit_exception_no_dust_on_change": "يتم رفض المعاملة مع هذا المبلغ. باستخدام هذه العملات المعدنية ، يمكنك إرسال ${min} دون تغيير أو ${max} الذي يعيد التغيير.", + "tx_commit_failed": "فشل ارتكاب المعاملة. يرجى الاتصال بالدعم.", + "tx_no_dust_exception": "يتم رفض المعاملة عن طريق إرسال مبلغ صغير جدًا. يرجى محاولة زيادة المبلغ.", + "tx_not_enough_inputs_exception": "لا يكفي المدخلات المتاحة. الرجاء تحديد المزيد تحت التحكم في العملة", + "tx_rejected_dust_change": "المعاملة التي يتم رفضها بموجب قواعد الشبكة ، ومبلغ التغيير المنخفض (الغبار). حاول إرسال كل أو تقليل المبلغ.", + "tx_rejected_dust_output": "المعاملة التي يتم رفضها بموجب قواعد الشبكة ، وكمية الإخراج المنخفض (الغبار). يرجى زيادة المبلغ.", + "tx_rejected_dust_output_send_all": "المعاملة التي يتم رفضها بموجب قواعد الشبكة ، وكمية الإخراج المنخفض (الغبار). يرجى التحقق من رصيد العملات المعدنية المحددة تحت التحكم في العملة.", + "tx_rejected_vout_negative": "لا يوجد ما يكفي من الرصيد لدفع رسوم هذه الصفقة. يرجى التحقق من رصيد العملات المعدنية تحت السيطرة على العملة.", + "tx_wrong_balance_exception": "ليس لديك ما يكفي من ${currency} لإرسال هذا المبلغ.", + "tx_zero_fee_exception": "لا يمكن إرسال معاملة مع 0 رسوم. حاول زيادة المعدل أو التحقق من اتصالك للحصول على أحدث التقديرات.", "unavailable_balance": "ﺮﻓﻮﺘﻣ ﺮﻴﻏ ﺪﻴﺻﺭ", "unavailable_balance_description": ".ﺎﻫﺪﻴﻤﺠﺗ ءﺎﻐﻟﺇ ﺭﺮﻘﺗ ﻰﺘﺣ ﺕﻼﻣﺎﻌﻤﻠﻟ ﻝﻮﺻﻮﻠﻟ ﺔﻠﺑﺎﻗ ﺮﻴﻏ ﺓﺪﻤﺠﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﻞﻈﺗ ﺎﻤﻨﻴﺑ ،ﺎﻬﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻣﺎﻌﻤﻟﺍ ﻝﺎﻤﺘﻛﺍ ﺩﺮﺠﻤﺑ ﺔﺣﺎﺘﻣ ﺔﻠﻔﻘﻤﻟﺍ ﺓﺪﺻﺭﻷﺍ ﺢﺒﺼﺘﺳ .ﻚﺑ ﺔﺻﺎﺨﻟﺍ ﺕﻼﻤﻌﻟﺍ ﻲﻓ ﻢﻜﺤﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻂﺸﻧ ﻞﻜﺸﺑ ﺎﻫﺪﻴﻤﺠﺘﺑ ﺖﻤﻗ", "unconfirmed": "رصيد غير مؤكد", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 1817b1807..6fe29a1a6 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -43,6 +43,7 @@ "already_have_account": "Вече имате профил?", "always": "Винаги", "amount": "Сума: ", + "amount_is_below_minimum_limit": "Вашето салдо след такси ще бъде по -малко от минималната сума, необходима за борсата (${min})", "amount_is_estimate": "Сумата за получаване е ", "amount_is_guaranteed": "Сумата за получаване е гарантирана", "and": "и", @@ -712,6 +713,16 @@ "transactions": "Транзакции", "transactions_by_date": "Транзакции по дата", "trusted": "Надежден", + "tx_commit_exception_no_dust_on_change": "Сделката се отхвърля с тази сума. С тези монети можете да изпратите ${min} без промяна или ${max}, която връща промяна.", + "tx_commit_failed": "Компетацията на транзакцията не успя. Моля, свържете се с поддръжката.", + "tx_no_dust_exception": "Сделката се отхвърля чрез изпращане на сума твърде малка. Моля, опитайте да увеличите сумата.", + "tx_not_enough_inputs_exception": "Няма достатъчно налични входове. Моля, изберете повече под контрол на монети", + "tx_rejected_dust_change": "Транзакция, отхвърлена от мрежови правила, ниска сума на промяна (прах). Опитайте да изпратите всички или да намалите сумата.", + "tx_rejected_dust_output": "Транзакция, отхвърлена от мрежови правила, ниска стойност на изхода (прах). Моля, увеличете сумата.", + "tx_rejected_dust_output_send_all": "Транзакция, отхвърлена от мрежови правила, ниска стойност на изхода (прах). Моля, проверете баланса на монетите, избрани под контрол на монети.", + "tx_rejected_vout_negative": "Няма достатъчно баланс, за да платите за таксите на тази транзакция. Моля, проверете баланса на монетите под контрол на монетите.", + "tx_wrong_balance_exception": "Нямате достатъчно ${currency}, за да изпратите тази сума.", + "tx_zero_fee_exception": "Не може да изпраща транзакция с 0 такса. Опитайте да увеличите скоростта или да проверите връзката си за най -новите оценки.", "unavailable_balance": "Неналично салдо", "unavailable_balance_description": "Неналично салдо: Тази обща сума включва средства, които са заключени в чакащи транзакции и тези, които сте замразили активно в настройките за контрол на монетите. Заключените баланси ще станат достъпни, след като съответните им транзакции бъдат завършени, докато замразените баланси остават недостъпни за транзакции, докато не решите да ги размразите.", "unconfirmed": "Непотвърден баланс", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 9bd416f45..a346f9494 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -43,6 +43,7 @@ "already_have_account": "Máte už účet?", "always": "Vždy", "amount": "Částka: ", + "amount_is_below_minimum_limit": "Váš zůstatek po poplatcích by byl menší než minimální částka potřebná pro burzu (${min})", "amount_is_estimate": "Částka, kterou dostanete, je jen odhad.", "amount_is_guaranteed": "Částka, kterou dostanete, je konečná", "and": "a", @@ -712,6 +713,16 @@ "transactions": "Transakce", "transactions_by_date": "Transakce podle data", "trusted": "Důvěřovat", + "tx_commit_exception_no_dust_on_change": "Transakce je zamítnuta s touto částkou. S těmito mincemi můžete odeslat ${min} bez změny nebo ${max}, které se vrátí změna.", + "tx_commit_failed": "Transakce COMPORT selhala. Kontaktujte prosím podporu.", + "tx_no_dust_exception": "Transakce je zamítnuta odesláním příliš malé. Zkuste prosím zvýšit částku.", + "tx_not_enough_inputs_exception": "Není k dispozici dostatek vstupů. Vyberte prosím více pod kontrolou mincí", + "tx_rejected_dust_change": "Transakce zamítnuta podle síťových pravidel, množství nízké změny (prach). Zkuste odeslat vše nebo snížit částku.", + "tx_rejected_dust_output": "Transakce zamítnuta síťovými pravidly, nízkým množstvím výstupu (prach). Zvyšte prosím částku.", + "tx_rejected_dust_output_send_all": "Transakce zamítnuta síťovými pravidly, nízkým množstvím výstupu (prach). Zkontrolujte prosím zůstatek mincí vybraných pod kontrolou mincí.", + "tx_rejected_vout_negative": "Nedostatek zůstatek na zaplacení poplatků za tuto transakci. Zkontrolujte prosím zůstatek mincí pod kontrolou mincí.", + "tx_wrong_balance_exception": "Nemáte dost ${currency} pro odeslání této částky.", + "tx_zero_fee_exception": "Nelze odeslat transakci s 0 poplatkem. Zkuste zvýšit sazbu nebo zkontrolovat připojení pro nejnovější odhady.", "unavailable_balance": "Nedostupný zůstatek", "unavailable_balance_description": "Nedostupný zůstatek: Tento součet zahrnuje prostředky, které jsou uzamčeny v nevyřízených transakcích a ty, které jste aktivně zmrazili v nastavení kontroly mincí. Uzamčené zůstatky budou k dispozici po dokončení příslušných transakcí, zatímco zmrazené zůstatky zůstanou pro transakce nepřístupné, dokud se nerozhodnete je uvolnit.", "unconfirmed": "Nepotvrzený zůstatek", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 109df5ef2..47375cedf 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -43,6 +43,7 @@ "already_have_account": "Sie haben bereits ein Konto?", "always": "immer", "amount": "Betrag: ", + "amount_is_below_minimum_limit": "Ihr Saldo nach Gebühren wäre geringer als der für den Austausch benötigte Mindestbetrag (${min})", "amount_is_estimate": "Der empfangene Betrag ist eine Schätzung", "amount_is_guaranteed": "Der Empfangsbetrag ist garantiert", "and": "Und", @@ -713,6 +714,16 @@ "transactions": "Transaktionen", "transactions_by_date": "Transaktionen nach Datum", "trusted": "Vertrauenswürdige", + "tx_commit_exception_no_dust_on_change": "Die Transaktion wird diesen Betrag abgelehnt. Mit diesen Münzen können Sie ${min} ohne Veränderung oder ${max} senden, die Änderungen zurückgeben.", + "tx_commit_failed": "Transaktionsausschüsse ist fehlgeschlagen. Bitte wenden Sie sich an Support.", + "tx_no_dust_exception": "Die Transaktion wird abgelehnt, indem eine Menge zu klein gesendet wird. Bitte versuchen Sie, die Menge zu erhöhen.", + "tx_not_enough_inputs_exception": "Nicht genügend Eingänge verfügbar. Bitte wählen Sie mehr unter Münzkontrolle aus", + "tx_rejected_dust_change": "Transaktion abgelehnt durch Netzwerkregeln, niedriger Änderungsbetrag (Staub). Versuchen Sie, alle zu senden oder die Menge zu reduzieren.", + "tx_rejected_dust_output": "Transaktion durch Netzwerkregeln, niedriger Ausgangsmenge (Staub) abgelehnt. Bitte erhöhen Sie den Betrag.", + "tx_rejected_dust_output_send_all": "Transaktion durch Netzwerkregeln, niedriger Ausgangsmenge (Staub) abgelehnt. Bitte überprüfen Sie den Gleichgewicht der unter Münzkontrolle ausgewählten Münzen.", + "tx_rejected_vout_negative": "Nicht genug Guthaben, um die Gebühren dieser Transaktion zu bezahlen. Bitte überprüfen Sie den Restbetrag der Münzen unter Münzkontrolle.", + "tx_wrong_balance_exception": "Sie haben nicht genug ${currency}, um diesen Betrag zu senden.", + "tx_zero_fee_exception": "Transaktion kann nicht mit 0 Gebühren gesendet werden. Versuchen Sie, die Rate zu erhöhen oder Ihre Verbindung auf die neuesten Schätzungen zu überprüfen.", "unavailable_balance": "Nicht verfügbares Guthaben", "unavailable_balance_description": "Nicht verfügbares Guthaben: Diese Summe umfasst Gelder, die in ausstehenden Transaktionen gesperrt sind, und solche, die Sie in Ihren Münzkontrolleinstellungen aktiv eingefroren haben. Gesperrte Guthaben werden verfügbar, sobald die entsprechenden Transaktionen abgeschlossen sind, während eingefrorene Guthaben für Transaktionen nicht zugänglich bleiben, bis Sie sich dazu entschließen, sie wieder freizugeben.", "unconfirmed": "Unbestätigter Saldo", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index f9e67d475..837033429 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -43,6 +43,7 @@ "already_have_account": "Already have an account?", "always": "Always", "amount": "Amount: ", + "amount_is_below_minimum_limit": "Your balance after fees would be less than the minimum amount needed for the exchange (${min})", "amount_is_estimate": "The receive amount is an estimate", "amount_is_guaranteed": "The receive amount is guaranteed", "and": "and", @@ -712,6 +713,16 @@ "transactions": "Transactions", "transactions_by_date": "Transactions by date", "trusted": "Trusted", + "tx_commit_exception_no_dust_on_change": "The transaction is rejected with this amount. With these coins you can send ${min} without change or ${max} that returns change.", + "tx_commit_failed": "Transaction commit failed. Please contact support.", + "tx_no_dust_exception": "The transaction is rejected by sending an amount too small. Please try increasing the amount.", + "tx_not_enough_inputs_exception": "Not enough inputs available. Please select more under Coin Control", + "tx_rejected_dust_change": "Transaction rejected by network rules, low change amount (dust). Try sending ALL or reducing the amount.", + "tx_rejected_dust_output": "Transaction rejected by network rules, low output amount (dust). Please increase the amount.", + "tx_rejected_dust_output_send_all": "Transaction rejected by network rules, low output amount (dust). Please check the balance of coins selected under Coin Control.", + "tx_rejected_vout_negative": "Not enough balance to pay for this transaction's fees. Please check the balance of coins under Coin Control.", + "tx_wrong_balance_exception": "You do not have enough ${currency} to send this amount.", + "tx_zero_fee_exception": "Cannot send transaction with 0 fee. Try increasing the rate or checking your connection for latest estimates.", "unavailable_balance": "Unavailable balance", "unavailable_balance_description": "Unavailable Balance: This total includes funds that are locked in pending transactions and those you have actively frozen in your coin control settings. Locked balances will become available once their respective transactions are completed, while frozen balances remain inaccessible for transactions until you decide to unfreeze them.", "unconfirmed": "Unconfirmed Balance", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index f84f892dd..b3afbd3a7 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -43,6 +43,7 @@ "already_have_account": "¿Ya tienes una cuenta?", "always": "siempre", "amount": "Cantidad: ", + "amount_is_below_minimum_limit": "Su saldo después de las tarifas sería menor que la cantidad mínima necesaria para el intercambio (${min})", "amount_is_estimate": "El monto recibido es un estimado", "amount_is_guaranteed": "La cantidad recibida está garantizada", "and": "y", @@ -713,6 +714,16 @@ "transactions": "Actas", "transactions_by_date": "Transacciones por fecha", "trusted": "de confianza", + "tx_commit_exception_no_dust_on_change": "La transacción se rechaza con esta cantidad. Con estas monedas puede enviar ${min} sin cambios o ${max} que devuelve el cambio.", + "tx_commit_failed": "La confirmación de transacción falló. Póngase en contacto con el soporte.", + "tx_no_dust_exception": "La transacción se rechaza enviando una cantidad demasiado pequeña. Intente aumentar la cantidad.", + "tx_not_enough_inputs_exception": "No hay suficientes entradas disponibles. Seleccione más bajo control de monedas", + "tx_rejected_dust_change": "Transacción rechazada por reglas de red, bajo cambio de cambio (polvo). Intente enviar todo o reducir la cantidad.", + "tx_rejected_dust_output": "Transacción rechazada por reglas de red, baja cantidad de salida (polvo). Aumente la cantidad.", + "tx_rejected_dust_output_send_all": "Transacción rechazada por reglas de red, baja cantidad de salida (polvo). Verifique el saldo de monedas seleccionadas bajo control de monedas.", + "tx_rejected_vout_negative": "No es suficiente saldo para pagar las tarifas de esta transacción. Verifique el saldo de monedas bajo control de monedas.", + "tx_wrong_balance_exception": "No tiene suficiente ${currency} para enviar esta cantidad.", + "tx_zero_fee_exception": "No se puede enviar transacciones con 0 tarifa. Intente aumentar la tasa o verificar su conexión para las últimas estimaciones.", "unavailable_balance": "Saldo no disponible", "unavailable_balance_description": "Saldo no disponible: este total incluye fondos que están bloqueados en transacciones pendientes y aquellos que usted ha congelado activamente en su configuración de control de monedas. Los saldos bloqueados estarán disponibles una vez que se completen sus respectivas transacciones, mientras que los saldos congelados permanecerán inaccesibles para las transacciones hasta que usted decida descongelarlos.", "unconfirmed": "Saldo no confirmado", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 048b97f66..2a62d351d 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -43,6 +43,7 @@ "already_have_account": "Vous avez déjà un compte ?", "always": "toujours", "amount": "Montant : ", + "amount_is_below_minimum_limit": "Votre solde après les frais serait inférieur au montant minimum nécessaire à l'échange (${min})", "amount_is_estimate": "Le montant reçu est estimé", "amount_is_guaranteed": "Le montant reçu est garanti", "and": "et", @@ -712,6 +713,16 @@ "transactions": "Transactions", "transactions_by_date": "Transactions par date", "trusted": "de confiance", + "tx_commit_exception_no_dust_on_change": "La transaction est rejetée avec ce montant. Avec ces pièces, vous pouvez envoyer ${min} sans changement ou ${max} qui renvoie le changement.", + "tx_commit_failed": "La validation de la transaction a échoué. Veuillez contacter l'assistance.", + "tx_no_dust_exception": "La transaction est rejetée en envoyant un montant trop faible. Veuillez essayer d'augmenter le montant.", + "tx_not_enough_inputs_exception": "Pas assez d'entrées disponibles. Veuillez sélectionner plus sous Control Control", + "tx_rejected_dust_change": "Transaction rejetée par les règles du réseau, montant de faible variation (poussière). Essayez d'envoyer tout ou de réduire le montant.", + "tx_rejected_dust_output": "Transaction rejetée par les règles du réseau, faible quantité de sortie (poussière). Veuillez augmenter le montant.", + "tx_rejected_dust_output_send_all": "Transaction rejetée par les règles du réseau, faible quantité de sortie (poussière). Veuillez vérifier le solde des pièces sélectionnées sous le contrôle des pièces de monnaie.", + "tx_rejected_vout_negative": "Pas assez de solde pour payer les frais de cette transaction. Veuillez vérifier le solde des pièces sous le contrôle des pièces.", + "tx_wrong_balance_exception": "Vous n'avez pas assez ${currency} pour envoyer ce montant.", + "tx_zero_fee_exception": "Impossible d'envoyer une transaction avec 0 frais. Essayez d'augmenter le taux ou de vérifier votre connexion pour les dernières estimations.", "unavailable_balance": "Solde indisponible", "unavailable_balance_description": "Solde indisponible : ce total comprend les fonds bloqués dans les transactions en attente et ceux que vous avez activement gelés dans vos paramètres de contrôle des pièces. Les soldes bloqués deviendront disponibles une fois leurs transactions respectives terminées, tandis que les soldes gelés resteront inaccessibles aux transactions jusqu'à ce que vous décidiez de les débloquer.", "unconfirmed": "Solde non confirmé", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 4eadc6333..1e18fb692 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -43,6 +43,7 @@ "already_have_account": "Kuna da asusu?", "always": "Koyaushe", "amount": "Adadi:", + "amount_is_below_minimum_limit": "Daidaitarku bayan kudade zai zama ƙasa da mafi ƙarancin adadin da ake buƙata don musayar (${min}", "amount_is_estimate": "Adadin da aka karɓa shine kimantawa", "amount_is_guaranteed": "Adadin da aka karɓa yana da garanti", "and": "kuma", @@ -714,6 +715,16 @@ "transactions": "Ma'amaloli", "transactions_by_date": "Ma'amaloli ta kwanan wata", "trusted": "Amintacce", + "tx_commit_exception_no_dust_on_change": "An ƙi ma'amala da wannan adadin. Tare da waɗannan tsabar kudi Zaka iya aika ${min}, ba tare da canji ba ko ${max} wanda ya dawo canzawa.", + "tx_commit_failed": "Ma'amala ya kasa. Da fatan za a tuntuɓi goyan baya.", + "tx_no_dust_exception": "An ƙi ma'amala ta hanyar aika adadin ƙarami. Da fatan za a gwada ƙara adadin.", + "tx_not_enough_inputs_exception": "Bai isa ba hanyoyin da ake samu. Da fatan za selectiari a karkashin Kwarewar Coin", + "tx_rejected_dust_change": "Ma'amala ta ƙi ta dokokin cibiyar sadarwa, ƙarancin canji (ƙura). Gwada aikawa da duka ko rage adadin.", + "tx_rejected_dust_output": "Ma'adar da aka ƙi ta dokokin cibiyar sadarwa, ƙananan fitarwa (ƙura). Da fatan za a ƙara adadin.", + "tx_rejected_dust_output_send_all": "Ma'adar da aka ƙi ta dokokin cibiyar sadarwa, ƙananan fitarwa (ƙura). Da fatan za a duba daidaiton tsabar kudi a ƙarƙashin ikon tsabar kudin.", + "tx_rejected_vout_negative": "Bai isa daidai ba don biyan wannan kudin ma'amala. Da fatan za a duba daidaiton tsabar kudi a ƙarƙashin ikon tsabar kudin.", + "tx_wrong_balance_exception": "Ba ku da isasshen ${currency} don aika wannan adadin.", + "tx_zero_fee_exception": "Ba zai iya aika ma'amala da kuɗi 0 ba. Gwada ƙara ƙimar ko bincika haɗin ku don mahimmin ƙididdiga.", "unavailable_balance": "Ma'aunin da ba ya samuwa", "unavailable_balance_description": "Ma'auni Babu: Wannan jimlar ya haɗa da kuɗi waɗanda ke kulle a cikin ma'amaloli da ke jiran aiki da waɗanda kuka daskare sosai a cikin saitunan sarrafa kuɗin ku. Ma'auni da aka kulle za su kasance da zarar an kammala ma'amalolinsu, yayin da daskararrun ma'auni ba za su iya samun damar yin ciniki ba har sai kun yanke shawarar cire su.", "unconfirmed": "Ba a tabbatar ba", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 500df31f7..b1ef9e4a2 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -43,6 +43,7 @@ "already_have_account": "क्या आपके पास पहले से एक खाता मौजूद है?", "always": "हमेशा", "amount": "रकम: ", + "amount_is_below_minimum_limit": "फीस के बाद आपका संतुलन विनिमय के लिए आवश्यक न्यूनतम राशि से कम होगा (${min})", "amount_is_estimate": "प्राप्त राशि एक अनुमान है", "amount_is_guaranteed": "प्राप्त राशि की गारंटी है", "and": "और", @@ -714,6 +715,16 @@ "transactions": "लेन-देन", "transactions_by_date": "तारीख से लेन-देन", "trusted": "भरोसा", + "tx_commit_exception_no_dust_on_change": "लेनदेन को इस राशि से खारिज कर दिया जाता है। इन सिक्कों के साथ आप चेंज या ${min} के बिना ${max} को भेज सकते हैं जो परिवर्तन लौटाता है।", + "tx_commit_failed": "लेन -देन प्रतिबद्ध विफल। कृपया संपर्क समर्थन करें।", + "tx_no_dust_exception": "लेनदेन को बहुत छोटी राशि भेजकर अस्वीकार कर दिया जाता है। कृपया राशि बढ़ाने का प्रयास करें।", + "tx_not_enough_inputs_exception": "पर्याप्त इनपुट उपलब्ध नहीं है। कृपया सिक्का नियंत्रण के तहत अधिक चुनें", + "tx_rejected_dust_change": "नेटवर्क नियमों, कम परिवर्तन राशि (धूल) द्वारा खारिज किए गए लेनदेन। सभी भेजने या राशि को कम करने का प्रयास करें।", + "tx_rejected_dust_output": "नेटवर्क नियमों, कम आउटपुट राशि (धूल) द्वारा खारिज किए गए लेनदेन। कृपया राशि बढ़ाएं।", + "tx_rejected_dust_output_send_all": "नेटवर्क नियमों, कम आउटपुट राशि (धूल) द्वारा खारिज किए गए लेनदेन। कृपया सिक्का नियंत्रण के तहत चुने गए सिक्कों के संतुलन की जाँच करें।", + "tx_rejected_vout_negative": "इस लेनदेन की फीस के लिए भुगतान करने के लिए पर्याप्त शेष राशि नहीं है। कृपया सिक्के नियंत्रण के तहत सिक्कों के संतुलन की जाँच करें।", + "tx_wrong_balance_exception": "इस राशि को भेजने के लिए आपके पास पर्याप्त ${currency} नहीं है।", + "tx_zero_fee_exception": "0 शुल्क के साथ लेनदेन नहीं भेज सकते। नवीनतम अनुमानों के लिए दर बढ़ाने या अपने कनेक्शन की जांच करने का प्रयास करें।", "unavailable_balance": "अनुपलब्ध शेष", "unavailable_balance_description": "अनुपलब्ध शेष राशि: इस कुल में वे धनराशि शामिल हैं जो लंबित लेनदेन में बंद हैं और जिन्हें आपने अपनी सिक्का नियंत्रण सेटिंग्स में सक्रिय रूप से जमा कर रखा है। लॉक किए गए शेष उनके संबंधित लेन-देन पूरे होने के बाद उपलब्ध हो जाएंगे, जबकि जमे हुए शेष लेन-देन के लिए अप्राप्य रहेंगे जब तक कि आप उन्हें अनफ्रीज करने का निर्णय नहीं लेते।", "unconfirmed": "अपुष्ट शेष राशि", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 9a6f74adb..55913f434 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -43,6 +43,7 @@ "already_have_account": "Već imate račun?", "always": "Uvijek", "amount": "Iznos: ", + "amount_is_below_minimum_limit": "Vaša bilanca nakon naknada bila bi manja od minimalnog iznosa potrebnog za razmjenu (${min})", "amount_is_estimate": "Iznos koji ćete primiti je okviran", "amount_is_guaranteed": "Iznos koji ćete primiti je zajamčen", "and": "i", @@ -712,6 +713,16 @@ "transactions": "Transakcije", "transactions_by_date": "Transakcije prema datumu", "trusted": "vjerovao", + "tx_commit_exception_no_dust_on_change": "Transakcija se odbija s tim iznosom. Pomoću ovih kovanica možete poslati ${min} bez promjene ili ${max} koja vraća promjenu.", + "tx_commit_failed": "Obveza transakcije nije uspjela. Molimo kontaktirajte podršku.", + "tx_no_dust_exception": "Transakcija se odbija slanjem iznosa premalo. Pokušajte povećati iznos.", + "tx_not_enough_inputs_exception": "Nema dovoljno unosa. Molimo odaberite više pod kontrolom novčića", + "tx_rejected_dust_change": "Transakcija odbijena mrežnim pravilima, niska količina promjene (prašina). Pokušajte poslati sve ili smanjiti iznos.", + "tx_rejected_dust_output": "Transakcija odbijena mrežnim pravilima, niska količina izlaza (prašina). Molimo povećajte iznos.", + "tx_rejected_dust_output_send_all": "Transakcija odbijena mrežnim pravilima, niska količina izlaza (prašina). Molimo provjerite ravnotežu kovanica odabranih pod kontrolom novčića.", + "tx_rejected_vout_negative": "Nema dovoljno salda za plaćanje naknada ove transakcije. Molimo provjerite ravnotežu kovanica pod kontrolom novčića.", + "tx_wrong_balance_exception": "Nemate dovoljno ${currency} da biste poslali ovaj iznos.", + "tx_zero_fee_exception": "Ne mogu poslati transakciju s 0 naknade. Pokušajte povećati stopu ili provjeriti vezu za najnovije procjene.", "unavailable_balance": "Nedostupno stanje", "unavailable_balance_description": "Nedostupno stanje: Ovaj ukupni iznos uključuje sredstva koja su zaključana u transakcijama na čekanju i ona koja ste aktivno zamrznuli u postavkama kontrole novčića. Zaključani saldi postat će dostupni kada se dovrše njihove transakcije, dok zamrznuti saldi ostaju nedostupni za transakcije sve dok ih ne odlučite odmrznuti.", "unconfirmed": "Nepotvrđeno stanje", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index b0c4276c3..8546e1f17 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -43,6 +43,7 @@ "already_have_account": "Sudah punya akun?", "always": "Selalu", "amount": "Jumlah: ", + "amount_is_below_minimum_limit": "Saldo Anda setelah biaya akan kurang dari jumlah minimum yang dibutuhkan untuk pertukaran (${min})", "amount_is_estimate": "Jumlah penerimaan diperkirakan", "amount_is_guaranteed": "Jumlah penerimaan dijamin", "and": "dan", @@ -715,6 +716,16 @@ "transactions": "Transaksi", "transactions_by_date": "Transaksi berdasarkan tanggal", "trusted": "Dipercayai", + "tx_commit_exception_no_dust_on_change": "Transaksi ditolak dengan jumlah ini. Dengan koin ini Anda dapat mengirim ${min} tanpa perubahan atau ${max} yang mengembalikan perubahan.", + "tx_commit_failed": "Transaksi Gagal. Silakan hubungi Dukungan.", + "tx_no_dust_exception": "Transaksi ditolak dengan mengirimkan jumlah yang terlalu kecil. Silakan coba tingkatkan jumlahnya.", + "tx_not_enough_inputs_exception": "Tidak cukup input yang tersedia. Pilih lebih banyak lagi di bawah Kontrol Koin", + "tx_rejected_dust_change": "Transaksi ditolak oleh aturan jaringan, jumlah perubahan rendah (debu). Coba kirim semua atau mengurangi jumlahnya.", + "tx_rejected_dust_output": "Transaksi ditolak oleh aturan jaringan, jumlah output rendah (debu). Harap tingkatkan jumlahnya.", + "tx_rejected_dust_output_send_all": "Transaksi ditolak oleh aturan jaringan, jumlah output rendah (debu). Silakan periksa saldo koin yang dipilih di bawah kontrol koin.", + "tx_rejected_vout_negative": "Tidak cukup saldo untuk membayar biaya transaksi ini. Silakan periksa saldo koin di bawah kendali koin.", + "tx_wrong_balance_exception": "Anda tidak memiliki cukup ${currency} untuk mengirim jumlah ini.", + "tx_zero_fee_exception": "Tidak dapat mengirim transaksi dengan biaya 0. Coba tingkatkan tarif atau periksa koneksi Anda untuk perkiraan terbaru.", "unavailable_balance": "Saldo tidak tersedia", "unavailable_balance_description": "Saldo Tidak Tersedia: Total ini termasuk dana yang terkunci dalam transaksi yang tertunda dan dana yang telah Anda bekukan secara aktif di pengaturan kontrol koin Anda. Saldo yang terkunci akan tersedia setelah transaksi masing-masing selesai, sedangkan saldo yang dibekukan tetap tidak dapat diakses untuk transaksi sampai Anda memutuskan untuk mencairkannya.", "unconfirmed": "Saldo Belum Dikonfirmasi", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index b96acc951..ef0ffecde 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -43,6 +43,7 @@ "already_have_account": "Hai già un account?", "always": "sempre", "amount": "Ammontare: ", + "amount_is_below_minimum_limit": "Il saldo dopo le commissioni sarebbe inferiore all'importo minimo necessario per lo scambio (${min})", "amount_is_estimate": "L'ammontare da ricevere è una stima", "amount_is_guaranteed": "L'ammontare da ricevere è fisso", "and": "e", @@ -714,6 +715,16 @@ "transactions": "Transazioni", "transactions_by_date": "Transazioni per data", "trusted": "di fiducia", + "tx_commit_exception_no_dust_on_change": "La transazione viene respinta con questo importo. Con queste monete è possibile inviare ${min} senza modifiche o ${max} che restituisce il cambiamento.", + "tx_commit_failed": "Commit di transazione non riuscita. Si prega di contattare il supporto.", + "tx_no_dust_exception": "La transazione viene respinta inviando un importo troppo piccolo. Per favore, prova ad aumentare l'importo.", + "tx_not_enough_inputs_exception": "Input non sufficienti disponibili. Seleziona di più sotto il controllo delle monete", + "tx_rejected_dust_change": "Transazione respinta dalle regole di rete, quantità bassa variazione (polvere). Prova a inviare tutto o ridurre l'importo.", + "tx_rejected_dust_output": "Transazione respinta dalle regole di rete, bassa quantità di output (polvere). Si prega di aumentare l'importo.", + "tx_rejected_dust_output_send_all": "Transazione respinta dalle regole di rete, bassa quantità di output (polvere). Si prega di controllare il saldo delle monete selezionate sotto controllo delle monete.", + "tx_rejected_vout_negative": "Non abbastanza saldo per pagare le commissioni di questa transazione. Si prega di controllare il saldo delle monete sotto controllo delle monete.", + "tx_wrong_balance_exception": "Non hai abbastanza ${currency} per inviare questo importo.", + "tx_zero_fee_exception": "Impossibile inviare transazioni con 0 tassa. Prova ad aumentare la tariffa o controlla la connessione per le ultime stime.", "unavailable_balance": "Saldo non disponibile", "unavailable_balance_description": "Saldo non disponibile: questo totale include i fondi bloccati nelle transazioni in sospeso e quelli che hai congelato attivamente nelle impostazioni di controllo delle monete. I saldi bloccati diventeranno disponibili una volta completate le rispettive transazioni, mentre i saldi congelati rimarranno inaccessibili per le transazioni finché non deciderai di sbloccarli.", "unconfirmed": "Saldo non confermato", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 9f8ddbe15..c3a025a7c 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -43,6 +43,7 @@ "already_have_account": "すでにアカウントをお持ちですか?", "always": "いつも", "amount": "量: ", + "amount_is_below_minimum_limit": "手数料後の残高は、交換に必要な最低額(${min})よりも少なくなります", "amount_is_estimate": "受け取り金額は見積もりです", "amount_is_guaranteed": "受け取り金額は保証されています", "and": "と", @@ -713,6 +714,16 @@ "transactions": "取引", "transactions_by_date": "日付ごとの取引", "trusted": "信頼できる", + "tx_commit_exception_no_dust_on_change": "この金額ではトランザクションは拒否されます。 これらのコインを使用すると、おつりなしの ${min} またはおつりを返す ${max} を送信できます。", + "tx_commit_failed": "トランザクションコミットは失敗しました。サポートに連絡してください。", + "tx_no_dust_exception": "トランザクションは、小さすぎる金額を送信することにより拒否されます。量を増やしてみてください。", + "tx_not_enough_inputs_exception": "利用可能な入力が十分ではありません。コイン制御下でもっと選択してください", + "tx_rejected_dust_change": "ネットワークルール、低い変更量(ほこり)によって拒否されたトランザクション。すべてを送信するか、金額を減らしてみてください。", + "tx_rejected_dust_output": "ネットワークルール、低出力量(ダスト)によって拒否されたトランザクション。金額を増やしてください。", + "tx_rejected_dust_output_send_all": "ネットワークルール、低出力量(ダスト)によって拒否されたトランザクション。コイン管理下で選択されたコインのバランスを確認してください。", + "tx_rejected_vout_negative": "この取引の料金に支払うのに十分な残高はありません。コイン制御下のコインのバランスを確認してください。", + "tx_wrong_balance_exception": "この金額を送信するのに十分な${currency}はありません。", + "tx_zero_fee_exception": "0料金でトランザクションを送信できません。レートを上げて、最新の見積もりについて接続を確認してみてください。", "unavailable_balance": "利用できない残高", "unavailable_balance_description": "利用不可能な残高: この合計には、保留中のトランザクションにロックされている資金と、コイン管理設定でアクティブに凍結した資金が含まれます。ロックされた残高は、それぞれの取引が完了すると利用可能になりますが、凍結された残高は、凍結を解除するまで取引にアクセスできません。", "unconfirmed": "残高未確認", @@ -790,4 +801,4 @@ "you_will_get": "に変換", "you_will_send": "から変換", "yy": "YY" -} \ No newline at end of file +} diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 757dc6cb3..d2b48913b 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -43,6 +43,7 @@ "already_have_account": "이미 계정이 있습니까?", "always": "언제나", "amount": "양: ", + "amount_is_below_minimum_limit": "수수료 후 잔액은 Exchange (${min})에 필요한 최소 금액보다 적습니다.", "amount_is_estimate": "수신 금액은 견적입니다", "amount_is_guaranteed": "수령 금액이 보장됩니다.", "and": "그리고", @@ -713,6 +714,16 @@ "transactions": "업무", "transactions_by_date": "날짜 별 거래", "trusted": "신뢰할 수 있는", + "tx_commit_exception_no_dust_on_change": "이 금액으로 거래가 거부되었습니다. 이 코인을 사용하면 거스름돈 없이 ${min}를 보내거나 거스름돈을 반환하는 ${max}를 보낼 수 있습니다.", + "tx_commit_failed": "거래 커밋이 실패했습니다. 지원에 연락하십시오.", + "tx_no_dust_exception": "너무 작은 금액을 보내면 거래가 거부됩니다. 금액을 늘리십시오.", + "tx_not_enough_inputs_exception": "사용 가능한 입력이 충분하지 않습니다. 코인 컨트롤에서 더 많은 것을 선택하십시오", + "tx_rejected_dust_change": "네트워크 규칙, 낮은 변경 금액 (먼지)에 의해 거부 된 거래. 전부를 보내거나 금액을 줄이십시오.", + "tx_rejected_dust_output": "네트워크 규칙, 낮은 출력 금액 (먼지)에 의해 거부 된 거래. 금액을 늘리십시오.", + "tx_rejected_dust_output_send_all": "네트워크 규칙, 낮은 출력 금액 (먼지)에 의해 거부 된 거래. 동전 제어에서 선택한 동전의 균형을 확인하십시오.", + "tx_rejected_vout_negative": "이 거래 수수료를 지불하기에 잔액이 충분하지 않습니다. 동전 통제하에 동전의 균형을 확인하십시오.", + "tx_wrong_balance_exception": "이 금액을 보내기에 충분한 ${currency}가 충분하지 않습니다.", + "tx_zero_fee_exception": "0 수수료로 거래를 보낼 수 없습니다. 최신 견적에 대해서는 속도를 높이거나 연결을 확인하십시오.", "unavailable_balance": "사용할 수 없는 잔액", "unavailable_balance_description": "사용할 수 없는 잔액: 이 총계에는 보류 중인 거래에 잠겨 있는 자금과 코인 관리 설정에서 적극적으로 동결된 자금이 포함됩니다. 잠긴 잔액은 해당 거래가 완료되면 사용할 수 있게 되며, 동결된 잔액은 동결을 해제하기 전까지 거래에 액세스할 수 없습니다.", "unconfirmed": "확인되지 않은 잔액", @@ -791,4 +802,4 @@ "you_will_send": "다음에서 변환", "YY": "YY", "yy": "YY" -} \ No newline at end of file +} diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 5b622c234..c7312b290 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -43,6 +43,7 @@ "already_have_account": "အကောင့်ရှိပြီးသားလား?", "always": "အမြဲတမ်း", "amount": "ပမာဏ:", + "amount_is_below_minimum_limit": "ငွေလဲလှယ်ရန်လိုအပ်သည့်အနိမ့်ဆုံးပမာဏထက်လျော့နည်းသွားပြီးသည့်နောက်ငွေလက်ကျန်ငွေပမာဏသည်ငွေလဲလှယ်မှုအတွက်လိုအပ်သည့်အနိမ့်ဆုံးပမာဏထက်နည်းသည် (${min})", "amount_is_estimate": "ရရှိသည့်ပမာဏသည် ခန့်မှန်းချက်တစ်ခုဖြစ်သည်။", "amount_is_guaranteed": "ရရှိသည့်ပမာဏကို အာမခံပါသည်။", "and": "နှင့်", @@ -712,6 +713,16 @@ "transactions": "ငွေပေးငွေယူ", "transactions_by_date": "ရက်စွဲအလိုက် ငွေလွှဲမှုများ", "trusted": "ယုံတယ်။", + "tx_commit_exception_no_dust_on_change": "အဆိုပါငွေပေးငွေယူကဒီပမာဏနှင့်အတူပယ်ချခံရသည်။ ဤဒင်္ဂါးပြားများနှင့်အတူပြောင်းလဲမှုကိုပြန်လည်ပြောင်းလဲခြင်းသို့မဟုတ် ${min} မပါဘဲ ${max} ပေးပို့နိုင်သည်။", + "tx_commit_failed": "ငွေပေးငွေယူကျူးလွန်မှုပျက်ကွက်။ ကျေးဇူးပြုပြီးပံ့ပိုးမှုဆက်သွယ်ပါ။", + "tx_no_dust_exception": "ငွေပမာဏကိုသေးငယ်လွန်းသောငွေပမာဏကိုပေးပို့ခြင်းဖြင့်ပယ်ဖျက်ခြင်းကိုငြင်းပယ်သည်။ ကျေးဇူးပြုပြီးငွေပမာဏကိုတိုးမြှင့်ကြိုးစားပါ။", + "tx_not_enough_inputs_exception": "အလုံအလောက်သွင်းအားစုများမလုံလောက်။ ကျေးဇူးပြုပြီးဒင်္ဂါးပြားထိန်းချုပ်မှုအောက်တွင်ပိုမိုရွေးချယ်ပါ", + "tx_rejected_dust_change": "Network စည်းမျဉ်းစည်းကမ်းများဖြင့်ပယ်ဖျက်ခြင်းသည် Network စည်းမျဉ်းစည်းကမ်းများဖြင့်ငြင်းပယ်ခြင်း, အားလုံးပေးပို့ခြင်းသို့မဟုတ်ငွေပမာဏကိုလျှော့ချကြိုးစားပါ။", + "tx_rejected_dust_output": "Network စည်းမျဉ်းစည်းကမ်းများဖြင့် ပယ်ချ. ငွေပေးချေမှုသည် output output (ဖုန်မှုန့်) ဖြင့်ပယ်ချခဲ့သည်။ ကျေးဇူးပြုပြီးငွေပမာဏကိုတိုးမြှင့်ပေးပါ။", + "tx_rejected_dust_output_send_all": "Network စည်းမျဉ်းစည်းကမ်းများဖြင့် ပယ်ချ. ငွေပေးချေမှုသည် output output (ဖုန်မှုန့်) ဖြင့်ပယ်ချခဲ့သည်။ ဒင်္ဂါးပြားထိန်းချုပ်မှုအောက်တွင်ရွေးချယ်ထားသောဒင်္ဂါးများ၏လက်ကျန်ငွေကိုစစ်ဆေးပါ။", + "tx_rejected_vout_negative": "ဒီငွေပေးငွေယူရဲ့အခကြေးငွေအတွက်ပေးဆောင်ဖို့လုံလောက်တဲ့ဟန်ချက်မလုံလောက်။ ဒင်္ဂါးပြား၏လက်ကျန်ငွေလက်ကျန်ငွေကိုစစ်ဆေးပါ။", + "tx_wrong_balance_exception": "ဤငွေပမာဏကိုပေးပို့ရန်သင့်တွင် ${currency} မရှိပါ။", + "tx_zero_fee_exception": "0 ကြေးနှင့်အတူငွေပေးငွေယူပေးပို့လို့မရပါဘူး။ နှုန်းကိုတိုးမြှင့်ခြင်းသို့မဟုတ်နောက်ဆုံးခန့်မှန်းချက်များအတွက်သင်၏ connection ကိုစစ်ဆေးပါ။", "unavailable_balance": "လက်ကျန်ငွေ မရရှိနိုင်ပါ။", "unavailable_balance_description": "မရရှိနိုင်သော လက်ကျန်ငွေ- ဤစုစုပေါင်းတွင် ဆိုင်းငံ့ထားသော ငွေပေးငွေယူများတွင် သော့ခတ်ထားသော ငွေကြေးများနှင့် သင်၏ coin ထိန်းချုပ်မှုဆက်တင်များတွင် သင် တက်ကြွစွာ အေးခဲထားသော ငွေများ ပါဝင်သည်။ သော့ခတ်ထားသော လက်ကျန်ငွေများကို ၎င်းတို့၏ သက်ဆိုင်ရာ ငွေပေးငွေယူများ ပြီးမြောက်သည်နှင့် တပြိုင်နက် ရရှိနိုင်မည်ဖြစ်ပြီး၊ အေးခဲထားသော လက်ကျန်များကို ၎င်းတို့အား ပြန်ဖြုတ်ရန် သင်ဆုံးဖြတ်သည်အထိ ငွေပေးငွေယူများအတွက် ဆက်လက်၍မရနိုင်ပါ။", "unconfirmed": "အတည်မပြုနိုင်သော လက်ကျန်ငွေ", @@ -789,4 +800,4 @@ "you_will_get": "သို့ပြောင်းပါ။", "you_will_send": "မှပြောင်းပါ။", "yy": "YY" -} \ No newline at end of file +} diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 121ade760..86881452e 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -43,6 +43,7 @@ "already_have_account": "Heb je al een account?", "always": "altijd", "amount": "Bedrag: ", + "amount_is_below_minimum_limit": "Uw saldo na vergoedingen zou lager zijn dan het minimale bedrag dat nodig is voor de uitwisseling (${min})", "amount_is_estimate": "Het ontvangen bedrag is een schatting", "amount_is_guaranteed": "Het ontvangen bedrag is gegarandeerd", "and": "en", @@ -712,6 +713,16 @@ "transactions": "Transacties", "transactions_by_date": "Transacties op datum", "trusted": "vertrouwd", + "tx_commit_exception_no_dust_on_change": "De transactie wordt afgewezen met dit bedrag. Met deze munten kunt u ${min} verzenden zonder verandering of ${max} die wijziging retourneert.", + "tx_commit_failed": "Transactiebewissing is mislukt. Neem contact op met de ondersteuning.", + "tx_no_dust_exception": "De transactie wordt afgewezen door een te klein bedrag te verzenden. Probeer het bedrag te verhogen.", + "tx_not_enough_inputs_exception": "Niet genoeg ingangen beschikbaar. Selecteer meer onder muntenbesturing", + "tx_rejected_dust_change": "Transactie afgewezen door netwerkregels, laag wijzigingsbedrag (stof). Probeer alles te verzenden of het bedrag te verminderen.", + "tx_rejected_dust_output": "Transactie afgewezen door netwerkregels, laag outputbedrag (stof). Verhoog het bedrag.", + "tx_rejected_dust_output_send_all": "Transactie afgewezen door netwerkregels, laag outputbedrag (stof). Controleer het saldo van munten die zijn geselecteerd onder muntcontrole.", + "tx_rejected_vout_negative": "Niet genoeg saldo om te betalen voor de kosten van deze transactie. Controleer het saldo van munten onder muntcontrole.", + "tx_wrong_balance_exception": "Je hebt niet genoeg ${currency} om dit bedrag te verzenden.", + "tx_zero_fee_exception": "Kan geen transactie verzenden met 0 kosten. Probeer het tarief te verhogen of uw verbinding te controleren op de laatste schattingen.", "unavailable_balance": "Onbeschikbaar saldo", "unavailable_balance_description": "Niet-beschikbaar saldo: Dit totaal omvat het geld dat is vergrendeld in lopende transacties en het geld dat u actief hebt bevroren in uw muntcontrole-instellingen. Vergrendelde saldi komen beschikbaar zodra de betreffende transacties zijn voltooid, terwijl bevroren saldi ontoegankelijk blijven voor transacties totdat u besluit ze weer vrij te geven.", "unconfirmed": "Onbevestigd saldo", @@ -790,4 +801,4 @@ "you_will_get": "Converteren naar", "you_will_send": "Converteren van", "yy": "JJ" -} \ No newline at end of file +} diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 88fbfb6e5..994820123 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -43,6 +43,7 @@ "already_have_account": "Masz już konto?", "always": "zawsze", "amount": "Ilość: ", + "amount_is_below_minimum_limit": "Twoje saldo po opłatach byłoby mniejsze niż minimalna kwota potrzebna do wymiany (${min})", "amount_is_estimate": "Otrzymana kwota jest wartością szacunkową", "amount_is_guaranteed": "Otrzymana kwota jest gwarantowana", "and": "i", @@ -712,6 +713,16 @@ "transactions": "Transakcje", "transactions_by_date": "Transakcje według daty", "trusted": "Zaufany", + "tx_commit_exception_no_dust_on_change": "Transakcja jest odrzucana z tą kwotą. Za pomocą tych monet możesz wysłać ${min} bez zmiany lub ${max}, które zwraca zmianę.", + "tx_commit_failed": "Zatwierdzenie transakcji nie powiodło się. Skontaktuj się z obsługą.", + "tx_no_dust_exception": "Transakcja jest odrzucana przez wysyłanie zbyt małej ilości. Spróbuj zwiększyć kwotę.", + "tx_not_enough_inputs_exception": "Za mało dostępnych danych wejściowych. Wybierz więcej pod kontrolą monet", + "tx_rejected_dust_change": "Transakcja odrzucona według reguł sieciowych, niska ilość zmiany (kurz). Spróbuj wysłać całość lub zmniejszyć kwotę.", + "tx_rejected_dust_output": "Transakcja odrzucona według reguł sieciowych, niskiej ilości wyjściowej (pyłu). Zwiększ kwotę.", + "tx_rejected_dust_output_send_all": "Transakcja odrzucona według reguł sieciowych, niskiej ilości wyjściowej (pyłu). Sprawdź saldo monet wybranych pod kontrolą monet.", + "tx_rejected_vout_negative": "Za mało salda, aby zapłacić za opłaty tej transakcji. Sprawdź saldo monet pod kontrolą monet.", + "tx_wrong_balance_exception": "Nie masz wystarczającej ilości ${currency}, aby wysłać tę kwotę.", + "tx_zero_fee_exception": "Nie można wysłać transakcji z 0 opłatą. Spróbuj zwiększyć stawkę lub sprawdzić połączenie w poszukiwaniu najnowszych szacunków.", "unavailable_balance": "Niedostępne saldo", "unavailable_balance_description": "Niedostępne saldo: Suma ta obejmuje środki zablokowane w transakcjach oczekujących oraz te, które aktywnie zamroziłeś w ustawieniach kontroli monet. Zablokowane salda staną się dostępne po zakończeniu odpowiednich transakcji, natomiast zamrożone salda pozostaną niedostępne dla transakcji, dopóki nie zdecydujesz się ich odblokować.", "unconfirmed": "Niepotwierdzone saldo", @@ -789,4 +800,4 @@ "you_will_get": "Konwertuj na", "you_will_send": "Konwertuj z", "yy": "RR" -} \ No newline at end of file +} diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 7487499ef..cec7b8c11 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -43,6 +43,7 @@ "already_have_account": "Já tem uma conta?", "always": "sempre", "amount": "Quantia: ", + "amount_is_below_minimum_limit": "Seu saldo após as taxas seria menor que o valor mínimo necessário para a troca (${min})", "amount_is_estimate": "O valor a ser recebido informado acima é uma estimativa", "amount_is_guaranteed": "O valor recebido é garantido", "and": "e", @@ -714,6 +715,16 @@ "transactions": "Transações", "transactions_by_date": "Transações por data", "trusted": "confiável", + "tx_commit_exception_no_dust_on_change": "A transação é rejeitada com esse valor. Com essas moedas, você pode enviar ${min} sem alteração ou ${max} que retorna alterações.", + "tx_commit_failed": "A confirmação da transação falhou. Entre em contato com o suporte.", + "tx_no_dust_exception": "A transação é rejeitada enviando uma quantia pequena demais. Por favor, tente aumentar o valor.", + "tx_not_enough_inputs_exception": "Não há entradas disponíveis. Selecione mais sob controle de moedas", + "tx_rejected_dust_change": "Transação rejeitada pelas regras de rede, baixa quantidade de troco (poeira). Tente enviar tudo ou reduzir o valor.", + "tx_rejected_dust_output": "Transação rejeitada por regras de rede, baixa quantidade de saída (poeira). Por favor, aumente o valor.", + "tx_rejected_dust_output_send_all": "Transação rejeitada por regras de rede, baixa quantidade de saída (poeira). Por favor, verifique o saldo de moedas selecionadas sob controle de moedas.", + "tx_rejected_vout_negative": "Não há saldo suficiente para pagar as taxas desta transação. Por favor, verifique o saldo de moedas sob controle de moedas.", + "tx_wrong_balance_exception": "Você não tem o suficiente ${currency} para enviar esse valor.", + "tx_zero_fee_exception": "Não pode enviar transação com taxa 0. Tente aumentar a taxa ou verificar sua conexão para obter as estimativas mais recentes.", "unavailable_balance": "Saldo indisponível", "unavailable_balance_description": "Saldo Indisponível: Este total inclui fundos bloqueados em transações pendentes e aqueles que você congelou ativamente nas configurações de controle de moedas. Os saldos bloqueados ficarão disponíveis assim que suas respectivas transações forem concluídas, enquanto os saldos congelados permanecerão inacessíveis para transações até que você decida descongelá-los.", "unconfirmed": "Saldo não confirmado", @@ -792,4 +803,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 443daa588..4ae5bb129 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -43,6 +43,7 @@ "already_have_account": "У вас уже есть аккаунт?", "always": "всегда", "amount": "Сумма: ", + "amount_is_below_minimum_limit": "Ваш баланс после сборов будет меньше, чем минимальная сумма, необходимая для обмена (${min}))", "amount_is_estimate": "Полученная сумма является приблизительной", "amount_is_guaranteed": "Полученная сумма гарантирована", "and": "и", @@ -713,6 +714,16 @@ "transactions": "Транзакции", "transactions_by_date": "Сортировать по дате", "trusted": "доверенный", + "tx_commit_exception_no_dust_on_change": "Транзакция отклоняется с этой суммой. С этими монетами вы можете отправлять ${min} без изменения или ${max}, которые возвращают изменение.", + "tx_commit_failed": "Комплект транзакции не удался. Пожалуйста, свяжитесь с поддержкой.", + "tx_no_dust_exception": "Транзакция отклоняется путем отправки слишком маленькой суммы. Пожалуйста, попробуйте увеличить сумму.", + "tx_not_enough_inputs_exception": "Недостаточно входов доступны. Пожалуйста, выберите больше под контролем монет", + "tx_rejected_dust_change": "Транзакция отклоняется в соответствии с правилами сети, низкой суммой изменений (пыль). Попробуйте отправить все или уменьшить сумму.", + "tx_rejected_dust_output": "Транзакция отклоняется в соответствии с правилами сети, низкой выходной суммой (пыль). Пожалуйста, увеличьте сумму.", + "tx_rejected_dust_output_send_all": "Транзакция отклоняется в соответствии с правилами сети, низкой выходной суммой (пыль). Пожалуйста, проверьте баланс монет, выбранных под контролем монет.", + "tx_rejected_vout_negative": "Недостаточно баланс, чтобы оплатить плату этой транзакции. Пожалуйста, проверьте баланс монет под контролем монет.", + "tx_wrong_balance_exception": "У вас не хватает ${currency}, чтобы отправить эту сумму.", + "tx_zero_fee_exception": "Не может отправить транзакцию с платой 0. Попробуйте увеличить ставку или проверить соединение на наличие последних оценок.", "unavailable_balance": "Недоступный баланс", "unavailable_balance_description": "Недоступный баланс: в эту сумму входят средства, заблокированные в ожидающих транзакциях, и средства, которые вы активно заморозили в настройках управления монетами. Заблокированные балансы станут доступны после завершения соответствующих транзакций, а замороженные балансы останутся недоступными для транзакций, пока вы не решите их разморозить.", "unconfirmed": "Неподтвержденный баланс", @@ -790,4 +801,4 @@ "you_will_get": "Конвертировать в", "you_will_send": "Конвертировать из", "yy": "ГГ" -} \ No newline at end of file +} diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index dc864c39c..6c8634e83 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -43,6 +43,7 @@ "already_have_account": "มีบัญชีอยู่แล้ว?", "always": "เสมอ", "amount": "จำนวน: ", + "amount_is_below_minimum_limit": "ยอดคงเหลือหลังจากค่าธรรมเนียมของคุณจะน้อยกว่าจำนวนเงินขั้นต่ำที่จำเป็นสำหรับการแลกเปลี่ยน (${min})", "amount_is_estimate": "จำนวนที่จะได้รับเป็นการประมาณการ", "amount_is_guaranteed": "จำนวนที่จะได้รับมีการรับประกัน", "and": "และ", @@ -712,6 +713,16 @@ "transactions": "ธุรกรรม", "transactions_by_date": "ธุรกรรมตามวันที่", "trusted": "มั่นคง", + "tx_commit_exception_no_dust_on_change": "ธุรกรรมถูกปฏิเสธด้วยจำนวนเงินนี้ ด้วยเหรียญเหล่านี้คุณสามารถส่ง ${min} โดยไม่ต้องเปลี่ยนแปลงหรือ ${max} ที่ส่งคืนการเปลี่ยนแปลง", + "tx_commit_failed": "การทำธุรกรรมล้มเหลว กรุณาติดต่อฝ่ายสนับสนุน", + "tx_no_dust_exception": "การทำธุรกรรมถูกปฏิเสธโดยการส่งจำนวนน้อยเกินไป โปรดลองเพิ่มจำนวนเงิน", + "tx_not_enough_inputs_exception": "มีอินพุตไม่เพียงพอ โปรดเลือกเพิ่มเติมภายใต้การควบคุมเหรียญ", + "tx_rejected_dust_change": "ธุรกรรมถูกปฏิเสธโดยกฎเครือข่ายจำนวนการเปลี่ยนแปลงต่ำ (ฝุ่น) ลองส่งทั้งหมดหรือลดจำนวนเงิน", + "tx_rejected_dust_output": "การทำธุรกรรมถูกปฏิเสธโดยกฎเครือข่ายจำนวนเอาต์พุตต่ำ (ฝุ่น) โปรดเพิ่มจำนวนเงิน", + "tx_rejected_dust_output_send_all": "การทำธุรกรรมถูกปฏิเสธโดยกฎเครือข่ายจำนวนเอาต์พุตต่ำ (ฝุ่น) โปรดตรวจสอบยอดคงเหลือของเหรียญที่เลือกภายใต้การควบคุมเหรียญ", + "tx_rejected_vout_negative": "ยอดคงเหลือไม่เพียงพอที่จะจ่ายสำหรับค่าธรรมเนียมการทำธุรกรรมนี้ โปรดตรวจสอบยอดคงเหลือของเหรียญภายใต้การควบคุมเหรียญ", + "tx_wrong_balance_exception": "คุณมีไม่เพียงพอ ${currency} ในการส่งจำนวนนี้", + "tx_zero_fee_exception": "ไม่สามารถส่งธุรกรรมด้วยค่าธรรมเนียม 0 ลองเพิ่มอัตราหรือตรวจสอบการเชื่อมต่อของคุณสำหรับการประมาณการล่าสุด", "unavailable_balance": "ยอดคงเหลือไม่พร้อมใช้งาน", "unavailable_balance_description": "ยอดคงเหลือที่ไม่พร้อมใช้งาน: ยอดรวมนี้รวมถึงเงินทุนที่ถูกล็อคในการทำธุรกรรมที่รอดำเนินการและที่คุณได้แช่แข็งไว้ในการตั้งค่าการควบคุมเหรียญของคุณ ยอดคงเหลือที่ถูกล็อคจะพร้อมใช้งานเมื่อธุรกรรมที่เกี่ยวข้องเสร็จสมบูรณ์ ในขณะที่ยอดคงเหลือที่แช่แข็งจะไม่สามารถเข้าถึงได้สำหรับธุรกรรมจนกว่าคุณจะตัดสินใจยกเลิกการแช่แข็ง", "unconfirmed": "ยอดคงเหลือที่ไม่ได้รับการยืนยัน", @@ -789,4 +800,4 @@ "you_will_get": "แปลงเป็น", "you_will_send": "แปลงจาก", "yy": "ปี" -} \ No newline at end of file +} diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 4abd6472f..4d88fe640 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -43,6 +43,7 @@ "already_have_account": "Mayroon nang account?", "always": "Palagi", "amount": "Halaga:", + "amount_is_below_minimum_limit": "Ang iyong balanse pagkatapos ng mga bayarin ay mas mababa kaysa sa minimum na halaga na kinakailangan para sa palitan (${min})", "amount_is_estimate": "Ang natanggap na halaga ay isang pagtatantya", "amount_is_guaranteed": "Ang natanggap na halaga ay garantisado", "and": "at", @@ -712,6 +713,16 @@ "transactions": "Mga Transaksyon", "transactions_by_date": "Mga Transaksyon ayon sa Petsa", "trusted": "Pinagkakatiwalaan", + "tx_commit_exception_no_dust_on_change": "Ang transaksyon ay tinanggihan sa halagang ito. Sa mga barya na ito maaari kang magpadala ng ${min} nang walang pagbabago o ${max} na nagbabalik ng pagbabago.", + "tx_commit_failed": "Nabigo ang transaksyon sa transaksyon. Mangyaring makipag -ugnay sa suporta.", + "tx_no_dust_exception": "Ang transaksyon ay tinanggihan sa pamamagitan ng pagpapadala ng isang maliit na maliit. Mangyaring subukang dagdagan ang halaga.", + "tx_not_enough_inputs_exception": "Hindi sapat na magagamit ang mga input. Mangyaring pumili ng higit pa sa ilalim ng control ng barya", + "tx_rejected_dust_change": "Ang transaksyon na tinanggihan ng mga patakaran sa network, mababang halaga ng pagbabago (alikabok). Subukang ipadala ang lahat o bawasan ang halaga.", + "tx_rejected_dust_output": "Ang transaksyon na tinanggihan ng mga patakaran sa network, mababang halaga ng output (alikabok). Mangyaring dagdagan ang halaga.", + "tx_rejected_dust_output_send_all": "Ang transaksyon na tinanggihan ng mga patakaran sa network, mababang halaga ng output (alikabok). Mangyaring suriin ang balanse ng mga barya na napili sa ilalim ng kontrol ng barya.", + "tx_rejected_vout_negative": "Hindi sapat na balanse upang magbayad para sa mga bayarin ng transaksyon na ito. Mangyaring suriin ang balanse ng mga barya sa ilalim ng kontrol ng barya.", + "tx_wrong_balance_exception": "Wala kang sapat na ${currency} upang maipadala ang halagang ito.", + "tx_zero_fee_exception": "Hindi maaaring magpadala ng transaksyon na may 0 bayad. Subukan ang pagtaas ng rate o pagsuri sa iyong koneksyon para sa pinakabagong mga pagtatantya.", "unavailable_balance": "Hindi available na balanse", "unavailable_balance_description": "Hindi Available na Balanse: Kasama sa kabuuang ito ang mga pondong naka-lock sa mga nakabinbing transaksyon at ang mga aktibong na-freeze mo sa iyong mga setting ng kontrol ng coin. Magiging available ang mga naka-lock na balanse kapag nakumpleto na ang kani-kanilang mga transaksyon, habang ang mga nakapirming balanse ay nananatiling hindi naa-access para sa mga transaksyon hanggang sa magpasya kang i-unfreeze ang mga ito.", "unconfirmed": "Hindi nakumpirma na balanse", @@ -789,4 +800,4 @@ "you_will_get": "Mag -convert sa", "you_will_send": "I -convert mula sa", "yy": "YY" -} \ No newline at end of file +} diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index c615864a7..599d5bf67 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -43,6 +43,7 @@ "already_have_account": "Zaten bir hesabınız var mı?", "always": "Her Zaman", "amount": "Miktar: ", + "amount_is_below_minimum_limit": "Ücretlerden sonra bakiyeniz, değişim için gereken minimum miktardan daha az olur (${min})", "amount_is_estimate": "Alacağınız tutar tahminidir", "amount_is_guaranteed": "Alacağınız tutar garantilidir", "and": "ve", @@ -712,6 +713,16 @@ "transactions": "İşlemler", "transactions_by_date": "Tarihe göre transferler", "trusted": "Güvenilir", + "tx_commit_exception_no_dust_on_change": "İşlem bu miktarla reddedilir. Bu madeni paralarla değişiklik yapmadan ${min} veya değişikliği döndüren ${max} gönderebilirsiniz.", + "tx_commit_failed": "İşlem taahhüdü başarısız oldu. Lütfen Destek ile iletişime geçin.", + "tx_no_dust_exception": "İşlem, çok küçük bir miktar gönderilerek reddedilir. Lütfen miktarı artırmayı deneyin.", + "tx_not_enough_inputs_exception": "Yeterli giriş yok. Lütfen madeni para kontrolü altında daha fazlasını seçin", + "tx_rejected_dust_change": "Ağ kurallarına göre reddedilen işlem, düşük değişim miktarı (toz). Tümünü göndermeyi veya miktarı azaltmayı deneyin.", + "tx_rejected_dust_output": "Ağ kurallarına göre reddedilen işlem, düşük çıktı miktarı (toz). Lütfen miktarı artırın.", + "tx_rejected_dust_output_send_all": "Ağ kurallarına göre reddedilen işlem, düşük çıktı miktarı (toz). Lütfen madeni para kontrolü altında seçilen madeni para dengesini kontrol edin.", + "tx_rejected_vout_negative": "Bu işlem ücretleri için ödeme yapmak için yeterli bakiye yok. Lütfen madeni para kontrolü altındaki madeni para dengesini kontrol edin.", + "tx_wrong_balance_exception": "Bu miktarı göndermek için yeterli ${currency} yok.", + "tx_zero_fee_exception": "0 ücret ile işlem gönderilemez. En son tahminler için oranı artırmayı veya bağlantınızı kontrol etmeyi deneyin.", "unavailable_balance": "Kullanılamayan bakiye", "unavailable_balance_description": "Kullanılamayan Bakiye: Bu toplam, bekleyen işlemlerde kilitlenen fonları ve jeton kontrol ayarlarınızda aktif olarak dondurduğunuz fonları içerir. Kilitli bakiyeler, ilgili işlemleri tamamlandıktan sonra kullanılabilir hale gelir; dondurulmuş bakiyeler ise siz onları dondurmaya karar verene kadar işlemler için erişilemez durumda kalır.", "unconfirmed": "Onaylanmamış Bakiye", @@ -789,4 +800,4 @@ "you_will_get": "Biçimine dönüştür:", "you_will_send": "Biçiminden dönüştür:", "yy": "YY" -} \ No newline at end of file +} diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 0fe324d11..b0902aada 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -43,6 +43,7 @@ "already_have_account": "Вже є обліковий запис?", "always": "Завжди", "amount": "Сума: ", + "amount_is_below_minimum_limit": "Ваш баланс після зборів буде меншим, ніж мінімальна сума, необхідна для обміну (${min})", "amount_is_estimate": "Отримана сума є приблизною", "amount_is_guaranteed": "Отримана сума є гарантованою", "and": "і", @@ -713,6 +714,16 @@ "transactions": "Транзакції", "transactions_by_date": "Сортувати по даті", "trusted": "довіряють", + "tx_commit_exception_no_dust_on_change": "Транзакція відхилена цією сумою. За допомогою цих монет ви можете надіслати ${min} без змін або ${max}, що повертає зміни.", + "tx_commit_failed": "Транзакційна комісія не вдалося. Будь ласка, зв'яжіться з підтримкою.", + "tx_no_dust_exception": "Угода відхиляється, відправивши суму занадто мала. Будь ласка, спробуйте збільшити суму.", + "tx_not_enough_inputs_exception": "Недостатньо доступних входів. Виберіть більше під контролем монети", + "tx_rejected_dust_change": "Транзакція відхилена за допомогою мережевих правил, низька кількість змін (пил). Спробуйте надіслати все або зменшити суму.", + "tx_rejected_dust_output": "Транзакція відхилена за допомогою мережевих правил, низька кількість вихідної кількості (пил). Будь ласка, збільшуйте суму.", + "tx_rejected_dust_output_send_all": "Транзакція відхилена за допомогою мережевих правил, низька кількість вихідної кількості (пил). Будь ласка, перевірте баланс монет, вибраних під контролем монет.", + "tx_rejected_vout_negative": "Недостатньо балансу, щоб оплатити плату за цю транзакцію. Будь ласка, перевірте баланс монет під контролем монет.", + "tx_wrong_balance_exception": "У вас недостатньо ${currency}, щоб надіслати цю суму.", + "tx_zero_fee_exception": "Не вдається відправити транзакцію з 0 платежами. Спробуйте збільшити ставку або перевірити з'єднання на останні оцінки.", "unavailable_balance": "Недоступний баланс", "unavailable_balance_description": "Недоступний баланс: ця сума включає кошти, заблоковані в незавершених транзакціях, і ті, які ви активно заморозили в налаштуваннях контролю монет. Заблоковані баланси стануть доступними після завершення відповідних транзакцій, тоді як заморожені баланси залишаються недоступними для транзакцій, доки ви не вирішите їх розморозити.", "unconfirmed": "Непідтверджений баланс", @@ -790,4 +801,4 @@ "you_will_get": "Конвертувати в", "you_will_send": "Конвертувати з", "yy": "YY" -} \ No newline at end of file +} diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 9de85a683..1d4d98f45 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -43,6 +43,7 @@ "already_have_account": "پہلے سے ہی اکاؤنٹ ہے؟", "always": "ہمیشہ", "amount": "رقم کی رقم:", + "amount_is_below_minimum_limit": "فیس کے بعد آپ کا توازن تبادلہ کے لئے درکار کم سے کم رقم سے کم ہوگا (${min}", "amount_is_estimate": "وصول شدہ رقم ایک تخمینہ ہے۔", "amount_is_guaranteed": "وصول شدہ رقم کی ضمانت ہے۔", "and": "اور", @@ -714,6 +715,16 @@ "transactions": "لین دین", "transactions_by_date": "تاریخ کے لحاظ سے لین دین", "trusted": "قابل اعتماد", + "tx_commit_exception_no_dust_on_change": "اس رقم سے لین دین کو مسترد کردیا گیا ہے۔ ان سککوں کے ذریعہ آپ بغیر کسی تبدیلی کے ${min} یا ${max} بھیج سکتے ہیں جو لوٹتے ہیں۔", + "tx_commit_failed": "ٹرانزیکشن کمٹ ناکام ہوگیا۔ براہ کرم سپورٹ سے رابطہ کریں۔", + "tx_no_dust_exception": "لین دین کو بہت چھوٹی رقم بھیج کر مسترد کردیا جاتا ہے۔ براہ کرم رقم میں اضافہ کرنے کی کوشش کریں۔", + "tx_not_enough_inputs_exception": "کافی ان پٹ دستیاب نہیں ہے۔ براہ کرم سکے کے کنٹرول میں مزید منتخب کریں", + "tx_rejected_dust_change": "نیٹ ورک کے قواعد ، کم تبدیلی کی رقم (دھول) کے ذریعہ لین دین کو مسترد کردیا گیا۔ سب کو بھیجنے یا رقم کو کم کرنے کی کوشش کریں۔", + "tx_rejected_dust_output": "لین دین کو نیٹ ورک کے قواعد ، کم آؤٹ پٹ رقم (دھول) کے ذریعہ مسترد کردیا گیا۔ براہ کرم رقم میں اضافہ کریں۔", + "tx_rejected_dust_output_send_all": "لین دین کو نیٹ ورک کے قواعد ، کم آؤٹ پٹ رقم (دھول) کے ذریعہ مسترد کردیا گیا۔ براہ کرم سکے کے کنٹرول میں منتخب کردہ سکے کا توازن چیک کریں۔", + "tx_rejected_vout_negative": "اس لین دین کی فیسوں کی ادائیگی کے لئے کافی توازن نہیں ہے۔ براہ کرم سکے کے کنٹرول میں سکے کا توازن چیک کریں۔", + "tx_wrong_balance_exception": "آپ کے پاس یہ رقم بھیجنے کے لئے کافی ${currency} نہیں ہے۔", + "tx_zero_fee_exception": "0 فیس کے ساتھ لین دین نہیں بھیج سکتا۔ شرح کو بڑھانے یا تازہ ترین تخمینے کے ل your اپنے کنکشن کی جانچ پڑتال کرنے کی کوشش کریں۔", "unavailable_balance": "ﺲﻨﻠﯿﺑ ﺏﺎﯿﺘﺳﺩ ﺮﯿﻏ", "unavailable_balance_description": "۔ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﮧﻠﺼﯿﻓ ﺎﮐ ﮯﻧﺮﮐ ﺪﻤﺠﻨﻣ ﻥﺍ ﮟﯿﮩﻧﺍ ﭖﺁ ﮧﮐ ﮏﺗ ﺐﺟ ﮟﯿﮨ ﮯﺘﮨﺭ ﯽﺋﺎﺳﺭ ﻞﺑﺎﻗﺎﻧ ﮏﺗ ﺖﻗﻭ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﻦﯾﺩ ﻦﯿﻟ ﺲﻨﻠﯿﺑ ﺪﻤﺠﻨﻣ ﮧﮐ ﺐﺟ ،ﮯﮔ ﮟﯿﺋﺎﺟ ﻮﮨ ﺏﺎﯿﺘﺳﺩ ﺲﻨﻠﯿﺑ ﻞﻔﻘﻣ ﺪﻌﺑ ﮯﮐ ﮯﻧﻮﮨ ﻞﻤﮑﻣ ﻦﯾﺩ ﻦﯿﻟ ﮧﻘﻠﻌﺘﻣ ﮯﮐ ﻥﺍ ۔ﮯﮨ ﺎﮭﮐﺭ ﺮ", "unconfirmed": "غیر تصدیق شدہ بیلنس", @@ -791,4 +802,4 @@ "you_will_get": "میں تبدیل کریں۔", "you_will_send": "سے تبدیل کریں۔", "yy": "YY" -} \ No newline at end of file +} diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 8d85f0d6e..9128427e5 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -43,6 +43,7 @@ "already_have_account": "Ṣé ẹ ti ní àkáǹtì?", "always": "Ní gbogbo àwọn ìgbà", "amount": "Iye: ", + "amount_is_below_minimum_limit": "Iwontunws.funfun rẹ lẹhin awọn idiyele yoo kere ju iye ti o kere ju nilo fun paṣipaarọ (${min}", "amount_is_estimate": "Ìdíyelé ni iye tó ń bọ̀", "amount_is_guaranteed": "ó di dandan pé owó á wọlé", "and": "àti", @@ -713,6 +714,16 @@ "transactions": "Àwọn àránṣẹ́", "transactions_by_date": "Àwọn àránṣẹ́ t'á ti fi aago ṣa", "trusted": "A ti fọkàn ẹ̀ tán", + "tx_commit_exception_no_dust_on_change": "Iṣowo naa ti kọ pẹlu iye yii. Pẹlu awọn owó wọnyi o le firanṣẹ ${min} laisi ayipada tabi ${max} ni iyipada iyipada.", + "tx_commit_failed": "Idunadura iṣowo kuna. Jọwọ kan si atilẹyin.", + "tx_no_dust_exception": "Iṣowo naa ni kọ nipa fifiranṣẹ iye ti o kere ju. Jọwọ gbiyanju pọ si iye naa.", + "tx_not_enough_inputs_exception": "Ko to awọn titẹsi to. Jọwọ yan diẹ sii labẹ iṣakoso owo", + "tx_rejected_dust_change": "Idunadura kọ nipasẹ awọn ofin nẹtiwọọki, iye iyipada kekere (eruku). Gbiyanju lati firanṣẹ gbogbo rẹ tabi dinku iye.", + "tx_rejected_dust_output": "Idunadura kọ nipasẹ awọn ofin nẹtiwọọki, iye ti o wuwe kekere (eruku). Jọwọ mu iye naa pọ si.", + "tx_rejected_dust_output_send_all": "Idunadura kọ nipasẹ awọn ofin nẹtiwọọki, iye ti o wuwe kekere (eruku). Jọwọ ṣayẹwo dọgbadọgba ti awọn owo ti a yan labẹ iṣakoso owo.", + "tx_rejected_vout_negative": "Iwontunws.funfun ti o to lati sanwo fun awọn idiyele iṣowo yii. Jọwọ ṣayẹwo iwọntunwọnsi ti awọn owo labẹ iṣakoso owo.", + "tx_wrong_balance_exception": "O ko ni to ${currency} lati firanṣẹ iye yii.", + "tx_zero_fee_exception": "Ko le firanṣẹ idunadura pẹlu ọya 0. Gbiyanju jijẹ oṣuwọn tabi ṣayẹwo asopọ rẹ fun awọn iṣiro tuntun.", "unavailable_balance": "Iwontunwonsi ti ko si", "unavailable_balance_description": "Iwontunws.funfun ti ko si: Lapapọ yii pẹlu awọn owo ti o wa ni titiipa ni awọn iṣowo isunmọ ati awọn ti o ti didi ni itara ninu awọn eto iṣakoso owo rẹ. Awọn iwọntunwọnsi titiipa yoo wa ni kete ti awọn iṣowo oniwun wọn ba ti pari, lakoko ti awọn iwọntunwọnsi tio tutunini ko ni iraye si fun awọn iṣowo titi iwọ o fi pinnu lati mu wọn kuro.", "unconfirmed": "A kò tí ì jẹ́rìí ẹ̀", @@ -790,4 +801,4 @@ "you_will_get": "Ṣe pàṣípààrọ̀ sí", "you_will_send": "Ṣe pàṣípààrọ̀ láti", "yy": "Ọd" -} \ No newline at end of file +} diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 4087d96e8..d9ac86b34 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -43,6 +43,7 @@ "already_have_account": "已经有账号了?", "always": "总是", "amount": "金额: ", + "amount_is_below_minimum_limit": "您的余额费用将小于交易所所需的最低金额(${min})", "amount_is_estimate": "收款金额为估算值", "amount_is_guaranteed": "保证收到的金额", "and": "和", @@ -712,6 +713,16 @@ "transactions": "交易情况", "transactions_by_date": "按日期交易", "trusted": "值得信赖", + "tx_commit_exception_no_dust_on_change": "交易被此金额拒绝。使用这些硬币,您可以发送${min}无需更改或返回${max}的变化。", + "tx_commit_failed": "交易承诺失败。请联系支持。", + "tx_no_dust_exception": "通过发送太小的金额来拒绝交易。请尝试增加金额。", + "tx_not_enough_inputs_exception": "没有足够的输入。请在硬币控制下选择更多", + "tx_rejected_dust_change": "交易被网络规则拒绝,较低的变化数量(灰尘)。尝试发送全部或减少金额。", + "tx_rejected_dust_output": "交易被网络规则,低输出量(灰尘)拒绝。请增加金额。", + "tx_rejected_dust_output_send_all": "交易被网络规则,低输出量(灰尘)拒绝。请检查在硬币控制下选择的硬币的余额。", + "tx_rejected_vout_negative": "没有足够的余额来支付此交易费用。请检查硬币控制下的硬币余额。", + "tx_wrong_balance_exception": "您没有足够的${currency}来发送此金额。", + "tx_zero_fee_exception": "无法以0费用发送交易。尝试提高速率或检查连接以获取最新估计。", "unavailable_balance": "不可用余额", "unavailable_balance_description": "不可用余额:此总额包括锁定在待处理交易中的资金以及您在硬币控制设置中主动冻结的资金。一旦各自的交易完成,锁定的余额将变得可用,而冻结的余额在您决定解冻之前仍然无法进行交易。", "unconfirmed": "未确认余额", @@ -789,4 +800,4 @@ "you_will_get": "转换到", "you_will_send": "转换自", "yy": "YY" -} \ No newline at end of file +} diff --git a/tool/configure.dart b/tool/configure.dart index 99d1fe8ee..e24ab2062 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -69,6 +69,7 @@ import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/output_info.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_service.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:hive/hive.dart'; import 'package:bitcoin_base/bitcoin_base.dart';"""; From 698c22229109ca4da39269ac96416c7bdc18bcd7 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Fri, 29 Mar 2024 20:54:59 +0200 Subject: [PATCH 141/241] Generic fixes (#1348) * Change order of currencies in currency picker * Disable Background sync until implemented properly * remove ability to use device pin in bio auth * Fix condition * Minor fix [skip ci] * make notifications red dot go when opened * Update Frozen coin text color * Update Frozen coin text color * Fetch internal transactions for eth and polygon * Remove debug prints [skip ci] * Fix Camera permission on iOS [skip ci] --------- Co-authored-by: tuxsudo --- cw_core/lib/crypto_currency.dart | 4 +-- cw_ethereum/lib/ethereum_client.dart | 25 +++++++++++++++++++ cw_evm/lib/evm_chain_client.dart | 2 ++ cw_evm/lib/evm_chain_transaction_model.dart | 18 ++++++------- cw_evm/lib/evm_chain_wallet.dart | 4 ++- cw_polygon/lib/polygon_client.dart | 24 ++++++++++++++++++ ios/Podfile | 6 ++--- ios/Podfile.lock | 2 +- lib/entities/background_tasks.dart | 3 ++- lib/entities/biometric_auth.dart | 1 + .../exchange/widgets/exchange_card.dart | 10 ++++---- .../settings/connection_sync_page.dart | 3 +-- .../widgets/unspent_coins_list_item.dart | 12 +++++---- lib/src/widgets/services_updates_widget.dart | 2 +- lib/utils/feature_flag.dart | 1 + 15 files changed, 87 insertions(+), 30 deletions(-) diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index 9cebce10a..f1c1cd8ae 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -38,6 +38,8 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen CryptoCurrency.trx, CryptoCurrency.usdt, CryptoCurrency.usdterc20, + CryptoCurrency.sol, + CryptoCurrency.maticpoly, CryptoCurrency.xlm, CryptoCurrency.xrp, CryptoCurrency.xhv, @@ -50,7 +52,6 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen CryptoCurrency.usdttrc20, CryptoCurrency.hbar, CryptoCurrency.sc, - CryptoCurrency.sol, CryptoCurrency.usdc, CryptoCurrency.usdcsol, CryptoCurrency.zaddr, @@ -61,7 +62,6 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen CryptoCurrency.dcr, CryptoCurrency.kmd, CryptoCurrency.mana, - CryptoCurrency.maticpoly, CryptoCurrency.matic, CryptoCurrency.mkr, CryptoCurrency.near, diff --git a/cw_ethereum/lib/ethereum_client.dart b/cw_ethereum/lib/ethereum_client.dart index 929dadf2f..10dc245d4 100644 --- a/cw_ethereum/lib/ethereum_client.dart +++ b/cw_ethereum/lib/ethereum_client.dart @@ -41,4 +41,29 @@ class EthereumClient extends EVMChainClient { return []; } } + + @override + Future> fetchInternalTransactions(String address) async { + try { + final response = await httpClient.get(Uri.https("api.etherscan.io", "/api", { + "module": "account", + "action": "txlistinternal", + "address": "0x72067Bf532b21A096D2e2B4953d69554E1a61917", + "apikey": secrets.etherScanApiKey, + })); + + final jsonResponse = json.decode(response.body) as Map; + + if (response.statusCode >= 200 && response.statusCode < 300 && jsonResponse['status'] != 0) { + return (jsonResponse['result'] as List) + .map((e) => EVMChainTransactionModel.fromJson(e as Map, 'ETH')) + .toList(); + } + + return []; + } catch (e) { + log(e.toString()); + return []; + } + } } diff --git a/cw_evm/lib/evm_chain_client.dart b/cw_evm/lib/evm_chain_client.dart index 5e84ec796..834e130a3 100644 --- a/cw_evm/lib/evm_chain_client.dart +++ b/cw_evm/lib/evm_chain_client.dart @@ -27,6 +27,8 @@ abstract class EVMChainClient { Future> fetchTransactions(String address, {String? contractAddress}); + Future> fetchInternalTransactions(String address); + Uint8List prepareSignedTransactionForSending(Uint8List signedTransaction); //! Common methods across all child classes diff --git a/cw_evm/lib/evm_chain_transaction_model.dart b/cw_evm/lib/evm_chain_transaction_model.dart index a328a2d6d..dfdeab8f5 100644 --- a/cw_evm/lib/evm_chain_transaction_model.dart +++ b/cw_evm/lib/evm_chain_transaction_model.dart @@ -32,15 +32,15 @@ class EVMChainTransactionModel { factory EVMChainTransactionModel.fromJson(Map json, String defaultSymbol) => EVMChainTransactionModel( date: DateTime.fromMillisecondsSinceEpoch(int.parse(json["timeStamp"]) * 1000), - hash: json["hash"], - from: json["from"], - to: json["to"], - amount: BigInt.parse(json["value"]), - gasUsed: int.parse(json["gasUsed"]), - gasPrice: BigInt.parse(json["gasPrice"]), - contractAddress: json["contractAddress"], - confirmations: int.parse(json["confirmations"]), - blockNumber: int.parse(json["blockNumber"]), + hash: json["hash"] ?? "", + from: json["from"] ?? "", + to: json["to"] ?? "", + amount: BigInt.parse(json["value"] ?? "0"), + gasUsed: int.parse(json["gasUsed"] ?? "0"), + gasPrice: BigInt.parse(json["gasPrice"] ?? "0"), + contractAddress: json["contractAddress"] ?? "", + confirmations: int.parse(json["confirmations"] ?? "0"), + blockNumber: int.parse(json["blockNumber"] ?? "0"), tokenSymbol: json["tokenSymbol"] ?? defaultSymbol, tokenDecimal: int.tryParse(json["tokenDecimal"] ?? ""), isError: json["isError"] == "1", diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart index 2d58e95ab..bebff4f54 100644 --- a/cw_evm/lib/evm_chain_wallet.dart +++ b/cw_evm/lib/evm_chain_wallet.dart @@ -318,6 +318,7 @@ abstract class EVMChainWalletBase Future> fetchTransactions() async { final address = _evmChainPrivateKey.address.hex; final transactions = await _client.fetchTransactions(address); + final internalTransactions = await _client.fetchInternalTransactions(address); final List>> erc20TokensTransactions = []; @@ -332,6 +333,7 @@ abstract class EVMChainWalletBase final tokensTransaction = await Future.wait(erc20TokensTransactions); transactions.addAll(tokensTransaction.expand((element) => element)); + transactions.addAll(internalTransactions); final Map result = {}; @@ -492,7 +494,7 @@ abstract class EVMChainWalletBase _transactionsUpdateTimer!.cancel(); } - _transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 10), (_) { + _transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 15), (_) { _updateTransactions(); _updateBalance(); }); diff --git a/cw_polygon/lib/polygon_client.dart b/cw_polygon/lib/polygon_client.dart index 35fbe5072..0cd671e41 100644 --- a/cw_polygon/lib/polygon_client.dart +++ b/cw_polygon/lib/polygon_client.dart @@ -56,4 +56,28 @@ class PolygonClient extends EVMChainClient { return []; } } + + @override + Future> fetchInternalTransactions(String address) async { + try { + final response = await httpClient.get(Uri.https("api.polygonscan.io", "/api", { + "module": "account", + "action": "txlistinternal", + "address": address, + "apikey": secrets.polygonScanApiKey, + })); + + final jsonResponse = json.decode(response.body) as Map; + + if (response.statusCode >= 200 && response.statusCode < 300 && jsonResponse['status'] != 0) { + return (jsonResponse['result'] as List) + .map((e) => EVMChainTransactionModel.fromJson(e as Map, 'ETH')) + .toList(); + } + + return []; + } catch (_) { + return []; + } + } } diff --git a/ios/Podfile b/ios/Podfile index 00b5fd2df..51622ff10 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -58,16 +58,16 @@ post_install do |installer| 'PERMISSION_CONTACTS=0', ## dart: PermissionGroup.camera - 'PERMISSION_CAMERA=0', + 'PERMISSION_CAMERA=1', ## dart: PermissionGroup.microphone - 'PERMISSION_MICROPHONE=0', + 'PERMISSION_MICROPHONE=1', ## dart: PermissionGroup.speech 'PERMISSION_SPEECH_RECOGNIZER=0', ## dart: PermissionGroup.photos - 'PERMISSION_PHOTOS=0', + 'PERMISSION_PHOTOS=1', ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse] 'PERMISSION_LOCATION=0', diff --git a/ios/Podfile.lock b/ios/Podfile.lock index be72b992d..67c0c9ee8 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -300,6 +300,6 @@ SPEC CHECKSUMS: wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47 workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6 -PODFILE CHECKSUM: fcb1b8418441a35b438585c9dd8374e722e6c6ca +PODFILE CHECKSUM: a2fe518be61cdbdc5b0e2da085ab543d556af2d3 COCOAPODS: 1.15.2 diff --git a/lib/entities/background_tasks.dart b/lib/entities/background_tasks.dart index ce1e2f6d8..5db42381e 100644 --- a/lib/entities/background_tasks.dart +++ b/lib/entities/background_tasks.dart @@ -4,6 +4,7 @@ import 'package:cake_wallet/core/wallet_loading_service.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/utils/device_info.dart'; +import 'package:cake_wallet/utils/feature_flag.dart'; import 'package:cake_wallet/view_model/settings/sync_mode.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart'; @@ -107,7 +108,7 @@ class BackgroundTasks { final SyncMode syncMode = settingsStore.currentSyncMode; final bool syncAll = settingsStore.currentSyncAll; - if (syncMode.type == SyncType.disabled) { + if (syncMode.type == SyncType.disabled || !FeatureFlag.isBackgroundSyncEnabled) { cancelSyncTask(); return; } diff --git a/lib/entities/biometric_auth.dart b/lib/entities/biometric_auth.dart index a0afc070a..febbfa469 100644 --- a/lib/entities/biometric_auth.dart +++ b/lib/entities/biometric_auth.dart @@ -10,6 +10,7 @@ class BiometricAuth { return await _localAuth.authenticate( localizedReason: S.current.biometric_auth_reason, options: AuthenticationOptions( + biometricOnly: true, useErrorDialogs: true, stickyAuth: false)); } on PlatformException catch (e) { diff --git a/lib/src/screens/exchange/widgets/exchange_card.dart b/lib/src/screens/exchange/widgets/exchange_card.dart index 8fa809de9..760b0c137 100644 --- a/lib/src/screens/exchange/widgets/exchange_card.dart +++ b/lib/src/screens/exchange/widgets/exchange_card.dart @@ -485,14 +485,14 @@ class ExchangeCardState extends State { context: context, builder: (dialogContext) { return AlertWithTwoActions( - alertTitle: S.of(context).overwrite_amount, - alertContent: S.of(context).qr_payment_amount, - rightButtonText: S.of(context).ok, - leftButtonText: S.of(context).cancel, + alertTitle: S.of(dialogContext).overwrite_amount, + alertContent: S.of(dialogContext).qr_payment_amount, + rightButtonText: S.of(dialogContext).ok, + leftButtonText: S.of(dialogContext).cancel, actionRightButton: () { widget.amountFocusNode?.requestFocus(); amountController.text = paymentRequest.amount; - Navigator.of(context).pop(); + Navigator.of(dialogContext).pop(); }, actionLeftButton: () => Navigator.of(dialogContext).pop()); }); diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart index cc04944b3..8c4da4cc5 100644 --- a/lib/src/screens/settings/connection_sync_page.dart +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -15,7 +15,6 @@ import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/widgets/standard_list.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -43,7 +42,7 @@ class ConnectionSyncPage extends BasePage { title: S.current.rescan, handler: (context) => Navigator.of(context).pushNamed(Routes.rescan), ), - if (DeviceInfo.instance.isMobile) ...[ + if (DeviceInfo.instance.isMobile && FeatureFlag.isBackgroundSyncEnabled) ...[ Observer(builder: (context) { return SettingsPickerCell( title: S.current.background_sync_mode, diff --git a/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart b/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart index d629e9454..e16026073 100644 --- a/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart +++ b/lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart @@ -27,10 +27,12 @@ class UnspentCoinsListItem extends StatelessWidget { Widget build(BuildContext context) { final unselectedItemColor = Theme.of(context).cardColor; final selectedItemColor = Theme.of(context).primaryColor; - final itemColor = isSending ? selectedItemColor : unselectedItemColor; - - final amountColor = - isSending ? Colors.white : Theme.of(context).extension()!.buttonTextColor; + final itemColor = isSending + ? selectedItemColor + : unselectedItemColor; + final amountColor = isSending + ? Colors.white + : Theme.of(context).extension()!.buttonTextColor; final addressColor = isSending ? Colors.white.withOpacity(0.5) : Theme.of(context).extension()!.buttonSecondaryTextColor; @@ -85,7 +87,7 @@ class UnspentCoinsListItem extends StatelessWidget { child: Text( S.of(context).frozen, style: TextStyle( - color: amountColor, fontSize: 7, fontWeight: FontWeight.w600), + color: Colors.black, fontSize: 7, fontWeight: FontWeight.w600), )), ], ), diff --git a/lib/src/widgets/services_updates_widget.dart b/lib/src/widgets/services_updates_widget.dart index 65dbe5e40..d094caf7f 100644 --- a/lib/src/widgets/services_updates_widget.dart +++ b/lib/src/widgets/services_updates_widget.dart @@ -111,7 +111,7 @@ class _ServicesUpdatesWidgetState extends State { color: Theme.of(context).extension()!.pageTitleTextColor, width: 30, ), - if (state.hasData && state.data!.hasUpdates) + if (state.hasData && state.data!.hasUpdates && !wasOpened) Container( height: 7, width: 7, diff --git a/lib/utils/feature_flag.dart b/lib/utils/feature_flag.dart index 2a29bd949..f71e6b489 100644 --- a/lib/utils/feature_flag.dart +++ b/lib/utils/feature_flag.dart @@ -2,4 +2,5 @@ class FeatureFlag { static const bool isCakePayEnabled = false; static const bool isExolixEnabled = true; static const bool isInAppTorEnabled = false; + static const bool isBackgroundSyncEnabled = false; } \ No newline at end of file From a9b8c03e55ba8e49e22d67496f4d4ee8c2a790a2 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Fri, 29 Mar 2024 19:55:29 +0100 Subject: [PATCH 142/241] CW-596-Solana-Bug-Fixes (#1340) * fix: Generic bug fixes across solana * fix: Remove back and forth parsing * fix: Add check to cut flow when estimated fee is higher than wallet balance * Update error message for fees exception * Remove logs --------- Co-authored-by: Omar Hatem --- cw_evm/lib/evm_chain_client.dart | 8 +- cw_evm/lib/evm_chain_exceptions.dart | 11 ++ cw_evm/lib/evm_chain_wallet.dart | 35 ++-- cw_solana/lib/solana_client.dart | 180 ++++++++++++------ cw_solana/lib/solana_wallet.dart | 56 ++++-- cw_solana/lib/solana_wallet_service.dart | 33 +++- lib/solana/cw_solana.dart | 23 ++- .../screens/dashboard/edit_token_page.dart | 12 +- lib/src/screens/send/widgets/send_card.dart | 7 +- .../dashboard/home_settings_view_model.dart | 31 ++- lib/view_model/send/output.dart | 5 + lib/view_model/send/send_view_model.dart | 7 +- tool/configure.dart | 7 +- 13 files changed, 297 insertions(+), 118 deletions(-) diff --git a/cw_evm/lib/evm_chain_client.dart b/cw_evm/lib/evm_chain_client.dart index 834e130a3..cf73b13db 100644 --- a/cw_evm/lib/evm_chain_client.dart +++ b/cw_evm/lib/evm_chain_client.dart @@ -82,7 +82,7 @@ abstract class EVMChainClient { Future signTransaction({ required EthPrivateKey privateKey, required String toAddress, - required String amount, + required BigInt amount, required int gas, required EVMChainTransactionPriority priority, required CryptoCurrency currency, @@ -103,7 +103,7 @@ abstract class EVMChainClient { from: privateKey.address, to: EthereumAddress.fromHex(toAddress), maxPriorityFeePerGas: EtherAmount.fromInt(EtherUnit.gwei, priority.tip), - amount: isEVMCompatibleChain ? EtherAmount.inWei(BigInt.parse(amount)) : EtherAmount.zero(), + amount: isEVMCompatibleChain ? EtherAmount.inWei(amount) : EtherAmount.zero(), data: data != null ? hexToBytes(data) : null, ); @@ -124,7 +124,7 @@ abstract class EVMChainClient { _sendTransaction = () async { await erc20.transfer( EthereumAddress.fromHex(toAddress), - BigInt.parse(amount), + amount, credentials: privateKey, transaction: transaction, ); @@ -133,7 +133,7 @@ abstract class EVMChainClient { return PendingEVMChainTransaction( signedTransaction: signedTransaction, - amount: amount, + amount: amount.toString(), fee: BigInt.from(gas) * (await price).getInWei, sendTransaction: _sendTransaction, exponent: exponent, diff --git a/cw_evm/lib/evm_chain_exceptions.dart b/cw_evm/lib/evm_chain_exceptions.dart index 1c09ecf6d..8aa371b19 100644 --- a/cw_evm/lib/evm_chain_exceptions.dart +++ b/cw_evm/lib/evm_chain_exceptions.dart @@ -9,3 +9,14 @@ class EVMChainTransactionCreationException implements Exception { @override String toString() => exceptionMessage; } + + +class EVMChainTransactionFeesException implements Exception { + final String exceptionMessage; + + EVMChainTransactionFeesException() + : exceptionMessage = 'Current balance is less than the estimated fees for this transaction.'; + + @override + String toString() => exceptionMessage; +} diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart index bebff4f54..c90a3e809 100644 --- a/cw_evm/lib/evm_chain_wallet.dart +++ b/cw_evm/lib/evm_chain_wallet.dart @@ -234,7 +234,7 @@ abstract class EVMChainWalletBase final CryptoCurrency transactionCurrency = balance.keys.firstWhere((element) => element.title == _credentials.currency.title); - final _erc20Balance = balance[transactionCurrency]!; + final erc20Balance = balance[transactionCurrency]!; BigInt totalAmount = BigInt.zero; int exponent = transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18; num amountToEVMChainMultiplier = pow(10, exponent); @@ -249,7 +249,7 @@ abstract class EVMChainWalletBase outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0))); totalAmount = BigInt.from(totalOriginalAmount * amountToEVMChainMultiplier); - if (_erc20Balance.balance < totalAmount) { + if (erc20Balance.balance < totalAmount) { throw EVMChainTransactionCreationException(transactionCurrency); } } else { @@ -258,18 +258,27 @@ abstract class EVMChainWalletBase // then no need to subtract the fees from the amount if send all final BigInt allAmount; if (transactionCurrency is Erc20Token) { - allAmount = _erc20Balance.balance; + allAmount = erc20Balance.balance; } else { - allAmount = _erc20Balance.balance - - BigInt.from(calculateEstimatedFee(_credentials.priority!, null)); - } - final totalOriginalAmount = - EVMChainFormatter.parseEVMChainAmountToDouble(output.formattedCryptoAmount ?? 0); - totalAmount = output.sendAll - ? allAmount - : BigInt.from(totalOriginalAmount * amountToEVMChainMultiplier); + final estimatedFee = BigInt.from(calculateEstimatedFee(_credentials.priority!, null)); - if (_erc20Balance.balance < totalAmount) { + if (estimatedFee > erc20Balance.balance) { + throw EVMChainTransactionFeesException(); + } + + allAmount = erc20Balance.balance - estimatedFee; + } + + if (output.sendAll) { + totalAmount = allAmount; + } else { + final totalOriginalAmount = + EVMChainFormatter.parseEVMChainAmountToDouble(output.formattedCryptoAmount ?? 0); + + totalAmount = BigInt.from(totalOriginalAmount * amountToEVMChainMultiplier); + } + + if (erc20Balance.balance < totalAmount) { throw EVMChainTransactionCreationException(transactionCurrency); } } @@ -279,7 +288,7 @@ abstract class EVMChainWalletBase toAddress: _credentials.outputs.first.isParsedAddress ? _credentials.outputs.first.extractedAddress! : _credentials.outputs.first.address, - amount: totalAmount.toString(), + amount: totalAmount, gas: _estimatedGas!, priority: _credentials.priority!, currency: transactionCurrency, diff --git a/cw_solana/lib/solana_client.dart b/cw_solana/lib/solana_client.dart index ea4a9161a..781fff5f7 100644 --- a/cw_solana/lib/solana_client.dart +++ b/cw_solana/lib/solana_client.dart @@ -96,16 +96,30 @@ class SolanaWalletClient { return SolanaBalance(totalBalance); } - Future getGasForMessage(String message) async { + Future getFeeForMessage(String message, Commitment commitment) async { try { - final gasPrice = await _client!.rpcClient.getFeeForMessage(message) ?? 0; - final fee = gasPrice / lamportsPerSol; + final feeForMessage = + await _client!.rpcClient.getFeeForMessage(message, commitment: commitment); + final fee = (feeForMessage ?? 0.0) / lamportsPerSol; return fee; } catch (_) { - return 0; + return 0.0; } } + Future getEstimatedFee(Ed25519HDKeyPair ownerKeypair) async { + const commitment = Commitment.confirmed; + + final message = + _getMessageForNativeTransaction(ownerKeypair, ownerKeypair.address, lamportsPerSol); + + final recentBlockhash = await _getRecentBlockhash(commitment); + + final estimatedFee = + _getFeeFromCompiledMessage(message, ownerKeypair.publicKey, recentBlockhash, commitment); + return estimatedFee; + } + /// Load the Address's transactions into the account Future> fetchTransactions( Ed25519HDPublicKey publicKey, { @@ -257,24 +271,15 @@ class SolanaWalletClient { Future signSolanaTransaction({ required String tokenTitle, required int tokenDecimals, - String? tokenMint, required double inputAmount, required String destinationAddress, required Ed25519HDKeyPair ownerKeypair, + required bool isSendAll, + String? tokenMint, List references = const [], }) async { const commitment = Commitment.confirmed; - final latestBlockhash = - await _client!.rpcClient.getLatestBlockhash(commitment: commitment).value; - - final recentBlockhash = RecentBlockhash( - blockhash: latestBlockhash.blockhash, - feeCalculator: const FeeCalculator( - lamportsPerSignature: 500, - ), - ); - if (tokenTitle == CryptoCurrency.sol.title) { final pendingNativeTokenTransaction = await _signNativeTokenTransaction( tokenTitle: tokenTitle, @@ -282,8 +287,8 @@ class SolanaWalletClient { inputAmount: inputAmount, destinationAddress: destinationAddress, ownerKeypair: ownerKeypair, - recentBlockhash: recentBlockhash, commitment: commitment, + isSendAll: isSendAll, ); return pendingNativeTokenTransaction; } else { @@ -294,25 +299,29 @@ class SolanaWalletClient { inputAmount: inputAmount, destinationAddress: destinationAddress, ownerKeypair: ownerKeypair, - recentBlockhash: recentBlockhash, commitment: commitment, ); return pendingSPLTokenTransaction; } } - Future _signNativeTokenTransaction({ - required String tokenTitle, - required int tokenDecimals, - required double inputAmount, - required String destinationAddress, - required Ed25519HDKeyPair ownerKeypair, - required RecentBlockhash recentBlockhash, - required Commitment commitment, - }) async { - // Convert SOL to lamport - int lamports = (inputAmount * lamportsPerSol).toInt(); + Future _getRecentBlockhash(Commitment commitment) async { + final latestBlockhash = + await _client!.rpcClient.getLatestBlockhash(commitment: commitment).value; + final recentBlockhash = RecentBlockhash( + blockhash: latestBlockhash.blockhash, + feeCalculator: const FeeCalculator(lamportsPerSignature: 500), + ); + + return recentBlockhash; + } + + Message _getMessageForNativeTransaction( + Ed25519HDKeyPair ownerKeypair, + String destinationAddress, + int lamports, + ) { final instructions = [ SystemInstruction.transfer( fundingAccount: ownerKeypair.publicKey, @@ -322,21 +331,75 @@ class SolanaWalletClient { ]; final message = Message(instructions: instructions); + return message; + } + + Future _getFeeFromCompiledMessage( + Message message, + Ed25519HDPublicKey feePayer, + RecentBlockhash recentBlockhash, + Commitment commitment, + ) async { + final compile = message.compile( + recentBlockhash: recentBlockhash.blockhash, + feePayer: feePayer, + ); + + final base64Message = base64Encode(compile.toByteArray().toList()); + + final fee = await getFeeForMessage(base64Message, commitment); + + return fee; + } + + Future _signNativeTokenTransaction({ + required String tokenTitle, + required int tokenDecimals, + required double inputAmount, + required String destinationAddress, + required Ed25519HDKeyPair ownerKeypair, + required Commitment commitment, + required bool isSendAll, + }) async { + // Convert SOL to lamport + int lamports = (inputAmount * lamportsPerSol).toInt(); + + Message message = _getMessageForNativeTransaction(ownerKeypair, destinationAddress, lamports); + final signers = [ownerKeypair]; - final signedTx = await _signTransactionInternal( - message: message, - signers: signers, - commitment: commitment, - recentBlockhash: recentBlockhash, - ); + RecentBlockhash recentBlockhash = await _getRecentBlockhash(commitment); final fee = await _getFeeFromCompiledMessage( message, - recentBlockhash, signers.first.publicKey, + recentBlockhash, + commitment, ); + SignedTx signedTx; + if (isSendAll) { + final feeInLamports = (fee * lamportsPerSol).toInt(); + final updatedLamports = lamports - feeInLamports; + + final updatedMessage = + _getMessageForNativeTransaction(ownerKeypair, destinationAddress, updatedLamports); + + signedTx = await _signTransactionInternal( + message: updatedMessage, + signers: signers, + commitment: commitment, + recentBlockhash: recentBlockhash, + ); + } else { + signedTx = await _signTransactionInternal( + message: message, + signers: signers, + commitment: commitment, + recentBlockhash: recentBlockhash, + ); + } + sendTx() async => await sendTransaction( signedTransaction: signedTx, commitment: commitment, @@ -360,7 +423,6 @@ class SolanaWalletClient { required double inputAmount, required String destinationAddress, required Ed25519HDKeyPair ownerKeypair, - required RecentBlockhash recentBlockhash, required Commitment commitment, }) async { final destinationOwner = Ed25519HDPublicKey.fromBase58(destinationAddress); @@ -408,8 +470,18 @@ class SolanaWalletClient { ); final message = Message(instructions: [instruction]); + final signers = [ownerKeypair]; + RecentBlockhash recentBlockhash = await _getRecentBlockhash(commitment); + + final fee = await _getFeeFromCompiledMessage( + message, + signers.first.publicKey, + recentBlockhash, + commitment, + ); + final signedTx = await _signTransactionInternal( message: message, signers: signers, @@ -417,12 +489,6 @@ class SolanaWalletClient { recentBlockhash: recentBlockhash, ); - final fee = await _getFeeFromCompiledMessage( - message, - recentBlockhash, - signers.first.publicKey, - ); - sendTx() async => await sendTransaction( signedTransaction: signedTx, commitment: commitment, @@ -438,19 +504,6 @@ class SolanaWalletClient { return pendingTransaction; } - Future _getFeeFromCompiledMessage( - Message message, RecentBlockhash recentBlockhash, Ed25519HDPublicKey feePayer) async { - final compile = message.compile( - recentBlockhash: recentBlockhash.blockhash, - feePayer: feePayer, - ); - - final base64Message = base64Encode(compile.toByteArray().toList()); - - final fee = await getGasForMessage(base64Message); - return fee; - } - Future _signTransactionInternal({ required Message message, required List signers, @@ -466,13 +519,18 @@ class SolanaWalletClient { required SignedTx signedTransaction, required Commitment commitment, }) async { - final signature = await _client!.rpcClient.sendTransaction( - signedTransaction.encode(), - preflightCommitment: commitment, - ); + try { + final signature = await _client!.rpcClient.sendTransaction( + signedTransaction.encode(), + preflightCommitment: commitment, + ); - _client!.waitForSignatureStatus(signature, status: commitment); + _client!.waitForSignatureStatus(signature, status: commitment); - return signature; + return signature; + } catch (e) { + print('Error while sending transaction: ${e.toString()}'); + throw Exception(e); + } } } diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart index de4d70674..f69a597ae 100644 --- a/cw_solana/lib/solana_wallet.dart +++ b/cw_solana/lib/solana_wallet.dart @@ -75,6 +75,9 @@ abstract class SolanaWalletBase late SolanaWalletClient _client; + @observable + double? estimatedFee; + Timer? _transactionsUpdateTimer; late final Box splTokensBox; @@ -171,6 +174,14 @@ abstract class SolanaWalletBase } } + Future _getEstimatedFees() async { + try { + estimatedFee = await _client.getEstimatedFee(_walletKeyPair!); + } catch (e) { + estimatedFee = 0.0; + } + } + @override Future createTransaction(Object credentials) async { final solCredentials = credentials as SolanaTransactionCredentials; @@ -188,6 +199,8 @@ abstract class SolanaWalletBase double totalAmount = 0.0; + bool isSendAll = false; + if (hasMultiDestination) { if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) { throw SolanaTransactionWrongBalanceException(transactionCurrency); @@ -204,9 +217,15 @@ abstract class SolanaWalletBase } else { final output = outputs.first; - final totalOriginalAmount = double.parse(output.cryptoAmount ?? '0.0'); + isSendAll = output.sendAll; - totalAmount = output.sendAll ? walletBalanceForCurrency : totalOriginalAmount; + if (isSendAll) { + totalAmount = walletBalanceForCurrency; + } else { + final totalOriginalAmount = double.parse(output.cryptoAmount ?? '0.0'); + + totalAmount = totalOriginalAmount; + } if (walletBalanceForCurrency < totalAmount) { throw SolanaTransactionWrongBalanceException(transactionCurrency); @@ -228,6 +247,7 @@ abstract class SolanaWalletBase destinationAddress: solCredentials.outputs.first.isParsedAddress ? solCredentials.outputs.first.extractedAddress! : solCredentials.outputs.first.address, + isSendAll: isSendAll, ); return pendingSolanaTransaction; @@ -269,7 +289,10 @@ abstract class SolanaWalletBase Future _updateSPLTokenTransactions() async { List splTokenTransactions = []; - for (var token in balance.keys) { + // Make a copy of keys to avoid concurrent modification + var tokenKeys = List.from(balance.keys); + + for (var token in tokenKeys) { if (token is SPLToken) { final tokenTxs = await _client.getSPLTokenTransfers( token.mintAddress, @@ -326,6 +349,7 @@ abstract class SolanaWalletBase _updateBalance(), _updateNativeSOLTransactions(), _updateSPLTokenTransactions(), + _getEstimatedFees(), ]); syncStatus = SyncedSyncStatus(); @@ -433,18 +457,22 @@ abstract class SolanaWalletBase final mintPublicKey = Ed25519HDPublicKey.fromBase58(mintAddress); // Fetch token's metadata account - final token = await solanaClient!.rpcClient.getMetadata(mint: mintPublicKey); + try { + final token = await solanaClient!.rpcClient.getMetadata(mint: mintPublicKey); - if (token == null) { + if (token == null) { + return null; + } + + return SPLToken.fromMetadata( + name: token.name, + mint: token.mint, + symbol: token.symbol, + mintAddress: mintAddress, + ); + } catch (e) { return null; } - - return SPLToken.fromMetadata( - name: token.name, - mint: token.mint, - symbol: token.symbol, - mintAddress: mintAddress, - ); } @override @@ -475,9 +503,9 @@ abstract class SolanaWalletBase } _transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 20), (_) { - _updateSPLTokenTransactions(); - _updateNativeSOLTransactions(); _updateBalance(); + _updateNativeSOLTransactions(); + _updateSPLTokenTransactions(); }); } diff --git a/cw_solana/lib/solana_wallet_service.dart b/cw_solana/lib/solana_wallet_service.dart index b3ff22e7e..83370ff73 100644 --- a/cw_solana/lib/solana_wallet_service.dart +++ b/cw_solana/lib/solana_wallet_service.dart @@ -32,6 +32,7 @@ class SolanaWalletService extends WalletService openWallet(String name, String password) async { final walletInfo = walletInfoSource.values.firstWhere((info) => info.id == WalletBase.idFor(name, getType())); - final wallet = await SolanaWalletBase.open( - name: name, - password: password, - walletInfo: walletInfo, - ); - await wallet.init(); - await wallet.save(); + try { + final wallet = await SolanaWalletBase.open( + name: name, + password: password, + walletInfo: walletInfo, + ); - return wallet; + await wallet.init(); + await wallet.save(); + saveBackup(name); + return wallet; + } catch (_) { + await restoreWalletFilesFromBackup(name); + + final wallet = await SolanaWalletBase.open( + name: name, + password: password, + walletInfo: walletInfo, + ); + + await wallet.init(); + await wallet.save(); + return wallet; + } } @override @@ -110,6 +126,7 @@ class SolanaWalletService extends WalletService addSPLToken(WalletBase wallet, CryptoCurrency token) async => - await (wallet as SolanaWallet).addSPLToken(token as SPLToken); + Future addSPLToken( + WalletBase wallet, + CryptoCurrency token, + String contractAddress, + ) async { + final splToken = SPLToken( + name: token.name, + symbol: token.title, + mintAddress: contractAddress, + decimal: token.decimals, + mint: token.name.toUpperCase(), + enabled: token.enabled, + ); + + await (wallet as SolanaWallet).addSPLToken(splToken); + } @override Future deleteSPLToken(WalletBase wallet, CryptoCurrency token) async => @@ -115,4 +129,9 @@ class CWSolana extends Solana { return null; } + + @override + double? getEstimateFees(WalletBase wallet) { + return (wallet as SolanaWallet).estimatedFee; + } } diff --git a/lib/src/screens/dashboard/edit_token_page.dart b/lib/src/screens/dashboard/edit_token_page.dart index 720a8cc14..1a1db8658 100644 --- a/lib/src/screens/dashboard/edit_token_page.dart +++ b/lib/src/screens/dashboard/edit_token_page.dart @@ -195,12 +195,14 @@ class _EditTokenPageBodyState extends State { onPressed: () async { if (_formKey.currentState!.validate() && (!_showDisclaimer || _disclaimerChecked)) { - await widget.homeSettingsViewModel.addToken(Erc20Token( - name: _tokenNameController.text, - symbol: _tokenSymbolController.text, + await widget.homeSettingsViewModel.addToken( + token: CryptoCurrency( + name: _tokenNameController.text, + title: _tokenSymbolController.text.toUpperCase(), + decimals: int.parse(_tokenDecimalController.text), + ), contractAddress: _contractAddressController.text, - decimal: int.parse(_tokenDecimalController.text), - )); + ); if (context.mounted) { Navigator.pop(context); } diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 3f5714be9..d36997814 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -323,8 +323,7 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin with AutomaticKeepAliveClientMixin GestureDetector( - onTap: () => _setTransactionPriority(context), + onTap: sendViewModel.hasFeesPriority + ? () => _setTransactionPriority(context) + : () {}, child: Container( padding: EdgeInsets.only(top: 24), child: Row( diff --git a/lib/view_model/dashboard/home_settings_view_model.dart b/lib/view_model/dashboard/home_settings_view_model.dart index 6d31a5af8..4b9811c37 100644 --- a/lib/view_model/dashboard/home_settings_view_model.dart +++ b/lib/view_model/dashboard/home_settings_view_model.dart @@ -44,17 +44,37 @@ abstract class HomeSettingsViewModelBase with Store { @action void setPinNativeToken(bool value) => _settingsStore.pinNativeTokenAtTop = value; - Future addToken(CryptoCurrency token) async { + Future addToken({ + required String contractAddress, + required CryptoCurrency token, + }) async { if (_balanceViewModel.wallet.type == WalletType.ethereum) { - await ethereum!.addErc20Token(_balanceViewModel.wallet, token); + final erc20token = Erc20Token( + name: token.name, + symbol: token.title, + decimal: token.decimals, + contractAddress: contractAddress, + ); + + await ethereum!.addErc20Token(_balanceViewModel.wallet, erc20token); } if (_balanceViewModel.wallet.type == WalletType.polygon) { - await polygon!.addErc20Token(_balanceViewModel.wallet, token); + final polygonToken = Erc20Token( + name: token.name, + symbol: token.title, + decimal: token.decimals, + contractAddress: contractAddress, + ); + await polygon!.addErc20Token(_balanceViewModel.wallet, polygonToken); } if (_balanceViewModel.wallet.type == WalletType.solana) { - await solana!.addSPLToken(_balanceViewModel.wallet, token); + await solana!.addSPLToken( + _balanceViewModel.wallet, + token, + contractAddress, + ); } _updateTokensList(); @@ -117,7 +137,8 @@ abstract class HomeSettingsViewModelBase with Store { } if (_balanceViewModel.wallet.type == WalletType.solana) { - solana!.addSPLToken(_balanceViewModel.wallet, token); + final address = solana!.getTokenAddress(token); + solana!.addSPLToken(_balanceViewModel.wallet, token, address); } _refreshTokensList(); diff --git a/lib/view_model/send/output.dart b/lib/view_model/send/output.dart index c881284b3..62db9cbcd 100644 --- a/lib/view_model/send/output.dart +++ b/lib/view_model/send/output.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/haven/haven.dart'; import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; +import 'package:cake_wallet/solana/solana.dart'; import 'package:cake_wallet/src/screens/send/widgets/extract_address_from_parsed.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:flutter/material.dart'; @@ -116,6 +117,10 @@ abstract class OutputBase with Store { @computed double get estimatedFee { try { + if (_wallet.type == WalletType.solana) { + return solana!.getEstimateFees(_wallet) ?? 0.0; + } + final fee = _wallet.calculateEstimatedFee( _settingsStore.priority[_wallet.type]!, formattedCryptoAmount); diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 28f964a9c..a631cde02 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -106,8 +106,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor @computed bool get isBatchSending => outputs.length > 1; - bool get shouldDisplaySendALL => walletType != WalletType.solana; - @computed String get pendingTransactionFiatAmount { if (pendingTransaction == null) { @@ -208,6 +206,11 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor @computed bool get hasFees => wallet.type != WalletType.nano && wallet.type != WalletType.banano; + @computed + bool get hasFeesPriority => + wallet.type != WalletType.nano && + wallet.type != WalletType.banano && + wallet.type != WalletType.solana; @observable CryptoCurrency selectedCryptoCurrency; diff --git a/tool/configure.dart b/tool/configure.dart index e24ab2062..30123c45e 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -948,7 +948,11 @@ abstract class Solana { required CryptoCurrency currency, }); List getSPLTokenCurrencies(WalletBase wallet); - Future addSPLToken(WalletBase wallet, CryptoCurrency token); + Future addSPLToken( + WalletBase wallet, + CryptoCurrency token, + String contractAddress, + ); Future deleteSPLToken(WalletBase wallet, CryptoCurrency token); Future getSPLToken(WalletBase wallet, String contractAddress); @@ -956,6 +960,7 @@ abstract class Solana { double getTransactionAmountRaw(TransactionInfo transactionInfo); String getTokenAddress(CryptoCurrency asset); List? getValidationLength(CryptoCurrency type); + double? getEstimateFees(WalletBase wallet); } """; From 1f904dcd47f0fb6162154f726a547634ea7300b7 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Fri, 29 Mar 2024 20:59:26 +0200 Subject: [PATCH 143/241] Generic fixes (#1354) * Change order of currencies in currency picker * Disable Background sync until implemented properly * remove ability to use device pin in bio auth * Fix condition * Minor fix [skip ci] * make notifications red dot go when opened * Update Frozen coin text color * Update Frozen coin text color * Fetch internal transactions for eth and polygon * Remove debug prints [skip ci] * Fix Camera permission on iOS [skip ci] * Minor fixes [skip ci] --------- Co-authored-by: tuxsudo --- cw_ethereum/lib/ethereum_client.dart | 2 +- cw_polygon/lib/polygon_client.dart | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/cw_ethereum/lib/ethereum_client.dart b/cw_ethereum/lib/ethereum_client.dart index 10dc245d4..f2b25bcdd 100644 --- a/cw_ethereum/lib/ethereum_client.dart +++ b/cw_ethereum/lib/ethereum_client.dart @@ -48,7 +48,7 @@ class EthereumClient extends EVMChainClient { final response = await httpClient.get(Uri.https("api.etherscan.io", "/api", { "module": "account", "action": "txlistinternal", - "address": "0x72067Bf532b21A096D2e2B4953d69554E1a61917", + "address": address, "apikey": secrets.etherScanApiKey, })); diff --git a/cw_polygon/lib/polygon_client.dart b/cw_polygon/lib/polygon_client.dart index 0cd671e41..42fdd2e25 100644 --- a/cw_polygon/lib/polygon_client.dart +++ b/cw_polygon/lib/polygon_client.dart @@ -13,8 +13,6 @@ class PolygonClient extends EVMChainClient { required EthereumAddress to, required EtherAmount amount, EtherAmount? maxPriorityFeePerGas, - Uint8List? data, - }) { return Transaction( from: from, @@ -71,7 +69,7 @@ class PolygonClient extends EVMChainClient { if (response.statusCode >= 200 && response.statusCode < 300 && jsonResponse['status'] != 0) { return (jsonResponse['result'] as List) - .map((e) => EVMChainTransactionModel.fromJson(e as Map, 'ETH')) + .map((e) => EVMChainTransactionModel.fromJson(e as Map, 'MATIC')) .toList(); } From 62ef545fce22227bdd50f0c155c91f57d126a256 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Mon, 1 Apr 2024 15:31:14 +0200 Subject: [PATCH 144/241] New versions (#1355) * New versions * Check for Taproot inputs when exchanging with ThorChain * Properly handle taproot case with thorchain * fix missing import --- assets/text/Monerocom_Release_Notes.txt | 6 ++--- assets/text/Release_Notes.txt | 7 +++++- cw_bitcoin/lib/electrum_wallet.dart | 24 ++++++++++++------- .../lib/pending_bitcoin_transaction.dart | 22 ++++++++++------- cw_polygon/lib/polygon_client.dart | 1 + lib/bitcoin/cw_bitcoin.dart | 5 ++++ lib/view_model/send/send_view_model.dart | 16 ++++++++++++- scripts/android/app_env.sh | 8 +++---- scripts/ios/app_env.sh | 6 ++--- scripts/macos/app_env.sh | 8 +++---- tool/configure.dart | 3 +++ 11 files changed, 71 insertions(+), 35 deletions(-) diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 90fcd2a75..e6aab2dda 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,4 +1,2 @@ -Monero enhancements -In-App live status page for the app services -Add Exolix exchange provider -Bug fixes and enhancements \ No newline at end of file +Exchange flow enhancements and fixes +Generic enhancements and bug fixes \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 83e18c18e..b32cd539d 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1 +1,6 @@ -Bug fixes and enhancements \ No newline at end of file +Exchange flow enhancements and fixes +Add MoonPay to Buy options +Add THORChain to Exchange providers +Improve Bitcoin fee calculations +Fixes and enhancements for Solana +Generic enhancements and bug fixes \ No newline at end of file diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index ffd8b5d52..9c144ac74 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -544,6 +544,8 @@ abstract class ElectrumWalletBase ); } + bool hasTaprootInputs = false; + final transaction = txb.buildTransaction((txDigest, utxo, publicKey, sighash) { final key = estimatedTx.privateKeys .firstWhereOrNull((element) => element.getPublic().toHex() == publicKey); @@ -553,21 +555,25 @@ abstract class ElectrumWalletBase } if (utxo.utxo.isP2tr()) { + hasTaprootInputs = true; return key.signTapRoot(txDigest, sighash: sighash); } else { return key.signInput(txDigest, sigHash: sighash); } }); - return PendingBitcoinTransaction(transaction, type, - electrumClient: electrumClient, - amount: estimatedTx.amount, - fee: estimatedTx.fee, - feeRate: feeRateInt.toString(), - network: network, - hasChange: estimatedTx.hasChange, - isSendAll: estimatedTx.isSendAll) - ..addListener((transaction) async { + return PendingBitcoinTransaction( + transaction, + type, + electrumClient: electrumClient, + amount: estimatedTx.amount, + fee: estimatedTx.fee, + feeRate: feeRateInt.toString(), + network: network, + hasChange: estimatedTx.hasChange, + isSendAll: estimatedTx.isSendAll, + hasTaprootInputs: hasTaprootInputs, + )..addListener((transaction) async { transactionHistory.addOne(transaction); await updateBalance(); }); diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart index ada39a8f7..eb4274e78 100644 --- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart +++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart @@ -8,15 +8,18 @@ import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/wallet_type.dart'; class PendingBitcoinTransaction with PendingTransaction { - PendingBitcoinTransaction(this._tx, this.type, - {required this.electrumClient, - required this.amount, - required this.fee, - required this.feeRate, - this.network, - required this.hasChange, - required this.isSendAll}) - : _listeners = []; + PendingBitcoinTransaction( + this._tx, + this.type, { + required this.electrumClient, + required this.amount, + required this.fee, + required this.feeRate, + this.network, + required this.hasChange, + required this.isSendAll, + this.hasTaprootInputs = false, + }) : _listeners = []; final WalletType type; final BtcTransaction _tx; @@ -27,6 +30,7 @@ class PendingBitcoinTransaction with PendingTransaction { final BasedUtxoNetwork? network; final bool hasChange; final bool isSendAll; + final bool hasTaprootInputs; @override String get id => _tx.txId(); diff --git a/cw_polygon/lib/polygon_client.dart b/cw_polygon/lib/polygon_client.dart index 42fdd2e25..d55ee2269 100644 --- a/cw_polygon/lib/polygon_client.dart +++ b/cw_polygon/lib/polygon_client.dart @@ -13,6 +13,7 @@ class PolygonClient extends EVMChainClient { required EthereumAddress to, required EtherAmount amount, EtherAmount? maxPriorityFeePerGas, + Uint8List? data, }) { return Transaction( from: from, diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index c9649a2e3..882facf39 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -239,4 +239,9 @@ class CWBitcoin extends Bitcoin { return SegwitAddresType.p2wpkh; } } + + @override + bool hasTaprootInput(PendingTransaction pendingTransaction) { + return (pendingTransaction as PendingBitcoinTransaction).hasTaprootInputs; + } } diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index a631cde02..df1c75def 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -308,13 +308,19 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor pendingTransaction = await wallet.createTransaction(_credentials()); if (provider is ThorChainExchangeProvider) { final outputCount = pendingTransaction?.outputCount ?? 0; - if (outputCount > 10) throw Exception("ThorChain does not support more than 10 outputs"); + if (outputCount > 10) { + throw Exception("ThorChain does not support more than 10 outputs"); + } + if (_hasTaprootInput(pendingTransaction)) { + throw Exception("ThorChain does not support Taproot addresses"); + } } state = ExecutedSuccessfullyState(); return pendingTransaction; } catch (e) { state = FailureState(translateErrorMessage(e, wallet.type, wallet.currency)); } + return null; } @action @@ -512,4 +518,12 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor return errorMessage; } + + bool _hasTaprootInput(PendingTransaction? pendingTransaction) { + if (walletType == WalletType.bitcoin && pendingTransaction != null) { + return bitcoin!.hasTaprootInput(pendingTransaction); + } + + return false; + } } diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index ed2b67de5..8387c1d1f 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.12.0" -MONERO_COM_BUILD_NUMBER=79 +MONERO_COM_VERSION="1.12.1" +MONERO_COM_BUILD_NUMBER=80 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.15.2" -CAKEWALLET_BUILD_NUMBER=200 +CAKEWALLET_VERSION="4.15.3" +CAKEWALLET_BUILD_NUMBER=202 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 53514b39b..7e4f214ab 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.12.0" +MONERO_COM_VERSION="1.12.1" MONERO_COM_BUILD_NUMBER=77 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.15.2" -CAKEWALLET_BUILD_NUMBER=219 +CAKEWALLET_VERSION="4.15.3" +CAKEWALLET_BUILD_NUMBER=221 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 1654a022a..1242945a6 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -16,13 +16,13 @@ if [ -n "$1" ]; then fi MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.2.0" -MONERO_COM_BUILD_NUMBER=10 +MONERO_COM_VERSION="1.2.1" +MONERO_COM_BUILD_NUMBER=11 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.8.2" -CAKEWALLET_BUILD_NUMBER=59 +CAKEWALLET_VERSION="1.8.3" +CAKEWALLET_BUILD_NUMBER=61 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then diff --git a/tool/configure.dart b/tool/configure.dart index 30123c45e..b3aa44feb 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -61,6 +61,7 @@ Future main(List args) async { Future generateBitcoin(bool hasImplementation) async { final outputFile = File(bitcoinOutputPath); const bitcoinCommonHeaders = """ +import 'package:cw_core/pending_transaction.dart'; import 'package:cw_core/receive_page_option.dart'; import 'package:cw_core/unspent_transaction_output.dart'; import 'package:cw_core/wallet_credentials.dart'; @@ -74,6 +75,7 @@ import 'package:cake_wallet/view_model/send/output.dart'; import 'package:hive/hive.dart'; import 'package:bitcoin_base/bitcoin_base.dart';"""; const bitcoinCWHeaders = """ +import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/bitcoin_receive_page_option.dart'; import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:cw_bitcoin/bitcoin_unspent.dart'; @@ -148,6 +150,7 @@ abstract class Bitcoin { ReceivePageOption getSelectedAddressType(Object wallet); List getBitcoinReceivePageOptions(); BitcoinAddressType getBitcoinAddressType(ReceivePageOption option); + bool hasTaprootInput(PendingTransaction pendingTransaction); } """; From 7eed97718e6f1d037b7f21787d2e8cd59fad2a95 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Tue, 2 Apr 2024 11:02:28 -0700 Subject: [PATCH 145/241] disable service status api if fiat api is disabled (#1357) --- lib/entities/default_settings_migration.dart | 17 ++++++++++ lib/main.dart | 33 ++++++++++---------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 8ce38e4c4..944d91cd3 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -1,6 +1,7 @@ import 'dart:io' show Directory, File, Platform; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; +import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; @@ -211,6 +212,10 @@ Future defaultSettingsMigration( await changeDefaultBitcoinNode(nodes, sharedPreferences); break; + case 30: + await disableServiceStatusFiatDisabled(sharedPreferences); + break; + default: break; } @@ -225,6 +230,18 @@ Future defaultSettingsMigration( await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version); } +Future disableServiceStatusFiatDisabled(SharedPreferences sharedPreferences) async { + final currentFiat = + await sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey) ?? -1; + if (currentFiat == -1 || currentFiat == FiatApiMode.enabled.raw) { + return; + } + + if (currentFiat == FiatApiMode.disabled.raw) { + await sharedPreferences.setBool(PreferencesKey.disableBulletinKey, true); + } +} + Future _updateMoneroPriority(SharedPreferences sharedPreferences) async { final currentPriority = await sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority) ?? diff --git a/lib/main.dart b/lib/main.dart index db505f15a..6868348f6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -149,25 +149,26 @@ Future initializeAppConfigs() async { final unspentCoinsInfoSource = await CakeHive.openBox(UnspentCoinsInfo.boxName); await initialSetup( - sharedPreferences: await SharedPreferences.getInstance(), - nodes: nodes, - powNodes: powNodes, - walletInfoSource: walletInfoSource, - contactSource: contacts, - tradesSource: trades, - ordersSource: orders, - unspentCoinsInfoSource: unspentCoinsInfoSource, - // fiatConvertationService: fiatConvertationService, - templates: templates, - exchangeTemplates: exchangeTemplates, - transactionDescriptions: transactionDescriptions, - secureStorage: secureStorage, - anonpayInvoiceInfo: anonpayInvoiceInfo, - initialMigrationVersion: 29); + sharedPreferences: await SharedPreferences.getInstance(), + nodes: nodes, + powNodes: powNodes, + walletInfoSource: walletInfoSource, + contactSource: contacts, + tradesSource: trades, + ordersSource: orders, + unspentCoinsInfoSource: unspentCoinsInfoSource, + // fiatConvertationService: fiatConvertationService, + templates: templates, + exchangeTemplates: exchangeTemplates, + transactionDescriptions: transactionDescriptions, + secureStorage: secureStorage, + anonpayInvoiceInfo: anonpayInvoiceInfo, + initialMigrationVersion: 30, + ); } Future initialSetup( - {required SharedPreferences sharedPreferences, + {required SharedPreferences sharedPreferences, required Box nodes, required Box powNodes, required Box walletInfoSource, From dbb62ef5c0cac9bc1af6fa88594e533ac907de3e Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Fri, 5 Apr 2024 09:11:47 -0700 Subject: [PATCH 146/241] update migration behavior slightly (#1364) --- lib/entities/default_settings_migration.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 944d91cd3..9a2db56af 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -237,7 +237,7 @@ Future disableServiceStatusFiatDisabled(SharedPreferences sharedPreference return; } - if (currentFiat == FiatApiMode.disabled.raw) { + if (currentFiat == FiatApiMode.disabled.raw || currentFiat == FiatApiMode.torOnly.raw) { await sharedPreferences.setBool(PreferencesKey.disableBulletinKey, true); } } From 653a6c678d0ff11806dc1cefb5900861d92584bb Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 15:45:49 -0400 Subject: [PATCH 147/241] Add app badge icons --- .github/assets/FullLogo_CakeWallet.png | Bin 0 -> 187345 bytes .github/assets/NOTICE.txt | 48 ++ .github/assets/app-store-badge.svg | 46 + .github/assets/f-droid-badge.png | Bin 0 -> 18971 bytes .github/assets/google-play-badge.png | Bin 0 -> 4904 bytes .github/assets/linux-badge.svg | 1071 ++++++++++++++++++++++++ .github/assets/mac-store-badge.svg | 51 ++ 7 files changed, 1216 insertions(+) create mode 100644 .github/assets/FullLogo_CakeWallet.png create mode 100644 .github/assets/NOTICE.txt create mode 100755 .github/assets/app-store-badge.svg create mode 100644 .github/assets/f-droid-badge.png create mode 100644 .github/assets/google-play-badge.png create mode 100755 .github/assets/linux-badge.svg create mode 100755 .github/assets/mac-store-badge.svg diff --git a/.github/assets/FullLogo_CakeWallet.png b/.github/assets/FullLogo_CakeWallet.png new file mode 100644 index 0000000000000000000000000000000000000000..9720c0c9e9f365455b6051af83ec770f55198674 GIT binary patch literal 187345 zcmeEvd0b8T|Nlv*n29Dn$QE)HhPt*$tFa^^#!tJ@UJKEk8FS%{N&yrKm8B>HE`!rr(Fy)VhH+2#XafK4@|#`Q0qkte)K<4 zC%>_Jbbz$|U+LMXvcoEy*_m8Ij9%yj)#w{<4l0Br6$8w3>Pq(wP;(zYlk+uvH+@u| zOeZMcNZd2stlX~jbY{Lm1M~WJ$wm7V*y+6(20XXfsZCn}%+U{%bW!Jq$`ySzyB`Jb7ilP;@%{)6OcN5+2sXU6ToeYnbP{fA`r6nQF1QUcjD^z4u~oJg;|eGP{8k%&92O?S0p;`Y1vW{&xV-^ zoXqoHnC~^P2+lfQ>_utUR1(xwm>n|j-tyUg?cD)Gn#b7O$l93mA#y}(OiGt$SDOXl z&AFwt?8^K3e%#sK9Vm|dZg-enbd$lB6Y)9UdRy9s|{_!XCpl9vl@jKjhg)6h`%pqk$bQNg_BN0b19aRjF18kj8bvU{{O@+_ z2V7g~H^kvBWAxTwlYf?tPyFU<$BSd?Uz1}=m3(OWdgFX9VSFx;Q?9b!-4qJ!Db#*6 zR=?|A$m5?hnY5OpRXtr!A%O^z7u5(iw=1!b`>5@v_j+{dj=2}x8Ht@{z%_rrq~;oV zu<|fxXkD9ogc<)RxM$3jr>gvB`K!VRzpUxE30<{H*4%yb{@-b?`MXm~RGLO<21GTq z?CJ7CJfzyt{WYzdOZ*U^v>$>Xb*xsY^CHt%>2J`HJ?E0redkGfvnmtaJi~RrUk5!TZ?2T<3V0~SFzxZ!40y<- za*E+Y`S$##hD-7>m>aTSCFPao(jP!$-Yy%JNJ-LBDoHL0B)MVz&)MmM9ZxT+Fd+{Y z=0-Ne(8ny7(=8R_V6hXi$qj;&u%(rzbwleAxjbtOK~aT(;ybs=?nl3vs&n#DO!ASl zdjj4zj|y)f509qX%65UZ-4gk>Xd=91 zRN4BbVauGP=}O)wO(5HHX01*?cDxNh5?b|mVQ$XuEKg(9Yhsw515}&aEz33C0}j-z zboNqVI`<#ynwcG>e8^m%t~2&ApjzCT^NX)~eHp`aUy_N0>|38)riZPemVsY{MIdQdQ8=ApoZlU;(ld;0(4q9Ry%b}t zF37Vew!CIAl0aOf)YQr^rK>Kt9yQ7sru_)rcvN7nyv?3GFT-qmb(h$QG(CE>LA3zmO+WhSl-Dqf(W^X%2B3FE#T2|l-4Ocr1t&OK zz%_gF*xJs+vETU>X0E{x#m!Vcw4hw`wvv^K9p+ndeEhB-FK(z*GF8j@cP2Zp{}xc;Q{Hhsur0ae)E z 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

    M^1$%3dNqM_UJ_x+CMb~ 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

    -* Website: https://cakewallet.com -* App Store (iOS / MacOS): https://cakewallet.com/ios -* Google Play: https://cakewallet.com/gp -* F-Droid: https://fdroid.cakelabs.com -* APK: https://github.com/cake-tech/cake_wallet/releases -* Linux: https://github.com/cake-tech/cake_wallet/releases +# Cake Wallet + +Cake Wallet is an open source, non-custodial, and private multi-currency crypto wallet. + +
    + +[](https://apps.apple.com/us/app/cake-wallet/id1334702542?platform=iphone) +[](https://play.google.com/store/apps/details?id=com.cakewallet.cake_wallet) +[](https://fdroid.cakelabs.com) +[](https://apps.apple.com/us/app/cake-wallet/id1334702542?platform=mac) +[](https://github.com/cake-tech/cake_wallet/releases) + +
    ## Features From 7b622230017aa6241a9b8d2c893085e971cc8d3b Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 19:03:52 -0400 Subject: [PATCH 150/241] Add more images --- .github/assets/desktop.png | Bin 0 -> 62736 bytes .github/assets/devices.png | Bin 0 -> 485931 bytes .github/assets/mobile.png | Bin 0 -> 154871 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 .github/assets/desktop.png create mode 100644 .github/assets/devices.png create mode 100644 .github/assets/mobile.png diff --git a/.github/assets/desktop.png b/.github/assets/desktop.png new file mode 100644 index 0000000000000000000000000000000000000000..369015e608cec345f80cc2033c3804c64bb256a0 GIT binary patch literal 62736 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 HgZ}nU1!RK* literal 0 HcmV?d00001 diff --git a/.github/assets/devices.png b/.github/assets/devices.png new file mode 100644 index 0000000000000000000000000000000000000000..e6fd7de436cdd028749bd44d899e065e89572145 GIT binary patch literal 485931 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

    _tmC7R7vH{^%iF(gzzf7|!9X{+rJ)deWWC(Y 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

    rBO>3@Q%6r7l2^)J88yuB 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 z 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�MCe0*x_6`pF#Icx^^HLl`% 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 z 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%0AJyrSMp1d@b)Hm30kWgz%8?oZtyMOJR{-Z)L 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 Date: Fri, 5 Apr 2024 19:07:01 -0400 Subject: [PATCH 151/241] Add devices SVG --- .github/assets/devices.svg | 56 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 .github/assets/devices.svg diff --git a/.github/assets/devices.svg b/.github/assets/devices.svg new file mode 100644 index 000000000..3b6fd2378 --- /dev/null +++ b/.github/assets/devices.svg @@ -0,0 +1,56 @@ + + + + From 50ae2ef8f3d8d88c9ee4fcf0a6c6f86bc1949b1c Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 19:09:34 -0400 Subject: [PATCH 152/241] Update devices --- .github/assets/devices.svg | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/assets/devices.svg b/.github/assets/devices.svg index 3b6fd2378..4ae84cf48 100644 --- a/.github/assets/devices.svg +++ b/.github/assets/devices.svg @@ -28,8 +28,8 @@ inkscape:deskcolor="#d1d1d1" inkscape:document-units="mm" inkscape:zoom="0.18850601" - inkscape:cx="1949.54" - inkscape:cy="1360.6993" + inkscape:cx="1546.3698" + inkscape:cy="1541.0649" inkscape:window-width="1762" inkscape:window-height="953" inkscape:window-x="26" @@ -40,8 +40,8 @@ inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1"> + x="739.67548" + y="132.02007" /> From 5e1d811cf60196113f15bbfa8279c43518d35133 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 19:13:00 -0400 Subject: [PATCH 153/241] Update devices.png --- .github/assets/devices.png | Bin 485931 -> 541506 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/.github/assets/devices.png b/.github/assets/devices.png index e6fd7de436cdd028749bd44d899e065e89572145..fd27a6a768f36ebf3556cbc89d74523791d5ae47 100644 GIT binary patch literal 541506 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

      &Q_b{nm7(+H(rC!6hC8?C=R&i4CK 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

      HxKy#9*v}dz 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

      _tmC7R7vH{^%iF(gzzf7|!9X{+rJ)deWWC(Y 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˖x! zi9Q`rb^M?xu}qR6eD3qGV+z~RmT2!}WPnEAg7hUZ^($cbM+>SyPq`Crtu8_N_yn@) zNu$_=>`H+3Z`!b}^NsE1oNbL4{5>?ugU>5blUz_}zQId-|51l=FL}3?<2aAHo~uN? zZD()DzyJ+$uH9h1G-t%Ic9jLhmEe(mkZvxhe|Mj|t-g8F?`rS|}IF9;B7q;GKAT|vRF<6CAt zjwjL}sZcFU{6*VH>|~+a+Liyv?)*3&#s%$iRWH`=;@2pe{Sih(E!+M+nJGfEQyqHmQpF4y|| zfq?b&FgF;jes>LEb^-@T<+|o+3|UvFZW}ZJitg07r>2)M#e3q2Q1)0OO4AHx&Z$6( z1q@TO`})o1Bjf%!{Nx2mDQmbr6PX&j`obfm8y@%=6QX(fAUGM@$}?u0BHSJ~NsLaG zvG_x>qQ}hLXp1|~adNzH>Vzx_;Ub=2hPxo)IK`!H_qsA+#wQ24& zRF!eC5#0<`jnZ-ECyP>q=8xeO7p{4pN#hHMrJm3UJ$_V6mU{6F<%upJhTU-VvL8%l zk)Oejo*aU$KD!Epv~C@GF~$|(+zqezGIKZ>ni?-5P-Cjt0}x?vN0=BzJ4e^CV`~ zXCz*Q8NeXh|A5u!a-H3@l}MfLuIyV>f-uZcCkq?P#l{R|f&1ogq$BVd<}QL$!OUJ7GljG#HcFpO z1~T)0#%WZpn<1@g-Y2AdFc~zqGMFo^C^o4r2AKKG^tp6H6lyc0-9X{^WOfcocQ&;h z-Y!vXgP~l6_*HCwFLt>#q@5|E7KN!4LDbI`mhShv-*NPB9e66-aN~Lwz`rjWP`oh^AEX~nq8)fvpMe|TDAFLnic8=^ z8P&v(!po~VFl+m|2YXR=Dp*<5fE6;58pW-&RK4L%AIbRVlujqrw@p<=d)i5*YSzK^ zjMDRv^4dsK`<82ioRltc`)RAIO&8 z66?5C$545Y7*XJ9W-Rcn9l#_B6c%f%z<-=Mp3}430PEGzQ^x`(_^(L8oKKdR7@d>) zZsa{{PpLV&aC`3aNfS9~nMgz4$6+We$e3%b+ph<3=jBtp`BIq@i3~ZF`|8DanKM=0 zze^;7b0}Beb3}Pu+CKVC_PpWaUk_?aC~TswtIN3g+t@!*U^xnsQN zyvqz{s|uPm_KY&&k+HJUlNEB314iRYk}F4$_l%Fc92!TTOPjcsU+V3978kzvz}Oza z4ut%*=L_qlw!8(Wo~z$h=GZ6CARU|_(n@9+(Y<7^J=j}G;cQ@`YN$~?NBp7S#M@^Z zM1-~Zh)VD4(^1|GEfY0ko<8J`tA9945%-imdD?5o^>W!EPo$2c63t=fRPtX7Z3phx zn^%*8Gh5>8_wHTh=A^!)E67u>Db6{wD28ZSaqFEp6MQG6ZwHA zinsRVKC}kJrvfzxbm{f=_P5R1!ESPZ#-A@FU?D9Gxa$_sTup^6uM1v1ODxWdVut7M z()bcwn0tyzKINHKV4jwG?-rGjoTSV=J$WD!qs$%?hO9D7fyGD9?mq((1%J4xomrvz zXyj0iv#Tymz?EQ_nZR#2omkPhNg&Hp z*?y`uKCCTgh8q>sYz`}P7f2Svjt$11=KOt=Q{rQa@ZO#newKqxEq`6FeUp>2xBj)J zV21x!9#LMtAd}8}d(HeiF2X4~9%Wwi5!BGw58P@!txqehs~IFHbWSt)W}oy$hdh)# zni#$-rZhC_|;{ z@eDgc8}`t(Ap7LoZT5T9(k2O7w3wsd>wz$wVa>W0JLQLg6<#V3o)Mol8GHCET|qx& z5La8qGPFn9guPrN?x2oEAF=i!p04pL4n~X)8tOP_=;I>_ z{aQv?gU88o=>FERC10`kIXzCZ@XE%vdP(AFtx3v$#yvP|J8hcJRTQzi74vK2b4v9+ z?K^`LX%`X=Xu{Ny`y?Ofv_{AO)lHnp|EnTtPM~`8ZRR&jPIS-+Y6UGGma`^0$JQCW zZy8;(xT6xXL6KMGE{66`MZEgVw{I_zl< z-|o=_yH|?32NX%7#nU~x`JD^RH>s3<%3os9UVL(`m)!j@MFpM((j>-|ISJZ z6p-_z&yk(YC7Dx*L5ql*v#POjH;h>iiW_KyV(eEoa`J*7mn4S6Lo!#upRt=JUAuqv z-2J3FocQohWXjMbcNdQbCyg@Ju-b=Is^?PeJ+{-{@#Iv?YS1~X zd}RLAs|3Fw4KkGe#ZNqQ>#h4t`s;N|qPxsISuvd~#dY{qjCM7{!<{8AcwzM}r zXSv%VIFR3Hi{@*O%W&-DfE2`ts|!xOqqVR6ZBdoRJN0gmWB+=Jszao(7aGIG{UiOQ z)51XW3p96q@v_|(V>=U<_ov~{Z?CqK#MeqCe4cY0f{QXGij`IG$D`mE94i}+aZe#D zzj`v*BAfugQRmslY00(jZ^nr zG%Fq!gw}N4R!6F^823> z_;QnD=9#7DygZox_c)vwf~ZM!@*18Q4IR8gk0{=0Y4+(Gh*V`;$;;R59H^ShfqbS0 zp^9GZv9qDXekhYbF;+1mCb^lXY93lw)Jg3jE=I}Q7o59$x(Pz+4$ha*U2#{a9*p%$ z(SVI-;X0A|{J=WjnYY5FZZ9=A)aoz_S0s}ATV`?EoxS(p$RRcO(n~QVgz62EA3AWC zb-GKD!@zw?;Hgfot?kJe`?$tqIq!M}C?D3ZQ2_XjT=+M;ve>cM;pH(NA%hrC3-3SU z@h`4+9O*Q+yCiCo&qB$322}1$XfLFnzJcj5rk<&(1nw&wOBB>RtRsP13Qz7q?BL>u z9MnX%Cy2d+yETT(C%kEhCv@W&2z@zQ@3onxypv@5wPoARu5?+cg>qW4>`&J})ILq|r*w1!RvonnA28$!UW5+zTCoK18o*BIg%}j9-X%my~&XCu-x*a3*?s6KEj#uKsc-rM zcI?Axb!3i@N`103GNKvJ_XLx_=e8b})plN$Y5t#0&YM3u!1hv6C8WYbBstGd@)Gj_ zkr|4v6Z343ake(>D(nzvBa%2H(A*^)+rfXsh%Jbzx&#lkf;9K+mBQ-KqAqHe_gVc{ zvT^3dC7V|(b71}2_y*NP`rZQH3$$Hse0Ae8Wk~j>R`@dIW<8F1wBA3vJNmRhSaf$s z>}au}=`5DZ`K7r#DEm8HOy}8H%JD|sgF6+~N#@b}eqR&!Mrj^s&%T?06zWM7Px<;)imtun=RnRRCjR=%WS z)_agEqNIWabH6vH@PMe%+XGFzjEsezea0WMpC&I{gD^ar0Z;8^s$L8Z(F62+lo1^{t9E zsX;|wOfV;cg3u-=sF>oHbE>&xQj1onja`HlB#?45E zVxuWX&QEeILGGYk{r}#cE$7ZOjm|K>$)N8LxxI!Ht8qCeBLwpaWHJf3z8$Z3BuY3Ed5PFKT~4&-jjJ4x8gQ zgG@EDiv?GU&y0=?8i;JHrl|vhudUZYLHe~*7r@=-v1Mi8X#QD24w@ss#Secz%k=I` zV)pLc4|5?|+H{YwH=5a*@5V2?Tf2F(8F#%D_Nx6N?oMR4^M*c^vetPxS?oEWBAFcH zd5~}AdeKU7Z8oIZgbb5mhbpYDWy8pt`^3~FFzCY)*c!vg3H~T~_ysprd($i?t#8u` z=NM`9Iv~fmsU6lzq%ZrUlsf%-*_a%xiilMkn`xd|KY$~b=L()&P z`=e5YY(?xAXJz9)%D>W^^*a>;!Ot+`Kb17QY1_o>f`dNPw9|ZEVoq9nUS_vp0LotK zBpSf~$U(u+B?Fd%nvyhN;Yl|y-xKxJG98_GPhlCjiCSxS`xM<;0-Qn@Xki*S2AAjF zSm&b`Hg*k?*N=>c<$7h@E2ucg2xbV?5M-G=fE~zBcor2}BNj{QcC1FNO&@k^6qL8udH;P(y8WYs*-fXuAN29E(o4Jy&EHZRq?@VqL*- z`^j{@rvlLs)555IPY=nE<<{*OdofOl`5Vv;-}i!KcNS#qC%GcmjKcFriK8JDx`%sP z;-I!<_8yYu6L$%8?s{x;^lzhX-mQFZWvFO5)UN+{9z#VhdIGjzU4N=Z?}zdr^E&7+ znHNc@Bw_8rmkJ&6|4H+Gj5@qxky@_hl%WhpvU$NOy(@~SWuY6Na&I{K!u0*ir?iP_ z4M|RPqH{8aI*h&=7F=~DQKHaxU!;`$v#m+Gu^YwW1i>x`64ONyD>Dsk6NbsYc||^q zXX2B`rkc(KkE(E4d;I+7XTNB{Uwj`U7i&lweabAb<%l1D{1DPr+gH4M(_dx1p@CFD zOsPStG|=>^+SmceAG6$~oWbv(5_Rw!y?zW16AJ3hoZvkV%jVCuqDhLGhKr*ne{WC2 z8Q*Swuf^=IK|$}$dlIin_IeDL#m!F%P zn^BP+s3N4mPS#AtTLPlXcA8HP-lI>7P^X%bkri=vHh98;$QSQbv`WMBjLBP&g&5v` z(hCJfbn&ICaadv9i{aGmt@e}kMC-=k&GRp`zC?o}{d^GUl*5u~HZ6U)t84=7SkmlR zG#VT~gx?s^_Ks^;H)2j4`FR^8`fW&Z&2+SWX3H-N|R=Wg_0 z;$0y9Gc#WnbqE)Eo*Tv0aWX_*G9&!25+og4zaMadBI zdOIh7&MT}(Ay1!qZ|l(7|6RNtaDZ+CauRBr?E{$I z-~vR(bj-q73*?b(Bph$P>zj~qx7{J(U@Eqwi%yp6p|)Z8TlLM%>{&wL!RWzR6){rs zZDWVZ!#f}VatC)g6|0{Uvwuys!Qa+XsNx6Ii`(O3*>0QQ{#x4W&v9@{Z#?-T1*irU z=*R-wLO~`u4G@-0Ib-8YQo?&-(5|=8PtK*I+F{<sl$#J`t- zAE6=?oIE)n$yC5CLr(u(CZx#QfSyfS$p-KDWXv6+Oc9#|3-CVqYh+%@dk$i1`kxn` z{B3u>sLJtGQng3m9}fLJw6rwl>u06gk2A)ad5-p!XXld!o|T%C&N*IU$QLu4zKCru zxt3`2d)MW#v{oqx@|7F*s>b+{$i3<4;`ay6F#PXlbx z5&_L_(q99sGAv|2C`!wu6+vKjEKwFV+aJ|j-%a8EPG)YN)2)mA5bi)lWu^4%an)*`f8| zpZ~;b$PxFsj=)`LeJ{T?^|2Mlh&El0<0XNAYvt3Am7Yo)?boeh_}^57;^p`l1<9y) z-o`NV2>Ed($+IViRY+`Wl8z`7P8{nBN(pH{VgKxJzbC@%0OM-AL)L}<$o`Q&kHnhaUuS_FhDCz6kbx#_$KIlWaf$L)K;&~wM<~gUYEapTy}$46=xoC>txhCD%0e6PQ6&ajK@lzN4O)Uk8B$5wA=^ zVTaEkh2}m0kG|epLk2es2Q&){MJDZ+J~uJ3ql;Hz$B~R-na;b(^Y4-0^+UmtF4$JF z5@${woP-nIteBNW?R9pH9;bJIX^M(D{wun;lR<8HwOl?|)NdE^3uG6{Z0L;{IkMjMTo4f;yOR^#pq7792K zwr*r-M~Cr*RB0qF!)ETajsGAgIuqQ!8Ib0IPNQsEHRHd0i8*tuV<9BGw|iYC9(^ZU z?fO(uI)lYbR+1(+i_DCB4(vt!s`Z*n>agCbQC_d{ANS}w+wCWxy3O1L>0Rz174}ft zP!p#~6(O8af;CXDKxYWRnP&iVf{R~YCNc3!*Wv7M(b{}#R@vO%tXTX+ivYH3m!zEw`i$t8`8O(u3|q7xKFhID)|50_^r!%~a?&(qfW8Ek}rm&}|B4W&_S zj$f~wj@$nll@|6~^#{=L<02d1zPw!_&*l6*6AWk^?R!~Tk1`HlNr*CjG$M4Qo&5Ok z6V@`fgTD&5e>41Qf$j>5Y8JAgnh8tWb}gb+i?xh)4Cls1R#n+xa*m5k4qnHr#L-0) z&q_5l-(j6C?5h0FTCbMAMsIqkEb@Q6EmYJ=9={lVvQ~KTW~!ptxF$_3%W9@IwHo}&9xxhvbcL?kXkMs+|A20L8aG8yPpXu4S%+>(>Lq zD^pg~ubDg35Z0gvFFcoUiATEUks(y&V0BY8I7!*h^RAan3Vxe?usg}sLAbT@S677| zn~Vj3@=IrIv-8HF3!R3vbe|KT zcO;`Ahx{pcyXnqQQBlFi&uUWk#xdR>|{ngW2JN=@4(t?w`ae9KjZs% z+~SR88j#Bkv;Xl8yMOn6ay;@U85za=&&N(qP8cV`|3IJr&fwoGM$UDhqgnhr>ELG3 zM!R+r#Ym~1tvIIJ`}`-OAB}-DD#=1#5rfMVDhflL(pOryDATut1Ad4Z7>Kmz4k|Tn zd#(H05BZ0q?4Q>9UoRbU8P|vCfUUlDIT$NNV-fGSB`S4}$ket{m68JGYJGVHDeX>l zGyM1n4k|>&4Qu6$abNY;HM;H_gzE0^Kvx{+m!u?NuXQR84vza9t$!IBwRLn#M`DuV zgONfkq#@{0-dSI7fQKNpU39H%K^l+R>&<$~e^E^eNMbU$1UzMf}INvP>1H+#^yt z76OG|tb?{E;6H#gUHZPG@Aq@Ur@HcOvdqEReErG{==DalW1zl+A*5`tb#&yx0FOk4 z*RNkov5;iIV9rmF!EngUuu!hH+Y!=Rh03bNck5A~;^SpsyubrpX`@bn5HUM1?`8v{ zzZLB5=FMC7dX%H~-wO*Dr4!puE~?NVqFstMnxk1mrs)max-#sEgNZH{jVqc--l#^{}b}H6N!DyDtxQULV_n8 zY5YgMdYB3Ws%C`9Z#`fW7_575tqe&zcw4G>Wf7?rs;jHR0XOQdn8!>`Zti{K*pb25 zPoDr1;t-C!9U^T3m>nsij0;<-o+&C4l#Zx_Yq|gMVdnR$1l1g+?C`l$3E3#RI}B00 zptxpdXSdVx?G59SC#tHX!G!e8bcAKD+ayYFG>}z~O-)V9`2-!0j_f^V+MV=3I*^o2 zDJ!Es^%I-2QK4zqQ0~Iw^5De8OP<7@31eV-j<2|kJ?QpRF1JT})Gf2s${uybKs)0& z4za0dX}Rc)-ja|=y^wRb6WATC-(fGi8h!S96MSU36Bt0}8$i;?hk;FNJ!yx6S?3=X z74kMn%IH1RpuX!W>Go(k#Wuw$x+3+^<9~$bf8NMkk7ty@g>!`?HmlnmZC<@Xm2O_r z?gcnwi^MgqHlnTnZhIGOq%44M*vmTIb5t-@fJ_8sy;J&slItUw_J_>Uci)^^u>iBVCNloqokWLo_!B`>cZzdyPc6&PXoBizKE->MY4^E6p%xpB^8OS6O)g0xU>7NT#BE* zEiFAo4h#&wP?m?U?E?-mzykPevwib4wzB`iUAdc;CgSz0S5KF@)SLfvYW|nLr|!I# z-8=YjE}Objo0;dTIfOQ%zh6LU;V^E}H{)wXH%^^Pj9z_Bse@>C!=~e$K(^5&Oqv-` zboLa{io4cMr{)!~b!|BFzI`J=ulIClJ1`IwFxZ!rlQqmJo0%=8bLTcOxw*N40kwl8 zBQnm;0$vT5->oWK-hGTteBt20)2paB2B^8jfoQpftUl%c zkq+=CX#BfJ2SZX-FN}#M2*zsh-61tC{Kf9{X{8cN`GPq#O z%W2yC2T~eO*vJS;E8qKPwl%7(`Ecd`&M_*0A~fTMht2=|T0>BVR-8gd`S8g?K-=ft zQfSiZ>f5$R+AID4+k&hTp(x~WMoFBNlf&ycQm`2U?)B&Rcv8aPmGyNND*XA~Qy?x0 zk14lZYiEw+M!#grMzL~m5X2)Q_|uh{qwNxa*7?E1dmos~?jIIl^6JmLP{1bH7ETTS zd|&nbiMoacXgryL(W?KaTCQF@xT}uLs`hI_5RYy#r~GTv%tMHDGvAo#wk z>!t3u@!kCqF2IEVIDlX4tB>r~?lq$SDI)?j*{w!^Kf_n$yMc-eDpfoH4gr>_kb@&Y zL=?;g9Mf|TmC2OOeAPwB*tY0^4tS8G<)k6Ne{fTFs8*P_pAvW>9T^3o3a8<}S+<56 znwmf$EUkvIzFaTM9RY5|EgU96wCX^+rR=RX)vbKaC!UMjy|HlwSfAVtq8M=8o|gbm zN|<0kMi_mg^xoDP<6Jaj+9v%!XWRXnh3{?v6mby6=)q-QEew~Vy0a14GX|R?jjZ74 zb{i9b#a2mK&wpGEStDFO=$YA<#J~`3dL37IE9JR#i+xsTF_@h?t|si6zG--02r@8& zNm+}4DGJd^%+o~QEf18+NL@}zNqKe<)@pRFUs+jsh*)k6Eelx!%GizbrLz1StwC+# z690xf)Gskr zbFC(#4{u+?4p$1f_#ody5aJb^*(JN>IQusy9dYGrx^hzu30n6E_z= zqRz&T&L)kUt?plGQ!=ZsiKINIXt3qI!1G9rQNFEw90p~frJb-oR+_Lsj78QVmBNfeE)?76NlX$>9oHH^|x5TaW=Bocq7`pM6V8Fddpj#=5+a}L#8 zZ1MP0LX1(ZM$7YCOYoN=bqzb%F^sKnI_ zalXBTy4xkH!5jbV3N=gFcDMRs3qdsD*g^F^udWpvp)#|PVLngEDD53mn}8dn(CZYK?lF)cOXOi$l+wH(8(Q z+!Z@;#B~uu_E%BGyoOw|x;jz^{Hzb&JAs@qC%lKLu9OwgjY#0A;WR4Q(Fa3(IH^OI zn-_SQJo%*IDnAJXYH>Gu{o9jIpPFCT;XFE}A7XGm5c0mC73CN7_QSg;7bZF0t@^G@ zm3_iQ3;UwO_P1C?QNu~yvxV_dXQ{M7j+?5KjR9J>d*0=(ZjPhr=&yNl2GJx5+%z*l zGnP-@*I6}O)*dTkXif=f&oXPC3^QCOGgq(@U-uw&E_Rs?miBnTwSvzse9KQusUftk z#1e~dnDF9w>jbg_{U|=-RtLRT@ZM;vw(>04@nZIjuF$>DEmZ?k!*iq>W^sP2#9r8B zq4Db)lPDusa#}urclv<}ieJu#Q^5fDIWMFswr;IQgwf{IyU!8f7ti45nH1z@dkvUL zEBXBevF-*ysM?lM^@vAZJ?p||h^bd&7w8%_HH9^A3!sO4RGI{t20|mSl88Hb?S!9F zJ%7>m@V`m9p5$O6eUs(1dawC-a(`GytNJ}Jn0_=@KO@-`sh5pbHT4)wV~my~gL8qg zxdF}50ge&9{d4{r293c*H6LMs%T*T^@x!|hc|RFy&r6a<26ppNi;MW5)mp#4@dBI{m~HvvQS%(TA_w%1+OX>A z$JraR$amXV<_^85efLBkraUtpK3lZyFSY8w^Ml9V<7_D#Gmg>szgmD~ZbY@k`;8!a zI~_o`R6@RaWROsukedJKz%~dj3Yk-@d)gAg zxlh#cxSnuHZ(Xcd0++Yn=|UkUEy=^57O*&qOaQBm3fLcGEa1Xr|2L#&etAjq!cKbs>_M$XcT2 zg!yTZ$#bkzRouHf^X@^WA8Gp31$GP0WYuOfZAu;5x-K%{aqzrykb7$2eRHDUO?G+9 z7pF6`Yw=H7>!(=hLD8z$Feq^|7d{f^zG)xDAX$%k+Smpw^!4OcEL%?F zC&5xhms8;oc%>FW3UTR`e3SIH`P#<_*X?}a756B$o9JSfcYRE)OIC7Me$-D{ci z3;eWLyIH=th>iDd2i9^Qa`K@>yj|ZDCcMnMEvpp>*Y#X-vdHdM7?dz}7{B{4Zwg%# z0c+yo0_>!U>SiBbX;~_yYBpx!8M|%GnY%f{BR}aYOGl>kFB=ambOPpM!q0K9byRu3 zM_GPRNEJ&2aSm{~wY0RZ;u)IT$@|A1;Lp^>qrlSAx*u-d8yd%Z!bg!=U7Z*g7l)ik zv;0C9-nnD|#?c(=!EP6~A20KFJ4k>z)?y1wCNW8$I)`GmuYQr5c7EJ4jemW+++1#E zH3c_pVk$M^x!b%qwUad9=@IF#p8jfGNy^8EZ&4sozki0FL-S|ml6JMraBf)X58r*P zqEkUG#T=0}pf?_5D@l-E>@R=(GFRZTm;>n@R4U=733`S|5qE+$g$6?wjelukkeZA7 z_7#XNPuiSNc%XusAnHE%chNCKv}b=Qu}S|lt{~0wSh-Vmu&dM%s396Fx7Ov}zNBb3 zP3fbFnR;GFT1)rxJ1HT`FXs5yYaGrqylIaSE%%Y*KKJM^=;K&+y&E8c*pIARau!;i znC4oiRTe=Z=Tel?kDH@}h8^P12?;ms`c?*_gng%Mtm2#Cm;KbAQZXo}aO0F#Td{Un*tnH6OW7*aTD;^oR%GYjZHM`x%ibLl&p?GOEDf`h{T znP3pO+>H_=S)rSMhTKHUgCfMy$L<)F_=CvT(Z1C3i>B;}tp8n<{jb!>avYt~YXuoi ze8tGuiDkZhUSnf?TJ&1t-I^ZWshhYBu)Bb;eE)yge#`6z0I;gp&kerTAr~IPU@#}UKXw(W=fhXV+9V5yIwd7?W*JQLF15RO2SYtJ zJ^!ZHf@C|WEB!#n7~kExN6ou+?6E#k5f*gPLT(F2ZT~tQSL-L3Bbl7-U3B<8KHhm1 zaUSGi>*%XHOS$(bC@jFJWYKS7LV z7bdNhXta|`GiGhXVzh70oC42#G)+!Sg2d0j3tj!J7f+HVi1ej6gO0wxyNxf5b=j%4 zKl#_%{91BX)*K-l=FbDIoH_@|1qzWl_00VDZ{WtP6@`iFL-a6^k{O~R# zO{hg`^sNa~irndnlorh7F+@B#TFFUYDk+O3ckwG!zQis%30KYLyWi^8z;KKwUa6A? zLNI+SHkFeRd096M>nfD|)@o)S18rXVsoC!7v|srvP!%U!-2ao#>s-y8(}vSyHcZKo zDmm}FIORWaAP|{tBtOwA$)9uX{QY>Z!uj>Bfo1 z+Uw*cE-lq}Vf_0-u(Oh5IpH6?fVifR{;LW{YETDyDz66`GHNE@Y6Q~$A^4^Z24z1} z|G@wA!90Gv@AgP$AC!pj_q8VM5JjlPbIvCj)CMZ*96GEm*Grl-&=xm*){*cK)=IPl zn$D@nw#?e=GR$@-SJZ2W)Ca5TuwM3P(e@(RE>+IN^>NmN{O^mEL=vq)XQG77&|Ew> z)E`$HN~~Dk$Gq{PCxt)6t&FYA8Qurc(vXg{UMkQ!I`@LvB4kumRhuRBi{n>#%?!V= z3JVL1x9{%m0vu=P&7pcHXx*!=HY4EjNE2OLG_&81;dOri7pN@XUXv69RMQPlRaGCh zlI~QW%?Ccx5{rky2-OSTTWOA5V{OsItHv{%1h;@7?X0^`$>>o}y4R>ed7~*A0v5d) z=(y zvg)!0w-C170_)?yPDSp)@hV_L@C9DOH(s^~)x-TDNR1Xnz)5Z8aVwY2OVp(D*$+W{ zMA?!L_qZ`+fO;xIDR6R=%X-F1-{bb*Hzg5PSLZ2 zAE19|FI3f!9)>~Zw~x}rB|(g-@bEqh2UQ~%zF#gn5AT4|ioSGKeE+iOyt$n36CcaL z9OSkunuVoh(~n0te9XZ-&RSVL71UlAqi?cYp zs0gncHeOd84qsH>$+^@4^q}PxX&!3-=AKeFO-{G8KieqTbaVZ4YG>H}3ppy`@-`3J zcB1QGq~)LA*T#IF??p)Nvxj5YBi%uR4B&GNJE=U4A&JTt;d+-a7%Dn9xcS8TH+}-_ z_J}x6>#kw5!m_KUaP79qyl^DT$E9^)UZNXM*@g2fd%4{ED=cJC+nVLxV=nB0yr%)N z(6Rlc-|boE&tygw8@@(oc#G3bth`xKBqW@k$)(uXT{AWO{;#xPf$v}B4`9HmjZ}BB zFu$e?0_O&aG1x|cUZHW#NAM=q`&S9nz2ohVXQfJ8H=g+m-Nw;n)Fao!I_}=h#_ZB<=*AC|IBt^zt@Lx-cZ15E=U;q68>_V>MJsisvj*@x z;MV~_Q%7%aD;GX+m{VgszXXM}Pn}Z71uC+WtsLt0M^D#gRsR4WA}Xv;@>Aj< z>&HZ5AS-6k7 zsy36o%{vVKks~eVM#OBl5iXOKe@hpxGR732$o7Z^uFsuFY8|dGr(TCt!~79!9vCA3 zT#ewPT^Go1=wMyg9MSc7pEvRa_=cqx)h( zlfN%3B&kJ$ajTqfRUAqPDs17uQmeAv*Y;77o%i}rG2gjX%sYk-v>q=Umbuw69Ios;W0z^xVaLW`8!sxv|!E2ui4oV zg@D_^Y)U{|J8FZ`yI)TzY(*?VhmkIA1Rtq((@d|D<+N7soj~7DXQ5K1Nh6)xdfQZ*^)%- zyjRQS)es*-dNV;+j1bO+8+=!+(t}`_-?rcV&W;ig2un*#FbrrNo$?2^|I@aGMZmp) zLr9li?e?cD7hv&M2`i8i<^^)hJKgUb=izvj zn_zbE$qYNNIu4FJ$6HR6_I=~LxZkiXEH`FnGhTktLEwGEWCw8X*x7I3l=AVz9A+3( z)5~_L^7^m+rw_GyW}LoJ(*(YJY#qlfoO7|k8TA8rUZB+2lQ!7AF#eLrrgkv*Nm2|t z<1uSE!*cn?djRoC!rUHLp-*38u~|&KCL+4Toz}%x9R4*tU(T??OqrxWZ^J!bX8)aGKe?WnYnbK(0chqt&6XClsBw@AT=vBUPG3-o0`Jcp) zUrP*A;P|-gV?lI7#MnEvF!8qGXh!O&%h;?m98~VEwcfZ9%r*;7^EvLxqPuK$b@x3*qAKJu$P zU)%g%!1q|+ffb;E_<$NJ>l^E*)Ho>?I@8`SUhhocpp6231uXY}C;?;3;CF z1U%wLrEX-Ay`~kT&xAECB+rUg z*lL;#^gy?MD|8<(E5=8QLbSHZ_sti$sn#@?Y>4fzuN7!Dq#Q&l#e6#JNfZu=@|ZOO zOT}#_`_}QPq=t(6EBCIxe-Yh66-QMU9^6m$_@K%5Swa8d&JtG;x6W#c$~yn$YJhzI z&&gaBtJb;JhP~o~_bkhLGdfQDvB7ht?kU2Nu;mR~A#wxHzGY|KBjT~@ZG26URc*d4Bw=KdfVWJF_ogp6x@i@Qe*ECtpX5rQ3;x#`v!?vc)#V=EZM6uM38bUy>5@~`<$AjP^e!S@ofoa ze3GiQF!imdDAKj|5@jFXUHyTFC!E}1aBvXhH_Iz3=<9aTI11@&x0lp`Yg$xwWX(#p z_$fLr6tTg4S3DM&GuH5a1)9ecQR4d#z?`?{4QKng>RnuH3_uE+dcG)jIFM8@ zRg!7GxjG?pg&nng_1JNc<#wFFT&0QhCUI@`Kb;uId}Tlbo#A$e5SZQ;x@KG(p8oF%ld zhMl+U@@eMfV10bwgn!K*;{?5pxKu}lZN=!O%6g;l&(RH=N}O;;qwPB*W$)0zJjA^O zNn4s*%l%o^*(u%$EN`HJqNIFZV%I-d}x)~O7&l5nH&J{{de#1m1EoX41J2v z5fQ*6w30SvlQdU#1ZY}3==&xL@&$Bl4|yZFt1~;gULpZ>!BxZ*Tt0-R{8;A&RB!M_ zVWkaH3G}!qG$mNSR*gyIHod|7O)0(L|0C-yz@mD-$Kh2FlrjJ*1q12sMwF10?(VLo zmNoz-L>i=}B$nM)8>9L*v#vcAr|&; zcBnE2Ocdxyiw;UWOrcBCXQD=|co*eZgB&E>T$mNzPEkVaSwqBGOmqv=2=$+z1^cD zH2cZW`JI=~ltPr8ozI-8_cS=rbbYRt=f9QkS$nJ0E_)^PrqC{aqpuMGw=4W{X1N%f!269WQ|B6Z9S)d2M{d`-r|v5w%hst8Nw4y-Dn+V1MYy@6H) zTC)1>W-abl!uI!NYs*Y-!gXFnlpn~=OcV#GsnxYg*j2s;pPt{ZeD4HD74K`Oj$M1( zJoCPb&hn_`dEd_k`gInZ7m|{uUFq9B$=p#HF^MgeukTUaU51W}?V{WZH#ewQ)Q}^B`_S%9lAChQ#j=m;weL~ zd)u>n&a26D434+F)$l4ed;XkI;6S+0%4RDT*!7q%NU0Dm%`IN-`uy`_K2zBIqdWl< z@$)gRPru;a)j=wMWu$Q+pI%_)sYLTWU!HN81}GfhgU&s(if$I6n6ku>#dyb&?pyU# z9a1R4nk?xUx2NuUF?PakZ~R=TSc^Sk7}57f5A2}*iKu0h1WWx88dm9^3+>n>(&UsW zp=OwzPU`kIq*E{ z9$hZ^5Hh4ptLo<&J8@#7h?LY$iVKi&(Zh)&;(@A+j2h*V*O?qEcnK3@q*t?B@juj) z+59fkwi3G1m`cYWU10|5)Jal4`6y~C{?WfJ+Pgiih$kYb{k9Bl!XBw^Xnbvg0<~bD zyfvAo7QcFp0j3rA4}E1-(l`vI1~!wJ$!Th5ek}e)+b2v5B*1exlmnG|9_> zv#-AL6KLS@b2~oT5s1&A^KNjLl-W#P=RKx^HkObikA9V5j&I+_1_-_H_mnfbZ1JWG z3!pA#w7#d4K)nqO^$A`$)lUwxKaDMr48pxH1_Fn!0_QU&om-JLjZT3)U?{G|4Q2XgK8oDnEq9ovJ8YTW3ZNH8D?zx@ec>8uY>P<{q?oxDhIidm&<8aHQauOco#;_vk`I_BG1e0dAcoh$Qsx;g@ke0Hzxbn&ExaIo`#kQ(tDmG6@b z9txW0y-xNb)jh*zsGhj-9YcbbP`&%Gxf+@9)KU6;4jL>mPjQKhS<#X~0i9uQv8Su3 z|M?&fM!KSd^Tdn~#G1x?w2QYO`hpCen#C*4yQbJ@4YoUp2;hzQl3{IWVqZGrYoGJd zB&{cmrrs~yp+F@4=di#1JJg4`yVzYZlS`irLw_%q40!KTZuK?lTOYDolktnpwcq<} z`6G<3jcQHUiN-~LW8yKUxtQou9ZEU0Xd>WyW-u{b^WtFe+t@QDX|3jWm)RY5uL%Nl1=LQ zaGxJkU>9tE)K8Nt-;sT1-34Uqeqec{Bs;R~XrOU-`)ICV3rR$93kL(l7Yn8ef&k9; zjb;{Hz;S)b>wr*~8AZTmH)5=)7|w!=UoeWs^_IUSo${0w=Z#sCPh!AjQ9^Ox1bXft z-uZ5S>5?xLU&VviHqLF&yBt@z#^(D0h1ZXcMP_@O>HlH@l8^j$iMtNC=SDi;Pp;9= zHEr>PijD|u2w=F+$srvC6xkDevkdqQ=8>1zi_l;7rqRw~H(Ydm+qkUlgW+UkkY60r zBOUT4J|%R0X;-?>N&con*O9!P{_g#gI!yJ`yj^1RQOzUs?J%V7;XP05cX~JH&fKRi z{Qv7B10#!**h2BXEp%Ya#ok4{yGLUshlZi|%8FQ!Xhk!67~hxkfURYf7|_X~zS)ojoaX z3uY^WT6Cf|B|@dl2Hsu`kMIPlX}R@mUzi=|lbuadVhmbZ+E~-eSvAh#VW9Vgg@rYh zt`3Isy_A!~GhMgzV3W+@4aZ+ z&*xIoXg6Mt=~~CqDzAF&G8S|`(X7RiTE@B^}t#E{Hrn0bpvAm zqJ>5}y;-A71N}K=*b|X!V^Y#F*UQ;Yn3 zn6zMz4s-9o)IgMIZJER3$6-AyE6cGmDeT$>t$jiFDQIRWvASC*4gQOH-R(J&TBbM8+ObqXQJ^-W4ax7 zNLN9WUvrr9KJ>}Rkn_!`Wni1j6gq;4e0#TWkM{)_3%a2T-Uy|OhCI#D*kRt^OM5a^TB(JdQ z@V2eMo-8h0ctaoDzTmJ%`l$({pq+hbR0`F8cna`Os5Du5Mu8Z3?E4{34ke|@j(}O8 z+rmeoFQG_R@9BcNjEuyZ`a?2cd}s7r!5`g8U1$0X)LSpiE=joqcIbpC1gm{{yVY){ zJ7*XaJ^g&X!UNqTsP`GQ0pk9_5B{lwXX~BB5&VJi!k#2*y54vY3=Bz0ZN9JY`|qR$xuAn;?t4-^}UTg?V;>F3YcC(E}U-+6CHih;uXIL^9QV4X=%r`&GJ zjbX8JXI&=b94lAit^UG-()!GjSwUbHCy2ywZ{GU<$+XMn>BEW+n64ULF1c{s>2G8K z(fRlOhQ+Qoc!yGRTXf)|qJd2}47A?llpMhCT0y+J`<(*RZSJTItn*8JUXn7CbcG)z!Mc6@ z=td@neT|GET5}1|!-gV_AI)F4vzd9$(B!uV5aepK3HaEeOBHdvFrPv4PM4y_oi)@Mi#4Kmac*3-R2JKP-0aHRa>S1f4j50O+mD1%fH5?vm9PbT;Yx z0ycectUKJe>}VSZETaA9!N4iIbGE}hUebW$>z{cy$#aD>Gln26;m2cs`jBoWfp~eI z*Qh?<`}#%{`&)RqqqasPdxpSP3NC${nrb_#aJhpe=D%?!D*mXu7^D$VK6x_lh+BU{ zPJlcsHTBhWjjNKn`nx_PNMQg()3$=FyZB3Xer9oTxIIsk*OD*TGgM3+#_Ut1y0YqU z(N2i03^T1Eumb^>GA_hSvMR#R4Pv3SnFepPaFzcYup)C?dLNUxTVjJ3GrIFVf*HDq z$!uWljW?b)0ALx*3%@>zkv#flcI%0)#@lYoFWENtMubm)pLbDlg28K{XT;XnTyrCn}}G>$IZbe!yHmUvtWu>vMFa8Z8V;#gK;*dy{<%?)O6a_w7ME z7Ucje9E!?I=>#?0$MrPjB)55h1Wv_F9n`gU;_Zcq6OITjRbC_eWMOv`_ft!;^{03( z5ZrC7ErN&aNfrUJy9y_+pqHb#nd8b7?U9!*9(g`!Z|k^lBc~VTJ2%>&uo2k%j;&p@ zr(N&T9&+~Ghn#fC41D6^Xw(GQj6guySotCZ7`HN`2^)iiHV5^>tBv?7F=ZPUN~O18<-(q2**Ykb}elir)PwJy3<(9_$=`@%Ekjau9Ew# zaDs+P{`1h^*_S}Ww>;L9JH-2g5li=fMGb<0dl2ZA**9zRfsV(rVewN%4e1a2)qIwC z^Os(slXA}+%H2GFwtfSsGNYn4+jB911%miuRTWW|Wq^hS5X5M-g%XyA{fJX|xM!Yb zNd`4Td`!F;z>5j~XTSvTM!m;yx-D^O`NP7Q7<3%y-O=TEe0f>sUm$nAnokzqTyyvePu)GYrqR)1=C{dPP;pL zuA{ViHC0;~o~`DR%-zmVT`{2fCC^^cOJg#*&)t!+3fdNEQi;DHE z$^`q$@+g;mWu8A}L(E7y9%#sO{poWfdLQp2UR}3U*~a6N{QT78w|%mIcK^?dG3D>J zaleA*mqvX!Xlg9?ZbTitl};qmStM58EJH5e8m9U{@Nt8za)ZoXQ1KSGf=bY)5k{Sd zYfYVmx(1LXf>5R#5+&-wxx7_v=T<|R7)cP!E|eSqUFkC(_*$f_JiI+Y7Ee>~@zsbk>AmXZ(s79FdAxiPr&mu%Iur;Iwy4%eyx6GjNfzy+qW zfT5J_(LDj}Rx}?NX=r;doVzYmo~JpP!u!L)hl{3C(C=@14_Z(H>azmtqJ_=+3!d56 z059Ha+9dDI{fHT(=SJAfwY3N7$oK7xz}vdi*wpp#)OylEzk@5euO*M9 zRfgss+EbVbF0c>?ta`n#jR%3$`mt0X({hQ3;OT35kYS~)qS8MwB{NlA$Pk41(BzX@ zIc*Elo}PPq3q?gmp@I(Ii^{o&hM5PSXAu5ihV!IuGcs=IG#rL*9A2J;)TlQ&jLyL{ zCp8Y5*YGFa{MMoV``z*4S0mDn>kBV8OCOdYoj<2oRBXCg&e~fizdCOxH&Yp(F?f^P zM2=l!dH3+8VCCt@xi0Re%$n%+y0HByy*!(QkmpXc{mK;7~kiH`P8mOl0r z0vUrqfguRKFAWk)QK2uZs9HJyj>pM=qxbjqE~~AS6_brvoT5h2+c8yL%U1Oa4%8E0 zTz6^2k)s(cZY=d!DP_<}0ZG>9Vvks7)N4Wx4sIbCKefb8F@VS(*6z=s1!YM5;m@61 zGIML&YY92hTICx?$Moyqoe5}SBM3b|?<53jy<^*tJAmIU>{s59Fd7=-D0Epw7-T;H z6$Ey4mDFax`poP?Iy)t&F0yX|aSus!c$ot{lW>oI1PsYm|7OvZ~nGY<*v9`)QTbQnn~M@y?FYe}!82Z< zC;=E9HO*=l=P?jqHQMp()9r%=t=P9d!LD2gzxL*2WQcPIzBSzkA`jk)8`&MI&Z;&X z_0Ar*+Ff{8S3G3WW->D~)4wGE?{-jK&85J< z`w0Gq75r{y{EO}n#CYFb^T^90Z}audH6Rx3!(aW7M`cOjmTvcL-`rsAA@ZJE9(}D9 zwWj=U5Qvv%uBdL-BVP^H;ogQ3fn>)y9UZOe;fWc+CIMr<}kevFM(ToUsPxll8fWVRvZX6Kr8a9Gufak;mr;p+aN0987ma)0z%*bFS?{ zy{|}q$EX(WYbS;pFx-Y$6`Ou{YQs$0tYvGHxno_&hD3+_pFwx~-8D#x2oF-*4%FPT zmbXfth|l?4=ZyCzKf_3F1_%59d;`)${z@GJAq6$=aPTT~+HI9;Wlf6hbK(uB36a_k zSO4!9^xebUZ-UFFOi9)`Qehu%wu}VE%8|Mywy^y85z4-Q5ZQgTv03FL&aTHP#ux(8 ze}udj({|;5ZlryO)bI+#{1$>YM&?7WM)*+3X)WE5CQf&Bv@D@pqAYQ_ZAdA^x2mPj z0n%u)SoFV3W%1zndKL2RK``q|@>vrFjJ}#Gud;Mew%F6tXfOj^JDA#$tKr$r>5)!2HXXQ86A#{fQORDXFQELPCzu7<(n*8fD5h zHjF#L3QRGhRl7t^OJf$`n#`!JI^%kRvKx)!t+%A)lB-9ZyKCzdd9ckS&h9ctv5N5b zu?bMrKfY$~^38HPoc5B9W_w81Ji4uCU_Lx5{3Rl*&&rJwzLNQtOJ_3epxl(?@v`G9 zxdgtfK{L$A?&X59Lp;b`N@Qi_|3Z8&{MMfxor>@|$x6Ks*R@TjeO_dm<4kmuNwOF* zjFT08HGeUb(?q>|gwM!0IIM(d6xP;}RYDFnHKHul)9&JG(cw&)PN>(W?fK5W;EC(y zYWwnXzq#nki}@|f*;9&jy~|alYFN9e*L*+!(8xskgX_zAgOeV3Ykdue!Q`-?ch7e( zSIAE0zA0o3l88O3Unq*jzzEn6Qgd1Ni}B`sxHQo}^SQm@B*n#cGX0yTSlaE7;LQC6 zX}i@pq^^=XgVv18ewXd}OhtVjXKplYd^hdw(ABYR_LI&&-ToSnn-=ZmvL|(RUK+BU zZ^gxx*4C^?t?Ygb-t;*;HSUIscN1Fi`vn(!0q)MDLW0|vvm?(B zXY*VS?hUP$oMXMV*KJUP$iGAf=jPuL6DY)mI=)cEhI;W6wW=PePYxVqV+c)X6y38z zKd3CJdtwkv-gYgmmdzCic0@!(Nz)$L$g3?6sZbLF^wbk(ob{}}`kXD{bHiR6W}FY- z$CDdU!MoQdnEuX#2kTC~C&SD8Z7*DB>t$D!#V?n~)tr~UThv{wc$~E6)(nH4Pn_h^ znHpiQ-uAcJ?+jBqSzh-*;e3qVY}z@+z5bEjI`_R)tujZGikS(hd_ir!8iLmg1p3jl zM-L0S&U|sUQq$hv!i6wUA~blVAAoYe{|pun)RN6XSHY5+%f<|~9hJA*?U=gK569@+ zh_4nx3W<4Wad!8UK4;z(68Nk_U%fAU8QPF0d@Ow7A$TzyFf`uJw=7h1=#@Twif3Wr z8j#;$>(xq{mXF{9NE(%E9&(?onE=& z|5H>qL5Qf+ii{pCxg|MC@zT%0*|jXUEW?7S-VXW9^muV2V7-2ANi z{D<+CQIhzqk2$pEgV9>%@F>e3E1NH2VFtaQ5AQ-)3KE)Gvi!E8)jum0KP_b^*QQfn z9$gO4Ui=_z{e1g;Wt4p6a&Oj4Nk{3eA-oI=4(#zr6=5n;CG)RvW%uu&#wu;GLR(cP zt8;8}nMCIkmbB-K9NP4lAq;pU{>5B*hs6IoF$_@vV_ytVqUKa7AWfy4PAHk-(-Kpr zt0lTyrW(EZdO}3W!2(>BxMB!P%K_1~u|dhMWo0J#7@~i{V`b8E7G-m{;A5xpa)Qz$ zha$@9LqWL4I6Tw%85&wk7ZNQbv#oUNJam6l_@wIMX!a}$xHV${)azVk+@{mp>o2PJ zC#tK|h%hAfI>RCetr9Q-#D@nWl{pq-VyN!00{S8@K1iq~m6m4V%xs~?py?K?J20GY zBF!Jwhsg)c*ApQ&w{SIsB?EGvomQs;Zp85kp?$%91Du00k)r!97fg9`Q^!?M0vM&d)#NZc-3wZ*CFuN{i+t*hQGC)@Lw zb(b+9UJI!>$TjPAJRfb?7ZW_0g9nN~3Xf3D|DkFQ#|V(1x>o`(lXRVSc~gHdcCK0F z`Tk(zQk~+yki#~;(*S+V0c}|DdVP(n<#3?w^iiCZb2nn0lZPW`ks7hqk7+j?14?lv zKqpQw+BIiO6uE6chvyB(>Wvk~>dguA`zK44y6(;ua*3ORA<0#${N*;0tOIHdp2-W_ zu``|?4RT3*+|08Q5cTWU#2x-k0!jUy{-ym_)zY55bGBuwRN=w%X@KMleNgrI3odov zNBiX9ZBH<3+gXJ0(PKMUfH9oDRo$vhBN1A>cr}NUSJv%i78#LkqG8H5e-~jN=OD&4 zwF^v0N*MZa@aLkH8#k}1HMdL1tu3p$u0wCm=C=#^RBYB+)hzVC6z z&el)nLw)iQA5^^#0D0PNlU>st$j5&3cw&F$bfRSIqvj|4lU_X^^@dA+y^-t^w25k1 z-HiJo+I^m*>;a>3`b$}K-)oO>c3b_&j*V<|llqdMzRC@Ox*%R#bKxvKveivGy{gWW z0NuT)z4jN9EP^w*7?7uERUi4+nbo@U4ru)htd`~4kp_uS&X$r4U+XHH@)0gSTr+}9 z&dk^>`0XiK$~#h_crQJ0AWzTVipX*G5XCpv(Yxo*&qwNd>HXAXZK7srB(eAu5`?Z=LY z)$^MlzMsBqNCEVlCh48UWq^d!-WZ9O+xIX2{z~o}A%_I$s`SyWo$TTiUXI#Z6g+wC zW|;ZkQIgIbE3|PIX6{f~D+I5fh+LTYvj}bJ>y3|=t$EBu%2|5o7xE~5#EaaX zZM&VZh2lagcM@Ko#R>>JwxShg4yC;&ft(DS52p#kvoX&-jz z<0g74ET9OTX78)hb-vu!t1B4w+4t_X!3+@JKbvjfUEf7(G*qmPZ9a3vdL3+-ucEjS zbO}-Sl!AZYO2~a`Er;-T)P0-$xKX8CC$_x(m33!k^7(n zp`o>CJ;tIJ@PNtJ-I0mmt@`v7hax{24bHA(E4KR;^|OSMR@2jCpUr=y%2?9h0zVW1 zU$dxNa)qh_OQV6vd}YRBE*}BE$y=6@9wY$IVa_8n4g8SgRI!qill=#k3M3@=4p; zx&LATASpsS$3@Sq@PH4tkussA3)!}0ea@8fu`h&B%Mez3^)5fM+0c!XJF6Y{Oq6A@(mG>Efkkm-Ov)n`spv z?+PVkEQ#>9Fl*WsfC;^nfTSplvlMs=J+`vwz6w#MKd-;F#E!K#hNqPvKK_FyRITw5 zGC@g*JCmjI&cpJc_7&vyLN{I{fj{rH8HV8{O(3^J7R5QzGcT zv}&7XyB+`ZxilvcZVANq1d5S_+~Qf+PSb6o)U_;b(sF|7bfpLW zAX$Nn-Luta1^t+HneFl0WnVEG9LFvb3BslJwSS?jkM&zk%*WwBr($1d<81oS;FH}> z33SjP3F4*5z6|4FYT-M%hddBpKGcILl!W4=q0s&KPHlUzIN&mB(^@+1cfW}~$Ht4K zYcAZySH#^RkyK=u`TT-|l^KZ+)-Ix2)$`)`((XU70-R_T`z75h=S3wxQq~+_(!@&n za5EJ_6V7*W4|>a(@qQC8wb_lft4|l{(QgNDgIV+;)np-+n!IM%xK>6jj!b!nJop5k zdIyUUbfi{_l;K}arf)noqB#p`0pKCLNKP8%T5E>tA@lNZ2}7Qk1apTXF^*Mf_2z}X@TUgq?sy;ZMSvaRzhTbsOX`2H zDl?TRG)N?xn8*b>P1;$$HITMLC-cEUCIquWNwwiPEjtHn5cRV>T!2uNlKtvRtT<1v zLm+qA&ET&e%Z@*hcUY9q^|LL}sz=*MqR&{O47-jYNGyV|Kj*tFBQJhSc zKlCU3PGlF_;$+qzT5VL?2?+usa0RcP5O$8iN-UNIxto!aZE>JasGfH@c% z%O$keM2!3l+Do{Yt=6Y`Zlr|qlF^l>-qkcF`tL#DRln%xnjm)e4!$4YE`xqN7|iO#x^sh%bd1Sm3viz1LJC=VRYYzu8CU1 zBGu!tFOJW2#gvL0FvQV<3P)u}*)5Cx0Jh)@N0E)0OIQp$nX_e)%y)zD`oekvg zIX-TuPcCpmgD_Yc2<6IrRO1-QGtZL*IAMGp97i--!2(wVU58m@UnU@!lBGUq;9h^n z3g$1q6`UQ#!ss|6h3JGODfjQKCD6}G9R{^mH-j3_$Q*Zl=__9}8OtEPt)0BN+Ag9Z zEUMSr#3RDhj-n#luR_!->3q(wzsUpp0qExS=Kr1eN<8;D6#)3dqc)|Nu&h4QsTz+% zWFBtTR5_ih@y2VnM%Ntg?%I-aQx67+zC(#Y%8#+afoyLR_UFY0`7@8NKr$EdUVCa9 zWea6UoDwXxixU5@GAn=cx8*8H$i8u!kv0bViCDT~w^fL0T~0-oM^Z5B^5oYL`UxYm zv2SW5#++^1)+xiSBcol=xWG86ZWy*8M7uY^I#vyVf#qnlbN1!zg?88r?Iel}*1M3k zo{6UhAC-uW2{Cvz$OwEe=QITVLJ$0v;{EH$KS-J=ZmlH?U7yyw&&15$)jx<$W8yU7T~$oOkZeAQWuelqR~uD&cr}PRCgcrbm4sr#%{*b= zqDe$y+mChx^xE9m+9IfGD$yYNs$G3eiBZm~K>Xo~EEAc(i{Xff{)axJro@2$Tc-zk zX7*c&y)VLx$F+NS&FJFQq&M;+NGJptIjeQ?*0rl{yRb#AOUV|y;304!>N467gEQn+ zVR40QkoC@vp32sH5Eg7iXD6W$pW1ET<#E3MS+D;5FAXovZQ;iL**wK+1UoRJJTOdT z&)`x;V%Zrc<8p6ut-7=>%H4Hm>}8oBQ@Um^y*q%14f*m){MrB93cOkTWm;7bI8OJE zta57@T2MaoWuG48MbeN+yUA>nqp8>3TNXi!5UBZ}`S)&(uT6q$&1G~s znDF0siarWQcDs2Wa~c9$h5vFw0&WJ&M{KllPdTRKs9t2N#~k>g@A32Bwt^&2MZJ4` z{2MOIzUu@J)r@+Ab?xs__%co(3T!Pnw85Eel(4$xNXngUb6Ee191!e}MA98E%R8jG z=m(UKzPE;lZ*_MN6l7{|-v+=?uy6fgwe4kx=p28_#ZSc_tr$xlb)QUyCpx^>Y+ZmJ zOrVhGw@F)|%p?fLT`#khG_Iq~2E(?ZeP_Ayz{b+*o>8^R_SX z(3(d!iGigqT|v~?y#=j7w9?^uQO&h7#8O-z^P-9j<_!^u5j!`q&MJL@PB+ISYFK^n zR`>DkxEIO*N@Y$2AOsnyc$S=5TA1#JX)-)XV4Jp@d zX+ONhuR>E!UdUspCzD{xB~;F61RW7M-W_zM?(kzK#IfjIujg~!1`=Z-F^N(wES%NRTRHH_lHrXib?v~m<%-g7 zI}0^WSSX+dJf0%QO}kkB%-_gS5YYZD*S@n8*pGBQp=OTSB3tYvX1CGG{qdE41Cbdw zY;KsMT21`5ZYYLD&}hj#;4jAcUTZnJEvCs&pjG_L+sZ6;qlcIl#{|qvMhYY{MD$5> zr5_W5Mx*P+g~pO{fkWU6wmVVafL(GV{+GNA`2zr(6+i@Upu z8hdbJ0SA2Z&+t9j0f6I=p&hAH)GgL%+XXmFLKYT79>$i&Ch`;l$gMu#h}1|IIxMb8 zp>r1tx484}cqSKYJKa!Pjeer+nTxe@)h=}u#g8;j6m5=u_)7`+1uR<5ue!vY>2JPi z@*;DI=|Hx6{)f=y=t+GuVxjx9d|K7Q5iCEB&NCOUxBlfDPp93$y{G930mO7`CBuy! zN#gcC%D9VCB`0oM^@2xyY0@N#kJ`~VevIbW|5h6sudNg>BOM>!YZDlf5xK>mG1aIs zuAMo9kK%XOzqPZkgP3@gH9^V9H!MyFpglac2zKny!&xl-(8;vXL>j8Rp7p zQ&Fm9pC?vw@ah|8lvLt7{7 zzwl{{LULEo7P-IqyfGb486nw8CLnPOOg1GcFG@1BgF?EKv#g_>Icjz&bH&O|-g_>A zEi05pCUnFDg}3@me?+jj%YASF2bL=ARzpBhb{=HHfRPc_8~ug0Hf@|*IedZp4T!rH z6>1M~v|w_&a{nAG`o5#vt!jBn-Ol`k8|rlUOH2ESkv=O*08N_KW|Enc)onj{+VT49YyXU})#jxd;i9ENt#?!Oa=Wes#@RN7rh z40LkpUMkt?yB{;_8qNaN_7sgpMDF4^Vh2GH^E%V}um zj4O?=(3VeUD1C+;!;Nj6PjgxQ8m&z1Rfx0Z}{IKa9BshP5qQR+o< znc@n75JT)a=i*p^w`n2U&a-8v-lRKyy&GPD=*;0W)x>L*yYm^Y%_o$kN#b~a7Q(;C zHP*!&cv{)qM6YRUb~p1cDnN!zAF*=o+p2h~6i{}O@i1Oav1+221F6Qx7@q?r7!jh2 z_~rXDvMB8ejkeGs4>s^@{h2>}@M3RpW|t7Rh*Ra7Os*`cKc~2(oT>jtKD2q_26Tc& zo{N)17>W7cY9YR2Z9&w-wcFx=BzL0o9wR?=k!=Bw+KyQHf!u~LculO(3t!xkkxwXr@~)a6GV}u{96%yUHl%(R1wj$j@wlaz$JUm2PkvM zB1@4vgJM-<$fI3B^=b(V+LT1t^vCMIC!lE0w z?J0(Trho@-@@JUR4NPTbTG@V#F%Or-?cCyj=y&`Jn7;Hq=)5pwXlHOp7l6bdXL4Aw zb^b2^G!jbu5+TB6sJcU^+hTK6$8MyK1-6ZTdZ>b=G|O<1Eh=H9mMzRkfkTV6Gl>6t z7Vx}(eaS^%HP60tr}G(c`QmvYvIg57TgikWyzaR0S19O-Q{OwkuLn=tm4@p~F*15%Y zTX`fh;P89rzn_$y`bUYDkKcZ5xiU`L^$&bqNZ-1XC9byxCrK0=Z$+$^}3)L=xTPbp2zMNy@nfWTJFa-Ke~4WMU^+4#9Wr`0VRB_}YIXJpBc7s>=)NA47@V5{czNwX-IMr9`$gf+s1^^&pwDkmi0`N{fm}B zLB@@L1cpqr;5)fo9d@=6otewHNrMCh=zuBBSt9dln@ZTKf*;xF1QuwkZM_G}^5y-# zRa_BVYJIy@94*z`+(uY7@EC5H4U@$f{I~yL0ZCA)3thdn^TV-ku2RJYbrJxh8lMp@ zErX4r1Uxxnc1RP6+JE1w-%>s2LmVw@W9K$ybOkeVA^6mQN_jiNmWI~~dw!zxYB8O_ zm2J9b)m%7H-Nt4P zf0923*HW5(VSs{0R+sS0sONdD-?C{LBJ-l4w$G%kbx4#5D;a}jp@1X)HCp8<)ar#V z)@+x5=0Vx=`Ly}H`PFcSRi_KoRaLFC|3V3(P0rk(e$=(^_n@Vbq;vc?Qi@X#S zQ9c>5jeIYF%b??1E;$JpaCFX%p(; z{vM6#!3u`0d~xP7RGbVEB=AE~aNS%UykX~}W4^0q2n*$~@Ivv}!k@nY;}Cg?MTidT ztImF2G!hb8C0AaQYw42+m!6Pd{{$HIeIirj z`9-Io6wg0Hn`)7^-V+{75e9_Sh`tezN8leEJV1^HbYApxAhVX1TOS3u_RaT?b;Wb1 zGv_pdvxHRAlnRK*)-H(*l>Ey=gcS64z?Kory5lDP7ch`;O5yR(=Ix5KI7_&PqaOFb zofz)S%<*>ewpOck20d95M6nrr$#==%5f93($Jyq?tuxw2iUa2?VHP2!*-EVPTH_D2 zo)2>=T{Fzm(sP)}@uGw!Q74Q3gFP?WXzHD!WGLyFIT`wafdd>LL!hS=-3B{Sv>CNe zjuIFuDgOj^p@gf=5iPsASa104r|{tpJ`H*2YMU;DvF+5!0X|7K(>B=>&QL~LJ3*5- z?;iDQP@s11&$vs-94(&?%{G1>*Z;~r6ixpFXqRI-K9FH)VWG-#SBV&1Dm27GfA00k z$q7^aO*9B#kz{L1vDPZqol+)!_YE`wAP}`6F>4fbo8k_@l7*c7q&kG^FooCI&u( z3dj2g`J?w;r!q(Ne4g9Yoqu2>xw;Lxn+4ZNDtB4hU$-jOyiYbbaW{Lsr##h3RO^#? zdYPhbz1)XmzU1w_LH1sEpQjVUL`wQFa!y*Lu{h?^f}~hXp7KRAj8{4ZC4z*!`Msdk ztmRfi8_Dd30}O0(gGkWaA#FIepzss_Z z`Wdge%w5*CRKhl{jM| zhx_|eXJ+;_YfM9`Yhuhh!=IcC#MGzYlDY2>nqA1Dp`kgSYeMw%^Ik|*Fyijj)TK>~ znGWCY>>V#k!zvRZvGh``&R|c=+b{K@%#6X9*q?H+czH=k_txBA*Il%nT|T|+xvoIA zy>;nt#>p=JOFVO!YmC_Zz`xmnho{Qynp4kI*#Dyd-&$&ZH1Jj)EoVD|rEradm4M&7 zZ~LLn<4&5$tXenCzXyEI^6rK<-QqEu5t`!I5u;8UF{4(wjBICmaaA5zqD~AiKuvPD zIU#2kr|*75m%8WYenIjDTBB)wLMQLQ8QDWE?)c1laurK&QTSrSj-EVpeKpG`{elFY zIE1zObd$f#x%+NijYoy|er|=C*UT#D5&~B*dUkuZKy!1603)@H&4`qgv_8E6Rts)g z=a|`eCig$KpL_}AL=E^@4ESM>$J<5ZK7gJaKn93Hc`++PUM!%7_yh! zC*$A%Br>|Z*{t4`0|lSV*GCvF?d(QxdLKn168ZH43eX`;$*coyTv-JLlB?ahCDrA} zI}}jUN1GZO)_vw?9^wtN_{03qCC_uw9O|YiQaQ^Ni95*1qHI=`OVi>}I0Yfa>cj`X zzeY1^$uJSUkKPQu854aqd%11IuyU9f%KDRU)0_6E=J<(aaJJ>!`#v8Asx?Ou@p+6c z&3Ub-;^N}<37&rimd4>OK%PsTB}cl_CDsHH3830#zun~scbWCLBJRzbAn38PL4}U< zvbRD|&}zT&{IHWatzTJ6_|t6Pu_pLEMkg zLMJi?kZTu_}YB=FskWECDDh4>-poT5}x{Nv#j8P0dp0^?kK;TxY(=kJCuW z$rT>mR+~MphY9-#@*}ljv$x()Q5QRQhsv%=&~?zQWeY{>du4@F1DpndO4V z4Ho*&)$Z;8VgW|&X7W6?>LikotIdAcCl`8`PuoA-k5P6D{TfKv?Yt%EnhR_(y}hzs z$X!0@L7uLMO^nb{$}K4&pNrayoq`L^hV7%#GT5&3MCG=o;8CNO`-)i~9c4Ot$`z-t zg6C^qC$KB8}@`jrOush z^*!oR#n{wO9kW08e{tCy)4gs?E|9)nFq;=|S1oB*w~wgBWbR86%oV=un^jO!Qj`cK zj~|7OY7zUpA1|xzby5f9Mpu-Ttrju+C`^`5r$|u1)IsTTB|bsbELt)>$~*mO$zJLp z_;=h|Rrt8mhc>|AiN$m^`T2^S=W`t$on@14H|^2#QuFg_XZOuxqP;Hqf==EnCq6jE zrH@apozJOjspYcN##GgFkAuycwTsDX-_$)H+iYR&GrMM%m6%k{EXs71z|KcLJ)Ewg zg!^1tWYr&rWyvfGZ&W*Ree6t6kH!NAW|Xi5NilHy6;!7Ec{_EaIdP}haWNM<2!u1P zt`9!j{TAUV8&Bvc8pL04FTF1L4^luGkW9ssfEe%8 z`T5&$jS|gVwSrHF8VOK7=t?jih0wEZ)Bc}73okauk(834afN1)p;#idCCCYwPEny( zlM0{lKGnG|u%`gifhtAR@3k_2$<37>(M%M8DHhb}n*V=Xy#-hl(AG7KqF@jr(xo7x zlG2TVAW{k<-O^n{4hSen3rLrQAUWjF-CdFc3_Wzi(DNVA_q+H0K97hpPMovPjuWb^*I%6e_!K3Y&6BMhg{GjS90*`P)hO4HYyYI+h;)c@LnfhNx3LWAXQVNWkvZ#x{f{WCC;^Fc886|UHTUpSLNF6$;;K(qa3wPSX9xhkw0E)9i3 z2YcuOUYD2-Jp~zuvYB)?=UAZV@sd7`5X7zHorN&%NV+W5&|uL=3Gfsd_FK~rf`YoM zphLUDz!~JqQt@S_7QK2Q+E*~wy5G)}^f)}G5+e%y+&!OUH>5H*Wv&|Pqy_|nEHhZS z1P#sltykGVM{K!IlI}@TZ|~A!3wcQ~_i8LYRk7Z}t!BMv`)KrP-8rGXu64dCqQq=u zWibx2G&$*NKiedw>AKEy;WGVS>r=`Gtuzu6uKdXyRKjSn_pF$V6)ubyo1~5-#(xm* z2-=*ciJs4g-$Xk0?*5sq7LVh#_+Vs|(Qy9{c%u$WeUcpuwne7|TBm}gR<-ZLE)ZyC zEog~p&lG;OT2cBP$YiBelKbggtrBls1j>25+^(|byhJ-{^Q7V|7-2taB^QZQ-kzy{ zbrC%-UUwL#ospL(mmnr~=23~ok@T_D=~x>cytJAvu_DsJc(k%}yW*Ef7Sc6ay7D9_ zucb6EW+M8Y&kk_1DbL0xW}Vn>fn>hpTw05txQX_A6 zZttw*KgTEE33Nk1cMM=*H;qVnHQK?UsVV)@!KfL zwT4=>>l3G1ja&Ie3Z3~u4YM`C{)ig(>(^`T(+1QJnMeB_*)Zv_;XKV$nDBu?u4bjg zFleF7pVV9gxwA&;+CFLaY7K%s2?nCcvUMC*)k5*j>QayK=WAI?%=^FC-Ct1g?vZK@ z!ao8}?s>8~n5SvA6q6*P&J{gYU927gU659*wM>Y&111a}vDB}BTu+#!;DMD+&3xF7Ppl_%cX7nU!baw(#9*}4J%{)k%bUz>9v%_$Z=KMeO* zja-5wEF(}S6-ViD_PgCej3iTv)2@jdwVPTZ=!x4d>-(BYn|9xtQ;v6{YJRI*maB$! zpthmfM!ktcAs(lt$9qffrM~9xydo6+DYRKteOQfe5ZDh5b+tdAHkGTdwz)i;3QFQHLyu9hFKaw6D+e>f#7ySBzWGG%s**{2QveQT0Z zb1m^d!3%gK zn^n7(&L@sj&dOALTG_ekrN$#vR&vJs6PG6u;Q-u4f|!R^*xtoGIR^)bDfqD|<{X=n zifZuKVRdh-k?_(?3iQ7Y_rB#i8kTU=);=E~yKp$bg!>b#PkvC!nhdQd9Zwk1^(Qz^ zCCi7<4ua}Vb`)(^du}G^cKEI4WOCEQ$w{2~V_sh)p~!ECRhK<8ZD$$e(FQu*Jc_4f z>9+P^m1XVvM;Z|qncmv16uAW9Un;_Rz_0ebA{6;)b*@~SEOvs%ywKN=S+0#9uxU+r z6$Y;J@2zT|`N!KGH+R-f?!rfKwiu&&Xe!o+)%QzaP$iEYCJdaKfVKQ+G44mF z;r;--)^NSI?|jZ+a00@ib-i>s*_XC&hC$MP<&TNfSM*D_1?G_D$T+Kk>FJ+ZPTQLf zYfH}nzPHM2F#uL254awv%ieFd-oexm;T+eEa%qr1jo9_p{shXXPe}tzP7bKRTLKQ~ zJlARkbL8leE@QZeRL|_QR5u+J+3S}iKBuWY7-y^A?WrsrHgzhic+oGAv39RMb*?pp zIpS?5kTLH2US+hIV~G8kdBG?6x%?zg+J^C*cH6743VP?W?fs0BN8{;YF6{0OLqhya z3oU6XFWv3p8vbnUom}`Vhs!eTb=p0jTvO+S6(teWe0&_71d>OA>aY_yD)cuE8~v}E znZ*@;w;CX=m$Fkz$fd{J>2)q)dAfc9Fkv-8lh!zFLmbX2GSG zPY}(m*@YfYBG2H!^TUA2*&l9&O7%`6Dz$_h&6Tx1YHKhfVtv!o-yfQ=g!fC=I;j>o z$q-I>B*BqRsSv=hwWl3;3nRKwy-B-1TA-=$Kzw{^Dlajy%k6GR{1D|cb;kFoTEKJ>YZ|NBnCFGH8hw6C}QE`ae zUmi3n)@ugs;UbBPvx!C`wM&pHg1MV+XjehV+F>)aC%(V%*W`GaO)9U&xXL+tU~n*1 z-Lggsq(Yb(v2#?`B9hCfXC(?&rFLF148Rr;N?wEN{J69B*!{>guKm+RF_V)1Nr6z* zsTQ&}nx|Pg72S`9r)6hnpE~Cr%z$LmzTyCbpmG^818Hbj8o&W!tgq~W+|Hm-wWPTC zLjo?=iix`9Pr6BwpTSG>A=p8Wv)*A&$6qv85r~xYX>Hn^dmL;C)#O$7>|$2q5km%2 zk>+EO0T0z94b&}dr1V;!r11^Bc_4G21CIk64|{DZ&Uvj%6hdaGYeYJ#OZtfT<^6EE zn>KgD_~jTjY&MnPjM*cIO%W8jH6m|_5fNq)gWlaPBUDAXAz1yOy#kxNg1InmdCueI@MH#I%A*B{fltIrNOo^@^9ks6mjVq9C%~(nyz$duwJ!1@e7qOIUXHCXvs&ZOY0+xJ7te90H}WXDuJX$IH8aqY;vs zm339;^svhP#A31{SKgs-C6-byp5L=|&ah*?-MdF!)Rh-#W@!pJGGWIV4OM&K5~v?9X{c(?Bm_-2Y|1~kqr@lC6$tG6x>mWaS#r@qgUi@$cC zot^!t>M5%Cx()(PbB6Q2(pMVwBWiBDY^*$c)9iM>K1zTbXKyZFNNd8W zovZ7~eb!!}1`H1K7I3a}*8IN(ps}S>Y6zw~RJXokil=P6^e72u)WXjozh#U%TQF z2CC8N&grj>YVAY}2CQC>zpyW9kEXM#j7pJ%T4s zL=V;xNT$)zsi~gxvy&LEjQHjNvh9vdZP`S-sS-0j=_oc`zzGr9*^^$7dGqtp?jq2? z9IesE4Sj?0)CIa$5D01JlT4ZDcb_c~(FDYU+^*L?^fF2>*_Pkc&qxmwb9b{vSc8l> zHa7MOc@&q^*WR1Nx3HqQjCfzahBg+-8ONRuLw!uyA@pEPp`t)FJv2P{RUBzo9V^L(b5Km=Zi?Q`4uasxeO0Q=hO#7AVij zL*LNfTUm)8S+);LN(uoa7YV;93q4-Ep#Lo53ZV#RA~_h_v=;>Ye?U`RG$}5*Y0l`S zu4Sp~_sE;+y7_Kn3YIkskKze%GtA76j>2o}Hqq!xHc1o@?W9#C8@=tbt{z}$S)`l^ zQAXtO0MBkzdWoXG(G~_0cor9dC(VNMk$P~U#lAeBekP!r{_@zpcyh66wiNjmLe8^| z8+aWD{P+W?o>IsTpm9`9I9lDjChdX1Yb3W8dMLNkRGIrv73AOD@p<{6nVrwepTV_0 z`Y(=8-bzcSx*eF`f8V{c7$@4F5j29jt}|72Yszhv)vI3oI{f13BnrQll6uz6$Yngy zC+^}xX<)#06X(_1XhBgcf4T{$k(|KorzkFij!!_sDc$4|9ZFGhaK`$bnpy)mKGAC2 z*F##vsnHtZ`hFa!cMlXCjehk5j2iGD9a|`BLSqL@O3pS`!Rm^q_S5RlTJtv~zoMZQ zg2cDdy8f7@;8H1BG1YQE;%m>!R}Ao1DYL%9$k?2gmOi~y^}cj)`QbfEt)Z&DJ#Nwu zA2}U2s4u7t_^JK;+faLg2UU51uwPh<5Uc*VbzdTQbFaF(WxLxy+gc3`Wn>Cy+I`ej z`5bJiq|3#{CE&dC=jZzF?OSE%$E$aBM+ZxU_X9FaESE87fYk|Dst{_KKik3YTVNU< zEIf(Tf*wIpIVxR#UsxjEN+wtLWSM#x&HBb;?Ah#lyv_#e3XXWTOF?FFaWv6SlBgr%s?;7I$!vErfM0 z%$}cY=pL+bnwqU1E~Vnf^E-zvE|T85&18$LP7+3;rXiK(3z2auWja>?m}EXx7?G9r z6dbVjj;`5)R$7tOXV59}8~o%q@W$ExP!LSjKyl+r%|%X{lYXhNv?NZtK1qD$E%lYy zraWGp{{2TSC`opns?@`~y66oNY7v*fmKKS40;Uk*o$36npK|fhPIO?0_}va~sKYHm zuLAH65q#7x@&}GBeq_ATs|L$5#HbGrRDuYYyhMZ`YoF%QyHPxjRy<(d-h=IFY(t`m zD{eJGs`;=Cpa$zV{xPEE;oZ`beg(0(un-y>J8ncv6ncBTw$~)RiSH1p9~H+U`6G!n z2bCwbX!Cnt4`%p7m9$BpJn|)r4yES9`-D^(7)oV`4W@f z?sa_^7^C@UzMsQp4WABzS((MC+24Rg<6S$TBlT;(JG4kZBPgS<&+s+;R?G*Lw$l!0 zmB{AdTsrg(ayE^3Qm>n-57ve1cG;`GAvfhWI@{ie!BEeD^N}WHpB*ij6F!-^4VdQ{ zQM`dgF!Pmdr?&R?dbow$2!WPfUPVRhz`)&fnV7Cfz@t&jAMdxj7ipl6c&DP$))Aph zjCalXII1=!ebL^QhJu1ZWw_6bQ#PE+s>%~YXD!WL!POC~H$KXqpZNCyx33K)6=jUt zho+{R*Uc$Xpt9X29UX@6KY**Po})f35&(q0Ilu___!kM0rJ zt&MKKXiZdAyCA~9>t}t~7D}X9`mN0xY8lyl7LJWlfdyBCOiI@J%f#~z3+uE#D>f^@sZ499gq9e4qAZ$@y z^NBaYv__y{4eafd4(kfDZ#it6!I9XJVh<^IOHt2?2>B4KHH5mZgh%v`_dKG;6h$V*3Q*=cgthW%<2kQ{#f_nY`xx;_2d#@X*j6;DMHxmfmcX zTEqn|lO4dk5^6ctqqornMl!Ex2oY`DFTPKJD(grVUhu-0L-`sb(46Oh$z zAdhGzhJasqz$dJ%4;UB{0t10}HMBwGmIBW>3b()oJeA%(&{HRp3uETu3YVXPk`)6A=0D?C!?!+tB;yg4cQSgl%!7a-(T=pFqIq;axyY1uCw`tWR1NZ1rLvm6w-K zxD7IaztbKZ;}&^f+=26ulaRmxwG*9Uy38Y1)`-AByv433r~)z99{@$U)yTo`ymJo$ zw_p+xNjTZ4u0)u{wKVw=mu`{pPA%?RTe)rAmKd}5r*fQ|-obsc zlx%{&%-c)8H{G0Fm=$|rH_m>+c9AJ9SRQ>Tw5c?|w7tMh>>Pxs?B@An1)cmvVIccp%InztRq) zxiY9f(+D|&qkwCXbmP$C*Kgxnc8gtxla-r{uV6z%Ll>cLAndMJ{e95>TN(7|9L{CY zs`>_ue&?uFO!7YYeI7=V&tmSyiOkA5!8Lqt1YckNi5Kn0Mk6IT$g%K%y16w!_1Z*vT`={B_lTc z30+T;x*G|h{s#vTmQH#e9?<7~rKCjC&C2>pEL4ub*Bca%F)BIC))v#&(coOm45lR~ zhw_+d$@@fy(7|TgLQ?@j>ef;QT}pZRb&wvv^#@s!{wwkTowK-d!H#ZALM0aTOtZ-$#AD{q*A0`RH2D&P&0qkT!CwcZme( z2qQ){5+-?#MDo2t*B1Ws>ZEGy>uHNGed2k$PqP&2^~5D$mGZK3T>-7KL`hZodX zN_W%gTCnPMF4JCVze~cRsAr8FIAWQ@F%s)pyh19!M)S5^sLW44k;By))#rpaTK?6X z*mi;mKS;?!x!B@}Gfep*r+=EY1_Zb+67_peQQa;6>gMN8WPp8=Z1Ar@<+s4sK4TRA zR6lo?RKCZ>Ndh+85(kI1scIt?C}eHowdxp)!k|KXcefOdUTOh36`y&->b8Qqa%;OH zG{g#E<=gY&@&)!|B=ew3qz<;8u6qHhe zx&TsRjAT*m0%JH=_#Ia62|+eevR1C$Ci~!pU!cN0258Ydv$BYbOG=qaEyfBXp5L#l zI@*0BE&Z!HHvylDuK*x4pdx5)<_e2&zjD=GOo>VEow{#wbabaCr1LtR-4nmqC6T8XoMa!GczzT;UeGy zE_>v-1hmtA$&J^%lSSLSZx9iKUnSs)@R|3Lm~()mK=f(?Il zIM)td%#m5Le;5UzFwB-Oo!fWEs;rLCxbRniWn3AK!}hFy?Z@6g>d;0Qv&2L`A13Fv>(-U zU6sl3j`X2aTgmcqxGFEs=Hat^-%)|lM^|g@mj)@`pl2rWh1gdkZ?cXs1x0343aFpe zO)M!+*_I{^4Aa7slCXIJEuVD-T=$-`iv$Gn2zg?Koc0-FJ}mX{h}=BiOw#)9Ea~03 zkd{*QLs{#P&#Rsz+sgSz762VwRWE&XR2tkT^-#Ta1K&ox$Hyer`=gSuI^4oBJKotQ zty}F27Xy{#zHXqk&JqE=ZTnM}__ov}_b)j)GUfns{|^0)cWjG@gCgl@&6VGhjj;Um2&wKG(k=m)SGUjX2z>=kOA6_H}ED= zVKer`THDtfMm&fS3yk|2j<>ZqrpbMYJc# zp}xNs>8a0P2yGi=5cz#UlBOa24;Nv~hCxJtNJpje_2DZGnVKOzq!OjWXEbsvnkJB+ zRHk^vlN@+>bt}Vc1yeO=`URa^-;yt$;9H;o^7wde0y6j%uzowuW|BGWENc@w_ftLx z9$d&$wHxWa+grdAhpay4MV_C~X?!NpR`CffdwfB#tjSp7`=1_2$xLZ#DY2U5{EVaQ^i6qz}K+FA|C8fNV z9Ht?bE#Hu;xhK?``f)ym*f}8PWqfVZl!)&9@h= zPgt|t-^i!_+FxTMr;t`~6D9o+X@}J08~8KOB6i+OM;x*``~MjGjs_v~OYhy!{|rvJ zBXYZ9 z^`!h;n{h?aMAe<1fgIzbl*vrCHJLqIPdKu@p#y>aHJUXRR2&FW8W z&vU@Bagrc1DDr3TTVbPxjl441{$N?5%b1a6c4Xyq^YZB~H<*5)udj_g@to1Xz#ymU z_$f#bZ7MZC85xBpBn)LhSx8e;8+#>JM~ZCb9-W@oy;dptcH>hS{zeS7FzUR&kSd?< z@aB_VC=rA8O&>iPwuX^YgA~r3MhCf9IUSbzE{0EC<1YCEfwNNiOB~oJGuXu4?e3lP zipEyjN6Gg_eWKMHxa($ecKvwMtdWQBi_3ir?bkzmPl{>``$|$(y}Bf6GY&u<=gb_&;KO@w7M-!+js*W z)Yl>LdHJFJS?LYfDQ9%>E_vG`mm;=XWxLS)zVqc8ati+aWT`H6?^d&RZs{N(A!3Ar zJy<7|xVpZS`agLkN*(q`5dv`C&tvO_Ca%$Te@PNG9?N#Kg8Zq-uxEN)sS^jUsX{~U zX@_)-l3>s<9CFq3J_W@xnN!K%ow_iDCx9&%unjf0D`v1AD2R*W7+`59IJ@hPvK53y zToXOJt&r$)jp2_dy?!ED<3sy7ZKF0zZ%6>6{PkVKqEr93Q%<|s!AkqpPV4@!?Nlp1iNY=Hs#fla!b*|P*Va_I zR5)tmGZk;Ox5>25L9R>_UK4;;0D72-u7iXV7q`uwqpAs)!Kb9`zo+NcT}P|YcSc}Z za#|M!sTLqJKO771B@V_r)qL8FS_qY&tdAdK{L(<=ju{s+pM?7!1UEIanq)rdiqULP zVkQM?Sip~abU+C>a+nwJjrT0(RvKGMO|(OG4Fu3gJFZ>k4uEY>#GAYC)nW)b3$dII znt1>e75I(-kwP{`e0(aE|%lkg|3i7h1~EOUMtT5J6+%l3u#?QVtg^!46G&q`4#vM_dF zHZwjeQ-3VX8Ikv0*ltW z&{NS;$fOH(aFboE;IHrMR%)-!)P+bEezB->lK~F@W$S5(ke|37OID7~K-yKUlSWs7 zu-LYto0hHf?YG@%p-XbNm`JB>Dhmp11Zevk=wnvj>#yXyN5oL)BO z8DKs0EmV0xgMkEe?SRd_;clrw^I6Z2N`a$%QD9vJq}JS#LU4qDMg7JS3&8g!M@sGly zv#&e~f5s5X{R%oP`|G2)FOPf6PnE8Q!kiwRCw|i=VlNaLIr8zb8@ZnyXI@2&8Barv z>NoaxyMnn$^k-yFhc+huKuxLQ%1FdEOD>a)Z-GCISz0__Nw#-VwXP^ht5(}Sfz=*~ zg0K>9v8dejss0oY_qGpPR0=pPIn{cqn7@&h|5aWd(XH=&?3WOZ#?o$Up9GSKkjM3n~ zQrg+PQSCcgV@Fq@64>B(oux7*Y^=!ed+aQz5F)}eO#LKqYf~%m!Kg^iPu5ml-SS2!Z2;y*pLwwM6B!T&bL=Yv$f~ zAyVq2lo8vPap05AUl{rYeA4-TZuYU6-dv2mNoiI=i;m|=kNC<@3!jq2#N-i6p)f>H zPswP4lD@?;jP`HMYnv%xyY?{BqUck0>ixj-pSLz68oZ z3W05Q`<$K9uSKuw_*k%tmah^`3lLx$tjs5(Pfn2{_>Nq%!&cG zR3Xi7@b%Ho8f-}%s2E6nonBv@B2`>+RK9w!8l(KarO8Ve z4ms%TdZXX(C6J@#d_B@&d!F5+I~xW|T@eSxEndc8J#ejl68axT{)EPawvYs%3V|7c zEIvVI!sV=7eyQZdeW|p;-0A=;!nm@96RU{p^j3nB&hkeRI5Qr? zf;z5WUfQI8c(*}DFjfI&XUA;Fn&0PRy6roL?gPZ-YhuNsd6REdj&rMEF_5%`K!nBUIn0YDUGRuA2!a_~~r$c_R@BYKXvry={#aBdC#g{3qavgH13wIJv~m=o^k^uKiSHSl29&5BTPqNoKGnj9ZDkxLVmJ-w3W(^C2WgB?8`-Mpy82-gE}Qdr=ss5ZTK=_nhPRjUteagpsT36zwIIdvMJkLrjLcd-;@iC z9V!SrX;{h(K4cskL7n8bf^#hrq#`V*uiyFIt}I>-)MP+lOrz42B0EowQwK3vvaj;d zO~vfL^b5*=1WK1%N66_b!tPsRYQuI;qn=Uu)Hp9#k4@QoIl4tHoyu!{=U{oBMS}Hz zHDll3%8FqeF)~*0{NbPd%6?`I!TdxrW~x3^%CtK(;eOUF#1ZaN#tL&E!#zZGh%UJf z!q2qeOeu+mqwrspGRe%#oNLyu?E#5tSCV=Q-}z4Om0zLwsDfs@?{X3ufy>3Nnzi&^1 z9*3VEBHjHARH5T~2+$U_10|6IzASdI>){)c3^S@8GYjloGQ=a&0N_}B%)#q`6>1<8 zLu2he?byQgiWhc>eI*$@*iUqy{FdE%mce{r=URX7jP>-vBQ}|5vUW=jp=Cr$ETnUF z_4@I@MJG}Fs{^B>4W6%BeccQH%V9)C8#uqBi=&g;PH9d^9);-)(+O{Gn_J=33)M>7 zPfe1s01s;?WG#S~Vxx(9bn!oJAN=i|N&FcJ;gd2$6a9Wb9ZX5;7w{RkQbzFozQd=* zP1^4?#yyEc+Qc)eskKmsqKAKT(AyoGg!%d-?r?KNw^Aorfy;$pD z<4pY~Nn4h%vZCf*YRDS;hI=fpk*<#J#_Yb!Xqf@7*x^h#cCd*mX~Afl@{8^+879VN z&<;s!+@vdnZtp#Dn;mCZNYK4u4;fKa>0C}kr7 zFPaDUoeQ{qLUZc;4H)5$aK4JGIgwwRWA2!aG}q(!os%BKAS=i5!cuqyvl}RV`cu`+ z_4reb7#R>P@SLV&!PernDH5|@%uB0(d+;kcGbY1*p9)~3av1^GzQGq^6?k0VwMyd` z*TJ#nE`{&T9Os%N3qqcAh;!Tnjd5ZENeS}=AQ>3KYd(iLMP~48BI*vSsB3nbeN`)* zXtiLdu3Z!J;iTQtnvC@8zEQvVq^=Ydo1xfPDUIM@QB zDwOs&vL6YG9*DRXTj645kHJ8Vjp2KBl zm2E-Zu9Mw=lwWyWG1+KqXv0Vy2tTe9fBwasV}_0%TsipMlb>gS?)lfG(bxft8wX#T z|AjmQ8Hjt69eZ`lc9!XE!i)ZTP=J~v9&s@Q6~=Hyb7x{fc2R6iFXW7;Ri6haxT8 zWtzbIawgwrFV8K>P4M;&0jja>ZExld)IXwcj2}b-Y(w1=h%lii!X|)xSp%8q2^MIX z$~>f8XbgdG_4|Ze$)6>y*NJwTXjq3RJgfZj=g&Q?S(|_|gPC3D7(s`-MVG5W}0|)y0Ph=(8Ug| z#y20_WzS9bZqz`Oyw~-Z8Z-Ug7D4p%ll);K_CY4(pr0{zR3sT*Moy4d3{WpS?pK30{M&$70H?#<%LJwXr@dc(X>EpD867C>xCCoUbkQsWUhk*52c=A^(LFS zqD9+Lx}Kh%jWZ8v0|+?0E_122W+PQn-{21k4z=J6?ZzojHNee5ovMFC5&`b?HiX{j zX0^ycmL=?rG2W9+ zY2|e=tx)?)g!Ge`_u^99A9BjR8mOwkn=@C`*0in+4m#kUq5@#Hm`T284jtkG{4x)wwTvtOWHuWE*jIMayFs zYFTyu7U028Vin$SQ_g(_8BE-!TT_{hDgdzRPyJ)Mo-jY6_PgUJK2~8t2&&Q;UI&Gc zZ4lL54`^pIFx%7)4nZucD)k^5lXkH)Q3mKT!@S28-wV)@o zr+-iJY(*z>UnM-HDo`E4XT~!_@VeI~ff3arwUhkONoke88}jw98nH^j^&CIHJ!2Ny z5H-JtnOBTn{%Zeh$^>+U9}J79(t0Xax_)!`E;Pj0x^b%+vN_0l-wf|h23e{)4;Dd1(cw%#@smH@#Ydi9tV)R(1Zw2pjtX( zeJ7y##C7&Y+9Bcq^ z7nG+jWMyfv0ERDeLSQ%h34e&E1js}(FgE*kE;kjLgQm7Ds|7Vb|JKQWnZZuRW72@_ zYLDY9m<0r~3AIZwCaU#LV!A#lbf*ht^I>zX2nor!sGph)3E1(>R7tI1P~XpDb%06% zBG;?S0Z}Hped#gEfBuWqq-O?O-*ZjBpWnlM{z;8_aF)b`>aXAaQUkQWfg^pK<5sW%^!Y85d zuZ=`g&Q{o)Ri(Op&aaX=U^&hiNGMRD1<2(7jSdJ|Kr@)wxCd}GO8a11=&X&L(#X!N z)fBmedcaDoi~DYedLykEWe~tx+#z`Hpbm43H0BdksYvKqb+G2k84dvS>#iP%G^+Vp zfGXg`d4J#0cS!5+8@&8_H<((W!?6}!dw5V<orp8 zxkp^LY+V-AvyXuMq0*7IC1J%S@I~(}ST%)Dzm>yiUd<$>m+qZ_mK#Ud zukv2}*PHwIZA&ni)!3TcgeE<|&!2PfQR|tfyqJ{ROJ_ar#@EwexPl(fZ1-T?@$g7d zK4~?~myz82H&2%0<=K8C_HQS5R#sS)f3prFYm#Sks`ayRbaWgy$g3P}VHQlZ2@i(z z?pP>u@TxjPzS~szescZbC%Z;Ht9tny|MR8o%`E{%N$BNU0;VQfKh5!~U`%mK?0|aP zkK|D7YhxGOvvK^aF*0N=>mLb=<7Qas4%|+E=~)1!vtOJj&?)AWJceyARZ{?c)gk6V||Y zp`Fp|QV#^po_y>P&*{=IFC{C=y;)R3FjCJNz0brpKAsc*GKKMWe&OwW#Ud=KqH@xr zBksIvI^AnR5|*49amLH^vvUFYg}cPCSCY34&9HkI5Y~UFH|!EI@i7E?Uw<`a^gIx? zyb9+dVIXb3arA68WKJ-jqUe|9r$tKfVy7#^O|$N30YdWzo8zT1LR0dl+v&t{qJ+#s zbj*y{;J=t>we(xxLe=1t7qmI&o#G*)U5ZA|XoSQ34sA zL%_Sivws1m^)f5092;gU+D8*>iul9N9$lKB4 zDPz3fDE<`Ie2{)sVm9863?X-IE!eVkcgAYV?eMNdo7k}#7tNQCqR*Y0HJc2(S|Me} zdAF$;Mm=3ePMoHo1n6J~l(44T4vQC`u*9eOeU;_0y%WJv(w?kpC*E_~-U_2P95rN}wiR@}OU~3K4#?u|w!`hZ-wGb%u=)WWz}h7k`Mk7;0bAh+W>zo%y5Q3C`i^ zIB6bs+?Ly(x-eZ8_tL7d(Bw6%qpSU6joJ22c~zUW)>@vUZKq}?n1PT2ktfgtiqQKM znA0($+fCzB_r`0tdc`{<_bZV_Cf(nz>oG)(%+z8KO-x;H+#ts@zlG!$#ioYrf@-)= z(a<=j^FKtYtdZtdso7DNia&9DYr4X;Pwug3oZE(OO(-4G9jea~2jIF}CTzw<#7G(sW!zvdC)unp z+NwUra3Cmssv*pkpX-=v<($S6UU|6VUtJ#t-JIJFu-4z;j<+|IW z@5Wqu2g86V;i{Y3oCakZmDlopr`0HM5#`E=FsI#XQg^R|*4mJSSOFa>hCeTkLu$T_ z4UhK9&0VdsBC};n?R5~@$;jrp^I+SgjAN$fl`rA$*(T<;Hs)A6EYbZuBFX{*#!`{f z;5sgOK1Y-BlC_~me)(mvnGZa-vS9>AIf@$D9&RI{5mshue|Al#v5uP< zw=JkgGV0T>;k@JurRa4%2c@VIT-Z!(&IdE{c17Ar!bo*^g4@GVMwE0;FZ{|RtNh=m zF5F#Jo|>&t7j3L2#E@83?VmSm1^?T6jr-fD^y4+hTracfD1>E3<4hi1jnzK7Sx-er zmG3nN<~8YeVZZhfy?2?kHzHMHF6kNJOagiT3IDx^-;|VLU{y z;2d$l^5H4r7IK$wR1V#@x_h{EIDu)vWMT-Jp%Y_Ymt}AZQpSp*XJR)rp~$vt+thMb zOV6(Nt11V!snoC1{W|N!ysgTg&lxt#NF%OVwi&NIzczgMq;Z9qJz4^xEhe?Ja?*Rg zt6udP4ikA{JcMnue^l{dRF01(jF$8%E zL*IqkUbw{2fEWJ`9C`eF{$Sw*RgDAS&8=!7MYZ7^~F@crvv%hy1rYHA9G`>h_5<7uxg{M(MU>vwvS-ky+o zyfJS%wIe7WtKq)th~Y`j-lQr2>fob`s6F)PVT&IRh){fk7)iXJC}gq)i7B@iK8MoV z!LIC1uniVz(t7c^M^5KzQwvj@#~yBC)ElI&urpTU7rn%J)G-+~uhMpo?Pyb_owmEb zd=zs#Pd4-opLPhjTZUF2O|-)^qj=Q6ylaAK5Yso9#~bI?;s`o`oqkd2U$euUx+rdo z?V-QG${hBx-GcL{yOWqWt$4^%ERCylD9jL_R=W|@|bObh7I%qk~FwSlt-hf$J+cZkq zy&qE1$ zC&4KlM{T)fT4$#8db_0?U^{cnmokplsTteO%YDKHU68WVscvAgGSNTcl7%E)tNq%w3-VhM6-`xIatzC z)rS=8;2nUB;9+)fchp8B8GqY9I{ncBIHHQN*zh=GE;tEd-(}Q<( zw5}0#e@CNm|E<1B>*N`2jQmISb-YqadmOp-o+|T^`r|x**yL4MABE|9Nv_$%h8XSu z)B{aaG2BO2sZO=lv+J=qTEU$4zoBODo~ku===Bke&~In#i{he~cz)X7sM3@$gHCt7e{A<7o(tIe!w$tUbmJT&ny3*m?`FD7&t0c<7-+ z8i!O6k&qSyhDI8ckWK+f>5xuoR6trnx}{SH|o`se9p_d8eVnljy`lU>UFUg@po6qAOw10&B+BKdnygkuRRR3Z&ef zH1w47=arB^WeBF0|6)|mN-#>PHQi|QyyiEf74Kof{^i4;?lKJ)FYZLKfAwf~}er|g6zhf4JzcF@fResVhZWulJM!Nxr>gvn)=y{E6~S$&50 z$b%e}R_ZnZ+RfdmjnzB`@3YZ0f>Jc=-p4^pVsA@|S$PE)qs8~$4zwq^H~GeEF~m0Q zv6Yjz;x$_#E-k1c>0ga%F);CcTdiuwhl*XT+gJ|u!)37OU5*arGF;NQV^<=RqDO)= zBu)x4NbNHCZ*A?o`BopP^qtuIx396y^ElkrURBbhcbxs2eTPMkZ0H-eUUZ}&>8r*> zzEw1CKzmre4nUB;!8#T%>JJSdDFTqXtv4jBIo;-8q_2B;y)(-pOS+ z7F4d;ECo&Wq=Ifa_G0f40l%IMw27poE2AVL8VycH8j0b4=jb{;X7 zJ1EC=ed-uL%85Q)y~ixuNX*6lYB6+6`|}HSpWO(<#UjHC?w2n|=4#dDo4A(mK0X|o zGe(dV;}z+~=AJE)q+L{R(NDv#dv=F~y?#ifASE@TQmj{xqf^ZsL}U!f%Km9BJ5enu zYs5$K+Lo~Y%m<#xDfSFez$!+{CR}}d2l`#7{J#x2lmeO0Gas3pYcuX_@{`uZj^x`*}dP{Kg%ZF~*0YE2J|R@y-_7bV`~U z_Y~Nx!VZ#j4)zdxHum8R&es>pO^{w((E_|s*HFBmIH7%=L+$j4!OzDG=j|658XSjb zhv1FLZm_im3EMPnmu}_vmd8B0HHPF|s`;eSK(sX<_wA5US1W66{0g<%c=)p3)z-hl z<55*Yt__*`9E?3@pow5CE739DPntP+zA2PA^|;(ol+XXbN{gQV(9Aq$ej1BG-PW8S zj{&ShxeQNf!m*#;Tjj6hUZ2y%E)=2(#Z(1YHlF$}M1RQHVEXkV?DCH;S4|0rwIZ>- z%t;c`vxc4_w(iXEv%hxhk~3;%qK{$u51mWu;y-1FmO^E&q{*#^sg*N2+;lQCg|tyh zp=DincFsmPO}}dV(Xu~!IXY)5Qt@I_X!;nKP;{9O1|Q$3{?w=UANGIgJwE+Cw;)J{ z*MTZ$a3~VyT}0!or+wf8M<%Ty>l4q?J;BA8&7q&u;vL3x*`?Zr+tWci!(yD! zq@^k9bt0c%vP1=Sj#meL-*F0yb1e*Vi}!E_q*v+;TrS(XhV3p|LV&jA(a9T#C{(7rzNdkvWxz5_bLQW`ul7irNysZ z2U#VJnv`{N2Hs`=04^IW(|yOFbmZNjce^uM)Z{-up!I_AlB68o&NU>Hy6 z=`siJygP>5Pvq+riR`-9W#`^QG6bzqANWbRb_~d}IZa0&H`pOH;vI z{2T>+W)k$T4q-blLrw%(5JcKLl=GVWigKZ$-G;iT79-dWvKiWAiB+!)BaeTAy+#gm zoIb%|i*LXta2qE-zq_CBvar#HU_k79ephB3Pgno2v@@klxSs0#GOoW~VacK2{hIwO{0F&Uh$~V6Ryr5Xo5(}~in^enRiV8Gpux5QQb@n;T8!N1+ zia+hgZ}y*1Idsut(9>vES)^uf6!8f#o{Y`KZ!*4~2qT46iH$OS*5=o(&;g$*wyyyx&ZX$}I#*ddH!@Whm<3$C~(s z%B!kU)^aP5sCTch!xJqeYxC(`aOB7{Bip-{)auJKQ;XY+Tjepy!M`;OS#Re(fe zsqoIm=Yiux&=~}5r0Z7k@#HkA;BPwLdwl+g?I?kx4s zTv@)PF1&lFY*8HSH|Eo>XXMK_o~k@*d~Bc4;(N>#v_cYoNK=;TP%<}Ro|yXIvy~aY zB3Th>4`or33EY0a&(cu(!7X9WIHXhMnT@B>1``!M*0!F?-B>4}GprIS6*)CCmwTFX zYtY0?p>#Z56u0+#>+h>G1#IgD+;Y(mx{j%@?KW4k+DuG`xx?I@dSCVNZ5I^vtYM}; z97dt1!O?()KD)hiCVhALr%tkw%~P$ML*R?GcyfLVcA6>I-$5EYg|_SwNfkz}l}ku^ zj%i$@N8iTx(B>2PabO?L>__5ja22b8=8ZVi*Cp~;V`#kRCvXtw_b^jK+OYA>)W>WXi{1Wt6O z5xZ>z&c_xd_f|~`AG^V(BTh1goYxrl+h?oc`wPL63+J{o_yuRPtSVu&857(2@(7Rf zX!_#4{?`)k$;STg%1ObKULZ*MXhZP^w1D^eMy)VcO7K;_BZ%iH-%dl|05c{?i%)K{ zl+Tu}h&#LIPA1(&`;cQ^2o3Q)k(aa%i9n? z5aw1IYfoD-8{VAYyNP2mL7NVFrG&f)?d*5t?v%DL(IjY;i@IY^wWLXtThaTh*Ul3h z`)*1X;>UHj5H`zU=#sg81>5i@TGc$IJ9#yW#p9rac@HbAg!*2VpmqsDn`I(H?Ut{}wrtdF9#_$YT%S__K56oKsG zEYDuz&i8y?-M8?wjrGqA8m-n+Iid4Kz9H2oWOdmM6t3HSFmCcU>)ZFIWU0yDQuyXN zWG{=)RbwoL3lMq!VOWXMRhWI&BCJmF8Z|wOyR>{5+Hx)%rdY`6RNui&?;X-0R9wAg z`@wp)s7KHF#A|JP;8%^VSTy#nuH#*K0$BR;0*hE<%&74VS4DvGcbzdMSY=&KadHhG%` zoL&z~>YvQqtIE=lyy#KY7;_016aZzsM5P^ zDFGY)*{Uy(Zs-FYs~jIOB~{ySx#fzPHG#a-YF~-Z7_T~TtDyJt`EQqD6E8>cUvKxT z`OwnW>C7qxbluWuziJ3hoap=#h*0T^-X4lc0?H+VOoko>=@-O~S3q{$xzIuTphP%#0UtDMX$NwUc}v&1KQ+ z1T--tRO1pZcVhsU0Z7VAgwSup+N;-MMBH&e8bBBG*2Fhp&jFybGJajoO^=T&JThxK z_{pZ-P}PL<=VoM`jsD3SrLq&`jIZ8Uu^ww#{D^r^j{bbVBUb_rjl(T0G|7i~d8tcO z#jt!jC_yhO+|%L3(=C4y@^@zc2Lzt+b)fTJeWZn0vNwLGl~<^exMR8oH;bDup|iq> z7#L5hjxXGzhLVX9l>8aE`-`3E4P&=B+hc;vdS5>QGrYIUbGdj8-{9J?gzp)`L*a#3 z+W{?3?d@z3r_&%MqE7c9#Nu4_qe0HzIuVJV7QHmSVs9~FEj3RnG&sbeUO57oH(l^$@U$<j!U2T_|5jxl$0?1RTqMai^< zwGw`ajgRjhpMSKi*!6OJ%SltpuK(i(#Q)FuhY@%in1NQO*j$>i!tQ3ZXI^NYw7*t4 zEH;K>u~r4$(_#Xb8P8Xa8Timvo$UO0FW4LtvNmnu2gh#hdKK_VSwQR@1!st3N?e+L zJ)+;+5%@f6>D5ESRosnqjToF)e0(|Ihw+7mHw%e;MkuovfOroM%4x#5&QKk1yB+X; z6}!YYuh#TFc9pt1G4#_)+R-^*y7K4QqU2z*W z<$Z<)8hxkvSsz>C+4pGY^q*0J+t!v!0qEYWZB9D_2lSK#CKGTGj|iXLd95f*j(D~6 zW&6@EJ0^K-JMbf&PaO&PSJ{mmw=I%=`qX2z_r~L_e0e(e_PU-!z&cbygVX;OnPzc- z--A;jHlIAsJWm(G&iCT3vcnc#*8ctf9mAWi@*4qx#88AKzII7w@|{6a!yz}V5O3_s zu*7+;J;=|bE1-l6-98Xg#1w6rKaRO_BgvLr=WYT?o7NRh$tQO?1(}zFu87)raZ}?w z;)~5z@jD35Mm@;2Cyor$gwcMv24cvDic??XGqkz=;O{Oi9-_%KP!%5a5?IJkHnh26h_^C9PvwwR<*uq ztxc}Kg=|pYqX)F0M~_ ztbDQK{9Xi$8hJi0`5fkopw?DccJtCRZ1DdboDqPh!Pk_2ot3|09-Y+BX%QUy!(+jtVkiQ1z@o6=Z zD){h|Ob5gfn{$$*7lwgyohXq0pvBm_OR@L1YqS7)VRAo#LevGWz0+4dH+rXUcfXk~ zMyH|!S`Hw4M3e^h9Zn>w8P~?#gS!E^w4vmP@u-KRsY6fWL=PQ7l5UF+Xbdf2YmQG? zD_$Pz-1a`;m1++^J~Hmvzr$}o8~&_N$}jz9mpJK^ER!4_NSu))pyZH$Op#Y069J@M+r$||Rqm!A zm7nly)Qtk31^nAftuaJBsSct)^9%#$t$qEq^dnB#uW-v=#`+#B;ta{QVA!fiK36Gw zpH-GJ2x&h5PHSERONf z5cCz_jWx!9tO*w+Cn0iLANR6>nO@O3F!$})Cz51(5O(Ms>1;2*Tqd9~JZLW4o(fp= z5+n3p&JD1(2zuwQR*R$2+IVZ%j7EKV`Xi+{y;Hl5w!#uhy6#vq;G5;ryqha$@(r=p zFCLjkX}q-qnGXv+pyN5(>RUtQzTW4dgAM78cXmakJoKJ=rmZR9lYaO#ec5=i>&L|B zTJ8mxn~cBk!9UZ2sKH4pv_gH&RpZi4G*(k}CbLg<>hiLaZQL_ZHbEeo$N>vatyZDT+jebn zeiW}4^O1huZ)a{&cG}+um8OF4l>NLno`17r90~`tp6t#K7KW+heQMr1Ng1Zy3Sr>X z;(f!O3dElED3vEP1$-Sf3>Nt$cUO5_X0LL9$)nfeJS8+zZ7aFyga_0$9vn~Tooeom zgVy01f4bnWjUiifWB6U0*QB#3nf; zHNxgR1*REHN8bUrlya#%xe=MZC01j_;M1W$I3?QZn?E6%qtb|asZ{~l(VG~y$UI#4 zJ)ryCgPcj{zg6OP$$G4fXuK8IdLaf785ur(C;)2;l>8ZTT|}NoqGrm1bOwh;bE5rq zru2bvd-t(%LG?nksFVPgzI^_bB{CfA@cSQ7H0kS8h~GTx{{emQnz-{)pK&c(it)`4 z-5Qg%_fN>`Yc^E>c+i4ln%*=clNH=(Thbk?WN`EuuYraxQ-_FbK>&Zi_yzn*eeljSkkAI!N7FgLLKi)M}?Zjvn z@Ay2b3~T(Yy;Z&|O$}S|a&@-1^>Q^s%MXvu(iIj$Cb_&B=>A0IC*V-$nZ6_g6~+g# zy^e_m8DktgkAEA}*3G-u1&sHa-^cfZH0uyZ(k)Iu-UsHb^XIZeo~JSTk{Le(XSG9D zISJd2KKe_G9g@N9{U7Vl?p4 zs!}Ja7e^u*m}M{N&FXX}XJ6euoI!lv#-QU)hGo;M7AJ!=%UoK^oug_7p}^VT-T(Wv zmUXTcSlO5L7;^79p<6MbBAX*%VT0s3X;D;tEE&gADD_RZn?2o(pU9uzTLZzR>mzP< z0V7I1)K^4ovEFn^-woJKn@hH5uuU(n!QVu!zRXK{{LjUoo3>(yq>DP%qI8YfJ+aA7 zFEj;WlfBuRR^aA|*IAWZ^`Q?()??%mU$&jDNLMtKi*|^~r}q=pMcBgBu19NAk8Wm0 zsGRbei(8{>NEPoZJD4K&{LwnC14SA2Ry6nW)AXb@qjGz=IVSP_(d490yDD_E{P83C zo8>6WoJqxnhudH$KCEP!Opv)sl(io01%C9K(`)M|S`OBL)4UMBo&ef-FZ`RGCK?m? zds%@UE+6d;aalM=K5){Y!w5>ObXPNFPO*4U;DY=IB}EO@yzDg;XS0~*!Rq!smU1&e z4&2h+ahlL{MlNi~S#%Up0so4wDEc!L$>9KDOS9+x+7=_EF0n%{MkD4ifg&!sj(8;{ zRQ|{5oH{5PUv-IIUp%~qfpe#3^muMNa$yq&A9Lk`r{&*Hek_#h0?tbmCbc{7Ok4H> zYUb=$IWtl9KzJ@8{u{g)gf32XwB|^7G0)4wN+s(VwB~{)xXoFlb+}fj{@MLLC54FS z%uNJ#+!L}gUcDzj(FpcDR5_pB*_f_^F}`~s686r$$IcED>tdppc>{=Frp+n;v zhd+i2oRf!CKO7Vq02w9KoC=DWExX#ia4t0!UfvBU=67v%71_qm!&A5qBum$`T3S$q z-T2yzb`G6yM*i9JCXxuixB9L)hUnay^pwncnit(T?4gdTF7a^(%SV=yTmpVFt#oMA zj=66=C4nir6gWv77D4AlRlw zXBX@ElsIlDU*9^34=*T+s?FR+pxN3>_8ObzV1i;>W+?%Uy|}|{$G79>Sl;6aHnFGl zL*JpETFIIlr@ea}HtotqG$Liiss+Mkc3z1b1V+TwXW!tPS(Lhn95lixB#ItmBr5bbMz36e zW&ZIITkGGxJ`(8t=;^ZMkwW00Go>a`+YUU4G0<2iF3`aHW->=2ONvG^xjUqmCY z7owBZd7WR{7@*Xx&F9hqQg)(7W^!v3kCm-B<~nE~!8~!TWVZqF(O6xX1Kc`k`fD4nb@|*D=R3iAZ^J?E*y}M;V(&}dd zmdgSGtjtDWyamh2ba$;BQW+m4z{xpNCJ}iUL14hA&dQJzr0QLU61(sc{$6cTLm(V8 zy}ITFw3|aTB$vshjfIRX>T_{0Cw%T{(qK8y5m+-V+LIgr_vr1QyNeLOEGx8W#!6@W z#>Q$|4CKqqY-myh?Ay{su(p{|Z$^4V`20O65M8gAgsH=(th~}-qL#Q}4hl0|lq9-B zkuMb1-*cmz=PmqHdSFsUkvYo`RbBH0BUV`#yqvG7vL3~`za-6mu z$coIzvc#K1ks$}R)*s2Rz08##(;38Psk15$)9Jc2+sEAg zx?IZ%4H+y(@2U82u5n>)+WQ=SHY;j~YU#=Gq}Pm~R2Wez;PeY)2Qy0bflRv&xBb<0 zN#p1`K@h|De4lj?4xw{$I9 z!__*2`m3O&i-Hy8Bg35^c^|9u=a}Ld)nB2{y~Y{a8z+2yPt%iYO;h}i&Szt{&I*Un z=wJa$_ud6SEdgMqT4U|C?yp$5Lb)~gN-pD2?U0gP3CiJK%-tbTqdaz7xDnVTkzUotbLhbDlnRnOm_Z)0?gBkxvgu)Jk49A9c0Km*smX% zMoX-1tjBK~dLQ$D*vwot`Dx)px;0qw&DH5pxPHgwQD3}$=9-qF%+kp|Lw0z%2l3It zFv#-es@q(QN?zZZYSH&g3#ndX|G-8LFVhV^C@z|hPB*B`vaUgi)!d zF!C5wT-^6rzc^)XmWIw&!GKsnRG3Q6z*(5l_mn@VB>%mQww%Gqle+5c_;qfrRy1P@ z?5{6{u4@#Wg#_nVv!2vv94?)UTMk_?{VJj2u^PfQ4?+zyjx5JV(Sa~w>R9<)F0d_A ziYZRA1s<^2kY6_E-_Z@Z{~PLi*_9pFXXx~-}aid#eh` zv+4bJ{#>AP9XV1ja9=Wsaa5D&0jA#<;Q>bPF_+jEAJ+*$)$@;GP)lv*Fj6ZJ)N-a; zc80S?-G9W}lb3v)uGj)a+@~S$u5~ZxvLg%1bK)W&ispjr8_tPrTWSWbMg)l1Zqopo z?u*{(i#FF1a{*AA7|gDpR(ty1U)yvaN6OdNB5_kE3j>IFE%4Z@7G zk=)YUlYq;-jBT2~C8vM(=udJGu-}8~U+c8|w5vR28ZmK}(mU0y@AXG(?_~l~MAOAZ zTMnK4aUA~rTZjJ5$Rma^@{V%j4la`uu9b#g78Z1Sj|qSLD9H!iObVXut_|D-C+8KD zo8q}|EQ4u8IU1L4^+vD6oDrKDQfnbpNMH1q)tuJ-?%wTW+fC)s?0%#(!H*Zq2}FVi z%CAA45L_-}#36iW#Fo@51>iqm@p;@2O0R2zB zeIqYgnD-H_wuK%VSi5j$!10)YN?*PurDoNp5jIGr;5y=erhpIX(9@*+ z0FWJH`3}Y%&W0JW*n(BL>79)7m<;^=4h*7Re)sC^SkY4xcgc}aacLp{LEKi>d{t`g zb8ZrWb1XCZjm8*2%IUOT5~13QV1Nh*ayt4FA~1ci=^j+Txjxeh#W1pYu2%6aVTM@* zefa`ADSO}nRAl)x&}gw=?cYJ&9`LX65;mhpMSkG9R`V5C;>u}*;=SqqUO>sUo&|6v zUS0KN5w1%$Ora`VpvoS=lqru5?T!Y?({k&DVqhZWsQZICPbU!;g2Qw$N8sk z&p*CQG^yCZ?jUzw@i3oo%O0nX*uY zUz4zFXzj{O2Yt=ud8xk)VPp_zSQ6DTV>T4#${>P1=Z@EvK!^+6(MgW)T@}b6eolWQ z6$l|t@sAI4ZJ}aLbW@^-`sSmmWiN>UlcYM^0Qu5Oe?CFz7;m{he%o`w$LvKazT0oo zKU+6svvBpsYH?@T7o8)|HhzHpum3_XuGl9Z1GErEkJH51rgH`J0SpM>76$=os%ZY5 z7P$S0`4kmKkKMe?hO;&rUew+Qv8P8Lre^h_VqO^oaE>hB3xecU4@R@PDK|qa?VeOF znxtDV5(SdpL;HQvyK4A48cJEq6C&Ago<_HrV}LhuFYsiLcjBpX2uRB9 zqS#0t2Blx|%})UYT)ul<*7uB5R7eTI!MrxR5Y8d-_llp&tLK5Q=&Xv3A3_yi6-*U!ov>p$&jeA0!39w7y()s= z+zuXTYfY4l3=O!S+e~fWK@wz8*ZSQR@Ep>|PFOMb@cziZ`I4gYf^Aq+&b=RvOW?tg z?eNj26p;8egqVBD&DB#au=sA!DC3Jb(H(>+ktMMhI<%Qi%IAAO@r3^HfOuY^vG~gQmkjCEoU?QNCY;XWL!K1ELu_b^H%6m=v8q~GJ!yQKmA_q zHXQL8oYy1&W`*tw_pFp%ntAMotypUV`LJ7h$;5FksDS?(HC|+gHlK%v_eno{Qt*sg zcfDp|=9t`Awu6ILp!WU!5BkKV>zSo?!U^nGM4-9rKf19Mu8zM{R2=OBX)3{cb&0Se zxRrSRv){ocPHDJZZ!wxjg+ev=1IuA;6aD^UTcPG2#?&|76PAp}1R2JW9RJZ`fCK&~ zp7nSiF+X4rMl`F1BpK-ylyT+KOJv0A*}?p5=8Dgv8ubzpS;kq>b;4wv8 zB3+?&osi4W=1vw`{N~tOEdn{N^nCT4_xVML5I*a1)83zdCThH~sA=4?)yJb&8=^s* z2%EVUwC{;!Uy%{yrm`K%Im7Yw4>A4@osRYx5JCXimkp%}%*Gw&_A}mt%m}yV=!y)9 zbRnqB;v&^0&={;X^>Pa+_mMVk408XAmd;|Y(^_bQ-QkVuB|im^2RdH8P)}gSDM@)9 z6-UsbqXvh?ux``zvb8|1f*VAFDqgXI9h}>PG__|nx(bHDJgZVygc&H5G~|*9#GrX2 z0C{|3mv?lw>*$V#ES$accl6M&PVZz9dS^Qut}+N-5r3&5Ze6{WyxOVcZBIvDqouA~ zb7>@1N@Dg|cZL)qua(f^7xuSB^>Cmq=ttfHhJKroYNpgbQ@k;ofWUo6Tq@T{_6{| z?hLRiTaYs?)elSFo(Y?PwFV2@ypHK2>ZQygoDBw{Al$H(kvFHmwZz?J;y682t+iBk zeWj1e4e#ft!j67(7wt7M?j*dm_0LzLcC(da4W*_N<(XV~FjV**5^*j{DGd$M^kvZ0 zW~G5(m^V&2Z-_dAAxW|A)oo~I<|{3xw*{nr>7sC$6#9puTOwga!9vN=PeVQ<1(Ab6|h|&lvlHkSkRY!?nj@6xzY# zp$XBrFp#_sBODC8lrM_8gjylt}y_v=?7H zM*t$fyO9Ft;4#pKh_3`AjZ0qRI;8C#i^v^puB+}}q{KF@49gjuJ?c@dI#5<`*E?lq zjJbjU5bUS5gzuz>wZO9NUk}bv61cSBf31%R7|KiwpXm93ZU*&FYz^NW_}(VI))X;V zw+o`X@aeptLAw>%FiPogtO06-oB-@IndRgbUjX=cco_i|JG`}`=Kfqy|C+SiBYGRA)um~M=+=2wO^fR9DxH62%oSn2r6^X<5n3Wn9+Ha*y=cxphG@U zspAH80Sj8!(~t#@XuU~S-X~H7u|s=McN+C{ozIZ|EjhZ?1V+ALwe#(c3?Ea9o37WE zl$5s$6qZXBkP8l<0_2tNr*(4R1IM3ymcM4R)C_m^K3G#^opsl?B{?(x%rn6BnzD)= z4V>37XJZRjB*}6i1UbMp=(9ex9!yU0Be|ke{;I2b@eUDJcgX=N4uss#FyfxH>m3rb zt6Wlc9r1OJFHJ!EuRyl4)GoTkB$wgLF#W3gO9WmI2D@|!r!3 z;W=1aA`Ws}bdZIE3JV@s&_KRQY5*Fi>$zew)?j&Fc!IiAhYmj-$RqXwYhm4Y0W`Sw znboa~P8*NPEmF}eHq>@r%61e{SG8s@OIX_lfMh4KK?B-^e0;EJ&9L$8IK%MKx_ozL zHScMaT$tjiQ@A^B`@n1j2$GCI2iE z`%yYBK+pN73+w-y_Tx_?r!<|VO6TGi5$(zxgI%x)V+!FDgx%S*XChjrH z`Cc(}v>5;jZNOC5hCgP@Rh_liF}_1jRWxUD((m*_2irF)Ly31^0E?gnwf4xqClu|X zYX=+0uA@dh@FNk%4PGgP=n7)IP3MBY`0hTS0Z^y+?0%(-{!xciIyCbeVU zJ`lF_a!Y7lGMP4B1O@$q?-j&vG*^TLn69P4+UJgw+mEs?KQ1Bt7Y&#Z#lk~-Q5;`bw)OKa_K&RdsJFKS>Bqmp{xJoX%+p0fzXR<6P zktqe@Nzs=WAs-T&$JDM@(H%?0L~FVA!lB$mySBFqYG}nQtS}e?<2KgGq2hv6U%=`5 zjb^&$k^#vCRN*zPb|`W)mV_ZwM7=c|(=+a;S%Hp$os+S4O>?s1u1rXbyq3iKOVcq#18mHu`bH%mOIESv~?jgPPdG+aBm@EO>SnoX=|o&lk^Rs~O*%a}^$J1|Gev z{G;jhBT7@ITD#Tu)OaGm#d(d>tNfFCfO1WUnMNLDk#4t;Acv&w#+77qN^Js8RK(ZlRooH`9SXQ7o6hF;p5`2^8 zqXcgjhH>YyK zy8Fc(PDL8hb?vFDRSk{xe#R5hASaKsNB_Q!|N9)@{?_Jt8a~95NDw>xAgq?ZhgxMG zWV+v-k3MGlw_yI)2>$aiYs)0~8n0bu>Qbq*n(vkuy|3qFZRS80x`V18*KM})R>xwk z7hm{Wb!-K=|DIOxACv#@m(D@|(oK;0`ciV7;Fr8g-lJCyKAQ6|L@BB`FG-36!o|Dou7r-NKYOWR!$Px^4Hz} z4()a=kwHAVjqvcOG?j&WVxUY$$C-_b|2x0`pXUayf5cf%sD3?!$*u%7HDcsxQ^M`# zld;yjQZFw>J1K@A5f$}shd0%z@Bg(ywQXz^sdffEr_M)E?H6{)wQAjRlSAgOCT~Rb zU@%LHbb(vhG9wb>E)e+e){6&*^~Abs)MxJI-u5f8{vTc)NJY{Kqr#6K%RNZ=@^qk? zpe&Lm?Ef0lP}@IguW_SYVi6a{{4FVV4lOeBKV%l{lX;832G3obPrWXw_pkbK6>f}p zrH33(o08v|NG3X8nwLa^-biBHSx&C56bs=xNUoA)bu79uT}@F@la8SkOq5>`K3|m4 zNWjN8G=0?ic$d3o(^6=~f5IQFkZV6Dn+O}Lu?nD550aWi`ggAee@=x|udjpKxHc0% zqe~Vwf55Cv8IMb;z)Bp$vfG7Fi0c)^@Qz95r(NvA3pKW^x7~HeiAX43-Ah(Zc}%|8 z9R(L8g+L~vBf7epwd>qnV#Yl;$(H9MhhNZBmO~)lMW_8nmi6{W`X^3|ca#bVZE9x4QglWNYG zA78Yix<@0ri~ch5|7$^6um3J>w7JWp+RnR)(^;K+HBVR>c$Ml0P&6D+D$(iB11kz= zoP2K)&EOsUHN9b;|uXws5si!_E$zylFij&JFQpqVV@u5gh*(cX5o(i)?&=4lk z|9PHA7lW{CqU;DEK#kRRyNG5Uv7HNcp{f1jqeOtouIF?*S$9_X+0p+Qwo!Ng%t?O? zZM*Px*#pYstbLVE{PDi7*eMiX0R+MTXB~ew)(J^%uTwbOJ8~yP~L~*VgV;HO(br z5f-;4eU4^>eoYRE7Dp>0ezQ@QiXc}p8cu*=tv+{&Awp#e!SCu8b7kPDpXbG+6M{Av zoEVI`eBs5HVq(C9aT93_aglQxc3(41|6D^1{V;CKt$fz{?sgZW;wuOv8D~p&F3?6i zXiA=%W^OjVb)c^cxmH>p)jq*CMZ5%v{KzJ%gXIg1U(~HRxy1?hAT8y{jR+NNI>fMM zov#Oy39xCv(rZmYOyI^a*PQ;^2k?Mt0Gb&&*&~hzym`PN?fY?k`qPZa4 z7FJdloz|-q(VjBL^on5mQ2|5hA+E+S)`mc}nR6AX!Cvr&3yR-rOd&>J2gQ+Wz4C8F zymTv^PtOAPa~iBHHzCs=-9H482aCi}A&x*rWnO>P6hKtJ-0HK)&&$tu-0Ao?>aK8+ z;skS<$+1899$<@@sI{ll(KYpME|z?2{+v?C85-bE|1*h~nkFSyIj>P9ng~@gltB6p zNyxG%=szp&#N#{8!YK403FT{xJEvI=GjhU-*yn5+Dt4>@$N`n_qX}sLI)AND;E6Wf@wojkdvQ9(nIF!&R(rcG z9e2w!m1sPuhb;LR4rI$Ves=0lO(J{cdi1(Ku@g6M!C8u}A^8XMUL}tSD%c`Ib%&+v z*vh`*L+_7%xY{!&bP?}0O2h$Nuk!D9QT0;lmGidG05bf~;K zoFi0KQ+t$CQ(IaWOvYx1^0BlfecO8*2^8x`jrIlxw6)WYJPL^%%wAIbnnl5?_Y@VZ zalMYWOn)RNPJm9{qJ}o*GHRq-&BwGHts9l%-6RB|uj*%>X=s8z8~jIGGqSdur^v_a z4uU7=A{mRnA}BKN;ly05zB2ImGwSryP4flwxZdYTwz7tR_5g_uR~mnKY~kAdS@#Pi z%@Q3YNz+9uWF?D#xznUV&2xZ(u&_tpgy zNxa@stTq=kJi$*#v{0l`PqF(Nqfhc^zf}6p za0%bK8BK{Mx;sQ{U}*K=yc%jS0@?5>ea3v@uT#j{(m>Cb+Afg1Afr%PC6U8^W8Z

      rBO>3@Q%6r7l2^)J88yuB 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 z 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 Date: Fri, 5 Apr 2024 19:14:36 -0400 Subject: [PATCH 154/241] Upload devices2.png --- .github/assets/devices2.png | Bin 0 -> 220908 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .github/assets/devices2.png diff --git a/.github/assets/devices2.png b/.github/assets/devices2.png new file mode 100644 index 0000000000000000000000000000000000000000..ee3c1eca7f01973b64e7cd945791ae57686347dd GIT binary patch literal 220908 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%0Ak~@^={LVZ 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 x@W)Rl$^Gr;-X-H5&llUl4{ Date: Fri, 5 Apr 2024 19:15:28 -0400 Subject: [PATCH 155/241] Update --- .github/assets/devices.png | Bin 541506 -> 73544 bytes .github/assets/devices2.png | Bin 220908 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .github/assets/devices2.png diff --git a/.github/assets/devices.png b/.github/assets/devices.png index fd27a6a768f36ebf3556cbc89d74523791d5ae47..7bdccc5b5a8798709ca7bf34fd7d5561eb2b8115 100644 GIT binary patch literal 73544 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 BIO+fZ literal 541506 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

        &Q_b{nm7(+H(rC!6hC8?C=R&i4CK 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

        HxKy#9*v}dz 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

        [](https://apps.apple.com/us/app/cake-wallet/id1334702542?platform=iphone) From 3d06a7d354cc71edf80c58b518bfa9766435f903 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 19:18:28 -0400 Subject: [PATCH 157/241] Update images --- .github/assets/devices.png | Bin 73544 -> 220908 bytes .github/assets/devices2.png | Bin 0 -> 73544 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 .github/assets/devices2.png diff --git a/.github/assets/devices.png b/.github/assets/devices.png index 7bdccc5b5a8798709ca7bf34fd7d5561eb2b8115..ee3c1eca7f01973b64e7cd945791ae57686347dd 100644 GIT binary patch literal 220908 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%0Ak~@^={LVZ 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 x@W)Rl$^Gr;-X-H5&llUl4{Y&(`v3su8z3&a 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 BIO+fZ diff --git a/.github/assets/devices2.png b/.github/assets/devices2.png new file mode 100644 index 0000000000000000000000000000000000000000..7bdccc5b5a8798709ca7bf34fd7d5561eb2b8115 GIT binary patch literal 73544 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 BIO+fZ literal 0 HcmV?d00001 From 23da88d6f4b2fab538f4b25716711fafd8171643 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 19:19:09 -0400 Subject: [PATCH 158/241] Update images --- .github/assets/devices.png | Bin 220908 -> 73544 bytes .github/assets/devices2.png | Bin 73544 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .github/assets/devices2.png diff --git a/.github/assets/devices.png b/.github/assets/devices.png index ee3c1eca7f01973b64e7cd945791ae57686347dd..7bdccc5b5a8798709ca7bf34fd7d5561eb2b8115 100644 GIT binary patch literal 73544 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 BIO+fZ literal 220908 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%0Ak~@^={LVZ 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 x@W)Rl$^Gr;-X-H5&llUl4{Y&(`v3su8z3&a zz zZ?xl`Zv|-utjr02eSHMH`HmN~g(3L&jTIJd(6ZgQ0K07pSsK8kS>ZWX5Rmvn~>=gQvA;~Kvq5gfzSV*+u_KEY5jLE`cMntp2q*bouyC#a3ue?<7Ui4 zd9MF`h!KEt|9{Vi2|oV69)j`zKjc5T{(nzgkz;NER=_+zc#T{ZxopbB1POJ0tF0NI zTz+wU(l*G^wV=H0KBW{J);W1hvFMQAUs)aO1upX?ja4Tvi;xF=^C6D{$fq$yU^j{Z z|rTxGl~+a=)g*te(iFe*3qr~AOAA+O_7VFHGl8c8~2+4qwM@tO_1 ziOCno^(Ny%2b;a~{(WUxU*R&R{&BIxKXdU}Rq5leaL<&y*L|0w>Z}l`brLzx#UK}C zX$MROEF#t7vIQx{=24UFQ9!^}Czq`~I`?jwkvMq+F;G5J_XSqAwC zGQmDZPouf}+?J)&$pp6SA1BdR@C4qC|R=t=Y|a z%qTxokGD;~Oq4Di!DD$dNV^$aW>=9jc<)}Y*?r>Vk6C6IYJPT$kez$b--h6%zWjb@ zRsDC1_Tq5Sz__7s!^TCe63*4y}qa|JUo2X zG+h3r3%@B3wnEB_V(vwSW&A!X3#Xo5VbP`sbqDuVQ4wL^Kt{h42Fn(&BXtJto*Stn z;q!qp!BCr?lE@S)d>l!C#lOo#?s1C^p&#au2(x^V&9A|Kl9{9?*IOK>c<@M=9YK;z z3kVPf!1QQV4q$;{LI15YoRphL=g2cO2;no}upsx1L1a^RcE#!V`>)1p!-e3C?ln*& zI4e@+LEh1B4G9`hF8Db$XL5j$-J*Cn@e{VMI;e3G$UZ!DOlYqTuAc}NUA^?gb~Qvn z&u$(GW^#TZoxEu|+ZD`j9YDSXNFWXtOE}8k!m}?sJ!Qp%MQBV1MBr}&-Fx?8md@c9 zjC^nGm-i&v{l~cXvLMfOc9sv~oURym{r{rGq?hb0@0GtQ)?Go(Vu*d2?BLCn={s+$ zj~J9?ezv9pQzV*s5my)Zuy>GJS%p}Aa}%Eo=YvTs`*SIe+3|ayqy~~*L~B=?j3}@{anQ&cy1So5?6i*I zp>Bmy_B||bQFf5Y@h|pCV|ZxBj=8X-2ZIVNYSpF5HL#d=;riz*OVmcFd~m=KZNnSJ zXLSwCoJG2+S+LMxdy>{ZF+jt}R91a`-rC)X$N`0!e6P@ma;H=YtH)!nv)>ZW;*q26 ze1$X%e#&3@wcKX1@q3&x5;e&1{R#wo9KKl)Ug&~oDM4L`0~eSg%Nw`UJ?EngJ&mU1 zONma`8Nof5!Um@1(}A9q=I3(I`G?wJ&;iuNl8bH6XJvDA-(O4l;oRckv6R*>l)Fm#jI=EJV$ktZ<`5w_t{q7e)A?o5D@?oy{>jf&`fR0=H#~C zC4c&F+u< zuhxR$u#=vv4LGBCV=o!D0y4;!o@q*EWH5VMLWx~ZNemH|!oO?YO;$xnXRTuc&w>@p zM2I&bDr23O=V0q+K@pF+g!_3RTD8WKT+*<&McXR+=T2+wj!)xQxkAO*dP#%G)^%|L zc|MIV&W4PIKnQK)`dmxI+;}WqruUehnieZLnUj;*Xu<_nel@LBzkT?)P!%J?P)N(T z>K}NhOK#$cJ5>J$Z9;nnGlTW92L2aS+)9~|TK2&*qG}d$X3OxQcL*Dpahh;)2XCZp z{v_&zMzW_nz|G09wIMG+brob3pLZJ&39)Si_?~i+rVk;TPmx=9#H?Tl)2Z zP>cv9U)`##EH&K)W`v&Jta~2nk;k2Qlz5YzNvKMHMka&v$f&mGj&40$&fXQ6o9MBk zZcYU6?pT?49l7^ZR+w_{zkrQHN=HzR7VQmBuky1uORVnN#(0?xNAI2MSQcf-*o16S zCb5vROl7WSWdHpS%W%9#y8s6(U7a^A<5of~2Eif8X}14A&P)0V?U9NW$Xl~0;q zbg~%c-oK(-D;{xK*jM)LZt)1Xo*hSpnhOzm z@ZZt%I4Y@7?Tj+o3_}rjOR8r%2*=d6hT$5vuX^+2aYC8M&V!iN5kAb?<~79iw;Ad- zWJ_-FHY{053VDsKv?*%&^~FxwUPPqjbdiNWn8fpCSbO3SBDP~iB!VDa(rqRA_grd;NFZeFN^D7{Nye(y;B-T0BQ z#!hRFarOt(CcW+eFtUCI`g}XrV@Y=|%fsAE5_Ealq`{z@kp^ zwYRV}%cR8(fRDFVjj~$7%_NQMS(Hzq^J8P)y{9*B@}V!guI{b7gMv*A#(AqKkQQdO zOnu8KOs5tUhC|f~SHl*4NY~%FITymSuquS@@Qif0lf=6_5b8Ip`|!%jfq}^DWS+VhVs+y zyJ)|=ze8fsDiJxkMOV?H3`McznFAjo5s5e=2GM^rUT5?O?e6s7W8qCZw~-DB_h&mvLXKZ{OlY z^51`K_N;QT^mF#)C@{pd6w(~kDc9g?TygwFH;?7OCbmGpYBgi?_c|M9w`7#=((pySkIG= z>ZMTSp?Ba<8v$bzz0A?pDRK@Wzke#c*3`7#8BChiu)fNdS-$+clkL$q``!GP2`;K4 z+fbLvi(aLbL}N$m+#CGqN8yWvJ;&dB2RSzT?lrs*ag8u4pS}zU?q29Adwgi1Xf&Tz zG#RUGs;Rw$dB#dhpNnc;rLy)%2GtKYhjU978kcqNPgkAcTav^<;cHaoGCYYEyY+06 zrm@~IudVik2F+UUgLVZ=y8IWMeEL`#A>fPLt4G%Mdz$YDRPih#G4%I4>nreuJh@sQ;_T+`o;W$+{2MM~dlq1wwOv z&hG=M(m4e|bQI>VPXz;4ETOl1S?1S2XrP{;FB4pmPcgRMGsqi>ZFZb=l{EDJf`x{T z@ryl-_V-5;x2mLZWPiyU;Ni-P92rrUZg-(!4!+R!>0-iG05V}KqpX#hv^|OW*lJ{# z@IC#0zcCyXYByLhyu7tE%r_*)Dd<5KE?sq2o5zqLO2n0d+EM)%LfhS1Z|xa)D<)RA zVf;(f&9XVTap%@}*M^uCqCInu(I50O=t5@Tzw~1Vt9dGA&03__M9-OBLP4LJ9wgyl z11^|~ABK7vt|aix!THs7=go{6C2yUrdp1C;raZ=8AM%_)mss0!)a|VGNZvaC-K>30=H3{r3x!3+s_)k@;UxvL>$ev7_0!9M=UX3*D zK;-d2e$S1Nj7Zd+mK4>H$672F9*NBM9-yJ;u$1FQQRr$h_V3r9ozew*yQ zr8Riyx-fJKLP!sL{d8~Og-!I)VAPV2TXBX3+EXTTMaBTlgD%gO^uO zecG4%s^I4pejzVMgXPzbSZvte(W-HeZ-5@>2ksw1w5hDyO5bKqxvP00jyLoR;~UJ(Q@P>mzCe(Xb#+JZG@h^O7-~5 zM7eQpTQEnaWR==GWb*U#9xT70WPlvrZtEr-6>9!PqC|WJXi_ykK5jL&(X-rWjfDnG zVn7fg7Bj>;?cFyllDE_9^T%#-{s$yz_brOQ?j_K~e}7N(W39%#c4)xT!{2+7`kTC_ zCgHkP70CMF@-nTK#2%$|mo452a#Sb0v-ekq{b6kLWUdjTUQ9%7Y~$@R4;IhYSEv)A-s?*wvkJDM7M0X+5Hm9V zh%=|<1&Cw0ZNMS$!1CQofv&kzqsdO@cGuyyfX!kr`D>H&ab$Ph8i*g?Ut4M!u9O=T zU1XqYmMbONMXSyZzs?_^hJOr2PT6dK-t$%>Z#LD{uy%JR2Cst{-o1O*=(VGgD3XKT zA*RDrY8ISt;i0#`ACihmZhyRoX#h>6X%)EG&sU~Gwr)>@uU0=zfK88zRj|Ck2`oU* z!>S6Kp=72H`$aLN%DQEw=W&~ieusgE%xQNUj>)EczKfhDG?R0I-xCNBt3E73HFS;dg z6aH*>SYS5n zWB>YkA-{@N8W7gN>qzLm^PbqS3ZwzWcD8Y$K{Z6}mY$U}Me8*-yy_)9(2^(H`w6C% zUG{C#uZjsH@+sFKtu!=HY_Z-v;qqvyL`1H@d?;K7a+Qc!_xnkA&VPNVOe1st^Ph+$ zeEx|DZF_!N>;6O9_ZKrvpO}|iMOo9JHRtpCTHjCBA%CWk2w+L2IFu6qWiW>%P13cO z?AufmDju&-V_p^AU5a4mt~$uX`U%Ci2;4Z|@b1wqAvK}vTwIXMQGc@sM32DqNLKhr zWj;83y6yXr+V*-pck;7aqZPT`A3m||mn&Ndw2&b}{z=5XqjGE0V7953dngFOA2&=t zq{jN$Wg_KF!t2ICS<*6;`%I7594OFG!a0nP?7T|t^0rmY7+c&!R&1UR`wO_Q^B_j+ za$s5_!NY#_-NCSRqnDd^gBs~lI6Ir zng?I=8sdMr@?A0?8YsY*AVlN->|UF}azQI~;El6KbNc## zkBe)JT9OAG;}a9sN9}IFz6|MO-d?}w5yIP%P)fett(F(;BmK1Kxe{GjcWtksZ`EiY zyw>ZFCcJ^-T-nD5J1k>~^}!Wpz-e>_8qK5hwT~;E%hP;v=xY7e7(DBbf$9y6^wG5# zuq8FJIqk8VzT7@4kr^w!68`j+#=ml-XdmBur2hl&TApZCT<(qY;u1B8;n&PL#@}4Z zP9pb6xgpxQ7MYr=Kg%)%hF9|7`~>xdp4=4nF!5xsrFFlTE=eLTONA?pSQ+7DGh%C= zcSrX-y(b->oo*bFjFM|AMz^AP=w5VM_nGx#Im`rbS+5fc;nPb z@h@e!tozFIQ<5dRX?=1@ zW>PR<8rt<*-A#Ajn9uN|shS4@P|tJvS%6qe|}K4RW*7a7#t#tYpoKJOW~? z)LwjMAAmn4g@3uWu}lgEF?^m>UB7O+N99spOQ=BCv$R3=XRTOy>{!3^(yLv9cp5`( z^JC9|COqSlliT0%9`|3&zZm?gsicdgOKWqqSa;;nv-eA``_P3kLV z4se7gh{^r__Wa3{CoF7g+q6TB!7rF$ZI9}%{ZF3{8_r}_54ZFETHgtt%0r!1#)EFo zaCE+=nb@Z{xYu)EEkJl5`+YoEwcx5fN~W8qh9YYyMhtyDnRrixOX6(`B2+$(DvzUP zNg9JG|5!cBmh_U zF0GaW-CUQq4|voPpB6fcl(zv|q(POhslHqThqgi8Y7Lu#-qn3QYc zEewMjs#{#L++rHug2$`7qv@0&@G4T7m*qG*0m>QTH@st2BOcSjF>I4DJY)4)E?#vz ztPgk>a$Ih(g3xG@J39Yo4}@`w2B!YR&io#7t*+y}GCv zRx2s(&!&ka&3*T;hEpSBt;QDXfZ>3hogH8wsWt63`n^p8$3izyU4j_jf4)U$EvX26 zo>At2W!`Vepy9c#i+P_vxrfn242|AP0zNw(ddr5Ia<$~^P}?BIg(S(FQBNEj^VXTH za^7Gn-{Llb9~NTMwd6L?pqh8w2AcYQV@)vFWW~wa%8=n!P6*qiuplG>OJ;tg%An+*o6jc%#?F1@ohR{oO4wGP>}=JBzoVPOLh7$MxMC zbpeIj-IPNTqK+5EtEQ#9jogfnR{l8Uodvx5wWaeho9*<^AADEwL+%$}HD53gF?x>+ z$Nrdx8MR{-aYW~J(HOSOnFW_+6MKy7BryKkUUN&B&A97!9m?;gb*xEBXv5*v(O@O) z8|4nNXb&uS^LoqDxcqMYpYYJ`)a#~Z$Ycl{9S+@HZQSv-6rgTL#@rsW+HIk+6l)!l zHSeWY?}(Wh=S)lH+-=d}W$X^^4f2G4!`DK@@eJS9ulH_=Dx_T=$+Q!Hpny5Yb%N*) zYQH{i#%atm&U^md*w0eZPc#gM3vEX98fwK=w?bndgb+GW#>@U^&E%A1-)930@vKx0 zlHj+??N9rSHie)do=JT`TRs;^rj9 zA9LWBo}Qkao7=zq_d_p#as*4ml3u+1m4#W`rxf-)rcbi*X!wGW;Uy_HS_jSAr91w7 zce{GHeGgLsnuw$AlV!=`W-gB3O!UDfqes>)B!u~Bv3}tGPNwID-T!g{Ze|c5mjOR> zj!7z=h<-1_7n~2S+AZL*I*Ju2hC?Pdax3Svd)Cn}xx^IY%F*hJ{RY9Fo;u#uv@cHSl2PWp zHnvO?ys5^MS{y#oHs@z<9RCtF$m&p9xke0Vhp~c-rZ9{uVe?TbPo~(XuCXI7F2mq= zXQ#u1&nIKDIfC<8N*PnHlqQ1VBLehk-)LP3Iu<^gU@a_4f!Ew4W+mE=a_-tn4hJq} zlq8%$1lF|QXy?GmYI(rNFG?JRi@3S^r@nuo8y}yvv9V#x!zuX~fk%vewdT8YemyFp zXe9VgYR?gM+MAuW@B_4Q3k|XmzI?5vWrKzxrnN5Cxb6=l!BWZ)t-qa$Kfq~_(*}=+ z!mGL)S5HJO`I8d|<5GhO%u0sHF1Ha8K2>p;q?VR?5#wB2iwqXC?vxr4%mujg9uNxB!))f7S}P+km+%!V9oL&}y>6-)Eu+rvZi zwh1m9b8Bdg!iL`^(){g?kf(y*^2S{AbL5CDW!tdTWq;jZBSWd~o%ByGJ#w5H6eH7;5 zCK!yoMU2Va&^SivR77XL2on*p2*CS%+!Wbx&~|WtcVnIS^N+dIj1!X*+7&{tP;L)X zH_n+Q#ecIjJ&i@&e!VK7Tgn0aJc?lUa?k3Sj)JWsM2VTDV>#4Oc`xJ-&TSs;Ri7Q- zMW#3-5imRe?c>K0i}co{KT~5K%htm(=RPkzQyf;@x}bRml#$!);?N@JE}PCT7@ARK zit03aCkKvv&?s;$YxJ}N${|JZ+k8u<;IlR7Qwlk8E!XK06Tp?HPX=10aIoi0zUIP>Dd6B zz9vaMV<&Z&TD<(yE!+8*`XZklY>ZAO(ScUGnbO9cyeqd?dc>BWyRQWZJb?yI+RVqK zu;YxJV70V(#}-$9u(zvO(EB8dTK;kxd>R;&H;jfB6wr2NI{EdPE#&cLkC&@!?HeWT zL^gC_bIH%W+sCDW2sRvAireja7W7xiHgj1=<5K1mqWmguzZ$g+Gq-j<1s6PK8dR}_ z%9;fclP`VI%i3gd7+^sizWCwY)aS}Dn5>I?!yf0YDoykr0N{=rOQR^>?rMxOWj16o z+WlqIFj}s7yK)V=HYun<g<*&%6xr;%M zbnl0Y^kRRIws^O29XsR90e)pIh${{c3x#Vr``aD;N_zhM`A(E04$B}*+|I?#$I5Jv zc>lZ)4PWyu45M>4g(9@XJiu=)uaVzoxhB_pPvl?7ZM4nMh&0qh2tKpmTnx6q&SgaY ziD*1$GW|`=^A@1`bOAUUwJdcET}8!F*;Dbzd==8kg^|6zu;eQXu>*Ts)Zd9sEotPa z!twC8r5{6b^+L2Z+;_Xrx*7CaKh=BQ&r7n@A_gpXTZsFsA)}0s$|=9ll=8LG`0p)M zt;^oT z5O4n=E8!UpFH!ZOncrFp-6sp&fbel@e9cN_1UhWOu?C0TP5@}B? zCsU*b{#zGI=S(&cAOqQ0f^fi-Kq?X)ejB$ST{E%Zg>Tcr&{^swUwc8HLKB+rV7#Hh zokCBy-*L-b!@+qGC8LYgJjfF-L#+2X3c8wNQ=_N(=Td}G+0|s15xE4uKc?G9uGZY$ zHne<%E8c&O@pToL?pNP|5XU3@zhJGhT5^x)9UdoqWWSwKUnXLA3q!;~ z!u+oT@0gdTR_SiXf>Zv(GV69%rxsx{kQPL{IL*~xjM&mt??BNXg*)f5og=f<2#3wb zxj|=iWd1K)S(h@Vs0({Z1j=-f=7RMU>7?%+cN^3Q!vVu3`$99qE<@;fwxjw1l&rE3 zfwnM{8WL`|s^s30&f_Zk|fkz~K0- z2`Xvp>^`J`l{aQ5H1H1DPh0tB$JX^sabe?X`PXx|jN(r_UMFts+Ww$Byvt5KDcT(+ zWR3pS`cZAys^a?5x8ZZ61GYHm!l~+j)~SFe*r4Nb=LJadGj+PetMe5}0{M!$8LuVR zH}B?vtdG!q-1(yZY!P{n09R7%y@MhVn|2RWTgGNvF6W`9i!Ylh@_EjQEW?%Rh!!6b zG=}S!!(VxJr~Jq0i?Vqg3I;=P7w0SrY*J}(uC+HG^OlXl22fJ2{d)EYfyQ(*x1!k| zHe^eSjLQu!te)S=89=~0R?#3(Nj>SW-gc_tcX&*JGko@Y;C0VHJWsxxQOaw=a%viz z#nCB*gQ$u$nS)t2s-F{J@EV<#K8d|3e(Q&7XV-Frx!ojY=c`k((Xa_!JMhIH*MzD^ zO5Fr6WqHArURxL1adB?CDb3dZ+Rb`56N*^g`?VD8MJ%1%#j6?v(d@h;foN-7i}<;R z`mpbnE!H@;=tk8aSuxnF#G9Q64H@Lw#(Sd$wzO6AkD<5^f>->H`-ldmGT-{G`*tym z8OT~uu~6+(>GBz;FxU!7iG30}?1|QIo@t+zWXM>x>EfcxSWMx-$iPk6#REt_&U}SV zSY-&1WEZiR%oAx~sOJ*>IPZ?ARf=*)yPg1U^ZevolC?+Qs{q-pujgM3C>6BZ)I=28vWs)ztAUg|7-RHX+A zqSFHgX4%*pF;%1!cnk8@E*r83Y;U_h;I@Cbm!&~dzUzvfn`IIga*Qwv;3tlpg<*1p z8DWxPg@w}+mEoA;la~}`0*0^3g4wAqG4~5e9S*A34_bUxuoVge!^z|+dHbK#>F3gZ z>py6LNQTdjlHU?whAq;or`i2bc5r)=QY%R7=*SsM5zz`E0OYkRfCOyQAK4St>AThW zN(#+Jv5?D?bEuGFTZ4#ay|enAa-48Dp7`a`0%t|ln&}uivC2p{zeFhW$=fd}gd`n~ zR~1uE6Ml?S0Zmk2NDQz5F-lJf3XVATISAIpwJeJ&Gku9Z^t*W_RoKW{cD#02Y8izx z*v1D&$rnCiNJY#E#mVCxbZU$lMy(%MJ-uSfJev_%@i!cx{LM{3HiVx@7HOTb zQr_H7!J)1<&jl6)zDP{{adHuowJ1zjvOPO`W9FrmXxG!uC7<5ULWtGx70yk74&BM3 ztpiTy>Ae_f;Lqh8BqU)4`4&+uK+++vR4x0dA_$ul&7cA)C4za#t0@>UPx}rIiG>^l zD;}{(g_etd*Kk26iEYU_yu|ol+An#gm0r0V-9J?acgU6BX)Exs#Iv=++~jAg+N*jb zdx*I3TZ!WXO+vJJE{~p?3(gjpd)qWai;A%Fpz0iPEjJAUlQ}mGc3I}2XLgs|t1KR4 zwMhtvd(BhkqE>-Ls~J<8p}lSHJRF;5QLUS3b(?)5jZ?!XBddJ;`gqnzm5f_&8dE%> zC+5HTfD8v7s-THipP_&6DCP0!)j`m6>DdAW^IH|3vS$#YK?c^KJP* z6~f}mFfB-CU0X_9=*APap3T1+ttp0q%Q_9ew;Wvm zn-oGcSq8E8q3=&lT0W`aur1hYZE*Ro>D*UXMMR^Mat~!VOA5ycFSq=WPV@I9f*;Y9 zER+-#kCv)fC|Q`^aC#ZX==NoE7(G#E`A85xz1!eOp3ZGc?#RRjWXHg+CKCh0aAju+TUKcT(&B3JB$Kf1sH#746E>PtC*5|qxL}ga5dFRtO z!iW`P)gPSm2yn@;()%^=iY{;?KLho9d>IoS`f?mc|EaYWa z*&RtNu8Jwdq!B_IB_B+B&br4U1hJSRfj_=+s2BGMy;w(fyC-UABi9laC7a{P{x$k)_IYFL$2R?>o&$)L*&hci%;eT3m@ZOb%QYG?zZS6Ih?7z5#Q8(>2!3t#fs0aMP;ytaPtjkf?X_78Ejaf(e zx<#T~S!oIkyOv?YC{#*RvMvSecfgX0GDX+LXRIqRbah4}ttqoP$k+#W=S+UED5doa zd6^k38<@IqVyZ1VwA^Hu%8{DV>r(oxB53KkyZx&o#HeD_8OW8`iZj|7J3q=haX!&H z>r^7g4%0|`6V74)Feq&GNfW?iVo~2-%d81!QDXGdti)P4Xt&J_;7j}_UnS3{X7k#W ze&UZx#ddCnJo-J(e3Pm7H2inn~K*-`1Y?)0QYv zHka$KtYvcRJkcWMmRC~frzNvh!Yj%zSbwZKfnOHUI_J>q6sM<=pk~9NF8W$qInV)3 z{HwNpy{2Vmfy0X~GKqU0qdgl(LFG(E8}WwHhuly3h{d}?jZGc1uJ7V!hg*1Kk>+eB zi(}>S(>@M!GGX$_)cE4)WJpu&frgC|eX5a{YYIoxj6x+Pwinp8kc|oZW0=O2@|tkc zAni8Cj7{Ppg(+0br3$&?LO{|%_cGu+&wxr*{j)+$9r0uv+YZ_ntTm(r zK6GhKrg9uoaRj%`WgNJAdJ3Pv7$1S%VhBSEjoaKxfMa3g`Wj$xFk zeFkl61y|iPWG9+Z2pQO_wg53J=mO_DXrVj2r^`fNqHe^l%n8v08fh7RKAyw!>7|3$ zwe*h^WxBbCTO_r=gRYg!)41Y;_^wro#`P)aZB08#1n>Pa=Zf2#=3(cdRfnzwl1FVW zUVlWv@Rrk#F6prMFv{hncm|&4Rn5)=G&Dr`Tr;F|v^`V>aI{K=j&B7#Z=SWD{wdoe zdDD_!>vNZN=J|=F)agtWSbMb5+;Ej{f45P2fAhnp4zDp~h?6+aI;4bn&(GB!O@;LO zaiGobH;utv#-g$JeA583p7%zP0-yC2HqL+1*g|W8IkryXGmY@I)dFoYY(R;k4%L?Q$UzoceNeM11nk21nsm7Tj_KD9g zRX~c@DsXyzAa)iZkFp)v#QRsqmQqCLwZGftnu*zpCMVP%@I|KJ^Z_O5hFP>b15Zyi zM_$pWu>DsESiJoDojZOt2O8N~Qe6RQct)`BQ-h3E}8R1!Vt5o*3@6ctsbf zb~+(~Y3EVcv{|PJG~xG*m!eZUFf`V}UeCXGPw){SQvKI;^F_xe+II|DBlL>HMd;|* zgqG@2-wIzBA0YnOfAy1gcEy##7cSF?na`NB2PbTV1?WdxW9JcS%C@bCTz-|htG<=> zf!^f)E4H+=qh`evu%V4*x1&-F({dIzs_iD-%y&XqWc-r$`%kQ8gBA=xCqNm+(3k@W ztKIkM78U0M5JdOB6TGkHkt!aj0l72g$t3W(P+j@28uK55rxh4dDj(xv&Z0Pc7=f8b zsQqLdVFuN!{xD(c9}tL2NTb#A{;xulj;byKDiVsTV4^jA7^A%X7dxZZPB6Yf76G)jgrjA>;qq>Y)pP|8~gsC?zn9&|#nJ>O5}2tILFMUpgbpx4qp;-xe+p{Ch1$6^9I#E;WhRVoKt6 zifDD9NtBLEss`wIxmpje{!qpvU)uwmToXXeq!YU{N#P*$@19}nF!^W$I8yxerD$={ zFY(EL@Xb|Wx<+}0AFmqf{HFlQC~fO4Y4U%HN2aS*!a*w;Zy_C@owP3L1_kD!M=#@2 znihd479R%x!{uNKxw${jz4+q`68=vUxv=@tHV`15X?&9?G!h!EcJy@t6RFp%njJ zPaXTC(R(ehuk|=d60nLeF+668tVQ#a)%gb)Uc_WCx(hxTg3tb^+SJL}*nP4eEeJ=> zNZ3C9kqcJ?nymcmf3bF@X1;F`yJoxR>ysN(_8-c#1Deqxa=@mQ564X%7qhR(u)n|0 z`DbxdsT}zAz4rlV65tTJg&04I>#oFiJ4r{2=8A^fQ7gCC`GyNoS~a5 zEx#nAI>=IzF27|egco`dHDw#%oF-TOZ=w`=qQ0z1be|bE3~Gm>=JrHmp3;WJ(gnTo z`hcP>extuiq@tz`G!aIRGN7N3aO=I~&GuRJW~j^)uEB&a1pnr(F&6k_aOihv&(`JN z^`&0x&I#6-Z)#d7X|=SnqQHWbg-2+mQl1VpS49w$V7Kg zBqSozx%MRGrBcm>mjd0p*C~R#EY_Y{N(FfbNhHU@nxg$7XKok3a!qt+cTLyze;|&-5%qnRb zu7AEjq>_DP=R->~1~*hSSv-SRa0;gIQm{fMG9^kOOp8~-(@M|Y`uyV3Dc^Rj3W3w9 zvvli5%S7ic$-o*T{BZNiaMhfckRYWPK+I_!hbj!plD^eJ(7!_}29~ zzJ#69#|g7`Ou%COm%$lTH(K6_{GPxjcZ4aU_y^LXr8;xx=OYw}dIY+*=4}gqrY^kd#ej9Pzjosc1^<;0CI|EJz zqUL`0J#^r}W$v7oTl@s;??;#ZTzF3oYRYxdxh%cj>FwPe(9!w3*n7{A-+JH^bhLW< zGq)l?Y9tPSEo5oEW8YzN2pW7t7R3rW2_m$-`_*gJhw|;Xg5ESaOj$@jq&W!s8R8$X z$JquQrx$#0xrZq)cY1S$T!nVO(_PqU{$DPD6}>R-!{33>a3ca5%MTa=LBE~{sq#ac zcJW`LYa>9>rrhUyB->$5-hOT=-6T!#l0C#W24%{H3Ks?>3Cq zw@Yr|9nFRZrdzmnXuQbWT*p!Vjpy&5XrGlfM@xRa9be_ojATFS15Ypj zXp#~!n)od)PK2FKVJp7XVcX;lPu@aRVWK%(jlM8Yt(g=;vu^{6Qr|}EeB!0t5g_9> zt4$D!)EeeR|K@g31B3uR-wwSx5l-Gbrf( zFm&)sj@C<;5ax>94{VFCwXK7K7;TfDB+H;2m8`LGaDa^mt@>zH3Xp!7b=bMbV^*S6 z-uLMeznj-5RVFKc!X+##8%=bySVSk{c_QJkv-p6*54oRx^%+vV>#2$j0i9w2lyoV? zL7wDwA_D%%7GX532RA>N)i9kL{fm?O=iizUB+=pJ@)}20={aQ#@rV z+9g!^tvraEiu@op_Wc;1@Z$xim$|QPUy~`N-qKxg5I>+A9sIke3pIS?9HauJQ(lEdg0Cf78>^mr?q( zSJvq{4|EHF-c1ps(_KJZ=0G$@7=s({)w@&Zr5M0pnNm0<1UnrNi_uD-G{_7v1FRKg zbXCnA+~&j{TNoY1(x4ssPk>dEA{jKX#rG=Chb$uV4+VIXR7DoO`lpm}(Cndv{9%cq z!VLw&HNX?P@TL1N(eKhxSHqxAklTjHLJ>cC1wJoNM!B z(08-=2#>Rw0&wlR++d%RDa}lJ4BT9nBVdk%OjhIkMd?iGOP;Q!0qUVALoOS*a(LIs z+S{K{bVnMi)cj06;@flp3Y&Pl-=myF^NzolBaqO3X73qF62rRA$4Pt5-SC!1hW9uW^=ah!48k}UPm@h6$*AoC7Q z=RPmsg)kUKfT?nZSDx9L4neKSLYnKmd*5h%k*^NT>WK3$aN0Uj16RF(=NMQp)4V&F z1b-U%lElreO!y=ZHp)&%F@;p?+NjT8#ou2!2@pn*OQs(MQe#a9l>mH{S2=vNXr zR^%#XF5?mh%EmY2%>Xw_cRi`oa+6WW(X0^l8B)lb0S$Xa64NjL`lRif`qqBcEODde zyZ*+@rMtPrZ`e}(;mZz|DvZ~Cud&Ezt0rgmhYE4fYQ%jh;SzyO@N2=Y^j!L6me)Bqen9Jzo}X4cs%1g*=g=1t9ckRGXh?pK@RDq z$E^p{?OX2`zVD35Mdb@$+{11AeTvQx{X@K7=1H{WwD^4>lRTSYDmekIemJNUL{cDg zcsR-O8!30c0h`99tVo*Xz!3FjA;_1o<&=pa7;DRQ@7ZxEVs87o>hZ$f3+y$Dw4Ywb zrCftdU;+MtL^-zqn$v15$3D+vSV72bjUMRAdBgOk)@F>)1^mF_Bz8&8m-`|qCB>?G zw)X>`cv7001VOTF6flwD1Z|>WqV6KFAh*1Oq^wl{otZ$iOiE5>P__JF!khg4JIm-V zL-`Fy}z-6Jpr-q zx>ahqEvzwcnbt)!wu<;1U7QYjXZ8jFl&{yh4PU>Z(7JS-OMkl(@4|_XUc^~B{(kx2 zX1n+PSy|6?LF~!=Bm1J+JyBA}Ht(e4r(QpLzhSQkD&H&A+vO{lfrdhFEjU<)wwJa-vwS?v_JosZ;^Lm{L*!|ykrj6v#W7_-05z{E9e0NF# zC;eDKL{H%HuPVtHFgzIP@%S(2W^&h+1HgB>fH!G_&MPN4ltkG`0d&(Zia5S<8|9W; zKQp@*L2R3KbuGQ2IoYE(Obt>CoOqSh;Y0!bZ$N8ecZUpZ-9Xn)|5&llf}r12DV>Nh|bvPN{)P zgF0!rJ|*Y-lKVNdSu#Q;R~53E0+(%=>I=S-jI+%P98bmYDkW~j{lb_pGm(okcvg7V z;I}^#iU;7y4#~#2kffrtKbM4fMwL?n0&b z%vk5MeXou%D!F5zF5nmQVt)8m@Eg7RP`XDPr05pz_`$_(qo;u#{&|EbqOkcvLcrA@ zeZ9VzebynKz_^-k-4S`UHNb$nk40cJXn<>0rT_jebPy;=qBn4JD6XLYWR$N=(4 zo>r5jNI6wUlz ziwnNPE20|A%Fl=NMDpr4yRbh2*TX|L*y=q!a33F$y3c2b0o-B*?|iWPWeDiA5A#nh zfjQ$|v>H^K_{F580nt^2Y|z%kYU`5C4-p_wX3gfpsRIUhfPOyqW|og=Pv|=P1)c)| z^Ma(y%hE2(2k%$^knpK|>Sp_{HnmQcc}?SUT{|i09Y z0gg1J=bm#ugpR48mcXp#Hn+bCm>*s1+Z5c`B1##YbMB}p;I4}?RL?%<*L&8zN$pClZf0j>R_8$vzL0L8k4L6gu0Tzd+{ z?~Z?$h;q+6tQQ2*b;Fhe-8NMOt)NXufJpmSI_}&K>*O{8{oJ_T6ac1@^7XqyXk5BB zVXwdIEjfP}{nv$yhc0oGU3IeFg_r@_E!fgETMp|-juZ6SQ86 zA*MoOCjj{uek#0cEer&WG4dOG486YIVv>xX2t}OvL7^)#C+?3`U4qVwQFtN8kuCdW zxo!tPn>XkX>vV4WrI~X(4|<^&dcS(_`iRu}fQ%`gM%3qNp@yc}s?bRv(Mf7%JL~Dxpas?2K=jTVI_|iBA>QTo{JvMB*yZ6-7w#2oxl29+jA7Uin8EDI!)DYZk#yCu z`*Y8yVO6X2xO>NW#Bt`WZJjBaC_jJnRR=uy`nQ}!#NWT?Ik*sfGE+YWiR&J`4frDh zev%IlLbuKLCN+J$o!{)|4B?hIFUDh6{QE5j769Y%u$rD=1#J)&cK1oUhELf_oMrosIhsax-Q;%l zwo@j_OY8Xy&D z_aAd=_Hc__+rZ*zv@iGi@-{jbv$791F7GbQm%WI_WW%ysIdDh4@R=TVPYb(zocHhM zyDnUj!U~ss1VcQGI6+t2H6c_;ZV;7bVyMLRmo8R`(4EjwG^Edrm`|!tR>Kn|6sN%D zX^#G;EJcP~AQPHLlE{r|$eZ#C)|3HFe^u~!aT03mLL`qiNEa%$v$F$O)!+uJ*$tL} z(?Zx2hv5gIS_xad{khsZo-cYL7kVxi2f}a-J}^3Ioe0LYEesaue0+ePi61IS^x$dmLoa#s(> zu$I8SoV~SXJS?R^V*0)YvU@(QHaIgwJTAOT?F8(y`m=&g>xU$`8pKPP{M_^`XPy|k zdh*G4ZBP=yJub9~^TVLwdFZ8WXiR)Org6y4w$RxqZ=L^{P5bR^%>dw|kEyy&sQfmm zR$FSHzhWhP!k8f=EKx$Y;uBvde9;JUHiPn~9KJ0p)Oue1QAT_7u~lIM*XB|@i7V$F zzQA=-<%d+SsiRSM2T_J+3k|k-68GzPn_uK;duH{_k{iZFu%En&Mbdjf4Cm#N$yc3M z9l-LKZeWt@WXv^$2p)0;uCpE?4LUGdHFP<{Q&JULM+I=tizg3r0`u*ndJ-mW=)L=s z?`gT-NW>18;N}kR2)x?(qr}* zwtuxzW%lrP<)Yg6>u?HiOa3E9$4?KQo}RuQ5bO-Es&2!A2kna1g@!&lm3Q5NyC8t@ z+>yHHfz1h)cV#NM$ADoGJe_0ZNwO)A*D3CQtuxoZ)&#w-Zu|E(2p+f!Q4w5@YHr_V zU-;!nW_r~&zphnyOT3ZgnkY;Spz9JVxgiZA89{E5v$GM)mkd!e3@`T(kB7^?LE1Wt z-6yN;TGK>QaFg_=B2Yaj%-r{g#Hk8qsHU;|f)t zb9#5>4&k1rkRL_*26N)-3^Tjcb7wr;!p5WUF7GU_Hbs76-p`65szR<@HUIa>$R^aa zOGbm(n1gKHjeMluZzG;bzr~Hgwd+BEHYK*bU2JD8cd$1a+kU><1O#4j*xuRsQzC~a zad*fI>%4OblAwb&Ia?hr)IC{loli(tVNw!~%~(#q?`kj^G-Ug$UcF_1g2-L)PPQ#M zm-#yQH0iSEnMVIXZF^S zpM;c@$8|+4At6EN?yw=7%K~LJ=c7UH;JsKn!ORKNJvW}axg$+9! zJO=N5k^!m{@WT_o=?BZ)#UzNsmJM|pRYQ8aJ<&+)G9$(%{Fm>O$39(sk z5WPbI9HeWNUbFu#0-Y2#3jOGnWMM@z_tI}+QabOdnX&pP+%*E@0@;el#!?B(nd1RL&AnGm#b%Hm zVU*jqoY#I1CCNTD!R+2%d-tSifV%nQqway;lU|^&&t_^@c@`!VAE(NY{ilagaVAX2 zZE=nl!(Vf(4cw>K6o1mU4+QLGM1y`qmHzktzmC2KPEdNOODvO2SFAff;b|absiSAS!%>@?LsRhqIAG@tP_co&@t4nFgEs=O_7JwC*LKlrcca zbGvVB3rES!9=j{~sko9W=k=y_2519`%L_$5&9B~ag^LrjCzpXg>Vp?*s8v%?_WspX{_O|8_M%Z8yOAt!k!=yJ0e1ah^K)ouEVS`%OO&^6&D{HYQM zk{~QfY|)m{P#&4F{P6d{Uds&aN}9n%SCPJr4(U=oTU;)CO@Dpu7RC<+8PL=Mee_svv-@6c_(xmYsW+_8Hj&tfGxgM^ zQ|BRZkmsI@3Re2}cZx{kV$Rfhral~^K08{bFx%xA_Pl^Uc1=!WrAxcJKUoUhrY|xZ z{FQJe%)-pMek%;pK?3Q5dn&%f*11pX;tIELK3?xK?mRRx_DpF0r}2$8PXbf)$P{85 z(Jo#L@|5WT!S2r%9q?kw?mmH-g{W~&10RA#<+dhcgl!|p zaOM19+rBNkpAOWC{rpews0DB3$M2{85O*8UAW=^N><~npH&xT|*y!K(t93H5$McRn zpHqEp9R@(Zah~aD`LEA@AI*Oh-OY1HDK9wFgSBsSCQ${a|ED*X*gCUrfnq|`s)4hl z3IUDGq~?^*zsP5qPo`M>uF$MI0Bq<*rC{GDEk*zg%&zoz^7|qzUD{zhq#UNIg)7Te zP;pwpXXxkK5B6r%wMsw7ZrwTb%-oR+gSit^|L`CQxGWCP#o%=Fy}(LTJdDY(?vlm& zVbqn~IP=jo^xzc_?;oMtiuLOtWScY^D3pnmtO^VWpobQYqYO}FOnyDON9n-F!~5#rtF$Ik0Fxy@UQwZ8ELm~vS+ z5bEA_3|nJ2nhb01kLIB}?E1qqSLL2(7n$5Hqw>`q`ynDt69fBR>bfwiIlL~Oo1ZE2 zYHHgPnR#PR7F$o^IJ8^$XRP!-GKc2#5%Ie;6OUyf@fKMZA?3;BAzZt8+#+*`Ry|3}v9_P?SHZpR zuY^JlF{-;RzL)I*{<4+An}gUnR?-BUb+TYO!4s+OiZxZ|!O4b*zG;@+a|XP+Zx%9f&e`R9Tt~)cI4)dX*xjJE zl01K~^N$L)JYCL^GfDUSYICyq0W+o-iCVx3$#LG*YO<#z3vt2ew3KdC61=PGOd(Xn z^msMNYW_atJti=-?j{rgDYnYFyefuGa^pOc(U{aG$(#a^F+~YB|$i!BQ-Vkbs7idYveY&bkG8CA+b!IQrsYght8(CCh|uL8h0d&*jGzF zSDVU0aK4oXyXV^yp&&5hKW;B|I@7FsZln*-FBxnDB_t8`S!juR?!%a`4p8@y5k@zZmwjUL`=5SYXq4Rr zU<)yn&C*^~)NPmr?kNsCuNvzQUuEcX5&6>_lL~L&ef|3){16I&%}t z>>Hia#_e}k6ClOB4qNKFHOsx*^ACxxW#Td^FdF}@@6E?Ik?kk<`Cf;glPfEYeMhwN z+?Fr~k|;k-7xOybrkwB1g#&B!j6Hhd+3tg17&RTOou{Sj{Aw;65%Xurp^^!YlX*A1uH&Q(gJF+-3qJ<=q9a>E_;aGv0Lh#9B%y^$>u1WdP=ooaZA(zNq)c zww~#0QPEsr;*>iS;R>KwVd-9rGUeb*0LDl9u4GFE1c=B{bEB9{KRpEP22DBmN?cP@ zQ|RCa??RI|RbhxgJ|+=|}jHApJ-tDC}0 zXDd0ux)*~o5uQ_C)VTSFKa^iiG5g;{BYi6`2M+QE5+T!3Nq3Da(Lz?b9Wv*<@SNGb z>!;5ai3hyP^cNg23ZkK{Bcr3U#KE*KPYh{PXN?FBrN_{h20j04uy6dB*)X)M5jJl{ z=Vz25!%RF7M`>5t+m6O6bkX~^?BA5fWWnYjxT*NT0Fh`8;{$|BM6YvjJNLQLxxFMZ(MfR%2e*6 zdLo~DEZUcYn6ZG1yT6{E07P~cTl~TQ^t-L!`i-sd!J#K+ECe&~#lfaqOV~2bq#k0C zF&M}*Q1@PPWF{tDj5?E&K$fd$_H^-L-Zn#_=?QcUmmP@UK#vKUc}-2jaiyA$k)5Bd zdBL|Q?RV=*`t)08Xl_DYd@8Squ{JN-xN*|{{NeG6Rb?c64OV#r_1*gNr69&SJF6@j zQoMPEuArh)R#AZ(3kfg#4tTJ^BhV7v+5}l){~4#6E!hE87o&8N~O1F4E-s0epxf;QU>3bF$S+phi3pUH`bJeARR3dr8aA4%79# zc4Ull1)r5R^UmYFQ7V&i$0ljwIz_mUEypch+J+=4sJDzDRf7eB2 zgvVcd9NGl{!(!{#`dvtb(nR40DrivF)TK2%7r6*`cJv8ub~wu=UAThri4+$0-Fu$0 z7<@!;J(zcWH_bOLa)1K^!;uq|6#dRZ(^#0(tztq*K;({lBRrXU$soda;ErX0*r!oXB0f&TzN4x9=~Zu1*WJ;ilq&^_JVi54Uan zvKq4kRI@(4+mnv+n@0j{;rpC01VZM?-0ZZIxuEry2f2eI+HVsqo4+WR*+~IR0cb;$ zLkzABK#oZc(L|_AJ4%BkqZ}ilb$_LI5*=@9>B#(=*S|)`%(1qM+?$O9x;nPRDh|n% zSx14%ay`M2Jn_Q1LE0f(vr)_Yg)dGcf8RSO^4y@w05Df-o_~1cA*$En3EW;u+)AOG zlWt8@NKSwM0B{s(fWsH{B?W3@2F(^!!qBsW#z&huv5cSkcneHSBO?#SC(UvT?cV5_ zrVse*@=;3FA)hagc!oHc83^Nfu9~;?NsT?HH=R}ux>Fj+N-E!KN#1Alf;2h6mlmg3 z3I3011}%BGh`VbQ<(oC5B^RbmIl2LMU&)b({wgIde#NzC{rru1Ej9<-Uvz}817ggG4 zi(OAb?sp|8j)AfZQM|01NIqbJ+AS9%?5RNioM;sLlRD88oiHfNVi_x#h6N^6)wGAX+C20|d8z?^GNZ;Y7Q~E0#S=DFBKx_ZAffDg(Cv-#pFf(}em(a0 z2Pb5$h@AM3Hs4aSzdTQfD6_9qT)GT2D*o1(w;~Syl9Srkw3I)3Z-M&?mrBvU6&_~d z*jZZ7miSXx6xr_~p8_?q_<7{oMyf}G(m%Qg{Z_iL)IXI1rPh}{n{CNZq~jY$o1OXU z=GcBx;zjiQ=G8l~S8_N&+;AToO99xJ+~(n)ulQp**6%0LSG11@F%dzpxgM2T&O@#* zofldfr%Iveho$xrjCgSWGmW^y-Pn)h#031yet1~Oj@ysKfU*FNktSdRd#ywt(@mnF6gTl?*41FM8#L?`eN9m zLDPF2%Px3BEbN{X|m6Zdjyg6n483o$JXw!UFg8*cjYc1s=?_B6_i^`7D5xbvTrvT7s+}!ak={5Ie}R# zL5+J=S<_)>m@d0D1Qp+O#t>YWEzaNBp4ii4U?ka3BxV7;~~!xtPsK&UxsF!vI(b2V z9T4UF(i=iY7L%8$J3f;%RTHLapIx%w=pHH!O6hpFy9|c>`|-qN^@VVG;V_m%`mdx` zEp!|Ux*mnL1ayD1cB(VSh5F79lCsNktuf($-lzw;KS}j_rJ=1~;5MOdhP_ljHC?pf zFFAH>84YfgXQ8$JKgC(1Dn=ZfhUghCxvMDf-jjedx>RFdOG+V{DxFh|ah7o-n&}p+ zOzs}G$z{{OZ4uAdw4CQG1ZP-poP8z2Y5dg2588hsn>3wfYo7UV(N_I472fKY%ge0v zm(d(CiQD0zd~x*WoP^=>tDUxka2)BVna!iNo+;{x4Lof*R_cB4I=*TqRXHTSQlV&t zFuP2Fk@_VumVjo1LR=1z#=FbBB6!_oYJIhN)LUAGT_O0hISt|Zmp}jOlY_O2Y zP&_O_2#H)a%TAw1L5i=ho=vI;saTwa`AwAF)DsbqKpFEu8_&Bd#xa7Tgw@ASqN1bm ztL-(Ta>ES=>&u*G^CEH?4L6~V-@nPGw3F=O!fM{Bu3!P&j60BuZzM>Q02Dn*WyHy_ zlzZ}v*k7?dN-uiL)=pZ6hUH&5kn7LdJ{tL~!SGP6lu|J3M%WU=YCgMFP@DLc{9cl) z!~2gDBuYm8uJh}On!}%cdgv(`Su5K}B|$Xn#i(G73T{V^uAu{us1GTA{2WbjQ6<*V zViSO+Vl57HUn*Dbbg#RWIH!512l!lONu)vs~7|t&kPlS!~ zSj88V8spXWTMx%y{q+a#MsXe6ZhIeX%KF6#HoQdsnLKy({hsrznd!yyx-5b-SMUY! z;`$jfd>c%}%*zMwO#Wkk4nv^z`;=i>QphBbOj0*Y>a|9qc>CHb3Znb-UX zrMH{zXwe?AP4j;}V|g)~1@jXqa6!?vyPuhg4_r_Xy$S1mV9!vJ*y%*raZyE1UdDHG z!{<}-pXGlyV=Mh(5z3>bR^?2n9C6g|saFO~;eYw8rb_$NF#Q7HP5I>OlYI~n!@BE+VL6eIOqI7FEvnD4mAdpF%TJw)UcPw}y$F;S%g+e3k4qzHb26)+RRmaBsGSMmTtB^g7k@9^GuVo!uFsMSv zSOF9GgOUnL-12taC(1SWV;ne6t$EW;N2hWpbH1e0e3JHb<+tI!WeO_F`=(fkT_sjR zgnbU+RP~bG79eZJ)A@U!+QQ|mv~~K|y$F+~0e&tP^1cz&+g^4c{pw50mA6QK6a=ix zy>xJq`Xw9roq;_?X=y2Vd48w*=d13lbLaCb;(lOK6A$V^ zi+-h7YCb(!Q^k13n%rht$}LcM*UZ zr2>R%)0#{-Mky|GX&vIlCdXKNasUB3EBUX;!IX z{L0GIf-m9rSpeUenwEBgj`HI9Bl}p(`Oo{RUE}td{M^6~gRk!$57f)HE*6g--X=uA z+=wu5Hk!X^+JMUo;QTk$P?ghwCylxQYGQoVbJXVx0y5vZe{{f>*>GNk%&GEmCXY#~ zDk}E!;qdVCa;p$QxVUg4x6+A;WqROe>s}%!ejSHPb&@j%3tId<+_QIm;|{@CoS#6`|XjJ572gb^!6Oh%TLpPwv=-+knvv7(4_Ubk=L zU%9JR;a(}w@)g6^Hyb^pKmC3M+!3ncNyrfLRH^|~BnO=$g^9A{os3VrWu$eszP>k4 zlTVLtl|$Sw9dKTr-8d!d;y0j1*5t&1j{#H&PVOF<6QsBRz=ly&@fHwY*J{e(W^rR< z`e{86Xo?xAZBFyWYa9EBnZ?;)B+-;4n>!}f=tZ^ zP4qkKxet~>e9trpuY|RA(5BOgy#EXRU@4xxm(^}UKXP<`(pSv2zkh9N!Bb^9#80uo zaY-=E_qWvw9qQ?6C9`K3xyjq4ZLEnw7r+qCTZr;=W9fS(f!I2S)Zjh)xo~8DGOv&r**KHIYbvoS-+XY4wv*2=)p-Gw z9i$-R{hB&rbSu(!_cW+-h*H@*9Py|!eRiA6xcTYpQ|IZ`;3W0_VN}l@&fQOUrrk@) z1cc&X->p<^)va>jE+U*J*y5T?a~dnBL~{7E03hiYX5tO0Y|aNUFCnfH$pvq@)YqoU zS9cmXZQ-Yzc>%rh9=^o2LE8htGoFBTNF8DUj?g&4fq8Z}o0a6*isO&)75OhhqjPEd zVv{Thz1Q5a?n~UUJb^IHGL=VeT~xPskF>^qm+r)*Ur%mD3)9Th|NLH&R{qszV{cE< zb~>=yv+S8moEhlf9Xgp@6{9P#|o655U`X*vHF`90CQ?>}nEJ!rdR9s}LIGEI#XIj6>slPSPlsqxD z%jhBS%^_`;r_Xy_zN(LKH9nBN_c~Q*D!eZOAF?+vT2LPQ77Q39`NMDno zZsZQ3icmb4PFN7aZ_6AZc0vq@Hp^>u7H4lhznrcWIden-+?0KH$MS^WPyn5J2Ko|b zD4a>{!_HOHwp`EJk*K@*&0VhE=Rp_YbD%Y9)Dn?4K!e%679MPunLqTzF7R@;Py8l` zbORe>!kkA=s&|zYU2{|#;dNo+^CACcuKZ!GWd6>lRMKxVQh7yQlpXGvW#wGhj@q=l z_;2T(S$w$d-{Atbu;F>ZvP?EF7u&q;Cn(C3HtK9wishPdg=j<~araf+6@;xmQOJ&8 zqL>Ce5YawP5F@xMINQp&-QIDYVk`cZS3@?RQ^Veyn_Zb$yfE6IIQq?eYAGnr&Y(`t%#t zId2+5vxywfw$dhwM7^X4l2>)pnJTNmjKV|Do@zF{C+$Q+ zP7CjqA3X$&JWm~#Ow;;B>4G3JD#B09Z}$E8Zu%Wc`|XY`AW}f!TSjq&HfU%QA`UqpkC6kzu7ErVmzPPcdxkYdtWl4J4r;~=%+%j; zfxc*M^>7&tFpcoBuVkH~VTYKF!IkC(7JPiJF1(5McxEizSXE{x^c}j8+u*}8#+uweJfX=u>ux}x9ZsIl z8yRnZX&QXSD}lI|bGbecP7<@krwch1Z-t%#+9BU(4jhtAzcH20hI5B56dXq5FXNPn z^pspIz|&)5SQDQ?fnF1Sm(#7x@>Ua$6#E6d3sVFj% zfl#$qaDUmhYFXNR6gxfL=xNQrY+!5T;Si`jMsOwZDu!+}QEj#NUZx80LwIQgA&F<> z7jn7CjCogx(n)EeHT4^@@swEQ|j4Cv9@s-VD@ zHbXwbKC=R{E1yhJl6i@M36(augT(bm-Hv8q8r)A39$a`5hye-zAJUj;N|(Oc8SzFTfa>UmixtEH_ukdD{+Wi1FVi}aAqy@(l?kK~UQ zpJMQvsfy^o5vG%Yv>{*92I&mo&ejr=DG#>8Aux@DT6Vz{y~isGMRBuA8>N8Ar^FBR z9?1I!7UUvl=ib+}FRd{YTNC{H_T0kJ(tuQQ)N~ZDfo!lz{BBsTZsalG-Zp%UmHIXUb^eP>hZTG@tsaRZ+*g_(p6t(309Vn@PcIX9X_y791nZ=?PNxI zsl?4mJ#jCfEUaG%ojT8VFJ3q{v$5(%FIM_FMwi&+`$)y*yv>~WARt|K$4O6p$aGH+6kN^N@8*ka!G#r6UoQ;-%NvKAn zXSqIhSH$~8X#O1NHKkAynRET0teZ^~4iQ^10031H({}`TNlk071YEHK zh~g=R6HSPQ_ksvb{Wp1yU6}Ng#n56u*q%apg|3pgzcB{-U5xE-ZPP78qte}WRb6i- z7H0dcoZR#HVgl9KZP#Xr{?!@@^icY~FR?VepYo%LNiu(3qc}<-$rocW7`D7nTHClY zhv9I6d~6;X9nCj2<;QEG%vjWd1hRQf&Dp|eHla8x+AT22<7FeRotJ?N_cLu;UkTc2Rbp_z|6E%0R85VdYXSIk2KP5P8VG++48|m2Lud z#M*ohx~p7OcV`95&zh^opRcv^4xAzed6A=6Iz)Iq`sf9mmwWR3N3IX7LqUzBgPE)2 z+cQLRu;$%KW0im%XWG`?n$hb3T(s!YZ{@E&7vq8D5b|_5kiJGX9LTpNGP~44!Lbaj z2e2?#vb;DHBtO%7uqDnUjV*YgVYf;%U~FgBwT8RUi5zlWR5{k#+&!z-lVE0Xrg*(8 z%5@tQ`02K8x5pX}a%xs&BG|I&tga(;LD}+;`})FDzZnDeNZfWF$?>qB7rJnl6jiiK zpLNb3_3Rj$>9+Xm_==3^R1>4F=85p)b$Byk)gz)i>vm<>Bdm?<-K|dLPz1ks{d8q z$gxTsDgSFJkfJB=-S!{^c#YUsEmxZgF*^=haqol99)e_P_)&FqvTxU$jU`TqS046^ zx3mN_0g&U*S~@A(LSG%WL#NSCCx{^ckAQp-67YK~)Q3}YnsZW6~cjU!ck>h0Uu5oDvxi^U}w zsWMPp8U-%|qSMX9y4sGtA;tolpcqgi859*qat=>OISe2tR(QMPxtumISJvxIf=F_K zM#-vq7Y6EhxBmX}&s!JAw@_ZB>yHC!#sO0b(l0dxT!u?qT9UX+Vv6l4Yr1$NvByO| z0VxMhE9fDdjb#Y(EJbw(0C<|(#sdIsYQ0~Kjh6M$NYZDLZ{82GfP>+8X2{a~J%zm0>jr73Y82?Z+MY?6)6^|C_ zGvM;~boLxJoBw)5m;bNTO%O6HXswhI+IjEdvUJI+>$0u?{-R{hfNjx9{l5Ukd+Kf}1YugI%;x0$&^QyrS&YYa-H_ ztxAweNPyRyQ2jE`(YW8fVXl0G9N?W1ZBKDgutXx&Xg-Z_CQE?U*TbAA9%x{9BSyhL)%?lPbvi+^7B5Ip;{!N<_NJm|r-=w~4RzIT^sI_{0tBhdC~@6x8VYzg~a_02Rk6O&=P%{^}R+t~6#{u2+Biwj;5u!B0UP zG8DCd-3EyqNsB4lr!QP{IJ}wed51YA5BYkoGZqfb4S#cXeZZv>=~j{CR=b~IfW^?q zQOD+okQJ4$!5OzkwAsCRst&Nk6zh-%RN)L!;fy0!S&p|_C}v2B;rh#rKMxvJ+?Zqoq{kAj#4g)rsDg$ zjYCDl8#_`Vf0cY7e)0G;>8J0R%dLi9msuEE6S~ zEXf#JKY!DP{RDd&p6*dSxv1TT%k+yub0vGZuJ^LkPHj`ji?O<|H_hy^mBUWu%f$}f zW}G^+pW*E$Oh9vMPU{R?VDd?NQd{${BP@;y1UwBN9peU@#V4L*muIGHD+k1US<3*- ziLV1_B+f-y%%)0HOZZJHlV{(+p~3;g8|9x%G<s}F{GyX4CR2Dz7Pj z&5!s9Q5P`_<*RDGMe%1#JU{o+R{1dRjRQd%0cy&rIT(1r-{D%or`QwXThU+y<(KTAWVHeRy z)+{%{b|0p^W83S8KyvR-`Scz_>uI}d5uu9*6?cl}V-eC_AgM#bCm^Xw+@GMrSTh>* z_R{H`lH%f)r&xD8nDLz}I}W6%r6TSf{kzopL<{n)7z;J~iV7|BoHq)loIaQ+XwA@q zssmQeL9V0)Fat3TAqHQ&@mGAyE1=z`?4Y9Z-kwbA@L9=tjN{`AN7BWfn=I@jeh7L> zgaFO@UW56_TcJZndBtbtRI+B~kBIx%*VDfytEuw5Uv2F!I2M}uF?mUn2jKmRJX0)` zzzg*!Y+-z$BAh?1j)C;%tQYP=3ExuyTx32)HM zp-_8o1|3&;xD)>4`=u*`A;uHm$~K~@45{esDR6Y*7ZaJPe@m%f7Pb3R-d(0i6xhUm zHfwD2mKf_bNC|}IA>#G?9RB{QnkK8u4GqZgpOWz*1=<*#e~?_QE@dw=BUF`Xc?E@@ zbuUe0ZD~frp3RfVjzHgt9{Pj%8Z|GnXnb~)6;l0MUbaWHPq`S0osrg(5CuK$Uw>O> z#>-qyEo`U7hq#XIe%qld>;nZk*6^CuS~(q4H+17m`k;HWJ46CjY`&dsN1EnQcfiQo z-#@Q$4;HXVCxEoX?a<$+C?8DQ^drh=`MamIgY=Q|&83Qu*-Hx`s&!&cN&U9>A<$zc z)>IkMEV7Bd94dFww8JzhjQF6V6jb*E0@!djz$q_uHrJwFpe;Ynh7m7>Z^( z1z68{yVdU>s1N}+`}Y^8(@)IA{tSaC!Lo}F&{Gb~lrSd{R^1@2`G7H_rRu%|+o^E# zr`05KSUH8031VrDZ9|V1ZBGA%!p+yh3fga1p(icYn0ySVwLzc6ox~`C8B>~IQm0j< zb@QK8Y@%8#b%Jcy11npn-L;$ap;gNv+clT?H%jo>GuPN`c(?asI8{OH7^_7$f!qEw zpIn*M@Gj!&Jk*YunP9fCR55a2%yXfSc&11Ugdc#cRO9Q&k7DM!;iHp9olkL@-*=_r z7OOk&y;gDs(t0;EpYS>(lYh%i^<%w-7Ki9r!g0XT^}P9-3LAunM@^6RQdMd_KJxzx!&f&fmp{H=%eud7m*h@Kt3*Ng<}?S z$7)*;faAHtUgZvk6i=7i+P0et1_$`O*C~z2#Yb=7b&ZNxsyyflvLs7-=64ptJQO?l zh|}-SwQa%7TF*OQiDjk|ldgOXqY(`ZSvAm!j-0MvZy>A0C61J6xe%K4x?X?Ayn-o6 z(97x zZow$n0^HWK@3k5s9YQ!mYM?JcV=VmYm2AV__=MYDqbo8(SGxNiy`Il{bpzd#=uafb z$StY78UddndsoQS_5(+s!#d=7s5)kOkf(af9^CyMH!ow@&q6z16EDQv)3(-SWi39f zUwSYwF^MVR@H_8yr%o0taYfY~&c&w1s~mgt*9>Gg@HSw zK$*^G^I6B+rl9|KWr0}JBT&q`T~h6PFLSWmNW8by&Rf2B*3_ex9O0sBJi@eTUFt6M z5p5rDayeO~QP-S=7{LQ(X5i6<#x( z^3Fg(5i=340D2OPevi%^&7h{O|**1*qAOf<#|FJZah;Iq@H=;TGL4|6^ldX55Uz zKU!ODE;sxaD@GuE@dm7f3If_r|H;os>{Hc148-g#;Tn!b(a;8H?V**gMb%a&97xJ& za!vorq^IJVh>(4tlM_{Iy9t-i=U^3Z)`<1I9r=ZtTws3aAD1!f)kV8P?xI^-48i6| zThR;ODv{lGNl3i!w~5D`pK3NW#gX`_pH=2`r0E*%Zf{RGy?92=vv9?UpTR*EGp}ZZ zRFBE!21t)(EgPIwRpU3e(^I5B0!VW|P{z(MA{&@ay-=PQAH7Va`|I@t^WT4bxFw4w z=kOP9ZNdl>2Po32uS)xu^(`GJ(l;gu-M_D1%HPwMQ{JeDawG`3RBEg1zL1{;8B4-R zmk!Vy@>@%Y{KTdW;eTZZQxF2>*H)GaaGatzm+MO)cVAfPrP@p9!(Ms8^Bc^4)Z4_v{435xjwLzI^PnDOE z!SeQWU7dkEy&&AD2H%F0+<}v2tqLcPv8jy9i_}8RrJgy#!dj$*y_jW;R=Wk-^uCCX zHZdPTO-Q=qJ*)V71NR<{+=YFgXKS?h10AQ0E}^T z$YW+@-)qy&)SgI7?z`YN9{c zC-R?DLJR8jzvqX6>ZPQF893p+Z@xNwiyF|`DLUu6Bck;Aa|U(}=qm#9wg-Dt8HeeT zvW$$kj>l!d>z(BQ=s8uh+r)tn`K=&_mQJ~VS-=gio<%sOq@z3ui68jwr!Rx&m@0p1k(GF$NuW>~4 zP9em$XHTCH%H-3yb93{tPVSYsP?HBF-oJm5M?({}+(;NI8E`YO)=t;6^dDjEmjL6Y zNY1`TMk1=*L^nHi*c2*T!Sfns@6`rv^m9hldAo zS21WS^gad3t)3{VD|GKs+;p&fg_}6H|2+V$swoxPqXZl7fE5Z@7G-Ns!X1LlQM^55 z)X}JBH0M#Op3P@z)g;@8W{ng=31XW)uTzuj;qNULft{sNp`f5VfH}ntM&bmc?~VYV zf`Q@O{vuXPv)!I}*7{wjWX?mKnOZ;$MQU)Q$$w6tW`xji^F8U8D*7zZt0|_knVvP( z+A~JwwI7@8L-a(>+xZ%M6V)g^G{#U30=L#KP$tF23o`51#!`e_4$J8LuDCWr zN>y?VR45xZT6lOEQ8HXBNt8sW+-{!lKO;kdta{c%tx5|jz4A2SR{n{fx_AJg22b$! z@8iYJ66WI1)zgNZf0d|DB1q+Z;QmNS5-ai+Gt#U}Hb(2+xbgKr$1SB-Wk8z8 zdO+6`_pQ9zFRAoT28dgguy&KdH5v+PimBgP#C6Uicgx1v)P^be?s?JU?$bk-z)K=j!&g|b0YZruS9~~)&IK&Cg z(|clJu-xzQjk_GO-yN`nU<#Ww0xk2*rLP$CR)xZG&y;2h)r`WH(b? z`2#N6Ne?=$Wwl&@h&x$RSHzKBPLVb!mf+vY$D2`$aIV>I>PvC1^{rlH7oE}7 z#TkDW&!M3F3`t_3Di+`WVa6Xl=)xPXV!wlyVD^%R=*7S{39Ih5JecrTO>io%SW%M5 z_X9}yR()|EilxycLZJ;L!xoMVOjE-3Y~0G3x=J5GvZ|Eh2rm~z2kft4!TOJ}-(n1Y zxYbuDBpG8O--iYo-<&RmO8SdaDcimeosv=F(m8Bila_gZnVg+~Ptzp329vG!z)Pwy zc=U*j0Qa)qHcq4!H}*dXdk7PrVEKdbvwFpLHq+&o$R|z&YQHG`OJ4c~#DOkuki5s!GyA2*B zfo#44v6SwLbqG+Z9c-JQGNIik)ggg$q3-H47iN@NLsTciwIzO46IfgciAj=o2aVs~ z$y2FIfFYsc6Lz(Sa>@>j7N^nTt`eb)k~pnybPVQ%H$u`c9l5ESJ{Yn=Th!r_IWo+a zdPtr1q>Za_l6|LzyKM+Hj`oo^cB{IKJlD&6MH+ z2|vi$@XD@qu@`YG@u4B>7WVT*5t*Ng?+NKA;?}h$<;w2=qNliQep4&8@t2$%8LUNI z3YRdfi`aw&|D^P!ow86N&;|*$6lu4Kwxic6u<*PzSSYF`eadRRkB%?mC+2+;aGe_- zyi(A*gH_Ixv4wRxs1!GfY8B6sjBmj-JOK8MM4nC3)ZvtP7?_yvMLcX}^=I@Ys8K#+znb^8jB9yyg`kyD?PiY{Ol0#QMJJzgNLv>A;UhMR{y0&h*6)<*uS& zyT<85cl{fQHSuaE-FneO5~san4a;!%lLyC%?oneQ$^U+o0x}^Vy{)mVYfjI`)&{%9 zKdFT2+`iQauW`PpA6b->zXZgVmRQo@m5Op@LiaN1NMB*Kz;D_Er7Y>gL zDdF2M3g^~3taq2kA^GOaT2%>B)L8R8E(d09H*2ym2xug~ff(x4t>x5PB^;$7J!X2l zYya}}a$45#o>SgvBXrfP@uWCs@4AEE>5oxopuN}CtXEa_I|c@Z&4=@0e{KNMi@eQ3Oa!Nrg7YoUZqtEk8fS*su5g&|;1xh9o^dxbmAS5cpat9xyO2 zemz zLkB7ug5l$+|LF7+B^nB}a z@n@#Cs;Y{B$L6(q8tw!qpWTm8@TJGc$6+dFt$V+Ng#U9U zh4CUT3*%pB@H=4TrHdZxwc0i6YL;HUx6#&S^uE8K zcsmxg__?5{DK#~f=rxsxb;#n^#@ktkKmHeOo9Z$9KHiAP2U4d319RL8? zxw+IHXyq|>ypaWS0r@!U#ffL(4i8*h;*_6ZzrswCp#u@wTO&#E27b|(|M2t?-ZkH~ zzpiqg=MF|EM-bs9p(R1%@c1XiZ9V7pdSvg{_Ey;oNn-?d>}vLL0kX-;d=A`Jd0YO* zPQkhB`4Ng|Zpc8kF@sjQHs?05WNF`K^L0PJ=HqMpJL(J`>K(_s8W!u20W2{Q_N#^gX=~^cq?es~D zQvIjeq|XE)-nMZIc|0zPv!@4h*Qv_k(%2)p@@YCU1AqSv4t`l)^7i6BcBFRUeTRlp zB3K;A91Pom%EZ#^jxDBp9^ID2qL=6%H!mny$G z#T8;T@$VSTE_VKz&{TEd@;V{*7ms$M4Elm(;hvr&u1cC9-0`N zzl^Z1W{4->xOI2Q*>AYg@`C(HLA0mWw(@bu7F#4n^NksLAEV^=W%z$mZ}CTZacSva zFSnOFzw>oS&PV=pxv}v^r($aFHyZ4g^Qvzl#!sInT<*T@?gzD`y%Zw4VK__k)DJ_? z93wgG2~Kvo{{Oa~XsC+fNUl`;eAEW_jg31#Rr7}h7ml|m%Q4FmwiC_$>u1lKm^08g8LDRZy63=(N3m7BCCJLz^`xn#s1_m^5F$JN%C zA&MO}GZp3O5%<0$*%n1FkkHyOo*U~8a=#cYRw7)_D}J7>$Mv&|`T0-hPUWI*ag;H_ z&gTpvI_Q{_-}my-HoJaTW{v6k^L))qP86=~Wd*x`#wk}X4=me%UtUd^Wjer!1`KDL z{LLWPwXQf?3f(_6tvJ#SIWE%2BJ!|_zfL$BWgkCk#FR&(}9{d|S+u)Qc_cd;q2H^FzVcvG-2xgk9LoY{3c z*(`q~Fm`oUdLd`g@^l+bD&V%ayX|&kioT*S*zGzoFTz>XEdD9nj5b-LU5RB4^kmDAaEWI&GZW)Hm6c2Jp z(_OY0*+j9ahR5ZB%b!P6MWV%xwwECR=fh-R4mMLD2FtKv&fV8`OcHNG`k>e)yyZkl z!B(~>G1sLYM`CKkQHPWqTw2EO-2K9~eVUKqE2HNp3s11IS3*jwZ+?D_FZ9@e5cGfF z;UoR!b3z{2jNV&iitV9Jmifu&gW0H-{r0u))tjGfMq?cFMsrw(^A@bWNK{-X%y_Wt zW!ZOaJR;Q?M*_ino_ZAHmFSE+bpLEg)M6fpsd7jO_&rSSC7&Y`m{l9v?6ih%T``Ef zTrN^wOm%!a7eiK>4?1@2!_4jPMIU=to7XTS|5+_O-*GW&!o^C(PygeX%T`PNSx|57 z0P&bOZ~N5AV_au)eK=DYUy$|0BCL;!A#cOGA~@SJ>Vm_H`3)P1EfL zYH%&j>!u-u^YI+VNnFXpXLK8;Kr2Y;rE2xutTw)9ZE_i2FOkkc z4(gQiy~b8njw9f2VACSp1r#Ez=$-VbY9?#PYOR(pH2Cu01Lrrt^bRWWnVu0S9J>}_X5;zf12GFD=ZYL<#=YTUW$-_9{GX<-xoiD=HzSSk;0)zFj7{@V zu_XV#DOP&HW{$2Xep~#@%Mfj~%_w{JG~x(8PwHucbS8PE!*Txn9hBy zt3x-?DZwH>p&Y%Gr`k=-TGPBiTiW*#10Q;l<;`*AE8q2arBZo+k>yO)MlKv~H0D|8 zhwf)L!co|`(bix&^)_z&bm8y+}++i1;2=hxSVfp z$o(g!c;{?)tdFjwUNrPrS<9W~t3ha6D{vdFO+LF4Acr#`pv@Zo^fJG{M};w?H@JzC(cmaj?)D^I((lr+;`Q4uvkqoCxakZ?L+C3q~EplPwBx zY_=c|rtl@ljXT_>Cn>Vyr#aOn-2$#gFMjd^J_J+zGt6+&8{{GMt9md%iQq z5(Wkc;`p;#glrEeoSnT7;ZkTFQ^&hJMws(w9MS}uUx+Y?kmiGV?TV{}J zJY6qqy-;>!*{WhI@>4DOD_QisY3|mF<|)IIH51Y$sqAf5Qo#6V(Evzv{APH9^^as! zeDS%EWm)QS(*R48>CEE7Q?B_-m}1l+6|#ZQPeeM^KS3CHt6XjGC4@cjmGlSBQd(A* zl&#p>vQOBmOtj^3mKPid>tJnD0@FSzE~4vPA< zxtqr)$-dT$aV9hE3j*vEi0}LOp!NSMr7>nIL&m%W3*MGiRw)hVd5i7zzTkGAYEE#8 zzMO5eB+v3`3+2o5?lBi?g0Z{WcxyGMEF$Vpb+z^LXR@Am1j+~`evAsCdLxa?Y2>*3 zzFHXEnq$AM{4kASb=sRj^FtXXRcx-~J6LFpkrFS^O|uF{JNjUwfamMGFLZZtqyP@~ z;oK&>%Rda!RrZ0T^3?}N+LMkC=SU%&L*W=}_qkV(F-7FQX55-D3Ve*#T`J4>!~3~v z(F0a~^ouuTMi>3+Z99?$QTV6n<|^bGPxX&t!!(lBK0bI=5)IpgV>#oFZ?Un`Amy_+ zsg*uF1SsbG={FtN@bf?m=-uzL*sv+DGgRB_y-DonM| zA#e519HaFh(@=Iw@wLWm2poBO-??pz$$PF1yI$VwdMlPINGgP`PW;5+8eqPbe%lw2 zW%q!;go;ND0(q~n&W-SFwJDpeV%Ga@1=8rf2IJ*_rUU3C^oHAILd(w6-PfS?o~@N? zQWOwyXjbbIFmn((_v+Z$*UC_B85K_6+^p7dJP4z7z|uD(+B~)8X?j3r-_RaIBf(LwmVSDOaY^T3w;&P>Gi=`!p4YjSSCVbb|ZhapLBtGV6} z)%f2MzoY&Bnyp--jsnTL60op%csMM*o@qXYdA>VF1S-#`i@%UxB_&%w^#up~COnl? zb^abS>MLohOD8M1TP?J-=4FzBi@7)x)5}mirefnSn-bTFc)fL6sb&SHlJi>itaJ<{$0*7lSBc5Jtn86N5E4Rb#acFnb}5uG z+6U)4dLTpyTc}ql;>)8b6xs#1C~GKV2a6gIob!z9^@tNte!y0Ejy%oO%{t=4o@{EI z+7@nk;Vt@H<&H6bYD-eHfA>JsyES~hnXp_udfipE(pSx+7SP$D46}>gW*l` z5&@fCya|<>_f8oLuZ5Ht&qn_oe)TBe1-tS)%V&K7Ct)n=)6za9R~z=}$C_2}Pk*0Y zBJx5!zJFYPE6#sSGoA-YT3ZAae^};q+U$;XGv=N^((eW)d!GkwW^5aMY}5<+5GHN6 zVNUxYueUC!(-)>l*Su6$ym63FP)Jm;WkrFq0u<@pQ*b=v4oJ~WIQwOn)PwimPO9GuNa~HeXBD;&)^%)V5D3dmc0vACW4Miiy znpDgE6Uo&fo6W8bun%zUt+S!H;?l?1<4LN**N`kuVnT&p1^!sYT;~^ba7wjrzfLD_ zks6}8Ryn;n*uij&!0ppGHe75(yS^|j^f)1RvvtE-=9*x)c40nrRi!*&1pc{ z#zfW&*$vkGag=_}b1)#>+jg+7>FcE-h=n?e-xB5Ar>(=0*>~Ob;aB>dFaf`&)r^K$ zxb->KzvqWQ&rD2Ryrc0f!#NT&;~?rmAGpFSPn%EIG*gF6M$;ALPbBwyBStZn`3ukx z#*5b)Vze7lQPcKOH+O$`495GO@nG4@|4bcYPl#wF!?)XWT_t5$T$MM}viE$nUFpP<~PwJ#QKE3j@ z?xIxAYzhZetYNMR^dh-Eh_Cd5yv`X#%KZWHCG8WE5EJ@-nKLimP$=qW+ds-JDD%BN zW^FPs=~*pb)paH9HuA>8k1X3m5$f~9Y7Mv;+8as!yO!4XRC&Ucq3emCtNV?II_<`I zPYNzPd!Kz%{F>*af03G5C3&B)9AUj~$c*?Z`?}E_nL+Wv4?IY=X-yaSG23+I;Cb*u zP1X-Bx7Izj>q%NzKQ@e*S*0bf-B=)KtM!lh6lh19r-Fn2QB?;R%>b>m6*qAc8Bhny zd}M_&z!xH+W1X=2LM#VIW((|PDnX}BrFnU{?_Z|+fgZpSOF$0(FcbA-vRQtSyh9g4dvh3|f22M1M8BY38OcCvRJFyRDrO>ref!?F>$g5Al?v7BU0o`?O7#y)3OP^F3p*j$rk12k3usT&q_^D5r*K8^ zsbPJNiK08~2TpY0mxE~WgmLXAo@{`V#!Jm8j_MQYVv2{V_~o0+rCrg-2=k+Mu~*C= zKCErWob3EFhc-Apj~j`BIP*491F(a(V?%rqMA&h@92Gcz7uueXJT47J6$lV+^*p~L zw(Yeh=Xav#S$3kjzdqic-OdCRj6E=rf9rlmU1!U-g6`|~6|@q~wDO1EZR`GeC6%Kd=5Ov&(E030l5{}l>L;Q9u~a3;AnZ8Bi4Be7-(FNo?jbw z?SS7t{}-W0RBnYNz$OyssZ|@>Z$_ScRT= zn9*c|V5!?~+1rYJ-tSx>g9OoeyF?Ddt}FeL_7MrD)!Wq{j&7RVG&NVyhfmtK4G|o; zI;mxefmm1FY`*-SYzqw?_H~plF6@#t#1W-r5#3PrfmOK<3r7Ggi8B>wS@ACJUNZS2 z*@rvOQjh*LLInNQ?(w_<7$kVHgZcUx`81yM_^gGI7~3}F;z=xl{Dy`U&!b1_9LFdE zK7Temul}}9(Wm?6dO{%&oSz?&BJx+AXuqYT08;G`ax;&;SslwjMfoSGOGUlD$B|!! zb{H^yovuic%|xIaI37o|8-BEWeE&)mjutb;4z=zQsMq3~k1?93;-(2z<~36&VBr=W|Nhi6_$c_?~RyhC>Abt2sJ zJ&L@RQc&2sT^52uOoRd^ocmMdh;JD9!hVW{uz&7!)APJE&h$KTB?!h8&{tLl4retT zyAI>|^27@^JUokTaQZCT-6yME1e|6Vu8Zz;gI_F|nhfEtWz8IQ%XelVZCNgPcYwbm(05eh41!Cquc*r5r zL%V;6hX&S#QSm~OQy1ZyIW`;gx(sW{r_Up%SUM7e7bzS^dtCcQyWEP=Yn*r#7$|&c zjDz;In}}J4Eo!+_tBeQ`ntXOPpW~V@dXE?cGIg=n0z-36R2rR!DCRjYJz;SIMSqs{ zl^SJhK@9-RfrsbV^7tIO-JXv*>O>@Qlisznbusp=1cf+?wA~CLj|EJ!4tvsA*Zt?p z?q>#jKGK$}kSrj+Kkmx3+^F!;aana^Z8TtpDw8Lo51gra1TqF#Nfhtvw5WLxbli^2 z5U!5Ve&3A25puQY=NQ?vYzg{2O^|cB3nx!>1ilSu*zm86RxLvQl=J;VNY`m%F z*22Zy?#{^dbSKk=7ZEf@b$8xzP>$x=W?9Y~@mb76MQxLYiYn+se%l~o7ReKDg5ew$ z&*@p(ai!O#NoFR1GN){}g9WlylF{}0LaOnr?d-jJe|+#k1pLbR9o1h9VJ#Q)h`gnq zAO12GF_f2V?WOU6MBL>$DG|d5X0k3!>w=lr%8NPnWjslpi!T=kIqvmx)r~UEF@hZln z`&$&2lSOE`ByLG3wjklCN{tmgk5P(m+FKq>{XSjb1-&VXwjd51VA zmtoe7xwE}v@=lxj%8fMCgE>b(mig;elC$;`zd563u9^;-Y^3mXL*s|;)@*w^uiL#UO1Hhm`@Igz4z= zXD|7er_RKMt9aAz&yzC4nQjPT2p81Z#2d9Es{t|X*`KBbhckI2(YKi;r*kIE+H_h{ zBWu3gT_5&>V^HZlPZo@N)RTHSKT5?fZ9{jfdrr^#>xZ2$0}NSAj5|sa=qL6|AMFTP zGr!^M@2S$yj{Q=yCfi4FC3^L! ze%4@7jHY0LF-^l&c=ext1&Goz7WDY1i-UYOq-1jVAY1LC>B;Gn9%UB|s&e93oT+UNde@r!YO?2b!ZQXB!#qw$?*7B*Ul`_2;i z*;S;ws;32bG{lfDNopNP`@M(~AzS+`SwwQF7=whi1(vk~hoM?hyIvhxOy36?8OrKy zmMGGClSh{#Az?3J$UZk-h1o7YGaiaQt6taFHHZB6XFg67B=Ma{glqAYFyAvF!(+q=}MmCZqNq<7#<_ePQZ z#>H2BLlQmumMz&n2LX6Gu7PLc;`+LNYYim@bxX@6X<-kIkv-kA`8>z8KVBXklrYOp zP}9)BH!lu{Co)xPm(~)V&+P4R%B2v;BF!E)S2}mS(lR-u2mH(IJW`wQT=FWwJ;ktE z>(t}%#^T|NX+9>>OZ!GFde%~EI;N@Bpke%(Bd zc`~vTQwwlJRh@z6*$Za8sDlzt3k%o=9pr>WjrhzY&_q(w+U(grCoi{EET$eP$#AP0 z)J|Zord4nTzu2b&G^zM}#ShzqnreGZnX}s=Kd8GqDs~I6Vc-J0B-~@R`1PxKex$gWtyR z&fxo~O6GZR4ix-GUF`IXWy|`$FBEg+J+Q6!gL^bcoD^Z2Y$~2bE`~hSYSBZZUqTlz zkQWd1xM+=yhcsk9E6Mbr+S;=FlS(*AdFrk$sJ>F09_9?&iQ~f;C21yYzT#MYXg-xv z*M?pU>G-|}u%>c?Q7mvZGl;yEWBZjbg4!=xZ7ORKCTJ3r>1iN(qM=4$Mgmw33^Z~d zU5EcN=ad{Jy?u8!+`PQpL@3kCJUI?lULHB@E?&1%CyMU=AKuMYv{B@uzP5T>8}0}<8Mz-@J{yp=OE!h& zYbkuR4Z@)N8~W3`u;|LZ3w>mh{Q3J(+arzB-nW6T*$#2>i@+Z#1mF_c`}{O{W1SX+ zgbb=`?v1YgC?{5EN^AVboV9%I{(())DOuvhVu&ZU3Ou=3r$&%F~h{37P;9PXClGsH?Gz z@1OE-y%;?HGrV{|#u;@!LevpFByelEDie%)7yzO(!&pzD<=yGzv}L2yUtTirGgM&s zkQ01qG@S{zQ9EGbX`KZm5`6tbJFAc1!H37iEr2Xrnb%$m-99&DP`xv_Ys*TA600sg zoX-e4RtsZjpl;7P zWzBepH^Kg%Awk)SX-2kw46c7@Xl2NE5SRnl%}T5@lo!$p2t+m8wnluR3TM~6YWIpkCoxk^& z+=6e*Trp4H;EK>mO+EALOgy4Np3jt%CJ)yvRWioLU5-Eq1JnVU~)VoH}FzaueO0bq}$SpP8>VZVWTlJHX< zH3O%i+HB4~Oz}+W_K?Z2eDzgjC+{E@Eiikf1J-eNGe|+52XiXjg`XekS&BQ^<-in- zujZ)$<$|h#`ukmF8ciw(0x)pDengbfs;_**ec;nmBo7P;a3ds)4*tAI zNYcO#+c}uk2rQ@d>-!|uht>#)T_k8gYA+FCC`k!)D(pX1LUcg3ovCjReDT=C;WPN= z9Y?lo9WGvCmEjQH-PN89b#}GkkjY*8R3lA$9)R(rWMp1J8XlBs6;q{-ms;1Zq6pqb z0z%SoI=gV4^9%VugROv`--KFq^*Mk7p#Zo5#~;W^tQ&(SHWtFXQJv|hCh zv22oUD8hbin^q%o$YQW^INx~^+1U-)E|p%B`Lx%idi5+FAe5YYx22SSi&Y3-BzCUfc{rWX*W#3RxBcUs$5a1`pN?=`H)GqvW{}+!!1gM zcIn2pD|FuG#m*Qh;P~Y;kRV5EdV+Fp5Pj>d&w?gkF`7-}qxSbpdp%w%W2GZg)6%|M zxp=}k0zFnEd#U z_XepZhuK>u%=A2#92*!c2&Pk|(q1Riw4CX+p!3)0eRuorVqMU}q$7LMzQaAkfZl6n z<-rYw2mwE_m+&dNuf=?PcxdJM;{p5B>1YAj&qlYIdzPDlAq=qb z#_Ftzi;9H~7Mt0(yr%F9{9~&S<;7zGMthk46NZin@Al zHwT^FkHS!;9Le;QG#pV94PXH*f958bPl!w{PCm)zqL(bsGjy}yeqe8<*VM@#DR~%( zvFsa6G4MU?IO#zyOr>Y4bROWLFI<{4mRdb0Sq0{uKE?EP`NN~^PBh~`-d#~J382LE zi8o!}gGCI!k0L|7=V^t#%eZjU<%!|6`3@BeZE z`eMI~O2mU{CaP};l*jzi?^X{{QM#0fONdX!X61i#zCLh4ENX0*0ehH5h$Q#)B_2gv zs}%3(xGu(814>Ajs=6vHpyMG0`vb%7gzPmeMnF&2(oBmx ziibFmx4U(Vt?n zi%l470@Q>~_DGUe-tz^i2ePR7eCLH^ZSly$v!;XNj=j? z1TbaDswqDhBilJ1bf^>NvSQ3WmKExoL&R&y(w&{#3H4Ukl_x#VA_%>0ulX!|Y$m$g-L34>}V)WN34tCg|(J!Zm z1RjAzw!dE6Lg$@D`@gowmuIB6>n+X0WBIG6-{0E73M$pV>`oSfd77nYC08#whr&yS z-=OtzI#I^L#8&9P3W9p+eE>AVvD|KP&jVezu6hlubQJrdw>ce2UjP^j{a^v0e^32a zY4j&IOjXPAy?fWsW9P0_v7f#Bxc_z1)Bh!OI*~N}$v3YK$g|HJtl@4YEf%^vmeMLo z;r_6Gn3}hH2-X}G2+L_%SX|75KX-3^n}%NrH-lMPXmPAweP<;j{0zN?cK@PUFrsg> zEcgj4%HgH_c%`?17xn z38;NJhw^ayM^O#Wk7*5tt$-C2@O_1LH}M|kM6vDb$_x_)R%er?P?+yM%?>7jv}xH- z`H>JS50)jzi6K2^<~qWrt& z8+D{H3urGQVLc{=hzN8|IO;MR&3g+bhXPRgCJ~Nb1<|UgL0`CiID4r}3&baBW4o-+ z!2q#iEP1tgODXQj=|hRU!Nq0@vW+r%hQE2W%H_^$tF$D*JM@oD!bXi`QD^jhOS-?6 zSNJVUYWhX)!ItU7OahIE@eBn9#{nSn2aRtPGy;i zA--o(P|W(ut{n3vVwU`0YzWMRIJ~8lrxRzjI>2`S26x`^2DhJp{em!`W z*hHM)1K}rLVB?~#-Q2;62GC*?IpIaK6?|BhmFNVxAz%Z3QI+S)?+P=oHqy3E8KzEH zCT`Vh_5x6H=ViO;{s_d5@+z4$x`j~>5>-QZI=0KPt%;KUg(8d zh2I@`hQG7*+G>QSMjUtDK9NUXG2pM|LR;BM%8Wh~j(J2QT;&r6W}dnt<#i_jZBd(t6xsea;LQkzLu5ecWM`aWACv6Jt2|Wo5!aN1ZzZ?ueJd zCP$XhVjC7{;ie$7w(tl`tffK3g2Yhoz6ER|4VNd9|CSmE+i!nvnYZ(~LRY1Sky&kh zLQb!Kip=x!)e%@m_m${Oo&bBEto?EB7X~sm;1?vSm~!92yy1Ni1uPpwhFQ{jA;7TH zc4nB;B~JCW3F1xsgW)=s``~r6^7xIP_pc33$_F0FdImK}w=Tm4LRJwpiioEF6Mezk zz?(j#lr|Kt{N8t=#d6|EJm|sh#N`7l;|3k4-8+wYn_MBz7wo4C=MJ3f!UkAV8T;(x zb5M$pR6jM8p!x6SA@CupULd{j2jpr-YKRuV&%fFQ5&eEQ6a#c$$%k!~%+!Fk0r{FF zI5z!#u8}POs4$QCN?h&4iXQ zXV1HN$nNS!nlR`{p&`k7@zv+nx>wCwY53)+ZR`FQv{gI*>g;)=v*!w-@lTw|WU)3= zs!zC*@xWu=E1`gyo0{~uc15_|bw_32>XBH5jebz60dB11yarbPewg#VgDS7zE5u6c z+hD1Jwi#|_QME*jBVmG8F}A^6r;959x|Yx`cuO4!#vTP!TI&ZndrnN3uD7o!0K^z8 z&C-TpE)2lNor{Rr!{mXxcG$bzFtWEk2Ta=_;)yrh8_0z)HR(@$d|_*a)Ox1&)g&wf z!hYvq^(hJP=CH5R;SsZ<@|@VFgwmpS8}Zk^P=b^v1sb=s3xM&Ix_9e7`)?x;qE(k49XKnvTEe$>8ZB0~tETn?v~Sq^nv* zSp@*DK*$a21F@Vg?Xs!wd$&h&!SMw)_?J|_Ro~NM8u1~1NYekn04Jz1UpLLBlyLz& zaxd^9F#)&Ca@VGYw|J81Q&@iVXM&w3pFivW+x5RgVUz&q*2Mzr47WEaYHlJW?-|y? z@}MMq%h>8hz_2L1B_PA`COLD*ab%y@by0wrL^9AqOlXaqA^hUwjD~NtdK1r4T)se% zREXXTH*2)83okM%AO6H@XPXzdwz0iav(VSk6-R(xLU|YJ0`)q!%WxAGeNB$m=hvKe zSXY~lM2D|X`HO)INovsOu4y(nZ*|rZ%-;ZaWo+KLtIp>0LZzf35uh1Wl&890j8yX) z#{RQntS{sHl9unI=;!~D{@-PTvm7VXwmmlnvb5#4ol&rK4@Tn-E0m&+R##UQp5AL| z5dR=g=PNgYZTclOWHs=#_=#EsBJ^SdynVAHge<>=ng81RAZ09)R3KR7 z%^%11M^e{CXF33b0BQW`XIKZYOWf=IYmnc%C~`#&TjF5qcQJc%q+7wQ87w z)IFYY$|u(;=l#?|$w(&8rF8nNK|dF^-3;@W{QS(6;s1iWSIC6{YW}3l;I=y;8Z_<| zF}d&c_f^jBjclK~RcJC-_Eif%gpOC;6rBc>k%l#RUX$@}Y<{kuZ9E^IpKWy9etRvO zPMHu)_Nvy2ty}3o#U<915%S3l`&9rzt=OEA#dbzo?LBnip?nWDzI=|;!f4q`ugVQMy>Y5vJu<+{ZS9jMyB5Wd7T&CkIQ z;O{Vcs@tHa1O;ijV=t-NbQy>`ka~LulhuM7Sy znGa}tixar0k`h)nv9r&!ZI_Mlk&Qiwn8^3Abg4|CHlr_b-QdDVwzhX^`lG?>&sGoI zzh*3jEO*R|S+LH6h90B^T?AVE^YF5H^7V1FnkF*anR?YDaYe~|M=zbBdX9nPew4?p z-S6Y4Sm}rG&vf4ax)yxP?Dd?E#o|WBWYnNDZRy|j^w%%1zsU_%RNvcp&o`|99N>vX zPSYJ^kW)at!tYp^|H}rC3_rHOQyPDGU;6ZtMe_AZA+P010L!!6*K^#>d2f^=Z&;{& zQp(Vi^&+Hk%X@);KKw5j4KUnOTXY?X!hcy9N&+%jVt3SlHA8L2<=<55Kmne)E%zo@ zz2+CK8g3PcKtunqRtxN@$(!%|-)rCTN$Q6AR*m3{m`I7`+cuN`y@~@&7!(MC`~9Hk zm%GqmZiLPK5mQnmqcWE*H6aU?6+fh$Uz#2FFWZl(w7D^oo?vmdKvTTp8^9DnFjQ#1q8h*Kdz#j%)BCv$86B?eV;g`Cvf5y zq@MWagPQcdKb#dp3&&SHwyB76yp2AliVx7sk1i_9^5*oH+~e;qRBdC3{uLv8Wr|_w zyvgFJDV191eRW;H#UJDkIHHW&U6aW1dw$xEg8{THK<1Gj{|)os6Uc^sB){A`rSGJ= ztSKjS-HlfAoP+PV^Xjk8^M1J3W|Dt(rBLu+^FP9VE?R{m(JgjFd2#O&lOqqHA937WXw@T7@KYNDjj>h|Y7jB%_dPnnya_iUbFGV+Qvj(xoa(Q8e@&v+i zHr#cQ@`k23M_!_4{SZiEbR~|4Q#I$f+keD0QGFjefHV`Fs9P7=#L~}K_#k3LiY{`} z06(wWMb_LQQlk|-Idad#H(+FUsW>BxC)_VE%MI~k0vlaoR*e_E*39W2!imxSs20LW}5ePA1K$* zQp>*2u?3t*KC3PjIX@4sYM{`Pui0IP`u*^$cm&3XV@5pnnjTT>1w{Y^qwp%ZA&pqx z5uCb}%NIG8-vq`A#^2*qtT*txU5@pl>ydom;%!xV0MhsJEPxpC zgDFI2uHvHYX#6lY*r$wlL1g{I=h{bAad9F@B*fhju5ZC9R~UJbT>9I6+$=o!ex?wjWr1Wj(2300a=M8%+=McNOTCs z%hjHtp^4C8Kn4GUtcASj2m7H%>+rM6Yd))^LY156+tqIsNcljbUCWEcb@kl(ZGS!m zc{L^Q16|S7J5z`0;-WEHTpIe8@>$h>bS`_-eCy4#M0J$4^hwi*_X2}}5y8dJBT>IR zmk2kp)B?cV) z>W*Nd!mMeYU%F)N-ls7tf4A;t8mLs(m+|3i4k`YH!zgK=5e{pcG>f7e!g?k?-e3q$fF3ldf@cHH`#y73Lxy8X(!riN(PG~{nLipbur zXnF}F%l7AOKJJ0QG0WgJN*YRzA5vz80~wWX(i*HmSc|28`2QUe+vfxV@?LsxJ(Ih)vB zgNpwe_RPpamX2uGwtkT#&QdG?InyY2eb^IKF}yC_ALkp|ly@;afA*1ik@4^CZ8)Dt znNlc=w2ExGXOxUAP<`51!-q?CH48zHR~+-*aDiZmSzJ3>rRGA`cFMWDTD5g`c_<9p96SjB{}B3b9J^qd34WlYM!fo&H96}`$KUe z@i*5fSN9kZs28Dg(}?L63kyr5DokLu=j>OUGr-Fvx!YCN}=I z@+b2|_x{2Bz8rhA8mw{6NXGwfXmv8OPF~Di)}^E?jqiioV5#nWZ<3ys7~~8APp^pD zSPm^Njt(#gQt=Gp2E_4|6ArR01Qw)<-fXr8(NmDNc zKnv>4J$oU#-r+u<3;xO4ohPW5F(i7H+Q$897HCp;NDq3*jSEPj_kS9My5B%uXeY9M zXJd0pBIhu|-Zs6tr(vY{^#&EHZ6S(=^PCk9&K=5N^=ZvU(mYe#$Im1j-osy>~z%B;R&KV<~zoSt((`+f#v_B z4^Ut5cOvS(Z0V`O)OZpRpEn;);F+icFFpAmpp&50CnfJ-aO@1HAC)E#&jPHMewa*b zUOL4_lot4(Ps>>A!w;6muRfHxbshxxwB+G6V7l^u08es5M;d1zae19C0Mjp?M#Sg- z;O&sdt3t?yjNHf)5BbvkQ(khR@)E&f^tqRhb5W2lm?$Xb%f0M#Iu|qm6Mq^l)69aC z9{iEXdK`W$+0*B_%jxv>T&J!obt^;=PO{@!$4_g8`MC9+|CRwkVA&sbmx|?0fA9=# zUPrRof4Jd`UcNf@kUBydi#q`Nz5Qmw9k;M+A3QsL-jWRXIq5A^i$ckL**?W;;WdC2 zXg9LeaaQK-7R%fQ#F!WC@PJPXqTJn%CU+{cUN1Bvg4Y}T{ zwklT`VRyQHe0Uoegnwucl5=IjcYoeV>Q5R;X%0No2OIRMOE81SgHNDIApTsx{|=h)6f4W^M@J`ehQ?J(A~gx+Ba1{-0*9K zSUNewmN}@+=`vAgQ}D1cNMQ{$!6*Owl;zF?G$>O;&6<8@W?T%a z?r53h^DC#89qEbM6No!l>=I`sN-zhqs}GvS#3sdm9xoUmU7SPk-%U(nId1*aujE{% z_IX7#hXT?bdTYjyx$R>#jQuCd=SKGEO>Yrt{zOzA>FmGNv?GR%MgslrZ2?Dvem%tE zWJXzuWYcQRQTB8rj=Z*=`gOzP&(sx9ct%kIYK=x)3SS?GG58CKs*2nrkn`5n6V zj4F9)N=U5K3WLi3+$tIslHeCh*k;Ys_H)?R>iU22xXHeJa8wPL_}OH zsx(f|`9_zf(1RYsk~`4ZYKz+&P5f+pg`%ODjQf|YA;ylV6i0n=#2m!QbEeeF~6 z>^48selqIEBoluA(Do_&bknj>CRsPhEWGiHxiX@D)-m+#O&+JAJzuYyZVf9rK4Dxb z6NlGLw)9$)FW#(t#H@C$o@ejvU1aT)m6AJa-NLV$_)Er2?qxi<6)#VMuDqGtIeR88 zj(5oF&MFf9oIb*6USqb@XhV6<+*^-pohh{(#Ih>l7V7@+;MN^&m!VIxg1s@sjnL!P zp?#mp7AsmGVVX_X|-tX zVom$Pr7ZBPlH8YKT|ZxG$>JO$|9Ky4@^9W)DX3z-LpWtX=a)J^XnM`?>eDJa{j7WA z12U`kbsWy}xJ3)ycB=D#cdNiXEpVJeown-cs=@z!0b=Ho`2%Qcqewqy5VHIT;EX&3k-j_4tLk=5+0-sJBDcp~s|+?#7$Ov{2csP9N-j%^b>^1xPUAkWu(z>+7!yw?`GiI*Xna`O^2ZyKq3f}_LKXSRW-gBNn6C?s?hb2vUuuqu#XopAnemF5l z%`}I;hUM7!i@rqK@^Hvtv+eSuYeNfX^6$wh~}USb3tOY)Kgo$ z!lW_|uh3b}QN0JAd!jDs(8NR#vsXB7#@R9!WU;+=YC%8~JM^Oy^tysXK%+iBZ~Oe1 z7O-i=?}x&|c`I!iwA2#+7C8)K~c{y-go>KZ8bR zikuTWNA!oL^g0D-XjnPK-l)A3H-hXCC;XqTN>Wu*EbAG0ZD#QG)rk^)%TrzW0Z?Ce zI0C1Rk}!W<{({C&6=DIftAD3O4+&3yu0;i#?gljM9j_tFeK(s2r-w`$-CKZ?W7pa; zxzE26#yn;X4vglVs-omsX8Lps_ya@0?{ECBfIBmE*@2YrLnGej(~Cw`T$DQx z8To^UM0B0b3zfI}|DKLyj=EZg>(uNDN)SIySX*Uw-zpG{sc%1BPxz^aaFjKYO~Z)m zZAodexaNrGNYmDTYt2WI^-`34@Mc7;_)h-mnsW^X98ZL++mh%e;7l}{H~v{!z7v49`_e9zM_fJ})M_mpDSwifBKF4D>`PvEw= z-T6QKuH_aCmzvmPn~8NemE>X~YkSu%Boc{&_@m8H>1><|A*Q3&uTJ;4f9?WGpmC#> zlDJx>vh}5fvd33#ZY1zHl~?$_2P$B??F^@KSlWL}yhHS*f!||DbnA+fEIy1x+SOEB znOJN!s}f!nGe}f_TGgn1@#^g~PdO_4Pa6ZA)GBHdJgEc4A8{hm$4!kX{$8x+=JM!T zke0bt;!;L=)#!Gf+J4x?_9^cb09yuo@?^>UsDj-wca?<&-LaHm%IvkS5kib>b~s zbELV>Qy}Ar^q5V7pv3<{@!Wgd`B>Ke1Rs9TXEC+ArP(5?C6OrlQ3b!ww-J!UVa10` z*;~gJfWWO9I&a^eU#8A9bys<1r$e?Zuv6G>pQAIL8}D9ctvzI#2?EI@W}5Q_!3NIb zO~x6;F>{u(6TU6r<{4U%2M_+u1U5TOUoE*Xv)4sw+RjsVA6ND)5WAZ*kHBFisGy+0 zK)eQdp~Oj6*w7Jy~1BBcod|Q92Pt1WgeLgupol*-v&=UJHjY!1*jN zWW?tsA z8NEdC_pl7{iUh~KxCd1O)!tA%`)E+Av{d+B`j6_`S3P6tqd8Uhpuir*Utd6f>V&`q zN0N}vP_4iUR;BZcNVJmJPNqN-;o))$GLu+Qvlfh6nZ!>xDM}Orag^QL1{D3W)=pzW z*a!*KLh*m-bN}SLhiuo@1Bf8rv93lT%j*F_-wojx9TyhY-Hmu(>65q1tnogP_p&Yn z&5&Dh_?9{Xh~(?Sj))<4$tskw9605Jff92Td^xG%bBHPj2S@R5Zy~K4d>-SizSiYZ zdU{+-w|ENn+K1IOHH&R$V(ys`c&5lW7k)z{g_sdD9ge#n-+xxl07H|1jkoq<-O$Ei-{9J1e)%4wXZ^jBNjV={a}eUa zL4uz@#2DbUVO&0GPo^_Yu9}LHVle1qh4c$!p{<-|Hrz@G1>B(RhRZ56NqVpf_TBdB zhp_$WT!#RKmsaTmTeFOe$tB+VapECsUpfKHm`9hkk+YOZ=I?K_`GB4;Q$@Oqg@bLb%}D?P)*ZF@D0}?(0;Fvn9T48A}%TE?3>w3>O$6SJ|%b zF4yExKK5lPSUhvWw}u0+DGdMUzGUMmG!ya-%^uegHze4f9M8353*Knx&M14YF&z zPf1DHneAd7@vf7P^C8aF4;AyTp1-kg?A%#>mID6NJoR~6k@)MNkHFX?Jh3lma!Y0@ z?01!)heD?(X1|C1@8LErx&aSTaL-|2;HYIdD4fZToOJnl&IkR)MAPWDP6u$0%{fwusZeYIj04y^~W zwiFt$9Y}j#@h{PKx4}F4KIYNJ_+xSmg02Qcy*|?hR*h)wFYrfXWZYpc*xI9XKMOe_>^dgOYhfw;J_jvuNX40NVys$YgrY-BwODl@B_dJlKBIcVlNNjS^(ZH19xe~Ukc z6SQq@iW5cW9AtSOlmU_1leBM+Qqw#AgpJzr_~bFus8O4qw#O!Yt&Sy*a{-frSC za?Sh){EU%%#{1EVF&c4WjSi;JoM@s48+Vw zK6LXeQ{?FM=Qg;4q(V6`z+Q8m6{$LxeoOPRk*UWc{X=>J>%) zArIYOKd?J}b)WUq52r`C*F~evC_W|FTI`0R@6W;BJwCCVZ`(io43uSRTR%FXO1S&F zI-Okt1~1#0JddO2d*&l#KobJuEPDYF+7}#pY4%-K+F$V^6I4D zys!_=&e@}Er&5EE4@+NVI%+rm{^@AW+y1AI2#>&RG+Vk~+ZkG}Y5rc3pkT>dC3v0rWJwSg2AWsG+I1iD>1=k1z4>JZGn*rP-hyw>v{)pj?=?2NPpX40 z<)U3*p%ui{;N9&%a9E_l9`wXGX+zfT`!f%*99es==KZg)KNvXf9~ANIn&zr0d0_ET zbHX?=HHsaeA0;2eIEirEjRMKDNHk@Ds?oXu7%bIT*oU9Q`OHb_whcoq?<{>dxOg|~ zGJ0&Omfjnx;4OPAkl;7gfHIGBt!X)_wT5xMrGGnK<5ndjBNM{_-tHUIKWEn}20dPH zfCrPhvs8pLC96W?*W~IHh8jo>`%JH<`V^HIG=#XCT;dw`1Ew~smt%*)y3msQxGC(m z%Q9t5MRwAgQ=TyY?O^BZ!8hrz{WUfEbYo{u8fQ2&_vOZ{iU;Hc3yH{72P^GvD;8hM zm^j)dk88)TS>?=sERVA(t9XFi2yM15w>5d=q+u1o)t<$Q(SSjo$_6i)H}f%z4J11A z@d#%YYwHmfB(XT$NJAgC@6e8Y@~s1f?@88t%*$t8)l9-ytu#b-CUBd?ziMW>Ee;d& zCtfG+7E*i#z6-rNWhT&vSuRT{l7H0JL{01n%M86e!i(RLZwKjq)4;;J(y^9ecXowF zT+VpfrN0m&!lLk*qWCU(H994obqN>dxyRpCxAr=`k3yK+9!x`pzJLp!$ozsl_LI1O z{`L_WZ8Qd#WxT0T4VZa`u?X$wxw!cKa(o{7ngw~gDCvSJx34Yv`QT=I~z(SF06F4*hk_!I{#!^2xBd!b}K8+2yut z`EC+UuFnLLBQl{kN1JDtODM@HnMuKVUGY!In6|SV{Un?F`yThuGBa@E;8=A>n3B%dY7K!>bmf}Ut)>is`Os4fkmiyhJ4^P zf*eVouYG*IXp~`|v|1g*x&baKP*AlB|2YO}4i#T#`(65ML5U6)(yk4%GwPvrW)^1_ z+is7++>8xvd02PT!9~dc%dydfCI&7NnOZmR2{}3Y2+bktlvh=|>U0Er>35%7W`;j0 zvHZPqHFdbFprqT>-PAoA4p!cmtX)4KzcR<94)O7R z*on0VCtpaiyD+lxW{Vv}M+zNc8T#CQGzDrN5M4`Pydb>(kZdUq?3LWz!En1VyHMZ; zOuh(U3=~RQnw??9)pfjO$=LBkScW}{YDrbH`%>1F&*2r$f~YzEIT@Ny zCyl=luvKwT5KaphG-W&BEd|`7y6_UM#tRk}T#80L{lmXEC0@fAmTy} zGgfqs8KMxb3)GU(;SMd0g!J`>Jn{t7IH869pG?)6!)Y)NW~}ic2HLs`?Tirlg%fo# zP%CWOI9SDDWx&&*`T_wESt4r7Dg$=B9`b^$1v%QSc#8R2Mo^sT1=Wl0$9=1-xmqZN zv4i&53HsNmT&NVAn7w+sH(7u$Sit#?zOiz_PO@7<5tY{Ey=FqmK@r*EHHtCgVlgIU z7V>)gPZl8^7+=3LbIE$UMAHwA_4a|%7w5&A;q6~Ykk8d?4E{sE7Dab{Dv*-R6p!A9 z+MCmzpQ&b#yHD?m;Ol;GkUM5^@-}I!b2B_7q3AO%K0I~ z;K>7z{R&LW*<_^OvTb}{YuS_@%SZbKN@8JlfX=tVu<_>$=z6W_^v*2vl~(5p#Jg+y zDoOS=SZ{I=Fvr%t#TiI*uHa_m=!%S(ObgeLpOA!pSH(*qVtn3a4_vKR(`YvIaj1F4vFlAUcJ5WJRc(Y!p- zuPPV!GRkGM&#Va7Z+(9o%(?gK*E3=#-@PI5`N|PbiH=%K)RZ^NAiZD0o9el*BB=`B zKGnNpck-MH)*kuI9!>{*zg3E$b*kqHW$7;P^Ew%0CpSL-B{K~okoHi)35}Zqx_6?kYPF2aL|+G=`Yb|Mh|>!1h2%;0->RDK0Xz; zKa9^dT|9HZmy3e#RWWimtju(_ZY`AyC-31VLbEs44l~K)^2~24I%Ue8nM9vY;XR|p=BV^GNnYnMZ`WmGh7bb&mru>>SPoyJh&17iG#Mzf$HhZoneH&`G+qWU+hG@|l zmi&BtZ-k)c0SoIXMrhW4W9{i!XbdReilX@M_lkoJpF1 zUno4pvv-mXwBfl^!WcE*qQ|1<<63nqkM@lHXzi?l{gq3NPxCRK@@hdG9KhaZaBZ!E zg_TuWRsnalHviM-m?PZ8(TuUy!YCVSnQnBp9~8kDA`@;JIk?$VokeJdHVt-2K_(e_ zR#ols69eNb87sRXQ*Fx^TVVy!tj$*o+;S|Y4f|3GHp}PbR*XoDl^?1}BSC5w1RKwg zA&!MamXIsY^eYz#nNzgB$$FqABdCdm0~@VKLF&^_(KwOt{yyeLTI|#lO3PufWy%2D zAQ--NyXBb0HWZiTDYFtXKg4bBaovCVFE~e*JYT0W741t){U)Y+FPeY;W@B~FKSc<$@Y)^Jo zHPNlL8Z-IUcm`W{Mq~h64?pv?i?8Kfm3?{-!B6Znc%#z);^P_fM^(_Nlfw5L6MxYe zd(94g>6KDR56-u=chXKYAG!3_=`6|ooNjy{(rtKagJ5q=TWaaZZHju3G)5twWEGiN zt6r4~`nw-JNY7S0p^!}c-~xp*!6|QDtBE%(S&PF--k-;Mw0>53lausTU{|H_7b}vb zvwYiocs)?25UGHfZx`5{wx2pxt50;)&YT_X0yFUJwkG-AW4o}u*{7le?fa*Aw}df{ z%+W}jT!7yksIP8wR>#^3jTRHbv32(MGA=9}?J|5S{&U7-C)yFU_ z?;ka;Ym0?D)19%O7Uy)c-5-;aCHnHb{9utC3;TQ6lLMcc>g7n79KrKM-m*UP2Q%Hk zvMR=XPlP*}*UU@OdII{`%|5JBY4(qvanbm3_%0F_p$yznN|NXk3y-1`uIJ9hs7Jux zd>)xMsA^sOp^yV#DU~%ZH`C}4jB!eLm8{ZrQ8Mw!s1uvlH!u@iBAt770u`JNI_G@C zhOfr2htb6XFVenTEpQ$;QoDpW7^JZ+xY#^%<*n+D<^I>GVbIG|lf5&^rK(?{T!ye^ zw16<|_3u)_6ti~+7ixI)ER5?^UC2YirgW1FyR2sr4FR=+y33$2XXKFJoVL_QmQaje|yF^!Zx_0k1E9z zyUCfVai!qL#H;=%d)s~8=I+5)lS-&?&`QF1j9zMDwXjw=EaH?d$cy zeuG3$F2KIBPF@JXGs{C?vky;5ee|zwYL0T@dyH|n3*P3)u(cT+J;>!SWcuk3#|H!$S)0FVb2~CQ^)a8bVbOqD zeS`w*qGRNi&&9r}!#r7nHjyAn>ZH-$7D0YWc!w~69Td5J#BrTVPV=_uCw>GcylG@k zna%`!Guxl=c|G3Tun497WIPOJMTkm}Butw+&BCcph? zg{&wC*V4-sIsT6en`5xggPhvs_D%^Pk6jL*C%AI&sdeq2=Y$ZThSj?#I0kLXc>yr| zYwoc9)!l4#SkYJLoekAa&t*RXr(2XJ8&nx$`x;y-D(qHw)dYI7N9gS{u~R^G zPH+r`m~6-;gi?lbiPt5%>B-tIzQuC>tpQ zPC5sLXKk#i4Zei50;Ur1M@?8|z)r6H6FYJi{#dqOiG)OKt=0556V|Xbp&7tR-J4>q zm5A7Qq?f4p%)kdNYfERN%g3C}fi_?7f5K>%m%qmMytxPE|7C-Jv3HTIzQ`=Y@hr5S zK!|O`r}vh_v-WE)`^a`ZPd^HrNgdKDX$jMphdXxDVLyObyyYUZTmp4I$X*Rt?8y`MCF znCVGPPrklX5KXGej90;++7F+&aLXVK`_nnD)t`BSl}KG!PVE7K3uc4Xt<>^dZY8yj zO-q_$X%`d%xN$oe{zch>%Vl8D+h<2`A@A zlTmelUknetXcSu{#g{+0vyL;IPHuQmFFK!E+}=_7;4hi|jJ)K+7z262y+Y(;PktW; z8xk-iRxzi~e*E^48lm+8F`E_vnR-_(uj-yL4YObu>ffUmJaUZGzDP5q76JG8f*=dP zXURE;y{HC(oUoNKSs5AE4~0j_IrH)nxa&hbz);m=)kH3{^yrTKRPlVtT&9Mm;O65l zSe~f?Bzg;fV~T6l{to@iH$C)IlgmA?YNt@YLD+5~`n&*oW+}HYkE+pUXCShltHZmM zKMl^tZ8iqk*RRyHy^T9el4Wj&k^{1m69y3(0bU!8tbokenaSC z@n;BY_riHSaD)rRn-xtMkVlXUafH7c4K;U#%Wp>f(_QAxUUlVY)XIQOhyCn!m=3#1 zcVB3fi>JVVq`f2TEbhBV$wxmW+ytoZfi2n_4$mXm<|)41dCg`gi0(#zH|!keWspDV zy6@E0P(w)BHsWYH-0xoGu5qkXTdy_lYAAEIhT8PI>6*dAFGfs8&>RhZmR%cfu0SnyRnrgq zJPHW%1Ck($N$zcSe@&KiG*62 zp_*hGdz_rdDH!5aG4IQ`tj?^_-qLrfgy6)$jzC7#I((fA`f~EC{AJdj-+EOwrKIcd z>5QTe{W*G&rgLOC=CQd}nN? z*XW{J?)CIA_2eXXirE{$nl5JET!InAp|B(38c_fYqoc%CeLiYjy^nW&saTDl^l|5# zgKvu&W_!OQqwQZ0c>40Miee-O@R%n(?4r^BqAT84py}04HHNfq`;!u6reOt_fPVRx z)y%H+A0=BzbxpeK;@7(SCp{V&OpmYTaMI5hd_KTTzE~Uzib*bRQCiA#r1=cmymC;~ zbNCf;U?6s~X%C-I#cayvP+Du;^hHc(E&YlHTSq4M7yT4y(CgA)9#stJEZR*U0uP=n z$poc8w(V;I0!vk}n_;f#Zy(TmP2XeK_Pf&i)RkIVieS(i0il~`NzTjNw*6B%aE+FC z&+dNqd)?qA`uUKk?X_hBo!n``DXEFvvr5Q`dFi>_*rQ_-cDpSHgJvJ)oVD25ZvI$Z z->|=2zf7LHXm$)izp(ySW8Np9^Cx3Yo3ha}+~oY-uib&-X_qQ?rZ7FPfpiwnu-d{s zCQ~o2c0-3>5QF6oBZD}WqxFL#2bYE@w$CJW(ARvfrcGt_i$zi(GWi2NWltj5ADje@ z!3?ZuDWhWY7zTY3GgjtQ}Jss@s z!>w|xdZH4)eSQ>=0#59?g>A`^ZUa!(kO48J)htFC53Iim2-Qo0yjL+#K zNmf~kXTMg77iU4be7cqT)Aoj{zRBvk3|z11Nzs+`v}-@`gJNHoE-@|M=e4$hxS)+$ zS}jB_KrA>{g0v6^1H{De;{H__91_;$ldd$BTC}ldQ55%{XPtf$D<4OHG>Xmjn}R?& z(geFV!nV+=Q;%*oMuGZ{R}y;aU;;km`VI1v)-WYkm+hYSy>qGGeJ=HIypJJ7hGoj* zzE-)DoB#If;qfX*9?jKhf{DF$iDnWI3`w_c>L?t=Asgy(o}C;rRXcg#B*?B;<-@Y5 z&Qkr0K2%4ha=?QIhM=#q6zH~S1qb>J+GKPLnyWlURjm zqxV<&bjqE_2Xy);b{9mU{jIkx`=fTvst=VYNu(x1-~VE3I+>zB5ihZ{awPp$^ZGoh<6Tdpu{vESP#L9npS?qw>msFHNGF)>;Wtv zDp{siT+hN-vM=uT5HFbFLaz2Q(rtfz+5ht|vtr4sk3|cqK2HylkPxnyG(Qc>2`<`S zonx4{vgtw`#>4C{Cr#ozjyjSr%z$G&a&I4PU%Cu7L13AbMQJa$V3nkR2lcRcu*Rdm zEb#kjd!Hz_f=kfO~LpWB81Q$W{tzW1J&6ckrtkTelT89`|wHj zR!|St(L!S|IKW%>=zOG!%HtnM_I*cO9VEfQ{x1}$3I+gp^6 z2wef3_XYDWhC}Z@#vG;riE>q}ZNkhJ7Bh=Fd9&OnocWgXqSrCYC;LZ;ljAD*!pzOx zkV(^Wvl0nmmsDl1qICtwrURl7oS-k;J9`K((N%6iEQqFKWbHA==?g~y8n2y|{<$bFZvTO63ZAY(+>fOjTlT4GygAavxAIXkhKp#~t~Y!woDJ@?!> zz{)Cme#wG`q;s;31}jnqhc<$jfH?_YOfRwf5_G(ln4FIMVZ_w1TbMO(%#ybeFs@?> z*>&219ldiBfCc8TZs_^{sotZ1uQ{1f@DFopNj2SC(BLhm=JmoWE?<2yiU&oKKXYG4 z!xx7Boueds3^&sv-@@n2BzkiLH&XL{3F2U%h3Ed>PN?S3R3#-z6PVD?p_x8tHi25! ze_l7uO>7mcMMVy>yG*H)ynVo$T8T_7axwQnRb$w|msij3Oh(Zhbvwf;XhhSV0QcXv zZGsAAU`nm0vvR+S0^iJ7I7ivDT*YwLiD)&S`NE4x1Dpe#bWIygqB=VL?i}@P8crP* zbGz2(fcK#MS|QPK_mV6y%Rz~(K%~y3;8;_ZUF1>i6e-*O2Kj^|^CJHo<6rGu_&%cG5nane|+ z%?ARa3g?%A+HErFg66wz*GE$JO07!;Jx7aNZHq^e64!bU+CJ%0-d;nM)%vP0|MnWu zz9Bs-`pIum16wHl=(0`XC8{fV#P#(0{B)i%cd(<@?~V)UsG1?s8=}HQgC`kM?=u41 zIfziHu`)?*NWCp6lVeIg--g6Tgnw2loHyr*i#eS$4?`8L@)5iNFip;MMQ{3E(?66BOim_`xa?i$5_}6 z&H_fWDnz=jE@pM%)qlij`@t+?hlpNe&y?UO9}>NKM@s^%huk2PeSy1+fIM^$X{PD#Ly_`*s1P@2g|40r+_w}G34OEr~&q%L_^r(|=Y3#l? z@E}f}xO%FFkQS=O8W2Z!eVU1gH1~IaDQIlDl`>UHfgg4T08YL0-wkq<3rtE3R=)USp2m1(his`iUG*iFqzc zBFaYJDDZ04$&{cFo2wc7!=YxBZGoVV7Qi!GRT;9A(!Uk8*$Ng#@Oj9M=wtd6tCoKG1HS~MS7Ju{0jE`G8FSP@4d%V9oo?)#;pRCmDjm9qWu;CC z7@nGj;`y?zDfVL`6koI(#}GbW!1xL4z0x#ws2Sc*4ntq%a>tAN;(X96nB(P~WgYv2 zL?CbI)|QJm(o@SMx#(z4=O!xy_b;lSqasS}DKiqe_9*LsV=AxV;&H*R1K5Z?MMfHe zK)R|No(RbWeK5x#L27qGPYOI4!=112O||D+_ClI0Lg8~Id^n#?_lbSiB1(e$GQL&E z)k{qhL1Hay-qiDH-QV!oVuZt9EPN?tIVM%fAwa$1n?y_TUTZ=8`ko1MwGTl}s>O&)pMyk7xDP1__6 z9z~;enodlMTi-KEdI=By`qnNw`-f8nu4|yYTU&u@BxjGU3?X*el#X^J6AP;lM;!8D z!LaHJpUqL8dK`Wa6kgKO=w1ab{s0W(gW+0!HOeWq-b`8^`8(5oW`GSX$Txd|^i7sz zfR^55wot@pW!_D|@kd4joN)%uaowMNXkM!579$lI5O5MiTLpPKZy32KIQN`Wa%dLFe zfCn-)=;C&Ad$?(%KDjAtE!)^eqzfmMRBUYM5VqvzF&dQhF^zajFgRr`0b*dT-2 ztn{Jr{-ff-a~4{DX5}g;Ttz)&0VOR2qEio)DG02!oL4TUZP#njtQ8dGSN|r?=m@3K zSa2vKD~tL(V0TiYpEU^N@28uq@$^IBuv9cFg}L8u7ud`q~|&Nz&51 ziRYwm$*=L4+0^Xe4jjU$%S`r@A0e}LkA%4oLTYsg%K0?`Wo#d(gSveIm4`S=819RSks6?Wh^T1xpj8~o_x{Mn^>3$ZdNr=-XC_Rb41R121>9PHfG%D9xkrV_7rAWVrPKdLzYS6t#N*t+i)z6CiW$0OC4M z!krj~9{1-M5p}qQ<3COawBZtq^G77h5S<_ww?$_H*?pJ$B;J+#uUdP*il_p5cwNt4 zJ~xg#4DHE?@b=AcGNyd9XW>$~mCCENb4U_fidO)S9UL?s_Z)4EWKQkS9{mW1j9Fl| zrImIDSj~{;yBTB6)(FY~YiBlsKYsS>O-G9vK5G0_#P_tV3rns?&8{cgWYk_Ie()Rj zv9K9t3zn_|Pv8~)P+Pm30u_>bk;QVnX&*0QpcP}FoHsv?V-8<1+5Zd}G_%EY-P~A{ z`ZfS*yGxJQ6dn&-ZK@3%*^SXx0`w}h$Gfr&-j8d%$tN_wj67!cq-{QtVU`gf++Kkl6BsN=+SdXhZsoK6m>4w9%mttV-c zhh$@!IZ0xnPG<73_3RXfgAi#eh0rWQA)8clgjQygg*k-H%&;fhY`*vAd;W&+b$x&P zT-WY>uKRw!@B4kf-uLJIdfm72^J#d$XATa^&uP@hzWBKSQ0vNYRXvf3xD-gDK+eAk zS@^4{dv<{Q{mGwaVsPI1HEYkk+K}^D$Elp>fS}$?k*{*+WDaZs#zUK)Nnp^ z`n}s2v+y@Gd#htNP42dq|4L@*8TWzXLOAL`(yT31p1$whPs`qfBV;Q%l2jVoEZqR;%9Z|cXGBA8NHn^y9XbmGyws*qS7nsY%bKG-L?XeAOf~&Nf34Yo%oIyj9qZ1O~7!0N<$UX=os)buD z{?3hB36l0$9nsk=%DFM}RYZVCB)T|6Nrl;V`UF)epemfPV<)f8q&sCi)!5M&@vOg? zC!G3m?O=iZ_b<0-VaK^G?Bfyx~_@-T3BvQi41)%`A>sl#Wy)A4~{qssP9beaSo}EuNYh{s9+6 zNgixT>c)gVB*++=3UH%unOY?m%={Apf^~@hI{v4chv6L)kpx*}{QS&s>Pd>GcFWkS zq8 zfuY6j$Kman6`+Gfm})lok9IgVzjg^c@n6!!Kd6-g3Uh9**3fMCeL;1zPiJS^I*;sF znmPiM#RO@RPtyspDLVm6d2xiGLQ92Q{PQ7M1B3-=2iVa+cSWB*eW(vjxaU*6`$t%l zV*IW|23fTC_?X!CNOZ9ihqSEQRY7ys;S(EJP1_&f zehE97_>C5YpL^7Oqo{)Qet%mDhSGQ_&CsIv@-h{+(}u!+a6licl$f;4v>7A`F|+`h z;x5fGKLu2pR`vH}sXu+LBXHeOsogAOaPUX2MtDH^0HWMCc!7bDj-=a7R-x5JhM+bJ zg=_Kp^UwjidnvHAd?WsR&8Tt=tzenw{WCv1nl$@1*ICg6Qwz{4sHAlnggJ=gk{JYz zL6b%)zyj?jNiIQduC$YLDWa5ajN~1n#J{|mVuCPLTV~fbjK7_u%h`Az5|dJ$kNQW5K7SMJTyDq3f=phD!mqZapK;sk;4$h zj3;)aX)Un+d}cluD;wBj?wsg{UKlBm4vk!FC z<(Xc);ym-2o3;K63Kf?^n{U;}GLP>11yq!83rrnZOX_XLYbGRxj0I`X+|vqHzeA+X zI7&e^v!fuir`=t4o>l4SHa}c0d25G-})~*U49%S%>08X-@u5m`GR>i70p&h|TqE}v4|mwu*zgZPluzB2t;>@7 zn(;nju{de|h>^A<%AVKg9;Pq!;aaO|7SMKiY(LRF15U&MbSs3msLxj%@BbFjh1b`i@FfhIThH@aHiyL*?V z?>@5+g&VmBhr=ara(yR9N%Pm-RgDaOmWGE%VOfF5J0z~Zi4V!0jCeURmNel)K*ptv zno1ap3OoLEv#7_II*lXY@TMuXc0P?_EdH{VdXt;`t`E5+ynX( zpHi1HzcqaJ4Yp6q{rITGy7aFl5df{6?g+=$2E<=7E@Ke7n2d~N47x8aa-F?B1 zzdtp=pq+xis$Y6Pa~E#@#|vIj*_gOjVCPO|Pd0)aIDEg6?xo-Y`oJn~%0U6!x*r#G z3nxpB4LjxkBwkd@9yLMDvk@!b+c_-Juzz|QRY^7`9&bT1yXMY!+fE|}26Fn51&PT{ zKfgLy`^>=W^!RaZ2tv(ozwOjehT7`AG_vGO zpM5LE>iDys$s!mzFlS4&<79Mou|EduQOm#Gc>}gthqM#gko9l`=T!iGqsiKc^BcBr z+7^7*EB_nfw$)2^i3O@6u{izhn?l!Uk-1*0?Ot7e|G#*+v~86Xt=A0y*BK>mqm09z zJ10pVgRN}4@TB(}KC>J<_oV~KtZW2aHqc!}&M4EiH8x(t^G}_=pcRUks!QMTJ)q~^ELLEu zNRAiPrGFJNn+VfsKzdhuSxi~uQTi`k6#HKJ_<834W~wt-7Gu2ntq!rUH&uuaFGMu ztcE>g9p%0|8<%l7r(Sk_Rl#aY-3mAtyo0{{YKGt5%~3u*RhBJHr(Dl6^QAkUBx{HFzLGUbG7ZOvamMs)zshpD+l@eC1Wen%^KMz_kR^L--aEU)&JM!g z^_oMNNY%6D6HE{7EW6an86O`HU~`@yL6Q=JFQK+(OQughQ}CmVzj%2rwFrIIzi_Qy zX2a%y<-8%RAlQ+<&;mxFV%n};GSBrhPIpOB^+=qT(hb%fRiJ-o2ZpR>THgu{r1UMG z;auMbD6_yjt?MK4cuf&_Ka+k3k{@6Gh*Q@YZ^C)XuHG2#WclZs_~Vws+&b%Dh=)6> zLu_E&?evAlM~i-xK1gB0Wk21y*QISm_NS@vDwL_m$B#RY%1>a7dksIWGV~0{D&d_i zDr2ys>nGTKeT)RE2Xsfc_m-#%c$K*WJtT&Vnm%jnFti!XUIViU?@C(du`Q~I`svJ0 zVhx)}N_gd$sq>EBCDf%zojQfyrxi=+_W$NVL-_W>r@o;wnl^LNgL(KItll4X BIO+fZ From 9e2868de00d3a8ebe96af26b3253ee58076b7bbb Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 19:22:57 -0400 Subject: [PATCH 159/241] Upload logo --- .github/assets/Logo_CakeWallet_Transparent.png | Bin 0 -> 140295 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .github/assets/Logo_CakeWallet_Transparent.png diff --git a/.github/assets/Logo_CakeWallet_Transparent.png b/.github/assets/Logo_CakeWallet_Transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..21f985eaa582e57730dc42acd43851d2dd227ab1 GIT binary patch literal 140295 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%0AZ5ru1LUBJfc`W$J|m%>2jG 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 From 55f6e8acb1814c2c47cdde8d33132d5bd686e5a4 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 19:26:00 -0400 Subject: [PATCH 161/241] Update --- ...keWallet_Transparent.png => Logo_CakeWallet.png} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/assets/{Logo_CakeWallet_Transparent.png => Logo_CakeWallet.png} (100%) diff --git a/.github/assets/Logo_CakeWallet_Transparent.png b/.github/assets/Logo_CakeWallet.png similarity index 100% rename from .github/assets/Logo_CakeWallet_Transparent.png rename to .github/assets/Logo_CakeWallet.png From ed4c6211fda0039540811061bcb607faf979d3fc Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 19:26:56 -0400 Subject: [PATCH 162/241] Upload --- .github/assets/Logo_CakeWallet2.png | Bin 0 -> 159969 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .github/assets/Logo_CakeWallet2.png diff --git a/.github/assets/Logo_CakeWallet2.png b/.github/assets/Logo_CakeWallet2.png new file mode 100644 index 0000000000000000000000000000000000000000..459a6b37cf2a93b7da5d11bfe23a0fd0fc31de46 GIT binary patch literal 159969 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%0AxcKM)XJNBVRNB^88&$)x{4-`k1P5Rgwn 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�s=xuIZ~)Oa(Zc#OpZAsH2`)So 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 F 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 CPow() literal 0 HcmV?d00001 From 6fbf49286e98f6027ac4973dc058e68d6d70c0f1 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 19:28:46 -0400 Subject: [PATCH 163/241] Update README.md --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 7aaa63653..b6d7a5a3c 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,9 @@

        -# Cake Wallet - -Cake Wallet is an open source, non-custodial, and private multi-currency crypto wallet. - ![devices](.github/assets/devices.png)
        From 2e2089a97a789b8500e90f6f8016a0102354a660 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 19:29:01 -0400 Subject: [PATCH 164/241] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b6d7a5a3c..970800dc6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
        - +
        From 458159ef59446ddb9a8cf6ccb92c953ae9c3c20d Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 19:32:55 -0400 Subject: [PATCH 165/241] Update README.md --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index 970800dc6..5a1c74b5a 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,21 @@
        +# Cake Wallet + +Cake Wallet is an open source, non-custodial, and private multi-currency crypto wallet for Android, iOS, macOS, and Linux. + +Cake Wallet includes support for several cryptocurrencies, including: +* Monero (XMR) +* Bitcoin (BTC) +* Ethereum (ETH) +* Litecoin (LTC) +* Bitcoin Cash (BCH) +* Polygon (MATIC) +* Solana (SOL) +* Nano (XNO) +* Haven (XHV) + ## Features ### App-Wide Features From d0d155bcc5db9e6d087ed78feb5ff10e75dbb55b Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 19:33:42 -0400 Subject: [PATCH 166/241] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5a1c74b5a..7823734fb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
        - +
        From 8fa0730c029ee1fbfd0466cf1a8815fa9807823f Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 19:34:23 -0400 Subject: [PATCH 167/241] Remove uneeded files --- .github/assets/Logo_CakeWallet2.png | Bin 159969 -> 0 bytes .github/assets/devices.svg | 56 ---------------------------- 2 files changed, 56 deletions(-) delete mode 100644 .github/assets/Logo_CakeWallet2.png delete mode 100644 .github/assets/devices.svg diff --git a/.github/assets/Logo_CakeWallet2.png b/.github/assets/Logo_CakeWallet2.png deleted file mode 100644 index 459a6b37cf2a93b7da5d11bfe23a0fd0fc31de46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 159969 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%0AxcKM)XJNBVRNB^88&$)x{4-`k1P5Rgwn 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�s=xuIZ~)Oa(Zc#OpZAsH2`)So zdQh+6+co2u+K*;L-L(vlH&NGjUuNrzN~vk5iAgzv2H^E1wnn6q4Mf+YWpoiCf~|gS z1a6%@5YOF}hwGUp?pPLfA7RX+x9nuV@Jlskxo~{>ViQC-ORW0rgj?OvN{Z!!L@wBs7prNf3#~N zUWtpuY^E*A4aFP{pB%zfp6Q8^h@Vx7eWn)Ucb^vEjHV{^Z!5eWn2A+l5Q>T0eFqOr zY$U2*7=>HM#9)(BpE_xVyiGXJE7i`G^NUw8BSHxoQ~!DDYkgEGJkHuSyCve=0j!xR znr@PCdAG{=Yu1>tLE4>w`xkx8duB=zmG3mbPcOz_KUl-GB`66&ri$8xy1EYR|L|@#&y&uaF3NUi^VyM@#-r(;&d8Xx2>Ef-5C#XaK?wT}lSc-D~@Sxh~XbS-_Y4+3r>pfmM6!+37ba&8cnA!r|F z8rd@yU(I8*t?wMpbXNFzU={8SV`;Bzv+%H6xVh~wo>V-F=$YZ9&p*tm!fsEl#2voN zI%h7Hx{cor#Ot&htT8h)IDvzWO4RSiLfBJ>o09@(7s?xwic0dZ=9^M}l*H&PM9xnuWg&)#d zH6h{tC3q^VB`o@`L71{R#iNCHh+$NOhdlLE^gKX=E%f~VM~oEG{EUvm>W{`^;`Ir5 zyrmu||ECZa6jU(HteTU7ZOx*K9yTSAXq2Cwg_jRc#ha%j;mg&k*T8d7Wz)zg-jl&mG(!bL8nPFMp>^v`!I*ZW<%48~f3D%$G!sYx}kkM?RN=(-@ilvNEE{ zSRr&^_6)pBCi4i^%<8ICVZvL%|En_G@XQ+g)y+PHvTtH5`rkL$-90AUO($o}Guzj; z0s)azrKOekZz?}#MiPtl#TftqAOJ~3K~&qoB97fpZ|?nza5TlMRNpC7xuCzU!ktVZ z{CQRsStS?Dk6=y12n~Dte;`NBv_ZZuR_SUJc0kZl8*8k43t(BKJr- zyt^Rtwvkkh$CNkc)5u>+T}`0ymhEA>M+ctevr{m0QGHm8oI}07x;7htsS}ZoB$zES z3MIZXk^~matcg*#tG>LBDB{G~cl>?O9Jgn{m>gxPgLRUJv z5*++y368mF0N#=OK9{qUZqf_Yko3g*bY&^dkQ;!vGp5K?03!}N+Pj!(y= zU6b%^b2ARRhf#UemDsDaJ`f3KaI1D_=cDHX(MQp&7?MGu{k$x^R2+_Xc8kaA3#ib~ zrt#N_q17Jq%Pv;aq#!ppK!>~iuVy#BB8xbWx% ze9!5*qvk%^3MW$$j8!XE(ITlzQ{`lkZr(>Q7!!?>7sg@Yc|T%CeKV_7>s4o8G}pDDaXd}NUV>F!>o<<_}}UXWYaUcn1LtNtRq_+ABjd8GgbSE^?DH- zFxp0t>lR3q5-NfJr|~$3aEf13AEsZk8k({DH|02V!gtt_DQgCkF>Lc6mSNM6X(!#_ zEf30|L}cH^w600?=yRJgHQA#(AgmuY`tm-}`lzURW-T5#bpU4X9gCHlX$`-VGO{b0 zc~|fri1@Y)cf7b3xA49S>n`U%z6J4Dr@M#TY94+$SjlOsul*7Na!fFzOWdI9zVTRc zK^CUGuo^e{PNB+$BRu|fXo)dkMlZooG_VU)06pIxk97pwNIB>ti`!O3zEPfK5b(&qm35>+U>!XzQ zp==TbTEbB_J{jLEDZsHkI=F%GJ)BWyzonTw*pa7&bWn49&vt|d;ZfKS(GO*t8jupy z7db&j@~lgXaLAME@rS>U!kuz}662x_XK&H5lr_bX!e`tV0Gv!q`ystb5uKp_vI4I$ zm}gA4k%I|8!ZBKMt(lq02@DL~DLV!eH=WF@uTS@dfT2ntUaqCkt}GT#WfVE}o;Col z{WBgnlvHDsZ|@@NBWMJkls6QE9vh3Bd8W(^*dgCU$rTBrrD2G@Y&l+7T#CJYOVfxL zyQkrk?W$`fx&p{mG!u+ zwT7Osp@fnX$oi#^X#{RT#C^;0cY2@ozkDF>w|hxQc{PK`U&xa`n1^0oA2u^eZ-$6G z5qaQ?hQwfM&aRmHw<5z(avIYiA2hq11hkQO*_{l*0;ZU39&AMxj*rK;6|s2#!=dxnpJ1kF4}5X!CC#5Q7OG6BY^cctK-PCSM-WQrFeE_(H7}FIOp}{ z*y)%Bc=PEAIQP;dK57>^{DSKq%tPKd5{!Nb)B`4-_Btc5wqN*la00$MX$bCqZ4K^r z!z_5PE#40y`oa&LP>|PzO#YTh7G#fWHsTuNWl@YAjYV!m99Df=kBxK&sG#s##cT-m zWcqX@TdBl|p)jaVG}BzBtgpvNCNdd)(2p3zC*sXCFxlpTZ6DFv)6Q5pTK_N_w~dQN zz8&Y3t!=EpHH&wR+sG$vaepck!@_Zf@4&4I5g*EGk#z#;@|Qc|)NxTL3bFq27vNW# z^5r}a*R82mrPVvud*bB(5k<>#=GS1tpN8RnDh;~C(^~@fH&r#jojmHw=h_ zquFL7XvL=$VQ1XF9FLaQQQq!OnZ*b%X6=hnl%-n(aH#2vgYD|;(v2V>8LEnW= zBK55pc=l3EnJtH0Khrew88-~Y-?gi5No2!C`1?yG9Vfc;W%b9gh1fKRJU z45Sz!8cZ-Qx|RPAGwz5M3FtP7fS4dD)09J=KYw^)Bz~A$j-*2eVvm+a9K!m8$COrK zmoN&v2D55frEI>(>e?(n*KRIav%H28hjqVWZP9_zn2{fbd3O!Oy35wL5lE$acEj*7 zEeF!%HK}^a4j6YuJ$zYpeyit(1ei`0BQ9Hr|FllPIhQ44W>?m2v%D8U zdQf;SoR$$-^?(IKH+vYQX$Eyzp|u3)n}^}CMfKQy;Rc-4V`*-CnqvOH8A)VGlD?_H zgm26<-x0(OYeu_|o;Ak`;e{Slq}bNr6h4j|f~nVJ;6GlxU-W(f&z`&#-H>~o;}a4v z_cIy#T^Me>SkqR=2pCB=(kbUmrVe_aSs1dqh!HkZDXpo;!8b3#BWudAd$+7hy@|p2 zOxGrE$0@IA%Dr}ZnxNr{j|X<*)VAev_KidCrGxSKJpy1c%5=*%hG-CeU>fTM+)tYTWW|1@^yb7;a^` zg>Q`7rfvXWan9mlWNcVajdLGgjYlf$F~HXjEu8D|nfUjxC={y{KyPh^T*;5*o?Z-w z&D(z_9dqA}L}j5LBM!YnQqqI0SS-6J4F#c=w?vEFMzXj8!X z-k0@%sqa}go6eoVBK@Kp%wC0af}Bh{ISK{umLEWk#W^sfUd9rPEqR`$(8pQ?^hEj~W+cJS3A!@7Wc5;Wsqx zn~%2;Fg?ShyL8%Qg!+9N{{3)3r3{ZawiX{>J_PsuCK=Bd zcX$Zqt8*;cMjiid7ca$A%%r)GZ}p>^C~4Nt8TgE4#lF@ayTK9djd*kE=V%ah-Q=80 zBXE_UW!SZ4*!#5kn0^`qq6R17Mc!uymKmA)+TojIP5ntVke>8*3SrxGmrDfFS~mM*ICwc%y#DuuHBsgxuw8Bigh>NG$W{C8 zlob0;MO%VX2{|%FoyGeW+??nS8*uXROl|a^9dQw9O}U*r+0D8{`qRn8lR-_t zXbrBMnuD9_8kx$xo5mTnHY0%w7KtT}4Zvh=oOgD!8Qrk244EJHJ&j5AAFdGnX?P<8{eK+legs0 z#YOn_L?1TIwJPG8^GuZKcF&dQ8LHB##v&Xo?=DbyZF z=fj(Z;BS+b;%{WW{LOxm)>qVEwi@^c6cK085f6nMsSux7yr%iVZ!z9V;bY$_QNhj__WBp&HMedT!P?qOUdd&>A zqaM%3^KydL*(UMT9moy;l+C_MwWjro9HwAAp zTD;dbGZOeG8i99W-v1QB)Uj2e8$!|a@){V4jSr5+1y?V|dn}BbX$hCQ;d=X~Y##y< z;b?kn4E}s*99DQC&>D^_WRS!ZdeP|pUfe$cOG?YJmt*4W#Y8$AL*A?#aniv}81Uj) zOk}<31qQDa3@L`g>aJ0A9BEqAbA>qTMn$B}<#4#>M%jUs~%m!*S2-QXI|=2)Qh08FuCxd7x^V5H}?oH^=wK zId#c+Ze)MFNe9x!hO*f5fLnji^w*Lhhmip3OtE#wi+Py1p%P<_!)%p_b~z76-2)D~ zw~oY}nSzaZ7JkpQannxC8to`Hh)0)yAY5uY@w@B#vo<+G`WUPXQFespzr zlcrq3N2h1t<#!5k&hipEZTMXfmNNzCJZn8pnAHzQAIVH~wNZG9CEGru!L!wj)^*BL zm^4lINhX2wpAsBDqYzhoCdXUzOD{GtSYwc09WfYFf6Xj1(qA)r)pZj}BzSb|Df=An z3jam`o6sWMl$oZe5_>*W!H?D-hx{;>3v37@Ip2i%^A|G1R0C+WVQUYcZQ%*Wq|taZ z3l4_yUNKO#XB&V$$g6kVAWV5H4;L5uxlp<5BNpTVh$F6W zn?>}xa-_dH0IB_&k-D}4Lw>Bqn0fUWK9|2oG$A#bbvbz`6F5i|KQ!kWSDAd8m<*dN zscLz$CRrovdp1U)bbEgG>W2-x$6@8z7_5!$hvEx1qU<;QQFMJes=ljf#ie+z$meSS?2oK83d^o6q*2IZpQZTn@ zdt5h>c)`;X?Q3PK58>D&r^Lf>^iWJWDj9EzvGjniH13o|6tatX-rOp13?pYa8qZF{ z$B&oN0Nf1(nf1ju@U&V?zi1fl;yv^X4dG3Kg;z~5C9|#cG|~Sp$EojZ#FcYPu)lH9 zcK7Ihu8pAT$GVY2xEjX>U@3sph%0hL=n7@9S9=|badhU*^x&%eDEmv)=;OFC0i zg<+pn;f|~XT)MCb^9~$cdx?ge_#=cO9 z^YSZk{Nf61-zJdoW0i>x#i7~SJ4k5u8Hnj;r?9@^iiaz)26Y; zN1*Jwp_qI{IbIK(UZ=x_uAdm^P3ZSY9?tC-i<6J4#7_f~Fzvh)yhR=|FP@Q_qES}v z2C0e^rO!TKL}vug?SR#FIPr`{IP1G|>_>B7l<)OPf;=}fIvVAF8j44V7oH`tRFIk* z`L{h%u*@fzQMH5+ttU~83F^h|1vctzndgg{RY}7K8MRc+zu8oTE^I{R@+$OWDrjSv zhrF1h#W6zeHSR_Fmw{m@KA1Jb-dKT0Ev~cgv8_RX#I3dlL$6qbH~u^tx9u8_hnaHN zwq8njFD0OA)h=YT*&WYjj4V2XKj!HzHi1i8{okkwK zwG!Yshs)Ag?>G|?G)zQr3SsOP&iXUP|9LrX;(VpsZRO9FdkV1W-eR;Q#i3R8WA-6~ z##DdCnxgXCB72#h+K39WdA2*mI|;dQe8(6Ho(J%KlbJqxKMF6Km8y1N$7dDw%e2j- zf4dM*Ensbg&E82i$1x_*jJTVZ;VI_%k2xg`k8R-kUGNm$`uxdbDxd35$}q z?beGIBgBo@=W2S^eLEIeuP)~ur6?^SL~jB_ci%{_=C6Gx4IY|?Sx=6|EkgndcDJZt z49h`=lLihIq4r?DiX_fY!B>w*81&xnCSYTRWp&7WBpd(upa^IGWf&gLjKNF_E#*$r zYwMnoFq6i6rgRe~{7{Y~9$JqJi>n!JqAx}7ySsuWfGcEPqCc*}P^M^_;}m`5J^dRx zndwdz%-!O((|P#4pHN28Ho4^W#Cy0=+RFgUAsT->7?bCfAj4zCcF}V>6XUnUcPNOCjGA%#}u-Jhb?D6r;~TvPjCw`(yXsMSfB4p za01h7RY&*7ocU4sf<=*5&DRStBZYdyHrd4+mtj7hi77PQ%hK5DUrj?S+ev_pFgB6 zi={W%u}X*L_K^5|tyZR|b3VTYi;3AyM2_GmxV17VFQ4ItPe{hhTQ{P)E3zy}GrA8` zDu|c$OiOALKFl)qby_qkOB6xUlW<J923&u(zBBllXq9Tx3&LFZ6OE7qGHO9SBibEb-fdd+v z(ZAKq%;SGe(&m(+`)1-f%IEV{zuXJnO3npW(Y<~i1u>Ng^rA6^a#2z&3M(p^(bc0d zy_i?0W3)F0clz*F9$^1<@(SEHw;H?NG8{Ki*_>lUU)hAI83o1^j7DAH4J0@RQm6`+ zK&9!aHZEUb7-?1ifL;`BIq#`MVN`NUz=7OQs3@DU`iOv;$~VKCaf|I#( zIUcSZjkrToabItb1XezBfn|8W2yAJyd%!~m3h5s%{^g-~w29I6Z>++tJz!~lOK<`K z(#C;tSpUj)xO`Y7D&)oNl+3h$y_7cvB+_!`apS?-eoRH$ZHmBxu}N5vU5eeifeF|! zjtHL1OL4#j{2ZK)|26c(j9rs3olN47gpH9sOn0>Iu`NGl$|GfvU?f=rQz4E2Zy64) zW$K#wWjJJhHPQmPF#g}8$%_qif=eFvq46i8Gz^2zPjilw;#YPgjTb+lOe7v8t?_u3 z{uxg9p`1E5QL*cV@N#7;X3ZXmSKiNMM5|p!DA-^jqqVvMJ3YD{zrTMN?h}o2dTexd zwLJ06PRG!4)qh8pC^>Bi?tL;FPjE25L9OFm2`Gr=_|wd6Jq@Ke^x2GJQq|UGbJ%EG{6XMzwnSHGd0t2G4aUj#^7L=2Z=}B-2$eP!r;j;r+^H~|TLfs^Hr<2}@ zXX>h`Jf`_xJUI&ah5@)IHSTY6f6SAfB{c*Z$8yq+b(AB#k|DOW70S|Z%|N{Qry?4F z{caEl$nRPUjkAdlufVOz@wn{3WPCt*VFn|DXEHj1Ma|j_NTy6->dN%H!LtM|CS}}U zhK^y({=0aPxj;*uRPC&$|^BF~RVJcPjY_IJ}3& zp)9)&`Na{aV-Qw7gM6B(e~+R=b4(+RzpEOMb?gQs@k$##>uz#|AzU&DFA>>y(y3bZ z3_1{c(sUObOq<1SDr4lyh(=brf+^+LIH#2c;NH}TsOgt z%tzJD!|=d$6?oZ|2F3MkdcXjI=%1N+IDH{=o8LVKe{2fFG(|o-QBIl4t?!x2^J*$$ zrJvEBiEt(X zkIYK3qA(oA4dKk7LuV&ue~4$g=p<&y$SiHdxE;U8cnWTVsia9OYCy^|sVy|7;)g2(3D<)NF|iXrExxPSTAyr0|Y&D;;z14j^iRQ_XtB7i->Dc!O6jKICq3vqH&BOMj| zW(lu`{nr2hAOJ~3K~&>>o?MF?&ZUuhk65gAiyxwMJh!fzXxvSM@vm>naMF*3tOwj3 zQXX$>#qAU~I()T^4qn-c!N%k5@k`H{pI{3Uu6Cz`&H*J2jU&q@k8Hg|O1sqVx)zUN zB$0GoV;J+4dYg60<7tL$I78W6rrbs>) z+3d>ehWBUF5ITXZtHyRt*5Kzp$0p*d_sfI7x4H{u2-%a)Bf$=^)O(mA?enNO6gAZ& zy-ShD?&cHO%j=Nwehn^)j=}k-RA4<#n;T=Iv7o96ONtt?j?Ryj)pWX|Q6##I&RLW< zQkm|0RLdspaL^AJTi=Ydye4EmQ%|X){k?5>F5Tq$R+f}2Yzm7fzgyvk)fLZY1`>9Y zrT0y<8$dufDTj9jLJ7xQvj`k;_joM7egqzzyc7?2Yh9lyD+GYTG(stPwft;NuF&7Q zJ3S)~L@=uPt}(cA&v?dF@OL*f%S3qzptnriC2E zl+bVecPO5`J`?wFzY3ia4yCOU9hD(iNS#Bk%!8O#F-7ko5$Q@{D@c(1#jwh!t;l2H zJ=02{lpob-kf5vdiAp0#dx!0&J&`lT+m$%@wiTGPxD@-gS+x0ax?x+Jg~sDNpU%O} zTuTBklfNX>;9z^gJ)naO^o%TrB7xOu`yuoInr2lODT- zHfu-om1A+!wS(-{jJE<4(;-KWLLRXR#wDYA?Y~aLoBz(kmDP<%>^2uqyL(yiE2hv= z+{(K4Vc5R79KT)ENtIisL2hfN@MCg&UfvH@Ha3*c=)SGTK)q7VW=@;e*QnEZ_`RRt zMCBk-h+C?yUG2M(1XiyzweX|oM3Z3QZ8SOJLm3*3$#Bj&}?%?8grlR z^27#7W+(DwP5&5&Yxl3hSFH^`G@Ls{WRrF|?eFJ)M4aeI)I2x}*N=@xVLi`Lu%p)e z43745lcGuGczW_xWp^)RaN0fr^ScfIVs(K$2m2;t9-V8~&h;ot#pX$ zd5?Kj+s^JBqPV{orr?urROh)THI@}SD;3{lQqf_%zL-roh#!%HdLA_tMi#puw;}zo z`ji3qcvr0e z>!jg3acw;lF@&SS4bLZ#NhbA7#&x=;zJ5It0?(EJcV&6QI|)~B9E>MFFT-K;3h>(= zgS0(at`Js}zMnW4|2TI5-jRKQ#$eBy>^gGz76`rK&uJfNP3VX9J&w1v0(C~6(>Bzf zWsVHqvqu|%CB%5r2&iFEsF}!=q!*UrASQ5+?v=>n2{79YB0|Ba&uObMF{c6tTrvu` zkBPtsGFUoo3OHKFFyPnd0s7KV;CWt9`zKJL9Z20~I@@?fOq|ZsO+T$cp3Cy!FzS2o zr$Bii*I8E$>`dWO2Jlicej=V)tC?BC&bp--QR<=okx2Uc2K@2Od|bn7$VovsM-2dKqqdYBVOQ9@)Ej zIKRg*hCaeI-%W-4e%werIcXRk3-FkpPSK=^QiOS_yOFo`aZEusG#Otnl@R0Q;GROD zlfmo?EiUftP%g{schxo_qmUZiax*oogBJ+Yy34yOsyJA(<1RY4;&~((G8>7jrm@5~ zT`?HXzP%CWtg66{zB2;zTrDreX|H9qzIY}hw%i&FSbr)ILgNZ_*f$nI;3`DhzcU{uth)ue#_ji?CD;*0{o-d$5t(GBzjA88oO&5B9EctyQic~K! z*szrjhR!s2glS;ts2uc0o~LEmfUq~IhdG@k3}U+Ny=zxiu={+_cOv*NAa2EcR*li5 z!>in&mgx8{)Ccw_-`5q{4uTJN8J(;=v&8qK+0Y)zrjF zyme|8o*f;FdsrW5gTcT%*h3+j>N%+p`C2Mw&!$_-2bDk;t!auJQ51=ALy@v2e1{@q z9lXW^0N5KsbFAZBb#RAsO@p{l2|8~vll@0r-wCW~#5$Qs<+}1!W!~QKo1YfgW%w1L zWNOMouUdr%H$wmh60K>(@P`U9n5lKwJLMrn-;Pdf^TzBdopg8EB!m!tY)Rw5&uB#St0av&4$Dm^O*k}5BoaLC=bTf&*zMVrr8$}0|?NTuJv5~kfBNCgGqRr*@cmCdP@`TQT zYIrVVJ>Eqqp$yRYmdv{D0IY#Y2|Duib%h?FK~!6$Nau5K%+{rMuZ>i|x+&|DJbeaOEyAGdsESoX=;7-FM#i zobNgBi6^bHLWzXvfmg!+Kx>ViCLnvK9PXWF(Anw?%APxLEcr(rj*h~LhqH0x-K#K> z4j{p*1a`WM-1kLUjJV#0hoJV2zPNHg7}JAU56`YTTZrO!F{5iNuWdcEy0RP?j(H!4 zqN=O`(Sf#(eqV{cQIbZBK+j8bCDlFO%i{`QSBGVhG5B0B+%jsm1mr(B4gZFn2QfNyee!AVVsf2Th#8)8Nt z*Mfj6ZNouJ|6~PVPGAY=Md5YR^L=nRw}kbdZR5Dq()kE*4m&CXpS;r-L?RtNCN4uCYdw2@I{j&hatFc(;8>U8!*wO21(S3ardJYLguCqcw zS+8Af<=RP!8`~P;yq*dhmlfXh-gLbGOA*FxEWx2ZCk&_XZhjGtn^c7J#--xj+73$c zWP6pwJ)RLg#z~0sJ=#+?KSn{#vRd@ZEyaFriwxsr9RvPrRv}Gf1PWg5k8vr%3@6Es zb5+j!&cIj3aVCvvyP0WO*clq+qBaN@&JU$&k)|~$r2@D!6z(lEqmeT-0>4f#^nW5L*z))ZKtC?Z6y_K*XCvF0)*(q);L za8n7Ud!l{%3@;Jj9&b1^l+5bY@#jmZdwCxM(2=_1@bnIQBp_!oSBBb`IZp0(K`JJ% zsl%YRH{w>O4=LJr?jz88aBR7?H|{(k9zV%G#+CXu*^7%VCY6WG5zgeT+)K-uTYc37 zA=qIkfCH?|sY4ed`w96@_F&sRt^jt&g13JpR$kg2&%d=659o=}4WmaqbZMdRUJWL$ zslWv{cE>|qLh&;_A5h!@!Iy0;$iyPnB(>ZSy~ps-r^iy5NGp>&nB(v$P6Z6#i7HVx zS+A4pWkIr~A#p>CTW`q+$us0xHpR94U%ZnKqJsKozOnb`Ge2%OU`{0!zeT{u^!&9c zxH~G;F}M&?ND!iL&%yYwb8+p~N@N*AJ^45*DeNdP)@gAbPCBs}@6H^Eiw+1yu7unS zv|>{NGk29y0#OMp!b^Iu)KBV-tF8$}$<&Rw-GCu4x3|V;pbbQKwwLq!FdT^nT+hsrc`oB{+%}IcD7}xO3om>E2>oR)?6=!_nPJQ4#}# zdHK8`>%63;5|M@rmobM(a{!4zcE9dMOa${hhZxI%x2oY#op*b&v>*x<&s1ael+7N> zt;}ckqA~VU>8d2 zoOj-pC9R5+jDNq}0XYKvqR|pT?RTafJd`qOF{E?FR3zzry7OKW=xq0E6$Y;>z)0P+ z`q*&boN`bm-o3ROUJ>1lt5Xxod?n*RBDT6??qce<+MpQxg=+M0%L9C@yLMKGFK9#) zdQ8r4)i-&vcw7PO>ITX{lt$dr1+V;2gwr>dV3?z}3kope;xZh0OgbiC zmx1SpMPjK;G#$_b8)8kkEg_V%`TKGXqMlrgqGdAT zwNf=XyvYHwN(LCOt9D?ZiKni7M?yb|g^S#a;jWEwMcp&{@<1W?4W`CVynN+%66QID z7tEs)SiU3m7Xhd%7F)T8ct0~lOziX$ob-A=Zm%xI(4FC)ZNOaI%?{m;ZQWjoV@EV$ z#;k$(_waCRkbViY(pCv9{njHuJ%M=$Zen=gJ3>QIJb4`+mdF9B1orc{fpg-~8JPY` zUtGwsT`hu+FgHr7#rszdEbiD`N>9jr&rQVF^HcH3x4HPY?i2iceD1FL9H;B5(SIHf z!3+cK^mvlxO!H9MH%4rRar9_(*&#-znv>)4{m2YV{bn2ASMCE{vca;iNqfJF6G~wv z`dqaIw|>?ecgtS1BT5X}KZw<~>_45I18qv7Q)94b;y$?K%4L{Z-$XIIvp3v31--%% z0(?=f$i}10clw^Ojd#U?!I9_t__ea1uH?Rh0(Oj`@vrKC|F^>qjl|F6x1*U+2i&+D z^Uy$%b95Yj-psvUN9N9s)>d9aNwM@U4bVk);H`0I$g_g6sCP6rtgk?CuT`X@K;`@7 zct9jpU6O>=rIed^VhIvC6b(I%HBo?oE=-TSC({fa-QxiMm+XI)GOUhK%xlA{%I*gGfIj@R~Rtc#(HuP zYQEyR;+O_}wT)!4<|y=lk&WvyX<4@kzZGyCGYm>^4o#o~qqh_@_Yc=6fP%eW%~ zpy++BO2W)L^Kph9t?oRR@a0NuLE=cJ9P@PXxB^%fJ$ID;VJNzTNw2S}z%(wZ9&eXB z+T>IBw5wDSk~b*<~MkqA)_8I;2|S|N@IR`AO4-pf1D5p9L6xxQrb>ba!rfLVkmOk zma};;Zr}|CZZdx*d5S-!KgU8IO5^zNE0XBpOJOqOv>O9UzAcAUIc&(Gv7_y^)kW?r zZDc)yeyqT`tIII{w<3D0$php>>V`SJLt~7*DoSv`Y0L2GCxdVva}KP?chmdbp?bRc z%QBoqHoZ#1*YfW`^8~iN4-y9Ro$i>xd{23gufc?pTBLUZ5tW-qkB{D-@9{BR@yVNg zF_w8mjPzaZ^2`+iGQ}C*5B!Har#VsR-I|5_XP4mkMok&vy1{3&;F8XB)q?13?YLIH zUxvf?OGG%=(mH2CI!Y7LI3Dx3r_r)^0>&1_Ds***cY9Beds2woa$`3<%W%ubmo?Ix z)t!^W-kaI(6{`zy`Qomac4Rb`bhPcRdUeF8@vKCAUeX`e+_D01@tq9vMRrai_s_3! z5j`Ul@7$PyN96n!=ZVM_MEEwiq8?#1PQlKElR^VC%d*Du69i0Q++xQ|3!udubxd>O9rC+#iTi z&1OXJs`Yel-5@fnXQ#_XYC}uWr*^yk<$u1$tpWGj#FIkRHH&=3v@_#cl zm-m53Z%E~Dzc{QCM-6)ZR=7p^D`UvIH$Rh3dG078o1r(Bq0y(ek^a$fkXKGGk_jM|P2U)#3bvruGMP#^Xc=aK=m~5SoLrEI_k#Ok?TcIS=B82%-Z_T7eSmXiXLrVX$vh*S z$bLFG6R*A28#hq-TPMP5cUb)Gics>LyW1m5hTw=8tbMQ-?!I#+Uh(O<)nCRKp~gjF zb5$elr5fR;QA7;~#?)m%0<9l8+*@@ZZ1!Iha9PY*+9rX+_R=eHMg%wL!TZ05Y%_Pph{?QuuN zO{j^A#cwr5_?O@BUqVsHQ0Obg_|F%L7_oa>0ZbGv;p|`RzzM#<#MwHS*bp-#QPg=7 zsMUZ}BB*(K{@{9Td6Hhhi+13++$!|b)C@%3JAq3;hS&#`k6%m&CRY|QE~S!c6VLR_76A9;_9x>SXpWYb7$fO%7uS2Ap6!L~)feX*}yS7pc$a{rj^U+E8es&&C z4?%x?&6{}l(4%;bRb*YkYsK4GJl!IB!zc+QWVI%B7iZ>D#^O3;Y$(NuZ}KsIVkr*Y z3C&Ftxy#!^R%KP_b>1>epF9xfQTh3+gdhpDVhaZ?p1@K9Q3)*VmcCC3#UGyz#>wZe z#VacdaB{2FMWBrcKWeY_z#SZd`t!2!(4;KOBZUnni15ZE-Ntz~(t~5<>I_W$ybMRp z%f)$tw9$0=h~)Sf@dRQelEwbqvDVwQA8XqG8Ao*M;!fb zAYL!~FHtxabI&3N7+1=C<=#*Az+*EDaVBb!;h71^fnH>rzsSX?k5lpP=?R!+cEP?^ z#-45e?Ckt2-z#UI9F>SCE!i+VzY&k{pc(9Q{2V~-mzPqIeONkXo|}R3424=B=WK`i zW#b*IwB$xSmWI4FOr_#(S%G6U^PQ_BINz)>VeX>^Q~>+S8L>TlTqF)m#O(ZLR7lh< zZz@G(iy&wIS@g=Q<$t_A_D+n&w?Bm9P8x*sP4L4)hVf=p9ua}LQy5m;lSR%f2h)E@ zKC<`o)O0I*o}M&lc#=^!MlHci3grQ(d|H zTC)aU&^e<|H6kM|puFC>BJ)d<&AG#g^NDj$)o%q70eM+gF|x*X%DF|(?5ZO7mHg^S zq4=Fj;Ir>rgO74+&{YjyTt(Q9`&j45E>YNieKszj()TaJ(8^6Sq}*0gW4K!;LPNmD zW0UdO>;jy|M|yi3W=BW3;1a^6-YSL>A-Yq6ziNmzdaVoYyw_WJ-0srd9zFxZvGw9! zc<}KRcum8e?X~}1bAe58--L+iTQPQeK1Q9Ef^QHz!H&^MSZ;K!2Z73?B&wPecc!grZ`_OV*SU%K{@b2-?47lE*kAk3>37-{ zU*x%h%HN{9`(Ug&1YcxFqFYJ~HWW#?S#K{4lqoJL!J)(Zq1)gHtaT=ohrHjSNSRLu z6=tNkPS^x958g^)aK(MKia2 zSEf;1buFXOda8I_0qo9($pj}JoA-3V#04c7`9luQ(h13(#M`;IC|zl_`dKdi6 F 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 CPow() diff --git a/.github/assets/devices.svg b/.github/assets/devices.svg deleted file mode 100644 index 4ae84cf48..000000000 --- a/.github/assets/devices.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - From e36f68f1855d7e45ab4b1e65f9e6216d25583475 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 19:47:00 -0400 Subject: [PATCH 168/241] Remove more unused images --- .github/assets/FullLogo_CakeWallet.png | Bin 187345 -> 0 bytes .github/assets/desktop.png | Bin 62736 -> 0 bytes .github/assets/devices.png | Bin 73544 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .github/assets/FullLogo_CakeWallet.png delete mode 100644 .github/assets/desktop.png delete mode 100644 .github/assets/devices.png diff --git a/.github/assets/FullLogo_CakeWallet.png b/.github/assets/FullLogo_CakeWallet.png deleted file mode 100644 index 9720c0c9e9f365455b6051af83ec770f55198674..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 187345 zcmeEvd0b8T|Nlv*n29Dn$QE)HhPt*$tFa^^#!tJ@UJKEk8FS%{N&yrKm8B>HE`!rr(Fy)VhH+2#XafK4@|#`Q0qkte)K<4 zC%>_Jbbz$|U+LMXvcoEy*_m8Ij9%yj)#w{<4l0Br6$8w3>Pq(wP;(zYlk+uvH+@u| zOeZMcNZd2stlX~jbY{Lm1M~WJ$wm7V*y+6(20XXfsZCn}%+U{%bW!Jq$`ySzyB`Jb7ilP;@%{)6OcN5+2sXU6ToeYnbP{fA`r6nQF1QUcjD^z4u~oJg;|eGP{8k%&92O?S0p;`Y1vW{&xV-^ zoXqoHnC~^P2+lfQ>_utUR1(xwm>n|j-tyUg?cD)Gn#b7O$l93mA#y}(OiGt$SDOXl z&AFwt?8^K3e%#sK9Vm|dZg-enbd$lB6Y)9UdRy9s|{_!XCpl9vl@jKjhg)6h`%pqk$bQNg_BN0b19aRjF18kj8bvU{{O@+_ z2V7g~H^kvBWAxTwlYf?tPyFU<$BSd?Uz1}=m3(OWdgFX9VSFx;Q?9b!-4qJ!Db#*6 zR=?|A$m5?hnY5OpRXtr!A%O^z7u5(iw=1!b`>5@v_j+{dj=2}x8Ht@{z%_rrq~;oV zu<|fxXkD9ogc<)RxM$3jr>gvB`K!VRzpUxE30<{H*4%yb{@-b?`MXm~RGLO<21GTq z?CJ7CJfzyt{WYzdOZ*U^v>$>Xb*xsY^CHt%>2J`HJ?E0redkGfvnmtaJi~RrUk5!TZ?2T<3V0~SFzxZ!40y<- za*E+Y`S$##hD-7>m>aTSCFPao(jP!$-Yy%JNJ-LBDoHL0B)MVz&)MmM9ZxT+Fd+{Y z=0-Ne(8ny7(=8R_V6hXi$qj;&u%(rzbwleAxjbtOK~aT(;ybs=?nl3vs&n#DO!ASl zdjj4zj|y)f509qX%65UZ-4gk>Xd=91 zRN4BbVauGP=}O)wO(5HHX01*?cDxNh5?b|mVQ$XuEKg(9Yhsw515}&aEz33C0}j-z zboNqVI`<#ynwcG>e8^m%t~2&ApjzCT^NX)~eHp`aUy_N0>|38)riZPemVsY{MIdQdQ8=ApoZlU;(ld;0(4q9Ry%b}t zF37Vew!CIAl0aOf)YQr^rK>Kt9yQ7sru_)rcvN7nyv?3GFT-qmb(h$QG(CE>LA3zmO+WhSl-Dqf(W^X%2B3FE#T2|l-4Ocr1t&OK zz%_gF*xJs+vETU>X0E{x#m!Vcw4hw`wvv^K9p+ndeEhB-FK(z*GF8j@cP2Zp{}xc;Q{Hhsur0ae)E z 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

        M^1$%3dNqM_UJ_x+CMb~ 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�MCe0*x_6`pF#Icx^^HLl`% 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 z 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%0AJyrSMp1d@b)Hm30kWgz%8?oZtyMOJR{-Z)L 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 Date: Mon, 8 Apr 2024 17:54:58 +0300 Subject: [PATCH 170/241] Add rbf (#1323) * Add initial checkbox for RBF * minor progress * minor progress * Minor progress * Debugging RBF * Minor fix * Fix RBF transaction inputs (now it's working) * New versions Fix issues with Monero.com * Add sending for Solana tokens exchanges * Add default keyword for P2WPKH [skip ci] * chore: Switch solana commitment to confirmed to reduced blockhash expiration (#1313) * Modify test workflow to send arm64-v8a build only * Fix workflow build path * Remove unnecessary reverse of txId * Update Replace by fee with the new bitcoin base implementation * btc custom fee priority * add feeRate to btc credential * UI fixes * add check if the change covers the fee * Update settings_store.dart * add check confirmation for rbf * add a check to see if the change is sufficient for the new fee * addressing PR comments * update localization files * addressing PR comments * minor fixes * Update transaction_details_view_model.dart * Minor Fix for building Monero.com [skip ci] * update localization files * add bump fee page * update localisation files * Update cw_bitcoin.dart * fix merge conflict * fix UI issues * Fix Conflicts, Fix RBF flow, some enhancements * prevent default custom fee rate * hide outputs and inputs items * minor fix [skip ci] * addressing PR comments * remove rbf checkbox * default picker value * minor ui change [skip ci] * min fee rate [skip ci] * Minor fix and some minor enhancements --------- Co-authored-by: OmarHatem Co-authored-by: Adegoke David <64401859+Blazebrain@users.noreply.github.com> --- .../lib/bitcoin_transaction_credentials.dart | 3 +- .../lib/bitcoin_transaction_priority.dart | 16 +- cw_bitcoin/lib/electrum_transaction_info.dart | 19 +- cw_bitcoin/lib/electrum_wallet.dart | 197 +++++++- .../lib/pending_bitcoin_transaction.dart | 2 +- cw_bitcoin/pubspec.lock | 4 +- cw_bitcoin/pubspec.yaml | 2 +- cw_bitcoin_cash/pubspec.yaml | 2 +- cw_core/lib/transaction_info.dart | 2 + cw_core/lib/wallet_base.dart | 1 + lib/bitcoin/cw_bitcoin.dart | 83 +++- lib/core/execution_state.dart | 9 + lib/di.dart | 9 +- lib/entities/preferences_key.dart | 1 + lib/router.dart | 7 + lib/routes.dart | 1 + lib/src/screens/send/send_page.dart | 9 +- lib/src/screens/send/widgets/send_card.dart | 48 +- .../screens/settings/other_settings_page.dart | 27 +- .../widgets/setting_priority_picker_cell.dart | 78 ++++ .../rbf_details_list_fee_picker_item.dart | 23 + .../transaction_details/rbf_details_page.dart | 199 ++++++++ .../transaction_details_page.dart | 98 ++-- .../transaction_expandable_list_item.dart | 7 + lib/src/widgets/checkbox_widget.dart | 1 - lib/src/widgets/picker.dart | 427 +++++++++++------- lib/src/widgets/search_bar_widget.dart | 2 +- lib/src/widgets/standard_expandable_list.dart | 58 +++ lib/src/widgets/standard_picker_list.dart | 81 ++++ lib/store/settings_store.dart | 16 +- lib/view_model/send/output.dart | 14 +- lib/view_model/send/send_view_model.dart | 60 ++- .../settings/other_settings_view_model.dart | 35 +- .../transaction_details_view_model.dart | 128 +++++- res/values/strings_ar.arb | 8 + res/values/strings_bg.arb | 8 + res/values/strings_cs.arb | 8 + res/values/strings_de.arb | 8 + res/values/strings_en.arb | 8 + res/values/strings_es.arb | 8 + res/values/strings_fr.arb | 8 + res/values/strings_ha.arb | 8 + res/values/strings_hi.arb | 8 + res/values/strings_hr.arb | 8 + res/values/strings_id.arb | 8 + res/values/strings_it.arb | 8 + res/values/strings_ja.arb | 8 + res/values/strings_ko.arb | 8 + res/values/strings_my.arb | 8 + res/values/strings_nl.arb | 8 + res/values/strings_pl.arb | 8 + res/values/strings_pt.arb | 8 + res/values/strings_ru.arb | 10 +- res/values/strings_th.arb | 8 + res/values/strings_tl.arb | 8 + res/values/strings_tr.arb | 8 + res/values/strings_uk.arb | 8 + res/values/strings_ur.arb | 8 + res/values/strings_yo.arb | 8 + res/values/strings_zh.arb | 8 + scripts/append_translation.sh | 23 - tool/configure.dart | 10 +- 62 files changed, 1591 insertions(+), 321 deletions(-) create mode 100644 lib/src/screens/settings/widgets/setting_priority_picker_cell.dart create mode 100644 lib/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart create mode 100644 lib/src/screens/transaction_details/rbf_details_page.dart create mode 100644 lib/src/screens/transaction_details/transaction_expandable_list_item.dart create mode 100644 lib/src/widgets/standard_expandable_list.dart create mode 100644 lib/src/widgets/standard_picker_list.dart delete mode 100755 scripts/append_translation.sh diff --git a/cw_bitcoin/lib/bitcoin_transaction_credentials.dart b/cw_bitcoin/lib/bitcoin_transaction_credentials.dart index bd8f1763c..bda7c39ae 100644 --- a/cw_bitcoin/lib/bitcoin_transaction_credentials.dart +++ b/cw_bitcoin/lib/bitcoin_transaction_credentials.dart @@ -2,7 +2,8 @@ import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; import 'package:cw_core/output_info.dart'; class BitcoinTransactionCredentials { - BitcoinTransactionCredentials(this.outputs, {required this.priority, this.feeRate}); + BitcoinTransactionCredentials(this.outputs, + {required this.priority, this.feeRate}); final List outputs; final BitcoinTransactionPriority? priority; diff --git a/cw_bitcoin/lib/bitcoin_transaction_priority.dart b/cw_bitcoin/lib/bitcoin_transaction_priority.dart index 10953a2e0..d51775368 100644 --- a/cw_bitcoin/lib/bitcoin_transaction_priority.dart +++ b/cw_bitcoin/lib/bitcoin_transaction_priority.dart @@ -4,13 +4,15 @@ class BitcoinTransactionPriority extends TransactionPriority { const BitcoinTransactionPriority({required String title, required int raw}) : super(title: title, raw: raw); - static const List all = [fast, medium, slow]; + static const List all = [fast, medium, slow, custom]; static const BitcoinTransactionPriority slow = BitcoinTransactionPriority(title: 'Slow', raw: 0); static const BitcoinTransactionPriority medium = BitcoinTransactionPriority(title: 'Medium', raw: 1); static const BitcoinTransactionPriority fast = BitcoinTransactionPriority(title: 'Fast', raw: 2); + static const BitcoinTransactionPriority custom = + BitcoinTransactionPriority(title: 'Custom', raw: 3); static BitcoinTransactionPriority deserialize({required int raw}) { switch (raw) { @@ -20,6 +22,8 @@ class BitcoinTransactionPriority extends TransactionPriority { return medium; case 2: return fast; + case 3: + return custom; default: throw Exception('Unexpected token: $raw for BitcoinTransactionPriority deserialize'); } @@ -39,7 +43,10 @@ class BitcoinTransactionPriority extends TransactionPriority { label = 'Medium'; // S.current.transaction_priority_medium; break; case BitcoinTransactionPriority.fast: - label = 'Fast'; // S.current.transaction_priority_fast; + label = 'Fast'; + break; // S.current.transaction_priority_fast; + case BitcoinTransactionPriority.custom: + label = 'Custom'; break; default: break; @@ -48,7 +55,10 @@ class BitcoinTransactionPriority extends TransactionPriority { return label; } - String labelWithRate(int rate) => '${toString()} ($rate ${units}/byte)'; + String labelWithRate(int rate, int? customRate) { + final rateValue = this == custom ? customRate ??= 0 : rate; + return '${toString()} ($rateValue ${units}/byte)'; + } } class LitecoinTransactionPriority extends BitcoinTransactionPriority { diff --git a/cw_bitcoin/lib/electrum_transaction_info.dart b/cw_bitcoin/lib/electrum_transaction_info.dart index cfea0e089..f980bd884 100644 --- a/cw_bitcoin/lib/electrum_transaction_info.dart +++ b/cw_bitcoin/lib/electrum_transaction_info.dart @@ -11,12 +11,11 @@ import 'package:cw_core/wallet_type.dart'; class ElectrumTransactionBundle { ElectrumTransactionBundle(this.originalTransaction, - {required this.ins, required this.confirmations, this.time, required this.height}); + {required this.ins, required this.confirmations, this.time}); final BtcTransaction originalTransaction; final List ins; final int? time; final int confirmations; - final int height; } class ElectrumTransactionInfo extends TransactionInfo { @@ -25,6 +24,8 @@ class ElectrumTransactionInfo extends TransactionInfo { required int height, required int amount, int? fee, + List? inputAddresses, + List? outputAddresses, required TransactionDirection direction, required bool isPending, required DateTime date, @@ -32,6 +33,8 @@ class ElectrumTransactionInfo extends TransactionInfo { this.id = id; this.height = height; this.amount = amount; + this.inputAddresses = inputAddresses; + this.outputAddresses = outputAddresses; this.fee = fee; this.direction = direction; this.date = date; @@ -100,6 +103,8 @@ class ElectrumTransactionInfo extends TransactionInfo { var amount = 0; var inputAmount = 0; var totalOutAmount = 0; + List inputAddresses = []; + List outputAddresses = []; for (var i = 0; i < bundle.originalTransaction.inputs.length; i++) { final input = bundle.originalTransaction.inputs[i]; @@ -108,6 +113,7 @@ class ElectrumTransactionInfo extends TransactionInfo { inputAmount += outTransaction.amount.toInt(); if (addresses.contains(addressFromOutputScript(outTransaction.scriptPubKey, network))) { direction = TransactionDirection.outgoing; + inputAddresses.add(addressFromOutputScript(outTransaction.scriptPubKey, network)); } } @@ -115,6 +121,7 @@ class ElectrumTransactionInfo extends TransactionInfo { for (final out in bundle.originalTransaction.outputs) { totalOutAmount += out.amount.toInt(); final addressExists = addresses.contains(addressFromOutputScript(out.scriptPubKey, network)); + outputAddresses.add(addressFromOutputScript(out.scriptPubKey, network)); if (addressExists) { receivedAmounts.add(out.amount.toInt()); @@ -137,6 +144,8 @@ class ElectrumTransactionInfo extends TransactionInfo { id: bundle.originalTransaction.txId(), height: height, isPending: bundle.confirmations == 0, + inputAddresses: inputAddresses, + outputAddresses: outputAddresses, fee: fee, direction: direction, amount: amount, @@ -187,6 +196,8 @@ class ElectrumTransactionInfo extends TransactionInfo { direction: parseTransactionDirectionFromInt(data['direction'] as int), date: DateTime.fromMillisecondsSinceEpoch(data['date'] as int), isPending: data['isPending'] as bool, + inputAddresses: data['inputAddresses'] as List, + outputAddresses: data['outputAddresses'] as List, confirmations: data['confirmations'] as int); } @@ -218,6 +229,8 @@ class ElectrumTransactionInfo extends TransactionInfo { direction: direction, date: date, isPending: isPending, + inputAddresses: inputAddresses, + outputAddresses: outputAddresses, confirmations: info.confirmations); } @@ -231,6 +244,8 @@ class ElectrumTransactionInfo extends TransactionInfo { m['isPending'] = isPending; m['confirmations'] = confirmations; m['fee'] = fee; + m['inputAddresses'] = inputAddresses; + m['outputAddresses'] = outputAddresses; return m; } } diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 9c144ac74..5bed6a449 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -7,6 +7,7 @@ import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin_base; import 'package:collection/collection.dart'; +import 'package:cw_bitcoin/address_from_output.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; @@ -188,11 +189,9 @@ abstract class ElectrumWalletBase } } - int _getDustAmount() { - return 546; - } + int get _dustAmount => 546; - bool _isBelowDust(int amount) => amount <= _getDustAmount() && network != BitcoinNetwork.testnet; + bool _isBelowDust(int amount) => amount <= _dustAmount && network != BitcoinNetwork.testnet; Future estimateSendAllTx( List outputs, @@ -418,7 +417,7 @@ abstract class ElectrumWalletBase } // Estimate to user how much is needed to send to cover the fee - final maxAmountWithReturningChange = allInputsAmount - _getDustAmount() - fee - 1; + final maxAmountWithReturningChange = allInputsAmount - _dustAmount - fee - 1; throw BitcoinTransactionNoDustOnChangeException( bitcoinAmountToString(amount: maxAmountWithReturningChange), bitcoinAmountToString(amount: estimatedSendAll.amount), @@ -532,6 +531,7 @@ abstract class ElectrumWalletBase network: network, memo: estimatedTx.memo, outputOrdering: BitcoinOrdering.none, + enableRBF: true, ); } else { txb = BitcoinTransactionBuilder( @@ -541,6 +541,7 @@ abstract class ElectrumWalletBase network: network, memo: estimatedTx.memo, outputOrdering: BitcoinOrdering.none, + enableRBF: true, ); } @@ -794,8 +795,180 @@ abstract class ElectrumWalletBase } } - Future getTransactionExpanded( - {required String hash, required int height}) async { + Future canReplaceByFee(String hash) async { + final verboseTransaction = await electrumClient.getTransactionRaw(hash: hash); + final confirmations = verboseTransaction['confirmations'] as int? ?? 0; + final transactionHex = verboseTransaction['hex'] as String?; + + if (confirmations > 0) return false; + + if (transactionHex == null) { + return false; + } + + final original = bitcoin.Transaction.fromHex(transactionHex); + + return original.ins + .any((element) => element.sequence != null && element.sequence! < 4294967293); + } + + Future isChangeSufficientForFee(String txId, int newFee) async { + final bundle = await getTransactionExpanded(hash: txId); + final outputs = bundle.originalTransaction.outputs; + + final changeAddresses = walletAddresses.allAddresses.where((element) => element.isHidden); + + // look for a change address in the outputs + final changeOutput = outputs.firstWhereOrNull((output) => changeAddresses.any( + (element) => element.address == addressFromOutputScript(output.scriptPubKey, network))); + + var allInputsAmount = 0; + + for (int i = 0; i < bundle.originalTransaction.inputs.length; i++) { + final input = bundle.originalTransaction.inputs[i]; + final inputTransaction = bundle.ins[i]; + final vout = input.txIndex; + final outTransaction = inputTransaction.outputs[vout]; + allInputsAmount += outTransaction.amount.toInt(); + } + + int totalOutAmount = bundle.originalTransaction.outputs + .fold(0, (previousValue, element) => previousValue + element.amount.toInt()); + + var currentFee = allInputsAmount - totalOutAmount; + + int remainingFee = (newFee - currentFee > 0) ? newFee - currentFee : newFee; + + return changeOutput != null && changeOutput.amount.toInt() - remainingFee >= 0; + } + + Future replaceByFee(String hash, int newFee) async { + try { + final bundle = await getTransactionExpanded(hash: hash); + + final utxos = []; + List privateKeys = []; + + var allInputsAmount = 0; + + // Add inputs + for (var i = 0; i < bundle.originalTransaction.inputs.length; i++) { + final input = bundle.originalTransaction.inputs[i]; + final inputTransaction = bundle.ins[i]; + final vout = input.txIndex; + final outTransaction = inputTransaction.outputs[vout]; + final address = addressFromOutputScript(outTransaction.scriptPubKey, network); + allInputsAmount += outTransaction.amount.toInt(); + + final addressRecord = + walletAddresses.allAddresses.firstWhere((element) => element.address == address); + + final btcAddress = addressTypeFromStr(addressRecord.address, network); + final privkey = generateECPrivate( + hd: addressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, + index: addressRecord.index, + network: network); + + privateKeys.add(privkey); + + utxos.add( + UtxoWithAddress( + utxo: BitcoinUtxo( + txHash: input.txId, + value: outTransaction.amount, + vout: vout, + scriptType: _getScriptType(btcAddress), + ), + ownerDetails: + UtxoAddressDetails(publicKey: privkey.getPublic().toHex(), address: btcAddress), + ), + ); + } + + int totalOutAmount = bundle.originalTransaction.outputs + .fold(0, (previousValue, element) => previousValue + element.amount.toInt()); + + var currentFee = allInputsAmount - totalOutAmount; + int remainingFee = newFee - currentFee; + + final outputs = []; + + // Add outputs and deduct the fees from it + for (int i = bundle.originalTransaction.outputs.length - 1; i >= 0; i--) { + final out = bundle.originalTransaction.outputs[i]; + final address = addressFromOutputScript(out.scriptPubKey, network); + final btcAddress = addressTypeFromStr(address, network); + + int newAmount; + if (out.amount.toInt() >= remainingFee) { + newAmount = out.amount.toInt() - remainingFee; + remainingFee = 0; + + // if new amount of output is less than dust amount, then don't add this output as well + if (newAmount <= _dustAmount) { + continue; + } + } else { + remainingFee -= out.amount.toInt(); + continue; + } + + outputs.add(BitcoinOutput(address: btcAddress, value: BigInt.from(newAmount))); + } + + final changeAddresses = walletAddresses.allAddresses.where((element) => element.isHidden); + + // look for a change address in the outputs + final changeOutput = outputs.firstWhereOrNull((output) => + changeAddresses.any((element) => element.address == output.address.toAddress(network))); + + // deduct the change amount from the output amount + if (changeOutput != null) { + totalOutAmount -= changeOutput.value.toInt(); + } + + final txb = BitcoinTransactionBuilder( + utxos: utxos, + outputs: outputs, + fee: BigInt.from(newFee), + network: network, + enableRBF: true, + ); + + final transaction = txb.buildTransaction((txDigest, utxo, publicKey, sighash) { + final key = + privateKeys.firstWhereOrNull((element) => element.getPublic().toHex() == publicKey); + + if (key == null) { + throw Exception("Cannot find private key"); + } + + if (utxo.utxo.isP2tr()) { + return key.signTapRoot(txDigest, sighash: sighash); + } else { + return key.signInput(txDigest, sigHash: sighash); + } + }); + + return PendingBitcoinTransaction( + transaction, + type, + electrumClient: electrumClient, + amount: totalOutAmount, + fee: newFee, + network: network, + hasChange: changeOutput != null, + feeRate: newFee.toString(), + )..addListener((transaction) async { + transactionHistory.addOne(transaction); + await updateBalance(); + }); + } catch (e) { + throw e; + } + } + + Future getTransactionExpanded({required String hash}) async { String transactionHex; int? time; int confirmations = 0; @@ -826,8 +999,12 @@ abstract class ElectrumWalletBase ins.add(tx); } - return ElectrumTransactionBundle(original, - ins: ins, time: time, confirmations: confirmations, height: height); + return ElectrumTransactionBundle( + original, + ins: ins, + time: time, + confirmations: confirmations, + ); } Future fetchTransactionInfo( @@ -837,7 +1014,7 @@ abstract class ElectrumWalletBase bool? retryOnFailure}) async { try { return ElectrumTransactionInfo.fromElectrumBundle( - await getTransactionExpanded(hash: hash, height: height), walletInfo.type, network, + await getTransactionExpanded(hash: hash), walletInfo.type, network, addresses: myAddresses, height: height); } catch (e) { if (e is FormatException && retryOnFailure == true) { diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart index eb4274e78..529ac61da 100644 --- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart +++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart @@ -17,7 +17,7 @@ class PendingBitcoinTransaction with PendingTransaction { required this.feeRate, this.network, required this.hasChange, - required this.isSendAll, + this.isSendAll = false, this.hasTaprootInputs = false, }) : _listeners = []; diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index b39dcae07..3d828243c 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -70,8 +70,8 @@ packages: dependency: "direct main" description: path: "." - ref: master - resolved-ref: ea65073efbaf395a5557e8cd7bd72f195cd7eb11 + ref: Add-Support-For-OP-Return-data + resolved-ref: "57b78afb85bd2c30d3cdb9f7884f3878a62be442" url: "https://github.com/cake-tech/bitbox-flutter.git" source: git version: "1.0.1" diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index bcbb55e11..632a3140a 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -26,7 +26,7 @@ dependencies: bitbox: git: url: https://github.com/cake-tech/bitbox-flutter.git - ref: master + ref: Add-Support-For-OP-Return-data rxdart: ^0.27.5 unorm_dart: ^0.2.0 cryptography: ^2.0.5 diff --git a/cw_bitcoin_cash/pubspec.yaml b/cw_bitcoin_cash/pubspec.yaml index 7130b3c58..37827f1ba 100644 --- a/cw_bitcoin_cash/pubspec.yaml +++ b/cw_bitcoin_cash/pubspec.yaml @@ -28,7 +28,7 @@ dependencies: bitbox: git: url: https://github.com/cake-tech/bitbox-flutter.git - ref: master + ref: Add-Support-For-OP-Return-data bitcoin_base: git: url: https://github.com/cake-tech/bitcoin_base.git diff --git a/cw_core/lib/transaction_info.dart b/cw_core/lib/transaction_info.dart index 7624b147f..992582ff8 100644 --- a/cw_core/lib/transaction_info.dart +++ b/cw_core/lib/transaction_info.dart @@ -16,6 +16,8 @@ abstract class TransactionInfo extends Object with Keyable { void changeFiatAmount(String amount); String? to; String? from; + List? inputAddresses; + List? outputAddresses; @override dynamic get keyIndex => id; diff --git a/cw_core/lib/wallet_base.dart b/cw_core/lib/wallet_base.dart index 49f1bdc94..037a26d38 100644 --- a/cw_core/lib/wallet_base.dart +++ b/cw_core/lib/wallet_base.dart @@ -67,6 +67,7 @@ abstract class WalletBase outputs, - {required TransactionPriority priority, int? feeRate}) => - BitcoinTransactionCredentials( - outputs - .map((out) => OutputInfo( - fiatAmount: out.fiatAmount, - cryptoAmount: out.cryptoAmount, - address: out.address, - note: out.note, - sendAll: out.sendAll, - extractedAddress: out.extractedAddress, - isParsedAddress: out.isParsedAddress, - formattedCryptoAmount: out.formattedCryptoAmount, - memo: out.memo)) - .toList(), - priority: priority as BitcoinTransactionPriority, - feeRate: feeRate); + {required TransactionPriority priority, int? feeRate}) { + final bitcoinFeeRate = + priority == BitcoinTransactionPriority.custom && feeRate != null ? feeRate : null; + return BitcoinTransactionCredentials( + outputs + .map((out) => OutputInfo( + fiatAmount: out.fiatAmount, + cryptoAmount: out.cryptoAmount, + address: out.address, + note: out.note, + sendAll: out.sendAll, + extractedAddress: out.extractedAddress, + isParsedAddress: out.isParsedAddress, + formattedCryptoAmount: out.formattedCryptoAmount, + memo: out.memo)) + .toList(), + priority: priority as BitcoinTransactionPriority, + feeRate: bitcoinFeeRate + ); + } @override Object createBitcoinTransactionCredentialsRaw(List outputs, @@ -172,8 +176,9 @@ class CWBitcoin extends Bitcoin { int formatterStringDoubleToBitcoinAmount(String amount) => stringDoubleToBitcoinAmount(amount); @override - String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate) => - (priority as BitcoinTransactionPriority).labelWithRate(rate); + String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate, + {int? customRate}) => + (priority as BitcoinTransactionPriority).labelWithRate(rate, customRate); @override List getUnspents(Object wallet) { @@ -199,6 +204,9 @@ class CWBitcoin extends Bitcoin { @override TransactionPriority getBitcoinTransactionPriorityMedium() => BitcoinTransactionPriority.medium; + @override + TransactionPriority getBitcoinTransactionPriorityCustom() => BitcoinTransactionPriority.custom; + @override TransactionPriority getLitecoinTransactionPriorityMedium() => LitecoinTransactionPriority.medium; @@ -244,4 +252,43 @@ class CWBitcoin extends Bitcoin { bool hasTaprootInput(PendingTransaction pendingTransaction) { return (pendingTransaction as PendingBitcoinTransaction).hasTaprootInputs; } + + @override + Future replaceByFee( + Object wallet, String transactionHash, String fee) async { + final bitcoinWallet = wallet as ElectrumWallet; + return await bitcoinWallet.replaceByFee(transactionHash, int.parse(fee)); + } + + @override + Future canReplaceByFee(Object wallet, String transactionHash) async { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.canReplaceByFee(transactionHash); + } + + @override + Future isChangeSufficientForFee(Object wallet, String txId, String newFee) async { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.isChangeSufficientForFee(txId, int.parse(newFee)); + } + + @override + int getFeeAmountForPriority( + Object wallet, TransactionPriority priority, int inputsCount, int outputsCount, + {int? size}) { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.feeAmountForPriority( + priority as BitcoinTransactionPriority, inputsCount, outputsCount); + } + + @override + int getFeeAmountWithFeeRate(Object wallet, int feeRate, int inputsCount, int outputsCount, + {int? size}) { + final bitcoinWallet = wallet as ElectrumWallet; + return bitcoinWallet.feeAmountWithFeeRate( + feeRate, + inputsCount, + outputsCount, + ); + } } diff --git a/lib/core/execution_state.dart b/lib/core/execution_state.dart index 18dc81030..6bc906010 100644 --- a/lib/core/execution_state.dart +++ b/lib/core/execution_state.dart @@ -14,4 +14,13 @@ class FailureState extends ExecutionState { FailureState(this.error); final String error; +} + +class AwaitingConfirmationState extends ExecutionState { + AwaitingConfirmationState({this.title, this.message, this.onConfirm, this.onCancel}); + + final String? title; + final String? message; + final Function()? onConfirm; + final Function()? onCancel; } \ No newline at end of file diff --git a/lib/di.dart b/lib/di.dart index 291555330..5262a01e6 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -13,6 +13,7 @@ import 'package:cake_wallet/core/yat_service.dart'; import 'package:cake_wallet/entities/background_tasks.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/parse_address_from_domain.dart'; +import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart'; import 'package:cw_core/receive_page_option.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/nano/nano.dart'; @@ -914,7 +915,8 @@ Future setup({ transactionInfo: transactionInfo, transactionDescriptionBox: _transactionDescriptionBox, wallet: wallet, - settingsStore: getIt.get()); + settingsStore: getIt.get(), + sendViewModel: getIt.get()); }); getIt.registerFactoryParam( @@ -1137,6 +1139,11 @@ Future setup({ getIt.registerFactory(() => IoniaAccountCardsPage(getIt.get())); + getIt.registerFactoryParam( + (TransactionInfo transactionInfo, _) => RBFDetailsPage( + transactionDetailsViewModel: + getIt.get(param1: transactionInfo))); + getIt.registerFactory(() => AnonPayApi( useTorOnly: getIt.get().exchangeStatus == ExchangeApiMode.torOnly, wallet: getIt.get().wallet!)); diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 5c22455d2..ba6d6ef4f 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -42,6 +42,7 @@ class PreferencesKey { static const ethereumTransactionPriority = 'current_fee_priority_ethereum'; static const polygonTransactionPriority = 'current_fee_priority_polygon'; static const bitcoinCashTransactionPriority = 'current_fee_priority_bitcoin_cash'; + static const customBitcoinFeeRate = 'custom_electrum_fee_rate'; static const shouldShowReceiveWarning = 'should_show_receive_warning'; static const shouldShowYatPopup = 'should_show_yat_popup'; static const moneroWalletPasswordUpdateV1Base = 'monero_wallet_update_v1'; diff --git a/lib/router.dart b/lib/router.dart index ef7b7f31e..9f5dfb838 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -54,6 +54,7 @@ import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart import 'package:cake_wallet/src/screens/support/support_page.dart'; import 'package:cake_wallet/src/screens/support_chat/support_chat_page.dart'; import 'package:cake_wallet/src/screens/support_other_links/support_other_links_page.dart'; +import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart'; import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart'; @@ -253,6 +254,12 @@ Route createRoute(RouteSettings settings) { builder: (_) => getIt.get(param1: settings.arguments as TransactionInfo)); + case Routes.bumpFeePage: + return CupertinoPageRoute( + fullscreenDialog: true, + builder: (_) => + getIt.get(param1: settings.arguments as TransactionInfo)); + case Routes.newSubaddress: return CupertinoPageRoute( builder: (_) => getIt.get(param1: settings.arguments)); diff --git a/lib/routes.dart b/lib/routes.dart index 7ad5c70bc..9c4e21651 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -12,6 +12,7 @@ class Routes { static const dashboard = '/dashboard'; static const send = '/send'; static const transactionDetails = '/transaction_info'; + static const bumpFeePage = '/bump_fee_page'; static const receive = '/receive'; static const newSubaddress = '/new_subaddress'; static const walletEdit = '/walletEdit'; diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 56b1b7af7..970bb31f2 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -100,7 +100,10 @@ class SendPage extends BasePage { AppBarStyle get appBarStyle => AppBarStyle.transparent; double _sendCardHeight(BuildContext context) { - final double initialHeight = sendViewModel.hasCoinControl ? 500 : 465; + double initialHeight = 450; + if (sendViewModel.hasCoinControl) { + initialHeight += 35; + } if (!responsiveLayoutUtil.shouldRenderMobileUI) { return initialHeight - 66; @@ -190,7 +193,7 @@ class SendPage extends BasePage { }, )), Padding( - padding: EdgeInsets.only(top: 10, left: 24, right: 24, bottom: 10), + padding: EdgeInsets.only(left: 24, right: 24, bottom: 10), child: Container( height: 10, child: Observer( @@ -456,7 +459,7 @@ class SendPage extends BasePage { ? '. ${S.of(_dialogContext).waitFewSecondForTxUpdate}' : ''; final newContactMessage = newContactAddress != null - ? '\n${S.of(context).add_contact_to_address_book}' : ''; + ? '\n${S.of(_dialogContext).add_contact_to_address_book}' : ''; final alertContent = "$successMessage$waitMessage$newContactMessage"; diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index d36997814..7c2bfedd0 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -1,16 +1,17 @@ -import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; +import 'package:cake_wallet/src/widgets/picker.dart'; +import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/currency.dart'; -import 'package:cw_core/transaction_priority.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; -import 'package:cake_wallet/src/widgets/picker.dart'; import 'package:cake_wallet/view_model/send/output.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -456,7 +457,7 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin GestureDetector( onTap: sendViewModel.hasFeesPriority - ? () => _setTransactionPriority(context) + ? () => pickTransactionPriority(context) : () {}, child: Container( padding: EdgeInsets.only(top: 24), @@ -669,22 +670,41 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin _setTransactionPriority(BuildContext context) async { + Future pickTransactionPriority(BuildContext context) async { final items = priorityForWalletType(sendViewModel.walletType); final selectedItem = items.indexOf(sendViewModel.transactionPriority); + final customItemIndex = sendViewModel.getCustomPriorityIndex(items); + final isBitcoinWallet = sendViewModel.walletType == WalletType.bitcoin; + double? customFeeRate = isBitcoinWallet ? sendViewModel.customBitcoinFeeRate.toDouble() : null; await showPopUp( context: context, - builder: (_) => Picker( - items: items, - displayItem: sendViewModel.displayFeeRate, - selectedAtIndex: selectedItem, - title: S.of(context).please_select, - mainAxisAlignment: MainAxisAlignment.center, - onItemSelected: (TransactionPriority priority) => - sendViewModel.setTransactionPriority(priority), - ), + builder: (BuildContext context) { + int selectedIdx = selectedItem; + return StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return Picker( + items: items, + displayItem: (TransactionPriority priority) => + sendViewModel.displayFeeRate(priority, customFeeRate?.round()), + selectedAtIndex: selectedIdx, + customItemIndex: customItemIndex, + title: S.of(context).please_select, + headerEnabled: !isBitcoinWallet, + closeOnItemSelected: !isBitcoinWallet, + mainAxisAlignment: MainAxisAlignment.center, + sliderValue: customFeeRate, + onSliderChanged: (double newValue) => setState(() => customFeeRate = newValue), + onItemSelected: (TransactionPriority priority) { + sendViewModel.setTransactionPriority(priority); + setState(() => selectedIdx = items.indexOf(priority)); + }, + ); + }, + ); + }, ); + if (isBitcoinWallet) sendViewModel.customBitcoinFeeRate = customFeeRate!.round(); } void _presentPicker(BuildContext context) { diff --git a/lib/src/screens/settings/other_settings_page.dart b/lib/src/screens/settings/other_settings_page.dart index fcf683050..90139e8c4 100644 --- a/lib/src/screens/settings/other_settings_page.dart +++ b/lib/src/screens/settings/other_settings_page.dart @@ -2,11 +2,12 @@ import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/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_version_cell.dart'; -import 'package:cake_wallet/src/widgets/standard_list.dart'; import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -27,13 +28,23 @@ class OtherSettingsPage extends BasePage { child: Column( children: [ if (_otherSettingsViewModel.displayTransactionPriority) - SettingsPickerCell( - title: S.current.settings_fee_priority, - items: priorityForWalletType(_otherSettingsViewModel.walletType), - displayItem: _otherSettingsViewModel.getDisplayPriority, - selectedItem: _otherSettingsViewModel.transactionPriority, - onItemSelected: _otherSettingsViewModel.onDisplayPrioritySelected, - ), + _otherSettingsViewModel.walletType == WalletType.bitcoin ? + SettingsPriorityPickerCell( + title: S.current.settings_fee_priority, + items: priorityForWalletType(_otherSettingsViewModel.walletType), + displayItem: _otherSettingsViewModel.getDisplayBitcoinPriority, + selectedItem: _otherSettingsViewModel.transactionPriority, + customItemIndex: _otherSettingsViewModel.customPriorityItemIndex, + onItemSelected: _otherSettingsViewModel.onDisplayBitcoinPrioritySelected, + customValue: _otherSettingsViewModel.customBitcoinFeeRate, + ) : + SettingsPickerCell( + title: S.current.settings_fee_priority, + items: priorityForWalletType(_otherSettingsViewModel.walletType), + displayItem: _otherSettingsViewModel.getDisplayPriority, + selectedItem: _otherSettingsViewModel.transactionPriority, + onItemSelected: _otherSettingsViewModel.onDisplayPrioritySelected, + ), if (_otherSettingsViewModel.changeRepresentativeEnabled) SettingsCellWithArrow( title: S.current.change_rep, diff --git a/lib/src/screens/settings/widgets/setting_priority_picker_cell.dart b/lib/src/screens/settings/widgets/setting_priority_picker_cell.dart new file mode 100644 index 000000000..bba44606d --- /dev/null +++ b/lib/src/screens/settings/widgets/setting_priority_picker_cell.dart @@ -0,0 +1,78 @@ +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:flutter/material.dart'; +import 'package:cake_wallet/src/widgets/picker.dart'; +import 'package:cake_wallet/src/widgets/standard_list.dart'; + +class SettingsPriorityPickerCell extends StandardListRow { + SettingsPriorityPickerCell( + {required String title, + required this.selectedItem, + required this.items, + this.displayItem, + this.images, + this.searchHintText, + this.isGridView = false, + this.matchingCriteria, + this.customValue, + this.customItemIndex, + this.onItemSelected}) + : super( + title: title, + isSelected: false, + onTap: (BuildContext context) async { + var selectedAtIndex = items.indexOf(selectedItem); + double sliderValue = customValue ?? 0.0; + + await showPopUp( + context: context, + builder: (BuildContext context) { + return StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return Picker( + items: items, + displayItem: (ItemType item) => displayItem!(item, sliderValue.round()), + selectedAtIndex: selectedAtIndex, + customItemIndex: customItemIndex, + headerEnabled: false, + closeOnItemSelected: false, + mainAxisAlignment: MainAxisAlignment.center, + sliderValue: sliderValue, + onSliderChanged: (double newValue) => + setState(() => sliderValue = newValue), + onItemSelected: (ItemType priority) { + setState(() => selectedAtIndex = items.indexOf(priority)); + onItemSelected?.call(priority, sliderValue); + }, + ); + }, + ); + }, + ); + onItemSelected?.call(items[selectedAtIndex], sliderValue); + }); + + final ItemType selectedItem; + final List items; + final void Function(ItemType item, double customValue)? onItemSelected; + final String Function(ItemType item, int value)? displayItem; + final List? images; + final String? searchHintText; + final bool isGridView; + final bool Function(ItemType, String)? matchingCriteria; + double? customValue; + int? customItemIndex; + + @override + Widget buildTrailing(BuildContext context) { + return Text( + displayItem?.call(selectedItem,customValue?.round() ?? 0) ?? selectedItem.toString(), + textAlign: TextAlign.right, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w500, + color: Theme.of(context).extension()!.detailsTitlesColor, + ), + ); + } +} diff --git a/lib/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart b/lib/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart new file mode 100644 index 000000000..8f722ee7e --- /dev/null +++ b/lib/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart @@ -0,0 +1,23 @@ +import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart'; + +class StandardPickerListItem extends TransactionDetailsListItem { + StandardPickerListItem( + {required String title, + required String value, + required this.items, + required this.displayItem, + required this.onSliderChanged, + required this.onItemSelected, + required this.selectedIdx, + required this.customItemIndex, + required this.customValue}) + : super(title: title, value: value); + + final List items; + final String Function(T item, double sliderValue) displayItem; + final Function(double) onSliderChanged; + final Function(T) onItemSelected; + final int selectedIdx; + final int customItemIndex; + double customValue; +} diff --git a/lib/src/screens/transaction_details/rbf_details_page.dart b/lib/src/screens/transaction_details/rbf_details_page.dart new file mode 100644 index 000000000..875e0a4ef --- /dev/null +++ b/lib/src/screens/transaction_details/rbf_details_page.dart @@ -0,0 +1,199 @@ +import 'package:cake_wallet/core/execution_state.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart'; +import 'package:cake_wallet/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart'; +import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; +import 'package:cake_wallet/src/screens/transaction_details/textfield_list_item.dart'; +import 'package:cake_wallet/src/screens/transaction_details/transaction_expandable_list_item.dart'; +import 'package:cake_wallet/src/screens/transaction_details/widgets/textfield_list_row.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/list_row.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/src/widgets/standard_expandable_list.dart'; +import 'package:cake_wallet/src/widgets/standard_list.dart'; +import 'package:cake_wallet/src/widgets/standard_picker_list.dart'; +import 'package:cake_wallet/utils/show_bar.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/view_model/send/send_view_model_state.dart'; +import 'package:cake_wallet/view_model/transaction_details_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:mobx/mobx.dart'; + +class RBFDetailsPage extends BasePage { + RBFDetailsPage({required this.transactionDetailsViewModel}); + + @override + String get title => S.current.bump_fee; + + final TransactionDetailsViewModel transactionDetailsViewModel; + + bool _effectsInstalled = false; + + @override + Widget body(BuildContext context) { + _setEffects(context); + + return Column( + children: [ + Expanded( + child: SectionStandardList( + sectionCount: 1, + itemCounter: (int _) => transactionDetailsViewModel.RBFListItems.length, + itemBuilder: (__, index) { + final item = transactionDetailsViewModel.RBFListItems[index]; + + if (item is StandartListItem) { + return GestureDetector( + onTap: () { + Clipboard.setData(ClipboardData(text: item.value)); + showBar(context, S.of(context).transaction_details_copied(item.title)); + }, + child: ListRow(title: '${item.title}:', value: item.value), + ); + } + + if (item is StandardExpandableListItem) { + return StandardExpandableList( + title: '${item.title}: ${item.expandableItems.length}', + expandableItems: item.expandableItems, + ); + } + + if (item is StandardPickerListItem) { + return StandardPickerList( + title: item.title, + value: item.value, + items: item.items, + displayItem: item.displayItem, + onSliderChanged: item.onSliderChanged, + onItemSelected: item.onItemSelected, + selectedIdx: item.selectedIdx, + customItemIndex: item.customItemIndex, + customValue: item.customValue, + ); + } + + if (item is TextFieldListItem) { + return TextFieldListRow( + title: item.title, + value: item.value, + onSubmitted: item.onSubmitted, + ); + } + + return Container(); + }), + ), + Padding( + padding: const EdgeInsets.all(24), + child: Observer( + builder: (_) => LoadingPrimaryButton( + onPressed: () async { + transactionDetailsViewModel + .replaceByFee(transactionDetailsViewModel.newFee.toString()); + }, + text: S.of(context).send, + isLoading: + transactionDetailsViewModel.sendViewModel.state is IsExecutingState, + color: Theme.of(context).primaryColor, + textColor: Colors.white, + ))), + ], + ); + } + + void _setEffects(BuildContext context) { + if (_effectsInstalled) { + return; + } + + reaction((_) => transactionDetailsViewModel.sendViewModel.state, (ExecutionState state) { + if (state is FailureState) { + WidgetsBinding.instance.addPostFrameCallback((_) { + showPopUp( + context: context, + builder: (BuildContext popupContext) { + return AlertWithOneAction( + alertTitle: S.of(popupContext).error, + alertContent: state.error, + buttonText: S.of(popupContext).ok, + buttonAction: () => Navigator.of(popupContext).pop()); + }); + }); + } + if (state is AwaitingConfirmationState) { + WidgetsBinding.instance.addPostFrameCallback((_) { + showPopUp( + context: context, + builder: (BuildContext popupContext) { + return AlertWithTwoActions( + alertTitle: state.title ?? '', + alertContent: state.message ?? '', + rightButtonText: S.of(context).ok, + leftButtonText: S.of(context).cancel, + actionRightButton: () { + state.onConfirm?.call(); + Navigator.of(popupContext).pop(); + }, + actionLeftButton: () { + state.onCancel?.call(); + Navigator.of(popupContext).pop(); + }); + }); + }); + } + + if (state is ExecutedSuccessfullyState) { + WidgetsBinding.instance.addPostFrameCallback((_) { + showPopUp( + context: context, + builder: (BuildContext popupContext) { + return ConfirmSendingAlert( + alertTitle: S.of(popupContext).confirm_sending, + amount: S.of(popupContext).send_amount, + amountValue: transactionDetailsViewModel + .sendViewModel.pendingTransaction!.amountFormatted, + fee: S.of(popupContext).send_fee, + feeValue: + transactionDetailsViewModel.sendViewModel.pendingTransaction!.feeFormatted, + rightButtonText: S.of(popupContext).send, + leftButtonText: S.of(popupContext).cancel, + actionRightButton: () async { + Navigator.of(popupContext).pop(); + await transactionDetailsViewModel.sendViewModel.commitTransaction(); + // transactionStatePopup(); + }, + actionLeftButton: () => Navigator.of(popupContext).pop(), + feeFiatAmount: + transactionDetailsViewModel.pendingTransactionFeeFiatAmountFormatted, + fiatAmountValue: + transactionDetailsViewModel.pendingTransactionFiatAmountValueFormatted, + outputs: transactionDetailsViewModel.sendViewModel.outputs); + }); + }); + } + + if (state is TransactionCommitted) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (context.mounted) { + showPopUp( + context: context, + builder: (BuildContext popupContext) { + return AlertWithOneAction( + alertTitle: S.of(popupContext).sending, + alertContent: S.of(popupContext).transaction_sent, + buttonText: S.of(popupContext).ok, + buttonAction: () => Navigator.of(popupContext).pop()); + }); + } + }); + } + }); + + _effectsInstalled = true; + } +} diff --git a/lib/src/screens/transaction_details/transaction_details_page.dart b/lib/src/screens/transaction_details/transaction_details_page.dart index a6f60a52d..7734f37ed 100644 --- a/lib/src/screens/transaction_details/transaction_details_page.dart +++ b/lib/src/screens/transaction_details/transaction_details_page.dart @@ -1,15 +1,18 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart'; +import 'package:cake_wallet/src/screens/transaction_details/blockexplorer_list_item.dart'; +import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; import 'package:cake_wallet/src/screens/transaction_details/textfield_list_item.dart'; import 'package:cake_wallet/src/screens/transaction_details/widgets/textfield_list_row.dart'; +import 'package:cake_wallet/src/widgets/list_row.dart'; import 'package:cake_wallet/src/widgets/standard_list.dart'; import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/view_model/transaction_details_view_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/widgets/list_row.dart'; -import 'package:cake_wallet/src/screens/transaction_details/blockexplorer_list_item.dart'; -import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; class TransactionDetailsPage extends BasePage { TransactionDetailsPage({required this.transactionDetailsViewModel}); @@ -21,41 +24,62 @@ class TransactionDetailsPage extends BasePage { @override Widget body(BuildContext context) { - return SectionStandardList( - sectionCount: 1, - itemCounter: (int _) => transactionDetailsViewModel.items.length, - itemBuilder: (__, index) { - final item = transactionDetailsViewModel.items[index]; + return Column( + children: [ + Expanded( + child: SectionStandardList( + sectionCount: 1, + itemCounter: (int _) => transactionDetailsViewModel.items.length, + itemBuilder: (__, index) { + final item = transactionDetailsViewModel.items[index]; - if (item is StandartListItem) { - return GestureDetector( - onTap: () { - Clipboard.setData(ClipboardData(text: item.value)); - showBar(context, - S.of(context).transaction_details_copied(item.title)); - }, - child: - ListRow(title: '${item.title}:', value: item.value), - ); - } + if (item is StandartListItem) { + return GestureDetector( + onTap: () { + Clipboard.setData(ClipboardData(text: item.value)); + showBar(context, S.of(context).transaction_details_copied(item.title)); + }, + child: ListRow(title: '${item.title}:', value: item.value), + ); + } - if (item is BlockExplorerListItem) { - return GestureDetector( - onTap: item.onTap, - child: - ListRow(title: '${item.title}:', value: item.value), - ); - } + if (item is BlockExplorerListItem) { + return GestureDetector( + onTap: item.onTap, + child: ListRow(title: '${item.title}:', value: item.value), + ); + } - if (item is TextFieldListItem) { - return TextFieldListRow( - title: item.title, - value: item.value, - onSubmitted: item.onSubmitted, - ); - } + if (item is TextFieldListItem) { + return TextFieldListRow( + title: item.title, + value: item.value, + onSubmitted: item.onSubmitted, + ); + } - return Container(); - }); + return Container(); + }), + ), + Observer( + builder: (_) { + if (transactionDetailsViewModel.canReplaceByFee) { + return Padding( + padding: const EdgeInsets.all(24), + child: SelectButton( + text: S.of(context).bump_fee, + onTap: () async { + Navigator.of(context).pushNamed(Routes.bumpFeePage, + arguments: transactionDetailsViewModel.transactionInfo); + }, + ), + ); + } + + return const SizedBox(); + }, + ), + ], + ); } } diff --git a/lib/src/screens/transaction_details/transaction_expandable_list_item.dart b/lib/src/screens/transaction_details/transaction_expandable_list_item.dart new file mode 100644 index 000000000..e87405de3 --- /dev/null +++ b/lib/src/screens/transaction_details/transaction_expandable_list_item.dart @@ -0,0 +1,7 @@ +import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart'; + +class StandardExpandableListItem extends TransactionDetailsListItem { + StandardExpandableListItem({required String title, required this.expandableItems}) + : super(title: title, value: ''); + final List expandableItems; +} diff --git a/lib/src/widgets/checkbox_widget.dart b/lib/src/widgets/checkbox_widget.dart index 1ea3ee698..a3c78d0cf 100644 --- a/lib/src/widgets/checkbox_widget.dart +++ b/lib/src/widgets/checkbox_widget.dart @@ -31,7 +31,6 @@ class CheckboxWidgetState extends State { }, child: Row( mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( height: 24.0, diff --git a/lib/src/widgets/picker.dart b/lib/src/widgets/picker.dart index 01b869b1b..d87b5721e 100644 --- a/lib/src/widgets/picker.dart +++ b/lib/src/widgets/picker.dart @@ -24,6 +24,13 @@ class Picker extends StatefulWidget { this.isGridView = false, this.isSeparated = true, this.hintText, + this.headerEnabled = true, + this.closeOnItemSelected = true, + this.sliderValue, + this.customItemIndex, + this.isWrapped = true, + this.borderColor, + this.onSliderChanged, this.matchingCriteria, }) : assert(hintText == null || matchingCriteria != @@ -40,6 +47,13 @@ class Picker extends StatefulWidget { final bool isGridView; final bool isSeparated; final String? hintText; + final bool headerEnabled; + final bool closeOnItemSelected; + final double? sliderValue; + final int? customItemIndex; + final bool isWrapped; + final Color? borderColor; + final Function(double)? onSliderChanged; final bool Function(Item, String)? matchingCriteria; @override @@ -124,8 +138,7 @@ class _PickerState extends State> { containerHeight = height * 0.75; } - return PickerWrapperWidget( - hasTitle: widget.title?.isNotEmpty ?? false, + final content = Column ( children: [ if (widget.title?.isNotEmpty ?? false) Container( @@ -144,61 +157,71 @@ class _PickerState extends State> { ), Padding( padding: EdgeInsets.symmetric(horizontal: padding), - child: ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(30)), - child: Container( - color: Theme.of(context).dialogTheme.backgroundColor, - child: ConstrainedBox( - constraints: BoxConstraints( - maxHeight: containerHeight, - maxWidth: ResponsiveLayoutUtilBase.kPopupWidth, - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - if (widget.hintText != null) - Padding( - padding: const EdgeInsets.all(16), - child: SearchBarWidget(searchController: searchController), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + border: Border.all( + color: widget.borderColor ?? Colors.transparent, + ), + ), + child: ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(30)), + child: Container( + color: Theme.of(context).dialogTheme.backgroundColor, + child: ConstrainedBox( + constraints: BoxConstraints( + maxHeight: containerHeight, + maxWidth: ResponsiveLayoutUtilBase.kPopupWidth, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (widget.hintText != null) + Padding( + padding: const EdgeInsets.all(16), + child: SearchBarWidget( + searchController: searchController, hintText: widget.hintText), + ), + Divider( + color: Theme.of(context).extension()!.dividerColor, + height: 1, ), - Divider( - color: Theme.of(context).extension()!.dividerColor, - height: 1, - ), - if (widget.selectedAtIndex != -1) buildSelectedItem(widget.selectedAtIndex), - Flexible( - child: Stack( - alignment: Alignment.center, - children: [ - filteredItems.length > 3 - ? Scrollbar( - controller: controller, - child: itemsList(), - ) - : itemsList(), - (widget.description?.isNotEmpty ?? false) - ? Positioned( - bottom: padding, - left: padding, - right: padding, - child: Text( - widget.description!, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - fontFamily: 'Lato', - decoration: TextDecoration.none, - color: - Theme.of(context).extension()!.titleColor, + if (widget.selectedAtIndex != -1 && widget.headerEnabled) + buildSelectedItem(widget.selectedAtIndex), + Flexible( + child: Stack( + alignment: Alignment.center, + children: [ + filteredItems.length > 3 + ? Scrollbar( + controller: controller, + child: itemsList(), + ) + : itemsList(), + (widget.description?.isNotEmpty ?? false) + ? Positioned( + bottom: padding, + left: padding, + right: padding, + child: Text( + widget.description!, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + fontFamily: 'Lato', + decoration: TextDecoration.none, + color: + Theme.of(context).extension()!.titleColor, + ), ), - ), - ) - : Offstage(), - ], + ) + : Offstage(), + ], + ), ), - ), - ], + ], + ), ), ), ), @@ -206,9 +229,23 @@ class _PickerState extends State> { ) ], ); + + if (widget.isWrapped) { + return PickerWrapperWidget( + hasTitle: widget.title?.isNotEmpty ?? false, + children: [content], + ); + } else { + return content; + } } Widget itemsList() { + final itemCount = !widget.headerEnabled + ? items.length + : filteredItems.isEmpty + ? 0 + : filteredItems.length; return Container( color: Theme.of(context).extension()!.dividerColor, child: widget.isGridView @@ -216,13 +253,16 @@ class _PickerState extends State> { padding: EdgeInsets.zero, controller: controller, shrinkWrap: true, - itemCount: filteredItems.isEmpty ? 0 : filteredItems.length, + itemCount: itemCount, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 2, childAspectRatio: 3, ), - itemBuilder: (context, index) => buildItem(index), + itemBuilder: (context, index) => + !widget.headerEnabled && widget.selectedAtIndex == index + ? buildSelectedItem(index) + : buildItem(index), ) : ListView.separated( padding: EdgeInsets.zero, @@ -234,83 +274,97 @@ class _PickerState extends State> { height: 1, ) : const SizedBox(), - itemCount: filteredItems.isEmpty ? 0 : filteredItems.length, - itemBuilder: (context, index) => buildItem(index), + itemCount: itemCount, + itemBuilder: (context, index) => + !widget.headerEnabled && widget.selectedAtIndex == index + ? buildSelectedItem(index) + : buildItem(index), ), ); } Widget buildItem(int index) { - final item = filteredItems[index]; + final item = widget.headerEnabled ? filteredItems[index] : items[index]; final tag = item is Currency ? item.tag : null; final icon = _getItemIcon(item); final image = images.isNotEmpty ? filteredImages[index] : icon; + final isCustomItem = widget.customItemIndex != null && index == widget.customItemIndex; + + final itemContent = Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: widget.mainAxisAlignment, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + image ?? Offstage(), + Expanded( + child: Padding( + padding: EdgeInsets.only(left: image != null ? 12 : 0), + child: Row( + children: [ + Flexible( + child: Text( + widget.displayItem?.call(item) ?? item.toString(), + softWrap: true, + style: TextStyle( + fontSize: 14, + fontFamily: 'Lato', + fontWeight: FontWeight.w600, + color: Theme.of(context).extension()!.titleColor, + decoration: TextDecoration.none, + ), + ), + ), + if (tag != null) + Align( + alignment: Alignment.topCenter, + child: Container( + width: 35.0, + height: 18.0, + child: Center( + child: Text( + tag, + style: TextStyle( + fontSize: 7.0, + fontFamily: 'Lato', + color: Theme.of(context).extension()!.thumbColor, + ), + ), + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6.0), + //border: Border.all(color: ), + color: Theme.of(context).extension()!.trackColor, + ), + ), + ), + ], + ), + ), + ), + ], + ); + return GestureDetector( onTap: () { - Navigator.of(context).pop(); + if (widget.closeOnItemSelected) Navigator.of(context).pop(); onItemSelected(item!); }, child: Container( - height: 55, + height: isCustomItem ? 95 : 55, color: Theme.of(context).dialogTheme.backgroundColor, padding: EdgeInsets.symmetric(horizontal: 24), - child: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: widget.mainAxisAlignment, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - image ?? Offstage(), - Expanded( - child: Padding( - padding: EdgeInsets.only(left: image != null ? 12 : 0), - child: Row( - children: [ - Flexible( - child: Text( - widget.displayItem?.call(item) ?? item.toString(), - softWrap: true, - style: TextStyle( - fontSize: 14, - fontFamily: 'Lato', - fontWeight: FontWeight.w600, - color: Theme.of(context).extension()!.titleColor, - decoration: TextDecoration.none, - ), - ), - ), - if (tag != null) - Align( - alignment: Alignment.topCenter, - child: Container( - width: 35.0, - height: 18.0, - child: Center( - child: Text( - tag, - style: TextStyle( - fontSize: 7.0, - fontFamily: 'Lato', - color: - Theme.of(context).extension()!.thumbColor, - ), - ), - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(6.0), - //border: Border.all(color: ), - color: Theme.of(context).extension()!.trackColor, - ), - ), - ), - ], - ), - ), - ), - ], - ), + child: isCustomItem + ? Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + itemContent, + buildSlider(index: index, isActivated: widget.selectedAtIndex == index) + ], + ) + : itemContent, ), ); } @@ -323,69 +377,80 @@ class _PickerState extends State> { final image = images.isNotEmpty ? images[index] : icon; - return GestureDetector( - onTap: () { - Navigator.of(context).pop(); - }, - child: Container( - height: 55, - color: Theme.of(context).dialogTheme.backgroundColor, - padding: EdgeInsets.symmetric(horizontal: 24), - child: Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: widget.mainAxisAlignment, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - image ?? Offstage(), - Expanded( - child: Padding( - padding: EdgeInsets.only(left: image != null ? 12 : 0), - child: Row( - children: [ - Flexible( - child: Text( - widget.displayItem?.call(item) ?? item.toString(), - softWrap: true, - style: TextStyle( - fontSize: 16, - fontFamily: 'Lato', - fontWeight: FontWeight.w700, - color: Theme.of(context).extension()!.titleColor, - decoration: TextDecoration.none, + final isCustomItem = widget.customItemIndex != null && index == widget.customItemIndex; + + final itemContent = Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: widget.mainAxisAlignment, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + image ?? Offstage(), + Expanded( + child: Padding( + padding: EdgeInsets.only(left: image != null ? 12 : 0), + child: Row( + children: [ + Flexible( + child: Text( + widget.displayItem?.call(item) ?? item.toString(), + softWrap: true, + style: TextStyle( + fontSize: 16, + fontFamily: 'Lato', + fontWeight: FontWeight.w700, + color: Theme.of(context).extension()!.titleColor, + decoration: TextDecoration.none, + ), + ), + ), + if (tag != null) + Align( + alignment: Alignment.topCenter, + child: Container( + width: 35.0, + height: 18.0, + child: Center( + child: Text( + tag, + style: TextStyle( + fontSize: 7.0, + fontFamily: 'Lato', + color: Theme.of(context).extension()!.thumbColor, + ), ), ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6.0), + //border: Border.all(color: ), + color: Theme.of(context).extension()!.trackColor, + ), ), - if (tag != null) - Align( - alignment: Alignment.topCenter, - child: Container( - width: 35.0, - height: 18.0, - child: Center( - child: Text( - tag, - style: TextStyle( - fontSize: 7.0, - fontFamily: 'Lato', - color: - Theme.of(context).extension()!.thumbColor, - ), - ), - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(6.0), - //border: Border.all(color: ), - color: Theme.of(context).extension()!.trackColor, - ), - ), - ), - ], - ), - ), + ), + ], ), - Icon(Icons.check_circle, color: Theme.of(context).primaryColor), - ], + ), ), + Icon(Icons.check_circle, color: Theme.of(context).primaryColor), + ], + ); + + return GestureDetector( + onTap: () { + if (widget.closeOnItemSelected) Navigator.of(context).pop(); + }, + child: Container( + height: isCustomItem ? 95 : 55, + color: Theme.of(context).dialogTheme.backgroundColor, + padding: EdgeInsets.symmetric(horizontal: 24), + child: isCustomItem + ? Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + itemContent, + buildSlider(index: index, isActivated: widget.selectedAtIndex == index) + ], + ) + : itemContent, ), ); } @@ -418,4 +483,20 @@ class _PickerState extends State> { return null; } + + Widget buildSlider({required int index, required bool isActivated}) { + return Row( + children: [ + Expanded( + child: Slider( + value: widget.sliderValue ?? 1, + onChanged: isActivated ? widget.onSliderChanged : null, + min: 1, + max: 100, + divisions: 100, + ), + ), + ], + ); + } } diff --git a/lib/src/widgets/search_bar_widget.dart b/lib/src/widgets/search_bar_widget.dart index dc604934f..45155b380 100644 --- a/lib/src/widgets/search_bar_widget.dart +++ b/lib/src/widgets/search_bar_widget.dart @@ -19,7 +19,7 @@ class SearchBarWidget extends StatelessWidget { controller: searchController, style: TextStyle(color: Theme.of(context).extension()!.searchHintColor), decoration: InputDecoration( - hintText: hintText ?? S.of(context).search_currency, + 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), diff --git a/lib/src/widgets/standard_expandable_list.dart b/lib/src/widgets/standard_expandable_list.dart new file mode 100644 index 000000000..d1bcae646 --- /dev/null +++ b/lib/src/widgets/standard_expandable_list.dart @@ -0,0 +1,58 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart'; +import 'package:flutter/material.dart'; + +class StandardExpandableList extends StatelessWidget { + StandardExpandableList({ + required this.title, + required this.expandableItems, + this.decoration, + }); + + final String title; + final List expandableItems; + final Decoration? decoration; + + @override + Widget build(BuildContext context) { + return Container( + decoration: decoration ?? + BoxDecoration( + color: Theme.of(context).colorScheme.background, + ), + child: Theme( + data: Theme.of(context).copyWith(dividerColor: Colors.transparent), + child: ExpansionTile( + iconColor: Theme.of(context).extension()!.detailsTitlesColor, + collapsedIconColor: + Theme.of(context).extension()!.detailsTitlesColor, + title: Text( + title, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Theme.of(context).extension()!.detailsTitlesColor, + ), + textAlign: TextAlign.left, + ), + children: expandableItems.map((item) { + return Padding( + padding: const EdgeInsets.only(left: 16.0, bottom: 8.0), + child: Align( + alignment: Alignment.centerLeft, + child: Text( + item.toString(), + maxLines: 1, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).extension()!.titleColor), + ), + ), + ); + }).toList(), + ), + ), + ); + } +} diff --git a/lib/src/widgets/standard_picker_list.dart b/lib/src/widgets/standard_picker_list.dart new file mode 100644 index 000000000..eb1d16900 --- /dev/null +++ b/lib/src/widgets/standard_picker_list.dart @@ -0,0 +1,81 @@ +import 'package:cake_wallet/src/widgets/list_row.dart'; +import 'package:cake_wallet/src/widgets/picker.dart'; +import 'package:cake_wallet/themes/extensions/picker_theme.dart'; +import 'package:flutter/material.dart'; + +class StandardPickerList extends StatefulWidget { + StandardPickerList({ + Key? key, + required this.title, + required this.value, + required this.items, + required this.displayItem, + required this.onSliderChanged, + required this.onItemSelected, + required this.selectedIdx, + required this.customItemIndex, + required this.customValue, + }) : super(key: key); + + final String title; + final List items; + final int customItemIndex; + final String Function(T item, double sliderValue) displayItem; + final Function(double) onSliderChanged; + final Function(T) onItemSelected; + final String value; + final int selectedIdx; + final double customValue; + + @override + _StandardPickerListState createState() => _StandardPickerListState(); +} + +class _StandardPickerListState extends State> { + late String value; + late int selectedIdx; + late double customValue; + + @override + void initState() { + super.initState(); + + value = widget.value; + selectedIdx = widget.selectedIdx; + customValue = widget.customValue; + } + + @override + Widget build(BuildContext context) { + String adaptedDisplayItem(T item) => widget.displayItem(item, customValue); + + return Column( + children: [ + ListRow(title: '${widget.title}:', value: value), + Padding( + padding: const EdgeInsets.only(left: 24, right: 24, top: 0, bottom: 24), + child: Picker( + items: widget.items, + displayItem: adaptedDisplayItem, + selectedAtIndex: selectedIdx, + customItemIndex: widget.customItemIndex, + headerEnabled: false, + closeOnItemSelected: false, + mainAxisAlignment: MainAxisAlignment.center, + sliderValue: customValue, + isWrapped: false, + borderColor: Theme.of(context).extension()!.dividerColor, + onSliderChanged: (newValue) { + setState(() => customValue = newValue); + value = widget.onSliderChanged(newValue).toString(); + }, + onItemSelected: (T item) { + setState(() => selectedIdx = widget.items.indexOf(item)); + value = widget.onItemSelected(item).toString(); + }, + ), + ), + ], + ); + } +} diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 9997e2675..df2b438b4 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -105,6 +105,7 @@ abstract class SettingsStoreBase with Store { required this.lookupsUnstoppableDomains, required this.lookupsOpenAlias, required this.lookupsENS, + required this.customBitcoinFeeRate, TransactionPriority? initialBitcoinTransactionPriority, TransactionPriority? initialMoneroTransactionPriority, TransactionPriority? initialHavenTransactionPriority, @@ -504,6 +505,11 @@ abstract class SettingsStoreBase with Store { (PinCodeRequiredDuration pinCodeInterval) => secureStorage.write( key: SecureKey.pinTimeOutDuration, value: pinCodeInterval.value.toString())); + reaction( + (_) => customBitcoinFeeRate, + (int customBitcoinFeeRate) => + _sharedPreferences.setInt(PreferencesKey.customBitcoinFeeRate, customBitcoinFeeRate)); + this.nodes.observe((change) { if (change.newValue != null && change.key != null) { _saveCurrentNode(change.newValue!, change.key!); @@ -690,6 +696,9 @@ abstract class SettingsStoreBase with Store { String deviceName; + @observable + int customBitcoinFeeRate; + final FlutterSecureStorage _secureStorage; final SharedPreferences _sharedPreferences; final BackgroundTasks _backgroundTasks; @@ -834,6 +843,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true; final lookupsOpenAlias = sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias) ?? true; final lookupsENS = sharedPreferences.getBool(PreferencesKey.lookupsENS) ?? true; + final customBitcoinFeeRate = sharedPreferences.getInt(PreferencesKey.customBitcoinFeeRate) ?? 1; // If no value if (pinLength == null || pinLength == 0) { @@ -1068,6 +1078,7 @@ abstract class SettingsStoreBase with Store { lookupsUnstoppableDomains: lookupsUnstoppableDomains, lookupsOpenAlias: lookupsOpenAlias, lookupsENS: lookupsENS, + customBitcoinFeeRate: customBitcoinFeeRate, initialMoneroTransactionPriority: moneroTransactionPriority, initialBitcoinTransactionPriority: bitcoinTransactionPriority, initialHavenTransactionPriority: havenTransactionPriority, @@ -1159,7 +1170,8 @@ abstract class SettingsStoreBase with Store { isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? isAppSecure; disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? disableBuy; disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? disableSell; - disableBulletin = sharedPreferences.getBool(PreferencesKey.disableBulletinKey) ?? disableBulletin; + disableBulletin = + sharedPreferences.getBool(PreferencesKey.disableBulletinKey) ?? disableBulletin; walletListOrder = WalletListOrderType.values[sharedPreferences.getInt(PreferencesKey.walletListOrder) ?? 0]; walletListAscending = sharedPreferences.getBool(PreferencesKey.walletListAscending) ?? true; @@ -1200,7 +1212,7 @@ abstract class SettingsStoreBase with Store { sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true; lookupsOpenAlias = sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias) ?? true; lookupsENS = sharedPreferences.getBool(PreferencesKey.lookupsENS) ?? true; - + customBitcoinFeeRate = sharedPreferences.getInt(PreferencesKey.customBitcoinFeeRate) ?? 1; final nodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey); final bitcoinElectrumServerId = sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey); diff --git a/lib/view_model/send/output.dart b/lib/view_model/send/output.dart index 62db9cbcd..6bb3fbb31 100644 --- a/lib/view_model/send/output.dart +++ b/lib/view_model/send/output.dart @@ -121,11 +121,19 @@ abstract class OutputBase with Store { return solana!.getEstimateFees(_wallet) ?? 0.0; } - final fee = _wallet.calculateEstimatedFee( + int? fee = _wallet.calculateEstimatedFee( _settingsStore.priority[_wallet.type]!, formattedCryptoAmount); - if (_wallet.type == WalletType.bitcoin || - _wallet.type == WalletType.litecoin || + if (_wallet.type == WalletType.bitcoin) { + if (_settingsStore.priority[_wallet.type] == bitcoin!.getBitcoinTransactionPriorityCustom()) { + fee = bitcoin!.getFeeAmountWithFeeRate( + _settingsStore.customBitcoinFeeRate, formattedCryptoAmount, 1, 1); + } + + return bitcoin!.formatterBitcoinAmountToDouble(amount: fee); + } + + if (_wallet.type == WalletType.litecoin || _wallet.type == WalletType.bitcoinCash) { return bitcoin!.formatterBitcoinAmountToDouble(amount: fee); } diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index df1c75def..28cd0128f 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -39,6 +39,7 @@ import 'package:cake_wallet/entities/parsed_address.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/haven/haven.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:collection/collection.dart'; part 'send_view_model.g.dart'; @@ -68,9 +69,12 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor _settingsStore = appStore.settingsStore, fiatFromSettings = appStore.settingsStore.fiatCurrency, super(appStore: appStore) { + if (wallet.type == WalletType.bitcoin && + _settingsStore.priority[wallet.type] == bitcoinTransactionPriorityCustom) { + setTransactionPriority(bitcoinTransactionPriorityMedium); + } final priority = _settingsStore.priority[wallet.type]; final priorities = priorityForWalletType(wallet.type); - if (!priorityForWalletType(wallet.type).contains(priority) && priorities.isNotEmpty) { _settingsStore.priority[wallet.type] = priorities.first; } @@ -152,6 +156,21 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor return priority; } + + int? getCustomPriorityIndex(List priorities) { + if (wallet.type == WalletType.bitcoin) { + final customItem = priorities.firstWhereOrNull((element) => element == bitcoin!.getBitcoinTransactionPriorityCustom()); + + return customItem != null ? priorities.indexOf(customItem) : null; + } + return null; + } + + @computed + int get customBitcoinFeeRate => _settingsStore.customBitcoinFeeRate; + + void set customBitcoinFeeRate(int value) => _settingsStore.customBitcoinFeeRate = value; + CryptoCurrency get currency => wallet.currency; Validator get amountValidator => @@ -323,6 +342,29 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor return null; } + @action + Future replaceByFee(String txId, String newFee) async { + state = IsExecutingState(); + + final isSufficient = await bitcoin!.isChangeSufficientForFee(wallet, txId, newFee); + + if (!isSufficient) { + state = AwaitingConfirmationState( + title: S.current.confirm_fee_deduction, + message: S.current.confirm_fee_deduction_content, + onConfirm: () async { + pendingTransaction = await bitcoin!.replaceByFee(wallet, txId, newFee); + state = ExecutedSuccessfullyState(); + }, + onCancel: () { + state = FailureState('Insufficient change for fee'); + }); + } else { + pendingTransaction = await bitcoin!.replaceByFee(wallet, txId, newFee); + state = ExecutedSuccessfullyState(); + } + } + @action Future commitTransaction() async { if (pendingTransaction == null) { @@ -380,7 +422,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor case WalletType.bitcoin: case WalletType.litecoin: case WalletType.bitcoinCash: - return bitcoin!.createBitcoinTransactionCredentials(outputs, priority: priority!); + return bitcoin!.createBitcoinTransactionCredentials(outputs, + priority: priority!, feeRate: customBitcoinFeeRate); case WalletType.monero: return monero! @@ -406,9 +449,14 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor } } - String displayFeeRate(dynamic priority) { + String displayFeeRate(dynamic priority, int? customValue) { final _priority = priority as TransactionPriority; + if (walletType == WalletType.bitcoin) { + final rate = bitcoin!.getFeeRate(wallet, _priority); + return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate, customRate: customValue); + } + if (isElectrumWallet) { final rate = bitcoin!.getFeeRate(wallet, _priority); return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate); @@ -420,6 +468,12 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor bool _isEqualCurrency(String currency) => wallet.balance.keys.any((e) => currency.toLowerCase() == e.title.toLowerCase()); + TransactionPriority get bitcoinTransactionPriorityCustom => + bitcoin!.getBitcoinTransactionPriorityCustom(); + + TransactionPriority get bitcoinTransactionPriorityMedium => + bitcoin!.getBitcoinTransactionPriorityMedium(); + @action void onClose() => _settingsStore.fiatCurrency = fiatFromSettings; diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart index 263532d29..cf410a1a9 100644 --- a/lib/view_model/settings/other_settings_view_model.dart +++ b/lib/view_model/settings/other_settings_view_model.dart @@ -11,6 +11,7 @@ import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; import 'package:package_info/package_info.dart'; +import 'package:collection/collection.dart'; part 'other_settings_view_model.g.dart'; @@ -77,6 +78,8 @@ abstract class OtherSettingsViewModelBase with Store { ProviderType get sellProviderType => _settingsStore.defaultSellProviders[walletType] ?? ProviderType.askEachTime; + + String getDisplayPriority(dynamic priority) { final _priority = priority as TransactionPriority; @@ -90,6 +93,19 @@ abstract class OtherSettingsViewModelBase with Store { return priority.toString(); } + String getDisplayBitcoinPriority(dynamic priority, int customValue) { + final _priority = priority as TransactionPriority; + + if (_wallet.type == WalletType.bitcoin || + _wallet.type == WalletType.litecoin || + _wallet.type == WalletType.bitcoinCash) { + final rate = bitcoin!.getFeeRate(_wallet, _priority); + return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate, customRate: customValue); + } + + return priority.toString(); + } + String getBuyProviderType(dynamic buyProviderType) { final _buyProviderType = buyProviderType as ProviderType; return _buyProviderType == ProviderType.askEachTime @@ -105,7 +121,24 @@ abstract class OtherSettingsViewModelBase with Store { } void onDisplayPrioritySelected(TransactionPriority priority) => - _settingsStore.priority[_wallet.type] = priority; + _settingsStore.priority[walletType] = priority; + + void onDisplayBitcoinPrioritySelected(TransactionPriority priority, double customValue) { + if (_wallet.type == WalletType.bitcoin) { + _settingsStore.customBitcoinFeeRate = customValue.round(); + } + _settingsStore.priority[_wallet.type] = priority; + } + + @computed + double get customBitcoinFeeRate => _settingsStore.customBitcoinFeeRate.toDouble(); + + int? get customPriorityItemIndex { + final priorities = priorityForWalletType(walletType); + final customItem = priorities + .firstWhereOrNull((element) => element == bitcoin!.getBitcoinTransactionPriorityCustom()); + return customItem != null ? priorities.indexOf(customItem) : null; + } @action ProviderType onBuyProviderTypeSelected(ProviderType buyProviderType) => diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index 1b1ceb814..fd6d3ef6e 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -1,20 +1,27 @@ -import 'package:cw_core/wallet_base.dart'; -import 'package:cw_core/transaction_info.dart'; -import 'package:cw_core/wallet_type.dart'; +import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; +import 'package:cake_wallet/entities/transaction_description.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/monero/monero.dart'; +import 'package:cake_wallet/src/screens/transaction_details/blockexplorer_list_item.dart'; +import 'package:cake_wallet/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart'; import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart'; import 'package:cake_wallet/src/screens/transaction_details/textfield_list_item.dart'; import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart'; -import 'package:cake_wallet/src/screens/transaction_details/blockexplorer_list_item.dart'; -import 'package:cw_core/transaction_direction.dart'; +import 'package:cake_wallet/src/screens/transaction_details/transaction_expandable_list_item.dart'; +import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/utils/date_formatter.dart'; -import 'package:cake_wallet/entities/transaction_description.dart'; +import 'package:cake_wallet/view_model/send/send_view_model.dart'; +import 'package:collection/collection.dart'; +import 'package:cw_core/transaction_direction.dart'; +import 'package:cw_core/transaction_info.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; import 'package:intl/src/intl/date_format.dart'; import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/store/settings_store.dart'; -import 'package:cake_wallet/generated/i18n.dart'; import 'package:url_launcher/url_launcher.dart'; -import 'package:cake_wallet/monero/monero.dart'; part 'transaction_details_view_model.g.dart'; @@ -26,8 +33,11 @@ abstract class TransactionDetailsViewModelBase with Store { {required this.transactionInfo, required this.transactionDescriptionBox, required this.wallet, - required this.settingsStore}) + required this.settingsStore, + required this.sendViewModel}) : items = [], + RBFListItems = [], + newFee = 0, isRecipientAddressShown = false, showRecipientAddress = settingsStore.shouldSaveRecipientAddress { final dateFormat = DateFormatter.withCurrentLocal(); @@ -38,6 +48,10 @@ abstract class TransactionDetailsViewModelBase with Store { _addMoneroListItems(tx, dateFormat); break; case WalletType.bitcoin: + _addElectrumListItems(tx, dateFormat); + _addBumpFeesListItems(tx); + _checkForRBF(); + break; case WalletType.litecoin: case WalletType.bitcoinCash: _addElectrumListItems(tx, dateFormat); @@ -109,10 +123,20 @@ abstract class TransactionDetailsViewModelBase with Store { final Box transactionDescriptionBox; final SettingsStore settingsStore; final WalletBase wallet; + final SendViewModel sendViewModel; final List items; + final List RBFListItems; bool showRecipientAddress; bool isRecipientAddressShown; + int newFee; + TransactionPriority? transactionPriority; + + @observable + bool _canReplaceByFee = false; + + @computed + bool get canReplaceByFee => _canReplaceByFee /*&& transactionInfo.confirmations <= 0*/; String _explorerUrl(WalletType type, String txId) { switch (type) { @@ -305,4 +329,88 @@ abstract class TransactionDetailsViewModelBase with Store { items.addAll(_items); } + + void _addBumpFeesListItems(TransactionInfo tx) { + transactionPriority = bitcoin!.getBitcoinTransactionPriorityMedium(); + + newFee = bitcoin!.getFeeAmountForPriority( + wallet, + bitcoin!.getBitcoinTransactionPriorityMedium(), + transactionInfo.inputAddresses?.length ?? 1, + transactionInfo.outputAddresses?.length ?? 1); + + RBFListItems.add(StandartListItem( + title: S.current.old_fee, + value: tx.feeFormatted() ?? '0.0')); + + final priorities = priorityForWalletType(wallet.type); + final selectedItem = priorities.indexOf(sendViewModel.transactionPriority); + final customItem = priorities.firstWhereOrNull( + (element) => element == sendViewModel.bitcoinTransactionPriorityCustom); + final customItemIndex = customItem != null ? priorities.indexOf(customItem) : null; + + RBFListItems.add(StandardPickerListItem( + title: S.current.estimated_new_fee, + value: bitcoin!.formatterBitcoinAmountToString(amount: newFee) + ' ${walletTypeToCryptoCurrency(wallet.type)}', + items: priorityForWalletType(wallet.type), + customValue: settingsStore.customBitcoinFeeRate.toDouble(), + selectedIdx: selectedItem, + customItemIndex: customItemIndex ?? 0, + displayItem: (dynamic priority, double sliderValue) => + sendViewModel.displayFeeRate(priority, sliderValue.round()), + onSliderChanged: (double newValue) => + setNewFee(value: newValue, priority: transactionPriority!), + onItemSelected: (dynamic item) { + transactionPriority = item as TransactionPriority; + return setNewFee(priority: transactionPriority!); + })); + + if (transactionInfo.inputAddresses != null) { + RBFListItems.add(StandardExpandableListItem( + title: S.current.inputs, expandableItems: transactionInfo.inputAddresses!)); + } + + if (transactionInfo.outputAddresses != null) { + RBFListItems.add(StandardExpandableListItem( + title: S.current.outputs, expandableItems: transactionInfo.outputAddresses!)); + } + } + + @action + Future _checkForRBF() async { + if (wallet.type == WalletType.bitcoin && + transactionInfo.direction == TransactionDirection.outgoing) { + if (await bitcoin!.canReplaceByFee(wallet, transactionInfo.id)) { + _canReplaceByFee = true; + } + } + } + + String setNewFee({double? value, required TransactionPriority priority}) { + newFee = priority == bitcoin!.getBitcoinTransactionPriorityCustom() && value != null + ? bitcoin!.getFeeAmountWithFeeRate( + wallet, + value.round(), + transactionInfo.inputAddresses?.length ?? 1, + transactionInfo.outputAddresses?.length ?? 1) + : bitcoin!.getFeeAmountForPriority( + wallet, + priority, + transactionInfo.inputAddresses?.length ?? 1, + transactionInfo.outputAddresses?.length ?? 1); + + return bitcoin!.formatterBitcoinAmountToString(amount: newFee); + } + + void replaceByFee(String newFee) => sendViewModel.replaceByFee(transactionInfo.id, newFee); + + @computed + String get pendingTransactionFiatAmountValueFormatted => sendViewModel.isFiatDisabled + ? '' + : sendViewModel.pendingTransactionFiatAmount + ' ' + sendViewModel.fiat.title; + + @computed + String get pendingTransactionFeeFiatAmountFormatted => sendViewModel.isFiatDisabled + ? '' + : sendViewModel.pendingTransactionFeeFiatAmount + ' ' + sendViewModel.fiat.title; } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index d4d0d664d..08815bf1d 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "تتطلب مدفوعات Bitcoin تأكيدًا واحدًا ، والذي قد يستغرق 20 دقيقة أو أكثر. شكرا لصبرك! سيتم إرسال بريد إلكتروني إليك عند تأكيد الدفع.", "Blocks_remaining": "بلوك متبقي ${status}", "bright_theme": "مشرق", + "bump_fee": "رسوم عثرة", "buy": "اشتري", "buy_alert_content": ".ﺎﻬﻴﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻭﺃ Monero ﻭﺃ Litecoin ﻭﺃ Ethereum ﻭﺃ Bitcoin ﺔﻈﻔﺤﻣ ءﺎﺸﻧﺇ ﻰﺟﺮﻳ .", "buy_bitcoin": "شراء Bitcoin", @@ -133,6 +134,8 @@ "confirm": "تأكيد", "confirm_delete_template": "سيؤدي هذا الإجراء إلى حذف هذا القالب. هل ترغب في الاستمرار؟", "confirm_delete_wallet": "سيؤدي هذا الإجراء إلى حذف هذه المحفظة. هل ترغب في الاستمرار؟", + "confirm_fee_deduction": "تأكيد خصم الرسوم", + "confirm_fee_deduction_content": "هل توافق على خصم الرسوم من الإخراج؟", "confirm_sending": "تأكيد الإرسال", "confirmations": "التأكيدات", "confirmed": "رصيد مؤكد", @@ -212,6 +215,7 @@ "edit_token": "تحرير الرمز المميز", "electrum_address_disclaimer": "نقوم بإنشاء عناوين جديدة في كل مرة تستخدم فيها عنوانًا ، لكن العناوين السابقة تستمر في العمل", "email_address": "عنوان البريد الالكترونى", + "enable_replace_by_fee": "تمكين الاستبدال", "enabled": "ممكنة", "enter_amount": "أدخل المبلغ", "enter_backup_password": "أدخل كلمة المرور الاحتياطية هنا", @@ -248,6 +252,7 @@ "errorGettingCredentials": "ﺩﺎﻤﺘﻋﻻﺍ ﺕﺎﻧﺎﻴﺑ ﻰﻠﻋ ﻝﻮﺼﺤﻟﺍ ءﺎﻨﺛﺃ ﺄﻄﺧ ﺙﺪﺣ :ﻞﺸﻓ", "errorSigningTransaction": "ﺔﻠﻣﺎﻌﻤﻟﺍ ﻊﻴﻗﻮﺗ ءﺎﻨﺛﺃ ﺄﻄﺧ ﺙﺪﺣ", "estimated": "مُقدَّر", + "estimated_new_fee": "رسوم جديدة مقدرة", "etherscan_history": "Etherscan تاريخ", "event": "ﺙﺪﺣ", "events": "ﺙﺍﺪﺣﻷﺍ", @@ -314,6 +319,7 @@ "in_store": "في المتجر", "incoming": "الواردة", "incorrect_seed": "النص الذي تم إدخاله غير صالح.", + "inputs": "المدخلات", "introducing_cake_pay": "نقدم لكم Cake Pay!", "invalid_input": "مدخل غير صالح", "invoice_details": "تفاصيل الفاتورة", @@ -381,6 +387,7 @@ "offer_expires_in": "ينتهي العرض في:", "offline": "غير متصل على الانترنت", "ok": "حسناً", + "old_fee": "الرسوم القديمة", "onion_link": "رابط البصل", "online": "متصل", "onramper_option_description": "شراء بسرعة التشفير مع العديد من طرق الدفع. متوفر في معظم البلدان. ينتشر وتختلف الرسوم.", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "محافظ Bitcoin الجديدة التي تم إنشاؤها في Cake الآن سييد مكونة من 24 كلمة. من الضروري أن تقوم بإنشاء محفظة Bitcoin جديدة وتحويل جميع أموالك إلى المحفظة الجديدة المكونة من 24 كلمة ، والتوقف عن استخدام محافظ سييد مكونة من 12 كلمة. يرجى القيام بذلك على الفور لتأمين أموالك.", "outdated_electrum_wallet_receive_warning": "إذا كانت هذه المحفظة تحتوي على سييد مكونة من 12 كلمة وتم إنشاؤها في Cake ، فلا تقم بإيداع Bitcoin في هذه المحفظة. قد يتم فقد أي BTC تم تحويله إلى هذه المحفظة. قم بإنشاء محفظة جديدة مكونة من 24 كلمة (انقر فوق القائمة في الجزء العلوي الأيمن ، وحدد محافظ ، واختر إنشاء محفظة جديدة ، ثم حدد Bitcoin) وقم على الفور بنقل BTC الخاص بك هناك. محافظ BTC الجديدة (24 كلمة) من Cake آمنة", "outgoing": "الصادره", + "outputs": "المخرجات", "overwrite_amount": "تغير المبلغ", "pairingInvalidEvent": "ﺢﻟﺎﺻ ﺮﻴﻏ ﺙﺪﺣ ﻥﺍﺮﻗﺇ", "password": "كلمة المرور", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 6fe29a1a6..49e494394 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "Плащанията с Bitcoin изискват потвърждение, което може да отнеме 20 минути или повече. Благодарим за търпението! Ще получите имейл, когато плащането е потвърдено.", "Blocks_remaining": "${status} оставащи блока", "bright_theme": "Ярко", + "bump_fee": "Такса за бум", "buy": "Купуване", "buy_alert_content": "В момента поддържаме само закупуването на Bitcoin, Ethereum, Litecoin и Monero. Моля, създайте или превключете към своя портфейл Bitcoin, Ethereum, Litecoin или Monero.", "buy_bitcoin": "Купуване на Bitcoin", @@ -133,6 +134,8 @@ "confirm": "Потвърждаване", "confirm_delete_template": "Този шаблон ще бъде изтрит. Искате ли да продължите?", "confirm_delete_wallet": "Този портфейл ще бъде изтрит. Искате ли да продължите?", + "confirm_fee_deduction": "Потвърдете приспадането на таксите", + "confirm_fee_deduction_content": "Съгласни ли сте да приспадате таксата от продукцията?", "confirm_sending": "Потвърждаване на изпращането", "confirmations": "потвърждения", "confirmed": "Потвърден баланс", @@ -212,6 +215,7 @@ "edit_token": "Редактиране на токена", "electrum_address_disclaimer": "Нови адреси се генерират всеки път, когато използвате този, но и предишните продължават да работят", "email_address": "Имейл адрес", + "enable_replace_by_fee": "Активиране на замяна по забрана", "enabled": "Активирано", "enter_amount": "Въведете сума", "enter_backup_password": "Въведете парола за възстановяване", @@ -248,6 +252,7 @@ "errorGettingCredentials": "Неуспешно: Грешка при получаване на идентификационни данни", "errorSigningTransaction": "Възникна грешка при подписване на транзакция", "estimated": "Изчислено", + "estimated_new_fee": "Прогнозна нова такса", "etherscan_history": "История на Etherscan", "event": "Събитие", "events": "събития", @@ -314,6 +319,7 @@ "in_store": "In Store", "incoming": "Входящи", "incorrect_seed": "Въведеният текст е невалиден.", + "inputs": "Входове", "introducing_cake_pay": "Запознайте се с Cake Pay!", "invalid_input": "Невалиден вход", "invoice_details": "IДанни за фактура", @@ -381,6 +387,7 @@ "offer_expires_in": "Предложението изтича след: ", "offline": "Офлайн", "ok": "Ок", + "old_fee": "Стара такса", "onion_link": "Лукова връзка", "online": "Онлайн", "onramper_option_description": "Бързо купувайте криптовалута с много методи за плащане. Предлага се в повечето страни. Разпространенията и таксите варират.", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "Нови Bitcoin портфейли, създадени в Cake, сега имат seed от 24 думи. Трябва да създадете нов Bitcoin адрес и да прехвърлите всичките си средства в него и веднага да спрете използването на стари портфейли. Моля, напревете това незабавно, за да подсигурите средствата си.", "outdated_electrum_wallet_receive_warning": "Ако този адрес има seed от 12 думи и е създаден чрез Cake, НЕ добавяйте Bitcoin в него. Всякакъв Bitcoin, изпратен на този адрес, може да бъде загубен завинаги. Създайте нов портфейл от 24 думи (натиснете менюто горе, вдясно, изберете Портфейли, изберете Създаване на нов портфейл, след това изберете Bitcoin) и НЕЗАБАВНО преместете своя Bitcoin там. Нови (такива с 24 думи) Bitcoin портфейли от Cake са надеждни", "outgoing": "Изходящи", + "outputs": "Изходи", "overwrite_amount": "Промени сума", "pairingInvalidEvent": "Невалидно събитие при сдвояване", "password": "Парола", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index a346f9494..348b6fa38 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "U plateb Bitcoinem je vyžadováno alespoň 1 potvrzení, což může trvat 20 minut i déle. Děkujeme za vaši trpělivost! Až bude platba potvrzena, budete informováni e-mailem.", "Blocks_remaining": "Zbývá ${status} bloků", "bright_theme": "Jasný", + "bump_fee": "Bump Fee", "buy": "Koupit", "buy_alert_content": "V současné době podporujeme pouze nákup bitcoinů, etherea, litecoinů a monero. Vytvořte nebo přepněte na svou peněženku bitcoinů, etherea, litecoinů nebo monero.", "buy_bitcoin": "Nakoupit Bitcoin", @@ -133,6 +134,8 @@ "confirm": "Potvrdit", "confirm_delete_template": "Tato akce smaže tuto šablonu. Přejete si pokračovat?", "confirm_delete_wallet": "Tato akce smaže tuto peněženku. Přejete si pokračovat?", + "confirm_fee_deduction": "Potvrďte odpočet poplatků", + "confirm_fee_deduction_content": "Souhlasíte s odečtením poplatku z výstupu?", "confirm_sending": "Potvrdit odeslání", "confirmations": "Potvrzení", "confirmed": "Potvrzený zůstatek", @@ -212,6 +215,7 @@ "edit_token": "Upravit token", "electrum_address_disclaimer": "Po každém použití je generována nová adresa, ale předchozí adresy také stále fungují", "email_address": "E-mailová adresa", + "enable_replace_by_fee": "Povolit výměnu podle poplatku", "enabled": "Povoleno", "enter_amount": "Zadejte částku", "enter_backup_password": "Zde zadejte své heslo pro zálohy", @@ -248,6 +252,7 @@ "errorGettingCredentials": "Selhalo: Chyba při získávání přihlašovacích údajů", "errorSigningTransaction": "Při podepisování transakce došlo k chybě", "estimated": "Odhadováno", + "estimated_new_fee": "Odhadovaný nový poplatek", "etherscan_history": "Historie Etherscanu", "event": "událost", "events": "Události", @@ -314,6 +319,7 @@ "in_store": "V obchodě", "incoming": "Příchozí", "incorrect_seed": "Zadaný text není správný.", + "inputs": "Vstupy", "introducing_cake_pay": "Představujeme Cake Pay!", "invalid_input": "Neplatný vstup", "invoice_details": "detaily faktury", @@ -381,6 +387,7 @@ "offer_expires_in": "Nabídka vyprší: ", "offline": "Offline", "ok": "OK", + "old_fee": "Starý poplatek", "onion_link": "Cibulový odkaz", "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ší.", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "Nové Bitcoinové peněženky vytvořené v Cake mají nyní seed se 24 slovy. Je třeba si vytvořit novou Bitcoinovou peněženku se 24 slovy, převést na ni všechny prostředky a přestat používat seed se 12 slovy. Prosím udělejte to hned pro zabezpečení svých prostředků.", "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", "overwrite_amount": "Přepsat částku", "pairingInvalidEvent": "Neplatná událost párování", "password": "Heslo", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 47375cedf..25ab3a54d 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "Bitcoin-Zahlungen erfordern 1 Bestätigung, was 20 Minuten oder länger dauern kann. Danke für Ihre Geduld! Sie erhalten eine E-Mail, wenn die Zahlung bestätigt ist.", "Blocks_remaining": "${status} verbleibende Blöcke", "bright_theme": "Strahlend hell", + "bump_fee": "Beulengebühr", "buy": "Kaufen", "buy_alert_content": "Derzeit unterstützen wir nur den Kauf von Bitcoin, Ethereum, Litecoin und Monero. Bitte erstellen Sie Ihr Bitcoin-, Ethereum-, Litecoin- oder Monero-Wallet oder wechseln Sie zu diesem.", "buy_bitcoin": "Bitcoin kaufen", @@ -133,6 +134,8 @@ "confirm": "Bestätigen", "confirm_delete_template": "Diese Aktion löscht diese Vorlage. Möchten Sie fortfahren?", "confirm_delete_wallet": "Diese Aktion löscht diese Wallet. Möchten Sie fortfahren?", + "confirm_fee_deduction": "Gebührenabzug bestätigen", + "confirm_fee_deduction_content": "Stimmen Sie zu, die Gebühr von der Ausgabe abzuziehen?", "confirm_sending": "Senden bestätigen", "confirmations": "Bestätigungen", "confirmed": "Bestätigter Saldo", @@ -212,6 +215,7 @@ "edit_token": "Token bearbeiten", "electrum_address_disclaimer": "Wir generieren jedes Mal neue Adressen, wenn Sie eine verwenden, aber vorherige Adressen funktionieren weiterhin", "email_address": "E-Mail-Adresse", + "enable_replace_by_fee": "Aktivieren Sie Ersatz für Fee", "enabled": "Ermöglicht", "enter_amount": "Betrag eingeben", "enter_backup_password": "Sicherungskennwort hier eingeben", @@ -248,6 +252,7 @@ "errorGettingCredentials": "Fehlgeschlagen: Fehler beim Abrufen der Anmeldeinformationen", "errorSigningTransaction": "Beim Signieren der Transaktion ist ein Fehler aufgetreten", "estimated": "Geschätzt", + "estimated_new_fee": "Geschätzte neue Gebühr", "etherscan_history": "Etherscan-Geschichte", "event": "Ereignis", "events": "Veranstaltungen", @@ -314,6 +319,7 @@ "in_store": "Im Geschäft", "incoming": "Eingehend", "incorrect_seed": "Der eingegebene Text ist ungültig.", + "inputs": "Eingänge", "introducing_cake_pay": "Einführung von Cake Pay!", "invalid_input": "Ungültige Eingabe", "invoice_details": "Rechnungs-Details", @@ -381,6 +387,7 @@ "offer_expires_in": "Angebot läuft ab in: ", "offline": "offline", "ok": "OK", + "old_fee": "Alte Gebühr", "onion_link": "Zwiebel-Link", "online": "online", "onramper_option_description": "Kaufen Sie schnell Krypto mit vielen Zahlungsmethoden. In den meisten Ländern erhältlich. Spreads und Gebühren variieren.", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "Neue Bitcoin-Wallets, die in Cake erstellt wurden, haben jetzt einen 24-Wort-Seed. Sie müssen eine neue Bitcoin-Wallet erstellen, Ihr gesamtes Geld in die neue 24-Wort-Wallet überweisen und keine Wallet mit einem 12-Wort-Seed mehr verwenden. Bitte tun Sie dies sofort, um Ihr Geld zu sichern.", "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", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Paarung ungültiges Ereignis", "password": "Passwort", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 837033429..45e8ef21b 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "Bitcoin payments require 1 confirmation, which can take 20 minutes or longer. Thanks for your patience! You will be emailed when the payment is confirmed.", "Blocks_remaining": "${status} Blocks Remaining", "bright_theme": "Bright", + "bump_fee": "Bump fee", "buy": "Buy", "buy_alert_content": "Currently we only support the purchase of Bitcoin, Ethereum, Litecoin, and Monero. Please create or switch to your Bitcoin, Ethereum, Litecoin, or Monero wallet.", "buy_bitcoin": "Buy Bitcoin", @@ -133,6 +134,8 @@ "confirm": "Confirm", "confirm_delete_template": "This action will delete this template. Do you wish to continue?", "confirm_delete_wallet": "This action will delete this wallet. Do you wish to continue?", + "confirm_fee_deduction": "Confirm Fee Deduction", + "confirm_fee_deduction_content": "Do you agree to deduct the fee from the output?", "confirm_sending": "Confirm sending", "confirmations": "Confirmations", "confirmed": "Confirmed Balance", @@ -212,6 +215,7 @@ "edit_token": "Edit token", "electrum_address_disclaimer": "We generate new addresses each time you use one, but previous addresses continue to work", "email_address": "Email Address", + "enable_replace_by_fee": "Enable Replace-By-Fee", "enabled": "Enabled", "enter_amount": "Enter Amount", "enter_backup_password": "Enter backup password here", @@ -248,6 +252,7 @@ "errorGettingCredentials": "Failed: Error while getting credentials", "errorSigningTransaction": "An error has occured while signing transaction", "estimated": "Estimated", + "estimated_new_fee": "Estimated new fee", "etherscan_history": "Etherscan history", "event": "Event", "events": "Events", @@ -314,6 +319,7 @@ "in_store": "In Store", "incoming": "Incoming", "incorrect_seed": "The text entered is not valid.", + "inputs": "Inputs", "introducing_cake_pay": "Introducing Cake Pay!", "invalid_input": "Invalid input", "invoice_details": "Invoice details", @@ -381,6 +387,7 @@ "offer_expires_in": "Offer expires in: ", "offline": "Offline", "ok": "OK", + "old_fee": "Old fee", "onion_link": "Onion link", "online": "Online", "onramper_option_description": "Quickly buy crypto with many payment methods. Available in most countries. Spreads and fees vary.", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "New Bitcoin wallets created in Cake now have a 24-word seed. It is mandatory that you create a new Bitcoin wallet and transfer all of your funds to the new 24-word wallet, and stop using wallets with a 12-word seed. Please do this immediately to secure your funds.", "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", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Pairing Invalid Event", "password": "Password", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index b3afbd3a7..e04bc4cfe 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "Los pagos de Bitcoin requieren 1 confirmación, que puede demorar 20 minutos o más. ¡Gracias por su paciencia! Se le enviará un correo electrónico cuando se confirme el pago.", "Blocks_remaining": "${status} Bloques restantes", "bright_theme": "Brillante", + "bump_fee": "Tarifa", "buy": "Comprar", "buy_alert_content": "Actualmente solo admitimos la compra de Bitcoin, Ethereum, Litecoin y Monero. Cree o cambie a su billetera Bitcoin, Ethereum, Litecoin o Monero.", "buy_bitcoin": "Comprar Bitcoin", @@ -133,6 +134,8 @@ "confirm": "Confirmar", "confirm_delete_template": "Esta acción eliminará esta plantilla. ¿Desea continuar?", "confirm_delete_wallet": "Esta acción eliminará esta billetera. ¿Desea continuar?", + "confirm_fee_deduction": "Confirmar la deducción de la tarifa", + "confirm_fee_deduction_content": "¿Acepta deducir la tarifa de la producción?", "confirm_sending": "Confirmar envío", "confirmations": "Confirmaciones", "confirmed": "Saldo confirmado", @@ -212,6 +215,7 @@ "edit_token": "Editar token", "electrum_address_disclaimer": "Generamos nuevas direcciones cada vez que usa una, pero las direcciones anteriores siguen funcionando", "email_address": "Dirección de correo electrónico", + "enable_replace_by_fee": "Habilitar reemplazar por tarea", "enabled": "Activado", "enter_amount": "Ingrese la cantidad", "enter_backup_password": "Ingrese la contraseña de respaldo aquí", @@ -248,6 +252,7 @@ "errorGettingCredentials": "Error: error al obtener las credenciales", "errorSigningTransaction": "Se ha producido un error al firmar la transacción.", "estimated": "Estimado", + "estimated_new_fee": "Nueva tarifa estimada", "etherscan_history": "historia de etherscan", "event": "Evento", "events": "Eventos", @@ -314,6 +319,7 @@ "in_store": "En la tienda", "incoming": "Entrante", "incorrect_seed": "El texto ingresado no es válido.", + "inputs": "Entradas", "introducing_cake_pay": "¡Presentamos Cake Pay!", "invalid_input": "Entrada inválida", "invoice_details": "Detalles de la factura", @@ -381,6 +387,7 @@ "offer_expires_in": "Oferta expira en: ", "offline": "fuera de línea", "ok": "OK", + "old_fee": "Tarifa antigua", "onion_link": "Enlace de cebolla", "online": "En línea", "onramper_option_description": "Compre 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.", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "Las nuevas carteras de Bitcoin creadas en Cake ahora tienen una semilla de 24 palabras. Es obligatorio que cree una nueva billetera de Bitcoin y transfiera todos sus fondos a la nueva billetera de 24 palabras, y deje de usar billeteras con una semilla de 12 palabras. Haga esto de inmediato para asegurar sus fondos.", "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", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Evento de emparejamiento no válido", "password": "Contraseña", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 2a62d351d..069f569ba 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "Les paiements Bitcoin nécessitent 1 confirmation, ce qui peut prendre 20 minutes ou plus. Merci pour votre patience ! Vous serez averti par e-mail lorsque le paiement sera confirmé.", "Blocks_remaining": "Blocs Restants : ${status}", "bright_theme": "Vif", + "bump_fee": "Frais de bosse", "buy": "Acheter", "buy_alert_content": "Actuellement, nous ne prenons en charge que l'achat de Bitcoin, Ethereum, Litecoin et Monero. Veuillez créer ou basculer vers votre portefeuille Bitcoin, Ethereum, Litecoin ou Monero.", "buy_bitcoin": "Acheter du Bitcoin", @@ -133,6 +134,8 @@ "confirm": "Confirmer", "confirm_delete_template": "Cette action va supprimer ce modèle. Souhaitez-vous continuer ?", "confirm_delete_wallet": "Cette action va supprimer ce portefeuille (wallet). Souhaitez-vous contnuer ?", + "confirm_fee_deduction": "Confirmer la déduction des frais", + "confirm_fee_deduction_content": "Acceptez-vous de déduire les frais de la production?", "confirm_sending": "Confirmer l'envoi", "confirmations": "Confirmations", "confirmed": "Solde confirmé", @@ -212,6 +215,7 @@ "edit_token": "Modifier le token", "electrum_address_disclaimer": "Nous générons de nouvelles adresses à chaque fois que vous en utilisez une, mais les adresses précédentes continuent à fonctionner", "email_address": "Adresse e-mail", + "enable_replace_by_fee": "Activer Remplace-by-Fee", "enabled": "Activé", "enter_amount": "Entrez le montant", "enter_backup_password": "Entrez le mot de passe de sauvegarde ici", @@ -248,6 +252,7 @@ "errorGettingCredentials": "Échec : erreur lors de l'obtention des informations d'identification", "errorSigningTransaction": "Une erreur s'est produite lors de la signature de la transaction", "estimated": "Estimé", + "estimated_new_fee": "De nouveaux frais estimés", "etherscan_history": "Historique d'Etherscan", "event": "Événement", "events": "Événements", @@ -314,6 +319,7 @@ "in_store": "En magasin", "incoming": "Entrantes", "incorrect_seed": "Le texte entré est invalide.", + "inputs": "Contributions", "introducing_cake_pay": "Présentation de Cake Pay !", "invalid_input": "Entrée invalide", "invoice_details": "Détails de la facture", @@ -381,6 +387,7 @@ "offer_expires_in": "L'Offre expire dans : ", "offline": "Hors ligne", "ok": "OK", + "old_fee": "Anciens", "onion_link": "Lien .onion", "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.", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "Les nouveaux portefeuilles (wallets) Bitcoin créés dans Cake ont dorénavant une phrase secrète (seed) de 24 mots. Il est impératif que vous créiez un nouveau portefeuille Bitcoin, que vous y transfériez tous vos fonds puis que vous cessiez d'utiliser le portefeuille avec une phrase secrète de 12 mots. Merci de faire cela immédiatement pour assurer la sécurité de vos avoirs.", "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", "overwrite_amount": "Remplacer le montant", "pairingInvalidEvent": "Événement de couplage non valide", "password": "Mot de passe", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 1e18fb692..7dd1cd52e 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "Akwatin Bitcoin na buɗe 1 sambumbu, da yake za ta samu mintuna 20 ko yawa. Ina kira ga sabuwar lafiya! Zaka sanarwa ta email lokacin da aka samu akwatin samun lambar waya.", "Blocks_remaining": "${status} Katanga ya rage", "bright_theme": "Mai haske", + "bump_fee": "Buin", "buy": "Sayi", "buy_alert_content": "A halin yanzu muna tallafawa kawai siyan Bitcoin, Ethereum, Litecoin, da Monero. Da fatan za a ƙirƙiri ko canza zuwa Bitcoin, Ethereum, Litecoin, ko Monero walat.", "buy_bitcoin": "Sayi Bitcoin", @@ -133,6 +134,8 @@ "confirm": "Tabbatar", "confirm_delete_template": "Wannan aikin zai share wannan samfuri. Kuna so ku ci gaba?", "confirm_delete_wallet": "Wannan aikin zai share wannan walat. Kuna so ku ci gaba?", + "confirm_fee_deduction": "Tabbatar da cire kudade", + "confirm_fee_deduction_content": "Shin kun yarda ku cire kuɗin daga fitarwa?", "confirm_sending": "Tabbatar da aikawa", "confirmations": "Tabbatar", "confirmed": "An tabbatar", @@ -212,6 +215,7 @@ "edit_token": "Gyara alamar", "electrum_address_disclaimer": "Muna samar da sababbin adireshi duk lokacin da kuka yi amfani da ɗaya, amma adiresoshin da suka gabata suna ci gaba da aiki", "email_address": "Adireshin i-mel", + "enable_replace_by_fee": "Ba da damar maye gurbin-by-kudin", "enabled": "An kunna", "enter_amount": "Shigar da Adadi", "enter_backup_password": "Shigar da kalmar wucewa ta madadin nan", @@ -248,6 +252,7 @@ "errorGettingCredentials": "Ba a yi nasara ba: Kuskure yayin samun takaddun shaida", "errorSigningTransaction": "An sami kuskure yayin sanya hannu kan ciniki", "estimated": "Kiyasta", + "estimated_new_fee": "An kiyasta sabon kudin", "etherscan_history": "Etherscan tarihin kowane zamani", "event": "Lamarin", "events": "Abubuwan da suka faru", @@ -314,6 +319,7 @@ "in_store": "A cikin Store", "incoming": "Mai shigowa", "incorrect_seed": "rubutun da aka shigar ba shi da inganci.", + "inputs": "Abubuwan da ke ciki", "introducing_cake_pay": "Gabatar da Cake Pay!", "invalid_input": "Shigar da ba daidai ba", "invoice_details": "Bayanin wadannan", @@ -381,6 +387,7 @@ "offer_expires_in": "tayin zai ƙare a:", "offline": "Offline", "ok": "OK", + "old_fee": "Tsohon kudin", "onion_link": "Lambar onion", "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.", @@ -399,6 +406,7 @@ "outdated_electrum_wallet_description": "Sabbin walat ɗin Bitcoin da aka kirkira a cikin Cake yanzu suna da nau'in kalma 24. Ya zama dole ka ƙirƙiri sabon walat ɗin Bitcoin kuma canza duk kuɗin ku zuwa sabon walat ɗin kalmomi 24, kuma ku daina amfani da walat tare da iri mai kalma 12. Da fatan za a yi haka nan take don samun kuɗin ku.", "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", "overwrite_amount": "Rubuta adadin", "pairingInvalidEvent": "Haɗa Lamarin mara inganci", "password": "Kalmar wucewa", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index b1ef9e4a2..5dbe22f0e 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "बिटकॉइन भुगतान के लिए 1 पुष्टिकरण की आवश्यकता होती है, जिसमें 20 मिनट या अधिक समय लग सकता है। आपके धैर्य के लिए धन्यवाद! भुगतान की पुष्टि होने पर आपको ईमेल किया जाएगा।", "Blocks_remaining": "${status} शेष रहते हैं", "bright_theme": "उज्ज्वल", + "bump_fee": "बम्प फीस", "buy": "खरीदें", "buy_alert_content": "वर्तमान में हम केवल बिटकॉइन, एथेरियम, लाइटकॉइन और मोनेरो की खरीद का समर्थन करते हैं। कृपया अपना बिटकॉइन, एथेरियम, लाइटकॉइन, या मोनेरो वॉलेट बनाएं या उस पर स्विच करें।", "buy_bitcoin": "बिटकॉइन खरीदें", @@ -133,6 +134,8 @@ "confirm": "की पुष्टि करें", "confirm_delete_template": "यह क्रिया इस टेम्पलेट को हटा देगी। क्या आप जारी रखना चाहते हैं?", "confirm_delete_wallet": "यह क्रिया इस वॉलेट को हटा देगी। क्या आप जारी रखना चाहते हैं?", + "confirm_fee_deduction": "शुल्क कटौती की पुष्टि करें", + "confirm_fee_deduction_content": "क्या आप आउटपुट से शुल्क में कटौती करने के लिए सहमत हैं?", "confirm_sending": "भेजने की पुष्टि करें", "confirmations": "पुष्टिकरण", "confirmed": "पुष्टि की गई शेष राशिी", @@ -212,6 +215,7 @@ "edit_token": "टोकन संपादित करें", "electrum_address_disclaimer": "हर बार जब आप एक का उपयोग करते हैं तो हम नए पते उत्पन्न करते हैं, लेकिन पिछले पते काम करना जारी रखते हैं", "email_address": "ईमेल पता", + "enable_replace_by_fee": "प्रतिस्थापित-दर-शुल्क सक्षम करें", "enabled": "सक्रिय", "enter_amount": "राशि दर्ज करें", "enter_backup_password": "यहां बैकअप पासवर्ड डालें", @@ -248,6 +252,7 @@ "errorGettingCredentials": "विफल: क्रेडेंशियल प्राप्त करते समय त्रुटि", "errorSigningTransaction": "लेन-देन पर हस्ताक्षर करते समय एक त्रुटि उत्पन्न हुई है", "estimated": "अनुमानित", + "estimated_new_fee": "अनुमानित नया शुल्क", "etherscan_history": "इथरस्कैन इतिहास", "event": "आयोजन", "events": "आयोजन", @@ -314,6 +319,7 @@ "in_store": "स्टोर में", "incoming": "आने वाली", "incorrect_seed": "दर्ज किया गया पाठ मान्य नहीं है।", + "inputs": "इनपुट", "introducing_cake_pay": "परिचय Cake Pay!", "invalid_input": "अमान्य निवेश", "invoice_details": "चालान विवरण", @@ -381,6 +387,7 @@ "offer_expires_in": "में ऑफर समाप्त हो रहा है: ", "offline": "ऑफ़लाइन", "ok": "ठीक है", + "old_fee": "पुराना फीस", "onion_link": "प्याज का लिंक", "online": "ऑनलाइन", "onramper_option_description": "जल्दी से कई भुगतान विधियों के साथ क्रिप्टो खरीदें। अधिकांश देशों में उपलब्ध है। फैलता है और फीस अलग -अलग होती है।", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "केक में बनाए गए नए बिटकॉइन वॉलेट में अब 24-शब्द का बीज है। यह अनिवार्य है कि आप एक नया बिटकॉइन वॉलेट बनाएं और अपने सभी फंड को नए 24-शब्द वाले वॉलेट में स्थानांतरित करें, और 12-शब्द बीज वाले वॉलेट का उपयोग करना बंद करें। कृपया अपने धन को सुरक्षित करने के लिए इसे तुरंत करें।", "outdated_electrum_wallet_receive_warning": "अगर इस वॉलेट में 12 शब्दों का बीज है और इसे केक में बनाया गया है, तो इस वॉलेट में बिटकॉइन जमा न करें। इस वॉलेट में स्थानांतरित किया गया कोई भी बीटीसी खो सकता है। एक नया 24-शब्द वॉलेट बनाएं (ऊपर दाईं ओर स्थित मेनू पर टैप करें, वॉलेट चुनें, नया वॉलेट बनाएं चुनें, फिर बिटकॉइन चुनें) और तुरंत अपना बीटीसी वहां ले जाएं। केक से नए (24-शब्द) बीटीसी वॉलेट सुरक्षित हैं", "outgoing": "निवर्तमान", + "outputs": "आउटपुट", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "अमान्य ईवेंट युग्मित करना", "password": "पारण शब्द", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 55913f434..4aac8216e 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "Bitcoin plaćanja zahtijevaju 1 potvrdu, što može potrajati 20 minuta ili dulje. Hvala na Vašem strpljenju! Dobit ćete e-poruku kada plaćanje bude potvrđeno.", "Blocks_remaining": "${status} preostalih blokova", "bright_theme": "Jarka", + "bump_fee": "Naplata", "buy": "Kupi", "buy_alert_content": "Trenutno podržavamo samo kupnju Bitcoina, Ethereuma, Litecoina i Monera. Izradite ili prijeđite na svoj Bitcoin, Ethereum, Litecoin ili Monero novčanik.", "buy_bitcoin": "Kupite Bitcoin", @@ -133,6 +134,8 @@ "confirm": "Potvrdi", "confirm_delete_template": "Ovom ćete radnjom izbrisati ovaj predložak. Želite li nastaviti?", "confirm_delete_wallet": "Ovom ćete radnjom izbrisati ovaj novčanik. Želite li nastaviti?", + "confirm_fee_deduction": "Potvrdite odbitak naknade", + "confirm_fee_deduction_content": "Slažete li se da ćete odbiti naknadu od izlaza?", "confirm_sending": "Potvrdi slanje", "confirmations": "Potvrde", "confirmed": "Potvrđeno stanje", @@ -212,6 +215,7 @@ "edit_token": "Uredi token", "electrum_address_disclaimer": "Minden egyes alkalommal új címeket generálunk, de a korábbi címek továbbra is működnek", "email_address": "Adresa e-pošte", + "enable_replace_by_fee": "Omogući zamjenu", "enabled": "Omogućeno", "enter_amount": "Unesite iznos", "enter_backup_password": "Unesite svoju lozinku za sigurnosnu kopiju ovdje", @@ -248,6 +252,7 @@ "errorGettingCredentials": "Neuspješno: Pogreška prilikom dobivanja vjerodajnica", "errorSigningTransaction": "Došlo je do pogreške prilikom potpisivanja transakcije", "estimated": "procijenjen", + "estimated_new_fee": "Procijenjena nova naknada", "etherscan_history": "Etherscan povijest", "event": "Događaj", "events": "Događaji", @@ -314,6 +319,7 @@ "in_store": "U trgovini", "incoming": "Dolazno", "incorrect_seed": "Uneseni tekst nije valjan.", + "inputs": "Unosi", "introducing_cake_pay": "Predstavljamo Cake Pay!", "invalid_input": "Pogrešan unos", "invoice_details": "Podaci o fakturi", @@ -381,6 +387,7 @@ "offer_expires_in": "Ponuda istječe za: ", "offline": "izvan mreže", "ok": "OK", + "old_fee": "Stara naknada", "onion_link": "Poveznica luka", "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.", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "Novi Bitcoin novčanici stvoreni u Cakeu sada imaju sjeme od 24 riječi. Obavezno je stvoriti novi Bitcoin novčanik i prenijeti sva svoja sredstva u novi novčanik od 24 riječi te prestati koristiti novčanike s sjemenkom od 12 riječi. Učinite to odmah kako biste osigurali svoja sredstva.", "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", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Nevažeći događaj uparivanja", "password": "Lozinka", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 8546e1f17..09d28e453 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "Pembayaran Bitcoin memerlukan 1 konfirmasi, yang bisa memakan waktu 20 menit atau lebih. Terima kasih atas kesabaran Anda! Anda akan diemail saat pembayaran dikonfirmasi.", "Blocks_remaining": "${status} Blok Tersisa", "bright_theme": "Cerah", + "bump_fee": "Biaya benjolan", "buy": "Beli", "buy_alert_content": "Saat ini kami hanya mendukung pembelian Bitcoin, Ethereum, Litecoin, dan Monero. Harap buat atau alihkan ke dompet Bitcoin, Ethereum, Litecoin, atau Monero Anda.", "buy_bitcoin": "Beli Bitcoin", @@ -133,6 +134,8 @@ "confirm": "Konfirmasi", "confirm_delete_template": "Tindakan ini akan menghapus template ini. Apakah Anda ingin melanjutkan?", "confirm_delete_wallet": "Tindakan ini akan menghapus dompet ini. Apakah Anda ingin melanjutkan?", + "confirm_fee_deduction": "Konfirmasi pengurangan biaya", + "confirm_fee_deduction_content": "Apakah Anda setuju untuk mengurangi biaya dari output?", "confirm_sending": "Konfirmasi pengiriman", "confirmations": "Konfirmasi", "confirmed": "Saldo Terkonfirmasi", @@ -212,6 +215,7 @@ "edit_token": "Mengedit token", "electrum_address_disclaimer": "Kami menghasilkan alamat baru setiap kali Anda menggunakan satu, tetapi alamat sebelumnya tetap berfungsi", "email_address": "Alamat Email", + "enable_replace_by_fee": "Aktifkan ganti-by-fee", "enabled": "Diaktifkan", "enter_amount": "Masukkan Jumlah", "enter_backup_password": "Masukkan kata sandi cadangan di sini", @@ -248,6 +252,7 @@ "errorGettingCredentials": "Gagal: Terjadi kesalahan saat mendapatkan kredensial", "errorSigningTransaction": "Terjadi kesalahan saat menandatangani transaksi", "estimated": "Diperkirakan", + "estimated_new_fee": "Perkiraan biaya baru", "etherscan_history": "Sejarah Etherscan", "event": "Peristiwa", "events": "Acara", @@ -314,6 +319,7 @@ "in_store": "Di Toko", "incoming": "Masuk", "incorrect_seed": "Teks yang dimasukkan tidak valid.", + "inputs": "Input", "introducing_cake_pay": "Perkenalkan Cake Pay!", "invalid_input": "Masukan tidak valid", "invoice_details": "Detail faktur", @@ -381,6 +387,7 @@ "offer_expires_in": "Penawaran kedaluwarsa dalam: ", "offline": "Offline", "ok": "OK", + "old_fee": "Biaya lama", "onion_link": "Tautan bawang", "online": "Online", "onramper_option_description": "Beli crypto dengan cepat dengan banyak metode pembayaran. Tersedia di sebagian besar negara. Spread dan biaya bervariasi.", @@ -399,6 +406,7 @@ "outdated_electrum_wallet_description": "Dompet Bitcoin baru yang dibuat di Cake sekarang memiliki biji semai 24 kata. Wajib bagi Anda untuk membuat dompet Bitcoin baru dan mentransfer semua dana Anda ke dompet 24 kata baru, dan berhenti menggunakan dompet dengan biji semai 12 kata. Silakan lakukan ini segera untuk mengamankan dana Anda.", "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", "overwrite_amount": "Timpa jumlah", "pairingInvalidEvent": "Menyandingkan Acara Tidak Valid", "password": "Kata Sandi", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index ef0ffecde..c9ac60bb5 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "I pagamenti in bitcoin richiedono 1 conferma, che può richiedere 20 minuti o più. Grazie per la vostra pazienza! Riceverai un'e-mail quando il pagamento sarà confermato.", "Blocks_remaining": "${status} Blocchi Rimanenti", "bright_theme": "Colorato", + "bump_fee": "Commissione per bump", "buy": "Comprare", "buy_alert_content": "Attualmente supportiamo solo l'acquisto di Bitcoin, Ethereum, Litecoin e Monero. Crea o passa al tuo portafoglio Bitcoin, Ethereum, Litecoin o Monero.", "buy_bitcoin": "Acquista Bitcoin", @@ -133,6 +134,8 @@ "confirm": "Conferma", "confirm_delete_template": "Questa azione cancellerà questo modello. Desideri continuare?", "confirm_delete_wallet": "Questa azione cancellerà questo portafoglio. Desideri continuare?", + "confirm_fee_deduction": "Conferma la detrazione delle commissioni", + "confirm_fee_deduction_content": "Accetti di detrarre la commissione dall'output?", "confirm_sending": "Conferma l'invio", "confirmations": "Conferme", "confirmed": "Saldo confermato", @@ -213,6 +216,7 @@ "edit_token": "Modifica token", "electrum_address_disclaimer": "Generiamo nuovi indirizzi ogni volta che ne utilizzi uno, ma gli indirizzi precedenti continuano a funzionare", "email_address": "Indirizzo e-mail", + "enable_replace_by_fee": "Abilita sostituzione per fee", "enabled": "Abilitato", "enter_amount": "Inserisci importo", "enter_backup_password": "Inserisci la password di backup qui", @@ -249,6 +253,7 @@ "errorGettingCredentials": "Non riuscito: errore durante il recupero delle credenziali", "errorSigningTransaction": "Si è verificato un errore durante la firma della transazione", "estimated": "Stimato", + "estimated_new_fee": "Nuova commissione stimata", "etherscan_history": "Storia Etherscan", "event": "Evento", "events": "Eventi", @@ -315,6 +320,7 @@ "in_store": "In negozio", "incoming": "In arrivo", "incorrect_seed": "Il testo inserito non è valido.", + "inputs": "Input", "introducing_cake_pay": "Presentazione di Cake Pay!", "invalid_input": "Inserimento non valido", "invoice_details": "Dettagli della fattura", @@ -382,6 +388,7 @@ "offer_expires_in": "Offerta termina tra: ", "offline": "Offline", "ok": "OK", + "old_fee": "Vecchia tassa", "onion_link": "Collegamento a cipolla", "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.", @@ -399,6 +406,7 @@ "outdated_electrum_wallet_description": "I nuovi portafogli Bitcoin creati in Cake ora hanno un seme di 24 parole. È obbligatorio creare un nuovo portafoglio Bitcoin e trasferire tutti i fondi nel nuovo portafoglio di 24 parole e smettere di usare portafogli con un seme di 12 parole. Ti preghiamo di farlo immediatamente per proteggere i tuoi fondi.", "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", "overwrite_amount": "Sovrascrivi quantità", "pairingInvalidEvent": "Associazione evento non valido", "password": "Password", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index c3a025a7c..98d87a90c 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "ビットコインの支払いには 1 回の確認が必要で、これには 20 分以上かかる場合があります。お待ち頂きまして、ありがとうございます!支払いが確認されると、メールが送信されます。", "Blocks_remaining": "${status} 残りのブロック", "bright_theme": "明るい", + "bump_fee": "バンプ料金", "buy": "購入", "buy_alert_content": "現在、ビットコイン、イーサリアム、ライトコイン、モネロの購入のみをサポートしています。ビットコイン、イーサリアム、ライトコイン、またはモネロのウォレットを作成するか、これらのウォレットに切り替えてください。", "buy_bitcoin": "ビットコインを購入する", @@ -133,6 +134,8 @@ "confirm": "確認する", "confirm_delete_template": "この操作により、このテンプレートが削除されます。 続行しますか?", "confirm_delete_wallet": "このアクションにより、このウォレットが削除されます。 続行しますか?", + "confirm_fee_deduction": "料金控除を確認します", + "confirm_fee_deduction_content": "出力から料金を差し引くことに同意しますか?", "confirm_sending": "送信を確認", "confirmations": "確認", "confirmed": "確認済み残高", @@ -212,6 +215,7 @@ "edit_token": "トークンの編集", "electrum_address_disclaimer": "使用するたびに新しいアドレスが生成されますが、以前のアドレスは引き続き機能します", "email_address": "メールアドレス", + "enable_replace_by_fee": "交換ごとに有効にします", "enabled": "有効", "enter_amount": "金額を入力", "enter_backup_password": "ここにバックアップパスワードを入力してください", @@ -248,6 +252,7 @@ "errorGettingCredentials": "失敗: 認証情報の取得中にエラーが発生しました", "errorSigningTransaction": "トランザクションの署名中にエラーが発生しました", "estimated": "推定", + "estimated_new_fee": "推定新しい料金", "etherscan_history": "イーサスキャンの歴史", "event": "イベント", "events": "イベント", @@ -315,6 +320,7 @@ "in_store": "インストア", "incoming": "着信", "incorrect_seed": "入力されたテキストは無効です。", + "inputs": "入力", "introducing_cake_pay": "序章Cake Pay!", "invalid_input": "無効入力", "invoice_details": "請求の詳細", @@ -382,6 +388,7 @@ "offer_expires_in": "で有効期限が切れます: ", "offline": "オフライン", "ok": "OK", + "old_fee": "古い料金", "onion_link": "オニオンリンク", "online": "オンライン", "onramper_option_description": "多くの支払い方法で暗号をすばやく購入してください。ほとんどの国で利用可能です。スプレッドと料金は異なります。", @@ -398,6 +405,7 @@ "outdated_electrum_wallet_description": "Cakeで作成された新しいビットコインウォレットには、24ワードのシードがあります。 新しいビットコインウォレットを作成し、すべての資金を新しい24ワードのウォレットに転送し、12ワードのシードを持つウォレットの使用を停止することが必須です。 あなたの資金を確保するためにこれをすぐに行ってください。", "outdated_electrum_wallet_receive_warning": "このウォレットに 12 ワードのシードがあり、Cake で作成された場合、このウォレットにビットコインを入金しないでください。 このウォレットに転送された BTC は失われる可能性があります。 新しい 24 ワードのウォレットを作成し (右上のメニューをタップし、[ウォレット]、[新しいウォレットの作成]、[ビットコイン] の順に選択)、すぐに BTC をそこに移動します。 Cake の新しい (24 ワード) BTC ウォレットは安全です", "outgoing": "発信", + "outputs": "出力", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "ペアリング無効イベント", "password": "パスワード", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index d2b48913b..7cc49e315 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "비트코인 결제는 1번의 확인이 필요하며 20분 이상이 소요될 수 있습니다. 기다려 주셔서 감사합니다! 결제가 확인되면 이메일이 전송됩니다.", "Blocks_remaining": "${status} 남은 블록", "bright_theme": "선명한", + "bump_fee": "범프 요금", "buy": "구입", "buy_alert_content": "현재 Bitcoin, Ethereum, Litecoin 및 Monero 구매만 지원합니다. Bitcoin, Ethereum, Litecoin 또는 Monero 지갑을 생성하거나 전환하십시오.", "buy_bitcoin": "비트 코인 구매", @@ -133,6 +134,8 @@ "confirm": "확인", "confirm_delete_template": "이 작업은이 템플릿을 삭제합니다. 계속 하시겠습니까?", "confirm_delete_wallet": "이 작업은이 지갑을 삭제합니다. 계속 하시겠습니까?", + "confirm_fee_deduction": "수수료 공제를 확인하십시오", + "confirm_fee_deduction_content": "출력에서 수수료를 공제하는 데 동의하십니까?", "confirm_sending": "전송 확인", "confirmations": "확인", "confirmed": "확인된 잔액", @@ -212,6 +215,7 @@ "edit_token": "토큰 편집", "electrum_address_disclaimer": "사용할 때마다 새 주소가 생성되지만 이전 주소는 계속 작동합니다.", "email_address": "이메일 주소", + "enable_replace_by_fee": "대체별로 활성화하십시오", "enabled": "사용", "enter_amount": "금액 입력", "enter_backup_password": "여기에 백업 비밀번호를 입력하세요.", @@ -248,6 +252,7 @@ "errorGettingCredentials": "실패: 자격 증명을 가져오는 중 오류가 발생했습니다.", "errorSigningTransaction": "거래에 서명하는 동안 오류가 발생했습니다.", "estimated": "예상", + "estimated_new_fee": "예상 새로운 수수료", "etherscan_history": "이더스캔 역사", "event": "이벤트", "events": "이벤트", @@ -314,6 +319,7 @@ "in_store": "매장 내", "incoming": "들어오는", "incorrect_seed": "입력하신 텍스트가 유효하지 않습니다.", + "inputs": "입력", "introducing_cake_pay": "소개 Cake Pay!", "invalid_input": "잘못된 입력", "invoice_details": "인보이스 세부정보", @@ -381,6 +387,7 @@ "offer_expires_in": "쿠폰 만료일: ", "offline": "오프라인", "ok": "승인", + "old_fee": "옛 수수료", "onion_link": "양파 링크", "online": "온라인", "onramper_option_description": "많은 결제 방법으로 암호화를 신속하게 구입하십시오. 대부분의 국가에서 사용할 수 있습니다. 스프레드와 수수료는 다양합니다.", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "Cake에서 생성 된 새로운 비트 코인 지갑에는 이제 24 단어 시드가 있습니다. 새로운 비트 코인 지갑을 생성하고 모든 자금을 새로운 24 단어 지갑으로 이체하고 12 단어 시드가있는 지갑 사용을 중지해야합니다. 자금을 확보하려면 즉시이 작업을 수행하십시오.", "outdated_electrum_wallet_receive_warning": "이 지갑에 12 단어 시드가 있고 Cake에서 생성 된 경우이 지갑에 비트 코인을 입금하지 마십시오. 이 지갑으로 전송 된 모든 BTC는 손실 될 수 있습니다. 새로운 24 단어 지갑을 생성하고 (오른쪽 상단의 메뉴를 탭하고 지갑을 선택한 다음 새 지갑 생성을 선택한 다음 비트 코인을 선택하십시오) 즉시 BTC를 그곳으로 이동하십시오. Cake의 새로운 (24 단어) BTC 지갑은 안전합니다", "outgoing": "나가는", + "outputs": "출력", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "잘못된 이벤트 페어링", "password": "암호", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index c7312b290..9c88dc817 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "Bitcoin ငွေပေးချေမှုများသည် မိနစ် 20 သို့မဟုတ် ထို့ထက်ပိုကြာနိုင်သည် 1 အတည်ပြုချက် လိုအပ်သည်။ မင်းရဲ့စိတ်ရှည်မှုအတွက် ကျေးဇူးတင်ပါတယ်။ ငွေပေးချေမှုကို အတည်ပြုပြီးသောအခါ သင့်ထံ အီးမေးလ်ပို့ပါမည်။", "Blocks_remaining": "${status} ဘလောက်များ ကျန်နေပါသည်။", "bright_theme": "တောက်ပ", + "bump_fee": "ဝင်ငွေ", "buy": "ဝယ်ပါ။", "buy_alert_content": "လက်ရှိတွင် ကျွန်ုပ်တို့သည် Bitcoin၊ Ethereum၊ Litecoin နှင့် Monero တို့ကိုသာ ဝယ်ယူမှုကို ပံ့ပိုးပေးပါသည်။ သင်၏ Bitcoin၊ Ethereum၊ Litecoin သို့မဟုတ် Monero ပိုက်ဆံအိတ်ကို ဖန်တီးပါ သို့မဟုတ် ပြောင်းပါ။", "buy_bitcoin": "Bitcoin ကိုဝယ်ပါ။", @@ -133,6 +134,8 @@ "confirm": "အတည်ပြုပါ။", "confirm_delete_template": "ဤလုပ်ဆောင်ချက်သည် ဤပုံစံပြားကို ဖျက်လိုက်ပါမည်။ ဆက်လုပ်လိုပါသလား။", "confirm_delete_wallet": "ဤလုပ်ဆောင်ချက်သည် ဤပိုက်ဆံအိတ်ကို ဖျက်လိုက်ပါမည်။ ဆက်လုပ်လိုပါသလား။", + "confirm_fee_deduction": "အခကြေးငွေကိုနှုတ်ယူခြင်း", + "confirm_fee_deduction_content": "output မှအခကြေးငွေကိုယူရန်သဘောတူပါသလား။", "confirm_sending": "ပေးပို့အတည်ပြုပါ။", "confirmations": "အတည်ပြုချက်များ", "confirmed": "အတည်ပြုထားသော လက်ကျန်ငွေ", @@ -212,6 +215,7 @@ "edit_token": "တိုကင်ကို တည်းဖြတ်ပါ။", "electrum_address_disclaimer": "သင်အသုံးပြုသည့်အချိန်တိုင်းတွင် ကျွန်ုပ်တို့သည် လိပ်စာအသစ်များကို ထုတ်ပေးသော်လည်း ယခင်လိပ်စာများသည် ဆက်လက်အလုပ်လုပ်နေပါသည်။", "email_address": "အီးမေးလ်လိပ်စာ", + "enable_replace_by_fee": "အစားထိုး - by- အခကြေးငွေ enable", "enabled": "ဖွင့်ထားသည်။", "enter_amount": "ပမာဏကို ထည့်ပါ။", "enter_backup_password": "အရန်စကားဝှက်ကို ဤနေရာတွင် ထည့်ပါ။", @@ -248,6 +252,7 @@ "errorGettingCredentials": "မအောင်မြင်ပါ- အထောက်အထားများ ရယူနေစဉ် အမှားအယွင်း", "errorSigningTransaction": "ငွေပေးငွေယူ လက်မှတ်ထိုးစဉ် အမှားအယွင်းတစ်ခု ဖြစ်ပေါ်ခဲ့သည်။", "estimated": "ခန့်မှန်း", + "estimated_new_fee": "ခန့်မှန်းသစ်ခန့်မှန်း", "etherscan_history": "Etherscan သမိုင်း", "event": "ပွဲ", "events": "အဲ့ဒါနဲ့", @@ -314,6 +319,7 @@ "in_store": "စတိုးတွင်", "incoming": "ဝင်လာ", "incorrect_seed": "ထည့်သွင်းထားသော စာသားသည် မမှန်ကန်ပါ။", + "inputs": "သွင်းငေှ", "introducing_cake_pay": "Cake Pay ကို မိတ်ဆက်ခြင်း။", "invalid_input": "ထည့်သွင်းမှု မမှန်ကန်ပါ။", "invoice_details": "ပြေစာအသေးစိတ်", @@ -381,6 +387,7 @@ "offer_expires_in": "ကမ်းလှမ်းချက် သက်တမ်းကုန်သည်:", "offline": "အော့ဖ်လိုင်း", "ok": "ရလား", + "old_fee": "ကြေးဟောင်း", "onion_link": "ကြက်သွန်လင့်", "online": "အွန်လိုင်း", "onramper_option_description": "ငွေပေးချေမှုနည်းလမ်းများစွာဖြင့် Crypto ကိုလျင်မြန်စွာ 0 ယ်ပါ။ နိုင်ငံအများစုတွင်ရရှိနိုင်ပါသည်။ ဖြန့်ဖြူးနှင့်အခကြေးငွေကွဲပြားခြားနားသည်။", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "ယခု Cake တွင်ဖန်တီးထားသော Bitcoin ပိုက်ဆံအိတ်အသစ်တွင် စကားလုံး 24 မျိုးရှိသည်။ Bitcoin ပိုက်ဆံအိတ်အသစ်တစ်ခုကို ဖန်တီးပြီး သင့်ငွေအားလုံးကို 24 စကားလုံးပိုက်ဆံအိတ်အသစ်သို့ လွှဲပြောင်းပြီး 12 စကားလုံးမျိုးစေ့ဖြင့် ပိုက်ဆံအိတ်များကို အသုံးပြုခြင်းကို ရပ်တန့်ရန် မဖြစ်မနေလိုအပ်ပါသည်။ သင့်ရန်ပုံငွေများကို လုံခြုံစေရန်အတွက် ၎င်းကိုချက်ချင်းလုပ်ဆောင်ပါ။", "outdated_electrum_wallet_receive_warning": "ဤပိုက်ဆံအိတ်တွင် စာလုံး 12 လုံးပါပြီး ကိတ်မုန့်တွင် ဖန်တီးပါက၊ Bitcoin ကို ဤပိုက်ဆံအိတ်ထဲသို့ မထည့်ပါနှင့်။ ဤပိုက်ဆံအိတ်သို့ လွှဲပြောင်းပေးသည့် မည်သည့် BTC မဆို ဆုံးရှုံးနိုင်သည်။ 24 စကားလုံးပိုက်ဆံအိတ်အသစ်တစ်ခုဖန်တီးပါ (ညာဘက်အပေါ်ထောင့်ရှိမီနူးကိုနှိပ်ပါ၊ Wallets ကိုရွေးချယ်ပါ၊ ပိုက်ဆံအိတ်အသစ်ဖန်တီးရန်ကိုရွေးချယ်ပါ၊ ထို့နောက် Bitcoin ကိုရွေးချယ်ပါ) နှင့်သင်၏ BTC ကိုထိုနေရာသို့ချက်ချင်းရွှေ့ပါ။ Cake မှ (24 စာလုံး) BTC ပိုက်ဆံအိတ်အသစ်များသည် လုံခြုံပါသည်။", "outgoing": "အထွက်", + "outputs": "ထုတ်လုပ်မှု", "overwrite_amount": "ပမာဏကို ထပ်ရေးပါ။", "pairingInvalidEvent": "မမှန်ကန်သောဖြစ်ရပ်ကို တွဲချိတ်ခြင်း။", "password": "စကားဝှက်", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 86881452e..74b111dcb 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "Bitcoin-betalingen vereisen 1 bevestiging, wat 20 minuten of langer kan duren. Dank voor uw geduld! U ontvangt een e-mail wanneer de betaling is bevestigd.", "Blocks_remaining": "${status} Resterende blokken", "bright_theme": "Helder", + "bump_fee": "Bult fee", "buy": "Kopen", "buy_alert_content": "Momenteel ondersteunen we alleen de aankoop van Bitcoin, Ethereum, Litecoin en Monero. Maak of schakel over naar uw Bitcoin-, Ethereum-, Litecoin- of Monero-portemonnee.", "buy_bitcoin": "Koop Bitcoin", @@ -133,6 +134,8 @@ "confirm": "Bevestigen", "confirm_delete_template": "Met deze actie wordt deze sjabloon verwijderd. Wilt u doorgaan?", "confirm_delete_wallet": "Met deze actie wordt deze portemonnee verwijderd. Wilt u doorgaan?", + "confirm_fee_deduction": "Bevestig de aftrek van de kosten", + "confirm_fee_deduction_content": "Stemt u ermee in om de vergoeding af te trekken van de output?", "confirm_sending": "Bevestig verzending", "confirmations": "Bevestigingen", "confirmed": "Bevestigd saldo", @@ -212,6 +215,7 @@ "edit_token": "Token bewerken", "electrum_address_disclaimer": "We genereren nieuwe adressen elke keer dat u er een gebruikt, maar eerdere adressen blijven werken", "email_address": "E-mailadres", + "enable_replace_by_fee": "Schakel vervangen door een fee", "enabled": "Ingeschakeld", "enter_amount": "Voer Bedrag in", "enter_backup_password": "Voer hier een back-upwachtwoord in", @@ -248,6 +252,7 @@ "errorGettingCredentials": "Mislukt: fout bij het ophalen van inloggegevens", "errorSigningTransaction": "Er is een fout opgetreden tijdens het ondertekenen van de transactie", "estimated": "Geschatte", + "estimated_new_fee": "Geschatte nieuwe vergoeding", "etherscan_history": "Etherscan-geschiedenis", "event": "Evenement", "events": "Evenementen", @@ -314,6 +319,7 @@ "in_store": "In winkel", "incoming": "inkomend", "incorrect_seed": "De ingevoerde tekst is niet geldig.", + "inputs": "Invoer", "introducing_cake_pay": "Introductie van Cake Pay!", "invalid_input": "Ongeldige invoer", "invoice_details": "Factuurgegevens", @@ -381,6 +387,7 @@ "offer_expires_in": "Aanbieding verloopt over: ", "offline": "Offline", "ok": "OK", + "old_fee": "Oude vergoeding", "onion_link": "Ui koppeling", "online": "online", "onramper_option_description": "Koop snel crypto met veel betaalmethoden. Beschikbaar in de meeste landen. Spreads en vergoedingen variëren.", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "Nieuwe Bitcoin-portefeuilles die in Cake zijn gemaakt, hebben nu een zaadje van 24 woorden. Het is verplicht dat u een nieuwe Bitcoin-portemonnee maakt en al uw geld overmaakt naar de nieuwe portemonnee van 24 woorden, en stopt met het gebruik van wallets met een seed van 12 woorden. Doe dit onmiddellijk om uw geld veilig te stellen.", "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", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Koppelen Ongeldige gebeurtenis", "password": "Wachtwoord", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 994820123..2ac1b9fb5 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "Płatności Bitcoin wymagają 1 potwierdzenia, co może zająć 20 minut lub dłużej. Dziękuję za cierpliwość! Otrzymasz wiadomość e-mail, gdy płatność zostanie potwierdzona.", "Blocks_remaining": "Pozostało ${status} bloków", "bright_theme": "Biały", + "bump_fee": "Opłata za nierówność", "buy": "Kup", "buy_alert_content": "Obecnie obsługujemy tylko zakup Bitcoin, Ethereum, Litecoin i Monero. Utwórz lub przełącz się na swój portfel Bitcoin, Ethereum, Litecoin lub Monero.", "buy_bitcoin": "Kup Bitcoin", @@ -133,6 +134,8 @@ "confirm": "Potwierdzać", "confirm_delete_template": "Ta czynność usunie ten szablon. Czy chcesz kontynuować?", "confirm_delete_wallet": "Ta czynność usunie ten portfel. Czy chcesz kontynuować?", + "confirm_fee_deduction": "Potwierdź odliczenie opłaty", + "confirm_fee_deduction_content": "Czy zgadzasz się odliczyć opłatę od wyników?", "confirm_sending": "Potwierdź wysłanie", "confirmations": "Potwierdzenia", "confirmed": "Potwierdzone saldo", @@ -212,6 +215,7 @@ "edit_token": "Edytuj token", "electrum_address_disclaimer": "Za każdym razem, gdy wykorzystasz adres, dla wiekszej prywatności generujemy nowy, ale poprzednie adresy nadal działają, i moga odbierać środki", "email_address": "Adres e-mail", + "enable_replace_by_fee": "Włącz wymianę po lewej", "enabled": "Włączone", "enter_amount": "Wprowadź kwotę", "enter_backup_password": "Wprowadź tutaj hasło kopii zapasowej", @@ -248,6 +252,7 @@ "errorGettingCredentials": "Niepowodzenie: Błąd podczas uzyskiwania poświadczeń", "errorSigningTransaction": "Wystąpił błąd podczas podpisywania transakcji", "estimated": "Oszacowano", + "estimated_new_fee": "Szacowana nowa opłata", "etherscan_history": "Historia Etherscanu", "event": "Wydarzenie", "events": "Wydarzenia", @@ -314,6 +319,7 @@ "in_store": "W Sklepie", "incoming": "Przychodzące", "incorrect_seed": "Wprowadzony seed jest nieprawidłowy.", + "inputs": "Wejścia", "introducing_cake_pay": "Przedstawiamy Cake Pay!", "invalid_input": "Nieprawidłowe dane wejściowe", "invoice_details": "Dane do faktury", @@ -381,6 +387,7 @@ "offer_expires_in": "Oferta wygasa za ", "offline": "Offline", "ok": "Ok", + "old_fee": "Stara opłata", "onion_link": "Łącznik cebulowy", "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ę.", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "Nowe portfele Bitcoin utworzone w Cake mają teraz fraze seed składające się z 24 słów. Konieczne jest utworzenie nowego portfela Bitcoin i przeniesienie wszystkich środków do nowego portfela na 24 słowa oraz zaprzestanie korzystania z portfeli z frazą seed na 12 słów. Zrób to natychmiast, aby zabezpieczyć swoje fundusze.", "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", "overwrite_amount": "Nadpisz ilość", "pairingInvalidEvent": "Nieprawidłowe zdarzenie parowania", "password": "Hasło", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index cec7b8c11..bf0b0082d 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "Os pagamentos em Bitcoin exigem 1 confirmação, o que pode levar 20 minutos ou mais. Obrigado pela sua paciência! Você receberá um e-mail quando o pagamento for confirmado.", "Blocks_remaining": "${status} blocos restantes", "bright_theme": "Brilhante", + "bump_fee": "Taxa de aumento", "buy": "Comprar", "buy_alert_content": "Atualmente, oferecemos suporte apenas à compra de Bitcoin, Ethereum, Litecoin e Monero. Crie ou troque para sua carteira Bitcoin, Ethereum, Litecoin ou Monero.", "buy_bitcoin": "Compre Bitcoin", @@ -133,6 +134,8 @@ "confirm": "Confirmar", "confirm_delete_template": "Esta ação excluirá este modelo. Você deseja continuar?", "confirm_delete_wallet": "Esta ação excluirá esta carteira. Você deseja continuar?", + "confirm_fee_deduction": "Confirme dedução da taxa", + "confirm_fee_deduction_content": "Você concorda em deduzir a taxa da saída?", "confirm_sending": "Confirmar o envio", "confirmations": "Confirmações", "confirmed": "Saldo Confirmado", @@ -212,6 +215,7 @@ "edit_token": "Editar símbolo", "electrum_address_disclaimer": "Geramos novos endereços cada vez que você usa um, mas os endereços anteriores continuam funcionando", "email_address": "Endereço de e-mail", + "enable_replace_by_fee": "Habilite substituir por taxa", "enabled": "Habilitado", "enter_amount": "Digite o valor", "enter_backup_password": "Digite a senha de backup aqui", @@ -248,6 +252,7 @@ "errorGettingCredentials": "Falha: Erro ao obter credenciais", "errorSigningTransaction": "Ocorreu um erro ao assinar a transação", "estimated": "Estimado", + "estimated_new_fee": "Nova taxa estimada", "etherscan_history": "história Etherscan", "event": "Evento", "events": "Eventos", @@ -314,6 +319,7 @@ "in_store": "Na loja", "incoming": "Recebidas", "incorrect_seed": "O texto digitado não é válido.", + "inputs": "Entradas", "introducing_cake_pay": "Apresentando o Cake Pay!", "invalid_input": "Entrada inválida", "invoice_details": "Detalhes da fatura", @@ -382,6 +388,7 @@ "offer_expires_in": "A oferta expira em: ", "offline": "offline", "ok": "Ok", + "old_fee": "Taxa antiga", "onion_link": "ligação de cebola", "online": "Online", "onramper_option_description": "Compre rapidamente criptografia com muitos métodos de pagamento. Disponível na maioria dos países. Os spreads e taxas variam.", @@ -399,6 +406,7 @@ "outdated_electrum_wallet_description": "As novas carteiras Bitcoin criadas no Cake agora têm uma semente de 24 palavras. É obrigatório que você crie uma nova carteira Bitcoin e transfira todos os seus fundos para a nova carteira de 24 palavras, e pare de usar carteiras com semente de 12 palavras. Faça isso imediatamente para garantir seus fundos.", "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", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Emparelhamento de evento inválido", "password": "Senha", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 4ae5bb129..999728faf 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -75,10 +75,11 @@ "billing_address_info": "Если вас попросят указать платежный адрес, укажите адрес доставки", "biometric_auth_reason": "Отсканируйте свой отпечаток пальца для аутентификации", "bitcoin_dark_theme": "Биткойн Темная тема", - "bitcoin_light_theme": "Легкая биткойн-тема", + "bitcoin_light_theme": "Светлая биткойн-тема", "bitcoin_payments_require_1_confirmation": "Биткойн-платежи требуют 1 подтверждения, что может занять 20 минут или дольше. Спасибо тебе за твое терпение! Вы получите электронное письмо, когда платеж будет подтвержден.", "Blocks_remaining": "${status} Осталось блоков", "bright_theme": "Яркая", + "bump_fee": "Повысить комиссию", "buy": "Купить", "buy_alert_content": "В настоящее время мы поддерживаем только покупку биткойнов, Ethereum, Litecoin и Monero. Пожалуйста, создайте или переключитесь на свой кошелек Bitcoin, Ethereum, Litecoin или Monero.", "buy_bitcoin": "Купить Bitcoin", @@ -133,6 +134,8 @@ "confirm": "Подтвердить", "confirm_delete_template": "Это действие удалит шаблон. Вы хотите продолжить?", "confirm_delete_wallet": "Это действие удалит кошелек. Вы хотите продолжить?", + "confirm_fee_deduction": "Подтвердите вычет платы", + "confirm_fee_deduction_content": "Согласны ли вы вычесть плату из вывода?", "confirm_sending": "Подтвердить отправку", "confirmations": "Подтверждения", "confirmed": "Подтвержденный баланс", @@ -212,6 +215,7 @@ "edit_token": "Изменить токен", "electrum_address_disclaimer": "Мы генерируем новые адреса каждый раз, когда вы их используете, но предыдущие адреса продолжают работать.", "email_address": "Адрес электронной почты", + "enable_replace_by_fee": "Включить замену за пикой", "enabled": "Включено", "enter_amount": "Введите сумму", "enter_backup_password": "Введите пароль резервной копии", @@ -248,6 +252,7 @@ "errorGettingCredentials": "Не удалось: ошибка при получении учетных данных.", "errorSigningTransaction": "Произошла ошибка при подписании транзакции", "estimated": "Примерно", + "estimated_new_fee": "Расчетная новая плата", "etherscan_history": "История Эфириума", "event": "Событие", "events": "События", @@ -314,6 +319,7 @@ "in_store": "В магазине", "incoming": "Входящие", "incorrect_seed": "Введённый текст некорректный.", + "inputs": "Входы", "introducing_cake_pay": "Представляем Cake Pay!", "invalid_input": "Неверный Ввод", "invoice_details": "Детали счета", @@ -381,6 +387,7 @@ "offer_expires_in": "Предложение истекает через: ", "offline": "Не в сети", "ok": "OK", + "old_fee": "Старая плата", "onion_link": "Луковая ссылка", "online": "Онлайн", "onramper_option_description": "Быстро купите крипто со многими способами оплаты. Доступно в большинстве стран. Спреды и сборы различаются.", @@ -398,6 +405,7 @@ "outdated_electrum_wallet_description": "Новые биткойн-кошельки, созданные в Cake, теперь содержат мнемоническую фразу из 24 слов. Вы обязательно должны создать новый биткойн-кошелек и перевести все свои средства в новый кошелек из 24 слов, а также прекратить использование кошельков с мнемонической фразой из 12 слов. Пожалуйста, сделайте это немедленно, чтобы обезопасить свои средства.", "outdated_electrum_wallet_receive_warning": "Если этот кошелек имеет мнемоническую фразу из 12 слов и был создан в Cake, НЕ переводите биткойны на этот кошелек. Любые BTC, переведенные на этот кошелек, могут быть потеряны. Создайте новый кошелек с мнемоническои фразы из 24 слов (коснитесь меню в правом верхнем углу, выберите «Кошельки», выберите «Создать новый кошелек», затем выберите «Bitcoin») и НЕМЕДЛЕННО переведите туда свои BTC. Новые (24 слова) кошельки BTC от Cake безопасны", "outgoing": "Исходящие", + "outputs": "Выходы", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Недействительное событие сопряжения", "password": "Пароль", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 6c8634e83..a71bc6b36 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "การชำระเงินด้วย Bitcoin ต้องการการยืนยัน 1 ครั้ง ซึ่งอาจใช้เวลา 20 นาทีหรือนานกว่านั้น ขอบคุณสำหรับความอดทนของคุณ! คุณจะได้รับอีเมลเมื่อการชำระเงินได้รับการยืนยัน", "Blocks_remaining": "${status} บล็อกที่เหลืออยู่", "bright_theme": "สดใส", + "bump_fee": "ค่าธรรมเนียมชน", "buy": "ซื้อ", "buy_alert_content": "ขณะนี้เรารองรับการซื้อ Bitcoin, Ethereum, Litecoin และ Monero เท่านั้น โปรดสร้างหรือเปลี่ยนเป็นกระเป๋าเงิน Bitcoin, Ethereum, Litecoin หรือ Monero", "buy_bitcoin": "ซื้อ Bitcoin", @@ -133,6 +134,8 @@ "confirm": "ยืนยัน", "confirm_delete_template": "การดำเนินการนี้จะลบแบบฟอร์มนี้ คุณต้องการดำเนินการต่อหรือไม่?", "confirm_delete_wallet": "การดำเนินการนี้จะลบกระเป๋านี้ คุณต้องการดำเนินการต่อหรือไม่?", + "confirm_fee_deduction": "ยืนยันการหักค่าธรรมเนียม", + "confirm_fee_deduction_content": "คุณตกลงที่จะหักค่าธรรมเนียมจากผลลัพธ์หรือไม่?", "confirm_sending": "ยืนยันการส่ง", "confirmations": "การยืนยัน", "confirmed": "ยอดคงเหลือที่ยืนยันแล้ว", @@ -212,6 +215,7 @@ "edit_token": "แก้ไขโทเค็น", "electrum_address_disclaimer": "เราสร้างที่อยู่ใหม่ทุกครั้งที่คุณใช้หนึ่งอย่าง แต่ที่อยู่เก่ายังสามารถใช้ได้ต่อไป", "email_address": "ที่อยู่อีเมล", + "enable_replace_by_fee": "เปิดใช้งานการเปลี่ยนโดยค่าธรรมเนียม", "enabled": "เปิดใช้งาน", "enter_amount": "กรอกจำนวน", "enter_backup_password": "ป้อนรหัสผ่านสำรองที่นี่", @@ -248,6 +252,7 @@ "errorGettingCredentials": "ล้มเหลว: เกิดข้อผิดพลาดขณะรับข้อมูลรับรอง", "errorSigningTransaction": "เกิดข้อผิดพลาดขณะลงนามธุรกรรม", "estimated": "ประมาณการ", + "estimated_new_fee": "ค่าธรรมเนียมใหม่โดยประมาณ", "etherscan_history": "ประวัติอีเธอร์สแกน", "event": "เหตุการณ์", "events": "กิจกรรม", @@ -314,6 +319,7 @@ "in_store": "ในร้าน", "incoming": "ขาเข้า", "incorrect_seed": "ข้อความที่ป้อนไม่ถูกต้อง", + "inputs": "อินพุต", "introducing_cake_pay": "ยินดีต้อนรับสู่ Cake Pay!", "invalid_input": "อินพุตไม่ถูกต้อง", "invoice_details": "รายละเอียดใบแจ้งหนี้", @@ -381,6 +387,7 @@ "offer_expires_in": "ข้อเสนอจะหมดอายุใน: ", "offline": "ออฟไลน์", "ok": "ตกลง", + "old_fee": "ค่าธรรมเนียมเก่า", "onion_link": "ลิงค์หัวหอม", "online": "ออนไลน์", "onramper_option_description": "ซื้อ crypto อย่างรวดเร็วด้วยวิธีการชำระเงินจำนวนมาก มีให้บริการในประเทศส่วนใหญ่ สเปรดและค่าธรรมเนียมแตกต่างกันไป", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "กระเป๋า Bitcoin ใหม่ที่สร้างใน Cake มี seed ขนาด 24 คำ ซึ่งจำเป็นต้องสร้างกระเป๋า Bitcoin ใหม่และโอนทุกเงินของคุณไปยังกระเป๋าใหม่ขนาด 24 คำ และหยุดใช้กระเป๋าที่มี seed ขนาด 12 คำ กรุณาทำด่วนเพื่อรักษาเงินของคุณ", "outdated_electrum_wallet_receive_warning": "หากกระเป๋านี้มีซีดีที่มี 12 คำและถูกสร้างขึ้นใน Cake อย่าโอน Bitcoin เข้ากระเป๋านี้ ทุกจำนวน BTC ที่โอนเข้ากระเป๋านี้อาจสูญหาย สร้างกระเป๋าใหม่ที่มีซีดีที่มี 24 คำ (กดที่เมนูที่มุมขวาบนแล้วเลือก Wallets และเลือก Create New Wallet จากนั้นเลือก Bitcoin) และย้าย BTC ไปที่นั้นทันที กระเป๋า BTC ที่มีซีดีที่มี 24 คำของ Cake ปลอดภัย", "outgoing": "ขาออก", + "outputs": "เอาต์พุต", "overwrite_amount": "เขียนทับจำนวน", "pairingInvalidEvent": "การจับคู่เหตุการณ์ที่ไม่ถูกต้อง", "password": "รหัสผ่าน", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 4d88fe640..73cd8a1f7 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "Ang mga pagbabayad sa Bitcoin ay nangangailangan ng 1 kumpirmasyon, na maaaring tumagal ng 20 minuto o mas mahaba. Salamat sa iyong pasensya! Mag -email ka kapag nakumpirma ang pagbabayad.", "Blocks_remaining": "Ang natitirang ${status} ay natitira", "bright_theme": "Maliwanag", + "bump_fee": "Bayad sa paga", "buy": "Bilhin", "buy_alert_content": "Sa kasalukuyan ay sinusuportahan lamang namin ang pagbili ng Bitcoin, Ethereum, Litecoin, at Monero. Mangyaring lumikha o lumipat sa iyong Bitcoin, Ethereum, Litecoin, o Monero Wallet.", "buy_bitcoin": "Bumili ng bitcoin", @@ -133,6 +134,8 @@ "confirm": "Kumpirmahin", "confirm_delete_template": "Ang pagkilos na ito ay tatanggalin ang template na ito. Nais mo bang magpatuloy?", "confirm_delete_wallet": "Ang pagkilos na ito ay tatanggalin ang pitaka na ito. Nais mo bang magpatuloy?", + "confirm_fee_deduction": "Kumpirmahin ang pagbabawas ng bayad", + "confirm_fee_deduction_content": "Sumasang -ayon ka bang bawasan ang bayad mula sa output?", "confirm_sending": "Kumpirmahin ang pagpapadala", "confirmations": "Mga kumpirmasyon", "confirmed": "Nakumpirma na balanse", @@ -212,6 +215,7 @@ "edit_token": "I -edit ang token", "electrum_address_disclaimer": "Bumubuo kami ng mga bagong address sa tuwing gumagamit ka ng isa, ngunit ang mga nakaraang address ay patuloy na gumagana", "email_address": "Email address", + "enable_replace_by_fee": "Paganahin ang palitan-by-fee", "enabled": "Pinagana", "enter_amount": "Ipasok ang halaga", "enter_backup_password": "Ipasok ang backup password dito", @@ -248,6 +252,7 @@ "errorGettingCredentials": "Nabigo: Error habang kumukuha ng mga kredensyal", "errorSigningTransaction": "May naganap na error habang pinipirmahan ang transaksyon", "estimated": "Tinatayang", + "estimated_new_fee": "Tinatayang bagong bayad", "etherscan_history": "Kasaysayan ng Etherscan", "event": "Kaganapan", "events": "Mga kaganapan", @@ -314,6 +319,7 @@ "in_store": "Nakatago", "incoming": "Papasok", "incorrect_seed": "Ang teksto na ipinasok ay hindi wasto.", + "inputs": "Mga input", "introducing_cake_pay": "Ipinakikilala ang cake pay!", "invalid_input": "Di -wastong input", "invoice_details": "Mga detalye ng invoice", @@ -381,6 +387,7 @@ "offer_expires_in": "Mag -expire ang alok sa:", "offline": "Offline", "ok": "Ok", + "old_fee": "Matandang bayad", "onion_link": "Link ng Onion", "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 bayarin.", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "Ang mga bagong wallets ng Bitcoin na nilikha sa cake ay mayroon na ngayong 24-salitang binhi. Ipinag-uutos na lumikha ka ng isang bagong pitaka ng Bitcoin at ilipat ang lahat ng iyong mga pondo sa bagong 24-salitang pitaka, at itigil ang paggamit ng mga pitaka na may 12-salitang binhi. Mangyaring gawin ito kaagad upang ma -secure ang iyong mga pondo.", "outdated_electrum_wallet_receive_warning": "Kung ang pitaka na ito ay may 12-salitang binhi at nilikha sa cake, huwag magdeposito sa Bitcoin sa pitaka na ito. Ang anumang BTC na inilipat sa pitaka na ito ay maaaring mawala. Lumikha ng isang bagong 24-word wallet (tapikin ang menu sa kanang tuktok, piliin ang mga pitaka, piliin ang Lumikha ng Bagong Wallet, pagkatapos ay piliin ang Bitcoin) at agad na ilipat ang iyong BTC doon. Ang mga bagong (24-salita) BTC Wallets mula sa cake ay ligtas", "outgoing": "Palabas", + "outputs": "Mga output", "overwrite_amount": "Overwrite na halaga", "pairingInvalidEvent": "Pagpares ng Di-wastong Kaganapan", "password": "Password", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 599d5bf67..de197c1b1 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "Bitcoin ödemeleri, 20 dakika veya daha uzun sürebilen 1 onay gerektirir. Sabrınız için teşekkürler! Ödeme onaylandığında e-posta ile bilgilendirileceksiniz.", "Blocks_remaining": "${status} Blok Kaldı", "bright_theme": "Parlak", + "bump_fee": "Çarpma ücreti", "buy": "Alış", "buy_alert_content": "Şu anda yalnızca Bitcoin, Ethereum, Litecoin ve Monero satın alımını destekliyoruz. Lütfen Bitcoin, Ethereum, Litecoin veya Monero cüzdanınızı oluşturun veya cüzdanınıza geçin.", "buy_bitcoin": "Bitcoin Satın Al", @@ -133,6 +134,8 @@ "confirm": "Onayla", "confirm_delete_template": "Bu eylem, bu şablonu silecek. Devam etmek istiyor musun?", "confirm_delete_wallet": "Bu eylem, bu cüzdanı silecek. Devam etmek istiyor musun?", + "confirm_fee_deduction": "Ücret kesintisini onaylayın", + "confirm_fee_deduction_content": "Ücreti çıktıdan düşürmeyi kabul ediyor musunuz?", "confirm_sending": "Göndermeyi onayla", "confirmations": "Onay", "confirmed": "Onaylanmış Bakiye", @@ -212,6 +215,7 @@ "edit_token": "Belirteci düzenle", "electrum_address_disclaimer": "Adresini her kullandığında yeni adres oluşturuyoruz, ancak önceki adresler de çalışmaya devam eder", "email_address": "E-posta Adresi", + "enable_replace_by_fee": "Farklı Değiştir'i Etkinleştir", "enabled": "Etkin", "enter_amount": "Miktar Girin", "enter_backup_password": "Yedekleme parolasını buraya gir", @@ -248,6 +252,7 @@ "errorGettingCredentials": "Başarısız: Kimlik bilgileri alınırken hata oluştu", "errorSigningTransaction": "İşlem imzalanırken bir hata oluştu", "estimated": "Tahmini", + "estimated_new_fee": "Tahmini yeni ücret", "etherscan_history": "Etherscan geçmişi", "event": "Etkinlik", "events": "Olaylar", @@ -314,6 +319,7 @@ "in_store": "Mağazada", "incoming": "Gelen", "incorrect_seed": "Girilen metin geçerli değil.", + "inputs": "Girişler", "introducing_cake_pay": "Cake Pay ile tanışın!", "invalid_input": "Geçersiz Giriş", "invoice_details": "fatura detayları", @@ -381,6 +387,7 @@ "offer_expires_in": "Teklifin bitmesine kalan: ", "offline": "Çevrimdışı", "ok": "Tamam", + "old_fee": "Eski ücret", "onion_link": "soğan bağlantısı", "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.", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "Cake'te oluşturulan yeni Bitcoin cüzdanları artık 24 kelimelik bir tohuma sahip. Yeni bir Bitcoin cüzdanı oluşturmanız ve tüm paranızı 24 kelimelik yeni cüzdana aktarmanız ve 12 kelimelik tohuma sahip cüzdanları kullanmayı bırakmanız zorunludur. Lütfen paranızı güvence altına almak için bunu hemen yapın.", "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", "overwrite_amount": "Miktarın üzerine yaz", "pairingInvalidEvent": "Geçersiz Etkinliği Eşleştirme", "password": "Parola", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index b0902aada..86e60214b 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "Платежі Bitcoin потребують 1 підтвердження, яке може зайняти 20 хвилин або більше. Дякую за Ваше терпіння! Ви отримаєте електронний лист, коли платіж буде підтверджено.", "Blocks_remaining": "${status} Залишилось блоків", "bright_theme": "Яскрава", + "bump_fee": "Підвищити комісію", "buy": "Купити", "buy_alert_content": "Наразі ми підтримуємо купівлю лише Bitcoin, Ethereum, Litecoin і Monero. Створіть або перейдіть на свій гаманець Bitcoin, Ethereum, Litecoin або Monero.", "buy_bitcoin": "Купити Bitcoin", @@ -133,6 +134,8 @@ "confirm": "Підтвердити", "confirm_delete_template": "Ця дія видалить шаблон. Ви хочете продовжити?", "confirm_delete_wallet": "Ця дія видалить гаманець. Ви хочете продовжити?", + "confirm_fee_deduction": "Підтвердьте відрахування комісії", + "confirm_fee_deduction_content": "Чи погоджуєтесь ви вирахувати комісію з сумми одержувача?", "confirm_sending": "Підтвердити відправлення", "confirmations": "Підтвердження", "confirmed": "Підтверджений баланс", @@ -212,6 +215,7 @@ "edit_token": "Редагувати маркер", "electrum_address_disclaimer": "Ми створюємо нові адреси щоразу, коли ви використовуєте їх, але попередні адреси продовжують працювати", "email_address": "Адреса електронної пошти", + "enable_replace_by_fee": "Увімкнути заміну з комісією", "enabled": "Увімкнено", "enter_amount": "Введіть суму", "enter_backup_password": "Введіть пароль резервної копії", @@ -248,6 +252,7 @@ "errorGettingCredentials": "Помилка: помилка під час отримання облікових даних", "errorSigningTransaction": "Під час підписання транзакції сталася помилка", "estimated": "Приблизно ", + "estimated_new_fee": "Орієнтовна нова комісія", "etherscan_history": "Історія Etherscan", "event": "Подія", "events": "Події", @@ -314,6 +319,7 @@ "in_store": "У магазині", "incoming": "Вхідні", "incorrect_seed": "Введений текст невірний.", + "inputs": "Вхoди", "introducing_cake_pay": "Представляємо Cake Pay!", "invalid_input": "Неправильні дані", "invoice_details": "Реквізити рахунку-фактури", @@ -381,6 +387,7 @@ "offer_expires_in": "Пропозиція закінчиться через: ", "offline": "Офлайн", "ok": "OK", + "old_fee": "Стара комісія", "onion_link": "Посилання на цибулю", "online": "Онлайн", "onramper_option_description": "Швидко купуйте криптовалюту з багатьма методами оплати. Доступний у більшості країн. Поширення та збори різняться.", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "Нові біткойн-гаманці, створені в Cake, тепер містять мнемонічну фразу з 24 слів. Обов’язково стовріть новий біткойн-гаманець, переведіть всі кошти на новий гаманець із 24 слів і припиніть використання гаманців із мнемонічною фразою з 12 слів. Зробіть це негайно, щоб убезпечити свої кошти.", "outdated_electrum_wallet_receive_warning": "Якщо цей гаманець має мнемонічну фразу з 12 слів і був створений у Cake, НЕ переводьте біткойни на цей гаманець. Будь-які BTC, переведений на цей гаманець, можуть бути втраченими. Створіть новий гаманець з мнемонічною фразою з 24 слів (торкніться меню у верхньому правому куті, виберіть Гаманці, виберіть Створити новий гаманець, потім виберіть Bitcoin) і НЕГАЙНО переведіть туди свії BTC. Нові (з мнемонічною фразою з 24 слів) гаманці BTC від Cake надійно захищені", "outgoing": "Вихідні", + "outputs": "Виходи", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Недійсна подія сполучення", "password": "Пароль", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 1d4d98f45..725a1d895 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "بٹ کوائن کی ادائیگی میں 1 تصدیق کی ضرورت ہوتی ہے ، جس میں 20 منٹ یا اس سے زیادہ وقت لگ سکتا ہے۔ آپ کے صبر کا شکریہ! ادائیگی کی تصدیق ہونے پر آپ کو ای میل کیا جائے گا۔", "Blocks_remaining": "${status} بلاکس باقی ہیں۔", "bright_theme": "روشن", + "bump_fee": "بمپ فیس", "buy": "خریدنے", "buy_alert_content": "۔ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﺱﺍ ﺎﯾ ﮟﯿﺋﺎﻨﺑ ﭧﯿﻟﺍﻭ Monero ﺎﯾ ،Bitcoin، Ethereum، Litecoin ﺎﻨﭘﺍ ﻡ", "buy_bitcoin": "Bitcoin خریدیں۔", @@ -133,6 +134,8 @@ "confirm": "تصدیق کریں۔", "confirm_delete_template": "یہ عمل اس ٹیمپلیٹ کو حذف کر دے گا۔ کیا آپ جاری رکھنا چاہتے ہیں؟", "confirm_delete_wallet": "اس کارروائی سے یہ پرس حذف ہو جائے گا۔ کیا آپ جاری رکھنا چاہتے ہیں؟", + "confirm_fee_deduction": "فیس میں کٹوتی کی تصدیق کریں", + "confirm_fee_deduction_content": "کیا آپ آؤٹ پٹ سے فیس کم کرنے پر راضی ہیں؟", "confirm_sending": "بھیجنے کی تصدیق کریں۔", "confirmations": "تصدیقات", "confirmed": "تصدیق شدہ بیلنس", @@ -212,6 +215,7 @@ "edit_token": "ٹوکن میں ترمیم کریں۔", "electrum_address_disclaimer": "جب بھی آپ ایک کا استعمال کرتے ہیں تو ہم نئے پتے تیار کرتے ہیں، لیکن پچھلے پتے کام کرتے رہتے ہیں۔", "email_address": "ای میل اڈریس", + "enable_replace_by_fee": "فی فیس کو تبدیل کریں", "enabled": "فعال", "enter_amount": "رقم درج کریں۔", "enter_backup_password": "یہاں بیک اپ پاس ورڈ درج کریں۔", @@ -248,6 +252,7 @@ "errorGettingCredentials": "۔ﯽﺑﺍﺮﺧ ﮟﯿﻣ ﮯﻧﺮﮐ ﻞﺻﺎﺣ ﺩﺎﻨﺳﺍ :ﻡﺎﮐﺎﻧ", "errorSigningTransaction": "۔ﮯﮨ ﯽﺌﮔﺁ ﺶﯿﭘ ﯽﺑﺍﺮﺧ ﮏﯾﺍ ﺖﻗﻭ ﮯﺗﺮﮐ ﻂﺨﺘﺳﺩ ﺮﭘ ﻦﯾﺩ ﻦﯿﻟ", "estimated": "تخمینہ لگایا", + "estimated_new_fee": "تخمینہ شدہ نئی فیس", "etherscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﺮﮭﺘﯾﺍ", "event": "ﺐﯾﺮﻘﺗ", "events": "ﺕﺎﺒﯾﺮﻘﺗ", @@ -314,6 +319,7 @@ "in_store": "اسٹور میں", "incoming": "آنے والا", "incorrect_seed": "درج کردہ متن درست نہیں ہے۔", + "inputs": "آدانوں", "introducing_cake_pay": "Cake پے کا تعارف!", "invalid_input": "غلط ان پٹ", "invoice_details": "رسید کی تفصیلات", @@ -381,6 +387,7 @@ "offer_expires_in": "پیشکش کی میعاد اس وقت ختم ہو جاتی ہے:", "offline": "آف لائن", "ok": "ٹھیک ہے", + "old_fee": "پرانی فیس", "onion_link": "پیاز کا لنک", "online": "آن لائن", "onramper_option_description": "ادائیگی کے بہت سے طریقوں سے جلدی سے کرپٹو خریدیں۔ زیادہ تر ممالک میں دستیاب ہے۔ پھیلاؤ اور فیس مختلف ہوتی ہے۔", @@ -399,6 +406,7 @@ "outdated_electrum_wallet_description": "Cake میں بنائے گئے نئے Bitcoin بٹوے میں اب 24 الفاظ کا بیج ہے۔ یہ لازمی ہے کہ آپ ایک نیا Bitcoin والیٹ بنائیں اور اپنے تمام فنڈز کو نئے 24 الفاظ والے والیٹ میں منتقل کریں، اور 12 الفاظ کے بیج والے بٹوے کا استعمال بند کریں۔ براہ کرم اپنے فنڈز کو محفوظ بنانے کے لیے فوری طور پر ایسا کریں۔", "outdated_electrum_wallet_receive_warning": "اگر اس پرس میں 12 الفاظ کا بیج ہے اور اسے Cake میں بنایا گیا ہے، تو اس بٹوے میں Bitcoin جمع نہ کریں۔ اس بٹوے میں منتقل کیا گیا کوئی بھی BTC ضائع ہو سکتا ہے۔ ایک نیا 24 الفاظ والا والیٹ بنائیں (اوپر دائیں جانب مینو کو تھپتھپائیں، Wallets کو منتخب کریں، نیا والیٹ بنائیں، پھر Bitcoin کو منتخب کریں) اور فوری طور پر اپنے BTC کو وہاں منتقل کریں۔ Cake کے نئے (24-لفظوں) BTC بٹوے محفوظ ہیں۔", "outgoing": "سبکدوش ہونے والے", + "outputs": "نتائج", "overwrite_amount": "رقم کو اوور رائٹ کریں۔", "pairingInvalidEvent": "ﭧﻧﻮﯾﺍ ﻂﻠﻏ ﺎﻧﺎﻨﺑ ﺍﮌﻮﺟ", "password": "پاس ورڈ", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 9128427e5..517757716 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "Àwọn àránṣẹ́ Bitcoin nílò ìjẹ́rìísí kan. Ó lè lo ìṣéjú ogun tàbí ìṣéjú jù. A dúpẹ́ fún sùúrù yín! Ẹ máa gba ímeèlì t'ó bá jẹ́rìísí àránṣẹ́ náà.", "Blocks_remaining": "Àkójọpọ̀ ${status} kikù", "bright_theme": "Funfun", + "bump_fee": "Ọya ija", "buy": "Rà", "buy_alert_content": "Lọwọlọwọ a ṣe atilẹyin rira Bitcoin, Ethereum, Litecoin, ati Monero. Jọwọ ṣẹda tabi yipada si Bitcoin, Ethereum, Litecoin, tabi apamọwọ Monero.", "buy_bitcoin": "Ra Bitcoin", @@ -133,6 +134,8 @@ "confirm": "Jẹ́rìísí", "confirm_delete_template": "Ìṣe yìí máa yọ àwòṣe yìí kúrò. Ṣé ẹ fẹ́ tẹ̀síwájú?", "confirm_delete_wallet": "Ìṣe yìí máa yọ àpamọ́wọ́ yìí kúrò. Ṣé ẹ fẹ́ tẹ̀síwájú?", + "confirm_fee_deduction": "Jẹrisi iyọkuro owo", + "confirm_fee_deduction_content": "Ṣe o gba lati yọkuro idiyele naa kuro ni iṣejade?", "confirm_sending": "Jẹ́rìí sí ránṣẹ́", "confirmations": "Àwọn ẹ̀rí", "confirmed": "A ti jẹ́rìí ẹ̀", @@ -213,6 +216,7 @@ "edit_token": "Ṣatunkọ àmi", "electrum_address_disclaimer": "A dá àwọn àdírẹ́sì títun ní gbogbo àwọn ìgbà t'ẹ́ lo ó kan ṣùgbọ́n ẹ lè tẹ̀síwájú lo àwọn àdírẹ́sì tẹ́lẹ̀tẹ́lẹ̀.", "email_address": "Àdírẹ́sì ímeèlì", + "enable_replace_by_fee": "Mu ki o rọpo", "enabled": "Wọ́n tíwọn ti tan", "enter_amount": "Tẹ̀ iye", "enter_backup_password": "Tẹ̀ ọ̀rọ̀ aṣínà ti ẹ̀dà ḿbí", @@ -249,6 +253,7 @@ "errorGettingCredentials": "Kuna: Aṣiṣe lakoko gbigba awọn iwe-ẹri", "errorSigningTransaction": "Aṣiṣe kan ti waye lakoko ti o fowo si iṣowo", "estimated": "Ó tó a fojú díwọ̀n", + "estimated_new_fee": "Ifoju tuntun owo tuntun", "etherscan_history": "Etherscan itan", "event": "Iṣẹlẹ", "events": "Awọn iṣẹlẹ", @@ -315,6 +320,7 @@ "in_store": "A níyí", "incoming": "Wọ́n tó ń bọ̀", "incorrect_seed": "Ọ̀rọ̀ tí a tẹ̀ kì í ṣe èyí.", + "inputs": "Igbewọle", "introducing_cake_pay": "Ẹ bá Cake Pay!", "invalid_input": "Iṣawọle ti ko tọ", "invoice_details": "Iru awọn ẹya ọrọ", @@ -382,6 +388,7 @@ "offer_expires_in": "Ìrònúdábàá máa gbẹ́mìí mì ní: ", "offline": "kò wà lórí ayélujára", "ok": "Ó dáa", + "old_fee": "Oya atijọ", "onion_link": "Kọja ilọ alubosa", "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ọ.", @@ -398,6 +405,7 @@ "outdated_electrum_wallet_description": "Àwọn àpamọ́wọ́ títun Bitcoin ti a ti dá nínú Cake Wallet lọ́wọ́lọ́wọ́. Àwọn àpamọ́wọ́ títun t'á dá nínú Cake Wallet ni hóró tó ní ọ̀rọ̀ mẹ́rinlélógún. Ẹ gbọ́dọ̀ dá àpamọ́wọ́. Ẹ sì sún gbogbo owó yín sí àpamọ́wọ́ títun náà tó dá lórí ọ̀rọ̀ mẹ́rinlélógún. Ẹ sì gbọ́dọ̀ yé lo àwọn àpamọ́wọ́ tó dá lórí hóró tó ní ọ̀rọ̀ méjìlá. Ẹ jọ̀wọ́ ṣe èyí láìpẹ́ kí ẹ ba owó yín.", "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", "overwrite_amount": "Pààrọ̀ iye owó", "pairingInvalidEvent": "Pipọpọ Iṣẹlẹ Ti ko tọ", "password": "Ọ̀rọ̀ aṣínà", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index d9ac86b34..104848996 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -79,6 +79,7 @@ "bitcoin_payments_require_1_confirmation": "比特币支付需要 1 次确认,这可能需要 20 分钟或更长时间。谢谢你的耐心!确认付款后,您将收到电子邮件。", "Blocks_remaining": "${status} 剩余的块", "bright_theme": "明亮", + "bump_fee": "撞费", "buy": "购买", "buy_alert_content": "目前我们仅支持购买比特币、以太坊、莱特币和门罗币。请创建或切换到您的比特币、以太坊、莱特币或门罗币钱包。", "buy_bitcoin": "购买比特币", @@ -133,6 +134,8 @@ "confirm": "确认", "confirm_delete_template": "此操作将刪除此模板。确定吗?", "confirm_delete_wallet": "此操作将刪除此钱包。确定吗?", + "confirm_fee_deduction": "确认费用扣除", + "confirm_fee_deduction_content": "您是否同意从产出中扣除费用?", "confirm_sending": "确认发送", "confirmations": "确认", "confirmed": "确认余额", @@ -212,6 +215,7 @@ "edit_token": "编辑令牌", "electrum_address_disclaimer": "每次您使用一个地址时,我们都会生成新地址,但之前的地址仍然有效", "email_address": "电子邮件地址", + "enable_replace_by_fee": "启用by-Fee替换", "enabled": "启用", "enter_amount": "输入金额", "enter_backup_password": "在此处输入備用密码", @@ -248,6 +252,7 @@ "errorGettingCredentials": "失败:获取凭据时出错", "errorSigningTransaction": "签署交易时发生错误", "estimated": "估计值", + "estimated_new_fee": "估计新费用", "etherscan_history": "以太扫描历史", "event": "事件", "events": "活动", @@ -314,6 +319,7 @@ "in_store": "店内", "incoming": "收到", "incorrect_seed": "输入的文字无效。", + "inputs": "输入", "introducing_cake_pay": "介绍 Cake Pay!", "invalid_input": "输入无效", "invoice_details": "发票明细", @@ -381,6 +387,7 @@ "offer_expires_in": "优惠有效期至 ", "offline": "离线", "ok": "确认", + "old_fee": "旧费用", "onion_link": "洋葱链接", "online": "在线", "onramper_option_description": "快速使用许多付款方式购买加密货币。在大多数国家 /地区可用。利差和费用各不相同。", @@ -397,6 +404,7 @@ "outdated_electrum_wallet_description": "在Cake创建的新比特币钱包现在有一个24字的种子。你必须创建一个新的比特币钱包,并将你所有的资金转移到新的24字钱包,并停止使用12字种子的钱包。请立即这样做以保证你的资金安全。", "outdated_electrum_wallet_receive_warning": "如果这个钱包有一个 12 字的种子并且是在 Cake 中创建的,不要将比特币存入这个钱包。 任何转移到此钱包的 BTC 都可能丢失。 创建一个新的 24 字钱包(点击右上角的菜单,选择钱包,选择创建新钱包,然后选择比特币)并立即将您的 BTC 移到那里。 Cake 的新(24 字)BTC 钱包是安全的", "outgoing": "发送", + "outputs": "输出", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "配对无效事件", "password": "密码", diff --git a/scripts/append_translation.sh b/scripts/append_translation.sh deleted file mode 100755 index 0cc33fc0f..000000000 --- a/scripts/append_translation.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -# to use on Mac first install the translation shell `brew install translate-shell` -# then install the jq `brew install jq` -# then run this file with the English key and value that you want to be translated -# `./append_translation.sh "greetings" "Hello World!"` -# if you get an error `command not found` -# give the correct permissions to this file using `chmod 777 append_translation.sh` - -langs=("ar" "bg" "cs" "de" "en" "es" "fr" "ha" "hi" "hr" "id" "it" "ja" "ko" "my" "nl" "pl" "pt" "ru" "th" "tl" "tr" "uk" "ur" "yo" "zh") - -name=$1 -text=$2 - -for lang in "${langs[@]}"; do - translation="$(trans en:$lang --brief "$text")" - - # Use jq to add the new key-value pair to the JSON object - jq_result=$(jq '. += { "'"$name"'": "'"$translation"'" }' ../res/values/strings_$lang.arb) - - echo "$jq_result" > ../res/values/strings_$lang.arb - echo 'Added { "'"$name"'": "'"$translation"'" } to '"strings_$lang.arb"'' -done diff --git a/tool/configure.dart b/tool/configure.dart index b3aa44feb..06243e8ab 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -87,6 +87,7 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_bitcoin/litecoin_wallet_service.dart'; +import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:mobx/mobx.dart'; """; const bitcoinCwPart = "part 'cw_bitcoin.dart';"; @@ -135,13 +136,14 @@ abstract class Bitcoin { String formatterBitcoinAmountToString({required int amount}); double formatterBitcoinAmountToDouble({required int amount}); int formatterStringDoubleToBitcoinAmount(String amount); - String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate); + String bitcoinTransactionPriorityWithLabel(TransactionPriority priority, int rate, {int? customRate}); List getUnspents(Object wallet); Future updateUnspents(Object wallet); WalletService createBitcoinWalletService(Box walletInfoSource, Box unspentCoinSource); WalletService createLitecoinWalletService(Box walletInfoSource, Box unspentCoinSource); TransactionPriority getBitcoinTransactionPriorityMedium(); + TransactionPriority getBitcoinTransactionPriorityCustom(); TransactionPriority getLitecoinTransactionPriorityMedium(); TransactionPriority getBitcoinTransactionPrioritySlow(); TransactionPriority getLitecoinTransactionPrioritySlow(); @@ -151,6 +153,12 @@ abstract class Bitcoin { List getBitcoinReceivePageOptions(); BitcoinAddressType getBitcoinAddressType(ReceivePageOption option); bool hasTaprootInput(PendingTransaction pendingTransaction); + + Future replaceByFee(Object wallet, String transactionHash, String fee); + Future canReplaceByFee(Object wallet, String transactionHash); + Future isChangeSufficientForFee(Object wallet, String txId, String newFee); + int getFeeAmountForPriority(Object wallet, TransactionPriority priority, int inputsCount, int outputsCount, {int? size}); + int getFeeAmountWithFeeRate(Object wallet, int feeRate, int inputsCount, int outputsCount, {int? size}); } """; From d4b317b3a0ee77245666651aad4638f9d2c3700c Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Mon, 8 Apr 2024 10:42:27 -0700 Subject: [PATCH 171/241] minor fix (#1371) --- lib/buy/moonpay/moonpay_provider.dart | 72 +++++++++++++-------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/lib/buy/moonpay/moonpay_provider.dart b/lib/buy/moonpay/moonpay_provider.dart index 52a4f6187..fea8fdabd 100644 --- a/lib/buy/moonpay/moonpay_provider.dart +++ b/lib/buy/moonpay/moonpay_provider.dart @@ -155,7 +155,7 @@ class MoonPayProvider extends BuyProvider { 'baseCurrencyAmount': amount ?? '0', 'currencyCode': currencyCode, 'walletAddress': walletAddress, - 'lockAmount': 'true', + 'lockAmount': 'false', 'showAllCurrencies': 'false', 'showWalletAddressForm': 'false', 'enabledPaymentMethods': @@ -256,44 +256,44 @@ class MoonPayProvider extends BuyProvider { @override Future launchProvider(BuildContext context, bool? isBuyAction) async { - // try { - late final Uri uri; - if (isBuyAction ?? true) { - uri = await requestBuyMoonPayUrl( - currency: wallet.currency, - walletAddress: wallet.walletAddresses.address, - settingsStore: _settingsStore, - ); - } else { - uri = await requestSellMoonPayUrl( - currency: wallet.currency, - refundWalletAddress: wallet.walletAddresses.address, - settingsStore: _settingsStore, - ); - } - - if (await canLaunchUrl(uri)) { - if (DeviceInfo.instance.isMobile) { - Navigator.of(context).pushNamed(Routes.webViewPage, arguments: ['MoonPay', uri]); + try { + late final Uri uri; + if (isBuyAction ?? true) { + uri = await requestBuyMoonPayUrl( + currency: wallet.currency, + walletAddress: wallet.walletAddresses.address, + settingsStore: _settingsStore, + ); } else { - await launchUrl(uri, mode: LaunchMode.externalApplication); + uri = await requestSellMoonPayUrl( + currency: wallet.currency, + refundWalletAddress: wallet.walletAddresses.address, + settingsStore: _settingsStore, + ); } - } else { - throw Exception('Could not launch URL'); + + if (await canLaunchUrl(uri)) { + if (DeviceInfo.instance.isMobile) { + Navigator.of(context).pushNamed(Routes.webViewPage, arguments: ['MoonPay', uri]); + } else { + await launchUrl(uri, mode: LaunchMode.externalApplication); + } + } else { + throw Exception('Could not launch URL'); + } + } catch (e) { + await showDialog( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: 'MoonPay', + alertContent: 'The MoonPay service is currently unavailable: $e', + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop(), + ); + }, + ); } - // } catch (e) { - // await showDialog( - // context: context, - // builder: (BuildContext context) { - // return AlertWithOneAction( - // alertTitle: 'MoonPay', - // alertContent: 'The MoonPay service is currently unavailable: $e', - // buttonText: S.of(context).ok, - // buttonAction: () => Navigator.of(context).pop(), - // ); - // }, - // ); - // } } String _normalizeCurrency(CryptoCurrency currency) { From 2877cc160c707e0826aa6ae75a7eab36fffa8648 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Mon, 8 Apr 2024 23:53:14 +0100 Subject: [PATCH 172/241] CW-608-Fetch-And-Save-Icons-Of-ERC20-And-SPL-Tokens-When-Adding-Them (#1365) * feat: Fetch and save icons of SPL tokens when adding them * feat: Implement fetch and save icons for ERC20 tokens when adding them * fix: Add moralisApiKey to evm secrets * Add check to ensure decimals cannot be zero * - Fallback to adding erc20 token from web3dart - Wrap fetching spl token icon in a try/catch block --------- Co-authored-by: OmarHatem --- .github/workflows/pr_test_build.yml | 1 + cw_evm/lib/evm_chain_client.dart | 51 ++++++++++++++++--- cw_evm/lib/evm_chain_wallet.dart | 19 ++++--- cw_solana/lib/solana_client.dart | 17 +++++++ cw_solana/lib/solana_wallet.dart | 6 +++ cw_solana/lib/spl_token.dart | 3 +- lib/ethereum/cw_ethereum.dart | 2 +- lib/polygon/cw_polygon.dart | 2 +- lib/solana/cw_solana.dart | 1 + .../screens/dashboard/edit_token_page.dart | 10 ++++ .../screens/dashboard/home_settings_page.dart | 38 +++++++------- .../screens/dashboard/pages/balance_page.dart | 42 +++++++-------- lib/src/widgets/cake_image_widget.dart | 2 +- .../dashboard/home_settings_view_model.dart | 2 + res/values/strings_ar.arb | 1 + res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 1 + res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 1 + res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 3 +- res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 3 +- res/values/strings_nl.arb | 3 +- res/values/strings_pl.arb | 3 +- res/values/strings_pt.arb | 3 +- res/values/strings_ru.arb | 3 +- res/values/strings_th.arb | 3 +- res/values/strings_tl.arb | 3 +- res/values/strings_tr.arb | 3 +- res/values/strings_uk.arb | 3 +- res/values/strings_ur.arb | 3 +- res/values/strings_yo.arb | 3 +- res/values/strings_zh.arb | 3 +- tool/utils/secret_key.dart | 1 + 41 files changed, 182 insertions(+), 69 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index ddc8869f0..db9870412 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -140,6 +140,7 @@ jobs: echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart + echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart echo "const exolixApiKey = '${{ secrets.EXOLIX_API_KEY }}';" >> lib/.secrets.g.dart echo "const robinhoodApplicationId = '${{ secrets.ROBINHOOD_APPLICATION_ID }}';" >> lib/.secrets.g.dart diff --git a/cw_evm/lib/evm_chain_client.dart b/cw_evm/lib/evm_chain_client.dart index cf73b13db..eebbe4f4f 100644 --- a/cw_evm/lib/evm_chain_client.dart +++ b/cw_evm/lib/evm_chain_client.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:developer'; import 'package:cw_core/node.dart'; @@ -9,6 +10,7 @@ import 'package:cw_evm/evm_erc20_balance.dart'; import 'package:cw_evm/evm_chain_transaction_model.dart'; import 'package:cw_evm/pending_evm_chain_transaction.dart'; import 'package:cw_evm/evm_chain_transaction_priority.dart'; +import 'package:cw_evm/.secrets.g.dart' as secrets; import 'package:flutter/services.dart'; import 'package:http/http.dart'; @@ -211,26 +213,61 @@ abstract class EVMChainClient { return EVMChainERC20Balance(balance, exponent: exponent); } - Future getErc20Token(String contractAddress) async { + Future getErc20Token(String contractAddress, String chainName) async { try { - final erc20 = ERC20(address: EthereumAddress.fromHex(contractAddress), client: _client!); - final name = await erc20.name(); - final symbol = await erc20.symbol(); - final decimal = await erc20.decimals(); + final uri = Uri.https( + 'deep-index.moralis.io', + '/api/v2.2/erc20/metadata', + { + "chain": chainName, + "addresses": contractAddress, + }, + ); + + final response = await httpClient.get( + uri, + headers: { + "Accept": "application/json", + "X-API-Key": secrets.moralisApiKey, + }, + ); + + final decodedResponse = jsonDecode(response.body)[0] as Map; + + final name = decodedResponse['name'] ?? ''; + final symbol = decodedResponse['symbol'] ?? ''; + final decimal = decodedResponse['decimals'] ?? '0'; + final iconPath = decodedResponse['logo'] ?? ''; return Erc20Token( name: name, symbol: symbol, contractAddress: contractAddress, - decimal: decimal.toInt(), + decimal: int.tryParse(decimal) ?? 0, + iconPath: iconPath, ); } catch (e) { + try { + final erc20 = ERC20(address: EthereumAddress.fromHex(contractAddress), client: _client!); + final name = await erc20.name(); + final symbol = await erc20.symbol(); + final decimal = await erc20.decimals(); + + return Erc20Token( + name: name, + symbol: symbol, + contractAddress: contractAddress, + decimal: decimal.toInt(), + ); + } catch (_) {} + return null; } } Uint8List hexToBytes(String hexString) { - return Uint8List.fromList(hex.HEX.decode(hexString.startsWith('0x') ? hexString.substring(2) : hexString)); + return Uint8List.fromList( + hex.HEX.decode(hexString.startsWith('0x') ? hexString.substring(2) : hexString)); } void stop() { diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart index c90a3e809..4193e590a 100644 --- a/cw_evm/lib/evm_chain_wallet.dart +++ b/cw_evm/lib/evm_chain_wallet.dart @@ -439,11 +439,16 @@ abstract class EVMChainWalletBase Future addErc20Token(Erc20Token token) async { String? iconPath; - try { - iconPath = CryptoCurrency.all - .firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase()) - .iconPath; - } catch (_) {} + + if (token.iconPath == null || token.iconPath!.isEmpty) { + try { + iconPath = CryptoCurrency.all + .firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase()) + .iconPath; + } catch (_) {} + } else { + iconPath = token.iconPath; + } final newToken = createNewErc20TokenObject(token, iconPath); @@ -466,8 +471,8 @@ abstract class EVMChainWalletBase _updateBalance(); } - Future getErc20Token(String contractAddress) async => - await _client.getErc20Token(contractAddress); + Future getErc20Token(String contractAddress, String chainName) async => + await _client.getErc20Token(contractAddress, chainName); void _onNewTransaction() { _updateBalance(); diff --git a/cw_solana/lib/solana_client.dart b/cw_solana/lib/solana_client.dart index 781fff5f7..6ed8cab29 100644 --- a/cw_solana/lib/solana_client.dart +++ b/cw_solana/lib/solana_client.dart @@ -533,4 +533,21 @@ class SolanaWalletClient { throw Exception(e); } } + + Future getIconImageFromTokenUri(String uri) async { + try { + final response = await httpClient.get(Uri.parse(uri)); + + final jsonResponse = json.decode(response.body) as Map; + + if (response.statusCode >= 200 && response.statusCode < 300) { + return jsonResponse['image']; + } else { + return null; + } + } catch (e) { + print('Error occurred while fetching token image: \n${e.toString()}'); + return null; + } + } } diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart index f69a597ae..ad58c4293 100644 --- a/cw_solana/lib/solana_wallet.dart +++ b/cw_solana/lib/solana_wallet.dart @@ -464,11 +464,17 @@ abstract class SolanaWalletBase return null; } + String? iconPath; + try { + iconPath = await _client.getIconImageFromTokenUri(token.uri); + } catch (_) {} + return SPLToken.fromMetadata( name: token.name, mint: token.mint, symbol: token.symbol, mintAddress: mintAddress, + iconPath: iconPath, ); } catch (e) { return null; diff --git a/cw_solana/lib/spl_token.dart b/cw_solana/lib/spl_token.dart index 0413990b1..0b3b8b372 100644 --- a/cw_solana/lib/spl_token.dart +++ b/cw_solana/lib/spl_token.dart @@ -55,6 +55,7 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin { required String mint, required String symbol, required String mintAddress, + String? iconPath }) { return SPLToken( name: name, @@ -62,7 +63,7 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin { mintAddress: mintAddress, decimal: 0, mint: mint, - iconPath: '', + iconPath: iconPath, ); } diff --git a/lib/ethereum/cw_ethereum.dart b/lib/ethereum/cw_ethereum.dart index 52839d68a..13fe3aafd 100644 --- a/lib/ethereum/cw_ethereum.dart +++ b/lib/ethereum/cw_ethereum.dart @@ -131,7 +131,7 @@ class CWEthereum extends Ethereum { @override Future getErc20Token(WalletBase wallet, String contractAddress) async { final ethereumWallet = wallet as EthereumWallet; - return await ethereumWallet.getErc20Token(contractAddress); + return await ethereumWallet.getErc20Token(contractAddress, 'eth'); } @override diff --git a/lib/polygon/cw_polygon.dart b/lib/polygon/cw_polygon.dart index 0ee7457eb..9f0f9a1bf 100644 --- a/lib/polygon/cw_polygon.dart +++ b/lib/polygon/cw_polygon.dart @@ -129,7 +129,7 @@ class CWPolygon extends Polygon { @override Future getErc20Token(WalletBase wallet, String contractAddress) async { final polygonWallet = wallet as PolygonWallet; - return await polygonWallet.getErc20Token(contractAddress); + return await polygonWallet.getErc20Token(contractAddress, 'polygon'); } @override diff --git a/lib/solana/cw_solana.dart b/lib/solana/cw_solana.dart index d6df78318..6f4b17309 100644 --- a/lib/solana/cw_solana.dart +++ b/lib/solana/cw_solana.dart @@ -86,6 +86,7 @@ class CWSolana extends Solana { decimal: token.decimals, mint: token.name.toUpperCase(), enabled: token.enabled, + iconPath: token.iconPath, ); await (wallet as SolanaWallet).addSPLToken(splToken); diff --git a/lib/src/screens/dashboard/edit_token_page.dart b/lib/src/screens/dashboard/edit_token_page.dart index 1a1db8658..59f7de9e5 100644 --- a/lib/src/screens/dashboard/edit_token_page.dart +++ b/lib/src/screens/dashboard/edit_token_page.dart @@ -59,6 +59,7 @@ class _EditTokenPageBodyState extends State { final TextEditingController _tokenNameController = TextEditingController(); final TextEditingController _tokenSymbolController = TextEditingController(); final TextEditingController _tokenDecimalController = TextEditingController(); + final TextEditingController _tokenIconPathController = TextEditingController(); final FocusNode _contractAddressFocusNode = FocusNode(); final FocusNode _tokenNameFocusNode = FocusNode(); @@ -83,6 +84,7 @@ class _EditTokenPageBodyState extends State { _tokenNameController.text = widget.token!.name; _tokenSymbolController.text = widget.token!.title; _tokenDecimalController.text = widget.token!.decimals.toString(); + _tokenIconPathController.text = widget.token?.iconPath ?? ''; } if (widget.initialContractAddress != null) { @@ -200,6 +202,7 @@ class _EditTokenPageBodyState extends State { name: _tokenNameController.text, title: _tokenSymbolController.text.toUpperCase(), decimals: int.parse(_tokenDecimalController.text), + iconPath: _tokenIconPathController.text, ), contractAddress: _contractAddressController.text, ); @@ -228,6 +231,8 @@ class _EditTokenPageBodyState extends State { if (token != null) { if (_tokenNameController.text.isEmpty) _tokenNameController.text = token.name; if (_tokenSymbolController.text.isEmpty) _tokenSymbolController.text = token.title; + if (_tokenIconPathController.text.isEmpty) + _tokenIconPathController.text = token.iconPath ?? ''; if (_tokenDecimalController.text.isEmpty) _tokenDecimalController.text = token.decimals.toString(); } @@ -305,10 +310,15 @@ class _EditTokenPageBodyState extends State { if (text?.isEmpty ?? true) { return S.of(context).field_required; } + if (int.tryParse(text!) == null) { return S.of(context).invalid_input; } + if (int.tryParse(text) == 0) { + return S.current.decimals_cannot_be_zero; + } + return null; }, ), diff --git a/lib/src/screens/dashboard/home_settings_page.dart b/lib/src/screens/dashboard/home_settings_page.dart index e841423c1..aa6bb12c0 100644 --- a/lib/src/screens/dashboard/home_settings_page.dart +++ b/lib/src/screens/dashboard/home_settings_page.dart @@ -129,25 +129,29 @@ class HomeSettingsPage extends BasePage { 'token': token, }); }, - leading: CakeImageWidget( - imageUrl: token.iconPath, - height: 40, - width: 40, - displayOnError: Container( - height: 30.0, - width: 30.0, - child: Center( - child: Text( - token.title.substring(0, min(token.title.length, 2)), - style: TextStyle(fontSize: 11), - ), - ), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.grey.shade400, + leading: Container( + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration(shape: BoxShape.circle), + child: CakeImageWidget( + imageUrl: token.iconPath, + height: 40, + width: 40, + displayOnError: Container( + height: 30.0, + width: 30.0, + child: Center( + child: Text( + token.title.substring(0, min(token.title.length, 2)), + style: TextStyle(fontSize: 11), ), + ), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.grey.shade400, + ), + ), ), - ), + ), decoration: BoxDecoration( color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(30), diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart index bb3ec70dc..0b7596469 100644 --- a/lib/src/screens/dashboard/pages/balance_page.dart +++ b/lib/src/screens/dashboard/pages/balance_page.dart @@ -323,7 +323,7 @@ class BalanceRowWidget extends StatelessWidget { style: TextStyle( fontSize: 16, fontFamily: 'Lato', - fontWeight: FontWeight.w500, + fontWeight: FontWeight.w500, color: Theme.of(context).extension()!.textColor, height: 1)), ], @@ -334,24 +334,28 @@ class BalanceRowWidget extends StatelessWidget { child: Center( child: Column( children: [ - CakeImageWidget( - imageUrl: currency.iconPath, - height: 40, - width: 40, - displayOnError: Container( - height: 30.0, - width: 30.0, - child: Center( - child: Text( - currency.title.substring(0, min(currency.title.length, 2)), - style: TextStyle(fontSize: 11), - ), - ), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.grey.shade400, + Container( + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration(shape: BoxShape.circle), + child: CakeImageWidget( + imageUrl: currency.iconPath, + height: 40, + width: 40, + displayOnError: Container( + height: 30.0, + width: 30.0, + child: Center( + child: Text( + currency.title.substring(0, min(currency.title.length, 2)), + style: TextStyle(fontSize: 11), ), ), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.grey.shade400, + ), + ), + ), ), const SizedBox(height: 10), Text( @@ -410,9 +414,7 @@ class BalanceRowWidget extends StatelessWidget { fontSize: 20, fontFamily: 'Lato', fontWeight: FontWeight.w400, - color: Theme.of(context) - .extension()! - .balanceAmountColor, + color: Theme.of(context).extension()!.balanceAmountColor, height: 1, ), maxLines: 1, diff --git a/lib/src/widgets/cake_image_widget.dart b/lib/src/widgets/cake_image_widget.dart index 14c62ad34..ad02c48dd 100644 --- a/lib/src/widgets/cake_image_widget.dart +++ b/lib/src/widgets/cake_image_widget.dart @@ -18,7 +18,7 @@ class CakeImageWidget extends StatelessWidget { @override Widget build(BuildContext context) { try { - if (imageUrl == null) return _displayOnError!; + if (imageUrl == null || imageUrl!.isEmpty) return _displayOnError!; if (imageUrl!.contains('assets/images')) { return Image.asset( diff --git a/lib/view_model/dashboard/home_settings_view_model.dart b/lib/view_model/dashboard/home_settings_view_model.dart index 4b9811c37..e60a37ccf 100644 --- a/lib/view_model/dashboard/home_settings_view_model.dart +++ b/lib/view_model/dashboard/home_settings_view_model.dart @@ -54,6 +54,7 @@ abstract class HomeSettingsViewModelBase with Store { symbol: token.title, decimal: token.decimals, contractAddress: contractAddress, + iconPath: token.iconPath, ); await ethereum!.addErc20Token(_balanceViewModel.wallet, erc20token); @@ -65,6 +66,7 @@ abstract class HomeSettingsViewModelBase with Store { symbol: token.title, decimal: token.decimals, contractAddress: contractAddress, + iconPath: token.iconPath, ); await polygon!.addErc20Token(_balanceViewModel.wallet, polygonToken); } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 08815bf1d..d0f1a2043 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -175,6 +175,7 @@ "debit_card": "بطاقة ائتمان", "debit_card_terms": "يخضع تخزين واستخدام رقم بطاقة الدفع الخاصة بك (وبيانات الاعتماد المقابلة لرقم بطاقة الدفع الخاصة بك) في هذه المحفظة الرقمية لشروط وأحكام اتفاقية حامل البطاقة المعمول بها مع جهة إصدار بطاقة الدفع ، كما هو معمول به من وقت لآخر.", "decimal_places_error": "عدد كبير جدًا من المنازل العشرية", + "decimals_cannot_be_zero": "الرمز العشري لا يمكن أن يكون الصفر.", "default_buy_provider": "مزود شراء الافتراضي", "default_sell_provider": "ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ", "delete": "حذف", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 49e494394..249952d75 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -175,6 +175,7 @@ "debit_card": "Дебитна карта", "debit_card_terms": "Съхранението и използването на данните от вашата платежна карта в този дигитален портфейл подлежат на условията на съответното съгласие за картодържец от издателя на картата.", "decimal_places_error": "Твърде много знаци след десетичната запетая", + "decimals_cannot_be_zero": "Десетичната точка не може да бъде нула.", "default_buy_provider": "Доставчик по подразбиране купува", "default_sell_provider": "Доставчик за продажба по подразбиране", "delete": "Изтрий", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 348b6fa38..9b3b06ffd 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -175,6 +175,7 @@ "debit_card": "Debetní karta", "debit_card_terms": "Uložení a použití vašeho čísla platební karty (a přihlašovací údaje k vašemu číslu karty) v této digitální peněžence se řídí Obchodními podmínkami smlouvy příslušného držitele karty s vydavatelem karty (v jejich nejaktuálnější verzi).", "decimal_places_error": "Příliš mnoho desetinných míst", + "decimals_cannot_be_zero": "Desetinná desetinná škola nemůže být nulová.", "default_buy_provider": "Výchozí poskytovatel nákupu", "default_sell_provider": "Výchozí poskytovatel prodeje", "delete": "Smazat", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 25ab3a54d..8a914628f 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -175,6 +175,7 @@ "debit_card": "Debitkarte", "debit_card_terms": "Die Speicherung und Nutzung Ihrer Zahlungskartennummer (und Ihrer Zahlungskartennummer entsprechenden Anmeldeinformationen) in dieser digitalen Geldbörse unterliegt den Allgemeinen Geschäftsbedingungen des geltenden Karteninhabervertrags mit dem Zahlungskartenaussteller, gültig ab von Zeit zu Zeit.", "decimal_places_error": "Zu viele Nachkommastellen", + "decimals_cannot_be_zero": "Token -Dezimalzahl kann nicht Null sein.", "default_buy_provider": "Standard-Kaufanbieter", "default_sell_provider": "Standard-Verkaufsanbieter", "delete": "Löschen", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 45e8ef21b..3fe9474c5 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -175,6 +175,7 @@ "debit_card": "Debit Card", "debit_card_terms": "The storage and usage of your payment card number (and credentials corresponding to your payment card number) in this digital wallet are subject to the Terms and Conditions of the applicable cardholder agreement with the payment card issuer, as in effect from time to time.", "decimal_places_error": "Too many decimal places", + "decimals_cannot_be_zero": "Token decimal cannot be zero.", "default_buy_provider": "Default Buy Provider", "default_sell_provider": "Default Sell Provider", "delete": "Delete", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index e04bc4cfe..47b11bc48 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -175,6 +175,7 @@ "debit_card": "Tarjeta de Débito", "debit_card_terms": "El almacenamiento y el uso de su número de tarjeta de pago (y las credenciales correspondientes a su número de tarjeta de pago) en esta billetera digital están sujetos a los Términos y condiciones del acuerdo del titular de la tarjeta aplicable con el emisor de la tarjeta de pago, en vigor desde tiempo al tiempo.", "decimal_places_error": "Demasiados lugares decimales", + "decimals_cannot_be_zero": "Token Decimal no puede ser cero.", "default_buy_provider": "Proveedor de compra predeterminado", "default_sell_provider": "Proveedor de venta predeterminado", "delete": "Borrar", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 069f569ba..edae901a3 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -175,6 +175,7 @@ "debit_card": "Carte de débit", "debit_card_terms": "Le stockage et l'utilisation de votre numéro de carte de paiement (et des informations d'identification correspondant à votre numéro de carte de paiement) dans ce portefeuille (wallet) numérique peuvent être soumis aux conditions générales de l'accord du titulaire de carte parfois en vigueur avec l'émetteur de la carte de paiement.", "decimal_places_error": "Trop de décimales", + "decimals_cannot_be_zero": "La décimale du jeton ne peut pas être nulle.", "default_buy_provider": "Fournisseur d'achat par défaut", "default_sell_provider": "Fournisseur de vente par défaut", "delete": "Effacer", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 7dd1cd52e..c7174d23f 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -175,6 +175,7 @@ "debit_card": "Katin Zare kudi", "debit_card_terms": "Adana da amfani da lambar katin kuɗin ku (da takaddun shaida masu dacewa da lambar katin kuɗin ku) a cikin wannan walat ɗin dijital suna ƙarƙashin Sharuɗɗa da Sharuɗɗa na yarjejeniya mai amfani da katin tare da mai fitar da katin biyan kuɗi, kamar yadda yake aiki daga lokaci zuwa lokaci.", "decimal_places_error": "Wadannan suna da tsawon harsuna", + "decimals_cannot_be_zero": "Alamar alama ba zata iya zama sifili ba.", "default_buy_provider": "Tsohuwar Siyarwa", "default_sell_provider": "Tsohuwar Mai Bayar Siyarwa", "delete": "Share", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 5dbe22f0e..4ee9bd4f8 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -175,6 +175,7 @@ "debit_card": "डेबिट कार्ड", "debit_card_terms": "इस डिजिटल वॉलेट में आपके भुगतान कार्ड नंबर (और आपके भुगतान कार्ड नंबर से संबंधित क्रेडेंशियल) का भंडारण और उपयोग भुगतान कार्ड जारीकर्ता के साथ लागू कार्डधारक समझौते के नियमों और शर्तों के अधीन है, जैसा कि प्रभावी है समय - समय पर।", "decimal_places_error": "बहुत अधिक दशमलव स्थान", + "decimals_cannot_be_zero": "टोकन दशमलव शून्य नहीं हो सकता।", "default_buy_provider": "डिफ़ॉल्ट खरीद प्रदाता", "default_sell_provider": "डिफ़ॉल्ट विक्रय प्रदाता", "delete": "हटाएं", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 4aac8216e..a4de56dcf 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -175,6 +175,7 @@ "debit_card": "Debitna kartica", "debit_card_terms": "Pohranjivanje i korištenje broja vaše platne kartice (i vjerodajnica koje odgovaraju broju vaše platne kartice) u ovom digitalnom novčaniku podliježu Uvjetima i odredbama važećeg ugovora vlasnika kartice s izdavateljem platne kartice, koji su na snazi ​​od S vremena na vrijeme.", "decimal_places_error": "Previše decimalnih mjesta", + "decimals_cannot_be_zero": "Token Decimal ne može biti nula.", "default_buy_provider": "Zadani davatelj kupnje", "default_sell_provider": "Zadani dobavljač prodaje", "delete": "Izbriši", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 09d28e453..411daf9e0 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -175,6 +175,7 @@ "debit_card": "Kartu Debit", "debit_card_terms": "Penyimpanan dan penggunaan nomor kartu pembayaran Anda (dan kredensial yang sesuai dengan nomor kartu pembayaran Anda) dalam dompet digital ini tertakluk pada Syarat dan Ketentuan persetujuan pemegang kartu yang berlaku dengan penerbit kartu pembayaran, seperti yang berlaku dari waktu ke waktu.", "decimal_places_error": "Terlalu banyak tempat desimal", + "decimals_cannot_be_zero": "Token desimal tidak bisa nol.", "default_buy_provider": "Penyedia beli default", "default_sell_provider": "Penyedia Penjualan Default", "delete": "Hapus", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index c9ac60bb5..7cf298cae 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -176,6 +176,7 @@ "debit_card": "Carta di debito", "debit_card_terms": "L'archiviazione e l'utilizzo del numero della carta di pagamento (e delle credenziali corrispondenti al numero della carta di pagamento) in questo portafoglio digitale sono soggetti ai Termini e condizioni del contratto applicabile con il titolare della carta con l'emittente della carta di pagamento, come in vigore da tempo al tempo.", "decimal_places_error": "Troppe cifre decimali", + "decimals_cannot_be_zero": "Il decimale token non può essere zero.", "default_buy_provider": "Provider di acquisto predefinito", "default_sell_provider": "Fornitore di vendita predefinito", "delete": "Elimina", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 98d87a90c..42377fa85 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -175,6 +175,7 @@ "debit_card": "デビットカード", "debit_card_terms": "このデジタルウォレットでの支払いカード番号(および支払いカード番号に対応する資格情報)の保存と使用には、支払いカード発行者との該当するカード所有者契約の利用規約が適用されます。時々。", "decimal_places_error": "小数点以下の桁数が多すぎる", + "decimals_cannot_be_zero": "トークン小数はゼロにすることはできません。", "default_buy_provider": "デフォルトの購入プロバイダー", "default_sell_provider": "デフォルトの販売プロバイダー", "delete": "削除する", @@ -809,4 +810,4 @@ "you_will_get": "に変換", "you_will_send": "から変換", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 7cc49e315..c67d531ce 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -175,6 +175,7 @@ "debit_card": "직불 카드", "debit_card_terms": "이 디지털 지갑에 있는 귀하의 지불 카드 번호(및 귀하의 지불 카드 번호에 해당하는 자격 증명)의 저장 및 사용은 부터 발효되는 지불 카드 발행자와의 해당 카드 소지자 계약의 이용 약관을 따릅니다. 수시로.", "decimal_places_error": "소수점 이하 자릿수가 너무 많습니다.", + "decimals_cannot_be_zero": "토큰 소수점은 0이 될 수 없습니다.", "default_buy_provider": "기본 구매 제공자", "default_sell_provider": "기본 판매 공급자", "delete": "지우다", @@ -810,4 +811,4 @@ "you_will_send": "다음에서 변환", "YY": "YY", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 9c88dc817..e373eefc0 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -175,6 +175,7 @@ "debit_card": "ဒက်ဘစ်ကတ်", "debit_card_terms": "ဤဒစ်ဂျစ်တယ်ပိုက်ဆံအိတ်ရှိ သင့်ငွေပေးချေမှုကတ်နံပါတ် (နှင့် သင့်ငွေပေးချေကတ်နံပါတ်နှင့် သက်ဆိုင်သောအထောက်အထားများ) ၏ သိုလှောင်မှုနှင့် အသုံးပြုမှုသည် အချိန်အခါနှင့်အမျှ သက်ရောက်မှုရှိသကဲ့သို့ ကတ်ကိုင်ဆောင်ထားသူ၏ သဘောတူညီချက်၏ စည်းကမ်းသတ်မှတ်ချက်များနှင့် ကိုက်ညီပါသည်။", "decimal_places_error": "ဒဿမနေရာများ များလွန်းသည်။", + "decimals_cannot_be_zero": "တိုကင်ဒ decimal မသုညမဖြစ်နိုင်ပါ။", "default_buy_provider": "Default Provider ကိုဝယ်ပါ", "default_sell_provider": "ပုံသေရောင်းချပေးသူ", "delete": "ဖျက်ပါ။", @@ -808,4 +809,4 @@ "you_will_get": "သို့ပြောင်းပါ။", "you_will_send": "မှပြောင်းပါ။", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 74b111dcb..1fc85a28b 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -175,6 +175,7 @@ "debit_card": "Debetkaart", "debit_card_terms": "De opslag en het gebruik van uw betaalkaartnummer (en inloggegevens die overeenkomen met uw betaalkaartnummer) in deze digitale portemonnee zijn onderworpen aan de Algemene voorwaarden van de toepasselijke kaarthouderovereenkomst met de uitgever van de betaalkaart, zoals van kracht vanaf tijd tot tijd.", "decimal_places_error": "Te veel decimalen", + "decimals_cannot_be_zero": "Token decimaal kan niet nul zijn.", "default_buy_provider": "Standaard Koopprovider", "default_sell_provider": "Standaard verkoopaanbieder", "delete": "Delete", @@ -809,4 +810,4 @@ "you_will_get": "Converteren naar", "you_will_send": "Converteren van", "yy": "JJ" -} +} \ No newline at end of file diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 2ac1b9fb5..f279dbaa7 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -175,6 +175,7 @@ "debit_card": "Karta debetowa", "debit_card_terms": "Przechowywanie i używanie numeru karty płatniczej (oraz danych uwierzytelniających odpowiadających numerowi karty płatniczej) w tym portfelu cyfrowym podlega Warunkom odpowiedniej umowy posiadacza karty z wydawcą karty płatniczej, zgodnie z obowiązującym od od czasu do czasu.", "decimal_places_error": "Za dużo miejsc dziesiętnych", + "decimals_cannot_be_zero": "Token dziesiętny nie może być zerowy.", "default_buy_provider": "Domyślny dostawca zakupu", "default_sell_provider": "Domyślny dostawca sprzedaży", "delete": "Skasuj", @@ -808,4 +809,4 @@ "you_will_get": "Konwertuj na", "you_will_send": "Konwertuj z", "yy": "RR" -} +} \ No newline at end of file diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index bf0b0082d..ba3acae88 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -175,6 +175,7 @@ "debit_card": "Cartão de débito", "debit_card_terms": "O armazenamento e uso do número do cartão de pagamento (e credenciais correspondentes ao número do cartão de pagamento) nesta carteira digital estão sujeitos aos Termos e Condições do contrato do titular do cartão aplicável com o emissor do cartão de pagamento, em vigor a partir de tempo ao tempo.", "decimal_places_error": "Muitas casas decimais", + "decimals_cannot_be_zero": "Decimal de token não pode ser zero.", "default_buy_provider": "Provedor de compra padrão", "default_sell_provider": "Provedor de venda padrão", "delete": "Excluir", @@ -811,4 +812,4 @@ "you_will_get": "Converter para", "you_will_send": "Converter de", "yy": "aa" -} +} \ No newline at end of file diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 999728faf..b24f940dd 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -175,6 +175,7 @@ "debit_card": "Дебетовая карта", "debit_card_terms": "Хранение и использование номера вашей платежной карты (и учетных данных, соответствующих номеру вашей платежной карты) в этом цифровом кошельке регулируются положениями и условиями применимого соглашения держателя карты с эмитентом платежной карты, действующим с время от времени.", "decimal_places_error": "Слишком много десятичных знаков", + "decimals_cannot_be_zero": "Десятичный токен не может быть нулевым.", "default_buy_provider": "По умолчанию поставщик покупки", "default_sell_provider": "Поставщик продаж по умолчанию", "delete": "Удалить", @@ -809,4 +810,4 @@ "you_will_get": "Конвертировать в", "you_will_send": "Конвертировать из", "yy": "ГГ" -} +} \ No newline at end of file diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index a71bc6b36..0795faf2e 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -175,6 +175,7 @@ "debit_card": "บัตรเดบิต", "debit_card_terms": "การเก็บรักษาและใช้หมายเลขบัตรจ่ายเงิน (และข้อมูลประจำตัวที่เกี่ยวข้องกับหมายเลขบัตรจ่ายเงิน) ในกระเป๋าดิจิทัลนี้ จะต้องยึดถือข้อกำหนดและเงื่อนไขของข้อตกลงผู้ใช้บัตรของผู้ถือบัตรที่เกี่ยวข้องกับบัตรผู้ถือบัตร ซึ่งจะมีผลตั้งแต่เวลานั้น", "decimal_places_error": "ทศนิยมมากเกินไป", + "decimals_cannot_be_zero": "ทศนิยมโทเค็นไม่สามารถเป็นศูนย์ได้", "default_buy_provider": "ผู้ให้บริการซื้อเริ่มต้น", "default_sell_provider": "ผู้ให้บริการการขายเริ่มต้น", "delete": "ลบ", @@ -808,4 +809,4 @@ "you_will_get": "แปลงเป็น", "you_will_send": "แปลงจาก", "yy": "ปี" -} +} \ No newline at end of file diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 73cd8a1f7..91ca5a548 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -175,6 +175,7 @@ "debit_card": "Debit card", "debit_card_terms": "Ang pag -iimbak at paggamit ng numero ng iyong card ng pagbabayad (at mga kredensyal na naaayon sa iyong numero ng card ng pagbabayad) sa digital na pitaka na ito ay napapailalim sa mga termino at kundisyon ng naaangkop na kasunduan sa cardholder kasama ang nagbigay ng card ng pagbabayad, tulad ng sa oras -oras.", "decimal_places_error": "Masyadong maraming mga lugar na desimal", + "decimals_cannot_be_zero": "Ang Token Decimal ay hindi maaaring maging zero.", "default_buy_provider": "Default na Provider ng Pagbili", "default_sell_provider": "Default na Sell Provider", "delete": "Tanggalin", @@ -808,4 +809,4 @@ "you_will_get": "Mag -convert sa", "you_will_send": "I -convert mula sa", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index de197c1b1..784ebfb7e 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -175,6 +175,7 @@ "debit_card": "Ön ödemeli Kart", "debit_card_terms": "Ödeme kartı numaranızın (ve kart numaranıza karşılık gelen kimlik bilgilerinin) bu dijital cüzdanda saklanması ve kullanılması, zaman zaman yürürlükte olan ödeme kartı veren kuruluşla yapılan ilgili kart sahibi sözleşmesinin Hüküm ve Koşullarına tabidir.", "decimal_places_error": "Çok fazla ondalık basamak", + "decimals_cannot_be_zero": "Token oncial sıfır olamaz.", "default_buy_provider": "Varsayılan Satın Alma Sağlayıcısı", "default_sell_provider": "Varsayılan Satış Sağlayıcısı", "delete": "Sil", @@ -808,4 +809,4 @@ "you_will_get": "Biçimine dönüştür:", "you_will_send": "Biçiminden dönüştür:", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 86e60214b..65a1f5c96 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -175,6 +175,7 @@ "debit_card": "Дебетова картка", "debit_card_terms": "Зберігання та використання номера вашої платіжної картки (та облікових даних, які відповідають номеру вашої платіжної картки) у цьому цифровому гаманці регулюються Умовами відповідної угоди власника картки з емітентом платіжної картки, що діє з час від часу.", "decimal_places_error": "Забагато знаків після коми", + "decimals_cannot_be_zero": "Десятковий знак не може бути нульовим.", "default_buy_provider": "Постачальник покупки за замовчуванням", "default_sell_provider": "Постачальник продажу за замовчуванням", "delete": "Видалити", @@ -809,4 +810,4 @@ "you_will_get": "Конвертувати в", "you_will_send": "Конвертувати з", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 725a1d895..6c768daa8 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -175,6 +175,7 @@ "debit_card": "ڈیبٹ کارڈ", "debit_card_terms": "اس ڈیجیٹل والیٹ میں آپ کے ادائیگی کارڈ نمبر (اور آپ کے ادائیگی کارڈ نمبر سے متعلقہ اسناد) کا ذخیرہ اور استعمال ادائیگی کارڈ جاری کنندہ کے ساتھ قابل اطلاق کارڈ ہولڈر کے معاہدے کی شرائط و ضوابط کے ساتھ مشروط ہے، جیسا کہ وقتاً فوقتاً نافذ ہوتا ہے۔", "decimal_places_error": "بہت زیادہ اعشاریہ جگہیں۔", + "decimals_cannot_be_zero": "ٹوکن اعشاریہ صفر نہیں ہوسکتا۔", "default_buy_provider": "پہلے سے طے شدہ خریدنے والا", "default_sell_provider": " ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ", "delete": "حذف کریں۔", @@ -810,4 +811,4 @@ "you_will_get": "میں تبدیل کریں۔", "you_will_send": "سے تبدیل کریں۔", "yy": "YY" -} +} \ No newline at end of file diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 517757716..b5f2d69a3 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -175,6 +175,7 @@ "debit_card": "Káàdì ìrajà", "debit_card_terms": "Òfin ti olùṣe àjọrò káàdì ìrajà bójú irú ọ̀nà t'á pamọ́ àti a lo òǹkà ti káàdì ìrajà yín (àti ọ̀rọ̀ ìdánimọ̀ tí káàdì náà) nínú àpamọ́wọ́ yìí.", "decimal_places_error": "Oọ̀rọ̀ ayipada ti o wa ni o dara julọ", + "decimals_cannot_be_zero": "Token eleemel ko le jẹ odo.", "default_buy_provider": "Aiyipada Ra Olupese", "default_sell_provider": "Aiyipada Olupese Tita", "delete": "Pa á", @@ -809,4 +810,4 @@ "you_will_get": "Ṣe pàṣípààrọ̀ sí", "you_will_send": "Ṣe pàṣípààrọ̀ láti", "yy": "Ọd" -} +} \ No newline at end of file diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 104848996..e9a6b63f2 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -175,6 +175,7 @@ "debit_card": "借记卡", "debit_card_terms": "您的支付卡号(以及与您的支付卡号对应的凭证)在此数字钱包中的存储和使用受适用的持卡人与支付卡发卡机构签订的协议的条款和条件的约束,自时不时。", "decimal_places_error": "小数位太多", + "decimals_cannot_be_zero": "代币十进制不能为零。", "default_buy_provider": "默认购买提供商", "default_sell_provider": "默认销售提供商", "delete": "删除", @@ -808,4 +809,4 @@ "you_will_get": "转换到", "you_will_send": "转换自", "yy": "YY" -} +} \ No newline at end of file diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index 430de03b6..8fedbb12a 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -42,6 +42,7 @@ class SecretKey { static final evmChainsSecrets = [ SecretKey('etherScanApiKey', () => ''), SecretKey('polygonScanApiKey', () => ''), + SecretKey('moralisApiKey', () => ''), ]; static final solanaSecrets = [ From 69587e813fb0bba4686d79626baa9baf72a50ed6 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Mon, 8 Apr 2024 19:04:16 -0400 Subject: [PATCH 173/241] Always show addresses page for Monero and remove unused text showing up for wallets it shouldn't be (#1363) --- .../screens/dashboard/pages/address_page.dart | 19 +++------- lib/src/screens/receive/receive_page.dart | 35 ++----------------- 2 files changed, 6 insertions(+), 48 deletions(-) diff --git a/lib/src/screens/dashboard/pages/address_page.dart b/lib/src/screens/dashboard/pages/address_page.dart index 0d7c4f11c..3c77cad48 100644 --- a/lib/src/screens/dashboard/pages/address_page.dart +++ b/lib/src/screens/dashboard/pages/address_page.dart @@ -163,12 +163,7 @@ class AddressPage extends BasePage { if (addressListViewModel.hasAddressList) { return SelectButton( text: addressListViewModel.buttonTitle, - onTap: () async => dashboardViewModel.isAutoGenerateSubaddressesEnabled && - (WalletType.monero == addressListViewModel.wallet.type || - WalletType.haven == addressListViewModel.wallet.type) - ? await showPopUp( - context: context, builder: (_) => getIt.get()) - : Navigator.of(context).pushNamed(Routes.receive), + onTap: () async => Navigator.of(context).pushNamed(Routes.receive), textColor: Theme.of(context).extension()!.textColor, color: Theme.of(context).extension()!.syncedBackgroundColor, borderColor: Theme.of(context).extension()!.cardBorderColor, @@ -176,17 +171,11 @@ class AddressPage extends BasePage { textSize: 14, height: 50, ); - } else if (dashboardViewModel.isAutoGenerateSubaddressesEnabled || - addressListViewModel.isElectrumWallet) { - return Text(S.of(context).electrum_address_disclaimer, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 15, - color: Theme.of(context).extension()!.labelTextColor)); - } else { + } + else { return const SizedBox(); } - }) + }), ], ), )); diff --git a/lib/src/screens/receive/receive_page.dart b/lib/src/screens/receive/receive_page.dart index 75719d123..ecba4acf5 100644 --- a/lib/src/screens/receive/receive_page.dart +++ b/lib/src/screens/receive/receive_page.dart @@ -99,12 +99,7 @@ class ReceivePage extends BasePage { @override Widget body(BuildContext context) { - final isElectrumWallet = addressListViewModel.isElectrumWallet; - return (addressListViewModel.type == WalletType.monero || - addressListViewModel.type == WalletType.haven || - addressListViewModel.type == WalletType.nano || - isElectrumWallet) - ? KeyboardActions( + return KeyboardActions( config: KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.IOS, keyboardBarColor: Theme.of(context).extension()!.keyboardBarColor, @@ -213,32 +208,6 @@ class ReceivePage extends BasePage { })), ], ), - )) - : Padding( - padding: EdgeInsets.fromLTRB(24, 24, 24, 32), - child: Column( - children: [ - Expanded( - flex: 7, - child: QRWidget( - formKey: _formKey, - heroTag: _heroTag, - addressListViewModel: addressListViewModel, - amountTextFieldFocusNode: _cryptoAmountFocus, - amountController: _amountController, - isLight: currentTheme.type == ThemeType.light), - ), - Expanded( - flex: 2, - child: SizedBox(), - ), - Text(S.of(context).electrum_address_disclaimer, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 15, - color: Theme.of(context).extension()!.labelTextColor)), - ], - ), - ); + )); } } From f9679fecbeaacbbf3d4694a14a00cf47e5262448 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Tue, 9 Apr 2024 01:26:11 +0100 Subject: [PATCH 174/241] CW-584-WalletConnect-For-Solana (#1362) * chore: Create cw_solana package and clean up files * feat: Add Solana Wallet - Create, Restore form seed, restore from Key, Restore from QR, Send, Receive, transaction history, spl tokens * fix: Make transactions file specific to solana only for solana transactions * chore: Revert inject app details script * fix: Fix issue with node and switch current node to main beta instead of testnet * fix: Fix merge conflicts and adjust migration version * fix: Fetch spl token error Signed-off-by: Blazebrain * fix: Diplay and activate spl tokens bug * fix: Review and fixes * fix: reverted formatting for cryptocurrency class * fix: Review comments, split sending flow into signing and sending separately, fix issues * fix: Revert throwing unimplenented error * chore: Fix comment * chore: Fix comment * fix: Errors in flow * Update provider_types.dart [skip ci] * fix: Issues with solana wallet * Update solana_wallet.dart [skip ci] * fix: Review comments * fix: Date time config * fix: Revert bash script for app details * fix: Error with balance, displaying fees, fixing sent or received identifier bug, displaying token symbol with token transaction item in transactions list * fix: Issues with address validation when sending spl tokens and walletconnect initial setup * fix: Issues with sending, fetching transactions history, almost wrapping up walletconnect * fix: Adjust imports that would affect monerocom building successfully * fix: Refine transaction direction and continue work on walletconnect * feat: Display SPL token transfers in the transaction history and finally settle the transaction direction * fix: Delay in transactions history dispaly, show native token transactions first, then process spl token transactions * feat: Switch node and revert solana chain id to previous id * fix: Remove print statement * fix: Remove await for transactions, fetch all transaction histories instantly and adjust solana send success message * chore: Code refactoring and streamlined wallet type check for solana send success message * fix: Make timeout error for node silent and add spl token images * fix: Still trying to figure out what's wrong * Sync with remote * feat: First run for walletconnect for solana * chore: Add ankr api key to secrets * remove duplicate transaction [skip ci] --------- Signed-off-by: Blazebrain Co-authored-by: Omar Hatem --- .github/workflows/pr_test_build.yml | 1 + .../chain_service/solana/solana_chain_id.dart | 19 +++++++++------- .../solana/solana_chain_service.dart | 14 +++++++----- .../wallet_connect/web3wallet_service.dart | 22 +++++++++++++++---- lib/reactions/wallet_connect.dart | 1 + tool/utils/secret_key.dart | 1 + 6 files changed, 40 insertions(+), 18 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index db9870412..dc231df42 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -139,6 +139,7 @@ jobs: echo "const anonPayReferralCode = '${{ secrets.ANON_PAY_REFERRAL_CODE }}';" >> lib/.secrets.g.dart echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart + echo "const ankrApiKey = '${{ secrets.ANKR_API_KEY }}';" >> lib/.secrets.g.dart echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart echo "const moralisApiKey = '${{ secrets.MORALIS_API_KEY }}';" >> cw_evm/lib/.secrets.g.dart echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart diff --git a/lib/core/wallet_connect/chain_service/solana/solana_chain_id.dart b/lib/core/wallet_connect/chain_service/solana/solana_chain_id.dart index bdc8a7d20..ed80a4f3f 100644 --- a/lib/core/wallet_connect/chain_service/solana/solana_chain_id.dart +++ b/lib/core/wallet_connect/chain_service/solana/solana_chain_id.dart @@ -2,8 +2,8 @@ import 'solana_chain_service.dart'; enum SolanaChainId { mainnet, - testnet, - devnet, + // testnet, + // devnet, } extension SolanaChainIdX on SolanaChainId { @@ -13,13 +13,16 @@ extension SolanaChainIdX on SolanaChainId { switch (this) { case SolanaChainId.mainnet: name = '4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ'; + // solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp break; - case SolanaChainId.testnet: - name = '8E9rvCKLFQia2Y35HXjjpWzj8weVo44K'; - break; - case SolanaChainId.devnet: - name = ''; - break; + // case SolanaChainId.devnet: + // name = '8E9rvCKLFQia2Y35HXjjpWzj8weVo44K'; + // // solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1 + // break; + // case SolanaChainId.testnet: + // name = ''; + // // solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z + // break; } return '${SolanaChainServiceImpl.namespace}:$name'; diff --git a/lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart b/lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart index f5c696be6..efbf9df74 100644 --- a/lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart +++ b/lib/core/wallet_connect/chain_service/solana/solana_chain_service.dart @@ -43,7 +43,7 @@ class SolanaChainServiceImpl implements ChainService { SolanaClient( rpcUrl: rpcUrl, websocketUrl: Uri.parse(webSocketUrl), - timeout: const Duration(minutes: 2), + timeout: const Duration(minutes: 5), ) { for (final String event in getEvents()) { wallet.registerEventEmitter(chainId: getChainId(), event: event); @@ -72,7 +72,7 @@ class SolanaChainServiceImpl implements ChainService { @override List getEvents() { - return ['']; + return ['chainChanged', 'accountsChanged']; } Future requestAuthorization(String? text) async { @@ -100,8 +100,7 @@ class SolanaChainServiceImpl implements ChainService { Future solanaSignTransaction(String topic, dynamic parameters) async { log('received solana sign transaction request $parameters'); - final solanaSignTx = - SolanaSignTransaction.fromJson(parameters as Map); + final solanaSignTx = SolanaSignTransaction.fromJson(parameters as Map); final String? authError = await requestAuthorization('Confirm request to sign transaction?'); @@ -122,10 +121,13 @@ class SolanaChainServiceImpl implements ChainService { return ''; } - String signature = sign.signatures.first.toBase58(); + String signature = await solanaClient.sendAndConfirmTransaction( + message: message, + signers: [ownerKeyPair!], + commitment: Commitment.confirmed, + ); print(signature); - print(signature.runtimeType); bottomSheetService.queueBottomSheet( isModalDismissible: true, diff --git a/lib/core/wallet_connect/web3wallet_service.dart b/lib/core/wallet_connect/web3wallet_service.dart index 4c71abe48..66ccb2d76 100644 --- a/lib/core/wallet_connect/web3wallet_service.dart +++ b/lib/core/wallet_connect/web3wallet_service.dart @@ -133,13 +133,27 @@ abstract class Web3WalletServiceBase with Store { if (appStore.wallet!.type == WalletType.solana) { for (final cId in SolanaChainId.values) { final node = appStore.settingsStore.getCurrentNode(appStore.wallet!.type); - final rpcUri = node.uri; - final webSocketUri = 'wss://${node.uriRaw}/ws${node.uri.path}'; + + Uri? rpcUri; + String webSocketUrl; + bool isModifiedNodeUri = false; + + if (node.uriRaw == 'rpc.ankr.com') { + isModifiedNodeUri = true; + + //A better way to handle this instead of adding this to the general secrets? + String ankrApiKey = secrets.ankrApiKey; + + rpcUri = Uri.https(node.uriRaw, '/solana/$ankrApiKey'); + webSocketUrl = 'wss://${node.uriRaw}/solana/ws/$ankrApiKey'; + } else { + webSocketUrl = 'wss://${node.uriRaw}'; + } SolanaChainServiceImpl( reference: cId, - rpcUrl: rpcUri, - webSocketUrl: webSocketUri, + rpcUrl: isModifiedNodeUri ? rpcUri! : node.uri, + webSocketUrl: webSocketUrl, wcKeyService: walletKeyService, bottomSheetService: _bottomSheetHandler, wallet: _web3Wallet, diff --git a/lib/reactions/wallet_connect.dart b/lib/reactions/wallet_connect.dart index f4487123e..ca908bc65 100644 --- a/lib/reactions/wallet_connect.dart +++ b/lib/reactions/wallet_connect.dart @@ -16,6 +16,7 @@ bool isWalletConnectCompatibleChain(WalletType walletType) { switch (walletType) { case WalletType.polygon: case WalletType.ethereum: + case WalletType.solana: return true; default: return false; diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index 8fedbb12a..5d5e61cec 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -37,6 +37,7 @@ class SecretKey { SecretKey('exchangeHelperApiKey', () => ''), SecretKey('walletConnectProjectId', () => ''), SecretKey('moralisApiKey', () => ''), + SecretKey('ankrApiKey', () => ''), ]; static final evmChainsSecrets = [ From 8a61ab77800ca2c896d88cbe28e6b9eddecd617f Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Wed, 10 Apr 2024 03:28:31 +0200 Subject: [PATCH 175/241] enhance UI for used addresses (#1337) * enhance UI for used addresses * Update electrum_wallet_addresses.dart * fix tablet UI --------- Co-authored-by: Serhii --- cw_bitcoin/lib/electrum_wallet_addresses.dart | 2 + .../screens/receive/widgets/address_cell.dart | 63 ++++++++++--------- lib/src/screens/settings/privacy_page.dart | 4 +- lib/utils/responsive_layout_util.dart | 4 ++ .../settings/privacy_settings_view_model.dart | 2 + res/values/strings_ar.arb | 1 + res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 3 +- res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 1 + res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 1 + res/values/strings_my.arb | 1 + res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_th.arb | 1 + res/values/strings_tl.arb | 1 + res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + 31 files changed, 72 insertions(+), 31 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart index ac2397561..c43d4988a 100644 --- a/cw_bitcoin/lib/electrum_wallet_addresses.dart +++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart @@ -241,6 +241,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store { final index = _addresses.indexOf(addressRecord); _addresses.remove(addressRecord); _addresses.insert(index, addressRecord); + + updateAddressesByMatch(); } @action diff --git a/lib/src/screens/receive/widgets/address_cell.dart b/lib/src/screens/receive/widgets/address_cell.dart index a07456284..9385a4df8 100644 --- a/lib/src/screens/receive/widgets/address_cell.dart +++ b/lib/src/screens/receive/widgets/address_cell.dart @@ -1,5 +1,6 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart'; import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; @@ -81,41 +82,45 @@ class AddressCell extends StatelessWidget { child: Column( children: [ Row( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: name.isNotEmpty ? MainAxisAlignment.spaceBetween : MainAxisAlignment.center, mainAxisSize: MainAxisSize.max, children: [ - if (isChange) - Padding( - padding: const EdgeInsets.only(right: 8.0), - child: Container( - height: 20, - padding: EdgeInsets.all(4), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(8.5)), - color: textColor), - alignment: Alignment.center, - child: Text( - S.of(context).unspent_change, - style: TextStyle( - color: backgroundColor, - fontSize: 10, - fontWeight: FontWeight.w600, + Row( + children: [ + if (isChange) + Padding( + padding: const EdgeInsets.only(right: 8.0), + child: Container( + height: 20, + padding: EdgeInsets.all(4), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(8.5)), + color: textColor), + alignment: Alignment.center, + child: Text( + S.of(context).unspent_change, + style: TextStyle( + color: backgroundColor, + fontSize: 10, + fontWeight: FontWeight.w600, + ), + ), ), ), - ), - ), - if (name.isNotEmpty) - Text( - '$name - ', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: textColor, - ), - ), + if (name.isNotEmpty) + Text( + '$name', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + color: textColor, + ), + ), + ], + ), Flexible( child: AutoSizeText( - formattedAddress, + responsiveLayoutUtil.shouldRenderTabletUI ? address : formattedAddress, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index 444457d1c..7e7f3589b 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -55,7 +55,9 @@ class PrivacyPage extends BasePage { }), if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible) SettingsSwitcherCell( - title: S.current.auto_generate_subaddresses, + title: _privacySettingsViewModel.isMoneroWallet + ? S.current.auto_generate_subaddresses + : S.current.auto_generate_addresses, value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled, onValueChange: (BuildContext _, bool value) { _privacySettingsViewModel.setAutoGenerateSubaddresses(value); diff --git a/lib/utils/responsive_layout_util.dart b/lib/utils/responsive_layout_util.dart index 428ab61cc..86a4a3776 100644 --- a/lib/utils/responsive_layout_util.dart +++ b/lib/utils/responsive_layout_util.dart @@ -46,6 +46,10 @@ abstract class ResponsiveLayoutUtilBase with Store, WidgetsBindingObserver { (orientation == Orientation.portrait && screenWidth < screenHeight) || (orientation == Orientation.landscape && screenWidth < screenHeight); } + + bool get shouldRenderTabletUI { + return screenWidth > _kMobileThreshold && screenWidth < kDesktopMaxDashBoardWidthConstraint; + } } _ResponsiveLayoutUtil _singletonResponsiveLayoutUtil = _ResponsiveLayoutUtil(); diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart index 831a45357..9ebbd92bb 100644 --- a/lib/view_model/settings/privacy_settings_view_model.dart +++ b/lib/view_model/settings/privacy_settings_view_model.dart @@ -44,6 +44,8 @@ abstract class PrivacySettingsViewModelBase with Store { _wallet.type == WalletType.litecoin || _wallet.type == WalletType.bitcoinCash; + bool get isMoneroWallet => _wallet.type == WalletType.monero; + @computed bool get shouldSaveRecipientAddress => _settingsStore.shouldSaveRecipientAddress; diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index d0f1a2043..6b3aae14e 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "PIN خطأ", "authenticated": "تم المصادقة", "authentication": "المصادقة", + "auto_generate_addresses": "تلقائي توليد العناوين", "auto_generate_subaddresses": "تلقائي توليد subddresses", "automatic": "تلقائي", "available_balance": "الرصيد المتوفر", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 249952d75..30d9945d1 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Грешен PIN", "authenticated": "Удостоверено", "authentication": "Удостоверяване", + "auto_generate_addresses": "Автоматично генериране на адреси", "auto_generate_subaddresses": "Автоматично генериране на подадреси", "automatic": "Автоматично", "available_balance": "Наличен баланс", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 9b3b06ffd..577cd9813 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Nesprávný PIN", "authenticated": "Ověřeno", "authentication": "Ověřování", + "auto_generate_addresses": "Automatické generování adres", "auto_generate_subaddresses": "Automaticky generovat podadresy", "automatic": "Automatický", "available_balance": "Dostupný zůstatek", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 8a914628f..f0ba70c84 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Falsche PIN", "authenticated": "Authentifiziert", "authentication": "Authentifizierung", + "auto_generate_addresses": "Automatisch generieren Adressen", "auto_generate_subaddresses": "Unteradressen automatisch generieren", "automatic": "Automatisch", "available_balance": "Verfügbares Guthaben", @@ -422,8 +423,8 @@ "placeholder_transactions": "Ihre Transaktionen werden hier angezeigt", "please_fill_totp": "Bitte geben Sie den 8-stelligen Code ein, der auf Ihrem anderen Gerät vorhanden ist", "please_make_selection": "Bitte treffen Sie unten eine Auswahl zum Erstellen oder Wiederherstellen Ihrer Wallet.", - "please_reference_document": "Bitte verweisen Sie auf die folgenden Dokumente, um weitere Informationen zu erhalten.", "Please_reference_document": "Weitere Informationen finden Sie in den Dokumenten unten.", + "please_reference_document": "Bitte verweisen Sie auf die folgenden Dokumente, um weitere Informationen zu erhalten.", "please_select": "Bitte auswählen:", "please_select_backup_file": "Bitte wählen Sie die Sicherungsdatei und geben Sie das Sicherungskennwort ein.", "please_try_to_connect_to_another_node": "Bitte versuchen Sie, sich mit einem anderen Knoten zu verbinden", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 3fe9474c5..f8bd6b3a2 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Wrong PIN", "authenticated": "Authenticated", "authentication": "Authentication", + "auto_generate_addresses": "Auto generate addresses", "auto_generate_subaddresses": "Auto generate subaddresses", "automatic": "Automatic", "available_balance": "Available Balance", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 47b11bc48..cf70a2c2d 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Contraseña PIN", "authenticated": "Autenticados", "authentication": "Autenticación", + "auto_generate_addresses": "Auto Generar direcciones", "auto_generate_subaddresses": "Generar subdirecciones automáticamente", "automatic": "Automático", "available_balance": "Balance disponible", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index edae901a3..d21e21dae 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Mauvais code PIN", "authenticated": "Authentifié", "authentication": "Authentification", + "auto_generate_addresses": "Adresses de génération automatique", "auto_generate_subaddresses": "Générer automatiquement des sous-adresses", "automatic": "Automatique", "available_balance": "Solde Disponible", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index c7174d23f..35a6be1b8 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "PIN na gaskiya", "authenticated": "Ingantacce", "authentication": "Tabbatarwa", + "auto_generate_addresses": "Adireshin Auto", "auto_generate_subaddresses": "Saɓaƙa subaddresses ta kai tsaye", "automatic": "Na atomatik", "available_balance": "KUDI", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 4ee9bd4f8..a6bcab4ab 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "गलत पिन", "authenticated": "प्रमाणीकृत", "authentication": "प्रमाणीकरण", + "auto_generate_addresses": "ऑटो उत्पन्न पते", "auto_generate_subaddresses": "स्वचालित रूप से उप-पते उत्पन्न करें", "automatic": "स्वचालित", "available_balance": "उपलब्ध शेष राशि", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index a4de56dcf..e01857a94 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Pogrešan PIN", "authenticated": "Autentificiran", "authentication": "Autentifikacija", + "auto_generate_addresses": "Automatsko generiranje adresa", "auto_generate_subaddresses": "Automatski generirajte podadrese", "automatic": "Automatski", "available_balance": "Raspoloživ iznos", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 411daf9e0..c487a6750 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "PIN yang salah", "authenticated": "Terotentikasi", "authentication": "Otentikasi", + "auto_generate_addresses": "Auto menghasilkan alamat", "auto_generate_subaddresses": "Menghasilkan subalamat secara otomatis", "automatic": "Otomatis", "available_balance": "Saldo Tersedia", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 7cf298cae..0af315426 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "PIN non corretto", "authenticated": "Autenticato", "authentication": "Autenticazione", + "auto_generate_addresses": "Auto Genera indirizzi", "auto_generate_subaddresses": "Genera automaticamente sottindirizzi", "automatic": "Automatico", "available_balance": "Saldo Disponibile", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 42377fa85..a0b3973b2 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "間違ったPIN", "authenticated": "認証済み", "authentication": "認証", + "auto_generate_addresses": "Autoはアドレスを生成します", "auto_generate_subaddresses": "Autoはサブアドレスを生成します", "automatic": "自動", "available_balance": "利用可能残高", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index c67d531ce..98bc40e77 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "잘못된 PIN", "authenticated": "인증", "authentication": "입증", + "auto_generate_addresses": "자동 생성 주소", "auto_generate_subaddresses": "자동 생성 서브 아드 드레스", "automatic": "자동적 인", "available_balance": "사용 가능한 잔액", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index e373eefc0..8d846f3d6 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "ပင်နံပါတ် မှားနေသည်။", "authenticated": "အစစ်အမှန်", "authentication": "စစ်ဆေးခြင်း", + "auto_generate_addresses": "Auto Generate လိပ်စာများ", "auto_generate_subaddresses": "အော်တို Generate Subaddresses", "automatic": "အလိုအလျောက်", "available_balance": "လက်ကျန်ငွေ ရရှိနိုင်", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 1fc85a28b..8b3edee4b 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Incorrect PIN", "authenticated": "Authenticated", "authentication": "Authenticatie", + "auto_generate_addresses": "Auto -genereer adressen", "auto_generate_subaddresses": "Automatisch subadressen genereren", "automatic": "automatisch", "available_balance": "Beschikbaar saldo", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index f279dbaa7..93dafa352 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Niepoprawny PIN", "authenticated": "Uwierzytelniony", "authentication": "Uwierzytelnianie", + "auto_generate_addresses": "Auto generują adresy", "auto_generate_subaddresses": "Automatycznie generuj podadresy", "automatic": "Automatyczny", "available_balance": "Dostępne środki", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index ba3acae88..ae07bb177 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "PIN incorreto", "authenticated": "Autenticado", "authentication": "Autenticação", + "auto_generate_addresses": "Endereços gerados automaticamente", "auto_generate_subaddresses": "Gerar subendereços automaticamente", "automatic": "Automático", "available_balance": "Saldo disponível", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index b24f940dd..5e75631c6 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Некорректный PIN", "authenticated": "Аутентифицировано", "authentication": "Аутентификация", + "auto_generate_addresses": "Авто генерируйте адреса", "auto_generate_subaddresses": "Авто генерируйте Subaddresses", "automatic": "автоматический", "available_balance": "Доступный баланс", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 0795faf2e..c8183c031 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "รหัสผ่านไม่ถูกต้อง", "authenticated": "ได้รับการยืนยันสิทธิ์", "authentication": "การยืนยันสิทธิ์", + "auto_generate_addresses": "สร้างที่อยู่อัตโนมัติ", "auto_generate_subaddresses": "Auto สร้าง subaddresses", "automatic": "อัตโนมัติ", "available_balance": "ยอดคงเหลือที่ใช้งานได้", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 91ca5a548..def38820c 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Maling pin", "authenticated": "Napatunayan", "authentication": "Pagpapatunay", + "auto_generate_addresses": "Auto bumuo ng mga address", "auto_generate_subaddresses": "Ang Auto ay bumubuo ng mga subaddresses", "automatic": "Awtomatiko", "available_balance": "Magagamit na balanse", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 784ebfb7e..111ff91f4 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Hatalı PIN", "authenticated": "Doğrulandı", "authentication": "Doğrulama", + "auto_generate_addresses": "Otomatik Adres Oluşturma", "auto_generate_subaddresses": "Alt adresleri otomatik olarak oluştur", "automatic": "Otomatik", "available_balance": "Kullanılabilir Bakiye", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 65a1f5c96..a0000418d 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Некоректний PIN", "authenticated": "Аутентифіковано", "authentication": "Аутентифікація", + "auto_generate_addresses": "Авто генерувати адреси", "auto_generate_subaddresses": "Автоматично генерувати підадреси", "automatic": "Автоматичний", "available_balance": "Доступний баланс", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 6c768daa8..a7d4b896d 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "غلط PIN", "authenticated": "تصدیق شدہ", "authentication": "تصدیق", + "auto_generate_addresses": "آٹو پیدا کرنے والے پتے", "auto_generate_subaddresses": "آٹو سب ایڈریس تیار کرتا ہے", "automatic": "خودکار", "available_balance": "دستیاب بیلنس", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index b5f2d69a3..9ac033917 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "Òǹkà ìdánimọ̀ àdáni kọ́ ni èyí", "authenticated": "A ti jẹ́rìísí yín", "authentication": "Ìfẹ̀rílàdí", + "auto_generate_addresses": "Awọn adirẹsi ṣe agbekalẹ awọn adirẹsi", "auto_generate_subaddresses": "Aṣiṣe Ibi-Afọwọkọ", "automatic": "Ó máa ń ṣàdédé", "available_balance": "Ìyókù owó tó wà níbẹ̀", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index e9a6b63f2..26bb1b286 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -59,6 +59,7 @@ "auth_store_incorrect_password": "PIN码错误", "authenticated": "已认证", "authentication": "认证方式", + "auto_generate_addresses": "自动生成地址", "auto_generate_subaddresses": "自动生成子辅助", "automatic": "自动的", "available_balance": "可用余额", From dcf8ef0d715e4475efdd1e9ee4006d1bdc31329f Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Tue, 9 Apr 2024 21:32:43 -0400 Subject: [PATCH 176/241] Create SECURITY.md (#1375) * Create SECURITY.md * Update SECURITY.md --- SECURITY.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..a1b489b76 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,12 @@ +# Security Policy + +## Reporting a Vulnerability + +If you need to report a vulnerability, please either: + +* Open a security advisory: https://github.com/cake-tech/cake_wallet/security/advisories/new +* Send an email to `dev@cakewallet.com` with details on the vulnerability + +## Supported Versions + +As we don't maintain prevoius versions of the app, only the latest release for each platform is supported and any updates will bump the version number. From 7abe5735c0d03f65a0b3576170e8814e159b3a0f Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Fri, 12 Apr 2024 01:33:43 +0100 Subject: [PATCH 177/241] CW-589-WalletConnect-Connections-Independent (#1361) * chore: Create cw_solana package and clean up files * feat: Add Solana Wallet - Create, Restore form seed, restore from Key, Restore from QR, Send, Receive, transaction history, spl tokens * fix: Make transactions file specific to solana only for solana transactions * chore: Revert inject app details script * fix: Fix issue with node and switch current node to main beta instead of testnet * fix: Fix merge conflicts and adjust migration version * fix: Fetch spl token error Signed-off-by: Blazebrain * fix: Diplay and activate spl tokens bug * fix: Review and fixes * fix: reverted formatting for cryptocurrency class * fix: Review comments, split sending flow into signing and sending separately, fix issues * fix: Revert throwing unimplenented error * chore: Fix comment * chore: Fix comment * fix: Errors in flow * Update provider_types.dart [skip ci] * fix: Issues with solana wallet * Update solana_wallet.dart [skip ci] * fix: Review comments * fix: Date time config * fix: Revert bash script for app details * fix: Error with balance, displaying fees, fixing sent or received identifier bug, displaying token symbol with token transaction item in transactions list * fix: Issues with address validation when sending spl tokens and walletconnect initial setup * fix: Issues with sending, fetching transactions history, almost wrapping up walletconnect * fix: Adjust imports that would affect monerocom building successfully * fix: Refine transaction direction and continue work on walletconnect * feat: Display SPL token transfers in the transaction history and finally settle the transaction direction * fix: Delay in transactions history dispaly, show native token transactions first, then process spl token transactions * feat: Switch node and revert solana chain id to previous id * fix: Remove print statement * fix: Remove await for transactions, fetch all transaction histories instantly and adjust solana send success message * chore: Code refactoring and streamlined wallet type check for solana send success message * fix: Make timeout error for node silent and add spl token images * fix: Still trying to figure out what's wrong * feat: Make walletconnect connections independent to wallet * fix: Add proper return type to method * fix: Alphabetizing translation files --------- Signed-off-by: Blazebrain Co-authored-by: Omar Hatem --- .../wallet_connect/web3wallet_service.dart | 88 +++++++++++++++++-- lib/di.dart | 1 + lib/entities/preferences_key.dart | 3 + .../widgets/pairing_item_widget.dart | 2 +- 4 files changed, 84 insertions(+), 10 deletions(-) diff --git a/lib/core/wallet_connect/web3wallet_service.dart b/lib/core/wallet_connect/web3wallet_service.dart index 66ccb2d76..adb516817 100644 --- a/lib/core/wallet_connect/web3wallet_service.dart +++ b/lib/core/wallet_connect/web3wallet_service.dart @@ -1,10 +1,12 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:developer'; import 'dart:typed_data'; import 'package:cake_wallet/core/wallet_connect/chain_service/eth/evm_chain_id.dart'; import 'package:cake_wallet/core/wallet_connect/chain_service/eth/evm_chain_service.dart'; import 'package:cake_wallet/core/wallet_connect/wallet_connect_key_service.dart'; +import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/core/wallet_connect/models/auth_request_model.dart'; import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart'; @@ -19,6 +21,7 @@ import 'package:cw_core/wallet_type.dart'; import 'package:eth_sig_util/eth_sig_util.dart'; import 'package:flutter/material.dart'; import 'package:mobx/mobx.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; import 'chain_service/solana/solana_chain_id.dart'; @@ -32,6 +35,7 @@ class Web3WalletService = Web3WalletServiceBase with _$Web3WalletService; abstract class Web3WalletServiceBase with Store { final AppStore appStore; + final SharedPreferences sharedPreferences; final BottomSheetService _bottomSheetHandler; final WalletConnectKeyService walletKeyService; @@ -52,7 +56,8 @@ abstract class Web3WalletServiceBase with Store { @observable ObservableList auth; - Web3WalletServiceBase(this._bottomSheetHandler, this.walletKeyService, this.appStore) + Web3WalletServiceBase( + this._bottomSheetHandler, this.walletKeyService, this.appStore, this.sharedPreferences) : pairings = ObservableList(), sessions = ObservableList(), auth = ObservableList(), @@ -191,13 +196,6 @@ abstract class Web3WalletServiceBase with Store { _refreshPairings(); } - @action - void _refreshPairings() { - pairings.clear(); - final allPairings = _web3Wallet.pairings.getAll(); - pairings.addAll(allPairings); - } - Future _onSessionProposalError(SessionProposalErrorEvent? args) async { log(args.toString()); } @@ -260,14 +258,37 @@ abstract class Web3WalletServiceBase with Store { } } + @action + void _refreshPairings() { + print('Refreshing pairings'); + pairings.clear(); + + final allPairings = _web3Wallet.pairings.getAll(); + + final keyForWallet = getKeyForStoringTopicsForWallet(); + + final currentTopicsForWallet = getPairingTopicsForWallet(keyForWallet); + + final filteredPairings = + allPairings.where((pairing) => currentTopicsForWallet.contains(pairing.topic)).toList(); + + pairings.addAll(filteredPairings); + } + void _onPairingCreate(PairingEvent? args) { log('Pairing Create Event: $args'); } @action - void _onSessionConnect(SessionConnect? args) { + Future _onSessionConnect(SessionConnect? args) async { if (args != null) { + log('Session Connected $args'); + + await savePairingTopicToLocalStorage(args.session.pairingTopic); + sessions.add(args.session); + + _refreshPairings(); } } @@ -335,4 +356,53 @@ abstract class Web3WalletServiceBase with Store { List getSessionsForPairingInfo(PairingInfo pairing) { return sessions.where((element) => element.pairingTopic == pairing.topic).toList(); } + + String getKeyForStoringTopicsForWallet() { + List chainKeys = walletKeyService.getKeysForChain(appStore.wallet!); + + final keyForPairingTopic = + PreferencesKey.walletConnectPairingTopicsListForWallet(chainKeys.first.publicKey); + + return keyForPairingTopic; + } + + List getPairingTopicsForWallet(String key) { + // Get the JSON-encoded string from shared preferences + final jsonString = sharedPreferences.getString(key); + + // If the string is null, return an empty list + if (jsonString == null) { + return []; + } + + // Decode the JSON string to a list of strings + final List jsonList = jsonDecode(jsonString) as List; + + // Cast each item to a string + return jsonList.map((item) => item as String).toList(); + } + + Future savePairingTopicToLocalStorage(String pairingTopic) async { + // Get key specific to the current wallet + final key = getKeyForStoringTopicsForWallet(); + + // Get all pairing topics attached to this key + final pairingTopicsForWallet = getPairingTopicsForWallet(key); + + print(pairingTopicsForWallet); + + bool isPairingTopicAlreadySaved = pairingTopicsForWallet.contains(pairingTopic); + print('Is Pairing Topic Saved: $isPairingTopicAlreadySaved'); + + if (!isPairingTopicAlreadySaved) { + // Update the list with the most recent pairing topic + pairingTopicsForWallet.add(pairingTopic); + + // Convert the list of updated pairing topics to a JSON-encoded string + final jsonString = jsonEncode(pairingTopicsForWallet); + + // Save the encoded string to shared preferences + await sharedPreferences.setString(key, jsonString); + } + } } diff --git a/lib/di.dart b/lib/di.dart index 5262a01e6..d78da638c 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -493,6 +493,7 @@ Future setup({ getIt.get(), getIt.get(), appStore, + getIt.get() ); web3WalletService.create(); return web3WalletService; diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index ba6d6ef4f..80a7acba1 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -75,4 +75,7 @@ class PreferencesKey { static const shouldShowMarketPlaceInDashboard = 'should_show_marketplace_in_dashboard'; static const isNewInstall = 'is_new_install'; static const serviceStatusShaKey = 'service_status_sha_key'; + static const walletConnectPairingTopicsList = 'wallet_connect_pairing_topics_list'; + static String walletConnectPairingTopicsListForWallet(String publicKey) => + '${PreferencesKey.walletConnectPairingTopicsList}_${publicKey}'; } diff --git a/lib/src/screens/wallet_connect/widgets/pairing_item_widget.dart b/lib/src/screens/wallet_connect/widgets/pairing_item_widget.dart index 0d425f904..518cf32f7 100644 --- a/lib/src/screens/wallet_connect/widgets/pairing_item_widget.dart +++ b/lib/src/screens/wallet_connect/widgets/pairing_item_widget.dart @@ -30,7 +30,7 @@ class PairingItemWidget extends StatelessWidget { leading: CakeImageWidget( imageUrl: metadata.icons.isNotEmpty ? metadata.icons[0]: null, displayOnError: CircleAvatar( - backgroundImage: AssetImage('assets/images/default_icon.png'), + backgroundImage: AssetImage('assets/images/walletconnect_logo.png'), ), ), title: Text( From fce6394bca336eb2a28e78650fa9eb34ceef80fe Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Fri, 12 Apr 2024 05:36:42 -0700 Subject: [PATCH 178/241] Cw 602 nano bad rep (#1356) * add support for paths in node settings * update translations and fixes * fix node path * add rep warning flag * update translations * code cleanup [skip ci] * add additional node options * add migration * update transaction history rpc to be under the limit * review fixes [skip ci] * [skip ci] updates * move n2_node.dart * minor code improvements * more minor code cleanup --- assets/nano_node_list.yml | 24 +- cw_core/lib/n2_node.dart | 31 ++ cw_core/lib/node.dart | 18 +- cw_nano/lib/nano_client.dart | 38 +- cw_nano/lib/nano_wallet.dart | 13 +- lib/core/node_address_validator.dart | 5 + lib/entities/default_settings_migration.dart | 34 +- lib/entities/preferences_key.dart | 1 + lib/main.dart | 2 +- lib/nano/cw_nano.dart | 10 + .../screens/dashboard/pages/balance_page.dart | 17 + .../screens/nano/nano_change_rep_page.dart | 393 ++++++++++++++---- .../nodes/node_create_or_edit_page.dart | 4 + lib/src/screens/nodes/widgets/node_form.dart | 128 +++--- lib/src/widgets/dashboard_card_widget.dart | 58 +-- .../scollable_with_bottom_section.dart | 21 +- lib/store/settings_store.dart | 151 ++++--- .../dashboard/dashboard_view_model.dart | 13 + .../node_create_or_edit_view_model.dart | 23 +- res/values/strings_ar.arb | 6 + res/values/strings_bg.arb | 6 + res/values/strings_cs.arb | 6 + res/values/strings_de.arb | 6 + res/values/strings_en.arb | 6 + res/values/strings_es.arb | 6 + res/values/strings_fr.arb | 6 + res/values/strings_ha.arb | 6 + res/values/strings_hi.arb | 6 + res/values/strings_hr.arb | 6 + res/values/strings_id.arb | 6 + res/values/strings_it.arb | 6 + res/values/strings_ja.arb | 6 + res/values/strings_ko.arb | 8 +- res/values/strings_my.arb | 6 + res/values/strings_nl.arb | 6 + res/values/strings_pl.arb | 6 + res/values/strings_pt.arb | 6 + res/values/strings_ru.arb | 6 + res/values/strings_th.arb | 6 + res/values/strings_tl.arb | 6 + res/values/strings_tr.arb | 6 + res/values/strings_uk.arb | 6 + res/values/strings_ur.arb | 6 + res/values/strings_yo.arb | 6 + res/values/strings_zh.arb | 6 + tool/configure.dart | 3 + 46 files changed, 881 insertions(+), 264 deletions(-) create mode 100644 cw_core/lib/n2_node.dart diff --git a/assets/nano_node_list.yml b/assets/nano_node_list.yml index 63b4baec1..2e4d1ec3c 100644 --- a/assets/nano_node_list.yml +++ b/assets/nano_node_list.yml @@ -3,4 +3,26 @@ useSSL: true is_default: true - - uri: node.perish.co:9076 \ No newline at end of file + uri: node.nautilus.io + path: /api + useSSL: true +- + uri: app.natrium.io + path: /api + useSSL: true +- + uri: rainstorm.city + path: /api + useSSL: true +- + uri: node.somenano.com + path: /proxy + useSSL: true +- + uri: nanoslo.0x.no + path: /proxy + useSSL: true +- + uri: www.bitrequest.app + port: 8020 + useSSL: true \ No newline at end of file diff --git a/cw_core/lib/n2_node.dart b/cw_core/lib/n2_node.dart new file mode 100644 index 000000000..0fad9d1b5 --- /dev/null +++ b/cw_core/lib/n2_node.dart @@ -0,0 +1,31 @@ +class N2Node { + N2Node({ + this.weight, + this.uptime, + this.score, + this.account, + this.alias, + }); + + String? uptime; + double? weight; + int? score; + String? account; + String? alias; + + factory N2Node.fromJson(Map json) => N2Node( + weight: double.tryParse((json['weight'] as num).toString()), + uptime: json['uptime'] as String?, + score: json['score'] as int?, + account: json['rep_address'] as String?, + alias: json['alias'] as String?, + ); + + Map toJson() => { + 'uptime': uptime, + 'weight': weight, + 'score': score, + 'rep_address': account, + 'alias': alias, + }; +} diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 585bc3c38..d7e91d692 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -21,6 +21,7 @@ class Node extends HiveObject with Keyable { this.trusted = false, this.socksProxyAddress, String? uri, + String? path, WalletType? type, }) { if (uri != null) { @@ -29,10 +30,14 @@ class Node extends HiveObject with Keyable { if (type != null) { this.type = type; } + if (path != null) { + this.path = path; + } } Node.fromMap(Map map) : uriRaw = map['uri'] as String? ?? '', + path = map['path'] as String? ?? '', login = map['login'] as String?, password = map['password'] as String?, useSSL = map['useSSL'] as bool?, @@ -63,6 +68,9 @@ class Node extends HiveObject with Keyable { @HiveField(6) String? socksProxyAddress; + @HiveField(7, defaultValue: '') + String? path; + bool get isSSL => useSSL ?? false; bool get useSocksProxy => socksProxyAddress == null ? false : socksProxyAddress!.isNotEmpty; @@ -79,9 +87,9 @@ class Node extends HiveObject with Keyable { case WalletType.nano: case WalletType.banano: if (isSSL) { - return Uri.https(uriRaw, ''); + return Uri.https(uriRaw, path ?? ''); } else { - return Uri.http(uriRaw, ''); + return Uri.http(uriRaw, path ?? ''); } case WalletType.ethereum: case WalletType.polygon: @@ -103,7 +111,8 @@ class Node extends HiveObject with Keyable { other.typeRaw == typeRaw && other.useSSL == useSSL && other.trusted == trusted && - other.socksProxyAddress == socksProxyAddress); + other.socksProxyAddress == socksProxyAddress && + other.path == path); @override int get hashCode => @@ -113,7 +122,8 @@ class Node extends HiveObject with Keyable { typeRaw.hashCode ^ useSSL.hashCode ^ trusted.hashCode ^ - socksProxyAddress.hashCode; + socksProxyAddress.hashCode ^ + path.hashCode; @override dynamic get keyIndex { diff --git a/cw_nano/lib/nano_client.dart b/cw_nano/lib/nano_client.dart index 661fbcab8..064a0bdee 100644 --- a/cw_nano/lib/nano_client.dart +++ b/cw_nano/lib/nano_client.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:convert'; import 'package:cw_core/nano_account_info_response.dart'; +import 'package:cw_core/n2_node.dart'; import 'package:cw_nano/nano_balance.dart'; import 'package:cw_nano/nano_transaction_model.dart'; import 'package:http/http.dart' as http; @@ -16,6 +17,8 @@ class NanoClient { "nano-app": "cake-wallet" }; + static const String N2_REPS_ENDPOINT = "https://rpc.nano.to"; + NanoClient() { SharedPreferences.getInstance().then((value) => prefs = value); } @@ -418,7 +421,7 @@ class NanoClient { body: jsonEncode({ "action": "account_history", "account": address, - "count": "250", // TODO: pick a number + "count": "100", // "raw": true, })); final data = await jsonDecode(response.body); @@ -434,4 +437,37 @@ class NanoClient { return []; } } + + Future> getN2Reps() async { + final response = await http.post( + Uri.parse(N2_REPS_ENDPOINT), + headers: CAKE_HEADERS, + body: jsonEncode({"action": "reps"}), + ); + try { + final List nodes = (json.decode(response.body) as List) + .map((dynamic e) => N2Node.fromJson(e as Map)) + .toList(); + return nodes; + } catch (error) { + return []; + } + } + + Future getRepScore(String rep) async { + final response = await http.post( + Uri.parse(N2_REPS_ENDPOINT), + headers: CAKE_HEADERS, + body: jsonEncode({ + "action": "rep_info", + "account": rep, + }), + ); + try { + final N2Node node = N2Node.fromJson(json.decode(response.body) as Map); + return node.score ?? 100; + } catch (error) { + return 100; + } + } } diff --git a/cw_nano/lib/nano_wallet.dart b/cw_nano/lib/nano_wallet.dart index 1f6ec36ae..265f78eb7 100644 --- a/cw_nano/lib/nano_wallet.dart +++ b/cw_nano/lib/nano_wallet.dart @@ -13,6 +13,7 @@ import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_nano/file.dart'; import 'package:cw_core/nano_account.dart'; +import 'package:cw_core/n2_node.dart'; import 'package:cw_nano/nano_balance.dart'; import 'package:cw_nano/nano_client.dart'; import 'package:cw_nano/nano_transaction_credentials.dart'; @@ -65,9 +66,11 @@ abstract class NanoWalletBase String? _privateKey; String? _publicAddress; String? _hexSeed; + Timer? _receiveTimer; String? _representativeAddress; - Timer? _receiveTimer; + int repScore = 100; + bool get isRepOk => repScore >= 90; late final NanoClient _client; bool _isTransactionUpdating; @@ -375,7 +378,7 @@ abstract class NanoWalletBase final data = json.decode(jsonSource) as Map; final mnemonic = data['mnemonic'] as String; - + final balance = NanoBalance.fromRawString( currentBalance: data['currentBalance'] as String? ?? "0", receivableBalance: data['receivableBalance'] as String? ?? "0", @@ -429,6 +432,8 @@ abstract class NanoWalletBase _representativeAddress = await _client.getRepFromPrefs(); throw Exception("Failed to get representative address $e"); } + + repScore = await _client.getRepScore(_representativeAddress!); } Future regenerateAddress() async { @@ -465,6 +470,10 @@ abstract class NanoWalletBase } } + Future> getN2Reps() async { + return _client.getN2Reps(); + } + Future? updateBalance() async => await _updateBalance(); @override diff --git a/lib/core/node_address_validator.dart b/lib/core/node_address_validator.dart index 0e034dabc..c1fe4ba91 100644 --- a/lib/core/node_address_validator.dart +++ b/lib/core/node_address_validator.dart @@ -8,3 +8,8 @@ class NodeAddressValidator extends TextValidator { pattern: '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\$|^[0-9a-zA-Z.\-]+\$'); } + +class NodePathValidator extends TextValidator { + NodePathValidator() + : super(errorMessage: S.current.error_text_node_address, pattern: '^([/0-9a-zA-Z.\-]+)?\$'); +} diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 9a2db56af..a0f570e95 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -216,6 +216,10 @@ Future defaultSettingsMigration( await disableServiceStatusFiatDisabled(sharedPreferences); break; + case 31: + await updateNanoNodeList(nodes: nodes); + break; + default: break; } @@ -230,9 +234,35 @@ Future defaultSettingsMigration( await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version); } +Future updateNanoNodeList({required Box nodes}) async { + final nodeList = await loadDefaultNanoNodes(); + var listOfNewEndpoints = [ + "app.natrium.io", + "rainstorm.city", + "node.somenano.com", + "nanoslo.0x.no", + "www.bitrequest.app", + ]; + // add new nodes: + for (final node in nodeList) { + if (listOfNewEndpoints.contains(node.uriRaw)) { + await nodes.add(node); + } + } + + // update the nautilus node: + final nautilusNode = + nodes.values.firstWhereOrNull((element) => element.uriRaw == "node.perish.co"); + if (nautilusNode != null) { + nautilusNode.uriRaw = "node.nautilus.io"; + nautilusNode.path = "/api"; + nautilusNode.useSSL = true; + await nautilusNode.save(); + } +} + Future disableServiceStatusFiatDisabled(SharedPreferences sharedPreferences) async { - final currentFiat = - await sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey) ?? -1; + final currentFiat = await sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey) ?? -1; if (currentFiat == -1 || currentFiat == FiatApiMode.enabled.raw) { return; } diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 80a7acba1..f512d6b72 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -45,6 +45,7 @@ class PreferencesKey { static const customBitcoinFeeRate = 'custom_electrum_fee_rate'; static const shouldShowReceiveWarning = 'should_show_receive_warning'; static const shouldShowYatPopup = 'should_show_yat_popup'; + static const shouldShowRepWarning = 'should_show_rep_warning'; static const moneroWalletPasswordUpdateV1Base = 'monero_wallet_update_v1'; static const syncModeKey = 'sync_mode'; static const syncAllKey = 'sync_all'; diff --git a/lib/main.dart b/lib/main.dart index 6868348f6..b80c9eb85 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -163,7 +163,7 @@ Future initializeAppConfigs() async { transactionDescriptions: transactionDescriptions, secureStorage: secureStorage, anonpayInvoiceInfo: anonpayInvoiceInfo, - initialMigrationVersion: 30, + initialMigrationVersion: 31, ); } diff --git a/lib/nano/cw_nano.dart b/lib/nano/cw_nano.dart index 06ebf60c2..5896f7c26 100644 --- a/lib/nano/cw_nano.dart +++ b/lib/nano/cw_nano.dart @@ -186,6 +186,16 @@ class CWNano extends Nano { String getRepresentative(Object wallet) { return (wallet as NanoWallet).representative; } + + @override + Future> getN2Reps(Object wallet) async { + return (wallet as NanoWallet).getN2Reps(); + } + + @override + bool isRepOk(Object wallet) { + return (wallet as NanoWallet).isRepOk; + } } class CWNanoUtil extends NanoUtil { diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart index 0b7596469..a2ad3fb80 100644 --- a/lib/src/screens/dashboard/pages/balance_page.dart +++ b/lib/src/screens/dashboard/pages/balance_page.dart @@ -8,6 +8,7 @@ import 'package:cake_wallet/src/screens/dashboard/pages/nft_listing_page.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/home_screen_account_widget.dart'; import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart'; +import 'package:cake_wallet/src/widgets/dashboard_card_widget.dart'; import 'package:cake_wallet/src/widgets/introducing_card.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; @@ -183,6 +184,22 @@ class CryptoBalanceWidget extends StatelessWidget { return Container(); }, ), + Observer(builder: (_) { + if (!dashboardViewModel.showRepWarning) { + return const SizedBox(); + } + return Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), + child: DashBoardRoundedCardWidget( + title: S.current.rep_warning, + subTitle: S.current.rep_warning_sub, + onTap: () => Navigator.of(context).pushNamed(Routes.changeRep), + onClose: () { + dashboardViewModel.settingsStore.shouldShowRepWarning = false; + }, + ), + ); + }), Observer( builder: (_) { return ListView.separated( diff --git a/lib/src/screens/nano/nano_change_rep_page.dart b/lib/src/screens/nano/nano_change_rep_page.dart index a625f7e29..9f71bb59c 100644 --- a/lib/src/screens/nano/nano_change_rep_page.dart +++ b/lib/src/screens/nano/nano_change_rep_page.dart @@ -5,10 +5,12 @@ import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/themes/extensions/address_theme.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/n2_node.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -21,9 +23,7 @@ class NanoChangeRepPage extends BasePage { : _wallet = wallet, _settingsStore = settingsStore, _addressController = TextEditingController(), - _formKey = GlobalKey() { - _addressController.text = nano!.getRepresentative(wallet); - } + _formKey = GlobalKey() {} final TextEditingController _addressController; final WalletBase _wallet; @@ -34,105 +34,314 @@ class NanoChangeRepPage extends BasePage { @override String get title => S.current.change_rep; + N2Node getCurrentRepNode(List nodes) { + final currentRepAccount = nano!.getRepresentative(_wallet); + final currentNode = nodes.firstWhere( + (node) => node.account == currentRepAccount, + orElse: () => N2Node( + account: currentRepAccount, + alias: currentRepAccount, + score: 0, + uptime: "???", + weight: 0, + ), + ); + + return currentNode; + } + @override Widget body(BuildContext context) { return Form( key: _formKey, - child: Container( - padding: EdgeInsets.only(left: 24, right: 24), - child: ScrollableWithBottomSection( - contentPadding: EdgeInsets.only(bottom: 24.0), - content: Container( - child: Column( - children: [ - Row( - children: [ - Expanded( - child: AddressTextField( - controller: _addressController, - onURIScanned: (uri) { - final paymentRequest = PaymentRequest.fromUri(uri); - _addressController.text = paymentRequest.address; - }, - options: [ - AddressTextFieldOption.paste, - AddressTextFieldOption.qrCode, - ], - buttonColor: Theme.of(context).extension()!.actionButtonColor, - validator: AddressValidator(type: CryptoCurrency.nano), + child: FutureBuilder( + future: nano!.getN2Reps(_wallet), + builder: (context, snapshot) { + if (snapshot.data == null) { + return SizedBox(); + } + + return Container( + padding: EdgeInsets.only(left: 24, right: 24), + child: ScrollableWithBottomSection( + topSectionPadding: EdgeInsets.only(bottom: 24), + topSection: Column( + children: [ + Row( + children: [ + Expanded( + child: AddressTextField( + controller: _addressController, + onURIScanned: (uri) { + final paymentRequest = PaymentRequest.fromUri(uri); + _addressController.text = paymentRequest.address; + }, + options: [ + AddressTextFieldOption.paste, + AddressTextFieldOption.qrCode, + ], + buttonColor: + Theme.of(context).extension()!.actionButtonColor, + validator: AddressValidator(type: CryptoCurrency.nano), + ), + ) + ], + ), + Column( + children: [ + Container( + margin: EdgeInsets.only(top: 12), + child: Text( + S.current.nano_current_rep, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + ), + ), ), - ) - ], + _buildSingleRepresentative( + context, + getCurrentRepNode(snapshot.data as List), + isList: false, + ), + Divider(height: 20), + Container( + margin: EdgeInsets.only(top: 12), + child: Text( + S.current.nano_pick_new_rep, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + ), + ), + ), + ], + ), + ], + ), + contentPadding: EdgeInsets.only(bottom: 24), + content: Container( + child: Column( + children: _getRepresentativeWidgets(context, snapshot.data as List), + ), + ), + bottomSectionPadding: EdgeInsets.only(bottom: 24), + bottomSection: Observer( + builder: (_) => Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Flexible( + child: Container( + padding: EdgeInsets.only(right: 8.0), + child: LoadingPrimaryButton( + onPressed: () => _onSubmit(context), + text: S.of(context).change, + color: Theme.of(context).primaryColor, + textColor: Colors.white, + ), + )), + ], + )), + ), + ); + }, + ), + ); + } + + Future _onSubmit(BuildContext context) async { + if (_formKey.currentState != null && !_formKey.currentState!.validate()) { + return; + } + + final confirmed = await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithTwoActions( + alertTitle: S.of(context).change_rep, + alertContent: S.of(context).change_rep_message, + rightButtonText: S.of(context).change, + leftButtonText: S.of(context).cancel, + actionRightButton: () => Navigator.pop(context, true), + actionLeftButton: () => Navigator.pop(context, false)); + }) ?? + false; + + if (confirmed) { + try { + _settingsStore.defaultNanoRep = _addressController.text; + + await nano!.changeRep(_wallet, _addressController.text); + + // reset this flag whenever we successfully change reps: + _settingsStore.shouldShowRepWarning = true; + + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: S.of(context).successful, + alertContent: S.of(context).change_rep_successful, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.pop(context)); + }); + } catch (e) { + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: S.of(context).error, + alertContent: e.toString(), + buttonText: S.of(context).ok, + buttonAction: () => Navigator.pop(context)); + }); + throw e; + } + } + } + + List _getRepresentativeWidgets(BuildContext context, List? list) { + if (list == null) { + return []; + } + final List ret = []; + for (final N2Node node in list) { + if (node.alias != null && node.alias!.trim().isNotEmpty) { + ret.add(_buildSingleRepresentative(context, node)); + } + } + return ret; + } + + Widget _buildSingleRepresentative(BuildContext context, N2Node rep, {bool isList = true}) { + return Column( + children: [ + if (isList) + Divider( + height: 2, + ), + TextButton( + style: TextButton.styleFrom( + padding: EdgeInsets.zero, + ), + onPressed: () async { + if (!isList) { + return; + } + _addressController.text = rep.account!; + }, + child: Container( + margin: const EdgeInsets.symmetric(vertical: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + margin: const EdgeInsetsDirectional.only(start: 24), + width: MediaQuery.of(context).size.width * 0.50, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + _sanitizeAlias(rep.alias), + style: TextStyle( + color: Theme.of(context).extension()!.titleColor, + fontWeight: FontWeight.w700, + fontSize: 18, + ), + ), + Container( + margin: const EdgeInsets.only(top: 7), + child: RichText( + text: TextSpan( + text: "${S.current.voting_weight}: ${rep.weight.toString()}%", + style: TextStyle( + color: + Theme.of(context).extension()!.secondaryTextColor, + fontWeight: FontWeight.w700, + fontSize: 14.0, + ), + ), + ), + ), + Container( + margin: const EdgeInsets.only(top: 4), + child: RichText( + text: TextSpan( + text: '', + children: [ + TextSpan( + text: "${S.current.uptime}: ", + style: TextStyle( + color: Theme.of(context) + .extension()! + .secondaryTextColor, + fontWeight: FontWeight.w700, + fontSize: 14, + ), + ), + TextSpan( + text: rep.uptime, + style: TextStyle( + color: Theme.of(context) + .extension()! + .secondaryTextColor, + fontWeight: FontWeight.w900, + fontSize: 14, + ), + ), + ], + ), + ), + ), + ], + ), + ), + Container( + margin: const EdgeInsetsDirectional.only(end: 24, start: 14), + child: Stack( + children: [ + Icon( + Icons.verified, + color: Theme.of(context).primaryColor, + size: 50, + ), + Positioned.fill( + child: Container( + margin: EdgeInsets.all(13), + color: Theme.of(context).primaryColor, + ), + ), + Container( + alignment: const AlignmentDirectional(-0.03, 0.03), + width: 50, + height: 50, + child: Text( + (rep.score).toString(), + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).extension()!.titleColor, + fontSize: 13, + fontWeight: FontWeight.w800, + ), + ), + ), + ], + ), ), ], ), ), - bottomSectionPadding: EdgeInsets.only(bottom: 24), - bottomSection: Observer( - builder: (_) => Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Flexible( - child: Container( - padding: EdgeInsets.only(right: 8.0), - child: LoadingPrimaryButton( - onPressed: () async { - if (_formKey.currentState != null && - !_formKey.currentState!.validate()) { - return; - } - - final confirmed = await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithTwoActions( - alertTitle: S.of(context).change_rep, - alertContent: S.of(context).change_rep_message, - rightButtonText: S.of(context).change, - leftButtonText: S.of(context).cancel, - actionRightButton: () => Navigator.pop(context, true), - actionLeftButton: () => Navigator.pop(context, false)); - }) ?? - false; - - if (confirmed) { - try { - _settingsStore.defaultNanoRep = _addressController.text; - - await nano!.changeRep(_wallet, _addressController.text); - - await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: S.of(context).successful, - alertContent: S.of(context).change_rep_successful, - buttonText: S.of(context).ok, - buttonAction: () => Navigator.pop(context)); - }); - } catch (e) { - await showPopUp( - context: context, - builder: (BuildContext context) { - return AlertWithOneAction( - alertTitle: S.of(context).error, - alertContent: e.toString(), - buttonText: S.of(context).ok, - buttonAction: () => Navigator.pop(context)); - }); - throw e; - } - } - }, - text: S.of(context).change, - color: Theme.of(context).primaryColor, - textColor: Colors.white, - ), - )), - ], - )), ), - ), + ], ); } + + String _sanitizeAlias(String? alias) { + if (alias != null) { + return alias.replaceAll(RegExp(r'[^a-zA-Z_.!?_;:-]'), ''); + } + return ''; + } } diff --git a/lib/src/screens/nodes/node_create_or_edit_page.dart b/lib/src/screens/nodes/node_create_or_edit_page.dart index 50c1c3be5..53c34f302 100644 --- a/lib/src/screens/nodes/node_create_or_edit_page.dart +++ b/lib/src/screens/nodes/node_create_or_edit_page.dart @@ -18,6 +18,7 @@ class NodeCreateOrEditPage extends BasePage { NodeCreateOrEditPage({required this.nodeCreateOrEditViewModel,this.editingNode, this.isSelected}) : _formKey = GlobalKey(), _addressController = TextEditingController(), + _pathController = TextEditingController(), _portController = TextEditingController(), _loginController = TextEditingController(), _passwordController = TextEditingController() { @@ -49,6 +50,8 @@ class NodeCreateOrEditPage extends BasePage { _addressController.addListener( () => nodeCreateOrEditViewModel.address = _addressController.text); + _pathController.addListener( + () => nodeCreateOrEditViewModel.path = _pathController.text); _portController.addListener( () => nodeCreateOrEditViewModel.port = _portController.text); _loginController.addListener( @@ -59,6 +62,7 @@ class NodeCreateOrEditPage extends BasePage { final GlobalKey _formKey; final TextEditingController _addressController; + final TextEditingController _pathController; final TextEditingController _portController; final TextEditingController _loginController; final TextEditingController _passwordController; diff --git a/lib/src/screens/nodes/widgets/node_form.dart b/lib/src/screens/nodes/widgets/node_form.dart index ab8dcafdf..e8c4b0ab3 100644 --- a/lib/src/screens/nodes/widgets/node_form.dart +++ b/lib/src/screens/nodes/widgets/node_form.dart @@ -16,13 +16,15 @@ class NodeForm extends StatelessWidget { required this.formKey, this.editingNode, }) : _addressController = TextEditingController(text: editingNode?.uri.host.toString()), + _pathController = TextEditingController(text: editingNode?.path.toString()), _portController = TextEditingController(text: editingNode?.uri.port.toString()), _loginController = TextEditingController(text: editingNode?.login), _passwordController = TextEditingController(text: editingNode?.password), - _socksAddressController = TextEditingController(text: editingNode?.socksProxyAddress){ + _socksAddressController = TextEditingController(text: editingNode?.socksProxyAddress) { if (editingNode != null) { nodeViewModel ..setAddress((editingNode!.uri.host.toString())) + ..setPath((editingNode!.path.toString())) ..setPort((editingNode!.uri.port.toString())) ..setPassword((editingNode!.password ?? '')) ..setLogin((editingNode!.login ?? '')) @@ -57,10 +59,12 @@ class NodeForm extends StatelessWidget { }); _addressController.addListener(() => nodeViewModel.address = _addressController.text); + _pathController.addListener(() => nodeViewModel.path = _pathController.text); _portController.addListener(() => nodeViewModel.port = _portController.text); _loginController.addListener(() => nodeViewModel.login = _loginController.text); _passwordController.addListener(() => nodeViewModel.password = _passwordController.text); - _socksAddressController.addListener(() => nodeViewModel.socksProxyAddress = _socksAddressController.text); + _socksAddressController + .addListener(() => nodeViewModel.socksProxyAddress = _socksAddressController.text); } final NodeCreateOrEditViewModel nodeViewModel; @@ -68,6 +72,7 @@ class NodeForm extends StatelessWidget { final Node? editingNode; final TextEditingController _addressController; + final TextEditingController _pathController; final TextEditingController _portController; final TextEditingController _loginController; final TextEditingController _passwordController; @@ -91,6 +96,18 @@ class NodeForm extends StatelessWidget { ], ), SizedBox(height: 10.0), + Row( + children: [ + Expanded( + child: BaseTextFormField( + controller: _pathController, + hintText: "/path", + validator: NodePathValidator(), + ), + ) + ], + ), + SizedBox(height: 10.0), Row( children: [ Expanded( @@ -103,6 +120,26 @@ class NodeForm extends StatelessWidget { ], ), SizedBox(height: 10.0), + Padding( + padding: EdgeInsets.only(top: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Observer( + builder: (_) => StandardCheckbox( + value: nodeViewModel.useSSL, + gradientBackground: true, + borderColor: Theme.of(context).dividerColor, + iconColor: Colors.white, + onChanged: (value) => nodeViewModel.useSSL = value, + caption: S.of(context).use_ssl, + ), + ) + ], + ), + ), + SizedBox(height: 10.0), if (nodeViewModel.hasAuthCredentials) ...[ Row( children: [ @@ -123,25 +160,6 @@ class NodeForm extends StatelessWidget { )) ], ), - Padding( - padding: EdgeInsets.only(top: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - Observer( - builder: (_) => StandardCheckbox( - value: nodeViewModel.useSSL, - gradientBackground: true, - borderColor: Theme.of(context).dividerColor, - iconColor: Colors.white, - onChanged: (value) => nodeViewModel.useSSL = value, - caption: S.of(context).use_ssl, - ), - ) - ], - ), - ), Padding( padding: EdgeInsets.only(top: 20), child: Row( @@ -163,44 +181,44 @@ class NodeForm extends StatelessWidget { ), Observer( builder: (_) => Column( - children: [ - Padding( - padding: EdgeInsets.only(top: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - StandardCheckbox( - value: nodeViewModel.useSocksProxy, - gradientBackground: true, - borderColor: Theme.of(context).dividerColor, - iconColor: Colors.white, - onChanged: (value) { - if (!value) { - _socksAddressController.text = ''; - } - nodeViewModel.useSocksProxy = value; - }, - caption: 'SOCKS Proxy', - ), - ], - ), - ), - if (nodeViewModel.useSocksProxy) ...[ - SizedBox(height: 10.0), - Row( - children: [ - Expanded( - child: BaseTextFormField( + children: [ + Padding( + padding: EdgeInsets.only(top: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + StandardCheckbox( + value: nodeViewModel.useSocksProxy, + gradientBackground: true, + borderColor: Theme.of(context).dividerColor, + iconColor: Colors.white, + onChanged: (value) { + if (!value) { + _socksAddressController.text = ''; + } + nodeViewModel.useSocksProxy = value; + }, + caption: 'SOCKS Proxy', + ), + ], + ), + ), + if (nodeViewModel.useSocksProxy) ...[ + SizedBox(height: 10.0), + Row( + children: [ + Expanded( + child: BaseTextFormField( controller: _socksAddressController, hintText: '[:]', validator: SocksProxyNodeAddressValidator(), )) - ], - ), - ] - ], - )), + ], + ), + ] + ], + )), ] ], ), diff --git a/lib/src/widgets/dashboard_card_widget.dart b/lib/src/widgets/dashboard_card_widget.dart index b3f92123a..74f2d598b 100644 --- a/lib/src/widgets/dashboard_card_widget.dart +++ b/lib/src/widgets/dashboard_card_widget.dart @@ -4,15 +4,15 @@ import 'package:flutter/material.dart'; import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; class DashBoardRoundedCardWidget extends StatelessWidget { - - DashBoardRoundedCardWidget({ required this.onTap, required this.title, required this.subTitle, + this.onClose, }); final VoidCallback onTap; + final VoidCallback? onClose; final String title; final String subTitle; @@ -26,7 +26,7 @@ class DashBoardRoundedCardWidget extends StatelessWidget { child: Stack( children: [ Container( - padding: EdgeInsets.all(20), + padding: EdgeInsets.fromLTRB(20, 20, 40, 20), width: double.infinity, decoration: BoxDecoration( color: Theme.of(context).extension()!.syncedBackgroundColor, @@ -35,32 +35,40 @@ class DashBoardRoundedCardWidget extends StatelessWidget { color: Theme.of(context).extension()!.cardBorderColor, ), ), - child: - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: TextStyle( - color: Theme.of(context).extension()!.cardTextColor, - fontSize: 24, - fontWeight: FontWeight.w900, - ), - ), - SizedBox(height: 5), - Text( - subTitle, - style: TextStyle( - color: Theme.of(context).extension()!.cardTextColor, - fontWeight: FontWeight.w500, - fontFamily: 'Lato'), - ) - ], + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: TextStyle( + color: Theme.of(context).extension()!.cardTextColor, + fontSize: 24, + fontWeight: FontWeight.w900, + ), ), + SizedBox(height: 5), + Text( + subTitle, + style: TextStyle( + color: Theme.of(context).extension()!.cardTextColor, + fontWeight: FontWeight.w500, + fontFamily: 'Lato'), + ) + ], + ), ), + if (onClose != null) + Positioned( + top: 10, + right: 10, + child: IconButton( + icon: Icon(Icons.close), + onPressed: onClose, + color: Theme.of(context).extension()!.cardTextColor, + ), + ), ], ), ); } } - diff --git a/lib/src/widgets/scollable_with_bottom_section.dart b/lib/src/widgets/scollable_with_bottom_section.dart index 2487e6130..e15be610e 100644 --- a/lib/src/widgets/scollable_with_bottom_section.dart +++ b/lib/src/widgets/scollable_with_bottom_section.dart @@ -2,16 +2,21 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class ScrollableWithBottomSection extends StatefulWidget { - ScrollableWithBottomSection( - {required this.content, - required this.bottomSection, - this.contentPadding, - this.bottomSectionPadding}); + ScrollableWithBottomSection({ + required this.content, + required this.bottomSection, + this.topSection, + this.contentPadding, + this.bottomSectionPadding, + this.topSectionPadding, + }); final Widget content; final Widget bottomSection; + final Widget? topSection; final EdgeInsets? contentPadding; final EdgeInsets? bottomSectionPadding; + final EdgeInsets? topSectionPadding; @override ScrollableWithBottomSectionState createState() => ScrollableWithBottomSectionState(); @@ -22,6 +27,12 @@ class ScrollableWithBottomSectionState extends State nodes, required Map powNodes, required this.shouldShowYatPopup, + required this.shouldShowRepWarning, required this.isBitcoinBuyEnabled, required this.actionlistDisplayMode, required this.pinTimeOutDuration, @@ -225,6 +226,9 @@ abstract class SettingsStoreBase with Store { (bool shouldShowYatPopup) => sharedPreferences.setBool(PreferencesKey.shouldShowYatPopup, shouldShowYatPopup)); + reaction((_) => shouldShowRepWarning, + (bool val) => sharedPreferences.setBool(PreferencesKey.shouldShowRepWarning, val)); + defaultBuyProviders.observe((change) { final String key = 'buyProvider_${change.key.toString()}'; if (change.newValue != null) { @@ -536,6 +540,9 @@ abstract class SettingsStoreBase with Store { @observable bool shouldShowYatPopup; + @observable + bool shouldShowRepWarning; + @observable bool shouldShowMarketPlaceInDashboard; @@ -878,6 +885,8 @@ abstract class SettingsStoreBase with Store { final packageInfo = await PackageInfo.fromPlatform(); final deviceName = await _getDeviceName() ?? ''; final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true; + final shouldShowRepWarning = + sharedPreferences.getBool(PreferencesKey.shouldShowRepWarning) ?? true; final generateSubaddresses = sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey); @@ -1034,75 +1043,77 @@ abstract class SettingsStoreBase with Store { ''; return SettingsStore( - secureStorage: secureStorage, - sharedPreferences: sharedPreferences, - initialShouldShowMarketPlaceInDashboard: shouldShowMarketPlaceInDashboard, - nodes: nodes, - powNodes: powNodes, - appVersion: packageInfo.version, - deviceName: deviceName, - isBitcoinBuyEnabled: isBitcoinBuyEnabled, - initialFiatCurrency: currentFiatCurrency, - initialBalanceDisplayMode: currentBalanceDisplayMode, - initialSaveRecipientAddress: shouldSaveRecipientAddress, - initialAutoGenerateSubaddressStatus: autoGenerateSubaddressStatus, - initialMoneroSeedType: moneroSeedType, - initialAppSecure: isAppSecure, - initialDisableBuy: disableBuy, - initialDisableSell: disableSell, - initialDisableBulletin: disableBulletin, - initialWalletListOrder: walletListOrder, - initialWalletListAscending: walletListAscending, - initialFiatMode: currentFiatApiMode, - initialAllowBiometricalAuthentication: allowBiometricalAuthentication, - initialCake2FAPresetOptions: selectedCake2FAPreset, - initialUseTOTP2FA: useTOTP2FA, - initialTotpSecretKey: totpSecretKey, - initialFailedTokenTrial: tokenTrialNumber, - initialExchangeStatus: exchangeStatus, - initialTheme: savedTheme, - actionlistDisplayMode: actionListDisplayMode, - initialPinLength: pinLength, - pinTimeOutDuration: pinCodeTimeOutDuration, - seedPhraseLength: seedPhraseWordCount, - initialLanguageCode: savedLanguageCode, - sortBalanceBy: sortBalanceBy, - pinNativeTokenAtTop: pinNativeTokenAtTop, - useEtherscan: useEtherscan, - usePolygonScan: usePolygonScan, - defaultNanoRep: defaultNanoRep, - defaultBananoRep: defaultBananoRep, - lookupsTwitter: lookupsTwitter, - lookupsMastodon: lookupsMastodon, - lookupsYatService: lookupsYatService, - lookupsUnstoppableDomains: lookupsUnstoppableDomains, - lookupsOpenAlias: lookupsOpenAlias, - lookupsENS: lookupsENS, - customBitcoinFeeRate: customBitcoinFeeRate, - initialMoneroTransactionPriority: moneroTransactionPriority, - initialBitcoinTransactionPriority: bitcoinTransactionPriority, - initialHavenTransactionPriority: havenTransactionPriority, - initialLitecoinTransactionPriority: litecoinTransactionPriority, - initialBitcoinCashTransactionPriority: bitcoinCashTransactionPriority, - initialShouldRequireTOTP2FAForAccessingWallet: shouldRequireTOTP2FAForAccessingWallet, - initialShouldRequireTOTP2FAForSendsToContact: shouldRequireTOTP2FAForSendsToContact, - initialShouldRequireTOTP2FAForSendsToNonContact: shouldRequireTOTP2FAForSendsToNonContact, - initialShouldRequireTOTP2FAForSendsToInternalWallets: - shouldRequireTOTP2FAForSendsToInternalWallets, - initialShouldRequireTOTP2FAForExchangesToInternalWallets: - shouldRequireTOTP2FAForExchangesToInternalWallets, - initialShouldRequireTOTP2FAForExchangesToExternalWallets: - shouldRequireTOTP2FAForExchangesToExternalWallets, - initialShouldRequireTOTP2FAForAddingContacts: shouldRequireTOTP2FAForAddingContacts, - initialShouldRequireTOTP2FAForCreatingNewWallets: shouldRequireTOTP2FAForCreatingNewWallets, - initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings: - shouldRequireTOTP2FAForAllSecurityAndBackupSettings, - initialEthereumTransactionPriority: ethereumTransactionPriority, - initialPolygonTransactionPriority: polygonTransactionPriority, - backgroundTasks: backgroundTasks, - initialSyncMode: savedSyncMode, - initialSyncAll: savedSyncAll, - shouldShowYatPopup: shouldShowYatPopup); + secureStorage: secureStorage, + sharedPreferences: sharedPreferences, + initialShouldShowMarketPlaceInDashboard: shouldShowMarketPlaceInDashboard, + nodes: nodes, + powNodes: powNodes, + appVersion: packageInfo.version, + deviceName: deviceName, + isBitcoinBuyEnabled: isBitcoinBuyEnabled, + initialFiatCurrency: currentFiatCurrency, + initialBalanceDisplayMode: currentBalanceDisplayMode, + initialSaveRecipientAddress: shouldSaveRecipientAddress, + initialAutoGenerateSubaddressStatus: autoGenerateSubaddressStatus, + initialMoneroSeedType: moneroSeedType, + initialAppSecure: isAppSecure, + initialDisableBuy: disableBuy, + initialDisableSell: disableSell, + initialDisableBulletin: disableBulletin, + initialWalletListOrder: walletListOrder, + initialWalletListAscending: walletListAscending, + initialFiatMode: currentFiatApiMode, + initialAllowBiometricalAuthentication: allowBiometricalAuthentication, + initialCake2FAPresetOptions: selectedCake2FAPreset, + initialUseTOTP2FA: useTOTP2FA, + initialTotpSecretKey: totpSecretKey, + initialFailedTokenTrial: tokenTrialNumber, + initialExchangeStatus: exchangeStatus, + initialTheme: savedTheme, + actionlistDisplayMode: actionListDisplayMode, + initialPinLength: pinLength, + pinTimeOutDuration: pinCodeTimeOutDuration, + seedPhraseLength: seedPhraseWordCount, + initialLanguageCode: savedLanguageCode, + sortBalanceBy: sortBalanceBy, + pinNativeTokenAtTop: pinNativeTokenAtTop, + useEtherscan: useEtherscan, + usePolygonScan: usePolygonScan, + defaultNanoRep: defaultNanoRep, + defaultBananoRep: defaultBananoRep, + lookupsTwitter: lookupsTwitter, + lookupsMastodon: lookupsMastodon, + lookupsYatService: lookupsYatService, + lookupsUnstoppableDomains: lookupsUnstoppableDomains, + lookupsOpenAlias: lookupsOpenAlias, + lookupsENS: lookupsENS, + customBitcoinFeeRate: customBitcoinFeeRate, + initialMoneroTransactionPriority: moneroTransactionPriority, + initialBitcoinTransactionPriority: bitcoinTransactionPriority, + initialHavenTransactionPriority: havenTransactionPriority, + initialLitecoinTransactionPriority: litecoinTransactionPriority, + initialBitcoinCashTransactionPriority: bitcoinCashTransactionPriority, + initialShouldRequireTOTP2FAForAccessingWallet: shouldRequireTOTP2FAForAccessingWallet, + initialShouldRequireTOTP2FAForSendsToContact: shouldRequireTOTP2FAForSendsToContact, + initialShouldRequireTOTP2FAForSendsToNonContact: shouldRequireTOTP2FAForSendsToNonContact, + initialShouldRequireTOTP2FAForSendsToInternalWallets: + shouldRequireTOTP2FAForSendsToInternalWallets, + initialShouldRequireTOTP2FAForExchangesToInternalWallets: + shouldRequireTOTP2FAForExchangesToInternalWallets, + initialShouldRequireTOTP2FAForExchangesToExternalWallets: + shouldRequireTOTP2FAForExchangesToExternalWallets, + initialShouldRequireTOTP2FAForAddingContacts: shouldRequireTOTP2FAForAddingContacts, + initialShouldRequireTOTP2FAForCreatingNewWallets: shouldRequireTOTP2FAForCreatingNewWallets, + initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings: + shouldRequireTOTP2FAForAllSecurityAndBackupSettings, + initialEthereumTransactionPriority: ethereumTransactionPriority, + initialPolygonTransactionPriority: polygonTransactionPriority, + backgroundTasks: backgroundTasks, + initialSyncMode: savedSyncMode, + initialSyncAll: savedSyncAll, + shouldShowYatPopup: shouldShowYatPopup, + shouldShowRepWarning: shouldShowRepWarning, + ); } Future reload({required Box nodeSource}) async { @@ -1198,6 +1209,8 @@ abstract class SettingsStoreBase with Store { languageCode = sharedPreferences.getString(PreferencesKey.currentLanguageCode) ?? languageCode; shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? shouldShowYatPopup; + shouldShowRepWarning = + sharedPreferences.getBool(PreferencesKey.shouldShowRepWarning) ?? shouldShowRepWarning; sortBalanceBy = SortBalanceBy .values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? sortBalanceBy.index]; pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true; diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 66d179523..ef43ddf40 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -11,6 +11,7 @@ import 'package:cake_wallet/entities/service_status.dart'; import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/monero/monero.dart'; +import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/dashboard/orders_store.dart'; @@ -370,6 +371,18 @@ abstract class DashboardViewModelBase with Store { @computed bool get hasPowNodes => wallet.type == WalletType.nano || wallet.type == WalletType.banano; + bool get showRepWarning { + if (wallet.type != WalletType.nano) { + return false; + } + + if (!settingsStore.shouldShowRepWarning) { + return false; + } + + return !nano!.isRepOk(wallet); + } + Future reconnect() async { final node = appStore.settingsStore.getCurrentNode(wallet.type); await wallet.connectToNode(node: node); diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart index e323268a0..283a32cbf 100644 --- a/lib/view_model/node_list/node_create_or_edit_view_model.dart +++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart @@ -12,16 +12,15 @@ import 'package:permission_handler/permission_handler.dart'; part 'node_create_or_edit_view_model.g.dart'; -class NodeCreateOrEditViewModel = NodeCreateOrEditViewModelBase - with _$NodeCreateOrEditViewModel; +class NodeCreateOrEditViewModel = NodeCreateOrEditViewModelBase with _$NodeCreateOrEditViewModel; abstract class NodeCreateOrEditViewModelBase with Store { - NodeCreateOrEditViewModelBase( - this._nodeSource, this._walletType, this._settingsStore) + NodeCreateOrEditViewModelBase(this._nodeSource, this._walletType, this._settingsStore) : state = InitialExecutionState(), connectionState = InitialExecutionState(), useSSL = false, address = '', + path = '', port = '', login = '', password = '', @@ -35,6 +34,9 @@ abstract class NodeCreateOrEditViewModelBase with Store { @observable String address; + @observable + String path; + @observable String port; @@ -84,6 +86,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { @action void reset() { address = ''; + path = ''; port = ''; login = ''; password = ''; @@ -99,6 +102,9 @@ abstract class NodeCreateOrEditViewModelBase with Store { @action void setAddress(String val) => address = val; + @action + void setPath(String val) => path = val; + @action void setLogin(String val) => login = val; @@ -121,6 +127,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { Future save({Node? editingNode, bool saveAsCurrent = false}) async { final node = Node( uri: uri, + path: path, type: _walletType, login: login, password: password, @@ -151,6 +158,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { Future connect() async { final node = Node( uri: uri, + path: path, type: _walletType, login: login, password: password, @@ -183,7 +191,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { Future scanQRCodeForNewNode(BuildContext context) async { try { bool isCameraPermissionGranted = - await PermissionHandler.checkPermission(Permission.camera, context); + await PermissionHandler.checkPermission(Permission.camera, context); if (!isCameraPermissionGranted) return; String code = await presentQRScanner(); @@ -198,7 +206,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { } final userInfo = uri.userInfo.split(':'); - + if (userInfo.length < 2) { throw Exception('Unexpected scan QR code value: Value is invalid'); } @@ -207,8 +215,11 @@ abstract class NodeCreateOrEditViewModelBase with Store { final rpcPassword = userInfo[1]; final ipAddress = uri.host; final port = uri.port.toString(); + final path = uri.path; + setAddress(ipAddress); + setPath(path); setPassword(rpcPassword); setLogin(rpcUser); setPort(port); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 6b3aae14e..f5b2dd5dd 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "يجب أن تكون قيمة المبلغ أكبر من أو تساوي ${minAmount} ${fiatCurrency}", "more_options": "المزيد من الخيارات", "name": "ﻢﺳﺍ", + "nano_current_rep": "الممثل الحالي", + "nano_pick_new_rep": "اختر ممثلًا جديدًا", "narrow": "ضيق", "new_first_wallet_text": "حافظ بسهولة على أمان العملة المشفرة", "new_node_testing": "تجربة العقدة الجديدة", @@ -465,6 +467,8 @@ "remove_node": "إزالة العقدة", "remove_node_message": "هل أنت متأكد أنك تريد إزالة العقدة المحددة؟", "rename": "إعادة تسمية", + "rep_warning": "تحذير تمثيلي", + "rep_warning_sub": "لا يبدو أن ممثلك في وضع جيد. اضغط هنا لاختيار واحدة جديدة", "require_for_adding_contacts": "تتطلب إضافة جهات اتصال", "require_for_all_security_and_backup_settings": "مطلوب لجميع إعدادات الأمان والنسخ الاحتياطي", "require_for_assessing_wallet": "تتطلب الوصول إلى المحفظة", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "تفاصيل العملات الغير المنفقة", "unspent_coins_title": "العملات الغير المنفقة", "unsupported_asset": ".ﻡﻮﻋﺪﻣ ﻞﺻﺃ ﻉﻮﻧ ﻦﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻭﺃ ءﺎﺸﻧﺇ ﻰﺟﺮﻳ .ﻞﺻﻷﺍ ﺍﺬﻬﻟ ءﺍﺮﺟﻹﺍ ﺍﺬﻫ ﻢﻋﺪﻧ ﻻ ﻦﺤﻧ", + "uptime": "مدة التشغيل", "upto": "حتى ${value}", "use": "التبديل إلى", "use_card_info_three": "استخدم البطاقة الرقمية عبر الإنترنت أو مع طرق الدفع غير التلامسية.", @@ -758,6 +763,7 @@ "view_key_private": "مفتاح العرض (خاص)", "view_key_public": "مفتاح العرض (عام)", "view_transaction_on": "عرض العملية على", + "voting_weight": "وزن التصويت", "waitFewSecondForTxUpdate": "ﺕﻼﻣﺎﻌﻤﻟﺍ ﻞﺠﺳ ﻲﻓ ﺔﻠﻣﺎﻌﻤﻟﺍ ﺲﻜﻌﻨﺗ ﻰﺘﺣ ﻥﺍﻮﺛ ﻊﻀﺒﻟ ﺭﺎﻈﺘﻧﻻﺍ ﻰﺟﺮﻳ", "wallet_keys": "سييد المحفظة / المفاتيح", "wallet_list_create_new_wallet": "إنشاء محفظة جديدة", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 30d9945d1..511a04e39 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Сумата трябва да бъде най-малко ${minAmount} ${fiatCurrency}", "more_options": "Още настройки", "name": "Име", + "nano_current_rep": "Настоящ представител", + "nano_pick_new_rep": "Изберете нов представител", "narrow": "Тесен", "new_first_wallet_text": "Лесно пазете криптовалутата си в безопасност", "new_node_testing": "Тестване на нов node", @@ -465,6 +467,8 @@ "remove_node": "Премахни node", "remove_node_message": "Сигурни ли сте, че искате да премахнете избрания node?", "rename": "Промяна на името", + "rep_warning": "Представително предупреждение", + "rep_warning_sub": "Вашият представител изглежда не е в добро състояние. Докоснете тук, за да изберете нов", "require_for_adding_contacts": "Изисква се за добавяне на контакти", "require_for_all_security_and_backup_settings": "Изисква се за всички настройки за сигурност и архивиране", "require_for_assessing_wallet": "Изискване за достъп до портфейла", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Подробности за неизползваните монети", "unspent_coins_title": "Неизползвани монети", "unsupported_asset": "Не поддържаме това действие за този актив. Моля, създайте или преминете към портфейл от поддържан тип актив.", + "uptime": "Време за работа", "upto": "до ${value}", "use": "Смяна на ", "use_card_info_three": "Използвайте дигиталната карта онлайн или чрез безконтактен метод на плащане.", @@ -758,6 +763,7 @@ "view_key_private": "View key (таен)", "view_key_public": "View key (публичен)", "view_transaction_on": "Вижте транзакция на ", + "voting_weight": "Тегло на гласуване", "waitFewSecondForTxUpdate": "Моля, изчакайте няколко секунди, докато транзакцията се отрази в историята на транзакциите", "wallet_keys": "Seed/keys на портфейла", "wallet_list_create_new_wallet": "Създаване на нов портфейл", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 577cd9813..8457de560 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Částka musí být větší nebo rovna ${minAmount} ${fiatCurrency}", "more_options": "Více možností", "name": "název", + "nano_current_rep": "Současný zástupce", + "nano_pick_new_rep": "Vyberte nového zástupce", "narrow": "Úzký", "new_first_wallet_text": "Snadno udržujte svou kryptoměnu v bezpečí", "new_node_testing": "Testování nového uzlu", @@ -465,6 +467,8 @@ "remove_node": "Odstranit uzel", "remove_node_message": "Opravdu chcete odstranit označený uzel?", "rename": "Přejmenovat", + "rep_warning": "Reprezentativní varování", + "rep_warning_sub": "Zdá se, že váš zástupce není v dobrém stavu. Klepnutím zde vyberte nový", "require_for_adding_contacts": "Vyžadovat pro přidání kontaktů", "require_for_all_security_and_backup_settings": "Vyžadovat všechna nastavení zabezpečení a zálohování", "require_for_assessing_wallet": "Vyžadovat pro přístup k peněžence", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Podrobnosti o neutracených mincích", "unspent_coins_title": "Neutracené mince", "unsupported_asset": "Tuto akci u tohoto díla nepodporujeme. Vytvořte nebo přepněte na peněženku podporovaného typu aktiv.", + "uptime": "Uptime", "upto": "až ${value}", "use": "Přepnout na ", "use_card_info_three": "Použijte tuto digitální kartu online nebo bezkontaktními platebními metodami.", @@ -758,6 +763,7 @@ "view_key_private": "Klíč pro zobrazení (soukromý)", "view_key_public": "Klíč pro zobrazení (veřejný)", "view_transaction_on": "Zobrazit transakci na ", + "voting_weight": "Hlasová váha", "waitFewSecondForTxUpdate": "Počkejte několik sekund, než se transakce projeví v historii transakcí", "wallet_keys": "Seed/klíče peněženky", "wallet_list_create_new_wallet": "Vytvořit novou peněženku", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index f0ba70c84..7caf82efa 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Der Wert des Betrags muss größer oder gleich ${minAmount} ${fiatCurrency} sein", "more_options": "Weitere Optionen", "name": "Name", + "nano_current_rep": "Aktueller Vertreter", + "nano_pick_new_rep": "Wählen Sie einen neuen Vertreter aus", "narrow": "Eng", "new_first_wallet_text": "Bewahren Sie Ihre Kryptowährung einfach sicher auf", "new_node_testing": "Neuen Knoten testen", @@ -466,6 +468,8 @@ "remove_node": "Knoten entfernen", "remove_node_message": "Möchten Sie den ausgewählten Knoten wirklich entfernen?", "rename": "Umbenennen", + "rep_warning": "Repräsentative Warnung", + "rep_warning_sub": "Ihr Vertreter scheint nicht gut zu sein. Tippen Sie hier, um eine neue auszuwählen", "require_for_adding_contacts": "Erforderlich zum Hinzufügen von Kontakten", "require_for_all_security_and_backup_settings": "Für alle Sicherheits- und Sicherungseinstellungen erforderlich", "require_for_assessing_wallet": "Für den Zugriff auf die Wallet erforderlich", @@ -744,6 +748,7 @@ "unspent_coins_details_title": "Details zu nicht ausgegebenen Coins", "unspent_coins_title": "Nicht ausgegebene Coins", "unsupported_asset": "Wir unterstützen diese Aktion für dieses Asset nicht. Bitte erstellen Sie eine Wallet eines unterstützten Asset-Typs oder wechseln Sie zu einer Wallet.", + "uptime": "Betriebszeit", "upto": "bis zu ${value}", "use": "Wechsel zu ", "use_card_info_three": "Verwenden Sie die digitale Karte online oder mit kontaktlosen Zahlungsmethoden.", @@ -760,6 +765,7 @@ "view_key_private": "View Key (geheim)", "view_key_public": "View Key (öffentlich)", "view_transaction_on": "Anzeigen der Transaktion auf ", + "voting_weight": "Stimmgewicht", "waitFewSecondForTxUpdate": "Bitte warten Sie einige Sekunden, bis die Transaktion im Transaktionsverlauf angezeigt wird", "waiting_payment_confirmation": "Warte auf Zahlungsbestätigung", "wallet_keys": "Wallet-Seed/-Schlüssel", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index f8bd6b3a2..e75bda358 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Value of the amount must be more or equal to ${minAmount} ${fiatCurrency}", "more_options": "More Options", "name": "Name", + "nano_current_rep": "Current Representative", + "nano_pick_new_rep": "Pick a new representative", "narrow": "Narrow", "new_first_wallet_text": "Keep your crypto safe, piece of cake", "new_node_testing": "New node testing", @@ -465,6 +467,8 @@ "remove_node": "Remove node", "remove_node_message": "Are you sure that you want to remove selected node?", "rename": "Rename", + "rep_warning": "Representative Warning", + "rep_warning_sub": "Your representative does not appear to be in good standing. Tap here to select a new one", "require_for_adding_contacts": "Require for adding contacts", "require_for_all_security_and_backup_settings": "Require for all security and backup settings", "require_for_assessing_wallet": "Require for accessing wallet", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Unspent coins details", "unspent_coins_title": "Unspent coins", "unsupported_asset": "We don't support this action for this asset. Please create or switch to a wallet of a supported asset type.", + "uptime": "Uptime", "upto": "up to ${value}", "use": "Switch to ", "use_card_info_three": "Use the digital card online or with contactless payment methods.", @@ -758,6 +763,7 @@ "view_key_private": "View key (private)", "view_key_public": "View key (public)", "view_transaction_on": "View Transaction on ", + "voting_weight": "Voting Weight", "waitFewSecondForTxUpdate": "Kindly wait for a few seconds for transaction to reflect in transactions history", "wallet_keys": "Wallet seed/keys", "wallet_list_create_new_wallet": "Create New Wallet", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index cf70a2c2d..c8a56bc66 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "El valor de la cantidad debe ser mayor o igual a ${minAmount} ${fiatCurrency}", "more_options": "Más Opciones", "name": "Nombre", + "nano_current_rep": "Representante actual", + "nano_pick_new_rep": "Elija un nuevo representante", "narrow": "Angosto", "new_first_wallet_text": "Mantenga fácilmente su criptomoneda segura", "new_node_testing": "Prueba de nuevos nodos", @@ -466,6 +468,8 @@ "remove_node": "Eliminar nodo", "remove_node_message": "¿Está seguro de que desea eliminar el nodo seleccionado?", "rename": "Rebautizar", + "rep_warning": "Advertencia representativa", + "rep_warning_sub": "Su representante no parece estar en buena posición. Toque aquí para seleccionar uno nuevo", "require_for_adding_contacts": "Requerido para agregar contactos", "require_for_all_security_and_backup_settings": "Requerido para todas las configuraciones de seguridad y copia de seguridad", "require_for_assessing_wallet": "Requerido para acceder a la billetera", @@ -743,6 +747,7 @@ "unspent_coins_details_title": "Detalles de monedas no gastadas", "unspent_coins_title": "Monedas no gastadas", "unsupported_asset": "No admitimos esta acción para este activo. Cree o cambie a una billetera de un tipo de activo admitido.", + "uptime": "Tiempo de actividad", "upto": "hasta ${value}", "use": "Utilizar a ", "use_card_info_three": "Utilice la tarjeta digital en línea o con métodos de pago sin contacto.", @@ -759,6 +764,7 @@ "view_key_private": "View clave (privado)", "view_key_public": "View clave (público)", "view_transaction_on": "View Transaction on ", + "voting_weight": "Peso de votación", "waitFewSecondForTxUpdate": "Espere unos segundos para que la transacción se refleje en el historial de transacciones.", "wallet_keys": "Billetera semilla/claves", "wallet_list_create_new_wallet": "Crear nueva billetera", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index d21e21dae..bbd2bde2b 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Le montant doit être au moins égal à ${minAmount} ${fiatCurrency}", "more_options": "Plus d'options", "name": "Nom", + "nano_current_rep": "Représentant actuel", + "nano_pick_new_rep": "Choisissez un nouveau représentant", "narrow": "Étroit", "new_first_wallet_text": "Gardez facilement votre crypto-monnaie en sécurité", "new_node_testing": "Test du nouveau nœud", @@ -465,6 +467,8 @@ "remove_node": "Supprimer le nœud", "remove_node_message": "Êtes vous certain de vouloir supprimer le nœud sélectionné ?", "rename": "Renommer", + "rep_warning": "Avertissement représentatif", + "rep_warning_sub": "Votre représentant ne semble pas être en règle. Appuyez ici pour en sélectionner un nouveau", "require_for_adding_contacts": "Requis pour ajouter des contacts", "require_for_all_security_and_backup_settings": "Exiger pour tous les paramètres de sécurité et de sauvegarde", "require_for_assessing_wallet": "Nécessaire pour accéder au portefeuille", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Détails des pièces (coins) non dépensées", "unspent_coins_title": "Pièces (coins) non dépensées", "unsupported_asset": "Nous ne prenons pas en charge cette action pour cet élément. Veuillez créer ou passer à un portefeuille d'un type d'actif pris en charge.", + "uptime": "Durée de la baisse", "upto": "jusqu'à ${value}", "use": "Changer vers code PIN à ", "use_card_info_three": "Utilisez la carte numérique en ligne ou avec des méthodes de paiement sans contact.", @@ -758,6 +763,7 @@ "view_key_private": "Clef d'audit (view key) (privée)", "view_key_public": "Clef d'audit (view key) (publique)", "view_transaction_on": "Voir la Transaction sur ", + "voting_weight": "Poids de vote", "waitFewSecondForTxUpdate": "Veuillez attendre quelques secondes pour que la transaction soit reflétée dans l'historique des transactions.", "wallet_keys": "Phrase secrète (seed)/Clefs du portefeuille (wallet)", "wallet_list_create_new_wallet": "Créer un Nouveau Portefeuille (Wallet)", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 35a6be1b8..a38f04fa4 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Darajar adadin dole ne ya zama fiye ko daidai da ${minAmount} ${fiatCurrency}", "more_options": "Ƙarin Zaɓuɓɓuka", "name": "Suna", + "nano_current_rep": "Wakilin Yanzu", + "nano_pick_new_rep": "Dauki sabon wakili", "narrow": "kunkuntar", "new_first_wallet_text": "A sauƙaƙe kiyaye kuzarin ku", "new_node_testing": "Sabbin gwajin kumburi", @@ -467,6 +469,8 @@ "remove_node": "Cire node", "remove_node_message": "Kuna tabbatar kuna so ku cire wannan node?", "rename": "Sake suna", + "rep_warning": "Gargadi Wakilin", + "rep_warning_sub": "Wakilinku bai bayyana ya kasance cikin kyakkyawan yanayi ba. Matsa nan don zaɓar sabon", "require_for_adding_contacts": "Bukatar ƙara lambobin sadarwa", "require_for_all_security_and_backup_settings": "Bukatar duk tsaro da saitunan wariyar ajiya", "require_for_assessing_wallet": "Bukatar samun damar walat", @@ -744,6 +748,7 @@ "unspent_coins_details_title": "Bayanan tsabar kudi da ba a kashe ba", "unspent_coins_title": "Tsabar da ba a kashe ba", "unsupported_asset": "Ba mu goyi bayan wannan aikin don wannan kadara. Da fatan za a ƙirƙira ko canza zuwa walat na nau'in kadara mai tallafi.", + "uptime": "Sama", "upto": "har zuwa ${value}", "use": "Canja zuwa", "use_card_info_three": "Yi amfani da katin dijital akan layi ko tare da hanyoyin biyan kuɗi mara lamba.", @@ -760,6 +765,7 @@ "view_key_private": "Duba maɓallin (maɓallin kalmar sirri)", "view_key_public": "Maɓallin Duba (maɓallin jama'a)", "view_transaction_on": "Dubo aikace-aikacen akan", + "voting_weight": "Nauyi mai nauyi", "waitFewSecondForTxUpdate": "Da fatan za a jira ƴan daƙiƙa don ciniki don yin tunani a tarihin ma'amala", "wallet_keys": "Iri/maɓalli na walat", "wallet_list_create_new_wallet": "Ƙirƙiri Sabon Wallet", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index a6bcab4ab..0131baa8b 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "राशि का मूल्य अधिक है या करने के लिए बराबर होना चाहिए ${minAmount} ${fiatCurrency}", "more_options": "और विकल्प", "name": "नाम", + "nano_current_rep": "वर्तमान प्रतिनिधि", + "nano_pick_new_rep": "एक नया प्रतिनिधि चुनें", "narrow": "सँकरा", "new_first_wallet_text": "आसानी से अपनी क्रिप्टोक्यूरेंसी को सुरक्षित रखें", "new_node_testing": "नई नोड परीक्षण", @@ -467,6 +469,8 @@ "remove_node": "नोड निकालें", "remove_node_message": "क्या आप वाकई चयनित नोड को निकालना चाहते हैं?", "rename": "नाम बदलें", + "rep_warning": "प्रतिनिधि चेतावनी", + "rep_warning_sub": "आपका प्रतिनिधि अच्छी स्थिति में नहीं दिखाई देता है। एक नया चयन करने के लिए यहां टैप करें", "require_for_adding_contacts": "संपर्क जोड़ने के लिए आवश्यकता है", "require_for_all_security_and_backup_settings": "सभी सुरक्षा और बैकअप सेटिंग्स की आवश्यकता है", "require_for_assessing_wallet": "वॉलेट तक पहुँचने के लिए आवश्यकता है", @@ -744,6 +748,7 @@ "unspent_coins_details_title": "अव्ययित सिक्कों का विवरण", "unspent_coins_title": "खर्च न किए गए सिक्के", "unsupported_asset": "हम इस संपत्ति के लिए इस कार्रवाई का समर्थन नहीं करते हैं. कृपया समर्थित परिसंपत्ति प्रकार का वॉलेट बनाएं या उस पर स्विच करें।", + "uptime": "अपटाइम", "upto": "${value} तक", "use": "उपयोग ", "use_card_info_three": "डिजिटल कार्ड का ऑनलाइन या संपर्क रहित भुगतान विधियों के साथ उपयोग करें।", @@ -760,6 +765,7 @@ "view_key_private": "कुंजी देखें(निजी)", "view_key_public": "कुंजी देखें (जनता)", "view_transaction_on": "View Transaction on ", + "voting_weight": "वोटिंग वेट", "waitFewSecondForTxUpdate": "लेन-देन इतिहास में लेन-देन प्रतिबिंबित होने के लिए कृपया कुछ सेकंड प्रतीक्षा करें", "wallet_keys": "बटुआ बीज / चाबियाँ", "wallet_list_create_new_wallet": "नया बटुआ बनाएँ", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index e01857a94..af53376cd 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Vrijednost iznosa mora biti veća ili jednaka ${minAmount} ${fiatCurrency}", "more_options": "Više opcija", "name": "Ime", + "nano_current_rep": "Trenutni predstavnik", + "nano_pick_new_rep": "Odaberite novog predstavnika", "narrow": "Usko", "new_first_wallet_text": "Jednostavno čuvajte svoju kripto valutu", "new_node_testing": "Provjera novog nodea", @@ -465,6 +467,8 @@ "remove_node": "Ukloni node", "remove_node_message": "Jeste li sigurni da želite ukloniti odabrani node?", "rename": "Preimenuj", + "rep_warning": "Reprezentativno upozorenje", + "rep_warning_sub": "Čini se da vaš predstavnik nije u dobrom stanju. Dodirnite ovdje za odabir novog", "require_for_adding_contacts": "Zahtijeva za dodavanje kontakata", "require_for_all_security_and_backup_settings": "Zahtijeva za sve postavke sigurnosti i sigurnosne kopije", "require_for_assessing_wallet": "Potreban za pristup novčaniku", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Nepotrošeni detalji o novčićima", "unspent_coins_title": "Nepotrošeni novčići", "unsupported_asset": "Ne podržavamo ovu radnju za ovaj materijal. Izradite ili prijeđite na novčanik podržane vrste sredstava.", + "uptime": "Radno vrijeme", "upto": "do ${value}", "use": "Prebaci na", "use_card_info_three": "Koristite digitalnu karticu online ili s beskontaktnim metodama plaćanja.", @@ -758,6 +763,7 @@ "view_key_private": "View key (privatni)", "view_key_public": "View key (javni)", "view_transaction_on": "View Transaction on ", + "voting_weight": "Težina glasanja", "waitFewSecondForTxUpdate": "Pričekajte nekoliko sekundi da se transakcija prikaže u povijesti transakcija", "wallet_keys": "Pristupni izraz/ključ novčanika", "wallet_list_create_new_wallet": "Izradi novi novčanik", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index c487a6750..0e0beb57e 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Nilai jumlah harus lebih atau sama dengan ${minAmount} ${fiatCurrency}", "more_options": "Opsi Lainnya", "name": "Nama", + "nano_current_rep": "Perwakilan saat ini", + "nano_pick_new_rep": "Pilih perwakilan baru", "narrow": "Sempit", "new_first_wallet_text": "Dengan mudah menjaga cryptocurrency Anda aman", "new_node_testing": "Pengujian node baru", @@ -467,6 +469,8 @@ "remove_node": "Hapus node", "remove_node_message": "Apakah Anda yakin ingin menghapus node yang dipilih?", "rename": "Ganti nama", + "rep_warning": "Peringatan Perwakilan", + "rep_warning_sub": "Perwakilan Anda tampaknya tidak bereputasi baik. Ketuk di sini untuk memilih yang baru", "require_for_adding_contacts": "Membutuhkan untuk menambahkan kontak", "require_for_all_security_and_backup_settings": "Memerlukan untuk semua pengaturan keamanan dan pencadangan", "require_for_assessing_wallet": "Diperlukan untuk mengakses dompet", @@ -745,6 +749,7 @@ "unspent_coins_details_title": "Rincian koin yang tidak terpakai", "unspent_coins_title": "Koin yang tidak terpakai", "unsupported_asset": "Kami tidak mendukung tindakan ini untuk aset ini. Harap buat atau alihkan ke dompet dari jenis aset yang didukung.", + "uptime": "Uptime", "upto": "hingga ${value}", "use": "Beralih ke ", "use_card_info_three": "Gunakan kartu digital secara online atau dengan metode pembayaran tanpa kontak.", @@ -761,6 +766,7 @@ "view_key_private": "Kunci tampilan (privat)", "view_key_public": "Kunci tampilan (publik)", "view_transaction_on": "Lihat Transaksi di ", + "voting_weight": "Berat voting", "waitFewSecondForTxUpdate": "Mohon tunggu beberapa detik hingga transaksi terlihat di riwayat transaksi", "wallet_keys": "Seed/kunci dompet", "wallet_list_create_new_wallet": "Buat Dompet Baru", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 0af315426..c73fa7080 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -358,6 +358,8 @@ "moonpay_alert_text": "Il valore dell'importo deve essere maggiore o uguale a ${minAmount} ${fiatCurrency}", "more_options": "Altre opzioni", "name": "Nome", + "nano_current_rep": "Rappresentante attuale", + "nano_pick_new_rep": "Scegli un nuovo rappresentante", "narrow": "Stretto", "new_first_wallet_text": "Mantieni facilmente la tua criptovaluta al sicuro", "new_node_testing": "Test novo nodo", @@ -467,6 +469,8 @@ "remove_node": "Rimuovi nodo", "remove_node_message": "Sei sicuro di voler rimuovere il nodo selezionato?", "rename": "Rinomina", + "rep_warning": "Avvertenza rappresentativa", + "rep_warning_sub": "Il tuo rappresentante non sembra essere in regola. Tocca qui per selezionarne uno nuovo", "require_for_adding_contacts": "Richiesto per l'aggiunta di contatti", "require_for_all_security_and_backup_settings": "Richiedi per tutte le impostazioni di sicurezza e backup", "require_for_assessing_wallet": "Richiesto per l'accesso al portafoglio", @@ -744,6 +748,7 @@ "unspent_coins_details_title": "Dettagli sulle monete non spese", "unspent_coins_title": "Monete non spese", "unsupported_asset": "Non supportiamo questa azione per questa risorsa. Crea o passa a un portafoglio di un tipo di asset supportato.", + "uptime": "Uptime", "upto": "fino a ${value}", "use": "Passa a ", "use_card_info_three": "Utilizza la carta digitale online o con metodi di pagamento contactless.", @@ -760,6 +765,7 @@ "view_key_private": "Chiave di visualizzazione (privata)", "view_key_public": "Chiave di visualizzazione (pubblica)", "view_transaction_on": "View Transaction on ", + "voting_weight": "Peso di voto", "waitFewSecondForTxUpdate": "Attendi qualche secondo affinché la transazione venga riflessa nella cronologia delle transazioni", "waiting_payment_confirmation": "In attesa di conferma del pagamento", "wallet_keys": "Seme Portafoglio /chiavi", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index a0b3973b2..65f2642d7 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -358,6 +358,8 @@ "moonpay_alert_text": "金額の値は以上でなければなりません ${minAmount} ${fiatCurrency}", "more_options": "その他のオプション", "name": "名前", + "nano_current_rep": "現在の代表", + "nano_pick_new_rep": "新しい代表者を選びます", "narrow": "狭い", "new_first_wallet_text": "暗号通貨を簡単に安全に保ちます", "new_node_testing": "新しいノードのテスト", @@ -466,6 +468,8 @@ "remove_node": "ノードを削除", "remove_node_message": "選択したノードを削除してもよろしいですか?", "rename": "リネーム", + "rep_warning": "代表的な警告", + "rep_warning_sub": "あなたの代表者は良好な状態ではないようです。ここをタップして、新しいものを選択します", "require_for_adding_contacts": "連絡先の追加に必要", "require_for_all_security_and_backup_settings": "すべてのセキュリティおよびバックアップ設定に必須", "require_for_assessing_wallet": "ウォレットにアクセスするために必要です", @@ -743,6 +747,7 @@ "unspent_coins_details_title": "未使用のコインの詳細", "unspent_coins_title": "未使用のコイン", "unsupported_asset": "このアセットに対するこのアクションはサポートされていません。サポートされているアセットタイプのウォレットを作成するか、ウォレットに切り替えてください。", + "uptime": "稼働時間", "upto": "up up ${value}", "use": "使用する ", "use_card_info_three": "デジタルカードをオンラインまたは非接触型決済方法で使用してください。", @@ -759,6 +764,7 @@ "view_key_private": "ビューキー (プライベート)", "view_key_public": "ビューキー (パブリック)", "view_transaction_on": "View Transaction on ", + "voting_weight": "投票重み", "waitFewSecondForTxUpdate": "取引履歴に取引が反映されるまで数秒お待ちください。", "wallet_keys": "ウォレットシード/キー", "wallet_list_create_new_wallet": "新しいウォレットを作成", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 98bc40e77..e9fab7d6f 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "금액은 다음보다 크거나 같아야합니다 ${minAmount} ${fiatCurrency}", "more_options": "추가 옵션", "name": "이름", + "nano_current_rep": "현재 대표", + "nano_pick_new_rep": "새로운 담당자를 선택하십시오", "narrow": "좁은", "new_first_wallet_text": "cryptocurrency를 쉽게 안전하게 유지하십시오", "new_node_testing": "새로운 노드 테스트", @@ -423,8 +425,8 @@ "placeholder_transactions": "거래가 여기에 표시됩니다", "please_fill_totp": "다른 기기에 있는 8자리 코드를 입력하세요.", "please_make_selection": "아래에서 선택하십시오 지갑 만들기 또는 복구.", - "Please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.", "please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.", + "Please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.", "please_select": "선택 해주세요:", "please_select_backup_file": "백업 파일을 선택하고 백업 암호를 입력하십시오.", "please_try_to_connect_to_another_node": "다른 노드에 연결을 시도하십시오", @@ -466,6 +468,8 @@ "remove_node": "노드 제거", "remove_node_message": "선택한 노드를 제거 하시겠습니까?", "rename": "이름 바꾸기", + "rep_warning": "대표 경고", + "rep_warning_sub": "귀하의 대표는 양호한 상태가 아닌 것 같습니다. 새 것을 선택하려면 여기를 탭하십시오", "require_for_adding_contacts": "연락처 추가에 필요", "require_for_all_security_and_backup_settings": "모든 보안 및 백업 설정에 필요", "require_for_assessing_wallet": "지갑 접근을 위해 필요", @@ -743,6 +747,7 @@ "unspent_coins_details_title": "사용하지 않은 동전 세부 정보", "unspent_coins_title": "사용하지 않은 동전", "unsupported_asset": "이 저작물에 대해 이 작업을 지원하지 않습니다. 지원되는 자산 유형의 지갑을 생성하거나 전환하십시오.", + "uptime": "가동 시간", "upto": "최대 ${value}", "use": "사용하다 ", "use_card_info_three": "디지털 카드를 온라인 또는 비접촉식 결제 수단으로 사용하십시오.", @@ -759,6 +764,7 @@ "view_key_private": "키보기(은밀한)", "view_key_public": "키보기 (공공의)", "view_transaction_on": "View Transaction on ", + "voting_weight": "투표 중량", "waitFewSecondForTxUpdate": "거래 내역에 거래가 반영될 때까지 몇 초 정도 기다려 주세요.", "wallet_keys": "지갑 시드 / 키", "wallet_list_create_new_wallet": "새 월렛 만들기", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 8d846f3d6..fb3832f05 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "ပမာဏ၏တန်ဖိုးသည် ${minAmount} ${fiatCurrency} နှင့် ပိုနေရမည်", "more_options": "နောက်ထပ် ရွေးချယ်စရာများ", "name": "နာမည်", + "nano_current_rep": "လက်ရှိကိုယ်စားလှယ်", + "nano_pick_new_rep": "အသစ်တစ်ခုကိုရွေးပါ", "narrow": "ကျဉ်းသော", "new_first_wallet_text": "သင့်ရဲ့ cryptocurrencrencres ကိုအလွယ်တကူလုံခြုံစွာထားရှိပါ", "new_node_testing": "နှာခေါင်း အသစ်စမ်းသပ်ခြင်း။", @@ -465,6 +467,8 @@ "remove_node": "နှာခေါင်း ကို ဖယ်ရှားပါ။", "remove_node_message": "ရွေးချယ်ထားသော ကုဒ်ကို ဖယ်ရှားလိုသည်မှာ သေချာပါသလား။", "rename": "အမည်ပြောင်းပါ။", + "rep_warning": "ကိုယ်စားလှယ်သတိပေးချက်", + "rep_warning_sub": "သင်၏ကိုယ်စားလှယ်သည်ကောင်းမွန်သောရပ်တည်မှုတွင်မဖြစ်သင့်ပါ။ အသစ်တစ်ခုကိုရွေးချယ်ရန်ဤနေရာတွင်အသာပုတ်ပါ", "require_for_adding_contacts": "အဆက်အသွယ်များထည့်ရန် လိုအပ်သည်။", "require_for_all_security_and_backup_settings": "လုံခြုံရေးနှင့် အရန်ဆက်တင်များအားလုံးအတွက် လိုအပ်ပါသည်။", "require_for_assessing_wallet": "ပိုက်ဆံအိတ်ကို ဝင်သုံးရန် လိုအပ်သည်။", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "အသုံးမဝင်သော အကြွေစေ့အသေးစိတ်များ", "unspent_coins_title": "အသုံးမဝင်သော အကြွေစေ့များ", "unsupported_asset": "ဤပိုင်ဆိုင်မှုအတွက် ဤလုပ်ဆောင်ချက်ကို ကျွန်ုပ်တို့ မပံ့ပိုးပါ။ ကျေးဇူးပြု၍ ပံ့ပိုးပေးထားသော ပိုင်ဆိုင်မှုအမျိုးအစား၏ ပိုက်ဆံအိတ်ကို ဖန်တီးပါ သို့မဟုတ် ပြောင်းပါ။", + "uptime": "အထက်က", "upto": "${value} အထိ", "use": "သို့ပြောင်းပါ။", "use_card_info_three": "ဒစ်ဂျစ်တယ်ကတ်ကို အွန်လိုင်း သို့မဟုတ် ထိတွေ့မှုမဲ့ ငွေပေးချေမှုနည်းလမ်းများဖြင့် အသုံးပြုပါ။", @@ -758,6 +763,7 @@ "view_key_private": "သော့ကိုကြည့်ရန် (သီးသန့်)", "view_key_public": "သော့ကိုကြည့်ရန် (အများပြည်သူ)", "view_transaction_on": "ငွေလွှဲခြင်းကို ဖွင့်ကြည့်ပါ။", + "voting_weight": "မဲပေးအလေးချိန်", "waitFewSecondForTxUpdate": "ငွေပေးငွေယူ မှတ်တမ်းတွင် ရောင်ပြန်ဟပ်ရန် စက္ကန့်အနည်းငယ်စောင့်ပါ။", "wallet_keys": "ပိုက်ဆံအိတ် အစေ့/သော့များ", "wallet_list_create_new_wallet": "Wallet အသစ်ဖန်တီးပါ။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 8b3edee4b..0db2f4ebf 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Waarde van het bedrag moet meer of gelijk zijn aan ${minAmount} ${fiatCurrency}", "more_options": "Meer opties", "name": "Naam", + "nano_current_rep": "Huidige vertegenwoordiger", + "nano_pick_new_rep": "Kies een nieuwe vertegenwoordiger", "narrow": "Smal", "new_first_wallet_text": "Houd uw cryptocurrency gemakkelijk veilig", "new_node_testing": "Nieuwe knooppunttest", @@ -465,6 +467,8 @@ "remove_node": "Knoop verwijderen", "remove_node_message": "Weet u zeker dat u het geselecteerde knooppunt wilt verwijderen?", "rename": "Hernoemen", + "rep_warning": "Representatieve waarschuwing", + "rep_warning_sub": "Uw vertegenwoordiger lijkt niet goed te staan. Tik hier om een ​​nieuwe te selecteren", "require_for_adding_contacts": "Vereist voor het toevoegen van contacten", "require_for_all_security_and_backup_settings": "Vereist voor alle beveiligings- en back-upinstellingen", "require_for_assessing_wallet": "Vereist voor toegang tot portemonnee", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Details van niet-uitgegeven munten", "unspent_coins_title": "Ongebruikte munten", "unsupported_asset": "We ondersteunen deze actie niet voor dit item. Maak of schakel over naar een portemonnee van een ondersteund activatype.", + "uptime": "Uptime", "upto": "tot ${value}", "use": "Gebruik ", "use_card_info_three": "Gebruik de digitale kaart online of met contactloze betaalmethoden.", @@ -758,6 +763,7 @@ "view_key_private": "Bekijk sleutel (privaat)", "view_key_public": "Bekijk sleutel (openbaar)", "view_transaction_on": "View Transaction on ", + "voting_weight": "Stemgewicht", "waitFewSecondForTxUpdate": "Wacht een paar seconden totdat de transactie wordt weergegeven in de transactiegeschiedenis", "waiting_payment_confirmation": "In afwachting van betalingsbevestiging", "wallet_keys": "Portemonnee zaad/sleutels", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 93dafa352..3c5e9024e 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Wartość kwoty musi być większa lub równa ${minAmount} ${fiatCurrency}", "more_options": "Więcej opcji", "name": "Nazwa", + "nano_current_rep": "Obecny przedstawiciel", + "nano_pick_new_rep": "Wybierz nowego przedstawiciela", "narrow": "Wąski", "new_first_wallet_text": "Łatwo zapewnić bezpieczeństwo kryptowalut", "new_node_testing": "Testowanie nowych węzłów", @@ -465,6 +467,8 @@ "remove_node": "Usuń węzeł", "remove_node_message": "Czy na pewno chcesz usunąć wybrany węzeł?", "rename": "Zmień nazwę", + "rep_warning": "Przedstawicielskie ostrzeżenie", + "rep_warning_sub": "Twój przedstawiciel nie wydaje się mieć dobrej opinii. Stuknij tutaj, aby wybrać nowy", "require_for_adding_contacts": "Wymagane do dodania kontaktów", "require_for_all_security_and_backup_settings": "Wymagaj dla wszystkich ustawień zabezpieczeń i kopii zapasowych", "require_for_assessing_wallet": "Wymagaj dostępu do portfela", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Szczegóły niewydanych monet", "unspent_coins_title": "Niewydane monety", "unsupported_asset": "Nie obsługujemy tego działania w przypadku tego zasobu. Utwórz lub przełącz się na portfel obsługiwanego typu aktywów.", + "uptime": "Czas aktu", "upto": "do ${value}", "use": "Użyj ", "use_card_info_three": "Użyj cyfrowej karty online lub za pomocą zbliżeniowych metod płatności.", @@ -758,6 +763,7 @@ "view_key_private": "Prywatny Klucz Wglądu", "view_key_public": "Publiczny Klucz Wglądu", "view_transaction_on": "Zobacz transakcje na ", + "voting_weight": "Waga głosu", "waitFewSecondForTxUpdate": "Poczekaj kilka sekund, aż transakcja zostanie odzwierciedlona w historii transakcji", "wallet_keys": "Klucze portfela", "wallet_list_create_new_wallet": "Utwórz nowy portfel", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index ae07bb177..e8ac0af2e 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -358,6 +358,8 @@ "moonpay_alert_text": "O valor do montante deve ser maior ou igual a ${minAmount} ${fiatCurrency}", "more_options": "Mais opções", "name": "Nome", + "nano_current_rep": "Representante atual", + "nano_pick_new_rep": "Escolha um novo representante", "narrow": "Estreito", "new_first_wallet_text": "Mantenha sua criptomoeda facilmente segura", "new_node_testing": "Teste de novo nó", @@ -467,6 +469,8 @@ "remove_node": "Remover nó", "remove_node_message": "Você realmente deseja remover o nó selecionado?", "rename": "Renomear", + "rep_warning": "Aviso representativo", + "rep_warning_sub": "Seu representante não parece estar em boa posição. Toque aqui para selecionar um novo", "require_for_adding_contacts": "Requer para adicionar contatos", "require_for_all_security_and_backup_settings": "Exigir todas as configurações de segurança e backup", "require_for_assessing_wallet": "Requer para acessar a carteira", @@ -744,6 +748,7 @@ "unspent_coins_details_title": "Detalhes de moedas não gastas", "unspent_coins_title": "Moedas não gastas", "unsupported_asset": "Não oferecemos suporte a esta ação para este recurso. Crie ou mude para uma carteira de um tipo de ativo compatível.", + "uptime": "Tempo de atividade", "upto": "até ${value}", "use": "Use PIN de ", "use_card_info_three": "Use o cartão digital online ou com métodos de pagamento sem contato.", @@ -760,6 +765,7 @@ "view_key_private": "Chave de visualização (privada)", "view_key_public": "Chave de visualização (pública)", "view_transaction_on": "View Transaction on ", + "voting_weight": "Peso de votação", "waitFewSecondForTxUpdate": "Aguarde alguns segundos para que a transação seja refletida no histórico de transações", "waiting_payment_confirmation": "Aguardando confirmação de pagamento", "wallet_keys": "Semente/chaves da carteira", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 5e75631c6..b049ab843 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Сумма должна быть больше или равна ${minAmount} ${fiatCurrency}", "more_options": "Дополнительные параметры", "name": "Имя", + "nano_current_rep": "Нынешний представитель", + "nano_pick_new_rep": "Выберите нового представителя", "narrow": "Узкий", "new_first_wallet_text": "Легко сохранить свою криптовалюту в безопасности", "new_node_testing": "Тестирование новой ноды", @@ -466,6 +468,8 @@ "remove_node": "Удалить ноду", "remove_node_message": "Вы уверены, что хотите удалить текущую ноду?", "rename": "Переименовать", + "rep_warning": "Представительное предупреждение", + "rep_warning_sub": "Ваш представитель, похоже, не в хорошей репутации. Нажмите здесь, чтобы выбрать новый", "require_for_adding_contacts": "Требовать добавления контактов", "require_for_all_security_and_backup_settings": "Требовать все настройки безопасности и резервного копирования", "require_for_assessing_wallet": "Требовать для доступа к кошельку", @@ -743,6 +747,7 @@ "unspent_coins_details_title": "Сведения о неизрасходованных монетах", "unspent_coins_title": "Неизрасходованные монеты", "unsupported_asset": "Мы не поддерживаем это действие для этого объекта. Пожалуйста, создайте или переключитесь на кошелек поддерживаемого типа активов.", + "uptime": "Время безотказной работы", "upto": "до ${value}", "use": "Использовать ", "use_card_info_three": "Используйте цифровую карту онлайн или с помощью бесконтактных способов оплаты.", @@ -759,6 +764,7 @@ "view_key_private": "Приватный ключ просмотра", "view_key_public": "Публичный ключ просмотра", "view_transaction_on": "View Transaction on ", + "voting_weight": "Вес голоса", "waitFewSecondForTxUpdate": "Пожалуйста, подождите несколько секунд, чтобы транзакция отразилась в истории транзакций.", "wallet_keys": "Мнемоническая фраза/ключи кошелька", "wallet_list_create_new_wallet": "Создать новый кошелёк", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index c8183c031..eebcaf4e5 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "มูลค่าของจำนวนต้องมากกว่าหรือเท่ากับ ${minAmount} ${fiatCurrency}", "more_options": "ตัวเลือกเพิ่มเติม", "name": "ชื่อ", + "nano_current_rep": "ตัวแทนปัจจุบัน", + "nano_pick_new_rep": "เลือกตัวแทนใหม่", "narrow": "แคบ", "new_first_wallet_text": "ทำให้สกุลเงินดิจิตอลของคุณปลอดภัยได้อย่างง่ายดาย", "new_node_testing": "การทดสอบโหนดใหม่", @@ -465,6 +467,8 @@ "remove_node": "ลบโหนด", "remove_node_message": "คุณแน่ใจหรือว่าต้องการลบโหนดที่เลือก?", "rename": "เปลี่ยนชื่อ", + "rep_warning": "คำเตือนตัวแทน", + "rep_warning_sub": "ตัวแทนของคุณดูเหมือนจะไม่อยู่ในสถานะที่ดี แตะที่นี่เพื่อเลือกอันใหม่", "require_for_adding_contacts": "ต้องการสำหรับการเพิ่มผู้ติดต่อ", "require_for_all_security_and_backup_settings": "จำเป็นสำหรับการตั้งค่าความปลอดภัยและการสำรองข้อมูลทั้งหมด", "require_for_assessing_wallet": "จำเป็นสำหรับการเข้าถึงกระเป๋าเงิน", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "รายละเอียดเหรียญที่ไม่ได้ใช้", "unspent_coins_title": "เหรียญที่ไม่ได้ใช้", "unsupported_asset": "เราไม่สนับสนุนการกระทำนี้สำหรับเนื้อหานี้ โปรดสร้างหรือเปลี่ยนเป็นกระเป๋าเงินประเภทสินทรัพย์ที่รองรับ", + "uptime": "เวลาทำงาน", "upto": "สูงสุด ${value}", "use": "สลับไปที่ ", "use_card_info_three": "ใช้บัตรดิจิตอลออนไลน์หรือผ่านวิธีการชำระเงินแบบไม่ต้องใช้บัตรกระดาษ", @@ -758,6 +763,7 @@ "view_key_private": "คีย์มุมมอง (ส่วนตัว)", "view_key_public": "คีย์มุมมอง (สาธารณะ)", "view_transaction_on": "ดูการทำธุรกรรมบน ", + "voting_weight": "น้ำหนักโหวต", "waitFewSecondForTxUpdate": "กรุณารอสักครู่เพื่อให้ธุรกรรมปรากฏในประวัติการทำธุรกรรม", "wallet_keys": "ซีดของกระเป๋า/คีย์", "wallet_list_create_new_wallet": "สร้างกระเป๋าใหม่", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index def38820c..1e85e5fb9 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Ang halaga ng halaga ay dapat na higit pa o katumbas ng ${minAmount} ${fiatCurrency}", "more_options": "Higit pang mga pagpipilian", "name": "Pangalan", + "nano_current_rep": "Kasalukuyang kinatawan", + "nano_pick_new_rep": "Pumili ng isang bagong kinatawan", "narrow": "Makitid", "new_first_wallet_text": "Panatilihing ligtas ang iyong crypto, piraso ng cake", "new_node_testing": "Bagong pagsubok sa node", @@ -465,6 +467,8 @@ "remove_node": "Alisin ang node", "remove_node_message": "Sigurado ka bang nais mong alisin ang napiling node?", "rename": "Palitan ang pangalan", + "rep_warning": "Babala ng kinatawan", + "rep_warning_sub": "Ang iyong kinatawan ay hindi lilitaw na nasa mabuting kalagayan. Tapikin dito upang pumili ng bago", "require_for_adding_contacts": "Nangangailangan para sa pagdaragdag ng mga contact", "require_for_all_security_and_backup_settings": "Nangangailangan para sa lahat ng mga setting ng seguridad at backup", "require_for_assessing_wallet": "Nangangailangan para sa pag -access ng pitaka", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Mga Detalye ng Unspent Coins", "unspent_coins_title": "Unspent barya", "unsupported_asset": "Hindi namin sinusuportahan ang pagkilos na ito para sa asset na ito. Mangyaring lumikha o lumipat sa isang pitaka ng isang suportadong uri ng pag -aari.", + "uptime": "Uptime", "upto": "Hanggang sa ${value}", "use": "Lumipat sa", "use_card_info_three": "Gamitin ang digital card online o sa mga pamamaraan ng pagbabayad na walang contact.", @@ -758,6 +763,7 @@ "view_key_private": "Tingnan ang Key (Pribado)", "view_key_public": "Tingnan ang Key (Publiko)", "view_transaction_on": "Tingnan ang transaksyon sa", + "voting_weight": "Bigat ng pagboto", "waitFewSecondForTxUpdate": "Mangyaring maghintay ng ilang segundo para makita ang transaksyon sa history ng mga transaksyon", "wallet_keys": "Mga buto/susi ng pitaka", "wallet_list_create_new_wallet": "Lumikha ng bagong pitaka", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 111ff91f4..73a911671 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Tutar ${minAmount} ${fiatCurrency} miktarına eşit veya daha fazla olmalıdır", "more_options": "Daha Fazla Seçenek", "name": "İsim", + "nano_current_rep": "Mevcut temsilci", + "nano_pick_new_rep": "Yeni bir temsilci seçin", "narrow": "Dar", "new_first_wallet_text": "Kripto para biriminizi kolayca güvende tutun", "new_node_testing": "Yeni düğüm test ediliyor", @@ -465,6 +467,8 @@ "remove_node": "Düğümü kaldır", "remove_node_message": "Seçili düğümü kaldırmak istediğinden emin misin?", "rename": "Yeniden adlandır", + "rep_warning": "Temsilci uyarı", + "rep_warning_sub": "Temsilciniz iyi durumda görünmüyor. Yeni bir tane seçmek için buraya dokunun", "require_for_adding_contacts": "Kişi eklemek için gerekli", "require_for_all_security_and_backup_settings": "Tüm güvenlik ve yedekleme ayarları için iste", "require_for_assessing_wallet": "Cüzdana erişmek için gerekli", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "Harcanmamış koin detayları", "unspent_coins_title": "Harcanmamış koinler", "unsupported_asset": "Bu öğe için bu eylemi desteklemiyoruz. Lütfen desteklenen bir varlık türünde bir cüzdan oluşturun veya cüzdana geçiş yapın.", + "uptime": "Çalışma süresi", "upto": "Şu miktara kadar: ${value}", "use": "Şuna geç: ", "use_card_info_three": "Dijital kartı çevrimiçi olarak veya temassız ödeme yöntemleriyle kullanın.", @@ -758,6 +763,7 @@ "view_key_private": "İzleme anahtarı (özel)", "view_key_public": "İzleme anahtarı (genel)", "view_transaction_on": "İşlemi şurada görüntüle ", + "voting_weight": "Oy kullanma", "waitFewSecondForTxUpdate": "İşlemin işlem geçmişine yansıması için lütfen birkaç saniye bekleyin", "wallet_keys": "Cüzdan tohumu/anahtarları", "wallet_list_create_new_wallet": "Yeni Cüzdan Oluştur", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index a0000418d..c38d2918a 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "Значення суми має бути більшим або дорівнювати ${minAmount} ${fiatCurrency}", "more_options": "Більше параметрів", "name": "Ім'я", + "nano_current_rep": "Поточний представник", + "nano_pick_new_rep": "Виберіть нового представника", "narrow": "вузькі", "new_first_wallet_text": "Легко зберігайте свою криптовалюту в безпеці", "new_node_testing": "Тестування нового вузла", @@ -466,6 +468,8 @@ "remove_node": "Видалити вузол", "remove_node_message": "Ви впевнені, що хочете видалити поточний вузол?", "rename": "Перейменувати", + "rep_warning": "Представницьке попередження", + "rep_warning_sub": "Ваш представник, схоже, не має доброго становища. Торкніться тут, щоб вибрати новий", "require_for_adding_contacts": "Потрібен для додавання контактів", "require_for_all_security_and_backup_settings": "Вимагати всіх налаштувань безпеки та резервного копіювання", "require_for_assessing_wallet": "Потрібен доступ до гаманця", @@ -743,6 +747,7 @@ "unspent_coins_details_title": "Відомості про невитрачені монети", "unspent_coins_title": "Невитрачені монети", "unsupported_asset": "Ми не підтримуємо цю дію для цього ресурсу. Створіть або перейдіть на гаманець підтримуваного типу активів.", + "uptime": "Час роботи", "upto": "до ${value}", "use": "Використати ", "use_card_info_three": "Використовуйте цифрову картку онлайн або за допомогою безконтактних методів оплати.", @@ -759,6 +764,7 @@ "view_key_private": "Приватний ключ перегляду", "view_key_public": "Публічний ключ перегляду", "view_transaction_on": "View Transaction on ", + "voting_weight": "Вага голосування", "waitFewSecondForTxUpdate": "Будь ласка, зачекайте кілька секунд, поки транзакція відобразиться в історії транзакцій", "wallet_keys": "Мнемонічна фраза/ключі гаманця", "wallet_list_create_new_wallet": "Створити новий гаманець", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index a7d4b896d..de9a4eb4c 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "رقم کی قدر ${minAmount} ${fiatCurrency} کے برابر یا زیادہ ہونی چاہیے۔", "more_options": "مزید زرائے", "name": "ﻡﺎﻧ", + "nano_current_rep": "موجودہ نمائندہ", + "nano_pick_new_rep": "ایک نیا نمائندہ منتخب کریں", "narrow": "تنگ", "new_first_wallet_text": "آسانی سے اپنے cryptocurrency محفوظ رکھیں", "new_node_testing": "نیا نوڈ ٹیسٹنگ", @@ -467,6 +469,8 @@ "remove_node": "نوڈ کو ہٹا دیں۔", "remove_node_message": "کیا آپ واقعی منتخب نوڈ کو ہٹانا چاہتے ہیں؟", "rename": "نام تبدیل کریں۔", + "rep_warning": "نمائندہ انتباہ", + "rep_warning_sub": "آپ کا نمائندہ اچھ standing ے مقام پر نہیں دکھائی دیتا ہے۔ نیا منتخب کرنے کے لئے یہاں ٹیپ کریں", "require_for_adding_contacts": "رابطوں کو شامل کرنے کی ضرورت ہے۔", "require_for_all_security_and_backup_settings": "تمام سیکورٹی اور بیک اپ کی ترتیبات کے لیے درکار ہے۔", "require_for_assessing_wallet": "بٹوے تک رسائی کے لیے درکار ہے۔", @@ -744,6 +748,7 @@ "unspent_coins_details_title": "غیر خرچ شدہ سککوں کی تفصیلات", "unspent_coins_title": "غیر خرچ شدہ سکے ۔", "unsupported_asset": "۔ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﺱﺍ ﺎﯾ ﮟﯿﺋﺎﻨﺑ ﺱﺮﭘ ﺎﮐ ﻢﺴﻗ ﯽﮐ ﮧﺛﺎﺛﺍ ﮧﺘﻓﺎﯾ ﻥﻭﺎﻌﺗ ﻡﺮﮐ ﮦﺍﺮﺑ ۔ﮟﯿﮨ ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﺖﯾﺎﻤﺣ ﯽﮐ ﯽﺋﺍﻭﺭﺭﺎﮐ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﮧﺛﺎﺛﺍ ﺱﺍ ﻢﮨ", + "uptime": "اپ ٹائم", "upto": "${value} تک", "use": "تبدیل کرنا", "use_card_info_three": "ڈیجیٹل کارڈ آن لائن یا کنٹیکٹ لیس ادائیگی کے طریقوں کے ساتھ استعمال کریں۔", @@ -760,6 +765,7 @@ "view_key_private": "کلید دیکھیں (نجی)", "view_key_public": "کلید دیکھیں (عوامی)", "view_transaction_on": "لین دین دیکھیں آن", + "voting_weight": "ووٹ کا وزن", "waitFewSecondForTxUpdate": "۔ﮟﯾﺮﮐ ﺭﺎﻈﺘﻧﺍ ﺎﮐ ﮉﻨﮑﯿﺳ ﺪﻨﭼ ﻡﺮﮐ ﮦﺍﺮﺑ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﯽﺳﺎﮑﻋ ﯽﮐ ﻦﯾﺩ ﻦﯿﻟ ﮟﯿﻣ ﺦﯾﺭﺎﺗ ﯽﮐ ﻦ", "wallet_keys": "بٹوے کے بیج / چابیاں", "wallet_list_create_new_wallet": "نیا والیٹ بنائیں", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 9ac033917..9a84c86c4 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -358,6 +358,8 @@ "moonpay_alert_text": "Iye owó kò gbọ́dọ̀ kéré ju ${minAmount} ${fiatCurrency}", "more_options": "Ìyàn àfikún", "name": "Oruko", + "nano_current_rep": "Aṣoju lọwọlọwọ", + "nano_pick_new_rep": "Mu aṣoju tuntun kan", "narrow": "Taara", "new_first_wallet_text": "Ni rọọrun jẹ ki o jẹ ki o jẹ ki o jẹ ki a mu", "new_node_testing": "A ń dán apẹka títun wò", @@ -466,6 +468,8 @@ "remove_node": "Yọ apẹka kúrò", "remove_node_message": "Ṣé ó da yín lójú pé ẹ fẹ́ yọ apẹka lọwọ́ kúrò?", "rename": "Pààrọ̀ orúkọ", + "rep_warning": "Ikilọ aṣoju", + "rep_warning_sub": "Aṣoju rẹ ko han lati wa ni iduro to dara. Fọwọ ba ibi lati yan ọkan titun kan", "require_for_adding_contacts": "Beere fun fifi awọn olubasọrọ kun", "require_for_all_security_and_backup_settings": "Beere fun gbogbo aabo ati awọn eto afẹyinti", "require_for_assessing_wallet": "Beere fun wiwọle si apamọwọ", @@ -743,6 +747,7 @@ "unspent_coins_details_title": "Àwọn owó ẹyọ t'á kò tí ì san", "unspent_coins_title": "Àwọn owó ẹyọ t'á kò tí ì san", "unsupported_asset": "A ko ṣe atilẹyin iṣẹ yii fun dukia yii. Jọwọ ṣẹda tabi yipada si apamọwọ iru dukia atilẹyin.", + "uptime": "Iduro", "upto": "kò tóbi ju ${value}", "use": "Lo", "use_card_info_three": "Ẹ lo káàdí ayélujára lórí wẹ́ẹ̀bù tàbí ẹ lò ó lórí àwọn ẹ̀rọ̀ ìrajà tíwọn kò kò.", @@ -759,6 +764,7 @@ "view_key_private": "Kọ́kọ́rọ́ ìwò (àdáni)", "view_key_public": "Kọ́kọ́rọ́ ìwò (kò àdáni)", "view_transaction_on": "Wo pàṣípààrọ̀ lórí ", + "voting_weight": "Idibo iwuwo", "waitFewSecondForTxUpdate": "Fi inurere duro fun awọn iṣeju diẹ fun idunadura lati ṣe afihan ninu itan-akọọlẹ iṣowo", "wallet_keys": "Hóró/kọ́kọ́rọ́ àpamọ́wọ́", "wallet_list_create_new_wallet": "Ṣe àpamọ́wọ́ títun", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 26bb1b286..1c568174d 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -357,6 +357,8 @@ "moonpay_alert_text": "金额的价值必须大于或等于 ${minAmount} ${fiatCurrency}", "more_options": "更多选项", "name": "姓名", + "nano_current_rep": "当前代表", + "nano_pick_new_rep": "选择新代表", "narrow": "狭窄的", "new_first_wallet_text": "轻松确保您的加密货币安全", "new_node_testing": "新节点测试", @@ -465,6 +467,8 @@ "remove_node": "删除节点", "remove_node_message": "您确定要删除所选节点吗?", "rename": "重命名", + "rep_warning": "代表性警告", + "rep_warning_sub": "您的代表似乎并不信誉良好。点击这里选择一个新的", "require_for_adding_contacts": "需要添加联系人", "require_for_all_security_and_backup_settings": "需要所有安全和备份设置", "require_for_assessing_wallet": "需要访问钱包", @@ -742,6 +746,7 @@ "unspent_coins_details_title": "未使用代幣詳情", "unspent_coins_title": "未使用的硬幣", "unsupported_asset": "我们不支持针对该资产采取此操作。请创建或切换到支持的资产类型的钱包。", + "uptime": "正常运行时间", "upto": "最高 ${value}", "use": "切换使用", "use_card_info_three": "在线使用电子卡或使用非接触式支付方式。", @@ -758,6 +763,7 @@ "view_key_private": "View 密钥(私钥)", "view_key_public": "View 密钥(公钥)", "view_transaction_on": "View Transaction on ", + "voting_weight": "投票权重", "waitFewSecondForTxUpdate": "请等待几秒钟,交易才会反映在交易历史记录中", "wallet_keys": "钱包种子/密钥", "wallet_list_create_new_wallet": "创建新钱包", diff --git a/tool/configure.dart b/tool/configure.dart index 06243e8ab..6ee84d63a 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -795,6 +795,7 @@ import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/output_info.dart'; import 'package:cw_core/nano_account_info_response.dart'; +import 'package:cw_core/n2_node.dart'; import 'package:mobx/mobx.dart'; import 'package:hive/hive.dart'; import 'package:cake_wallet/view_model/send/output.dart'; @@ -853,6 +854,8 @@ abstract class Nano { Future updateTransactions(Object wallet); BigInt getTransactionAmountRaw(TransactionInfo transactionInfo); String getRepresentative(Object wallet); + Future> getN2Reps(Object wallet); + bool isRepOk(Object wallet); } abstract class NanoAccountList { From 1769db1641c37aa6d829bb0270c6d72ed78b3fb8 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Fri, 12 Apr 2024 16:01:21 +0200 Subject: [PATCH 179/241] Generic Fixes (#1373) * Fix exchanges not showing * Fix button text on Monero receive screen * Temp fix for ERC20 and SPL tokens not having raw value * Manually Add Trocador new providers temporarily until API integration * properly handle nullability of n2 node [skip ci] --------- Co-authored-by: tuxsudo --- cw_core/lib/n2_node.dart | 2 +- cw_core/lib/wallet_addresses.dart | 3 ++- .../provider/trocador_exchange_provider.dart | 12 +++++++++++- lib/view_model/send/send_view_model.dart | 8 +++++--- .../wallet_address_list_view_model.dart | 4 ---- scripts/ios/app_env.sh | 4 ++-- 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/cw_core/lib/n2_node.dart b/cw_core/lib/n2_node.dart index 0fad9d1b5..a2eb6e4d3 100644 --- a/cw_core/lib/n2_node.dart +++ b/cw_core/lib/n2_node.dart @@ -14,7 +14,7 @@ class N2Node { String? alias; factory N2Node.fromJson(Map json) => N2Node( - weight: double.tryParse((json['weight'] as num).toString()), + weight: double.tryParse((json['weight'] as num?).toString()), uptime: json['uptime'] as String?, score: json['score'] as int?, account: json['rep_address'] as String?, diff --git a/cw_core/lib/wallet_addresses.dart b/cw_core/lib/wallet_addresses.dart index a2a2a50a3..e987b5d0e 100644 --- a/cw_core/lib/wallet_addresses.dart +++ b/cw_core/lib/wallet_addresses.dart @@ -41,5 +41,6 @@ abstract class WalletAddresses { } } - bool containsAddress(String address) => allAddressesMap.containsKey(address); + bool containsAddress(String address) => + addressesMap.containsKey(address) || allAddressesMap.containsKey(address); } diff --git a/lib/exchange/provider/trocador_exchange_provider.dart b/lib/exchange/provider/trocador_exchange_provider.dart index 326573016..688bf15c9 100644 --- a/lib/exchange/provider/trocador_exchange_provider.dart +++ b/lib/exchange/provider/trocador_exchange_provider.dart @@ -32,7 +32,17 @@ class TrocadorExchangeProvider extends ExchangeProvider { 'Exolix', 'Godex', 'Exch', - 'CoinCraddle' + 'CoinCraddle', + 'Alfacash', + 'LocalMonero', + 'XChange', + 'NeroSwap', + 'Changee', + 'BitcoinVN', + 'EasyBit', + 'WizardSwap', + 'Quantex', + 'SwapSpace', ]; static const List _notSupported = [ diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 28cd0128f..038301db4 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -156,10 +156,10 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor return priority; } - int? getCustomPriorityIndex(List priorities) { if (wallet.type == WalletType.bitcoin) { - final customItem = priorities.firstWhereOrNull((element) => element == bitcoin!.getBitcoinTransactionPriorityCustom()); + final customItem = priorities + .firstWhereOrNull((element) => element == bitcoin!.getBitcoinTransactionPriorityCustom()); return customItem != null ? priorities.indexOf(customItem) : null; } @@ -503,7 +503,9 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor address = output.address; } - if (address.isNotEmpty && !contactAddresses.contains(address)) { + if (address.isNotEmpty && + !contactAddresses.contains(address) && + selectedCryptoCurrency.raw != -1) { return ContactRecord( contactListViewModel.contactSource, Contact( diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index a2aab5251..20980f5f0 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -213,10 +213,6 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo return S.current.addresses; } - if (isAutoGenerateSubaddressEnabled) { - return hasAccounts ? S.current.accounts : S.current.account; - } - return hasAccounts ? S.current.accounts_subaddresses : S.current.addresses; } diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 7e4f214ab..61f690c0b 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -18,8 +18,8 @@ MONERO_COM_BUILD_NUMBER=77 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.15.3" -CAKEWALLET_BUILD_NUMBER=221 +CAKEWALLET_VERSION="4.16.0" +CAKEWALLET_BUILD_NUMBER=226 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" From 953c278f8c168377ead1fb92aeefaea3dfe71feb Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Mon, 15 Apr 2024 23:49:11 +0200 Subject: [PATCH 180/241] Update versions (#1380) --- assets/text/Monerocom_Release_Notes.txt | 4 ++-- assets/text/Release_Notes.txt | 13 +++++++------ scripts/android/app_env.sh | 8 ++++---- scripts/ios/app_env.sh | 8 ++++---- scripts/macos/app_env.sh | 8 ++++---- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index e6aab2dda..09092a8df 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,2 +1,2 @@ -Exchange flow enhancements and fixes -Generic enhancements and bug fixes \ No newline at end of file +UI enhancements +Bug fixes \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index b32cd539d..69a5145c9 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,6 +1,7 @@ -Exchange flow enhancements and fixes -Add MoonPay to Buy options -Add THORChain to Exchange providers -Improve Bitcoin fee calculations -Fixes and enhancements for Solana -Generic enhancements and bug fixes \ No newline at end of file +Add Replace-By-Fee to boost pending Bitcoin transactions +Enable WalletConnect for Solana +WalletConnect Enhancements +Enhancements for ERC-20 tokens and Solana tokens +Enhancements for Nano wallet +UI enhancements +Bug fixes \ No newline at end of file diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 8387c1d1f..ca65345c8 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.12.1" -MONERO_COM_BUILD_NUMBER=80 +MONERO_COM_VERSION="1.12.2" +MONERO_COM_BUILD_NUMBER=81 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.15.3" -CAKEWALLET_BUILD_NUMBER=202 +CAKEWALLET_VERSION="4.15.4" +CAKEWALLET_BUILD_NUMBER=203 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 61f690c0b..b2a92f796 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.12.1" -MONERO_COM_BUILD_NUMBER=77 +MONERO_COM_VERSION="1.12.2" +MONERO_COM_BUILD_NUMBER=78 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.16.0" -CAKEWALLET_BUILD_NUMBER=226 +CAKEWALLET_VERSION="4.15.4" +CAKEWALLET_BUILD_NUMBER=227 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 1242945a6..c600bfffc 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -16,13 +16,13 @@ if [ -n "$1" ]; then fi MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.2.1" -MONERO_COM_BUILD_NUMBER=11 +MONERO_COM_VERSION="1.2.2" +MONERO_COM_BUILD_NUMBER=12 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.8.3" -CAKEWALLET_BUILD_NUMBER=61 +CAKEWALLET_VERSION="1.8.4" +CAKEWALLET_BUILD_NUMBER=62 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From fb9534a0e929ecbd61a52d1294f6e5aef05285e6 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Mon, 15 Apr 2024 15:45:40 -0700 Subject: [PATCH 181/241] service status button updates (#1388) * service status button updates * small fix * update wording --- lib/src/screens/dashboard/dashboard_page.dart | 8 +++--- .../desktop_sidebar_wrapper.dart | 5 +++- lib/src/widgets/services_updates_widget.dart | 27 ++++++++++++++++++- 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_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_yo.arb | 2 ++ res/values/strings_zh.arb | 2 ++ 29 files changed, 86 insertions(+), 6 deletions(-) diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index ed06f4704..820e94928 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -106,10 +106,10 @@ class _DashboardPageView extends BasePage { Widget leading(BuildContext context) { return Observer( builder: (context) { - if (dashboardViewModel.isEnabledBulletinAction) { - return ServicesUpdatesWidget(dashboardViewModel.getServicesStatus()); - } - return const SizedBox(); + return ServicesUpdatesWidget( + dashboardViewModel.getServicesStatus(), + enabled: dashboardViewModel.isEnabledBulletinAction, + ); }, ); } diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart index d0ddb19e6..7ba169154 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart @@ -107,7 +107,10 @@ class DesktopSidebarWrapper extends BasePage { : unselectedIconPath, ), SideMenuItem( - widget: ServicesUpdatesWidget(dashboardViewModel.getServicesStatus()), + widget: ServicesUpdatesWidget( + dashboardViewModel.getServicesStatus(), + enabled: dashboardViewModel.isEnabledBulletinAction, + ), isSelected: desktopSidebarViewModel.currentPage == SidebarItem.status, onTap: () {}, ), diff --git a/lib/src/widgets/services_updates_widget.dart b/lib/src/widgets/services_updates_widget.dart index d094caf7f..5d56e967d 100644 --- a/lib/src/widgets/services_updates_widget.dart +++ b/lib/src/widgets/services_updates_widget.dart @@ -1,10 +1,13 @@ import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/service_status.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/service_status_tile.dart'; import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -12,8 +15,9 @@ import 'package:url_launcher/url_launcher.dart'; class ServicesUpdatesWidget extends StatefulWidget { final Future servicesResponse; + final bool enabled; - const ServicesUpdatesWidget(this.servicesResponse, {super.key}); + const ServicesUpdatesWidget(this.servicesResponse, {super.key, required this.enabled}); @override State createState() => _ServicesUpdatesWidgetState(); @@ -24,6 +28,27 @@ class _ServicesUpdatesWidgetState extends State { @override Widget build(BuildContext context) { + if (!widget.enabled) { + return InkWell( + onTap: () async { + await showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: S.current.service_health_disabled, + alertContent: S.current.service_health_disabled_message, + buttonText: S.current.ok, + buttonAction: () => Navigator.of(context).pop(), + ); + }); + }, + child: SvgPicture.asset( + "assets/images/notification_icon.svg", + color: Theme.of(context).extension()!.pageTitleTextColor, + width: 30, + ), + ); + } return Padding( padding: const EdgeInsets.all(8.0), child: FutureBuilder( diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index f5b2dd5dd..15b9712fc 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -583,6 +583,8 @@ "send_your_wallet": "محفظتك", "sending": "يتم الإرسال", "sent": "تم الأرسال", + "service_health_disabled": "تم تعطيل نشرة صحة الخدمة", + "service_health_disabled_message": "هذه هي صفحة نشرة صحة الخدمة ، يمكنك تمكين هذه الصفحة ضمن الإعدادات -> الخصوصية", "settings": "إعدادات", "settings_all": "الكل", "settings_allow_biometrical_authentication": "السماح بالمصادقة البيومترية", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 511a04e39..d479bd57d 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -583,6 +583,8 @@ "send_your_wallet": "Вашият портфейл", "sending": "Изпращане", "sent": "Изпратени", + "service_health_disabled": "Service Health Bulletin е деактивиран", + "service_health_disabled_message": "Това е страницата на Bulletin на Service Health, можете да активирате тази страница в Настройки -> Поверителност", "settings": "Настройки", "settings_all": "Всичко", "settings_allow_biometrical_authentication": "Позволяване на биометрично удостоверяване.", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 8457de560..547c926af 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -583,6 +583,8 @@ "send_your_wallet": "Vaše peněženka", "sending": "Odesílání", "sent": "Odesláno", + "service_health_disabled": "Bulletin zdraví služeb je deaktivován", + "service_health_disabled_message": "Toto je stránka Bulletin Service Health Bulletin, můžete tuto stránku povolit v rámci nastavení -> Ochrana osobních údajů", "settings": "Nastavení", "settings_all": "VŠE", "settings_allow_biometrical_authentication": "Povolit biometrické ověření", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 7caf82efa..97f2ccdc2 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -584,6 +584,8 @@ "send_your_wallet": "Ihre Wallet", "sending": "Senden", "sent": "Versendet", + "service_health_disabled": "Service Health Bulletin ist behindert", + "service_health_disabled_message": "Dies ist die Seite \"Service Health Bulletin\", können Sie diese Seite unter Einstellungen -> Privatsphäre aktivieren", "settings": "Einstellungen", "settings_all": "ALLE", "settings_allow_biometrical_authentication": "Biometrische Authentifizierung zulassen", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index e75bda358..60de404fd 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -583,6 +583,8 @@ "send_your_wallet": "Your wallet", "sending": "Sending", "sent": "Sent", + "service_health_disabled": "Service Health Bulletin is disabled", + "service_health_disabled_message": "This is the service health bulletin page, you can enable this page under Settings -> Privacy", "settings": "Settings", "settings_all": "ALL", "settings_allow_biometrical_authentication": "Allow biometrical authentication", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index c8a56bc66..60cac3a8c 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -584,6 +584,8 @@ "send_your_wallet": "Tu billetera", "sending": "Enviando", "sent": "Expedido", + "service_health_disabled": "El boletín de salud del servicio está deshabilitado", + "service_health_disabled_message": "Esta es la página del Boletín de Salud del Servicio, puede habilitar esta página en Configuración -> Privacidad", "settings": "Configuraciones", "settings_all": "TODOS", "settings_allow_biometrical_authentication": "Permitir autenticación biométrica", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index bbd2bde2b..691c481c1 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -583,6 +583,8 @@ "send_your_wallet": "Votre portefeuille (wallet)", "sending": "Envoi", "sent": "Envoyés", + "service_health_disabled": "Le bulletin de santé du service est handicapé", + "service_health_disabled_message": "Ceci est la page du Bulletin de santé du service, vous pouvez activer cette page sous Paramètres -> Confidentialité", "settings": "Paramètres", "settings_all": "TOUT", "settings_allow_biometrical_authentication": "Autoriser l'authentification biométrique", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index a38f04fa4..f310f67f3 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -585,6 +585,8 @@ "send_your_wallet": "Walat ɗin ku", "sending": "Aika", "sent": "Aika", + "service_health_disabled": "Ba a kashe Bayar da Kiwon Lafiya", + "service_health_disabled_message": "Wannan shafin yanar gizo mai kula da sabis ne, zaka iya kunna wannan shafin a karkashin saiti -> Sirri", "settings": "Saiti", "settings_all": "DUK", "settings_allow_biometrical_authentication": "Bada izinin tantance sawun yatsa", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 0131baa8b..671c7a765 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -585,6 +585,8 @@ "send_your_wallet": "आपका बटुआ", "sending": "भेजना", "sent": "भेज दिया", + "service_health_disabled": "सेवा स्वास्थ्य बुलेटिन अक्षम है", + "service_health_disabled_message": "यह सेवा स्वास्थ्य बुलेटिन पृष्ठ है, आप इस पृष्ठ को सेटिंग्स के तहत सक्षम कर सकते हैं -> गोपनीयता", "settings": "समायोजन", "settings_all": "सब", "settings_allow_biometrical_authentication": "बायोमेट्रिक प्रमाणीकरण की अनुमति दें", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index af53376cd..67e25d59a 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -583,6 +583,8 @@ "send_your_wallet": "Tvoj novčanik", "sending": "Slanje", "sent": "Poslano", + "service_health_disabled": "Zdravstveni bilten usluge je onemogućen", + "service_health_disabled_message": "Ovo je stranica zdravstvenog biltena o usluzi, možete omogućiti ovu stranicu pod postavkama -> privatnost", "settings": "Postavke", "settings_all": "SVE", "settings_allow_biometrical_authentication": "Dopusti biometrijsku autentifikaciju", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 0e0beb57e..cca6f9b2a 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -586,6 +586,8 @@ "send_your_wallet": "Dompetmu", "sending": "Mengirim", "sent": "Dikirim", + "service_health_disabled": "Buletin Kesehatan Layanan dinonaktifkan", + "service_health_disabled_message": "Ini adalah halaman Buletin Kesehatan Layanan, Anda dapat mengaktifkan halaman ini di bawah Pengaturan -> Privasi", "settings": "Pengaturan", "settings_all": "SEMUA", "settings_allow_biometrical_authentication": "Izinkan otentikasi biometrik", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index c73fa7080..4e04c0498 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -585,6 +585,8 @@ "send_your_wallet": "Il tuo portafoglio", "sending": "Invio", "sent": "Inviato", + "service_health_disabled": "Il Bollettino sanitario di servizio è disabilitato", + "service_health_disabled_message": "Questa è la pagina del Bollettino sanitario del servizio, è possibile abilitare questa pagina in Impostazioni -> Privacy", "settings": "Impostazioni", "settings_all": "TUTTO", "settings_allow_biometrical_authentication": "Consenti autenticazione biometrica", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 65f2642d7..b3aa527d6 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -584,6 +584,8 @@ "send_your_wallet": "あなたの財布", "sending": "送信", "sent": "送信済み", + "service_health_disabled": "サービスヘルス速報は無効です", + "service_health_disabled_message": "これはService Health Bulletinページです。設定の下でこのページを有効にすることができます - >プライバシー", "settings": "設定", "settings_all": "すべて", "settings_allow_biometrical_authentication": "生体認証を許可する", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index e9fab7d6f..6c5800614 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -584,6 +584,8 @@ "send_your_wallet": "지갑", "sending": "배상", "sent": "보냄", + "service_health_disabled": "서비스 건강 게시판이 장애가되었습니다", + "service_health_disabled_message": "이것은 서비스 건강 게시판 페이지입니다. 설정 에서이 페이지를 활성화 할 수 있습니다 -> 개인 정보", "settings": "설정", "settings_all": "모든", "settings_allow_biometrical_authentication": "생체 인증 허용", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index fb3832f05..96f141eae 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -583,6 +583,8 @@ "send_your_wallet": "သင့်ပိုက်ဆံအိတ်", "sending": "ပေးပို့ခြင်း။", "sent": "ပို့လိုက်ပါတယ်။", + "service_health_disabled": "ဝန်ဆောင်မှုကျန်းမာရေးစာစောင်အားပိတ်ထားသည်", + "service_health_disabled_message": "ဤသည်မှာ 0 န်ဆောင်မှုကျန်းမာရေးစာစောင်စာမျက်နှာတွင်ဤစာမျက်နှာကို Settings အောက်တွင်ဖွင့်ထားနိုင်သည်", "settings": "ဆက်တင်များ", "settings_all": "အားလုံး", "settings_allow_biometrical_authentication": "ဇီဝဗေဒဆိုင်ရာ အထောက်အထားစိစစ်ခြင်းကို ခွင့်ပြုပါ။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 0db2f4ebf..1ce17f706 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -583,6 +583,8 @@ "send_your_wallet": "Uw portemonnee", "sending": "Bezig met verzenden", "sent": "Verzonden", + "service_health_disabled": "Service Health Bulletin is uitgeschakeld", + "service_health_disabled_message": "Dit is de Service Health Bulletin -pagina, u kunt deze pagina instellingen inschakelen -> Privacy", "settings": "Instellingen", "settings_all": "ALLE", "settings_allow_biometrical_authentication": "Biometrische authenticatie toestaan", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 3c5e9024e..f48ad5dde 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -583,6 +583,8 @@ "send_your_wallet": "Twój portfel", "sending": "Wysyłanie", "sent": "Wysłano", + "service_health_disabled": "Biuletyn zdrowia usług jest wyłączony", + "service_health_disabled_message": "To jest strona Biuletynu Zdrowie Service, możesz włączyć tę stronę w Ustawieniach -> Prywatność", "settings": "Ustawienia", "settings_all": "Wszystkie", "settings_allow_biometrical_authentication": "Zezwalaj na uwierzytelnianie biometryczne", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index e8ac0af2e..15cc9f01e 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -585,6 +585,8 @@ "send_your_wallet": "Sua carteira", "sending": "Enviando", "sent": "Enviada", + "service_health_disabled": "O Boletim de Saúde de Serviço está desativado", + "service_health_disabled_message": "Esta é a página do Boletim de Saúde de Serviço, você pode ativar esta página em Configurações -> Privacidade", "settings": "Configurações", "settings_all": "Tudo", "settings_allow_biometrical_authentication": "Permitir autenticação biométrica", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index b049ab843..ac0fac2ba 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -584,6 +584,8 @@ "send_your_wallet": "Ваш кошелёк", "sending": "Отправка", "sent": "Отправленные", + "service_health_disabled": "Бюллетень для здоровья обслуживания инвалид", + "service_health_disabled_message": "Это страница бюллетени обслуживания услуг, вы можете включить эту страницу в соответствии с настройками -> Конфиденциальность", "settings": "Настройки", "settings_all": "ВСЕ", "settings_allow_biometrical_authentication": "Включить биометрическую аутентификацию", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index eebcaf4e5..7030f6f7f 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -583,6 +583,8 @@ "send_your_wallet": "กระเป๋าของคุณ", "sending": "กำลังส่ง", "sent": "ส่ง", + "service_health_disabled": "Service Health Bulletin ถูกปิดใช้งาน", + "service_health_disabled_message": "นี่คือหน้า Service Health Bulletin คุณสามารถเปิดใช้งานหน้านี้ภายใต้การตั้งค่า -> ความเป็นส่วนตัว", "settings": "การตั้งค่า", "settings_all": "ทั้งหมด", "settings_allow_biometrical_authentication": "อนุญาตให้ใช้การยืนยันตัวตนทางระบบชีวภาพ", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 1e85e5fb9..05a363bac 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -583,6 +583,8 @@ "send_your_wallet": "Iyong pitaka", "sending": "Pagpapadala", "sent": "Ipinadala", + "service_health_disabled": "Hindi pinagana ang Bulletin ng Serbisyo sa Kalusugan", + "service_health_disabled_message": "Ito ang pahina ng Bulletin ng Serbisyo ng Bulletin, maaari mong paganahin ang pahinang ito sa ilalim ng Mga Setting -> Pagkapribado", "settings": "Mga setting", "settings_all": "Lahat", "settings_allow_biometrical_authentication": "Payagan ang pagpapatunay ng biometrical", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 73a911671..ce342df2f 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -583,6 +583,8 @@ "send_your_wallet": "Cüzdanın", "sending": "Gönderiliyor", "sent": "Gönderildi", + "service_health_disabled": "Service Health Bülten devre dışı bırakıldı", + "service_health_disabled_message": "Bu Hizmet Sağlığı Bülten Sayfası, bu sayfayı Ayarlar -> Gizlilik altında etkinleştirebilirsiniz", "settings": "ayarlar", "settings_all": "HEPSİ", "settings_allow_biometrical_authentication": "Biyometrik doğrulamaya izin ver", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index c38d2918a..4afd47fe2 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -584,6 +584,8 @@ "send_your_wallet": "Ваш гаманець", "sending": "Відправлення", "sent": "Відправлені", + "service_health_disabled": "Вісник охорони здоров'я інвалідів", + "service_health_disabled_message": "Це сторінка бюлетеня Health Service, ви можете включити цю сторінку в налаштуваннях -> конфіденційність", "settings": "Налаштування", "settings_all": "ВСІ", "settings_allow_biometrical_authentication": "Включити біометричну аутентифікацію", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index de9a4eb4c..fac066ace 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -585,6 +585,8 @@ "send_your_wallet": "آپ کا بٹوہ", "sending": "بھیج رہا ہے۔", "sent": "بھیجا", + "service_health_disabled": "سروس ہیلتھ بلیٹن غیر فعال ہے", + "service_health_disabled_message": "یہ سروس ہیلتھ بلیٹن پیج ہے ، آپ اس صفحے کو ترتیبات کے تحت اہل بنا سکتے ہیں -> رازداری", "settings": "ترتیبات", "settings_all": "تمام", "settings_allow_biometrical_authentication": "بایومیٹریکل تصدیق کی اجازت دیں۔", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 9a84c86c4..1f131f3d9 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -584,6 +584,8 @@ "send_your_wallet": "Àpamọ́wọ́ yín", "sending": "Ó ń ránṣẹ́", "sent": "Owó t'á ti ránṣẹ́", + "service_health_disabled": "IPỌRỌ IWE TI AGBARA TI O LE RẸ", + "service_health_disabled_message": "Eyi ni oju-iwe Iwe itẹlera Iṣẹ Ile-iṣẹ Iṣẹ: O le mu oju-iwe yii ṣiṣẹ labẹ Eto -> Asiri", "settings": "Awọn aseṣe", "settings_all": "Gbogbo", "settings_allow_biometrical_authentication": "Fi àyè gba ìfẹ̀rílàdí biometrical", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 1c568174d..10d11b2c0 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -583,6 +583,8 @@ "send_your_wallet": "你的钱包", "sending": "正在发送", "sent": "已发送", + "service_health_disabled": "服务健康公告被禁用", + "service_health_disabled_message": "这是服务健康公告页面,您可以在设置 - >隐私下启用此页面", "settings": "设置", "settings_all": "全部", "settings_allow_biometrical_authentication": "允许生物识别认证", From a0820e8a7358fb25d304979fba1d9cfe0519925a Mon Sep 17 00:00:00 2001 From: Serhii Date: Tue, 16 Apr 2024 02:04:49 +0300 Subject: [PATCH 182/241] pull to refresh (#1389) --- lib/src/screens/dashboard/dashboard_page.dart | 21 ++++++++++++++----- .../dashboard/dashboard_view_model.dart | 4 ++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index 820e94928..52a4d8f61 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -51,14 +51,25 @@ class DashboardPage extends StatelessWidget { @override Widget build(BuildContext context) { + final screenHeight = MediaQuery.of(context).size.height; return Scaffold( body: Observer( builder: (_) { - final dashboardPageView = _DashboardPageView( - balancePage: balancePage, - bottomSheetService: bottomSheetService, - dashboardViewModel: dashboardViewModel, - addressListViewModel: addressListViewModel, + final dashboardPageView = RefreshIndicator( + displacement: screenHeight * 0.1, + onRefresh: () async => await dashboardViewModel.refreshDashboard(), + child: SingleChildScrollView( + physics: AlwaysScrollableScrollPhysics(), + child: Container( + height: screenHeight, + child: _DashboardPageView( + balancePage: balancePage, + bottomSheetService: bottomSheetService, + dashboardViewModel: dashboardViewModel, + addressListViewModel: addressListViewModel, + ), + ), + ), ); if (DeviceInfo.instance.isDesktop) { diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index ef43ddf40..ef521c311 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -547,4 +547,8 @@ abstract class DashboardViewModelBase with Store { return ServicesResponse([], false, ''); } } + + Future refreshDashboard() async { + reconnect(); + } } From 59d44e8c57e03180a694be303f22454d8df42fa2 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Tue, 16 Apr 2024 01:49:49 +0200 Subject: [PATCH 183/241] Generic enhancements (#1386) * Update versions * Show private key for electrum based wallets * update polyseed * fix webview page on desktop remove private keys temporarily from electrum * update versions --- .../dashboard/pages/transactions_page.dart | 18 +++++++++++++----- lib/view_model/wallet_keys_view_model.dart | 9 +++++++++ pubspec_base.yaml | 2 +- scripts/android/app_env.sh | 4 ++-- scripts/ios/app_env.sh | 4 ++-- scripts/macos/app_env.sh | 4 ++-- 6 files changed, 29 insertions(+), 12 deletions(-) diff --git a/lib/src/screens/dashboard/pages/transactions_page.dart b/lib/src/screens/dashboard/pages/transactions_page.dart index c983b1c37..4691fa0ca 100644 --- a/lib/src/screens/dashboard/pages/transactions_page.dart +++ b/lib/src/screens/dashboard/pages/transactions_page.dart @@ -2,6 +2,7 @@ import 'package:cake_wallet/src/screens/dashboard/widgets/anonpay_transaction_ro import 'package:cake_wallet/src/screens/dashboard/widgets/order_row.dart'; import 'package:cake_wallet/themes/extensions/placeholder_theme.dart'; import 'package:cake_wallet/src/widgets/dashboard_card_widget.dart'; +import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.dart'; import 'package:cake_wallet/view_model/dashboard/order_list_item.dart'; @@ -20,6 +21,7 @@ import 'package:cake_wallet/view_model/dashboard/date_section_item.dart'; import 'package:intl/intl.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:url_launcher/url_launcher.dart'; class TransactionsPage extends StatelessWidget { TransactionsPage({required this.dashboardViewModel}); @@ -46,11 +48,17 @@ class TransactionsPage extends StatelessWidget { return Padding( padding: const EdgeInsets.fromLTRB(24, 0, 24, 8), child: DashBoardRoundedCardWidget( - onTap: () => Navigator.of(context).pushNamed(Routes.webViewPage, arguments: [ - '', - Uri.parse( - 'https://guides.cakewallet.com/docs/FAQ/why_are_my_funds_not_appearing/') - ]), + onTap: () { + try { + final uri = Uri.parse( + "https://guides.cakewallet.com/docs/FAQ/why_are_my_funds_not_appearing/"); + if (DeviceInfo.instance.isMobile) { + Navigator.of(context).pushNamed(Routes.webViewPage, arguments: ['', uri]); + } else { + launchUrl(uri); + } + } catch (_) {} + }, title: S.of(context).syncing_wallet_alert_title, subTitle: S.of(context).syncing_wallet_alert_content, ), diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart index d88316a04..c33c85504 100644 --- a/lib/view_model/wallet_keys_view_model.dart +++ b/lib/view_model/wallet_keys_view_model.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cw_core/transaction_direction.dart'; @@ -103,7 +104,15 @@ abstract class WalletKeysViewModelBase with Store { if (_appStore.wallet!.type == WalletType.bitcoin || _appStore.wallet!.type == WalletType.litecoin || _appStore.wallet!.type == WalletType.bitcoinCash) { + // final keys = bitcoin!.getWalletKeys(_appStore.wallet!); + items.addAll([ + // if (keys['wif'] != null) + // StandartListItem(title: "WIF", value: keys['wif']!), + // if (keys['privateKey'] != null) + // StandartListItem(title: S.current.private_key, value: keys['privateKey']!), + // if (keys['publicKey'] != null) + // StandartListItem(title: S.current.public_key, value: keys['publicKey']!), StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!), ]); } diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 0293df1d1..3ec3e7978 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -104,7 +104,7 @@ dependencies: # ref: main socks5_proxy: ^1.0.4 flutter_svg: ^2.0.9 - polyseed: ^0.0.2 + polyseed: ^0.0.4 nostr_tools: ^1.0.9 solana: ^0.30.1 bitcoin_base: diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index ca65345c8..c55be8900 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -16,14 +16,14 @@ APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" MONERO_COM_VERSION="1.12.2" -MONERO_COM_BUILD_NUMBER=81 +MONERO_COM_BUILD_NUMBER=82 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="4.15.4" -CAKEWALLET_BUILD_NUMBER=203 +CAKEWALLET_BUILD_NUMBER=204 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index b2a92f796..b9dc0e435 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -14,12 +14,12 @@ APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" MONERO_COM_VERSION="1.12.2" -MONERO_COM_BUILD_NUMBER=78 +MONERO_COM_BUILD_NUMBER=79 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="4.15.4" -CAKEWALLET_BUILD_NUMBER=227 +CAKEWALLET_BUILD_NUMBER=228 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index c600bfffc..42708f3e3 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -17,12 +17,12 @@ fi MONERO_COM_NAME="Monero.com" MONERO_COM_VERSION="1.2.2" -MONERO_COM_BUILD_NUMBER=12 +MONERO_COM_BUILD_NUMBER=13 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_VERSION="1.8.4" -CAKEWALLET_BUILD_NUMBER=62 +CAKEWALLET_BUILD_NUMBER=63 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From e6b4b08c24c1c2fb6987dcca233a3fee67c50d25 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Thu, 18 Apr 2024 10:00:24 -0700 Subject: [PATCH 184/241] version bump to 3.13.9, auth working on mac (#1367) * version bump to 3.13.9, auth working on mac * bump flutter version in workflow file * workflow fix * test fix * downgrade flutter version * test fix * test fix * update gradle version * fixes for updated dart version, localization file updates * remove accidental inclusion * missed some unimplemented throws --- .github/workflows/pr_test_build.yml | 2 +- android/build.gradle | 2 +- cw_bitcoin/pubspec.yaml | 5 +- cw_bitcoin_cash/pubspec.yaml | 5 +- cw_core/pubspec.yaml | 5 +- cw_ethereum/pubspec.yaml | 6 +- cw_evm/pubspec.yaml | 5 +- cw_haven/pubspec.yaml | 5 +- cw_monero/pubspec.yaml | 5 +- cw_nano/pubspec.yaml | 5 +- cw_polygon/pubspec.yaml | 5 +- cw_solana/pubspec.yaml | 5 +- lib/entities/biometric_auth.dart | 26 +- lib/locales/hausa_intl.dart | 64 ++ lib/locales/yoruba_intl.dart | 937 ++++++++++-------- .../settings/security_backup_page.dart | 4 +- lib/src/screens/settings/tor_page.dart | 4 +- .../validable_annotated_editable_text.dart | 14 +- lib/view_model/auth_view_model.dart | 15 +- pubspec_base.yaml | 2 +- pubspec_description.yaml | 2 +- 21 files changed, 642 insertions(+), 481 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index dc231df42..bfa378342 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -42,7 +42,7 @@ jobs: - name: Flutter action uses: subosito/flutter-action@v1 with: - flutter-version: "3.10.x" + flutter-version: "3.13.9" channel: stable - name: Install package dependencies diff --git a/android/build.gradle b/android/build.gradle index 8286d9cb9..e182e39af 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.7.10' + ext.kotlin_version = '1.8.10' repositories { google() jcenter() diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index 632a3140a..1ccdb70c9 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -39,11 +39,14 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_bitcoin_cash/pubspec.yaml b/cw_bitcoin_cash/pubspec.yaml index 37827f1ba..ceef539c3 100644 --- a/cw_bitcoin_cash/pubspec.yaml +++ b/cw_bitcoin_cash/pubspec.yaml @@ -39,10 +39,13 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml index 04a840d4e..51d671dc7 100644 --- a/cw_core/pubspec.yaml +++ b/cw_core/pubspec.yaml @@ -28,11 +28,14 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 hive_generator: ^2.0.1 +dependency_overrides: + watcher: ^1.1.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_ethereum/pubspec.yaml b/cw_ethereum/pubspec.yaml index 649ec574b..cbe6644a4 100644 --- a/cw_ethereum/pubspec.yaml +++ b/cw_ethereum/pubspec.yaml @@ -22,7 +22,11 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 + +dependency_overrides: + watcher: ^1.1.0 + flutter: # assets: # - images/a_dot_burr.jpeg diff --git a/cw_evm/pubspec.yaml b/cw_evm/pubspec.yaml index c202cc72a..eaafb8415 100644 --- a/cw_evm/pubspec.yaml +++ b/cw_evm/pubspec.yaml @@ -27,11 +27,14 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 flutter_lints: ^2.0.0 +dependency_overrides: + watcher: ^1.1.0 + flutter: # assets: # - images/a_dot_burr.jpeg diff --git a/cw_haven/pubspec.yaml b/cw_haven/pubspec.yaml index c215ab779..d868c986d 100644 --- a/cw_haven/pubspec.yaml +++ b/cw_haven/pubspec.yaml @@ -24,11 +24,14 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 build_resolvers: ^2.0.9 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_monero/pubspec.yaml b/cw_monero/pubspec.yaml index a6fe7f967..c49a541ab 100644 --- a/cw_monero/pubspec.yaml +++ b/cw_monero/pubspec.yaml @@ -26,11 +26,14 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_nano/pubspec.yaml b/cw_nano/pubspec.yaml index a4b8732fd..768c1bb4e 100644 --- a/cw_nano/pubspec.yaml +++ b/cw_nano/pubspec.yaml @@ -32,10 +32,13 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_polygon/pubspec.yaml b/cw_polygon/pubspec.yaml index 505838d7c..61a474002 100644 --- a/cw_polygon/pubspec.yaml +++ b/cw_polygon/pubspec.yaml @@ -28,7 +28,10 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.0 - build_runner: ^2.1.11 + build_runner: ^2.4.7 + +dependency_overrides: + watcher: ^1.1.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_solana/pubspec.yaml b/cw_solana/pubspec.yaml index 7e24983bf..6b59282b4 100644 --- a/cw_solana/pubspec.yaml +++ b/cw_solana/pubspec.yaml @@ -26,10 +26,13 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.0 - build_runner: ^2.1.11 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + flutter: # assets: # - images/a_dot_burr.jpeg diff --git a/lib/entities/biometric_auth.dart b/lib/entities/biometric_auth.dart index febbfa469..463a22775 100644 --- a/lib/entities/biometric_auth.dart +++ b/lib/entities/biometric_auth.dart @@ -1,32 +1,28 @@ -import 'package:local_auth/local_auth.dart'; import 'package:flutter/services.dart'; -import 'package:cake_wallet/generated/i18n.dart'; +import 'package:flutter_local_authentication/flutter_local_authentication.dart'; class BiometricAuth { - final _localAuth = LocalAuthentication(); + final _flutterLocalAuthenticationPlugin = FlutterLocalAuthentication(); Future isAuthenticated() async { try { - return await _localAuth.authenticate( - localizedReason: S.current.biometric_auth_reason, - options: AuthenticationOptions( - biometricOnly: true, - useErrorDialogs: true, - stickyAuth: false)); - } on PlatformException catch (e) { + final authenticated = await _flutterLocalAuthenticationPlugin.authenticate(); + return authenticated; + } catch (e) { print(e); } - return false; } Future canCheckBiometrics() async { + bool canAuthenticate; try { - return await _localAuth.canCheckBiometrics; - } on PlatformException catch (e) { - print(e); + canAuthenticate = await _flutterLocalAuthenticationPlugin.canAuthenticate(); + } catch (error) { + print("Exception checking support. $error"); + canAuthenticate = false; } - return false; + return canAuthenticate; } } diff --git a/lib/locales/hausa_intl.dart b/lib/locales/hausa_intl.dart index 749d39a4d..6cf757b60 100644 --- a/lib/locales/hausa_intl.dart +++ b/lib/locales/hausa_intl.dart @@ -751,6 +751,50 @@ class HaMaterialLocalizations extends GlobalMaterialLocalizations { @override String get scrimOnTapHintRaw => "Scrip on Tap"; + + @override + // TODO: implement collapsedHint + String get collapsedHint => "collapsedHint"; + + @override + // TODO: implement expandedHint + String get expandedHint => "expandedHint"; + + @override + // TODO: implement expansionTileCollapsedHint + String get expansionTileCollapsedHint => "expansionTileCollapsedHint"; + + @override + // TODO: implement expansionTileCollapsedTapHint + String get expansionTileCollapsedTapHint => "expansionTileCollapsedTapHint"; + + @override + // TODO: implement expansionTileExpandedHint + String get expansionTileExpandedHint => "expansionTileExpandedHint"; + + @override + // TODO: implement expansionTileExpandedTapHint + String get expansionTileExpandedTapHint => "expansionTileExpandedTapHint"; + + @override + // TODO: implement scanTextButtonLabel + String get scanTextButtonLabel => "scanTextButtonLabel"; + + @override + // TODO: implement lookUpButtonLabel + String get lookUpButtonLabel => "lookUpButtonLabel"; + + @override + // TODO: implement menuDismissLabel + String get menuDismissLabel => "menuDismissLabel"; + + @override + // TODO: implement searchWebButtonLabel + String get searchWebButtonLabel => "searchWebButtonLabel"; + + @override + // TODO: implement shareButtonLabel + String get shareButtonLabel => "shareButtonLabel"; } /// Cupertino Support @@ -955,4 +999,24 @@ class HaCupertinoLocalizations extends GlobalCupertinoLocalizations { @override String get noSpellCheckReplacementsLabel => ""; + + @override + // TODO: implement clearButtonLabel + String get clearButtonLabel => "clearButtonLabel"; + + @override + // TODO: implement lookUpButtonLabel + String get lookUpButtonLabel => "lookUpButtonLabel"; + + @override + // TODO: implement menuDismissLabel + String get menuDismissLabel => "menuDismissLabel"; + + @override + // TODO: implement searchWebButtonLabel + String get searchWebButtonLabel => "searchWebButtonLabel"; + + @override + // TODO: implement shareButtonLabel + String get shareButtonLabel => "shareButtonLabel"; } diff --git a/lib/locales/yoruba_intl.dart b/lib/locales/yoruba_intl.dart index 889c21cb7..3c720b80e 100644 --- a/lib/locales/yoruba_intl.dart +++ b/lib/locales/yoruba_intl.dart @@ -1,4 +1,3 @@ - import 'dart:async'; import 'package:flutter/cupertino.dart'; @@ -164,62 +163,62 @@ const yoDateSymbols = { 'ọjọ́ Àbámẹ́ta', ], 'STANDALONEWEEKDAYS': [ -'Ọjọ́ Ajé', -'Ọjọ́ Ìsẹ́gun', -'Ọjọ́ Ìsẹ́gun-Ẹtì', -'Ọjọ́ Ìsẹ́gun-Ọ̀rú', -'Ọjọ́ Àìkú', -'Ọjọ́ Jímọ̀', -'Ọjọ́ Àbámẹ́ta', -], -'SHORTWEEKDAYS': [ -'Ajé', -'Ìsẹ́gun', -'Ìsẹ́gun-Ẹtì', -'Ìsẹ́gun-Ọ̀rú', -'Àìkú', -'Jímọ̀', -'Àbámẹ́ta', -], -'STANDALONESHORTWEEKDAYS': [ -'Ajé', -'Ìsẹ́gun', -'Ìsẹ́gun-Ẹtì', -'Ìsẹ́gun-Ọ̀rú', -'Àìkú', -'Jímọ̀', -'Àbámẹ́ta', -], -'NARROWWEEKDAYS': [ -'A', -'A', -'Ì', -'A', -'À', -'J', -'À', -], -'STANDALONENARROWWEEKDAYS': [ -'A', -'A', -'Ì', -'A', -'À', -'J', -'À', -], -'SHORTQUARTERS': [ -'K1', -'K2', -'K3', -'K4', -], -'QUARTERS': [ -'1. kwata', -'2. kwata', -'3. kwata', -'4. kwata', -], + 'Ọjọ́ Ajé', + 'Ọjọ́ Ìsẹ́gun', + 'Ọjọ́ Ìsẹ́gun-Ẹtì', + 'Ọjọ́ Ìsẹ́gun-Ọ̀rú', + 'Ọjọ́ Àìkú', + 'Ọjọ́ Jímọ̀', + 'Ọjọ́ Àbámẹ́ta', + ], + 'SHORTWEEKDAYS': [ + 'Ajé', + 'Ìsẹ́gun', + 'Ìsẹ́gun-Ẹtì', + 'Ìsẹ́gun-Ọ̀rú', + 'Àìkú', + 'Jímọ̀', + 'Àbámẹ́ta', + ], + 'STANDALONESHORTWEEKDAYS': [ + 'Ajé', + 'Ìsẹ́gun', + 'Ìsẹ́gun-Ẹtì', + 'Ìsẹ́gun-Ọ̀rú', + 'Àìkú', + 'Jímọ̀', + 'Àbámẹ́ta', + ], + 'NARROWWEEKDAYS': [ + 'A', + 'A', + 'Ì', + 'A', + 'À', + 'J', + 'À', + ], + 'STANDALONENARROWWEEKDAYS': [ + 'A', + 'A', + 'Ì', + 'A', + 'À', + 'J', + 'À', + ], + 'SHORTQUARTERS': [ + 'K1', + 'K2', + 'K3', + 'K4', + ], + 'QUARTERS': [ + '1. kwata', + '2. kwata', + '3. kwata', + '4. kwata', + ], 'AMPMS': [ 'a.m.', 'p.m.', @@ -316,339 +315,339 @@ class YoMaterialLocalizations extends GlobalMaterialLocalizations { }); // #docregion Getters -@override -String get moreButtonTooltip => r'Kò sí ìròhùn tí ó múni'; + @override + String get moreButtonTooltip => r'Kò sí ìròhùn tí ó múni'; -@override -String get aboutListTileTitleRaw => r'Fun Àpótí àwọn $applicationname'; + @override + String get aboutListTileTitleRaw => r'Fun Àpótí àwọn $applicationname'; -@override -String get alertDialogLabel => r'Ìròhùn Àlàyé'; + @override + String get alertDialogLabel => r'Ìròhùn Àlàyé'; // #enddocregion Getters -@override -String get anteMeridiemAbbreviation => r'AM'; + @override + String get anteMeridiemAbbreviation => r'AM'; -@override -String get backButtonTooltip => r'Fíran'; + @override + String get backButtonTooltip => r'Fíran'; -@override -String get cancelButtonLabel => r'FAGILE'; + @override + String get cancelButtonLabel => r'FAGILE'; -@override -String get closeButtonLabel => r'KÚ'; + @override + String get closeButtonLabel => r'KÚ'; -@override -String get closeButtonTooltip => r'Kú'; + @override + String get closeButtonTooltip => r'Kú'; -@override -String get collapsedIconTapHint => r'Tá'; + @override + String get collapsedIconTapHint => r'Tá'; -@override -String get continueButtonLabel => r'TÓ WÁ'; + @override + String get continueButtonLabel => r'TÓ WÁ'; -@override -String get copyButtonLabel => r'DÚPLÍKÉTÍ'; + @override + String get copyButtonLabel => r'DÚPLÍKÉTÍ'; -@override -String get cutButtonLabel => r'TÒ'; + @override + String get cutButtonLabel => r'TÒ'; -@override -String get deleteButtonTooltip => r'Máa kú'; + @override + String get deleteButtonTooltip => r'Máa kú'; -@override -String get dialogLabel => r'Ìròhùn'; + @override + String get dialogLabel => r'Ìròhùn'; -@override -String get drawerLabel => r'Àgbèjọ àwọn àpọ̀tí'; + @override + String get drawerLabel => r'Àgbèjọ àwọn àpọ̀tí'; -@override -String get expandedIconTapHint => r'Tá'; + @override + String get expandedIconTapHint => r'Tá'; -@override -String get firstPageTooltip => r'Ojú ewe'; + @override + String get firstPageTooltip => r'Ojú ewe'; -@override -String get hideAccountsLabel => r'Fí èrò àpótí wáyé sílẹ̀'; + @override + String get hideAccountsLabel => r'Fí èrò àpótí wáyé sílẹ̀'; -@override -String get lastPageTooltip => r'Ojú ayé'; + @override + String get lastPageTooltip => r'Ojú ayé'; -@override -String get licensesPageTitle => r'Ìròhùn Ọdún'; + @override + String get licensesPageTitle => r'Ìròhùn Ọdún'; -@override -String get modalBarrierDismissLabel => r'Sọ'; + @override + String get modalBarrierDismissLabel => r'Sọ'; -@override -String get nextMonthTooltip => r'Oṣù kọja'; + @override + String get nextMonthTooltip => r'Oṣù kọja'; -@override -String get nextPageTooltip => r'Ojú ọjọ́ kẹta'; + @override + String get nextPageTooltip => r'Ojú ọjọ́ kẹta'; -@override -String get okButtonLabel => r'Ò daájú'; -@override + @override + String get okButtonLabel => r'Ò daájú'; + @override // A custom drawer tooltip message. -String get openAppDrawerTooltip => r'Aya ntọju Iwe Awọn Aka'; + String get openAppDrawerTooltip => r'Aya ntọju Iwe Awọn Aka'; // #docregion Raw -@override -String get pageRowsInfoTitleRaw => r'$firstRow–$lastRow lati $rowCount'; + @override + String get pageRowsInfoTitleRaw => r'$firstRow–$lastRow lati $rowCount'; -@override -String get pageRowsInfoTitleApproximateRaw => r'$firstRow–$lastRow lati kiakia $rowCount'; + @override + String get pageRowsInfoTitleApproximateRaw => r'$firstRow–$lastRow lati kiakia $rowCount'; // #enddocregion Raw -@override -String get pasteButtonLabel => r'TÌ'; - -@override -String get popupMenuLabel => r'Meniu Pop-up'; - -@override -String get menuBarMenuLabel => r'Meniu Akọkọ'; - -@override -String get postMeridiemAbbreviation => r'PM'; - -@override -String get previousMonthTooltip => r'Oṣu Kanakana'; - -@override -String get previousPageTooltip => r'Ojú ewé akọkọ kan'; - -@override -String get refreshIndicatorSemanticLabel => r'Gbiyanju'; - -@override -String? get remainingTextFieldCharacterCountFew => null; - -@override -String? get remainingTextFieldCharacterCountMany => null; - -@override -String get remainingTextFieldCharacterCountOne => r'1 àmì báálẹ̀'; - -@override -String get remainingTextFieldCharacterCountOther => r'$remainingCount àmì báálẹ̀'; - -@override -String? get remainingTextFieldCharacterCountTwo => null; - -@override -String get remainingTextFieldCharacterCountZero => r'Kò sí ìwọlé létà láti ń ṣe'; - -@override -String get reorderItemDown => r'Jù sí ilẹ'; - -@override -String get reorderItemLeft => r'Jù sí àrà'; - -@override -String get reorderItemRight => r'Jù sí òtútù'; - -@override -String get reorderItemToEnd => r'Jù sí ìbẹ̀jì'; - -@override -String get reorderItemToStart => r'Jù sí àkọ́kọ́'; - -@override -String get reorderItemUp => r'Jù sí ọ̀rùn'; - -@override -String get rowsPerPageTitle => r'Ìlò Fún àwọn Ìtọ́kasíwájú:'; - -@override -ScriptCategory get scriptCategory => ScriptCategory.englishLike; - -@override -String get searchFieldLabel => 'Ṣẹda'; - -@override -String get selectAllButtonLabel => 'FADỌHỌN DỌFÚN GBÁJÚMỌ̀'; - -@override -String? get selectedRowCountTitleFew => null; - -@override -String? get selectedRowCountTitleMany => null; - -@override -String get selectedRowCountTitleOne => '1 káyé'; - -@override -String get selectedRowCountTitleOther => r'$selectedRowCount káyé'; - -@override -String? get selectedRowCountTitleTwo => null; - -@override -String get selectedRowCountTitleZero => 'Kò sí káyé ti o wọlé'; - -@override -String get showAccountsLabel => 'Fi iyipada mu kọ'; - -@override -String get showMenuTooltip => 'Fi Meniu mu kọ'; - -@override -String get signedInLabel => 'Ọ̀nà'; - -@override -String get tabLabelRaw => r'Àwọn tabin $tabIndex lati $tabCount'; - @override -TimeOfDayFormat get timeOfDayFormatRaw => TimeOfDayFormat.h_colon_mm_space_a; - -@override -String get timePickerHourModeAnnouncement => 'Tuntun waqtu lọ'; - -@override -String get timePickerMinuteModeAnnouncement => 'Tuntun daɗi minti'; - -@override -String get viewLicensesButtonLabel => 'WO NIKI'; - -@override -List get narrowWeekdays => const ['L', 'L', 'A', 'O', 'Ọ', 'Ẹ', 'Ẹ']; - -@override -int get firstDayOfWeekIndex => 0; - -static const LocalizationsDelegate delegate = -_YoMaterialLocalizationsDelegate(); - -@override -String get calendarModeButtonLabel => 'Tọ́rọ̀ kálẹ̀ndà'; - -@override -String get dateHelpText => 'mm/dd/yyyy'; - -@override -String get dateInputLabel => 'Firanṣẹ̀ Ọjọ́'; - -@override -String get dateOutOfRangeLabel => 'Nínú iwọ̀ lọ́wọ́'; - -@override -String get datePickerHelpText => 'WÁSÍ'; - -@override -String get dateRangeEndDateSemanticLabelRaw => r'Ọjọ́ tuntun to ṣà'; - -@override -String get dateRangeEndLabel => 'Ọjọ́ tuntun to ṣà'; - -@override -String get dateRangePickerHelpText => 'WÁSÍ ÌGBÀ'; - -@override -String get dateRangeStartDateSemanticLabelRaw => 'Ọjọ́ tuntun ti dá'; - -@override -String get dateRangeStartLabel => 'Ọjọ́ tuntun ti dá'; - -@override -String get dateSeparator => '/'; - -@override -String get dialModeButtonLabel => 'Tọ́rọ̀ wakati'; - -@override -String get inputDateModeButtonLabel => 'Tọ́rọ̀ firanṣẹ̀ ọjọ́'; - -@override -String get inputTimeModeButtonLabel => 'Tọ́rọ̀ wakati bayi lọ́wọ́'; - -@override -String get invalidDateFormatLabel => 'Akọ́kọ́tọ́ tó jẹ́kúnrin'; - -@override -String get invalidDateRangeLabel => 'Àmì jẹ́ káàkiri lẹ́yìn ilé'; - -@override -String get invalidTimeLabel => 'Akọ́kọ́tọ́ àkójọ ìwádìí'; - -@override -String get licensesPackageDetailTextOther => r'$licenseCount àwọn níkí'; - -@override -String get saveButtonLabel => 'TÙN DÁRA'; - -@override -String get selectYearSemanticsLabel => 'Fọ́ọ̀ shẹ́kàrà'; - -@override -String get timePickerDialHelpText => 'WÁSÍ WÁKÀTÌ'; - -@override -String get timePickerHourLabel => 'Wákàtì àṣà'; - -@override -String get timePickerInputHelpText => 'Shìgárà wákàtì'; - -@override -String get timePickerMinuteLabel => 'Mìntì'; - -@override -String get unspecifiedDate => 'Ọjọ̀kúnrin'; - -@override -String get unspecifiedDateRange => 'Ọjọ̀kúnrin àdáyọ̀'; - -@override -String get keyboardKeyAlt => 'Alt'; - -@override -String get keyboardKeyAltGraph => 'AltGraph'; - -@override -String get keyboardKeyBackspace => 'Báckspàcè'; - -@override -String get keyboardKeyCapsLock => 'Caps Lock'; - -@override -String get keyboardKeyChannelDown => 'Báyàkàmmàlàsàké'; - -@override -String get keyboardKeyChannelUp => 'Yíkàmmàlàsàké'; - -@override -String get keyboardKeyControl => 'Kọ́ntírọ̀l'; - -@override -String get keyboardKeyDelete => 'Shápè'; - -@override -String get keyboardKeyEject => 'Èjẹ̀tì'; - -@override -String get keyboardKeyEnd => 'Tàbí'; - -@override -String get keyboardKeyEscape => 'Tòkè'; + String get pasteButtonLabel => r'TÌ'; @override -String get keyboardKeyFn => 'Fn'; + String get popupMenuLabel => r'Meniu Pop-up'; -@override -String get keyboardKeyHome => 'Ile'; + @override + String get menuBarMenuLabel => r'Meniu Akọkọ'; -@override -String get keyboardKeyInsert => 'Fi sori'; + @override + String get postMeridiemAbbreviation => r'PM'; -@override -String get keyboardKeyMeta => 'Meta'; + @override + String get previousMonthTooltip => r'Oṣu Kanakana'; -@override -String get keyboardKeyMetaMacOs => 'Amfani pẹlu Command'; + @override + String get previousPageTooltip => r'Ojú ewé akọkọ kan'; -@override -String get keyboardKeyMetaWindows => 'Windows'; + @override + String get refreshIndicatorSemanticLabel => r'Gbiyanju'; + + @override + String? get remainingTextFieldCharacterCountFew => null; + + @override + String? get remainingTextFieldCharacterCountMany => null; + + @override + String get remainingTextFieldCharacterCountOne => r'1 àmì báálẹ̀'; + + @override + String get remainingTextFieldCharacterCountOther => r'$remainingCount àmì báálẹ̀'; + + @override + String? get remainingTextFieldCharacterCountTwo => null; + + @override + String get remainingTextFieldCharacterCountZero => r'Kò sí ìwọlé létà láti ń ṣe'; + + @override + String get reorderItemDown => r'Jù sí ilẹ'; + + @override + String get reorderItemLeft => r'Jù sí àrà'; + + @override + String get reorderItemRight => r'Jù sí òtútù'; + + @override + String get reorderItemToEnd => r'Jù sí ìbẹ̀jì'; + + @override + String get reorderItemToStart => r'Jù sí àkọ́kọ́'; + + @override + String get reorderItemUp => r'Jù sí ọ̀rùn'; + + @override + String get rowsPerPageTitle => r'Ìlò Fún àwọn Ìtọ́kasíwájú:'; + + @override + ScriptCategory get scriptCategory => ScriptCategory.englishLike; + + @override + String get searchFieldLabel => 'Ṣẹda'; + + @override + String get selectAllButtonLabel => 'FADỌHỌN DỌFÚN GBÁJÚMỌ̀'; + + @override + String? get selectedRowCountTitleFew => null; + + @override + String? get selectedRowCountTitleMany => null; + + @override + String get selectedRowCountTitleOne => '1 káyé'; + + @override + String get selectedRowCountTitleOther => r'$selectedRowCount káyé'; + + @override + String? get selectedRowCountTitleTwo => null; + + @override + String get selectedRowCountTitleZero => 'Kò sí káyé ti o wọlé'; + + @override + String get showAccountsLabel => 'Fi iyipada mu kọ'; + + @override + String get showMenuTooltip => 'Fi Meniu mu kọ'; + + @override + String get signedInLabel => 'Ọ̀nà'; + + @override + String get tabLabelRaw => r'Àwọn tabin $tabIndex lati $tabCount'; + + @override + TimeOfDayFormat get timeOfDayFormatRaw => TimeOfDayFormat.h_colon_mm_space_a; + + @override + String get timePickerHourModeAnnouncement => 'Tuntun waqtu lọ'; + + @override + String get timePickerMinuteModeAnnouncement => 'Tuntun daɗi minti'; + + @override + String get viewLicensesButtonLabel => 'WO NIKI'; + + @override + List get narrowWeekdays => const ['L', 'L', 'A', 'O', 'Ọ', 'Ẹ', 'Ẹ']; + + @override + int get firstDayOfWeekIndex => 0; + + static const LocalizationsDelegate delegate = + _YoMaterialLocalizationsDelegate(); + + @override + String get calendarModeButtonLabel => 'Tọ́rọ̀ kálẹ̀ndà'; + + @override + String get dateHelpText => 'mm/dd/yyyy'; + + @override + String get dateInputLabel => 'Firanṣẹ̀ Ọjọ́'; + + @override + String get dateOutOfRangeLabel => 'Nínú iwọ̀ lọ́wọ́'; + + @override + String get datePickerHelpText => 'WÁSÍ'; + + @override + String get dateRangeEndDateSemanticLabelRaw => r'Ọjọ́ tuntun to ṣà'; + + @override + String get dateRangeEndLabel => 'Ọjọ́ tuntun to ṣà'; + + @override + String get dateRangePickerHelpText => 'WÁSÍ ÌGBÀ'; + + @override + String get dateRangeStartDateSemanticLabelRaw => 'Ọjọ́ tuntun ti dá'; + + @override + String get dateRangeStartLabel => 'Ọjọ́ tuntun ti dá'; + + @override + String get dateSeparator => '/'; + + @override + String get dialModeButtonLabel => 'Tọ́rọ̀ wakati'; + + @override + String get inputDateModeButtonLabel => 'Tọ́rọ̀ firanṣẹ̀ ọjọ́'; + + @override + String get inputTimeModeButtonLabel => 'Tọ́rọ̀ wakati bayi lọ́wọ́'; + + @override + String get invalidDateFormatLabel => 'Akọ́kọ́tọ́ tó jẹ́kúnrin'; + + @override + String get invalidDateRangeLabel => 'Àmì jẹ́ káàkiri lẹ́yìn ilé'; + + @override + String get invalidTimeLabel => 'Akọ́kọ́tọ́ àkójọ ìwádìí'; + + @override + String get licensesPackageDetailTextOther => r'$licenseCount àwọn níkí'; + + @override + String get saveButtonLabel => 'TÙN DÁRA'; + + @override + String get selectYearSemanticsLabel => 'Fọ́ọ̀ shẹ́kàrà'; + + @override + String get timePickerDialHelpText => 'WÁSÍ WÁKÀTÌ'; + + @override + String get timePickerHourLabel => 'Wákàtì àṣà'; + + @override + String get timePickerInputHelpText => 'Shìgárà wákàtì'; + + @override + String get timePickerMinuteLabel => 'Mìntì'; + + @override + String get unspecifiedDate => 'Ọjọ̀kúnrin'; + + @override + String get unspecifiedDateRange => 'Ọjọ̀kúnrin àdáyọ̀'; + + @override + String get keyboardKeyAlt => 'Alt'; + + @override + String get keyboardKeyAltGraph => 'AltGraph'; + + @override + String get keyboardKeyBackspace => 'Báckspàcè'; + + @override + String get keyboardKeyCapsLock => 'Caps Lock'; + + @override + String get keyboardKeyChannelDown => 'Báyàkàmmàlàsàké'; + + @override + String get keyboardKeyChannelUp => 'Yíkàmmàlàsàké'; + + @override + String get keyboardKeyControl => 'Kọ́ntírọ̀l'; + + @override + String get keyboardKeyDelete => 'Shápè'; + + @override + String get keyboardKeyEject => 'Èjẹ̀tì'; + + @override + String get keyboardKeyEnd => 'Tàbí'; + + @override + String get keyboardKeyEscape => 'Tòkè'; + + @override + String get keyboardKeyFn => 'Fn'; + + @override + String get keyboardKeyHome => 'Ile'; + + @override + String get keyboardKeyInsert => 'Fi sori'; + + @override + String get keyboardKeyMeta => 'Meta'; + + @override + String get keyboardKeyMetaMacOs => 'Amfani pẹlu Command'; + + @override + String get keyboardKeyMetaWindows => 'Windows'; @override String get keyboardKeyNumLock => 'Num Lock'; @@ -751,6 +750,50 @@ String get keyboardKeyMetaWindows => 'Windows'; @override String get scrimOnTapHintRaw => "Scrip on Tap"; + + @override + // TODO: implement collapsedHint + String get collapsedHint => "collapsedHint"; + + @override + // TODO: implement expandedHint + String get expandedHint => "expandedHint"; + + @override + // TODO: implement expansionTileCollapsedHint + String get expansionTileCollapsedHint => "expansionTileCollapsedHint"; + + @override + // TODO: implement expansionTileCollapsedTapHint + String get expansionTileCollapsedTapHint => "expansionTileCollapsedTapHint"; + + @override + // TODO: implement expansionTileExpandedHint + String get expansionTileExpandedHint => "expansionTileExpandedHint"; + + @override + // TODO: implement expansionTileExpandedTapHint + String get expansionTileExpandedTapHint => "expansionTileExpandedTapHint"; + + @override + // TODO: implement scanTextButtonLabel + String get scanTextButtonLabel => "scanTextButtonLabel"; + + @override + // TODO: implement lookUpButtonLabel + String get lookUpButtonLabel => "lookUpButtonLabel"; + + @override + // TODO: implement menuDismissLabel + String get menuDismissLabel => "menuDismissLabel"; + + @override + // TODO: implement searchWebButtonLabel + String get searchWebButtonLabel => "searchWebButtonLabel"; + + @override + // TODO: implement shareButtonLabel + String get shareButtonLabel => "shareButtonLabel"; } /// Cupertino Support @@ -821,138 +864,158 @@ class YoCupertinoLocalizations extends GlobalCupertinoLocalizations { required super.singleDigitSecondFormat, }); -@override -String get alertDialogLabel => 'Àdàkárò'; + @override + String get alertDialogLabel => 'Àdàkárò'; -@override -String get anteMeridiemAbbreviation => 'AM'; + @override + String get anteMeridiemAbbreviation => 'AM'; -@override -String get copyButtonLabel => 'Kòpy'; + @override + String get copyButtonLabel => 'Kòpy'; -@override -String get cutButtonLabel => 'Kọ́t'; + @override + String get cutButtonLabel => 'Kọ́t'; -@override -String get datePickerDateOrderString => 'mdy'; + @override + String get datePickerDateOrderString => 'mdy'; -@override -String get datePickerDateTimeOrderString => 'date_time_dayPeriod'; + @override + String get datePickerDateTimeOrderString => 'date_time_dayPeriod'; -@override -String? get datePickerHourSemanticsLabelFew => null; + @override + String? get datePickerHourSemanticsLabelFew => null; -@override -String? get datePickerHourSemanticsLabelMany => null; + @override + String? get datePickerHourSemanticsLabelMany => null; -@override -String? get datePickerHourSemanticsLabelOne => r"$hour o'clock"; + @override + String? get datePickerHourSemanticsLabelOne => r"$hour o'clock"; -@override -String get datePickerHourSemanticsLabelOther => r"$hour o'clock"; + @override + String get datePickerHourSemanticsLabelOther => r"$hour o'clock"; -@override -String? get datePickerHourSemanticsLabelTwo => null; + @override + String? get datePickerHourSemanticsLabelTwo => null; -@override -String? get datePickerHourSemanticsLabelZero => null; + @override + String? get datePickerHourSemanticsLabelZero => null; -@override -String? get datePickerMinuteSemanticsLabelFew => null; + @override + String? get datePickerMinuteSemanticsLabelFew => null; -@override -String? get datePickerMinuteSemanticsLabelMany => null; + @override + String? get datePickerMinuteSemanticsLabelMany => null; -@override -String? get datePickerMinuteSemanticsLabelOne => '1 wakati'; + @override + String? get datePickerMinuteSemanticsLabelOne => '1 wakati'; -@override -String get datePickerMinuteSemanticsLabelOther => r'$minute wakati'; + @override + String get datePickerMinuteSemanticsLabelOther => r'$minute wakati'; -@override -String? get datePickerMinuteSemanticsLabelTwo => null; + @override + String? get datePickerMinuteSemanticsLabelTwo => null; -@override -String? get datePickerMinuteSemanticsLabelZero => null; + @override + String? get datePickerMinuteSemanticsLabelZero => null; -@override -String get modalBarrierDismissLabel => 'Búta'; + @override + String get modalBarrierDismissLabel => 'Búta'; -@override -String get pasteButtonLabel => 'Tẹ́ẹ́'; + @override + String get pasteButtonLabel => 'Tẹ́ẹ́'; -@override -String get postMeridiemAbbreviation => 'PM'; + @override + String get postMeridiemAbbreviation => 'PM'; -@override -String get searchTextFieldPlaceholderLabel => 'Wúró àtúntà'; + @override + String get searchTextFieldPlaceholderLabel => 'Wúró àtúntà'; -@override -String get selectAllButtonLabel => 'Fírànsé gbógbo'; + @override + String get selectAllButtonLabel => 'Fírànsé gbógbo'; -@override -String get tabSemanticsLabelRaw => r'Tab $tabIndex nínú $tabCount'; + @override + String get tabSemanticsLabelRaw => r'Tab $tabIndex nínú $tabCount'; -@override -String? get timerPickerHourLabelFew => null; + @override + String? get timerPickerHourLabelFew => null; -@override -String? get timerPickerHourLabelMany => null; + @override + String? get timerPickerHourLabelMany => null; -@override -String? get timerPickerHourLabelOne => 'òǹdì'; + @override + String? get timerPickerHourLabelOne => 'òǹdì'; -@override -String get timerPickerHourLabelOther => 'òǹdì'; + @override + String get timerPickerHourLabelOther => 'òǹdì'; -@override -String? get timerPickerHourLabelTwo => null; + @override + String? get timerPickerHourLabelTwo => null; -@override -String? get timerPickerHourLabelZero => null; + @override + String? get timerPickerHourLabelZero => null; -@override -String? get timerPickerMinuteLabelFew => null; + @override + String? get timerPickerMinuteLabelFew => null; -@override -String? get timerPickerMinuteLabelMany => null; + @override + String? get timerPickerMinuteLabelMany => null; -@override -String? get timerPickerMinuteLabelOne => 'wakati.'; + @override + String? get timerPickerMinuteLabelOne => 'wakati.'; -@override -String get timerPickerMinuteLabelOther => 'wakati.'; + @override + String get timerPickerMinuteLabelOther => 'wakati.'; -@override -String? get timerPickerMinuteLabelTwo => null; + @override + String? get timerPickerMinuteLabelTwo => null; -@override -String? get timerPickerMinuteLabelZero => null; + @override + String? get timerPickerMinuteLabelZero => null; -@override -String? get timerPickerSecondLabelFew => null; + @override + String? get timerPickerSecondLabelFew => null; -@override -String? get timerPickerSecondLabelMany => null; + @override + String? get timerPickerSecondLabelMany => null; -@override -String? get timerPickerSecondLabelOne => 'dákìkà.'; + @override + String? get timerPickerSecondLabelOne => 'dákìkà.'; -@override -String get timerPickerSecondLabelOther => 'dákìkà.'; + @override + String get timerPickerSecondLabelOther => 'dákìkà.'; -@override -String? get timerPickerSecondLabelTwo => null; + @override + String? get timerPickerSecondLabelTwo => null; -@override -String? get timerPickerSecondLabelZero => null; + @override + String? get timerPickerSecondLabelZero => null; -@override -String get todayLabel => 'Oyọ'; + @override + String get todayLabel => 'Oyọ'; static const LocalizationsDelegate delegate = _YoCupertinoLocalizationsDelegate(); @override String get noSpellCheckReplacementsLabel => ""; + + @override + // TODO: implement clearButtonLabel + String get clearButtonLabel => "clearButtonLabel"; + + @override + // TODO: implement lookUpButtonLabel + String get lookUpButtonLabel => "lookUpButtonLabel"; + + @override + // TODO: implement menuDismissLabel + String get menuDismissLabel => "menuDismissLabel"; + + @override + // TODO: implement searchWebButtonLabel + String get searchWebButtonLabel => "searchWebButtonLabel"; + + @override + // TODO: implement shareButtonLabel + String get shareButtonLabel => "shareButtonLabel"; } diff --git a/lib/src/screens/settings/security_backup_page.dart b/lib/src/screens/settings/security_backup_page.dart index e559e9b15..1f0f58ad4 100644 --- a/lib/src/screens/settings/security_backup_page.dart +++ b/lib/src/screens/settings/security_backup_page.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/routes.dart'; @@ -58,7 +60,7 @@ class SecurityBackupPage extends BasePage { .shouldRequireTOTP2FAForAllSecurityAndBackupSettings, ), ), - if (DeviceInfo.instance.isMobile) + if (DeviceInfo.instance.isMobile || Platform.isMacOS || Platform.isLinux) Observer(builder: (_) { return SettingsSwitcherCell( title: S.current.settings_allow_biometrical_authentication, diff --git a/lib/src/screens/settings/tor_page.dart b/lib/src/screens/settings/tor_page.dart index ae1ef1677..2f544be35 100644 --- a/lib/src/screens/settings/tor_page.dart +++ b/lib/src/screens/settings/tor_page.dart @@ -146,7 +146,7 @@ class ConnectScreen extends StatelessWidget { ElevatedButton( onPressed: connect, style: ElevatedButton.styleFrom( - primary: Colors.blue, + // primary: Colors.blue, padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30), @@ -211,7 +211,7 @@ class DisconnectScreen extends StatelessWidget { ElevatedButton( onPressed: disconnect, style: ElevatedButton.styleFrom( - primary: Colors.red, + // primary: Colors.red, padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30), diff --git a/lib/src/widgets/validable_annotated_editable_text.dart b/lib/src/widgets/validable_annotated_editable_text.dart index 6c3fc4f16..7ea928d8a 100644 --- a/lib/src/widgets/validable_annotated_editable_text.dart +++ b/lib/src/widgets/validable_annotated_editable_text.dart @@ -1,8 +1,14 @@ -import 'package:cake_wallet/core/seed_validator.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; -class Annotation extends Comparable { + +extension Compare on Comparable { + bool operator <=(T other) => compareTo(other) <= 0; + bool operator >=(T other) => compareTo(other) >= 0; + bool operator <(T other) => compareTo(other) < 0; + bool operator >(T other) => compareTo(other) > 0; +} + +class Annotation implements Comparable { Annotation({required this.range, required this.style}); final TextRange range; @@ -12,7 +18,7 @@ class Annotation extends Comparable { int compareTo(Annotation other) => range.start.compareTo(other.range.start); } -class TextAnnotation extends Comparable { +class TextAnnotation implements Comparable { TextAnnotation({required this.text, required this.style}); final TextStyle style; diff --git a/lib/view_model/auth_view_model.dart b/lib/view_model/auth_view_model.dart index e50f4db0c..0e6590845 100644 --- a/lib/view_model/auth_view_model.dart +++ b/lib/view_model/auth_view_model.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:flutter_local_authentication/flutter_local_authentication.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/view_model/auth_state.dart'; @@ -105,16 +106,14 @@ abstract class AuthViewModelBase with Store { @action Future biometricAuth() async { + final _flutterLocalAuthenticationPlugin = FlutterLocalAuthentication(); + try { - final canBiometricAuth = await _biometricAuth.canCheckBiometrics(); - - if (canBiometricAuth) { - final isAuthenticated = await _biometricAuth.isAuthenticated(); - - if (isAuthenticated) { - state = ExecutedSuccessfullyState(); - } + final authenticated = await _flutterLocalAuthenticationPlugin.authenticate(); + if (!authenticated) { + throw Exception('Biometric authentication failed'); } + state = ExecutedSuccessfullyState(); } catch (e) { state = FailureState(e.toString()); } diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 3ec3e7978..e1022864c 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -33,8 +33,8 @@ dependencies: dio: ^4.0.6 hive: ^2.2.3 hive_flutter: ^1.1.0 - local_auth: ^2.1.0 local_auth_android: 1.0.21 + flutter_local_authentication: ^1.2.0 package_info: ^2.0.0 #package_info_plus: ^1.4.2 devicelocale: diff --git a/pubspec_description.yaml b/pubspec_description.yaml index ebb6bf001..b51fe96d6 100644 --- a/pubspec_description.yaml +++ b/pubspec_description.yaml @@ -4,4 +4,4 @@ version: 0.0.0 publish_to: none environment: - sdk: ">=2.17.5 <3.0.0" \ No newline at end of file + sdk: ">=3.1.0 <4.0.0" \ No newline at end of file From e48962361a71888cb1c25d75204359ab2a660686 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Thu, 18 Apr 2024 11:10:32 -0700 Subject: [PATCH 185/241] script updates and new run-android script (#1396) --- configure_cake_wallet.sh | 12 +----------- run-android.sh | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 11 deletions(-) create mode 100755 run-android.sh diff --git a/configure_cake_wallet.sh b/configure_cake_wallet.sh index cc55e8fcc..837a002e9 100755 --- a/configure_cake_wallet.sh +++ b/configure_cake_wallet.sh @@ -23,14 +23,4 @@ source ./app_env.sh cakewallet ./app_config.sh cd ../.. && flutter pub get flutter packages pub run tool/generate_localization.dart -cd cw_core && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -cd cw_evm && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -cd cw_monero && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -cd cw_solana && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. -cd cw_ethereum && flutter pub get && cd .. -cd cw_polygon && flutter pub get && cd .. -flutter packages pub run build_runner build --delete-conflicting-outputs +./model_generator.sh diff --git a/run-android.sh b/run-android.sh new file mode 100755 index 000000000..dd694267a --- /dev/null +++ b/run-android.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# Get the current git branch +get_current_branch() { + if git rev-parse --git-dir > /dev/null 2>&1; then + branch=$(git rev-parse --abbrev-ref HEAD) + echo "$branch" + else + echo "Error: Not a git repository." + return 1 + fi +} + +# Update the app.properties file +update_app_properties() { + local branch=$1 + local file_path="./android/app.properties" + + sed -i "s/^id=.*/id=com.cakewallet.$branch/" "$file_path" + sed -i "s/^name=.*/name=$branch-Cake Wallet/" "$file_path" +} + +# only update app.properties if getting the current branch was successful +current_branch=$(get_current_branch) +if [[ $? -eq 0 ]]; then + update_app_properties "$current_branch" +fi + +# run the app +flutter run \ No newline at end of file From 4ed4659f9edfe60cbf063b6c10d0a1dc304d81e8 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Thu, 18 Apr 2024 20:10:58 +0200 Subject: [PATCH 186/241] Revert "version bump to 3.13.9, auth working on mac (#1367)" (#1397) This reverts commit e6b4b08c24c1c2fb6987dcca233a3fee67c50d25. --- .github/workflows/pr_test_build.yml | 2 +- android/build.gradle | 2 +- cw_bitcoin/pubspec.yaml | 5 +- cw_bitcoin_cash/pubspec.yaml | 5 +- cw_core/pubspec.yaml | 5 +- cw_ethereum/pubspec.yaml | 6 +- cw_evm/pubspec.yaml | 5 +- cw_haven/pubspec.yaml | 5 +- cw_monero/pubspec.yaml | 5 +- cw_nano/pubspec.yaml | 5 +- cw_polygon/pubspec.yaml | 5 +- cw_solana/pubspec.yaml | 5 +- lib/entities/biometric_auth.dart | 26 +- lib/locales/hausa_intl.dart | 64 -- lib/locales/yoruba_intl.dart | 787 ++++++++---------- .../settings/security_backup_page.dart | 4 +- lib/src/screens/settings/tor_page.dart | 4 +- .../validable_annotated_editable_text.dart | 14 +- lib/view_model/auth_view_model.dart | 15 +- pubspec_base.yaml | 2 +- pubspec_description.yaml | 2 +- 21 files changed, 406 insertions(+), 567 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index bfa378342..dc231df42 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -42,7 +42,7 @@ jobs: - name: Flutter action uses: subosito/flutter-action@v1 with: - flutter-version: "3.13.9" + flutter-version: "3.10.x" channel: stable - name: Install package dependencies diff --git a/android/build.gradle b/android/build.gradle index e182e39af..8286d9cb9 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.8.10' + ext.kotlin_version = '1.7.10' repositories { google() jcenter() diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index 1ccdb70c9..632a3140a 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -39,14 +39,11 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.7 + build_runner: ^2.1.11 build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 -dependency_overrides: - watcher: ^1.1.0 - # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_bitcoin_cash/pubspec.yaml b/cw_bitcoin_cash/pubspec.yaml index ceef539c3..37827f1ba 100644 --- a/cw_bitcoin_cash/pubspec.yaml +++ b/cw_bitcoin_cash/pubspec.yaml @@ -39,13 +39,10 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.7 + build_runner: ^2.1.11 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 -dependency_overrides: - watcher: ^1.1.0 - # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml index 51d671dc7..04a840d4e 100644 --- a/cw_core/pubspec.yaml +++ b/cw_core/pubspec.yaml @@ -28,14 +28,11 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.7 + build_runner: ^2.1.11 build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 hive_generator: ^2.0.1 -dependency_overrides: - watcher: ^1.1.0 - # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_ethereum/pubspec.yaml b/cw_ethereum/pubspec.yaml index cbe6644a4..649ec574b 100644 --- a/cw_ethereum/pubspec.yaml +++ b/cw_ethereum/pubspec.yaml @@ -22,11 +22,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.7 - -dependency_overrides: - watcher: ^1.1.0 - + build_runner: ^2.1.11 flutter: # assets: # - images/a_dot_burr.jpeg diff --git a/cw_evm/pubspec.yaml b/cw_evm/pubspec.yaml index eaafb8415..c202cc72a 100644 --- a/cw_evm/pubspec.yaml +++ b/cw_evm/pubspec.yaml @@ -27,14 +27,11 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.7 + build_runner: ^2.1.11 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 flutter_lints: ^2.0.0 -dependency_overrides: - watcher: ^1.1.0 - flutter: # assets: # - images/a_dot_burr.jpeg diff --git a/cw_haven/pubspec.yaml b/cw_haven/pubspec.yaml index d868c986d..c215ab779 100644 --- a/cw_haven/pubspec.yaml +++ b/cw_haven/pubspec.yaml @@ -24,14 +24,11 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.7 + build_runner: ^2.1.11 mobx_codegen: ^2.0.7 build_resolvers: ^2.0.9 hive_generator: ^1.1.3 -dependency_overrides: - watcher: ^1.1.0 - # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_monero/pubspec.yaml b/cw_monero/pubspec.yaml index c49a541ab..a6fe7f967 100644 --- a/cw_monero/pubspec.yaml +++ b/cw_monero/pubspec.yaml @@ -26,14 +26,11 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.7 + build_runner: ^2.1.11 build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 -dependency_overrides: - watcher: ^1.1.0 - # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_nano/pubspec.yaml b/cw_nano/pubspec.yaml index 768c1bb4e..a4b8732fd 100644 --- a/cw_nano/pubspec.yaml +++ b/cw_nano/pubspec.yaml @@ -32,13 +32,10 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.7 + build_runner: ^2.1.11 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 -dependency_overrides: - watcher: ^1.1.0 - # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_polygon/pubspec.yaml b/cw_polygon/pubspec.yaml index 61a474002..505838d7c 100644 --- a/cw_polygon/pubspec.yaml +++ b/cw_polygon/pubspec.yaml @@ -28,10 +28,7 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.0 - build_runner: ^2.4.7 - -dependency_overrides: - watcher: ^1.1.0 + build_runner: ^2.1.11 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_solana/pubspec.yaml b/cw_solana/pubspec.yaml index 6b59282b4..7e24983bf 100644 --- a/cw_solana/pubspec.yaml +++ b/cw_solana/pubspec.yaml @@ -26,13 +26,10 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.0 - build_runner: ^2.4.7 + build_runner: ^2.1.11 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 -dependency_overrides: - watcher: ^1.1.0 - flutter: # assets: # - images/a_dot_burr.jpeg diff --git a/lib/entities/biometric_auth.dart b/lib/entities/biometric_auth.dart index 463a22775..febbfa469 100644 --- a/lib/entities/biometric_auth.dart +++ b/lib/entities/biometric_auth.dart @@ -1,28 +1,32 @@ +import 'package:local_auth/local_auth.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_local_authentication/flutter_local_authentication.dart'; +import 'package:cake_wallet/generated/i18n.dart'; class BiometricAuth { - final _flutterLocalAuthenticationPlugin = FlutterLocalAuthentication(); + final _localAuth = LocalAuthentication(); Future isAuthenticated() async { try { - final authenticated = await _flutterLocalAuthenticationPlugin.authenticate(); - return authenticated; - } catch (e) { + return await _localAuth.authenticate( + localizedReason: S.current.biometric_auth_reason, + options: AuthenticationOptions( + biometricOnly: true, + useErrorDialogs: true, + stickyAuth: false)); + } on PlatformException catch (e) { print(e); } + return false; } Future canCheckBiometrics() async { - bool canAuthenticate; try { - canAuthenticate = await _flutterLocalAuthenticationPlugin.canAuthenticate(); - } catch (error) { - print("Exception checking support. $error"); - canAuthenticate = false; + return await _localAuth.canCheckBiometrics; + } on PlatformException catch (e) { + print(e); } - return canAuthenticate; + return false; } } diff --git a/lib/locales/hausa_intl.dart b/lib/locales/hausa_intl.dart index 6cf757b60..749d39a4d 100644 --- a/lib/locales/hausa_intl.dart +++ b/lib/locales/hausa_intl.dart @@ -751,50 +751,6 @@ class HaMaterialLocalizations extends GlobalMaterialLocalizations { @override String get scrimOnTapHintRaw => "Scrip on Tap"; - - @override - // TODO: implement collapsedHint - String get collapsedHint => "collapsedHint"; - - @override - // TODO: implement expandedHint - String get expandedHint => "expandedHint"; - - @override - // TODO: implement expansionTileCollapsedHint - String get expansionTileCollapsedHint => "expansionTileCollapsedHint"; - - @override - // TODO: implement expansionTileCollapsedTapHint - String get expansionTileCollapsedTapHint => "expansionTileCollapsedTapHint"; - - @override - // TODO: implement expansionTileExpandedHint - String get expansionTileExpandedHint => "expansionTileExpandedHint"; - - @override - // TODO: implement expansionTileExpandedTapHint - String get expansionTileExpandedTapHint => "expansionTileExpandedTapHint"; - - @override - // TODO: implement scanTextButtonLabel - String get scanTextButtonLabel => "scanTextButtonLabel"; - - @override - // TODO: implement lookUpButtonLabel - String get lookUpButtonLabel => "lookUpButtonLabel"; - - @override - // TODO: implement menuDismissLabel - String get menuDismissLabel => "menuDismissLabel"; - - @override - // TODO: implement searchWebButtonLabel - String get searchWebButtonLabel => "searchWebButtonLabel"; - - @override - // TODO: implement shareButtonLabel - String get shareButtonLabel => "shareButtonLabel"; } /// Cupertino Support @@ -999,24 +955,4 @@ class HaCupertinoLocalizations extends GlobalCupertinoLocalizations { @override String get noSpellCheckReplacementsLabel => ""; - - @override - // TODO: implement clearButtonLabel - String get clearButtonLabel => "clearButtonLabel"; - - @override - // TODO: implement lookUpButtonLabel - String get lookUpButtonLabel => "lookUpButtonLabel"; - - @override - // TODO: implement menuDismissLabel - String get menuDismissLabel => "menuDismissLabel"; - - @override - // TODO: implement searchWebButtonLabel - String get searchWebButtonLabel => "searchWebButtonLabel"; - - @override - // TODO: implement shareButtonLabel - String get shareButtonLabel => "shareButtonLabel"; } diff --git a/lib/locales/yoruba_intl.dart b/lib/locales/yoruba_intl.dart index 3c720b80e..889c21cb7 100644 --- a/lib/locales/yoruba_intl.dart +++ b/lib/locales/yoruba_intl.dart @@ -1,3 +1,4 @@ + import 'dart:async'; import 'package:flutter/cupertino.dart'; @@ -163,62 +164,62 @@ const yoDateSymbols = { 'ọjọ́ Àbámẹ́ta', ], 'STANDALONEWEEKDAYS': [ - 'Ọjọ́ Ajé', - 'Ọjọ́ Ìsẹ́gun', - 'Ọjọ́ Ìsẹ́gun-Ẹtì', - 'Ọjọ́ Ìsẹ́gun-Ọ̀rú', - 'Ọjọ́ Àìkú', - 'Ọjọ́ Jímọ̀', - 'Ọjọ́ Àbámẹ́ta', - ], - 'SHORTWEEKDAYS': [ - 'Ajé', - 'Ìsẹ́gun', - 'Ìsẹ́gun-Ẹtì', - 'Ìsẹ́gun-Ọ̀rú', - 'Àìkú', - 'Jímọ̀', - 'Àbámẹ́ta', - ], - 'STANDALONESHORTWEEKDAYS': [ - 'Ajé', - 'Ìsẹ́gun', - 'Ìsẹ́gun-Ẹtì', - 'Ìsẹ́gun-Ọ̀rú', - 'Àìkú', - 'Jímọ̀', - 'Àbámẹ́ta', - ], - 'NARROWWEEKDAYS': [ - 'A', - 'A', - 'Ì', - 'A', - 'À', - 'J', - 'À', - ], - 'STANDALONENARROWWEEKDAYS': [ - 'A', - 'A', - 'Ì', - 'A', - 'À', - 'J', - 'À', - ], - 'SHORTQUARTERS': [ - 'K1', - 'K2', - 'K3', - 'K4', - ], - 'QUARTERS': [ - '1. kwata', - '2. kwata', - '3. kwata', - '4. kwata', - ], +'Ọjọ́ Ajé', +'Ọjọ́ Ìsẹ́gun', +'Ọjọ́ Ìsẹ́gun-Ẹtì', +'Ọjọ́ Ìsẹ́gun-Ọ̀rú', +'Ọjọ́ Àìkú', +'Ọjọ́ Jímọ̀', +'Ọjọ́ Àbámẹ́ta', +], +'SHORTWEEKDAYS': [ +'Ajé', +'Ìsẹ́gun', +'Ìsẹ́gun-Ẹtì', +'Ìsẹ́gun-Ọ̀rú', +'Àìkú', +'Jímọ̀', +'Àbámẹ́ta', +], +'STANDALONESHORTWEEKDAYS': [ +'Ajé', +'Ìsẹ́gun', +'Ìsẹ́gun-Ẹtì', +'Ìsẹ́gun-Ọ̀rú', +'Àìkú', +'Jímọ̀', +'Àbámẹ́ta', +], +'NARROWWEEKDAYS': [ +'A', +'A', +'Ì', +'A', +'À', +'J', +'À', +], +'STANDALONENARROWWEEKDAYS': [ +'A', +'A', +'Ì', +'A', +'À', +'J', +'À', +], +'SHORTQUARTERS': [ +'K1', +'K2', +'K3', +'K4', +], +'QUARTERS': [ +'1. kwata', +'2. kwata', +'3. kwata', +'4. kwata', +], 'AMPMS': [ 'a.m.', 'p.m.', @@ -315,339 +316,339 @@ class YoMaterialLocalizations extends GlobalMaterialLocalizations { }); // #docregion Getters - @override - String get moreButtonTooltip => r'Kò sí ìròhùn tí ó múni'; +@override +String get moreButtonTooltip => r'Kò sí ìròhùn tí ó múni'; - @override - String get aboutListTileTitleRaw => r'Fun Àpótí àwọn $applicationname'; +@override +String get aboutListTileTitleRaw => r'Fun Àpótí àwọn $applicationname'; - @override - String get alertDialogLabel => r'Ìròhùn Àlàyé'; +@override +String get alertDialogLabel => r'Ìròhùn Àlàyé'; // #enddocregion Getters - @override - String get anteMeridiemAbbreviation => r'AM'; +@override +String get anteMeridiemAbbreviation => r'AM'; - @override - String get backButtonTooltip => r'Fíran'; +@override +String get backButtonTooltip => r'Fíran'; - @override - String get cancelButtonLabel => r'FAGILE'; +@override +String get cancelButtonLabel => r'FAGILE'; - @override - String get closeButtonLabel => r'KÚ'; +@override +String get closeButtonLabel => r'KÚ'; - @override - String get closeButtonTooltip => r'Kú'; +@override +String get closeButtonTooltip => r'Kú'; - @override - String get collapsedIconTapHint => r'Tá'; +@override +String get collapsedIconTapHint => r'Tá'; - @override - String get continueButtonLabel => r'TÓ WÁ'; +@override +String get continueButtonLabel => r'TÓ WÁ'; - @override - String get copyButtonLabel => r'DÚPLÍKÉTÍ'; +@override +String get copyButtonLabel => r'DÚPLÍKÉTÍ'; - @override - String get cutButtonLabel => r'TÒ'; +@override +String get cutButtonLabel => r'TÒ'; - @override - String get deleteButtonTooltip => r'Máa kú'; +@override +String get deleteButtonTooltip => r'Máa kú'; - @override - String get dialogLabel => r'Ìròhùn'; +@override +String get dialogLabel => r'Ìròhùn'; - @override - String get drawerLabel => r'Àgbèjọ àwọn àpọ̀tí'; +@override +String get drawerLabel => r'Àgbèjọ àwọn àpọ̀tí'; - @override - String get expandedIconTapHint => r'Tá'; +@override +String get expandedIconTapHint => r'Tá'; - @override - String get firstPageTooltip => r'Ojú ewe'; +@override +String get firstPageTooltip => r'Ojú ewe'; - @override - String get hideAccountsLabel => r'Fí èrò àpótí wáyé sílẹ̀'; +@override +String get hideAccountsLabel => r'Fí èrò àpótí wáyé sílẹ̀'; - @override - String get lastPageTooltip => r'Ojú ayé'; +@override +String get lastPageTooltip => r'Ojú ayé'; - @override - String get licensesPageTitle => r'Ìròhùn Ọdún'; +@override +String get licensesPageTitle => r'Ìròhùn Ọdún'; - @override - String get modalBarrierDismissLabel => r'Sọ'; +@override +String get modalBarrierDismissLabel => r'Sọ'; - @override - String get nextMonthTooltip => r'Oṣù kọja'; +@override +String get nextMonthTooltip => r'Oṣù kọja'; - @override - String get nextPageTooltip => r'Ojú ọjọ́ kẹta'; +@override +String get nextPageTooltip => r'Ojú ọjọ́ kẹta'; - @override - String get okButtonLabel => r'Ò daájú'; - @override +@override +String get okButtonLabel => r'Ò daájú'; +@override // A custom drawer tooltip message. - String get openAppDrawerTooltip => r'Aya ntọju Iwe Awọn Aka'; +String get openAppDrawerTooltip => r'Aya ntọju Iwe Awọn Aka'; // #docregion Raw - @override - String get pageRowsInfoTitleRaw => r'$firstRow–$lastRow lati $rowCount'; +@override +String get pageRowsInfoTitleRaw => r'$firstRow–$lastRow lati $rowCount'; - @override - String get pageRowsInfoTitleApproximateRaw => r'$firstRow–$lastRow lati kiakia $rowCount'; +@override +String get pageRowsInfoTitleApproximateRaw => r'$firstRow–$lastRow lati kiakia $rowCount'; // #enddocregion Raw - @override - String get pasteButtonLabel => r'TÌ'; +@override +String get pasteButtonLabel => r'TÌ'; - @override - String get popupMenuLabel => r'Meniu Pop-up'; +@override +String get popupMenuLabel => r'Meniu Pop-up'; - @override - String get menuBarMenuLabel => r'Meniu Akọkọ'; +@override +String get menuBarMenuLabel => r'Meniu Akọkọ'; - @override - String get postMeridiemAbbreviation => r'PM'; +@override +String get postMeridiemAbbreviation => r'PM'; - @override - String get previousMonthTooltip => r'Oṣu Kanakana'; +@override +String get previousMonthTooltip => r'Oṣu Kanakana'; - @override - String get previousPageTooltip => r'Ojú ewé akọkọ kan'; +@override +String get previousPageTooltip => r'Ojú ewé akọkọ kan'; - @override - String get refreshIndicatorSemanticLabel => r'Gbiyanju'; +@override +String get refreshIndicatorSemanticLabel => r'Gbiyanju'; - @override - String? get remainingTextFieldCharacterCountFew => null; +@override +String? get remainingTextFieldCharacterCountFew => null; - @override - String? get remainingTextFieldCharacterCountMany => null; +@override +String? get remainingTextFieldCharacterCountMany => null; - @override - String get remainingTextFieldCharacterCountOne => r'1 àmì báálẹ̀'; +@override +String get remainingTextFieldCharacterCountOne => r'1 àmì báálẹ̀'; - @override - String get remainingTextFieldCharacterCountOther => r'$remainingCount àmì báálẹ̀'; +@override +String get remainingTextFieldCharacterCountOther => r'$remainingCount àmì báálẹ̀'; - @override - String? get remainingTextFieldCharacterCountTwo => null; +@override +String? get remainingTextFieldCharacterCountTwo => null; - @override - String get remainingTextFieldCharacterCountZero => r'Kò sí ìwọlé létà láti ń ṣe'; +@override +String get remainingTextFieldCharacterCountZero => r'Kò sí ìwọlé létà láti ń ṣe'; - @override - String get reorderItemDown => r'Jù sí ilẹ'; +@override +String get reorderItemDown => r'Jù sí ilẹ'; - @override - String get reorderItemLeft => r'Jù sí àrà'; +@override +String get reorderItemLeft => r'Jù sí àrà'; - @override - String get reorderItemRight => r'Jù sí òtútù'; +@override +String get reorderItemRight => r'Jù sí òtútù'; - @override - String get reorderItemToEnd => r'Jù sí ìbẹ̀jì'; +@override +String get reorderItemToEnd => r'Jù sí ìbẹ̀jì'; - @override - String get reorderItemToStart => r'Jù sí àkọ́kọ́'; +@override +String get reorderItemToStart => r'Jù sí àkọ́kọ́'; - @override - String get reorderItemUp => r'Jù sí ọ̀rùn'; +@override +String get reorderItemUp => r'Jù sí ọ̀rùn'; - @override - String get rowsPerPageTitle => r'Ìlò Fún àwọn Ìtọ́kasíwájú:'; +@override +String get rowsPerPageTitle => r'Ìlò Fún àwọn Ìtọ́kasíwájú:'; - @override - ScriptCategory get scriptCategory => ScriptCategory.englishLike; +@override +ScriptCategory get scriptCategory => ScriptCategory.englishLike; - @override - String get searchFieldLabel => 'Ṣẹda'; +@override +String get searchFieldLabel => 'Ṣẹda'; - @override - String get selectAllButtonLabel => 'FADỌHỌN DỌFÚN GBÁJÚMỌ̀'; +@override +String get selectAllButtonLabel => 'FADỌHỌN DỌFÚN GBÁJÚMỌ̀'; - @override - String? get selectedRowCountTitleFew => null; +@override +String? get selectedRowCountTitleFew => null; - @override - String? get selectedRowCountTitleMany => null; +@override +String? get selectedRowCountTitleMany => null; - @override - String get selectedRowCountTitleOne => '1 káyé'; +@override +String get selectedRowCountTitleOne => '1 káyé'; - @override - String get selectedRowCountTitleOther => r'$selectedRowCount káyé'; +@override +String get selectedRowCountTitleOther => r'$selectedRowCount káyé'; - @override - String? get selectedRowCountTitleTwo => null; +@override +String? get selectedRowCountTitleTwo => null; - @override - String get selectedRowCountTitleZero => 'Kò sí káyé ti o wọlé'; +@override +String get selectedRowCountTitleZero => 'Kò sí káyé ti o wọlé'; - @override - String get showAccountsLabel => 'Fi iyipada mu kọ'; +@override +String get showAccountsLabel => 'Fi iyipada mu kọ'; - @override - String get showMenuTooltip => 'Fi Meniu mu kọ'; +@override +String get showMenuTooltip => 'Fi Meniu mu kọ'; - @override - String get signedInLabel => 'Ọ̀nà'; +@override +String get signedInLabel => 'Ọ̀nà'; +@override +String get tabLabelRaw => r'Àwọn tabin $tabIndex lati $tabCount'; + @override - String get tabLabelRaw => r'Àwọn tabin $tabIndex lati $tabCount'; +TimeOfDayFormat get timeOfDayFormatRaw => TimeOfDayFormat.h_colon_mm_space_a; - @override - TimeOfDayFormat get timeOfDayFormatRaw => TimeOfDayFormat.h_colon_mm_space_a; +@override +String get timePickerHourModeAnnouncement => 'Tuntun waqtu lọ'; - @override - String get timePickerHourModeAnnouncement => 'Tuntun waqtu lọ'; +@override +String get timePickerMinuteModeAnnouncement => 'Tuntun daɗi minti'; - @override - String get timePickerMinuteModeAnnouncement => 'Tuntun daɗi minti'; +@override +String get viewLicensesButtonLabel => 'WO NIKI'; - @override - String get viewLicensesButtonLabel => 'WO NIKI'; +@override +List get narrowWeekdays => const ['L', 'L', 'A', 'O', 'Ọ', 'Ẹ', 'Ẹ']; - @override - List get narrowWeekdays => const ['L', 'L', 'A', 'O', 'Ọ', 'Ẹ', 'Ẹ']; +@override +int get firstDayOfWeekIndex => 0; - @override - int get firstDayOfWeekIndex => 0; +static const LocalizationsDelegate delegate = +_YoMaterialLocalizationsDelegate(); - static const LocalizationsDelegate delegate = - _YoMaterialLocalizationsDelegate(); +@override +String get calendarModeButtonLabel => 'Tọ́rọ̀ kálẹ̀ndà'; - @override - String get calendarModeButtonLabel => 'Tọ́rọ̀ kálẹ̀ndà'; +@override +String get dateHelpText => 'mm/dd/yyyy'; - @override - String get dateHelpText => 'mm/dd/yyyy'; +@override +String get dateInputLabel => 'Firanṣẹ̀ Ọjọ́'; - @override - String get dateInputLabel => 'Firanṣẹ̀ Ọjọ́'; +@override +String get dateOutOfRangeLabel => 'Nínú iwọ̀ lọ́wọ́'; - @override - String get dateOutOfRangeLabel => 'Nínú iwọ̀ lọ́wọ́'; +@override +String get datePickerHelpText => 'WÁSÍ'; - @override - String get datePickerHelpText => 'WÁSÍ'; +@override +String get dateRangeEndDateSemanticLabelRaw => r'Ọjọ́ tuntun to ṣà'; - @override - String get dateRangeEndDateSemanticLabelRaw => r'Ọjọ́ tuntun to ṣà'; - - @override - String get dateRangeEndLabel => 'Ọjọ́ tuntun to ṣà'; +@override +String get dateRangeEndLabel => 'Ọjọ́ tuntun to ṣà'; - @override - String get dateRangePickerHelpText => 'WÁSÍ ÌGBÀ'; +@override +String get dateRangePickerHelpText => 'WÁSÍ ÌGBÀ'; - @override - String get dateRangeStartDateSemanticLabelRaw => 'Ọjọ́ tuntun ti dá'; +@override +String get dateRangeStartDateSemanticLabelRaw => 'Ọjọ́ tuntun ti dá'; - @override - String get dateRangeStartLabel => 'Ọjọ́ tuntun ti dá'; +@override +String get dateRangeStartLabel => 'Ọjọ́ tuntun ti dá'; - @override - String get dateSeparator => '/'; +@override +String get dateSeparator => '/'; - @override - String get dialModeButtonLabel => 'Tọ́rọ̀ wakati'; +@override +String get dialModeButtonLabel => 'Tọ́rọ̀ wakati'; - @override - String get inputDateModeButtonLabel => 'Tọ́rọ̀ firanṣẹ̀ ọjọ́'; +@override +String get inputDateModeButtonLabel => 'Tọ́rọ̀ firanṣẹ̀ ọjọ́'; - @override - String get inputTimeModeButtonLabel => 'Tọ́rọ̀ wakati bayi lọ́wọ́'; +@override +String get inputTimeModeButtonLabel => 'Tọ́rọ̀ wakati bayi lọ́wọ́'; - @override - String get invalidDateFormatLabel => 'Akọ́kọ́tọ́ tó jẹ́kúnrin'; +@override +String get invalidDateFormatLabel => 'Akọ́kọ́tọ́ tó jẹ́kúnrin'; - @override - String get invalidDateRangeLabel => 'Àmì jẹ́ káàkiri lẹ́yìn ilé'; +@override +String get invalidDateRangeLabel => 'Àmì jẹ́ káàkiri lẹ́yìn ilé'; - @override - String get invalidTimeLabel => 'Akọ́kọ́tọ́ àkójọ ìwádìí'; +@override +String get invalidTimeLabel => 'Akọ́kọ́tọ́ àkójọ ìwádìí'; - @override - String get licensesPackageDetailTextOther => r'$licenseCount àwọn níkí'; +@override +String get licensesPackageDetailTextOther => r'$licenseCount àwọn níkí'; - @override - String get saveButtonLabel => 'TÙN DÁRA'; +@override +String get saveButtonLabel => 'TÙN DÁRA'; - @override - String get selectYearSemanticsLabel => 'Fọ́ọ̀ shẹ́kàrà'; +@override +String get selectYearSemanticsLabel => 'Fọ́ọ̀ shẹ́kàrà'; - @override - String get timePickerDialHelpText => 'WÁSÍ WÁKÀTÌ'; +@override +String get timePickerDialHelpText => 'WÁSÍ WÁKÀTÌ'; - @override - String get timePickerHourLabel => 'Wákàtì àṣà'; +@override +String get timePickerHourLabel => 'Wákàtì àṣà'; - @override - String get timePickerInputHelpText => 'Shìgárà wákàtì'; +@override +String get timePickerInputHelpText => 'Shìgárà wákàtì'; - @override - String get timePickerMinuteLabel => 'Mìntì'; +@override +String get timePickerMinuteLabel => 'Mìntì'; - @override - String get unspecifiedDate => 'Ọjọ̀kúnrin'; +@override +String get unspecifiedDate => 'Ọjọ̀kúnrin'; - @override - String get unspecifiedDateRange => 'Ọjọ̀kúnrin àdáyọ̀'; +@override +String get unspecifiedDateRange => 'Ọjọ̀kúnrin àdáyọ̀'; - @override - String get keyboardKeyAlt => 'Alt'; +@override +String get keyboardKeyAlt => 'Alt'; - @override - String get keyboardKeyAltGraph => 'AltGraph'; +@override +String get keyboardKeyAltGraph => 'AltGraph'; - @override - String get keyboardKeyBackspace => 'Báckspàcè'; +@override +String get keyboardKeyBackspace => 'Báckspàcè'; - @override - String get keyboardKeyCapsLock => 'Caps Lock'; +@override +String get keyboardKeyCapsLock => 'Caps Lock'; - @override - String get keyboardKeyChannelDown => 'Báyàkàmmàlàsàké'; +@override +String get keyboardKeyChannelDown => 'Báyàkàmmàlàsàké'; - @override - String get keyboardKeyChannelUp => 'Yíkàmmàlàsàké'; +@override +String get keyboardKeyChannelUp => 'Yíkàmmàlàsàké'; - @override - String get keyboardKeyControl => 'Kọ́ntírọ̀l'; +@override +String get keyboardKeyControl => 'Kọ́ntírọ̀l'; - @override - String get keyboardKeyDelete => 'Shápè'; +@override +String get keyboardKeyDelete => 'Shápè'; - @override - String get keyboardKeyEject => 'Èjẹ̀tì'; +@override +String get keyboardKeyEject => 'Èjẹ̀tì'; - @override - String get keyboardKeyEnd => 'Tàbí'; +@override +String get keyboardKeyEnd => 'Tàbí'; - @override - String get keyboardKeyEscape => 'Tòkè'; +@override +String get keyboardKeyEscape => 'Tòkè'; @override - String get keyboardKeyFn => 'Fn'; +String get keyboardKeyFn => 'Fn'; - @override - String get keyboardKeyHome => 'Ile'; +@override +String get keyboardKeyHome => 'Ile'; - @override - String get keyboardKeyInsert => 'Fi sori'; +@override +String get keyboardKeyInsert => 'Fi sori'; - @override - String get keyboardKeyMeta => 'Meta'; +@override +String get keyboardKeyMeta => 'Meta'; - @override - String get keyboardKeyMetaMacOs => 'Amfani pẹlu Command'; +@override +String get keyboardKeyMetaMacOs => 'Amfani pẹlu Command'; - @override - String get keyboardKeyMetaWindows => 'Windows'; +@override +String get keyboardKeyMetaWindows => 'Windows'; @override String get keyboardKeyNumLock => 'Num Lock'; @@ -750,50 +751,6 @@ class YoMaterialLocalizations extends GlobalMaterialLocalizations { @override String get scrimOnTapHintRaw => "Scrip on Tap"; - - @override - // TODO: implement collapsedHint - String get collapsedHint => "collapsedHint"; - - @override - // TODO: implement expandedHint - String get expandedHint => "expandedHint"; - - @override - // TODO: implement expansionTileCollapsedHint - String get expansionTileCollapsedHint => "expansionTileCollapsedHint"; - - @override - // TODO: implement expansionTileCollapsedTapHint - String get expansionTileCollapsedTapHint => "expansionTileCollapsedTapHint"; - - @override - // TODO: implement expansionTileExpandedHint - String get expansionTileExpandedHint => "expansionTileExpandedHint"; - - @override - // TODO: implement expansionTileExpandedTapHint - String get expansionTileExpandedTapHint => "expansionTileExpandedTapHint"; - - @override - // TODO: implement scanTextButtonLabel - String get scanTextButtonLabel => "scanTextButtonLabel"; - - @override - // TODO: implement lookUpButtonLabel - String get lookUpButtonLabel => "lookUpButtonLabel"; - - @override - // TODO: implement menuDismissLabel - String get menuDismissLabel => "menuDismissLabel"; - - @override - // TODO: implement searchWebButtonLabel - String get searchWebButtonLabel => "searchWebButtonLabel"; - - @override - // TODO: implement shareButtonLabel - String get shareButtonLabel => "shareButtonLabel"; } /// Cupertino Support @@ -864,158 +821,138 @@ class YoCupertinoLocalizations extends GlobalCupertinoLocalizations { required super.singleDigitSecondFormat, }); - @override - String get alertDialogLabel => 'Àdàkárò'; +@override +String get alertDialogLabel => 'Àdàkárò'; - @override - String get anteMeridiemAbbreviation => 'AM'; +@override +String get anteMeridiemAbbreviation => 'AM'; - @override - String get copyButtonLabel => 'Kòpy'; +@override +String get copyButtonLabel => 'Kòpy'; - @override - String get cutButtonLabel => 'Kọ́t'; +@override +String get cutButtonLabel => 'Kọ́t'; - @override - String get datePickerDateOrderString => 'mdy'; +@override +String get datePickerDateOrderString => 'mdy'; - @override - String get datePickerDateTimeOrderString => 'date_time_dayPeriod'; +@override +String get datePickerDateTimeOrderString => 'date_time_dayPeriod'; - @override - String? get datePickerHourSemanticsLabelFew => null; +@override +String? get datePickerHourSemanticsLabelFew => null; - @override - String? get datePickerHourSemanticsLabelMany => null; +@override +String? get datePickerHourSemanticsLabelMany => null; - @override - String? get datePickerHourSemanticsLabelOne => r"$hour o'clock"; +@override +String? get datePickerHourSemanticsLabelOne => r"$hour o'clock"; - @override - String get datePickerHourSemanticsLabelOther => r"$hour o'clock"; +@override +String get datePickerHourSemanticsLabelOther => r"$hour o'clock"; - @override - String? get datePickerHourSemanticsLabelTwo => null; +@override +String? get datePickerHourSemanticsLabelTwo => null; - @override - String? get datePickerHourSemanticsLabelZero => null; +@override +String? get datePickerHourSemanticsLabelZero => null; - @override - String? get datePickerMinuteSemanticsLabelFew => null; +@override +String? get datePickerMinuteSemanticsLabelFew => null; - @override - String? get datePickerMinuteSemanticsLabelMany => null; +@override +String? get datePickerMinuteSemanticsLabelMany => null; - @override - String? get datePickerMinuteSemanticsLabelOne => '1 wakati'; +@override +String? get datePickerMinuteSemanticsLabelOne => '1 wakati'; - @override - String get datePickerMinuteSemanticsLabelOther => r'$minute wakati'; +@override +String get datePickerMinuteSemanticsLabelOther => r'$minute wakati'; - @override - String? get datePickerMinuteSemanticsLabelTwo => null; +@override +String? get datePickerMinuteSemanticsLabelTwo => null; - @override - String? get datePickerMinuteSemanticsLabelZero => null; +@override +String? get datePickerMinuteSemanticsLabelZero => null; - @override - String get modalBarrierDismissLabel => 'Búta'; +@override +String get modalBarrierDismissLabel => 'Búta'; - @override - String get pasteButtonLabel => 'Tẹ́ẹ́'; +@override +String get pasteButtonLabel => 'Tẹ́ẹ́'; - @override - String get postMeridiemAbbreviation => 'PM'; +@override +String get postMeridiemAbbreviation => 'PM'; - @override - String get searchTextFieldPlaceholderLabel => 'Wúró àtúntà'; +@override +String get searchTextFieldPlaceholderLabel => 'Wúró àtúntà'; - @override - String get selectAllButtonLabel => 'Fírànsé gbógbo'; +@override +String get selectAllButtonLabel => 'Fírànsé gbógbo'; - @override - String get tabSemanticsLabelRaw => r'Tab $tabIndex nínú $tabCount'; +@override +String get tabSemanticsLabelRaw => r'Tab $tabIndex nínú $tabCount'; - @override - String? get timerPickerHourLabelFew => null; +@override +String? get timerPickerHourLabelFew => null; - @override - String? get timerPickerHourLabelMany => null; +@override +String? get timerPickerHourLabelMany => null; - @override - String? get timerPickerHourLabelOne => 'òǹdì'; +@override +String? get timerPickerHourLabelOne => 'òǹdì'; - @override - String get timerPickerHourLabelOther => 'òǹdì'; +@override +String get timerPickerHourLabelOther => 'òǹdì'; - @override - String? get timerPickerHourLabelTwo => null; +@override +String? get timerPickerHourLabelTwo => null; - @override - String? get timerPickerHourLabelZero => null; +@override +String? get timerPickerHourLabelZero => null; - @override - String? get timerPickerMinuteLabelFew => null; +@override +String? get timerPickerMinuteLabelFew => null; - @override - String? get timerPickerMinuteLabelMany => null; +@override +String? get timerPickerMinuteLabelMany => null; - @override - String? get timerPickerMinuteLabelOne => 'wakati.'; +@override +String? get timerPickerMinuteLabelOne => 'wakati.'; - @override - String get timerPickerMinuteLabelOther => 'wakati.'; +@override +String get timerPickerMinuteLabelOther => 'wakati.'; - @override - String? get timerPickerMinuteLabelTwo => null; +@override +String? get timerPickerMinuteLabelTwo => null; - @override - String? get timerPickerMinuteLabelZero => null; +@override +String? get timerPickerMinuteLabelZero => null; - @override - String? get timerPickerSecondLabelFew => null; +@override +String? get timerPickerSecondLabelFew => null; - @override - String? get timerPickerSecondLabelMany => null; +@override +String? get timerPickerSecondLabelMany => null; - @override - String? get timerPickerSecondLabelOne => 'dákìkà.'; +@override +String? get timerPickerSecondLabelOne => 'dákìkà.'; - @override - String get timerPickerSecondLabelOther => 'dákìkà.'; +@override +String get timerPickerSecondLabelOther => 'dákìkà.'; - @override - String? get timerPickerSecondLabelTwo => null; +@override +String? get timerPickerSecondLabelTwo => null; - @override - String? get timerPickerSecondLabelZero => null; +@override +String? get timerPickerSecondLabelZero => null; - @override - String get todayLabel => 'Oyọ'; +@override +String get todayLabel => 'Oyọ'; static const LocalizationsDelegate delegate = _YoCupertinoLocalizationsDelegate(); @override String get noSpellCheckReplacementsLabel => ""; - - @override - // TODO: implement clearButtonLabel - String get clearButtonLabel => "clearButtonLabel"; - - @override - // TODO: implement lookUpButtonLabel - String get lookUpButtonLabel => "lookUpButtonLabel"; - - @override - // TODO: implement menuDismissLabel - String get menuDismissLabel => "menuDismissLabel"; - - @override - // TODO: implement searchWebButtonLabel - String get searchWebButtonLabel => "searchWebButtonLabel"; - - @override - // TODO: implement shareButtonLabel - String get shareButtonLabel => "shareButtonLabel"; } diff --git a/lib/src/screens/settings/security_backup_page.dart b/lib/src/screens/settings/security_backup_page.dart index 1f0f58ad4..e559e9b15 100644 --- a/lib/src/screens/settings/security_backup_page.dart +++ b/lib/src/screens/settings/security_backup_page.dart @@ -1,5 +1,3 @@ -import 'dart:io'; - import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/routes.dart'; @@ -60,7 +58,7 @@ class SecurityBackupPage extends BasePage { .shouldRequireTOTP2FAForAllSecurityAndBackupSettings, ), ), - if (DeviceInfo.instance.isMobile || Platform.isMacOS || Platform.isLinux) + if (DeviceInfo.instance.isMobile) Observer(builder: (_) { return SettingsSwitcherCell( title: S.current.settings_allow_biometrical_authentication, diff --git a/lib/src/screens/settings/tor_page.dart b/lib/src/screens/settings/tor_page.dart index 2f544be35..ae1ef1677 100644 --- a/lib/src/screens/settings/tor_page.dart +++ b/lib/src/screens/settings/tor_page.dart @@ -146,7 +146,7 @@ class ConnectScreen extends StatelessWidget { ElevatedButton( onPressed: connect, style: ElevatedButton.styleFrom( - // primary: Colors.blue, + primary: Colors.blue, padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30), @@ -211,7 +211,7 @@ class DisconnectScreen extends StatelessWidget { ElevatedButton( onPressed: disconnect, style: ElevatedButton.styleFrom( - // primary: Colors.red, + primary: Colors.red, padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30), diff --git a/lib/src/widgets/validable_annotated_editable_text.dart b/lib/src/widgets/validable_annotated_editable_text.dart index 7ea928d8a..6c3fc4f16 100644 --- a/lib/src/widgets/validable_annotated_editable_text.dart +++ b/lib/src/widgets/validable_annotated_editable_text.dart @@ -1,14 +1,8 @@ +import 'package:cake_wallet/core/seed_validator.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; - -extension Compare on Comparable { - bool operator <=(T other) => compareTo(other) <= 0; - bool operator >=(T other) => compareTo(other) >= 0; - bool operator <(T other) => compareTo(other) < 0; - bool operator >(T other) => compareTo(other) > 0; -} - -class Annotation implements Comparable { +class Annotation extends Comparable { Annotation({required this.range, required this.style}); final TextRange range; @@ -18,7 +12,7 @@ class Annotation implements Comparable { int compareTo(Annotation other) => range.start.compareTo(other.range.start); } -class TextAnnotation implements Comparable { +class TextAnnotation extends Comparable { TextAnnotation({required this.text, required this.style}); final TextStyle style; diff --git a/lib/view_model/auth_view_model.dart b/lib/view_model/auth_view_model.dart index 0e6590845..e50f4db0c 100644 --- a/lib/view_model/auth_view_model.dart +++ b/lib/view_model/auth_view_model.dart @@ -1,6 +1,5 @@ import 'dart:async'; import 'package:flutter/material.dart'; -import 'package:flutter_local_authentication/flutter_local_authentication.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/view_model/auth_state.dart'; @@ -106,14 +105,16 @@ abstract class AuthViewModelBase with Store { @action Future biometricAuth() async { - final _flutterLocalAuthenticationPlugin = FlutterLocalAuthentication(); - try { - final authenticated = await _flutterLocalAuthenticationPlugin.authenticate(); - if (!authenticated) { - throw Exception('Biometric authentication failed'); + final canBiometricAuth = await _biometricAuth.canCheckBiometrics(); + + if (canBiometricAuth) { + final isAuthenticated = await _biometricAuth.isAuthenticated(); + + if (isAuthenticated) { + state = ExecutedSuccessfullyState(); + } } - state = ExecutedSuccessfullyState(); } catch (e) { state = FailureState(e.toString()); } diff --git a/pubspec_base.yaml b/pubspec_base.yaml index e1022864c..3ec3e7978 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -33,8 +33,8 @@ dependencies: dio: ^4.0.6 hive: ^2.2.3 hive_flutter: ^1.1.0 + local_auth: ^2.1.0 local_auth_android: 1.0.21 - flutter_local_authentication: ^1.2.0 package_info: ^2.0.0 #package_info_plus: ^1.4.2 devicelocale: diff --git a/pubspec_description.yaml b/pubspec_description.yaml index b51fe96d6..ebb6bf001 100644 --- a/pubspec_description.yaml +++ b/pubspec_description.yaml @@ -4,4 +4,4 @@ version: 0.0.0 publish_to: none environment: - sdk: ">=3.1.0 <4.0.0" \ No newline at end of file + sdk: ">=2.17.5 <3.0.0" \ No newline at end of file From 65799a8764b339c2db329400d74bd7462632e63d Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Wed, 24 Apr 2024 03:04:16 +0100 Subject: [PATCH 187/241] fix: Issue with the privateKey of Solana wallets being different accross various apps (#1400) --- cw_solana/lib/solana_wallet.dart | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart index ad58c4293..43a6d0b83 100644 --- a/cw_solana/lib/solana_wallet.dart +++ b/cw_solana/lib/solana_wallet.dart @@ -27,6 +27,7 @@ import 'package:hex/hex.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:solana/base58.dart'; import 'package:solana/metaplex.dart' as metaplex; import 'package:solana/solana.dart'; @@ -108,7 +109,17 @@ abstract class SolanaWalletBase String? get seed => _mnemonic; @override - String get privateKey => HEX.encode(_keyPairData!.bytes); + String get privateKey { + final privateKeyBytes = _keyPairData!.bytes; + + final publicKeyBytes = _keyPairData!.publicKey.bytes; + + final encodedBytes = privateKeyBytes + publicKeyBytes; + + final privateKey = base58encode(encodedBytes); + + return privateKey; + } Future init() async { final boxName = "${walletInfo.name.replaceAll(" ", "_")}_${SPLToken.boxName}"; @@ -135,8 +146,8 @@ abstract class SolanaWalletBase assert(mnemonic != null || privateKey != null); if (privateKey != null) { - final privateKeyBytes = HEX.decode(privateKey); - return await Wallet.fromPrivateKeyBytes(privateKey: privateKeyBytes); + final privateKeyBytes = base58decode(privateKey); + return await Wallet.fromPrivateKeyBytes(privateKey: privateKeyBytes.take(32).toList()); } return Wallet.fromMnemonic(mnemonic!, account: 0, change: 0); From dcfb2b2b730f27a849f0e866acba48517b821195 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Wed, 24 Apr 2024 17:00:53 -0700 Subject: [PATCH 188/241] fix empty string case (#1401) * bio auth mac fix * remove comment and change duration from 2 to 0 * cherry pick previous changes * fix empty string case * add support for path for all currency types * disable paths on electrum and monero nodes * undo mac auth changes * stuff I missed * 1 last thing * another thing I missed --- cw_bitcoin/pubspec.lock | 32 +++++++++----- cw_core/lib/node.dart | 6 +-- cw_core/pubspec.lock | 32 +++++++++----- cw_core/pubspec.yaml | 1 + cw_haven/pubspec.lock | 44 +++++++++++-------- cw_monero/example/pubspec.lock | 30 ++++++++----- cw_monero/pubspec.lock | 44 +++++++++++-------- cw_nano/pubspec.lock | 44 +++++++++++-------- lib/core/node_address_validator.dart | 6 ++- lib/entities/biometric_auth.dart | 2 +- lib/locales/yoruba_intl.dart | 2 +- lib/src/screens/nodes/widgets/node_form.dart | 26 ++++++----- .../validable_annotated_editable_text.dart | 2 +- lib/view_model/auth_view_model.dart | 2 +- .../node_create_or_edit_view_model.dart | 19 +++++++- 15 files changed, 182 insertions(+), 110 deletions(-) diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 3d828243c..53cf550c8 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -217,10 +217,10 @@ packages: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.17.2" convert: dependency: transitive description: @@ -434,18 +434,18 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.5.0" meta: dependency: transitive description: @@ -663,10 +663,10 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: @@ -711,10 +711,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.0" timing: dependency: transitive description: @@ -748,13 +748,21 @@ packages: source: hosted version: "2.1.4" watcher: - dependency: transitive + dependency: "direct overridden" description: name: watcher sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.dev" source: hosted version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" web_socket_channel: dependency: transitive description: @@ -788,5 +796,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.1.0-185.0.dev <4.0.0" flutter: ">=3.10.0" diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index d7e91d692..9d0806851 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -10,7 +10,7 @@ import 'package:http/io_client.dart' as ioc; part 'node.g.dart'; -Uri createUriFromElectrumAddress(String address) => Uri.tryParse('tcp://$address')!; +Uri createUriFromElectrumAddress(String address, String path) => Uri.tryParse('tcp://$address$path')!; @HiveType(typeId: Node.typeId) class Node extends HiveObject with Keyable { @@ -83,7 +83,7 @@ class Node extends HiveObject with Keyable { case WalletType.bitcoin: case WalletType.litecoin: case WalletType.bitcoinCash: - return createUriFromElectrumAddress(uriRaw); + return createUriFromElectrumAddress(uriRaw, path ?? ''); case WalletType.nano: case WalletType.banano: if (isSSL) { @@ -94,7 +94,7 @@ class Node extends HiveObject with Keyable { case WalletType.ethereum: case WalletType.polygon: case WalletType.solana: - return Uri.https(uriRaw, ''); + return Uri.https(uriRaw, path ?? ''); default: throw Exception('Unexpected type ${type.toString()} for Node uri'); } diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock index 678e57b54..aef76f300 100644 --- a/cw_core/pubspec.lock +++ b/cw_core/pubspec.lock @@ -149,10 +149,10 @@ packages: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.17.2" convert: dependency: transitive description: @@ -343,18 +343,18 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.5.0" meta: dependency: transitive description: @@ -564,10 +564,10 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: @@ -612,10 +612,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.0" timing: dependency: transitive description: @@ -641,13 +641,21 @@ packages: source: hosted version: "2.1.4" watcher: - dependency: transitive + dependency: "direct overridden" description: name: watcher sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.dev" source: hosted version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" web_socket_channel: dependency: transitive description: @@ -681,5 +689,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.1.0-185.0.dev <4.0.0" flutter: ">=3.10.0" diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml index 04a840d4e..36fe9967e 100644 --- a/cw_core/pubspec.yaml +++ b/cw_core/pubspec.yaml @@ -33,6 +33,7 @@ dev_dependencies: mobx_codegen: ^2.0.7 hive_generator: ^2.0.1 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_haven/pubspec.lock b/cw_haven/pubspec.lock index b0a350cc7..d84523539 100644 --- a/cw_haven/pubspec.lock +++ b/cw_haven/pubspec.lock @@ -69,10 +69,10 @@ packages: dependency: transitive description: name: build_daemon - sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" + sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "4.0.0" build_resolvers: dependency: "direct dev" description: @@ -85,10 +85,10 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.9" build_runner_core: dependency: transitive description: @@ -149,10 +149,10 @@ packages: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.17.2" convert: dependency: transitive description: @@ -350,18 +350,18 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.5.0" meta: dependency: transitive description: @@ -563,10 +563,10 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: @@ -611,10 +611,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.0" timing: dependency: transitive description: @@ -640,13 +640,21 @@ packages: source: hosted version: "2.1.4" watcher: - dependency: transitive + dependency: "direct overridden" description: name: watcher - sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" web_socket_channel: dependency: transitive description: @@ -680,5 +688,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.1.0-185.0.dev <4.0.0" flutter: ">=3.7.0" diff --git a/cw_monero/example/pubspec.lock b/cw_monero/example/pubspec.lock index c9ca8d92b..ece0d4395 100644 --- a/cw_monero/example/pubspec.lock +++ b/cw_monero/example/pubspec.lock @@ -53,10 +53,10 @@ packages: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.17.2" convert: dependency: transitive description: @@ -213,18 +213,18 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.5.0" meta: dependency: transitive description: @@ -354,10 +354,10 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: @@ -394,10 +394,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.0" typed_data: dependency: transitive description: @@ -414,6 +414,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" win32: dependency: transitive description: @@ -431,5 +439,5 @@ packages: source: hosted version: "0.2.0+3" sdks: - dart: ">=3.0.6 <4.0.0" + dart: ">=3.1.0-185.0.dev <4.0.0" flutter: ">=3.7.0" diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index 0f8f2c90e..b736f80cb 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -69,10 +69,10 @@ packages: dependency: transitive description: name: build_daemon - sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" + sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "4.0.0" build_resolvers: dependency: "direct dev" description: @@ -85,10 +85,10 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.9" build_runner_core: dependency: transitive description: @@ -149,10 +149,10 @@ packages: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.17.2" convert: dependency: transitive description: @@ -366,18 +366,18 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.5.0" meta: dependency: transitive description: @@ -587,10 +587,10 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: @@ -635,10 +635,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.0" timing: dependency: transitive description: @@ -664,13 +664,21 @@ packages: source: hosted version: "2.1.4" watcher: - dependency: transitive + dependency: "direct overridden" description: name: watcher - sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" web_socket_channel: dependency: transitive description: @@ -704,5 +712,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=3.0.6 <4.0.0" + dart: ">=3.1.0-185.0.dev <4.0.0" flutter: ">=3.7.0" diff --git a/cw_nano/pubspec.lock b/cw_nano/pubspec.lock index a42bb9ab4..0ebc5e75f 100644 --- a/cw_nano/pubspec.lock +++ b/cw_nano/pubspec.lock @@ -93,10 +93,10 @@ packages: dependency: transitive description: name: build_daemon - sha256: "757153e5d9cd88253cb13f28c2fb55a537dc31fefd98137549895b5beb7c6169" + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "4.0.1" build_resolvers: dependency: transitive description: @@ -109,10 +109,10 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.9" build_runner_core: dependency: transitive description: @@ -173,10 +173,10 @@ packages: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.17.2" convert: dependency: transitive description: @@ -419,18 +419,18 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.5.0" meta: dependency: transitive description: @@ -713,10 +713,10 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: @@ -761,10 +761,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.0" timing: dependency: transitive description: @@ -790,13 +790,21 @@ packages: source: hosted version: "2.1.4" watcher: - dependency: transitive + dependency: "direct overridden" description: name: watcher - sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" web_socket_channel: dependency: transitive description: @@ -830,5 +838,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.1.0-185.0.dev <4.0.0" flutter: ">=3.7.0" diff --git a/lib/core/node_address_validator.dart b/lib/core/node_address_validator.dart index c1fe4ba91..0c8a0c37c 100644 --- a/lib/core/node_address_validator.dart +++ b/lib/core/node_address_validator.dart @@ -11,5 +11,9 @@ class NodeAddressValidator extends TextValidator { class NodePathValidator extends TextValidator { NodePathValidator() - : super(errorMessage: S.current.error_text_node_address, pattern: '^([/0-9a-zA-Z.\-]+)?\$'); + : super( + errorMessage: S.current.error_text_node_address, + pattern: '^([/0-9a-zA-Z.\-]+)?\$', + isAutovalidate: true, + ); } diff --git a/lib/entities/biometric_auth.dart b/lib/entities/biometric_auth.dart index febbfa469..4b2bfd906 100644 --- a/lib/entities/biometric_auth.dart +++ b/lib/entities/biometric_auth.dart @@ -29,4 +29,4 @@ class BiometricAuth { return false; } -} +} \ No newline at end of file diff --git a/lib/locales/yoruba_intl.dart b/lib/locales/yoruba_intl.dart index 889c21cb7..f16188529 100644 --- a/lib/locales/yoruba_intl.dart +++ b/lib/locales/yoruba_intl.dart @@ -955,4 +955,4 @@ String get todayLabel => 'Oyọ'; @override String get noSpellCheckReplacementsLabel => ""; -} +} \ No newline at end of file diff --git a/lib/src/screens/nodes/widgets/node_form.dart b/lib/src/screens/nodes/widgets/node_form.dart index e8c4b0ab3..74daa41cc 100644 --- a/lib/src/screens/nodes/widgets/node_form.dart +++ b/lib/src/screens/nodes/widgets/node_form.dart @@ -96,18 +96,20 @@ class NodeForm extends StatelessWidget { ], ), SizedBox(height: 10.0), - Row( - children: [ - Expanded( - child: BaseTextFormField( - controller: _pathController, - hintText: "/path", - validator: NodePathValidator(), - ), - ) - ], - ), - SizedBox(height: 10.0), + if (nodeViewModel.hasPathSupport) ...[ + Row( + children: [ + Expanded( + child: BaseTextFormField( + controller: _pathController, + hintText: "/path", + validator: NodePathValidator(), + ), + ) + ], + ), + SizedBox(height: 10.0), + ], Row( children: [ Expanded( diff --git a/lib/src/widgets/validable_annotated_editable_text.dart b/lib/src/widgets/validable_annotated_editable_text.dart index 6c3fc4f16..16ccc76f6 100644 --- a/lib/src/widgets/validable_annotated_editable_text.dart +++ b/lib/src/widgets/validable_annotated_editable_text.dart @@ -167,4 +167,4 @@ class ValidatableAnnotatedEditableTextState extends EditableTextState { return TextSpan(style: widget.style, text: text); } -} +} \ No newline at end of file diff --git a/lib/view_model/auth_view_model.dart b/lib/view_model/auth_view_model.dart index e50f4db0c..4fb93cfea 100644 --- a/lib/view_model/auth_view_model.dart +++ b/lib/view_model/auth_view_model.dart @@ -125,4 +125,4 @@ abstract class AuthViewModelBase with Store { _authService.saveLastAuthTime(); } } -} +} \ No newline at end of file diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart index 283a32cbf..7fe3d1c98 100644 --- a/lib/view_model/node_list/node_create_or_edit_view_model.dart +++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart @@ -69,6 +69,24 @@ abstract class NodeCreateOrEditViewModelBase with Store { bool get hasTestnetSupport => _walletType == WalletType.bitcoin; + bool get hasPathSupport { + switch (_walletType) { + case WalletType.ethereum: + case WalletType.polygon: + case WalletType.solana: + case WalletType.banano: + case WalletType.nano: + return true; + case WalletType.none: + case WalletType.monero: + case WalletType.haven: + case WalletType.litecoin: + case WalletType.bitcoinCash: + case WalletType.bitcoin: + return false; + } + } + String get uri { var uri = address; @@ -217,7 +235,6 @@ abstract class NodeCreateOrEditViewModelBase with Store { final port = uri.port.toString(); final path = uri.path; - setAddress(ipAddress); setPath(path); setPassword(rpcPassword); From 2ac81250c24ebe84610242ac62591a3e063d974f Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Thu, 25 Apr 2024 02:14:11 +0100 Subject: [PATCH 189/241] CW-615-Add-Check-For-Contract-Address (#1387) * feat: Check if address is a valid Externally Owned Address * feat: Check if the EVM address received when exchanging tokens is a valid EOA address * move the contract address check to be only in the case of ThorChain [skip ci] * some enhancements * feat: Implement check for contract address for inputAddress when exchanging to ETH * fix: Remove previous implementation and clean up current implementation for the check for contract address * chore: Remove unneed space * chore: Remove unneed space --------- Co-authored-by: OmarHatem --- lib/core/create_trade_result.dart | 9 ++ .../exchange/exchange_view_model.dart | 120 +++++++++++++++--- lib/view_model/send/send_view_model.dart | 6 +- res/values/strings_ar.arb | 1 + res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 1 + res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 1 + res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 1 + res/values/strings_my.arb | 1 + res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_th.arb | 1 + res/values/strings_tl.arb | 1 + res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + tool/configure.dart | 3 +- 30 files changed, 146 insertions(+), 18 deletions(-) create mode 100644 lib/core/create_trade_result.dart diff --git a/lib/core/create_trade_result.dart b/lib/core/create_trade_result.dart new file mode 100644 index 000000000..0e873d51e --- /dev/null +++ b/lib/core/create_trade_result.dart @@ -0,0 +1,9 @@ +class CreateTradeResult { + bool result; + String? errorMessage; + + CreateTradeResult({ + required this.result, + this.errorMessage, + }); +} diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index eba347ac4..4e5902faa 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -3,8 +3,20 @@ import 'dart:collection'; import 'dart:convert'; import 'package:bitcoin_base/bitcoin_base.dart'; -import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; +import 'package:cake_wallet/core/create_trade_result.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/sync_status.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:hive/hive.dart'; +import 'package:http/http.dart' as http; +import 'package:intl/intl.dart'; +import 'package:mobx/mobx.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/core/wallet_change_listener_view_model.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; @@ -33,14 +45,6 @@ import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/store/templates/exchange_template_store.dart'; import 'package:cake_wallet/utils/feature_flag.dart'; import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/sync_status.dart'; -import 'package:cw_core/transaction_priority.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:hive/hive.dart'; -import 'package:intl/intl.dart'; -import 'package:mobx/mobx.dart'; -import 'package:shared_preferences/shared_preferences.dart'; part 'exchange_view_model.g.dart'; @@ -516,10 +520,12 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with trade.walletId = wallet.id; trade.fromWalletAddress = wallet.walletAddresses.address; - if (!isCanCreateTrade(trade)) { + final canCreateTrade = await isCanCreateTrade(trade); + if (!canCreateTrade.result) { tradeState = TradeIsCreatedFailure( - title: S.current.trade_not_created, - error: S.current.thorchain_taproot_address_not_supported); + title: S.current.trade_not_created, + error: canCreateTrade.errorMessage ?? '', + ); return; } @@ -776,16 +782,100 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with int get receiveMaxDigits => receiveCurrency.decimals; - bool isCanCreateTrade(Trade trade) { + Future isCanCreateTrade(Trade trade) async { if (trade.provider == ExchangeProviderDescription.thorChain) { final payoutAddress = trade.payoutAddress ?? ''; final fromWalletAddress = trade.fromWalletAddress ?? ''; final tapRootPattern = RegExp(P2trAddress.regex.pattern); if (tapRootPattern.hasMatch(payoutAddress) || tapRootPattern.hasMatch(fromWalletAddress)) { - return false; + return CreateTradeResult( + result: false, + errorMessage: S.current.thorchain_taproot_address_not_supported, + ); + } + + final currenciesToCheckPattern = RegExp('0x[0-9a-zA-Z]'); + + // Perform checks for payOutAddress + final isPayOutAddressAccordingToPattern = currenciesToCheckPattern.hasMatch(payoutAddress); + + if (isPayOutAddressAccordingToPattern) { + final isPayOutAddressEOA = await _isExternallyOwnedAccountAddress(payoutAddress); + + return CreateTradeResult( + result: isPayOutAddressEOA, + errorMessage: + !isPayOutAddressEOA ? S.current.thorchain_contract_address_not_supported : null, + ); + } + + // Perform checks for fromWalletAddress + final isFromWalletAddressAddressAccordingToPattern = + currenciesToCheckPattern.hasMatch(fromWalletAddress); + + if (isFromWalletAddressAddressAccordingToPattern) { + final isFromWalletAddressEOA = await _isExternallyOwnedAccountAddress(fromWalletAddress); + + return CreateTradeResult( + result: isFromWalletAddressEOA, + errorMessage: + !isFromWalletAddressEOA ? S.current.thorchain_contract_address_not_supported : null, + ); } } - return true; + return CreateTradeResult(result: true); + } + + String _normalizeReceiveCurrency(CryptoCurrency receiveCurrency) { + switch (receiveCurrency) { + case CryptoCurrency.eth: + return 'eth'; + case CryptoCurrency.maticpoly: + return 'polygon'; + default: + return receiveCurrency.tag ?? ''; + } + } + + Future _isExternallyOwnedAccountAddress(String receivingAddress) async { + final normalizedReceiveCurrency = _normalizeReceiveCurrency(receiveCurrency); + + final isEOAAddress = !(await _isContractAddress(normalizedReceiveCurrency, receivingAddress)); + return isEOAAddress; + } + + Future _isContractAddress(String chainName, String contractAddress) async { + final httpClient = http.Client(); + + final uri = Uri.https( + 'deep-index.moralis.io', + '/api/v2.2/erc20/metadata', + { + "chain": chainName, + "addresses": contractAddress, + }, + ); + + try { + final response = await httpClient.get( + uri, + headers: { + "Accept": "application/json", + "X-API-Key": secrets.moralisApiKey, + }, + ); + + final decodedResponse = jsonDecode(response.body)[0] as Map; + + final name = decodedResponse['name'] as String?; + + bool isContractAddress = name!.isNotEmpty; + + return isContractAddress; + } catch (e) { + print(e); + return false; + } } } diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 038301db4..298cc3eed 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -324,14 +324,16 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor Future createTransaction({ExchangeProvider? provider}) async { try { state = IsExecutingState(); + pendingTransaction = await wallet.createTransaction(_credentials()); if (provider is ThorChainExchangeProvider) { final outputCount = pendingTransaction?.outputCount ?? 0; if (outputCount > 10) { - throw Exception("ThorChain does not support more than 10 outputs"); + throw Exception("THORChain does not support more than 10 outputs"); } + if (_hasTaprootInput(pendingTransaction)) { - throw Exception("ThorChain does not support Taproot addresses"); + throw Exception("THORChain does not support Taproot addresses"); } } state = ExecutedSuccessfullyState(); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 15b9712fc..cf9959f17 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -660,6 +660,7 @@ "template_name": "اسم القالب", "third_intro_content": "يعيش Yats خارج Cake Wallet أيضًا. يمكن استبدال أي عنوان محفظة على وجه الأرض بـ Yat!", "third_intro_title": "يتماشي Yat بلطف مع الآخرين", + "thorchain_contract_address_not_supported": "لا يدعم Thorchain الإرسال إلى عنوان العقد", "thorchain_taproot_address_not_supported": "لا يدعم مزود Thorchain عناوين Taproot. يرجى تغيير العنوان أو تحديد مزود مختلف.", "time": "${minutes}د ${seconds}س", "tip": "بقشيش:", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index d479bd57d..bd1cd645d 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -660,6 +660,7 @@ "template_name": "Име на шаблон", "third_intro_content": "Yats също живее извън Cake Wallet. Всеки адрес на портфейл може да бъде заменен с Yat!", "third_intro_title": "Yat добре се сработва с други", + "thorchain_contract_address_not_supported": "Thorchain не подкрепя изпращането до адрес на договор", "thorchain_taproot_address_not_supported": "Доставчикът на Thorchain не поддържа адреси на TapRoot. Моля, променете адреса или изберете друг доставчик.", "time": "${minutes} мин ${seconds} сек", "tip": "Tip:", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 547c926af..4d3458bec 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -660,6 +660,7 @@ "template_name": "Název šablony", "third_intro_content": "Yat existuje i mimo Cake Wallet. Jakákoliv adresa peněženky na světě může být nahrazena Yatem!", "third_intro_title": "Yat dobře spolupracuje s ostatními", + "thorchain_contract_address_not_supported": "Thorchain nepodporuje odeslání na adresu smlouvy", "thorchain_taproot_address_not_supported": "Poskytovatel Thorchain nepodporuje adresy Taproot. Změňte adresu nebo vyberte jiného poskytovatele.", "time": "${minutes}m ${seconds}s", "tip": "Spropitné:", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 97f2ccdc2..7efb0b682 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -661,6 +661,7 @@ "template_name": "Vorlagenname", "third_intro_content": "Yats leben auch außerhalb von Cake Wallet. Jede Wallet-Adresse auf der Welt kann durch ein Yat ersetzt werden!", "third_intro_title": "Yat spielt gut mit anderen", + "thorchain_contract_address_not_supported": "Thorchain unterstützt das Senden an eine Vertragsadresse nicht", "thorchain_taproot_address_not_supported": "Der Thorchain -Anbieter unterstützt keine Taproot -Adressen. Bitte ändern Sie die Adresse oder wählen Sie einen anderen Anbieter aus.", "time": "${minutes}m ${seconds}s", "tip": "Hinweis:", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 60de404fd..8f8b753d6 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -660,6 +660,7 @@ "template_name": "Template Name", "third_intro_content": "Yats live outside of Cake Wallet, too. Any wallet address on earth can be replaced with a Yat!", "third_intro_title": "Yat plays nicely with others", + "thorchain_contract_address_not_supported": "THORChain does not support sending to a contract address", "thorchain_taproot_address_not_supported": "The ThorChain provider does not support Taproot addresses. Please change the address or select a different provider.", "time": "${minutes}m ${seconds}s", "tip": "Tip:", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 60cac3a8c..7de9cff53 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -661,6 +661,7 @@ "template_name": "Nombre de la plantilla", "third_intro_content": "Los Yats también viven fuera de Cake Wallet. Cualquier dirección de billetera en la tierra se puede reemplazar con un Yat!", "third_intro_title": "Yat juega muy bien con otras", + "thorchain_contract_address_not_supported": "Thorchain no admite enviar a una dirección de contrato", "thorchain_taproot_address_not_supported": "El proveedor de Thorchain no admite las direcciones de Taproot. Cambie la dirección o seleccione un proveedor diferente.", "time": "${minutes}m ${seconds}s", "tip": "Consejo:", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 691c481c1..2c76122fc 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -660,6 +660,7 @@ "template_name": "Nom du modèle", "third_intro_content": "Les Yats existent aussi en dehors de Cake Wallet. Toute adresse sur terre peut être remplacée par un Yat !", "third_intro_title": "Yat est universel", + "thorchain_contract_address_not_supported": "Thorchain ne prend pas en charge l'envoi à une adresse de contrat", "thorchain_taproot_address_not_supported": "Le fournisseur de Thorchain ne prend pas en charge les adresses de tapoot. Veuillez modifier l'adresse ou sélectionner un autre fournisseur.", "time": "${minutes}m ${seconds}s", "tip": "Pourboire :", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index f310f67f3..bac970207 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -662,6 +662,7 @@ "template_name": "Sunan Samfura", "third_intro_content": "Yats suna zaune a wajen Kek Wallet, kuma. Ana iya maye gurbin kowane adireshin walat a duniya da Yat!", "third_intro_title": "Yat yana wasa da kyau tare da wasu", + "thorchain_contract_address_not_supported": "Thorchain baya goyon bayan aika zuwa adireshin kwangila", "thorchain_taproot_address_not_supported": "Mai ba da tallafi na ThorChain baya goyan bayan adreshin taproot. Da fatan za a canza adireshin ko zaɓi mai bayarwa daban.", "time": "${minutes}m ${seconds}s", "tip": "Tukwici:", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 671c7a765..5a9706bd5 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -662,6 +662,7 @@ "template_name": "टेम्पलेट नाम", "third_intro_content": "Yats Cake Wallet के बाहर भी रहता है। धरती पर किसी भी वॉलेट पते को Yat से बदला जा सकता है!", "third_intro_title": "Yat दूसरों के साथ अच्छा खेलता है", + "thorchain_contract_address_not_supported": "थोरचेन एक अनुबंध पते पर भेजने का समर्थन नहीं करता है", "thorchain_taproot_address_not_supported": "थोरचेन प्रदाता टैपरोट पते का समर्थन नहीं करता है। कृपया पता बदलें या एक अलग प्रदाता का चयन करें।", "time": "${minutes}m ${seconds}s", "tip": "टिप:", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 67e25d59a..94f675a1d 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -660,6 +660,7 @@ "template_name": "Naziv predloška", "third_intro_content": "Yats žive i izvan Cake Wallet -a. Bilo koja adresa novčanika na svijetu može se zamijeniti Yat!", "third_intro_title": "Yat se lijepo igra s drugima", + "thorchain_contract_address_not_supported": "Thorchain ne podržava slanje na adresu ugovora", "thorchain_taproot_address_not_supported": "Thorchain pružatelj ne podržava Taproot adrese. Promijenite adresu ili odaberite drugog davatelja usluga.", "time": "${minutes}m ${seconds}s", "tip": "Savjet:", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index cca6f9b2a..69e270d10 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -663,6 +663,7 @@ "template_name": "Nama Templat", "third_intro_content": "Yats hidup di luar Cake Wallet juga. Setiap alamat dompet di dunia dapat diganti dengan Yat!", "third_intro_title": "Yat bermain baik dengan yang lain", + "thorchain_contract_address_not_supported": "Thorchain tidak mendukung pengiriman ke alamat kontrak", "thorchain_taproot_address_not_supported": "Penyedia Thorchain tidak mendukung alamat Taproot. Harap ubah alamatnya atau pilih penyedia yang berbeda.", "time": "${minutes}m ${seconds}s", "tip": "Tip:", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 4e04c0498..09b3e43bb 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -662,6 +662,7 @@ "template_name": "Nome modello", "third_intro_content": "Yat può funzionare anche fuori da Cake Wallet. Qualsiasi indirizzo di portafoglio sulla terra può essere sostituito con uno Yat!", "third_intro_title": "Yat gioca bene con gli altri", + "thorchain_contract_address_not_supported": "Thorchain non supporta l'invio a un indirizzo contrattuale", "thorchain_taproot_address_not_supported": "Il provider di Thorchain non supporta gli indirizzi di TapRoot. Si prega di modificare l'indirizzo o selezionare un fornitore diverso.", "time": "${minutes}m ${seconds}s", "tip": "Suggerimento:", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index b3aa527d6..b067c2721 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -661,6 +661,7 @@ "template_name": "テンプレート名", "third_intro_content": "YatsはCakeWalletの外にも住んでいます。 地球上のどのウォレットアドレスもYatに置き換えることができます!", "third_intro_title": "Yatは他の人とうまく遊ぶ", + "thorchain_contract_address_not_supported": "Thorchainは、契約アドレスへの送信をサポートしていません", "thorchain_taproot_address_not_supported": "Thorchainプロバイダーは、TapRootアドレスをサポートしていません。アドレスを変更するか、別のプロバイダーを選択してください。", "time": "${minutes}m ${seconds}s", "tip": "ヒント: ", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 6c5800614..d9881ad04 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -661,6 +661,7 @@ "template_name": "템플릿 이름", "third_intro_content": "Yats는 Cake Wallet 밖에서도 살고 있습니다. 지구상의 모든 지갑 주소는 Yat!", "third_intro_title": "Yat는 다른 사람들과 잘 놉니다.", + "thorchain_contract_address_not_supported": "Thorchain은 계약 주소로 보내는 것을 지원하지 않습니다", "thorchain_taproot_address_not_supported": "Thorchain 제공 업체는 Taproot 주소를 지원하지 않습니다. 주소를 변경하거나 다른 공급자를 선택하십시오.", "time": "${minutes}m ${seconds}s", "tip": "팁:", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 96f141eae..c36f63414 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -660,6 +660,7 @@ "template_name": "နမူနာပုံစံ", "third_intro_content": "Yats သည် Cake Wallet အပြင်ဘက်တွင် နေထိုင်ပါသည်။ ကမ္ဘာပေါ်ရှိ မည်သည့်ပိုက်ဆံအိတ်လိပ်စာကို Yat ဖြင့် အစားထိုးနိုင်ပါသည်။", "third_intro_title": "Yat သည် အခြားသူများနှင့် ကောင်းစွာကစားသည်။", + "thorchain_contract_address_not_supported": "Thorchain သည်စာချုပ်လိပ်စာသို့ပို့ခြင်းမပြုပါ", "thorchain_taproot_address_not_supported": "Thorchain Provider သည် Taproot လိပ်စာများကိုမထောက်ခံပါ။ ကျေးဇူးပြု. လိပ်စာကိုပြောင်းပါသို့မဟုတ်အခြားပံ့ပိုးပေးသူကိုရွေးချယ်ပါ။", "time": "${minutes}m ${seconds}s", "tip": "အကြံပြုချက်-", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 1ce17f706..f258b8f62 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -660,6 +660,7 @@ "template_name": "Sjabloonnaam", "third_intro_content": "Yats wonen ook buiten Cake Wallet. Elk portemonnee-adres op aarde kan worden vervangen door een Yat!", "third_intro_title": "Yat speelt leuk met anderen", + "thorchain_contract_address_not_supported": "Thorchain ondersteunt het verzenden niet naar een contractadres", "thorchain_taproot_address_not_supported": "De Thorchain -provider ondersteunt geen Taprooot -adressen. Wijzig het adres of selecteer een andere provider.", "time": "${minutes}m ${seconds}s", "tip": "Tip:", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index f48ad5dde..4627d0242 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -660,6 +660,7 @@ "template_name": "Nazwa szablonu", "third_intro_content": "Yats mieszkają również poza Cake Wallet. Każdy adres portfela na ziemi można zastąpić Yat!", "third_intro_title": "Yat ładnie bawi się z innymi", + "thorchain_contract_address_not_supported": "Thorchain nie wspiera wysyłania na adres umowy", "thorchain_taproot_address_not_supported": "Dostawca Thorchain nie obsługuje adresów TAPROOT. Zmień adres lub wybierz innego dostawcę.", "time": "${minutes}m ${seconds}s", "tip": "wskazówka:", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 15cc9f01e..2a781c76b 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -662,6 +662,7 @@ "template_name": "Nome do modelo", "third_intro_content": "Yats também mora fora da Cake Wallet. Qualquer endereço de carteira na Terra pode ser substituído por um Yat!", "third_intro_title": "Yat joga bem com os outros", + "thorchain_contract_address_not_supported": "Thorchain não suporta o envio para um endereço de contrato", "thorchain_taproot_address_not_supported": "O provedor de Thorchain não suporta endereços de raiz de Tap. Altere o endereço ou selecione um provedor diferente.", "time": "${minutes}m ${seconds}s", "tip": "Dica:", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index ac0fac2ba..22bac3e33 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -661,6 +661,7 @@ "template_name": "Имя Шаблона", "third_intro_content": "Yat находятся за пределами Cake Wallet. Любой адрес кошелька на земле можно заменить на Yat!", "third_intro_title": "Yat хорошо взаимодействует с другими", + "thorchain_contract_address_not_supported": "Thorchain не поддерживает отправку на адрес контракта", "thorchain_taproot_address_not_supported": "Поставщик Thorchain не поддерживает адреса taproot. Пожалуйста, измените адрес или выберите другого поставщика.", "time": "${minutes}мин ${seconds}сек", "tip": "Совет:", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 7030f6f7f..c0f58495c 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -660,6 +660,7 @@ "template_name": "ชื่อแม่แบบ", "third_intro_content": "Yat อาศัยอยู่นอก Cake Wallet ด้วย ที่อยู่กระเป๋าใดๆ ทั่วโลกสามารถแทนด้วย Yat ได้อีกด้วย!", "third_intro_title": "Yat ปฏิบัติตนอย่างดีกับผู้อื่น", + "thorchain_contract_address_not_supported": "Thorchain ไม่สนับสนุนการส่งไปยังที่อยู่สัญญา", "thorchain_taproot_address_not_supported": "ผู้ให้บริการ Thorchain ไม่รองรับที่อยู่ taproot โปรดเปลี่ยนที่อยู่หรือเลือกผู้ให้บริการอื่น", "time": "${minutes}m ${seconds}s", "tip": "เพิ่มค่าตอบแทน:", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 05a363bac..8c3b13b3b 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -660,6 +660,7 @@ "template_name": "Pangalan ng Template", "third_intro_content": "Ang mga yats ay nakatira sa labas ng cake wallet, din. Ang anumang address ng pitaka sa mundo ay maaaring mapalitan ng isang yat!", "third_intro_title": "Si Yat ay mahusay na gumaganap sa iba", + "thorchain_contract_address_not_supported": "Hindi sinusuportahan ng Thorchain ang pagpapadala sa isang address ng kontrata", "thorchain_taproot_address_not_supported": "Ang Tagabigay ng Thorchain ay hindi sumusuporta sa mga address ng taproot. Mangyaring baguhin ang address o pumili ng ibang provider.", "time": "${minutes} m ${seconds} s", "tip": "Tip:", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index ce342df2f..534a36c77 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -660,6 +660,7 @@ "template_name": "şablon adı", "third_intro_content": "Yat'lar Cake Wallet'ın dışında da çalışabilir. Dünya üzerindeki herhangi bir cüzdan adresi Yat ile değiştirilebilir!", "third_intro_title": "Yat diğerleriyle iyi çalışır", + "thorchain_contract_address_not_supported": "Thorchain bir sözleşme adresine göndermeyi desteklemiyor", "thorchain_taproot_address_not_supported": "Thorchain sağlayıcısı Taproot adreslerini desteklemiyor. Lütfen adresi değiştirin veya farklı bir sağlayıcı seçin.", "time": "${minutes}d ${seconds}s", "tip": "Bahşiş:", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 4afd47fe2..5d1e2be05 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -661,6 +661,7 @@ "template_name": "Назва шаблону", "third_intro_content": "Yat знаходиться за межами Cake Wallet. Будь-яку адресу гаманця на землі можна замінити на Yat!", "third_intro_title": "Yat добре взаємодіє з іншими", + "thorchain_contract_address_not_supported": "Thorchain не підтримує надсилання на адресу контракту", "thorchain_taproot_address_not_supported": "Постачальник Thorchain не підтримує адреси Taproot. Будь ласка, змініть адресу або виберіть іншого постачальника.", "time": "${minutes}хв ${seconds}сек", "tip": "Порада:", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index fac066ace..d98a85753 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -662,6 +662,7 @@ "template_name": "ٹیمپلیٹ کا نام", "third_intro_content": "Yats بھی Cake والیٹ سے باہر رہتے ہیں۔ زمین پر کسی بھی بٹوے کے پتے کو Yat سے تبدیل کیا جا سکتا ہے!", "third_intro_title": "Yat دوسروں کے ساتھ اچھی طرح کھیلتا ہے۔", + "thorchain_contract_address_not_supported": "تھورچین معاہدے کے پتے بھیجنے کی حمایت نہیں کرتا ہے", "thorchain_taproot_address_not_supported": "تھورچین فراہم کنندہ ٹیپروٹ پتے کی حمایت نہیں کرتا ہے۔ براہ کرم پتہ تبدیل کریں یا ایک مختلف فراہم کنندہ کو منتخب کریں۔", "time": "${minutes}m ${seconds}s", "tip": "ٹپ:", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 1f131f3d9..faaeb8837 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -661,6 +661,7 @@ "template_name": "Orukọ Awoṣe", "third_intro_content": "A sì lè lo Yats níta Cake Wallet. A lè rọ́pò Àdírẹ́sì kankan àpamọ́wọ́ fún Yat!", "third_intro_title": "Àlàáfíà ni Yat àti àwọn ìmíìn jọ wà", + "thorchain_contract_address_not_supported": "Thorchain ko ṣe atilẹyin fifiranṣẹ si adirẹsi adehun kan", "thorchain_taproot_address_not_supported": "Olupese Trockchain ko ṣe atilẹyin awọn adirẹsi Taproot. Jọwọ yi adirẹsi pada tabi yan olupese ti o yatọ.", "time": "${minutes}ìṣj ${seconds}ìṣs", "tip": "Owó àfikún:", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 10d11b2c0..2d5251d86 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -660,6 +660,7 @@ "template_name": "模板名称", "third_intro_content": "Yats 也住在 Cake Wallet 之外。 地球上任何一個錢包地址都可以用一個Yat來代替!", "third_intro_title": "Yat 和別人玩得很好", + "thorchain_contract_address_not_supported": "Thorchain不支持发送到合同地址", "thorchain_taproot_address_not_supported": "Thorchain提供商不支持Taproot地址。请更改地址或选择其他提供商。", "time": "${minutes}m ${seconds}s", "tip": "提示:", diff --git a/tool/configure.dart b/tool/configure.dart index 6ee84d63a..d08724e42 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -1057,7 +1057,8 @@ Future generatePubspec( final inputFile = File(pubspecOutputPath); final inputText = await inputFile.readAsString(); final inputLines = inputText.split('\n'); - final dependenciesIndex = inputLines.indexWhere((line) => line.toLowerCase().contains('dependencies:')); + final dependenciesIndex = + inputLines.indexWhere((line) => line.toLowerCase().contains('dependencies:')); var output = cwCore; if (hasMonero) { From fff77519d9cd889b5a17705a1488611640378e33 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Thu, 25 Apr 2024 02:14:53 +0100 Subject: [PATCH 190/241] Generic Fixes: Support Errors and others (#1394) * fix: Crypto amout formatting when calculating fiat amount * fix: Issue with some token symbols coming up with a dollar sign * feat: Split transactions to display on history screen token byh token * fix: Remove restriction on balance length * fix: error when a particular token is not available * fix: Remove token transactions when a token is deleted * fix: Revert previous change * make added spl tokens enabled by default fix issue when entering invalid contract address --------- Co-authored-by: OmarHatem --- cw_core/lib/crypto_currency.dart | 2 +- cw_evm/lib/evm_chain_client.dart | 7 ++- cw_evm/lib/evm_chain_wallet.dart | 6 +++ cw_solana/lib/solana_transaction_info.dart | 5 +-- cw_solana/lib/solana_wallet.dart | 52 +++++++++++----------- cw_solana/lib/spl_token.dart | 4 +- lib/entities/calculate_fiat_amount.dart | 2 + lib/ethereum/cw_ethereum.dart | 6 ++- lib/polygon/cw_polygon.dart | 4 +- lib/solana/cw_solana.dart | 6 ++- 10 files changed, 54 insertions(+), 40 deletions(-) diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index f1c1cd8ae..a7edd409f 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -10,7 +10,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen this.fullName, this.iconPath, this.tag, - this.enabled = false, + this.enabled = true, }) : super(title: title, raw: raw); diff --git a/cw_evm/lib/evm_chain_client.dart b/cw_evm/lib/evm_chain_client.dart index eebbe4f4f..8f0df3926 100644 --- a/cw_evm/lib/evm_chain_client.dart +++ b/cw_evm/lib/evm_chain_client.dart @@ -234,14 +234,17 @@ abstract class EVMChainClient { final decodedResponse = jsonDecode(response.body)[0] as Map; + + final symbol = (decodedResponse['symbol'] ?? '') as String; + String filteredSymbol = symbol.replaceFirst(RegExp('^\\\$'), ''); + final name = decodedResponse['name'] ?? ''; - final symbol = decodedResponse['symbol'] ?? ''; final decimal = decodedResponse['decimals'] ?? '0'; final iconPath = decodedResponse['logo'] ?? ''; return Erc20Token( name: name, - symbol: symbol, + symbol: filteredSymbol, contractAddress: contractAddress, decimal: int.tryParse(decimal) ?? 0, iconPath: iconPath, diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart index 4193e590a..558013252 100644 --- a/cw_evm/lib/evm_chain_wallet.dart +++ b/cw_evm/lib/evm_chain_wallet.dart @@ -468,9 +468,15 @@ abstract class EVMChainWalletBase await token.delete(); balance.remove(token); + await _removeTokenTransactionsInHistory(token); _updateBalance(); } + Future _removeTokenTransactionsInHistory(Erc20Token token) async { + transactionHistory.transactions.removeWhere((key, value) => value.tokenSymbol == token.title); + await transactionHistory.save(); + } + Future getErc20Token(String contractAddress, String chainName) async => await _client.getErc20Token(contractAddress, chainName); diff --git a/cw_solana/lib/solana_transaction_info.dart b/cw_solana/lib/solana_transaction_info.dart index 1b7610e34..7a0844e52 100644 --- a/cw_solana/lib/solana_transaction_info.dart +++ b/cw_solana/lib/solana_transaction_info.dart @@ -34,10 +34,7 @@ class SolanaTransactionInfo extends TransactionInfo { @override String amountFormatted() { String stringBalance = solAmount.toString(); - - if (stringBalance.toString().length >= 6) { - stringBalance = stringBalance.substring(0, 6); - } + return '$stringBalance $tokenSymbol'; } diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart index 43a6d0b83..f3eef465c 100644 --- a/cw_solana/lib/solana_wallet.dart +++ b/cw_solana/lib/solana_wallet.dart @@ -273,32 +273,12 @@ abstract class SolanaWalletBase final transactions = await _client.fetchTransactions(address); - final Map result = {}; - - for (var transactionModel in transactions) { - result[transactionModel.id] = SolanaTransactionInfo( - id: transactionModel.id, - to: transactionModel.to, - from: transactionModel.from, - blockTime: transactionModel.blockTime, - direction: transactionModel.isOutgoingTx - ? TransactionDirection.outgoing - : TransactionDirection.incoming, - solAmount: transactionModel.amount, - isPending: false, - txFee: transactionModel.fee, - tokenSymbol: transactionModel.tokenSymbol, - ); - } - - transactionHistory.addMany(result); - - await transactionHistory.save(); + await _addTransactionsToTransactionHistory(transactions); } /// Fetches the SPL Tokens transactions linked to the token account Public Key Future _updateSPLTokenTransactions() async { - List splTokenTransactions = []; + // List splTokenTransactions = []; // Make a copy of keys to avoid concurrent modification var tokenKeys = List.from(balance.keys); @@ -312,13 +292,20 @@ abstract class SolanaWalletBase _walletKeyPair!, ); - splTokenTransactions.addAll(tokenTxs); + // splTokenTransactions.addAll(tokenTxs); + await _addTransactionsToTransactionHistory(tokenTxs); } } + // await _addTransactionsToTransactionHistory(splTokenTransactions); + } + + Future _addTransactionsToTransactionHistory( + List transactions, + ) async { final Map result = {}; - for (var transactionModel in splTokenTransactions) { + for (var transactionModel in transactions) { result[transactionModel.id] = SolanaTransactionInfo( id: transactionModel.id, to: transactionModel.to, @@ -460,12 +447,23 @@ abstract class SolanaWalletBase await token.delete(); balance.remove(token); + await _removeTokenTransactionsInHistory(token); _updateBalance(); } + Future _removeTokenTransactionsInHistory(SPLToken token) async { + transactionHistory.transactions.removeWhere((key, value) => value.tokenSymbol == token.title); + await transactionHistory.save(); + } + Future getSPLToken(String mintAddress) async { // Convert SPL token mint address to public key - final mintPublicKey = Ed25519HDPublicKey.fromBase58(mintAddress); + final Ed25519HDPublicKey mintPublicKey; + try { + mintPublicKey = Ed25519HDPublicKey.fromBase58(mintAddress); + } catch (_) { + return null; + } // Fetch token's metadata account try { @@ -480,10 +478,12 @@ abstract class SolanaWalletBase iconPath = await _client.getIconImageFromTokenUri(token.uri); } catch (_) {} + String filteredTokenSymbol = token.symbol.replaceFirst(RegExp('^\\\$'), ''); + return SPLToken.fromMetadata( name: token.name, mint: token.mint, - symbol: token.symbol, + symbol: filteredTokenSymbol, mintAddress: mintAddress, iconPath: iconPath, ); diff --git a/cw_solana/lib/spl_token.dart b/cw_solana/lib/spl_token.dart index 0b3b8b372..a40eb0b86 100644 --- a/cw_solana/lib/spl_token.dart +++ b/cw_solana/lib/spl_token.dart @@ -19,7 +19,7 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin { @HiveField(3) final int decimal; - @HiveField(4, defaultValue: false) + @HiveField(4, defaultValue: true) bool _enabled; @HiveField(5) @@ -39,7 +39,7 @@ class SPLToken extends CryptoCurrency with HiveObjectMixin { required this.mint, this.iconPath, this.tag = 'SOL', - bool enabled = false, + bool enabled = true, }) : _enabled = enabled, super( name: mint.toLowerCase(), diff --git a/lib/entities/calculate_fiat_amount.dart b/lib/entities/calculate_fiat_amount.dart index 689ada31b..b0b38eacb 100644 --- a/lib/entities/calculate_fiat_amount.dart +++ b/lib/entities/calculate_fiat_amount.dart @@ -3,6 +3,8 @@ String calculateFiatAmount({double? price, String? cryptoAmount}) { return '0.00'; } + cryptoAmount = cryptoAmount.replaceAll(',', '.'); + final _amount = double.parse(cryptoAmount); final _result = price * _amount; final result = _result < 0 ? _result * -1 : _result; diff --git a/lib/ethereum/cw_ethereum.dart b/lib/ethereum/cw_ethereum.dart index 13fe3aafd..61d5b6ae3 100644 --- a/lib/ethereum/cw_ethereum.dart +++ b/lib/ethereum/cw_ethereum.dart @@ -142,8 +142,10 @@ class CWEthereum extends Ethereum { } wallet as EthereumWallet; - return wallet.erc20Currencies - .firstWhere((element) => transaction.tokenSymbol == element.symbol); + + return wallet.erc20Currencies.firstWhere( + (element) => transaction.tokenSymbol == element.symbol, + ); } @override diff --git a/lib/polygon/cw_polygon.dart b/lib/polygon/cw_polygon.dart index 9f0f9a1bf..5baf4fbbc 100644 --- a/lib/polygon/cw_polygon.dart +++ b/lib/polygon/cw_polygon.dart @@ -140,8 +140,10 @@ class CWPolygon extends Polygon { } wallet as PolygonWallet; + return wallet.erc20Currencies.firstWhere( - (element) => transaction.tokenSymbol.toLowerCase() == element.symbol.toLowerCase()); + (element) => transaction.tokenSymbol.toLowerCase() == element.symbol.toLowerCase(), + ); } @override diff --git a/lib/solana/cw_solana.dart b/lib/solana/cw_solana.dart index 6f4b17309..af66cf3e5 100644 --- a/lib/solana/cw_solana.dart +++ b/lib/solana/cw_solana.dart @@ -110,8 +110,10 @@ class CWSolana extends Solana { } wallet as SolanaWallet; - return wallet.splTokenCurrencies - .firstWhere((element) => transaction.tokenSymbol == element.symbol); + + return wallet.splTokenCurrencies.firstWhere( + (element) => transaction.tokenSymbol == element.symbol, + ); } @override From 3732a4c646c2affe228b055a73e560143f8c5216 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Thu, 25 Apr 2024 05:52:24 -0500 Subject: [PATCH 191/241] Language Fixes for DE (#1409) --- lib/buy/dfx/dfx_buy_provider.dart | 4 ++-- lib/entities/provider_types.dart | 2 +- res/values/strings_de.arb | 18 +++++++++--------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/buy/dfx/dfx_buy_provider.dart b/lib/buy/dfx/dfx_buy_provider.dart index 8e2d58d11..b5c5d3b02 100644 --- a/lib/buy/dfx/dfx_buy_provider.dart +++ b/lib/buy/dfx/dfx_buy_provider.dart @@ -23,7 +23,7 @@ class DFXBuyProvider extends BuyProvider { static const walletName = 'CakeWallet'; @override - String get title => 'DFX Connect'; + String get title => 'DFX.swiss'; @override String get providerDescription => S.current.dfx_option_description; @@ -198,7 +198,7 @@ class DFXBuyProvider extends BuyProvider { context: context, builder: (BuildContext context) { return AlertWithOneAction( - alertTitle: "DFX Connect", + alertTitle: "DFX.swiss", alertContent: S.of(context).buy_provider_unavailable + ': $e', buttonText: S.of(context).ok, buttonAction: () => Navigator.of(context).pop()); diff --git a/lib/entities/provider_types.dart b/lib/entities/provider_types.dart index 701781cc2..ca168a299 100644 --- a/lib/entities/provider_types.dart +++ b/lib/entities/provider_types.dart @@ -22,7 +22,7 @@ extension ProviderTypeName on ProviderType { case ProviderType.robinhood: return 'Robinhood Connect'; case ProviderType.dfx: - return 'DFX Connect'; + return 'DFX.swiss'; case ProviderType.onramper: return 'Onramper'; case ProviderType.moonpay: diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 7efb0b682..0546140eb 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -50,7 +50,7 @@ "anonpay_description": "Generieren Sie ${type}. Der Empfänger kann ${method} mit jeder unterstützten Kryptowährung verwenden, und Sie erhalten Geld in dieser Wallet.", "apk_update": "APK-Update", "approve": "Genehmigen", - "arrive_in_this_address": "${currency} ${tag}wird an dieser Adresse ankommen", + "arrive_in_this_address": "${currency} ${tag} wird an dieser Adresse ankommen", "ascending": "Aufsteigend", "ask_each_time": "Jedes Mal fragen", "auth_store_ban_timeout": "ban_timeout", @@ -87,7 +87,7 @@ "buy_provider_unavailable": "Anbieter derzeit nicht verfügbar.", "buy_with": "Kaufen mit", "by_cake_pay": "von Cake Pay", - "cake_2fa_preset": "Kuchen 2FA-Voreinstellung", + "cake_2fa_preset": "Cake 2FA-Voreinstellung", "cake_dark_theme": "Cake Dark Thema", "cake_pay_account_note": "Melden Sie sich nur mit einer E-Mail-Adresse an, um Karten anzuzeigen und zu kaufen. Einige sind sogar mit Rabatt erhältlich!", "cake_pay_learn_more": "Kaufen und lösen Sie Geschenkkarten sofort in der App ein!\nWischen Sie von links nach rechts, um mehr zu erfahren.", @@ -120,7 +120,7 @@ "change_wallet_alert_title": "Aktuelle Wallet ändern", "choose_account": "Konto auswählen", "choose_address": "\n\nBitte wählen Sie die Adresse:", - "choose_derivation": "Wählen Sie Brieftaschenableitung", + "choose_derivation": "Wählen Sie Wallet-Ableitung", "choose_from_available_options": "Wähle aus verfügbaren Optionen:", "choose_one": "Wähle ein", "choose_relay": "Bitte wählen Sie ein zu verwendendes Relais aus", @@ -199,7 +199,7 @@ "disable_fiat": "Fiat deaktivieren", "disable_sell": "Verkaufsaktion deaktivieren", "disableBatteryOptimization": "Batterieoptimierung deaktivieren", - "disableBatteryOptimizationDescription": "Möchten Sie die Batterieoptimierung deaktivieren, um die Hintergrundsynchronisierung freier und reibungsloser zu gestalten?", + "disableBatteryOptimizationDescription": "Möchten Sie die Batterieoptimierung deaktivieren, um die Hintergrundsynchronisierung reibungsloser zu gestalten?", "disabled": "Deaktiviert", "discount": "${value} % sparen", "display_settings": "Anzeigeeinstellungen", @@ -459,8 +459,8 @@ "reconnect_alert_text": "Sind Sie sicher, dass Sie sich neu verbinden möchten?", "reconnection": "Neu verbinden", "red_dark_theme": "Red Dark Thema", - "red_light_theme": "Rotlichtthema", - "redeemed": "Versilbert", + "red_light_theme": "Red Light Thema", + "redeemed": "Eingelöst", "refund_address": "Rückerstattungsadresse", "reject": "Ablehnen", "remaining": "Rest", @@ -532,7 +532,7 @@ "seed_alert_title": "Achtung", "seed_alert_yes": "Ja, habe ich", "seed_choose": "Seed-Sprache auswählen", - "seed_hex_form": "Brieftaschensamen (Sechskantform)", + "seed_hex_form": "Seed (Hexformat)", "seed_key": "Seed-Schlüssel", "seed_language": "Seed-Sprache", "seed_language_chinese": "Chinesisch", @@ -584,7 +584,7 @@ "send_your_wallet": "Ihre Wallet", "sending": "Senden", "sent": "Versendet", - "service_health_disabled": "Service Health Bulletin ist behindert", + "service_health_disabled": "Service Health Bulletin ist deaktiviert", "service_health_disabled_message": "Dies ist die Seite \"Service Health Bulletin\", können Sie diese Seite unter Einstellungen -> Privatsphäre aktivieren", "settings": "Einstellungen", "settings_all": "ALLE", @@ -822,4 +822,4 @@ "you_will_get": "Konvertieren zu", "you_will_send": "Konvertieren von", "yy": "YY" -} \ No newline at end of file +} From 190c8e06b9c2121e4694ccdd048b3daf61f99270 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Thu, 25 Apr 2024 06:06:11 -0500 Subject: [PATCH 192/241] Use the latest version of the DFX Auth Api to minimize the number of API calls (#1410) --- lib/buy/dfx/dfx_buy_provider.dart | 76 +++++++++---------------------- 1 file changed, 21 insertions(+), 55 deletions(-) diff --git a/lib/buy/dfx/dfx_buy_provider.dart b/lib/buy/dfx/dfx_buy_provider.dart index b5c5d3b02..bf67edd23 100644 --- a/lib/buy/dfx/dfx_buy_provider.dart +++ b/lib/buy/dfx/dfx_buy_provider.dart @@ -17,9 +17,8 @@ class DFXBuyProvider extends BuyProvider { : super(wallet: wallet, isTestEnvironment: isTestEnvironment); static const _baseUrl = 'api.dfx.swiss'; - static const _authPath = '/v1/auth/signMessage'; - static const _signUpPath = '/v1/auth/signUp'; - static const _signInPath = '/v1/auth/signIn'; + // static const _signMessagePath = '/v1/auth/signMessage'; + static const _authPath = '/v1/auth'; static const walletName = 'CakeWallet'; @override @@ -73,21 +72,25 @@ class DFXBuyProvider extends BuyProvider { String get walletAddress => wallet.walletAddresses.primaryAddress ?? wallet.walletAddresses.address; - Future getSignMessage() async { - final uri = Uri.https(_baseUrl, _authPath, {'address': walletAddress}); + Future getSignMessage() async => + "By_signing_this_message,_you_confirm_that_you_are_the_sole_owner_of_the_provided_Blockchain_address._Your_ID:_$walletAddress"; - var response = await http.get(uri, headers: {'accept': 'application/json'}); + // // Lets keep this just in case, but we can avoid this API Call + // Future getSignMessage() async { + // final uri = Uri.https(_baseUrl, _signMessagePath, {'address': walletAddress}); + // + // final response = await http.get(uri, headers: {'accept': 'application/json'}); + // + // if (response.statusCode == 200) { + // final responseBody = jsonDecode(response.body); + // return responseBody['message'] as String; + // } else { + // throw Exception( + // 'Failed to get sign message. Status: ${response.statusCode} ${response.body}'); + // } + // } - if (response.statusCode == 200) { - final responseBody = jsonDecode(response.body); - return responseBody['message'] as String; - } else { - throw Exception( - 'Failed to get sign message. Status: ${response.statusCode} ${response.body}'); - } - } - - Future signUp() async { + Future auth() async { final signMessage = getSignature(await getSignMessage()); final requestBody = jsonEncode({ @@ -96,7 +99,7 @@ class DFXBuyProvider extends BuyProvider { 'signature': signMessage, }); - final uri = Uri.https(_baseUrl, _signUpPath); + final uri = Uri.https(_baseUrl, _authPath); var response = await http.post( uri, headers: {'Content-Type': 'application/json'}, @@ -115,33 +118,6 @@ class DFXBuyProvider extends BuyProvider { } } - Future signIn() async { - final signMessage = getSignature(await getSignMessage()); - - final requestBody = jsonEncode({ - 'address': walletAddress, - 'signature': signMessage, - }); - - final uri = Uri.https(_baseUrl, _signInPath); - var response = await http.post( - uri, - headers: {'Content-Type': 'application/json'}, - body: requestBody, - ); - - if (response.statusCode == 201) { - final responseBody = jsonDecode(response.body); - return responseBody['accessToken'] as String; - } else if (response.statusCode == 403) { - final responseBody = jsonDecode(response.body); - final message = responseBody['message'] ?? 'Service unavailable in your country'; - throw Exception(message); - } else { - throw Exception('Failed to sign in. Status: ${response.statusCode} ${response.body}'); - } - } - String getSignature(String message) { switch (wallet.type) { case WalletType.ethereum: @@ -164,17 +140,7 @@ class DFXBuyProvider extends BuyProvider { final blockchain = this.blockchain; final actionType = isBuyAction == true ? '/buy' : '/sell'; - String accessToken; - - try { - accessToken = await signUp(); - } on Exception catch (e) { - if (e.toString().contains('409')) { - accessToken = await signIn(); - } else { - rethrow; - } - } + final accessToken = await auth(); final uri = Uri.https('services.dfx.swiss', actionType, { 'session': accessToken, From 9ff6da3d5d2db04069deed46c35a15e4138d777e Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 25 Apr 2024 19:28:18 +0300 Subject: [PATCH 193/241] dynamic max fee rate value (#1395) --- lib/bitcoin/cw_bitcoin.dart | 6 ++++ lib/src/screens/send/widgets/send_card.dart | 2 ++ .../screens/settings/other_settings_page.dart | 1 + .../widgets/setting_priority_picker_cell.dart | 3 ++ .../rbf_details_list_fee_picker_item.dart | 2 ++ .../transaction_details/rbf_details_page.dart | 1 + lib/src/widgets/picker.dart | 28 +++++++++++++------ lib/src/widgets/standard_picker_list.dart | 3 ++ lib/view_model/send/send_view_model.dart | 7 +++++ .../settings/other_settings_view_model.dart | 7 +++++ .../transaction_details_view_model.dart | 2 ++ tool/configure.dart | 1 + 12 files changed, 54 insertions(+), 9 deletions(-) diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 862ce9db5..9bdc0f3ac 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -291,4 +291,10 @@ class CWBitcoin extends Bitcoin { outputsCount, ); } + + @override + int getMaxCustomFeeRate(Object wallet) { + final bitcoinWallet = wallet as ElectrumWallet; + return (bitcoinWallet.feeRate(BitcoinTransactionPriority.fast) * 1.1).round(); + } } diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 7c2bfedd0..c9ae5182a 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -675,6 +675,7 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin( @@ -689,6 +690,7 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin extends StandardListRow { this.isGridView = false, this.matchingCriteria, this.customValue, + this.maxValue, this.customItemIndex, this.onItemSelected}) : super( @@ -34,6 +35,7 @@ class SettingsPriorityPickerCell extends StandardListRow { displayItem: (ItemType item) => displayItem!(item, sliderValue.round()), selectedAtIndex: selectedAtIndex, customItemIndex: customItemIndex, + maxValue: maxValue, headerEnabled: false, closeOnItemSelected: false, mainAxisAlignment: MainAxisAlignment.center, @@ -61,6 +63,7 @@ class SettingsPriorityPickerCell extends StandardListRow { final bool isGridView; final bool Function(ItemType, String)? matchingCriteria; double? customValue; + double? maxValue; int? customItemIndex; @override diff --git a/lib/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart b/lib/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart index 8f722ee7e..7615065d7 100644 --- a/lib/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart +++ b/lib/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart @@ -10,6 +10,7 @@ class StandardPickerListItem extends TransactionDetailsListItem { required this.onItemSelected, required this.selectedIdx, required this.customItemIndex, + this.maxValue, required this.customValue}) : super(title: title, value: value); @@ -18,6 +19,7 @@ class StandardPickerListItem extends TransactionDetailsListItem { final Function(double) onSliderChanged; final Function(T) onItemSelected; final int selectedIdx; + final double? maxValue; final int customItemIndex; double customValue; } diff --git a/lib/src/screens/transaction_details/rbf_details_page.dart b/lib/src/screens/transaction_details/rbf_details_page.dart index 875e0a4ef..3faec48a8 100644 --- a/lib/src/screens/transaction_details/rbf_details_page.dart +++ b/lib/src/screens/transaction_details/rbf_details_page.dart @@ -74,6 +74,7 @@ class RBFDetailsPage extends BasePage { selectedIdx: item.selectedIdx, customItemIndex: item.customItemIndex, customValue: item.customValue, + maxValue: item.maxValue, ); } diff --git a/lib/src/widgets/picker.dart b/lib/src/widgets/picker.dart index d87b5721e..b744d1db0 100644 --- a/lib/src/widgets/picker.dart +++ b/lib/src/widgets/picker.dart @@ -27,14 +27,21 @@ class Picker extends StatefulWidget { this.headerEnabled = true, this.closeOnItemSelected = true, this.sliderValue, + this.minValue, + this.maxValue, this.customItemIndex, this.isWrapped = true, this.borderColor, this.onSliderChanged, this.matchingCriteria, - }) : assert(hintText == null || - matchingCriteria != - null); // make sure that if the search field is enabled then there is a searching criteria provided + }) : assert(hintText == null || matchingCriteria != null) { + // make sure that if the search field is enabled then there is a searching criteria provided + if (sliderValue != null && maxValue != null) { + if (sliderValue! > maxValue!) { + sliderValue = maxValue; + } + } + } final int selectedAtIndex; final List items; @@ -49,12 +56,14 @@ class Picker extends StatefulWidget { final String? hintText; final bool headerEnabled; final bool closeOnItemSelected; - final double? sliderValue; + double? sliderValue; + final double? minValue; final int? customItemIndex; final bool isWrapped; final Color? borderColor; final Function(double)? onSliderChanged; final bool Function(Item, String)? matchingCriteria; + final double? maxValue; @override _PickerState createState() => _PickerState(items, images, onItemSelected); @@ -138,7 +147,7 @@ class _PickerState extends State> { containerHeight = height * 0.75; } - final content = Column ( + final content = Column( children: [ if (widget.title?.isNotEmpty ?? false) Container( @@ -211,8 +220,9 @@ class _PickerState extends State> { fontWeight: FontWeight.w500, fontFamily: 'Lato', decoration: TextDecoration.none, - color: - Theme.of(context).extension()!.titleColor, + color: Theme.of(context) + .extension()! + .titleColor, ), ), ) @@ -491,8 +501,8 @@ class _PickerState extends State> { child: Slider( value: widget.sliderValue ?? 1, onChanged: isActivated ? widget.onSliderChanged : null, - min: 1, - max: 100, + min: widget.minValue ?? 1, + max: widget.maxValue ?? 100, divisions: 100, ), ), diff --git a/lib/src/widgets/standard_picker_list.dart b/lib/src/widgets/standard_picker_list.dart index eb1d16900..ea8b07097 100644 --- a/lib/src/widgets/standard_picker_list.dart +++ b/lib/src/widgets/standard_picker_list.dart @@ -15,6 +15,7 @@ class StandardPickerList extends StatefulWidget { required this.selectedIdx, required this.customItemIndex, required this.customValue, + this.maxValue, }) : super(key: key); final String title; @@ -26,6 +27,7 @@ class StandardPickerList extends StatefulWidget { final String value; final int selectedIdx; final double customValue; + final double? maxValue; @override _StandardPickerListState createState() => _StandardPickerListState(); @@ -59,6 +61,7 @@ class _StandardPickerListState extends State> { displayItem: adaptedDisplayItem, selectedAtIndex: selectedIdx, customItemIndex: widget.customItemIndex, + maxValue: widget.maxValue, headerEnabled: false, closeOnItemSelected: false, mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 298cc3eed..2e00d1f0b 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -166,6 +166,13 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor return null; } + int? get maxCustomFeeRate { + if (wallet.type == WalletType.bitcoin) { + return bitcoin!.getMaxCustomFeeRate(wallet); + } + return null; + } + @computed int get customBitcoinFeeRate => _settingsStore.customBitcoinFeeRate; diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart index cf410a1a9..0493acf81 100644 --- a/lib/view_model/settings/other_settings_view_model.dart +++ b/lib/view_model/settings/other_settings_view_model.dart @@ -140,6 +140,13 @@ abstract class OtherSettingsViewModelBase with Store { return customItem != null ? priorities.indexOf(customItem) : null; } + int? get maxCustomFeeRate { + if (_wallet.type == WalletType.bitcoin) { + return bitcoin!.getMaxCustomFeeRate(_wallet); + } + return null; + } + @action ProviderType onBuyProviderTypeSelected(ProviderType buyProviderType) => _settingsStore.defaultBuyProviders[walletType] = buyProviderType; diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index fd6d3ef6e..be2ebc545 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -348,12 +348,14 @@ abstract class TransactionDetailsViewModelBase with Store { final customItem = priorities.firstWhereOrNull( (element) => element == sendViewModel.bitcoinTransactionPriorityCustom); final customItemIndex = customItem != null ? priorities.indexOf(customItem) : null; + final maxCustomFeeRate = sendViewModel.maxCustomFeeRate?.toDouble(); RBFListItems.add(StandardPickerListItem( title: S.current.estimated_new_fee, value: bitcoin!.formatterBitcoinAmountToString(amount: newFee) + ' ${walletTypeToCryptoCurrency(wallet.type)}', items: priorityForWalletType(wallet.type), customValue: settingsStore.customBitcoinFeeRate.toDouble(), + maxValue: maxCustomFeeRate, selectedIdx: selectedItem, customItemIndex: customItemIndex ?? 0, displayItem: (dynamic priority, double sliderValue) => diff --git a/tool/configure.dart b/tool/configure.dart index d08724e42..34a39d28b 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -159,6 +159,7 @@ abstract class Bitcoin { Future isChangeSufficientForFee(Object wallet, String txId, String newFee); int getFeeAmountForPriority(Object wallet, TransactionPriority priority, int inputsCount, int outputsCount, {int? size}); int getFeeAmountWithFeeRate(Object wallet, int feeRate, int inputsCount, int outputsCount, {int? size}); + int getMaxCustomFeeRate(Object wallet); } """; From a5a3b4ac0ee0392fd0823f1752536fd04654a49a Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Fri, 26 Apr 2024 05:32:13 +0300 Subject: [PATCH 194/241] Update crypto_currency.dart --- cw_core/lib/crypto_currency.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index a7edd409f..f1c1cd8ae 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -10,7 +10,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen this.fullName, this.iconPath, this.tag, - this.enabled = true, + this.enabled = false, }) : super(title: title, raw: raw); From 7fcf48f91da3d82121704bf25c530549a24c9322 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 26 Apr 2024 19:18:26 +0300 Subject: [PATCH 195/241] Fix estimated fee calculation for customs fee rate (#1406) * Update output.dart * fix estimated fee calculation * Update bitcoin_transaction_priority.dart --- cw_bitcoin/lib/bitcoin_transaction_priority.dart | 2 +- lib/bitcoin/cw_bitcoin.dart | 11 ++++++----- lib/view_model/send/output.dart | 4 ++-- lib/view_model/transaction_details_view_model.dart | 14 +++++--------- tool/configure.dart | 2 +- 5 files changed, 15 insertions(+), 18 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_transaction_priority.dart b/cw_bitcoin/lib/bitcoin_transaction_priority.dart index d51775368..7c4dcfd5f 100644 --- a/cw_bitcoin/lib/bitcoin_transaction_priority.dart +++ b/cw_bitcoin/lib/bitcoin_transaction_priority.dart @@ -37,7 +37,7 @@ class BitcoinTransactionPriority extends TransactionPriority { switch (this) { case BitcoinTransactionPriority.slow: - label = 'Slow ~24hrs'; // '${S.current.transaction_priority_slow} ~24hrs'; + label = 'Slow ~24hrs+'; // '${S.current.transaction_priority_slow} ~24hrs'; break; case BitcoinTransactionPriority.medium: label = 'Medium'; // S.current.transaction_priority_medium; diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 9bdc0f3ac..707f1157b 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -282,13 +282,14 @@ class CWBitcoin extends Bitcoin { } @override - int getFeeAmountWithFeeRate(Object wallet, int feeRate, int inputsCount, int outputsCount, - {int? size}) { + int getEstimatedFeeWithFeeRate(Object wallet, int feeRate, int? amount, + {int? outputsCount, int? size}) { final bitcoinWallet = wallet as ElectrumWallet; - return bitcoinWallet.feeAmountWithFeeRate( + return bitcoinWallet.calculateEstimatedFeeWithFeeRate( feeRate, - inputsCount, - outputsCount, + amount, + outputsCount: outputsCount, + size: size, ); } diff --git a/lib/view_model/send/output.dart b/lib/view_model/send/output.dart index 6bb3fbb31..07d98ff32 100644 --- a/lib/view_model/send/output.dart +++ b/lib/view_model/send/output.dart @@ -126,8 +126,8 @@ abstract class OutputBase with Store { if (_wallet.type == WalletType.bitcoin) { if (_settingsStore.priority[_wallet.type] == bitcoin!.getBitcoinTransactionPriorityCustom()) { - fee = bitcoin!.getFeeAmountWithFeeRate( - _settingsStore.customBitcoinFeeRate, formattedCryptoAmount, 1, 1); + fee = bitcoin!.getEstimatedFeeWithFeeRate(_wallet, + _settingsStore.customBitcoinFeeRate,formattedCryptoAmount); } return bitcoin!.formatterBitcoinAmountToDouble(amount: fee); diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index be2ebc545..faa49dfc4 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -390,16 +390,12 @@ abstract class TransactionDetailsViewModelBase with Store { String setNewFee({double? value, required TransactionPriority priority}) { newFee = priority == bitcoin!.getBitcoinTransactionPriorityCustom() && value != null - ? bitcoin!.getFeeAmountWithFeeRate( - wallet, - value.round(), - transactionInfo.inputAddresses?.length ?? 1, - transactionInfo.outputAddresses?.length ?? 1) + ? bitcoin!.getEstimatedFeeWithFeeRate(wallet, value.round(), transactionInfo.amount) : bitcoin!.getFeeAmountForPriority( - wallet, - priority, - transactionInfo.inputAddresses?.length ?? 1, - transactionInfo.outputAddresses?.length ?? 1); + wallet, + priority, + transactionInfo.inputAddresses?.length ?? 1, + transactionInfo.outputAddresses?.length ?? 1); return bitcoin!.formatterBitcoinAmountToString(amount: newFee); } diff --git a/tool/configure.dart b/tool/configure.dart index 34a39d28b..3b73bfe80 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -158,7 +158,7 @@ abstract class Bitcoin { Future canReplaceByFee(Object wallet, String transactionHash); Future isChangeSufficientForFee(Object wallet, String txId, String newFee); int getFeeAmountForPriority(Object wallet, TransactionPriority priority, int inputsCount, int outputsCount, {int? size}); - int getFeeAmountWithFeeRate(Object wallet, int feeRate, int inputsCount, int outputsCount, {int? size}); + int getEstimatedFeeWithFeeRate(Object wallet, int feeRate, int? amount, {int? outputsCount, int? size}); int getMaxCustomFeeRate(Object wallet); } """; From a6dc9bf9d675d27297afbdec616ba5e1d251d566 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 26 Apr 2024 19:18:35 +0300 Subject: [PATCH 196/241] Update electrum_wallet.dart (#1411) --- cw_bitcoin/lib/electrum_wallet.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 5bed6a449..6b305722e 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -1037,9 +1037,11 @@ abstract class ElectrumWalletBase return Future.wait(addressesByType.map((addressRecord) async { final history = await _fetchAddressHistory(addressRecord, addressesSet, currentHeight); + final balance = await electrumClient.getBalance(addressRecord.scriptHash!); if (history.isNotEmpty) { addressRecord.txCount = history.length; + addressRecord.balance = balance['confirmed'] as int? ?? 0; historiesWithDetails.addAll(history); final matchedAddresses = From f3160860b1796ef0abe41299eb954ce26c1b899b Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Fri, 26 Apr 2024 22:13:44 +0300 Subject: [PATCH 197/241] Better handle corrupted wallets (#1384) * Fix exchanges not showing * Fix button text on Monero receive screen * Temp fix for ERC20 and SPL tokens not having raw value * fallback to other wallets if the current wallet is corrupted so we give user access to the app --------- Co-authored-by: tuxsudo --- lib/core/wallet_loading_service.dart | 61 ++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/lib/core/wallet_loading_service.dart b/lib/core/wallet_loading_service.dart index 3323e7831..1f17a7a1c 100644 --- a/lib/core/wallet_loading_service.dart +++ b/lib/core/wallet_loading_service.dart @@ -1,27 +1,28 @@ import 'package:cake_wallet/core/generate_wallet_password.dart'; import 'package:cake_wallet/core/key_service.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; +import 'package:cake_wallet/utils/exception_handler.dart'; +import 'package:cw_core/cake_hive.dart'; import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/wallet_type.dart'; +import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class WalletLoadingService { - WalletLoadingService( - this.sharedPreferences, this.keyService, this.walletServiceFactory); + WalletLoadingService(this.sharedPreferences, this.keyService, this.walletServiceFactory); final SharedPreferences sharedPreferences; final KeyService keyService; final WalletService Function(WalletType type) walletServiceFactory; - Future renameWallet( - WalletType type, String name, String newName) async { + Future renameWallet(WalletType type, String name, String newName) async { final walletService = walletServiceFactory.call(type); final password = await keyService.getWalletPassword(walletName: name); // Save the current wallet's password to the new wallet name's key - await keyService.saveWalletPassword( - walletName: newName, password: password); + await keyService.saveWalletPassword(walletName: newName, password: password); // Delete previous wallet name from keyService to keep only new wallet's name // otherwise keeps duplicate (old and new names) await keyService.deleteWalletPassword(walletName: name); @@ -38,15 +39,43 @@ class WalletLoadingService { } Future load(WalletType type, String name) async { - final walletService = walletServiceFactory.call(type); - final password = await keyService.getWalletPassword(walletName: name); - final wallet = await walletService.openWallet(name, password); + try { + final walletService = walletServiceFactory.call(type); + final password = await keyService.getWalletPassword(walletName: name); + final wallet = await walletService.openWallet(name, password); - if (type == WalletType.monero) { - await updateMoneroWalletPassword(wallet); + if (type == WalletType.monero) { + await updateMoneroWalletPassword(wallet); + } + + return wallet; + } catch (error, stack) { + ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack)); + + // try opening another wallet that is not corrupted to give user access to the app + final walletInfoSource = await CakeHive.openBox(WalletInfo.boxName); + + for (var walletInfo in walletInfoSource.values) { + try { + final walletService = walletServiceFactory.call(walletInfo.type); + final password = await keyService.getWalletPassword(walletName: walletInfo.name); + final wallet = await walletService.openWallet(walletInfo.name, password); + + if (walletInfo.type == WalletType.monero) { + await updateMoneroWalletPassword(wallet); + } + + await sharedPreferences.setString(PreferencesKey.currentWalletName, wallet.name); + await sharedPreferences.setInt( + PreferencesKey.currentWalletType, serializeToInt(wallet.type)); + + return wallet; + } catch (_) {} + } + + // if all user's wallets are corrupted throw exception + throw error; } - - return wallet; } Future updateMoneroWalletPassword(WalletBase wallet) async { @@ -61,11 +90,9 @@ class WalletLoadingService { // Save new generated password with backup key for case where // wallet will change password, but it will fail to update in secure storage final bakWalletName = '#__${wallet.name}_bak__#'; - await keyService.saveWalletPassword( - walletName: bakWalletName, password: password); + await keyService.saveWalletPassword(walletName: bakWalletName, password: password); await wallet.changePassword(password); - await keyService.saveWalletPassword( - walletName: wallet.name, password: password); + await keyService.saveWalletPassword(walletName: wallet.name, password: password); isPasswordUpdated = true; await sharedPreferences.setBool(key, isPasswordUpdated); } From 9e4a7f4331d0ed9a26f5d1c73135a7ae06b4d8c8 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Fri, 26 Apr 2024 22:29:31 +0300 Subject: [PATCH 198/241] Enhance bitcoin error message (#1399) * Enhance bitcoin error message * fix: unconfirmed spends, spend confirmed first, wrong balance exception * Minor fixes --------- Co-authored-by: Rafael Saes --- cw_bitcoin/lib/electrum_wallet.dart | 44 +++++++++++++++++-- cw_bitcoin/lib/exceptions.dart | 4 +- .../lib/pending_bitcoin_transaction.dart | 2 + cw_bitcoin/pubspec.lock | 34 +++++++------- .../src/pending_bitcoin_cash_transaction.dart | 2 + cw_core/lib/exceptions.dart | 6 ++- cw_core/lib/unspent_transaction_output.dart | 1 + lib/src/screens/send/send_page.dart | 2 +- lib/view_model/send/send_view_model.dart | 2 +- 9 files changed, 72 insertions(+), 25 deletions(-) diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 6b305722e..4a76ee5dd 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -203,10 +203,14 @@ abstract class ElectrumWalletBase List privateKeys = []; int allInputsAmount = 0; + bool spendsUnconfirmedTX = false; + for (int i = 0; i < unspentCoins.length; i++) { final utx = unspentCoins[i]; - if (utx.isSending) { + if (utx.isSending && !utx.isFrozen) { + if (!spendsUnconfirmedTX) spendsUnconfirmedTX = utx.confirmations == 0; + allInputsAmount += utx.value; final address = addressTypeFromStr(utx.address, network); @@ -264,6 +268,10 @@ abstract class ElectrumWalletBase // Here, when sending all, the output amount equals to the input value - fee to fully spend every input on the transaction and have no amount left for change int amount = allInputsAmount - fee; + if (amount <= 0) { + throw BitcoinTransactionWrongBalanceException(); + } + // Attempting to send less than the dust limit if (_isBelowDust(amount)) { throw BitcoinTransactionNoDustException(); @@ -288,6 +296,7 @@ abstract class ElectrumWalletBase isSendAll: true, hasChange: false, memo: memo, + spendsUnconfirmedTX: spendsUnconfirmedTX, ); } @@ -297,17 +306,25 @@ abstract class ElectrumWalletBase int feeRate, { int? inputsCount, String? memo, + bool? useUnconfirmed, }) async { final utxos = []; List privateKeys = []; int allInputsAmount = 0; + bool spendsUnconfirmedTX = false; int leftAmount = credentialsAmount; - final sendingCoins = unspentCoins.where((utx) => utx.isSending).toList(); + final sendingCoins = unspentCoins.where((utx) => utx.isSending && !utx.isFrozen).toList(); + final unconfirmedCoins = sendingCoins.where((utx) => utx.confirmations == 0).toList(); for (int i = 0; i < sendingCoins.length; i++) { final utx = sendingCoins[i]; + final isUncormirmed = utx.confirmations == 0; + if (useUnconfirmed != true && isUncormirmed) continue; + + if (!spendsUnconfirmedTX) spendsUnconfirmedTX = isUncormirmed; + allInputsAmount += utx.value; leftAmount = leftAmount - utx.value; @@ -345,11 +362,23 @@ abstract class ElectrumWalletBase } final spendingAllCoins = sendingCoins.length == utxos.length; + final spendingAllConfirmedCoins = + !spendsUnconfirmedTX && utxos.length == sendingCoins.length - unconfirmedCoins.length; // How much is being spent - how much is being sent int amountLeftForChangeAndFee = allInputsAmount - credentialsAmount; if (amountLeftForChangeAndFee <= 0) { + if (!spendingAllCoins) { + return estimateTxForAmount( + credentialsAmount, + outputs, + feeRate, + inputsCount: utxos.length + 1, + memo: memo, + useUnconfirmed: useUnconfirmed ?? spendingAllConfirmedCoins, + ); + } throw BitcoinTransactionWrongBalanceException(); } @@ -403,6 +432,7 @@ abstract class ElectrumWalletBase feeRate, inputsCount: utxos.length + 1, memo: memo, + useUnconfirmed: useUnconfirmed ?? spendingAllConfirmedCoins, ); } @@ -449,6 +479,7 @@ abstract class ElectrumWalletBase feeRate, inputsCount: utxos.length + 1, memo: memo, + useUnconfirmed: useUnconfirmed ?? spendingAllConfirmedCoins, ); } } @@ -461,6 +492,7 @@ abstract class ElectrumWalletBase hasChange: true, isSendAll: false, memo: memo, + spendsUnconfirmedTX: spendsUnconfirmedTX, ); } @@ -531,7 +563,7 @@ abstract class ElectrumWalletBase network: network, memo: estimatedTx.memo, outputOrdering: BitcoinOrdering.none, - enableRBF: true, + enableRBF: !estimatedTx.spendsUnconfirmedTX, ); } else { txb = BitcoinTransactionBuilder( @@ -541,7 +573,7 @@ abstract class ElectrumWalletBase network: network, memo: estimatedTx.memo, outputOrdering: BitcoinOrdering.none, - enableRBF: true, + enableRBF: !estimatedTx.spendsUnconfirmedTX, ); } @@ -721,6 +753,7 @@ abstract class ElectrumWalletBase final tx = await fetchTransactionInfo( hash: coin.hash, height: 0, myAddresses: addressesSet); coin.isChange = tx?.direction == TransactionDirection.outgoing; + coin.confirmations = tx?.confirmations; updatedUnspentCoins.add(coin); } catch (_) {} })))); @@ -745,6 +778,7 @@ abstract class ElectrumWalletBase coin.isFrozen = coinInfo.isFrozen; coin.isSending = coinInfo.isSending; coin.note = coinInfo.note; + coin.bitcoinAddressRecord.balance += coinInfo.value; } else { _addCoinInfo(coin); } @@ -1272,6 +1306,7 @@ class EstimatedTxResult { required this.hasChange, required this.isSendAll, this.memo, + required this.spendsUnconfirmedTX, }); final List utxos; @@ -1281,6 +1316,7 @@ class EstimatedTxResult { final bool hasChange; final bool isSendAll; final String? memo; + final bool spendsUnconfirmedTX; } BitcoinBaseAddress addressTypeFromStr(String address, BasedUtxoNetwork network) { diff --git a/cw_bitcoin/lib/exceptions.dart b/cw_bitcoin/lib/exceptions.dart index 4b03eb922..979c1a433 100644 --- a/cw_bitcoin/lib/exceptions.dart +++ b/cw_bitcoin/lib/exceptions.dart @@ -15,7 +15,9 @@ class BitcoinTransactionNoDustOnChangeException extends TransactionNoDustOnChang BitcoinTransactionNoDustOnChangeException(super.max, super.min); } -class BitcoinTransactionCommitFailed extends TransactionCommitFailed {} +class BitcoinTransactionCommitFailed extends TransactionCommitFailed { + BitcoinTransactionCommitFailed({super.errorMessage}); +} class BitcoinTransactionCommitFailedDustChange extends TransactionCommitFailedDustChange {} diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart index 529ac61da..a59b4f429 100644 --- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart +++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart @@ -73,7 +73,9 @@ class PendingBitcoinTransaction with PendingTransaction { if (error.contains("bad-txns-vout-negative")) { throw BitcoinTransactionCommitFailedVoutNegative(); } + throw BitcoinTransactionCommitFailed(errorMessage: error); } + throw BitcoinTransactionCommitFailed(); } diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 53cf550c8..50cd432c0 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -21,10 +21,10 @@ packages: dependency: transitive description: name: args - sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.5.0" asn1lib: dependency: transitive description: @@ -80,7 +80,7 @@ packages: description: path: "." ref: cake-update-v2 - resolved-ref: "3fd81d238b990bb767fc7a4fdd5053a22a142e2e" + resolved-ref: "01d844a5f5a520a31df5254e34169af4664aa769" url: "https://github.com/cake-tech/bitcoin_base.git" source: git version: "4.2.0" @@ -153,10 +153,10 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21" + sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22" url: "https://pub.dev" source: hosted - version: "2.4.8" + version: "2.4.9" build_runner_core: dependency: transitive description: @@ -177,10 +177,10 @@ packages: dependency: transitive description: name: built_value - sha256: a3ec2e0f967bc47f69f95009bb93db936288d61d5343b9436e378b28a2f830c6 + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb url: "https://pub.dev" source: hosted - version: "8.9.0" + version: "8.9.2" characters: dependency: transitive description: @@ -309,10 +309,10 @@ packages: dependency: "direct main" description: name: flutter_mobx - sha256: "4a5d062ff85ed3759f4aac6410ff0ffae32e324b2e71ca722ae1b37b32e865f4" + sha256: "859fbf452fa9c2519d2700b125dd7fb14c508bbdd7fb65e26ca8ff6c92280e2e" url: "https://pub.dev" source: hosted - version: "2.2.0+2" + version: "2.2.1+1" flutter_test: dependency: "direct dev" description: flutter @@ -322,10 +322,10 @@ packages: dependency: transitive description: name: frontend_server_client - sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "4.0.0" glob: dependency: transitive description: @@ -466,10 +466,10 @@ packages: dependency: "direct main" description: name: mobx - sha256: "74ee54012dc7c1b3276eaa960a600a7418ef5f9997565deb8fca1fd88fb36b78" + sha256: "63920b27b32ad1910adfe767ab1750e4c212e8923232a1f891597b362074ea5e" url: "https://pub.dev" source: hosted - version: "2.3.0+1" + version: "2.3.3+2" mobx_codegen: dependency: "direct dev" description: @@ -570,10 +570,10 @@ packages: dependency: transitive description: name: pointycastle - sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" + sha256: "70fe966348fe08c34bf929582f1d8247d9d9408130723206472b4687227e4333" url: "https://pub.dev" source: hosted - version: "3.7.4" + version: "3.8.0" pool: dependency: transitive description: @@ -586,10 +586,10 @@ packages: dependency: transitive description: name: provider - sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c url: "https://pub.dev" source: hosted - version: "6.1.1" + version: "6.1.2" pub_semver: dependency: transitive description: diff --git a/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart b/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart index da4710a8b..6d2ab4696 100644 --- a/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart +++ b/cw_bitcoin_cash/lib/src/pending_bitcoin_cash_transaction.dart @@ -62,7 +62,9 @@ class PendingBitcoinCashTransaction with PendingTransaction { if (error.contains("bad-txns-vout-negative")) { throw BitcoinTransactionCommitFailedVoutNegative(); } + throw BitcoinTransactionCommitFailed(errorMessage: error); } + throw BitcoinTransactionCommitFailed(); } diff --git a/cw_core/lib/exceptions.dart b/cw_core/lib/exceptions.dart index 848ac40e6..d07da8109 100644 --- a/cw_core/lib/exceptions.dart +++ b/cw_core/lib/exceptions.dart @@ -19,7 +19,11 @@ class TransactionNoDustOnChangeException implements Exception { final String min; } -class TransactionCommitFailed implements Exception {} +class TransactionCommitFailed implements Exception { + final String? errorMessage; + + TransactionCommitFailed({this.errorMessage}); +} class TransactionCommitFailedDustChange implements Exception {} diff --git a/cw_core/lib/unspent_transaction_output.dart b/cw_core/lib/unspent_transaction_output.dart index b52daf43c..595df18f4 100644 --- a/cw_core/lib/unspent_transaction_output.dart +++ b/cw_core/lib/unspent_transaction_output.dart @@ -14,6 +14,7 @@ class Unspent { bool isChange; bool isSending; bool isFrozen; + int? confirmations; String note; bool get isP2wpkh => address.startsWith('bc') || address.startsWith('ltc'); diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 970bb31f2..93fadea72 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -100,7 +100,7 @@ class SendPage extends BasePage { AppBarStyle get appBarStyle => AppBarStyle.transparent; double _sendCardHeight(BuildContext context) { - double initialHeight = 450; + double initialHeight = 480; if (sendViewModel.hasCoinControl) { initialHeight += 35; } diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 2e00d1f0b..cabb723e1 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -562,7 +562,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor return S.current.tx_no_dust_exception; } if (error is TransactionCommitFailed) { - return S.current.tx_commit_failed; + return "${S.current.tx_commit_failed}${error.errorMessage != null ? "\n\n${error.errorMessage}" : ""}"; } if (error is TransactionCommitFailedDustChange) { return S.current.tx_rejected_dust_change; From 509b92e97f51731a73736ca5c27e3e2d7df3def4 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Mon, 29 Apr 2024 17:49:56 -0700 Subject: [PATCH 199/241] Bitcoin derivations (#1089) * - Update and Fix Conflicts with main * Add Balances for ERC20 tokens * Fix conflicts with main * Add erc20 abi json * Add send erc20 tokens initial function * add missing getHeightByDate in Haven [skip ci] * Allow contacts and wallets from the same tag * Add Shiba Inu icon * Add send ERC-20 tokens initial flow * Add missing import in generated file * Add initial approach for transaction sending for ERC-20 tokens * Refactor signing/sending transactions * Add initial flow for transactions subscription * Refactor signing/sending transactions * Add home settings icon * Fix conflicts with main * Initial flow for home settings * Add logic flow for adding erc20 tokens * Fix initial UI * Finalize UI for Tokens * Integrate UI with Ethereum flow * Add "Enable/Disable" feature for ERC20 tokens * Add initial Erc20 tokens * Add Sorting and Pin Native Token features * Fix price sorting * Sort tokens list as well when Sort criteria changes * - Improve sorting balances flow - Add initial add token from search bar flow * Fix Accounts Popup UI * Fix Pin native token * Fix Enabling/Disabling tokens Fix sorting by fiat once app is opened Improve token availability mechanism * Fix deleting token Fix renaming tokens * Fix issue with search * Add more tokens * - Fix scroll issue - Add ERC20 tokens placeholder image in picker * - Separate and organize default erc20 tokens - Fix scrolling - Add token placeholder images in picker - Sort disabled tokens alphabetically * Change BNB token initial availability [skip ci] * Fix Conflicts with main * Fix Conflicts with main * Add Verse ERC20 token to the initial tokens list * Add rename wallet to Ethereum * Integrate EtherScan API for fetching address transactions Generate Ethereum specific secrets in Ethereum package * Adjust transactions fiat price for ERC20 tokens * Free Up GitHub Actions Ubuntu Runner Disk Space * Free Up GitHub Actions Ubuntu Runner Disk space (trial 2) * Fix Transaction Fee display * Save transaction history * Enhance loading time for erc20 tokens transactions * Minor Fixes and Enhancements * Fix sending erc20 fix block explorer issue * Fix int overflow * Fix transaction amount conversions * Minor: `slow` -> `Slow` [skip-ci] * initial changes * more base config stuff * config changes * successfully builds! * save * successfully add nano wallet * save * seed generation * receive screen + node screen working * tx history working and fiat fixes * balance working * derivation updates * nano-unfinished * sends working * remove fees from send screen, send and receive transactions working * fixes + auto receive incoming txs * fix for scanning QR codes * save * update translations * fixes * more fixes * more strings * small fix * fix github actions workflow * potential fix * potential fix * ci/cd fix * change rep working * seed generation fixes * fixes * save * change rep screen functional * save * banano changes * fixes, start adding ui for PoW * pow node changes * update translations * fix * account changing barely working * save * disable account generation * small fix * save * UI work * save * fixes after merge main * fixes * remove monero stuff, work on derivation ui * lots of fixes + finish up seed derivation * last minute fixes * node related fixes * more fixes * small fix * more fixes * fixes * pretty big refactor for pow, still some bugs * finally works! * get transactions after send * fix * merge conflict fixes * save * fix pow node showing up twice * done * initial changes * small fix * more merge fixes * fixes * more fixes * fix * save * fix manage pow nodes setting appearing on other wallets * fix contact bug * fixes * fiat fixes * save * save * save * save * updates * cleanup * restore fix * fixes * remove deprecated alert * fix * small fix * remove outdated warning * electrum restore fixes * fixes * fixes * fix * derivation fixes * nano fixes pt.1 * nano fixes pt.2 * bip39 fixes * pownode refactor * nodes pages fixes * observer fix * ssl fix * remove old references * remove unused imports * code cleanup * small fix * small potential fix * save * derivation fixes * deterministic fix * fix pt.2 * derivation class fixes * review fixes from nano that also apply here * formatting * stuff that should've stayed deleted * post merge fixes * remove problematic imports and duplicate changes * Delete lib/nano/nano.dart * move wallet restore page proxy code to the view model * fix dashboard page indicators being the same color * debatably better refactoring of derivationInfo, migration needed * additional refactor improvements * blanket comment some stuff out to narrow down this issue * refactor fixes * fix nano exchange * fix , bug, i.e. replace , with . when making a nano transaction * fix nano sending, update restore page wording, and other minor fixes * write migration for existing bitcoin and nano wallets * merge fixes * minor fixes * use default derivation type when restoring from qr code * fixes for restoring * fixes * fixes * merge fix * Fix issues with Creating Electrum and Restoring Bip39 * updates & fixes * Add missing case for no transactions BIP39 wallet restore * Make the default BIP39 the 84 derivation path * Add Samourai Deposit * litecoin mnemonic error fix * Bip39 passphrase support (#1412) * save * passphrase working * fix for when loading wallets + translation update * minor fix * Fix Nano * minor fix [skip ci] --------- Co-authored-by: OmarHatem * change error state seed conditions into throwables [skip ci] * litecoin fixes * Bip39 minor enhancements (#1416) * minor enhancements * rename bitcoin_derivations -> electrum_derivations * Remove duplicate derivations handle default case * minor fix * Enable passphrase for Litecoin * obscure text of passphrase --------- Co-authored-by: OmarHatem Co-authored-by: Justin Ehrenhofer Co-authored-by: fossephate --- assets/nano_pow_node_list.yml | 2 +- cw_bitcoin/lib/bitcoin_mnemonic.dart | 32 +-- cw_bitcoin/lib/bitcoin_wallet.dart | 56 +++++- .../bitcoin_wallet_creation_credentials.dart | 33 +++- cw_bitcoin/lib/bitcoin_wallet_service.dart | 7 +- cw_bitcoin/lib/electrum_derivations.dart | 104 ++++++++++ cw_bitcoin/lib/electrum_wallet.dart | 8 +- cw_bitcoin/lib/electrum_wallet_snapshot.dart | 15 ++ cw_bitcoin/lib/litecoin_wallet.dart | 18 +- cw_bitcoin/lib/litecoin_wallet_service.dart | 7 +- cw_bitcoin/lib/utils.dart | 67 +++++-- cw_bitcoin/pubspec.lock | 32 ++- cw_core/lib/hive_type_ids.dart | 3 +- cw_core/lib/wallet_credentials.dart | 14 +- cw_core/lib/wallet_info.dart | 79 +++++--- cw_core/pubspec.lock | 32 ++- cw_nano/lib/nano_wallet.dart | 7 +- .../lib/nano_wallet_creation_credentials.dart | 19 +- cw_nano/lib/nano_wallet_service.dart | 12 +- lib/bitcoin/cw_bitcoin.dart | 186 +++++++++++++++--- lib/entities/default_settings_migration.dart | 18 ++ lib/entities/parse_address_from_domain.dart | 6 +- lib/main.dart | 6 +- lib/nano/cw_nano.dart | 74 +++++-- .../wallet_restore_choose_derivation.dart | 22 +-- .../wallet_restore_from_seed_form.dart | 30 ++- .../screens/restore/wallet_restore_page.dart | 140 +++++-------- .../screens/wallet_list/wallet_list_page.dart | 4 +- lib/src/widgets/base_text_form_field.dart | 3 + .../restore/restore_from_qr_vm.dart | 44 +++-- lib/view_model/send/send_view_model.dart | 2 +- lib/view_model/wallet_creation_vm.dart | 46 ++++- lib/view_model/wallet_restore_view_model.dart | 52 +++-- res/values/strings_ar.arb | 1 + res/values/strings_bg.arb | 1 + res/values/strings_cs.arb | 1 + res/values/strings_de.arb | 5 +- res/values/strings_en.arb | 1 + res/values/strings_es.arb | 1 + res/values/strings_fr.arb | 1 + res/values/strings_ha.arb | 1 + res/values/strings_hi.arb | 1 + res/values/strings_hr.arb | 1 + res/values/strings_id.arb | 1 + res/values/strings_it.arb | 1 + res/values/strings_ja.arb | 1 + res/values/strings_ko.arb | 3 +- res/values/strings_my.arb | 1 + res/values/strings_nl.arb | 1 + res/values/strings_pl.arb | 1 + res/values/strings_pt.arb | 1 + res/values/strings_ru.arb | 1 + res/values/strings_th.arb | 1 + res/values/strings_tl.arb | 1 + res/values/strings_tr.arb | 1 + res/values/strings_uk.arb | 1 + res/values/strings_ur.arb | 1 + res/values/strings_yo.arb | 1 + res/values/strings_zh.arb | 1 + tool/configure.dart | 37 +++- 60 files changed, 908 insertions(+), 341 deletions(-) create mode 100644 cw_bitcoin/lib/electrum_derivations.dart diff --git a/assets/nano_pow_node_list.yml b/assets/nano_pow_node_list.yml index b90845034..3bbc7c3fb 100644 --- a/assets/nano_pow_node_list.yml +++ b/assets/nano_pow_node_list.yml @@ -6,4 +6,4 @@ uri: workers.perish.co - uri: worker.nanoriver.cc - useSSL: true \ No newline at end of file + useSSL: true diff --git a/cw_bitcoin/lib/bitcoin_mnemonic.dart b/cw_bitcoin/lib/bitcoin_mnemonic.dart index 9163fcb11..4a01d6ddc 100644 --- a/cw_bitcoin/lib/bitcoin_mnemonic.dart +++ b/cw_bitcoin/lib/bitcoin_mnemonic.dart @@ -90,8 +90,7 @@ List prefixMatches(String source, List prefixes) { return prefixes.map((prefix) => hx.startsWith(prefix.toLowerCase())).toList(); } -Future generateMnemonic( - {int strength = 264, String prefix = segwit}) async { +Future generateElectrumMnemonic({int strength = 264, String prefix = segwit}) async { final wordBitlen = logBase(wordlist.length, 2).ceil(); final wordCount = strength / wordBitlen; final byteCount = ((wordCount * wordBitlen).ceil() / 8).ceil(); @@ -106,22 +105,29 @@ Future generateMnemonic( return result; } +Future checkIfMnemonicIsElectrum2(String mnemonic) async { + return prefixMatches(mnemonic, [segwit]).first; +} + +Future getMnemonicHash(String mnemonic) async { + final hmacSha512 = Hmac(sha512, utf8.encode('Seed version')); + final digest = hmacSha512.convert(utf8.encode(normalizeText(mnemonic))); + final hx = digest.toString(); + return hx; +} + Future mnemonicToSeedBytes(String mnemonic, {String prefix = segwit}) async { - final pbkdf2 = cryptography.Pbkdf2( - macAlgorithm: cryptography.Hmac.sha512(), - iterations: 2048, - bits: 512); + final pbkdf2 = + cryptography.Pbkdf2(macAlgorithm: cryptography.Hmac.sha512(), iterations: 2048, bits: 512); final text = normalizeText(mnemonic); // pbkdf2.deriveKey(secretKey: secretKey, nonce: nonce) final key = await pbkdf2.deriveKey( - secretKey: cryptography.SecretKey(text.codeUnits), - nonce: 'electrum'.codeUnits); + secretKey: cryptography.SecretKey(text.codeUnits), nonce: 'electrum'.codeUnits); final bytes = await key.extractBytes(); return Uint8List.fromList(bytes); } -bool matchesAnyPrefix(String mnemonic) => - prefixMatches(mnemonic, [segwit]).any((el) => el); +bool matchesAnyPrefix(String mnemonic) => prefixMatches(mnemonic, [segwit]).any((el) => el); bool validateMnemonic(String mnemonic, {String prefix = segwit}) { try { @@ -208,10 +214,8 @@ String removeCJKSpaces(String source) { } String normalizeText(String source) { - final res = removeCombiningCharacters(unorm.nfkd(source).toLowerCase()) - .trim() - .split('/\s+/') - .join(' '); + final res = + removeCombiningCharacters(unorm.nfkd(source).toLowerCase()).trim().split('/\s+/').join(' '); return removeCJKSpaces(res); } diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index bf59e8637..1d29307ca 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -12,6 +12,7 @@ import 'package:cw_core/wallet_info.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum_balance.dart'; import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart'; +import 'package:bip39/bip39.dart' as bip39; part 'bitcoin_wallet.g.dart'; @@ -30,8 +31,10 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { ElectrumBalance? initialBalance, Map? initialRegularAddressIndex, Map? initialChangeAddressIndex, + String? passphrase, }) : super( mnemonic: mnemonic, + passphrase: passphrase, password: password, walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfo, @@ -44,14 +47,19 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialBalance: initialBalance, seedBytes: seedBytes, currency: CryptoCurrency.btc) { + // in a standard BIP44 wallet, mainHd derivation path = m/84'/0'/0'/0 (account 0, index unspecified here) + // the sideHd derivation path = m/84'/0'/0'/1 (account 1, index unspecified here) + String derivationPath = walletInfo.derivationInfo!.derivationPath!; + String sideDerivationPath = derivationPath.substring(0, derivationPath.length - 1) + "1"; + final hd = bitcoin.HDWallet.fromSeed(seedBytes, network: networkType); walletAddresses = BitcoinWalletAddresses( walletInfo, electrumClient: electrumClient, initialAddresses: initialAddresses, initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex, - mainHd: hd, - sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"), + mainHd: hd.derivePath(derivationPath), + sideHd: hd.derivePath(sideDerivationPath), network: networkParam ?? network, ); autorun((_) { @@ -64,6 +72,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { required String password, required WalletInfo walletInfo, required Box unspentCoinsInfo, + String? passphrase, String? addressPageType, BasedUtxoNetwork? network, List? initialAddresses, @@ -71,14 +80,29 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { Map? initialRegularAddressIndex, Map? initialChangeAddressIndex, }) async { + late Uint8List seedBytes; + + switch (walletInfo.derivationInfo?.derivationType) { + case DerivationType.bip39: + seedBytes = await bip39.mnemonicToSeed( + mnemonic, + passphrase: passphrase ?? "", + ); + break; + case DerivationType.electrum: + default: + seedBytes = await mnemonicToSeedBytes(mnemonic); + break; + } return BitcoinWallet( mnemonic: mnemonic, + passphrase: passphrase ?? "", password: password, walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfo, initialAddresses: initialAddresses, initialBalance: initialBalance, - seedBytes: await mnemonicToSeedBytes(mnemonic), + seedBytes: seedBytes, initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex, addressPageType: addressPageType, @@ -97,14 +121,38 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { : BitcoinNetwork.mainnet; final snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password, network); + walletInfo.derivationInfo ??= DerivationInfo( + derivationType: snp.derivationType ?? DerivationType.electrum, + derivationPath: snp.derivationPath, + ); + + // set the default if not present: + walletInfo.derivationInfo!.derivationPath = snp.derivationPath ?? "m/0'/1"; + + late Uint8List seedBytes; + + switch (walletInfo.derivationInfo!.derivationType) { + case DerivationType.electrum: + seedBytes = await mnemonicToSeedBytes(snp.mnemonic); + break; + case DerivationType.bip39: + default: + seedBytes = await bip39.mnemonicToSeed( + snp.mnemonic, + passphrase: snp.passphrase ?? '', + ); + break; + } + return BitcoinWallet( mnemonic: snp.mnemonic, password: password, + passphrase: snp.passphrase, walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfo, initialAddresses: snp.addresses, initialBalance: snp.balance, - seedBytes: await mnemonicToSeedBytes(snp.mnemonic), + seedBytes: seedBytes, initialRegularAddressIndex: snp.regularAddressIndex, initialChangeAddressIndex: snp.changeAddressIndex, addressPageType: snp.addressPageType, diff --git a/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart b/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart index 37b272a1b..981c7a466 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart @@ -2,14 +2,35 @@ import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; class BitcoinNewWalletCredentials extends WalletCredentials { - BitcoinNewWalletCredentials({required String name, WalletInfo? walletInfo}) - : super(name: name, walletInfo: walletInfo); + BitcoinNewWalletCredentials( + {required String name, + WalletInfo? walletInfo, + DerivationType? derivationType, + String? derivationPath}) + : super( + name: name, + walletInfo: walletInfo, + ); } class BitcoinRestoreWalletFromSeedCredentials extends WalletCredentials { - BitcoinRestoreWalletFromSeedCredentials( - {required String name, required String password, required this.mnemonic, WalletInfo? walletInfo}) - : super(name: name, password: password, walletInfo: walletInfo); + BitcoinRestoreWalletFromSeedCredentials({ + required String name, + required String password, + required this.mnemonic, + WalletInfo? walletInfo, + required DerivationType derivationType, + required String derivationPath, + String? passphrase, + }) : super( + name: name, + password: password, + passphrase: passphrase, + walletInfo: walletInfo, + derivationInfo: DerivationInfo( + derivationType: derivationType, + derivationPath: derivationPath, + )); final String mnemonic; } @@ -20,4 +41,4 @@ class BitcoinRestoreWalletFromWIFCredentials extends WalletCredentials { : super(name: name, password: password, walletInfo: walletInfo); final String wif; -} \ No newline at end of file +} diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index 38e769d15..e0548771b 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -12,6 +12,7 @@ import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; import 'package:collection/collection.dart'; +import 'package:bip39/bip39.dart' as bip39; class BitcoinWalletService extends WalletService { @@ -29,8 +30,9 @@ class BitcoinWalletService extends WalletService restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { - if (!validateMnemonic(credentials.mnemonic)) { + if (!validateMnemonic(credentials.mnemonic) && !bip39.validateMnemonic(credentials.mnemonic)) { throw BitcoinMnemonicIsIncorrectException(); } @@ -114,6 +116,7 @@ class BitcoinWalletService extends WalletService> electrum_derivations = { + DerivationType.electrum: [ + DerivationInfo( + derivationType: DerivationType.electrum, + derivationPath: "m/0'/0", + description: "Electrum", + scriptType: "p2wpkh", + ), + ], + DerivationType.bip39: [ + DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/44'/0'/0'", + description: "Standard BIP44", + scriptType: "p2pkh", + ), + DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/49'/0'/0'", + description: "Standard BIP49 compatibility segwit", + scriptType: "p2wpkh-p2sh", + ), + DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/84'/0'/0'", + description: "Standard BIP84 native segwit", + scriptType: "p2wpkh", + ), + DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/0'", + description: "Non-standard legacy", + scriptType: "p2pkh", + ), + DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/0'", + description: "Non-standard compatibility segwit", + scriptType: "p2wpkh-p2sh", + ), + DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/0'", + description: "Non-standard native segwit", + scriptType: "p2wpkh", + ), + DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/44'/0'/0'", + description: "Samourai Deposit", + scriptType: "p2wpkh", + ), + DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/49'/0'/0'", + description: "Samourai Deposit", + scriptType: "p2wpkh", + ), + DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/84'/0'/2147483644'", + description: "Samourai Bad Bank (toxic change)", + scriptType: "p2wpkh", + ), + DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/84'/0'/2147483645'", + description: "Samourai Whirlpool Pre Mix", + scriptType: "p2wpkh", + ), + DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/84'/0'/2147483646'", + description: "Samourai Whirlpool Post Mix", + scriptType: "p2wpkh", + ), + DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/44'/0'/2147483647'", + description: "Samourai Ricochet legacy", + scriptType: "p2pkh", + ), + DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/49'/0'/2147483647'", + description: "Samourai Ricochet compatibility segwit", + scriptType: "p2wpkh-p2sh", + ), + DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/84'/0'/2147483647'", + description: "Samourai Ricochet native segwit", + scriptType: "p2wpkh", + ), + DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/84'/2'/0'", + description: "Default Litecoin", + scriptType: "p2wpkh", + ), + ], +}; diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 4a76ee5dd..8342e4816 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -55,13 +55,15 @@ abstract class ElectrumWalletBase required this.networkType, required this.mnemonic, required Uint8List seedBytes, + this.passphrase, List? initialAddresses, ElectrumClient? electrumClient, ElectrumBalance? initialBalance, CryptoCurrency? currency}) : hd = currency == CryptoCurrency.bch ? bitcoinCashHDWallet(seedBytes) - : bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/0"), + : bitcoin.HDWallet.fromSeed(seedBytes, network: networkType) + .derivePath(walletInfo.derivationInfo?.derivationPath ?? "m/0'/0"), syncStatus = NotConnectedSyncStatus(), _password = password, _feeRates = [], @@ -92,6 +94,7 @@ abstract class ElectrumWalletBase final bitcoin.HDWallet hd; final String mnemonic; + final String? passphrase; @override @observable @@ -617,6 +620,7 @@ abstract class ElectrumWalletBase String toJSON() => json.encode({ 'mnemonic': mnemonic, + 'passphrase': passphrase ?? '', 'account_index': walletAddresses.currentReceiveAddressIndexByType, 'change_address_index': walletAddresses.currentChangeAddressIndexByType, 'addresses': walletAddresses.allAddresses.map((addr) => addr.toJSON()).toList(), @@ -624,6 +628,8 @@ abstract class ElectrumWalletBase ? SegwitAddresType.p2wpkh.toString() : walletInfo.addressPageType.toString(), 'balance': balance[currency]?.toJSON(), + 'derivationTypeIndex': walletInfo.derivationInfo?.derivationType?.index, + 'derivationPath': walletInfo.derivationInfo?.derivationPath, }); int feeRate(TransactionPriority priority) { diff --git a/cw_bitcoin/lib/electrum_wallet_snapshot.dart b/cw_bitcoin/lib/electrum_wallet_snapshot.dart index 6f76ab312..218792e3c 100644 --- a/cw_bitcoin/lib/electrum_wallet_snapshot.dart +++ b/cw_bitcoin/lib/electrum_wallet_snapshot.dart @@ -3,6 +3,7 @@ import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum_balance.dart'; import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/utils/file.dart'; import 'package:cw_core/wallet_type.dart'; @@ -17,6 +18,9 @@ class ElectrumWalletSnapshot { required this.regularAddressIndex, required this.changeAddressIndex, required this.addressPageType, + this.passphrase, + this.derivationType, + this.derivationPath, }); final String name; @@ -29,6 +33,9 @@ class ElectrumWalletSnapshot { ElectrumBalance balance; Map regularAddressIndex; Map changeAddressIndex; + String? passphrase; + DerivationType? derivationType; + String? derivationPath; static Future load( String name, WalletType type, String password, BasedUtxoNetwork network) async { @@ -37,6 +44,7 @@ class ElectrumWalletSnapshot { final data = json.decode(jsonSource) as Map; final addressesTmp = data['addresses'] as List? ?? []; final mnemonic = data['mnemonic'] as String; + final passphrase = data['passphrase'] as String? ?? ''; final addresses = addressesTmp .whereType() .map((addr) => BitcoinAddressRecord.fromJSON(addr, network)) @@ -46,6 +54,10 @@ class ElectrumWalletSnapshot { var regularAddressIndexByType = {SegwitAddresType.p2wpkh.toString(): 0}; var changeAddressIndexByType = {SegwitAddresType.p2wpkh.toString(): 0}; + final derivationType = + DerivationType.values[(data['derivationTypeIndex'] as int?) ?? DerivationType.electrum.index]; + final derivationPath = data['derivationPath'] as String? ?? "m/0'/0"; + try { regularAddressIndexByType = { SegwitAddresType.p2wpkh.toString(): int.parse(data['account_index'] as String? ?? '0') @@ -65,12 +77,15 @@ class ElectrumWalletSnapshot { name: name, type: type, password: password, + passphrase: passphrase, mnemonic: mnemonic, addresses: addresses, balance: balance, regularAddressIndex: regularAddressIndexByType, changeAddressIndex: changeAddressIndexByType, addressPageType: data['address_page_type'] as String?, + derivationType: derivationType, + derivationPath: derivationPath, ); } } diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index d2379d5a5..4d166e47b 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -15,6 +15,7 @@ import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum_balance.dart'; import 'package:cw_bitcoin/litecoin_network.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; +import 'package:bip39/bip39.dart' as bip39; part 'litecoin_wallet.g.dart'; @@ -62,11 +63,26 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { required String password, required WalletInfo walletInfo, required Box unspentCoinsInfo, + String? passphrase, String? addressPageType, List? initialAddresses, ElectrumBalance? initialBalance, Map? initialRegularAddressIndex, Map? initialChangeAddressIndex}) async { + late Uint8List seedBytes; + + switch (walletInfo.derivationInfo?.derivationType) { + case DerivationType.bip39: + seedBytes = await bip39.mnemonicToSeed( + mnemonic, + passphrase: passphrase ?? "", + ); + break; + case DerivationType.electrum: + default: + seedBytes = await mnemonicToSeedBytes(mnemonic); + break; + } return LitecoinWallet( mnemonic: mnemonic, password: password, @@ -74,7 +90,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { unspentCoinsInfo: unspentCoinsInfo, initialAddresses: initialAddresses, initialBalance: initialBalance, - seedBytes: await mnemonicToSeedBytes(mnemonic), + seedBytes: seedBytes, initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex, addressPageType: addressPageType, diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index ee3b0e628..9143556ab 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -11,6 +11,7 @@ import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:collection/collection.dart'; +import 'package:bip39/bip39.dart' as bip39; class LitecoinWalletService extends WalletService< BitcoinNewWalletCredentials, @@ -27,8 +28,9 @@ class LitecoinWalletService extends WalletService< @override Future create(BitcoinNewWalletCredentials credentials, {bool? isTestnet}) async { final wallet = await LitecoinWalletBase.create( - mnemonic: await generateMnemonic(), + mnemonic: await generateElectrumMnemonic(), password: credentials.password!, + passphrase: credentials.passphrase, walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.save(); @@ -100,12 +102,13 @@ class LitecoinWalletService extends WalletService< @override Future restoreFromSeed( BitcoinRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { - if (!validateMnemonic(credentials.mnemonic)) { + if (!validateMnemonic(credentials.mnemonic) && !bip39.validateMnemonic(credentials.mnemonic)) { throw LitecoinMnemonicIsIncorrectException(); } final wallet = await LitecoinWalletBase.create( password: credentials.password!, + passphrase: credentials.passphrase, mnemonic: credentials.mnemonic, walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource); diff --git a/cw_bitcoin/lib/utils.dart b/cw_bitcoin/lib/utils.dart index b156ccba3..b3707e764 100644 --- a/cw_bitcoin/lib/utils.dart +++ b/cw_bitcoin/lib/utils.dart @@ -5,29 +5,58 @@ import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData; import 'package:hex/hex.dart'; -bitcoin.PaymentData generatePaymentData({required bitcoin.HDWallet hd, required int index}) => - PaymentData(pubkey: Uint8List.fromList(HEX.decode(hd.derive(index).pubKey!))); +bitcoin.PaymentData generatePaymentData({required bitcoin.HDWallet hd, int? index}) { + final pubKey = index != null ? hd.derive(index).pubKey! : hd.pubKey!; + return PaymentData(pubkey: Uint8List.fromList(HEX.decode(pubKey))); +} ECPrivate generateECPrivate( - {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => - ECPrivate.fromWif(hd.derive(index).wif!, netVersion: network.wifNetVer); + {required bitcoin.HDWallet hd, required BasedUtxoNetwork network, int? index}) { + final wif = index != null ? hd.derive(index).wif! : hd.wif!; + return ECPrivate.fromWif(wif, netVersion: network.wifNetVer); +} -String generateP2WPKHAddress( - {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => - ECPublic.fromHex(hd.derive(index).pubKey!).toP2wpkhAddress().toAddress(network); +String generateP2WPKHAddress({ + required bitcoin.HDWallet hd, + required BasedUtxoNetwork network, + int? index, +}) { + final pubKey = index != null ? hd.derive(index).pubKey! : hd.pubKey!; + return ECPublic.fromHex(pubKey).toP2wpkhAddress().toAddress(network); +} -String generateP2SHAddress( - {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => - ECPublic.fromHex(hd.derive(index).pubKey!).toP2wpkhInP2sh().toAddress(network); +String generateP2SHAddress({ + required bitcoin.HDWallet hd, + required BasedUtxoNetwork network, + int? index, +}) { + final pubKey = index != null ? hd.derive(index).pubKey! : hd.pubKey!; + return ECPublic.fromHex(pubKey).toP2wpkhInP2sh().toAddress(network); +} -String generateP2WSHAddress( - {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => - ECPublic.fromHex(hd.derive(index).pubKey!).toP2wshAddress().toAddress(network); +String generateP2WSHAddress({ + required bitcoin.HDWallet hd, + required BasedUtxoNetwork network, + int? index, +}) { + final pubKey = index != null ? hd.derive(index).pubKey! : hd.pubKey!; + return ECPublic.fromHex(pubKey).toP2wshAddress().toAddress(network); +} -String generateP2PKHAddress( - {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => - ECPublic.fromHex(hd.derive(index).pubKey!).toP2pkhAddress().toAddress(network); +String generateP2PKHAddress({ + required bitcoin.HDWallet hd, + required BasedUtxoNetwork network, + int? index, +}) { + final pubKey = index != null ? hd.derive(index).pubKey! : hd.pubKey!; + return ECPublic.fromHex(pubKey).toP2pkhAddress().toAddress(network); +} -String generateP2TRAddress( - {required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) => - ECPublic.fromHex(hd.derive(index).pubKey!).toTaprootAddress().toAddress(network); +String generateP2TRAddress({ + required bitcoin.HDWallet hd, + required BasedUtxoNetwork network, + int? index, +}) { + final pubKey = index != null ? hd.derive(index).pubKey! : hd.pubKey!; + return ECPublic.fromHex(pubKey).toTaprootAddress().toAddress(network); +} diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 50cd432c0..86d58b9b1 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -217,10 +217,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.17.1" convert: dependency: transitive description: @@ -434,18 +434,18 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.15" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.2.0" meta: dependency: transitive description: @@ -663,10 +663,10 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" stack_trace: dependency: transitive description: @@ -711,10 +711,10 @@ packages: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.5.1" timing: dependency: transitive description: @@ -748,21 +748,13 @@ packages: source: hosted version: "2.1.4" watcher: - dependency: "direct overridden" + dependency: transitive description: name: watcher sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.dev" source: hosted version: "1.1.0" - web: - dependency: transitive - description: - name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 - url: "https://pub.dev" - source: hosted - version: "0.1.4-beta" web_socket_channel: dependency: transitive description: @@ -796,5 +788,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.0-185.0.dev <4.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.10.0" diff --git a/cw_core/lib/hive_type_ids.dart b/cw_core/lib/hive_type_ids.dart index 3fa2eb647..e0896bab1 100644 --- a/cw_core/lib/hive_type_ids.dart +++ b/cw_core/lib/hive_type_ids.dart @@ -14,4 +14,5 @@ const ERC20_TOKEN_TYPE_ID = 12; const NANO_ACCOUNT_TYPE_ID = 13; const POW_NODE_TYPE_ID = 14; const DERIVATION_TYPE_TYPE_ID = 15; -const SPL_TOKEN_TYPE_ID = 16; +const SPL_TOKEN_TYPE_ID = 16; +const DERIVATION_INFO_TYPE_ID = 17; diff --git a/cw_core/lib/wallet_credentials.dart b/cw_core/lib/wallet_credentials.dart index 4d5f331c9..9b28680f9 100644 --- a/cw_core/lib/wallet_credentials.dart +++ b/cw_core/lib/wallet_credentials.dart @@ -7,15 +7,19 @@ abstract class WalletCredentials { this.seedPhraseLength, this.walletInfo, this.password, - this.derivationType, - this.derivationPath, - }); + this.passphrase, + this.derivationInfo, + }) { + if (this.walletInfo != null && derivationInfo != null) { + this.walletInfo!.derivationInfo = derivationInfo; + } + } final String name; final int? height; int? seedPhraseLength; String? password; - DerivationType? derivationType; - String? derivationPath; + String? passphrase; WalletInfo? walletInfo; + DerivationInfo? derivationInfo; } diff --git a/cw_core/lib/wallet_info.dart b/cw_core/lib/wallet_info.dart index 2a44175a7..4892f6d1d 100644 --- a/cw_core/lib/wallet_info.dart +++ b/cw_core/lib/wallet_info.dart @@ -17,28 +17,42 @@ enum DerivationType { @HiveField(3) bip39, @HiveField(4) - electrum1, - @HiveField(5) - electrum2, + electrum, } -class DerivationInfo { +@HiveType(typeId: DerivationInfo.typeId) +class DerivationInfo extends HiveObject { DerivationInfo({ - required this.derivationType, + this.derivationType, this.derivationPath, this.balance = "", this.address = "", - this.height = 0, - this.script_type, + this.transactionsCount = 0, + this.scriptType, this.description, }); - String balance; + static const typeId = DERIVATION_INFO_TYPE_ID; + + @HiveField(0, defaultValue: '') String address; - int height; - final DerivationType derivationType; - final String? derivationPath; - final String? script_type; + + @HiveField(1, defaultValue: '') + String balance; + + @HiveField(2) + int transactionsCount; + + @HiveField(3) + DerivationType? derivationType; + + @HiveField(4) + String? derivationPath; + + @HiveField(5) + final String? scriptType; + + @HiveField(6) final String? description; } @@ -57,8 +71,7 @@ class WalletInfo extends HiveObject { this.yatEid, this.yatLastUsedAddressRaw, this.showIntroCakePayCard, - this.derivationType, - this.derivationPath) + this.derivationInfo) : _yatLastUsedAddressController = StreamController.broadcast(); factory WalletInfo.external({ @@ -74,24 +87,23 @@ class WalletInfo extends HiveObject { bool? showIntroCakePayCard, String yatEid = '', String yatLastUsedAddressRaw = '', - DerivationType? derivationType, - String? derivationPath, + DerivationInfo? derivationInfo, }) { return WalletInfo( - id, - name, - type, - isRecovery, - restoreHeight, - date.millisecondsSinceEpoch, - dirPath, - path, - address, - yatEid, - yatLastUsedAddressRaw, - showIntroCakePayCard, - derivationType, - derivationPath); + id, + name, + type, + isRecovery, + restoreHeight, + date.millisecondsSinceEpoch, + dirPath, + path, + address, + yatEid, + yatLastUsedAddressRaw, + showIntroCakePayCard, + derivationInfo, + ); } static const typeId = WALLET_INFO_TYPE_ID; @@ -143,10 +155,10 @@ class WalletInfo extends HiveObject { List? usedAddresses; @HiveField(16) - DerivationType? derivationType; + DerivationType? derivationType; // no longer used @HiveField(17) - String? derivationPath; + String? derivationPath; // no longer used @HiveField(18) String? addressPageType; @@ -154,6 +166,9 @@ class WalletInfo extends HiveObject { @HiveField(19) String? network; + @HiveField(20) + DerivationInfo? derivationInfo; + String get yatLastUsedAddress => yatLastUsedAddressRaw ?? ''; set yatLastUsedAddress(String address) { diff --git a/cw_core/pubspec.lock b/cw_core/pubspec.lock index aef76f300..678e57b54 100644 --- a/cw_core/pubspec.lock +++ b/cw_core/pubspec.lock @@ -149,10 +149,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.17.1" convert: dependency: transitive description: @@ -343,18 +343,18 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.15" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.2.0" meta: dependency: transitive description: @@ -564,10 +564,10 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" stack_trace: dependency: transitive description: @@ -612,10 +612,10 @@ packages: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.5.1" timing: dependency: transitive description: @@ -641,21 +641,13 @@ packages: source: hosted version: "2.1.4" watcher: - dependency: "direct overridden" + dependency: transitive description: name: watcher sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.dev" source: hosted version: "1.1.0" - web: - dependency: transitive - description: - name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 - url: "https://pub.dev" - source: hosted - version: "0.1.4-beta" web_socket_channel: dependency: transitive description: @@ -689,5 +681,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.0-185.0.dev <4.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.10.0" diff --git a/cw_nano/lib/nano_wallet.dart b/cw_nano/lib/nano_wallet.dart index 265f78eb7..5efe3006d 100644 --- a/cw_nano/lib/nano_wallet.dart +++ b/cw_nano/lib/nano_wallet.dart @@ -43,7 +43,7 @@ abstract class NanoWalletBase }) : syncStatus = NotConnectedSyncStatus(), _password = password, _mnemonic = mnemonic, - _derivationType = walletInfo.derivationType!, + _derivationType = walletInfo.derivationInfo!.derivationType!, _isTransactionUpdating = false, _client = NanoClient(), walletAddresses = NanoWalletAddresses(walletInfo), @@ -389,7 +389,10 @@ abstract class NanoWalletBase derivationType = DerivationType.bip39; } - walletInfo.derivationType = derivationType; + walletInfo.derivationInfo ??= DerivationInfo(derivationType: derivationType); + if (walletInfo.derivationInfo!.derivationType == null) { + walletInfo.derivationInfo!.derivationType = derivationType; + } return NanoWallet( walletInfo: walletInfo, diff --git a/cw_nano/lib/nano_wallet_creation_credentials.dart b/cw_nano/lib/nano_wallet_creation_credentials.dart index 3616fcf44..4ee79ce48 100644 --- a/cw_nano/lib/nano_wallet_creation_credentials.dart +++ b/cw_nano/lib/nano_wallet_creation_credentials.dart @@ -2,8 +2,15 @@ import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; class NanoNewWalletCredentials extends WalletCredentials { - NanoNewWalletCredentials({required String name, String? password}) - : super(name: name, password: password); + NanoNewWalletCredentials({ + required String name, + String? password, + DerivationType? derivationType, + }) : super( + name: name, + password: password, + derivationInfo: DerivationInfo(derivationType: derivationType), + ); } class NanoRestoreWalletFromSeedCredentials extends WalletCredentials { @@ -11,11 +18,11 @@ class NanoRestoreWalletFromSeedCredentials extends WalletCredentials { required String name, required this.mnemonic, String? password, - DerivationType? derivationType, + required DerivationType derivationType, }) : super( name: name, password: password, - derivationType: derivationType, + derivationInfo: DerivationInfo(derivationType: derivationType), ); final String mnemonic; @@ -30,12 +37,12 @@ class NanoRestoreWalletFromKeysCredentials extends WalletCredentials { NanoRestoreWalletFromKeysCredentials({ required String name, required String password, + required DerivationType derivationType, required this.seedKey, - DerivationType? derivationType, }) : super( name: name, password: password, - derivationType: derivationType, + derivationInfo: DerivationInfo(derivationType: derivationType), ); final String seedKey; diff --git a/cw_nano/lib/nano_wallet_service.dart b/cw_nano/lib/nano_wallet_service.dart index 7ab502d49..b1497a625 100644 --- a/cw_nano/lib/nano_wallet_service.dart +++ b/cw_nano/lib/nano_wallet_service.dart @@ -28,11 +28,11 @@ class NanoWalletService extends WalletService create(NanoNewWalletCredentials credentials, {bool? isTestnet}) async { // nano standard: - DerivationType derivationType = DerivationType.nano; String seedKey = NanoSeeds.generateSeed(); String mnemonic = NanoDerivations.standardSeedToMnemonic(seedKey); - credentials.walletInfo!.derivationType = derivationType; + // ensure default if not present: + credentials.walletInfo!.derivationInfo ??= DerivationInfo(derivationType: DerivationType.nano); final wallet = NanoWallet( walletInfo: credentials.walletInfo!, @@ -88,9 +88,6 @@ class NanoWalletService extends WalletService BitcoinTransactionPriority.medium; - - @override - WalletCredentials createBitcoinRestoreWalletFromSeedCredentials( - {required String name, required String mnemonic, required String password}) => - BitcoinRestoreWalletFromSeedCredentials(name: name, mnemonic: mnemonic, password: password); + WalletCredentials createBitcoinRestoreWalletFromSeedCredentials({ + required String name, + required String mnemonic, + required String password, + required DerivationType derivationType, + required String derivationPath, + String? passphrase, + }) => + BitcoinRestoreWalletFromSeedCredentials( + name: name, + mnemonic: mnemonic, + password: password, + derivationType: derivationType, + derivationPath: derivationPath, + passphrase: passphrase, + ); @override WalletCredentials createBitcoinRestoreWalletFromWIFCredentials( @@ -23,6 +32,9 @@ class CWBitcoin extends Bitcoin { {required String name, WalletInfo? walletInfo}) => BitcoinNewWalletCredentials(name: name, walletInfo: walletInfo); + @override + TransactionPriority getMediumTransactionPriority() => BitcoinTransactionPriority.medium; + @override List getWordList() => wordlist; @@ -78,21 +90,20 @@ class CWBitcoin extends Bitcoin { final bitcoinFeeRate = priority == BitcoinTransactionPriority.custom && feeRate != null ? feeRate : null; return BitcoinTransactionCredentials( - outputs - .map((out) => OutputInfo( - fiatAmount: out.fiatAmount, - cryptoAmount: out.cryptoAmount, - address: out.address, - note: out.note, - sendAll: out.sendAll, - extractedAddress: out.extractedAddress, - isParsedAddress: out.isParsedAddress, - formattedCryptoAmount: out.formattedCryptoAmount, - memo: out.memo)) - .toList(), - priority: priority as BitcoinTransactionPriority, - feeRate: bitcoinFeeRate - ); + outputs + .map((out) => OutputInfo( + fiatAmount: out.fiatAmount, + cryptoAmount: out.cryptoAmount, + address: out.address, + note: out.note, + sendAll: out.sendAll, + extractedAddress: out.extractedAddress, + isParsedAddress: out.isParsedAddress, + formattedCryptoAmount: out.formattedCryptoAmount, + memo: out.memo)) + .toList(), + priority: priority as BitcoinTransactionPriority, + feeRate: bitcoinFeeRate); } @override @@ -248,6 +259,137 @@ class CWBitcoin extends Bitcoin { } } + @override + Future> compareDerivationMethods( + {required String mnemonic, required Node node}) async { + if (await checkIfMnemonicIsElectrum2(mnemonic)) { + return [DerivationType.electrum]; + } + + return [DerivationType.bip39, DerivationType.electrum]; + } + + int _countOccurrences(String str, String charToCount) { + int count = 0; + for (int i = 0; i < str.length; i++) { + if (str[i] == charToCount) { + count++; + } + } + return count; + } + + @override + Future> getDerivationsFromMnemonic({ + required String mnemonic, + required Node node, + String? passphrase, + }) async { + List list = []; + + List types = await compareDerivationMethods(mnemonic: mnemonic, node: node); + if (types.length == 1 && types.first == DerivationType.electrum) { + return [ + DerivationInfo( + derivationType: DerivationType.electrum, + derivationPath: "m/0'/0", + description: "Electrum", + scriptType: "p2wpkh", + ) + ]; + } + + final electrumClient = ElectrumClient(); + await electrumClient.connectToUri(node.uri); + + late BasedUtxoNetwork network; + btc.NetworkType networkType; + switch (node.type) { + case WalletType.litecoin: + network = LitecoinNetwork.mainnet; + networkType = litecoinNetwork; + break; + case WalletType.bitcoin: + default: + network = BitcoinNetwork.mainnet; + networkType = btc.bitcoin; + break; + } + + for (DerivationType dType in electrum_derivations.keys) { + late Uint8List seedBytes; + if (dType == DerivationType.electrum) { + seedBytes = await mnemonicToSeedBytes(mnemonic); + } else if (dType == DerivationType.bip39) { + seedBytes = bip39.mnemonicToSeed(mnemonic, passphrase: passphrase ?? ''); + } + + for (DerivationInfo dInfo in electrum_derivations[dType]!) { + try { + DerivationInfo dInfoCopy = DerivationInfo( + derivationType: dInfo.derivationType, + derivationPath: dInfo.derivationPath, + description: dInfo.description, + scriptType: dInfo.scriptType, + ); + + String derivationPath = dInfoCopy.derivationPath!; + int derivationDepth = _countOccurrences(derivationPath, "/"); + + // the correct derivation depth is dependant on the derivation type: + // the derivation paths defined in electrum_derivations are at the ROOT level, i.e.: + // electrum's format doesn't specify subaddresses, just subaccounts: + + // for BIP44 + if (derivationDepth == 3) { + // we add "/0/0" so that we generate account 0, index 0 and correctly get balance + derivationPath += "/0/0"; + // we don't support sub-ACCOUNTS in bitcoin like we do monero, and so the path dInfoCopy + // expects should be ACCOUNT 0, index unspecified: + dInfoCopy.derivationPath = dInfoCopy.derivationPath! + "/0"; + } + + // var hd = bip32.BIP32.fromSeed(seedBytes).derivePath(derivationPath); + final hd = btc.HDWallet.fromSeed( + seedBytes, + network: networkType, + ).derivePath(derivationPath); + + String? address; + switch (dInfoCopy.scriptType) { + case "p2wpkh": + address = generateP2WPKHAddress(hd: hd, network: network); + break; + case "p2pkh": + address = generateP2PKHAddress(hd: hd, network: network); + break; + case "p2wpkh-p2sh": + address = generateP2SHAddress(hd: hd, network: network); + break; + default: + continue; + } + + final sh = scriptHash(address, network: network); + final history = await electrumClient.getHistory(sh); + + final balance = await electrumClient.getBalance(sh); + dInfoCopy.balance = balance.entries.first.value.toString(); + dInfoCopy.address = address; + dInfoCopy.transactionsCount = history.length; + + list.add(dInfoCopy); + } catch (e) { + print(e); + } + } + } + + // sort the list such that derivations with the most transactions are first: + list.sort((a, b) => b.transactionsCount.compareTo(a.transactionsCount)); + return list; + } + @override bool hasTaprootInput(PendingTransaction pendingTransaction) { return (pendingTransaction as PendingBitcoinTransaction).hasTaprootInputs; diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index a0f570e95..99178c815 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -220,6 +220,10 @@ Future defaultSettingsMigration( await updateNanoNodeList(nodes: nodes); break; + case 32: + await updateBtcNanoWalletInfos(walletInfoSource); + break; + default: break; } @@ -756,6 +760,20 @@ Future changeDefaultMoneroNode( } } +Future updateBtcNanoWalletInfos(Box walletsInfoSource) async { + for (WalletInfo walletInfo in walletsInfoSource.values) { + if (walletInfo.type == WalletType.nano || walletInfo.type == WalletType.bitcoin) { + walletInfo.derivationInfo = DerivationInfo( + derivationPath: walletInfo.derivationPath, + derivationType: walletInfo.derivationType, + address: walletInfo.address, + transactionsCount: walletInfo.restoreHeight, + ); + await walletInfo.save(); + } + } +} + Future changeDefaultBitcoinNode( Box nodeSource, SharedPreferences sharedPreferences) async { const cakeWalletBitcoinNodeUriPattern = '.cakewallet.com'; diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart index bab0ef51d..f729e6392 100644 --- a/lib/entities/parse_address_from_domain.dart +++ b/lib/entities/parse_address_from_domain.dart @@ -51,10 +51,12 @@ class AddressResolver { } final match = RegExp(addressPattern).firstMatch(raw); - return match?.group(0)?.replaceAllMapped(RegExp('[^0-9a-zA-Z]|bitcoincash:|nano_'), + return match?.group(0)?.replaceAllMapped(RegExp('[^0-9a-zA-Z]|bitcoincash:|nano_|ban_'), (Match match) { String group = match.group(0)!; - if (group.startsWith('bitcoincash:') || group.startsWith('nano_')) { + if (group.startsWith('bitcoincash:') || + group.startsWith('nano_') || + group.startsWith('ban_')) { return group; } return ''; diff --git a/lib/main.dart b/lib/main.dart index b80c9eb85..ff5b0e5c0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -102,6 +102,10 @@ Future initializeAppConfigs() async { CakeHive.registerAdapter(DerivationTypeAdapter()); } + if (!CakeHive.isAdapterRegistered(DERIVATION_INFO_TYPE_ID)) { + CakeHive.registerAdapter(DerivationInfoAdapter()); + } + if (!CakeHive.isAdapterRegistered(WALLET_TYPE_TYPE_ID)) { CakeHive.registerAdapter(WalletTypeAdapter()); } @@ -163,7 +167,7 @@ Future initializeAppConfigs() async { transactionDescriptions: transactionDescriptions, secureStorage: secureStorage, anonpayInvoiceInfo: anonpayInvoiceInfo, - initialMigrationVersion: 31, + initialMigrationVersion: 32, ); } diff --git a/lib/nano/cw_nano.dart b/lib/nano/cw_nano.dart index 5896f7c26..13800cff6 100644 --- a/lib/nano/cw_nano.dart +++ b/lib/nano/cw_nano.dart @@ -96,6 +96,7 @@ class CWNano extends Nano { NanoNewWalletCredentials( name: name, password: password, + derivationType: DerivationType.nano, ); @override @@ -103,15 +104,10 @@ class CWNano extends Nano { required String name, required String password, required String mnemonic, - DerivationType? derivationType, + required DerivationType derivationType, }) { - if (derivationType == null) { - // figure out the derivation type as best we can, otherwise set it to "unknown" - if (mnemonic.split(" ").length == 12) { - derivationType = DerivationType.bip39; - } else { - derivationType = DerivationType.unknown; - } + if (mnemonic.split(" ").length == 12 && derivationType != DerivationType.bip39) { + throw Exception("Invalid mnemonic for derivation type!"); } return NanoRestoreWalletFromSeedCredentials( @@ -127,15 +123,10 @@ class CWNano extends Nano { required String name, required String password, required String seedKey, - DerivationType? derivationType, + required DerivationType derivationType, }) { - if (derivationType == null) { - // figure out the derivation type as best we can, otherwise set it to "unknown" - if (seedKey.length == 64) { - derivationType = DerivationType.nano; - } else { - derivationType = DerivationType.unknown; - } + if (seedKey.length == 128 && derivationType != DerivationType.bip39) { + throw Exception("Invalid seed key length for derivation type!"); } return NanoRestoreWalletFromKeysCredentials( @@ -199,7 +190,6 @@ class CWNano extends Nano { } class CWNanoUtil extends NanoUtil { - @override bool isValidBip39Seed(String seed) { return NanoDerivations.isValidBip39Seed(seed); @@ -353,4 +343,54 @@ class CWNanoUtil extends NanoUtil { return [DerivationType.nano, DerivationType.bip39]; } } + + @override + Future> getDerivationsFromMnemonic({ + String? mnemonic, + String? seedKey, + required Node node, + }) async { + List list = []; + + List possibleDerivationTypes = await compareDerivationMethods( + mnemonic: mnemonic, + privateKey: seedKey, + node: node, + ); + if (possibleDerivationTypes.length == 1) { + return [DerivationInfo(derivationType: possibleDerivationTypes.first)]; + } + + AccountInfoResponse? bip39Info = await nanoUtil!.getInfoFromSeedOrMnemonic( + DerivationType.bip39, + mnemonic: mnemonic, + seedKey: seedKey, + node: node, + ); + AccountInfoResponse? standardInfo = await nanoUtil!.getInfoFromSeedOrMnemonic( + DerivationType.nano, + mnemonic: mnemonic, + seedKey: seedKey, + node: node, + ); + + if (standardInfo?.confirmationHeight != null && standardInfo!.confirmationHeight > 0) { + list.add(DerivationInfo( + derivationType: DerivationType.nano, + balance: nanoUtil!.getRawAsUsableString(standardInfo.balance, nanoUtil!.rawPerNano), + address: standardInfo.address!, + transactionsCount: standardInfo.confirmationHeight, + )); + } + + if (bip39Info?.confirmationHeight != null && bip39Info!.confirmationHeight > 0) { + list.add(DerivationInfo( + derivationType: DerivationType.bip39, + balance: nanoUtil!.getRawAsUsableString(bip39Info.balance, nanoUtil!.rawPerNano), + address: bip39Info.address!, + transactionsCount: bip39Info.confirmationHeight, + )); + } + return list; + } } diff --git a/lib/src/screens/restore/wallet_restore_choose_derivation.dart b/lib/src/screens/restore/wallet_restore_choose_derivation.dart index 5cf40e588..9a7d8eb67 100644 --- a/lib/src/screens/restore/wallet_restore_choose_derivation.dart +++ b/lib/src/screens/restore/wallet_restore_choose_derivation.dart @@ -1,8 +1,5 @@ -import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; -import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/view_model/wallet_restore_choose_derivation_view_model.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:flutter/material.dart'; @@ -13,15 +10,14 @@ class WalletRestoreChooseDerivationPage extends BasePage { WalletRestoreChooseDerivationPage(this.walletRestoreChooseDerivationViewModel) {} @override - Widget middle(BuildContext context) => Observer( - builder: (_) => Text( - S.current.choose_derivation, - style: TextStyle( - fontSize: 18.0, - fontWeight: FontWeight.bold, - fontFamily: 'Lato', - color: titleColor(context)), - )); + Widget middle(BuildContext context) => Text( + S.current.choose_derivation, + style: TextStyle( + fontSize: 18.0, + fontWeight: FontWeight.bold, + fontFamily: 'Lato', + color: titleColor(context)), + ); final WalletRestoreChooseDerivationViewModel walletRestoreChooseDerivationViewModel; DerivationType derivationType = DerivationType.unknown; @@ -105,7 +101,7 @@ class WalletRestoreChooseDerivationPage extends BasePage { ), ), Text( - "${S.current.transactions}: ${derivation.height}", + "${S.current.transactions}: ${derivation.transactionsCount}", style: Theme.of(context).primaryTextTheme.labelMedium!.copyWith( fontSize: 16, fontWeight: FontWeight.w500, diff --git a/lib/src/screens/restore/wallet_restore_from_seed_form.dart b/lib/src/screens/restore/wallet_restore_from_seed_form.dart index 6f8f9eb2b..288862ce7 100644 --- a/lib/src/screens/restore/wallet_restore_from_seed_form.dart +++ b/lib/src/screens/restore/wallet_restore_from_seed_form.dart @@ -20,6 +20,7 @@ class WalletRestoreFromSeedForm extends StatefulWidget { {Key? key, required this.displayLanguageSelector, required this.displayBlockHeightSelector, + required this.displayPassphrase, required this.type, required this.seedTypeViewModel, this.blockHeightFocusNode, @@ -31,6 +32,7 @@ class WalletRestoreFromSeedForm extends StatefulWidget { final WalletType type; final bool displayLanguageSelector; final bool displayBlockHeightSelector; + final bool displayPassphrase; final SeedTypeViewModel seedTypeViewModel; final FocusNode? blockHeightFocusNode; final Function(bool)? onHeightOrDateEntered; @@ -48,6 +50,7 @@ class WalletRestoreFromSeedFormState extends State { formKey = GlobalKey(), languageController = TextEditingController(), nameTextEditingController = TextEditingController(), + passphraseController = TextEditingController(), seedTypeController = TextEditingController(); final GlobalKey seedWidgetStateKey; @@ -55,6 +58,7 @@ class WalletRestoreFromSeedFormState extends State { final TextEditingController languageController; final TextEditingController nameTextEditingController; final TextEditingController seedTypeController; + final TextEditingController passphraseController; final GlobalKey formKey; late ReactionDisposer moneroSeedTypeReaction; String language; @@ -166,15 +170,15 @@ class WalletRestoreFromSeedFormState extends State { ), if (widget.displayLanguageSelector) GestureDetector( - onTap: () async { - await showPopUp( - context: context, - builder: (_) => SeedLanguagePicker( - selected: language, - onItemSelected: _changeLanguage, - seedType: isPolyseed ? SeedType.polyseed : SeedType.legacy, - )); - }, + onTap: () async { + await showPopUp( + context: context, + builder: (_) => SeedLanguagePicker( + selected: language, + onItemSelected: _changeLanguage, + seedType: isPolyseed ? SeedType.polyseed : SeedType.legacy, + )); + }, child: Container( color: Colors.transparent, padding: EdgeInsets.only(top: 20.0), @@ -194,6 +198,14 @@ class WalletRestoreFromSeedFormState extends State { key: blockchainHeightKey, onHeightOrDateEntered: widget.onHeightOrDateEntered, hasDatePicker: widget.type == WalletType.monero), + if (widget.displayPassphrase) ...[ + const SizedBox(height: 10), + BaseTextFormField( + hintText: S.current.passphrase, + controller: passphraseController, + obscureText: true, + ), + ] ])); } diff --git a/lib/src/screens/restore/wallet_restore_page.dart b/lib/src/screens/restore/wallet_restore_page.dart index fe5ac8487..6fcacfb0a 100644 --- a/lib/src/screens/restore/wallet_restore_page.dart +++ b/lib/src/screens/restore/wallet_restore_page.dart @@ -1,7 +1,5 @@ import 'package:cake_wallet/core/execution_state.dart'; -import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/restore/wallet_restore_from_keys_form.dart'; @@ -9,7 +7,6 @@ import 'package:cake_wallet/src/screens/restore/wallet_restore_from_seed_form.da import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; -import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; @@ -17,7 +14,6 @@ import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/restore/restore_mode.dart'; import 'package:cake_wallet/view_model/seed_type_view_model.dart'; import 'package:cake_wallet/view_model/wallet_restore_view_model.dart'; -import 'package:cw_core/nano_account_info_response.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; @@ -42,6 +38,7 @@ class WalletRestorePage extends BasePage { displayBlockHeightSelector: walletRestoreViewModel.hasBlockchainHeightLanguageSelector, displayLanguageSelector: walletRestoreViewModel.hasSeedLanguageSelector, + displayPassphrase: walletRestoreViewModel.hasPassphrase, type: walletRestoreViewModel.type, key: walletRestoreFromSeedFormKey, blockHeightFocusNode: _blockHeightFocusNode, @@ -99,8 +96,10 @@ class WalletRestorePage extends BasePage { final GlobalKey walletRestoreFromSeedFormKey; final GlobalKey walletRestoreFromKeysFormKey; final FocusNode _blockHeightFocusNode; - DerivationType derivationType = DerivationType.unknown; - String? derivationPath = null; + + // DerivationType derivationType = DerivationType.unknown; + // String? derivationPath = null; + DerivationInfo? derivationInfo; @override Widget body(BuildContext context) { @@ -298,6 +297,11 @@ class WalletRestorePage extends BasePage { -1; } + if (walletRestoreViewModel.hasPassphrase) { + credentials['passphrase'] = + walletRestoreFromSeedFormKey.currentState!.passphraseController.text; + } + credentials['name'] = walletRestoreFromSeedFormKey.currentState!.nameTextEditingController.text; } else if (walletRestoreViewModel.mode == WalletRestoreMode.keys) { @@ -318,58 +322,11 @@ class WalletRestorePage extends BasePage { } } - credentials['derivationType'] = this.derivationType; - credentials['derivationPath'] = this.derivationPath; + credentials['derivationInfo'] = this.derivationInfo; credentials['walletType'] = walletRestoreViewModel.type; return credentials; } - Future> getDerivationInfo(dynamic credentials) async { - var list = []; - var walletType = credentials["walletType"] as WalletType; - var appStore = getIt.get(); - var node = appStore.settingsStore.getCurrentNode(walletType); - - switch (walletType) { - case WalletType.nano: - String? mnemonic = credentials['seed'] as String?; - String? seedKey = credentials['private_key'] as String?; - AccountInfoResponse? bip39Info = await nanoUtil!.getInfoFromSeedOrMnemonic( - DerivationType.bip39, - mnemonic: mnemonic, - seedKey: seedKey, - node: node); - AccountInfoResponse? standardInfo = await nanoUtil!.getInfoFromSeedOrMnemonic( - DerivationType.nano, - mnemonic: mnemonic, - seedKey: seedKey, - node: node, - ); - - if (standardInfo?.balance != null) { - list.add(DerivationInfo( - derivationType: DerivationType.nano, - balance: nanoUtil!.getRawAsUsableString(standardInfo!.balance, nanoUtil!.rawPerNano), - address: standardInfo.address!, - height: standardInfo.confirmationHeight, - )); - } - - if (bip39Info?.balance != null) { - list.add(DerivationInfo( - derivationType: DerivationType.bip39, - balance: nanoUtil!.getRawAsUsableString(bip39Info!.balance, nanoUtil!.rawPerNano), - address: bip39Info.address!, - height: bip39Info.confirmationHeight, - )); - } - break; - default: - break; - } - return list; - } - Future _confirmForm(BuildContext context) async { // Dismissing all visible keyboard to provide context for navigation FocusManager.instance.primaryFocus?.unfocus(); @@ -398,51 +355,46 @@ class WalletRestorePage extends BasePage { walletRestoreViewModel.state = IsExecutingState(); - List derivationTypes = - await walletRestoreViewModel.getDerivationTypes(_credentials()); + DerivationInfo? dInfo; - if (derivationTypes[0] == DerivationType.unknown || derivationTypes.length > 1) { - // push screen to choose the derivation type: - List derivations = await getDerivationInfo(_credentials()); + // get info about the different derivations: + List derivations = + await walletRestoreViewModel.getDerivationInfo(_credentials()); - int derivationsWithHistory = 0; - int derivationWithHistoryIndex = 0; - for (int i = 0; i < derivations.length; i++) { - if (derivations[i].height > 0) { - derivationsWithHistory++; - derivationWithHistoryIndex = i; - } + int derivationsWithHistory = 0; + int derivationWithHistoryIndex = 0; + for (int i = 0; i < derivations.length; i++) { + if (derivations[i].transactionsCount > 0) { + derivationsWithHistory++; + derivationWithHistoryIndex = i; } - - DerivationInfo? derivationInfo; - - if (derivationsWithHistory > 1) { - derivationInfo = await Navigator.of(context).pushNamed(Routes.restoreWalletChooseDerivation, - arguments: derivations) as DerivationInfo?; - } else if (derivationsWithHistory == 1) { - derivationInfo = derivations[derivationWithHistoryIndex]; - } else if (derivationsWithHistory == 0) { - // default derivation: - derivationInfo = DerivationInfo( - derivationType: derivationTypes[0], - derivationPath: "m/0'/1", - height: 0, - ); - } - - if (derivationInfo == null) { - walletRestoreViewModel.state = InitialExecutionState(); - return; - } - this.derivationType = derivationInfo.derivationType; - this.derivationPath = derivationInfo.derivationPath; - } else { - // electrum derivation: - this.derivationType = derivationTypes[0]; - this.derivationPath = "m/0'/1"; } - walletRestoreViewModel.state = InitialExecutionState(); + if (derivationsWithHistory > 1) { + dInfo = await Navigator.of(context).pushNamed( + Routes.restoreWalletChooseDerivation, + arguments: derivations, + ) as DerivationInfo?; + } else if (derivationsWithHistory == 1) { + dInfo = derivations[derivationWithHistoryIndex]; + } + + // get the default derivation for this wallet type: + if (dInfo == null) { + // we only return 1 derivation if we're pretty sure we know which one to use: + if (derivations.length == 1) { + dInfo = derivations.first; + } else { + // if we have multiple possible derivations, and none have histories + // we just default to the most common one: + dInfo = walletRestoreViewModel.getCommonRestoreDerivation(); + } + } + + this.derivationInfo = dInfo; + if (this.derivationInfo == null) { + this.derivationInfo = walletRestoreViewModel.getDefaultDerivation(); + } walletRestoreViewModel.create(options: _credentials()); } diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index b57473cba..81c78b1ab 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -343,7 +343,9 @@ class WalletListBodyState extends State { }); } } catch (e) { - changeProcessText(S.of(context).wallet_list_failed_to_load(wallet.name, e.toString())); + if (this.mounted) { + changeProcessText(S.of(context).wallet_list_failed_to_load(wallet.name, e.toString())); + } } }, conditionToDetermineIfToUse2FA: diff --git a/lib/src/widgets/base_text_form_field.dart b/lib/src/widgets/base_text_form_field.dart index 5649a0784..534e6dae2 100644 --- a/lib/src/widgets/base_text_form_field.dart +++ b/lib/src/widgets/base_text_form_field.dart @@ -22,6 +22,7 @@ class BaseTextFormField extends StatelessWidget { this.enabled = true, this.readOnly = false, this.enableInteractiveSelection = true, + this.obscureText = false, this.validator, this.textStyle, this.placeholderTextStyle, @@ -57,6 +58,7 @@ class BaseTextFormField extends StatelessWidget { final String? initialValue; final double borderWidth; final void Function(String)? onSubmit; + final bool obscureText; @override Widget build(BuildContext context) { @@ -70,6 +72,7 @@ class BaseTextFormField extends StatelessWidget { textInputAction: textInputAction, textAlign: textAlign, autovalidateMode: autovalidateMode, + obscureText: obscureText, maxLines: maxLines, inputFormatters: inputFormatters, enabled: enabled, diff --git a/lib/view_model/restore/restore_from_qr_vm.dart b/lib/view_model/restore/restore_from_qr_vm.dart index 31f0bfdd2..b9b493f04 100644 --- a/lib/view_model/restore/restore_from_qr_vm.dart +++ b/lib/view_model/restore/restore_from_qr_vm.dart @@ -30,8 +30,7 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store spendKey = '', wif = '', address = '', - super(appStore, walletInfoSource, walletCreationService, - type: type, isRecovery: true); + super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: true); @observable int height; @@ -51,8 +50,16 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store bool get hasRestorationHeight => type == WalletType.monero; @override - WalletCredentials getCredentialsFromRestoredWallet(dynamic options, RestoredWallet restoreWallet) { + WalletCredentials getCredentialsFromRestoredWallet( + dynamic options, RestoredWallet restoreWallet) { final password = generateWalletPassword(); + String? passphrase; + DerivationInfo? derivationInfo; + if (options != null) { + derivationInfo = options["derivationInfo"] as DerivationInfo?; + passphrase = options["passphrase"] as String?; + } + derivationInfo ??= getDefaultDerivation(); switch (restoreWallet.restoreMode) { case WalletRestoreMode.keys: @@ -86,23 +93,37 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store switch (restoreWallet.type) { case WalletType.monero: return monero!.createMoneroRestoreWalletFromSeedCredentials( - name: name, - height: restoreWallet.height ?? 0, - mnemonic: restoreWallet.mnemonicSeed ?? '', - password: password); + name: name, + height: restoreWallet.height ?? 0, + mnemonic: restoreWallet.mnemonicSeed ?? '', + password: password, + ); case WalletType.bitcoin: case WalletType.litecoin: return bitcoin!.createBitcoinRestoreWalletFromSeedCredentials( - name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); + name: name, + mnemonic: restoreWallet.mnemonicSeed ?? '', + password: password, + passphrase: passphrase, + derivationType: derivationInfo!.derivationType!, + derivationPath: derivationInfo.derivationPath!, + ); case WalletType.bitcoinCash: return bitcoinCash!.createBitcoinCashRestoreWalletFromSeedCredentials( - name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); + name: name, + mnemonic: restoreWallet.mnemonicSeed ?? '', + password: password, + ); case WalletType.ethereum: return ethereum!.createEthereumRestoreWalletFromSeedCredentials( name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); case WalletType.nano: return nano!.createNanoRestoreWalletFromSeedCredentials( - name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); + name: name, + mnemonic: restoreWallet.mnemonicSeed ?? '', + password: password, + derivationType: derivationInfo!.derivationType!, + ); case WalletType.polygon: return polygon!.createPolygonRestoreWalletFromSeedCredentials( name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); @@ -118,7 +139,8 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store } @override - Future processFromRestoredWallet(WalletCredentials credentials, RestoredWallet restoreWallet) async { + Future processFromRestoredWallet( + WalletCredentials credentials, RestoredWallet restoreWallet) async { try { switch (restoreWallet.restoreMode) { case WalletRestoreMode.keys: diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index cabb723e1..6c0c3870b 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -423,7 +423,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor Object _credentials() { final priority = _settingsStore.priority[wallet.type]; - if (priority == null && wallet.type != WalletType.nano && wallet.type != WalletType.solana) { + if (priority == null && wallet.type != WalletType.nano && wallet.type != WalletType.banano && wallet.type != WalletType.solana) { throw Exception('Priority is null for wallet type: ${wallet.type}'); } diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index 4a1e054d6..5c9c29a16 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -71,9 +71,9 @@ abstract class WalletCreationVMBase with Store { dirPath: dirPath, address: '', showIntroCakePayCard: (!walletCreationService.typeExists(type)) && type != WalletType.haven, - derivationPath: credentials.derivationPath, - derivationType: credentials.derivationType, + derivationInfo: credentials.derivationInfo ?? getDefaultDerivation(), ); + credentials.walletInfo = walletInfo; final wallet = restoreWallet != null ? await processFromRestoredWallet(credentials, restoreWallet) @@ -89,6 +89,48 @@ abstract class WalletCreationVMBase with Store { } } + DerivationInfo? getDefaultDerivation() { + switch (this.type) { + case WalletType.nano: + return DerivationInfo( + derivationType: DerivationType.nano, + ); + case WalletType.bitcoin: + case WalletType.litecoin: + return DerivationInfo( + derivationType: DerivationType.electrum, + derivationPath: "m/0'/0", + ); + default: + return null; + } + } + + DerivationInfo? getCommonRestoreDerivation() { + switch (this.type) { + case WalletType.nano: + return DerivationInfo( + derivationType: DerivationType.nano, + ); + case WalletType.bitcoin: + return DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/84'/0'/0'/0", + description: "Standard BIP84 native segwit", + scriptType: "p2wpkh", + ); + case WalletType.litecoin: + return DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/84'/2'/0'/0", + description: "Standard BIP84 native segwit (litecoin)", + scriptType: "p2wpkh", + ); + default: + return null; + } + } + WalletCredentials getCredentials(dynamic options) => throw UnimplementedError(); Future process(WalletCredentials credentials) => throw UnimplementedError(); diff --git a/lib/view_model/wallet_restore_view_model.dart b/lib/view_model/wallet_restore_view_model.dart index 93ca813d6..21339f1ae 100644 --- a/lib/view_model/wallet_restore_view_model.dart +++ b/lib/view_model/wallet_restore_view_model.dart @@ -2,6 +2,7 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; +import 'package:cw_core/nano_account_info_response.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/solana/solana.dart'; @@ -66,6 +67,8 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { final bool hasBlockchainHeightLanguageSelector; final bool hasRestoreFromPrivateKey; + bool get hasPassphrase => [WalletType.bitcoin, WalletType.litecoin].contains(type); + @observable WalletRestoreMode mode; @@ -75,10 +78,10 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { @override WalletCredentials getCredentials(dynamic options) { final password = generateWalletPassword(); + String? passphrase = options['passphrase'] as String?; final height = options['height'] as int? ?? 0; name = options['name'] as String; - DerivationType? derivationType = options["derivationType"] as DerivationType?; - String? derivationPath = options["derivationPath"] as String?; + DerivationInfo? derivationInfo = options["derivationInfo"] as DerivationInfo?; if (mode == WalletRestoreMode.seed) { final seed = options['seed'] as String; @@ -87,14 +90,15 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { return monero!.createMoneroRestoreWalletFromSeedCredentials( name: name, height: height, mnemonic: seed, password: password); case WalletType.bitcoin: + case WalletType.litecoin: return bitcoin!.createBitcoinRestoreWalletFromSeedCredentials( name: name, mnemonic: seed, password: password, + passphrase: passphrase, + derivationType: derivationInfo!.derivationType!, + derivationPath: derivationInfo.derivationPath!, ); - case WalletType.litecoin: - return bitcoin!.createBitcoinRestoreWalletFromSeedCredentials( - name: name, mnemonic: seed, password: password); case WalletType.haven: return haven!.createHavenRestoreWalletFromSeedCredentials( name: name, height: height, mnemonic: seed, password: password); @@ -106,7 +110,11 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { name: name, mnemonic: seed, password: password); case WalletType.nano: return nano!.createNanoRestoreWalletFromSeedCredentials( - name: name, mnemonic: seed, password: password, derivationType: derivationType); + name: name, + mnemonic: seed, + password: password, + derivationType: derivationInfo!.derivationType!, + ); case WalletType.polygon: return polygon!.createPolygonRestoreWalletFromSeedCredentials( name: name, @@ -185,23 +193,34 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { throw Exception('Unexpected type: ${type.toString()}'); } - Future> getDerivationTypes(dynamic options) async { - final seedKey = options['private_key'] as String?; - final mnemonic = options['seed'] as String?; - WalletType walletType = options['walletType'] as WalletType; + Future> getDerivationInfo(dynamic credentials) async { + var list = []; + var walletType = credentials["walletType"] as WalletType; var appStore = getIt.get(); var node = appStore.settingsStore.getCurrentNode(walletType); - switch (type) { + switch (walletType) { + case WalletType.bitcoin: + case WalletType.litecoin: + String? mnemonic = credentials['seed'] as String?; + String? passphrase = credentials['passphrase'] as String?; + return bitcoin!.getDerivationsFromMnemonic( + mnemonic: mnemonic!, + node: node, + passphrase: passphrase, + ); case WalletType.nano: - return nanoUtil! - .compareDerivationMethods(mnemonic: mnemonic, privateKey: seedKey, node: node); + String? mnemonic = credentials['seed'] as String?; + String? seedKey = credentials['private_key'] as String?; + return nanoUtil!.getDerivationsFromMnemonic( + mnemonic: mnemonic, + seedKey: seedKey, + node: node, + ); default: break; } - - // throw Exception('Unexpected type: ${type.toString()}'); - return [DerivationType.def]; + return list; } @override @@ -209,7 +228,6 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { if (mode == WalletRestoreMode.keys) { return walletCreationService.restoreFromKeys(credentials, isTestnet: useTestnet); } - return walletCreationService.restoreFromSeed(credentials, isTestnet: useTestnet); } } diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index cf9959f17..16a87a850 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -411,6 +411,7 @@ "outputs": "المخرجات", "overwrite_amount": "تغير المبلغ", "pairingInvalidEvent": "ﺢﻟﺎﺻ ﺮﻴﻏ ﺙﺪﺣ ﻥﺍﺮﻗﺇ", + "passphrase": "عبارة الممر (اختياري)", "password": "كلمة المرور", "paste": "لصق", "pause_wallet_creation": ".ﺎﻴًﻟﺎﺣ ﺎﺘًﻗﺆﻣ ﺔﻔﻗﻮﺘﻣ Haven Wallet ءﺎﺸﻧﺇ ﻰﻠﻋ ﺓﺭﺪﻘﻟﺍ", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index bd1cd645d..4e92cd707 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -411,6 +411,7 @@ "outputs": "Изходи", "overwrite_amount": "Промени сума", "pairingInvalidEvent": "Невалидно събитие при сдвояване", + "passphrase": "Passphrase (по избор)", "password": "Парола", "paste": "Поставяне", "pause_wallet_creation": "Възможността за създаване на Haven Wallet в момента е на пауза.", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 4d3458bec..95fdc2a93 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -411,6 +411,7 @@ "outputs": "Výstupy", "overwrite_amount": "Přepsat částku", "pairingInvalidEvent": "Neplatná událost párování", + "passphrase": "Passphrase (volitelné)", "password": "Heslo", "paste": "Vložit", "pause_wallet_creation": "Možnost vytvářet Haven Wallet je momentálně pozastavena.", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 0546140eb..d2731d3e7 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -411,6 +411,7 @@ "outputs": "Ausgänge", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Paarung ungültiges Ereignis", + "passphrase": "Passphrase (optional)", "password": "Passwort", "paste": "Einfügen", "pause_wallet_creation": "Die Möglichkeit, Haven Wallet zu erstellen, ist derzeit pausiert.", @@ -425,8 +426,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", @@ -822,4 +823,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 8f8b753d6..8c302d096 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -411,6 +411,7 @@ "outputs": "Outputs", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Pairing Invalid Event", + "passphrase": "Passphrase (Optional)", "password": "Password", "paste": "Paste", "pause_wallet_creation": "Ability to create Haven Wallet is currently paused.", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 7de9cff53..17c4ff681 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -411,6 +411,7 @@ "outputs": "Salidas", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Evento de emparejamiento no válido", + "passphrase": "Passfrase (opcional)", "password": "Contraseña", "paste": "Pegar", "pause_wallet_creation": "La capacidad para crear Haven Wallet está actualmente pausada.", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 2c76122fc..12716ab33 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -411,6 +411,7 @@ "outputs": "Les sorties", "overwrite_amount": "Remplacer le montant", "pairingInvalidEvent": "Événement de couplage non valide", + "passphrase": "Phrase de passe (facultative)", "password": "Mot de passe", "paste": "Coller", "pause_wallet_creation": "La possibilité de créer Haven Wallet est actuellement suspendue.", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index bac970207..29754cf72 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -413,6 +413,7 @@ "outputs": "Abubuwan fashewa", "overwrite_amount": "Rubuta adadin", "pairingInvalidEvent": "Haɗa Lamarin mara inganci", + "passphrase": "Passphrase (Zabi)", "password": "Kalmar wucewa", "paste": "Manna", "pause_wallet_creation": "A halin yanzu an dakatar da ikon ƙirƙirar Haven Wallet.", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 5a9706bd5..278adde0f 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -411,6 +411,7 @@ "outputs": "आउटपुट", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "अमान्य ईवेंट युग्मित करना", + "passphrase": "पासफ्रेज़ (वैकल्पिक)", "password": "पारण शब्द", "paste": "पेस्ट करें", "pause_wallet_creation": "हेवन वॉलेट बनाने की क्षमता फिलहाल रुकी हुई है।", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 94f675a1d..7940b1add 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -411,6 +411,7 @@ "outputs": "Izlazi", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Nevažeći događaj uparivanja", + "passphrase": "Prolaznica (neobavezno)", "password": "Lozinka", "paste": "Zalijepi", "pause_wallet_creation": "Mogućnost stvaranja novčanika Haven trenutno je pauzirana.", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 69e270d10..8177afdc2 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -413,6 +413,7 @@ "outputs": "Output", "overwrite_amount": "Timpa jumlah", "pairingInvalidEvent": "Menyandingkan Acara Tidak Valid", + "passphrase": "Frasa sandi (opsional)", "password": "Kata Sandi", "paste": "Tempel", "pause_wallet_creation": "Kemampuan untuk membuat Haven Wallet saat ini dijeda.", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 09b3e43bb..4cc08f9b1 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -413,6 +413,7 @@ "outputs": "Output", "overwrite_amount": "Sovrascrivi quantità", "pairingInvalidEvent": "Associazione evento non valido", + "passphrase": "Passphrase (opzionale)", "password": "Password", "paste": "Incolla", "pause_wallet_creation": "La possibilità di creare Haven Wallet è attualmente sospesa.", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index b067c2721..a72bbb0e4 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -412,6 +412,7 @@ "outputs": "出力", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "ペアリング無効イベント", + "passphrase": "パスフレーズ(オプション)", "password": "パスワード", "paste": "ペースト", "pause_wallet_creation": "Haven Wallet を作成する機能は現在一時停止されています。", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index d9881ad04..b80494e80 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -411,6 +411,7 @@ "outputs": "출력", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "잘못된 이벤트 페어링", + "passphrase": "암호화 (선택 사항)", "password": "암호", "paste": "풀", "pause_wallet_creation": "Haven Wallet 생성 기능이 현재 일시 중지되었습니다.", @@ -425,8 +426,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": "다른 노드에 연결을 시도하십시오", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index c36f63414..97a22d807 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -411,6 +411,7 @@ "outputs": "ထုတ်လုပ်မှု", "overwrite_amount": "ပမာဏကို ထပ်ရေးပါ။", "pairingInvalidEvent": "မမှန်ကန်သောဖြစ်ရပ်ကို တွဲချိတ်ခြင်း။", + "passphrase": "passphrase (optional)", "password": "စကားဝှက်", "paste": "ငါးပိ", "pause_wallet_creation": "Haven Wallet ဖန်တီးနိုင်မှုကို လောလောဆယ် ခေတ္တရပ်ထားသည်။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index f258b8f62..a64e264c0 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -411,6 +411,7 @@ "outputs": "Uitgangen", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Koppelen Ongeldige gebeurtenis", + "passphrase": "PassaspHRASE (optioneel)", "password": "Wachtwoord", "paste": "Plakken", "pause_wallet_creation": "De mogelijkheid om Haven Wallet te maken is momenteel onderbroken.", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 4627d0242..109a800ad 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -411,6 +411,7 @@ "outputs": "Wyjścia", "overwrite_amount": "Nadpisz ilość", "pairingInvalidEvent": "Nieprawidłowe zdarzenie parowania", + "passphrase": "PassPhraza (opcjonalnie)", "password": "Hasło", "paste": "Wklej", "pause_wallet_creation": "Możliwość utworzenia Portfela Haven jest obecnie wstrzymana.", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 2a781c76b..2d877794a 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -413,6 +413,7 @@ "outputs": "Saídas", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Emparelhamento de evento inválido", + "passphrase": "Senha (opcional)", "password": "Senha", "paste": "Colar", "pause_wallet_creation": "A capacidade de criar a Haven Wallet está atualmente pausada.", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 22bac3e33..e6141c29b 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -412,6 +412,7 @@ "outputs": "Выходы", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Недействительное событие сопряжения", + "passphrase": "Passfrase (необязательно)", "password": "Пароль", "paste": "Вставить", "pause_wallet_creation": "Возможность создания Haven Wallet в настоящее время приостановлена.", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index c0f58495c..ef1a3ea4e 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -411,6 +411,7 @@ "outputs": "เอาต์พุต", "overwrite_amount": "เขียนทับจำนวน", "pairingInvalidEvent": "การจับคู่เหตุการณ์ที่ไม่ถูกต้อง", + "passphrase": "ข้อความรหัสผ่าน (ไม่บังคับ)", "password": "รหัสผ่าน", "paste": "วาง", "pause_wallet_creation": "ขณะนี้ความสามารถในการสร้าง Haven Wallet ถูกหยุดชั่วคราว", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 8c3b13b3b..e0258e38a 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -411,6 +411,7 @@ "outputs": "Mga output", "overwrite_amount": "Overwrite na halaga", "pairingInvalidEvent": "Pagpares ng Di-wastong Kaganapan", + "passphrase": "Passphrase (opsyonal)", "password": "Password", "paste": "I -paste", "pause_wallet_creation": "Kasalukuyang naka-pause ang kakayahang gumawa ng Haven Wallet.", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 534a36c77..6cacbfd42 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -411,6 +411,7 @@ "outputs": "çıktılar", "overwrite_amount": "Miktarın üzerine yaz", "pairingInvalidEvent": "Geçersiz Etkinliği Eşleştirme", + "passphrase": "Passfrase (isteğe bağlı)", "password": "Parola", "paste": "Yapıştır", "pause_wallet_creation": "Haven Cüzdanı oluşturma yeteneği şu anda duraklatıldı.", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 5d1e2be05..d3f1c5088 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -411,6 +411,7 @@ "outputs": "Виходи", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "Недійсна подія сполучення", + "passphrase": "Пасофрази (необов’язково)", "password": "Пароль", "paste": "Вставити", "pause_wallet_creation": "Можливість створення гаманця Haven зараз призупинено.", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index d98a85753..97851b210 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -413,6 +413,7 @@ "outputs": "نتائج", "overwrite_amount": "رقم کو اوور رائٹ کریں۔", "pairingInvalidEvent": "ﭧﻧﻮﯾﺍ ﻂﻠﻏ ﺎﻧﺎﻨﺑ ﺍﮌﻮﺟ", + "passphrase": "پاسفریز (اختیاری)", "password": "پاس ورڈ", "paste": "چسپاں کریں۔", "pause_wallet_creation": "Haven Wallet ۔ﮯﮨ ﻑﻮﻗﻮﻣ ﻝﺎﺤﻟﺍ ﯽﻓ ﺖﯿﻠﮨﺍ ﯽﮐ ﮯﻧﺎﻨﺑ", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index faaeb8837..acb533536 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -412,6 +412,7 @@ "outputs": "Awọn iṣan", "overwrite_amount": "Pààrọ̀ iye owó", "pairingInvalidEvent": "Pipọpọ Iṣẹlẹ Ti ko tọ", + "passphrase": "Ọrọ kukuru (iyan)", "password": "Ọ̀rọ̀ aṣínà", "paste": "Fikún ẹ̀dà yín", "pause_wallet_creation": "Agbara lati ṣẹda Haven Wallet ti wa ni idaduro lọwọlọwọ.", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 2d5251d86..e17c4a89b 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -411,6 +411,7 @@ "outputs": "输出", "overwrite_amount": "Overwrite amount", "pairingInvalidEvent": "配对无效事件", + "passphrase": "密码(可选)", "password": "密码", "paste": "粘贴", "pause_wallet_creation": "创建 Haven 钱包的功能当前已暂停。", diff --git a/tool/configure.dart b/tool/configure.dart index 3b73bfe80..ceb0c9ccc 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -61,6 +61,8 @@ Future main(List args) async { Future generateBitcoin(bool hasImplementation) async { final outputFile = File(bitcoinOutputPath); const bitcoinCommonHeaders = """ +import 'dart:typed_data'; +import 'package:cw_core/node.dart'; import 'package:cw_core/pending_transaction.dart'; import 'package:cw_core/receive_page_option.dart'; import 'package:cw_core/unspent_transaction_output.dart'; @@ -73,8 +75,17 @@ import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:hive/hive.dart'; -import 'package:bitcoin_base/bitcoin_base.dart';"""; +import 'package:bitcoin_base/bitcoin_base.dart'; +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as btc; +import 'package:bip32/bip32.dart' as bip32; +import 'package:bip39/bip39.dart' as bip39; +import 'package:hive/hive.dart'; +"""; const bitcoinCWHeaders = """ +import 'package:cw_bitcoin/utils.dart'; +import 'package:cw_bitcoin/litecoin_network.dart'; +import 'package:cw_bitcoin/electrum_derivations.dart'; +import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/bitcoin_receive_page_option.dart'; import 'package:cw_bitcoin/electrum_wallet.dart'; @@ -87,6 +98,7 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_bitcoin/litecoin_wallet_service.dart'; +import 'package:cw_bitcoin/script_hash.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:mobx/mobx.dart'; """; @@ -112,7 +124,14 @@ import 'package:mobx/mobx.dart'; abstract class Bitcoin { TransactionPriority getMediumTransactionPriority(); - WalletCredentials createBitcoinRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password}); + WalletCredentials createBitcoinRestoreWalletFromSeedCredentials({ + required String name, + required String mnemonic, + required String password, + required DerivationType derivationType, + required String derivationPath, + String? passphrase, + }); WalletCredentials createBitcoinRestoreWalletFromWIFCredentials({required String name, required String password, required String wif, WalletInfo? walletInfo}); WalletCredentials createBitcoinNewWalletCredentials({required String name, WalletInfo? walletInfo}); List getWordList(); @@ -147,7 +166,10 @@ abstract class Bitcoin { TransactionPriority getLitecoinTransactionPriorityMedium(); TransactionPriority getBitcoinTransactionPrioritySlow(); TransactionPriority getLitecoinTransactionPrioritySlow(); - + Future> compareDerivationMethods( + {required String mnemonic, required Node node}); + Future> getDerivationsFromMnemonic( + {required String mnemonic, required Node node, String? passphrase}); Future setAddressType(Object wallet, dynamic option); ReceivePageOption getSelectedAddressType(Object wallet); List getBitcoinReceivePageOptions(); @@ -838,14 +860,14 @@ abstract class Nano { required String name, required String password, required String mnemonic, - DerivationType? derivationType, + required DerivationType derivationType, }); WalletCredentials createNanoRestoreWalletFromKeysCredentials({ required String name, required String password, required String seedKey, - DerivationType? derivationType, + required DerivationType derivationType, }); List getNanoWordList(String language); @@ -892,6 +914,11 @@ abstract class NanoUtil { String? privateKey, required Node node, }); + Future> getDerivationsFromMnemonic({ + String? mnemonic, + String? seedKey, + required Node node, + }); } """; From f9e9b1d67ea2c21aa891cf3eb95803f47ac78058 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Tue, 30 Apr 2024 04:05:48 +0300 Subject: [PATCH 200/241] update versions (#1418) --- assets/text/Monerocom_Release_Notes.txt | 3 +-- assets/text/Release_Notes.txt | 10 +++------- lib/src/screens/send/send_page.dart | 2 +- scripts/android/app_env.sh | 8 ++++---- scripts/ios/app_env.sh | 8 ++++---- scripts/macos/app_env.sh | 8 ++++---- 6 files changed, 17 insertions(+), 22 deletions(-) diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt index 09092a8df..d5297ebe1 100644 --- a/assets/text/Monerocom_Release_Notes.txt +++ b/assets/text/Monerocom_Release_Notes.txt @@ -1,2 +1 @@ -UI enhancements -Bug fixes \ No newline at end of file +Generic bug fixes and enhancements \ No newline at end of file diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index 69a5145c9..ac648921c 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,7 +1,3 @@ -Add Replace-By-Fee to boost pending Bitcoin transactions -Enable WalletConnect for Solana -WalletConnect Enhancements -Enhancements for ERC-20 tokens and Solana tokens -Enhancements for Nano wallet -UI enhancements -Bug fixes \ No newline at end of file +Support restoring Non-Electrum Bitcoin Wallets (check supported derivation paths https://github.com/cake-tech/cake_wallet/blob/main/cw_bitcoin/lib/bitcoin_derivations.dart) +Bitcoin enhancements and bug fixes +Generic bug fixes and enhancements \ No newline at end of file diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 93fadea72..9067a2951 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -102,7 +102,7 @@ class SendPage extends BasePage { double _sendCardHeight(BuildContext context) { double initialHeight = 480; if (sendViewModel.hasCoinControl) { - initialHeight += 35; + initialHeight += 55; } if (!responsiveLayoutUtil.shouldRenderMobileUI) { diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index c55be8900..5e52d9d96 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.12.2" -MONERO_COM_BUILD_NUMBER=82 +MONERO_COM_VERSION="1.12.3" +MONERO_COM_BUILD_NUMBER=84 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.15.4" -CAKEWALLET_BUILD_NUMBER=204 +CAKEWALLET_VERSION="4.15.5" +CAKEWALLET_BUILD_NUMBER=206 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index b9dc0e435..6f5e810eb 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.12.2" -MONERO_COM_BUILD_NUMBER=79 +MONERO_COM_VERSION="1.12.3" +MONERO_COM_BUILD_NUMBER=82 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.15.4" -CAKEWALLET_BUILD_NUMBER=228 +CAKEWALLET_VERSION="4.15.5" +CAKEWALLET_BUILD_NUMBER=231 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 42708f3e3..309213b4a 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -16,13 +16,13 @@ if [ -n "$1" ]; then fi MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.2.2" -MONERO_COM_BUILD_NUMBER=13 +MONERO_COM_VERSION="1.2.3" +MONERO_COM_BUILD_NUMBER=16 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.8.4" -CAKEWALLET_BUILD_NUMBER=63 +CAKEWALLET_VERSION="1.8.5" +CAKEWALLET_BUILD_NUMBER=66 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From e87353c012a12ea82e9841228b67b46c1f76a63d Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Wed, 1 May 2024 19:21:04 +0300 Subject: [PATCH 201/241] fix backward compatibility issue with existing electrum wallets (#1424) --- assets/text/Release_Notes.txt | 4 +--- cw_bitcoin/lib/bitcoin_wallet.dart | 8 ++++---- cw_nano/pubspec.lock | 32 +++++++++++------------------- scripts/android/app_env.sh | 4 ++-- scripts/ios/app_env.sh | 4 ++-- scripts/macos/app_env.sh | 4 ++-- 6 files changed, 23 insertions(+), 33 deletions(-) diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index ac648921c..ae6306209 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1,3 +1 @@ -Support restoring Non-Electrum Bitcoin Wallets (check supported derivation paths https://github.com/cake-tech/cake_wallet/blob/main/cw_bitcoin/lib/bitcoin_derivations.dart) -Bitcoin enhancements and bug fixes -Generic bug fixes and enhancements \ No newline at end of file +Bitcoin Bug fixes and enhancements \ No newline at end of file diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 1d29307ca..33401d666 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -51,15 +51,14 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { // the sideHd derivation path = m/84'/0'/0'/1 (account 1, index unspecified here) String derivationPath = walletInfo.derivationInfo!.derivationPath!; String sideDerivationPath = derivationPath.substring(0, derivationPath.length - 1) + "1"; - final hd = bitcoin.HDWallet.fromSeed(seedBytes, network: networkType); walletAddresses = BitcoinWalletAddresses( walletInfo, electrumClient: electrumClient, initialAddresses: initialAddresses, initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex, - mainHd: hd.derivePath(derivationPath), - sideHd: hd.derivePath(sideDerivationPath), + mainHd: hd, + sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath(sideDerivationPath), network: networkParam ?? network, ); autorun((_) { @@ -127,7 +126,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { ); // set the default if not present: - walletInfo.derivationInfo!.derivationPath = snp.derivationPath ?? "m/0'/1"; + walletInfo.derivationInfo!.derivationPath = snp.derivationPath ?? "m/0'/0"; + walletInfo.derivationInfo!.derivationType = snp.derivationType ?? DerivationType.electrum; late Uint8List seedBytes; diff --git a/cw_nano/pubspec.lock b/cw_nano/pubspec.lock index 0ebc5e75f..cbcf3d38d 100644 --- a/cw_nano/pubspec.lock +++ b/cw_nano/pubspec.lock @@ -173,10 +173,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.17.1" convert: dependency: transitive description: @@ -419,18 +419,18 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.15" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.2.0" meta: dependency: transitive description: @@ -713,10 +713,10 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" stack_trace: dependency: transitive description: @@ -761,10 +761,10 @@ packages: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.5.1" timing: dependency: transitive description: @@ -790,21 +790,13 @@ packages: source: hosted version: "2.1.4" watcher: - dependency: "direct overridden" + dependency: transitive description: name: watcher sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.dev" source: hosted version: "1.1.0" - web: - dependency: transitive - description: - name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 - url: "https://pub.dev" - source: hosted - version: "0.1.4-beta" web_socket_channel: dependency: transitive description: @@ -838,5 +830,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.0-185.0.dev <4.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.7.0" diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 5e52d9d96..52f32b297 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -22,8 +22,8 @@ MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.15.5" -CAKEWALLET_BUILD_NUMBER=206 +CAKEWALLET_VERSION="4.15.6" +CAKEWALLET_BUILD_NUMBER=207 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 6f5e810eb..90f7d807c 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -18,8 +18,8 @@ MONERO_COM_BUILD_NUMBER=82 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.15.5" -CAKEWALLET_BUILD_NUMBER=231 +CAKEWALLET_VERSION="4.15.6" +CAKEWALLET_BUILD_NUMBER=232 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 309213b4a..758bfe900 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -21,8 +21,8 @@ MONERO_COM_BUILD_NUMBER=16 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.8.5" -CAKEWALLET_BUILD_NUMBER=66 +CAKEWALLET_VERSION="1.8.6" +CAKEWALLET_BUILD_NUMBER=67 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then From 4c50cc7551fedf7b7d6aded09988c41c7d6d2b76 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Wed, 1 May 2024 09:44:22 -0700 Subject: [PATCH 202/241] minor script fix (#1423) --- run-android.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run-android.sh b/run-android.sh index dd694267a..bdacef392 100755 --- a/run-android.sh +++ b/run-android.sh @@ -4,6 +4,7 @@ get_current_branch() { if git rev-parse --git-dir > /dev/null 2>&1; then branch=$(git rev-parse --abbrev-ref HEAD) + branch=${branch//[-]/_} # Replace all dashes with underscores echo "$branch" else echo "Error: Not a git repository." @@ -15,7 +16,6 @@ get_current_branch() { update_app_properties() { local branch=$1 local file_path="./android/app.properties" - sed -i "s/^id=.*/id=com.cakewallet.$branch/" "$file_path" sed -i "s/^name=.*/name=$branch-Cake Wallet/" "$file_path" } From e4fd53494927d4915fcf9aa9e52d83ed6e108914 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Fri, 3 May 2024 20:36:00 +0300 Subject: [PATCH 203/241] Generic Enhancements (#1426) * Better handle deep links after authentication * handle no auth required case and some enhancements * deprecate old variables [skip ci] --- cw_core/lib/wallet_info.dart | 2 + lib/src/screens/root/root.dart | 74 ++++++++++++++++++---------------- 2 files changed, 42 insertions(+), 34 deletions(-) diff --git a/cw_core/lib/wallet_info.dart b/cw_core/lib/wallet_info.dart index 4892f6d1d..2768fdc6e 100644 --- a/cw_core/lib/wallet_info.dart +++ b/cw_core/lib/wallet_info.dart @@ -154,9 +154,11 @@ class WalletInfo extends HiveObject { @HiveField(15) List? usedAddresses; + @deprecated @HiveField(16) DerivationType? derivationType; // no longer used + @deprecated @HiveField(17) String? derivationPath; // no longer used diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index 8a75b78bb..e3472f510 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -52,6 +52,7 @@ class RootState extends State with WidgetsBindingObserver { StreamSubscription? stream; ReactionDisposer? _walletReactionDisposer; + ReactionDisposer? _deepLinksReactionDisposer; Uri? launchUri; @override @@ -76,6 +77,7 @@ class RootState extends State with WidgetsBindingObserver { void dispose() { stream?.cancel(); _walletReactionDisposer?.call(); + _deepLinksReactionDisposer?.call(); super.dispose(); } @@ -93,10 +95,32 @@ class RootState extends State with WidgetsBindingObserver { } } - void handleDeepLinking(Uri? uri) { + void handleDeepLinking(Uri? uri) async { if (uri == null || !mounted) return; launchUri = uri; + + bool requireAuth = await widget.authService.requireAuth(); + + if (!requireAuth && widget.authenticationStore.state == AuthenticationState.allowed) { + _navigateToDeepLinkScreen(); + return; + } + + _deepLinksReactionDisposer = reaction( + (_) => widget.authenticationStore.state, + (AuthenticationState state) { + if (state == AuthenticationState.allowed) { + if (widget.appStore.wallet == null) { + waitForWalletInstance(context, launchUri!); + } else { + _navigateToDeepLinkScreen(); + } + _deepLinksReactionDisposer?.call(); + _deepLinksReactionDisposer = null; + } + }, + ); } @override @@ -172,35 +196,8 @@ class RootState extends State with WidgetsBindingObserver { }, ); }); - } else if (_isValidPaymentUri()) { - if (widget.authenticationStore.state == AuthenticationState.uninitialized) { - launchUri = null; - } else { - if (widget.appStore.wallet == null) { - waitForWalletInstance(context, launchUri!); - launchUri = null; - } else { - widget.navigatorKey.currentState?.pushNamed( - Routes.send, - arguments: PaymentRequest.fromUri(launchUri), - ); - launchUri = null; - } - } - launchUri = null; - } else if (isWalletConnectLink) { - if (isEVMCompatibleChain(widget.appStore.wallet!.type)) { - widget.navigatorKey.currentState?.pushNamed( - Routes.walletConnectConnectionsListing, - arguments: launchUri, - ); - launchUri = null; - } else { - _nonETHWalletErrorToast(S.current.switchToEVMCompatibleWallet); - } } - launchUri = null; return WillPopScope( onWillPop: () async => false, child: widget.child, @@ -252,13 +249,10 @@ class RootState extends State with WidgetsBindingObserver { WidgetsBinding.instance.addPostFrameCallback((_) { if (context.mounted) { _walletReactionDisposer = reaction( - (_) => widget.appStore.wallet, - (WalletBase? wallet) { + (_) => widget.appStore.wallet, + (WalletBase? wallet) { if (wallet != null) { - widget.navigatorKey.currentState?.pushNamed( - Routes.send, - arguments: PaymentRequest.fromUri(tempLaunchUri), - ); + _navigateToDeepLinkScreen(); _walletReactionDisposer?.call(); _walletReactionDisposer = null; } @@ -267,4 +261,16 @@ class RootState extends State with WidgetsBindingObserver { } }); } + + void _navigateToDeepLinkScreen() { + if (_getRouteToGo() != null) { + WidgetsBinding.instance.addPostFrameCallback((_) { + widget.navigatorKey.currentState?.pushNamed( + _getRouteToGo()!, + arguments: isWalletConnectLink ? launchUri : PaymentRequest.fromUri(launchUri), + ); + launchUri = null; + }); + } + } } From d1870ba8b87dbe918c0667f588f4376a802a8406 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Fri, 3 May 2024 19:00:05 +0100 Subject: [PATCH 204/241] CW-525-Add-Tron-Wallet (#1327) * chore: Initial setup for Tron Wallet * feat: Create Tron Wallet base flow implemented, keys, address, receive, restore and proxy classes all setup * feat: Display seed and key within the app * feat: Activate restore from key and seed for Tron wallet * feat: Add icon for tron wallet in wallet listing page * feat: Activate display of receive address for tron * feat: Fetch and display tron balance, sending transaction flow setup, fee limit calculation setup * feat: Implement sending of native tron, setup sending of trc20 tokens * chore: Rename function * Delete lib/tron/tron.dart * feat: Activate exchange for tron and its tokens, implement balance display for trc20 tokens and setup secrets configuration for tron * feat: Implement tron token management, add, remove, delete, and get tokens in home settings view, also minor cleanup * feat: Activate buy and sell for tron * feat: Implement restore from QR, transactions history listing for both native transactions and trc20 transactions * feat: Activate send all and do some minor cleanups * chore: Fix some lint infos and warnings * chore: Adjust configurations * ci: Modify CI to create and add secrets for node * fix: Fixes made while self reviewing the PR for this feature * feat: Add guide for adding new wallet types, and add fixes to requested changes * fix: Handle exceptions gracefully * fix: Alternative for trc20 estimated fee * fix: Fixes to display of amount and fee, removing clashes * fix: Fee calculation WIP * fix: Fix issue with handling of send all flow and display of amount and fee values before broadcasting transaction * fix: PR review fixes and fix merge conflicts * fix: Modify fetching assetOfTransaction [skip ci] * fix: Move tron settings migration to 33 --- .github/workflows/pr_test_build.yml | 2 + .gitignore | 3 + android/app/src/main/AndroidManifestBase.xml | 3 + assets/tron_node_list.yml | 4 + cw_core/lib/crypto_currency.dart | 2 + cw_core/lib/currency_for_wallet_type.dart | 5 +- cw_core/lib/hive_type_ids.dart | 1 + cw_core/lib/node.dart | 2 + cw_core/lib/wallet_type.dart | 16 +- cw_tron/.gitignore | 30 + cw_tron/.metadata | 10 + cw_tron/CHANGELOG.md | 3 + cw_tron/LICENSE | 1 + cw_tron/README.md | 39 ++ cw_tron/analysis_options.yaml | 4 + cw_tron/lib/cw_tron.dart | 7 + cw_tron/lib/default_tron_tokens.dart | 103 ++++ cw_tron/lib/file.dart | 39 ++ cw_tron/lib/pending_tron_transaction.dart | 33 + cw_tron/lib/tron_abi.dart | 436 +++++++++++++ cw_tron/lib/tron_balance.dart | 34 ++ cw_tron/lib/tron_client.dart | 574 ++++++++++++++++++ cw_tron/lib/tron_exception.dart | 16 + cw_tron/lib/tron_http_provider.dart | 41 ++ cw_tron/lib/tron_token.dart | 80 +++ cw_tron/lib/tron_transaction_credentials.dart | 12 + cw_tron/lib/tron_transaction_history.dart | 80 +++ cw_tron/lib/tron_transaction_info.dart | 93 +++ cw_tron/lib/tron_transaction_model.dart | 205 +++++++ cw_tron/lib/tron_wallet.dart | 560 +++++++++++++++++ cw_tron/lib/tron_wallet_addresses.dart | 36 ++ .../lib/tron_wallet_creation_credentials.dart | 29 + cw_tron/lib/tron_wallet_service.dart | 148 +++++ cw_tron/pubspec.yaml | 33 + cw_tron/test/cw_tron_test.dart | 12 + how_to_add_new_wallet_type.md | 300 +++++++++ ios/Runner/InfoBase.plist | 30 + lib/core/address_validator.dart | 2 + lib/core/seed_validator.dart | 3 + lib/di.dart | 3 + lib/entities/default_settings_migration.dart | 41 +- lib/entities/node_list.dart | 20 +- lib/entities/preferences_key.dart | 1 + lib/entities/priority_for_wallet_type.dart | 3 +- lib/entities/provider_types.dart | 13 + lib/main.dart | 2 +- lib/reactions/fiat_rate_update.dart | 6 + lib/reactions/on_current_wallet_change.dart | 14 +- .../desktop_wallet_selection_dropdown.dart | 3 + .../dashboard/pages/transactions_page.dart | 30 +- .../dashboard/widgets/menu_widget.dart | 6 +- .../screens/wallet_list/wallet_list_page.dart | 3 + lib/store/settings_store.dart | 15 + lib/tron/cw_tron.dart | 114 ++++ .../advanced_privacy_settings_view_model.dart | 1 + .../dashboard/balance_view_model.dart | 7 +- .../dashboard/home_settings_view_model.dart | 33 +- .../dashboard/transaction_list_item.dart | 46 ++ .../exchange/exchange_trade_view_model.dart | 7 +- .../exchange/exchange_view_model.dart | 4 + .../node_create_or_edit_view_model.dart | 1 + .../node_list/node_list_view_model.dart | 3 + .../restore/restore_from_qr_vm.dart | 9 +- .../restore/wallet_restore_from_qr_code.dart | 11 + lib/view_model/send/output.dart | 22 +- .../send/send_template_view_model.dart | 3 +- lib/view_model/send/send_view_model.dart | 19 +- .../settings/other_settings_view_model.dart | 5 +- .../transaction_details_view_model.dart | 54 +- .../wallet_address_list_view_model.dart | 26 + lib/view_model/wallet_keys_view_model.dart | 5 +- lib/view_model/wallet_new_vm.dart | 4 + lib/view_model/wallet_restore_view_model.dart | 17 +- model_generator.sh | 1 + pubspec_base.yaml | 1 + scripts/android/pubspec_gen.sh | 2 +- scripts/ios/app_config.sh | 2 +- scripts/macos/app_config.sh | 2 +- tool/configure.dart | 96 ++- tool/generate_secrets_config.dart | 18 +- tool/import_secrets_config.dart | 14 + tool/utils/secret_key.dart | 4 + 82 files changed, 3660 insertions(+), 62 deletions(-) create mode 100644 assets/tron_node_list.yml create mode 100644 cw_tron/.gitignore create mode 100644 cw_tron/.metadata create mode 100644 cw_tron/CHANGELOG.md create mode 100644 cw_tron/LICENSE create mode 100644 cw_tron/README.md create mode 100644 cw_tron/analysis_options.yaml create mode 100644 cw_tron/lib/cw_tron.dart create mode 100644 cw_tron/lib/default_tron_tokens.dart create mode 100644 cw_tron/lib/file.dart create mode 100644 cw_tron/lib/pending_tron_transaction.dart create mode 100644 cw_tron/lib/tron_abi.dart create mode 100644 cw_tron/lib/tron_balance.dart create mode 100644 cw_tron/lib/tron_client.dart create mode 100644 cw_tron/lib/tron_exception.dart create mode 100644 cw_tron/lib/tron_http_provider.dart create mode 100644 cw_tron/lib/tron_token.dart create mode 100644 cw_tron/lib/tron_transaction_credentials.dart create mode 100644 cw_tron/lib/tron_transaction_history.dart create mode 100644 cw_tron/lib/tron_transaction_info.dart create mode 100644 cw_tron/lib/tron_transaction_model.dart create mode 100644 cw_tron/lib/tron_wallet.dart create mode 100644 cw_tron/lib/tron_wallet_addresses.dart create mode 100644 cw_tron/lib/tron_wallet_creation_credentials.dart create mode 100644 cw_tron/lib/tron_wallet_service.dart create mode 100644 cw_tron/pubspec.yaml create mode 100644 cw_tron/test/cw_tron_test.dart create mode 100644 how_to_add_new_wallet_type.md create mode 100644 lib/tron/cw_tron.dart diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index dc231df42..46924cb35 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -113,6 +113,7 @@ jobs: touch lib/.secrets.g.dart touch cw_evm/lib/.secrets.g.dart touch cw_solana/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 @@ -150,6 +151,7 @@ jobs: 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 tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart - name: Rename app run: | diff --git a/.gitignore b/.gitignore index 6f2d0a182..f1e5b6da3 100644 --- a/.gitignore +++ b/.gitignore @@ -94,9 +94,11 @@ android/app/key.jks **/tool/.evm-secrets-config.json **/tool/.ethereum-secrets-config.json **/tool/.solana-secrets-config.json +**/tool/.tron-secrets-config.json **/lib/.secrets.g.dart **/cw_evm/lib/.secrets.g.dart **/cw_solana/lib/.secrets.g.dart +**/cw_tron/lib/.secrets.g.dart vendor/ @@ -132,6 +134,7 @@ lib/bitcoin_cash/bitcoin_cash.dart lib/nano/nano.dart lib/polygon/polygon.dart lib/solana/solana.dart +lib/tron/tron.dart ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_180.png ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_120.png diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index eea9b5521..485f049e8 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -67,6 +67,9 @@ + + + with Serializable implemen CryptoCurrency.kaspa, CryptoCurrency.digibyte, CryptoCurrency.usdtSol, + CryptoCurrency.usdcTrc20, ]; static const havenCurrencies = [ @@ -217,6 +218,7 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen static const kaspa = CryptoCurrency(title: 'KAS', fullName: 'Kaspa', raw: 89, name: 'kas', iconPath: 'assets/images/kaspa_icon.png', decimals: 8); static const digibyte = CryptoCurrency(title: 'DGB', fullName: 'DigiByte', raw: 90, name: 'dgb', iconPath: 'assets/images/digibyte.png', decimals: 8); static const usdtSol = CryptoCurrency(title: 'USDT', tag: 'SOL', fullName: 'USDT Tether', raw: 91, name: 'usdtsol', iconPath: 'assets/images/usdt_icon.png', decimals: 6); + static const usdcTrc20 = CryptoCurrency(title: 'USDC', tag: 'TRX', fullName: 'USDC Coin', raw: 92, name: 'usdctrc20', iconPath: 'assets/images/usdc_icon.png', decimals: 6); static final Map _rawCurrencyMap = diff --git a/cw_core/lib/currency_for_wallet_type.dart b/cw_core/lib/currency_for_wallet_type.dart index 58ee37669..92e78b2e6 100644 --- a/cw_core/lib/currency_for_wallet_type.dart +++ b/cw_core/lib/currency_for_wallet_type.dart @@ -23,7 +23,10 @@ CryptoCurrency currencyForWalletType(WalletType type) { return CryptoCurrency.maticpoly; case WalletType.solana: return CryptoCurrency.sol; + case WalletType.tron: + return CryptoCurrency.trx; default: - throw Exception('Unexpected wallet type: ${type.toString()} for CryptoCurrency currencyForWalletType'); + throw Exception( + 'Unexpected wallet type: ${type.toString()} for CryptoCurrency currencyForWalletType'); } } diff --git a/cw_core/lib/hive_type_ids.dart b/cw_core/lib/hive_type_ids.dart index e0896bab1..e3332a043 100644 --- a/cw_core/lib/hive_type_ids.dart +++ b/cw_core/lib/hive_type_ids.dart @@ -16,3 +16,4 @@ const POW_NODE_TYPE_ID = 14; const DERIVATION_TYPE_TYPE_ID = 15; const SPL_TOKEN_TYPE_ID = 16; const DERIVATION_INFO_TYPE_ID = 17; +const TRON_TOKEN_TYPE_ID = 18; diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 9d0806851..1195b6819 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -94,6 +94,7 @@ class Node extends HiveObject with Keyable { case WalletType.ethereum: case WalletType.polygon: case WalletType.solana: + case WalletType.tron: return Uri.https(uriRaw, path ?? ''); default: throw Exception('Unexpected type ${type.toString()} for Node uri'); @@ -152,6 +153,7 @@ class Node extends HiveObject with Keyable { case WalletType.ethereum: case WalletType.polygon: case WalletType.solana: + case WalletType.tron: return requestElectrumServer(); default: return false; diff --git a/cw_core/lib/wallet_type.dart b/cw_core/lib/wallet_type.dart index a63ddf37c..e846093d0 100644 --- a/cw_core/lib/wallet_type.dart +++ b/cw_core/lib/wallet_type.dart @@ -15,6 +15,7 @@ const walletTypes = [ WalletType.banano, WalletType.polygon, WalletType.solana, + WalletType.tron, ]; @HiveType(typeId: WALLET_TYPE_TYPE_ID) @@ -50,7 +51,10 @@ enum WalletType { polygon, @HiveField(10) - solana + solana, + + @HiveField(11) + tron } int serializeToInt(WalletType type) { @@ -75,6 +79,8 @@ int serializeToInt(WalletType type) { return 8; case WalletType.solana: return 9; + case WalletType.tron: + return 10; default: return -1; } @@ -102,6 +108,8 @@ WalletType deserializeFromInt(int raw) { return WalletType.polygon; case 9: return WalletType.solana; + case 10: + return WalletType.tron; default: throw Exception('Unexpected token: $raw for WalletType deserializeFromInt'); } @@ -129,6 +137,8 @@ String walletTypeToString(WalletType type) { return 'Polygon'; case WalletType.solana: return 'Solana'; + case WalletType.tron: + return 'Tron'; default: return ''; } @@ -156,6 +166,8 @@ String walletTypeToDisplayName(WalletType type) { return 'Polygon (MATIC)'; case WalletType.solana: return 'Solana (SOL)'; + case WalletType.tron: + return 'Tron (TRX)'; default: return ''; } @@ -183,6 +195,8 @@ CryptoCurrency walletTypeToCryptoCurrency(WalletType type) { return CryptoCurrency.maticpoly; case WalletType.solana: return CryptoCurrency.sol; + case WalletType.tron: + return CryptoCurrency.trx; default: throw Exception( 'Unexpected wallet type: ${type.toString()} for CryptoCurrency walletTypeToCryptoCurrency'); diff --git a/cw_tron/.gitignore b/cw_tron/.gitignore new file mode 100644 index 000000000..96486fd93 --- /dev/null +++ b/cw_tron/.gitignore @@ -0,0 +1,30 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/cw_tron/.metadata b/cw_tron/.metadata new file mode 100644 index 000000000..fa347fc6a --- /dev/null +++ b/cw_tron/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 + channel: stable + +project_type: package diff --git a/cw_tron/CHANGELOG.md b/cw_tron/CHANGELOG.md new file mode 100644 index 000000000..41cc7d819 --- /dev/null +++ b/cw_tron/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/cw_tron/LICENSE b/cw_tron/LICENSE new file mode 100644 index 000000000..ba75c69f7 --- /dev/null +++ b/cw_tron/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/cw_tron/README.md b/cw_tron/README.md new file mode 100644 index 000000000..02fe8ecab --- /dev/null +++ b/cw_tron/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/cw_tron/analysis_options.yaml b/cw_tron/analysis_options.yaml new file mode 100644 index 000000000..a5744c1cf --- /dev/null +++ b/cw_tron/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/cw_tron/lib/cw_tron.dart b/cw_tron/lib/cw_tron.dart new file mode 100644 index 000000000..6981fccba --- /dev/null +++ b/cw_tron/lib/cw_tron.dart @@ -0,0 +1,7 @@ +library cw_tron; + +/// A Calculator. +class Calculator { + /// Returns [value] plus 1. + int addOne(int value) => value + 1; +} diff --git a/cw_tron/lib/default_tron_tokens.dart b/cw_tron/lib/default_tron_tokens.dart new file mode 100644 index 000000000..ad70f28cd --- /dev/null +++ b/cw_tron/lib/default_tron_tokens.dart @@ -0,0 +1,103 @@ +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_tron/tron_token.dart'; + +class DefaultTronTokens { + final List _defaultTokens = [ + TronToken( + name: "Tether USD", + symbol: "USDT", + contractAddress: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", + decimal: 6, + enabled: true, + ), + TronToken( + name: "USD Coin", + symbol: "USDC", + contractAddress: "TEkxiTehnzSmSe2XqrBj4w32RUN966rdz8", + decimal: 6, + enabled: true, + ), + TronToken( + name: "Bitcoin", + symbol: "BTC", + contractAddress: "TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9", + decimal: 8, + enabled: true, + ), + TronToken( + name: "Ethereum", + symbol: "ETH", + contractAddress: "TRFe3hT5oYhjSZ6f3ji5FJ7YCfrkWnHRvh", + decimal: 18, + enabled: true, + ), + TronToken( + name: "Wrapped BTC", + symbol: "WBTC", + contractAddress: "TXpw8XeWYeTUd4quDskoUqeQPowRh4jY65", + decimal: 8, + enabled: true, + ), + TronToken( + name: "Dogecoin", + symbol: "DOGE", + contractAddress: "THbVQp8kMjStKNnf2iCY6NEzThKMK5aBHg", + decimal: 8, + enabled: true, + ), + TronToken( + name: "JUST Stablecoin", + symbol: "USDJ", + contractAddress: "TMwFHYXLJaRUPeW6421aqXL4ZEzPRFGkGT", + decimal: 18, + enabled: false, + ), + TronToken( + name: "SUN", + symbol: "SUN", + contractAddress: "TSSMHYeV2uE9qYH95DqyoCuNCzEL1NvU3S", + decimal: 18, + enabled: false, + ), + TronToken( + name: "Wrapped TRX", + symbol: "WTRX", + contractAddress: "TNUC9Qb1rRpS5CbWLmNMxXBjyFoydXjWFR", + decimal: 6, + enabled: false, + ), + TronToken( + name: "BitTorent", + symbol: "BTT", + contractAddress: "TAFjULxiVgT4qWk6UZwjqwZXTSaGaqnVp4", + decimal: 18, + enabled: false, + ), + TronToken( + name: "BUSD Token", + symbol: "BUSD", + contractAddress: "TMz2SWatiAtZVVcH2ebpsbVtYwUPT9EdjH", + decimal: 18, + enabled: false, + ), + TronToken( + name: "HTX", + symbol: "HTX", + contractAddress: "TUPM7K8REVzD2UdV4R5fe5M8XbnR2DdoJ6", + decimal: 18, + enabled: false, + ), + ]; + + List get initialTronTokens => _defaultTokens.map((token) { + String? iconPath; + try { + iconPath = CryptoCurrency.all + .firstWhere((element) => + element.title.toUpperCase() == token.symbol.split(".").first.toUpperCase()) + .iconPath; + } catch (_) {} + + return TronToken.copyWith(token, iconPath, 'TRX'); + }).toList(); +} diff --git a/cw_tron/lib/file.dart b/cw_tron/lib/file.dart new file mode 100644 index 000000000..8fd236ec3 --- /dev/null +++ b/cw_tron/lib/file.dart @@ -0,0 +1,39 @@ +import 'dart:io'; +import 'package:cw_core/key.dart'; +import 'package:encrypt/encrypt.dart' as encrypt; + +Future write( + {required String path, + required String password, + required String data}) async { + final keys = extractKeys(password); + final key = encrypt.Key.fromBase64(keys.first); + final iv = encrypt.IV.fromBase64(keys.last); + final encrypted = await encode(key: key, iv: iv, data: data); + final f = File(path); + f.writeAsStringSync(encrypted); +} + +Future writeData( + {required String path, + required String password, + required String data}) async { + final keys = extractKeys(password); + final key = encrypt.Key.fromBase64(keys.first); + final iv = encrypt.IV.fromBase64(keys.last); + final encrypted = await encode(key: key, iv: iv, data: data); + final f = File(path); + f.writeAsStringSync(encrypted); +} + +Future read({required String path, required String password}) async { + final file = File(path); + + if (!file.existsSync()) { + file.createSync(); + } + + final encrypted = file.readAsStringSync(); + + return decode(password: password, data: encrypted); +} diff --git a/cw_tron/lib/pending_tron_transaction.dart b/cw_tron/lib/pending_tron_transaction.dart new file mode 100644 index 000000000..b6d064b31 --- /dev/null +++ b/cw_tron/lib/pending_tron_transaction.dart @@ -0,0 +1,33 @@ + + +import 'package:cw_core/pending_transaction.dart'; +import 'package:web3dart/crypto.dart'; + +class PendingTronTransaction with PendingTransaction { + final Function sendTransaction; + final List signedTransaction; + final String fee; + final String amount; + + PendingTronTransaction({ + required this.sendTransaction, + required this.signedTransaction, + required this.fee, + required this.amount, + }); + + @override + String get amountFormatted => amount; + + @override + Future commit() async => await sendTransaction(); + + @override + String get feeFormatted => fee; + + @override + String get hex => bytesToHex(signedTransaction); + + @override + String get id => ''; +} diff --git a/cw_tron/lib/tron_abi.dart b/cw_tron/lib/tron_abi.dart new file mode 100644 index 000000000..fdb998636 --- /dev/null +++ b/cw_tron/lib/tron_abi.dart @@ -0,0 +1,436 @@ +final trc20Abi = [ + {"inputs": [], "stateMutability": "nonpayable", "type": "constructor"}, + { + "anonymous": false, + "inputs": [ + {"indexed": true, "internalType": "address", "name": "owner", "type": "address"}, + {"indexed": true, "internalType": "address", "name": "spender", "type": "address"}, + {"indexed": false, "internalType": "uint256", "name": "value", "type": "uint256"} + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + {"indexed": false, "internalType": "uint256", "name": "total", "type": "uint256"}, + {"indexed": true, "internalType": "uint16", "name": "order_id", "type": "uint16"}, + {"indexed": true, "internalType": "address", "name": "buyer", "type": "address"}, + {"indexed": true, "internalType": "address", "name": "seller", "type": "address"}, + {"indexed": false, "internalType": "address", "name": "contract_address", "type": "address"} + ], + "name": "OrderPaid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + {"indexed": true, "internalType": "address", "name": "previousOwner", "type": "address"}, + {"indexed": true, "internalType": "address", "name": "newOwner", "type": "address"} + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + {"indexed": false, "internalType": "address", "name": "token", "type": "address"}, + {"indexed": false, "internalType": "bool", "name": "active", "type": "bool"} + ], + "name": "TokenUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + {"indexed": true, "internalType": "address", "name": "from", "type": "address"}, + {"indexed": true, "internalType": "address", "name": "to", "type": "address"}, + {"indexed": false, "internalType": "uint256", "name": "value", "type": "uint256"} + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + {"indexed": false, "internalType": "string", "name": "username", "type": "string"}, + {"indexed": true, "internalType": "address", "name": "seller", "type": "address"} + ], + "name": "UserRegistred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + {"indexed": true, "internalType": "uint16", "name": "order_id", "type": "uint16"}, + {"indexed": true, "internalType": "address", "name": "buyer", "type": "address"}, + {"indexed": false, "internalType": "address", "name": "seller", "type": "address"} + ], + "name": "WBuyer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + {"indexed": true, "internalType": "uint16", "name": "order_id", "type": "uint16"}, + {"indexed": true, "internalType": "address", "name": "seller", "type": "address"}, + {"indexed": false, "internalType": "address", "name": "buyer", "type": "address"} + ], + "name": "WSeller", + "type": "event" + }, + { + "inputs": [], + "name": "CONTRACTPERCENTAGE", + "outputs": [ + {"internalType": "uint8", "name": "", "type": "uint8"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "uint16", "name": "order_id", "type": "uint16"}, + {"internalType": "uint256", "name": "order_total", "type": "uint256"}, + {"internalType": "address", "name": "contractAddress", "type": "address"}, + {"internalType": "address", "name": "seller", "type": "address"} + ], + "name": "PayWithTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "TOKENINCREAMENT", + "outputs": [ + {"internalType": "uint16", "name": "", "type": "uint16"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "", "type": "address"} + ], + "name": "_signer", + "outputs": [ + {"internalType": "bool", "name": "", "type": "bool"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "", "type": "address"} + ], + "name": "_tokens", + "outputs": [ + {"internalType": "bool", "name": "active", "type": "bool"}, + {"internalType": "uint16", "name": "token", "type": "uint16"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "", "type": "address"} + ], + "name": "_users", + "outputs": [ + {"internalType": "bool", "name": "active", "type": "bool"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "owner", "type": "address"}, + {"internalType": "address", "name": "spender", "type": "address"} + ], + "name": "allowance", + "outputs": [ + {"internalType": "uint256", "name": "", "type": "uint256"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "spender", "type": "address"}, + {"internalType": "uint256", "name": "amount", "type": "uint256"} + ], + "name": "approve", + "outputs": [ + {"internalType": "bool", "name": "", "type": "bool"} + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "account", "type": "address"} + ], + "name": "balanceOf", + "outputs": [ + {"internalType": "uint256", "name": "", "type": "uint256"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "token", "type": "address"} + ], + "name": "balanceOfContract", + "outputs": [ + {"internalType": "uint256", "name": "", "type": "uint256"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "uint256", "name": "amount", "type": "uint256"} + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "account", "type": "address"}, + {"internalType": "uint256", "name": "amount", "type": "uint256"} + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + {"internalType": "uint256", "name": "value", "type": "uint256"}, + {"internalType": "address", "name": "_contractAddress", "type": "address"} + ], + "name": "contractWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + {"internalType": "uint8", "name": "", "type": "uint8"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "spender", "type": "address"}, + {"internalType": "uint256", "name": "subtractedValue", "type": "uint256"} + ], + "name": "decreaseAllowance", + "outputs": [ + {"internalType": "bool", "name": "", "type": "bool"} + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "spender", "type": "address"}, + {"internalType": "uint256", "name": "addedValue", "type": "uint256"} + ], + "name": "increaseAllowance", + "outputs": [ + {"internalType": "bool", "name": "", "type": "bool"} + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "to", "type": "address"}, + {"internalType": "uint256", "name": "amount", "type": "uint256"} + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + {"internalType": "string", "name": "", "type": "string"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + {"internalType": "address", "name": "", "type": "address"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "token", "type": "address"}, + {"internalType": "uint256", "name": "value", "type": "uint256"} + ], + "name": "payToContract", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + {"internalType": "uint16", "name": "order_id", "type": "uint16"}, + {"internalType": "address", "name": "seller", "type": "address"} + ], + "name": "payWithNativeToken", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + {"internalType": "string", "name": "username", "type": "string"} + ], + "name": "regiserUser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + {"internalType": "uint16", "name": "id", "type": "uint16"}, + {"internalType": "address", "name": "buyer", "type": "address"}, + {"internalType": "address", "name": "seller", "type": "address"} + ], + "name": "selectOrder", + "outputs": [ + {"internalType": "uint232", "name": "", "type": "uint232"}, + {"internalType": "uint16", "name": "", "type": "uint16"}, + {"internalType": "uint8", "name": "", "type": "uint8"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + {"internalType": "string", "name": "", "type": "string"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "signer", "type": "address"} + ], + "name": "toggleSigner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "tokenAddress", "type": "address"} + ], + "name": "toggleToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + {"internalType": "uint256", "name": "", "type": "uint256"} + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "to", "type": "address"}, + {"internalType": "uint256", "name": "amount", "type": "uint256"} + ], + "name": "transfer", + "outputs": [ + {"internalType": "bool", "name": "", "type": "bool"} + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "from", "type": "address"}, + {"internalType": "address", "name": "to", "type": "address"}, + {"internalType": "uint256", "name": "amount", "type": "uint256"} + ], + "name": "transferFrom", + "outputs": [ + {"internalType": "bool", "name": "", "type": "bool"} + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "newOwner", "type": "address"} + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + {"internalType": "uint8", "name": "newPercentage", "type": "uint8"} + ], + "name": "updateContractPercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address[]", "name": "buyer", "type": "address[]"}, + {"internalType": "bytes[]", "name": "signature", "type": "bytes[]"}, + {"internalType": "uint16[]", "name": "order_id", "type": "uint16[]"}, + {"internalType": "address", "name": "contractAddress", "type": "address"} + ], + "name": "widthrawForSellers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + {"internalType": "address", "name": "seller", "type": "address"}, + {"internalType": "bytes", "name": "signature", "type": "bytes"}, + {"internalType": "uint16", "name": "order_id", "type": "uint16"}, + {"internalType": "address", "name": "contractAddress", "type": "address"} + ], + "name": "widthrowForBuyers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +]; diff --git a/cw_tron/lib/tron_balance.dart b/cw_tron/lib/tron_balance.dart new file mode 100644 index 000000000..5b2ba3fa7 --- /dev/null +++ b/cw_tron/lib/tron_balance.dart @@ -0,0 +1,34 @@ +import 'dart:convert'; + +import 'package:cw_core/balance.dart'; +import 'package:on_chain/on_chain.dart'; + +class TronBalance extends Balance { + TronBalance(this.balance) : super(balance.toInt(), balance.toInt()); + + final BigInt balance; + + @override + String get formattedAdditionalBalance => TronHelper.fromSun(balance); + + @override + String get formattedAvailableBalance => TronHelper.fromSun(balance); + + String toJSON() => json.encode({ + 'balance': balance.toString(), + }); + + static TronBalance? fromJSON(String? jsonSource) { + if (jsonSource == null) { + return null; + } + + final decoded = json.decode(jsonSource) as Map; + + try { + return TronBalance(BigInt.parse(decoded['balance'])); + } catch (e) { + return TronBalance(BigInt.zero); + } + } +} diff --git a/cw_tron/lib/tron_client.dart b/cw_tron/lib/tron_client.dart new file mode 100644 index 000000000..f03a8abce --- /dev/null +++ b/cw_tron/lib/tron_client.dart @@ -0,0 +1,574 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:developer'; + +import 'package:blockchain_utils/blockchain_utils.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/node.dart'; +import 'package:cw_tron/pending_tron_transaction.dart'; +import 'package:cw_tron/tron_abi.dart'; +import 'package:cw_tron/tron_balance.dart'; +import 'package:cw_tron/tron_http_provider.dart'; +import 'package:cw_tron/tron_token.dart'; +import 'package:cw_tron/tron_transaction_model.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:http/http.dart'; +import '.secrets.g.dart' as secrets; +import 'package:on_chain/on_chain.dart'; + +class TronClient { + final httpClient = Client(); + TronProvider? _provider; + // This is an internal tracker, so we don't have to "refetch". + int _nativeTxEstimatedFee = 0; + + int get chainId => 1000; + + Future> fetchTransactions(String address, + {String? contractAddress}) async { + try { + final response = await httpClient.get( + Uri.https( + "api.trongrid.io", + "/v1/accounts/$address/transactions", + { + "only_confirmed": "true", + "limit": "200", + }, + ), + headers: { + 'Content-Type': 'application/json', + 'TRON-PRO-API-KEY': secrets.tronGridApiKey, + }, + ); + final jsonResponse = json.decode(response.body) as Map; + + if (response.statusCode >= 200 && + response.statusCode < 300 && + jsonResponse['status'] != false) { + return (jsonResponse['data'] as List).map((e) { + return TronTransactionModel.fromJson(e as Map); + }).toList(); + } + + return []; + } catch (e, s) { + log('Error getting tx: ${e.toString()}\n ${s.toString()}'); + return []; + } + } + + Future> fetchTrc20ExcludedTransactions(String address) async { + try { + final response = await httpClient.get( + Uri.https( + "api.trongrid.io", + "/v1/accounts/$address/transactions/trc20", + { + "only_confirmed": "true", + "limit": "200", + }, + ), + headers: { + 'Content-Type': 'application/json', + 'TRON-PRO-API-KEY': secrets.tronGridApiKey, + }, + ); + final jsonResponse = json.decode(response.body) as Map; + + if (response.statusCode >= 200 && + response.statusCode < 300 && + jsonResponse['status'] != false) { + return (jsonResponse['data'] as List).map((e) { + return TronTRC20TransactionModel.fromJson(e as Map); + }).toList(); + } + + return []; + } catch (e, s) { + log('Error getting trc20 tx: ${e.toString()}\n ${s.toString()}'); + return []; + } + } + + bool connect(Node node) { + try { + final formattedUrl = '${node.isSSL ? 'https' : 'http'}://${node.uriRaw}'; + _provider = TronProvider(TronHTTPProvider(url: formattedUrl)); + + return true; + } catch (e) { + return false; + } + } + + Future getBalance(TronAddress address) async { + try { + final accountDetails = await _provider!.request(TronRequestGetAccount(address: address)); + + return accountDetails?.balance ?? BigInt.zero; + } catch (_) { + return BigInt.zero; + } + } + + Future getFeeLimit( + TransactionRaw rawTransaction, + TronAddress address, + TronAddress receiverAddress, { + int energyUsed = 0, + bool isEstimatedFeeFlow = false, + }) async { + try { + // Get the tron chain parameters. + final chainParams = await _provider!.request(TronRequestGetChainParameters()); + + final bandWidthInSun = chainParams.getTransactionFee!; + log('BandWidth In Sun: $bandWidthInSun'); + + final energyInSun = chainParams.getEnergyFee!; + log('Energy In Sun: $energyInSun'); + + log( + 'Create Account Fee In System Contract for Chain: ${chainParams.getCreateNewAccountFeeInSystemContract!}', + ); + log('Create Account Fee for Chain: ${chainParams.getCreateAccountFee}'); + + final fakeTransaction = Transaction( + rawData: rawTransaction, + signature: [Uint8List(65)], + ); + + // Calculate the total size of the fake transaction, considering the required network overhead. + final transactionSize = fakeTransaction.length + 64; + + // Assign the calculated size to the variable representing the required bandwidth. + int neededBandWidth = transactionSize; + log('Initial Needed Bandwidth: $neededBandWidth'); + + int neededEnergy = energyUsed; + log('Initial Needed Energy: $neededEnergy'); + + // Fetch account resources to assess the available bandwidth and energy + final accountResource = + await _provider!.request(TronRequestGetAccountResource(address: address)); + + neededEnergy -= accountResource.howManyEnergy.toInt(); + log('Account resource energy: ${accountResource.howManyEnergy.toInt()}'); + log('Needed Energy after deducting from account resource energy: $neededEnergy'); + + // Deduct the bandwidth from the account's available bandwidth. + final BigInt accountBandWidth = accountResource.howManyBandwIth; + log('Account resource bandwidth: ${accountResource.howManyBandwIth.toInt()}'); + + if (accountBandWidth >= BigInt.from(neededBandWidth) && !isEstimatedFeeFlow) { + log('Account has more bandwidth than required'); + neededBandWidth = 0; + } + + if (neededEnergy < 0) { + neededEnergy = 0; + } + + final energyBurn = neededEnergy * energyInSun.toInt(); + log('Energy Burn: $energyBurn'); + + final bandWidthBurn = neededBandWidth * bandWidthInSun; + log('Bandwidth Burn: $bandWidthBurn'); + + int totalBurn = energyBurn + bandWidthBurn; + log('Total Burn: $totalBurn'); + + /// If there is a note (memo), calculate the memo fee. + if (rawTransaction.data != null) { + totalBurn += chainParams.getMemoFee!; + } + + // Check if receiver's account is active + final receiverAccountInfo = + await _provider!.request(TronRequestGetAccount(address: receiverAddress)); + + /// Calculate the resources required to create a new account. + if (receiverAccountInfo == null) { + totalBurn += chainParams.getCreateNewAccountFeeInSystemContract!; + + totalBurn += (chainParams.getCreateAccountFee! * bandWidthInSun); + } + + log('Final total burn: $totalBurn'); + + return totalBurn; + } catch (_) { + return 0; + } + } + + Future getEstimatedFee(TronAddress ownerAddress) async { + const constantAmount = '1000'; + // Fetch the latest Tron block + final block = await _provider!.request(TronRequestGetNowBlock()); + + // Create the transfer contract + final contract = TransferContract( + amount: TronHelper.toSun(constantAmount), + ownerAddress: ownerAddress, + toAddress: ownerAddress, + ); + + // Prepare the contract parameter for the transaction. + final parameter = Any(typeUrl: contract.typeURL, value: contract); + + // Create a TransactionContract object with the contract type and parameter. + final transactionContract = + TransactionContract(type: contract.contractType, parameter: parameter); + + // Set the transaction expiration time (maximum 24 hours) + final expireTime = DateTime.now().toUtc().add(const Duration(hours: 24)); + + // Create a raw transaction + TransactionRaw rawTransaction = TransactionRaw( + refBlockBytes: block.blockHeader.rawData.refBlockBytes, + refBlockHash: block.blockHeader.rawData.refBlockHash, + expiration: BigInt.from(expireTime.millisecondsSinceEpoch), + contract: [transactionContract], + timestamp: block.blockHeader.rawData.timestamp, + ); + + final estimatedFee = await getFeeLimit( + rawTransaction, + ownerAddress, + ownerAddress, + isEstimatedFeeFlow: true, + ); + + _nativeTxEstimatedFee = estimatedFee; + + return estimatedFee; + } + + Future getTRCEstimatedFee(TronAddress ownerAddress) async { + String contractAddress = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t'; + String constantAmount = + '0'; // We're using 0 as the base amount here as we get an error when balance is zero i.e for new wallets. + final contract = ContractABI.fromJson(trc20Abi, isTron: true); + + final function = contract.functionFromName("transfer"); + + /// address /// amount + final transferparams = [ + ownerAddress, + TronHelper.toSun(constantAmount), + ]; + + final contractAddr = TronAddress(contractAddress); + + final request = await _provider!.request( + TronRequestTriggerConstantContract( + ownerAddress: ownerAddress, + contractAddress: contractAddr, + data: function.encodeHex(transferparams), + ), + ); + + if (!request.isSuccess) { + log("Tron TRC20 error: ${request.error} \n ${request.respose}"); + } + + final feeLimit = await getFeeLimit( + request.transactionRaw!, + ownerAddress, + ownerAddress, + energyUsed: request.energyUsed ?? 0, + isEstimatedFeeFlow: true, + ); + return feeLimit; + } + + Future signTransaction({ + required TronPrivateKey ownerPrivKey, + required String toAddress, + required String amount, + required CryptoCurrency currency, + required BigInt tronBalance, + required bool sendAll, + }) async { + // Get the owner tron address from the key + final ownerAddress = ownerPrivKey.publicKey().toAddress(); + + // Define the receiving Tron address for the transaction. + final receiverAddress = TronAddress(toAddress); + + bool isNativeTransaction = currency == CryptoCurrency.trx; + + String totalAmount; + TransactionRaw rawTransaction; + if (isNativeTransaction) { + if (sendAll) { + final accountResource = + await _provider!.request(TronRequestGetAccountResource(address: ownerAddress)); + + final availableBandWidth = accountResource.howManyBandwIth.toInt(); + + // 269 is the current middle ground for bandwidth per transaction + if (availableBandWidth >= 269) { + totalAmount = amount; + } else { + final amountInSun = TronHelper.toSun(amount).toInt(); + + // 5000 added here is a buffer since we're working with "estimated" value of the fee. + final result = amountInSun - (_nativeTxEstimatedFee + 5000); + + totalAmount = TronHelper.fromSun(BigInt.from(result)); + } + } else { + totalAmount = amount; + } + rawTransaction = await _signNativeTransaction( + ownerAddress, + receiverAddress, + totalAmount, + tronBalance, + sendAll, + ); + } else { + final tokenAddress = (currency as TronToken).contractAddress; + totalAmount = amount; + rawTransaction = await _signTrcTokenTransaction( + ownerAddress, + receiverAddress, + totalAmount, + tokenAddress, + tronBalance, + ); + } + + final signature = ownerPrivKey.sign(rawTransaction.toBuffer()); + + sendTx() async => await sendTransaction( + rawTransaction: rawTransaction, + signature: signature, + ); + + return PendingTronTransaction( + signedTransaction: signature, + amount: totalAmount, + fee: TronHelper.fromSun(rawTransaction.feeLimit ?? BigInt.zero), + sendTransaction: sendTx, + ); + } + + Future _signNativeTransaction( + TronAddress ownerAddress, + TronAddress receiverAddress, + String amount, + BigInt tronBalance, + bool sendAll, + ) async { + // This is introduce to server as a limit in cases where feeLimit is 0 + // The transaction signing will fail if the feeLimit is explicitly 0. + int defaultFeeLimit = 100000; + + final block = await _provider!.request(TronRequestGetNowBlock()); + // Create the transfer contract + final contract = TransferContract( + amount: TronHelper.toSun(amount), + ownerAddress: ownerAddress, + toAddress: receiverAddress, + ); + + // Prepare the contract parameter for the transaction. + final parameter = Any(typeUrl: contract.typeURL, value: contract); + + // Create a TransactionContract object with the contract type and parameter. + final transactionContract = + TransactionContract(type: contract.contractType, parameter: parameter); + + // Set the transaction expiration time (maximum 24 hours) + final expireTime = DateTime.now().toUtc().add(const Duration(hours: 24)); + + // Create a raw transaction + TransactionRaw rawTransaction = TransactionRaw( + refBlockBytes: block.blockHeader.rawData.refBlockBytes, + refBlockHash: block.blockHeader.rawData.refBlockHash, + expiration: BigInt.from(expireTime.millisecondsSinceEpoch), + contract: [transactionContract], + timestamp: block.blockHeader.rawData.timestamp, + ); + + final feeLimit = await getFeeLimit(rawTransaction, ownerAddress, receiverAddress); + final feeLimitToUse = feeLimit != 0 ? feeLimit : defaultFeeLimit; + final tronBalanceInt = tronBalance.toInt(); + + if (feeLimit > tronBalanceInt) { + throw Exception( + 'You don\'t have enough TRX to cover the transaction fee for this transaction. Kindly top up.', + ); + } + + rawTransaction = rawTransaction.copyWith( + feeLimit: BigInt.from(feeLimitToUse), + ); + + return rawTransaction; + } + + Future _signTrcTokenTransaction( + TronAddress ownerAddress, + TronAddress receiverAddress, + String amount, + String contractAddress, + BigInt tronBalance, + ) async { + final contract = ContractABI.fromJson(trc20Abi, isTron: true); + + final function = contract.functionFromName("transfer"); + + /// address /// amount + final transferparams = [ + receiverAddress, + TronHelper.toSun(amount), + ]; + + final contractAddr = TronAddress(contractAddress); + + final request = await _provider!.request( + TronRequestTriggerConstantContract( + ownerAddress: ownerAddress, + contractAddress: contractAddr, + data: function.encodeHex(transferparams), + ), + ); + + if (!request.isSuccess) { + log("Tron TRC20 error: ${request.error} \n ${request.respose}"); + } + + final feeLimit = await getFeeLimit( + request.transactionRaw!, + ownerAddress, + receiverAddress, + energyUsed: request.energyUsed ?? 0, + ); + + final tronBalanceInt = tronBalance.toInt(); + + if (feeLimit > tronBalanceInt) { + throw Exception( + 'You don\'t have enough TRX to cover the transaction fee for this transaction. Kindly top up.', + ); + } + + final rawTransaction = request.transactionRaw!.copyWith( + feeLimit: BigInt.from(feeLimit), + ); + + return rawTransaction; + } + + Future sendTransaction({ + required TransactionRaw rawTransaction, + required List signature, + }) async { + try { + final transaction = Transaction(rawData: rawTransaction, signature: [signature]); + + final raw = BytesUtils.toHexString(transaction.toBuffer()); + + final txBroadcastResult = await _provider!.request(TronRequestBroadcastHex(transaction: raw)); + + if (txBroadcastResult.isSuccess) { + return txBroadcastResult.txId!; + } else { + throw Exception(txBroadcastResult.error); + } + } catch (e) { + log('Send block Exception: ${e.toString()}'); + throw Exception(e); + } + } + + Future fetchTronTokenBalances(String userAddress, String contractAddress) async { + try { + final ownerAddress = TronAddress(userAddress); + + final tokenAddress = TronAddress(contractAddress); + + final contract = ContractABI.fromJson(trc20Abi, isTron: true); + + final function = contract.functionFromName("balanceOf"); + + final request = await _provider!.request( + TronRequestTriggerConstantContract.fromMethod( + ownerAddress: ownerAddress, + contractAddress: tokenAddress, + function: function, + params: [ownerAddress], + ), + ); + + final outputResult = request.outputResult?.first ?? BigInt.zero; + + return TronBalance(outputResult); + } catch (_) { + return TronBalance(BigInt.zero); + } + } + + Future getTronToken(String contractAddress, String userAddress) async { + try { + final tokenAddress = TronAddress(contractAddress); + + final ownerAddress = TronAddress(userAddress); + + final contract = ContractABI.fromJson(trc20Abi, isTron: true); + + final name = + (await getTokenDetail(contract, "name", ownerAddress, tokenAddress) as String?) ?? ''; + + final symbol = + (await getTokenDetail(contract, "symbol", ownerAddress, tokenAddress) as String?) ?? ''; + + final decimal = + (await getTokenDetail(contract, "decimals", ownerAddress, tokenAddress) as BigInt?) ?? + BigInt.zero; + + return TronToken( + name: name, + symbol: symbol, + contractAddress: contractAddress, + decimal: decimal.toInt(), + ); + } catch (e) { + return null; + } + } + + Future getTokenDetail( + ContractABI contract, + String functionName, + TronAddress ownerAddress, + TronAddress tokenAddress, + ) async { + final function = contract.functionFromName(functionName); + + try { + final request = await _provider!.request( + TronRequestTriggerConstantContract.fromMethod( + ownerAddress: ownerAddress, + contractAddress: tokenAddress, + function: function, + params: [], + ), + ); + + final outputResult = request.outputResult?.first; + + return outputResult; + } catch (_) { + log('Erorr fetching detail: ${_.toString()}'); + + return null; + } + } +} diff --git a/cw_tron/lib/tron_exception.dart b/cw_tron/lib/tron_exception.dart new file mode 100644 index 000000000..13b98c024 --- /dev/null +++ b/cw_tron/lib/tron_exception.dart @@ -0,0 +1,16 @@ +import 'package:cw_core/crypto_currency.dart'; + +class TronMnemonicIsIncorrectException implements Exception { + @override + String toString() => + 'Tron mnemonic has incorrect format. Mnemonic should contain 12 or 24 words separated by space.'; +} +class TronTransactionCreationException implements Exception { + final String exceptionMessage; + + TronTransactionCreationException(CryptoCurrency currency) + : exceptionMessage = 'Wrong balance. Not enough ${currency.title} on your balance.'; + + @override + String toString() => exceptionMessage; +} \ No newline at end of file diff --git a/cw_tron/lib/tron_http_provider.dart b/cw_tron/lib/tron_http_provider.dart new file mode 100644 index 000000000..193a3dbdd --- /dev/null +++ b/cw_tron/lib/tron_http_provider.dart @@ -0,0 +1,41 @@ +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:on_chain/tron/tron.dart'; +import '.secrets.g.dart' as secrets; + +class TronHTTPProvider implements TronServiceProvider { + TronHTTPProvider( + {required this.url, + http.Client? client, + this.defaultRequestTimeout = const Duration(seconds: 30)}) + : client = client ?? http.Client(); + @override + final String url; + final http.Client client; + final Duration defaultRequestTimeout; + + @override + Future> get(TronRequestDetails params, [Duration? timeout]) async { + final response = await client.get(Uri.parse(params.url(url)), headers: { + 'Content-Type': 'application/json', + 'TRON-PRO-API-KEY': secrets.tronGridApiKey, + }).timeout(timeout ?? defaultRequestTimeout); + final data = json.decode(response.body) as Map; + return data; + } + + @override + Future> post(TronRequestDetails params, [Duration? timeout]) async { + final response = await client + .post(Uri.parse(params.url(url)), + headers: { + 'Content-Type': 'application/json', + 'TRON-PRO-API-KEY': secrets.tronGridApiKey, + }, + body: params.toRequestBody()) + .timeout(timeout ?? defaultRequestTimeout); + final data = json.decode(response.body) as Map; + return data; + } +} diff --git a/cw_tron/lib/tron_token.dart b/cw_tron/lib/tron_token.dart new file mode 100644 index 000000000..8c45ab486 --- /dev/null +++ b/cw_tron/lib/tron_token.dart @@ -0,0 +1,80 @@ +// ignore_for_file: annotate_overrides, overridden_fields + +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/hive_type_ids.dart'; +import 'package:hive/hive.dart'; + +part 'tron_token.g.dart'; + +@HiveType(typeId: TronToken.typeId) +class TronToken extends CryptoCurrency with HiveObjectMixin { + @HiveField(0) + final String name; + + @HiveField(1) + final String symbol; + + @HiveField(2) + final String contractAddress; + + @HiveField(3) + final int decimal; + + @HiveField(4, defaultValue: true) + bool _enabled; + + @HiveField(5) + final String? iconPath; + + @HiveField(6) + final String? tag; + + bool get enabled => _enabled; + + set enabled(bool value) => _enabled = value; + + TronToken({ + required this.name, + required this.symbol, + required this.contractAddress, + required this.decimal, + bool enabled = true, + this.iconPath, + this.tag = 'TRX', + }) : _enabled = enabled, + super( + name: symbol.toLowerCase(), + title: symbol.toUpperCase(), + fullName: name, + tag: tag, + iconPath: iconPath, + decimals: decimal); + + TronToken.copyWith(TronToken other, String? icon, String? tag) + : name = other.name, + symbol = other.symbol, + contractAddress = other.contractAddress, + decimal = other.decimal, + _enabled = other.enabled, + tag = tag ?? other.tag, + iconPath = icon ?? other.iconPath, + super( + name: other.name, + title: other.symbol.toUpperCase(), + fullName: other.name, + tag: tag ?? other.tag, + iconPath: icon ?? other.iconPath, + decimals: other.decimal, + ); + + static const typeId = TRON_TOKEN_TYPE_ID; + static const boxName = 'TronTokens'; + + @override + bool operator ==(other) => + (other is TronToken && other.contractAddress == contractAddress) || + (other is CryptoCurrency && other.title == title); + + @override + int get hashCode => contractAddress.hashCode; +} diff --git a/cw_tron/lib/tron_transaction_credentials.dart b/cw_tron/lib/tron_transaction_credentials.dart new file mode 100644 index 000000000..e68d5525b --- /dev/null +++ b/cw_tron/lib/tron_transaction_credentials.dart @@ -0,0 +1,12 @@ +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/output_info.dart'; + +class TronTransactionCredentials { + TronTransactionCredentials( + this.outputs, { + required this.currency, + }); + + final List outputs; + final CryptoCurrency currency; +} diff --git a/cw_tron/lib/tron_transaction_history.dart b/cw_tron/lib/tron_transaction_history.dart new file mode 100644 index 000000000..7d7274226 --- /dev/null +++ b/cw_tron/lib/tron_transaction_history.dart @@ -0,0 +1,80 @@ +import 'dart:convert'; +import 'dart:core'; +import 'dart:developer'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_evm/file.dart'; +import 'package:cw_tron/tron_transaction_info.dart'; +import 'package:mobx/mobx.dart'; +import 'package:cw_core/transaction_history.dart'; + +part 'tron_transaction_history.g.dart'; + +class TronTransactionHistory = TronTransactionHistoryBase with _$TronTransactionHistory; + +abstract class TronTransactionHistoryBase extends TransactionHistoryBase + with Store { + TronTransactionHistoryBase({required this.walletInfo, required String password}) + : _password = password { + transactions = ObservableMap(); + } + + String _password; + + final WalletInfo walletInfo; + + Future init() async => await _load(); + + @override + Future save() async { + String transactionsHistoryFileNameForWallet = 'tron_transactions.json'; + try { + final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type); + String path = '$dirPath/$transactionsHistoryFileNameForWallet'; + final transactionMaps = transactions.map((key, value) => MapEntry(key, value.toJson())); + final data = json.encode({'transactions': transactionMaps}); + await writeData(path: path, password: _password, data: data); + } catch (e, s) { + log('Error while saving ${walletInfo.type.name} transaction history: ${e.toString()}'); + log(s.toString()); + } + } + + @override + void addOne(TronTransactionInfo transaction) => transactions[transaction.id] = transaction; + + @override + void addMany(Map transactions) => + this.transactions.addAll(transactions); + + Future> _read() async { + String transactionsHistoryFileNameForWallet = 'tron_transactions.json'; + final dirPath = await pathForWalletDir(name: walletInfo.name, type: walletInfo.type); + String path = '$dirPath/$transactionsHistoryFileNameForWallet'; + final content = await read(path: path, password: _password); + if (content.isEmpty) { + return {}; + } + return json.decode(content) as Map; + } + + Future _load() async { + try { + final content = await _read(); + final txs = content['transactions'] as Map? ?? {}; + + for (var entry in txs.entries) { + final val = entry.value; + + if (val is Map) { + final tx = TronTransactionInfo.fromJson(val); + _update(tx); + } + } + } catch (e) { + log(e.toString()); + } + } + + void _update(TronTransactionInfo transaction) => transactions[transaction.id] = transaction; +} diff --git a/cw_tron/lib/tron_transaction_info.dart b/cw_tron/lib/tron_transaction_info.dart new file mode 100644 index 000000000..28c704d20 --- /dev/null +++ b/cw_tron/lib/tron_transaction_info.dart @@ -0,0 +1,93 @@ +import 'package:cw_core/format_amount.dart'; +import 'package:cw_core/transaction_direction.dart'; +import 'package:cw_core/transaction_info.dart'; +import 'package:on_chain/on_chain.dart' as onchain; +import 'package:on_chain/tron/tron.dart'; + +class TronTransactionInfo extends TransactionInfo { + TronTransactionInfo({ + required this.id, + required this.tronAmount, + required this.txFee, + required this.direction, + required this.blockTime, + required this.to, + required this.from, + required this.isPending, + this.tokenSymbol = 'TRX', + }) : amount = tronAmount.toInt(); + + final String id; + final String? to; + final String? from; + final int amount; + final BigInt tronAmount; + final String tokenSymbol; + final DateTime blockTime; + final bool isPending; + final int? txFee; + final TransactionDirection direction; + + factory TronTransactionInfo.fromJson(Map data) { + return TronTransactionInfo( + id: data['id'] as String, + tronAmount: BigInt.parse(data['tronAmount']), + txFee: data['txFee'], + direction: parseTransactionDirectionFromInt(data['direction'] as int), + blockTime: DateTime.fromMillisecondsSinceEpoch(data['blockTime'] as int), + tokenSymbol: data['tokenSymbol'] as String, + to: data['to'], + from: data['from'], + isPending: data['isPending'], + ); + } + + Map toJson() => { + 'id': id, + 'tronAmount': tronAmount.toString(), + 'txFee': txFee, + 'direction': direction.index, + 'blockTime': blockTime.millisecondsSinceEpoch, + 'tokenSymbol': tokenSymbol, + 'to': to, + 'from': from, + 'isPending': isPending, + }; + + @override + DateTime get date => blockTime; + + String? _fiatAmount; + + @override + String amountFormatted() { + String formattedAmount = _rawAmountAsString(tronAmount); + + return '$formattedAmount $tokenSymbol'; + } + + @override + String fiatAmount() => _fiatAmount ?? ''; + + @override + void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount); + + @override + String feeFormatted() { + final formattedFee = onchain.TronHelper.fromSun(BigInt.from(txFee ?? 0)); + + return '$formattedFee TRX'; + } + + String _rawAmountAsString(BigInt amount) { + String formattedAmount = TronHelper.fromSun(amount); + + if (formattedAmount.length >= 8) { + formattedAmount = formattedAmount.substring(0, 8); + } + + return formattedAmount; + } + + String rawTronAmount() => _rawAmountAsString(tronAmount); +} diff --git a/cw_tron/lib/tron_transaction_model.dart b/cw_tron/lib/tron_transaction_model.dart new file mode 100644 index 000000000..1748adc53 --- /dev/null +++ b/cw_tron/lib/tron_transaction_model.dart @@ -0,0 +1,205 @@ +import 'package:blockchain_utils/hex/hex.dart'; +import 'package:on_chain/on_chain.dart'; + +class TronTRC20TransactionModel extends TronTransactionModel { + String? transactionId; + + String? tokenSymbol; + + int? timestamp; + + @override + String? from; + + @override + String? to; + + String? value; + + @override + String get hash => transactionId!; + + @override + DateTime get date => DateTime.fromMillisecondsSinceEpoch(timestamp ?? 0); + + @override + BigInt? get amount => BigInt.parse(value ?? '0'); + + @override + int? get fee => 0; + + TronTRC20TransactionModel({ + this.transactionId, + this.tokenSymbol, + this.timestamp, + this.from, + this.to, + this.value, + }); + + TronTRC20TransactionModel.fromJson(Map json) { + transactionId = json['transaction_id']; + tokenSymbol = json['token_info'] != null ? json['token_info']['symbol'] : null; + timestamp = json['block_timestamp']; + from = json['from']; + to = json['to']; + value = json['value']; + } +} + +class TronTransactionModel { + List? ret; + String? txID; + int? blockTimestamp; + List? contracts; + + /// Getters to extract out the needed/useful information directly from the model params + /// Without having to go through extra steps in the methods that use this model. + bool get isError { + if (ret?.first.contractRet == null) return true; + + return ret?.first.contractRet != "SUCCESS"; + } + + String get hash => txID!; + + DateTime get date => DateTime.fromMillisecondsSinceEpoch(blockTimestamp ?? 0); + + String? get from => contracts?.first.parameter?.value?.ownerAddress; + + String? get to => contracts?.first.parameter?.value?.receiverAddress; + + BigInt? get amount => contracts?.first.parameter?.value?.txAmount; + + int? get fee => ret?.first.fee; + + String? get contractAddress => contracts?.first.parameter?.value?.contractAddress; + + TronTransactionModel({ + this.ret, + this.txID, + this.blockTimestamp, + this.contracts, + }); + + TronTransactionModel.fromJson(Map json) { + if (json['ret'] != null) { + ret = []; + json['ret'].forEach((v) { + ret!.add(Ret.fromJson(v)); + }); + } + txID = json['txID']; + blockTimestamp = json['block_timestamp']; + contracts = json['raw_data'] != null + ? (json['raw_data']['contract'] as List) + .map((e) => Contract.fromJson(e as Map)) + .toList() + : null; + } +} + +class Ret { + String? contractRet; + int? fee; + + Ret({this.contractRet, this.fee}); + + Ret.fromJson(Map json) { + contractRet = json['contractRet']; + fee = json['fee']; + } +} + +class Contract { + Parameter? parameter; + String? type; + + Contract({this.parameter, this.type}); + + Contract.fromJson(Map json) { + parameter = json['parameter'] != null ? Parameter.fromJson(json['parameter']) : null; + type = json['type']; + } +} + +class Parameter { + Value? value; + String? typeUrl; + + Parameter({this.value, this.typeUrl}); + + Parameter.fromJson(Map json) { + value = json['value'] != null ? Value.fromJson(json['value']) : null; + typeUrl = json['type_url']; + } +} + +class Value { + String? data; + String? ownerAddress; + String? contractAddress; + int? amount; + String? toAddress; + String? assetName; + + //Getters to extract address for tron transactions + /// If the contract address is null, it returns the toAddress + /// If it's not null, it decodes the data field and gets the receiver address. + String? get receiverAddress { + if (contractAddress == null) return toAddress; + + if (data == null) return null; + + return _decodeAddressFromEncodedDataField(data!); + } + + //Getters to extract amount for tron transactions + /// If the contract address is null, it returns the amount + /// If it's not null, it decodes the data field and gets the tx amount. + BigInt? get txAmount { + if (contractAddress == null) return BigInt.from(amount ?? 0); + + if (data == null) return null; + + return _decodeAmountInvolvedFromEncodedDataField(data!); + } + + Value( + {this.data, + this.ownerAddress, + this.contractAddress, + this.amount, + this.toAddress, + this.assetName}); + + Value.fromJson(Map json) { + data = json['data']; + ownerAddress = json['owner_address']; + contractAddress = json['contract_address']; + amount = json['amount']; + toAddress = json['to_address']; + assetName = json['asset_name']; + } + + /// To get the address from the encoded data field + String _decodeAddressFromEncodedDataField(String output) { + // To get the receiver address from the encoded params + output = output.replaceFirst('0x', '').substring(8); + final abiCoder = ABICoder.fromType('address'); + final decoded = abiCoder.decode(AbiParameter.bytes, hex.decode(output)); + final tronAddress = TronAddress.fromEthAddress((decoded.result as ETHAddress).toBytes()); + + return tronAddress.toString(); + } + + /// To get the amount from the encoded data field + BigInt _decodeAmountInvolvedFromEncodedDataField(String output) { + output = output.replaceFirst('0x', '').substring(72); + final amountAbiCoder = ABICoder.fromType('uint256'); + final decodedA = amountAbiCoder.decode(AbiParameter.uint256, hex.decode(output)); + final amount = decodedA.result as BigInt; + + return amount; + } +} diff --git a/cw_tron/lib/tron_wallet.dart b/cw_tron/lib/tron_wallet.dart new file mode 100644 index 000000000..a798f343a --- /dev/null +++ b/cw_tron/lib/tron_wallet.dart @@ -0,0 +1,560 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:bip39/bip39.dart' as bip39; +import 'package:blockchain_utils/blockchain_utils.dart'; +import 'package:cw_core/cake_hive.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/node.dart'; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/pending_transaction.dart'; +import 'package:cw_core/sync_status.dart'; +import 'package:cw_core/transaction_direction.dart'; +import 'package:cw_core/transaction_priority.dart'; +import 'package:cw_core/wallet_addresses.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:cw_tron/default_tron_tokens.dart'; +import 'package:cw_tron/file.dart'; +import 'package:cw_tron/tron_abi.dart'; +import 'package:cw_tron/tron_balance.dart'; +import 'package:cw_tron/tron_client.dart'; +import 'package:cw_tron/tron_exception.dart'; +import 'package:cw_tron/tron_token.dart'; +import 'package:cw_tron/tron_transaction_credentials.dart'; +import 'package:cw_tron/tron_transaction_history.dart'; +import 'package:cw_tron/tron_transaction_info.dart'; +import 'package:cw_tron/tron_wallet_addresses.dart'; +import 'package:hive/hive.dart'; +import 'package:mobx/mobx.dart'; +import 'package:on_chain/on_chain.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +part 'tron_wallet.g.dart'; + +class TronWallet = TronWalletBase with _$TronWallet; + +abstract class TronWalletBase + extends WalletBase with Store { + TronWalletBase({ + required WalletInfo walletInfo, + String? mnemonic, + String? privateKey, + required String password, + TronBalance? initialBalance, + }) : syncStatus = const NotConnectedSyncStatus(), + _password = password, + _mnemonic = mnemonic, + _hexPrivateKey = privateKey, + _client = TronClient(), + walletAddresses = TronWalletAddresses(walletInfo), + balance = ObservableMap.of( + {CryptoCurrency.trx: initialBalance ?? TronBalance(BigInt.zero)}, + ), + super(walletInfo) { + this.walletInfo = walletInfo; + transactionHistory = TronTransactionHistory(walletInfo: walletInfo, password: password); + + if (!CakeHive.isAdapterRegistered(TronToken.typeId)) { + CakeHive.registerAdapter(TronTokenAdapter()); + } + + sharedPrefs.complete(SharedPreferences.getInstance()); + } + + final String? _mnemonic; + final String? _hexPrivateKey; + final String _password; + + late final Box tronTokensBox; + + late final TronPrivateKey _tronPrivateKey; + + late final TronPublicKey _tronPublicKey; + + TronPublicKey get tronPublicKey => _tronPublicKey; + + TronPrivateKey get tronPrivateKey => _tronPrivateKey; + + late String _tronAddress; + + late TronClient _client; + + Timer? _transactionsUpdateTimer; + + @override + WalletAddresses walletAddresses; + + @observable + String? nativeTxEstimatedFee; + + @observable + String? trc20EstimatedFee; + + @override + @observable + SyncStatus syncStatus; + + @override + @observable + late ObservableMap balance; + + Completer sharedPrefs = Completer(); + + Future init() async { + await initTronTokensBox(); + + await walletAddresses.init(); + await transactionHistory.init(); + _tronPrivateKey = await getPrivateKey( + mnemonic: _mnemonic, + privateKey: _hexPrivateKey, + password: _password, + ); + + _tronPublicKey = _tronPrivateKey.publicKey(); + + _tronAddress = _tronPublicKey.toAddress().toString(); + + walletAddresses.address = _tronAddress; + + await save(); + } + + static Future open({ + required String name, + required String password, + required WalletInfo walletInfo, + }) async { + final path = await pathForWallet(name: name, type: walletInfo.type); + final jsonSource = await read(path: path, password: password); + final data = json.decode(jsonSource) as Map; + final mnemonic = data['mnemonic'] as String?; + final privateKey = data['private_key'] as String?; + final balance = TronBalance.fromJSON(data['balance'] as String) ?? TronBalance(BigInt.zero); + + return TronWallet( + walletInfo: walletInfo, + password: password, + mnemonic: mnemonic, + privateKey: privateKey, + initialBalance: balance, + ); + } + + void addInitialTokens() { + final initialTronTokens = DefaultTronTokens().initialTronTokens; + + for (var token in initialTronTokens) { + tronTokensBox.put(token.contractAddress, token); + } + } + + Future initTronTokensBox() async { + final boxName = "${walletInfo.name.replaceAll(" ", "_")}_${TronToken.boxName}"; + + tronTokensBox = await CakeHive.openBox(boxName); + } + + String idFor(String name, WalletType type) => '${walletTypeToString(type).toLowerCase()}_$name'; + + Future getPrivateKey({ + String? mnemonic, + String? privateKey, + required String password, + }) async { + assert(mnemonic != null || privateKey != null); + + if (privateKey != null) { + return TronPrivateKey(privateKey); + } + + final seed = bip39.mnemonicToSeed(mnemonic!); + + // Derive a TRON private key from the seed + final bip44 = Bip44.fromSeed(seed, Bip44Coins.tron); + + final childKey = bip44.deriveDefaultPath; + + return TronPrivateKey.fromBytes(childKey.privateKey.raw); + } + + @override + int calculateEstimatedFee(TransactionPriority priority, int? amount) => 0; + + @override + Future changePassword(String password) { + throw UnimplementedError("changePassword"); + } + + @override + void close() { + _transactionsUpdateTimer?.cancel(); + } + + @action + @override + Future connectToNode({required Node node}) async { + try { + syncStatus = ConnectingSyncStatus(); + + final isConnected = _client.connect(node); + + if (!isConnected) { + throw Exception("${walletInfo.type.name.toUpperCase()} Node connection failed"); + } + + _getEstimatedFees(); + _setTransactionUpdateTimer(); + + syncStatus = ConnectedSyncStatus(); + } catch (e) { + syncStatus = FailedSyncStatus(); + } + } + + Future _getEstimatedFees() async { + final nativeFee = await _getNativeTxFee(); + nativeTxEstimatedFee = TronHelper.fromSun(BigInt.from(nativeFee)); + + final trc20Fee = await _getTrc20TxFee(); + trc20EstimatedFee = TronHelper.fromSun(BigInt.from(trc20Fee)); + + log('Native Estimated Fee: $nativeTxEstimatedFee'); + log('TRC20 Estimated Fee: $trc20EstimatedFee'); + } + + Future _getNativeTxFee() async { + try { + final fee = await _client.getEstimatedFee(_tronPublicKey.toAddress()); + return fee; + } catch (e) { + log(e.toString()); + return 0; + } + } + + Future _getTrc20TxFee() async { + try { + final trc20fee = await _client.getTRCEstimatedFee(_tronPublicKey.toAddress()); + return trc20fee; + } catch (e) { + log(e.toString()); + return 0; + } + } + + @action + @override + Future startSync() async { + try { + syncStatus = AttemptingSyncStatus(); + await _updateBalance(); + await fetchTransactions(); + fetchTrc20ExcludedTransactions(); + + syncStatus = SyncedSyncStatus(); + } catch (e) { + syncStatus = FailedSyncStatus(); + } + } + + @override + Future createTransaction(Object credentials) async { + final tronCredentials = credentials as TronTransactionCredentials; + + final outputs = tronCredentials.outputs; + + final hasMultiDestination = outputs.length > 1; + + final CryptoCurrency transactionCurrency = + balance.keys.firstWhere((element) => element.title == tronCredentials.currency.title); + + final walletBalanceForCurrency = balance[transactionCurrency]!.balance; + + BigInt totalAmount = BigInt.zero; + bool shouldSendAll = false; + if (hasMultiDestination) { + if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) { + throw TronTransactionCreationException(transactionCurrency); + } + + final totalAmountFromCredentials = + outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0)); + + totalAmount = BigInt.from(totalAmountFromCredentials); + + if (walletBalanceForCurrency < totalAmount) { + throw TronTransactionCreationException(transactionCurrency); + } + } else { + final output = outputs.first; + + shouldSendAll = output.sendAll; + + if (shouldSendAll) { + totalAmount = walletBalanceForCurrency; + } else { + final totalOriginalAmount = double.parse(output.cryptoAmount ?? '0.0'); + totalAmount = TronHelper.toSun(totalOriginalAmount.toString()); + } + + if (walletBalanceForCurrency < totalAmount || totalAmount < BigInt.zero) { + throw TronTransactionCreationException(transactionCurrency); + } + } + + final tronBalance = balance[CryptoCurrency.trx]?.balance ?? BigInt.zero; + + final pendingTransaction = await _client.signTransaction( + ownerPrivKey: _tronPrivateKey, + toAddress: tronCredentials.outputs.first.isParsedAddress + ? tronCredentials.outputs.first.extractedAddress! + : tronCredentials.outputs.first.address, + amount: TronHelper.fromSun(totalAmount), + currency: transactionCurrency, + tronBalance: tronBalance, + sendAll: shouldSendAll, + ); + + return pendingTransaction; + } + + @override + Future> fetchTransactions() async { + final address = _tronAddress; + + final transactions = await _client.fetchTransactions(address); + + final Map result = {}; + + final contract = ContractABI.fromJson(trc20Abi, isTron: true); + + final ownerAddress = TronAddress(_tronAddress); + + for (var transactionModel in transactions) { + if (transactionModel.isError) { + continue; + } + + String? tokenSymbol; + if (transactionModel.contractAddress != null) { + final tokenAddress = TronAddress(transactionModel.contractAddress!); + + tokenSymbol = (await _client.getTokenDetail( + contract, + "symbol", + ownerAddress, + tokenAddress, + ) as String?) ?? + ''; + } + + result[transactionModel.hash] = TronTransactionInfo( + id: transactionModel.hash, + tronAmount: transactionModel.amount ?? BigInt.zero, + direction: TronAddress(transactionModel.from!, visible: false).toAddress() == address + ? TransactionDirection.outgoing + : TransactionDirection.incoming, + blockTime: transactionModel.date, + txFee: transactionModel.fee, + tokenSymbol: tokenSymbol ?? "TRX", + to: transactionModel.to, + from: transactionModel.from, + isPending: false, + ); + } + + transactionHistory.addMany(result); + + await transactionHistory.save(); + + return transactionHistory.transactions; + } + + Future fetchTrc20ExcludedTransactions() async { + final address = _tronAddress; + + final transactions = await _client.fetchTrc20ExcludedTransactions(address); + + final Map result = {}; + + for (var transactionModel in transactions) { + if (transactionHistory.transactions.containsKey(transactionModel.hash)) { + continue; + } + + result[transactionModel.hash] = TronTransactionInfo( + id: transactionModel.hash, + tronAmount: transactionModel.amount ?? BigInt.zero, + direction: transactionModel.from! == address + ? TransactionDirection.outgoing + : TransactionDirection.incoming, + blockTime: transactionModel.date, + txFee: transactionModel.fee, + tokenSymbol: transactionModel.tokenSymbol ?? "TRX", + to: transactionModel.to, + from: transactionModel.from, + isPending: false, + ); + } + + transactionHistory.addMany(result); + + await transactionHistory.save(); + } + + @override + Object get keys => throw UnimplementedError("keys"); + + @override + Future rescan({required int height}) { + throw UnimplementedError("rescan"); + } + + @override + Future save() async { + await walletAddresses.updateAddressesInBox(); + final path = await makePath(); + await write(path: path, password: _password, data: toJSON()); + await transactionHistory.save(); + } + + @override + String? get seed => _mnemonic; + + @override + String get privateKey => _tronPrivateKey.toHex(); + + Future makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); + + String toJSON() => json.encode({ + 'mnemonic': _mnemonic, + 'private_key': privateKey, + 'balance': balance[currency]!.toJSON(), + }); + + Future _updateBalance() async { + balance[currency] = await _fetchTronBalance(); + + await _fetchTronTokenBalances(); + await save(); + } + + Future _fetchTronBalance() async { + final balance = await _client.getBalance(_tronPublicKey.toAddress()); + return TronBalance(balance); + } + + Future _fetchTronTokenBalances() async { + for (var token in tronTokensBox.values) { + try { + if (token.enabled) { + balance[token] = await _client.fetchTronTokenBalances( + _tronAddress, + token.contractAddress, + ); + } else { + balance.remove(token); + } + } catch (_) {} + } + } + + Future? updateBalance() async => await _updateBalance(); + + List get tronTokenCurrencies => tronTokensBox.values.toList(); + + Future addTronToken(TronToken token) async { + String? iconPath; + try { + iconPath = CryptoCurrency.all + .firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase()) + .iconPath; + } catch (_) {} + + final newToken = TronToken( + name: token.name, + symbol: token.symbol, + contractAddress: token.contractAddress, + decimal: token.decimal, + enabled: token.enabled, + tag: token.tag ?? "TRX", + iconPath: iconPath, + ); + + await tronTokensBox.put(newToken.contractAddress, newToken); + + if (newToken.enabled) { + balance[newToken] = await _client.fetchTronTokenBalances( + _tronAddress, + newToken.contractAddress, + ); + } else { + balance.remove(newToken); + } + } + + Future deleteTronToken(TronToken token) async { + await token.delete(); + + balance.remove(token); + await _removeTokenTransactionsInHistory(token); + _updateBalance(); + } + + Future _removeTokenTransactionsInHistory(TronToken token) async { + transactionHistory.transactions.removeWhere((key, value) => value.tokenSymbol == token.title); + await transactionHistory.save(); + } + + Future getTronToken(String contractAddress) async => + await _client.getTronToken(contractAddress, _tronAddress); + + @override + Future renameWalletFiles(String newWalletName) async { + String transactionHistoryFileNameForWallet = 'tron_transactions.json'; + + final currentWalletPath = await pathForWallet(name: walletInfo.name, type: type); + final currentWalletFile = File(currentWalletPath); + + final currentDirPath = await pathForWalletDir(name: walletInfo.name, type: type); + final currentTransactionsFile = File('$currentDirPath/$transactionHistoryFileNameForWallet'); + + // Copies current wallet files into new wallet name's dir and files + if (currentWalletFile.existsSync()) { + final newWalletPath = await pathForWallet(name: newWalletName, type: type); + await currentWalletFile.copy(newWalletPath); + } + if (currentTransactionsFile.existsSync()) { + final newDirPath = await pathForWalletDir(name: newWalletName, type: type); + await currentTransactionsFile.copy('$newDirPath/$transactionHistoryFileNameForWallet'); + } + + // Delete old name's dir and files + await Directory(currentDirPath).delete(recursive: true); + } + + void _setTransactionUpdateTimer() { + if (_transactionsUpdateTimer?.isActive ?? false) { + _transactionsUpdateTimer!.cancel(); + } + + _transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 20), (_) async { + _updateBalance(); + await fetchTransactions(); + fetchTrc20ExcludedTransactions(); + }); + } + + @override + String signMessage(String message, {String? address}) => + _tronPrivateKey.signPersonalMessage(ascii.encode(message)); + + String getTronBase58AddressFromHex(String hexAddress) { + return TronAddress(hexAddress).toAddress(); + } +} diff --git a/cw_tron/lib/tron_wallet_addresses.dart b/cw_tron/lib/tron_wallet_addresses.dart new file mode 100644 index 000000000..35939de26 --- /dev/null +++ b/cw_tron/lib/tron_wallet_addresses.dart @@ -0,0 +1,36 @@ +import 'dart:developer'; + +import 'package:cw_core/wallet_addresses.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:mobx/mobx.dart'; + +part 'tron_wallet_addresses.g.dart'; + +class TronWalletAddresses = TronWalletAddressesBase with _$TronWalletAddresses; + +abstract class TronWalletAddressesBase extends WalletAddresses with Store { + TronWalletAddressesBase(WalletInfo walletInfo) + : address = '', + super(walletInfo); + + @override + @observable + String address; + + @override + Future init() async { + address = walletInfo.address; + await updateAddressesInBox(); + } + + @override + Future updateAddressesInBox() async { + try { + addressesMap.clear(); + addressesMap[address] = ''; + await saveAddressesInBox(); + } catch (e) { + log(e.toString()); + } + } +} diff --git a/cw_tron/lib/tron_wallet_creation_credentials.dart b/cw_tron/lib/tron_wallet_creation_credentials.dart new file mode 100644 index 000000000..dc4f389aa --- /dev/null +++ b/cw_tron/lib/tron_wallet_creation_credentials.dart @@ -0,0 +1,29 @@ +import 'package:cw_core/wallet_credentials.dart'; +import 'package:cw_core/wallet_info.dart'; + +class TronNewWalletCredentials extends WalletCredentials { + TronNewWalletCredentials({required String name, WalletInfo? walletInfo}) + : super(name: name, walletInfo: walletInfo); +} + +class TronRestoreWalletFromSeedCredentials extends WalletCredentials { + TronRestoreWalletFromSeedCredentials( + {required String name, + required String password, + required this.mnemonic, + WalletInfo? walletInfo}) + : super(name: name, password: password, walletInfo: walletInfo); + + final String mnemonic; +} + +class TronRestoreWalletFromPrivateKey extends WalletCredentials { + TronRestoreWalletFromPrivateKey( + {required String name, + required String password, + required this.privateKey, + WalletInfo? walletInfo}) + : super(name: name, password: password, walletInfo: walletInfo); + + final String privateKey; +} diff --git a/cw_tron/lib/tron_wallet_service.dart b/cw_tron/lib/tron_wallet_service.dart new file mode 100644 index 000000000..f4e98ee5d --- /dev/null +++ b/cw_tron/lib/tron_wallet_service.dart @@ -0,0 +1,148 @@ +import 'dart:io'; + +import 'package:bip39/bip39.dart' as bip39; +import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/wallet_base.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_tron/tron_client.dart'; +import 'package:cw_tron/tron_exception.dart'; +import 'package:cw_tron/tron_wallet.dart'; +import 'package:cw_tron/tron_wallet_creation_credentials.dart'; +import 'package:hive/hive.dart'; +import 'package:collection/collection.dart'; + +class TronWalletService extends WalletService { + TronWalletService(this.walletInfoSource, {required this.client}); + + late TronClient client; + + final Box walletInfoSource; + + @override + WalletType getType() => WalletType.tron; + + @override + Future create( + TronNewWalletCredentials credentials, { + bool? isTestnet, + }) async { + final strength = credentials.seedPhraseLength == 24 ? 256 : 128; + + final mnemonic = bip39.generateMnemonic(strength: strength); + + final wallet = TronWallet( + walletInfo: credentials.walletInfo!, + mnemonic: mnemonic, + password: credentials.password!, + ); + + await wallet.init(); + wallet.addInitialTokens(); + await wallet.save(); + + return wallet; + } + + @override + Future openWallet(String name, String password) async { + final walletInfo = + walletInfoSource.values.firstWhere((info) => info.id == WalletBase.idFor(name, getType())); + + try { + final wallet = await TronWalletBase.open( + name: name, + password: password, + walletInfo: walletInfo, + ); + + await wallet.init(); + await wallet.save(); + saveBackup(name); + return wallet; + } catch (_) { + await restoreWalletFilesFromBackup(name); + + final wallet = await TronWalletBase.open( + name: name, + password: password, + walletInfo: walletInfo, + ); + + await wallet.init(); + await wallet.save(); + return wallet; + } + } + + @override + Future restoreFromKeys( + TronRestoreWalletFromPrivateKey credentials, { + bool? isTestnet, + }) async { + final wallet = TronWallet( + password: credentials.password!, + privateKey: credentials.privateKey, + walletInfo: credentials.walletInfo!, + ); + + await wallet.init(); + wallet.addInitialTokens(); + await wallet.save(); + + return wallet; + } + + @override + Future restoreFromSeed( + TronRestoreWalletFromSeedCredentials credentials, { + bool? isTestnet, + }) async { + if (!bip39.validateMnemonic(credentials.mnemonic)) { + throw TronMnemonicIsIncorrectException(); + } + + final wallet = TronWallet( + password: credentials.password!, + mnemonic: credentials.mnemonic, + walletInfo: credentials.walletInfo!, + ); + + await wallet.init(); + wallet.addInitialTokens(); + await wallet.save(); + + return wallet; + } + + @override + Future rename(String currentName, String password, String newName) async { + final currentWalletInfo = walletInfoSource.values + .firstWhere((info) => info.id == WalletBase.idFor(currentName, getType())); + final currentWallet = await TronWalletBase.open( + password: password, name: currentName, walletInfo: currentWalletInfo); + + await currentWallet.renameWalletFiles(newName); + await saveBackup(newName); + + final newWalletInfo = currentWalletInfo; + newWalletInfo.id = WalletBase.idFor(newName, getType()); + newWalletInfo.name = newName; + + await walletInfoSource.put(currentWalletInfo.key, newWalletInfo); + } + + @override + Future isWalletExit(String name) async => + File(await pathForWallet(name: name, type: getType())).existsSync(); + + @override + Future remove(String wallet) async { + File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true); + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; + await walletInfoSource.delete(walletInfo.key); + } +} diff --git a/cw_tron/pubspec.yaml b/cw_tron/pubspec.yaml new file mode 100644 index 000000000..9d32c4290 --- /dev/null +++ b/cw_tron/pubspec.yaml @@ -0,0 +1,33 @@ +name: cw_tron +description: A new Flutter package project. +version: 0.0.1 +publish_to: none +homepage: https://cakewallet.com + +environment: + sdk: '>=3.0.6 <4.0.0' + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + cw_core: + path: ../cw_core + cw_evm: + path: ../cw_evm + on_chain: ^3.0.1 + blockchain_utils: ^2.1.1 + mobx: ^2.3.0+1 + bip39: ^1.0.6 + hive: ^2.2.3 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^2.0.0 + build_runner: ^2.3.3 + mobx_codegen: ^2.1.1 + hive_generator: ^1.1.3 +flutter: + # assets: + # - images/a_dot_burr.jpeg diff --git a/cw_tron/test/cw_tron_test.dart b/cw_tron/test/cw_tron_test.dart new file mode 100644 index 000000000..55a2b04be --- /dev/null +++ b/cw_tron/test/cw_tron_test.dart @@ -0,0 +1,12 @@ +import 'package:flutter_test/flutter_test.dart'; + +import 'package:cw_tron/cw_tron.dart'; + +void main() { + test('adds one to input values', () { + final calculator = Calculator(); + expect(calculator.addOne(2), 3); + expect(calculator.addOne(-7), -6); + expect(calculator.addOne(0), 1); + }); +} diff --git a/how_to_add_new_wallet_type.md b/how_to_add_new_wallet_type.md new file mode 100644 index 000000000..011e99990 --- /dev/null +++ b/how_to_add_new_wallet_type.md @@ -0,0 +1,300 @@ +# Guide to adding a new wallet type in Cake Wallet + +## Wallet Integration + +**N:B** Throughout this guide, `walletx` refers to the specific wallet type you want to add. If you're adding `BNB` to CakeWallet, then `walletx` for you here is `bnb`. + +**Core Folder/Files Setup** +- Idenitify your core component/package (major project component), which would power the integration e.g web3dart, solana, onchain etc +- Add a new entry to `WalletType` class in `cw_core/wallet_type.dart`. +- Fill out the necessary information int he various functions in the files, concerning the wallet name, the native currency type, symbol etc. +- Go to `cw_core/lib/currency_for_wallet_type.dart`, in the `currencyForWalletType` function, add a case for `walletx`, returning the native cryptocurrency for `walletx`. +- If the cryptocurrency for walletx is not available among the default cryptocurrencies, add a new cryptocurrency entry in `cw_core/lib/cryptocurrency.dart`. +- Add the newly created cryptocurrency name to the list named `all` in this file. +- Create a package for the wallet specific integration, name it. `cw_walletx` +- Add the following initial common files and replicate to fit the wallet + - walletx_transaction_history.dart + - walletx_transaction_info.dart + - walletx_mnemonics_exception.dart + - walletx_tokens.dart + - walletx_wallet_service.dart: + - walletx_wallet.dart + - etc. + +- Add the code to run the code generation needed for the files in the `cw_walletx` package to the `model_generator.sh` script + + cd cw_walletx && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. + +- Add the relevant dev_dependencies for generating the files also + - build_runner + - mobx_codegen + - hive_generator + +**WalletX Proxy Setup** + +A `Proxy` class is used to communicate with the specific wallet package we have. Instead of directly making use of methods and parameters in `cw_walletx` within the `lib` directory, we use a proxy to access these data. All important functions, calls and interactions we want to make with our `cw_walletx` package would be defined and done through the proxy class. The class would define the import + +- Create a proxy folder titled `walletx` to handle the wallet operations. It would contain 2 files: `cw_walletx.dart` and `walletx.dart`. +- `cw_walletx.dart` file would hold an implementation class containing major operations to be done in the lib directory. It serves as the link between the cw_walletx package and the rest of the codebase(lib directory files and folders). +- `walletx.dart` would contain the abstract class highlighting the methods that would bring the functionalities and features in the `cw_walletx` package to the rest of the `lib` directory. +- Add `walletx.dart` to `.gitignore` as we won’t be pushing it: `lib/tron/tron.dart`. +- `walletx.dart` would always be generated based on the configure files we would be setting up in the next step. + +**Configuration Files Setup** +- Before we populate the field, head over to `tool/configure.dart` to setup the necessary configurations for the `walletx` proxy. +- Define the output path, it’ll follow the format `lib/walletx/walletx.dart`. +- Add the variable to check if `walletx` is to be activated +- Define the function that would generate the abstract class for the proxy.(We will flesh out this function in the next steps). +- Add the defined variable in step 2 to the `generatePubspec` and `generateWalletTypes`. +- Next, modify the following functions: + - generatePubspec function + 1. Add the parameters to the method params (i.e required bool hasWalletX) + 2. Define a variable to hold the entry for the pubspec.yaml file + + const cwWalletX = """ + cw_tron: + path: ./cw_walletx + """; + + 3. Add an if block that takes in the passed parameter and adds the defined variable(inn the previous step) to the list of outputs + + if (hasWalletX) { + output += '\n$cwWalletX’; + } + + - generateWalletTypes function + 1. Add the parameters to the method params (i.e required bool hasWalletX) + 2. Add an if block to add the wallet type to the list of outputs this function generates + + if (hasWalletX) { + outputContent += '\tWalletType.walletx,\n’; + } + +- Head over to `scripts/android/pubspec.sh` script, and modify the `CONFIG_ARGS` under `$CAKEWALLET`. Add `"—walletx”` to the end of the passed in params. +- Repeat this in `scripts/ios/app_config.sh` and `scripts/macos/app_config.sh` +- Open a terminal and cd into `scripts/android/`. Run the following commands to run setup configuration scripts(proxy class, add walletx to list of wallet types and add cw_walletx to pubspec). + + source ./app_env.sh cakewallet + + ./app_config.sh + + cd cw_walletx && flutter pub get && flutter packages pub run build_runner build + + flutter packages pub run build_runner build --delete-conflicting-outputs + +Moving forward, our interactions with the cw_walletx package would be through the proxy class and its methods. + +**Pre-Wallet Creation for WalletX** +- Go to `di.dart` and locate the block to `registerWalletService`. In this, add the case to handle creating the WalletXWalletService + + case WalletType.walletx: + return walletx!.createWalletXWalletService(_walletInfoSource); + +- Go to `lib/view_model/wallet_new_vm.dart`, in the getCredentials method, which gets the new wallet credentials for walletX add the case for the new wallet + + case WalletType.walletx: + return walletx!.createWalletXNewWalletCredentials(name: name); + +**Node Setup** +- Before we can be able to successfully create a new wallet of wallet type walletx we need to setup the node that the wallet would use: +- In the assets directory, create a new file and name it `walletx_node_list.yml`. This yml file would contain the details for nodes to be used for walletX. An example structure for each node entry + + uri: "api.nodeurl.io" + is_default: true + useSSL: true + +You can add as many node entries as desired. + +- Add the path to the yml file created to the `pubspec_base.yaml` file (`“assets/walletx_node_list.yml”`) +- Go to `lib/entities/node_list.dart`, add a function to load the node entries we made in `walletx_node_list.yml` for walletx. +- Name your function `loadDefaultWalletXNodes()`. The function would handle loading the yml file as a string and parsing it into a Node Object to be used within the app. Here’s a template for the function. + + Future> loadDefaultWalletXNodes() async { + final nodesRaw = await rootBundle.loadString('assets/tron_node_list.yml'); + final loadedNodes = loadYaml(nodesRaw) as YamlList; + final nodes = []; + for (final raw in loadedNodes) { + if (raw is Map) { + final node = Node.fromMap(Map.from(raw)); + node.type = WalletType.tron; + nodes.add(node); + } + } + return nodes; + } + +- Inside the `resetToDefault` function, call the function you created and add the result to the nodes result variable. +- Go to `lib/entities/default_settings_migration.dart` file, we’ll be adding the following to the file. +- At the top of the file, after the imports, define the default nodeUrl for wallet-name. +- Next, write a function to fetch the node for this default uri you added above. + + Node? getWalletXDefaultNode({required Box nodes}) { + return nodes.values.firstWhereOrNull((Node node) => node.uriRaw == walletXDefaultNodeUri) ?? + nodes.values.firstWhereOrNull((node) => node.type == WalletType.walletx); + } + +- Next, write a function that will add the list of nodes we declared in the `walletx_node_list.yml` file to the Nodes Box, to be used in the app. Here’s the format for this function + + Future addWalletXNodeList({required Box nodes}) async { + final nodeList = await loadDefaultWalletXNodes(); + for (var node in nodeList) { + if (nodes.values.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) { + await nodes.add(node); + } + } + } + +- Next, we’ll write the function to change walletX current node to default. An handy function we would make use of later on. Add a new preference key in `lib/entities/preference_key.dart` with the format `PreferencesKey.currentWalletXNodeIdKey`, we’ll use it to identify the current node id. + + Future changeWalletXCurrentNodeToDefault( + {required SharedPreferences sharedPreferences, required Box nodes}) async { + final node = getWalletXDefaultNode(nodes: nodes); + final nodeId = node?.key as int? ?? 0; + await sharedPreferences.setInt(PreferencesKey.currentWalletXNodeIdKey, nodeId); + } + +- Next, in the `defaultSettingsMigration` function at the top of the file, add a new case to handle both `addWalletXNodeList` and `changeWalletXCurrentNodeToDefault` + + case “next-number-increment”: + await addWalletXNodeList(nodes: nodes); + await changeWalletXCurrentNodeToDefault(sharedPreferences: sharedPreferences, nodes: nodes); + break; + +- Next, increase the `initialMigrationVersion` number in `main.dart` to be the new case entry number you entered in the step above for the `defaultSettingsMigration` function. +- Next, go to `lib/view_model/node_list/node_list_view_model.dart` +- In the `reset` function, add a case for walletX: + + case WalletType.tron: + node = getTronDefaultNode(nodes: _nodeSource)!; + break; + +- Lastly, go to `cw_core/lib/node.dart`, +- In the uri getter, add a case to handle the uri setup for walletX. If the node uses http, return `Uri.http`, if not, return `Uri.https` + + case WalletType.walletX: + return Uri.https(uriRaw, ‘’); + +- Also, in the `requestNode` method, add a case for `WalletType.walletx` +- Next is the modifications to `lib/store/settings_store.dart` file: +- In the `load` function, create a variable to fetch the currentWalletxNodeId using the `PreferencesKey.currentWalletXNodeIdKey` we created earlier. +- Create another variable `walletXNode` which gets the walletx node using the nodeId variable assigned in the step above. +- Add a check to see if walletXNode is not null, if it’s not null, assign the created tronNode variable to the nodeMap with a type of walletX + + final walletXNode = nodeSource.get(walletXNodeId); + final walletXNodeId = sharedPreferences.getInt(PreferencesKey.currentWalletXNodeIdKey); + if (walletXNode != null) { + nodes[WalletType.walletx] = walletXNode; + } + +- Repeat the steps above in the `reload` function +- Next, add a case for walletX in the `_saveCurrentNode` function. + +- Run the following commands after to generate modified files in cw_core and lib + + cd cw_core && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. + + flutter packages pub run build_runner build --delete-conflicting-outputs + +- Lastly, before we run the app to test what we’ve done so far, +- Go to `lib/src/dashboard/widgets/menu_widget.dart` and add an icon for walletX to be used within the app. +- Go to `lib/src/screens/wallet_list/wallet_list_page.dart` and add an icon for walletx, add a case for walletx also in the `imageFor` method. +- Do the same thing in `lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart` + +- One last thing before we can create a wallet for walletx, go to `lib/view_model/wallet_new_vm.dart` +- Modify the `seedPhraseWordsLength` getter by adding a case for `WalletType.walletx` + +Now you can run the codebase and successfully create a wallet for type walletX successfully. + +**Display Seeds/Keys** +- Next, we want to set up our wallet to display the seeds and/or keys in the security page of the app. +- Go to `lib/view_model/wallet_keys_view_model.dart` +- Modify the `populateItems` function by adding a case for `WalletType.walletx` in it. +- Now your seeds and/or keys should display when you go to Security and Backup -> Show seed/keys page within the app. + +**Restore Wallet** +- Go to `lib/core/seed_validator.dart` +- In the `getWordList` method, add a case to handle `WalletType.walletx` which would return the word list to be used to validate the passed in seeds. +- Next, go to `lib/restore_view_model.dart` +- Modify the `hasRestoreFromPrivateKey` to reflect if walletx supports restore from Key +- Add a switch case to handle the various restore modes that walletX supports +- Modify the `getCredential` method to handle the restore flows for `WalletType.walletx` +- Run the build_runner code generation command + +**Receive** +- Go to `lib/view_model/wallet_address_list/wallet_address_list_view_model.dart` +- Create an implementation of `PaymentUri` for type WalletX. +- In the uri getter, add a case for `WalletType.walletx` returning the implementation class for `PaymentUri` +- Modify the `addressList` getter to return the address/addresses for walletx + +**Balance Screen** +- Go to `lib/view_model/dashboard/balance_view_model.dart` +- Modify the function to adjust the way the balance is being display on the app: `isHomeScreenSettingsEnabled` +- Add a case to the `availableBalanceLabel` getter to modify the text being displayed (Available or confirmed) +- Same for `additionalBalanceLabel` +- Next, go to `lib/reactions/fiat_rate_update.dart` +- Modify the `startFiatRateUpdate` function and add a check for `WalletType.walletx` to return all the token currencies +- Next, go to `lib/reactions/on_current_wallet_change.dart` +- Modify the `startCurrentWalletChangeReaction` function and add a check for `WalletType.walletx` to return all the token currencies +- Lastly, go to `lib/view_model/dashboard/transaction_list_item.dart` +- In the `formattedFiatAmount` getter, add a case to handle the fiat amount conversion for `WalletType.walletx` + +**Send ViewModel** +- Go to `lib/view_model/send/send_view_model.dart` +- Modify the `_credentials` function to reflect `WalletType.walletx` +- Modify `hasMultipleTokens` to reflect wallets + +**Exchange** +- Go to lib/view_model/exchange/exchange_view_model.dart +- First, add a case for WalletType.walletx in the `initialPairBasedOnWallet` method. +- If WalletX supports tokens, go to `lib/view_model/exchange/exchange_trade_view_model.dart` +- Modify the `_checkIfCanSend` method by creating a `_isWalletXToken` that checks if the from currency is WalletX and if its tag is for walletx +- Add `_isWalletXToken` to the return logic for the method. + +**Secrets** +- Create a json file named `wallet-secrets-config.json` and put an empty curly bracket “{}” in it +- Add a new entry to `tool/utils/secret_key.dart` for walletx +- Modify the `tool/generate_secrets_config.dart` file for walletx, don’t forget to call `secrets.clear()` before adding a new set of generation logic +- Modify the `tool/import_secrets_config.dart` file for walletx +- In the `.gitignore` file, add `**/tool/.walletx-secrets-config.json` and `**/cw_walletx/lib/.secrets.g.dart` + +**HomeSettings: WalletX Tokens Display and Management** +- Go to `lib/view_model/dashboard/home_settings_view_model.dart` +- Modify the `_updateTokensList` method to add all walletx tokens if the wallet type is `WalletType.walletx`. +- Modify the `getTokenAddressBasedOnWallet` method to include a case to fetch the address for a WalletX token. +- Modify the `getToken` method to return a specific walletx token +- Modify the `addToken`, `deleteToken` and `changeTokenAvailability` methods to handle cases where the walletType is walletx + +**Buy and Sell WalletX** +- Go to `lib/entities/provider_types.dart` +- Add a case for `WalletType.walletx` in the `getAvailableBuyProviderTypes` method. Return a list of providers that support buying WalletX. +- Add a case for `WalletType.walletx` in the `getAvailableSellProviderTypes` method. Return a list of providers that support selling WalletX. + +**Restore QR setup** +- Go to `lib/view_model/restore/wallet_restore_from_qr_code.dart` +- Add the scheme for walletx in `_walletTypeMap` +- Also modify `_determineWalletRestoreMode` to include a case for walletx +- Go to `lib/view_model/restore/restore_from_qr_vm.dart` +- Modify `getCredentialsFromRestoredWallet` method +- Go to `lib/core/address_validator.dart` +- Modify the `getAddressFromStringPattern` method to add a case for `WalletType.walletx` +- Add the scheme for walletx for both Android in `AndroidManifestBase.xml` and iOS in `InfoBase.plist` + +**Transaction History** +- Go to `lib/view_model/transaction_details_view_model.dart` +- Add a case for `WalletType.walletx` to add the items to be displayed on the detailed view +- Modify the `_explorerUrl` method to add the blockchain explorer link for WalletX in order to view the more info on a transaction +- Modify the `_explorerDescription` to display the name of the explorer + + + + +# Points to note when adding the new wallet type + +1. if it has tokens (ex. ERC20, SPL, etc...) make sure to add that to this function `_checkIfCanSend` in `exchange_trade_view_model.dart` +2. Check On/Off ramp providers that support the new wallet currency and add them accordingly in `provider_types.dart` +3. Add support for wallet uri scheme to restore from QR for both Android in `AndroidManifestBase.xml` and iOS in `InfoBase.plist` +4. Make sure no imports are using the wallet internal package files directly, instead use the proxy layers that is created in the main lib `lib/cw_ethereum.dart` for example. (i.e try building Monero.com if you get compilation errors, then you probably missed something) +5. + + +Copyright (C) 2018-2023 Cake Labs LLC diff --git a/ios/Runner/InfoBase.plist b/ios/Runner/InfoBase.plist index a7f208870..443f9791f 100644 --- a/ios/Runner/InfoBase.plist +++ b/ios/Runner/InfoBase.plist @@ -190,6 +190,36 @@ solana-wallet + + CFBundleTypeRole + Viewer + CFBundleURLName + tron + CFBundleURLSchemes + + tron + + + + CFBundleTypeRole + Viewer + CFBundleURLName + tron-wallet + CFBundleURLSchemes + + tron-wallet + + + + CFBundleTypeRole + Viewer + CFBundleURLName + tron_wallet + CFBundleURLSchemes + + tron_wallet + + CFBundleVersion $(CURRENT_PROJECT_VERSION) diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 967cf9bf0..01374d5a2 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -294,6 +294,8 @@ class AddressValidator extends TextValidator { '|([^0-9a-zA-Z]|^)q[0-9a-zA-Z]{42}([^0-9a-zA-Z]|\$)'; case CryptoCurrency.sol: return '([^0-9a-zA-Z]|^)[1-9A-HJ-NP-Za-km-z]{43,44}([^0-9a-zA-Z]|\$)'; + case CryptoCurrency.trx: + return '^(T|t)[1-9A-HJ-NP-Za-km-z]{33}\$'; default: if (type.tag == CryptoCurrency.eth.title) { return '0x[0-9a-zA-Z]{42}'; diff --git a/lib/core/seed_validator.dart b/lib/core/seed_validator.dart index 6d04055ba..3e3445757 100644 --- a/lib/core/seed_validator.dart +++ b/lib/core/seed_validator.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/core/validator.dart'; import 'package:cake_wallet/entities/mnemonic_item.dart'; import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/solana/solana.dart'; +import 'package:cake_wallet/tron/tron.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/nano/nano.dart'; @@ -40,6 +41,8 @@ class SeedValidator extends Validator { return polygon!.getPolygonWordList(language); case WalletType.solana: return solana!.getSolanaWordList(language); + case WalletType.tron: + return tron!.getTronWordList(language); default: return []; } diff --git a/lib/di.dart b/lib/di.dart index d78da638c..00710897f 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -13,6 +13,7 @@ import 'package:cake_wallet/core/yat_service.dart'; import 'package:cake_wallet/entities/background_tasks.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/parse_address_from_domain.dart'; +import 'package:cake_wallet/tron/tron.dart'; import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart'; import 'package:cw_core/receive_page_option.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; @@ -873,6 +874,8 @@ Future setup({ return polygon!.createPolygonWalletService(_walletInfoSource); case WalletType.solana: return solana!.createSolanaWalletService(_walletInfoSource); + case WalletType.tron: + return tron!.createTronWalletService(_walletInfoSource); default: throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService'); } diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 99178c815..94b23d3c9 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -36,6 +36,7 @@ const cakeWalletBitcoinCashDefaultNodeUri = 'bitcoincash.stackwallet.com:50002'; const nanoDefaultNodeUri = 'rpc.nano.to'; const nanoDefaultPowNodeUri = 'rpc.nano.to'; const solanaDefaultNodeUri = 'rpc.ankr.com'; +const tronDefaultNodeUri = 'api.trongrid.io'; const newCakeWalletBitcoinUri = 'btc-electrum.cakewallet.com:50002'; Future defaultSettingsMigration( @@ -207,23 +208,22 @@ Future defaultSettingsMigration( case 28: await _updateMoneroPriority(sharedPreferences); break; - case 29: await changeDefaultBitcoinNode(nodes, sharedPreferences); break; - case 30: await disableServiceStatusFiatDisabled(sharedPreferences); break; - case 31: await updateNanoNodeList(nodes: nodes); break; - case 32: await updateBtcNanoWalletInfos(walletInfoSource); break; - + case 33: + await addTronNodeList(nodes: nodes); + await changeTronCurrentNodeToDefault(sharedPreferences: sharedPreferences, nodes: nodes); + break; default: break; } @@ -478,6 +478,11 @@ Node? getSolanaDefaultNode({required Box nodes}) { nodes.values.firstWhereOrNull((node) => node.type == WalletType.solana); } +Node? getTronDefaultNode({required Box nodes}) { + return nodes.values.firstWhereOrNull((Node node) => node.uriRaw == tronDefaultNodeUri) ?? + nodes.values.firstWhereOrNull((node) => node.type == WalletType.tron); +} + Future insecureStorageMigration({ required SharedPreferences sharedPreferences, required FlutterSecureStorage secureStorage, @@ -809,6 +814,7 @@ Future checkCurrentNodes( final currentBitcoinCashNodeId = sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey); final currentSolanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey); + final currentTronNodeId = sharedPreferences.getInt(PreferencesKey.currentTronNodeIdKey); final currentMoneroNode = nodeSource.values.firstWhereOrNull((node) => node.key == currentMoneroNodeId); final currentBitcoinElectrumServer = @@ -829,6 +835,8 @@ Future checkCurrentNodes( nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinCashNodeId); final currentSolanaNodeServer = nodeSource.values.firstWhereOrNull((node) => node.key == currentSolanaNodeId); + final currentTronNodeServer = + nodeSource.values.firstWhereOrNull((node) => node.key == currentTronNodeId); if (currentMoneroNode == null) { final newCakeWalletNode = Node(uri: newCakeWalletMoneroUri, type: WalletType.monero); await nodeSource.add(newCakeWalletNode); @@ -894,6 +902,12 @@ Future checkCurrentNodes( await nodeSource.add(node); await sharedPreferences.setInt(PreferencesKey.currentSolanaNodeIdKey, node.key as int); } + + if (currentTronNodeServer == null) { + final node = Node(uri: tronDefaultNodeUri, type: WalletType.tron); + await nodeSource.add(node); + await sharedPreferences.setInt(PreferencesKey.currentTronNodeIdKey, node.key as int); + } } Future resetBitcoinElectrumServer( @@ -1022,3 +1036,20 @@ Future changeSolanaCurrentNodeToDefault( await sharedPreferences.setInt(PreferencesKey.currentSolanaNodeIdKey, nodeId); } + +Future addTronNodeList({required Box nodes}) async { + final nodeList = await loadDefaultTronNodes(); + for (var node in nodeList) { + if (nodes.values.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) { + await nodes.add(node); + } + } +} + +Future changeTronCurrentNodeToDefault( + {required SharedPreferences sharedPreferences, required Box nodes}) async { + final node = getTronDefaultNode(nodes: nodes); + final nodeId = node?.key as int? ?? 0; + + await sharedPreferences.setInt(PreferencesKey.currentTronNodeIdKey, nodeId); +} diff --git a/lib/entities/node_list.dart b/lib/entities/node_list.dart index 3c82a3f6c..c1211d2fe 100644 --- a/lib/entities/node_list.dart +++ b/lib/entities/node_list.dart @@ -166,6 +166,23 @@ Future> loadDefaultSolanaNodes() async { return nodes; } +Future> loadDefaultTronNodes() async { + final nodesRaw = await rootBundle.loadString('assets/tron_node_list.yml'); + final loadedNodes = loadYaml(nodesRaw) as YamlList; + final nodes = []; + + for (final raw in loadedNodes) { + if (raw is Map) { + final node = Node.fromMap(Map.from(raw)); + + node.type = WalletType.tron; + nodes.add(node); + } + } + + return nodes; +} + Future resetToDefault(Box nodeSource) async { final moneroNodes = await loadDefaultNodes(); final bitcoinElectrumServerList = await loadBitcoinElectrumServerList(); @@ -176,6 +193,7 @@ Future resetToDefault(Box nodeSource) async { final nanoNodes = await loadDefaultNanoNodes(); final polygonNodes = await loadDefaultPolygonNodes(); final solanaNodes = await loadDefaultSolanaNodes(); + final tronNodes = await loadDefaultTronNodes(); final nodes = moneroNodes + bitcoinElectrumServerList + @@ -185,7 +203,7 @@ Future resetToDefault(Box nodeSource) async { bitcoinCashElectrumServerList + nanoNodes + polygonNodes + - solanaNodes; + solanaNodes + tronNodes; await nodeSource.clear(); await nodeSource.addAll(nodes); diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index f512d6b72..55b5d55a1 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -14,6 +14,7 @@ class PreferencesKey { static const currentFiatCurrencyKey = 'current_fiat_currency'; static const currentBitcoinCashNodeIdKey = 'current_node_id_bch'; static const currentSolanaNodeIdKey = 'current_node_id_sol'; + static const currentTronNodeIdKey = 'current_node_id_trx'; static const currentTransactionPriorityKeyLegacy = 'current_fee_priority'; static const currentBalanceDisplayModeKey = 'current_balance_display_mode'; static const shouldSaveRecipientAddressKey = 'save_recipient_address'; diff --git a/lib/entities/priority_for_wallet_type.dart b/lib/entities/priority_for_wallet_type.dart index 5fc0b5566..0151c8115 100644 --- a/lib/entities/priority_for_wallet_type.dart +++ b/lib/entities/priority_for_wallet_type.dart @@ -23,10 +23,11 @@ List priorityForWalletType(WalletType type) { return bitcoinCash!.getTransactionPriorities(); case WalletType.polygon: return polygon!.getTransactionPriorities(); - // no such thing for nano/banano/solana: + // no such thing for nano/banano/solana/tron: case WalletType.nano: case WalletType.banano: case WalletType.solana: + case WalletType.tron: return []; default: return []; diff --git a/lib/entities/provider_types.dart b/lib/entities/provider_types.dart index ca168a299..37a492987 100644 --- a/lib/entities/provider_types.dart +++ b/lib/entities/provider_types.dart @@ -69,6 +69,13 @@ class ProvidersHelper { return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood, ProviderType.moonpay]; case WalletType.solana: return [ProviderType.askEachTime, ProviderType.onramper, ProviderType.robinhood]; + case WalletType.tron: + return [ + ProviderType.askEachTime, + ProviderType.onramper, + ProviderType.robinhood, + ProviderType.moonpay, + ]; case WalletType.none: case WalletType.haven: return []; @@ -96,6 +103,12 @@ class ProvidersHelper { ProviderType.robinhood, ProviderType.moonpay, ]; + case WalletType.tron: + return [ + ProviderType.askEachTime, + ProviderType.robinhood, + ProviderType.moonpay, + ]; case WalletType.monero: case WalletType.nano: case WalletType.banano: diff --git a/lib/main.dart b/lib/main.dart index ff5b0e5c0..eef8cef62 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -167,7 +167,7 @@ Future initializeAppConfigs() async { transactionDescriptions: transactionDescriptions, secureStorage: secureStorage, anonpayInvoiceInfo: anonpayInvoiceInfo, - initialMigrationVersion: 32, + initialMigrationVersion: 33, ); } diff --git a/lib/reactions/fiat_rate_update.dart b/lib/reactions/fiat_rate_update.dart index fb1d4cd1a..e46ef4b64 100644 --- a/lib/reactions/fiat_rate_update.dart +++ b/lib/reactions/fiat_rate_update.dart @@ -8,6 +8,7 @@ import 'package:cake_wallet/solana/solana.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/tron/tron.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/erc20_token.dart'; import 'package:cw_core/wallet_type.dart'; @@ -53,6 +54,11 @@ Future startFiatRateUpdate( solana!.getSPLTokenCurrencies(appStore.wallet!).where((element) => element.enabled); } + if (appStore.wallet!.type == WalletType.tron) { + currencies = + tron!.getTronTokenCurrencies(appStore.wallet!).where((element) => element.enabled); + } + if (currencies != null) { for (final currency in currencies) { diff --git a/lib/reactions/on_current_wallet_change.dart b/lib/reactions/on_current_wallet_change.dart index a2f2491f1..a6ce2bae9 100644 --- a/lib/reactions/on_current_wallet_change.dart +++ b/lib/reactions/on_current_wallet_change.dart @@ -4,8 +4,8 @@ import 'package:cake_wallet/entities/update_haven_rate.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/solana/solana.dart'; +import 'package:cake_wallet/tron/tron.dart'; import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/erc20_token.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/transaction_info.dart'; @@ -70,8 +70,10 @@ void startCurrentWalletChangeReaction( .get() .setInt(PreferencesKey.currentWalletType, serializeToInt(wallet.type)); - if (wallet.type == WalletType.monero || wallet.type == WalletType.bitcoin || - wallet.type == WalletType.litecoin || wallet.type == WalletType.bitcoinCash ) { + if (wallet.type == WalletType.monero || + wallet.type == WalletType.bitcoin || + wallet.type == WalletType.litecoin || + wallet.type == WalletType.bitcoinCash) { _setAutoGenerateSubaddressStatus(wallet, settingsStore); } @@ -124,7 +126,11 @@ void startCurrentWalletChangeReaction( currencies = solana!.getSPLTokenCurrencies(appStore.wallet!).where((element) => element.enabled); } - + if (wallet.type == WalletType.tron) { + currencies = + tron!.getTronTokenCurrencies(appStore.wallet!).where((element) => element.enabled); + } + if (currencies != null) { for (final currency in currencies) { () async { diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart index 17a22a88f..18ab9d030 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart @@ -38,6 +38,7 @@ class _DesktopWalletSelectionDropDownState extends State Image.asset( @@ -156,6 +157,8 @@ class _DesktopWalletSelectionDropDownState extends State TransactionRow( - onTap: () => Navigator.of(context) - .pushNamed(Routes.transactionDetails, arguments: transaction), - direction: transaction.direction, - formattedDate: DateFormat('HH:mm').format(transaction.date), - formattedAmount: item.formattedCryptoAmount, - formattedFiatAmount: - dashboardViewModel.balanceViewModel.isFiatDisabled - ? '' - : item.formattedFiatAmount, - isPending: transaction.isPending, - title: item.formattedTitle + item.formattedStatus)); + builder: (_) => TransactionRow( + onTap: () => Navigator.of(context) + .pushNamed(Routes.transactionDetails, arguments: transaction), + direction: transaction.direction, + formattedDate: DateFormat('HH:mm').format(transaction.date), + formattedAmount: item.formattedCryptoAmount, + formattedFiatAmount: + dashboardViewModel.balanceViewModel.isFiatDisabled + ? '' + : item.formattedFiatAmount, + isPending: transaction.isPending, + title: item.formattedTitle + item.formattedStatus, + ), + ); } if (item is AnonpayTransactionListItem) { diff --git a/lib/src/screens/dashboard/widgets/menu_widget.dart b/lib/src/screens/dashboard/widgets/menu_widget.dart index acd666025..d9e03dbf9 100644 --- a/lib/src/screens/dashboard/widgets/menu_widget.dart +++ b/lib/src/screens/dashboard/widgets/menu_widget.dart @@ -34,7 +34,8 @@ class MenuWidgetState extends State { this.bananoIcon = Image.asset('assets/images/nano_icon.png'), this.bitcoinCashIcon = Image.asset('assets/images/bch_icon.png'), this.polygonIcon = Image.asset('assets/images/matic_icon.png'), - this.solanaIcon = Image.asset('assets/images/sol_icon.png'); + this.solanaIcon = Image.asset('assets/images/sol_icon.png'), + this.tronIcon = Image.asset('assets/images/trx_icon.png'); final largeScreen = 731; @@ -57,6 +58,7 @@ class MenuWidgetState extends State { Image bananoIcon; Image polygonIcon; Image solanaIcon; + Image tronIcon; @override void initState() { @@ -226,6 +228,8 @@ class MenuWidgetState extends State { return polygonIcon; case WalletType.solana: return solanaIcon; + case WalletType.tron: + return tronIcon; default: throw Exception('No icon for ${type.toString()}'); } diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index 81c78b1ab..601f5d878 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -104,6 +104,7 @@ class WalletListBodyState extends State { final nanoIcon = Image.asset('assets/images/nano_icon.png', height: 24, width: 24); final polygonIcon = Image.asset('assets/images/matic_icon.png', height: 24, width: 24); final solanaIcon = Image.asset('assets/images/sol_icon.png', height: 24, width: 24); + final tronIcon = Image.asset('assets/images/trx_icon.png', height: 24, width: 24); final scrollController = ScrollController(); final double tileHeight = 60; Flushbar? _progressBar; @@ -316,6 +317,8 @@ class WalletListBodyState extends State { return polygonIcon; case WalletType.solana: return solanaIcon; + case WalletType.tron: + return tronIcon; default: return nonWalletTypeIcon; } diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 165c72242..607551827 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -872,6 +872,7 @@ abstract class SettingsStoreBase with Store { final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); final nanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey); final solanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey); + final tronNodeId = sharedPreferences.getInt(PreferencesKey.currentTronNodeIdKey); final moneroNode = nodeSource.get(nodeId); final bitcoinElectrumServer = nodeSource.get(bitcoinElectrumServerId); final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId); @@ -882,6 +883,7 @@ abstract class SettingsStoreBase with Store { final nanoNode = nodeSource.get(nanoNodeId); final nanoPowNode = powNodeSource.get(nanoPowNodeId); final solanaNode = nodeSource.get(solanaNodeId); + final tronNode = nodeSource.get(tronNodeId); final packageInfo = await PackageInfo.fromPlatform(); final deviceName = await _getDeviceName() ?? ''; final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true; @@ -944,6 +946,10 @@ abstract class SettingsStoreBase with Store { nodes[WalletType.solana] = solanaNode; } + if (tronNode != null) { + nodes[WalletType.tron] = tronNode; + } + final savedSyncMode = SyncMode.all.firstWhere((element) { return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 0); }); @@ -1238,6 +1244,7 @@ abstract class SettingsStoreBase with Store { final polygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey); final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey); final solanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey); + final tronNodeId = sharedPreferences.getInt(PreferencesKey.currentTronNodeIdKey); final moneroNode = nodeSource.get(nodeId); final bitcoinElectrumServer = nodeSource.get(bitcoinElectrumServerId); final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId); @@ -1247,6 +1254,7 @@ abstract class SettingsStoreBase with Store { final bitcoinCashNode = nodeSource.get(bitcoinCashElectrumServerId); final nanoNode = nodeSource.get(nanoNodeId); final solanaNode = nodeSource.get(solanaNodeId); + final tronNode = nodeSource.get(tronNodeId); if (moneroNode != null) { nodes[WalletType.monero] = moneroNode; } @@ -1283,6 +1291,10 @@ abstract class SettingsStoreBase with Store { nodes[WalletType.solana] = solanaNode; } + if (tronNode != null) { + nodes[WalletType.tron] = tronNode; + } + // MIGRATED: useTOTP2FA = await SecureKey.getBool( @@ -1413,6 +1425,9 @@ abstract class SettingsStoreBase with Store { case WalletType.solana: await _sharedPreferences.setInt(PreferencesKey.currentSolanaNodeIdKey, node.key as int); break; + case WalletType.tron: + await _sharedPreferences.setInt(PreferencesKey.currentTronNodeIdKey, node.key as int); + break; default: break; } diff --git a/lib/tron/cw_tron.dart b/lib/tron/cw_tron.dart new file mode 100644 index 000000000..6e4b0a7b0 --- /dev/null +++ b/lib/tron/cw_tron.dart @@ -0,0 +1,114 @@ +part of 'tron.dart'; + +class CWTron extends Tron { + @override + List getTronWordList(String language) => EVMChainMnemonics.englishWordlist; + + WalletService createTronWalletService(Box walletInfoSource) => + TronWalletService(walletInfoSource, client: TronClient()); + + @override + WalletCredentials createTronNewWalletCredentials({ + required String name, + WalletInfo? walletInfo, + }) => + TronNewWalletCredentials(name: name, walletInfo: walletInfo); + + @override + WalletCredentials createTronRestoreWalletFromSeedCredentials({ + required String name, + required String mnemonic, + required String password, + }) => + TronRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic); + + @override + WalletCredentials createTronRestoreWalletFromPrivateKey({ + required String name, + required String privateKey, + required String password, + }) => + TronRestoreWalletFromPrivateKey(name: name, password: password, privateKey: privateKey); + + @override + String getAddress(WalletBase wallet) => (wallet as TronWallet).walletAddresses.address; + + Object createTronTransactionCredentials( + List outputs, { + required CryptoCurrency currency, + }) => + TronTransactionCredentials( + outputs + .map( + (out) => OutputInfo( + fiatAmount: out.fiatAmount, + cryptoAmount: out.cryptoAmount, + address: out.address, + note: out.note, + sendAll: out.sendAll, + extractedAddress: out.extractedAddress, + isParsedAddress: out.isParsedAddress, + formattedCryptoAmount: out.formattedCryptoAmount, + ), + ) + .toList(), + currency: currency, + ); + + @override + List getTronTokenCurrencies(WalletBase wallet) => + (wallet as TronWallet).tronTokenCurrencies; + + @override + Future addTronToken(WalletBase wallet, CryptoCurrency token, String contractAddress) async { + final tronToken = TronToken( + name: token.name, + symbol: token.title, + contractAddress: contractAddress, + decimal: token.decimals, + enabled: token.enabled, + iconPath: token.iconPath, + ); + await (wallet as TronWallet).addTronToken(tronToken); + } + + @override + Future deleteTronToken(WalletBase wallet, CryptoCurrency token) async => + await (wallet as TronWallet).deleteTronToken(token as TronToken); + + @override + Future getTronToken(WalletBase wallet, String contractAddress) async => + (wallet as TronWallet).getTronToken(contractAddress); + + @override + double getTransactionAmountRaw(TransactionInfo transactionInfo) { + final amount = (transactionInfo as TronTransactionInfo).rawTronAmount(); + return double.parse(amount); + } + + @override + CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) { + transaction as TronTransactionInfo; + if (transaction.tokenSymbol == CryptoCurrency.trx.title) { + return CryptoCurrency.trx; + } + + wallet as TronWallet; + return wallet.tronTokenCurrencies.firstWhere( + (element) => transaction.tokenSymbol.toLowerCase() == element.symbol.toLowerCase()); + } + + @override + String getTokenAddress(CryptoCurrency asset) => (asset as TronToken).contractAddress; + + @override + String getTronBase58Address(String hexAddress, WalletBase wallet) => + (wallet as TronWallet).getTronBase58AddressFromHex(hexAddress); + + @override + String? getTronNativeEstimatedFee(WalletBase wallet) => + (wallet as TronWallet).nativeTxEstimatedFee; + + @override + String? getTronTRC20EstimatedFee(WalletBase wallet) => (wallet as TronWallet).trc20EstimatedFee; +} diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart index a17ddff36..c87e097c3 100644 --- a/lib/view_model/advanced_privacy_settings_view_model.dart +++ b/lib/view_model/advanced_privacy_settings_view_model.dart @@ -38,6 +38,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store { case WalletType.bitcoinCash: case WalletType.polygon: case WalletType.solana: + case WalletType.tron: return true; case WalletType.monero: case WalletType.none: diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index eee53516e..6f4db52a6 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -80,7 +80,9 @@ abstract class BalanceViewModelBase with Store { @computed bool get isHomeScreenSettingsEnabled => - isEVMCompatibleChain(wallet.type) || wallet.type == WalletType.solana; + isEVMCompatibleChain(wallet.type) || + wallet.type == WalletType.solana || + wallet.type == WalletType.tron; @computed bool get hasAccounts => wallet.type == WalletType.monero; @@ -126,6 +128,7 @@ abstract class BalanceViewModelBase with Store { case WalletType.nano: case WalletType.banano: case WalletType.solana: + case WalletType.tron: return S.current.xmr_available_balance; default: return S.current.confirmed; @@ -140,6 +143,7 @@ abstract class BalanceViewModelBase with Store { case WalletType.ethereum: case WalletType.polygon: case WalletType.solana: + case WalletType.tron: return S.current.xmr_full_balance; case WalletType.nano: case WalletType.banano: @@ -287,6 +291,7 @@ abstract class BalanceViewModelBase with Store { case WalletType.ethereum: case WalletType.polygon: case WalletType.solana: + case WalletType.tron: return false; default: return true; diff --git a/lib/view_model/dashboard/home_settings_view_model.dart b/lib/view_model/dashboard/home_settings_view_model.dart index e60a37ccf..9e3be746e 100644 --- a/lib/view_model/dashboard/home_settings_view_model.dart +++ b/lib/view_model/dashboard/home_settings_view_model.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/solana/solana.dart'; import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/tron/tron.dart'; import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/erc20_token.dart'; @@ -79,6 +80,10 @@ abstract class HomeSettingsViewModelBase with Store { ); } + if (_balanceViewModel.wallet.type == WalletType.tron) { + await tron!.addTronToken(_balanceViewModel.wallet, token, contractAddress); + } + _updateTokensList(); _updateFiatPrices(token); } @@ -96,6 +101,9 @@ abstract class HomeSettingsViewModelBase with Store { await solana!.deleteSPLToken(_balanceViewModel.wallet, token); } + if (_balanceViewModel.wallet.type == WalletType.tron) { + await tron!.deleteTronToken(_balanceViewModel.wallet, token); + } _updateTokensList(); } @@ -112,6 +120,10 @@ abstract class HomeSettingsViewModelBase with Store { return await solana!.getSPLToken(_balanceViewModel.wallet, contractAddress); } + if (_balanceViewModel.wallet.type == WalletType.tron) { + return await tron!.getTronToken(_balanceViewModel.wallet, contractAddress); + } + return null; } @@ -143,6 +155,11 @@ abstract class HomeSettingsViewModelBase with Store { solana!.addSPLToken(_balanceViewModel.wallet, token, address); } + if (_balanceViewModel.wallet.type == WalletType.tron) { + final address = tron!.getTokenAddress(token); + tron!.addTronToken(_balanceViewModel.wallet, token, address); + } + _refreshTokensList(); } @@ -189,6 +206,14 @@ abstract class HomeSettingsViewModelBase with Store { .toList() ..sort(_sortFunc)); } + + if (_balanceViewModel.wallet.type == WalletType.tron) { + tokens.addAll(tron! + .getTronTokenCurrencies(_balanceViewModel.wallet) + .where((element) => _matchesSearchText(element)) + .toList() + ..sort(_sortFunc)); + } } @action @@ -207,7 +232,7 @@ abstract class HomeSettingsViewModelBase with Store { bool _matchesSearchText(CryptoCurrency asset) { final address = getTokenAddressBasedOnWallet(asset); - // The homes settings would only be displayed for either of Ethereum, Polygon or Solana Wallets. + // The homes settings would only be displayed for either of Tron, Ethereum, Polygon or Solana Wallets. if (address == null) return false; return searchText.isEmpty || @@ -217,6 +242,10 @@ abstract class HomeSettingsViewModelBase with Store { } String? getTokenAddressBasedOnWallet(CryptoCurrency asset) { + if (_balanceViewModel.wallet.type == WalletType.tron) { + return tron!.getTokenAddress(asset); + } + if (_balanceViewModel.wallet.type == WalletType.solana) { return solana!.getTokenAddress(asset); } @@ -229,7 +258,7 @@ abstract class HomeSettingsViewModelBase with Store { return polygon!.getTokenAddress(asset); } - // We return null if it's neither Polygin, Ethereum or Solana wallet (which is actually impossible because we only display home settings for either of these three wallets). + // We return null if it's neither Tron, Polygon, Ethereum or Solana wallet (which is actually impossible because we only display home settings for either of these three wallets). return null; } } diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart index 99de14a18..fb5348a29 100644 --- a/lib/view_model/dashboard/transaction_list_item.dart +++ b/lib/view_model/dashboard/transaction_list_item.dart @@ -4,7 +4,10 @@ import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/solana/solana.dart'; +import 'package:cake_wallet/tron/tron.dart'; +import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cake_wallet/store/settings_store.dart'; @@ -34,6 +37,11 @@ class TransactionListItem extends ActionListItem with Keyable { @override dynamic get keyIndex => transaction.id; + bool get hasTokens => + isEVMCompatibleChain(balanceViewModel.wallet.type) || + balanceViewModel.wallet.type == WalletType.solana || + balanceViewModel.wallet.type == WalletType.tron; + String get formattedCryptoAmount { return displayMode == BalanceDisplayMode.hiddenBalance ? '---' : transaction.amountFormatted(); } @@ -63,6 +71,34 @@ class TransactionListItem extends ActionListItem with Keyable { return transaction.isPending ? S.current.pending : ''; } + CryptoCurrency? get assetOfTransaction { + try { + if (balanceViewModel.wallet.type == WalletType.ethereum) { + final asset = ethereum!.assetOfTransaction(balanceViewModel.wallet, transaction); + return asset; + } + + if (balanceViewModel.wallet.type == WalletType.polygon) { + final asset = polygon!.assetOfTransaction(balanceViewModel.wallet, transaction); + return asset; + } + + if (balanceViewModel.wallet.type == WalletType.solana) { + final asset = solana!.assetOfTransaction(balanceViewModel.wallet, transaction); + return asset; + } + + if (balanceViewModel.wallet.type == WalletType.tron) { + final asset = tron!.assetOfTransaction(balanceViewModel.wallet, transaction); + return asset; + } + } catch (e) { + return null; + } + + return null; + } + String get formattedFiatAmount { var amount = ''; @@ -114,6 +150,16 @@ class TransactionListItem extends ActionListItem with Keyable { price: price, ); break; + + case WalletType.tron: + final asset = tron!.assetOfTransaction(balanceViewModel.wallet, transaction); + final price = balanceViewModel.fiatConvertationStore.prices[asset]; + final cryptoAmount = tron!.getTransactionAmountRaw(transaction); + amount = calculateFiatAmountRaw( + cryptoAmount: cryptoAmount, + price: price, + ); + break; default: break; } diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index 9bd9ef913..94fec2fa2 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -178,6 +178,10 @@ abstract class ExchangeTradeViewModelBase with Store { wallet.currency == CryptoCurrency.maticpoly && tradesStore.trade!.from.tag == CryptoCurrency.maticpoly.tag; + bool _isTronToken() => + wallet.currency == CryptoCurrency.trx && + tradesStore.trade!.from.tag == CryptoCurrency.trx.title; + bool _isSplToken() => wallet.currency == CryptoCurrency.sol && tradesStore.trade!.from.tag == CryptoCurrency.sol.title; @@ -186,6 +190,7 @@ abstract class ExchangeTradeViewModelBase with Store { tradesStore.trade!.provider == ExchangeProviderDescription.xmrto || _isEthToken() || _isPolygonToken() || - _isSplToken(); + _isSplToken() || + _isTronToken(); } } diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index 4e5902faa..e5533f48a 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -676,6 +676,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with depositCurrency = CryptoCurrency.sol; receiveCurrency = CryptoCurrency.xmr; break; + case WalletType.tron: + depositCurrency = CryptoCurrency.trx; + receiveCurrency = CryptoCurrency.xmr; + break; default: break; } diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart index 7fe3d1c98..000c9bdea 100644 --- a/lib/view_model/node_list/node_create_or_edit_view_model.dart +++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart @@ -76,6 +76,7 @@ abstract class NodeCreateOrEditViewModelBase with Store { case WalletType.solana: case WalletType.banano: case WalletType.nano: + case WalletType.tron: return true; case WalletType.none: case WalletType.monero: diff --git a/lib/view_model/node_list/node_list_view_model.dart b/lib/view_model/node_list/node_list_view_model.dart index 9c2d2611e..a7fe9c6ca 100644 --- a/lib/view_model/node_list/node_list_view_model.dart +++ b/lib/view_model/node_list/node_list_view_model.dart @@ -82,6 +82,9 @@ abstract class NodeListViewModelBase with Store { case WalletType.solana: node = getSolanaDefaultNode(nodes: _nodeSource)!; break; + case WalletType.tron: + node = getTronDefaultNode(nodes: _nodeSource)!; + break; default: throw Exception('Unexpected wallet type: ${_appStore.wallet!.type}'); } diff --git a/lib/view_model/restore/restore_from_qr_vm.dart b/lib/view_model/restore/restore_from_qr_vm.dart index b9b493f04..1e9aea2c2 100644 --- a/lib/view_model/restore/restore_from_qr_vm.dart +++ b/lib/view_model/restore/restore_from_qr_vm.dart @@ -4,13 +4,14 @@ import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/solana/solana.dart'; +import 'package:cake_wallet/tron/tron.dart'; import 'package:cake_wallet/view_model/restore/restore_mode.dart'; import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/store/app_store.dart'; -import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_base.dart'; import 'package:cake_wallet/core/generate_wallet_password.dart'; import 'package:cake_wallet/core/wallet_creation_service.dart'; import 'package:cw_core/wallet_credentials.dart'; @@ -86,6 +87,9 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store case WalletType.solana: return solana!.createSolanaRestoreWalletFromPrivateKey( name: name, password: password, privateKey: restoreWallet.privateKey!); + case WalletType.tron: + return tron!.createTronRestoreWalletFromPrivateKey( + name: name, password: password, privateKey: restoreWallet.privateKey!); default: throw Exception('Unexpected type: ${restoreWallet.type.toString()}'); } @@ -130,6 +134,9 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store case WalletType.solana: return solana!.createSolanaRestoreWalletFromSeedCredentials( name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); + case WalletType.tron: + return tron!.createTronRestoreWalletFromSeedCredentials( + name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password); default: throw Exception('Unexpected type: ${type.toString()}'); } diff --git a/lib/view_model/restore/wallet_restore_from_qr_code.dart b/lib/view_model/restore/wallet_restore_from_qr_code.dart index 925c08cca..09b5c9d96 100644 --- a/lib/view_model/restore/wallet_restore_from_qr_code.dart +++ b/lib/view_model/restore/wallet_restore_from_qr_code.dart @@ -33,6 +33,9 @@ class WalletRestoreFromQRCode { 'bitcoincash-wallet': WalletType.bitcoinCash, 'bitcoincash_wallet': WalletType.bitcoinCash, 'solana-wallet': WalletType.solana, + 'tron': WalletType.tron, + 'tron-wallet': WalletType.tron, + 'tron_wallet': WalletType.tron, }; static bool _containsAssetSpecifier(String code) => _extractWalletType(code) != null; @@ -184,6 +187,14 @@ class WalletRestoreFromQRCode { return WalletRestoreMode.keys; } + if (type == WalletType.tron && credentials.containsKey('private_key')) { + final privateKey = credentials['private_key'] as String; + if (privateKey.isEmpty) { + throw Exception('Unexpected restore mode: private_key'); + } + return WalletRestoreMode.keys; + } + throw Exception('Unexpected restore mode: restore params are invalid'); } } diff --git a/lib/view_model/send/output.dart b/lib/view_model/send/output.dart index 07d98ff32..a79baea48 100644 --- a/lib/view_model/send/output.dart +++ b/lib/view_model/send/output.dart @@ -8,6 +8,7 @@ import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/solana/solana.dart'; import 'package:cake_wallet/src/screens/send/widgets/extract_address_from_parsed.dart'; +import 'package:cake_wallet/tron/tron.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; @@ -117,6 +118,17 @@ abstract class OutputBase with Store { @computed double get estimatedFee { try { + if (_wallet.type == WalletType.tron) { + if (cryptoCurrencyHandler() == CryptoCurrency.trx) { + final nativeEstimatedFee = tron!.getTronNativeEstimatedFee(_wallet) ?? 0; + return double.parse(nativeEstimatedFee.toString()); + } else { + final trc20EstimatedFee = tron!.getTronTRC20EstimatedFee(_wallet) ?? 0; + return double.parse(trc20EstimatedFee.toString()); + } + + } + if (_wallet.type == WalletType.solana) { return solana!.getEstimateFees(_wallet) ?? 0.0; } @@ -163,8 +175,11 @@ abstract class OutputBase with Store { @computed String get estimatedFeeFiatAmount { try { - final currency = - isEVMCompatibleChain(_wallet.type) ? _wallet.currency : cryptoCurrencyHandler(); + final currency = (isEVMCompatibleChain(_wallet.type) || + _wallet.type == WalletType.solana || + _wallet.type == WalletType.tron) + ? _wallet.currency + : cryptoCurrencyHandler(); final fiat = calculateFiatAmountRaw( price: _fiatConversationStore.prices[currency]!, cryptoAmount: estimatedFee); return fiat; @@ -269,6 +284,9 @@ abstract class OutputBase with Store { case WalletType.solana: maximumFractionDigits = 12; break; + case WalletType.tron: + maximumFractionDigits = 12; + break; default: break; } diff --git a/lib/view_model/send/send_template_view_model.dart b/lib/view_model/send/send_template_view_model.dart index f79fbddc7..66a3c37c8 100644 --- a/lib/view_model/send/send_template_view_model.dart +++ b/lib/view_model/send/send_template_view_model.dart @@ -53,7 +53,8 @@ abstract class SendTemplateViewModelBase with Store { _wallet.type != WalletType.haven && _wallet.type != WalletType.ethereum && _wallet.type != WalletType.polygon && - _wallet.type != WalletType.solana; + _wallet.type != WalletType.solana && + _wallet.type != WalletType.tron; @computed CryptoCurrency get cryptoCurrency => _wallet.currency; diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 6c0c3870b..bafc1317d 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -12,6 +12,7 @@ import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/solana/solana.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'; import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; import 'package:cw_core/exceptions.dart'; @@ -50,7 +51,9 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor void onWalletChange(wallet) { currencies = wallet.balance.keys.toList(); selectedCryptoCurrency = wallet.currency; - hasMultipleTokens = isEVMCompatibleChain(wallet.type) || wallet.type == WalletType.solana; + hasMultipleTokens = isEVMCompatibleChain(wallet.type) || + wallet.type == WalletType.solana || + wallet.type == WalletType.tron; } SendViewModelBase( @@ -64,7 +67,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor currencies = appStore.wallet!.balance.keys.toList(), selectedCryptoCurrency = appStore.wallet!.currency, hasMultipleTokens = isEVMCompatibleChain(appStore.wallet!.type) || - appStore.wallet!.type == WalletType.solana, + appStore.wallet!.type == WalletType.solana || + appStore.wallet!.type == WalletType.tron, outputs = ObservableList(), _settingsStore = appStore.settingsStore, fiatFromSettings = appStore.settingsStore.fiatCurrency, @@ -110,6 +114,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor @computed bool get isBatchSending => outputs.length > 1; + bool get shouldDisplaySendALL => walletType != WalletType.solana || walletType != WalletType.tron; + @computed String get pendingTransactionFiatAmount { if (pendingTransaction == null) { @@ -236,7 +242,9 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor bool get hasFeesPriority => wallet.type != WalletType.nano && wallet.type != WalletType.banano && - wallet.type != WalletType.solana; + wallet.type != WalletType.solana && + wallet.type != WalletType.tron; + @observable CryptoCurrency selectedCryptoCurrency; @@ -423,7 +431,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor Object _credentials() { final priority = _settingsStore.priority[wallet.type]; - if (priority == null && wallet.type != WalletType.nano && wallet.type != WalletType.banano && wallet.type != WalletType.solana) { + if (priority == null && wallet.type != WalletType.nano && wallet.type != WalletType.banano && wallet.type != WalletType.solana && + wallet.type != WalletType.tron) { throw Exception('Priority is null for wallet type: ${wallet.type}'); } @@ -453,6 +462,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor case WalletType.solana: return solana! .createSolanaTransactionCredentials(outputs, currency: selectedCryptoCurrency); + case WalletType.tron: + return tron!.createTronTransactionCredentials(outputs, currency: selectedCryptoCurrency); default: throw Exception('Unexpected wallet type: ${wallet.type}'); } diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart index 0493acf81..7e751a920 100644 --- a/lib/view_model/settings/other_settings_view_model.dart +++ b/lib/view_model/settings/other_settings_view_model.dart @@ -56,8 +56,9 @@ abstract class OtherSettingsViewModelBase with Store { _wallet.type == WalletType.nano || _wallet.type == WalletType.banano; @computed - bool get displayTransactionPriority => - !(changeRepresentativeEnabled || _wallet.type == WalletType.solana); + bool get displayTransactionPriority => !(changeRepresentativeEnabled || + _wallet.type == WalletType.solana || + _wallet.type == WalletType.tron); @computed bool get isEnabledBuyAction => !_settingsStore.disableBuy && _wallet.type != WalletType.haven; diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index faa49dfc4..526ff0335 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -1,3 +1,7 @@ +import 'package:cake_wallet/tron/tron.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/transaction_info.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; import 'package:cake_wallet/entities/transaction_description.dart'; @@ -14,10 +18,7 @@ import 'package:cake_wallet/utils/date_formatter.dart'; import 'package:cake_wallet/view_model/send/send_view_model.dart'; import 'package:collection/collection.dart'; import 'package:cw_core/transaction_direction.dart'; -import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/transaction_priority.dart'; -import 'package:cw_core/wallet_base.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; import 'package:intl/src/intl/date_format.dart'; import 'package:mobx/mobx.dart'; @@ -71,6 +72,9 @@ abstract class TransactionDetailsViewModelBase with Store { case WalletType.solana: _addSolanaListItems(tx, dateFormat); break; + case WalletType.tron: + _addTronListItems(tx, dateFormat); + break; default: break; } @@ -160,6 +164,8 @@ abstract class TransactionDetailsViewModelBase with Store { return 'https://polygonscan.com/tx/${txId}'; case WalletType.solana: return 'https://solscan.io/tx/${txId}'; + case WalletType.tron: + return 'https://tronscan.org/#/transaction/${txId}'; default: return ''; } @@ -186,6 +192,8 @@ abstract class TransactionDetailsViewModelBase with Store { return S.current.view_transaction_on + 'polygonscan.com'; case WalletType.solana: return S.current.view_transaction_on + 'solscan.io'; + case WalletType.tron: + return S.current.view_transaction_on + 'tronscan.org'; default: return ''; } @@ -339,20 +347,19 @@ abstract class TransactionDetailsViewModelBase with Store { transactionInfo.inputAddresses?.length ?? 1, transactionInfo.outputAddresses?.length ?? 1); - RBFListItems.add(StandartListItem( - title: S.current.old_fee, - value: tx.feeFormatted() ?? '0.0')); + RBFListItems.add(StandartListItem(title: S.current.old_fee, value: tx.feeFormatted() ?? '0.0')); final priorities = priorityForWalletType(wallet.type); final selectedItem = priorities.indexOf(sendViewModel.transactionPriority); - final customItem = priorities.firstWhereOrNull( - (element) => element == sendViewModel.bitcoinTransactionPriorityCustom); + final customItem = priorities + .firstWhereOrNull((element) => element == sendViewModel.bitcoinTransactionPriorityCustom); final customItemIndex = customItem != null ? priorities.indexOf(customItem) : null; final maxCustomFeeRate = sendViewModel.maxCustomFeeRate?.toDouble(); RBFListItems.add(StandardPickerListItem( title: S.current.estimated_new_fee, - value: bitcoin!.formatterBitcoinAmountToString(amount: newFee) + ' ${walletTypeToCryptoCurrency(wallet.type)}', + value: bitcoin!.formatterBitcoinAmountToString(amount: newFee) + + ' ${walletTypeToCryptoCurrency(wallet.type)}', items: priorityForWalletType(wallet.type), customValue: settingsStore.customBitcoinFeeRate.toDouble(), maxValue: maxCustomFeeRate, @@ -378,6 +385,27 @@ abstract class TransactionDetailsViewModelBase with Store { } } + void _addTronListItems(TransactionInfo tx, DateFormat dateFormat) { + final _items = [ + StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.id), + StandartListItem( + title: S.current.transaction_details_date, value: dateFormat.format(tx.date)), + StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()), + if (tx.feeFormatted()?.isNotEmpty ?? false) + StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!), + if (showRecipientAddress && tx.to != null) + StandartListItem( + title: S.current.transaction_details_recipient_address, + value: tron!.getTronBase58Address(tx.to!, wallet)), + if (tx.from != null) + StandartListItem( + title: S.current.transaction_details_source_address, + value: tron!.getTronBase58Address(tx.from!, wallet)), + ]; + + items.addAll(_items); + } + @action Future _checkForRBF() async { if (wallet.type == WalletType.bitcoin && @@ -392,10 +420,10 @@ abstract class TransactionDetailsViewModelBase with Store { newFee = priority == bitcoin!.getBitcoinTransactionPriorityCustom() && value != null ? bitcoin!.getEstimatedFeeWithFeeRate(wallet, value.round(), transactionInfo.amount) : bitcoin!.getFeeAmountForPriority( - wallet, - priority, - transactionInfo.inputAddresses?.length ?? 1, - transactionInfo.outputAddresses?.length ?? 1); + wallet, + priority, + transactionInfo.inputAddresses?.length ?? 1, + transactionInfo.outputAddresses?.length ?? 1); return bitcoin!.formatterBitcoinAmountToString(amount: newFee); } diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index 20980f5f0..f6e1359e1 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -12,6 +12,7 @@ import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; +import 'package:cake_wallet/tron/tron.dart'; import 'package:cake_wallet/utils/list_item.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_account_list_header.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_header.dart'; @@ -175,6 +176,21 @@ class SolanaURI extends PaymentURI { } } +class TronURI extends PaymentURI { + TronURI({required String amount, required String address}) + : super(amount: amount, address: address); + + @override + String toString() { + var base = 'tron:' + address; + if (amount.isNotEmpty) { + base += '?amount=${amount.replaceAll(',', '.')}'; + } + + return base; + } +} + abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewModel with Store { WalletAddressListViewModelBase({ required AppStore appStore, @@ -273,6 +289,10 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo return SolanaURI(amount: amount, address: address.address); } + if (wallet.type == WalletType.tron) { + return TronURI(amount: amount, address: address.address); + } + throw Exception('Unexpected type: ${type.toString()}'); } @@ -348,6 +368,12 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo addressList.add(WalletAddressListItem(isPrimary: true, name: null, address: primaryAddress)); } + if (wallet.type == WalletType.tron) { + final primaryAddress = tron!.getAddress(wallet); + + addressList.add(WalletAddressListItem(isPrimary: true, name: null, address: primaryAddress)); + } + if (searchText.isNotEmpty) { return ObservableList.of(addressList.where((item) { if (item is WalletAddressListItem) { diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart index c33c85504..6b5ae5559 100644 --- a/lib/view_model/wallet_keys_view_model.dart +++ b/lib/view_model/wallet_keys_view_model.dart @@ -118,7 +118,8 @@ abstract class WalletKeysViewModelBase with Store { } if (isEVMCompatibleChain(_appStore.wallet!.type) || - _appStore.wallet!.type == WalletType.solana) { + _appStore.wallet!.type == WalletType.solana || + _appStore.wallet!.type == WalletType.tron) { items.addAll([ if (_appStore.wallet!.privateKey != null) StandartListItem(title: S.current.private_key, value: _appStore.wallet!.privateKey!), @@ -175,6 +176,8 @@ abstract class WalletKeysViewModelBase with Store { return 'polygon-wallet'; case WalletType.solana: return 'solana-wallet'; + case WalletType.tron: + return 'tron-wallet'; default: throw Exception('Unexpected wallet type: ${_appStore.wallet!.toString()}'); } diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart index 8b19108ec..e19efabc5 100644 --- a/lib/view_model/wallet_new_vm.dart +++ b/lib/view_model/wallet_new_vm.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/solana/solana.dart'; +import 'package:cake_wallet/tron/tron.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/monero/monero.dart'; @@ -43,6 +44,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { return 16; } return 25; + case WalletType.tron: case WalletType.solana: case WalletType.polygon: case WalletType.ethereum: @@ -79,6 +81,8 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { return polygon!.createPolygonNewWalletCredentials(name: name); case WalletType.solana: return solana!.createSolanaNewWalletCredentials(name: name); + case WalletType.tron: + return tron!.createTronNewWalletCredentials(name: name); default: throw Exception('Unexpected type: ${type.toString()}'); } diff --git a/lib/view_model/wallet_restore_view_model.dart b/lib/view_model/wallet_restore_view_model.dart index 21339f1ae..e19a83bc3 100644 --- a/lib/view_model/wallet_restore_view_model.dart +++ b/lib/view_model/wallet_restore_view_model.dart @@ -6,6 +6,7 @@ import 'package:cw_core/nano_account_info_response.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/solana/solana.dart'; +import 'package:cake_wallet/tron/tron.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/store/app_store.dart'; @@ -34,7 +35,8 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { type == WalletType.polygon || type == WalletType.nano || type == WalletType.banano || - type == WalletType.solana, + type == WalletType.solana || + type == WalletType.tron, isButtonEnabled = false, mode = WalletRestoreMode.seed, super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: true) { @@ -48,6 +50,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { case WalletType.nano: case WalletType.banano: case WalletType.solana: + case WalletType.tron: availableModes = [WalletRestoreMode.seed, WalletRestoreMode.keys]; break; default: @@ -127,6 +130,12 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { mnemonic: seed, password: password, ); + case WalletType.tron: + return tron!.createTronRestoreWalletFromSeedCredentials( + name: name, + mnemonic: seed, + password: password, + ); default: break; } @@ -185,6 +194,12 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store { password: password, privateKey: options['private_key'] as String, ); + case WalletType.tron: + return tron!.createTronRestoreWalletFromPrivateKey( + name: name, + password: password, + privateKey: options['private_key'] as String, + ); default: break; } diff --git a/model_generator.sh b/model_generator.sh index 8a6098621..ee88644b6 100755 --- a/model_generator.sh +++ b/model_generator.sh @@ -6,6 +6,7 @@ cd cw_haven && flutter pub get && flutter packages pub run build_runner build -- cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_bitcoin_cash && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_solana && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. +cd cw_tron && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd .. cd cw_ethereum && flutter pub get && cd .. cd cw_polygon && flutter pub get && cd .. flutter packages pub run build_runner build --delete-conflicting-outputs diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 3ec3e7978..bdfa70964 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -158,6 +158,7 @@ flutter: - assets/nano_pow_node_list.yml - assets/polygon_node_list.yml - assets/solana_node_list.yml + - assets/tron_node_list.yml - assets/text/ - assets/faq/ - assets/animation/ diff --git a/scripts/android/pubspec_gen.sh b/scripts/android/pubspec_gen.sh index d238052fe..bc7985506 100755 --- a/scripts/android/pubspec_gen.sh +++ b/scripts/android/pubspec_gen.sh @@ -10,7 +10,7 @@ case $APP_ANDROID_TYPE in CONFIG_ARGS="--monero" ;; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --haven --ethereum --polygon --nano --bitcoinCash --solana" + CONFIG_ARGS="--monero --bitcoin --haven --ethereum --polygon --nano --bitcoinCash --solana --tron" ;; $HAVEN) CONFIG_ARGS="--haven" diff --git a/scripts/ios/app_config.sh b/scripts/ios/app_config.sh index 9f59d6632..ab7fbd422 100755 --- a/scripts/ios/app_config.sh +++ b/scripts/ios/app_config.sh @@ -28,7 +28,7 @@ case $APP_IOS_TYPE in CONFIG_ARGS="--monero" ;; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --haven --ethereum --polygon --nano --bitcoinCash --solana" + CONFIG_ARGS="--monero --bitcoin --haven --ethereum --polygon --nano --bitcoinCash --solana --tron" ;; $HAVEN) diff --git a/scripts/macos/app_config.sh b/scripts/macos/app_config.sh index bd1417c4b..a1143bb12 100755 --- a/scripts/macos/app_config.sh +++ b/scripts/macos/app_config.sh @@ -31,7 +31,7 @@ case $APP_MACOS_TYPE in $MONERO_COM) CONFIG_ARGS="--monero";; $CAKEWALLET) - CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana";; #--haven + CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron";; #--haven esac cp -rf pubspec_description.yaml pubspec.yaml diff --git a/tool/configure.dart b/tool/configure.dart index ceb0c9ccc..f136c9a2a 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -8,6 +8,7 @@ const bitcoinCashOutputPath = 'lib/bitcoin_cash/bitcoin_cash.dart'; const nanoOutputPath = 'lib/nano/nano.dart'; const polygonOutputPath = 'lib/polygon/polygon.dart'; const solanaOutputPath = 'lib/solana/solana.dart'; +const tronOutputPath = 'lib/tron/tron.dart'; const walletTypesPath = 'lib/wallet_types.g.dart'; const pubspecDefaultPath = 'pubspec_default.yaml'; const pubspecOutputPath = 'pubspec.yaml'; @@ -23,6 +24,7 @@ Future main(List args) async { final hasBanano = args.contains('${prefix}banano'); final hasPolygon = args.contains('${prefix}polygon'); final hasSolana = args.contains('${prefix}solana'); + final hasTron = args.contains('${prefix}tron'); await generateBitcoin(hasBitcoin); await generateMonero(hasMonero); @@ -32,6 +34,7 @@ Future main(List args) async { await generateNano(hasNano); await generatePolygon(hasPolygon); await generateSolana(hasSolana); + await generateTron(hasTron); // await generateBanano(hasEthereum); await generatePubspec( @@ -44,6 +47,7 @@ Future main(List args) async { hasBitcoinCash: hasBitcoinCash, hasPolygon: hasPolygon, hasSolana: hasSolana, + hasTron: hasTron, ); await generateWalletTypes( hasMonero: hasMonero, @@ -55,6 +59,7 @@ Future main(List args) async { hasBitcoinCash: hasBitcoinCash, hasPolygon: hasPolygon, hasSolana: hasSolana, + hasTron: hasTron, ); } @@ -1024,6 +1029,79 @@ abstract class Solana { await outputFile.writeAsString(output); } +Future generateTron(bool hasImplementation) async { + final outputFile = File(tronOutputPath); + const tronCommonHeaders = """ +import 'package:cake_wallet/view_model/send/output.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/output_info.dart'; +import 'package:cw_core/transaction_info.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_credentials.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_service.dart'; +import 'package:hive/hive.dart'; + +"""; + const tronCWHeaders = """ +import 'package:cw_evm/evm_chain_mnemonics.dart'; +import 'package:cw_tron/tron_transaction_credentials.dart'; +import 'package:cw_tron/tron_transaction_info.dart'; +import 'package:cw_tron/tron_wallet_creation_credentials.dart'; + +import 'package:cw_tron/tron_client.dart'; +import 'package:cw_tron/tron_token.dart'; +import 'package:cw_tron/tron_wallet.dart'; +import 'package:cw_tron/tron_wallet_service.dart'; + +"""; + const tronCwPart = "part 'cw_tron.dart';"; + const tronContent = """ +abstract class Tron { + List getTronWordList(String language); + WalletService createTronWalletService(Box walletInfoSource); + WalletCredentials createTronNewWalletCredentials({required String name, WalletInfo? walletInfo}); + WalletCredentials createTronRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password}); + WalletCredentials createTronRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password}); + String getAddress(WalletBase wallet); + + Object createTronTransactionCredentials( + List outputs, { + required CryptoCurrency currency, + }); + + List getTronTokenCurrencies(WalletBase wallet); + Future addTronToken(WalletBase wallet, CryptoCurrency token, String contractAddress); + Future deleteTronToken(WalletBase wallet, CryptoCurrency token); + Future getTronToken(WalletBase wallet, String contractAddress); + + double getTransactionAmountRaw(TransactionInfo transactionInfo); + CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction); + String getTokenAddress(CryptoCurrency asset); + String getTronBase58Address(String hexAddress, WalletBase wallet); + + String? getTronNativeEstimatedFee(WalletBase wallet); + String? getTronTRC20EstimatedFee(WalletBase wallet); +} + """; + + const tronEmptyDefinition = 'Tron? tron;\n'; + const tronCWDefinition = 'Tron? tron = CWTron();\n'; + + final output = '$tronCommonHeaders\n' + + (hasImplementation ? '$tronCWHeaders\n' : '\n') + + (hasImplementation ? '$tronCwPart\n\n' : '\n') + + (hasImplementation ? tronCWDefinition : tronEmptyDefinition) + + '\n' + + tronContent; + + if (outputFile.existsSync()) { + await outputFile.delete(); + } + + await outputFile.writeAsString(output); +} + Future generatePubspec( {required bool hasMonero, required bool hasBitcoin, @@ -1033,7 +1111,8 @@ Future generatePubspec( required bool hasBanano, required bool hasBitcoinCash, required bool hasPolygon, - required bool hasSolana}) async { + required bool hasSolana, + required bool hasTron}) async { const cwCore = """ cw_core: path: ./cw_core @@ -1082,6 +1161,10 @@ Future generatePubspec( cw_evm: path: ./cw_evm """; + const cwTron = """ + cw_tron: + path: ./cw_tron + """; final inputFile = File(pubspecOutputPath); final inputText = await inputFile.readAsString(); final inputLines = inputText.split('\n'); @@ -1121,6 +1204,10 @@ Future generatePubspec( output += '\n$cwSolana'; } + if (hasTron) { + output += '\n$cwTron'; + } + if (hasHaven && !hasMonero) { output += '\n$cwSharedExternal\n$cwHaven'; } else if (hasHaven) { @@ -1152,7 +1239,8 @@ Future generateWalletTypes( required bool hasBanano, required bool hasBitcoinCash, required bool hasPolygon, - required bool hasSolana}) async { + required bool hasSolana, + required bool hasTron}) async { final walletTypesFile = File(walletTypesPath); if (walletTypesFile.existsSync()) { @@ -1191,6 +1279,10 @@ Future generateWalletTypes( outputContent += '\tWalletType.solana,\n'; } + if (hasTron) { + outputContent += '\tWalletType.tron,\n'; + } + if (hasNano) { outputContent += '\tWalletType.nano,\n'; } diff --git a/tool/generate_secrets_config.dart b/tool/generate_secrets_config.dart index 8745c2933..6aaa39b7c 100644 --- a/tool/generate_secrets_config.dart +++ b/tool/generate_secrets_config.dart @@ -6,6 +6,7 @@ import 'utils/utils.dart'; const configPath = 'tool/.secrets-config.json'; const evmChainsConfigPath = 'tool/.evm-secrets-config.json'; const solanaConfigPath = 'tool/.solana-secrets-config.json'; +const tronConfigPath = 'tool/.tron-secrets-config.json'; Future main(List args) async => generateSecretsConfig(args); @@ -20,9 +21,10 @@ Future generateSecretsConfig(List args) async { final configFile = File(configPath); final evmChainsConfigFile = File(evmChainsConfigPath); final solanaConfigFile = File(solanaConfigPath); + final tronConfigFile = File(tronConfigPath); final secrets = {}; - + secrets.addAll(extraInfo); secrets.removeWhere((key, dynamic value) { if (key.contains('--')) { @@ -78,4 +80,18 @@ Future generateSecretsConfig(List args) async { secretsJson = JsonEncoder.withIndent(' ').convert(secrets); await solanaConfigFile.writeAsString(secretsJson); + + secrets.clear(); + + SecretKey.tronSecrets.forEach((sec) { + if (secrets[sec.name] != null) { + return; + } + + secrets[sec.name] = sec.generate(); + }); + + secretsJson = JsonEncoder.withIndent(' ').convert(secrets); + + await tronConfigFile.writeAsString(secretsJson); } diff --git a/tool/import_secrets_config.dart b/tool/import_secrets_config.dart index 02061669b..b2f3ca691 100644 --- a/tool/import_secrets_config.dart +++ b/tool/import_secrets_config.dart @@ -10,6 +10,9 @@ const evmChainsOutputPath = 'cw_evm/lib/.secrets.g.dart'; const solanaConfigPath = 'tool/.solana-secrets-config.json'; const solanaOutputPath = 'cw_solana/lib/.secrets.g.dart'; + +const tronConfigPath = 'tool/.tron-secrets-config.json'; +const tronOutputPath = 'cw_tron/lib/.secrets.g.dart'; Future main(List args) async => importSecretsConfig(); Future importSecretsConfig() async { @@ -29,6 +32,11 @@ Future importSecretsConfig() async { final solanaOutput = solanaInput.keys.fold('', (String acc, String val) => acc + generateConst(val, solanaInput)); + final tronOutputFile = File(tronOutputPath); + final tronInput = json.decode(File(tronConfigPath).readAsStringSync()) as Map; + final tronOutput = + tronInput.keys.fold('', (String acc, String val) => acc + generateConst(val, tronInput)); + if (outputFile.existsSync()) { await outputFile.delete(); } @@ -46,4 +54,10 @@ Future importSecretsConfig() async { } await solanaOutputFile.writeAsString(solanaOutput); + + if (tronOutputFile.existsSync()) { + await tronOutputFile.delete(); + } + + await tronOutputFile.writeAsString(tronOutput); } diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index 5d5e61cec..542e91b38 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -50,6 +50,10 @@ class SecretKey { SecretKey('ankrApiKey', () => ''), ]; + static final tronSecrets = [ + SecretKey('tronGridApiKey', () => ''), + ]; + final String name; final String Function() generate; } From d5543ceb08b055d5c0b3342ba7a3b5ca9983a8cb Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Sat, 4 May 2024 05:35:15 -0700 Subject: [PATCH 205/241] nano derivation fix (#1428) --- lib/nano/cw_nano.dart | 54 ++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/lib/nano/cw_nano.dart b/lib/nano/cw_nano.dart index 13800cff6..ad02d2ccb 100644 --- a/lib/nano/cw_nano.dart +++ b/lib/nano/cw_nano.dart @@ -228,35 +228,47 @@ class CWNanoUtil extends NanoUtil { }) async { NanoClient nanoClient = NanoClient(); nanoClient.connect(node); - late String publicAddress; + String? publicAddress; - if (seedKey != null) { - if (seedKey.length == 64) { - try { - mnemonic = NanoDerivations.standardSeedToMnemonic(seedKey); - } catch (e) { - print("not a valid 'nano' seed key"); + if (seedKey == null && mnemonic == null) { + throw Exception("One of seed key OR mnemonic must be provided!"); + } + + try { + if (seedKey != null) { + if (seedKey.length == 64) { + try { + mnemonic = NanoDerivations.standardSeedToMnemonic(seedKey); + } catch (e) { + print("not a valid 'nano' seed key"); + } + } + if (derivationType == DerivationType.bip39) { + publicAddress = await NanoDerivations.hdSeedToAddress(seedKey, index: 0); + } else if (derivationType == DerivationType.nano) { + publicAddress = await NanoDerivations.standardSeedToAddress(seedKey, index: 0); } } + if (derivationType == DerivationType.bip39) { - publicAddress = await NanoDerivations.hdSeedToAddress(seedKey, index: 0); - } else if (derivationType == DerivationType.nano) { - publicAddress = await NanoDerivations.standardSeedToAddress(seedKey, index: 0); + if (mnemonic != null) { + seedKey = await NanoDerivations.hdMnemonicListToSeed(mnemonic.split(' ')); + publicAddress = await NanoDerivations.hdSeedToAddress(seedKey, index: 0); + } } - } - if (derivationType == DerivationType.bip39) { - if (mnemonic != null) { - seedKey = await NanoDerivations.hdMnemonicListToSeed(mnemonic.split(' ')); - publicAddress = await NanoDerivations.hdSeedToAddress(seedKey, index: 0); + if (derivationType == DerivationType.nano) { + if (mnemonic != null) { + seedKey = await NanoDerivations.standardMnemonicToSeed(mnemonic); + publicAddress = await NanoDerivations.standardSeedToAddress(seedKey, index: 0); + } } - } + } catch (_) {} - if (derivationType == DerivationType.nano) { - if (mnemonic != null) { - seedKey = await NanoDerivations.standardMnemonicToSeed(mnemonic); - publicAddress = await NanoDerivations.standardSeedToAddress(seedKey, index: 0); - } + if (publicAddress == null) { + // we couldn't derive a public address for the derivation type provided + // i.e. a bip39 seed was provided and we were instructed to derive a "nano" type address + return null; } AccountInfoResponse? accountInfo = await nanoClient.getAccountInfo(publicAddress); From 043d7d7c8bcfa2e85ea9ad6b0c6bfef9bca40a00 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Sat, 4 May 2024 15:35:26 +0300 Subject: [PATCH 206/241] Generic fixes (#1427) * fix for private key solana * Fix Solana wallet open --- cw_solana/lib/solana_wallet.dart | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart index f3eef465c..6692b65a6 100644 --- a/cw_solana/lib/solana_wallet.dart +++ b/cw_solana/lib/solana_wallet.dart @@ -145,12 +145,17 @@ abstract class SolanaWalletBase Future getWalletPair({String? mnemonic, String? privateKey}) async { assert(mnemonic != null || privateKey != null); - if (privateKey != null) { - final privateKeyBytes = base58decode(privateKey); - return await Wallet.fromPrivateKeyBytes(privateKey: privateKeyBytes.take(32).toList()); + if (mnemonic != null) { + return Wallet.fromMnemonic(mnemonic, account: 0, change: 0); } - return Wallet.fromMnemonic(mnemonic!, account: 0, change: 0); + try { + final privateKeyBytes = base58decode(privateKey!); + return await Wallet.fromPrivateKeyBytes(privateKey: privateKeyBytes.take(32).toList()); + } catch (_) { + final privateKeyBytes = HEX.decode(privateKey!); + return await Wallet.fromPrivateKeyBytes(privateKey: privateKeyBytes); + } } @override @@ -360,7 +365,7 @@ abstract class SolanaWalletBase String toJSON() => json.encode({ 'mnemonic': _mnemonic, - 'private_key': privateKey, + 'private_key': _hexPrivateKey, 'balance': balance[currency]!.toJSON(), }); From 5eabdcdca1973fc892aef540d1fb3efb91eed89a Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Sat, 4 May 2024 20:44:50 -0500 Subject: [PATCH 207/241] Cw 604 integrate bitcoin ledger (#1407) * CW-503 Prepare Ledger integration * CW-503 Revert Tor ignore * CW-503 Add Connect Device Page * CW-503 Add createWalletFromDevice for monero * CW-503 Add Connect Device Page * CW-503 Add Connect Device Page * CW-503 Add Debug Options * CW-503 Add proper hardware wallet selection screen * CW-503 Minor design changes on connect_device_page * CW-503 Add Create Wallet from Ledger * CW-503 Spent Ledger ETH Funds * CW-503 Minor fixes * CW-503 Fix Merge conflicts * CW-503 Fix Merge conflicts * CW-503 Fix Merge conflicts * CW-503 Fix minor conflicts * CW-503 Improve Ledger BLE Communication * CW-503 Improve Ledger BLE Communication * CW-503 Rollback Monero Test code * CW-503 Fix Execution failed for task :app:checkReleaseDuplicateClasses * CW-503 Better Error-Exceptions * CW-503 Add SetPinScreen before restore from hardware-wallet * CW-503 override web3dart to use cake's git hosted version * CW-503 Implement ledger sign messages * CW-503 Implement ledger sign messages and send erc20 tokens * CW-503 Fix merge conflicts * CW-503 Fix merge conflicts * CW-503 Use dep override for ledger_flutter * CW-503 Ledger ERC20 finalisation * CW-503 More graceful error handling * CW-503 Even more graceful error handling & remove debug code * CW-503 Minor Changes for Vik * CW-503 Fix USB connection * CW-503 Maybe this overrides web3dart finally * Indicate Loading on the first 5 Wallet Accounts * Prepare Ledger Bitcoin * Fix conflicts with main * Add Bluetooth permission to iOS [skip ci] * add privacyinfo for ios [skip ci] * update PrivacyInfo.xcprivacy [scip ci] * ios shit [skip ci] * Improve bitcoin xpub * Resolve open Todos regarding iOS Support * Minor debug * Remove erc20 dependency to have more granular control over the tx UX * Create Bitcoin Wallets using xpub * Create Bitcoin Wallets using xpub * Better error handling * Improve Ledger account handling * Add Bitcoin Support for Ledger * Add Bitcoin Support for Ledger * Add Bitcoin Support for Ledger * Implement requested Changes * Implement requested Changes * Minor fix * Implement requested Changes * Implement requested Changes * Add comment to remind me * Enable RBF for Bitcoin Ledger * Fix merge conflicts * Update wallet_info.dart * Cw 503 ledger support (#1310) * CW-503 Prepare Ledger integration * CW-503 Revert Tor ignore * CW-503 Add Connect Device Page * CW-503 Add createWalletFromDevice for monero * CW-503 Add Connect Device Page * CW-503 Add Connect Device Page * CW-503 Add Debug Options * CW-503 Add proper hardware wallet selection screen * CW-503 Minor design changes on connect_device_page * CW-503 Add Create Wallet from Ledger * CW-503 Spent Ledger ETH Funds * CW-503 Minor fixes * CW-503 Fix Merge conflicts * CW-503 Fix Merge conflicts * CW-503 Fix Merge conflicts * CW-503 Fix minor conflicts * CW-503 Improve Ledger BLE Communication * CW-503 Improve Ledger BLE Communication * CW-503 Rollback Monero Test code * CW-503 Fix Execution failed for task :app:checkReleaseDuplicateClasses * CW-503 Better Error-Exceptions * CW-503 Add SetPinScreen before restore from hardware-wallet * CW-503 override web3dart to use cake's git hosted version * CW-503 Implement ledger sign messages * CW-503 Implement ledger sign messages and send erc20 tokens * CW-503 Fix merge conflicts * CW-503 Fix merge conflicts * CW-503 Use dep override for ledger_flutter * CW-503 Ledger ERC20 finalisation * CW-503 More graceful error handling * CW-503 Even more graceful error handling & remove debug code * CW-503 Minor Changes for Vik * CW-503 Fix USB connection * CW-503 Maybe this overrides web3dart finally * Indicate Loading on the first 5 Wallet Accounts * Fix conflicts with main * Add Bluetooth permission to iOS [skip ci] * add privacyinfo for ios [skip ci] * update PrivacyInfo.xcprivacy [scip ci] * ios shit [skip ci] * Resolve open Todos regarding iOS Support * Remove erc20 dependency to have more granular control over the tx UX * Better error handling * Improve Ledger account handling * Implement requested Changes * Implement requested Changes * Implement requested Changes * Implement requested Changes * Fix merge conflicts * Update wallet_info.dart --------- Co-authored-by: Omar Hatem * Fix merge conflicts * Fix merge conflicts * Minor Fix to derivations * Update cw_bitcoin/lib/bitcoin_wallet.dart [skip ci] * Update cw_bitcoin/lib/bitcoin_wallet.dart [skip ci] * Update cw_bitcoin/lib/electrum_wallet.dart [skip ci] * Fix backward compatibility issues * Merge Tron * Fix Tron with HW changes * fix ble on iOS fix tron address validation --------- Co-authored-by: Omar Hatem --- android/app/src/main/AndroidManifestBase.xml | 20 ++ android/build.gradle | 2 +- assets/images/bluetooth.png | Bin 0 -> 1809 bytes assets/images/ledger_nano.png | Bin 0 -> 1463 bytes assets/images/usb.png | Bin 0 -> 2490 bytes .../lib/bitcoin_hardware_wallet_service.dart | 43 +++ cw_bitcoin/lib/bitcoin_wallet.dart | 118 +++++-- .../bitcoin_wallet_creation_credentials.dart | 20 +- cw_bitcoin/lib/bitcoin_wallet_service.dart | 28 +- cw_bitcoin/lib/electrum_derivations.dart | 2 +- cw_bitcoin/lib/electrum_wallet.dart | 163 +++++++-- cw_bitcoin/lib/electrum_wallet_snapshot.dart | 8 +- cw_bitcoin/lib/litecoin_wallet.dart | 6 +- cw_bitcoin/lib/litecoin_wallet_service.dart | 7 +- cw_bitcoin/lib/psbt_transaction_builder.dart | 96 ++++++ cw_bitcoin/pubspec.lock | 75 +++- cw_bitcoin/pubspec.yaml | 4 + .../lib/src/bitcoin_cash_wallet.dart | 8 +- .../lib/src/bitcoin_cash_wallet_service.dart | 7 +- .../lib/hardware/device_connection_type.dart | 28 ++ .../device_not_connected_exception.dart | 7 + .../lib/hardware/hardware_account_data.dart | 19 + cw_core/lib/hive_type_ids.dart | 1 + cw_core/lib/wallet_base.dart | 4 +- cw_core/lib/wallet_credentials.dart | 2 + cw_core/lib/wallet_info.dart | 21 +- cw_core/lib/wallet_service.dart | 4 +- cw_ethereum/lib/ethereum_wallet_service.dart | 26 +- cw_ethereum/pubspec.yaml | 6 + cw_evm/lib/contract/erc20.dart | 209 +++++++++++ cw_evm/lib/evm_chain_client.dart | 53 ++- cw_evm/lib/evm_chain_exceptions.dart | 2 + .../evm_chain_hardware_wallet_service.dart | 35 ++ .../evm_chain_transaction_credentials.dart | 1 + cw_evm/lib/evm_chain_wallet.dart | 36 +- ...evm_chain_wallet_creation_credentials.dart | 11 + cw_evm/lib/evm_chain_wallet_service.dart | 6 +- cw_evm/lib/evm_ledger_credentials.dart | 103 ++++++ cw_evm/pubspec.yaml | 15 +- cw_haven/lib/haven_wallet_service.dart | 8 +- cw_monero/lib/api/signatures.dart | 3 + cw_monero/lib/api/types.dart | 3 + cw_monero/lib/api/wallet_manager.dart | 37 ++ cw_monero/lib/monero_wallet.dart | 2 +- cw_monero/lib/monero_wallet_service.dart | 7 +- cw_nano/lib/nano_wallet_service.dart | 7 +- cw_polygon/lib/polygon_wallet_service.dart | 24 ++ cw_polygon/pubspec.yaml | 5 + cw_solana/lib/solana_wallet_service.dart | 11 +- cw_tron/lib/tron_wallet.dart | 2 +- cw_tron/lib/tron_wallet_service.dart | 16 +- how_to_add_new_wallet_type.md | 3 +- ios/Podfile.lock | 11 + ios/Runner.xcodeproj/project.pbxproj | 4 + ios/Runner/InfoBase.plist | 14 +- ios/Runner/PrivacyInfo.xcprivacy | 24 ++ lib/bitcoin/cw_bitcoin.dart | 30 +- lib/buy/buy_provider.dart | 3 + lib/buy/dfx/dfx_buy_provider.dart | 24 +- lib/buy/moonpay/moonpay_provider.dart | 3 +- lib/buy/onramper/onramper_buy_provider.dart | 2 +- lib/buy/robinhood/robinhood_buy_provider.dart | 25 +- lib/buy/wyre/wyre_buy_provider.dart | 2 +- lib/core/address_validator.dart | 5 +- lib/core/wallet_creation_service.dart | 15 + lib/di.dart | 325 +++++++++--------- lib/ethereum/cw_ethereum.dart | 33 +- lib/main.dart | 6 +- lib/polygon/cw_polygon.dart | 62 +++- lib/router.dart | 198 +++++++---- lib/routes.dart | 3 + .../connect_device/connect_device_page.dart | 221 ++++++++++++ .../connect_device/debug_device_page.dart | 212 ++++++++++++ .../select_hardware_wallet_account_page.dart | 256 ++++++++++++++ .../connect_device/widgets/device_tile.dart | 78 +++++ .../desktop_sidebar/side_menu_item.dart | 1 + .../desktop_sidebar_wrapper.dart | 3 +- .../screens/dashboard/pages/balance_page.dart | 11 + .../new_wallet/new_wallet_type_page.dart | 150 ++++---- .../new_wallet/widgets/select_button.dart | 71 ++-- .../screens/restore/restore_options_page.dart | 114 +++--- lib/src/screens/send/send_page.dart | 68 +++- .../settings/connection_sync_page.dart | 11 +- .../dashboard/dashboard_view_model.dart | 4 +- .../hardware_wallet/ledger_view_model.dart | 66 ++++ lib/view_model/send/send_view_model.dart | 25 +- .../send/send_view_model_state.dart | 1 + lib/view_model/wallet_creation_vm.dart | 3 +- .../wallet_hardware_restore_view_model.dart | 110 ++++++ macos/Runner/InfoBase.plist | 17 + pubspec_base.yaml | 9 + res/values/strings_ar.arb | 14 + res/values/strings_bg.arb | 14 + res/values/strings_cs.arb | 14 + res/values/strings_de.arb | 14 + res/values/strings_en.arb | 14 + res/values/strings_es.arb | 14 + res/values/strings_fr.arb | 14 + res/values/strings_ha.arb | 14 + res/values/strings_hi.arb | 14 + res/values/strings_hr.arb | 14 + res/values/strings_id.arb | 14 + res/values/strings_it.arb | 14 + res/values/strings_ja.arb | 14 + res/values/strings_ko.arb | 14 + res/values/strings_my.arb | 14 + res/values/strings_nl.arb | 14 + res/values/strings_pl.arb | 14 + res/values/strings_pt.arb | 14 + res/values/strings_ru.arb | 14 + res/values/strings_th.arb | 14 + res/values/strings_tl.arb | 14 + res/values/strings_tr.arb | 14 + res/values/strings_uk.arb | 14 + res/values/strings_ur.arb | 14 + res/values/strings_yo.arb | 14 + res/values/strings_zh.arb | 14 + tool/configure.dart | 34 +- 118 files changed, 3363 insertions(+), 579 deletions(-) create mode 100644 assets/images/bluetooth.png create mode 100644 assets/images/ledger_nano.png create mode 100644 assets/images/usb.png create mode 100644 cw_bitcoin/lib/bitcoin_hardware_wallet_service.dart create mode 100644 cw_bitcoin/lib/psbt_transaction_builder.dart create mode 100644 cw_core/lib/hardware/device_connection_type.dart create mode 100644 cw_core/lib/hardware/device_not_connected_exception.dart create mode 100644 cw_core/lib/hardware/hardware_account_data.dart create mode 100644 cw_evm/lib/contract/erc20.dart create mode 100644 cw_evm/lib/evm_chain_hardware_wallet_service.dart create mode 100644 cw_evm/lib/evm_ledger_credentials.dart create mode 100644 ios/Runner/PrivacyInfo.xcprivacy create mode 100644 lib/src/screens/connect_device/connect_device_page.dart create mode 100644 lib/src/screens/connect_device/debug_device_page.dart create mode 100644 lib/src/screens/connect_device/select_hardware_wallet_account_page.dart create mode 100644 lib/src/screens/connect_device/widgets/device_tile.dart create mode 100644 lib/view_model/hardware_wallet/ledger_view_model.dart create mode 100644 lib/view_model/wallet_hardware_restore_view_model.dart diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index 485f049e8..23207d629 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -9,6 +9,26 @@ + + + + + + + + + + + + + + @~0drDELIAGL9O(c600d`2O+f$vv5yPiYq2%h9LkSeAb$aHE4UTp-UvtP z0bxgQNw4vxQIFgTw!G7M3npY^yl>3z{MgJ#ie%Yi$;_L1^PTr&1K@Bt91e%W;cz%U zHW*mK$agEF%wv!7HTU`R+V7O|ks<>GSm%<`W&p6wC8f{+ZR~JKDKC*sc&?+GL9sXX{>a7nQnpj-T27@?qgmG!EU zRP9(Dhp<>>>_GKamvu?FV{tb_!o+R>#`!*BSg_R}e!E-%g~+-j#vt+E7rOya?TFR0 z6g`p;c^Pj{_2G;zsRiB^%^f9AA}*-5TUw+U;p%W!W`swR%Y{D152EF%7{P(En{P#8 zX8;;O`~@?Vm4-&hPpobxt&s9lPiHxJdyFvoV$70?yGx>naJ5|860&HFbnr2l?(e^o z*x`(K6LBNlpp3=IKf(p1fW%c$wfxhG=W(JDST1gbgu5y~wYu5qZqnfgoZ_xkHTj4V z8H(xyjUb%O31N63Q}YwQ=HQm(zF*1Wt`a_OI%;gNK*VkhcCA8`SH?Y@Sl#d#%u>dB zjLrGn7lvRzb{xQAt6H9)>GV-B`F;=%$wCA;`CfyM9crksQ+^Q(Zly$pgf~)gXg&r> z@B-E6d&fYTe9lkqio3y~rt(HD;pjl72BCpyD2nAesB|#+NBbV%J}Q@nD;f)YwdDga zGyvR_h*m};t8}WnrD@QN)`X0dLW+Q{bb^54oJytB4I|3azZ3^%%ZEMjbL5ndIE0(c zv$;U&Fv@q?Dfj(xlbSn>=?_4?-al|><3`2P2?iBmge(}Ybh=?&gT~0@$|3_6YitOW zj@N{7(OgRey-n2ka#@a=oe^B?}&|K(pW5Mx`EFjwGZGMgYNL$9MU zrqe4%_lV))?2FqhC;0dPK>S#!WfdcHNTYll2AGfgwnBK@{v?lN4HvF z4MrOvH}Mn$abHP&NmHt`SBz6ZZ7_An7!%nm_!N3$^z#Sbz(245lyqTgG4c?`fEqQX z6UpUm+0>4D121Bo9!qdb#6_$rE@CEj)SDHGxHGs;$zHt!J7m~>qD(dNu?9vQ!ZNAD z_u%Y}j#OuyXg9!B>X5OXCI;^cBCb!ZcFO|GxE7^0GO5ETWK*4{$W(0xkV_rXkV$n0 z#bA?b>!2Ae29QY|%GPkor8;>rKe3{AxG^K;7 zLq2w!fSRsiFjNPXDLMo)>xK;j0# zfEu|%4O53P=WQ_rf#oOEo&_;(OQk|e)Bw1eE^6^9GLvuLZJsBVG&i+pAu$7>(!te4 zt;NSxnskL48o_V*m9>oYMdcZ2YLaK#_>C@vdZ@XDQ>Y?h(6*c7+;V zmOvpG`jCk`sp=7neFp@6!i;rnzz{2{a<6$duCg5bqU7-t41E-7$q#V}WUy4-nO9O( zp{`Gu^Jlg4{Fu_oZ(jgK%!e}m>Jq51q$RmNVG&BeNymTqx>_zNjls*h9Q>U+I%N`j zUeKlgtbk&Abvd=&d1b5qI*A!T2eK;XLJ;^`OV(3U8E1>j31j^Zu+8O!vD*M1v{g=) zGTa206UOofx56k`=5oTM>JaXXSuQ6`stsVG%L$X-r>7h0a>Ar=2bk@0!lcRoHn^NH z>2X1pxSTM??*N~(Q?Kg{%PyA_#`qo3?Kz}6!pCuAY>!x*w|~E=ckG-OF302!cq&FW zYF{Tv_Fq;hV6HYT|DCPF;cz${4u`|x`1trA%wM^0H~j||00000NkvXXu0mjfmUmu1 literal 0 HcmV?d00001 diff --git a/assets/images/ledger_nano.png b/assets/images/ledger_nano.png new file mode 100644 index 0000000000000000000000000000000000000000..bb61ba1750728b5584680110bd90727c3e195eca GIT binary patch literal 1463 zcmV;o1xWgdP)@~0drDELIAGL9O(c600d`2O+f$vv5yPXg70CCgwzCt2)>6E5>gQmA^0Admtb5#jNp4@T7ppl2?XCG zvl5I6&<#GdX&}HZO+ObEO*1LMh=4G`-``rVKYsMEJvYB3Y?P3=fUv>$ez#RZq5`4@ z-@`@;i3x}sd=J|sBqAWG;Ct94A+~^|gYRLBgjfPh1>eI436TYu4!%d$B}5WX{=8Yr zA+%KO;s)O%%Mv09c=gh?Iz{7ZP@ANJ?~zpr4n%;;XqSUOPd4}-hqO(kZL8W*oBBJ{ zMZ!5Ck^qg(A{ZiT5+Zd$ugrgVMbQNr?FO>c9Yq@h-ds8oLevz^Sb_$T1U&xZVRsr1 zJ_`~euLGv#;Lp2+SSw+c5TDq&AeIo1M6#hQAv%fG16V>d60L}_gzzL@6J`nFFmhJ} zOVG!N00~Rb!~R z=8tYgi|P$ufI;;41FB$<)CEZN4j!Mt6zm5I=z&2dB0!=#cvm=Wn1cNP7usNuRL6i( z{Q6>fSHthapnDIPE+Dk~eQYH0ZX+!L z2|n?jEf6;2ickuW4`UQu@fR>Yh@K;$@%xXrBlQl-R74&fqsgfA56-%Xccb14uM{BA zEd!$@>hlN_OU7jpDdFAgcUHrECl4{80i;VglQv`=1SnB`qAa@`Ra+Nfqg-vabO+{G z0%Y(Hw%2ZeB~+H1H4?EQh4{C^*+M})pda1`4Y&&mflN)GoE%-Dv;2NwLjj92!wVY3 zx&pGs*_Hla^-IN=(UotfRhJdA)yhhfx+DLx=`g+CR{c-D0*1)NW}$fDKS5JUI)iIe zoY@eL*r_akvqOD)X|#R+Z1%P6uPu)qOD0bx4arV#hN?UaZ{&lp?Hykk0rm)b+g1Q zASCk4FU(xHOA)RGweuS@MqvS(3<6)6sSdgwR4lNlSihG>JwWD3C|UIYvQG&$3o@rO zCRgk1m&CmSN-}c@79c?HHFz|LH}*o@roz+E1Q|Tn5c2jEr2rI;axTk6e^sYaz|-UZ zH-QO2^k{sz74=!!QiPFbu=Q;yG(reAP{& RfT{oh002ovPDHLkV1g$1iR}OY literal 0 HcmV?d00001 diff --git a/assets/images/usb.png b/assets/images/usb.png new file mode 100644 index 0000000000000000000000000000000000000000..1163c573dca2792b4b7afeed0e3a9aeb146b3f8a GIT binary patch literal 2490 zcmV;r2}SmaP)@~0drDELIAGL9O(c600d`2O+f$vv5yPi7QC^PRa&!L4UJx^4H=`K@Vm^t zbo4FwC1!xeyhtWzfQUMx;?_sPGj8i}Y!uK#z2}XIs-SEO4NDvNN%$pRpu)rV)u^fCC z?hJOVdj~>@|06w&Qa}*AG;yrQS@*qxs7~%Z*}*6UAPdm<8VmN`%?nisV2kfjDS-&; zU=T(rK-T7d!V4?>r_b?Gf;`8xuyqa$Lxjhhal>1yWyEd{AhfX0k&Pd0tAq}{;`=a! z9p0ZF?e9AEX8po8Xe4v_fZ4_6>-=q>?t78o`sUjCGZ2E(d&|Xq8^2@;%s~_g8m$(c z(WQt?ZNj=JEqqbRIoAEi!WZ~6`GR$ScHy%UXkg?NAR|AAbcgqYX&4y(EavW%%F9KF z$;c@n$IDJU;d{_@KF>>7Oh!rpGWv0lWycSGmb;0^ATcYbRIX0vauX$1@f;GqEbkH0 zBWhE#-QH_7>(xN7RW~`Z%Cd`Ug)J!ly8#2DT>-9j;ouShR-R7vuC0ag$ClUB&g{ZU zovn$>y3INj90!sa&=-Dtn@!b5-)lV5S#8C>*Hq?f2(&6-_S6?k{6kh{eMH4ba}|S7 zVQZrN#;Gfpf4cE;4N|~D84&$7Aj0=EVY{Yp5t8_xKob&1<{?&#w!zV~Lv;0Z`Rs_I zMFBGM-O6u@#Ufyrj>rhLM{Eu@oStCfk+) z2@Xz@aEyknqPkcb>RYYT?lVV-SXPj27v?}Y`f2rldr!_bx;DQEH(!{j`3BSYS+4I8 z!>%3}HZ|Ea_Va9y`+t!Bh8VGeLTh6P4EJyMgd(U}Q zo&g$&Wd+HG`r5+Es)ewmxUI;c2C*;zgF?aVFQgTwc4q>>{4w_A_c=_BPHF zsp(kOs%+xAt14ngL-RJ(+KzP^Vtd1~raGw?Rdp3nn^{~r?zcBN2YN&m0`dhdSbIuiy69g<6+4l~0p^|KOp`4{)o| z&^Z^)xbr(TL(A{_!3`%s6M2?daMtmYtq1 z`!atYMdi&28wT2Q!re`+!f8D4Qv!i=ZEG#PQ7`_7m7gfvfXAf-K1%qU2T7uafpN8= zx;Vzko&5W~)ki9AC89EdNAVD%Qe+!C|UnX+OZ4o+qO`-gcK8Wpq zFNIk;q#2M-;}fVe0-|do{6#Qw!0h6czXC!O+fLg#7o}8D*&h%I_CYxF=8&`g|JH83 zF@#b{A<;cR%uNJT6P84l7REm@js+n=HUL5=CFj` zOQH(c-`lNm{&y)S9WAGY<+#c0fv!y zi_&ZFd|sAO4mxlZVinbn6fZ4&AMZcw2Y3IuZo(*6kxGx)%;Iu2U@6i9`xom6T2Csb z3%!?A&Wd>a;CAE1qbJxp$2mxrjUT`L^af;z)H-A&T54N#SZh_ne}Gh5lq68MwRV19 z4$P3MxxiAz5nw2xh_16EFOZyUt3@TtLJlL~D_VQFGQiNIq22Jcyq;E=dEM*mNF29- zN~FqGWt>cO%JSzLJ;|3fn(6Ei>}ryRUnVh3w3#PI^# z5>(q4`qII$lK{=N`6Ixd$Rtw4A1oF?&Gwn45>bH$(_C z1SRhC`?=ze-+q{AFIrfP*#mf4DFs{)U88AR>Luoh-AbkCDh$RbK-KgewH?%L8j(%f z2Mf)KC7GiD_2#<`(VzE=@3kbG!6Pz~=Z2buF$xH1`d01_eV?Zo;eN9VE5&~2jk=DUjC`UBDB!GG>doLPjEaVKPSl!u7^;}J zGh4R1|0sposAcruyLtXF7=%$~s8l~Y?RL1T2H9lgge&(I&Pp?GTVKWTG%jkZc(%;!;qZsMnHoaBsJk zg+`6cD8R$36P56F?=OasP)4B@{}jV9W5$dbGbSzm1;CLXRIgSxn*aa+07*qoM6N<$ Eg4H^$Hvj+t literal 0 HcmV?d00001 diff --git a/cw_bitcoin/lib/bitcoin_hardware_wallet_service.dart b/cw_bitcoin/lib/bitcoin_hardware_wallet_service.dart new file mode 100644 index 000000000..345d645d1 --- /dev/null +++ b/cw_bitcoin/lib/bitcoin_hardware_wallet_service.dart @@ -0,0 +1,43 @@ +import 'dart:async'; + +import 'package:bitcoin_base/bitcoin_base.dart'; +import 'package:bitcoin_flutter/bitcoin_flutter.dart'; +import 'package:cw_bitcoin/utils.dart'; +import 'package:cw_core/hardware/hardware_account_data.dart'; +import 'package:ledger_bitcoin/ledger_bitcoin.dart'; +import 'package:ledger_flutter/ledger_flutter.dart'; + +class BitcoinHardwareWalletService { + BitcoinHardwareWalletService(this.ledger, this.device); + + final Ledger ledger; + final LedgerDevice device; + + Future> getAvailableAccounts({int index = 0, int limit = 5}) async { + final bitcoinLedgerApp = BitcoinLedgerApp(ledger); + + final masterFp = await bitcoinLedgerApp.getMasterFingerprint(device); + print(masterFp); + + final accounts = []; + final indexRange = List.generate(limit, (i) => i + index); + + for (final i in indexRange) { + final derivationPath = "m/84'/0'/$i'"; + final xpub = await bitcoinLedgerApp.getXPubKey(device, derivationPath: derivationPath); + HDWallet hd = HDWallet.fromBase58(xpub).derive(0); + + final address = generateP2WPKHAddress(hd: hd, index: 0, network: BitcoinNetwork.mainnet); + + accounts.add(HardwareAccountData( + address: address, + accountIndex: i, + derivationPath: derivationPath, + masterFingerprint: masterFp, + xpub: xpub, + )); + } + + return accounts; + } +} diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 33401d666..f96b0e4da 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -1,8 +1,13 @@ import 'package:bitcoin_base/bitcoin_base.dart'; +import 'package:convert/convert.dart'; + import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; +import 'package:cw_bitcoin/psbt_transaction_builder.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:hive/hive.dart'; +import 'package:ledger_bitcoin/ledger_bitcoin.dart'; +import 'package:ledger_flutter/ledger_flutter.dart'; import 'package:mobx/mobx.dart'; import 'package:flutter/foundation.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; @@ -20,11 +25,12 @@ class BitcoinWallet = BitcoinWalletBase with _$BitcoinWallet; abstract class BitcoinWalletBase extends ElectrumWallet with Store { BitcoinWalletBase({ - required String mnemonic, required String password, required WalletInfo walletInfo, required Box unspentCoinsInfo, - required Uint8List seedBytes, + Uint8List? seedBytes, + String? mnemonic, + String? xpub, String? addressPageType, BasedUtxoNetwork? networkParam, List? initialAddresses, @@ -33,24 +39,26 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { Map? initialChangeAddressIndex, String? passphrase, }) : super( - mnemonic: mnemonic, - passphrase: passphrase, - password: password, - walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfo, - networkType: networkParam == null - ? bitcoin.bitcoin - : networkParam == BitcoinNetwork.mainnet - ? bitcoin.bitcoin - : bitcoin.testnet, - initialAddresses: initialAddresses, - initialBalance: initialBalance, - seedBytes: seedBytes, - currency: CryptoCurrency.btc) { + mnemonic: mnemonic, + passphrase: passphrase, + xpub: xpub, + password: password, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfo, + networkType: networkParam == null + ? bitcoin.bitcoin + : networkParam == BitcoinNetwork.mainnet + ? bitcoin.bitcoin + : bitcoin.testnet, + initialAddresses: initialAddresses, + initialBalance: initialBalance, + seedBytes: seedBytes, + currency: CryptoCurrency.btc) { // in a standard BIP44 wallet, mainHd derivation path = m/84'/0'/0'/0 (account 0, index unspecified here) // the sideHd derivation path = m/84'/0'/0'/1 (account 1, index unspecified here) - String derivationPath = walletInfo.derivationInfo!.derivationPath!; - String sideDerivationPath = derivationPath.substring(0, derivationPath.length - 1) + "1"; + // String derivationPath = walletInfo.derivationInfo!.derivationPath!; + // String sideDerivationPath = derivationPath.substring(0, derivationPath.length - 1) + "1"; + // final hd = bitcoin.HDWallet.fromSeed(seedBytes, network: networkType); walletAddresses = BitcoinWalletAddresses( walletInfo, electrumClient: electrumClient, @@ -58,7 +66,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex, mainHd: hd, - sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath(sideDerivationPath), + sideHd: accountHD.derive(1), network: networkParam ?? network, ); autorun((_) { @@ -129,23 +137,26 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { walletInfo.derivationInfo!.derivationPath = snp.derivationPath ?? "m/0'/0"; walletInfo.derivationInfo!.derivationType = snp.derivationType ?? DerivationType.electrum; - late Uint8List seedBytes; + Uint8List? seedBytes = null; - switch (walletInfo.derivationInfo!.derivationType) { - case DerivationType.electrum: - seedBytes = await mnemonicToSeedBytes(snp.mnemonic); - break; - case DerivationType.bip39: - default: - seedBytes = await bip39.mnemonicToSeed( - snp.mnemonic, - passphrase: snp.passphrase ?? '', - ); - break; + if (snp.mnemonic != null) { + switch (walletInfo.derivationInfo!.derivationType) { + case DerivationType.electrum: + seedBytes = await mnemonicToSeedBytes(snp.mnemonic!); + break; + case DerivationType.bip39: + default: + seedBytes = await bip39.mnemonicToSeed( + snp.mnemonic!, + passphrase: snp.passphrase ?? '', + ); + break; + } } return BitcoinWallet( mnemonic: snp.mnemonic, + xpub: snp.xpub, password: password, passphrase: snp.passphrase, walletInfo: walletInfo, @@ -159,4 +170,49 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store { networkParam: network, ); } + + Ledger? _ledger; + LedgerDevice? _ledgerDevice; + BitcoinLedgerApp? _bitcoinLedgerApp; + + void setLedger(Ledger setLedger, LedgerDevice setLedgerDevice) { + _ledger = setLedger; + _ledgerDevice = setLedgerDevice; + _bitcoinLedgerApp = BitcoinLedgerApp(_ledger!, derivationPath: walletInfo.derivationInfo!.derivationPath!); + } + + @override + Future buildHardwareWalletTransaction({ + required List outputs, + required BigInt fee, + required BasedUtxoNetwork network, + required List utxos, + required Map publicKeys, + String? memo, + bool enableRBF = false, + BitcoinOrdering inputOrdering = BitcoinOrdering.bip69, + BitcoinOrdering outputOrdering = BitcoinOrdering.bip69, + }) async { + final masterFingerprint = await _bitcoinLedgerApp!.getMasterFingerprint(_ledgerDevice!); + + final psbtReadyInputs = []; + for (final utxo in utxos) { + final rawTx = await electrumClient.getTransactionHex(hash: utxo.utxo.txHash); + final publicKeyAndDerivationPath = publicKeys[utxo.ownerDetails.address.pubKeyHash()]!; + + psbtReadyInputs.add(PSBTReadyUtxoWithAddress( + utxo: utxo.utxo, + rawTx: rawTx, + ownerDetails: utxo.ownerDetails, + ownerDerivationPath: publicKeyAndDerivationPath.derivationPath, + ownerMasterFingerprint: masterFingerprint, + ownerPublicKey: publicKeyAndDerivationPath.publicKey, + )); + } + + final psbt = PSBTTransactionBuild(inputs: psbtReadyInputs, outputs: outputs, enableRBF: enableRBF); + + final rawHex = await _bitcoinLedgerApp!.signPsbt(_ledgerDevice!, psbt: psbt.psbt); + return BtcTransaction.fromRaw(hex.encode(rawHex)); + } } diff --git a/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart b/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart index 981c7a466..915d7cc10 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart @@ -1,3 +1,4 @@ +import 'package:cw_core/hardware/hardware_account_data.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; @@ -36,9 +37,22 @@ class BitcoinRestoreWalletFromSeedCredentials extends WalletCredentials { } class BitcoinRestoreWalletFromWIFCredentials extends WalletCredentials { - BitcoinRestoreWalletFromWIFCredentials( - {required String name, required String password, required this.wif, WalletInfo? walletInfo}) - : super(name: name, password: password, walletInfo: walletInfo); + BitcoinRestoreWalletFromWIFCredentials({ + required String name, + required String password, + required this.wif, + WalletInfo? walletInfo, + }) : super(name: name, password: password, walletInfo: walletInfo); final String wif; } + +class BitcoinRestoreWalletFromHardware extends WalletCredentials { + BitcoinRestoreWalletFromHardware({ + required String name, + required this.hwAccountData, + WalletInfo? walletInfo, + }) : super(name: name, walletInfo: walletInfo); + + final HardwareAccountData hwAccountData; +} diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index e0548771b..cf99324da 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -14,8 +14,11 @@ import 'package:hive/hive.dart'; import 'package:collection/collection.dart'; import 'package:bip39/bip39.dart' as bip39; -class BitcoinWalletService extends WalletService { +class BitcoinWalletService extends WalletService< + BitcoinNewWalletCredentials, + BitcoinRestoreWalletFromSeedCredentials, + BitcoinRestoreWalletFromWIFCredentials, + BitcoinRestoreWalletFromHardware> { BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); final Box walletInfoSource; @@ -99,9 +102,28 @@ class BitcoinWalletService extends WalletService restoreFromHardwareWallet(BitcoinRestoreWalletFromHardware credentials, + {bool? isTestnet}) async { + + final network = isTestnet == true ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet; + credentials.walletInfo?.network = network.value; + credentials.walletInfo?.derivationInfo?.derivationPath = credentials.hwAccountData.derivationPath; + + final wallet = await BitcoinWallet(password: credentials.password!, + xpub: credentials.hwAccountData.xpub, + walletInfo: credentials.walletInfo!, + unspentCoinsInfo: unspentCoinsInfoSource, + networkParam: network, + ); + await wallet.save(); + await wallet.init(); + return wallet; + } + @override Future restoreFromKeys(BitcoinRestoreWalletFromWIFCredentials credentials, - {bool? isTestnet}) async => + {bool? isTestnet}) async => throw UnimplementedError(); @override diff --git a/cw_bitcoin/lib/electrum_derivations.dart b/cw_bitcoin/lib/electrum_derivations.dart index 631805c54..19d444a41 100644 --- a/cw_bitcoin/lib/electrum_derivations.dart +++ b/cw_bitcoin/lib/electrum_derivations.dart @@ -4,7 +4,7 @@ Map> electrum_derivations = { DerivationType.electrum: [ DerivationInfo( derivationType: DerivationType.electrum, - derivationPath: "m/0'/0", + derivationPath: "m/0'", description: "Electrum", scriptType: "p2wpkh", ), diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 8342e4816..783eb10d7 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -4,8 +4,8 @@ import 'dart:io'; import 'dart:math'; import 'package:bitcoin_base/bitcoin_base.dart'; -import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:bitcoin_base/bitcoin_base.dart' as bitcoin_base; +import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:collection/collection.dart'; import 'package:cw_bitcoin/address_from_output.dart'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; @@ -37,9 +37,9 @@ import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; +import 'package:http/http.dart' as http; import 'package:mobx/mobx.dart'; import 'package:rxdart/subjects.dart'; -import 'package:http/http.dart' as http; part 'electrum_wallet.g.dart'; @@ -53,17 +53,16 @@ abstract class ElectrumWalletBase required WalletInfo walletInfo, required Box unspentCoinsInfo, required this.networkType, - required this.mnemonic, - required Uint8List seedBytes, + String? xpub, + String? mnemonic, + Uint8List? seedBytes, this.passphrase, List? initialAddresses, ElectrumClient? electrumClient, ElectrumBalance? initialBalance, CryptoCurrency? currency}) - : hd = currency == CryptoCurrency.bch - ? bitcoinCashHDWallet(seedBytes) - : bitcoin.HDWallet.fromSeed(seedBytes, network: networkType) - .derivePath(walletInfo.derivationInfo?.derivationPath ?? "m/0'/0"), + : accountHD = + getAccountHDWallet(currency, networkType, seedBytes, xpub, walletInfo.derivationInfo), syncStatus = NotConnectedSyncStatus(), _password = password, _feeRates = [], @@ -80,20 +79,44 @@ abstract class ElectrumWalletBase this.unspentCoinsInfo = unspentCoinsInfo, this.network = _getNetwork(networkType, currency), this.isTestnet = networkType == bitcoin.testnet, + this._mnemonic = mnemonic, super(walletInfo) { this.electrumClient = electrumClient ?? ElectrumClient(); this.walletInfo = walletInfo; transactionHistory = ElectrumTransactionHistory(walletInfo: walletInfo, password: password); } + static bitcoin.HDWallet getAccountHDWallet( + CryptoCurrency? currency, + bitcoin.NetworkType networkType, + Uint8List? seedBytes, + String? xpub, + DerivationInfo? derivationInfo) { + if (seedBytes == null && xpub == null) { + throw Exception( + "To create a Wallet you need either a seed or an xpub. This should not happen"); + } + + if (seedBytes != null) { + return currency == CryptoCurrency.bch + ? bitcoinCashHDWallet(seedBytes) + : bitcoin.HDWallet.fromSeed(seedBytes, network: networkType) + .derivePath(_hardenedDerivationPath(derivationInfo?.derivationPath ?? "m/0'")); + } + + return bitcoin.HDWallet.fromBase58(xpub!); + } + static bitcoin.HDWallet bitcoinCashHDWallet(Uint8List seedBytes) => - bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/0"); + bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'"); static int estimatedTransactionSize(int inputsCount, int outputsCounts) => inputsCount * 68 + outputsCounts * 34 + 10; - final bitcoin.HDWallet hd; - final String mnemonic; + final bitcoin.HDWallet accountHD; + final String? _mnemonic; + + bitcoin.HDWallet get hd => accountHD.derive(0); final String? passphrase; @override @@ -123,10 +146,10 @@ abstract class ElectrumWalletBase .map((addr) => scriptHash(addr.address, network: network)) .toList(); - String get xpub => hd.base58!; + String get xpub => accountHD.base58!; @override - String get seed => mnemonic; + String? get seed => _mnemonic; bitcoin.NetworkType networkType; BasedUtxoNetwork network; @@ -203,7 +226,9 @@ abstract class ElectrumWalletBase int credentialsAmount = 0, }) async { final utxos = []; - List privateKeys = []; + final privateKeys = []; + final publicKeys = {}; + int allInputsAmount = 0; bool spendsUnconfirmedTX = false; @@ -217,12 +242,22 @@ abstract class ElectrumWalletBase allInputsAmount += utx.value; final address = addressTypeFromStr(utx.address, network); - final privkey = generateECPrivate( - hd: utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, - index: utx.bitcoinAddressRecord.index, - network: network); + final hd = + utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd; + final derivationPath = + "${_hardenedDerivationPath(walletInfo.derivationInfo?.derivationPath ?? "m/0'")}" + "/${utx.bitcoinAddressRecord.isHidden ? "1" : "0"}" + "/${utx.bitcoinAddressRecord.index}"; + final pubKeyHex = hd.derive(utx.bitcoinAddressRecord.index).pubKey!; - privateKeys.add(privkey); + publicKeys[address.pubKeyHash()] = PublicKeyWithDerivationPath(pubKeyHex, derivationPath); + + if (!walletInfo.isHardwareWallet) { + final privkey = + generateECPrivate(hd: hd, index: utx.bitcoinAddressRecord.index, network: network); + + privateKeys.add(privkey); + } utxos.add( UtxoWithAddress( @@ -233,7 +268,7 @@ abstract class ElectrumWalletBase scriptType: _getScriptType(address), ), ownerDetails: UtxoAddressDetails( - publicKey: privkey.getPublic().toHex(), + publicKey: pubKeyHex, address: address, ), ), @@ -294,6 +329,7 @@ abstract class ElectrumWalletBase return EstimatedTxResult( utxos: utxos, privateKeys: privateKeys, + publicKeys: publicKeys, fee: fee, amount: amount, isSendAll: true, @@ -312,7 +348,9 @@ abstract class ElectrumWalletBase bool? useUnconfirmed, }) async { final utxos = []; - List privateKeys = []; + final privateKeys = []; + final publicKeys = {}; + int allInputsAmount = 0; bool spendsUnconfirmedTX = false; @@ -332,12 +370,23 @@ abstract class ElectrumWalletBase leftAmount = leftAmount - utx.value; final address = addressTypeFromStr(utx.address, network); - final privkey = generateECPrivate( - hd: utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd, - index: utx.bitcoinAddressRecord.index, - network: network); - privateKeys.add(privkey); + final hd = + utx.bitcoinAddressRecord.isHidden ? walletAddresses.sideHd : walletAddresses.mainHd; + final derivationPath = + "${_hardenedDerivationPath(walletInfo.derivationInfo?.derivationPath ?? "m/0'")}" + "/${utx.bitcoinAddressRecord.isHidden ? "1" : "0"}" + "/${utx.bitcoinAddressRecord.index}"; + final pubKeyHex = hd.derive(utx.bitcoinAddressRecord.index).pubKey!; + + publicKeys[address.pubKeyHash()] = PublicKeyWithDerivationPath(pubKeyHex, derivationPath); + + if (!walletInfo.isHardwareWallet) { + final privkey = + generateECPrivate(hd: hd, index: utx.bitcoinAddressRecord.index, network: network); + + privateKeys.add(privkey); + } utxos.add( UtxoWithAddress( @@ -348,7 +397,7 @@ abstract class ElectrumWalletBase scriptType: _getScriptType(address), ), ownerDetails: UtxoAddressDetails( - publicKey: privkey.getPublic().toHex(), + publicKey: pubKeyHex, address: address, ), ), @@ -490,6 +539,7 @@ abstract class ElectrumWalletBase return EstimatedTxResult( utxos: utxos, privateKeys: privateKeys, + publicKeys: publicKeys, fee: fee, amount: amount, hasChange: true, @@ -557,6 +607,35 @@ abstract class ElectrumWalletBase ); } + if (walletInfo.isHardwareWallet) { + final transaction = await buildHardwareWalletTransaction( + utxos: estimatedTx.utxos, + outputs: outputs, + publicKeys: estimatedTx.publicKeys, + fee: BigInt.from(estimatedTx.fee), + network: network, + memo: estimatedTx.memo, + outputOrdering: BitcoinOrdering.none, + enableRBF: true, + ); + + return PendingBitcoinTransaction( + transaction, + type, + electrumClient: electrumClient, + amount: estimatedTx.amount, + fee: estimatedTx.fee, + feeRate: feeRateInt.toString(), + network: network, + hasChange: estimatedTx.hasChange, + isSendAll: estimatedTx.isSendAll, + hasTaprootInputs: false, // ToDo: (Konsti) Support Taproot + )..addListener((transaction) async { + transactionHistory.addOne(transaction); + await updateBalance(); + }); + } + BasedBitcoinTransacationBuilder txb; if (network is BitcoinCashNetwork) { txb = ForkedTransactionBuilder( @@ -618,8 +697,22 @@ abstract class ElectrumWalletBase } } + Future buildHardwareWalletTransaction({ + required List outputs, + required BigInt fee, + required BasedUtxoNetwork network, + required List utxos, + required Map publicKeys, + String? memo, + bool enableRBF = false, + BitcoinOrdering inputOrdering = BitcoinOrdering.bip69, + BitcoinOrdering outputOrdering = BitcoinOrdering.bip69, + }) async => + throw UnimplementedError(); + String toJSON() => json.encode({ - 'mnemonic': mnemonic, + 'mnemonic': _mnemonic, + 'xpub': xpub, 'passphrase': passphrase ?? '', 'account_index': walletAddresses.currentReceiveAddressIndexByType, 'change_address_index': walletAddresses.currentChangeAddressIndexByType, @@ -1263,7 +1356,7 @@ abstract class ElectrumWalletBase void setExceptionHandler(void Function(FlutterErrorDetails) onError) => _onError = onError; @override - String signMessage(String message, {String? address = null}) { + Future signMessage(String message, {String? address = null}) async { final index = address != null ? walletAddresses.allAddresses.firstWhere((element) => element.address == address).index : null; @@ -1286,6 +1379,9 @@ abstract class ElectrumWalletBase return BitcoinNetwork.mainnet; } + + static String _hardenedDerivationPath(String derivationPath) => + derivationPath.substring(0, derivationPath.lastIndexOf("'") + 1); } class EstimateTxParams { @@ -1307,6 +1403,7 @@ class EstimatedTxResult { EstimatedTxResult({ required this.utxos, required this.privateKeys, + required this.publicKeys, required this.fee, required this.amount, required this.hasChange, @@ -1317,6 +1414,7 @@ class EstimatedTxResult { final List utxos; final List privateKeys; + final Map publicKeys; // PubKey to derivationPath final int fee; final int amount; final bool hasChange; @@ -1325,6 +1423,13 @@ class EstimatedTxResult { final bool spendsUnconfirmedTX; } +class PublicKeyWithDerivationPath { + const PublicKeyWithDerivationPath(this.publicKey, this.derivationPath); + + final String derivationPath; + final String publicKey; +} + BitcoinBaseAddress addressTypeFromStr(String address, BasedUtxoNetwork network) { if (network is BitcoinCashNetwork) { if (!address.startsWith("bitcoincash:") && diff --git a/cw_bitcoin/lib/electrum_wallet_snapshot.dart b/cw_bitcoin/lib/electrum_wallet_snapshot.dart index 218792e3c..340b17cfb 100644 --- a/cw_bitcoin/lib/electrum_wallet_snapshot.dart +++ b/cw_bitcoin/lib/electrum_wallet_snapshot.dart @@ -13,6 +13,7 @@ class ElectrumWalletSnapshot { required this.type, required this.password, required this.mnemonic, + required this.xpub, required this.addresses, required this.balance, required this.regularAddressIndex, @@ -28,7 +29,8 @@ class ElectrumWalletSnapshot { final WalletType type; final String? addressPageType; - String mnemonic; + String? mnemonic; + String? xpub; List addresses; ElectrumBalance balance; Map regularAddressIndex; @@ -43,7 +45,8 @@ class ElectrumWalletSnapshot { final jsonSource = await read(path: path, password: password); final data = json.decode(jsonSource) as Map; final addressesTmp = data['addresses'] as List? ?? []; - final mnemonic = data['mnemonic'] as String; + final mnemonic = data['mnemonic'] as String?; + final xpub = data['xpub'] as String?; final passphrase = data['passphrase'] as String? ?? ''; final addresses = addressesTmp .whereType() @@ -79,6 +82,7 @@ class ElectrumWalletSnapshot { password: password, passphrase: passphrase, mnemonic: mnemonic, + xpub: xpub, addresses: addresses, balance: balance, regularAddressIndex: regularAddressIndexByType, diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart index 4d166e47b..2ffb99405 100644 --- a/cw_bitcoin/lib/litecoin_wallet.dart +++ b/cw_bitcoin/lib/litecoin_wallet.dart @@ -50,7 +50,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex, mainHd: hd, - sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"), + sideHd: accountHD.derive(1), network: network, ); autorun((_) { @@ -106,13 +106,13 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store { final snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password, LitecoinNetwork.mainnet); return LitecoinWallet( - mnemonic: snp.mnemonic, + mnemonic: snp.mnemonic!, password: password, walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfo, initialAddresses: snp.addresses, initialBalance: snp.balance, - seedBytes: await mnemonicToSeedBytes(snp.mnemonic), + seedBytes: await mnemonicToSeedBytes(snp.mnemonic!), initialRegularAddressIndex: snp.regularAddressIndex, initialChangeAddressIndex: snp.changeAddressIndex, addressPageType: snp.addressPageType, diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index 9143556ab..bb51a4eaa 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -16,7 +16,7 @@ import 'package:bip39/bip39.dart' as bip39; class LitecoinWalletService extends WalletService< BitcoinNewWalletCredentials, BitcoinRestoreWalletFromSeedCredentials, - BitcoinRestoreWalletFromWIFCredentials> { + BitcoinRestoreWalletFromWIFCredentials,BitcoinNewWalletCredentials> { LitecoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); final Box walletInfoSource; @@ -94,6 +94,11 @@ class LitecoinWalletService extends WalletService< await walletInfoSource.put(currentWalletInfo.key, newWalletInfo); } + @override + Future restoreFromHardwareWallet(BitcoinNewWalletCredentials credentials) { + throw UnimplementedError("Restoring a Litecoin wallet from a hardware wallet is not yet supported!"); + } + @override Future restoreFromKeys( BitcoinRestoreWalletFromWIFCredentials credentials, {bool? isTestnet}) async => diff --git a/cw_bitcoin/lib/psbt_transaction_builder.dart b/cw_bitcoin/lib/psbt_transaction_builder.dart new file mode 100644 index 000000000..d8d2c9fac --- /dev/null +++ b/cw_bitcoin/lib/psbt_transaction_builder.dart @@ -0,0 +1,96 @@ +import 'dart:typed_data'; + +import 'package:bitcoin_base/bitcoin_base.dart'; +import 'package:convert/convert.dart'; +import 'package:ledger_bitcoin/psbt.dart'; + +class PSBTTransactionBuild { + final PsbtV2 psbt = PsbtV2(); + + PSBTTransactionBuild( + {required List inputs, required List outputs, bool enableRBF = true}) { + psbt.setGlobalTxVersion(2); + psbt.setGlobalInputCount(inputs.length); + psbt.setGlobalOutputCount(outputs.length); + + for (var i = 0; i < inputs.length; i++) { + final input = inputs[i]; + + print(input.utxo.isP2tr()); + print(input.utxo.isSegwit()); + print(input.utxo.isP2shSegwit()); + + psbt.setInputPreviousTxId(i, Uint8List.fromList(hex.decode(input.utxo.txHash).reversed.toList())); + psbt.setInputOutputIndex(i, input.utxo.vout); + psbt.setInputSequence(i, enableRBF ? 0x1 : 0xffffffff); + + + if (input.utxo.isSegwit()) { + setInputSegwit(i, input); + } else if (input.utxo.isP2shSegwit()) { + setInputP2shSegwit(i, input); + } else if (input.utxo.isP2tr()) { + // ToDo: (Konsti) Handle Taproot Inputs + } else { + setInputP2pkh(i, input); + } + } + + for (var i = 0; i < outputs.length; i++) { + final output = outputs[i]; + + if (output is BitcoinOutput) { + psbt.setOutputScript(i, Uint8List.fromList(output.address.toScriptPubKey().toBytes())); + psbt.setOutputAmount(i, output.value.toInt()); + } + } + } + + void setInputP2pkh(int i, PSBTReadyUtxoWithAddress input) { + psbt.setInputNonWitnessUtxo(i, Uint8List.fromList(hex.decode(input.rawTx))); + psbt.setInputBip32Derivation( + i, + Uint8List.fromList(hex.decode(input.ownerPublicKey)), + input.ownerMasterFingerprint, + BIPPath.fromString(input.ownerDerivationPath).toPathArray()); + } + + void setInputSegwit(int i, PSBTReadyUtxoWithAddress input) { + psbt.setInputNonWitnessUtxo(i, Uint8List.fromList(hex.decode(input.rawTx))); + psbt.setInputBip32Derivation( + i, + Uint8List.fromList(hex.decode(input.ownerPublicKey)), + input.ownerMasterFingerprint, + BIPPath.fromString(input.ownerDerivationPath).toPathArray()); + + psbt.setInputWitnessUtxo(i, Uint8List.fromList(bigIntToUint64LE(input.utxo.value)), + Uint8List.fromList(input.ownerDetails.address.toScriptPubKey().toBytes())); + } + + void setInputP2shSegwit(int i, PSBTReadyUtxoWithAddress input) { + psbt.setInputNonWitnessUtxo(i, Uint8List.fromList(hex.decode(input.rawTx))); + psbt.setInputBip32Derivation(i, Uint8List.fromList(hex.decode(input.ownerPublicKey)), + input.ownerMasterFingerprint, BIPPath.fromString(input.ownerDerivationPath).toPathArray()); + + psbt.setInputRedeemScript( + i, Uint8List.fromList(input.ownerDetails.address.toScriptPubKey().toBytes())); + psbt.setInputWitnessUtxo(i, Uint8List.fromList(bigIntToUint64LE(input.utxo.value)), + Uint8List.fromList(input.ownerDetails.address.toScriptPubKey().toBytes())); + } +} + +class PSBTReadyUtxoWithAddress extends UtxoWithAddress { + final String rawTx; + final String ownerDerivationPath; + final Uint8List ownerMasterFingerprint; + final String ownerPublicKey; + + PSBTReadyUtxoWithAddress({ + required super.utxo, + required this.rawTx, + required super.ownerDetails, + required this.ownerDerivationPath, + required this.ownerMasterFingerprint, + required this.ownerPublicKey, + }); +} diff --git a/cw_bitcoin/pubspec.lock b/cw_bitcoin/pubspec.lock index 86d58b9b1..a398a11e0 100644 --- a/cw_bitcoin/pubspec.lock +++ b/cw_bitcoin/pubspec.lock @@ -260,6 +260,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.4" + dart_varuint_bitcoin: + dependency: transitive + description: + name: dart_varuint_bitcoin + sha256: "4f0ccc9733fb54148b9d3688eea822b7aaabf5cc00025998f8c09a1d45b31b4b" + url: "https://pub.dev" + source: hosted + version: "1.0.3" encrypt: dependency: transitive description: @@ -313,6 +321,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.1+1" + flutter_reactive_ble: + dependency: transitive + description: + name: flutter_reactive_ble + sha256: "247e2efa76de203d1ba11335c13754b5b9d0504b5423e5b0c93a600f016b24e0" + url: "https://pub.dev" + source: hosted + version: "5.3.1" flutter_test: dependency: "direct dev" description: flutter @@ -326,6 +342,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + functional_data: + dependency: transitive + description: + name: functional_data + sha256: aefdec4365452283b2a7cf420a3169654d51d3e9553069a22d76680d7a9d7c3d + url: "https://pub.dev" + source: hosted + version: "1.1.1" glob: dependency: transitive description: @@ -422,6 +446,31 @@ packages: url: "https://pub.dev" source: hosted version: "4.8.1" + ledger_bitcoin: + dependency: "direct main" + description: + path: "." + ref: HEAD + resolved-ref: b6ed573cbeb57d5f0d39dfe4254bf9d15b620ab6 + url: "https://github.com/cake-tech/ledger-bitcoin.git" + source: git + version: "0.0.1" + ledger_flutter: + dependency: "direct main" + description: + name: ledger_flutter + sha256: f1680060ed6ff78f275837e0024ccaf667715a59ba7aa29fa7354bc7752e71c8 + url: "https://pub.dev" + source: hosted + version: "1.0.1" + ledger_usb: + dependency: transitive + description: + name: ledger_usb + sha256: "52c92d03a4cffe06c82921c8e2f79f3cdad6e1cf78e1e9ca35444196ff8f14c2" + url: "https://pub.dev" + source: hosted + version: "1.0.0" logging: dependency: transitive description: @@ -582,6 +631,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" + protobuf: + dependency: transitive + description: + name: protobuf + sha256: "01dd9bd0fa02548bf2ceee13545d4a0ec6046459d847b6b061d8a27237108a08" + url: "https://pub.dev" + source: hosted + version: "2.1.0" provider: dependency: transitive description: @@ -606,6 +663,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.3" + reactive_ble_mobile: + dependency: transitive + description: + name: reactive_ble_mobile + sha256: "9ec2b4c9c725e439950838d551579750060258fbccd5536d0543b4d07d225798" + url: "https://pub.dev" + source: hosted + version: "5.3.1" + reactive_ble_platform_interface: + dependency: transitive + description: + name: reactive_ble_platform_interface + sha256: "632c92401a2d69c9b94bd48f8fd47488a7013f3d1f9b291884350291a4a81813" + url: "https://pub.dev" + source: hosted + version: "5.3.1" rxdart: dependency: "direct main" description: @@ -788,5 +861,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.0.6 <4.0.0" flutter: ">=3.10.0" diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index 632a3140a..9adf77652 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -35,6 +35,10 @@ dependencies: url: https://github.com/cake-tech/bitcoin_base.git ref: cake-update-v2 blockchain_utils: ^2.1.1 + ledger_flutter: ^1.0.1 + ledger_bitcoin: + git: + url: https://github.com/cake-tech/ledger-bitcoin.git dev_dependencies: flutter_test: diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart index 1f04e5624..d58144f1e 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart @@ -51,7 +51,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { initialRegularAddressIndex: initialRegularAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex, mainHd: hd, - sideHd: bitcoin.HDWallet.fromSeed(seedBytes).derivePath("m/44'/145'/0'/1"), + sideHd: accountHD.derive(1), network: network, initialAddressPageType: addressPageType, ); @@ -93,7 +93,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { final snp = await ElectrumWalletSnapshot.load( name, walletInfo.type, password, BitcoinCashNetwork.mainnet); return BitcoinCashWallet( - mnemonic: snp.mnemonic, + mnemonic: snp.mnemonic!, password: password, walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfo, @@ -118,7 +118,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { } }).toList(), initialBalance: snp.balance, - seedBytes: await Mnemonic.toSeed(snp.mnemonic), + seedBytes: await Mnemonic.toSeed(snp.mnemonic!), initialRegularAddressIndex: snp.regularAddressIndex, initialChangeAddressIndex: snp.changeAddressIndex, addressPageType: P2pkhAddressType.p2pkh, @@ -166,7 +166,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store { } @override - String signMessage(String message, {String? address = null}) { + Future signMessage(String message, {String? address = null}) async { final index = address != null ? walletAddresses.allAddresses .firstWhere((element) => element.address == AddressUtils.toLegacyAddress(address)) diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart index df8e841f8..e6c0cad07 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart @@ -12,7 +12,7 @@ import 'package:collection/collection.dart'; import 'package:hive/hive.dart'; class BitcoinCashWalletService extends WalletService { + BitcoinCashRestoreWalletFromSeedCredentials, BitcoinCashRestoreWalletFromWIFCredentials, BitcoinCashNewWalletCredentials> { BitcoinCashWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); final Box walletInfoSource; @@ -93,6 +93,11 @@ class BitcoinCashWalletService extends WalletService restoreFromHardwareWallet(BitcoinCashNewWalletCredentials credentials) { + throw UnimplementedError("Restoring a Bitcoin Cash wallet from a hardware wallet is not yet supported!"); + } + @override Future restoreFromKeys(credentials, {bool? isTestnet}) { // TODO: implement restoreFromKeys diff --git a/cw_core/lib/hardware/device_connection_type.dart b/cw_core/lib/hardware/device_connection_type.dart new file mode 100644 index 000000000..99fd5b1f0 --- /dev/null +++ b/cw_core/lib/hardware/device_connection_type.dart @@ -0,0 +1,28 @@ +import 'package:cw_core/wallet_type.dart'; + +enum DeviceConnectionType { + usb, + ble; + + static List supportedConnectionTypes(WalletType walletType, + [bool isIOS = false]) { + switch (walletType) { + case WalletType.bitcoin: + case WalletType.ethereum: + case WalletType.polygon: + if (isIOS) return [DeviceConnectionType.ble]; + return [DeviceConnectionType.ble, DeviceConnectionType.usb]; + default: + return []; + } + } + + String get iconString { + switch (this) { + case ble: + return 'assets/images/bluetooth.png'; + case usb: + return 'assets/images/usb.png'; + } + } +} diff --git a/cw_core/lib/hardware/device_not_connected_exception.dart b/cw_core/lib/hardware/device_not_connected_exception.dart new file mode 100644 index 000000000..bc2a1b095 --- /dev/null +++ b/cw_core/lib/hardware/device_not_connected_exception.dart @@ -0,0 +1,7 @@ +class DeviceNotConnectedException implements Exception { + final String message; + + DeviceNotConnectedException({ + this.message = '', + }); +} diff --git a/cw_core/lib/hardware/hardware_account_data.dart b/cw_core/lib/hardware/hardware_account_data.dart new file mode 100644 index 000000000..a9562f8be --- /dev/null +++ b/cw_core/lib/hardware/hardware_account_data.dart @@ -0,0 +1,19 @@ +import 'dart:typed_data'; + +class HardwareAccountData { + HardwareAccountData({ + required this.address, + required this.accountIndex, + required this.derivationPath, + this.xpub, + this.masterFingerprint, + }); + + final String address; + final int accountIndex; + final String derivationPath; + + // Bitcoin Specific + final Uint8List? masterFingerprint; + final String? xpub; +} diff --git a/cw_core/lib/hive_type_ids.dart b/cw_core/lib/hive_type_ids.dart index e3332a043..4da616a79 100644 --- a/cw_core/lib/hive_type_ids.dart +++ b/cw_core/lib/hive_type_ids.dart @@ -17,3 +17,4 @@ const DERIVATION_TYPE_TYPE_ID = 15; 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; diff --git a/cw_core/lib/wallet_base.dart b/cw_core/lib/wallet_base.dart index 037a26d38..709462fa1 100644 --- a/cw_core/lib/wallet_base.dart +++ b/cw_core/lib/wallet_base.dart @@ -56,6 +56,8 @@ abstract class WalletBase false; + bool get isHardwareWallet => walletInfo.isHardwareWallet; + Future connectToNode({required Node node}); // there is a default definition here because only coins with a pow node (nano based) need to override this @@ -88,7 +90,7 @@ abstract class WalletBase renameWalletFiles(String newWalletName); - String signMessage(String message, {String? address = null}) => throw UnimplementedError(); + Future signMessage(String message, {String? address = null}) => throw UnimplementedError(); bool? isTestnet; } diff --git a/cw_core/lib/wallet_credentials.dart b/cw_core/lib/wallet_credentials.dart index 9b28680f9..30ae2546c 100644 --- a/cw_core/lib/wallet_credentials.dart +++ b/cw_core/lib/wallet_credentials.dart @@ -9,6 +9,7 @@ abstract class WalletCredentials { this.password, this.passphrase, this.derivationInfo, + this.hardwareWalletType, }) { if (this.walletInfo != null && derivationInfo != null) { this.walletInfo!.derivationInfo = derivationInfo; @@ -22,4 +23,5 @@ abstract class WalletCredentials { String? passphrase; WalletInfo? walletInfo; DerivationInfo? derivationInfo; + HardwareWalletType? hardwareWalletType; } diff --git a/cw_core/lib/wallet_info.dart b/cw_core/lib/wallet_info.dart index 2768fdc6e..57cdad81b 100644 --- a/cw_core/lib/wallet_info.dart +++ b/cw_core/lib/wallet_info.dart @@ -1,4 +1,5 @@ import 'dart:async'; + import 'package:cw_core/address_info.dart'; import 'package:cw_core/hive_type_ids.dart'; import 'package:cw_core/wallet_type.dart'; @@ -20,6 +21,12 @@ enum DerivationType { electrum, } +@HiveType(typeId: HARDWARE_WALLET_TYPE_TYPE_ID) +enum HardwareWalletType { + @HiveField(0) + ledger, +} + @HiveType(typeId: DerivationInfo.typeId) class DerivationInfo extends HiveObject { DerivationInfo({ @@ -40,7 +47,7 @@ class DerivationInfo extends HiveObject { @HiveField(1, defaultValue: '') String balance; - @HiveField(2) + @HiveField(2, defaultValue: 0) int transactionsCount; @HiveField(3) @@ -71,8 +78,9 @@ class WalletInfo extends HiveObject { this.yatEid, this.yatLastUsedAddressRaw, this.showIntroCakePayCard, - this.derivationInfo) - : _yatLastUsedAddressController = StreamController.broadcast(); + this.derivationInfo, + this.hardwareWalletType, + ): _yatLastUsedAddressController = StreamController.broadcast(); factory WalletInfo.external({ required String id, @@ -88,6 +96,7 @@ class WalletInfo extends HiveObject { String yatEid = '', String yatLastUsedAddressRaw = '', DerivationInfo? derivationInfo, + HardwareWalletType? hardwareWalletType, }) { return WalletInfo( id, @@ -103,6 +112,7 @@ class WalletInfo extends HiveObject { yatLastUsedAddressRaw, showIntroCakePayCard, derivationInfo, + hardwareWalletType, ); } @@ -171,6 +181,9 @@ class WalletInfo extends HiveObject { @HiveField(20) DerivationInfo? derivationInfo; + @HiveField(21) + HardwareWalletType? hardwareWalletType; + String get yatLastUsedAddress => yatLastUsedAddressRaw ?? ''; set yatLastUsedAddress(String address) { @@ -187,6 +200,8 @@ class WalletInfo extends HiveObject { return showIntroCakePayCard!; } + bool get isHardwareWallet => hardwareWalletType != null; + DateTime get date => DateTime.fromMillisecondsSinceEpoch(timestamp); Stream get yatLastUsedAddressStream => _yatLastUsedAddressController.stream; diff --git a/cw_core/lib/wallet_service.dart b/cw_core/lib/wallet_service.dart index 22981b9db..fcbd59ff3 100644 --- a/cw_core/lib/wallet_service.dart +++ b/cw_core/lib/wallet_service.dart @@ -6,11 +6,13 @@ import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_type.dart'; abstract class WalletService { + RFK extends WalletCredentials, RFH extends WalletCredentials> { WalletType getType(); Future create(N credentials, {bool? isTestnet}); + Future restoreFromHardwareWallet(RFH credentials); + Future restoreFromSeed(RFS credentials, {bool? isTestnet}); Future restoreFromKeys(RFK credentials, {bool? isTestnet}); diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index 53c8bfea9..c0d3df2d6 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -1,11 +1,12 @@ +import 'package:bip39/bip39.dart' as bip39; import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cw_ethereum/ethereum_client.dart'; import 'package:cw_ethereum/ethereum_mnemonics_exception.dart'; import 'package:cw_ethereum/ethereum_wallet.dart'; import 'package:cw_evm/evm_chain_wallet_creation_credentials.dart'; import 'package:cw_evm/evm_chain_wallet_service.dart'; -import 'package:bip39/bip39.dart' as bip39; class EthereumWalletService extends EVMChainWalletService { EthereumWalletService(super.walletInfoSource, {required this.client}); @@ -82,6 +83,29 @@ class EthereumWalletService extends EVMChainWalletService { await walletInfoSource.put(currentWalletInfo.key, newWalletInfo); } + @override + Future restoreFromHardwareWallet( + EVMChainRestoreWalletFromHardware credentials) async { + credentials.walletInfo!.derivationInfo = DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/44'/60'/${credentials.hwAccountData.accountIndex}'/0/0" + ); + credentials.walletInfo!.hardwareWalletType = credentials.hardwareWalletType; + credentials.walletInfo!.address = credentials.hwAccountData.address; + + final wallet = EthereumWallet( + walletInfo: credentials.walletInfo!, + password: credentials.password!, + client: client, + ); + + await wallet.init(); + wallet.addInitialTokens(); + await wallet.save(); + + return wallet; + } + @override Future restoreFromKeys(EVMChainRestoreWalletFromPrivateKey credentials, {bool? isTestnet}) async { diff --git a/cw_ethereum/pubspec.yaml b/cw_ethereum/pubspec.yaml index 649ec574b..5f78fba3d 100644 --- a/cw_ethereum/pubspec.yaml +++ b/cw_ethereum/pubspec.yaml @@ -19,6 +19,12 @@ dependencies: path: ../cw_evm hive: ^2.2.3 +dependency_overrides: + web3dart: + git: + url: https://github.com/cake-tech/web3dart.git + ref: cake + dev_dependencies: flutter_test: sdk: flutter diff --git a/cw_evm/lib/contract/erc20.dart b/cw_evm/lib/contract/erc20.dart new file mode 100644 index 000000000..297b77e71 --- /dev/null +++ b/cw_evm/lib/contract/erc20.dart @@ -0,0 +1,209 @@ +import 'dart:typed_data'; + +import 'package:web3dart/web3dart.dart' as web3; + +final _contractAbi = web3.ContractAbi.fromJson( + '[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]', + 'Erc20'); + +/// Interface of the ERC20 standard as defined in the EIP. +class ERC20 extends web3.GeneratedContract { + /// Constructor. + ERC20({ + required web3.EthereumAddress address, + required web3.Web3Client client, + int? chainId, + }) : super(web3.DeployedContract(_contractAbi, address), client, chainId); + + /// Returns the remaining number of tokens that [spender] will be allowed to spend on behalf of [owner] through [transferFrom]. This is zero by default. This value changes when [approve] or [transferFrom] are called. + /// + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future allowance( + web3.EthereumAddress owner, + web3.EthereumAddress spender, { + web3.BlockNum? atBlock, + }) async { + final function = self.abi.functions[0]; + assert(checkSignature(function, 'dd62ed3e')); + final params = [owner, spender]; + final response = await read(function, params, atBlock); + return (response[0] as BigInt); + } + + /// Sets [amount] as the allowance of [spender] over the caller's tokens. Returns a boolean value indicating whether the operation succeeded. IMPORTANT: Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 Emits an [Approval] event. + /// + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future approve( + web3.EthereumAddress spender, + BigInt amount, { + required web3.Credentials credentials, + web3.Transaction? transaction, + }) async { + final function = self.abi.functions[1]; + assert(checkSignature(function, '095ea7b3')); + final params = [spender, amount]; + return writeRaw(credentials, transaction, function, params); + } + + /// Returns the amount of tokens owned by [account]. + /// + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future balanceOf( + web3.EthereumAddress account, { + web3.BlockNum? atBlock, + }) async { + final function = self.abi.functions[2]; + assert(checkSignature(function, '70a08231')); + final params = [account]; + final response = await read(function, params, atBlock); + return (response[0] as BigInt); + } + + /// Returns the decimal precision of the token. + /// + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future decimals({web3.BlockNum? atBlock}) async { + final function = self.abi.functions[3]; + assert(checkSignature(function, '313ce567')); + final params = []; + final response = await read(function, params, atBlock); + return (response[0] as BigInt); + } + + /// Returns the name of the token. + /// + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future name({web3.BlockNum? atBlock}) async { + final function = self.abi.functions[4]; + assert(checkSignature(function, '06fdde03')); + final params = []; + final response = await read(function, params, atBlock); + return (response[0] as String); + } + + /// Returns the symbol of the token. + /// + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future symbol({web3.BlockNum? atBlock}) async { + final function = self.abi.functions[5]; + assert(checkSignature(function, '95d89b41')); + final params = []; + final response = await read(function, params, atBlock); + return (response[0] as String); + } + + /// Returns the amount of tokens in existence. + /// + /// The optional [atBlock] parameter can be used to view historical data. When + /// set, the function will be evaluated in the specified block. By default, the + /// latest on-chain block will be used. + Future totalSupply({web3.BlockNum? atBlock}) async { + final function = self.abi.functions[6]; + assert(checkSignature(function, '18160ddd')); + final params = []; + final response = await read(function, params, atBlock); + return (response[0] as BigInt); + } + + /// Moves [amount] tokens from the caller's account to [recipient]. Returns a boolean value indicating whether the operation succeeded. Emits a [Transfer] event. + /// + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future transfer( + web3.EthereumAddress recipient, + BigInt amount, { + required web3.Credentials credentials, + web3.Transaction? transaction, + }) async { + final function = self.abi.functions[7]; + assert(checkSignature(function, 'a9059cbb')); + final params = [recipient, amount]; + return writeRaw(credentials, transaction, function, params); + } + + /// Moves [amount] tokens from [sender] to [recipient] using the allowance mechanism. [amount] is then deducted from the caller's allowance. Returns a boolean value indicating whether the operation succeeded. Emits a [Transfer] event. + /// + /// The optional [transaction] parameter can be used to override parameters + /// like the gas price, nonce and max gas. The `data` and `to` fields will be + /// set by the contract. + Future transferFrom(web3.EthereumAddress sender, + web3.EthereumAddress recipient, BigInt amount, + {required web3.Credentials credentials, + web3.Transaction? transaction}) async { + final function = self.abi.functions[8]; + assert(checkSignature(function, '23b872dd')); + final params = [sender, recipient, amount]; + return writeRaw(credentials, transaction, function, params); + } + + /// Returns a live stream of all Approval events emitted by this contract. + Stream approvalEvents( + {web3.BlockNum? fromBlock, web3.BlockNum? toBlock}) { + final event = self.event('Approval'); + final filter = web3.FilterOptions.events( + contract: self, event: event, fromBlock: fromBlock, toBlock: toBlock); + return client.events(filter).map((web3.FilterEvent result) { + final decoded = event.decodeResults(result.topics!, result.data!); + return Approval._(decoded); + }); + } + + /// Returns a live stream of all Transfer events emitted by this contract. + Stream transferEvents( + {web3.BlockNum? fromBlock, web3.BlockNum? toBlock}) { + final event = self.event('Transfer'); + final filter = web3.FilterOptions.events( + contract: self, event: event, fromBlock: fromBlock, toBlock: toBlock); + return client.events(filter).map((web3.FilterEvent result) { + final decoded = event.decodeResults(result.topics!, result.data!); + return Transfer._(decoded); + }); + } +} + +/// Emitted when the allowance of a [spender] for an [owner] is set by a call to [ERC20.approve]. [value] is the new allowance. +class Approval { + Approval._(List response) + : owner = (response[0] as web3.EthereumAddress), + spender = (response[1] as web3.EthereumAddress), + value = (response[2] as BigInt); + + /// The owner address. + final web3.EthereumAddress owner; + + /// The spender address. + final web3.EthereumAddress spender; + + /// Value. + final BigInt value; +} + +/// Emitted when [value] tokens are moved from one account ([from]) to another ([to]). Note that [value] may be zero. +class Transfer { + Transfer._(List response) + : from = (response[0] as web3.EthereumAddress), + to = (response[1] as web3.EthereumAddress), + value = (response[2] as BigInt); + + /// From address. + final web3.EthereumAddress from; + + /// To address. + final web3.EthereumAddress to; + + /// Value. + final BigInt value; +} diff --git a/cw_evm/lib/evm_chain_client.dart b/cw_evm/lib/evm_chain_client.dart index 8f0df3926..2185936ea 100644 --- a/cw_evm/lib/evm_chain_client.dart +++ b/cw_evm/lib/evm_chain_client.dart @@ -2,21 +2,20 @@ import 'dart:async'; import 'dart:convert'; import 'dart:developer'; -import 'package:cw_core/node.dart'; -import 'package:cw_core/erc20_token.dart'; import 'package:cw_core/crypto_currency.dart'; - -import 'package:cw_evm/evm_erc20_balance.dart'; +import 'package:cw_core/erc20_token.dart'; +import 'package:cw_core/node.dart'; import 'package:cw_evm/evm_chain_transaction_model.dart'; -import 'package:cw_evm/pending_evm_chain_transaction.dart'; import 'package:cw_evm/evm_chain_transaction_priority.dart'; +import 'package:cw_evm/evm_erc20_balance.dart'; +import 'package:cw_evm/pending_evm_chain_transaction.dart'; import 'package:cw_evm/.secrets.g.dart' as secrets; import 'package:flutter/services.dart'; - -import 'package:http/http.dart'; -import 'package:erc20/erc20.dart'; -import 'package:web3dart/web3dart.dart'; import 'package:hex/hex.dart' as hex; +import 'package:http/http.dart'; +import 'package:web3dart/web3dart.dart'; + +import 'contract/erc20.dart'; abstract class EVMChainClient { final httpClient = Client(); @@ -82,7 +81,7 @@ abstract class EVMChainClient { } Future signTransaction({ - required EthPrivateKey privateKey, + required Credentials privateKey, required String toAddress, required BigInt amount, required int gas, @@ -96,8 +95,7 @@ abstract class EVMChainClient { currency == CryptoCurrency.maticpoly || contractAddress != null); - bool isEVMCompatibleChain = - currency == CryptoCurrency.eth || currency == CryptoCurrency.maticpoly; + bool isNativeToken = currency == CryptoCurrency.eth || currency == CryptoCurrency.maticpoly; final price = _client!.getGasPrice(); @@ -105,17 +103,16 @@ abstract class EVMChainClient { from: privateKey.address, to: EthereumAddress.fromHex(toAddress), maxPriorityFeePerGas: EtherAmount.fromInt(EtherUnit.gwei, priority.tip), - amount: isEVMCompatibleChain ? EtherAmount.inWei(amount) : EtherAmount.zero(), + amount: isNativeToken ? EtherAmount.inWei(amount) : EtherAmount.zero(), data: data != null ? hexToBytes(data) : null, ); - final signedTransaction = - await _client!.signTransaction(privateKey, transaction, chainId: chainId); + Uint8List signedTransaction; final Function _sendTransaction; - if (isEVMCompatibleChain) { - _sendTransaction = () async => await sendTransaction(signedTransaction); + if (isNativeToken) { + signedTransaction = await _client!.signTransaction(privateKey, transaction, chainId: chainId); } else { final erc20 = ERC20( client: _client!, @@ -123,16 +120,17 @@ abstract class EVMChainClient { chainId: chainId, ); - _sendTransaction = () async { - await erc20.transfer( - EthereumAddress.fromHex(toAddress), - amount, - credentials: privateKey, - transaction: transaction, - ); - }; + signedTransaction = await erc20.transfer( + EthereumAddress.fromHex(toAddress), + amount, + credentials: privateKey, + transaction: transaction, + ); } + _sendTransaction = () async => await sendTransaction(signedTransaction); + + return PendingEVMChainTransaction( signedTransaction: signedTransaction, amount: amount.toString(), @@ -158,8 +156,9 @@ abstract class EVMChainClient { ); } - Future sendTransaction(Uint8List signedTransaction) async => - await _client!.sendRawTransaction(prepareSignedTransactionForSending(signedTransaction)); + Future sendTransaction(Uint8List signedTransaction) async { + return await _client!.sendRawTransaction(prepareSignedTransactionForSending(signedTransaction)); + } Future getTransactionDetails(String transactionHash) async { // Wait for the transaction receipt to become available diff --git a/cw_evm/lib/evm_chain_exceptions.dart b/cw_evm/lib/evm_chain_exceptions.dart index 8aa371b19..d0f300270 100644 --- a/cw_evm/lib/evm_chain_exceptions.dart +++ b/cw_evm/lib/evm_chain_exceptions.dart @@ -6,6 +6,8 @@ class EVMChainTransactionCreationException implements Exception { EVMChainTransactionCreationException(CryptoCurrency currency) : exceptionMessage = 'Wrong balance. Not enough ${currency.title} on your balance.'; + EVMChainTransactionCreationException.fromMessage(this.exceptionMessage); + @override String toString() => exceptionMessage; } diff --git a/cw_evm/lib/evm_chain_hardware_wallet_service.dart b/cw_evm/lib/evm_chain_hardware_wallet_service.dart new file mode 100644 index 000000000..6f0d11f2e --- /dev/null +++ b/cw_evm/lib/evm_chain_hardware_wallet_service.dart @@ -0,0 +1,35 @@ +import 'dart:async'; + +import 'package:cw_core/hardware/hardware_account_data.dart'; +import 'package:ledger_ethereum/ledger_ethereum.dart'; +import 'package:ledger_flutter/ledger_flutter.dart'; + +class EVMChainHardwareWalletService { + EVMChainHardwareWalletService(this.ledger, this.device); + + final Ledger ledger; + final LedgerDevice device; + + Future> getAvailableAccounts({int index = 0, int limit = 5}) async { + final ethereumLedgerApp = EthereumLedgerApp(ledger); + + final version = await ethereumLedgerApp.getVersion(device); + + final accounts = []; + final indexRange = List.generate(limit, (i) => i + index); + + for (final i in indexRange) { + final derivationPath = "m/44'/60'/$i'/0/0"; + final address = + await ethereumLedgerApp.getAccounts(device, accountsDerivationPath: derivationPath); + + accounts.add(HardwareAccountData( + address: address.first, + accountIndex: i, + derivationPath: derivationPath, + )); + } + + return accounts; + } +} diff --git a/cw_evm/lib/evm_chain_transaction_credentials.dart b/cw_evm/lib/evm_chain_transaction_credentials.dart index 5b5bdf170..02927cb4d 100644 --- a/cw_evm/lib/evm_chain_transaction_credentials.dart +++ b/cw_evm/lib/evm_chain_transaction_credentials.dart @@ -1,6 +1,7 @@ import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/output_info.dart'; import 'package:cw_evm/evm_chain_transaction_priority.dart'; +import 'package:ledger_flutter/ledger_flutter.dart'; class EVMChainTransactionCredentials { EVMChainTransactionCredentials( diff --git a/cw_evm/lib/evm_chain_wallet.dart b/cw_evm/lib/evm_chain_wallet.dart index 558013252..56b58d400 100644 --- a/cw_evm/lib/evm_chain_wallet.dart +++ b/cw_evm/lib/evm_chain_wallet.dart @@ -25,6 +25,7 @@ import 'package:cw_evm/evm_chain_transaction_history.dart'; import 'package:cw_evm/evm_chain_transaction_model.dart'; import 'package:cw_evm/evm_chain_transaction_priority.dart'; import 'package:cw_evm/evm_chain_wallet_addresses.dart'; +import 'package:cw_evm/evm_ledger_credentials.dart'; import 'package:cw_evm/file.dart'; import 'package:hex/hex.dart'; import 'package:hive/hive.dart'; @@ -83,9 +84,9 @@ abstract class EVMChainWalletBase late final Box evmChainErc20TokensBox; - late final EthPrivateKey _evmChainPrivateKey; + late final Credentials _evmChainPrivateKey; - EthPrivateKey get evmChainPrivateKey => _evmChainPrivateKey; + Credentials get evmChainPrivateKey => _evmChainPrivateKey; late EVMChainClient _client; @@ -141,12 +142,18 @@ abstract class EVMChainWalletBase await walletAddresses.init(); await transactionHistory.init(); - _evmChainPrivateKey = await getPrivateKey( - mnemonic: _mnemonic, - privateKey: _hexPrivateKey, - password: _password, - ); - walletAddresses.address = _evmChainPrivateKey.address.hexEip55; + + if (walletInfo.isHardwareWallet) { + _evmChainPrivateKey = EvmLedgerCredentials(walletInfo.address); + walletAddresses.address = walletInfo.address; + } else { + _evmChainPrivateKey = await getPrivateKey( + mnemonic: _mnemonic, + privateKey: _hexPrivateKey, + password: _password, + ); + walletAddresses.address = _evmChainPrivateKey.address.hexEip55; + } await save(); } @@ -283,6 +290,11 @@ abstract class EVMChainWalletBase } } + if (transactionCurrency is Erc20Token && isHardwareWallet) { + await (_evmChainPrivateKey as EvmLedgerCredentials) + .provideERC20Info(transactionCurrency.contractAddress, _client.chainId); + } + final pendingEVMChainTransaction = await _client.signTransaction( privateKey: _evmChainPrivateKey, toAddress: _credentials.outputs.first.isParsedAddress @@ -377,7 +389,9 @@ abstract class EVMChainWalletBase String? get seed => _mnemonic; @override - String get privateKey => HEX.encode(_evmChainPrivateKey.privateKey); + String? get privateKey => evmChainPrivateKey is EthPrivateKey + ? HEX.encode((evmChainPrivateKey as EthPrivateKey).privateKey) + : null; Future makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type); @@ -535,8 +549,8 @@ abstract class EVMChainWalletBase } @override - String signMessage(String message, {String? address}) => - bytesToHex(_evmChainPrivateKey.signPersonalMessageToUint8List(ascii.encode(message))); + Future signMessage(String message, {String? address}) async => + bytesToHex(await _evmChainPrivateKey.signPersonalMessage(ascii.encode(message))); Web3Client? getWeb3Client() => _client.getWeb3Client(); } diff --git a/cw_evm/lib/evm_chain_wallet_creation_credentials.dart b/cw_evm/lib/evm_chain_wallet_creation_credentials.dart index 7c3271daf..be763bac7 100644 --- a/cw_evm/lib/evm_chain_wallet_creation_credentials.dart +++ b/cw_evm/lib/evm_chain_wallet_creation_credentials.dart @@ -1,3 +1,4 @@ +import 'package:cw_core/hardware/hardware_account_data.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; @@ -27,3 +28,13 @@ class EVMChainRestoreWalletFromPrivateKey extends WalletCredentials { final String privateKey; } + +class EVMChainRestoreWalletFromHardware extends WalletCredentials { + EVMChainRestoreWalletFromHardware({ + required String name, + required this.hwAccountData, + WalletInfo? walletInfo, + }) : super(name: name, walletInfo: walletInfo); + + final HardwareAccountData hwAccountData; +} diff --git a/cw_evm/lib/evm_chain_wallet_service.dart b/cw_evm/lib/evm_chain_wallet_service.dart index d77a3a81a..2bbe6bd47 100644 --- a/cw_evm/lib/evm_chain_wallet_service.dart +++ b/cw_evm/lib/evm_chain_wallet_service.dart @@ -13,7 +13,8 @@ import 'package:hive/hive.dart'; abstract class EVMChainWalletService extends WalletService< EVMChainNewWalletCredentials, EVMChainRestoreWalletFromSeedCredentials, - EVMChainRestoreWalletFromPrivateKey> { + EVMChainRestoreWalletFromPrivateKey, + EVMChainRestoreWalletFromHardware> { EVMChainWalletService(this.walletInfoSource); final Box walletInfoSource; @@ -24,6 +25,9 @@ abstract class EVMChainWalletService extends WalletSer @override Future create(EVMChainNewWalletCredentials credentials, {bool? isTestnet}); + @override + Future restoreFromHardwareWallet(EVMChainRestoreWalletFromHardware credentials); + @override Future openWallet(String name, String password); diff --git a/cw_evm/lib/evm_ledger_credentials.dart b/cw_evm/lib/evm_ledger_credentials.dart new file mode 100644 index 000000000..0d8de1736 --- /dev/null +++ b/cw_evm/lib/evm_ledger_credentials.dart @@ -0,0 +1,103 @@ +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:cw_core/hardware/device_not_connected_exception.dart'; +import 'package:ledger_ethereum/ledger_ethereum.dart'; +import 'package:ledger_flutter/ledger_flutter.dart'; +import 'package:web3dart/crypto.dart'; +import 'package:web3dart/web3dart.dart'; + +class EvmLedgerCredentials extends CredentialsWithKnownAddress { + final String _address; + + Ledger? ledger; + LedgerDevice? ledgerDevice; + EthereumLedgerApp? ethereumLedgerApp; + + EvmLedgerCredentials(this._address); + + @override + EthereumAddress get address => EthereumAddress.fromHex(_address); + + void setLedger(Ledger setLedger, [LedgerDevice? setLedgerDevice, String? derivationPath]) { + ledger = setLedger; + ledgerDevice = setLedgerDevice; + ethereumLedgerApp = + EthereumLedgerApp(ledger!, derivationPath: derivationPath ?? "m/44'/60'/0'/0/0"); + } + + @override + MsgSignature signToEcSignature(Uint8List payload, {int? chainId, bool isEIP1559 = false}) => + throw UnimplementedError("EvmLedgerCredentials.signToEcSignature"); + + @override + Future signToSignature(Uint8List payload, + {int? chainId, bool isEIP1559 = false}) async { + if (ledgerDevice == null && ledger?.devices.isNotEmpty != true) { + throw DeviceNotConnectedException(); + } + + final sig = await ethereumLedgerApp!.signTransaction(device, payload); + + final v = sig[0].toInt(); + final r = bytesToHex(sig.sublist(1, 1 + 32)); + final s = bytesToHex(sig.sublist(1 + 32, 1 + 32 + 32)); + + var truncChainId = chainId ?? 1; + while (truncChainId.bitLength > 32) { + truncChainId >>= 8; + } + + final truncTarget = truncChainId * 2 + 35; + + int parity = v; + if (truncTarget & 0xff == v) { + parity = 0; + } else if ((truncTarget + 1) & 0xff == v) { + parity = 1; + } + + // https://github.com/ethereumjs/ethereumjs-util/blob/8ffe697fafb33cefc7b7ec01c11e3a7da787fe0e/src/signature.ts#L26 + int chainIdV; + if (isEIP1559) { + chainIdV = v; + } else { + chainIdV = chainId != null ? (parity + (chainId * 2 + 35)) : parity; + } + + return MsgSignature(BigInt.parse(r, radix: 16), BigInt.parse(s, radix: 16), chainIdV); + } + + @override + Future signPersonalMessage(Uint8List payload, {int? chainId}) async { + if (isNotConnected) throw DeviceNotConnectedException(); + + final sig = await ethereumLedgerApp!.signMessage(device, payload); + + final r = sig.sublist(1, 1 + 32); + final s = sig.sublist(1 + 32, 1 + 32 + 32); + final v = [sig[0]]; + + // https://github.com/ethereumjs/ethereumjs-util/blob/8ffe697fafb33cefc7b7ec01c11e3a7da787fe0e/src/signature.ts#L63 + return Uint8List.fromList(r + s + v); + } + + @override + Uint8List signPersonalMessageToUint8List(Uint8List payload, {int? chainId}) => + throw UnimplementedError("EvmLedgerCredentials.signPersonalMessageToUint8List"); + + Future provideERC20Info(String erc20ContractAddress, int chainId) async { + if (isNotConnected) throw DeviceNotConnectedException(); + + try { + await ethereumLedgerApp!.getAndProvideERC20TokenInformation(device, + erc20ContractAddress: erc20ContractAddress, chainId: chainId); + } on LedgerException catch (e) { + if (e.errorCode != -28672) rethrow; + } + } + + bool get isNotConnected => (ledgerDevice ?? ledger?.devices.firstOrNull) == null; + + LedgerDevice get device => ledgerDevice ?? ledger!.devices.first; +} diff --git a/cw_evm/pubspec.yaml b/cw_evm/pubspec.yaml index c202cc72a..fb0384064 100644 --- a/cw_evm/pubspec.yaml +++ b/cw_evm/pubspec.yaml @@ -13,7 +13,6 @@ dependencies: flutter: sdk: flutter web3dart: ^2.7.1 - erc20: ^1.0.1 bip39: ^1.0.6 bip32: ^2.0.0 hex: ^0.2.0 @@ -23,6 +22,20 @@ dependencies: shared_preferences: ^2.0.15 cw_core: path: ../cw_core + ledger_flutter: ^1.0.1 + ledger_ethereum: + git: + url: https://github.com/cake-tech/ledger-ethereum.git + +dependency_overrides: + web3dart: + git: + url: https://github.com/cake-tech/web3dart.git + ref: cake + ledger_flutter: + git: + url: https://github.com/cake-tech/ledger-flutter.git + ref: cake dev_dependencies: flutter_test: diff --git a/cw_haven/lib/haven_wallet_service.dart b/cw_haven/lib/haven_wallet_service.dart index d4808c2d6..14bc520da 100644 --- a/cw_haven/lib/haven_wallet_service.dart +++ b/cw_haven/lib/haven_wallet_service.dart @@ -56,7 +56,8 @@ class HavenRestoreWalletFromKeysCredentials extends WalletCredentials { class HavenWalletService extends WalletService< HavenNewWalletCredentials, HavenRestoreWalletFromSeedCredentials, - HavenRestoreWalletFromKeysCredentials> { + HavenRestoreWalletFromKeysCredentials, + HavenNewWalletCredentials> { HavenWalletService(this.walletInfoSource); final Box walletInfoSource; @@ -172,6 +173,11 @@ class HavenWalletService extends WalletService< await walletInfoSource.put(currentWalletInfo.key, newWalletInfo); } + @override + Future restoreFromHardwareWallet(HavenNewWalletCredentials credentials) { + throw UnimplementedError("Restoring a Haven wallet from a hardware wallet is not yet supported!"); + } + @override Future restoreFromKeys( HavenRestoreWalletFromKeysCredentials credentials, {bool? isTestnet}) async { diff --git a/cw_monero/lib/api/signatures.dart b/cw_monero/lib/api/signatures.dart index bc4fc9d38..bba7b5528 100644 --- a/cw_monero/lib/api/signatures.dart +++ b/cw_monero/lib/api/signatures.dart @@ -17,6 +17,9 @@ typedef restore_wallet_from_keys = Int8 Function(Pointer, Pointer, P typedef restore_wallet_from_spend_key = Int8 Function(Pointer, Pointer, Pointer, Pointer, Pointer, Int32, Int64, Pointer); +// typedef restore_wallet_from_device = Int8 Function(Pointer, Pointer, Pointer, +// Int32, Int64, Pointer); + typedef is_wallet_exist = Int8 Function(Pointer); typedef load_wallet = Int8 Function(Pointer, Pointer, Int8); diff --git a/cw_monero/lib/api/types.dart b/cw_monero/lib/api/types.dart index 40a1e0321..87d8a153e 100644 --- a/cw_monero/lib/api/types.dart +++ b/cw_monero/lib/api/types.dart @@ -17,6 +17,9 @@ typedef RestoreWalletFromKeys = int Function(Pointer, Pointer, typedef RestoreWalletFromSpendKey = int Function(Pointer, Pointer, Pointer, Pointer, Pointer, int, int, Pointer); +typedef RestoreWalletFromDevice = int Function(Pointer, Pointer, Pointer, + int, int, Pointer); + typedef IsWalletExist = int Function(Pointer); typedef LoadWallet = int Function(Pointer, Pointer, int); diff --git a/cw_monero/lib/api/wallet_manager.dart b/cw_monero/lib/api/wallet_manager.dart index 0aa694e9a..ae88f76ab 100644 --- a/cw_monero/lib/api/wallet_manager.dart +++ b/cw_monero/lib/api/wallet_manager.dart @@ -31,6 +31,11 @@ final restoreWalletFromSpendKeyNative = moneroApi 'restore_wallet_from_spend_key') .asFunction(); +// final restoreWalletFromDeviceNative = moneroApi +// .lookup>( +// 'restore_wallet_from_device') +// .asFunction(); + final isWalletExistNative = moneroApi .lookup>('is_wallet_exist') .asFunction(); @@ -185,6 +190,38 @@ void restoreWalletFromSpendKeySync( } } +// void restoreMoneroWalletFromDevice( +// {required String path, +// required String password, +// required String deviceName, +// int nettype = 0, +// int restoreHeight = 0}) { +// +// final pathPointer = path.toNativeUtf8(); +// final passwordPointer = password.toNativeUtf8(); +// final deviceNamePointer = deviceName.toNativeUtf8(); +// final errorMessagePointer = ''.toNativeUtf8(); +// +// final isWalletRestored = restoreWalletFromDeviceNative( +// pathPointer, +// passwordPointer, +// deviceNamePointer, +// nettype, +// restoreHeight, +// errorMessagePointer) != 0; +// +// calloc.free(pathPointer); +// calloc.free(passwordPointer); +// +// storeSync(); +// +// if (!isWalletRestored) { +// throw WalletRestoreFromKeysException( +// message: convertUTF8ToString(pointer: errorMessagePointer)); +// } +// } + + void loadWallet({ required String path, required String password, diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index d00a54c8f..c270bb113 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -686,7 +686,7 @@ abstract class MoneroWalletBase void setExceptionHandler(void Function(FlutterErrorDetails) e) => onError = e; @override - String signMessage(String message, {String? address}) { + Future signMessage(String message, {String? address}) async { final useAddress = address ?? ""; return monero_wallet.signMessage(message, address: useAddress); } diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 1f33dbb3d..bc59499f9 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -55,7 +55,7 @@ class MoneroRestoreWalletFromKeysCredentials extends WalletCredentials { } class MoneroWalletService extends WalletService { + MoneroRestoreWalletFromSeedCredentials, MoneroRestoreWalletFromKeysCredentials, MoneroNewWalletCredentials> { MoneroWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); final Box walletInfoSource; @@ -227,6 +227,11 @@ class MoneroWalletService extends WalletService restoreFromHardwareWallet(MoneroNewWalletCredentials credentials) { + throw UnimplementedError("Restoring a Monero wallet from a hardware wallet is not yet supported!"); + } + @override Future restoreFromSeed(MoneroRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { diff --git a/cw_nano/lib/nano_wallet_service.dart b/cw_nano/lib/nano_wallet_service.dart index b1497a625..a1af3c872 100644 --- a/cw_nano/lib/nano_wallet_service.dart +++ b/cw_nano/lib/nano_wallet_service.dart @@ -14,7 +14,7 @@ import 'package:nanodart/nanodart.dart'; import 'package:nanoutil/nanoutil.dart'; class NanoWalletService extends WalletService { + NanoRestoreWalletFromSeedCredentials, NanoRestoreWalletFromKeysCredentials, NanoNewWalletCredentials> { NanoWalletService(this.walletInfoSource); final Box walletInfoSource; @@ -109,6 +109,11 @@ class NanoWalletService extends WalletService restoreFromHardwareWallet(NanoNewWalletCredentials credentials) { + throw UnimplementedError("Restoring a Nano wallet from a hardware wallet is not yet supported!"); + } + @override Future restoreFromSeed(NanoRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { if (credentials.mnemonic.contains(' ')) { diff --git a/cw_polygon/lib/polygon_wallet_service.dart b/cw_polygon/lib/polygon_wallet_service.dart index 59e14abbf..ee84a014e 100644 --- a/cw_polygon/lib/polygon_wallet_service.dart +++ b/cw_polygon/lib/polygon_wallet_service.dart @@ -1,5 +1,6 @@ import 'package:bip39/bip39.dart' as bip39; import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cw_evm/evm_chain_wallet_creation_credentials.dart'; import 'package:cw_evm/evm_chain_wallet_service.dart'; @@ -86,6 +87,29 @@ class PolygonWalletService extends EVMChainWalletService { return wallet; } + @override + Future restoreFromHardwareWallet( + EVMChainRestoreWalletFromHardware credentials) async { + credentials.walletInfo!.derivationInfo = DerivationInfo( + derivationType: DerivationType.bip39, + derivationPath: "m/44'/60'/${credentials.hwAccountData.accountIndex}'/0/0" + ); + credentials.walletInfo!.hardwareWalletType = credentials.hardwareWalletType; + credentials.walletInfo!.address = credentials.hwAccountData.address; + + final wallet = PolygonWallet( + walletInfo: credentials.walletInfo!, + password: credentials.password!, + client: client, + ); + + await wallet.init(); + wallet.addInitialTokens(); + await wallet.save(); + + return wallet; + } + @override Future restoreFromSeed(EVMChainRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { diff --git a/cw_polygon/pubspec.yaml b/cw_polygon/pubspec.yaml index 505838d7c..dbef40b46 100644 --- a/cw_polygon/pubspec.yaml +++ b/cw_polygon/pubspec.yaml @@ -23,6 +23,11 @@ dependencies: bip39: ^1.0.6 collection: ^1.17.1 +dependency_overrides: + web3dart: + git: + url: https://github.com/cake-tech/web3dart.git + ref: cake dev_dependencies: flutter_test: diff --git a/cw_solana/lib/solana_wallet_service.dart b/cw_solana/lib/solana_wallet_service.dart index 83370ff73..4afb2f7f4 100644 --- a/cw_solana/lib/solana_wallet_service.dart +++ b/cw_solana/lib/solana_wallet_service.dart @@ -2,7 +2,10 @@ import 'dart:io'; import 'package:bip39/bip39.dart' as bip39; import 'package:collection/collection.dart'; +import 'package:cw_core/balance.dart'; import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/transaction_history.dart'; +import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; @@ -13,7 +16,7 @@ import 'package:cw_solana/solana_wallet_creation_credentials.dart'; import 'package:hive/hive.dart'; class SolanaWalletService extends WalletService { + SolanaRestoreWalletFromSeedCredentials, SolanaRestoreWalletFromPrivateKey, SolanaNewWalletCredentials> { SolanaWalletService(this.walletInfoSource); final Box walletInfoSource; @@ -134,4 +137,10 @@ class SolanaWalletService extends WalletService, TransactionInfo>> restoreFromHardwareWallet(SolanaNewWalletCredentials credentials) { + // TODO: implement restoreFromHardwareWallet + throw UnimplementedError(); + } } diff --git a/cw_tron/lib/tron_wallet.dart b/cw_tron/lib/tron_wallet.dart index a798f343a..6cef05348 100644 --- a/cw_tron/lib/tron_wallet.dart +++ b/cw_tron/lib/tron_wallet.dart @@ -551,7 +551,7 @@ abstract class TronWalletBase } @override - String signMessage(String message, {String? address}) => + Future signMessage(String message, {String? address}) async => _tronPrivateKey.signPersonalMessage(ascii.encode(message)); String getTronBase58AddressFromHex(String hexAddress) { diff --git a/cw_tron/lib/tron_wallet_service.dart b/cw_tron/lib/tron_wallet_service.dart index f4e98ee5d..c8344d5f4 100644 --- a/cw_tron/lib/tron_wallet_service.dart +++ b/cw_tron/lib/tron_wallet_service.dart @@ -1,7 +1,10 @@ import 'dart:io'; import 'package:bip39/bip39.dart' as bip39; +import 'package:cw_core/balance.dart'; import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/transaction_history.dart'; +import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; @@ -13,8 +16,11 @@ import 'package:cw_tron/tron_wallet_creation_credentials.dart'; import 'package:hive/hive.dart'; import 'package:collection/collection.dart'; -class TronWalletService extends WalletService { +class TronWalletService extends WalletService< + TronNewWalletCredentials, + TronRestoreWalletFromSeedCredentials, + TronRestoreWalletFromPrivateKey, + TronNewWalletCredentials> { TronWalletService(this.walletInfoSource, {required this.client}); late TronClient client; @@ -145,4 +151,10 @@ class TronWalletService extends WalletService info.id == WalletBase.idFor(wallet, getType()))!; await walletInfoSource.delete(walletInfo.key); } + + @override + Future, TransactionInfo>> restoreFromHardwareWallet(TronNewWalletCredentials credentials) { + // TODO: implement restoreFromHardwareWallet + throw UnimplementedError(); + } } diff --git a/how_to_add_new_wallet_type.md b/how_to_add_new_wallet_type.md index 011e99990..95b82d802 100644 --- a/how_to_add_new_wallet_type.md +++ b/how_to_add_new_wallet_type.md @@ -277,6 +277,7 @@ Now you can run the codebase and successfully create a wallet for type walletX s - Modify `getCredentialsFromRestoredWallet` method - Go to `lib/core/address_validator.dart` - Modify the `getAddressFromStringPattern` method to add a case for `WalletType.walletx` +- and if it has tokens (ex. erc20, trc20, spl tokens) then add them to the switch case as well - Add the scheme for walletx for both Android in `AndroidManifestBase.xml` and iOS in `InfoBase.plist` **Transaction History** @@ -291,10 +292,10 @@ Now you can run the codebase and successfully create a wallet for type walletX s # Points to note when adding the new wallet type 1. if it has tokens (ex. ERC20, SPL, etc...) make sure to add that to this function `_checkIfCanSend` in `exchange_trade_view_model.dart` +1. if it has tokens (ex. ERC20, SPL, etc...) make sure to add a check for the tags as well in the 2. Check On/Off ramp providers that support the new wallet currency and add them accordingly in `provider_types.dart` 3. Add support for wallet uri scheme to restore from QR for both Android in `AndroidManifestBase.xml` and iOS in `InfoBase.plist` 4. Make sure no imports are using the wallet internal package files directly, instead use the proxy layers that is created in the main lib `lib/cw_ethereum.dart` for example. (i.e try building Monero.com if you get compilation errors, then you probably missed something) -5. Copyright (C) 2018-2023 Cake Labs LLC diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 67c0c9ee8..cd03e10a9 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -131,7 +131,12 @@ PODS: - FlutterMacOS - permission_handler_apple (9.1.1): - Flutter + - Protobuf (3.25.3) - ReachabilitySwift (5.0.0) + - reactive_ble_mobile (0.0.1): + - Flutter + - Protobuf (~> 3.5) + - SwiftProtobuf (~> 1.0) - SDWebImage (5.18.11): - SDWebImage/Core (= 5.18.11) - SDWebImage/Core (5.18.11) @@ -179,6 +184,7 @@ DEPENDENCIES: - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) + - reactive_ble_mobile (from `.symlinks/plugins/reactive_ble_mobile/ios`) - sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) @@ -196,6 +202,7 @@ SPEC REPOS: - DKPhotoGallery - MTBBarcodeScanner - OrderedSet + - Protobuf - ReachabilitySwift - SDWebImage - SwiftProtobuf @@ -244,6 +251,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/path_provider_foundation/darwin" permission_handler_apple: :path: ".symlinks/plugins/permission_handler_apple/ios" + reactive_ble_mobile: + :path: ".symlinks/plugins/reactive_ble_mobile/ios" sensitive_clipboard: :path: ".symlinks/plugins/sensitive_clipboard/ios" share_plus: @@ -286,7 +295,9 @@ SPEC CHECKSUMS: package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 + Protobuf: 8e9074797a13c484a79959fdb819ef4ae6da7dbe ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 + reactive_ble_mobile: 9ce6723d37ccf701dbffd202d487f23f5de03b4c SDWebImage: a3ba0b8faac7228c3c8eadd1a55c9c9fe5e16457 sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986 share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 7a8b99b49..8ed46a028 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + 9F46EE5E2BC11178009318F5 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 9F46EE5D2BC11178009318F5 /* PrivacyInfo.xcprivacy */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -40,6 +41,7 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9F46EE5D2BC11178009318F5 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; AD0937B0140D5A4C24E73BEA /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -123,6 +125,7 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 97C147021CF9000F007C117D /* Info.plist */, + 9F46EE5D2BC11178009318F5 /* PrivacyInfo.xcprivacy */, 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, @@ -196,6 +199,7 @@ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 9F46EE5E2BC11178009318F5 /* PrivacyInfo.xcprivacy in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ios/Runner/InfoBase.plist b/ios/Runner/InfoBase.plist index 443f9791f..02365bda7 100644 --- a/ios/Runner/InfoBase.plist +++ b/ios/Runner/InfoBase.plist @@ -210,16 +210,6 @@ tron-wallet - - CFBundleTypeRole - Viewer - CFBundleURLName - tron_wallet - CFBundleURLSchemes - - tron_wallet - - CFBundleVersion $(CURRENT_PROJECT_VERSION) @@ -238,6 +228,10 @@ Enable Face ID for fast and secure access to wallets and private keys NSPhotoLibraryUsageDescription We need access to documents folder for getting access to open/save backup file + NSBluetoothPeripheralUsageDescription + We need access to Bluetooth in order to connect to your hardware wallet when needed + NSBluetoothAlwaysUsageDescription + We need access to Bluetooth in order to connect to your hardware wallet when needed UIBackgroundModes fetch diff --git a/ios/Runner/PrivacyInfo.xcprivacy b/ios/Runner/PrivacyInfo.xcprivacy new file mode 100644 index 000000000..51fa92043 --- /dev/null +++ b/ios/Runner/PrivacyInfo.xcprivacy @@ -0,0 +1,24 @@ + + + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + CA92.1 + + + + + \ No newline at end of file diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 7ae01df1c..56c9c7dff 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -32,6 +32,14 @@ class CWBitcoin extends Bitcoin { {required String name, WalletInfo? walletInfo}) => BitcoinNewWalletCredentials(name: name, walletInfo: walletInfo); + @override + WalletCredentials createBitcoinHardwareWalletCredentials( + {required String name, + required HardwareAccountData accountData, + WalletInfo? walletInfo}) => + BitcoinRestoreWalletFromHardware( + name: name, hwAccountData: accountData, walletInfo: walletInfo); + @override TransactionPriority getMediumTransactionPriority() => BitcoinTransactionPriority.medium; @@ -292,7 +300,7 @@ class CWBitcoin extends Bitcoin { return [ DerivationInfo( derivationType: DerivationType.electrum, - derivationPath: "m/0'/0", + derivationPath: "m/0'", description: "Electrum", scriptType: "p2wpkh", ) @@ -344,9 +352,6 @@ class CWBitcoin extends Bitcoin { if (derivationDepth == 3) { // we add "/0/0" so that we generate account 0, index 0 and correctly get balance derivationPath += "/0/0"; - // we don't support sub-ACCOUNTS in bitcoin like we do monero, and so the path dInfoCopy - // expects should be ACCOUNT 0, index unspecified: - dInfoCopy.derivationPath = dInfoCopy.derivationPath! + "/0"; } // var hd = bip32.BIP32.fromSeed(seedBytes).derivePath(derivationPath); @@ -440,4 +445,21 @@ class CWBitcoin extends Bitcoin { final bitcoinWallet = wallet as ElectrumWallet; return (bitcoinWallet.feeRate(BitcoinTransactionPriority.fast) * 1.1).round(); } + + @override + void setLedger(WalletBase wallet, Ledger ledger, LedgerDevice device) { + (wallet as BitcoinWallet).setLedger(ledger, device); + } + + @override + Future> getHardwareWalletAccounts(LedgerViewModel ledgerVM, + {int index = 0, int limit = 5}) async { + final hardwareWalletService = BitcoinHardwareWalletService(ledgerVM.ledger, ledgerVM.device); + try { + return hardwareWalletService.getAvailableAccounts(index: index, limit: limit); + } on LedgerException catch (err) { + print(err.message); + throw err; + } + } } diff --git a/lib/buy/buy_provider.dart b/lib/buy/buy_provider.dart index 4e4c113f4..1a37e09b3 100644 --- a/lib/buy/buy_provider.dart +++ b/lib/buy/buy_provider.dart @@ -1,5 +1,6 @@ import 'package:cake_wallet/buy/buy_amount.dart'; import 'package:cake_wallet/buy/order.dart'; +import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:flutter/material.dart'; @@ -7,10 +8,12 @@ abstract class BuyProvider { BuyProvider({ required this.wallet, required this.isTestEnvironment, + required this.ledgerVM, }); final WalletBase wallet; final bool isTestEnvironment; + final LedgerViewModel? ledgerVM; String get title; diff --git a/lib/buy/dfx/dfx_buy_provider.dart b/lib/buy/dfx/dfx_buy_provider.dart index bf67edd23..2a7e2ab13 100644 --- a/lib/buy/dfx/dfx_buy_provider.dart +++ b/lib/buy/dfx/dfx_buy_provider.dart @@ -3,9 +3,11 @@ import 'dart:convert'; import 'package:cake_wallet/buy/buy_provider.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; @@ -13,8 +15,8 @@ import 'package:http/http.dart' as http; import 'package:url_launcher/url_launcher.dart'; class DFXBuyProvider extends BuyProvider { - DFXBuyProvider({required WalletBase wallet, bool isTestEnvironment = false}) - : super(wallet: wallet, isTestEnvironment: isTestEnvironment); + DFXBuyProvider({required WalletBase wallet, bool isTestEnvironment = false, LedgerViewModel? ledgerVM}) + : super(wallet: wallet, isTestEnvironment: isTestEnvironment, ledgerVM: ledgerVM); static const _baseUrl = 'api.dfx.swiss'; // static const _signMessagePath = '/v1/auth/signMessage'; @@ -91,7 +93,7 @@ class DFXBuyProvider extends BuyProvider { // } Future auth() async { - final signMessage = getSignature(await getSignMessage()); + final signMessage = await getSignature(await getSignMessage()); final requestBody = jsonEncode({ 'wallet': walletName, @@ -118,7 +120,7 @@ class DFXBuyProvider extends BuyProvider { } } - String getSignature(String message) { + Future getSignature(String message) async { switch (wallet.type) { case WalletType.ethereum: case WalletType.polygon: @@ -135,6 +137,20 @@ class DFXBuyProvider extends BuyProvider { @override Future launchProvider(BuildContext context, bool? isBuyAction) async { + if (wallet.isHardwareWallet) { + if (!ledgerVM!.isConnected) { + await Navigator.of(context).pushNamed(Routes.connectDevices, + arguments: ConnectDevicePageParams( + walletType: wallet.walletInfo.type, + onConnectDevice: (BuildContext context, LedgerViewModel ledgerVM) { + ledgerVM.setLedger(wallet); + Navigator.of(context).pop(); + })); + } else { + ledgerVM!.setLedger(wallet); + } + } + try { final assetOut = this.assetOut; final blockchain = this.blockchain; diff --git a/lib/buy/moonpay/moonpay_provider.dart b/lib/buy/moonpay/moonpay_provider.dart index fea8fdabd..53f018d57 100644 --- a/lib/buy/moonpay/moonpay_provider.dart +++ b/lib/buy/moonpay/moonpay_provider.dart @@ -14,7 +14,6 @@ import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/device_info.dart'; -import 'package:crypto/crypto.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; @@ -30,7 +29,7 @@ class MoonPayProvider extends BuyProvider { }) : baseSellUrl = isTestEnvironment ? _baseSellTestUrl : _baseSellProductUrl, baseBuyUrl = isTestEnvironment ? _baseBuyTestUrl : _baseBuyProductUrl, this._settingsStore = settingsStore, - super(wallet: wallet, isTestEnvironment: isTestEnvironment); + super(wallet: wallet, isTestEnvironment: isTestEnvironment, ledgerVM: null); final SettingsStore _settingsStore; diff --git a/lib/buy/onramper/onramper_buy_provider.dart b/lib/buy/onramper/onramper_buy_provider.dart index 3819f074d..1f1c86962 100644 --- a/lib/buy/onramper/onramper_buy_provider.dart +++ b/lib/buy/onramper/onramper_buy_provider.dart @@ -13,7 +13,7 @@ import 'package:url_launcher/url_launcher.dart'; class OnRamperBuyProvider extends BuyProvider { OnRamperBuyProvider(this._settingsStore, {required WalletBase wallet, bool isTestEnvironment = false}) - : super(wallet: wallet, isTestEnvironment: isTestEnvironment); + : super(wallet: wallet, isTestEnvironment: isTestEnvironment, ledgerVM: null); static const _baseUrl = 'buy.onramper.com'; diff --git a/lib/buy/robinhood/robinhood_buy_provider.dart b/lib/buy/robinhood/robinhood_buy_provider.dart index 7610e51f3..ab58754dd 100644 --- a/lib/buy/robinhood/robinhood_buy_provider.dart +++ b/lib/buy/robinhood/robinhood_buy_provider.dart @@ -3,8 +3,11 @@ import 'dart:convert'; import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/buy/buy_provider.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; @@ -12,8 +15,8 @@ import 'package:http/http.dart' as http; import 'package:url_launcher/url_launcher.dart'; class RobinhoodBuyProvider extends BuyProvider { - RobinhoodBuyProvider({required WalletBase wallet, bool isTestEnvironment = false}) - : super(wallet: wallet, isTestEnvironment: isTestEnvironment); + RobinhoodBuyProvider({required WalletBase wallet, bool isTestEnvironment = false, LedgerViewModel? ledgerVM}) + : super(wallet: wallet, isTestEnvironment: isTestEnvironment, ledgerVM: ledgerVM); static const _baseUrl = 'applink.robinhood.com'; static const _cIdBaseUrl = 'exchange-helper.cakewallet.com'; @@ -34,7 +37,7 @@ class RobinhoodBuyProvider extends BuyProvider { String get _apiSecret => secrets.exchangeHelperApiKey; - String getSignature(String message) { + Future getSignature(String message) { switch (wallet.type) { case WalletType.ethereum: case WalletType.polygon: @@ -53,7 +56,7 @@ class RobinhoodBuyProvider extends BuyProvider { final valid_until = (DateTime.now().millisecondsSinceEpoch / 1000).round() + 10; final message = "$_apiSecret:${valid_until}"; - final signature = getSignature(message); + final signature = await getSignature(message); final uri = Uri.https(_cIdBaseUrl, "/api/robinhood"); @@ -84,6 +87,20 @@ class RobinhoodBuyProvider extends BuyProvider { } Future launchProvider(BuildContext context, bool? isBuyAction) async { + if (wallet.isHardwareWallet) { + if (!ledgerVM!.isConnected) { + await Navigator.of(context).pushNamed(Routes.connectDevices, + arguments: ConnectDevicePageParams( + walletType: wallet.walletInfo.type, + onConnectDevice: (BuildContext context, LedgerViewModel ledgerVM) { + ledgerVM.setLedger(wallet); + Navigator.of(context).pop(); + })); + } else { + ledgerVM!.setLedger(wallet); + } + } + try { final uri = await requestProviderUrl(); await launchUrl(uri, mode: LaunchMode.externalApplication); diff --git a/lib/buy/wyre/wyre_buy_provider.dart b/lib/buy/wyre/wyre_buy_provider.dart index 4dd091c33..e09186ad5 100644 --- a/lib/buy/wyre/wyre_buy_provider.dart +++ b/lib/buy/wyre/wyre_buy_provider.dart @@ -14,7 +14,7 @@ import 'package:cake_wallet/.secrets.g.dart' as secrets; class WyreBuyProvider extends BuyProvider { WyreBuyProvider({required WalletBase wallet, bool isTestEnvironment = false}) : baseApiUrl = isTestEnvironment ? _baseTestApiUrl : _baseProductApiUrl, - super(wallet: wallet, isTestEnvironment: isTestEnvironment); + super(wallet: wallet, isTestEnvironment: isTestEnvironment, ledgerVM: null); static const _baseTestApiUrl = 'https://api.testwyre.com'; static const _baseProductApiUrl = 'https://api.sendwyre.com'; diff --git a/lib/core/address_validator.dart b/lib/core/address_validator.dart index 01374d5a2..e507f5212 100644 --- a/lib/core/address_validator.dart +++ b/lib/core/address_validator.dart @@ -295,7 +295,7 @@ class AddressValidator extends TextValidator { case CryptoCurrency.sol: return '([^0-9a-zA-Z]|^)[1-9A-HJ-NP-Za-km-z]{43,44}([^0-9a-zA-Z]|\$)'; case CryptoCurrency.trx: - return '^(T|t)[1-9A-HJ-NP-Za-km-z]{33}\$'; + return '(T|t)[1-9A-HJ-NP-Za-km-z]{33}'; default: if (type.tag == CryptoCurrency.eth.title) { return '0x[0-9a-zA-Z]{42}'; @@ -306,6 +306,9 @@ class AddressValidator extends TextValidator { if (type.tag == CryptoCurrency.sol.title) { return '([^0-9a-zA-Z]|^)[1-9A-HJ-NP-Za-km-z]{43,44}([^0-9a-zA-Z]|\$)'; } + if (type.tag == CryptoCurrency.trx.title) { + return '(T|t)[1-9A-HJ-NP-Za-km-z]{33}'; + } return null; } diff --git a/lib/core/wallet_creation_service.dart b/lib/core/wallet_creation_service.dart index 31a893ad6..646e47537 100644 --- a/lib/core/wallet_creation_service.dart +++ b/lib/core/wallet_creation_service.dart @@ -101,4 +101,19 @@ class WalletCreationService { return wallet; } + + Future restoreFromHardwareWallet(WalletCredentials credentials) async { + checkIfExists(credentials.name); + final password = generateWalletPassword(); + credentials.password = password; + await keyService.saveWalletPassword(password: password, walletName: credentials.name); + final wallet = await _service!.restoreFromHardwareWallet(credentials); + + if (wallet.type == WalletType.monero) { + await sharedPreferences.setBool( + PreferencesKey.moneroWalletUpdateV1Key(wallet.name), _isNewMoneroWalletPasswordUpdated); + } + + return wallet; + } } diff --git a/lib/di.dart b/lib/di.dart index 00710897f..d280362b4 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -1,237 +1,240 @@ +import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/anonpay/anonpay_api.dart'; import 'package:cake_wallet/anonpay/anonpay_info_base.dart'; import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart'; +import 'package:cake_wallet/anypay/any_pay_payment_committed_info.dart'; +import 'package:cake_wallet/anypay/anypay_api.dart'; +import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:cake_wallet/buy/moonpay/moonpay_provider.dart'; import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart'; -import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; +import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/buy/payfura/payfura_buy_provider.dart'; +import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart'; +import 'package:cake_wallet/core/auth_service.dart'; +import 'package:cake_wallet/core/backup_service.dart'; +import 'package:cake_wallet/core/key_service.dart'; import 'package:cake_wallet/core/wallet_connect/wallet_connect_key_service.dart'; import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart'; -import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart'; import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart'; +import 'package:cake_wallet/core/wallet_creation_service.dart'; +import 'package:cake_wallet/core/wallet_loading_service.dart'; import 'package:cake_wallet/core/yat_service.dart'; import 'package:cake_wallet/entities/background_tasks.dart'; +import 'package:cake_wallet/entities/biometric_auth.dart'; +import 'package:cake_wallet/entities/contact.dart'; +import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/parse_address_from_domain.dart'; import 'package:cake_wallet/tron/tron.dart'; import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart'; import 'package:cw_core/receive_page_option.dart'; +import 'package:cake_wallet/entities/qr_view_data.dart'; +import 'package:cake_wallet/entities/template.dart'; +import 'package:cake_wallet/entities/transaction_description.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; -import 'package:cake_wallet/nano/nano.dart'; +import 'package:cake_wallet/exchange/exchange_template.dart'; +import 'package:cake_wallet/exchange/trade.dart'; +import 'package:cake_wallet/haven/haven.dart'; +import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart'; import 'package:cake_wallet/ionia/ionia_anypay.dart'; +import 'package:cake_wallet/ionia/ionia_api.dart'; import 'package:cake_wallet/ionia/ionia_gift_card.dart'; +import 'package:cake_wallet/ionia/ionia_merchant.dart'; +import 'package:cake_wallet/ionia/ionia_service.dart'; import 'package:cake_wallet/ionia/ionia_tip.dart'; +import 'package:cake_wallet/monero/monero.dart'; +import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cake_wallet/reactions/on_authentication_state_change.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/solana/solana.dart'; import 'package:cake_wallet/src/screens/anonpay_details/anonpay_details_page.dart'; +import 'package:cake_wallet/src/screens/auth/auth_page.dart'; +import 'package:cake_wallet/src/screens/backup/backup_page.dart'; +import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart'; import 'package:cake_wallet/src/screens/buy/buy_options_page.dart'; +import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart'; import 'package:cake_wallet/src/screens/buy/webview_page.dart'; +import 'package:cake_wallet/src/screens/contact/contact_list_page.dart'; +import 'package:cake_wallet/src/screens/contact/contact_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/dashboard_page.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_dashboard_page.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart'; import 'package:cake_wallet/src/screens/dashboard/edit_token_page.dart'; import 'package:cake_wallet/src/screens/dashboard/home_settings_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/address_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/balance_page.dart'; import 'package:cake_wallet/src/screens/dashboard/pages/transactions_page.dart'; +import 'package:cake_wallet/src/screens/exchange/exchange_page.dart'; +import 'package:cake_wallet/src/screens/exchange/exchange_template_page.dart'; +import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dart'; +import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_page.dart'; +import 'package:cake_wallet/src/screens/faq/faq_page.dart'; +import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_cards_page.dart'; +import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_page.dart'; +import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dart'; +import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_tip_page.dart'; +import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart'; +import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart'; +import 'package:cake_wallet/src/screens/ionia/cards/ionia_payment_status_page.dart'; +import 'package:cake_wallet/src/screens/ionia/ionia.dart'; +import 'package:cake_wallet/src/screens/monero_accounts/monero_account_edit_or_create_page.dart'; +import 'package:cake_wallet/src/screens/monero_accounts/monero_account_list_page.dart'; import 'package:cake_wallet/src/screens/nano/nano_change_rep_page.dart'; import 'package:cake_wallet/src/screens/nano_accounts/nano_account_edit_or_create_page.dart'; import 'package:cake_wallet/src/screens/nano_accounts/nano_account_list_page.dart'; +import 'package:cake_wallet/src/screens/new_wallet/new_wallet_type_page.dart'; +import 'package:cake_wallet/src/screens/nodes/node_create_or_edit_page.dart'; import 'package:cake_wallet/src/screens/nodes/pow_node_create_or_edit_page.dart'; +import 'package:cake_wallet/src/screens/order_details/order_details_page.dart'; +import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/screens/receive/anonpay_invoice_page.dart'; import 'package:cake_wallet/src/screens/receive/anonpay_receive_page.dart'; +import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart'; +import 'package:cake_wallet/src/screens/receive/receive_page.dart'; +import 'package:cake_wallet/src/screens/rescan/rescan_page.dart'; +import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart'; +import 'package:cake_wallet/src/screens/restore/restore_options_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/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/settings/connection_sync_page.dart'; import 'package:cake_wallet/src/screens/settings/display_settings_page.dart'; import 'package:cake_wallet/src/screens/settings/domain_lookups_page.dart'; import 'package:cake_wallet/src/screens/settings/manage_nodes_page.dart'; import 'package:cake_wallet/src/screens/settings/other_settings_page.dart'; import 'package:cake_wallet/src/screens/settings/privacy_page.dart'; import 'package:cake_wallet/src/screens/settings/security_backup_page.dart'; -import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dart'; -import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart'; -import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart'; -import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; -import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart'; import 'package:cake_wallet/src/screens/settings/tor_page.dart'; +import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart'; -import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_info_page.dart'; -import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart'; +import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_info_page.dart'; +import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; +import 'package:cake_wallet/src/screens/setup_pin_code/setup_pin_code.dart'; +import 'package:cake_wallet/src/screens/subaddress/address_edit_or_create_page.dart'; +import 'package:cake_wallet/src/screens/support/support_page.dart'; import 'package:cake_wallet/src/screens/support_chat/support_chat_page.dart'; import 'package:cake_wallet/src/screens/support_other_links/support_other_links_page.dart'; -import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart'; -import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart'; -import 'package:cake_wallet/themes/theme_list.dart'; -import 'package:cake_wallet/utils/device_info.dart'; -import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart'; -import 'package:cake_wallet/utils/payment_request.dart'; -import 'package:cake_wallet/utils/responsive_layout_util.dart'; -import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart'; -import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart'; -import 'package:cake_wallet/view_model/anonpay_details_view_model.dart'; -import 'package:cake_wallet/view_model/dashboard/home_settings_view_model.dart'; -import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart'; -import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart'; -import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart'; -import 'package:cake_wallet/view_model/ionia/ionia_auth_view_model.dart'; -import 'package:cake_wallet/view_model/ionia/ionia_buy_card_view_model.dart'; -import 'package:cake_wallet/view_model/ionia/ionia_custom_tip_view_model.dart'; -import 'package:cake_wallet/view_model/ionia/ionia_custom_redeem_view_model.dart'; -import 'package:cake_wallet/ionia/ionia_service.dart'; -import 'package:cake_wallet/ionia/ionia_api.dart'; -import 'package:cake_wallet/ionia/ionia_merchant.dart'; -import 'package:cake_wallet/monero/monero.dart'; -import 'package:cake_wallet/haven/haven.dart'; -import 'package:cake_wallet/bitcoin/bitcoin.dart'; -import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_cards_page.dart'; -import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_page.dart'; -import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_tip_page.dart'; -import 'package:cake_wallet/src/screens/ionia/ionia.dart'; -import 'package:cake_wallet/src/screens/dashboard/pages/balance_page.dart'; -import 'package:cake_wallet/view_model/ionia/ionia_account_view_model.dart'; -import 'package:cake_wallet/view_model/ionia/ionia_gift_cards_list_view_model.dart'; -import 'package:cake_wallet/view_model/ionia/ionia_purchase_merch_view_model.dart'; -import 'package:cake_wallet/view_model/nano_account_list/nano_account_edit_or_create_view_model.dart'; -import 'package:cake_wallet/view_model/nano_account_list/nano_account_list_view_model.dart'; -import 'package:cake_wallet/view_model/node_list/pow_node_list_view_model.dart'; -import 'package:cake_wallet/view_model/seed_type_view_model.dart'; -import 'package:cake_wallet/view_model/set_up_2fa_viewmodel.dart'; -import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart'; -import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart'; -import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart'; -import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart'; -import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart'; -import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; -import 'package:cake_wallet/view_model/settings/trocador_providers_view_model.dart'; -import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart'; -import 'package:cake_wallet/view_model/wallet_list/wallet_edit_view_model.dart'; -import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart'; -import 'package:cake_wallet/view_model/wallet_restore_choose_derivation_view_model.dart'; -import 'package:cw_core/erc20_token.dart'; -import 'package:cw_core/nano_account.dart'; -import 'package:cw_core/unspent_coins_info.dart'; -import 'package:cake_wallet/core/backup_service.dart'; -import 'package:cw_core/wallet_service.dart'; -import 'package:cake_wallet/entities/biometric_auth.dart'; -import 'package:cake_wallet/entities/contact_record.dart'; -import 'package:cake_wallet/buy/order.dart'; -import 'package:cake_wallet/entities/transaction_description.dart'; -import 'package:cw_core/transaction_info.dart'; -import 'package:cake_wallet/entities/contact.dart'; -import 'package:cw_core/node.dart'; -import 'package:cake_wallet/exchange/trade.dart'; -import 'package:cake_wallet/reactions/on_authentication_state_change.dart'; -import 'package:cake_wallet/src/screens/backup/backup_page.dart'; -import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart'; -import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart'; -import 'package:cake_wallet/src/screens/contact/contact_list_page.dart'; -import 'package:cake_wallet/src/screens/contact/contact_page.dart'; -import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dart'; -import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_page.dart'; -import 'package:cake_wallet/src/screens/faq/faq_page.dart'; -import 'package:cake_wallet/src/screens/new_wallet/new_wallet_type_page.dart'; -import 'package:cake_wallet/src/screens/nodes/node_create_or_edit_page.dart'; -import 'package:cake_wallet/src/screens/order_details/order_details_page.dart'; -import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; -import 'package:cake_wallet/src/screens/rescan/rescan_page.dart'; -import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart'; -import 'package:cake_wallet/src/screens/restore/restore_options_page.dart'; -import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; -import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart'; -import 'package:cake_wallet/src/screens/seed/wallet_seed_page.dart'; -import 'package:cake_wallet/src/screens/send/send_template_page.dart'; -import 'package:cake_wallet/src/screens/setup_pin_code/setup_pin_code.dart'; -import 'package:cake_wallet/src/screens/support/support_page.dart'; import 'package:cake_wallet/src/screens/trade_details/trade_details_page.dart'; +import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart'; import 'package:cake_wallet/src/screens/transaction_details/transaction_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart'; +import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart'; +import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart'; import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart'; -import 'package:cake_wallet/src/screens/exchange/exchange_page.dart'; -import 'package:cake_wallet/src/screens/exchange/exchange_template_page.dart'; +import 'package:cake_wallet/src/screens/wallet_list/wallet_list_page.dart'; +import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart'; +import 'package:cake_wallet/store/app_store.dart'; +import 'package:cake_wallet/store/authentication_store.dart'; +import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; import 'package:cake_wallet/store/dashboard/orders_store.dart'; +import 'package:cake_wallet/store/dashboard/trade_filter_store.dart'; +import 'package:cake_wallet/store/dashboard/trades_store.dart'; +import 'package:cake_wallet/store/dashboard/transaction_filter_store.dart'; import 'package:cake_wallet/store/node_list_store.dart'; import 'package:cake_wallet/store/secret_store.dart'; import 'package:cake_wallet/store/settings_store.dart'; -import 'package:cake_wallet/core/auth_service.dart'; -import 'package:cake_wallet/core/key_service.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cake_wallet/src/screens/monero_accounts/monero_account_list_page.dart'; -import 'package:cake_wallet/src/screens/monero_accounts/monero_account_edit_or_create_page.dart'; -import 'package:cake_wallet/src/screens/auth/auth_page.dart'; -import 'package:cake_wallet/src/screens/dashboard/dashboard_page.dart'; -import 'package:cake_wallet/src/screens/receive/receive_page.dart'; -import 'package:cake_wallet/src/screens/send/send_page.dart'; -import 'package:cake_wallet/src/screens/subaddress/address_edit_or_create_page.dart'; -import 'package:cake_wallet/src/screens/wallet_list/wallet_list_page.dart'; +import 'package:cake_wallet/store/templates/exchange_template_store.dart'; +import 'package:cake_wallet/store/templates/send_template_store.dart'; import 'package:cake_wallet/store/wallet_list_store.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; +import 'package:cake_wallet/themes/theme_list.dart'; +import 'package:cake_wallet/utils/device_info.dart'; +import 'package:cake_wallet/utils/payment_request.dart'; +import 'package:cake_wallet/utils/responsive_layout_util.dart'; +import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; +import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart'; +import 'package:cake_wallet/view_model/anonpay_details_view_model.dart'; +import 'package:cake_wallet/view_model/auth_view_model.dart'; import 'package:cake_wallet/view_model/backup_view_model.dart'; import 'package:cake_wallet/view_model/buy/buy_amount_view_model.dart'; import 'package:cake_wallet/view_model/buy/buy_view_model.dart'; import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart'; import 'package:cake_wallet/view_model/contact_list/contact_view_model.dart'; +import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; +import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart'; +import 'package:cake_wallet/view_model/dashboard/home_settings_view_model.dart'; +import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart'; +import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart'; +import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart'; import 'package:cake_wallet/view_model/edit_backup_password_view_model.dart'; import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart'; +import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart'; +import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart'; +import 'package:cake_wallet/view_model/ionia/ionia_account_view_model.dart'; +import 'package:cake_wallet/view_model/ionia/ionia_auth_view_model.dart'; +import 'package:cake_wallet/view_model/ionia/ionia_buy_card_view_model.dart'; +import 'package:cake_wallet/view_model/ionia/ionia_custom_redeem_view_model.dart'; +import 'package:cake_wallet/view_model/ionia/ionia_custom_tip_view_model.dart'; +import 'package:cake_wallet/view_model/ionia/ionia_gift_card_details_view_model.dart'; +import 'package:cake_wallet/view_model/ionia/ionia_gift_cards_list_view_model.dart'; +import 'package:cake_wallet/view_model/ionia/ionia_payment_status_view_model.dart'; +import 'package:cake_wallet/view_model/ionia/ionia_purchase_merch_view_model.dart'; import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; -import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart'; +import 'package:cake_wallet/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart'; +import 'package:cake_wallet/view_model/monero_account_list/monero_account_list_view_model.dart'; +import 'package:cake_wallet/view_model/nano_account_list/nano_account_edit_or_create_view_model.dart'; +import 'package:cake_wallet/view_model/nano_account_list/nano_account_list_view_model.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; +import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart'; +import 'package:cake_wallet/view_model/node_list/pow_node_list_view_model.dart'; import 'package:cake_wallet/view_model/order_details_view_model.dart'; import 'package:cake_wallet/view_model/rescan_view_model.dart'; +import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart'; import 'package:cake_wallet/view_model/restore_from_backup_view_model.dart'; +import 'package:cake_wallet/view_model/seed_type_view_model.dart'; import 'package:cake_wallet/view_model/send/send_template_view_model.dart'; +import 'package:cake_wallet/view_model/send/send_view_model.dart'; +import 'package:cake_wallet/view_model/set_up_2fa_viewmodel.dart'; +import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart'; +import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart'; +import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart'; +import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart'; +import 'package:cake_wallet/view_model/settings/trocador_providers_view_model.dart'; import 'package:cake_wallet/view_model/setup_pin_code_view_model.dart'; import 'package:cake_wallet/view_model/support_view_model.dart'; -import 'package:cake_wallet/view_model/transaction_details_view_model.dart'; import 'package:cake_wallet/view_model/trade_details_view_model.dart'; +import 'package:cake_wallet/view_model/transaction_details_view_model.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_details_view_model.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_item.dart'; import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_list_view_model.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart'; -import 'package:cake_wallet/view_model/auth_view_model.dart'; -import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; -import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; +import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart'; -import 'package:cake_wallet/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart'; -import 'package:cake_wallet/view_model/monero_account_list/monero_account_list_view_model.dart'; -import 'package:cake_wallet/view_model/send/send_view_model.dart'; +import 'package:cake_wallet/view_model/wallet_hardware_restore_view_model.dart'; import 'package:cake_wallet/view_model/wallet_keys_view_model.dart'; +import 'package:cake_wallet/view_model/wallet_list/wallet_edit_view_model.dart'; +import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart'; import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart'; +import 'package:cake_wallet/view_model/wallet_new_vm.dart'; +import 'package:cake_wallet/view_model/wallet_restore_choose_derivation_view_model.dart'; import 'package:cake_wallet/view_model/wallet_restore_view_model.dart'; import 'package:cake_wallet/view_model/wallet_seed_view_model.dart'; -import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/nano_account.dart'; +import 'package:cw_core/node.dart'; +import 'package:cw_core/receive_page_option.dart'; +import 'package:cw_core/transaction_info.dart'; +import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_service.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:get_it/get_it.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:cake_wallet/core/wallet_creation_service.dart'; -import 'package:cake_wallet/store/app_store.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:cake_wallet/view_model/wallet_new_vm.dart'; -import 'package:cake_wallet/store/authentication_store.dart'; -import 'package:cake_wallet/store/dashboard/trades_store.dart'; -import 'package:cake_wallet/store/dashboard/trade_filter_store.dart'; -import 'package:cake_wallet/store/dashboard/transaction_filter_store.dart'; -import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; -import 'package:cake_wallet/store/templates/send_template_store.dart'; -import 'package:cake_wallet/store/templates/exchange_template_store.dart'; -import 'package:cake_wallet/entities/template.dart'; -import 'package:cake_wallet/exchange/exchange_template.dart'; -import 'package:cake_wallet/.secrets.g.dart' as secrets; -import 'package:cake_wallet/src/screens/dashboard/pages/address_page.dart'; -import 'package:cake_wallet/anypay/anypay_api.dart'; -import 'package:cake_wallet/view_model/ionia/ionia_gift_card_details_view_model.dart'; -import 'package:cake_wallet/src/screens/ionia/cards/ionia_payment_status_page.dart'; -import 'package:cake_wallet/view_model/ionia/ionia_payment_status_view_model.dart'; -import 'package:cake_wallet/anypay/any_pay_payment_committed_info.dart'; -import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart'; -import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart'; -import 'package:cake_wallet/core/wallet_loading_service.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cake_wallet/entities/qr_view_data.dart'; import 'buy/dfx/dfx_buy_provider.dart'; import 'core/totp_request_details.dart'; @@ -308,6 +311,7 @@ Future setup({ getIt.registerFactory>(() => _powNodeSource, instanceName: Node.boxName + "pow"); getIt.registerSingleton(AuthenticationStore()); + getIt.registerSingleton(LedgerViewModel()); getIt.registerSingleton(WalletListStore()); getIt.registerSingleton(NodeListStoreBase.instance); getIt.registerSingleton(settingsStore); @@ -367,6 +371,11 @@ Future setup({ getIt.get(param1: type), _walletInfoSource, type); }); + getIt.registerFactoryParam((type, _) => + WalletHardwareRestoreViewModel(getIt.get(), getIt.get(), + getIt.get(param1: type), _walletInfoSource, + type: type)); + getIt.registerFactory(() => WalletAddressListViewModel( appStore: getIt.get(), yatStore: getIt.get(), @@ -490,12 +499,8 @@ Future setup({ getIt.registerLazySingleton(() => KeyServiceImpl()); getIt.registerLazySingleton(() { - final Web3WalletService web3WalletService = Web3WalletService( - getIt.get(), - getIt.get(), - appStore, - getIt.get() - ); + final Web3WalletService web3WalletService = Web3WalletService(getIt.get(), + getIt.get(), appStore, getIt.get()); web3WalletService.create(); return web3WalletService; }); @@ -599,6 +604,7 @@ Future setup({ getIt.get(), getIt.get(), _transactionDescriptionBox, + getIt.get(), ), ); @@ -804,11 +810,11 @@ Future setup({ editingNode: editingNode, isSelected: isSelected)); - getIt.registerFactory( - () => RobinhoodBuyProvider(wallet: getIt.get().wallet!)); + getIt.registerFactory(() => RobinhoodBuyProvider( + wallet: getIt.get().wallet!, ledgerVM: getIt.get())); - getIt - .registerFactory(() => DFXBuyProvider(wallet: getIt.get().wallet!)); + getIt.registerFactory(() => DFXBuyProvider( + wallet: getIt.get().wallet!, ledgerVM: getIt.get())); getIt.registerFactory(() => MoonPayProvider( settingsStore: getIt.get().settingsStore, @@ -928,8 +934,17 @@ Future setup({ transactionDetailsViewModel: getIt.get(param1: transactionInfo))); - getIt.registerFactoryParam( - (param1, isCreate) => NewWalletTypePage(onTypeSelected: param1, isCreate: isCreate ?? true)); + getIt.registerFactoryParam?>((param1, additionalParams) { + final isCreate = additionalParams?[0] ?? true; + final isHardwareWallet = additionalParams?[1] ?? false; + + return NewWalletTypePage( + onTypeSelected: param1, + isCreate: isCreate, + isHardwareWallet: isHardwareWallet, + ); + }); getIt.registerFactoryParam( (seedPhraseLength, _) => PreSeedPage(seedPhraseLength)); @@ -1144,9 +1159,9 @@ Future setup({ getIt.registerFactory(() => IoniaAccountCardsPage(getIt.get())); getIt.registerFactoryParam( - (TransactionInfo transactionInfo, _) => RBFDetailsPage( + (TransactionInfo transactionInfo, _) => RBFDetailsPage( transactionDetailsViewModel: - getIt.get(param1: transactionInfo))); + getIt.get(param1: transactionInfo))); getIt.registerFactory(() => AnonPayApi( useTorOnly: getIt.get().exchangeStatus == ExchangeApiMode.torOnly, diff --git a/lib/ethereum/cw_ethereum.dart b/lib/ethereum/cw_ethereum.dart index 61d5b6ae3..e72108e79 100644 --- a/lib/ethereum/cw_ethereum.dart +++ b/lib/ethereum/cw_ethereum.dart @@ -30,14 +30,23 @@ class CWEthereum extends Ethereum { }) => EVMChainRestoreWalletFromPrivateKey(name: name, password: password, privateKey: privateKey); + @override + WalletCredentials createEthereumHardwareWalletCredentials({ + required String name, + required HardwareAccountData hwAccountData, + WalletInfo? walletInfo, + }) => + EVMChainRestoreWalletFromHardware( + name: name, hwAccountData: hwAccountData, walletInfo: walletInfo); + @override String getAddress(WalletBase wallet) => (wallet as EthereumWallet).walletAddresses.address; @override String getPrivateKey(WalletBase wallet) { final privateKeyHolder = (wallet as EthereumWallet).evmChainPrivateKey; - String stringKey = bytesToHex(privateKeyHolder.privateKey); - return stringKey; + if (privateKeyHolder is EthPrivateKey) return bytesToHex(privateKeyHolder.privateKey); + return ""; } @override @@ -159,4 +168,24 @@ class CWEthereum extends Ethereum { } String getTokenAddress(CryptoCurrency asset) => (asset as Erc20Token).contractAddress; + + @override + void setLedger(WalletBase wallet, Ledger ledger, LedgerDevice device) { + ((wallet as EVMChainWallet).evmChainPrivateKey as EvmLedgerCredentials).setLedger( + ledger, + device.connectionType == ConnectionType.usb ? device : null, + wallet.walletInfo.derivationInfo?.derivationPath); + } + + @override + Future> getHardwareWalletAccounts(LedgerViewModel ledgerVM, + {int index = 0, int limit = 5}) async { + final hardwareWalletService = EVMChainHardwareWalletService(ledgerVM.ledger, ledgerVM.device); + try { + return await hardwareWalletService.getAvailableAccounts(index: index, limit: limit); + } on LedgerException catch (err) { + print(err.message); + throw err; + } + } } diff --git a/lib/main.dart b/lib/main.dart index eef8cef62..b274c7a84 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -105,7 +105,11 @@ Future initializeAppConfigs() async { if (!CakeHive.isAdapterRegistered(DERIVATION_INFO_TYPE_ID)) { CakeHive.registerAdapter(DerivationInfoAdapter()); } - + + if (!CakeHive.isAdapterRegistered(HARDWARE_WALLET_TYPE_TYPE_ID)) { + CakeHive.registerAdapter(HardwareWalletTypeAdapter()); + } + if (!CakeHive.isAdapterRegistered(WALLET_TYPE_TYPE_ID)) { CakeHive.registerAdapter(WalletTypeAdapter()); } diff --git a/lib/polygon/cw_polygon.dart b/lib/polygon/cw_polygon.dart index 5baf4fbbc..16aba284d 100644 --- a/lib/polygon/cw_polygon.dart +++ b/lib/polygon/cw_polygon.dart @@ -30,14 +30,23 @@ class CWPolygon extends Polygon { }) => EVMChainRestoreWalletFromPrivateKey(name: name, password: password, privateKey: privateKey); + @override + WalletCredentials createPolygonHardwareWalletCredentials({ + required String name, + required HardwareAccountData hwAccountData, + WalletInfo? walletInfo, + }) => + EVMChainRestoreWalletFromHardware( + name: name, hwAccountData: hwAccountData, walletInfo: walletInfo); + @override String getAddress(WalletBase wallet) => (wallet as PolygonWallet).walletAddresses.address; @override String getPrivateKey(WalletBase wallet) { final privateKeyHolder = (wallet as PolygonWallet).evmChainPrivateKey; - String stringKey = bytesToHex(privateKeyHolder.privateKey); - return stringKey; + if (privateKeyHolder is EthPrivateKey) return bytesToHex(privateKeyHolder.privateKey); + return ""; } @override @@ -67,21 +76,21 @@ class CWPolygon extends Polygon { int? feeRate, }) => EVMChainTransactionCredentials( - outputs - .map((out) => OutputInfo( - fiatAmount: out.fiatAmount, - cryptoAmount: out.cryptoAmount, - address: out.address, - note: out.note, - sendAll: out.sendAll, - extractedAddress: out.extractedAddress, - isParsedAddress: out.isParsedAddress, - formattedCryptoAmount: out.formattedCryptoAmount)) - .toList(), - priority: priority as EVMChainTransactionPriority, - currency: currency, - feeRate: feeRate, - ); + outputs + .map((out) => OutputInfo( + fiatAmount: out.fiatAmount, + cryptoAmount: out.cryptoAmount, + address: out.address, + note: out.note, + sendAll: out.sendAll, + extractedAddress: out.extractedAddress, + isParsedAddress: out.isParsedAddress, + formattedCryptoAmount: out.formattedCryptoAmount)) + .toList(), + priority: priority as EVMChainTransactionPriority, + currency: currency, + feeRate: feeRate, + ); Object createPolygonTransactionCredentialsRaw( List outputs, { @@ -157,4 +166,23 @@ class CWPolygon extends Polygon { } String getTokenAddress(CryptoCurrency asset) => (asset as Erc20Token).contractAddress; + + @override + void setLedger(WalletBase wallet, Ledger ledger, LedgerDevice device) { + ((wallet as EVMChainWallet).evmChainPrivateKey as EvmLedgerCredentials).setLedger( + ledger, + device.connectionType == ConnectionType.usb ? device : null, + wallet.walletInfo.derivationInfo?.derivationPath); + } + + @override + Future> getHardwareWalletAccounts(LedgerViewModel ledgerVM, + {int index = 0, int limit = 5}) async { + final hardwareWalletService = EVMChainHardwareWalletService(ledgerVM.ledger, ledgerVM.device); + try { + return await hardwareWalletService.getAvailableAccounts(index: index, limit: limit); + } on LedgerException catch (err) { + throw err; + } + } } diff --git a/lib/router.dart b/lib/router.dart index 9f5dfb838..3032ceb6a 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -1,29 +1,74 @@ import 'package:cake_wallet/anonpay/anonpay_info_base.dart'; import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart'; +import 'package:cake_wallet/anypay/any_pay_payment_committed_info.dart'; +import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/core/totp_request_details.dart'; import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart'; +import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/contact_record.dart'; -import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/entities/qr_view_data.dart'; import 'package:cake_wallet/entities/wallet_nft_response.dart'; +import 'package:cake_wallet/exchange/trade.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart'; +import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/anonpay_details/anonpay_details_page.dart'; +import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:cake_wallet/src/screens/backup/backup_page.dart'; import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart'; import 'package:cake_wallet/src/screens/buy/buy_options_page.dart'; import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart'; import 'package:cake_wallet/src/screens/buy/webview_page.dart'; +import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart'; +import 'package:cake_wallet/src/screens/connect_device/select_hardware_wallet_account_page.dart'; +import 'package:cake_wallet/src/screens/contact/contact_list_page.dart'; +import 'package:cake_wallet/src/screens/contact/contact_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/dashboard_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart'; import 'package:cake_wallet/src/screens/dashboard/edit_token_page.dart'; import 'package:cake_wallet/src/screens/dashboard/home_settings_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/address_page.dart'; import 'package:cake_wallet/src/screens/dashboard/pages/nft_details_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/transactions_page.dart'; +import 'package:cake_wallet/src/screens/disclaimer/disclaimer_page.dart'; +import 'package:cake_wallet/src/screens/exchange/exchange_page.dart'; +import 'package:cake_wallet/src/screens/exchange/exchange_template_page.dart'; +import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dart'; +import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_page.dart'; +import 'package:cake_wallet/src/screens/faq/faq_page.dart'; +import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_cards_page.dart'; +import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_page.dart'; +import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dart'; +import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_tip_page.dart'; +import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart'; +import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart'; +import 'package:cake_wallet/src/screens/ionia/cards/ionia_payment_status_page.dart'; +import 'package:cake_wallet/src/screens/ionia/ionia.dart'; +import 'package:cake_wallet/src/screens/monero_accounts/monero_account_edit_or_create_page.dart'; import 'package:cake_wallet/src/screens/nano/nano_change_rep_page.dart'; import 'package:cake_wallet/src/screens/nano_accounts/nano_account_edit_or_create_page.dart'; +import 'package:cake_wallet/src/screens/new_wallet/advanced_privacy_settings_page.dart'; +import 'package:cake_wallet/src/screens/new_wallet/new_wallet_page.dart'; +import 'package:cake_wallet/src/screens/new_wallet/new_wallet_type_page.dart'; +import 'package:cake_wallet/src/screens/nodes/node_create_or_edit_page.dart'; import 'package:cake_wallet/src/screens/nodes/pow_node_create_or_edit_page.dart'; -import 'package:cake_wallet/src/screens/restore/sweeping_wallet_page.dart'; +import 'package:cake_wallet/src/screens/order_details/order_details_page.dart'; +import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/screens/receive/anonpay_invoice_page.dart'; import 'package:cake_wallet/src/screens/receive/anonpay_receive_page.dart'; -import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart'; -import 'package:cake_wallet/src/screens/dashboard/pages/transactions_page.dart'; +import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart'; +import 'package:cake_wallet/src/screens/receive/receive_page.dart'; +import 'package:cake_wallet/src/screens/rescan/rescan_page.dart'; +import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart'; +import 'package:cake_wallet/src/screens/restore/restore_options_page.dart'; +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/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/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'; import 'package:cake_wallet/src/screens/settings/domain_lookups_page.dart'; @@ -31,90 +76,49 @@ import 'package:cake_wallet/src/screens/settings/manage_nodes_page.dart'; import 'package:cake_wallet/src/screens/settings/other_settings_page.dart'; import 'package:cake_wallet/src/screens/settings/privacy_page.dart'; import 'package:cake_wallet/src/screens/settings/security_backup_page.dart'; -import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_cards_page.dart'; -import 'package:cake_wallet/src/screens/ionia/cards/ionia_account_page.dart'; -import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_redeem_page.dart'; -import 'package:cake_wallet/src/screens/ionia/cards/ionia_custom_tip_page.dart'; -import 'package:cake_wallet/src/screens/ionia/cards/ionia_gift_card_detail_page.dart'; -import 'package:cake_wallet/src/screens/ionia/cards/ionia_more_options_page.dart'; -import 'package:cake_wallet/src/screens/new_wallet/advanced_privacy_settings_page.dart'; -import 'package:cake_wallet/src/screens/order_details/order_details_page.dart'; -import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; -import 'package:cake_wallet/src/screens/restore/restore_from_backup_page.dart'; -import 'package:cake_wallet/src/screens/restore/wallet_restore_page.dart'; -import 'package:cake_wallet/src/screens/seed/pre_seed_page.dart'; -import 'package:cake_wallet/src/screens/settings/connection_sync_page.dart'; -import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart'; import 'package:cake_wallet/src/screens/settings/tor_page.dart'; +import 'package:cake_wallet/src/screens/settings/trocador_providers_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart'; -import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_info_page.dart'; -import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart'; import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart'; +import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_info_page.dart'; +import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart'; +import 'package:cake_wallet/src/screens/setup_pin_code/setup_pin_code.dart'; +import 'package:cake_wallet/src/screens/subaddress/address_edit_or_create_page.dart'; import 'package:cake_wallet/src/screens/support/support_page.dart'; import 'package:cake_wallet/src/screens/support_chat/support_chat_page.dart'; import 'package:cake_wallet/src/screens/support_other_links/support_other_links_page.dart'; +import 'package:cake_wallet/src/screens/trade_details/trade_details_page.dart'; +import 'package:cake_wallet/src/screens/transaction_details/transaction_details_page.dart'; import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart'; import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart'; +import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart'; import 'package:cake_wallet/src/screens/wallet_connect/wc_connections_listing_view.dart'; +import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart'; +import 'package:cake_wallet/src/screens/wallet_list/wallet_list_page.dart'; +import 'package:cake_wallet/src/screens/welcome/create_welcome_page.dart'; import 'package:cake_wallet/utils/payment_request.dart'; +import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart'; +import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart'; import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; -import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart'; import 'package:cake_wallet/view_model/seed_type_view_model.dart'; +import 'package:cake_wallet/view_model/wallet_hardware_restore_view_model.dart'; +import 'package:cake_wallet/view_model/wallet_new_vm.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; +import 'package:cake_wallet/wallet_types.g.dart'; +import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/nano_account.dart'; +import 'package:cw_core/node.dart'; +import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_type.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/di.dart'; -import 'package:cake_wallet/view_model/wallet_new_vm.dart'; -import 'package:cake_wallet/exchange/trade.dart'; -import 'package:cw_core/transaction_info.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:cake_wallet/src/screens/dashboard/dashboard_page.dart'; -import 'package:cake_wallet/src/screens/seed/wallet_seed_page.dart'; -import 'package:cake_wallet/src/screens/auth/auth_page.dart'; -import 'package:cake_wallet/src/screens/nodes/node_create_or_edit_page.dart'; -import 'package:cake_wallet/src/screens/receive/receive_page.dart'; -import 'package:cake_wallet/src/screens/subaddress/address_edit_or_create_page.dart'; -import 'package:cake_wallet/src/screens/wallet_list/wallet_list_page.dart'; -import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart'; -import 'package:cake_wallet/src/screens/new_wallet/new_wallet_page.dart'; -import 'package:cake_wallet/src/screens/setup_pin_code/setup_pin_code.dart'; -import 'package:cake_wallet/src/screens/restore/restore_options_page.dart'; -import 'package:cake_wallet/src/screens/send/send_page.dart'; -import 'package:cake_wallet/src/screens/disclaimer/disclaimer_page.dart'; -import 'package:cake_wallet/src/screens/transaction_details/transaction_details_page.dart'; -import 'package:cake_wallet/src/screens/monero_accounts/monero_account_edit_or_create_page.dart'; -import 'package:cake_wallet/src/screens/contact/contact_list_page.dart'; -import 'package:cake_wallet/src/screens/contact/contact_page.dart'; -import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart'; -import 'package:cake_wallet/src/screens/exchange/exchange_page.dart'; -import 'package:cake_wallet/src/screens/rescan/rescan_page.dart'; -import 'package:cake_wallet/src/screens/faq/faq_page.dart'; -import 'package:cake_wallet/src/screens/trade_details/trade_details_page.dart'; -import 'package:cake_wallet/src/screens/welcome/create_welcome_page.dart'; -import 'package:cake_wallet/src/screens/new_wallet/new_wallet_type_page.dart'; -import 'package:cake_wallet/src/screens/send/send_template_page.dart'; -import 'package:cake_wallet/src/screens/exchange/exchange_template_page.dart'; -import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dart'; -import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_page.dart'; import 'package:flutter/services.dart'; -import 'package:cake_wallet/wallet_types.g.dart'; -import 'package:cake_wallet/src/screens/dashboard/pages/address_page.dart'; -import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart'; -import 'package:cake_wallet/src/screens/ionia/ionia.dart'; -import 'package:cake_wallet/src/screens/ionia/cards/ionia_payment_status_page.dart'; -import 'package:cake_wallet/anypay/any_pay_payment_committed_info.dart'; -import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/node.dart'; import 'src/screens/dashboard/pages/nft_import_page.dart'; @@ -151,7 +155,15 @@ Route createRoute(RouteSettings settings) { final walletNewVM = getIt.get(param1: type); final seedTypeViewModel = getIt.get(); - return CupertinoPageRoute(builder: (_) => NewWalletPage(walletNewVM, seedTypeViewModel)); + return CupertinoPageRoute( + builder: (_) => NewWalletPage(walletNewVM, seedTypeViewModel)); + + case Routes.chooseHardwareWalletAccount: + final arguments = settings.arguments as List; + final type = arguments[0] as WalletType; + final walletVM = getIt.get(param1: type); + + return CupertinoPageRoute(builder: (_) => SelectHardwareWalletAccountPage(walletVM)); case Routes.setupPin: Function(PinCodeState, String)? callback; @@ -168,7 +180,7 @@ Route createRoute(RouteSettings settings) { builder: (_) => getIt.get( param1: (BuildContext context, WalletType type) => Navigator.of(context).pushNamed(Routes.restoreWallet, arguments: type), - param2: false)); + param2: [false, false])); case Routes.restoreOptions: final isNewInstall = settings.arguments as bool; @@ -199,7 +211,46 @@ Route createRoute(RouteSettings settings) { builder: (_) => getIt.get( param1: (BuildContext context, WalletType type) => Navigator.of(context).pushNamed(Routes.restoreWallet, arguments: type), - param2: false)); + param2: [false, false])); + } + + case Routes.restoreWalletFromHardwareWallet: + final isNewInstall = settings.arguments as bool; + + if (isNewInstall) { + return CupertinoPageRoute( + builder: (_) => getIt.get( + param1: (PinCodeState context, dynamic _) => + Navigator.of(context.context).pushNamed(Routes.restoreWalletFromHardwareWallet, arguments: false), + ), + fullscreenDialog: true, + ); + } + if (isSingleCoin) { + return MaterialPageRoute( + builder: (_) => ConnectDevicePage( + ConnectDevicePageParams( + walletType: availableWalletTypes.first, + onConnectDevice: (BuildContext context, _) => + Navigator.of(context).pushNamed(Routes.chooseHardwareWalletAccount, + arguments: [availableWalletTypes.first]), + ), + getIt.get(), + )); + } else { + return CupertinoPageRoute( + builder: (_) => getIt.get( + param1: (BuildContext context, WalletType type) { + final arguments = ConnectDevicePageParams( + walletType: type, + onConnectDevice: (BuildContext context, _) => + Navigator.of(context).pushNamed(Routes.chooseHardwareWalletAccount, + arguments: [type]), + ); + + Navigator.of(context).pushNamed(Routes.connectDevices, arguments: arguments); + }, + param2: [false, true])); } case Routes.restoreWalletTypeFromQR: @@ -400,8 +451,7 @@ Route createRoute(RouteSettings settings) { case Routes.buySellPage: final args = settings.arguments as bool; - return MaterialPageRoute( - builder: (_) => getIt.get(param1: args)); + return MaterialPageRoute(builder: (_) => getIt.get(param1: args)); case Routes.buyWebView: final args = settings.arguments as List; @@ -424,8 +474,7 @@ Route createRoute(RouteSettings settings) { case Routes.preSeedPage: return MaterialPageRoute( - builder: (_) => getIt.get( - param1: settings.arguments as int)); + builder: (_) => getIt.get(param1: settings.arguments as int)); case Routes.backup: return CupertinoPageRoute( @@ -647,6 +696,11 @@ Route createRoute(RouteSettings settings) { case Routes.torPage: return MaterialPageRoute(builder: (_) => getIt.get()); + case Routes.connectDevices: + final params = settings.arguments as ConnectDevicePageParams; + return MaterialPageRoute( + builder: (_) => ConnectDevicePage(params, getIt.get())); + default: return MaterialPageRoute( builder: (_) => Scaffold( diff --git a/lib/routes.dart b/lib/routes.dart index 9c4e21651..1b518d328 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -6,9 +6,11 @@ class Routes { static const seed = '/seed'; static const restoreOptions = '/restore_options'; static const restoreWalletFromSeedKeys = '/restore_wallet_from_seeds_keys'; + static const restoreWalletFromHardwareWallet = '/restore/hardware_wallet'; static const restoreWalletTypeFromQR = '/restore_wallet_from_qr_code'; static const restoreWalletChooseDerivation = '/restore_wallet_choose_derivation'; + static const chooseHardwareWalletAccount = '/restore/hardware_wallet/accounts'; static const dashboard = '/dashboard'; static const send = '/send'; static const transactionDetails = '/transaction_info'; @@ -107,4 +109,5 @@ class Routes { static const nftDetailsPage = '/nft_details_page'; static const importNFTPage = '/import_nft_page'; static const torPage = '/tor_page'; + static const connectDevices = '/device/connect'; } diff --git a/lib/src/screens/connect_device/connect_device_page.dart b/lib/src/screens/connect_device/connect_device_page.dart new file mode 100644 index 000000000..dfb32beba --- /dev/null +++ b/lib/src/screens/connect_device/connect_device_page.dart @@ -0,0 +1,221 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/connect_device/widgets/device_tile.dart'; +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/utils/responsive_layout_util.dart'; +import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:flutter/material.dart'; +import 'package:ledger_flutter/ledger_flutter.dart'; +import 'package:permission_handler/permission_handler.dart'; + +typedef OnConnectDevice = void Function(BuildContext, LedgerViewModel); + +class ConnectDevicePageParams { + final WalletType walletType; + final OnConnectDevice onConnectDevice; + + ConnectDevicePageParams({required this.walletType, required this.onConnectDevice}); +} + +class ConnectDevicePage extends BasePage { + final WalletType walletType; + final OnConnectDevice onConnectDevice; + final LedgerViewModel ledgerVM; + + ConnectDevicePage(ConnectDevicePageParams params, this.ledgerVM) + : walletType = params.walletType, + onConnectDevice = params.onConnectDevice; + + @override + String get title => S.current.restore_title_from_hardware_wallet; + + @override + Widget body(BuildContext context) => ConnectDevicePageBody(walletType, onConnectDevice, ledgerVM); +} + +class ConnectDevicePageBody extends StatefulWidget { + final WalletType walletType; + final OnConnectDevice onConnectDevice; + final LedgerViewModel ledgerVM; + + const ConnectDevicePageBody(this.walletType, this.onConnectDevice, this.ledgerVM); + + @override + ConnectDevicePageBodyState createState() => ConnectDevicePageBodyState(); +} + +class ConnectDevicePageBodyState extends State { + final imageLedger = 'assets/images/ledger_nano.png'; + + final ledger = Ledger( + options: LedgerOptions( + scanMode: ScanMode.balanced, + maxScanDuration: const Duration(minutes: 5), + ), + onPermissionRequest: (_) async { + Map statuses = await [ + Permission.bluetoothScan, + Permission.bluetoothConnect, + Permission.bluetoothAdvertise, + ].request(); + + return statuses.values.where((status) => status.isDenied).isEmpty; + }, + ); + + var bleIsEnabled = true; + var bleDevices = []; + var usbDevices = []; + + late Timer? _usbRefreshTimer = null; + late Timer? _bleRefreshTimer = null; + late StreamSubscription? _bleRefresh = null; + + @override + void initState() { + super.initState(); + Future.delayed( + Duration(seconds: 1), + () => _bleRefresh = ledger.scan().listen((device) => setState(() => bleDevices.add(device))), + ); + // _bleRefreshTimer = Timer.periodic(Duration(seconds: 1), (_) => _refreshBleDevices()); + + if (Platform.isAndroid) { + _usbRefreshTimer = Timer.periodic(Duration(seconds: 1), (_) => _refreshUsbDevices()); + } + } + + @override + void dispose() { + _bleRefreshTimer?.cancel(); + _usbRefreshTimer?.cancel(); + _bleRefresh?.cancel(); + super.dispose(); + } + + Future _refreshUsbDevices() async { + final dev = await ledger.listUsbDevices(); + if (usbDevices.length != dev.length) setState(() => usbDevices = dev); + } + + Future _refreshBleDevices() async { + final isBleEnabled = await Permission.bluetooth.serviceStatus.isEnabled; + + setState(() => bleIsEnabled = isBleEnabled); + + if (isBleEnabled) { + _bleRefresh = ledger.scan().listen((device) => setState(() => bleDevices.add(device))); + _bleRefreshTimer?.cancel(); + _bleRefreshTimer = null; + } + } + + Future _connectToDevice(LedgerDevice device) async { + await widget.ledgerVM.connectLedger(device); + widget.onConnectDevice(context, widget.ledgerVM); + } + + @override + Widget build(BuildContext context) { + return Center( + child: Container( + width: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint, + height: double.infinity, + padding: EdgeInsets.symmetric(vertical: 24, horizontal: 24), + child: SingleChildScrollView( + child: Column( + children: [ + Padding( + padding: EdgeInsets.only(left: 20, right: 20, bottom: 20), + child: Text( + Platform.isIOS + ? S.of(context).connect_your_hardware_wallet_ios + : S.of(context).connect_your_hardware_wallet, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).extension()!.titleColor), + textAlign: TextAlign.center, + ), + ), + if (!bleIsEnabled) + Padding( + padding: EdgeInsets.only(left: 20, right: 20, bottom: 20), + child: Text( + S.of(context).ledger_please_enable_bluetooth, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).extension()!.titleColor), + textAlign: TextAlign.center, + ), + ), + if (bleDevices.length > 0) ...[ + Padding( + padding: EdgeInsets.only(left: 20, right: 20, bottom: 20), + child: Container( + width: double.infinity, + child: Text( + S.of(context).bluetooth, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.titleColor, + ), + ), + ), + ), + ...bleDevices + .map( + (device) => Padding( + padding: EdgeInsets.only(bottom: 20), + child: DeviceTile( + onPressed: () => _connectToDevice(device), + title: device.name, + leading: imageLedger, + connectionType: device.connectionType, + ), + ), + ) + .toList() + ], + if (usbDevices.length > 0) ...[ + Padding( + padding: EdgeInsets.only(left: 20, right: 20, bottom: 20), + child: Container( + width: double.infinity, + child: Text( + S.of(context).usb, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.titleColor, + ), + ), + ), + ), + ...usbDevices + .map( + (device) => Padding( + padding: EdgeInsets.only(bottom: 20), + child: DeviceTile( + onPressed: () => _connectToDevice(device), + title: device.name, + leading: imageLedger, + connectionType: device.connectionType, + ), + ), + ) + .toList(), + ] + ], + ), + ), + ), + ); + } +} diff --git a/lib/src/screens/connect_device/debug_device_page.dart b/lib/src/screens/connect_device/debug_device_page.dart new file mode 100644 index 000000000..f5a9ef2a4 --- /dev/null +++ b/lib/src/screens/connect_device/debug_device_page.dart @@ -0,0 +1,212 @@ +// import 'dart:convert'; +// +// import 'package:cake_wallet/src/screens/base_page.dart'; +// import 'package:cake_wallet/src/screens/connect_device/widgets/device_tile.dart'; +// import 'package:cake_wallet/src/widgets/primary_button.dart'; +// import 'package:cake_wallet/utils/responsive_layout_util.dart'; +// import 'package:convert/convert.dart'; +// import 'package:flutter/material.dart'; +// import 'package:ledger_bitcoin/ledger_bitcoin.dart'; +// import 'package:ledger_flutter/ledger_flutter.dart'; +// import 'package:permission_handler/permission_handler.dart'; +// import 'package:polyseed/polyseed.dart'; +// +// class DebugDevicePage extends BasePage { +// @override +// String get title => "Connect Ledger"; +// +// @override +// Widget body(BuildContext context) => DebugDevicePageBody(); +// } +// +// class DebugDevicePageBody extends StatefulWidget { +// @override +// DebugDevicePageBodyState createState() => DebugDevicePageBodyState(); +// } +// +// class DebugDevicePageBodyState extends State { +// final imageLedger = Image.asset( +// 'assets/images/ledger_icon_black.png', +// width: 40, +// ); +// final ledger = Ledger( +// options: LedgerOptions( +// scanMode: ScanMode.balanced, +// maxScanDuration: const Duration(milliseconds: 5000), +// ), +// onPermissionRequest: (status) async { +// Map statuses = await [ +// // Permission.location, +// Permission.bluetoothScan, +// Permission.bluetoothConnect, +// Permission.bluetoothAdvertise, +// ].request(); +// +// if (status != BleStatus.ready) { +// return false; +// } +// +// return statuses.values.where((status) => status.isDenied).isEmpty; +// }, +// ); +// +// late BitcoinLedgerApp btc; +// var devices = []; +// var status = ""; +// var counter = 0; +// LedgerDevice? selectedDevice = null; +// +// @override +// void initState() { +// super.initState(); +// btc = BitcoinLedgerApp(ledger); +// } +// +// @override +// void dispose() { +// super.dispose(); +// ledger.close(ConnectionType.ble); +// ledger.close(ConnectionType.usb); +// } +// +// Future reconnectCurrentDevice() async { +// // await ledger.disconnect(selectedDevice!); +// // await ledger.connect(selectedDevice!); +// } +// +// Future disconnectCurrentDevice() async { +// await ledger.disconnect(selectedDevice!); +// setState(() => selectedDevice = null); +// } +// +// @override +// Widget build(BuildContext context) { +// final imageLedger = 'assets/images/ledger_nano.png'; +// +// return Center( +// child: Container( +// width: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint, +// height: double.infinity, +// padding: EdgeInsets.symmetric(vertical: 24, horizontal: 24), +// child: SingleChildScrollView( +// child: Column( +// children: [ +// Padding( +// padding: EdgeInsets.only(top: 20), +// child: Text(status), +// ), +// if (selectedDevice != null) ...[ +// DebugButton( +// title: "Get Version", +// method: "Version", +// func: () async => await btc.getVersion(selectedDevice!), +// ), +// DebugButton( +// title: "Get Master Fingerprint", +// method: "Master Fingerprint", +// func: () async => hex.encode(await btc.getMasterFingerprint(selectedDevice!)), +// ), +// DebugButton( +// title: "Get XPub", +// method: "XPub", +// func: () async => await btc.getXPubKey(selectedDevice!, derivationPath: "m/84'/0'/$counter'"), +// ), +// DebugButton( +// title: "Get Wallet Address", +// method: "Wallet Address", +// func: () async { +// setState(() => counter++); +// final derivationPath = "m/84'/0'/$counter'/0/0"; +// return await btc.getAccounts(selectedDevice!, accountsDerivationPath: derivationPath); +// // return await ethereum!.getHardwareWalletAccounts(selectedDevice!); +// }, +// ), +// DebugButton( +// title: "Send Money", +// method: "Sig", +// func: () async { +// final psbt = PsbtV2(); +// final psbtBuf = base64.decode( +// "cHNidP8BAgQCAAAAAQQBAQEFAQIAAQ4gTW6k/cwKKu1u7m9oKr5ob7VcAC0IPkfaDitRi/FkD7sBDwQAAAAAARAE/////wEA/ekBAQAAAAABA9AYVQLI722H0osKMa/4dvMucrnKV1Myxtlp0l0BoOBDAQAAAAD/////ku6r2ABaHt9N26f/P4eMljX8t1f4lBcFfEwuNm/uXYoBAAAAAP////+YeAl8arEGKOcyrWJAYwSboyCstkhHN8zn7/vy7pkYTAEAAAAA/////wHlHgAAAAAAABYAFKdq0umSucBGVkl2MpT6Hgo/0a/xAkcwRAIgMkiJmNFbEi2I3CQYOwyV/JepCnFQRvj4xghkySpFcJMCIGAypkkWltfj+ucvqUIu27tusDAIAAB+rBhX/GV7hPlEASEDyLmWyTLjLfC9kn8pnW42jW5N6EJo5fObjWWEyfLDu9UCSDBFAiEAg9crVtwBPF+sWk+Th6pLwzDjJGItwsUCvoBPtmMTEb4CIDGuM7WOguV0TP21oidF3bSUZlEAjUHWfWzxLKw+3LofASEDfN16xKb70UZSeQyX5Tlh8iRq7np5Nlz9GYdcSU50sKwCSDBFAiEAvotOblaEiBptRWkvb6bj2MGyRjTphKLBLiHYmrRMTCgCIEKJH+z65uPSSz1NIb0d/u3bU9l0xcWk0idEsXjB+BIiASEDrAEiEtrSNKxbh6F/KPaCTafF2LVjCzb75WB+x4xSuoQAAAAAAQEf5R4AAAAAAAAWABSnatLpkrnARlZJdjKU+h4KP9Gv8SIGA3xMuxmPsBAm9aMEUBs3N46DB+Kdts3bZR/Wxt+uM0H4GKtN6bpUAACAAAAAgAAAAIAAAAAAAAAAAAABBBTk7bEOxYcdXDi1eeWraYDufm6eJgEDCOgDAAAAAAAAAAEEFDX3g/pnDXIfsRw8shK42NZn+SdpAQMIiBMAAAAAAAAiAgN8TLsZj7AQJvWjBFAbNzeOgwfinbbN22Uf1sbfrjNB+BirTem6VAAAgAAAAIAAAACAAAAAAAAAAAAA" +// ); +// psbt.deserialize(psbtBuf); +// final result = await btc.signPsbt(selectedDevice!, psbt: psbt); +// return result.toHexString(); +// }, +// ), +// Padding( +// padding: EdgeInsets.only(top: 20), +// child: PrimaryButton( +// text: "Disconnect", +// onPressed: () => disconnectCurrentDevice(), +// color: Theme.of(context).primaryColor, +// textColor: Colors.white), +// ), +// ], +// if (selectedDevice == null) ...[ +// ...devices +// .map( +// (device) => Padding( +// padding: EdgeInsets.only(bottom: 20), +// child: DeviceTile( +// onPressed: () { +// setState(() => selectedDevice = device); +// ledger.connect(device); +// }, +// title: device.name, +// leading: imageLedger, +// connectionType: device.connectionType, +// ), +// ), +// ) +// .toList(), +// PrimaryButton( +// text: "Refresh BLE", +// onPressed: () async { +// setState(() => devices = []); +// ledger.scan().listen((device) => setState(() { +// devices.add(device); +// })); +// }, +// color: Theme.of(context).primaryColor, +// textColor: Colors.white), +// Padding( +// padding: EdgeInsets.only(top: 20), +// child: PrimaryButton( +// text: "Use USB", +// onPressed: () async { +// final dev = await ledger.listUsbDevices(); +// setState(() => devices = dev); +// }, +// color: Theme.of(context).primaryColor, +// textColor: Colors.white), +// ), +// ], +// ], +// ), +// )), +// ); +// } +// +// Widget DebugButton( +// {required String title, required String method, required Future Function() func}) { +// return Padding( +// padding: EdgeInsets.only(top: 20), +// child: PrimaryButton( +// text: title, +// onPressed: () async { +// try { +// setState(() => status = "Sending..."); +// final acc = await func(); +// setState(() => status = "$method: $acc"); +// print("$method: $acc"); +// } on LedgerException catch (ex) { +// setState(() => status = "${ex.errorCode.toRadixString(16)} ${ex.message}"); +// print("${ex.errorCode.toRadixString(16)} ${ex.message}"); +// } +// }, +// color: Theme.of(context).primaryColor, +// textColor: Colors.white), +// ); +// } +// } diff --git a/lib/src/screens/connect_device/select_hardware_wallet_account_page.dart b/lib/src/screens/connect_device/select_hardware_wallet_account_page.dart new file mode 100644 index 000000000..31542ab5f --- /dev/null +++ b/lib/src/screens/connect_device/select_hardware_wallet_account_page.dart @@ -0,0 +1,256 @@ +import 'package:cake_wallet/core/wallet_name_validator.dart'; +import 'package:cake_wallet/entities/generate_name.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart'; +import 'package:cake_wallet/src/widgets/alert_with_one_action.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/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart'; +import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; +import 'package:cake_wallet/utils/responsive_layout_util.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/view_model/wallet_hardware_restore_view_model.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:mobx/mobx.dart'; + +class SelectHardwareWalletAccountPage extends BasePage { + SelectHardwareWalletAccountPage(this._walletHardwareRestoreVM); + + final WalletHardwareRestoreViewModel _walletHardwareRestoreVM; + + @override + String get title => S.current.restore_title_from_hardware_wallet; + + @override + Widget body(BuildContext context) => SelectHardwareWalletAccountForm(_walletHardwareRestoreVM); +} + +class SelectHardwareWalletAccountForm extends StatefulWidget { + SelectHardwareWalletAccountForm(this._walletHardwareRestoreVM); + + final WalletHardwareRestoreViewModel _walletHardwareRestoreVM; + + @override + _SelectHardwareWalletAccountFormState createState() => + _SelectHardwareWalletAccountFormState(_walletHardwareRestoreVM); +} + +class _SelectHardwareWalletAccountFormState extends State { + _SelectHardwareWalletAccountFormState(this._walletHardwareRestoreVM) + : _formKey = GlobalKey(), + _controller = TextEditingController(); + + final GlobalKey _formKey; + final WalletHardwareRestoreViewModel _walletHardwareRestoreVM; + final TextEditingController _controller; + + @override + void initState() { + super.initState(); + _setEffects(context); + if (_walletHardwareRestoreVM.availableAccounts.length == 0) _loadMoreAccounts(); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only(top: 24), + child: ScrollableWithBottomSection( + contentPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), + content: Center( + child: ConstrainedBox( + constraints: + BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.only(top: 0), + child: Form( + key: _formKey, + child: Stack( + alignment: Alignment.centerRight, + children: [ + TextFormField( + onChanged: (value) => _walletHardwareRestoreVM.name = value, + controller: _controller, + style: TextStyle( + fontSize: 20.0, + fontWeight: FontWeight.w600, + color: Theme.of(context).extension()!.titleColor, + ), + decoration: InputDecoration( + hintStyle: TextStyle( + fontSize: 18.0, + fontWeight: FontWeight.w500, + color: Theme.of(context).extension()!.hintTextColor, + ), + hintText: S.of(context).wallet_name, + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + Theme.of(context).extension()!.underlineColor, + width: 1.0, + ), + ), + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: + Theme.of(context).extension()!.underlineColor, + width: 1.0, + ), + ), + suffixIcon: Semantics( + label: S.of(context).generate_name, + child: IconButton( + onPressed: () async { + final rName = await generateName(); + FocusManager.instance.primaryFocus?.unfocus(); + + setState(() { + _controller.text = rName; + _walletHardwareRestoreVM.name = rName; + _controller.selection = TextSelection.fromPosition( + TextPosition(offset: _controller.text.length)); + }); + }, + icon: Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6.0), + color: Theme.of(context).hintColor, + ), + width: 34, + height: 34, + child: Image.asset( + 'assets/images/refresh_icon.png', + color: Theme.of(context) + .extension()! + .textFieldButtonIconColor, + ), + ), + ), + ), + ), + validator: WalletNameValidator(), + ), + ], + ), + ), + ), + Padding( + padding: EdgeInsets.only(top: 20), + child: Container( + width: double.infinity, + child: Text( + "Available accounts", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).extension()!.titleColor, + ), + ), + ), + ), + Observer( + builder: (context) => Column( + children: _walletHardwareRestoreVM.availableAccounts.map((acc) { + final address = acc.address; + return Padding( + padding: EdgeInsets.only(top: 10), + child: SelectButton( + image: Image.asset( + walletTypeToCryptoCurrency(_walletHardwareRestoreVM.type).iconPath ?? + '', + height: 24, + width: 24, + ), + text: + "${address.substring(0, 6)}...${address.substring(address.length - 6)}", + showTrailingIcon: false, + height: 54, + isSelected: _walletHardwareRestoreVM.selectedAccount == acc, + onTap: () => + setState(() => _walletHardwareRestoreVM.selectedAccount = acc), + ), + ); + }).toList(), + ), + ), + Padding( + padding: EdgeInsets.only(top: 10), + child: Observer(builder: (context) { + return LoadingPrimaryButton( + onPressed: _loadMoreAccounts, + text: S.of(context).load_more, + color: Theme.of(context).primaryColor, + textColor: Colors.white, + isLoading: _walletHardwareRestoreVM.isLoadingMoreAccounts, + ); + }), + ), + ], + ), + ), + ), + bottomSectionPadding: EdgeInsets.all(24), + bottomSection: Observer( + builder: (context) { + return LoadingPrimaryButton( + onPressed: _confirmForm, + text: S.of(context).seed_language_next, + color: Colors.green, + textColor: Colors.white, + isDisabled: _walletHardwareRestoreVM.name.isEmpty, + ); + }, + ), + ), + ); + } + + Future _loadMoreAccounts() async { + _walletHardwareRestoreVM.isLoadingMoreAccounts = true; + _walletHardwareRestoreVM.getNextAvailableAccounts(5); + } + + Future _confirmForm() async { + await _walletHardwareRestoreVM.create(); + } + + bool _effectsInstalled = false; + + void _setEffects(BuildContext context) { + if (_effectsInstalled) return; + + reaction((_) => _walletHardwareRestoreVM.error, (String? error) { + + if (error != null) { + + if (error == S.current.ledger_connection_error) + Navigator.of(context).pop(); + + WidgetsBinding.instance.addPostFrameCallback((_) { + showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: S.of(context).error, + alertContent: error, + buttonText: S.of(context).ok, + buttonAction: () { + _walletHardwareRestoreVM.error = null; + Navigator.of(context).pop(); + }); + }); + }); + } + }); + + _effectsInstalled = true; + } +} diff --git a/lib/src/screens/connect_device/widgets/device_tile.dart b/lib/src/screens/connect_device/widgets/device_tile.dart new file mode 100644 index 000000000..8367d1606 --- /dev/null +++ b/lib/src/screens/connect_device/widgets/device_tile.dart @@ -0,0 +1,78 @@ +import 'package:cake_wallet/themes/extensions/option_tile_theme.dart'; +import 'package:flutter/material.dart'; +import 'package:ledger_flutter/ledger_flutter.dart'; + +class DeviceTile extends StatelessWidget { + const DeviceTile({ + required this.onPressed, + required this.title, + this.leading, + this.connectionType, + }); + + final VoidCallback onPressed; + final String title; + final String? leading; + final ConnectionType? connectionType; + + String? get connectionTypeIcon { + switch (connectionType) { + case ConnectionType.ble: + return 'assets/images/bluetooth.png'; + case ConnectionType.usb: + return 'assets/images/usb.png'; + case null: + return null; + } + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onPressed, + child: Container( + width: double.infinity, + padding: EdgeInsets.all(24), + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(12)), + color: Theme.of(context).cardColor, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + if (leading != null) + Image.asset( + leading!, + height: 30, + color: Theme.of(context).extension()!.titleColor, + ), + Expanded( + child: Padding( + padding: EdgeInsets.only(left: 16), + child: Text( + title, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + color: Theme.of(context).extension()!.titleColor, + ), + ), + ), + ), + if (connectionTypeIcon != null) + Center( + child: Image.asset( + connectionTypeIcon!, + height: 25, + color: Theme.of(context).extension()!.titleColor, + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart index 940ab54ca..f839f9d27 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_item.dart @@ -45,6 +45,7 @@ class SideMenuItem extends StatelessWidget { ? Icon( icon, color: _setColor(context), + size: 30, ) : Image.asset( imagePath ?? '', diff --git a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart index 7ba169154..d9b509136 100644 --- a/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart +++ b/lib/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart @@ -82,7 +82,8 @@ class DesktopSidebarWrapper extends BasePage { width: sideMenuWidth, topItems: [ SideMenuItem( - imagePath: 'assets/images/wallet_outline.png', + // imagePath: 'assets/images/wallet_outline.png', + icon: Icons.home, isSelected: desktopSidebarViewModel.currentPage == SidebarItem.dashboard, onTap: () { desktopSidebarViewModel.onPageChange(SidebarItem.dashboard); diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart index a2ad3fb80..83a57060d 100644 --- a/lib/src/screens/dashboard/pages/balance_page.dart +++ b/lib/src/screens/dashboard/pages/balance_page.dart @@ -148,6 +148,17 @@ class CryptoBalanceWidget extends StatelessWidget { maxLines: 1, textAlign: TextAlign.center, ), + if (dashboardViewModel.wallet.isHardwareWallet) + Padding( + padding: const EdgeInsets.all(8.0), + child: Image.asset( + 'assets/images/ledger_nano.png', + width: 24, + color: Theme.of(context) + .extension()! + .pageTitleTextColor, + ), + ), if (dashboardViewModel .balanceViewModel.isHomeScreenSettingsEnabled) InkWell( diff --git a/lib/src/screens/new_wallet/new_wallet_type_page.dart b/lib/src/screens/new_wallet/new_wallet_type_page.dart index 8c8a94a7e..dc22a60db 100644 --- a/lib/src/screens/new_wallet/new_wallet_type_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_type_page.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart'; @@ -10,14 +12,20 @@ import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/wallet_types.g.dart'; +import 'package:cw_core/hardware/device_connection_type.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; class NewWalletTypePage extends BasePage { - NewWalletTypePage({required this.onTypeSelected, required this.isCreate}); + NewWalletTypePage({ + required this.onTypeSelected, + required this.isCreate, + required this.isHardwareWallet, + }); final void Function(BuildContext, WalletType) onTypeSelected; final bool isCreate; + final bool isHardwareWallet; final walletTypeImage = Image.asset('assets/images/wallet_type.png'); final walletTypeLightImage = Image.asset('assets/images/wallet_type_light.png'); @@ -31,15 +39,22 @@ class NewWalletTypePage extends BasePage { onTypeSelected: onTypeSelected, walletImage: currentTheme.type == ThemeType.dark ? walletTypeImage : walletTypeLightImage, isCreate: isCreate, + isHardwareWallet: isHardwareWallet, ); } class WalletTypeForm extends StatefulWidget { - WalletTypeForm({required this.onTypeSelected, required this.walletImage, required this.isCreate}); + WalletTypeForm({ + required this.onTypeSelected, + required this.walletImage, + required this.isCreate, + required this.isHardwareWallet, + }); final void Function(BuildContext, WalletType) onTypeSelected; final Image walletImage; final bool isCreate; + final bool isHardwareWallet; @override WalletTypeFormState createState() => WalletTypeFormState(); @@ -58,7 +73,11 @@ class WalletTypeFormState extends State { @override void initState() { - types = filteredTypes = availableWalletTypes; + types = filteredTypes = availableWalletTypes + .where((element) => + !widget.isHardwareWallet || + DeviceConnectionType.supportedConnectionTypes(element, Platform.isIOS).isNotEmpty) + .toList(); super.initState(); searchController.addListener(() { @@ -74,76 +93,81 @@ class WalletTypeFormState extends State { @override Widget build(BuildContext context) { return Center( - child: ConstrainedBox( - constraints: - BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), - child: Column( - children: [ - Padding( - padding: EdgeInsets.only(top: 48), - child: Text( - S.of(context).choose_wallet_currency, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).extension()!.titleColor), - ), + child: ConstrainedBox( + constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint), + child: Column( + children: [ + Padding( + padding: EdgeInsets.only(top: 48), + child: Text( + S.of(context).choose_wallet_currency, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).extension()!.titleColor, ), - Padding( - padding: const EdgeInsets.fromLTRB(24, 24, 24, 12), - child: SearchBarWidget(searchController: searchController, borderRadius: 24), - ), - Expanded( - child: ScrollableWithBottomSection( - contentPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), - content: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - ...filteredTypes.map((type) => Padding( - padding: EdgeInsets.only(top: 12), - child: SelectButton( - image: Image.asset( - walletTypeToCryptoCurrency(type).iconPath ?? '', - height: 24, - width: 24), - text: walletTypeToDisplayName(type), - showTrailingIcon: false, - height: 54, - isSelected: selected == type, - onTap: () => setState(() => selected = type)), - )) - ], + ), + ), + Padding( + padding: EdgeInsets.fromLTRB(24, 24, 24, 12), + child: SearchBarWidget(searchController: searchController, borderRadius: 24), + ), + Expanded( + child: ScrollableWithBottomSection( + contentPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), + content: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ...filteredTypes.map( + (type) => Padding( + padding: EdgeInsets.only(top: 12), + child: SelectButton( + image: Image.asset( + walletTypeToCryptoCurrency(type).iconPath ?? '', + height: 24, + width: 24, + ), + text: walletTypeToDisplayName(type), + showTrailingIcon: false, + height: 54, + isSelected: selected == type, + onTap: () => setState(() => selected = type), + deviceConnectionTypes: widget.isHardwareWallet + ? DeviceConnectionType.supportedConnectionTypes(type, Platform.isIOS) + : [], + ), + ), ), - bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), - bottomSection: PrimaryButton( - onPressed: () => onTypeSelected(), - text: S.of(context).seed_language_next, - color: Theme.of(context).primaryColor, - textColor: Colors.white, - isDisabled: selected == null, - ), - ), + ], ), - ], - ))); + bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), + bottomSection: PrimaryButton( + onPressed: () => onTypeSelected(), + text: S.of(context).seed_language_next, + color: Theme.of(context).primaryColor, + textColor: Colors.white, + isDisabled: selected == null, + ), + ), + ), + ], + ), + ), + ); } Future onTypeSelected() async { - if (selected == null) { - throw Exception('Wallet Type is not selected yet.'); - } + if (selected == null) throw Exception('Wallet Type is not selected yet.'); if (selected == WalletType.haven && widget.isCreate) { return await showPopUp( context: context, - builder: (BuildContext context) { - return PopUpCancellableAlertDialog( - contentText: S.of(context).pause_wallet_creation, - actionButtonText: S.of(context).ok, - buttonAction: () => Navigator.of(context).pop(), - ); - }, + builder: (BuildContext context) => PopUpCancellableAlertDialog( + contentText: S.of(context).pause_wallet_creation, + actionButtonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop(), + ), ); } diff --git a/lib/src/screens/new_wallet/widgets/select_button.dart b/lib/src/screens/new_wallet/widgets/select_button.dart index d94c9767d..2eda77d01 100644 --- a/lib/src/screens/new_wallet/widgets/select_button.dart +++ b/lib/src/screens/new_wallet/widgets/select_button.dart @@ -1,7 +1,8 @@ -import 'package:flutter/material.dart'; import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; import 'package:cake_wallet/themes/extensions/filter_theme.dart'; import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart'; +import 'package:cw_core/hardware/device_connection_type.dart'; +import 'package:flutter/material.dart'; class SelectButton extends StatelessWidget { SelectButton({ @@ -16,6 +17,7 @@ class SelectButton extends StatelessWidget { this.textColor, this.arrowColor, this.borderColor, + this.deviceConnectionTypes, }); final Image? image; @@ -24,6 +26,7 @@ class SelectButton extends StatelessWidget { final bool isSelected; final VoidCallback onTap; final bool showTrailingIcon; + final List? deviceConnectionTypes; final double height; final Color? color; final Color? textColor; @@ -33,15 +36,26 @@ class SelectButton extends StatelessWidget { @override Widget build(BuildContext context) { final backgroundColor = color ?? (isSelected ? Colors.green : Theme.of(context).cardColor); - final effectiveTextColor = textColor ?? (isSelected - ? Theme.of(context).extension()!.restoreWalletButtonTextColor - : Theme.of(context).extension()!.buttonTextColor); - final effectiveArrowColor = arrowColor ?? (isSelected - ? Theme.of(context).extension()!.restoreWalletButtonTextColor - : Theme.of(context).extension()!.titlesColor); + final effectiveTextColor = textColor ?? + (isSelected + ? Theme.of(context).extension()!.restoreWalletButtonTextColor + : Theme.of(context).extension()!.buttonTextColor); + final effectiveArrowColor = arrowColor ?? + (isSelected + ? Theme.of(context).extension()!.restoreWalletButtonTextColor + : Theme.of(context).extension()!.titlesColor); - final selectArrowImage = Image.asset('assets/images/select_arrow.png', - color: effectiveArrowColor); + final trailingIcons = []; + final selectArrowImage = + Image.asset('assets/images/select_arrow.png', color: effectiveArrowColor); + + deviceConnectionTypes?.forEach((element) => trailingIcons.add(Image.asset( + element.iconString, + color: effectiveArrowColor, + height: 24, + ))); + + if (showTrailingIcon) trailingIcons.add(selectArrowImage); return GestureDetector( onTap: onTap, @@ -54,34 +68,33 @@ class SelectButton extends StatelessWidget { borderRadius: BorderRadius.all(Radius.circular(30)), color: backgroundColor, border: borderColor != null ? Border.all(color: borderColor!) : null, - ), child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - image ?? Offstage(), - Padding( - padding: image != null - ? EdgeInsets.only(left: 15) - : EdgeInsets.only(left: 0), - child: Text( - text, - style: TextStyle( - fontSize: textSize, - fontWeight: FontWeight.w500, - color: effectiveTextColor, + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + image ?? Offstage(), + Padding( + padding: image != null ? EdgeInsets.only(left: 15) : EdgeInsets.only(left: 0), + child: Text( + text, + style: TextStyle( + fontSize: textSize, + fontWeight: FontWeight.w500, + color: effectiveTextColor, + ), ), - ), - ) - ], + ) + ], + ), ), - if (showTrailingIcon) selectArrowImage + ...trailingIcons ], ), ), diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart index 91ee9bd0b..a0f3a597e 100644 --- a/lib/src/screens/restore/restore_options_page.dart +++ b/lib/src/screens/restore/restore_options_page.dart @@ -1,19 +1,19 @@ import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/option_tile.dart'; +import 'package:cake_wallet/themes/extensions/option_tile_theme.dart'; +import 'package:cake_wallet/utils/permission_handler.dart'; +import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart'; import 'package:cake_wallet/view_model/restore/wallet_restore_from_qr_code.dart'; -import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:flutter/material.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/generated/i18n.dart'; import 'package:permission_handler/permission_handler.dart'; -import 'package:cake_wallet/utils/permission_handler.dart'; class RestoreOptionsPage extends BasePage { RestoreOptionsPage({required this.isNewInstall}); @@ -22,12 +22,15 @@ class RestoreOptionsPage extends BasePage { String get title => S.current.restore_restore_wallet; final bool isNewInstall; - final imageSeedKeys = Image.asset('assets/images/restore_wallet_image.png'); - final imageBackup = Image.asset('assets/images/backup.png'); - final qrCode = Image.asset('assets/images/restore_qr.png'); @override Widget body(BuildContext context) { + final imageColor = Theme.of(context).extension()!.titleColor; + final imageLedger = Image.asset('assets/images/ledger_nano.png', width: 40, color: imageColor); + final imageSeedKeys = Image.asset('assets/images/restore_wallet_image.png', color: imageColor); + final imageBackup = Image.asset('assets/images/backup.png', color: imageColor); + final qrCode = Image.asset('assets/images/restore_qr.png', color: imageColor); + return Center( child: Container( width: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint, @@ -37,53 +40,37 @@ class RestoreOptionsPage extends BasePage { child: Column( children: [ OptionTile( - onPressed: () => Navigator.pushNamed(context, Routes.restoreWalletFromSeedKeys, - arguments: isNewInstall), - image: imageSeedKeys, - title: S.of(context).restore_title_from_seed_keys, - description: S.of(context).restore_description_from_seed_keys), + onPressed: () => Navigator.pushNamed(context, Routes.restoreWalletFromSeedKeys, + arguments: isNewInstall), + image: imageSeedKeys, + title: S.of(context).restore_title_from_seed_keys, + description: S.of(context).restore_description_from_seed_keys, + ), if (isNewInstall) Padding( padding: EdgeInsets.only(top: 24), child: OptionTile( - onPressed: () => Navigator.pushNamed(context, Routes.restoreFromBackup), - image: imageBackup, - title: S.of(context).restore_title_from_backup, - description: S.of(context).restore_description_from_backup), + onPressed: () => Navigator.pushNamed(context, Routes.restoreFromBackup), + image: imageBackup, + title: S.of(context).restore_title_from_backup, + description: S.of(context).restore_description_from_backup, + ), ), Padding( padding: EdgeInsets.only(top: 24), child: OptionTile( - onPressed: () async { - bool isCameraPermissionGranted = - await PermissionHandler.checkPermission(Permission.camera, context); - if (!isCameraPermissionGranted) return; - bool isPinSet = false; - if (isNewInstall) { - await Navigator.pushNamed(context, Routes.setupPin, - arguments: (PinCodeState setupPinContext, String _) { - setupPinContext.close(); - isPinSet = true; - }); - } - if (!isNewInstall || isPinSet) { - try { - final restoreWallet = - await WalletRestoreFromQRCode.scanQRCodeForRestoring(context); - - final restoreFromQRViewModel = - getIt.get(param1: restoreWallet.type); - - await restoreFromQRViewModel.create(restoreWallet: restoreWallet); - if (restoreFromQRViewModel.state is FailureState) { - _onWalletCreateFailure(context, - 'Create wallet state: ${(restoreFromQRViewModel.state as FailureState).error}'); - } - } catch (e) { - _onWalletCreateFailure(context, e.toString()); - } - } - }, + onPressed: () => Navigator.pushNamed( + context, Routes.restoreWalletFromHardwareWallet, + arguments: isNewInstall), + image: imageLedger, + title: S.of(context).restore_title_from_hardware_wallet, + description: S.of(context).restore_description_from_hardware_wallet, + ), + ), + Padding( + padding: EdgeInsets.only(top: 24), + child: OptionTile( + onPressed: () => _onScanQRCode(context), image: qrCode, title: S.of(context).scan_qr_code, description: S.of(context).cold_or_recover_wallet), @@ -105,4 +92,35 @@ class RestoreOptionsPage extends BasePage { buttonAction: () => Navigator.of(context).pop()); }); } + + Future _onScanQRCode(BuildContext context) async { + final isCameraPermissionGranted = + await PermissionHandler.checkPermission(Permission.camera, context); + + if (!isCameraPermissionGranted) return; + bool isPinSet = false; + if (isNewInstall) { + await Navigator.pushNamed(context, Routes.setupPin, + arguments: (PinCodeState setupPinContext, String _) { + setupPinContext.close(); + isPinSet = true; + }); + } + if (!isNewInstall || isPinSet) { + try { + final restoreWallet = await WalletRestoreFromQRCode.scanQRCodeForRestoring(context); + + final restoreFromQRViewModel = + getIt.get(param1: restoreWallet.type); + + await restoreFromQRViewModel.create(restoreWallet: restoreWallet); + if (restoreFromQRViewModel.state is FailureState) { + _onWalletCreateFailure(context, + 'Create wallet state: ${(restoreFromQRViewModel.state as FailureState).error}'); + } + } catch (e) { + _onWalletCreateFailure(context, e.toString()); + } + } + } } diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 9067a2951..648133391 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -1,39 +1,40 @@ import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/entities/contact_record.dart'; +import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/entities/template.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.dart'; +import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart'; import 'package:cake_wallet/src/screens/send/widgets/send_card.dart'; import 'package:cake_wallet/src/widgets/add_template_button.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/picker.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/template_tile.dart'; +import 'package:cake_wallet/src/widgets/trail_button.dart'; import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart'; import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/utils/request_review_handler.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cw_core/wallet_type.dart'; +import 'package:cake_wallet/view_model/send/send_view_model.dart'; +import 'package:cake_wallet/view_model/send/send_view_model_state.dart'; +import 'package:cw_core/crypto_currency.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/view_model/send/send_view_model.dart'; -import 'package:cake_wallet/core/execution_state.dart'; -import 'package:cake_wallet/src/screens/base_page.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/trail_button.dart'; -import 'package:cake_wallet/utils/show_pop_up.dart'; -import 'package:cake_wallet/view_model/send/send_view_model_state.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart'; -import 'package:cw_core/crypto_currency.dart'; class SendPage extends BasePage { SendPage({ @@ -369,6 +370,21 @@ class SendPage extends BasePage { return; } + if (sendViewModel.wallet.isHardwareWallet) { + if (!sendViewModel.ledgerViewModel.isConnected) { + await Navigator.of(context).pushNamed(Routes.connectDevices, + arguments: ConnectDevicePageParams( + walletType: sendViewModel.walletType, + onConnectDevice: (BuildContext context, _) { + sendViewModel.ledgerViewModel.setLedger(sendViewModel.wallet); + Navigator.of(context).pop(); + }, + )); + } else { + sendViewModel.ledgerViewModel.setLedger(sendViewModel.wallet); + } + } + final check = sendViewModel.shouldDisplayTotp(); authService.authenticateAction( context, @@ -384,7 +400,8 @@ class SendPage extends BasePage { color: Theme.of(context).primaryColor, textColor: Colors.white, isLoading: sendViewModel.state is IsExecutingState || - sendViewModel.state is TransactionCommitting, + sendViewModel.state is TransactionCommitting || + sendViewModel.state is IsAwaitingDeviceResponseState, isDisabled: !sendViewModel.isReadyForSend, ); }, @@ -395,12 +412,20 @@ class SendPage extends BasePage { ); } + BuildContext? dialogContext; + void _setEffects(BuildContext context) { if (_effectsInstalled) { return; } reaction((_) => sendViewModel.state, (ExecutionState state) { + + if (dialogContext != null && dialogContext?.mounted == true) { + Navigator.of(dialogContext!).pop(); + } + + if (state is FailureState) { WidgetsBinding.instance.addPostFrameCallback((_) { showPopUp( @@ -510,6 +535,21 @@ class SendPage extends BasePage { sendViewModel.clearOutputs(); }); } + + if (state is IsAwaitingDeviceResponseState) { + WidgetsBinding.instance.addPostFrameCallback((_) { + showPopUp( + context: context, + builder: (BuildContext context) { + dialogContext = context; + return 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()); + }); + }); + } }); _effectsInstalled = true; diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart index 8c4da4cc5..7b4fb3b1c 100644 --- a/lib/src/screens/settings/connection_sync_page.dart +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -1,10 +1,14 @@ import 'dart:io'; +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/base_page.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/wallet_connect_button.dart'; +import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/feature_flag.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; @@ -12,10 +16,6 @@ import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/settings/sync_mode.dart'; import 'package:cw_core/battery_optimization_native.dart'; import 'package:flutter/material.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; class ConnectionSyncPage extends BasePage { @@ -106,7 +106,8 @@ class ConnectionSyncPage extends BasePage { ); }, ), - if (isWalletConnectCompatibleChain(dashboardViewModel.wallet.type)) ...[ + if (isWalletConnectCompatibleChain(dashboardViewModel.wallet.type) && + !dashboardViewModel.wallet.isHardwareWallet) ...[ // ToDo: Remove this line once WalletConnect is implemented WalletConnectTile( onTap: () => Navigator.of(context).pushNamed(Routes.walletConnectConnectionsListing), ), diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index ef521c311..24d02d68d 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -509,7 +509,9 @@ abstract class DashboardViewModelBase with Store { final path = await pathForWallet(name: walletInfo.name, type: walletInfo.type); final jsonSource = await read(path: path, password: password); final data = json.decode(jsonSource) as Map; - final mnemonic = data['mnemonic'] as String; + final mnemonic = data['mnemonic'] as String?; + + if (mnemonic == null) continue; final hash = await Cryptography.instance.sha256().hash(utf8.encode(mnemonic)); final seedSha = bytesToHex(hash.bytes); diff --git a/lib/view_model/hardware_wallet/ledger_view_model.dart b/lib/view_model/hardware_wallet/ledger_view_model.dart new file mode 100644 index 000000000..453df44db --- /dev/null +++ b/lib/view_model/hardware_wallet/ledger_view_model.dart @@ -0,0 +1,66 @@ +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/polygon/polygon.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:ledger_flutter/ledger_flutter.dart'; +import 'package:permission_handler/permission_handler.dart'; + +class LedgerViewModel { + final Ledger ledger = Ledger( + options: LedgerOptions( + scanMode: ScanMode.balanced, + maxScanDuration: const Duration(minutes: 5), + ), + onPermissionRequest: (_) async { + Map statuses = await [ + Permission.bluetoothScan, + Permission.bluetoothConnect, + Permission.bluetoothAdvertise, + ].request(); + + return statuses.values.where((status) => status.isDenied).isEmpty; + }, + ); + + Future connectLedger(LedgerDevice device) async { + await ledger.connect(device); + + if (device.connectionType == ConnectionType.usb) _device = device; + } + + LedgerDevice? _device; + + bool get isConnected => ledger.devices.isNotEmpty || _device != null; + + LedgerDevice get device => _device ?? ledger.devices.first; + + void setLedger(WalletBase wallet) { + switch (wallet.type) { + case WalletType.bitcoin: + return bitcoin!.setLedger(wallet, ledger, device); + case WalletType.ethereum: + return ethereum!.setLedger(wallet, ledger, device); + case WalletType.polygon: + return polygon!.setLedger(wallet, ledger, device); + default: + throw Exception('Unexpected wallet type: ${wallet.type}'); + } + } + + String? interpretErrorCode(String errorCode) { + switch (errorCode) { + case "6985": + return S.current.ledger_error_tx_rejected_by_user; + case "5515": + return S.current.ledger_error_device_locked; + case "6d02": // UNKNOWN_APDU + case "6511": + case "6e00": + return S.current.ledger_error_wrong_app; + default: + return null; + } + } +} diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index bafc1317d..2a6bf553b 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -15,11 +15,13 @@ 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'; import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; +import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart'; import 'package:cw_core/exceptions.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cake_wallet/view_model/send/send_template_view_model.dart'; import 'package:hive/hive.dart'; +import 'package:ledger_flutter/ledger_flutter.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/entities/template.dart'; import 'package:cake_wallet/core/address_validator.dart'; @@ -63,6 +65,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor this.balanceViewModel, this.contactListViewModel, this.transactionDescriptionBox, + this.ledgerViewModel, ) : state = InitialExecutionState(), currencies = appStore.wallet!.balance.keys.toList(), selectedCryptoCurrency = appStore.wallet!.currency, @@ -266,6 +269,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor final SendTemplateViewModel sendTemplateViewModel; final BalanceViewModel balanceViewModel; final ContactListViewModel contactListViewModel; + final LedgerViewModel ledgerViewModel; final FiatConversionStore _fiatConversationStore; final Box transactionDescriptionBox; @@ -340,7 +344,10 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor try { state = IsExecutingState(); + if (wallet.isHardwareWallet) state = IsAwaitingDeviceResponseState(); + pendingTransaction = await wallet.createTransaction(_credentials()); + if (provider is ThorChainExchangeProvider) { final outputCount = pendingTransaction?.outputCount ?? 0; if (outputCount > 10) { @@ -354,7 +361,15 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor state = ExecutedSuccessfullyState(); return pendingTransaction; } catch (e) { - state = FailureState(translateErrorMessage(e, wallet.type, wallet.currency)); + if (e is LedgerException) { + final errorCode = e.errorCode.toRadixString(16); + final fallbackMsg = e.message.isNotEmpty ? e.message : "Unexpected Ledger Error Code: $errorCode"; + final errorMsg = ledgerViewModel.interpretErrorCode(errorCode) ?? fallbackMsg; + + state = FailureState(errorMsg); + } else { + state = FailureState(translateErrorMessage(e, wallet.type, wallet.currency)); + } } return null; } @@ -390,15 +405,13 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor String address = outputs.fold('', (acc, value) { return value.isParsedAddress - ? acc + value.address + '\n' + value.extractedAddress + '\n\n' - : acc + value.address + '\n\n'; + ? '$acc${value.address}\n${value.extractedAddress}\n\n' + : '$acc${value.address}\n\n'; }); address = address.trim(); - String note = outputs.fold('', (acc, value) { - return acc + value.note + '\n'; - }); + String note = outputs.fold('', (acc, value) => '$acc${value.note}\n'); note = note.trim(); diff --git a/lib/view_model/send/send_view_model_state.dart b/lib/view_model/send/send_view_model_state.dart index 6d63eb9c2..df31041bc 100644 --- a/lib/view_model/send/send_view_model_state.dart +++ b/lib/view_model/send/send_view_model_state.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/core/execution_state.dart'; +class IsAwaitingDeviceResponseState extends IsExecutingState {} class TransactionCommitting extends ExecutionState {} class TransactionCommitted extends ExecutionState {} diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index 5c9c29a16..f825f0c47 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -72,6 +72,7 @@ abstract class WalletCreationVMBase with Store { address: '', showIntroCakePayCard: (!walletCreationService.typeExists(type)) && type != WalletType.haven, derivationInfo: credentials.derivationInfo ?? getDefaultDerivation(), + hardwareWalletType: credentials.hardwareWalletType, ); credentials.walletInfo = walletInfo; @@ -99,7 +100,7 @@ abstract class WalletCreationVMBase with Store { case WalletType.litecoin: return DerivationInfo( derivationType: DerivationType.electrum, - derivationPath: "m/0'/0", + derivationPath: "m/0'", ); default: return null; diff --git a/lib/view_model/wallet_hardware_restore_view_model.dart b/lib/view_model/wallet_hardware_restore_view_model.dart new file mode 100644 index 000000000..804ef7e3c --- /dev/null +++ b/lib/view_model/wallet_hardware_restore_view_model.dart @@ -0,0 +1,110 @@ +import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/core/wallet_creation_service.dart'; +import 'package:cake_wallet/ethereum/ethereum.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cake_wallet/store/app_store.dart'; +import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart'; +import 'package:cake_wallet/view_model/wallet_creation_vm.dart'; +import 'package:cw_core/hardware/hardware_account_data.dart'; +import 'package:cw_core/wallet_base.dart'; +import 'package:cw_core/wallet_credentials.dart'; +import 'package:cw_core/wallet_info.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:hive/hive.dart'; +import 'package:ledger_flutter/ledger_flutter.dart'; +import 'package:mobx/mobx.dart'; + +part 'wallet_hardware_restore_view_model.g.dart'; + +class WalletHardwareRestoreViewModel = WalletHardwareRestoreViewModelBase + with _$WalletHardwareRestoreViewModel; + +abstract class WalletHardwareRestoreViewModelBase extends WalletCreationVM with Store { + final LedgerViewModel ledgerViewModel; + + int _nextIndex = 0; + + WalletHardwareRestoreViewModelBase(this.ledgerViewModel, AppStore appStore, + WalletCreationService walletCreationService, Box walletInfoSource, + {required WalletType type}) + : super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: true); + + @observable + String name = ""; + + @observable + HardwareAccountData? selectedAccount = null; + + @observable + bool isLoadingMoreAccounts = false; + + @observable + String? error = null; + + // @observable + ObservableList availableAccounts = ObservableList(); + + @action + Future getNextAvailableAccounts(int limit) async { + try { + List accounts; + switch (type) { + case WalletType.bitcoin: + accounts = await bitcoin! + .getHardwareWalletAccounts(ledgerViewModel, index: _nextIndex, limit: limit); + break; + case WalletType.ethereum: + accounts = await ethereum! + .getHardwareWalletAccounts(ledgerViewModel, index: _nextIndex, limit: limit); + break; + case WalletType.polygon: + accounts = await polygon! + .getHardwareWalletAccounts(ledgerViewModel, index: _nextIndex, limit: limit); + break; + default: + return; + } + + availableAccounts.addAll(accounts); + _nextIndex += limit; + } on LedgerException catch (e) { + error = ledgerViewModel.interpretErrorCode(e.errorCode.toRadixString(16)); + } catch (e) { + error = S.current.ledger_connection_error; + } + + isLoadingMoreAccounts = false; + _nextIndex += limit; + } + + @override + WalletCredentials getCredentials(dynamic _options) { + WalletCredentials credentials; + switch (type) { + case WalletType.bitcoin: + credentials = + bitcoin!.createBitcoinHardwareWalletCredentials(name: name, accountData: selectedAccount!); + break; + case WalletType.ethereum: + credentials = + ethereum!.createEthereumHardwareWalletCredentials(name: name, hwAccountData: selectedAccount!); + break; + case WalletType.polygon: + credentials = polygon!.createPolygonHardwareWalletCredentials(name: name, hwAccountData: selectedAccount!); + break; + default: + throw Exception('Unexpected type: ${type.toString()}'); + } + + credentials.hardwareWalletType = HardwareWalletType.ledger; + + return credentials; + } + + @override + Future process(WalletCredentials credentials) async { + walletCreationService.changeWalletType(type: type); + return walletCreationService.restoreFromHardwareWallet(credentials); + } +} diff --git a/macos/Runner/InfoBase.plist b/macos/Runner/InfoBase.plist index c849a42c7..dcd0de5a6 100644 --- a/macos/Runner/InfoBase.plist +++ b/macos/Runner/InfoBase.plist @@ -32,5 +32,22 @@ NSApplication LSApplicationCategoryType public.app-category.finance + NSCameraUsageDescription + Used for scanning QR code and can be used to capture images for identification purposes by third-party providers. + NSDocumentsFolderUsageDescription + We need access to documents folder for getting access to open/save backup file + NSFaceIDUsageDescription + Enable Face ID for fast and secure access to wallets and private keys + NSPhotoLibraryUsageDescription + We need access to documents folder for getting access to open/save backup file + NSBluetoothPeripheralUsageDescription + We need access to Bluetooth in order to connect to your hardware wallet when needed + NSBluetoothAlwaysUsageDescription + We need access to Bluetooth in order to connect to your hardware wallet when needed + UIBackgroundModes + + fetch + processing + diff --git a/pubspec_base.yaml b/pubspec_base.yaml index bdfa70964..cf04509ac 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -111,6 +111,7 @@ dependencies: git: url: https://github.com/cake-tech/bitcoin_base.git ref: cake-update-v2 + ledger_flutter: ^1.0.1 dev_dependencies: flutter_test: @@ -133,6 +134,14 @@ dependency_overrides: bech32: git: url: https://github.com/cake-tech/bech32.git + ledger_flutter: + git: + url: https://github.com/cake-tech/ledger-flutter.git + ref: cake + web3dart: + git: + url: https://github.com/cake-tech/web3dart.git + ref: cake flutter_icons: image_path: "assets/images/app_logo.png" diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 16a87a850..365912743 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "موضوع البيتكوين الخفيفة", "bitcoin_payments_require_1_confirmation": "تتطلب مدفوعات Bitcoin تأكيدًا واحدًا ، والذي قد يستغرق 20 دقيقة أو أكثر. شكرا لصبرك! سيتم إرسال بريد إلكتروني إليك عند تأكيد الدفع.", "Blocks_remaining": "بلوك متبقي ${status}", + "bluetooth": "بلوتوث", "bright_theme": "مشرق", "bump_fee": "رسوم عثرة", "buy": "اشتري", @@ -144,6 +145,8 @@ "congratulations": "تهانينا!", "connect_an_existing_yat": "توصيل Yat الحالي", "connect_yats": "توصيل Yats", + "connect_your_hardware_wallet": "قم بتوصيل محفظة الأجهزة الخاصة بك باستخدام Bluetooth أو USB", + "connect_your_hardware_wallet_ios": "قم بتوصيل محفظة الأجهزة الخاصة بك باستخدام Bluetooth", "connection_sync": "الاتصال والمزامنة", "connectWalletPrompt": "ﺕﻼﻣﺎﻌﻤﻟﺍ ءﺍﺮﺟﻹ WalletConnect ﻊﻣ ﻚﺘﻈﻔﺤﻣ ﻞﻴﺻﻮﺘﺑ ﻢﻗ", "contact": "تواصل", @@ -328,7 +331,13 @@ "is_percentage": "يكون", "last_30_days": "آخر 30 يومًا", "learn_more": "اعرف المزيد", + "ledger_connection_error": "فشل في الاتصال بك دفتر الأستاذ. حاول مرة اخرى.", + "ledger_error_device_locked": "تم قفل دفتر الأستاذ", + "ledger_error_tx_rejected_by_user": "تم رفض المعاملة على الجهاز", + "ledger_error_wrong_app": "يرجى التأكد", + "ledger_please_enable_bluetooth": "يرجى تمكين البلوتوث للكشف عن دفتر الأستاذ الخاص بك", "light_theme": "فاتح", + "load_more": "تحميل المزيد", "loading_your_wallet": "يتم تحميل محفظتك", "login": "تسجيل الدخول", "logout": "تسجيل خروج", @@ -442,6 +451,8 @@ "privacy_settings": "إعدادات الخصوصية", "private_key": "مفتاح خاص", "proceed_after_one_minute": "إذا لم تستمر الشاشة بعد دقيقة واحدة ، فتحقق من بريدك الإلكتروني.", + "proceed_on_device": "تابع جهازك", + "proceed_on_device_description": "يرجى اتباع الإرشادات المطلوبة على محفظة الأجهزة الخاصة بك", "profile": "حساب تعريفي", "provider_error": "خطأ ${provider}", "public_key": "مفتاح عمومي", @@ -490,6 +501,7 @@ "restore_bitcoin_description_from_seed": "قم باستعادة محفظتك من كود مكون من 24 كلمة", "restore_bitcoin_title_from_keys": "استعادة من WIF", "restore_description_from_backup": "يمكنك استعادة تطبيق Cake Wallet بالكامل من ملف النسخ الاحتياطي", + "restore_description_from_hardware_wallet": "استعادة من محفظة أجهزة دفتر الأستاذ", "restore_description_from_keys": "قم باستعادة محفظتك من ضغطات المفاتيح المولدة المحفوظة من مفاتيحك الخاصة", "restore_description_from_seed": "قم باستعادة محفظتك من الرمز المكون من 25 كلمة أو 13 كلمة", "restore_description_from_seed_keys": "استرجع محفظتك من السييد / المفاتيح التي قمت بحفظها في مكان آمن", @@ -502,6 +514,7 @@ "restore_seed_keys_restore": "استعادة السييد / المفاتيح", "restore_spend_key_private": "مفتاح الإنفاق (خاص)", "restore_title_from_backup": "استعادة من النسخة الاحتياطية", + "restore_title_from_hardware_wallet": "استعادة من محفظة الأجهزة", "restore_title_from_keys": "استعادة من المفاتيح", "restore_title_from_seed": "استعادة من السييد", "restore_title_from_seed_keys": "استعادة من السييد / المفاتيح", @@ -752,6 +765,7 @@ "unsupported_asset": ".ﻡﻮﻋﺪﻣ ﻞﺻﺃ ﻉﻮﻧ ﻦﻣ ﺔﻈﻔﺤﻣ ﻰﻟﺇ ﻞﻳﺪﺒﺘﻟﺍ ﻭﺃ ءﺎﺸﻧﺇ ﻰﺟﺮﻳ .ﻞﺻﻷﺍ ﺍﺬﻬﻟ ءﺍﺮﺟﻹﺍ ﺍﺬﻫ ﻢﻋﺪﻧ ﻻ ﻦﺤﻧ", "uptime": "مدة التشغيل", "upto": "حتى ${value}", + "usb": "USB", "use": "التبديل إلى", "use_card_info_three": "استخدم البطاقة الرقمية عبر الإنترنت أو مع طرق الدفع غير التلامسية.", "use_card_info_two": "يتم تحويل الأموال إلى الدولار الأمريكي عند الاحتفاظ بها في الحساب المدفوع مسبقًا ، وليس بالعملات الرقمية.", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 4e92cd707..8a7682221 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Лека биткойн тема", "bitcoin_payments_require_1_confirmation": "Плащанията с Bitcoin изискват потвърждение, което може да отнеме 20 минути или повече. Благодарим за търпението! Ще получите имейл, когато плащането е потвърдено.", "Blocks_remaining": "${status} оставащи блока", + "bluetooth": "Bluetooth", "bright_theme": "Ярко", "bump_fee": "Такса за бум", "buy": "Купуване", @@ -144,6 +145,8 @@ "congratulations": "Поздравления!", "connect_an_existing_yat": "Добавете съществуващ Yat", "connect_yats": "Добавете Yats", + "connect_your_hardware_wallet": "Свържете хардуерния си портфейл с помощта на Bluetooth или USB", + "connect_your_hardware_wallet_ios": "Свържете хардуерния си портфейл с помощта на Bluetooth", "connection_sync": "Свързване и синхронизиране", "connectWalletPrompt": "Свържете портфейла си с WalletConnect, за да извършвате транзакции", "contact": "Контакт", @@ -328,7 +331,13 @@ "is_percentage": "е", "last_30_days": "Последните 30 дни", "learn_more": "Научете още", + "ledger_connection_error": "Не успя да се свърже с вашата книга. Моля, опитайте отново.", + "ledger_error_device_locked": "Главната книга е заключена", + "ledger_error_tx_rejected_by_user": "Транзакция, отхвърлена на устройство", + "ledger_error_wrong_app": "Моля, уверете се, че сте отворили правилното приложение на вашата книга", + "ledger_please_enable_bluetooth": "Моля, активирайте Bluetooth да открие вашата книга", "light_theme": "Светло", + "load_more": "Зареди още", "loading_your_wallet": "Зареждане на портфейл", "login": "Влизане", "logout": "Logout", @@ -442,6 +451,8 @@ "privacy_settings": "Настройки за поверителност", "private_key": "Таен ключ", "proceed_after_one_minute": "Ако процесът продължи повече от 1 минута, проверете своя имейл.", + "proceed_on_device": "Продължете на вашето устройство", + "proceed_on_device_description": "Моля, следвайте инструкциите, подканени на вашия хардуер", "profile": "Профил", "provider_error": "Грешка на ${provider} ", "public_key": "Публичен ключ", @@ -490,6 +501,7 @@ "restore_bitcoin_description_from_seed": "Възстановяване на портфейл чрез код от 24 думи", "restore_bitcoin_title_from_keys": "Възстановяване от WIF", "restore_description_from_backup": "Можете да възстановите цялото приложение Cake Wallet от своя резервен файл", + "restore_description_from_hardware_wallet": "Възстановяване от хардуерния портфейл на главната книга", "restore_description_from_keys": "Възстановяване на портфейл от генерираните от Вашите тайни ключове клавиши", "restore_description_from_seed": "Възстановяване на портфейл от кода от 13 или 25 думи", "restore_description_from_seed_keys": "Възстановете своя портфейл от seed/keys, които сте съхранили на сигурно място", @@ -502,6 +514,7 @@ "restore_seed_keys_restore": "Възстановяне от Seed/Keys", "restore_spend_key_private": "Spend key (публичен)", "restore_title_from_backup": "Възстановяване от резервно копие", + "restore_title_from_hardware_wallet": "Възстановяване от хардуерния портфейл", "restore_title_from_keys": "Възстановяване от keys", "restore_title_from_seed": "Възстановяване от seed", "restore_title_from_seed_keys": "Възстановяване от seed/keys", @@ -752,6 +765,7 @@ "unsupported_asset": "Не поддържаме това действие за този актив. Моля, създайте или преминете към портфейл от поддържан тип актив.", "uptime": "Време за работа", "upto": "до ${value}", + "usb": "USB", "use": "Смяна на ", "use_card_info_three": "Използвайте дигиталната карта онлайн или чрез безконтактен метод на плащане.", "use_card_info_two": "Средствата се обръщат в USD, когато биват запазени в предплатената карта, а не в дигитална валута.", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 95fdc2a93..e3bbad5a3 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Světlé téma bitcoinů", "bitcoin_payments_require_1_confirmation": "U plateb Bitcoinem je vyžadováno alespoň 1 potvrzení, což může trvat 20 minut i déle. Děkujeme za vaši trpělivost! Až bude platba potvrzena, budete informováni e-mailem.", "Blocks_remaining": "Zbývá ${status} bloků", + "bluetooth": "Bluetooth", "bright_theme": "Jasný", "bump_fee": "Bump Fee", "buy": "Koupit", @@ -144,6 +145,8 @@ "congratulations": "Gratulujeme!", "connect_an_existing_yat": "Připojit existující Yat", "connect_yats": "Připojit Yaty", + "connect_your_hardware_wallet": "Připojte hardwarovou peněženku pomocí Bluetooth nebo USB", + "connect_your_hardware_wallet_ios": "Připojte hardwarovou peněženku pomocí Bluetooth", "connection_sync": "Připojení a synch.", "connectWalletPrompt": "Propojte svou peněženku s WalletConnect a provádějte transakce", "contact": "Kontakt", @@ -328,7 +331,13 @@ "is_percentage": "je", "last_30_days": "Posledních 30 dnů", "learn_more": "Zjistit více", + "ledger_connection_error": "Nepodařilo se připojit k vaší knize. Prosím zkuste to znovu.", + "ledger_error_device_locked": "Kniha je uzamčena", + "ledger_error_tx_rejected_by_user": "Transakce zamítnuta na zařízení", + "ledger_error_wrong_app": "Ujistěte se, že se na své knize otevřete správnou aplikaci", + "ledger_please_enable_bluetooth": "Umožněte prosím Bluetooth detekovat vaši knihu", "light_theme": "Světlý", + "load_more": "Načíst další", "loading_your_wallet": "Načítám peněženku", "login": "Login", "logout": "Odhlásit", @@ -442,6 +451,8 @@ "privacy_settings": "Nastavení soukromí", "private_key": "Soukromý klíč", "proceed_after_one_minute": "Pokud proces nepokročí během 1 minuty, zkontrolujte svůj e-mail.", + "proceed_on_device": "Pokračujte ve svém zařízení", + "proceed_on_device_description": "Postupujte podle pokynů na výzvu na vaší hardwarové peněžence", "profile": "Profil", "provider_error": "${provider} chyba", "public_key": "Veřejný klíč", @@ -490,6 +501,7 @@ "restore_bitcoin_description_from_seed": "Obnovte svou peněženku pomocí kombinace 24 slov", "restore_bitcoin_title_from_keys": "Obnovit z WIF", "restore_description_from_backup": "Můžete obnovit celou Cake Wallet aplikaci ze souboru se zálohou", + "restore_description_from_hardware_wallet": "Obnovit z peněženky hardwaru knihy", "restore_description_from_keys": "Obnovte svou peněženku pomocí generovaných stisků kláves uložených z vašich soukromých klíčů", "restore_description_from_seed": "Obnovte svou peněženku pomocí kombinace 25, nebo 13 slov", "restore_description_from_seed_keys": "Obnovte svou peněženku ze seedu/klíčů, které jste si uložili na bezpečném místě", @@ -502,6 +514,7 @@ "restore_seed_keys_restore": "Obnovit ze seedu/klíčů", "restore_spend_key_private": "Klíč pro platby (soukromý)", "restore_title_from_backup": "Obnovit ze zálohy", + "restore_title_from_hardware_wallet": "Obnovit z hardwarové peněženky", "restore_title_from_keys": "Obnovit z klíčů", "restore_title_from_seed": "Obnovit ze seedu", "restore_title_from_seed_keys": "Obnovit ze seedu/klíčů", @@ -752,6 +765,7 @@ "unsupported_asset": "Tuto akci u tohoto díla nepodporujeme. Vytvořte nebo přepněte na peněženku podporovaného typu aktiv.", "uptime": "Uptime", "upto": "až ${value}", + "usb": "USB", "use": "Přepnout na ", "use_card_info_three": "Použijte tuto digitální kartu online nebo bezkontaktními platebními metodami.", "use_card_info_two": "Prostředky jsou převedeny na USD, když jsou drženy na předplaceném účtu, nikoliv na digitální měnu.", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index d2731d3e7..ff974f28c 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Bitcoin Light-Thema", "bitcoin_payments_require_1_confirmation": "Bitcoin-Zahlungen erfordern 1 Bestätigung, was 20 Minuten oder länger dauern kann. Danke für Ihre Geduld! Sie erhalten eine E-Mail, wenn die Zahlung bestätigt ist.", "Blocks_remaining": "${status} verbleibende Blöcke", + "bluetooth": "Bluetooth", "bright_theme": "Strahlend hell", "bump_fee": "Beulengebühr", "buy": "Kaufen", @@ -144,6 +145,8 @@ "congratulations": "Glückwunsch!", "connect_an_existing_yat": "Verbinden Sie ein vorhandenes Yat", "connect_yats": "Yats verbinden", + "connect_your_hardware_wallet": "Verbinden Sie Ihre Hardware-Wallet über Bluetooth oder USB", + "connect_your_hardware_wallet_ios": "Verbinden Sie Ihre Hardware-Wallet über Bluetooth", "connection_sync": "Verbindung und Synchronisierung", "connectWalletPrompt": "Verbinden Sie Ihr Wallet mit WalletConnect, um Transaktionen durchzuführen", "contact": "Kontakt", @@ -328,7 +331,13 @@ "is_percentage": "ist", "last_30_days": "Letzte 30 Tage", "learn_more": "Erfahren Sie mehr", + "ledger_connection_error": "Verbindung zum Ledger gescheitert. Bitte versuche es erneut.", + "ledger_error_device_locked": "Der Ledger ist gesperrt", + "ledger_error_tx_rejected_by_user": "Transaktion auf dem Gerät abgelehnt", + "ledger_error_wrong_app": "Bitte stellen Sie sicher, dass Sie die richtige App auf Ihrem Ledger geöffnet haben", + "ledger_please_enable_bluetooth": "Bitte aktivieren Sie Bluetooth um sich mit Ihren Ledger zu verbinden.", "light_theme": "Hell", + "load_more": "Mehr laden", "loading_your_wallet": "Wallet wird geladen", "login": "Einloggen", "logout": "Abmelden", @@ -443,6 +452,8 @@ "privacy_settings": "Datenschutzeinstellungen", "private_key": "Privater Schlüssel", "proceed_after_one_minute": "Wenn der Bildschirm nach 1 Minute nicht weitergeht, überprüfen Sie bitte Ihre E-Mail.", + "proceed_on_device": "Fahren Sie auf Ihrem Gerät fort", + "proceed_on_device_description": "Bitte befolgen Sie die Anweisungen, die auf Ihrer Hardware-Wallet angezeigt werden", "profile": "Profil", "provider_error": "${provider}-Fehler", "public_key": "Öffentlicher Schlüssel", @@ -491,6 +502,7 @@ "restore_bitcoin_description_from_seed": "Stellen Sie Ihre Wallet aus dem 24-Wort-Kombinationscode wieder her", "restore_bitcoin_title_from_keys": "Aus WIF wiederherstellen", "restore_description_from_backup": "Sie können die gesamte Cake Wallet-App aus Ihrer Sicherungsdatei wiederherstellen", + "restore_description_from_hardware_wallet": "Stellen Sie eine Wallet von Ledger wieder her", "restore_description_from_keys": "Stellen Sie Ihr Wallet aus generierten Tastenanschlägen her, die von Ihren privaten Schlüsseln gespeichert wurden", "restore_description_from_seed": "Stellen Sie Ihre Wallet aus den 25 Wörtern oder dem 13-Wort-Kombinationscode wieder her", "restore_description_from_seed_keys": "Stellen Sie Ihr Wallet aus Seed/Schlüsseln wieder her, die Sie sicher aufbewahrt haben", @@ -503,6 +515,7 @@ "restore_seed_keys_restore": "Seed/Schlüssel wiederherstellen", "restore_spend_key_private": "Spend Key (geheim)", "restore_title_from_backup": "Aus einer Sicherungsdatei wiederherstellen", + "restore_title_from_hardware_wallet": "Von Hardware-Wallet wiederherstellen", "restore_title_from_keys": "Aus Schlüsseln wiederherstellen", "restore_title_from_seed": "Aus Seed wiederherstellen", "restore_title_from_seed_keys": "Aus Seed/Schlüssel wiederherstellen", @@ -754,6 +767,7 @@ "unsupported_asset": "Wir unterstützen diese Aktion für dieses Asset nicht. Bitte erstellen Sie eine Wallet eines unterstützten Asset-Typs oder wechseln Sie zu einer Wallet.", "uptime": "Betriebszeit", "upto": "bis zu ${value}", + "usb": "USB", "use": "Wechsel zu ", "use_card_info_three": "Verwenden Sie die digitale Karte online oder mit kontaktlosen Zahlungsmethoden.", "use_card_info_two": "Guthaben werden auf dem Prepaid-Konto in USD umgerechnet, nicht in digitale Währung.", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 8c302d096..241d12415 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Bitcoin Light Theme", "bitcoin_payments_require_1_confirmation": "Bitcoin payments require 1 confirmation, which can take 20 minutes or longer. Thanks for your patience! You will be emailed when the payment is confirmed.", "Blocks_remaining": "${status} Blocks Remaining", + "bluetooth": "Bluetooth", "bright_theme": "Bright", "bump_fee": "Bump fee", "buy": "Buy", @@ -144,6 +145,8 @@ "congratulations": "Congratulations!", "connect_an_existing_yat": "Connect an existing Yat", "connect_yats": "Connect Yats", + "connect_your_hardware_wallet": "Connect your hardware wallet using Bluetooth or USB", + "connect_your_hardware_wallet_ios": "Connect your hardware wallet using Bluetooth", "connection_sync": "Connection and sync", "connectWalletPrompt": "Connect your wallet with WalletConnect to make transactions", "contact": "Contact", @@ -328,7 +331,13 @@ "is_percentage": "is", "last_30_days": "Last 30 days", "learn_more": "Learn More", + "ledger_connection_error": "Failed to connect to you Ledger. Please try again.", + "ledger_error_device_locked": "The Ledger is locked", + "ledger_error_tx_rejected_by_user": "Transaction rejected on device", + "ledger_error_wrong_app": "Please make sure you opend the right app on your ledger", + "ledger_please_enable_bluetooth": "Please enable Bluetooth to detect your Ledger", "light_theme": "Light", + "load_more": "Load more", "loading_your_wallet": "Loading your wallet", "login": "Login", "logout": "Logout", @@ -442,6 +451,8 @@ "privacy_settings": "Privacy settings", "private_key": "Private key", "proceed_after_one_minute": "If the screen doesn’t proceed after 1 minute, check your email.", + "proceed_on_device": "Proceed on your device", + "proceed_on_device_description": "Please follow the instructions prompted on your hardware wallet", "profile": "Profile", "provider_error": "${provider} error", "public_key": "Public key", @@ -490,6 +501,7 @@ "restore_bitcoin_description_from_seed": "Restore your wallet from 24 word combination code", "restore_bitcoin_title_from_keys": "Restore from WIF", "restore_description_from_backup": "You can restore the whole Cake Wallet app from your back-up file", + "restore_description_from_hardware_wallet": "Restore from a Ledger hardware wallet", "restore_description_from_keys": "Restore your wallet from generated keystrokes saved from your private keys", "restore_description_from_seed": "Restore your wallet from either the 25 word or 13 word combination code", "restore_description_from_seed_keys": "Get back your wallet from seed/keys that you've saved to secure place", @@ -502,6 +514,7 @@ "restore_seed_keys_restore": "Seed/Keys Restore", "restore_spend_key_private": "Spend key (private)", "restore_title_from_backup": "Restore from backup", + "restore_title_from_hardware_wallet": "Restore from hardware wallet", "restore_title_from_keys": "Restore from keys", "restore_title_from_seed": "Restore from seed", "restore_title_from_seed_keys": "Restore from seed/keys", @@ -752,6 +765,7 @@ "unsupported_asset": "We don't support this action for this asset. Please create or switch to a wallet of a supported asset type.", "uptime": "Uptime", "upto": "up to ${value}", + "usb": "USB", "use": "Switch to ", "use_card_info_three": "Use the digital card online or with contactless payment methods.", "use_card_info_two": "Funds are converted to USD when they're held in the prepaid account, not in digital currencies.", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 17c4ff681..59c40f67b 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Tema de la luz de Bitcoin", "bitcoin_payments_require_1_confirmation": "Los pagos de Bitcoin requieren 1 confirmación, que puede demorar 20 minutos o más. ¡Gracias por su paciencia! Se le enviará un correo electrónico cuando se confirme el pago.", "Blocks_remaining": "${status} Bloques restantes", + "bluetooth": "Bluetooth", "bright_theme": "Brillante", "bump_fee": "Tarifa", "buy": "Comprar", @@ -144,6 +145,8 @@ "congratulations": "Felicidades!", "connect_an_existing_yat": "Conectar un Yat existente", "connect_yats": "Conectar Yats", + "connect_your_hardware_wallet": "Conecte su billetera de hardware con Bluetooth o USB", + "connect_your_hardware_wallet_ios": "Conecte su billetera de hardware con Bluetooth", "connection_sync": "Conexión y sincronización", "connectWalletPrompt": "Conecte su billetera con WalletConnect para realizar transacciones", "contact": "Contacto", @@ -328,7 +331,13 @@ "is_percentage": "es", "last_30_days": "Últimos 30 días", "learn_more": "Aprende más", + "ledger_connection_error": "No se pudo conectar con su libro mayor. Inténtalo de nuevo.", + "ledger_error_device_locked": "El libro mayor está bloqueado", + "ledger_error_tx_rejected_by_user": "Transacción rechazada en el dispositivo", + "ledger_error_wrong_app": "Por favor, asegúrese de abrir la aplicación correcta en su libro mayor.", + "ledger_please_enable_bluetooth": "Habilite Bluetooth para detectar su libro mayor", "light_theme": "Ligera", + "load_more": "Carga más", "loading_your_wallet": "Cargando tu billetera", "login": "Iniciar sesión", "logout": "Cerrar sesión", @@ -443,6 +452,8 @@ "privacy_settings": "Configuración de privacidad", "private_key": "Clave privada", "proceed_after_one_minute": "Si la pantalla no continúa después de 1 minuto, revisa tu correo electrónico.", + "proceed_on_device": "Continúe con su dispositivo", + "proceed_on_device_description": "Siga las instrucciones solicitadas en su billetera de hardware", "profile": "Perfil", "provider_error": "${provider} error", "public_key": "Clave pública", @@ -491,6 +502,7 @@ "restore_bitcoin_description_from_seed": "Restaure su billetera a partir del código de combinación de 24 palabras", "restore_bitcoin_title_from_keys": "Restaurar desde WIF", "restore_description_from_backup": "Puede restaurar toda la aplicación Cake Wallet desde ysu archivo de respaldo", + "restore_description_from_hardware_wallet": "Restaurar desde una billetera de hardware Ledger", "restore_description_from_keys": "Restaure su billetera de las pulsaciones de teclas generadas guardadas de sus claves privadas", "restore_description_from_seed": "Restaure su billetera desde el código de combinación de 25 palabras i de 13 palabras", "restore_description_from_seed_keys": "Recupere su billetera de las semillas/claves que ha guardado en un lugar seguro", @@ -503,6 +515,7 @@ "restore_seed_keys_restore": "Restauración de semillas / llaves", "restore_spend_key_private": "Spend clave (privado)", "restore_title_from_backup": "Restaurar desde un archivo de respaldo", + "restore_title_from_hardware_wallet": "Restaurar desde la billetera de hardware", "restore_title_from_keys": "De las claves", "restore_title_from_seed": "De la semilla", "restore_title_from_seed_keys": "Restaurar desde semilla/claves", @@ -753,6 +766,7 @@ "unsupported_asset": "No admitimos esta acción para este activo. Cree o cambie a una billetera de un tipo de activo admitido.", "uptime": "Tiempo de actividad", "upto": "hasta ${value}", + "usb": "USB", "use": "Utilizar a ", "use_card_info_three": "Utilice la tarjeta digital en línea o con métodos de pago sin contacto.", "use_card_info_two": "Los fondos se convierten a USD cuando se mantienen en la cuenta prepaga, no en monedas digitales.", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 12716ab33..08b6d54b0 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Thème léger Bitcoin", "bitcoin_payments_require_1_confirmation": "Les paiements Bitcoin nécessitent 1 confirmation, ce qui peut prendre 20 minutes ou plus. Merci pour votre patience ! Vous serez averti par e-mail lorsque le paiement sera confirmé.", "Blocks_remaining": "Blocs Restants : ${status}", + "bluetooth": "Bluetooth", "bright_theme": "Vif", "bump_fee": "Frais de bosse", "buy": "Acheter", @@ -144,6 +145,8 @@ "congratulations": "Félicitations !", "connect_an_existing_yat": "Connecter un Yat existant", "connect_yats": "Connecter Yats", + "connect_your_hardware_wallet": "Connectez votre portefeuille matériel à l'aide de Bluetooth ou USB", + "connect_your_hardware_wallet_ios": "Connectez votre portefeuille matériel à l'aide de Bluetooth", "connection_sync": "Connexion et synchronisation", "connectWalletPrompt": "Connectez votre portefeuille (wallet) avec WalletConnect pour effectuer des transactions", "contact": "Contact", @@ -328,7 +331,13 @@ "is_percentage": "est", "last_30_days": "30 derniers jours", "learn_more": "En savoir plus", + "ledger_connection_error": "Impossible de se connecter à votre grand livre. Veuillez réessayer.", + "ledger_error_device_locked": "Le grand livre est verrouillé", + "ledger_error_tx_rejected_by_user": "Transaction rejetée sur l'appareil", + "ledger_error_wrong_app": "Veuillez vous assurer d'ouvrir la bonne application sur votre grand livre", + "ledger_please_enable_bluetooth": "Veuillez activer Bluetooth pour détecter votre grand livre", "light_theme": "Clair", + "load_more": "Charger plus", "loading_your_wallet": "Chargement de votre portefeuille (wallet)", "login": "Utilisateur", "logout": "Déconnexion", @@ -442,6 +451,8 @@ "privacy_settings": "Paramètres de confidentialité", "private_key": "Clef privée", "proceed_after_one_minute": "Si l'écran ne s'affiche pas après 1 minute, vérifiez vos e-mails.", + "proceed_on_device": "Continuez sur votre appareil", + "proceed_on_device_description": "Veuillez suivre les instructions invitées sur votre portefeuille matériel", "profile": "Profil", "provider_error": "Erreur de ${provider}", "public_key": "Clef publique", @@ -490,6 +501,7 @@ "restore_bitcoin_description_from_seed": "Restaurer votre portefeuille (wallet) à l'aide d'une phrase secrète (seed) de 24 mots", "restore_bitcoin_title_from_keys": "Restaurer depuis la chaîne WIF", "restore_description_from_backup": "Vous pouvez restaurer l'intégralité de l'application Cake Wallet depuis un fichier de sauvegarde", + "restore_description_from_hardware_wallet": "Restaurer à partir d'un portefeuille matériel de grand livre", "restore_description_from_keys": "Restaurer votre portefeuille (wallet) d'après les séquences de touches générées d'après vos clefs privées", "restore_description_from_seed": "Restaurer votre portefeuille (wallet) depuis une phrase secrète (seed) de 25 ou 13 mots", "restore_description_from_seed_keys": "Restaurez votre portefeuille (wallet) depuis une phrase secrète (seed) ou des clefs que vous avez stockées en lieu sûr", @@ -502,6 +514,7 @@ "restore_seed_keys_restore": "Restaurer depuis Phrase secrète (seed)/Clefs", "restore_spend_key_private": "Clef de dépense (spend key) (privée)", "restore_title_from_backup": "Restaurer depuis une sauvegarde", + "restore_title_from_hardware_wallet": "Restaurer à partir du portefeuille matériel", "restore_title_from_keys": "Restaurer depuis des clefs", "restore_title_from_seed": "Restaurer depuis une phrase secrète (seed)", "restore_title_from_seed_keys": "Restaurer depuis une phrase secrète (seed) ou des clefs", @@ -752,6 +765,7 @@ "unsupported_asset": "Nous ne prenons pas en charge cette action pour cet élément. Veuillez créer ou passer à un portefeuille d'un type d'actif pris en charge.", "uptime": "Durée de la baisse", "upto": "jusqu'à ${value}", + "usb": "USB", "use": "Changer vers code PIN à ", "use_card_info_three": "Utilisez la carte numérique en ligne ou avec des méthodes de paiement sans contact.", "use_card_info_two": "Les fonds sont convertis en USD lorsqu'ils sont détenus sur le compte prépayé, et non en devises numériques.", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 29754cf72..94c030a21 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Jigon Hasken Bitcoin", "bitcoin_payments_require_1_confirmation": "Akwatin Bitcoin na buɗe 1 sambumbu, da yake za ta samu mintuna 20 ko yawa. Ina kira ga sabuwar lafiya! Zaka sanarwa ta email lokacin da aka samu akwatin samun lambar waya.", "Blocks_remaining": "${status} Katanga ya rage", + "bluetooth": "Bluetooth", "bright_theme": "Mai haske", "bump_fee": "Buin", "buy": "Sayi", @@ -144,6 +145,8 @@ "congratulations": "Taya murna!", "connect_an_existing_yat": "Haɗa Yat da ke akwai", "connect_yats": "Haɗa Yats", + "connect_your_hardware_wallet": "Haɗa Wallake Wallware ɗinku ta Bluetooth ko USB", + "connect_your_hardware_wallet_ios": "Haɗa kayan aikinku ta Bluetooth", "connection_sync": "Haɗi da daidaitawa", "connectWalletPrompt": "Haɗa walat ɗin ku tare da WalletConnect don yin ma'amala", "contact": "Tuntuɓar", @@ -328,7 +331,13 @@ "is_percentage": "shine", "last_30_days": "Kwanaki 30 na ƙarshe", "learn_more": "Ƙara Koyi", + "ledger_connection_error": "Ba a yi nasarar haɗawa da ku ba. Da fatan za a sake gwadawa.", + "ledger_error_device_locked": "An kulle Ledger", + "ledger_error_tx_rejected_by_user": "Ma'amala da aka ƙi akan na'urar", + "ledger_error_wrong_app": "Da fatan za a tabbata kun yi amfani da app ɗin dama akan dillalarku", + "ledger_please_enable_bluetooth": "Da fatan za a kunna Bluetooth don gano Ledger ɗinku", "light_theme": "Haske", + "load_more": "Like more", "loading_your_wallet": "Ana loda walat ɗin ku", "login": "Shiga", "logout": "Fita", @@ -444,6 +453,8 @@ "privacy_settings": "Saitunan sirri", "private_key": "Keɓaɓɓen maɓalli", "proceed_after_one_minute": "Idan allon bai ci gaba ba bayan minti 1, duba imel ɗin ku.", + "proceed_on_device": "Ci gaba akan na'urarka", + "proceed_on_device_description": "Da fatan za a bi umarnin akan walatware", "profile": "Rabin fuska", "provider_error": "${provider} kuskure", "public_key": "Maɓallin jama'a", @@ -492,6 +503,7 @@ "restore_bitcoin_description_from_seed": "Dawo da kwalinku daga 24 lambar haɗin kalma", "restore_bitcoin_title_from_keys": "Dawo daga WIF", "restore_description_from_backup": "Kuna iya dawo da duk aikace-aikacen Wallet ɗin Cake daga fayil ɗin ajiyar ku", + "restore_description_from_hardware_wallet": "Maidowa da walatware mai wanki", "restore_description_from_keys": "Maido da walat ɗin ku daga maɓallan maɓalli da aka ƙera da aka ajiye daga maɓallan ku na sirri", "restore_description_from_seed": "Dawo da kwalinku daga 25 ko 13 lambar haɗin kalma", "restore_description_from_seed_keys": "Maido da walat ɗin ku daga iri/maɓallan da kuka adana don amintaccen wuri", @@ -504,6 +516,7 @@ "restore_seed_keys_restore": "Mayar da iri/Maɓallai", "restore_spend_key_private": "Maɓallin kashewa (key kalmar sirri)", "restore_title_from_backup": "Dawo daga madadin", + "restore_title_from_hardware_wallet": "Dawowa daga walatware mai wuya", "restore_title_from_keys": "Dawo daga maɓallai", "restore_title_from_seed": "Maidowa daga iri", "restore_title_from_seed_keys": "Dawo da iri/maɓallai", @@ -754,6 +767,7 @@ "unsupported_asset": "Ba mu goyi bayan wannan aikin don wannan kadara. Da fatan za a ƙirƙira ko canza zuwa walat na nau'in kadara mai tallafi.", "uptime": "Sama", "upto": "har zuwa ${value}", + "usb": "Alib", "use": "Canja zuwa", "use_card_info_three": "Yi amfani da katin dijital akan layi ko tare da hanyoyin biyan kuɗi mara lamba.", "use_card_info_two": "Ana canza kuɗi zuwa dalar Amurka lokacin da ake riƙe su a cikin asusun da aka riga aka biya, ba cikin agogon dijital ba.", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 278adde0f..4279e0bee 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "बिटकॉइन लाइट थीम", "bitcoin_payments_require_1_confirmation": "बिटकॉइन भुगतान के लिए 1 पुष्टिकरण की आवश्यकता होती है, जिसमें 20 मिनट या अधिक समय लग सकता है। आपके धैर्य के लिए धन्यवाद! भुगतान की पुष्टि होने पर आपको ईमेल किया जाएगा।", "Blocks_remaining": "${status} शेष रहते हैं", + "bluetooth": "ब्लूटूथ", "bright_theme": "उज्ज्वल", "bump_fee": "बम्प फीस", "buy": "खरीदें", @@ -144,6 +145,8 @@ "congratulations": "बधाई!", "connect_an_existing_yat": "मौजूदा Yat कनेक्ट करें", "connect_yats": "कनेक्ट Yats", + "connect_your_hardware_wallet": "ब्लूटूथ या यूएसबी का उपयोग करके अपने हार्डवेयर वॉलेट को कनेक्ट करें", + "connect_your_hardware_wallet_ios": "ब्लूटूथ का उपयोग करके अपने हार्डवेयर वॉलेट को कनेक्ट करें", "connection_sync": "कनेक्शन और सिंक", "connectWalletPrompt": "लेन-देन करने के लिए अपने वॉलेट को वॉलेटकनेक्ट से कनेक्ट करें", "contact": "संपर्क करें", @@ -328,7 +331,13 @@ "is_percentage": "है", "last_30_days": "पिछले 30 दिन", "learn_more": "और अधिक जानें", + "ledger_connection_error": "आप लेजर से जुड़ने में विफल रहे। कृपया पुन: प्रयास करें।", + "ledger_error_device_locked": "खाता बंद है", + "ledger_error_tx_rejected_by_user": "डिवाइस पर लेनदेन खारिज कर दिया गया", + "ledger_error_wrong_app": "कृपया सुनिश्चित करें कि आप अपने लेजर पर सही ऐप को खोलते हैं", + "ledger_please_enable_bluetooth": "कृपया अपने बहीखाने का पता लगाने के लिए ब्लूटूथ को सक्षम करें", "light_theme": "रोशनी", + "load_more": "और लोड करें", "loading_your_wallet": "अपना बटुआ लोड कर रहा है", "login": "लॉग इन करें", "logout": "लॉगआउट", @@ -443,6 +452,8 @@ "privacy_settings": "गोपनीयता सेटिंग्स", "private_key": "निजी चाबी", "proceed_after_one_minute": "यदि 1 मिनट के बाद भी स्क्रीन आगे नहीं बढ़ती है, तो अपना ईमेल देखें।", + "proceed_on_device": "अपने डिवाइस पर आगे बढ़ें", + "proceed_on_device_description": "कृपया अपने हार्डवेयर वॉलेट पर दिए गए निर्देशों का पालन करें", "profile": "प्रोफ़ाइल", "provider_error": "${provider} त्रुटि", "public_key": "सार्वजनिक कुंजी", @@ -492,6 +503,7 @@ "restore_bitcoin_description_from_seed": "24 शब्द संयोजन कोड से अपने वॉलेट को पुनर्स्थापित करें", "restore_bitcoin_title_from_keys": "WIF से पुनर्स्थापित करें", "restore_description_from_backup": "आप से पूरे केक वॉलेट एप्लिकेशन को पुनर्स्थापित कर सकते हैं आपकी बैक-अप फ़ाइल", + "restore_description_from_hardware_wallet": "एक लेजर हार्डवेयर वॉलेट से पुनर्स्थापित करें", "restore_description_from_keys": "अपने वॉलेट को जेनरेट से पुनर्स्थापित करें आपकी निजी कुंजी से कीस्ट्रोक्स सहेजे गए", "restore_description_from_seed": "या तो 25 शब्द से अपने वॉलेट को पुनर्स्थापित करें या 13 शब्द संयोजन कोड", "restore_description_from_seed_keys": "अपने बटुए को बीज से वापस लें/वे कुंजियाँ जिन्हें आपने सुरक्षित स्थान पर सहेजा है", @@ -504,6 +516,7 @@ "restore_seed_keys_restore": "बीज / कुंजी पुनर्स्थापित करें", "restore_spend_key_private": "कुंजी खर्च करें (निजीe)", "restore_title_from_backup": "बैक-अप फ़ाइल से पुनर्स्थापित करें", + "restore_title_from_hardware_wallet": "हार्डवेयर वॉलेट से पुनर्स्थापित करें", "restore_title_from_keys": "कुंजी से पुनर्स्थापित करें", "restore_title_from_seed": "बीज से पुनर्स्थापित करें", "restore_title_from_seed_keys": "बीज / कुंजियों से पुनर्स्थापित करें", @@ -754,6 +767,7 @@ "unsupported_asset": "हम इस संपत्ति के लिए इस कार्रवाई का समर्थन नहीं करते हैं. कृपया समर्थित परिसंपत्ति प्रकार का वॉलेट बनाएं या उस पर स्विच करें।", "uptime": "अपटाइम", "upto": "${value} तक", + "usb": "USB", "use": "उपयोग ", "use_card_info_three": "डिजिटल कार्ड का ऑनलाइन या संपर्क रहित भुगतान विधियों के साथ उपयोग करें।", "use_card_info_two": "डिजिटल मुद्राओं में नहीं, प्रीपेड खाते में रखे जाने पर निधियों को यूएसडी में बदल दिया जाता है।", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 7940b1add..106243e51 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Bitcoin Light Theme", "bitcoin_payments_require_1_confirmation": "Bitcoin plaćanja zahtijevaju 1 potvrdu, što može potrajati 20 minuta ili dulje. Hvala na Vašem strpljenju! Dobit ćete e-poruku kada plaćanje bude potvrđeno.", "Blocks_remaining": "${status} preostalih blokova", + "bluetooth": "Bluetooth", "bright_theme": "Jarka", "bump_fee": "Naplata", "buy": "Kupi", @@ -144,6 +145,8 @@ "congratulations": "Čestitamo!", "connect_an_existing_yat": "Povežite postojeći Yat", "connect_yats": "Povežite Yats", + "connect_your_hardware_wallet": "Spojite svoj hardverski novčanik pomoću Bluetooth -a ili USB -a", + "connect_your_hardware_wallet_ios": "Spojite svoj hardverski novčanik pomoću Bluetooth -a", "connection_sync": "Povezivanje i sinkronizacija", "connectWalletPrompt": "Povežite svoj novčanik s WalletConnectom za obavljanje transakcija", "contact": "Kontakt", @@ -328,7 +331,13 @@ "is_percentage": "je", "last_30_days": "Zadnjih 30 dana", "learn_more": "Saznajte više", + "ledger_connection_error": "Nije uspio povezati se s knjigom. Molim te pokušaj ponovno.", + "ledger_error_device_locked": "Knjiga je zaključana", + "ledger_error_tx_rejected_by_user": "Transakcija odbijena na uređaju", + "ledger_error_wrong_app": "Obavezno obavezno otvorite pravu aplikaciju na knjizi", + "ledger_please_enable_bluetooth": "Omogućite Bluetooth da otkrije svoju knjigu", "light_theme": "Svijetla", + "load_more": "Učitaj više", "loading_your_wallet": "Novčanik se učitava", "login": "Prijava", "logout": "Odjava", @@ -442,6 +451,8 @@ "privacy_settings": "Postavke privatnosti", "private_key": "Privatni ključ", "proceed_after_one_minute": "Ako se zaslon ne nastavi nakon 1 minute, provjerite svoju e-poštu.", + "proceed_on_device": "Nastavite na svom uređaju", + "proceed_on_device_description": "Slijedite upute zatražene na vašem hardverskom novčaniku", "profile": "Profil", "provider_error": "${provider} greška", "public_key": "Javni ključ", @@ -490,6 +501,7 @@ "restore_bitcoin_description_from_seed": "Oporavi novčanik pomoću koda od 12 riječi", "restore_bitcoin_title_from_keys": "Oporavi pomoću formata uvoza novčanika (WIF)", "restore_description_from_backup": "Možete oporaviti cijelu Cake Wallet aplikaciju pomoću vlastite datoteke sa sigurnosnom kopijom", + "restore_description_from_hardware_wallet": "Vratite se iz novčanice od knjige", "restore_description_from_keys": "Oporavi novčanik pomoću generiranih pritisaka na tipke spremljenih od vlastitih privatnih ključeva (keys)", "restore_description_from_seed": "Oporavi novčanik pomoću koda koji sadrži kombinaciju od 25 ili 13 riječi", "restore_description_from_seed_keys": "Oporavi novčanik pomoću pristupnog izraza/ključa spremljenog na sigurno mjesto", @@ -502,6 +514,7 @@ "restore_seed_keys_restore": "Oporavak pomoću pristupnog izraza/ključa", "restore_spend_key_private": "Spend key (privatni)", "restore_title_from_backup": "Oporavak pomoću sigurnosne kopije", + "restore_title_from_hardware_wallet": "Vrati iz hardverskog novčanika", "restore_title_from_keys": "Oporavi pomoću ključa", "restore_title_from_seed": "Oporavi pomoću pristupnog izraza", "restore_title_from_seed_keys": "Oporavi pomoću pristupnog izraza/ključa", @@ -752,6 +765,7 @@ "unsupported_asset": "Ne podržavamo ovu radnju za ovaj materijal. Izradite ili prijeđite na novčanik podržane vrste sredstava.", "uptime": "Radno vrijeme", "upto": "do ${value}", + "usb": "USB", "use": "Prebaci na", "use_card_info_three": "Koristite digitalnu karticu online ili s beskontaktnim metodama plaćanja.", "use_card_info_two": "Sredstva se pretvaraju u USD kada se drže na prepaid računu, a ne u digitalnim valutama.", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 8177afdc2..01c36da93 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Tema Cahaya Bitcoin", "bitcoin_payments_require_1_confirmation": "Pembayaran Bitcoin memerlukan 1 konfirmasi, yang bisa memakan waktu 20 menit atau lebih. Terima kasih atas kesabaran Anda! Anda akan diemail saat pembayaran dikonfirmasi.", "Blocks_remaining": "${status} Blok Tersisa", + "bluetooth": "Bluetooth", "bright_theme": "Cerah", "bump_fee": "Biaya benjolan", "buy": "Beli", @@ -144,6 +145,8 @@ "congratulations": "Selamat!", "connect_an_existing_yat": "Hubungkan Yat yang ada", "connect_yats": "Hubungkan Yats", + "connect_your_hardware_wallet": "Hubungkan dompet perangkat keras Anda menggunakan Bluetooth atau USB", + "connect_your_hardware_wallet_ios": "Hubungkan dompet perangkat keras Anda menggunakan Bluetooth", "connection_sync": "Koneksi dan sinkronisasi", "connectWalletPrompt": "Hubungkan dompet Anda dengan WalletConnect untuk melakukan transaksi", "contact": "Kontak", @@ -328,7 +331,13 @@ "is_percentage": "adalah", "last_30_days": "30 hari terakhir", "learn_more": "Pelajari Lebih Lanjut", + "ledger_connection_error": "Gagal terhubung ke buku besar Anda. Tolong coba lagi.", + "ledger_error_device_locked": "Ledger terkunci", + "ledger_error_tx_rejected_by_user": "Transaksi ditolak pada perangkat", + "ledger_error_wrong_app": "Pastikan Anda membuka aplikasi yang tepat di buku besar Anda", + "ledger_please_enable_bluetooth": "Harap aktifkan Bluetooth untuk mendeteksi buku besar Anda", "light_theme": "Terang", + "load_more": "Muat lebih banyak", "loading_your_wallet": "Memuat dompet Anda", "login": "Masuk", "logout": "Keluar", @@ -444,6 +453,8 @@ "privacy_settings": "Pengaturan privasi", "private_key": "Kunci privat", "proceed_after_one_minute": "Jika layar tidak bergerak setelah 1 menit, periksa email Anda.", + "proceed_on_device": "Lanjutkan di perangkat Anda", + "proceed_on_device_description": "Harap ikuti instruksi yang diminta di dompet perangkat keras Anda", "profile": "Profil", "provider_error": "${provider} error", "public_key": "Kunci publik", @@ -492,6 +503,7 @@ "restore_bitcoin_description_from_seed": "Pulihkan dompet Anda dari kombinasi kode 24 kata", "restore_bitcoin_title_from_keys": "Pulihkan dari WIF", "restore_description_from_backup": "Anda dapat memulihkan seluruh aplikasi Cake Wallet dari file cadangan Anda", + "restore_description_from_hardware_wallet": "Kembalikan dari dompet perangkat keras Ledger", "restore_description_from_keys": "Pulihkan dompet Anda dari tombol yang dihasilkan yang disimpan dari kunci pribadi Anda", "restore_description_from_seed": "Pulihkan dompet Anda dari kombinasi kode 25 atau 13 kata", "restore_description_from_seed_keys": "Dapatkan kembali dompet Anda dari seed/kunci yang Anda simpan di tempat yang aman", @@ -505,6 +517,7 @@ "restore_seed_keys_restore": "Pulihkan Seed/Kunci", "restore_spend_key_private": "Habiskan kunci (pribadi)", "restore_title_from_backup": "Pulihkan dari cadangan", + "restore_title_from_hardware_wallet": "Kembalikan dari dompet perangkat keras", "restore_title_from_keys": "Pulihkan dari kunci", "restore_title_from_seed": "Pulihkan dari seed", "restore_title_from_seed_keys": "Pulihkan dari seed/kunci", @@ -755,6 +768,7 @@ "unsupported_asset": "Kami tidak mendukung tindakan ini untuk aset ini. Harap buat atau alihkan ke dompet dari jenis aset yang didukung.", "uptime": "Uptime", "upto": "hingga ${value}", + "usb": "USB", "use": "Beralih ke ", "use_card_info_three": "Gunakan kartu digital secara online atau dengan metode pembayaran tanpa kontak.", "use_card_info_two": "Dana dikonversi ke USD ketika disimpan dalam akun pra-bayar, bukan dalam mata uang digital.", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 4cc08f9b1..61a3fa2cf 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Tema luce Bitcoin", "bitcoin_payments_require_1_confirmation": "I pagamenti in bitcoin richiedono 1 conferma, che può richiedere 20 minuti o più. Grazie per la vostra pazienza! Riceverai un'e-mail quando il pagamento sarà confermato.", "Blocks_remaining": "${status} Blocchi Rimanenti", + "bluetooth": "Bluetooth", "bright_theme": "Colorato", "bump_fee": "Commissione per bump", "buy": "Comprare", @@ -145,6 +146,8 @@ "congratulations": "Congratulazioni!", "connect_an_existing_yat": "Collegare un Yat esistente", "connect_yats": "Connetti Yats", + "connect_your_hardware_wallet": "Collega il tuo portafoglio hardware con Bluetooth o USB", + "connect_your_hardware_wallet_ios": "Collega il tuo portafoglio hardware con Bluetooth", "connection_sync": "Connessione e sincronizzazione", "connectWalletPrompt": "Collega il tuo portafoglio con WalletConnect per effettuare transazioni", "contact": "Contatta", @@ -329,7 +332,13 @@ "is_percentage": "è", "last_30_days": "Ultimi 30 giorni", "learn_more": "Impara di più", + "ledger_connection_error": "Impossibile connettersi al libro mastro. Per favore riprova.", + "ledger_error_device_locked": "Il libro mastro è bloccato", + "ledger_error_tx_rejected_by_user": "Transazione rifiutata sul dispositivo", + "ledger_error_wrong_app": "Assicurati di aprire l'app giusta sul libro mastro", + "ledger_please_enable_bluetooth": "Si prega di consentire al Bluetooth di rilevare il libro mastro", "light_theme": "Bianco", + "load_more": "Carica di più", "loading_your_wallet": "Caricamento portafoglio", "login": "Accedi", "logout": "Logout", @@ -444,6 +453,8 @@ "privacy_settings": "Impostazioni privacy", "private_key": "Chiave privata", "proceed_after_one_minute": "Se lo schermo non procede dopo 1 minuto, controlla la tua email.", + "proceed_on_device": "Procedi sul tuo dispositivo", + "proceed_on_device_description": "Segui le istruzioni richieste sul portafoglio hardware", "profile": "Profilo", "provider_error": "${provider} errore", "public_key": "Chiave pubblica", @@ -492,6 +503,7 @@ "restore_bitcoin_description_from_seed": "Recupera il tuo portafoglio da una combinazione di 12 parole", "restore_bitcoin_title_from_keys": "Recupera da WIF", "restore_description_from_backup": "Puoi recuperare l'app Cake Wallet per intero dal tuo file di backup", + "restore_description_from_hardware_wallet": "Ripristina da un portafoglio hardware di libro mastro", "restore_description_from_keys": "Recupera il tuo portafoglio da una sequenza di caratteri generati dalle tue chiavi private", "restore_description_from_seed": "Recupera il tuo portafoglio da una combinazione di 25 o 13 parole", "restore_description_from_seed_keys": "Recupera il tuo portafoglio dal seme/chiavi che hai salvato in un posto sicuro", @@ -504,6 +516,7 @@ "restore_seed_keys_restore": "Recupera Seme/Chiavi", "restore_spend_key_private": "Chiave di Spesa (privata)", "restore_title_from_backup": "Recupera da backup", + "restore_title_from_hardware_wallet": "Ripristina dal portafoglio hardware", "restore_title_from_keys": "Recupera dalle chiavi", "restore_title_from_seed": "Recupera dal seme", "restore_title_from_seed_keys": "Recupera dal seme/chiavi", @@ -754,6 +767,7 @@ "unsupported_asset": "Non supportiamo questa azione per questa risorsa. Crea o passa a un portafoglio di un tipo di asset supportato.", "uptime": "Uptime", "upto": "fino a ${value}", + "usb": "USB", "use": "Passa a ", "use_card_info_three": "Utilizza la carta digitale online o con metodi di pagamento contactless.", "use_card_info_two": "I fondi vengono convertiti in USD quando sono detenuti nel conto prepagato, non in valute digitali.", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index a72bbb0e4..db92a2f92 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "ビットコインライトテーマ", "bitcoin_payments_require_1_confirmation": "ビットコインの支払いには 1 回の確認が必要で、これには 20 分以上かかる場合があります。お待ち頂きまして、ありがとうございます!支払いが確認されると、メールが送信されます。", "Blocks_remaining": "${status} 残りのブロック", + "bluetooth": "ブルートゥース", "bright_theme": "明るい", "bump_fee": "バンプ料金", "buy": "購入", @@ -144,6 +145,8 @@ "congratulations": "おめでとうございます!", "connect_an_existing_yat": "既存のYatを接続します", "connect_yats": "Yatsを接続します", + "connect_your_hardware_wallet": "BluetoothまたはUSBを使用して、ハードウェアウォレットを接続します", + "connect_your_hardware_wallet_ios": "Bluetoothを使用してハードウェアウォレットを接続します", "connection_sync": "接続と同期", "connectWalletPrompt": "ウォレットを WalletConnect に接続して取引を行う", "contact": "接触", @@ -329,7 +332,13 @@ "is_percentage": "is", "last_30_days": "過去30日", "learn_more": "もっと詳しく知る", + "ledger_connection_error": "元帳に接続できませんでした。もう一度やり直してください。", + "ledger_error_device_locked": "元帳がロックされています", + "ledger_error_tx_rejected_by_user": "トランザクションはデバイスで拒否されました", + "ledger_error_wrong_app": "元帳に適切なアプリを開始するようにしてください", + "ledger_please_enable_bluetooth": "Bluetoothが元帳を検出できるようにしてください", "light_theme": "光", + "load_more": "もっと読み込む", "loading_your_wallet": "ウォレットをロードしています", "login": "ログイン", "logout": "ログアウト", @@ -443,6 +452,8 @@ "privacy_settings": "プライバシー設定", "private_key": "秘密鍵", "proceed_after_one_minute": "1分経っても画面が進まない場合は、メールを確認してください。", + "proceed_on_device": "デバイスに進みます", + "proceed_on_device_description": "ハードウェアウォレットにプロンプ​​トされた指示に従ってください", "profile": "プロフィール", "provider_error": "${provider} エラー", "public_key": "公開鍵", @@ -491,6 +502,7 @@ "restore_bitcoin_description_from_seed": "24ワードの組み合わせコードからウォレットを復元する", "restore_bitcoin_title_from_keys": "WIFから復元", "restore_description_from_backup": "Cake Walletアプリ全体を復元できますバックアップファイル", + "restore_description_from_hardware_wallet": "元帳ハードウェアウォレットから復元します", "restore_description_from_keys": "生成されたウォレットを復元します秘密鍵から保存されたキーストローク", "restore_description_from_seed": "25ワードからウォレットを復元しますまたは13ワードの組み合わせコード", "restore_description_from_seed_keys": "安全な場所に保存したシード/キーから財布を取り戻す", @@ -503,6 +515,7 @@ "restore_seed_keys_restore": "シード/キーの復元", "restore_spend_key_private": "キーを使う (プライベート)", "restore_title_from_backup": "バックアップファイルから復元する", + "restore_title_from_hardware_wallet": "ハードウェアウォレットから復元します", "restore_title_from_keys": "キーから復元する", "restore_title_from_seed": "シードから復元", "restore_title_from_seed_keys": "シード/キーから復元", @@ -753,6 +766,7 @@ "unsupported_asset": "このアセットに対するこのアクションはサポートされていません。サポートされているアセットタイプのウォレットを作成するか、ウォレットに切り替えてください。", "uptime": "稼働時間", "upto": "up up ${value}", + "usb": "USB", "use": "使用する ", "use_card_info_three": "デジタルカードをオンラインまたは非接触型決済方法で使用してください。", "use_card_info_two": "デジタル通貨ではなく、プリペイドアカウントで保持されている場合、資金は米ドルに変換されます。", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index b80494e80..fc84d7c35 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "비트코인 라이트 테마", "bitcoin_payments_require_1_confirmation": "비트코인 결제는 1번의 확인이 필요하며 20분 이상이 소요될 수 있습니다. 기다려 주셔서 감사합니다! 결제가 확인되면 이메일이 전송됩니다.", "Blocks_remaining": "${status} 남은 블록", + "bluetooth": "블루투스", "bright_theme": "선명한", "bump_fee": "범프 요금", "buy": "구입", @@ -144,6 +145,8 @@ "congratulations": "축하합니다!", "connect_an_existing_yat": "기존 Yat 연결", "connect_yats": "야츠 연결", + "connect_your_hardware_wallet": "Bluetooth 또는 USB를 사용하여 하드웨어 지갑을 연결하십시오", + "connect_your_hardware_wallet_ios": "Bluetooth를 사용하여 하드웨어 지갑을 연결하십시오", "connection_sync": "연결 및 동기화", "connectWalletPrompt": "거래를 하려면 WalletConnect에 지갑을 연결하세요.", "contact": "접촉", @@ -328,7 +331,13 @@ "is_percentage": "이다", "last_30_days": "지난 30일", "learn_more": "더 알아보기", + "ledger_connection_error": "원장에 연결하지 못했습니다. 다시 시도하십시오.", + "ledger_error_device_locked": "원장이 잠겨 있습니다", + "ledger_error_tx_rejected_by_user": "장치에서 거래가 거부되었습니다", + "ledger_error_wrong_app": "원장에서 올바른 앱을 반대하는지 확인하십시오.", + "ledger_please_enable_bluetooth": "Bluetooth가 원장을 감지 할 수 있도록하십시오", "light_theme": "빛", + "load_more": "더로드하십시오", "loading_your_wallet": "지갑 넣기", "login": "로그인", "logout": "로그아웃", @@ -443,6 +452,8 @@ "privacy_settings": "개인정보 설정", "private_key": "개인 키", "proceed_after_one_minute": "1분 후에도 화면이 진행되지 않으면 이메일을 확인하세요.", + "proceed_on_device": "장치를 진행하십시오", + "proceed_on_device_description": "하드웨어 지갑에 표시된 지침을 따르십시오", "profile": "프로필", "provider_error": "${provider} 오류", "public_key": "공개 키", @@ -491,6 +502,7 @@ "restore_bitcoin_description_from_seed": "24 단어 조합 코드에서 지갑 복원", "restore_bitcoin_title_from_keys": "WIF에서 복원", "restore_description_from_backup": "백업 파일에서 전체 Cake Wallet 앱을 복원 할 수 있습니다.", + "restore_description_from_hardware_wallet": "원장 하드웨어 지갑에서 복원하십시오", "restore_description_from_keys": "개인 키에서 저장된 생성 된 키 스트로크에서 월렛 복원", "restore_description_from_seed": "25 단어 또는 13 단어 조합 코드에서 지갑을 복원하십시오.", "restore_description_from_seed_keys": "안전한 장소에 저장 한 종자 / 키로 지갑을 되 찾으십시오.", @@ -503,6 +515,7 @@ "restore_seed_keys_restore": "종자 / 키 복원", "restore_spend_key_private": "지출 키 (은밀한)", "restore_title_from_backup": "백업 파일에서 복원", + "restore_title_from_hardware_wallet": "하드웨어 지갑에서 복원하십시오", "restore_title_from_keys": "키에서 복원", "restore_title_from_seed": "종자에서 복원", "restore_title_from_seed_keys": "시드 / 키에서 복원", @@ -753,6 +766,7 @@ "unsupported_asset": "이 저작물에 대해 이 작업을 지원하지 않습니다. 지원되는 자산 유형의 지갑을 생성하거나 전환하십시오.", "uptime": "가동 시간", "upto": "최대 ${value}", + "usb": "USB", "use": "사용하다 ", "use_card_info_three": "디지털 카드를 온라인 또는 비접촉식 결제 수단으로 사용하십시오.", "use_card_info_two": "디지털 화폐가 아닌 선불 계정에 보유하면 자금이 USD로 변환됩니다.", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 97a22d807..0e18179e1 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Bitcoin Light အပြင်အဆင်", "bitcoin_payments_require_1_confirmation": "Bitcoin ငွေပေးချေမှုများသည် မိနစ် 20 သို့မဟုတ် ထို့ထက်ပိုကြာနိုင်သည် 1 အတည်ပြုချက် လိုအပ်သည်။ မင်းရဲ့စိတ်ရှည်မှုအတွက် ကျေးဇူးတင်ပါတယ်။ ငွေပေးချေမှုကို အတည်ပြုပြီးသောအခါ သင့်ထံ အီးမေးလ်ပို့ပါမည်။", "Blocks_remaining": "${status} ဘလောက်များ ကျန်နေပါသည်။", + "bluetooth": "ဘလူးတုသ်", "bright_theme": "တောက်ပ", "bump_fee": "ဝင်ငွေ", "buy": "ဝယ်ပါ။", @@ -144,6 +145,8 @@ "congratulations": "ဂုဏ်ယူပါသည်။", "connect_an_existing_yat": "ရှိပြီးသား Yat ကို ချိတ်ဆက်ပါ။", "connect_yats": "Yats ကိုချိတ်ဆက်ပါ။", + "connect_your_hardware_wallet": "သင်၏ hardware ပိုက်ဆံအိတ်ကို Bluetooth သို့မဟုတ် USB ကို သုံး. ချိတ်ဆက်ပါ", + "connect_your_hardware_wallet_ios": "သင်၏ hardware ပိုက်ဆံအိတ်ကို Bluetooth ကို အသုံးပြု. ချိတ်ဆက်ပါ", "connection_sync": "ချိတ်ဆက်မှုနှင့် ထပ်တူပြုခြင်း။", "connectWalletPrompt": "အရောင်းအဝယ်ပြုလုပ်ရန် သင့်ပိုက်ဆံအိတ်ကို WalletConnect နှင့် ချိတ်ဆက်ပါ။", "contact": "ဆက်သွယ်ရန်", @@ -328,7 +331,13 @@ "is_percentage": "သည်", "last_30_days": "လွန်ခဲ့သော ရက် 30", "learn_more": "ပိုမိုသိရှိရန်", + "ledger_connection_error": "သငျသညျ Ledger နှင့်ချိတ်ဆက်ရန်မအောင်မြင်ပါ။ ကျေးဇူးပြုပြီးထပ်ကြိုးစားပါ", + "ledger_error_device_locked": "အဆိုပါလမ်းပြသော့ခတ်သည်", + "ledger_error_tx_rejected_by_user": "ငွေပေးငွေယူ device ကိုအပေါ်ငြင်းပယ်ခဲ့သည်", + "ledger_error_wrong_app": "ကျေးဇူးပြု. သင့်လက်ျာအက်ပ်ကိုသင်၏ Ledger တွင်ဖွင့်ရန်သေချာစေပါ", + "ledger_please_enable_bluetooth": "သင်၏ Ledger ကိုရှာဖွေရန် Bluetooth ကိုဖွင့်ပါ", "light_theme": "အလင်း", + "load_more": "ပိုပြီး load", "loading_your_wallet": "သင့်ပိုက်ဆံအိတ်ကို ဖွင့်နေသည်။", "login": "လော့ဂ်အင်", "logout": "ထွက်လိုက်ပါ။", @@ -442,6 +451,8 @@ "privacy_settings": "Privacy settings တွေကို", "private_key": "သီးသန့်သော့", "proceed_after_one_minute": "မျက်နှာပြင်သည် ၁ မိနစ်အကြာတွင် ဆက်လက်မလုပ်ဆောင်ပါက သင့်အီးမေးလ်ကို စစ်ဆေးပါ။", + "proceed_on_device": "သင့်စက်ပေါ်တွင်ဆက်လက်ဆောင်ရွက်ပါ", + "proceed_on_device_description": "သင်၏ hardware ပိုက်ဆံအိတ်ပေါ်ရှိညွှန်ကြားချက်များကိုလိုက်နာပါ", "profile": "ကိုယ်ရေးအကျဉ်း", "provider_error": "${provider} အမှား", "public_key": "အများသူငှာသော့", @@ -490,6 +501,7 @@ "restore_bitcoin_description_from_seed": "24 စကားလုံးပေါင်းစပ်ကုဒ်မှ သင့်ပိုက်ဆံအိတ်ကို ပြန်ယူပါ။", "restore_bitcoin_title_from_keys": "WIF မှ ပြန်လည်ရယူပါ။", "restore_description_from_backup": "သင့်အရန်ဖိုင်မှ Cake Wallet အက်ပ်တစ်ခုလုံးကို သင်ပြန်လည်ရယူနိုင်သည်။", + "restore_description_from_hardware_wallet": "Ledger ဟာ့ဒ်ဝဲပိုက်ဆံအိတ်မှ Restore", "restore_description_from_keys": "သင့်ကိုယ်ပိုင်သော့များမှ သိမ်းဆည်းထားသော ထုတ်ပေးထားသော သော့ချက်များမှ သင့်ပိုက်ဆံအိတ်ကို ပြန်လည်ရယူပါ။", "restore_description_from_seed": "25 စကားလုံး သို့မဟုတ် 13 စကားလုံးပေါင်းစပ်ကုဒ်မှ သင့်ပိုက်ဆံအိတ်ကို ပြန်လည်ရယူပါ။", "restore_description_from_seed_keys": "သင့်ပိုက်ဆံအိတ်ကို လုံခြုံသောနေရာတွင် သိမ်းဆည်းထားသော မျိုးစေ့/သော့များမှ ပြန်လည်ရယူပါ။", @@ -502,6 +514,7 @@ "restore_seed_keys_restore": "မျိုးစေ့/သော့များ ပြန်လည်ရယူပါ။", "restore_spend_key_private": "သော့သုံးရန် (သီးသန့်)", "restore_title_from_backup": "အရန်သိမ်းခြင်းမှ ပြန်လည်ရယူပါ။", + "restore_title_from_hardware_wallet": "ဟာ့ဒ်ဝဲပိုက်ဆံအိတ်မှ restore", "restore_title_from_keys": "သော့များမှ ပြန်လည်ရယူပါ။", "restore_title_from_seed": "မျိုးစေ့မှပြန်လည်ရယူပါ။", "restore_title_from_seed_keys": "မျိုးစေ့/သော့များမှ ပြန်လည်ရယူပါ။", @@ -752,6 +765,7 @@ "unsupported_asset": "ဤပိုင်ဆိုင်မှုအတွက် ဤလုပ်ဆောင်ချက်ကို ကျွန်ုပ်တို့ မပံ့ပိုးပါ။ ကျေးဇူးပြု၍ ပံ့ပိုးပေးထားသော ပိုင်ဆိုင်မှုအမျိုးအစား၏ ပိုက်ဆံအိတ်ကို ဖန်တီးပါ သို့မဟုတ် ပြောင်းပါ။", "uptime": "အထက်က", "upto": "${value} အထိ", + "usb": "ယူအက်စ်ဘီ", "use": "သို့ပြောင်းပါ။", "use_card_info_three": "ဒစ်ဂျစ်တယ်ကတ်ကို အွန်လိုင်း သို့မဟုတ် ထိတွေ့မှုမဲ့ ငွေပေးချေမှုနည်းလမ်းများဖြင့် အသုံးပြုပါ။", "use_card_info_two": "ဒစ်ဂျစ်တယ်ငွေကြေးများဖြင့်မဟုတ်ဘဲ ကြိုတင်ငွေပေးချေသည့်အကောင့်တွင် သိမ်းထားသည့်အခါ ရန်ပုံငွေများကို USD သို့ ပြောင်းလဲပါသည်။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index a64e264c0..dff34c122 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Bitcoin Light-thema", "bitcoin_payments_require_1_confirmation": "Bitcoin-betalingen vereisen 1 bevestiging, wat 20 minuten of langer kan duren. Dank voor uw geduld! U ontvangt een e-mail wanneer de betaling is bevestigd.", "Blocks_remaining": "${status} Resterende blokken", + "bluetooth": "Bluetooth", "bright_theme": "Helder", "bump_fee": "Bult fee", "buy": "Kopen", @@ -144,6 +145,8 @@ "congratulations": "gefeliciteerd!", "connect_an_existing_yat": "Verbind een bestaande Yat", "connect_yats": "Verbind Yats", + "connect_your_hardware_wallet": "Sluit uw hardware -portemonnee aan met Bluetooth of USB", + "connect_your_hardware_wallet_ios": "Sluit uw hardware -portemonnee aan met Bluetooth", "connection_sync": "Verbinding en synchronisatie", "connectWalletPrompt": "Verbind uw portemonnee met WalletConnect om transacties uit te voeren", "contact": "Contact", @@ -328,7 +331,13 @@ "is_percentage": "is", "last_30_days": "Laatste 30 dagen", "learn_more": "Kom meer te weten", + "ledger_connection_error": "Kan geen verbinding maken met u grootboek. Probeer het opnieuw.", + "ledger_error_device_locked": "Het grootboek is vergrendeld", + "ledger_error_tx_rejected_by_user": "Transactie afgewezen op apparaat", + "ledger_error_wrong_app": "Zorg ervoor dat u de juiste app op uw grootboek opent", + "ledger_please_enable_bluetooth": "Schakel Bluetooth in staat om uw grootboek te detecteren", "light_theme": "Licht", + "load_more": "Meer laden", "loading_your_wallet": "Uw portemonnee laden", "login": "Log in", "logout": "Uitloggen", @@ -442,6 +451,8 @@ "privacy_settings": "Privacy-instellingen", "private_key": "Prive sleutel", "proceed_after_one_minute": "Als het scherm na 1 minuut niet verder gaat, controleer dan uw e-mail.", + "proceed_on_device": "Ga verder met uw apparaat", + "proceed_on_device_description": "Volg de instructies die zijn aangevraagd op uw hardware -portemonnee", "profile": "Profiel", "provider_error": "${provider} fout", "public_key": "Publieke sleutel", @@ -490,6 +501,7 @@ "restore_bitcoin_description_from_seed": "Herstel uw portemonnee met een combinatiecode van 24 woorden", "restore_bitcoin_title_from_keys": "Herstel van WIF", "restore_description_from_backup": "Je kunt de hele Cake Wallet-app herstellen van uw back-upbestand", + "restore_description_from_hardware_wallet": "Herstel van een grootboekhardware -portemonnee", "restore_description_from_keys": "Herstel uw portemonnee van gegenereerd toetsaanslagen opgeslagen van uw privésleutels", "restore_description_from_seed": "Herstel uw portemonnee van het 25 woord of 13 woord combinatiecode", "restore_description_from_seed_keys": "Ontvang uw portemonnee terug uit seed / keys die u hebt opgeslagen op een veilige plaats", @@ -502,6 +514,7 @@ "restore_seed_keys_restore": "Zaad / sleutels herstellen", "restore_spend_key_private": "Sleutel uitgeven (privaat)", "restore_title_from_backup": "Herstellen vanuit een back-upbestand", + "restore_title_from_hardware_wallet": "Herstel van de hardware -portemonnee", "restore_title_from_keys": "Herstel van sleutels", "restore_title_from_seed": "Herstel van zaad", "restore_title_from_seed_keys": "Herstel van zaad / sleutels", @@ -752,6 +765,7 @@ "unsupported_asset": "We ondersteunen deze actie niet voor dit item. Maak of schakel over naar een portemonnee van een ondersteund activatype.", "uptime": "Uptime", "upto": "tot ${value}", + "usb": "USB", "use": "Gebruik ", "use_card_info_three": "Gebruik de digitale kaart online of met contactloze betaalmethoden.", "use_card_info_two": "Tegoeden worden omgezet naar USD wanneer ze op de prepaid-rekening staan, niet in digitale valuta.", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 109a800ad..b8640f5fe 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Lekki motyw Bitcoin", "bitcoin_payments_require_1_confirmation": "Płatności Bitcoin wymagają 1 potwierdzenia, co może zająć 20 minut lub dłużej. Dziękuję za cierpliwość! Otrzymasz wiadomość e-mail, gdy płatność zostanie potwierdzona.", "Blocks_remaining": "Pozostało ${status} bloków", + "bluetooth": "Bluetooth", "bright_theme": "Biały", "bump_fee": "Opłata za nierówność", "buy": "Kup", @@ -144,6 +145,8 @@ "congratulations": "gratulacje!", "connect_an_existing_yat": "Podłącz istniejący Yat", "connect_yats": "Połącz Yats", + "connect_your_hardware_wallet": "Podłącz portfel sprzętowy za pomocą Bluetooth lub USB", + "connect_your_hardware_wallet_ios": "Podłącz portfel sprzętowy za pomocą Bluetooth", "connection_sync": "Połączenie i synchronizacja", "connectWalletPrompt": "Połącz swój portfel z WalletConnect, aby dokonywać transakcji", "contact": "Kontakt", @@ -328,7 +331,13 @@ "is_percentage": "jest", "last_30_days": "Ostatnie 30 dni", "learn_more": "Dowiedz się więcej", + "ledger_connection_error": "Nie udało się połączyć z twoją księgą. Proszę spróbuj ponownie.", + "ledger_error_device_locked": "Księga jest zamknięta", + "ledger_error_tx_rejected_by_user": "Transakcja odrzucona na urządzeniu", + "ledger_error_wrong_app": "Upewnij się, że opisz odpowiednią aplikację na swojej księdze", + "ledger_please_enable_bluetooth": "Włącz Bluetooth wykrywanie księgi", "light_theme": "Jasny", + "load_more": "Załaduj więcej", "loading_your_wallet": "Ładowanie portfela", "login": "Login", "logout": "Wyloguj", @@ -442,6 +451,8 @@ "privacy_settings": "Ustawienia prywatności", "private_key": "Klucz prywatny", "proceed_after_one_minute": "Jeśli ekran nie przejdzie dalej po 1 minucie, sprawdź pocztę.", + "proceed_on_device": "Kontynuuj swoje urządzenie", + "proceed_on_device_description": "Postępuj zgodnie z instrukcjami wyświetlonymi w portfelu sprzętowym", "profile": "Profil", "provider_error": "${provider} pomyłka", "public_key": "Klucz publiczny", @@ -490,6 +501,7 @@ "restore_bitcoin_description_from_seed": "Przywróć swój portfel z frazy seed złożonej z 24 słów", "restore_bitcoin_title_from_keys": "Przywróć z klucza prywatnego", "restore_description_from_backup": "Możesz przywrócić całą aplikację Cake Wallet z pliku kopii zapasowej", + "restore_description_from_hardware_wallet": "Przywróć z portfela sprzętowego księgi", "restore_description_from_keys": "Przywróć swój portfel z kluczy prywatnych", "restore_description_from_seed": "Przywróć swój portfel z 25 lub 13-słownej frazy seed", "restore_description_from_seed_keys": "Odzyskaj swój portfel z seedów / kluczy, które zapisałeś w bezpiecznym miejscu", @@ -502,6 +514,7 @@ "restore_seed_keys_restore": "Przywracanie seedów / kluczy", "restore_spend_key_private": "Podaj prywatny klucz wglądu (view key)", "restore_title_from_backup": "Przywróć z pliku kopii zapasowej", + "restore_title_from_hardware_wallet": "Przywróć z portfela sprzętowego", "restore_title_from_keys": "Przywróć z kluczy", "restore_title_from_seed": "Przywróć z seedów", "restore_title_from_seed_keys": "Przywróć z seedów / kluczy", @@ -752,6 +765,7 @@ "unsupported_asset": "Nie obsługujemy tego działania w przypadku tego zasobu. Utwórz lub przełącz się na portfel obsługiwanego typu aktywów.", "uptime": "Czas aktu", "upto": "do ${value}", + "usb": "USB", "use": "Użyj ", "use_card_info_three": "Użyj cyfrowej karty online lub za pomocą zbliżeniowych metod płatności.", "use_card_info_two": "Środki są przeliczane na USD, gdy są przechowywane na koncie przedpłaconym, a nie w walutach cyfrowych.", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 2d877794a..7d606e2c1 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Tema claro de bitcoin", "bitcoin_payments_require_1_confirmation": "Os pagamentos em Bitcoin exigem 1 confirmação, o que pode levar 20 minutos ou mais. Obrigado pela sua paciência! Você receberá um e-mail quando o pagamento for confirmado.", "Blocks_remaining": "${status} blocos restantes", + "bluetooth": "Bluetooth", "bright_theme": "Brilhante", "bump_fee": "Taxa de aumento", "buy": "Comprar", @@ -144,6 +145,8 @@ "congratulations": "Parabéns!", "connect_an_existing_yat": "Conecte um Yat existente", "connect_yats": "Connect Yats", + "connect_your_hardware_wallet": "Conecte sua carteira de hardware usando Bluetooth ou USB", + "connect_your_hardware_wallet_ios": "Conecte sua carteira de hardware usando o Bluetooth", "connection_sync": "Conexão e sincronização", "connectWalletPrompt": "Conecte sua carteira ao WalletConnect para fazer transações", "contact": "Contato", @@ -328,7 +331,13 @@ "is_percentage": "é", "last_30_days": "Últimos 30 dias", "learn_more": "Saber mais", + "ledger_connection_error": "Falha ao se conectar ao seu livro. Por favor, tente novamente.", + "ledger_error_device_locked": "O livro está trancado", + "ledger_error_tx_rejected_by_user": "Transação rejeitada no dispositivo", + "ledger_error_wrong_app": "Por favor, certifique -se de optar pelo aplicativo certo no seu livro", + "ledger_please_enable_bluetooth": "Ative o Bluetooth para detectar seu livro", "light_theme": "Luz", + "load_more": "Carregue mais", "loading_your_wallet": "Abrindo sua carteira", "login": "Login", "logout": "Logout", @@ -444,6 +453,8 @@ "privacy_settings": "Configurações de privacidade", "private_key": "Chave privada", "proceed_after_one_minute": "Se a tela não prosseguir após 1 minuto, verifique seu e-mail.", + "proceed_on_device": "Prossiga no seu dispositivo", + "proceed_on_device_description": "Siga as instruções solicitadas em sua carteira de hardware", "profile": "Perfil", "provider_error": "${provider} erro", "public_key": "Chave pública", @@ -492,6 +503,7 @@ "restore_bitcoin_description_from_seed": "Restaure sua carteira a partir de um código de combinação de 24 palavras", "restore_bitcoin_title_from_keys": "Restaurar de WIF", "restore_description_from_backup": "Você pode restaurar todo o aplicativo Cake Wallet de seu arquivo de backup", + "restore_description_from_hardware_wallet": "Restaurar de uma carteira de hardware do Ledger", "restore_description_from_keys": "Restaure sua carteira a partir de suas chaves privadas", "restore_description_from_seed": "Restaure sua carteira a partir de semente com 25 palavras ou 13 palavras", "restore_description_from_seed_keys": "Restaure a sua carteira a partir de sementes/chaves que você salvou em um local seguro", @@ -504,6 +516,7 @@ "restore_seed_keys_restore": "Restauração com sementes/chaves", "restore_spend_key_private": "Chave de gastos (privada)", "restore_title_from_backup": "Restaurar a partir de um arquivo de backup", + "restore_title_from_hardware_wallet": "Restaurar da carteira de hardware", "restore_title_from_keys": "Restaurar a partir de chaves", "restore_title_from_seed": "Restaurar a partir de semente", "restore_title_from_seed_keys": "Restaurar a partir de sementes/chaves", @@ -754,6 +767,7 @@ "unsupported_asset": "Não oferecemos suporte a esta ação para este recurso. Crie ou mude para uma carteira de um tipo de ativo compatível.", "uptime": "Tempo de atividade", "upto": "até ${value}", + "usb": "USB", "use": "Use PIN de ", "use_card_info_three": "Use o cartão digital online ou com métodos de pagamento sem contato.", "use_card_info_two": "Os fundos são convertidos para USD quando mantidos na conta pré-paga, não em moedas digitais.", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index e6141c29b..c6466a24e 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Светлая биткойн-тема", "bitcoin_payments_require_1_confirmation": "Биткойн-платежи требуют 1 подтверждения, что может занять 20 минут или дольше. Спасибо тебе за твое терпение! Вы получите электронное письмо, когда платеж будет подтвержден.", "Blocks_remaining": "${status} Осталось блоков", + "bluetooth": "Bluetooth", "bright_theme": "Яркая", "bump_fee": "Повысить комиссию", "buy": "Купить", @@ -144,6 +145,8 @@ "congratulations": "Поздравляем!", "connect_an_existing_yat": "Подключить существующий Yat", "connect_yats": "Подключить Yats", + "connect_your_hardware_wallet": "Подключите свой аппаратный кошелек с помощью Bluetooth или USB", + "connect_your_hardware_wallet_ios": "Подключите свой аппаратный кошелек с помощью Bluetooth", "connection_sync": "Подключение и синхронизация", "connectWalletPrompt": "Подключите свой кошелек к WalletConnect для совершения транзакций.", "contact": "Контакт", @@ -328,7 +331,13 @@ "is_percentage": "есть", "last_30_days": "Последние 30 дней", "learn_more": "Узнать больше", + "ledger_connection_error": "Не удалось подключиться к вам, книги. Пожалуйста, попробуйте еще раз.", + "ledger_error_device_locked": "Ledger заблокирован", + "ledger_error_tx_rejected_by_user": "Транзакция отклоняется на устройстве", + "ledger_error_wrong_app": "Пожалуйста, убедитесь, что вы предлагаете правильное приложение в своей бухгалтерской книге", + "ledger_please_enable_bluetooth": "Пожалуйста, включите Bluetooth обнаружить вашу бухгалтерскую книгу", "light_theme": "Светлая", + "load_more": "Загрузи больше", "loading_your_wallet": "Загрузка кошелька", "login": "Логин", "logout": "Выйти", @@ -443,6 +452,8 @@ "privacy_settings": "Настройки конфиденциальности", "private_key": "Приватный ключ", "proceed_after_one_minute": "Если через 1 минуту экран не отображается, проверьте свою электронную почту.", + "proceed_on_device": "Пройдите на свое устройство", + "proceed_on_device_description": "Пожалуйста, следуйте инструкциям, представленным на вашем аппаратном кошельке", "profile": "Профиль", "provider_error": "${provider} ошибка", "public_key": "Публичный ключ", @@ -491,6 +502,7 @@ "restore_bitcoin_description_from_seed": "Вы можете восстановить кошелёк используя 24-ти значную мнемоническую фразу", "restore_bitcoin_title_from_keys": "Восстановить с помощью WIF", "restore_description_from_backup": "Вы можете восстановить Cake Wallet из вашего back-up файла", + "restore_description_from_hardware_wallet": "Восстановите из оборудования", "restore_description_from_keys": "Вы можете восстановить кошелёк с помощью приватных ключей", "restore_description_from_seed": "Вы можете восстановить кошелёк используя 25-ти значную мнемоническую фразу", "restore_description_from_seed_keys": "Вы можете восстановить кошелёк из мнемонической фразы/ключей, которые вы сохранили ранее", @@ -503,6 +515,7 @@ "restore_seed_keys_restore": "Восстановить из мнемонической фразы/ключей", "restore_spend_key_private": "Приватный ключ траты", "restore_title_from_backup": "Восстановить из back-up файла", + "restore_title_from_hardware_wallet": "Восстановить из аппаратного кошелька", "restore_title_from_keys": "Восстановить с помощью ключей", "restore_title_from_seed": "Восстановить из мнемонической фразы", "restore_title_from_seed_keys": "Восстановить из мнемонической фразы/ключей", @@ -753,6 +766,7 @@ "unsupported_asset": "Мы не поддерживаем это действие для этого объекта. Пожалуйста, создайте или переключитесь на кошелек поддерживаемого типа активов.", "uptime": "Время безотказной работы", "upto": "до ${value}", + "usb": "USB", "use": "Использовать ", "use_card_info_three": "Используйте цифровую карту онлайн или с помощью бесконтактных способов оплаты.", "use_card_info_two": "Средства конвертируются в доллары США, когда они хранятся на предоплаченном счете, а не в цифровых валютах.", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index ef1a3ea4e..6b68d1e50 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "ธีมแสง Bitcoin", "bitcoin_payments_require_1_confirmation": "การชำระเงินด้วย Bitcoin ต้องการการยืนยัน 1 ครั้ง ซึ่งอาจใช้เวลา 20 นาทีหรือนานกว่านั้น ขอบคุณสำหรับความอดทนของคุณ! คุณจะได้รับอีเมลเมื่อการชำระเงินได้รับการยืนยัน", "Blocks_remaining": "${status} บล็อกที่เหลืออยู่", + "bluetooth": "บลูทู ธ", "bright_theme": "สดใส", "bump_fee": "ค่าธรรมเนียมชน", "buy": "ซื้อ", @@ -144,6 +145,8 @@ "congratulations": "ขอแสดงความยินดี!", "connect_an_existing_yat": "เชื่อมต่อ Yat ที่มีอยู่", "connect_yats": "เชื่อมต่อ Yats", + "connect_your_hardware_wallet": "เชื่อมต่อกระเป๋าเงินฮาร์ดแวร์ของคุณโดยใช้บลูทู ธ หรือ USB", + "connect_your_hardware_wallet_ios": "เชื่อมต่อกระเป๋าเงินฮาร์ดแวร์ของคุณโดยใช้บลูทู ธ", "connection_sync": "การเชื่อมต่อและการซิงค์", "connectWalletPrompt": "เชื่อมต่อกระเป๋าเงินของคุณด้วย WalletConnect เพื่อทำธุรกรรม", "contact": "ผู้ติดต่อ", @@ -328,7 +331,13 @@ "is_percentage": "เป็น", "last_30_days": "30 วันล่าสุด", "learn_more": "ศึกษาเพิ่มเติม", + "ledger_connection_error": "ไม่สามารถเชื่อมต่อกับบัญชีแยกประเภทของคุณได้ กรุณาลองอีกครั้ง.", + "ledger_error_device_locked": "บัญชีแยกประเภทถูกล็อค", + "ledger_error_tx_rejected_by_user": "ธุรกรรมถูกปฏิเสธบนอุปกรณ์", + "ledger_error_wrong_app": "โปรดตรวจสอบให้แน่ใจว่าคุณเปิดแอพที่เหมาะสมในบัญชีแยกประเภทของคุณ", + "ledger_please_enable_bluetooth": "โปรดเปิดใช้งานบลูทู ธ ในการตรวจจับบัญชีแยกประเภทของคุณ", "light_theme": "สว่าง", + "load_more": "โหลดมากขึ้น", "loading_your_wallet": "กำลังโหลดกระเป๋าของคุณ", "login": "เข้าสู่ระบบ", "logout": "ออกจากระบบ", @@ -442,6 +451,8 @@ "privacy_settings": "การตั้งค่าความเป็นส่วนตัว", "private_key": "คีย์ส่วนตัว", "proceed_after_one_minute": "หากหน้าจอไม่ดำเนินการหลังจาก 1 นาทีโปรดตรวจสอบอีเมลของคุณ", + "proceed_on_device": "ดำเนินการบนอุปกรณ์ของคุณ", + "proceed_on_device_description": "โปรดทำตามคำแนะนำที่ได้รับแจ้งไว้ในกระเป๋าเงินฮาร์ดแวร์ของคุณ", "profile": "ประวัติโดยย่อ", "provider_error": "ข้อผิดพลาด ${provider}", "public_key": "คีย์สาธารณะ", @@ -490,6 +501,7 @@ "restore_bitcoin_description_from_seed": "กู้กระเป๋าของคุณจากรหัสผสมของ 24 คำ", "restore_bitcoin_title_from_keys": "กู้จาก WIF", "restore_description_from_backup": "คุณสามารถกู้แอพ Cake Wallet ทั้งหมดจากไฟล์สำรองข้อมูลของคุณ", + "restore_description_from_hardware_wallet": "กู้คืนจากกระเป๋าเงินฮาร์ดแวร์บัญชีแยกประเภท", "restore_description_from_keys": "กู้กระเป๋าของคุณจากการกดปุ่มที่สร้างขึ้นจาก private keys ของคุณที่บันทึกไว้", "restore_description_from_seed": "กู้กระเป๋าของคุณจากรหัสผสมของ 25 คำหรือ 13 คำ", "restore_description_from_seed_keys": "เรียกกระเป๋าของคุณกลับมาจาก seed/keys ที่คุณได้บันทึกไว้ในที่ปลอดภัย", @@ -502,6 +514,7 @@ "restore_seed_keys_restore": "กู้จาก Seed/Keys", "restore_spend_key_private": "คีย์สำหรับใช้ (ส่วนตัว)", "restore_title_from_backup": "กู้จากการสำรองข้อมูล", + "restore_title_from_hardware_wallet": "กู้คืนจากกระเป๋าเงินฮาร์ดแวร์", "restore_title_from_keys": "กู้จาก keys", "restore_title_from_seed": "กู้จาก seed", "restore_title_from_seed_keys": "กู้จาก seed/keys", @@ -752,6 +765,7 @@ "unsupported_asset": "เราไม่สนับสนุนการกระทำนี้สำหรับเนื้อหานี้ โปรดสร้างหรือเปลี่ยนเป็นกระเป๋าเงินประเภทสินทรัพย์ที่รองรับ", "uptime": "เวลาทำงาน", "upto": "สูงสุด ${value}", + "usb": "ยูเอสบี", "use": "สลับไปที่ ", "use_card_info_three": "ใช้บัตรดิจิตอลออนไลน์หรือผ่านวิธีการชำระเงินแบบไม่ต้องใช้บัตรกระดาษ", "use_card_info_two": "เงินจะถูกแปลงค่าเป็นดอลลาร์สหรัฐเมื่อถือไว้ในบัญชีสำรองเงิน ไม่ใช่สกุลเงินดิจิตอล", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index e0258e38a..6d388973a 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Tema ng ilaw ng bitcoin", "bitcoin_payments_require_1_confirmation": "Ang mga pagbabayad sa Bitcoin ay nangangailangan ng 1 kumpirmasyon, na maaaring tumagal ng 20 minuto o mas mahaba. Salamat sa iyong pasensya! Mag -email ka kapag nakumpirma ang pagbabayad.", "Blocks_remaining": "Ang natitirang ${status} ay natitira", + "bluetooth": "Bluetooth", "bright_theme": "Maliwanag", "bump_fee": "Bayad sa paga", "buy": "Bilhin", @@ -144,6 +145,8 @@ "congratulations": "Binabati kita!", "connect_an_existing_yat": "Ikonekta ang isang umiiral na yat", "connect_yats": "Ikonekta ang mga yats", + "connect_your_hardware_wallet": "Ikonekta ang iyong wallet ng hardware gamit ang Bluetooth o USB", + "connect_your_hardware_wallet_ios": "Ikonekta ang iyong wallet ng hardware gamit ang Bluetooth", "connection_sync": "Koneksyon at pag -sync", "connectWalletPrompt": "Ikonekta ang iyong wallet sa WalletConnect upang gumawa ng mga transaksyon", "contact": "Makipag -ugnay", @@ -328,7 +331,13 @@ "is_percentage": "ay", "last_30_days": "Huling 30 araw", "learn_more": "Matuto nang higit pa", + "ledger_connection_error": "Nabigong kumonekta sa iyo ledger. Pakisubukang muli.", + "ledger_error_device_locked": "Naka -lock ang ledger", + "ledger_error_tx_rejected_by_user": "Ang transaksyon ay tinanggihan sa aparato", + "ledger_error_wrong_app": "Mangyaring tiyaking pinipili mo ang tamang app sa iyong ledger", + "ledger_please_enable_bluetooth": "Mangyaring paganahin ang Bluetooth upang makita ang iyong ledger", "light_theme": "Ilaw", + "load_more": "Mag -load pa", "loading_your_wallet": "Naglo -load ng iyong pitaka", "login": "Mag log in", "logout": "Mag -logout", @@ -442,6 +451,8 @@ "privacy_settings": "Settings para sa pagsasa-pribado", "private_key": "Pribadong susi", "proceed_after_one_minute": "Kung ang screen ay hindi magpatuloy pagkatapos ng 1 minuto, suriin ang iyong email.", + "proceed_on_device": "Magpatuloy sa iyong aparato", + "proceed_on_device_description": "Mangyaring sundin ang mga tagubilin na sinenyasan sa iyong wallet ng hardware", "profile": "Profile", "provider_error": "${provider} error", "public_key": "Pampublikong susi", @@ -490,6 +501,7 @@ "restore_bitcoin_description_from_seed": "Ibalik ang iyong pitaka mula sa 24 na code ng kombinasyon ng salita", "restore_bitcoin_title_from_keys": "Ibalik mula sa WIF", "restore_description_from_backup": "Maaari mong ibalik ang buong cake wallet app mula sa iyong back-up file", + "restore_description_from_hardware_wallet": "Ibalik mula sa isang ledger hardware wallet", "restore_description_from_keys": "Ibalik ang iyong pitaka mula sa nabuong mga keystroke na na -save mula sa iyong mga pribadong susi", "restore_description_from_seed": "Ibalik ang iyong pitaka mula sa alinman sa 25 salita o 13 na code ng kombinasyon ng salita", "restore_description_from_seed_keys": "Ibalik ang iyong pitaka mula sa mga binhi/susi na na -save mo upang ma -secure ang lugar", @@ -502,6 +514,7 @@ "restore_seed_keys_restore": "Ibinalik ang mga binhi/susi", "restore_spend_key_private": "Gumastos ng susi (pribado)", "restore_title_from_backup": "Ibalik mula sa backup", + "restore_title_from_hardware_wallet": "Ibalik mula sa pitaka ng hardware", "restore_title_from_keys": "Ibalik mula sa mga susi", "restore_title_from_seed": "Ibalik mula sa binhi", "restore_title_from_seed_keys": "Ibalik mula sa mga binhi/susi", @@ -752,6 +765,7 @@ "unsupported_asset": "Hindi namin sinusuportahan ang pagkilos na ito para sa asset na ito. Mangyaring lumikha o lumipat sa isang pitaka ng isang suportadong uri ng pag -aari.", "uptime": "Uptime", "upto": "Hanggang sa ${value}", + "usb": "USB", "use": "Lumipat sa", "use_card_info_three": "Gamitin ang digital card online o sa mga pamamaraan ng pagbabayad na walang contact.", "use_card_info_two": "Ang mga pondo ay na -convert sa USD kapag gaganapin sila sa prepaid account, hindi sa mga digital na pera.", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 6cacbfd42..ddf99696b 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Bitcoin Hafif Tema", "bitcoin_payments_require_1_confirmation": "Bitcoin ödemeleri, 20 dakika veya daha uzun sürebilen 1 onay gerektirir. Sabrınız için teşekkürler! Ödeme onaylandığında e-posta ile bilgilendirileceksiniz.", "Blocks_remaining": "${status} Blok Kaldı", + "bluetooth": "Bluetooth", "bright_theme": "Parlak", "bump_fee": "Çarpma ücreti", "buy": "Alış", @@ -144,6 +145,8 @@ "congratulations": "Tebrikler!", "connect_an_existing_yat": "Mevcut bir Yat'ı bağla", "connect_yats": "Yat'lara bağlan", + "connect_your_hardware_wallet": "Bluetooth veya USB kullanarak donanım cüzdanınızı bağlayın", + "connect_your_hardware_wallet_ios": "Bluetooth kullanarak donanım cüzdanınızı bağlayın", "connection_sync": "Bağlantı ve senkronizasyon", "connectWalletPrompt": "İşlem yapmak için cüzdanınızı WalletConnect'e bağlayın", "contact": "Rehber", @@ -328,7 +331,13 @@ "is_percentage": "is", "last_30_days": "Son 30 gün", "learn_more": "Daha fazla öğren", + "ledger_connection_error": "Ledger'e bağlanamadı. Lütfen tekrar deneyin.", + "ledger_error_device_locked": "Defter kilitli", + "ledger_error_tx_rejected_by_user": "Cihazda reddedilen işlem", + "ledger_error_wrong_app": "Lütfen defterinizde doğru uygulamayı açtığınızdan emin olun", + "ledger_please_enable_bluetooth": "Defterinizi algılamak için lütfen Bluetooth'u etkinleştirin", "light_theme": "Aydınlık", + "load_more": "Daha fazla yükle", "loading_your_wallet": "Cüzdanın yükleniyor", "login": "Login", "logout": "Çıkış yap", @@ -442,6 +451,8 @@ "privacy_settings": "Gizlilik ayarları", "private_key": "Özel anahtar", "proceed_after_one_minute": "Ekran 1 dakika sonra ilerlemezse, e-postanızı kontrol edin.", + "proceed_on_device": "Cihazınıza devam edin", + "proceed_on_device_description": "Lütfen donanım cüzdanınızda istenen talimatları izleyin", "profile": "Profil", "provider_error": "${provider} hatası", "public_key": "Genel Anahtar", @@ -490,6 +501,7 @@ "restore_bitcoin_description_from_seed": "Cüzdanınızı 24 kelimelik kombinasyon kodundan geri yükle", "restore_bitcoin_title_from_keys": "WIF'den geri yükle", "restore_description_from_backup": "Yedek dosyandan tüm Cake Wallet uygulamasını geri döndürebilirsin", + "restore_description_from_hardware_wallet": "Bir defter donanım cüzdanından geri yükleyin", "restore_description_from_keys": "Cüzdanınızı özel anahtarlarınızdan kaydedilen oluşturulmuş tuş vuruşlarından geri yükleyin", "restore_description_from_seed": "Cüzdanınızı 25 veya 13 kelimelik kombinasyon kodundan geri döndürün", "restore_description_from_seed_keys": "Güvenli bir yere kaydettiğin tohumdan/anahtarlardan cüzdanını geri döndür", @@ -502,6 +514,7 @@ "restore_seed_keys_restore": "Tohumu/Anahtarları Geri Döndür", "restore_spend_key_private": "Harcama anahtarı (Özel)", "restore_title_from_backup": "Yedekten geri döndür", + "restore_title_from_hardware_wallet": "Donanım cüzdanından geri yükleme", "restore_title_from_keys": "Anahtarlardan geri döndür", "restore_title_from_seed": "Tohumdan geri döndür", "restore_title_from_seed_keys": "Tohumdan/anahtarlardan geri döndür", @@ -752,6 +765,7 @@ "unsupported_asset": "Bu öğe için bu eylemi desteklemiyoruz. Lütfen desteklenen bir varlık türünde bir cüzdan oluşturun veya cüzdana geçiş yapın.", "uptime": "Çalışma süresi", "upto": "Şu miktara kadar: ${value}", + "usb": "USB", "use": "Şuna geç: ", "use_card_info_three": "Dijital kartı çevrimiçi olarak veya temassız ödeme yöntemleriyle kullanın.", "use_card_info_two": "Paralar, dijital para birimlerinde değil, ön ödemeli hesapta tutulduğunda USD'ye dönüştürülür.", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index d3f1c5088..2f294817e 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Світла тема Bitcoin", "bitcoin_payments_require_1_confirmation": "Платежі Bitcoin потребують 1 підтвердження, яке може зайняти 20 хвилин або більше. Дякую за Ваше терпіння! Ви отримаєте електронний лист, коли платіж буде підтверджено.", "Blocks_remaining": "${status} Залишилось блоків", + "bluetooth": "Блюдот", "bright_theme": "Яскрава", "bump_fee": "Підвищити комісію", "buy": "Купити", @@ -144,6 +145,8 @@ "congratulations": "Вітаємо!", "connect_an_existing_yat": "Підключити існуючий Yat", "connect_yats": "Підключіть Yats", + "connect_your_hardware_wallet": "Підключіть апаратний гаманець за допомогою Bluetooth або USB", + "connect_your_hardware_wallet_ios": "Підключіть апаратний гаманець за допомогою Bluetooth", "connection_sync": "Підключення та синхронізація", "connectWalletPrompt": "Підключіть свій гаманець до WalletConnect, щоб здійснювати транзакції", "contact": "Контакт", @@ -328,7 +331,13 @@ "is_percentage": "є", "last_30_days": "Останні 30 днів", "learn_more": "Дізнатися більше", + "ledger_connection_error": "Не вдалося підключитися до вас. Будь ласка спробуйте ще раз.", + "ledger_error_device_locked": "Книга заблокована", + "ledger_error_tx_rejected_by_user": "Транзакція відхилена на пристрої", + "ledger_error_wrong_app": "Будь ласка, переконайтеся, що ви відкриваєте потрібну програму на своїй книзі", + "ledger_please_enable_bluetooth": "Будь ласка, ввімкніть Bluetooth виявити свою книгу", "light_theme": "Світла", + "load_more": "Завантажити ще", "loading_your_wallet": "Завантаження гаманця", "login": "Логін", "logout": "Вийти", @@ -442,6 +451,8 @@ "privacy_settings": "Налаштування конфіденційності", "private_key": "Приватний ключ", "proceed_after_one_minute": "Якщо екран не продовжується через 1 хвилину, перевірте свою електронну пошту.", + "proceed_on_device": "Продовжуйте свій пристрій", + "proceed_on_device_description": "Будь ласка, дотримуйтесь інструкцій, підказаних на вашому апаратному гаманці", "profile": "Профіль", "provider_error": "${provider} помилка", "public_key": "Публічний ключ", @@ -491,6 +502,7 @@ "restore_bitcoin_description_from_seed": "Ви можете відновити гаманець використовуючи 24-ти слівну мнемонічну фразу", "restore_bitcoin_title_from_keys": "Відновити за допомогою WIF", "restore_description_from_backup": "Ви можете відновити Cake Wallet з вашого резервного файлу", + "restore_description_from_hardware_wallet": "Відновлення з апаратного гаманця", "restore_description_from_keys": "Ви можете відновити гаманець за допомогою приватних ключів", "restore_description_from_seed": "Ви можете відновити гаманець використовуючи 25-ти слівну мнемонічну фразу", "restore_description_from_seed_keys": "Ви можете відновити гаманець з мнемонічної фрази/ключів, які ви зберегли раніше", @@ -503,6 +515,7 @@ "restore_seed_keys_restore": "Відновити за допомогою мнемонічної фрази/ключів", "restore_spend_key_private": "Приватний ключ витрати", "restore_title_from_backup": "Відновити із резервного файлу", + "restore_title_from_hardware_wallet": "Відновити з апаратного гаманця", "restore_title_from_keys": "Відновити за допомогою ключів", "restore_title_from_seed": "Відновити з мнемонічної фрази", "restore_title_from_seed_keys": "Відновити з мнемонічної фрази/ключів", @@ -753,6 +766,7 @@ "unsupported_asset": "Ми не підтримуємо цю дію для цього ресурсу. Створіть або перейдіть на гаманець підтримуваного типу активів.", "uptime": "Час роботи", "upto": "до ${value}", + "usb": "USB", "use": "Використати ", "use_card_info_three": "Використовуйте цифрову картку онлайн або за допомогою безконтактних методів оплати.", "use_card_info_two": "Кошти конвертуються в долари США, якщо вони зберігаються на передплаченому рахунку, а не в цифрових валютах.", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 97851b210..048cfb070 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "بٹ کوائن لائٹ تھیم", "bitcoin_payments_require_1_confirmation": "بٹ کوائن کی ادائیگی میں 1 تصدیق کی ضرورت ہوتی ہے ، جس میں 20 منٹ یا اس سے زیادہ وقت لگ سکتا ہے۔ آپ کے صبر کا شکریہ! ادائیگی کی تصدیق ہونے پر آپ کو ای میل کیا جائے گا۔", "Blocks_remaining": "${status} بلاکس باقی ہیں۔", + "bluetooth": "بلوٹوتھ", "bright_theme": "روشن", "bump_fee": "بمپ فیس", "buy": "خریدنے", @@ -144,6 +145,8 @@ "congratulations": "مبارک ہو!", "connect_an_existing_yat": "ایک موجودہ Yat کو جوڑیں۔", "connect_yats": "Yats کو جوڑیں۔", + "connect_your_hardware_wallet": "بلوٹوتھ یا USB کا استعمال کرتے ہوئے اپنے ہارڈ ویئر پرس کو مربوط کریں", + "connect_your_hardware_wallet_ios": "بلوٹوتھ کا استعمال کرتے ہوئے اپنے ہارڈ ویئر پرس کو جوڑیں", "connection_sync": "کنکشن اور مطابقت پذیری", "connectWalletPrompt": "۔ﮟﯾﮌﻮﺟ ﮫﺗﺎﺳ ﮯﮐ WalletConnect ﻮﮐ ﮮﻮﭩﺑ ﮯﻨﭘﺍ ﮯﯿﻟ ﮯﮐ ﮯﻧﺮﮐ ﻦﯾﺩ ﻦﯿﻟ", "contact": "رابطہ کریں۔", @@ -328,7 +331,13 @@ "is_percentage": "ہے", "last_30_days": "آخری 30 دن", "learn_more": "اورجانیے", + "ledger_connection_error": "آپ سے لیجر سے رابطہ قائم کرنے میں ناکام۔ دوبارہ کوشش کریں.", + "ledger_error_device_locked": "لیجر لاک ہے", + "ledger_error_tx_rejected_by_user": "آلہ پر لین دین کو مسترد کردیا گیا", + "ledger_error_wrong_app": "براہ کرم یقینی بنائیں کہ آپ اپنے لیجر پر صحیح ایپ کو کھولتے ہیں", + "ledger_please_enable_bluetooth": "براہ کرم بلوٹوتھ کو اپنے لیجر کا پتہ لگانے کے لئے اہل بنائیں", "light_theme": "روشنی", + "load_more": "مزید لوڈ کریں", "loading_your_wallet": "آپ کا بٹوہ لوڈ ہو رہا ہے۔", "login": "لاگ ان کریں", "logout": "لاگ آوٹ", @@ -444,6 +453,8 @@ "privacy_settings": "رازداری کی ترتیبات", "private_key": "نجی کلید", "proceed_after_one_minute": "اگر اسکرین 1 منٹ کے بعد آگے نہیں بڑھتی ہے تو اپنا ای میل چیک کریں۔", + "proceed_on_device": "اپنے آلے پر آگے بڑھیں", + "proceed_on_device_description": "براہ کرم اپنے ہارڈ ویئر پرس پر آنے والی ہدایات پر عمل کریں", "profile": "پروفائل", "provider_error": "${provider} خرابی۔", "public_key": "عوامی کلید", @@ -492,6 +503,7 @@ "restore_bitcoin_description_from_seed": "24 الفاظ کے مجموعہ کوڈ سے اپنے بٹوے کو بحال کریں۔", "restore_bitcoin_title_from_keys": "WIF سے بحال کریں۔", "restore_description_from_backup": "آپ اپنی بیک اپ فائل سے پوری کیک والیٹ ایپ کو بحال کر سکتے ہیں۔", + "restore_description_from_hardware_wallet": "لیجر ہارڈ ویئر پرس سے بحال کریں", "restore_description_from_keys": "اپنے بٹوے کو اپنی نجی کلیدوں سے محفوظ کردہ کی اسٹروکس سے بحال کریں۔", "restore_description_from_seed": "اپنے بٹوے کو 25 لفظ یا 13 الفاظ کے مجموعہ کوڈ سے بحال کریں۔", "restore_description_from_seed_keys": "اپنے بٹوے کو بیج / چابیاں سے واپس حاصل کریں جنہیں آپ نے محفوظ جگہ پر محفوظ کیا ہے۔", @@ -504,6 +516,7 @@ "restore_seed_keys_restore": "بیج/کیز کی بحالی", "restore_spend_key_private": "خرچ کی کلید (نجی)", "restore_title_from_backup": "بیک اپ سے بحال کریں۔", + "restore_title_from_hardware_wallet": "ہارڈ ویئر پرس سے بحال کریں", "restore_title_from_keys": "چابیاں سے بحال کریں۔", "restore_title_from_seed": "بیج سے بحال کریں۔", "restore_title_from_seed_keys": "بیج / چابیاں سے بحال کریں۔", @@ -754,6 +767,7 @@ "unsupported_asset": "۔ﮟﯾﺮﮐ ﭻﺋﻮﺳ ﺮﭘ ﺱﺍ ﺎﯾ ﮟﯿﺋﺎﻨﺑ ﺱﺮﭘ ﺎﮐ ﻢﺴﻗ ﯽﮐ ﮧﺛﺎﺛﺍ ﮧﺘﻓﺎﯾ ﻥﻭﺎﻌﺗ ﻡﺮﮐ ﮦﺍﺮﺑ ۔ﮟﯿﮨ ﮯﺗﺮﮐ ﮟﯿﮩﻧ ﺖﯾﺎﻤﺣ ﯽﮐ ﯽﺋﺍﻭﺭﺭﺎﮐ ﺱﺍ ﮯﯿﻟ ﮯﮐ ﮧﺛﺎﺛﺍ ﺱﺍ ﻢﮨ", "uptime": "اپ ٹائم", "upto": "${value} تک", + "usb": "یو ایس بی", "use": "تبدیل کرنا", "use_card_info_three": "ڈیجیٹل کارڈ آن لائن یا کنٹیکٹ لیس ادائیگی کے طریقوں کے ساتھ استعمال کریں۔", "use_card_info_two": "رقوم کو امریکی ڈالر میں تبدیل کیا جاتا ہے جب پری پیڈ اکاؤنٹ میں رکھا جاتا ہے، ڈیجیٹل کرنسیوں میں نہیں۔", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index acb533536..8a379a258 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "Bitcoin Light Akori", "bitcoin_payments_require_1_confirmation": "Àwọn àránṣẹ́ Bitcoin nílò ìjẹ́rìísí kan. Ó lè lo ìṣéjú ogun tàbí ìṣéjú jù. A dúpẹ́ fún sùúrù yín! Ẹ máa gba ímeèlì t'ó bá jẹ́rìísí àránṣẹ́ náà.", "Blocks_remaining": "Àkójọpọ̀ ${status} kikù", + "bluetooth": "Bluetooth", "bright_theme": "Funfun", "bump_fee": "Ọya ija", "buy": "Rà", @@ -144,6 +145,8 @@ "congratulations": "Ẹ kúuṣẹ́ ooo!", "connect_an_existing_yat": "So Yat wíwà", "connect_yats": "So àwọn Yat", + "connect_your_hardware_wallet": "So apamọwọ irinṣẹ rẹ nipa lilo Bluetooth tabi USB", + "connect_your_hardware_wallet_ios": "So apamọwọ ẹrọ rẹ ni lilo Bluetooth", "connection_sync": "Ìkànpọ̀ àti ìbádọ́gba", "connectWalletPrompt": "So apamọwọ rẹ pọ pẹlu WalletConnect lati ṣe awọn iṣowo", "contact": "Olùbásọ̀rọ̀", @@ -329,7 +332,13 @@ "is_percentage": "jẹ́", "last_30_days": "Ọ̀jọ̀ mọ́gbọ̀n tó kọjà", "learn_more": "Túbọ̀ kọ́", + "ledger_connection_error": "O kuna lati sopọ mọ ọ. Jọwọ gbiyanju lẹẹkansi.", + "ledger_error_device_locked": "Ledger wa ni titiipa", + "ledger_error_tx_rejected_by_user": "Idunadura kọ lori ẹrọ", + "ledger_error_wrong_app": "Jọwọ rii daju pe iwọ yoo sọ app ti o tọ loju omi rẹ", + "ledger_please_enable_bluetooth": "Jọwọ jẹ ki Bluetooth lati rii iṣupọ rẹ", "light_theme": "Funfun bí eérú", + "load_more": "Ẹru diẹ sii", "loading_your_wallet": "A ń ṣí àpamọ́wọ́ yín", "login": "Orúkọ", "logout": "Jáde", @@ -443,6 +452,8 @@ "privacy_settings": "Ààtò àdáni", "private_key": "Kọ́kọ́rọ́ àdáni", "proceed_after_one_minute": "Tí aṣàfihàn kò bá tẹ̀síwájú l'áàárín ìṣẹ́jú kan, ẹ tọ́ ímeèlì yín wò.", + "proceed_on_device": "Tẹsiwaju lori ẹrọ rẹ", + "proceed_on_device_description": "Jọwọ tẹle awọn ilana ti a ṣe lori apamọwọ ohun elo rẹ", "profile": "profaili", "provider_error": "Àṣìṣe ${provider}", "public_key": "Kọ́kọ́rọ́ tó kò àdáni", @@ -491,6 +502,7 @@ "restore_bitcoin_description_from_seed": "Mú àpamọ́wọ́ yín padà láti àkànpọ̀ ọlọ́rọ̀ ẹ̀ẹ̀mẹrinlélógun", "restore_bitcoin_title_from_keys": "Mú padà láti WIF", "restore_description_from_backup": "Ẹ lè fi ẹ̀dà nípamọ́ yín mú odindi Cake Wallet áàpù padà.", + "restore_description_from_hardware_wallet": "Mu pada kuro ninu apamọwọ ohun elo ti o yanilenu", "restore_description_from_keys": "Mú àpamọ́wọ́ yín padà láti àwọn àtẹ̀ nípamọ́ láti àwọn kọ́kọ́rọ́ àdáni yín", "restore_description_from_seed": "Ẹ mú àpamọ́wọ́ yín padà láti àkànpọ̀ ọlọ́rọ̀ ẹ̀ẹ̀marùndínlọgbọ̀n tàbí ti mẹ́talá.", "restore_description_from_seed_keys": "Mú àpamọ́wọ́ yín padà láti hóró/kọ́kọ́rọ́ t'ẹ́ ti pamọ́ sí ibi láìléwu", @@ -503,6 +515,7 @@ "restore_seed_keys_restore": "Mú hóró/kọ́kọ́rọ́ padà", "restore_spend_key_private": "kọ́kọ́rọ́ àdáni fún níná", "restore_title_from_backup": "Fi ẹ̀dà nípamọ́ mú padà", + "restore_title_from_hardware_wallet": "Mu pada kuro ninu apamọwọ ohun elo", "restore_title_from_keys": "Fi kọ́kọ́rọ́ ṣẹ̀dá", "restore_title_from_seed": "Fi hóró mú padà", "restore_title_from_seed_keys": "Fi hóró/kọ́kọ́rọ́ mú padà", @@ -753,6 +766,7 @@ "unsupported_asset": "A ko ṣe atilẹyin iṣẹ yii fun dukia yii. Jọwọ ṣẹda tabi yipada si apamọwọ iru dukia atilẹyin.", "uptime": "Iduro", "upto": "kò tóbi ju ${value}", + "usb": "USB", "use": "Lo", "use_card_info_three": "Ẹ lo káàdí ayélujára lórí wẹ́ẹ̀bù tàbí ẹ lò ó lórí àwọn ẹ̀rọ̀ ìrajà tíwọn kò kò.", "use_card_info_two": "A pààrọ̀ owó sí owó Amẹ́ríkà tó bá wà nínú àkanti t'á ti fikún tẹ́lẹ̀tẹ́lẹ̀. A kò kó owó náà nínú owó ayélujára.", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index e17c4a89b..bf6684dee 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -79,6 +79,7 @@ "bitcoin_light_theme": "比特币浅色主题", "bitcoin_payments_require_1_confirmation": "比特币支付需要 1 次确认,这可能需要 20 分钟或更长时间。谢谢你的耐心!确认付款后,您将收到电子邮件。", "Blocks_remaining": "${status} 剩余的块", + "bluetooth": "蓝牙", "bright_theme": "明亮", "bump_fee": "撞费", "buy": "购买", @@ -144,6 +145,8 @@ "congratulations": "恭喜!", "connect_an_existing_yat": "連接現有 Yat", "connect_yats": "连接 Yats", + "connect_your_hardware_wallet": "使用蓝牙或USB连接硬件钱包", + "connect_your_hardware_wallet_ios": "使用蓝牙连接硬件钱包", "connection_sync": "连接和同步", "connectWalletPrompt": "将您的钱包与 WalletConnect 连接以进行交易", "contact": "联系", @@ -328,7 +331,13 @@ "is_percentage": "是", "last_30_days": "过去 30 天", "learn_more": "了解更多", + "ledger_connection_error": "无法连接到您的分类帐。请再试一次。", + "ledger_error_device_locked": "分类帐已锁定", + "ledger_error_tx_rejected_by_user": "交易在设备上拒绝", + "ledger_error_wrong_app": "请确保您在分类帐中操作正确的应用程序", + "ledger_please_enable_bluetooth": "请启用蓝牙来检测您的分类帐", "light_theme": "艳丽", + "load_more": "装载更多", "loading_your_wallet": "加载您的钱包", "login": "登录", "logout": "注销", @@ -442,6 +451,8 @@ "privacy_settings": "隐私设置", "private_key": "私钥", "proceed_after_one_minute": "如果屏幕在 1 分钟后没有继续,请检查您的电子邮件。", + "proceed_on_device": "在设备上继续", + "proceed_on_device_description": "请按照您的硬件钱包上提示的说明进行操作", "profile": "轮廓", "provider_error": "${provider} 错误", "public_key": "公钥", @@ -490,6 +501,7 @@ "restore_bitcoin_description_from_seed": "从24个文字的组成码恢复您的钱包", "restore_bitcoin_title_from_keys": "从WIF还原", "restore_description_from_backup": "您可以从还原整个Cake Wallet应用您的备份文件", + "restore_description_from_hardware_wallet": "从分类帐硬件钱包还原", "restore_description_from_keys": "使用私钥恢复钱包", "restore_description_from_seed": "从25个字中恢复您的钱包或13个字的组合码", "restore_description_from_seed_keys": "从保存到安全地方的种子/钥匙取回钱包", @@ -502,6 +514,7 @@ "restore_seed_keys_restore": "种子/密钥还原", "restore_spend_key_private": "Spend私钥", "restore_title_from_backup": "从备份文件还原", + "restore_title_from_hardware_wallet": "从硬件钱包还原", "restore_title_from_keys": "从密钥还原", "restore_title_from_seed": "从种子还原", "restore_title_from_seed_keys": "从种子/密钥还原", @@ -752,6 +765,7 @@ "unsupported_asset": "我们不支持针对该资产采取此操作。请创建或切换到支持的资产类型的钱包。", "uptime": "正常运行时间", "upto": "最高 ${value}", + "usb": "USB", "use": "切换使用", "use_card_info_three": "在线使用电子卡或使用非接触式支付方式。", "use_card_info_two": "预付账户中的资金转换为美元,不是数字货币。", diff --git a/tool/configure.dart b/tool/configure.dart index f136c9a2a..f2391103d 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -68,9 +68,13 @@ Future generateBitcoin(bool hasImplementation) async { const bitcoinCommonHeaders = """ import 'dart:typed_data'; import 'package:cw_core/node.dart'; +import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart'; +import 'package:cake_wallet/view_model/send/output.dart'; +import 'package:cw_core/hardware/hardware_account_data.dart'; import 'package:cw_core/pending_transaction.dart'; import 'package:cw_core/receive_page_option.dart'; import 'package:cw_core/unspent_transaction_output.dart'; +import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/transaction_priority.dart'; @@ -78,8 +82,8 @@ import 'package:cw_core/output_info.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:cake_wallet/view_model/send/output.dart'; import 'package:hive/hive.dart'; +import 'package:ledger_flutter/ledger_flutter.dart'; import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_flutter/bitcoin_flutter.dart' as btc; import 'package:bip32/bip32.dart' as bip32; @@ -93,6 +97,7 @@ import 'package:cw_bitcoin/electrum_derivations.dart'; import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/bitcoin_receive_page_option.dart'; +import 'package:cw_bitcoin/bitcoin_wallet.dart'; import 'package:cw_bitcoin/electrum_wallet.dart'; import 'package:cw_bitcoin/bitcoin_unspent.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; @@ -105,6 +110,7 @@ import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_bitcoin/litecoin_wallet_service.dart'; import 'package:cw_bitcoin/script_hash.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; +import 'package:cw_bitcoin/bitcoin_hardware_wallet_service.dart'; import 'package:mobx/mobx.dart'; """; const bitcoinCwPart = "part 'cw_bitcoin.dart';"; @@ -139,6 +145,7 @@ abstract class Bitcoin { }); WalletCredentials createBitcoinRestoreWalletFromWIFCredentials({required String name, required String password, required String wif, WalletInfo? walletInfo}); WalletCredentials createBitcoinNewWalletCredentials({required String name, WalletInfo? walletInfo}); + WalletCredentials createBitcoinHardwareWalletCredentials({required String name, required HardwareAccountData accountData, WalletInfo? walletInfo}); List getWordList(); Map getWalletKeys(Object wallet); List getTransactionPriorities(); @@ -187,6 +194,9 @@ abstract class Bitcoin { int getFeeAmountForPriority(Object wallet, TransactionPriority priority, int inputsCount, int outputsCount, {int? size}); int getEstimatedFeeWithFeeRate(Object wallet, int feeRate, int? amount, {int? outputsCount, int? size}); int getMaxCustomFeeRate(Object wallet); + + void setLedger(WalletBase wallet, Ledger ledger, LedgerDevice device); + Future> getHardwareWalletAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5}); } """; @@ -568,9 +578,11 @@ abstract class HavenAccountList { Future generateEthereum(bool hasImplementation) async { final outputFile = File(ethereumOutputPath); const ethereumCommonHeaders = """ +import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/erc20_token.dart'; +import 'package:cw_core/hardware/hardware_account_data.dart'; import 'package:cw_core/output_info.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/transaction_priority.dart'; @@ -579,6 +591,7 @@ import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:hive/hive.dart'; +import 'package:ledger_flutter/ledger_flutter.dart'; import 'package:web3dart/web3dart.dart'; """; @@ -589,6 +602,9 @@ import 'package:cw_evm/evm_chain_transaction_credentials.dart'; import 'package:cw_evm/evm_chain_transaction_info.dart'; import 'package:cw_evm/evm_chain_transaction_priority.dart'; import 'package:cw_evm/evm_chain_wallet_creation_credentials.dart'; +import 'package:cw_evm/evm_chain_hardware_wallet_service.dart'; +import 'package:cw_evm/evm_ledger_credentials.dart'; +import 'package:cw_evm/evm_chain_wallet.dart'; import 'package:cw_ethereum/ethereum_client.dart'; import 'package:cw_ethereum/ethereum_wallet.dart'; @@ -605,6 +621,7 @@ abstract class Ethereum { WalletCredentials createEthereumNewWalletCredentials({required String name, WalletInfo? walletInfo}); WalletCredentials createEthereumRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password}); WalletCredentials createEthereumRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password}); + WalletCredentials createEthereumHardwareWalletCredentials({required String name, required HardwareAccountData hwAccountData, WalletInfo? walletInfo}); String getAddress(WalletBase wallet); String getPrivateKey(WalletBase wallet); String getPublicKey(WalletBase wallet); @@ -638,6 +655,9 @@ abstract class Ethereum { void updateEtherscanUsageState(WalletBase wallet, bool isEnabled); Web3Client? getWeb3Client(WalletBase wallet); String getTokenAddress(CryptoCurrency asset); + + void setLedger(WalletBase wallet, Ledger ledger, LedgerDevice device); + Future> getHardwareWalletAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5}); } """; @@ -661,9 +681,11 @@ abstract class Ethereum { Future generatePolygon(bool hasImplementation) async { final outputFile = File(polygonOutputPath); const polygonCommonHeaders = """ +import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart'; import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/erc20_token.dart'; +import 'package:cw_core/hardware/hardware_account_data.dart'; import 'package:cw_core/output_info.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/transaction_priority.dart'; @@ -672,16 +694,20 @@ import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:hive/hive.dart'; +import 'package:ledger_flutter/ledger_flutter.dart'; import 'package:web3dart/web3dart.dart'; """; const polygonCWHeaders = """ import 'package:cw_evm/evm_chain_formatter.dart'; import 'package:cw_evm/evm_chain_mnemonics.dart'; +import 'package:cw_evm/evm_chain_transaction_credentials.dart'; import 'package:cw_evm/evm_chain_transaction_info.dart'; import 'package:cw_evm/evm_chain_transaction_priority.dart'; -import 'package:cw_evm/evm_chain_transaction_credentials.dart'; import 'package:cw_evm/evm_chain_wallet_creation_credentials.dart'; +import 'package:cw_evm/evm_chain_hardware_wallet_service.dart'; +import 'package:cw_evm/evm_ledger_credentials.dart'; +import 'package:cw_evm/evm_chain_wallet.dart'; import 'package:cw_polygon/polygon_client.dart'; import 'package:cw_polygon/polygon_wallet.dart'; @@ -698,6 +724,7 @@ abstract class Polygon { WalletCredentials createPolygonNewWalletCredentials({required String name, WalletInfo? walletInfo}); WalletCredentials createPolygonRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password}); WalletCredentials createPolygonRestoreWalletFromPrivateKey({required String name, required String privateKey, required String password}); + WalletCredentials createPolygonHardwareWalletCredentials({required String name, required HardwareAccountData hwAccountData, WalletInfo? walletInfo}); String getAddress(WalletBase wallet); String getPrivateKey(WalletBase wallet); String getPublicKey(WalletBase wallet); @@ -731,6 +758,9 @@ abstract class Polygon { void updatePolygonScanUsageState(WalletBase wallet, bool isEnabled); Web3Client? getWeb3Client(WalletBase wallet); String getTokenAddress(CryptoCurrency asset); + + void setLedger(WalletBase wallet, Ledger ledger, LedgerDevice device); + Future> getHardwareWalletAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5}); } """; From 55cdec810e472d3f487a99b9fb85edc299f6cd31 Mon Sep 17 00:00:00 2001 From: rottenwheel <92872541+rottenwheel@users.noreply.github.com> Date: Mon, 6 May 2024 11:32:31 +0000 Subject: [PATCH 208/241] fix: remove comma in OpenAlias title (#1430) --- lib/src/screens/settings/domain_lookups_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/screens/settings/domain_lookups_page.dart b/lib/src/screens/settings/domain_lookups_page.dart index 80849b8ea..aa7e68cd0 100644 --- a/lib/src/screens/settings/domain_lookups_page.dart +++ b/lib/src/screens/settings/domain_lookups_page.dart @@ -38,7 +38,7 @@ class DomainLookupsPage extends BasePage { value: _privacySettingsViewModel.looksUpUnstoppableDomains, onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsUnstoppableDomains(value)), SettingsSwitcherCell( - title: 'OpenAlias,', + title: 'OpenAlias', value: _privacySettingsViewModel.looksUpOpenAlias, onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsOpenAlias(value)), SettingsSwitcherCell( From 2a88b32eee6a97c7528c25d5b822e904711d8783 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Mon, 6 May 2024 20:11:18 +0100 Subject: [PATCH 209/241] fix: Add another node, handle errors gracefully (#1433) --- assets/tron_node_list.yml | 4 ++++ cw_tron/lib/tron_client.dart | 11 ++++++++--- lib/view_model/send/send_view_model.dart | 20 +++++++++++++++++--- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/assets/tron_node_list.yml b/assets/tron_node_list.yml index e30f79d53..4c67b920e 100644 --- a/assets/tron_node_list.yml +++ b/assets/tron_node_list.yml @@ -1,4 +1,8 @@ - uri: api.trongrid.io is_default: true + useSSL: true +- + uri: tron-rpc.publicnode.com:443 + is_default: false useSSL: true \ No newline at end of file diff --git a/cw_tron/lib/tron_client.dart b/cw_tron/lib/tron_client.dart index f03a8abce..73812f14c 100644 --- a/cw_tron/lib/tron_client.dart +++ b/cw_tron/lib/tron_client.dart @@ -367,7 +367,7 @@ class TronClient { ) async { // This is introduce to server as a limit in cases where feeLimit is 0 // The transaction signing will fail if the feeLimit is explicitly 0. - int defaultFeeLimit = 100000; + int defaultFeeLimit = 269000; final block = await _provider!.request(TronRequestGetNowBlock()); // Create the transfer contract @@ -401,8 +401,9 @@ class TronClient { final tronBalanceInt = tronBalance.toInt(); if (feeLimit > tronBalanceInt) { + final feeInTrx = TronHelper.fromSun(BigInt.parse(feeLimit.toString())); throw Exception( - 'You don\'t have enough TRX to cover the transaction fee for this transaction. Kindly top up.', + 'You don\'t have enough TRX to cover the transaction fee for this transaction. Kindly top up.\nTransaction fee: $feeInTrx TRX', ); } @@ -442,6 +443,9 @@ class TronClient { if (!request.isSuccess) { log("Tron TRC20 error: ${request.error} \n ${request.respose}"); + throw Exception( + 'An error occured while creating the transfer request. Please try again.', + ); } final feeLimit = await getFeeLimit( @@ -454,8 +458,9 @@ class TronClient { final tronBalanceInt = tronBalance.toInt(); if (feeLimit > tronBalanceInt) { + final feeInTrx = TronHelper.fromSun(BigInt.parse(feeLimit.toString())); throw Exception( - 'You don\'t have enough TRX to cover the transaction fee for this transaction. Kindly top up.', + 'You don\'t have enough TRX to cover the transaction fee for this transaction. Kindly top up. Transaction fee: $feeInTrx TRX', ); } diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 2a6bf553b..0d53c59cc 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -247,7 +247,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor wallet.type != WalletType.banano && wallet.type != WalletType.solana && wallet.type != WalletType.tron; - + @observable CryptoCurrency selectedCryptoCurrency; @@ -363,7 +363,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor } catch (e) { if (e is LedgerException) { final errorCode = e.errorCode.toRadixString(16); - final fallbackMsg = e.message.isNotEmpty ? e.message : "Unexpected Ledger Error Code: $errorCode"; + final fallbackMsg = + e.message.isNotEmpty ? e.message : "Unexpected Ledger Error Code: $errorCode"; final errorMsg = ledgerViewModel.interpretErrorCode(errorCode) ?? fallbackMsg; state = FailureState(errorMsg); @@ -444,7 +445,10 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor Object _credentials() { final priority = _settingsStore.priority[wallet.type]; - if (priority == null && wallet.type != WalletType.nano && wallet.type != WalletType.banano && wallet.type != WalletType.solana && + if (priority == null && + wallet.type != WalletType.nano && + wallet.type != WalletType.banano && + wallet.type != WalletType.solana && wallet.type != WalletType.tron) { throw Exception('Priority is null for wallet type: ${wallet.type}'); } @@ -570,6 +574,16 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor return errorMessage; } + if (walletType == WalletType.tron) { + if (errorMessage.contains('balance is not sufficient')) { + return S.current.do_not_have_enough_gas_asset(currency.toString()); + } + + if (errorMessage.contains('Transaction expired')) { + return 'An error occurred while processing the transaction. Kindly retry the transaction'; + } + } + if (walletType == WalletType.bitcoin || walletType == WalletType.litecoin || walletType == WalletType.bitcoinCash) { From cd41766e697a23f1d8c2945526825062daf573cd Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Mon, 6 May 2024 20:14:43 +0100 Subject: [PATCH 210/241] Desktop-Enhancements (#1434) * feat: Add minimum size for macos app * fix: Adjust font sizing and spaces in wallet list page and wallet selection dropdown --- cw_core/lib/window_size.dart | 22 +++++++++++++++++++ lib/main.dart | 3 +++ .../desktop_widgets/dropdown_item_widget.dart | 2 +- .../desktop_settings_page.dart | 2 +- .../screens/wallet_list/wallet_list_page.dart | 2 +- macos/Runner/AppDelegate.swift | 16 +++++++++++++- 6 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 cw_core/lib/window_size.dart diff --git a/cw_core/lib/window_size.dart b/cw_core/lib/window_size.dart new file mode 100644 index 000000000..a0f192f66 --- /dev/null +++ b/cw_core/lib/window_size.dart @@ -0,0 +1,22 @@ +import 'dart:io'; + +import 'package:flutter/services.dart'; + +const MethodChannel _channel = MethodChannel('com.cake_wallet/native_utils'); + +Future setDefaultMinimumWindowSize() async { + if (!Platform.isMacOS) return; + + try { + final result = await _channel.invokeMethod( + 'setMinWindowSize', + {'width': 500, 'height': 700}, + ) as bool; + + if (!result) { + print("Failed to set minimum window size."); + } + } on PlatformException catch (e) { + print("Failed to set minimum window size: '${e.message}'."); + } +} diff --git a/lib/main.dart b/lib/main.dart index b274c7a84..b2e32d7a9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -41,6 +41,7 @@ import 'package:uni_links/uni_links.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cw_core/cake_hive.dart'; +import 'package:cw_core/window_size.dart'; final navigatorKey = GlobalKey(); final rootKey = GlobalKey(); @@ -60,6 +61,8 @@ Future main() async { return true; }; + await setDefaultMinimumWindowSize(); + await CakeHive.close(); await initializeAppConfigs(); diff --git a/lib/src/screens/dashboard/desktop_widgets/dropdown_item_widget.dart b/lib/src/screens/dashboard/desktop_widgets/dropdown_item_widget.dart index aa7012ae5..f8f92dc08 100644 --- a/lib/src/screens/dashboard/desktop_widgets/dropdown_item_widget.dart +++ b/lib/src/screens/dashboard/desktop_widgets/dropdown_item_widget.dart @@ -22,7 +22,7 @@ class DropDownItemWidget extends StatelessWidget { child: Text( title, style: TextStyle( - fontSize: 22, + fontSize: 18, fontWeight: FontWeight.w500, color: Theme.of(context).extension()!.titleColor, ), diff --git a/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart b/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart index 1d6168e4a..6896177e4 100644 --- a/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart +++ b/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart @@ -38,7 +38,7 @@ class _DesktopSettingsPageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( - padding: const EdgeInsets.all(24), + padding: const EdgeInsets.fromLTRB(24, 24, 24, 4), child: Text( S.current.settings, style: textXLarge(), diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index 601f5d878..9a0c29564 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -171,7 +171,7 @@ class WalletListBodyState extends State { maxLines: null, softWrap: true, style: TextStyle( - fontSize: 20, + fontSize: DeviceInfo.instance.isDesktop ? 18 : 20, fontWeight: FontWeight.w500, color: Theme.of(context) .extension()! diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift index 0c8973175..cd7f006e6 100644 --- a/macos/Runner/AppDelegate.swift +++ b/macos/Runner/AppDelegate.swift @@ -24,7 +24,21 @@ class AppDelegate: FlutterAppDelegate { } result(secRandom(count: count)) - + case "setMinWindowSize": + guard let self = self else { + result(false) + return + } + if let arguments = call.arguments as? [String: Any], + let width = arguments["width"] as? Double, + let height = arguments["height"] as? Double { + DispatchQueue.main.async { + self.mainFlutterWindow?.minSize = CGSize(width: width, height: height) + } + result(true) + } else { + result(false) + } default: result(FlutterMethodNotImplemented) } From 3f3cd10158245f550f84db129e226a95a13e4c78 Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 6 May 2024 22:16:25 +0300 Subject: [PATCH 211/241] thor name to address lookup (#1390) * thor name to address lookup * minor fix [skip ci] * Addressing code review comments * minor fix --- lib/entities/parse_address_from_domain.dart | 24 ++++++++---- lib/entities/parsed_address.dart | 11 +++++- .../provider/thorchain_exchange.provider.dart | 35 +++++++++++++++-- lib/src/screens/exchange/exchange_page.dart | 38 ++++++++----------- .../widgets/extract_address_from_parsed.dart | 5 +++ lib/view_model/send/output.dart | 4 +- 6 files changed, 82 insertions(+), 35 deletions(-) diff --git a/lib/entities/parse_address_from_domain.dart b/lib/entities/parse_address_from_domain.dart index f729e6392..409724c6e 100644 --- a/lib/entities/parse_address_from_domain.dart +++ b/lib/entities/parse_address_from_domain.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/entities/openalias_record.dart'; import 'package:cake_wallet/entities/parsed_address.dart'; import 'package:cake_wallet/entities/unstoppable_domain_address.dart'; import 'package:cake_wallet/entities/emoji_string_extension.dart'; +import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart'; import 'package:cake_wallet/mastodon/mastodon_api.dart'; import 'package:cake_wallet/nostr/nostr_api.dart'; import 'package:cake_wallet/store/settings_store.dart'; @@ -71,8 +72,8 @@ class AddressResolver { return emailRegex.hasMatch(address); } - // TODO: refactor this to take Crypto currency instead of ticker, or at least pass in the tag as well - Future resolve(BuildContext context, String text, String ticker) async { + Future resolve(BuildContext context, String text, CryptoCurrency currency) async { + final ticker = currency.title; try { if (text.startsWith('@') && !text.substring(1).contains('@')) { if (settingsStore.lookupsTwitter) { @@ -116,8 +117,7 @@ class AddressResolver { await MastodonAPI.lookupUserByUserName(userName: userName, apiHost: hostName); if (mastodonUser != null) { - String? addressFromBio = extractAddressByType( - raw: mastodonUser.note, type: CryptoCurrency.fromString(ticker)); + String? addressFromBio = extractAddressByType(raw: mastodonUser.note, type: currency); if (addressFromBio != null) { return ParsedAddress.fetchMastodonAddress( @@ -131,8 +131,8 @@ class AddressResolver { if (pinnedPosts.isNotEmpty) { final userPinnedPostsText = pinnedPosts.map((item) => item.content).join('\n'); - String? addressFromPinnedPost = extractAddressByType( - raw: userPinnedPostsText, type: CryptoCurrency.fromString(ticker)); + String? addressFromPinnedPost = + extractAddressByType(raw: userPinnedPostsText, type: currency); if (addressFromPinnedPost != null) { return ParsedAddress.fetchMastodonAddress( @@ -162,6 +162,16 @@ class AddressResolver { } } } + + final thorChainAddress = await ThorChainExchangeProvider.lookupAddressByName(text); + if (thorChainAddress != null) { + String? address = + thorChainAddress[ticker] ?? (ticker == 'RUNE' ? thorChainAddress['THOR'] : null); + if (address != null) { + return ParsedAddress.thorChainAddress(address: address, name: text); + } + } + final formattedName = OpenaliasRecord.formatDomainName(text); final domainParts = formattedName.split('.'); final name = domainParts.last; @@ -204,7 +214,7 @@ class AddressResolver { if (nostrUserData != null) { String? addressFromBio = extractAddressByType( - raw: nostrUserData.about, type: CryptoCurrency.fromString(ticker)); + raw: nostrUserData.about, type: currency); if (addressFromBio != null) { return ParsedAddress.nostrAddress( address: addressFromBio, diff --git a/lib/entities/parsed_address.dart b/lib/entities/parsed_address.dart index fc8ab2440..cfd69acbe 100644 --- a/lib/entities/parsed_address.dart +++ b/lib/entities/parsed_address.dart @@ -11,7 +11,8 @@ enum ParseFrom { ens, contact, mastodon, - nostr + nostr, + thorChain } class ParsedAddress { @@ -133,6 +134,14 @@ class ParsedAddress { ); } + factory ParsedAddress.thorChainAddress({required String address, required String name}) { + return ParsedAddress( + addresses: [address], + name: name, + parseFrom: ParseFrom.thorChain, + ); + } + final List addresses; final String name; final String description; diff --git a/lib/exchange/provider/thorchain_exchange.provider.dart b/lib/exchange/provider/thorchain_exchange.provider.dart index 32dce7db8..826e203f3 100644 --- a/lib/exchange/provider/thorchain_exchange.provider.dart +++ b/lib/exchange/provider/thorchain_exchange.provider.dart @@ -34,11 +34,13 @@ class ThorChainExchangeProvider extends ExchangeProvider { static final isRefundAddressSupported = [CryptoCurrency.eth]; - static const _baseURL = 'thornode.ninerealms.com'; + static const _baseNodeURL = 'thornode.ninerealms.com'; + static const _baseURL = 'midgard.ninerealms.com'; static const _quotePath = '/thorchain/quote/swap'; static const _txInfoPath = '/thorchain/tx/status/'; static const _affiliateName = 'cakewallet'; static const _affiliateBps = '175'; + static const _nameLookUpPath= 'v2/thorname/lookup/'; final Box tradesStore; @@ -154,7 +156,7 @@ class ThorChainExchangeProvider extends ExchangeProvider { Future findTradeById({required String id}) async { if (id.isEmpty) throw Exception('Trade id is empty'); final formattedId = id.startsWith('0x') ? id.substring(2) : id; - final uri = Uri.https(_baseURL, '$_txInfoPath$formattedId'); + final uri = Uri.https(_baseNodeURL, '$_txInfoPath$formattedId'); final response = await http.get(uri); if (response.statusCode == 404) { @@ -206,8 +208,35 @@ class ThorChainExchangeProvider extends ExchangeProvider { ); } + static Future?>? lookupAddressByName(String name) async { + final uri = Uri.https(_baseURL, '$_nameLookUpPath$name'); + final response = await http.get(uri); + + if (response.statusCode != 200) { + return null; + } + + final body = json.decode(response.body) as Map; + final entries = body['entries'] as List?; + + if (entries == null || entries.isEmpty) { + return null; + } + + Map chainToAddressMap = {}; + + for (final entry in entries) { + final chain = entry['chain'] as String; + final address = entry['address'] as String; + chainToAddressMap[chain] = address; + } + + return chainToAddressMap; + } + + Future> _getSwapQuote(Map params) async { - Uri uri = Uri.https(_baseURL, _quotePath, params); + Uri uri = Uri.https(_baseNodeURL, _quotePath, params); final response = await http.get(uri); diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index d9e119038..c4e4aa199 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -330,10 +330,12 @@ class ExchangePage extends BasePage { void applyTemplate( BuildContext context, ExchangeViewModel exchangeViewModel, ExchangeTemplate template) async { - exchangeViewModel.changeDepositCurrency( - currency: CryptoCurrency.fromString(template.depositCurrency)); - exchangeViewModel.changeReceiveCurrency( - currency: CryptoCurrency.fromString(template.receiveCurrency)); + + final depositCryptoCurrency = CryptoCurrency.fromString(template.depositCurrency); + final receiveCryptoCurrency = CryptoCurrency.fromString(template.receiveCurrency); + + exchangeViewModel.changeDepositCurrency(currency: depositCryptoCurrency); + exchangeViewModel.changeReceiveCurrency(currency: receiveCryptoCurrency); exchangeViewModel.changeDepositAmount(amount: template.amount); exchangeViewModel.depositAddress = template.depositAddress; @@ -342,12 +344,10 @@ class ExchangePage extends BasePage { exchangeViewModel.isFixedRateMode = false; var domain = template.depositAddress; - var ticker = template.depositCurrency.toLowerCase(); - exchangeViewModel.depositAddress = await fetchParsedAddress(context, domain, ticker); + exchangeViewModel.depositAddress = await fetchParsedAddress(context, domain, depositCryptoCurrency); domain = template.receiveAddress; - ticker = template.receiveCurrency.toLowerCase(); - exchangeViewModel.receiveAddress = await fetchParsedAddress(context, domain, ticker); + exchangeViewModel.receiveAddress = await fetchParsedAddress(context, domain, receiveCryptoCurrency); } void _setReactions(BuildContext context, ExchangeViewModel exchangeViewModel) { @@ -519,16 +519,14 @@ class ExchangePage extends BasePage { _depositAddressFocus.addListener(() async { if (!_depositAddressFocus.hasFocus && depositAddressController.text.isNotEmpty) { final domain = depositAddressController.text; - final ticker = exchangeViewModel.depositCurrency.title.toLowerCase(); - exchangeViewModel.depositAddress = await fetchParsedAddress(context, domain, ticker); + exchangeViewModel.depositAddress = await fetchParsedAddress(context, domain, exchangeViewModel.depositCurrency); } }); _receiveAddressFocus.addListener(() async { if (!_receiveAddressFocus.hasFocus && receiveAddressController.text.isNotEmpty) { final domain = receiveAddressController.text; - final ticker = exchangeViewModel.receiveCurrency.title.toLowerCase(); - exchangeViewModel.receiveAddress = await fetchParsedAddress(context, domain, ticker); + exchangeViewModel.receiveAddress = await fetchParsedAddress(context, domain, exchangeViewModel.receiveCurrency); } }); @@ -575,8 +573,8 @@ class ExchangePage extends BasePage { } } - Future fetchParsedAddress(BuildContext context, String domain, String ticker) async { - final parsedAddress = await getIt.get().resolve(context, domain, ticker); + Future fetchParsedAddress(BuildContext context, String domain, CryptoCurrency currency) async { + final parsedAddress = await getIt.get().resolve(context, domain, currency); final address = await extractAddressFromParsed(context, parsedAddress); return address; } @@ -663,15 +661,13 @@ class ExchangePage extends BasePage { addressTextFieldValidator: AddressValidator(type: exchangeViewModel.depositCurrency), onPushPasteButton: (context) async { final domain = exchangeViewModel.depositAddress; - final ticker = exchangeViewModel.depositCurrency.title.toLowerCase(); exchangeViewModel.depositAddress = - await fetchParsedAddress(context, domain, ticker); + await fetchParsedAddress(context, domain, exchangeViewModel.depositCurrency); }, onPushAddressBookButton: (context) async { final domain = exchangeViewModel.depositAddress; - final ticker = exchangeViewModel.depositCurrency.title.toLowerCase(); exchangeViewModel.depositAddress = - await fetchParsedAddress(context, domain, ticker); + await fetchParsedAddress(context, domain, exchangeViewModel.depositCurrency); }, )); @@ -712,15 +708,13 @@ class ExchangePage extends BasePage { addressTextFieldValidator: AddressValidator(type: exchangeViewModel.receiveCurrency), onPushPasteButton: (context) async { final domain = exchangeViewModel.receiveAddress; - final ticker = exchangeViewModel.receiveCurrency.title.toLowerCase(); exchangeViewModel.receiveAddress = - await fetchParsedAddress(context, domain, ticker); + await fetchParsedAddress(context, domain, exchangeViewModel.receiveCurrency); }, onPushAddressBookButton: (context) async { final domain = exchangeViewModel.receiveAddress; - final ticker = exchangeViewModel.receiveCurrency.title.toLowerCase(); exchangeViewModel.receiveAddress = - await fetchParsedAddress(context, domain, ticker); + await fetchParsedAddress(context, domain, exchangeViewModel.receiveCurrency); }, )); diff --git a/lib/src/screens/send/widgets/extract_address_from_parsed.dart b/lib/src/screens/send/widgets/extract_address_from_parsed.dart index eb997c11b..9ce3ca2b1 100644 --- a/lib/src/screens/send/widgets/extract_address_from_parsed.dart +++ b/lib/src/screens/send/widgets/extract_address_from_parsed.dart @@ -56,6 +56,11 @@ Future extractAddressFromParsed( profileImageUrl = parsedAddress.profileImageUrl; profileName = parsedAddress.profileName; break; + case ParseFrom.thorChain: + title = S.of(context).address_detected; + content = S.of(context).extracted_address_content('${parsedAddress.name} (ThorChain)'); + address = parsedAddress.addresses.first; + break; case ParseFrom.yatRecord: if (parsedAddress.name.isEmpty) { title = S.of(context).yat_error; diff --git a/lib/view_model/send/output.dart b/lib/view_model/send/output.dart index a79baea48..d6f2589c1 100644 --- a/lib/view_model/send/output.dart +++ b/lib/view_model/send/output.dart @@ -296,8 +296,8 @@ abstract class OutputBase with Store { Future fetchParsedAddress(BuildContext context) async { final domain = address; - final ticker = cryptoCurrencyHandler().title.toLowerCase(); - parsedAddress = await getIt.get().resolve(context, domain, ticker); + final currency = cryptoCurrencyHandler(); + parsedAddress = await getIt.get().resolve(context, domain, currency); extractedAddress = await extractAddressFromParsed(context, parsedAddress); note = parsedAddress.description; } From e5be7372362d1ca443ab4434ae5401f2ff04f703 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Mon, 6 May 2024 12:55:05 -0700 Subject: [PATCH 212/241] bio auth on mac + package updates for 3.19.3/5 (#1398) * bio auth mac fix * remove comment and change duration from 2 to 0 * cherry pick previous changes * workaround for secure storage bug on mac * bump version to 3.19.5 (because breez will need this version anyways) * some code cleanup * some changess didn't get saved * just documenting the issue [skip ci] * undo accidental removal + minor code cleanup * merge conflicts * Minor UI change [skip ci] --------- Co-authored-by: Omar Hatem --- .github/workflows/pr_test_build.yml | 2 +- cw_bitcoin/pubspec.yaml | 5 +- cw_bitcoin_cash/pubspec.yaml | 5 +- cw_core/pubspec.yaml | 4 +- cw_ethereum/pubspec.yaml | 4 +- cw_evm/pubspec.yaml | 3 +- cw_haven/pubspec.yaml | 5 +- cw_monero/pubspec.yaml | 5 +- cw_nano/pubspec.yaml | 5 +- cw_polygon/pubspec.yaml | 4 +- cw_solana/pubspec.yaml | 5 +- lib/core/auth_service.dart | 13 +- lib/core/backup_service.dart | 17 +- lib/core/key_service.dart | 3 +- lib/core/secure_storage.dart | 11 + lib/entities/biometric_auth.dart | 27 +- lib/entities/fs_migration.dart | 5 +- lib/entities/get_encryption_key.dart | 4 +- lib/locales/hausa_intl.dart | 64 ++ lib/locales/yoruba_intl.dart | 939 ++++++++++-------- .../desktop_settings_page.dart | 60 +- .../settings/security_backup_page.dart | 4 +- lib/src/screens/settings/tor_page.dart | 4 +- .../support_chat/widgets/chatwoot_widget.dart | 4 +- .../validable_annotated_editable_text.dart | 14 +- lib/store/settings_store.dart | 37 +- lib/view_model/auth_view_model.dart | 12 +- .../edit_backup_password_view_model.dart | 4 +- macos/Flutter/GeneratedPluginRegistrant.swift | 2 + macos/Podfile.lock | 6 + pubspec_base.yaml | 6 +- pubspec_description.yaml | 2 +- 32 files changed, 730 insertions(+), 555 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 46924cb35..23902f110 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -42,7 +42,7 @@ jobs: - name: Flutter action uses: subosito/flutter-action@v1 with: - flutter-version: "3.10.x" + flutter-version: "3.19.5" channel: stable - name: Install package dependencies diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index 9adf77652..84254b5b5 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -43,11 +43,14 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_bitcoin_cash/pubspec.yaml b/cw_bitcoin_cash/pubspec.yaml index 37827f1ba..ceef539c3 100644 --- a/cw_bitcoin_cash/pubspec.yaml +++ b/cw_bitcoin_cash/pubspec.yaml @@ -39,10 +39,13 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml index 36fe9967e..51d671dc7 100644 --- a/cw_core/pubspec.yaml +++ b/cw_core/pubspec.yaml @@ -28,11 +28,13 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 hive_generator: ^2.0.1 +dependency_overrides: + watcher: ^1.1.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_ethereum/pubspec.yaml b/cw_ethereum/pubspec.yaml index 5f78fba3d..462e1d77e 100644 --- a/cw_ethereum/pubspec.yaml +++ b/cw_ethereum/pubspec.yaml @@ -24,11 +24,13 @@ dependency_overrides: git: url: https://github.com/cake-tech/web3dart.git ref: cake + watcher: ^1.1.0 dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 + flutter: # assets: # - images/a_dot_burr.jpeg diff --git a/cw_evm/pubspec.yaml b/cw_evm/pubspec.yaml index fb0384064..e4b29b676 100644 --- a/cw_evm/pubspec.yaml +++ b/cw_evm/pubspec.yaml @@ -36,11 +36,12 @@ dependency_overrides: git: url: https://github.com/cake-tech/ledger-flutter.git ref: cake + watcher: ^1.1.0 dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 flutter_lints: ^2.0.0 diff --git a/cw_haven/pubspec.yaml b/cw_haven/pubspec.yaml index c215ab779..d868c986d 100644 --- a/cw_haven/pubspec.yaml +++ b/cw_haven/pubspec.yaml @@ -24,11 +24,14 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 build_resolvers: ^2.0.9 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_monero/pubspec.yaml b/cw_monero/pubspec.yaml index a6fe7f967..c49a541ab 100644 --- a/cw_monero/pubspec.yaml +++ b/cw_monero/pubspec.yaml @@ -26,11 +26,14 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_nano/pubspec.yaml b/cw_nano/pubspec.yaml index a4b8732fd..768c1bb4e 100644 --- a/cw_nano/pubspec.yaml +++ b/cw_nano/pubspec.yaml @@ -32,10 +32,13 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_polygon/pubspec.yaml b/cw_polygon/pubspec.yaml index dbef40b46..8421562b4 100644 --- a/cw_polygon/pubspec.yaml +++ b/cw_polygon/pubspec.yaml @@ -28,12 +28,14 @@ dependency_overrides: git: url: https://github.com/cake-tech/web3dart.git ref: cake + watcher: ^1.1.0 dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.0 - build_runner: ^2.1.11 + build_runner: ^2.4.7 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_solana/pubspec.yaml b/cw_solana/pubspec.yaml index 7e24983bf..6b59282b4 100644 --- a/cw_solana/pubspec.yaml +++ b/cw_solana/pubspec.yaml @@ -26,10 +26,13 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.0 - build_runner: ^2.1.11 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + flutter: # assets: # - images/a_dot_burr.jpeg diff --git a/lib/core/auth_service.dart b/lib/core/auth_service.dart index 48610784c..66943bb7f 100644 --- a/lib/core/auth_service.dart +++ b/lib/core/auth_service.dart @@ -42,12 +42,7 @@ class AuthService with Store { Future setPassword(String password) async { final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final encodedPassword = encodedPinCode(pin: password); - // secure storage has a weird bug on macOS, where overwriting a key doesn't work, unless - // we delete what's there first: - if (Platform.isMacOS) { - await secureStorage.delete(key: key); - } - await secureStorage.write(key: key, value: encodedPassword); + await writeSecureStorage(secureStorage, key: key, value: encodedPassword); } Future canAuthenticate() async { @@ -74,7 +69,11 @@ class AuthService with Store { void saveLastAuthTime() { int timestamp = DateTime.now().millisecondsSinceEpoch; - secureStorage.write(key: SecureKey.lastAuthTimeMilliseconds, value: timestamp.toString()); + writeSecureStorage( + secureStorage, + key: SecureKey.lastAuthTimeMilliseconds, + value: timestamp.toString(), + ); } Future requireAuth() async { diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 2ec5f293d..d1092b024 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/themes/theme_list.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cw_core/wallet_type.dart'; @@ -275,7 +276,7 @@ class BackupService { if (currentTransactionPriorityKeyLegacy != null) await _sharedPreferences.setInt( PreferencesKey.currentTransactionPriorityKeyLegacy, currentTransactionPriorityKeyLegacy); - + if (currentBitcoinElectrumSererId != null) await _sharedPreferences.setInt( PreferencesKey.currentBitcoinElectrumSererIdKey, currentBitcoinElectrumSererId); @@ -373,16 +374,15 @@ class BackupService { final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPassword = keychainJSON[backupPasswordKey] as String; - await _flutterSecureStorage.delete(key: backupPasswordKey); - await _flutterSecureStorage.write(key: backupPasswordKey, value: backupPassword); + await writeSecureStorage(_flutterSecureStorage, key: backupPasswordKey, value: backupPassword); keychainWalletsInfo.forEach((dynamic rawInfo) async { final info = rawInfo as Map; await importWalletKeychainInfo(info); }); - await _flutterSecureStorage.delete(key: pinCodeKey); - await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin)); + await writeSecureStorage(_flutterSecureStorage, + key: pinCodeKey, value: encodedPinCode(pin: decodedPin)); keychainDumpFile.deleteSync(); } @@ -401,16 +401,15 @@ class BackupService { final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPassword = keychainJSON[backupPasswordKey] as String; - await _flutterSecureStorage.delete(key: backupPasswordKey); - await _flutterSecureStorage.write(key: backupPasswordKey, value: backupPassword); + await writeSecureStorage(_flutterSecureStorage, key: backupPasswordKey, value: backupPassword); keychainWalletsInfo.forEach((dynamic rawInfo) async { final info = rawInfo as Map; await importWalletKeychainInfo(info); }); - await _flutterSecureStorage.delete(key: pinCodeKey); - await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin)); + await writeSecureStorage(_flutterSecureStorage, + key: pinCodeKey, value: encodedPinCode(pin: decodedPin)); keychainDumpFile.deleteSync(); } diff --git a/lib/core/key_service.dart b/lib/core/key_service.dart index f829c22b5..ba2da4de6 100644 --- a/lib/core/key_service.dart +++ b/lib/core/key_service.dart @@ -20,8 +20,7 @@ class KeyService { key: SecretStoreKey.moneroWalletPassword, walletName: walletName); final encodedPassword = encodeWalletPassword(password: password); - await _secureStorage.delete(key: key); - await _secureStorage.write(key: key, value: encodedPassword); + await writeSecureStorage(_secureStorage, key: key, value: encodedPassword); } Future deleteWalletPassword({required String walletName}) async { diff --git a/lib/core/secure_storage.dart b/lib/core/secure_storage.dart index 4d9334a10..5afb36d29 100644 --- a/lib/core/secure_storage.dart +++ b/lib/core/secure_storage.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:io'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; // For now, we can create a utility function to handle this. // @@ -25,3 +26,13 @@ Future readSecureStorage(FlutterSecureStorage secureStorage, String key return result; } + +Future writeSecureStorage(FlutterSecureStorage secureStorage, + {required String key, required String value}) async { + // delete the value before writing on macOS because of a weird bug + // https://github.com/mogol/flutter_secure_storage/issues/581 + if (Platform.isMacOS) { + await secureStorage.delete(key: key); + } + await secureStorage.write(key: key, value: value); +} diff --git a/lib/entities/biometric_auth.dart b/lib/entities/biometric_auth.dart index 4b2bfd906..353cd0492 100644 --- a/lib/entities/biometric_auth.dart +++ b/lib/entities/biometric_auth.dart @@ -1,32 +1,29 @@ -import 'package:local_auth/local_auth.dart'; import 'package:flutter/services.dart'; -import 'package:cake_wallet/generated/i18n.dart'; +import 'package:flutter_local_authentication/flutter_local_authentication.dart'; class BiometricAuth { - final _localAuth = LocalAuthentication(); + final _flutterLocalAuthenticationPlugin = FlutterLocalAuthentication(); Future isAuthenticated() async { try { - return await _localAuth.authenticate( - localizedReason: S.current.biometric_auth_reason, - options: AuthenticationOptions( - biometricOnly: true, - useErrorDialogs: true, - stickyAuth: false)); - } on PlatformException catch (e) { + final authenticated = await _flutterLocalAuthenticationPlugin.authenticate(); + return authenticated; + } catch (e) { print(e); } - return false; } Future canCheckBiometrics() async { + bool canAuthenticate; try { - return await _localAuth.canCheckBiometrics; - } on PlatformException catch (e) { - print(e); + canAuthenticate = await _flutterLocalAuthenticationPlugin.canAuthenticate(); + await _flutterLocalAuthenticationPlugin.setTouchIDAuthenticationAllowableReuseDuration(0); + } catch (error) { + print("Exception checking support. $error"); + canAuthenticate = false; } - return false; + return canAuthenticate; } } \ No newline at end of file diff --git a/lib/entities/fs_migration.dart b/lib/entities/fs_migration.dart index 4280949cd..869ed66ff 100644 --- a/lib/entities/fs_migration.dart +++ b/lib/entities/fs_migration.dart @@ -1,5 +1,6 @@ import 'dart:io'; import 'dart:convert'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:collection/collection.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -147,8 +148,8 @@ Future ios_migrate_pin() async { final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final encodedPassword = encodedPinCode(pin: pinPassword); - await flutterSecureStorage.delete(key: key); - await flutterSecureStorage.write(key: key, value: encodedPassword); + await writeSecureStorage(flutterSecureStorage, key: key, value: encodedPassword); + await prefs.setBool('ios_migration_pin_completed', true); } diff --git a/lib/entities/get_encryption_key.dart b/lib/entities/get_encryption_key.dart index a32d4e311..04c3a65f7 100644 --- a/lib/entities/get_encryption_key.dart +++ b/lib/entities/get_encryption_key.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:cw_core/cake_hive.dart'; @@ -10,8 +11,7 @@ Future> getEncryptionKey( key = CakeHive.generateSecureKey(); final keyStringified = key.join(','); String storageKey = 'transactionDescriptionsBoxKey'; - await secureStorage.delete(key: storageKey); - await secureStorage.write(key: storageKey, value: keyStringified); + await writeSecureStorage(secureStorage, key: storageKey, value: keyStringified); } else { key = stringifiedKey.split(',').map((i) => int.parse(i)).toList(); } diff --git a/lib/locales/hausa_intl.dart b/lib/locales/hausa_intl.dart index 749d39a4d..6cf757b60 100644 --- a/lib/locales/hausa_intl.dart +++ b/lib/locales/hausa_intl.dart @@ -751,6 +751,50 @@ class HaMaterialLocalizations extends GlobalMaterialLocalizations { @override String get scrimOnTapHintRaw => "Scrip on Tap"; + + @override + // TODO: implement collapsedHint + String get collapsedHint => "collapsedHint"; + + @override + // TODO: implement expandedHint + String get expandedHint => "expandedHint"; + + @override + // TODO: implement expansionTileCollapsedHint + String get expansionTileCollapsedHint => "expansionTileCollapsedHint"; + + @override + // TODO: implement expansionTileCollapsedTapHint + String get expansionTileCollapsedTapHint => "expansionTileCollapsedTapHint"; + + @override + // TODO: implement expansionTileExpandedHint + String get expansionTileExpandedHint => "expansionTileExpandedHint"; + + @override + // TODO: implement expansionTileExpandedTapHint + String get expansionTileExpandedTapHint => "expansionTileExpandedTapHint"; + + @override + // TODO: implement scanTextButtonLabel + String get scanTextButtonLabel => "scanTextButtonLabel"; + + @override + // TODO: implement lookUpButtonLabel + String get lookUpButtonLabel => "lookUpButtonLabel"; + + @override + // TODO: implement menuDismissLabel + String get menuDismissLabel => "menuDismissLabel"; + + @override + // TODO: implement searchWebButtonLabel + String get searchWebButtonLabel => "searchWebButtonLabel"; + + @override + // TODO: implement shareButtonLabel + String get shareButtonLabel => "shareButtonLabel"; } /// Cupertino Support @@ -955,4 +999,24 @@ class HaCupertinoLocalizations extends GlobalCupertinoLocalizations { @override String get noSpellCheckReplacementsLabel => ""; + + @override + // TODO: implement clearButtonLabel + String get clearButtonLabel => "clearButtonLabel"; + + @override + // TODO: implement lookUpButtonLabel + String get lookUpButtonLabel => "lookUpButtonLabel"; + + @override + // TODO: implement menuDismissLabel + String get menuDismissLabel => "menuDismissLabel"; + + @override + // TODO: implement searchWebButtonLabel + String get searchWebButtonLabel => "searchWebButtonLabel"; + + @override + // TODO: implement shareButtonLabel + String get shareButtonLabel => "shareButtonLabel"; } diff --git a/lib/locales/yoruba_intl.dart b/lib/locales/yoruba_intl.dart index f16188529..3c720b80e 100644 --- a/lib/locales/yoruba_intl.dart +++ b/lib/locales/yoruba_intl.dart @@ -1,4 +1,3 @@ - import 'dart:async'; import 'package:flutter/cupertino.dart'; @@ -164,62 +163,62 @@ const yoDateSymbols = { 'ọjọ́ Àbámẹ́ta', ], 'STANDALONEWEEKDAYS': [ -'Ọjọ́ Ajé', -'Ọjọ́ Ìsẹ́gun', -'Ọjọ́ Ìsẹ́gun-Ẹtì', -'Ọjọ́ Ìsẹ́gun-Ọ̀rú', -'Ọjọ́ Àìkú', -'Ọjọ́ Jímọ̀', -'Ọjọ́ Àbámẹ́ta', -], -'SHORTWEEKDAYS': [ -'Ajé', -'Ìsẹ́gun', -'Ìsẹ́gun-Ẹtì', -'Ìsẹ́gun-Ọ̀rú', -'Àìkú', -'Jímọ̀', -'Àbámẹ́ta', -], -'STANDALONESHORTWEEKDAYS': [ -'Ajé', -'Ìsẹ́gun', -'Ìsẹ́gun-Ẹtì', -'Ìsẹ́gun-Ọ̀rú', -'Àìkú', -'Jímọ̀', -'Àbámẹ́ta', -], -'NARROWWEEKDAYS': [ -'A', -'A', -'Ì', -'A', -'À', -'J', -'À', -], -'STANDALONENARROWWEEKDAYS': [ -'A', -'A', -'Ì', -'A', -'À', -'J', -'À', -], -'SHORTQUARTERS': [ -'K1', -'K2', -'K3', -'K4', -], -'QUARTERS': [ -'1. kwata', -'2. kwata', -'3. kwata', -'4. kwata', -], + 'Ọjọ́ Ajé', + 'Ọjọ́ Ìsẹ́gun', + 'Ọjọ́ Ìsẹ́gun-Ẹtì', + 'Ọjọ́ Ìsẹ́gun-Ọ̀rú', + 'Ọjọ́ Àìkú', + 'Ọjọ́ Jímọ̀', + 'Ọjọ́ Àbámẹ́ta', + ], + 'SHORTWEEKDAYS': [ + 'Ajé', + 'Ìsẹ́gun', + 'Ìsẹ́gun-Ẹtì', + 'Ìsẹ́gun-Ọ̀rú', + 'Àìkú', + 'Jímọ̀', + 'Àbámẹ́ta', + ], + 'STANDALONESHORTWEEKDAYS': [ + 'Ajé', + 'Ìsẹ́gun', + 'Ìsẹ́gun-Ẹtì', + 'Ìsẹ́gun-Ọ̀rú', + 'Àìkú', + 'Jímọ̀', + 'Àbámẹ́ta', + ], + 'NARROWWEEKDAYS': [ + 'A', + 'A', + 'Ì', + 'A', + 'À', + 'J', + 'À', + ], + 'STANDALONENARROWWEEKDAYS': [ + 'A', + 'A', + 'Ì', + 'A', + 'À', + 'J', + 'À', + ], + 'SHORTQUARTERS': [ + 'K1', + 'K2', + 'K3', + 'K4', + ], + 'QUARTERS': [ + '1. kwata', + '2. kwata', + '3. kwata', + '4. kwata', + ], 'AMPMS': [ 'a.m.', 'p.m.', @@ -316,339 +315,339 @@ class YoMaterialLocalizations extends GlobalMaterialLocalizations { }); // #docregion Getters -@override -String get moreButtonTooltip => r'Kò sí ìròhùn tí ó múni'; + @override + String get moreButtonTooltip => r'Kò sí ìròhùn tí ó múni'; -@override -String get aboutListTileTitleRaw => r'Fun Àpótí àwọn $applicationname'; + @override + String get aboutListTileTitleRaw => r'Fun Àpótí àwọn $applicationname'; -@override -String get alertDialogLabel => r'Ìròhùn Àlàyé'; + @override + String get alertDialogLabel => r'Ìròhùn Àlàyé'; // #enddocregion Getters -@override -String get anteMeridiemAbbreviation => r'AM'; + @override + String get anteMeridiemAbbreviation => r'AM'; -@override -String get backButtonTooltip => r'Fíran'; + @override + String get backButtonTooltip => r'Fíran'; -@override -String get cancelButtonLabel => r'FAGILE'; + @override + String get cancelButtonLabel => r'FAGILE'; -@override -String get closeButtonLabel => r'KÚ'; + @override + String get closeButtonLabel => r'KÚ'; -@override -String get closeButtonTooltip => r'Kú'; + @override + String get closeButtonTooltip => r'Kú'; -@override -String get collapsedIconTapHint => r'Tá'; + @override + String get collapsedIconTapHint => r'Tá'; -@override -String get continueButtonLabel => r'TÓ WÁ'; + @override + String get continueButtonLabel => r'TÓ WÁ'; -@override -String get copyButtonLabel => r'DÚPLÍKÉTÍ'; + @override + String get copyButtonLabel => r'DÚPLÍKÉTÍ'; -@override -String get cutButtonLabel => r'TÒ'; + @override + String get cutButtonLabel => r'TÒ'; -@override -String get deleteButtonTooltip => r'Máa kú'; + @override + String get deleteButtonTooltip => r'Máa kú'; -@override -String get dialogLabel => r'Ìròhùn'; + @override + String get dialogLabel => r'Ìròhùn'; -@override -String get drawerLabel => r'Àgbèjọ àwọn àpọ̀tí'; + @override + String get drawerLabel => r'Àgbèjọ àwọn àpọ̀tí'; -@override -String get expandedIconTapHint => r'Tá'; + @override + String get expandedIconTapHint => r'Tá'; -@override -String get firstPageTooltip => r'Ojú ewe'; + @override + String get firstPageTooltip => r'Ojú ewe'; -@override -String get hideAccountsLabel => r'Fí èrò àpótí wáyé sílẹ̀'; + @override + String get hideAccountsLabel => r'Fí èrò àpótí wáyé sílẹ̀'; -@override -String get lastPageTooltip => r'Ojú ayé'; + @override + String get lastPageTooltip => r'Ojú ayé'; -@override -String get licensesPageTitle => r'Ìròhùn Ọdún'; + @override + String get licensesPageTitle => r'Ìròhùn Ọdún'; -@override -String get modalBarrierDismissLabel => r'Sọ'; + @override + String get modalBarrierDismissLabel => r'Sọ'; -@override -String get nextMonthTooltip => r'Oṣù kọja'; + @override + String get nextMonthTooltip => r'Oṣù kọja'; -@override -String get nextPageTooltip => r'Ojú ọjọ́ kẹta'; + @override + String get nextPageTooltip => r'Ojú ọjọ́ kẹta'; -@override -String get okButtonLabel => r'Ò daájú'; -@override + @override + String get okButtonLabel => r'Ò daájú'; + @override // A custom drawer tooltip message. -String get openAppDrawerTooltip => r'Aya ntọju Iwe Awọn Aka'; + String get openAppDrawerTooltip => r'Aya ntọju Iwe Awọn Aka'; // #docregion Raw -@override -String get pageRowsInfoTitleRaw => r'$firstRow–$lastRow lati $rowCount'; + @override + String get pageRowsInfoTitleRaw => r'$firstRow–$lastRow lati $rowCount'; -@override -String get pageRowsInfoTitleApproximateRaw => r'$firstRow–$lastRow lati kiakia $rowCount'; + @override + String get pageRowsInfoTitleApproximateRaw => r'$firstRow–$lastRow lati kiakia $rowCount'; // #enddocregion Raw -@override -String get pasteButtonLabel => r'TÌ'; - -@override -String get popupMenuLabel => r'Meniu Pop-up'; - -@override -String get menuBarMenuLabel => r'Meniu Akọkọ'; - -@override -String get postMeridiemAbbreviation => r'PM'; - -@override -String get previousMonthTooltip => r'Oṣu Kanakana'; - -@override -String get previousPageTooltip => r'Ojú ewé akọkọ kan'; - -@override -String get refreshIndicatorSemanticLabel => r'Gbiyanju'; - -@override -String? get remainingTextFieldCharacterCountFew => null; - -@override -String? get remainingTextFieldCharacterCountMany => null; - -@override -String get remainingTextFieldCharacterCountOne => r'1 àmì báálẹ̀'; - -@override -String get remainingTextFieldCharacterCountOther => r'$remainingCount àmì báálẹ̀'; - -@override -String? get remainingTextFieldCharacterCountTwo => null; - -@override -String get remainingTextFieldCharacterCountZero => r'Kò sí ìwọlé létà láti ń ṣe'; - -@override -String get reorderItemDown => r'Jù sí ilẹ'; - -@override -String get reorderItemLeft => r'Jù sí àrà'; - -@override -String get reorderItemRight => r'Jù sí òtútù'; - -@override -String get reorderItemToEnd => r'Jù sí ìbẹ̀jì'; - -@override -String get reorderItemToStart => r'Jù sí àkọ́kọ́'; - -@override -String get reorderItemUp => r'Jù sí ọ̀rùn'; - -@override -String get rowsPerPageTitle => r'Ìlò Fún àwọn Ìtọ́kasíwájú:'; - -@override -ScriptCategory get scriptCategory => ScriptCategory.englishLike; - -@override -String get searchFieldLabel => 'Ṣẹda'; - -@override -String get selectAllButtonLabel => 'FADỌHỌN DỌFÚN GBÁJÚMỌ̀'; - -@override -String? get selectedRowCountTitleFew => null; - -@override -String? get selectedRowCountTitleMany => null; - -@override -String get selectedRowCountTitleOne => '1 káyé'; - -@override -String get selectedRowCountTitleOther => r'$selectedRowCount káyé'; - -@override -String? get selectedRowCountTitleTwo => null; - -@override -String get selectedRowCountTitleZero => 'Kò sí káyé ti o wọlé'; - -@override -String get showAccountsLabel => 'Fi iyipada mu kọ'; - -@override -String get showMenuTooltip => 'Fi Meniu mu kọ'; - -@override -String get signedInLabel => 'Ọ̀nà'; - -@override -String get tabLabelRaw => r'Àwọn tabin $tabIndex lati $tabCount'; - @override -TimeOfDayFormat get timeOfDayFormatRaw => TimeOfDayFormat.h_colon_mm_space_a; - -@override -String get timePickerHourModeAnnouncement => 'Tuntun waqtu lọ'; - -@override -String get timePickerMinuteModeAnnouncement => 'Tuntun daɗi minti'; - -@override -String get viewLicensesButtonLabel => 'WO NIKI'; - -@override -List get narrowWeekdays => const ['L', 'L', 'A', 'O', 'Ọ', 'Ẹ', 'Ẹ']; - -@override -int get firstDayOfWeekIndex => 0; - -static const LocalizationsDelegate delegate = -_YoMaterialLocalizationsDelegate(); - -@override -String get calendarModeButtonLabel => 'Tọ́rọ̀ kálẹ̀ndà'; - -@override -String get dateHelpText => 'mm/dd/yyyy'; - -@override -String get dateInputLabel => 'Firanṣẹ̀ Ọjọ́'; - -@override -String get dateOutOfRangeLabel => 'Nínú iwọ̀ lọ́wọ́'; - -@override -String get datePickerHelpText => 'WÁSÍ'; - -@override -String get dateRangeEndDateSemanticLabelRaw => r'Ọjọ́ tuntun to ṣà'; - -@override -String get dateRangeEndLabel => 'Ọjọ́ tuntun to ṣà'; - -@override -String get dateRangePickerHelpText => 'WÁSÍ ÌGBÀ'; - -@override -String get dateRangeStartDateSemanticLabelRaw => 'Ọjọ́ tuntun ti dá'; - -@override -String get dateRangeStartLabel => 'Ọjọ́ tuntun ti dá'; - -@override -String get dateSeparator => '/'; - -@override -String get dialModeButtonLabel => 'Tọ́rọ̀ wakati'; - -@override -String get inputDateModeButtonLabel => 'Tọ́rọ̀ firanṣẹ̀ ọjọ́'; - -@override -String get inputTimeModeButtonLabel => 'Tọ́rọ̀ wakati bayi lọ́wọ́'; - -@override -String get invalidDateFormatLabel => 'Akọ́kọ́tọ́ tó jẹ́kúnrin'; - -@override -String get invalidDateRangeLabel => 'Àmì jẹ́ káàkiri lẹ́yìn ilé'; - -@override -String get invalidTimeLabel => 'Akọ́kọ́tọ́ àkójọ ìwádìí'; - -@override -String get licensesPackageDetailTextOther => r'$licenseCount àwọn níkí'; - -@override -String get saveButtonLabel => 'TÙN DÁRA'; - -@override -String get selectYearSemanticsLabel => 'Fọ́ọ̀ shẹ́kàrà'; - -@override -String get timePickerDialHelpText => 'WÁSÍ WÁKÀTÌ'; - -@override -String get timePickerHourLabel => 'Wákàtì àṣà'; - -@override -String get timePickerInputHelpText => 'Shìgárà wákàtì'; - -@override -String get timePickerMinuteLabel => 'Mìntì'; - -@override -String get unspecifiedDate => 'Ọjọ̀kúnrin'; - -@override -String get unspecifiedDateRange => 'Ọjọ̀kúnrin àdáyọ̀'; - -@override -String get keyboardKeyAlt => 'Alt'; - -@override -String get keyboardKeyAltGraph => 'AltGraph'; - -@override -String get keyboardKeyBackspace => 'Báckspàcè'; - -@override -String get keyboardKeyCapsLock => 'Caps Lock'; - -@override -String get keyboardKeyChannelDown => 'Báyàkàmmàlàsàké'; - -@override -String get keyboardKeyChannelUp => 'Yíkàmmàlàsàké'; - -@override -String get keyboardKeyControl => 'Kọ́ntírọ̀l'; - -@override -String get keyboardKeyDelete => 'Shápè'; - -@override -String get keyboardKeyEject => 'Èjẹ̀tì'; - -@override -String get keyboardKeyEnd => 'Tàbí'; - -@override -String get keyboardKeyEscape => 'Tòkè'; + String get pasteButtonLabel => r'TÌ'; @override -String get keyboardKeyFn => 'Fn'; + String get popupMenuLabel => r'Meniu Pop-up'; -@override -String get keyboardKeyHome => 'Ile'; + @override + String get menuBarMenuLabel => r'Meniu Akọkọ'; -@override -String get keyboardKeyInsert => 'Fi sori'; + @override + String get postMeridiemAbbreviation => r'PM'; -@override -String get keyboardKeyMeta => 'Meta'; + @override + String get previousMonthTooltip => r'Oṣu Kanakana'; -@override -String get keyboardKeyMetaMacOs => 'Amfani pẹlu Command'; + @override + String get previousPageTooltip => r'Ojú ewé akọkọ kan'; -@override -String get keyboardKeyMetaWindows => 'Windows'; + @override + String get refreshIndicatorSemanticLabel => r'Gbiyanju'; + + @override + String? get remainingTextFieldCharacterCountFew => null; + + @override + String? get remainingTextFieldCharacterCountMany => null; + + @override + String get remainingTextFieldCharacterCountOne => r'1 àmì báálẹ̀'; + + @override + String get remainingTextFieldCharacterCountOther => r'$remainingCount àmì báálẹ̀'; + + @override + String? get remainingTextFieldCharacterCountTwo => null; + + @override + String get remainingTextFieldCharacterCountZero => r'Kò sí ìwọlé létà láti ń ṣe'; + + @override + String get reorderItemDown => r'Jù sí ilẹ'; + + @override + String get reorderItemLeft => r'Jù sí àrà'; + + @override + String get reorderItemRight => r'Jù sí òtútù'; + + @override + String get reorderItemToEnd => r'Jù sí ìbẹ̀jì'; + + @override + String get reorderItemToStart => r'Jù sí àkọ́kọ́'; + + @override + String get reorderItemUp => r'Jù sí ọ̀rùn'; + + @override + String get rowsPerPageTitle => r'Ìlò Fún àwọn Ìtọ́kasíwájú:'; + + @override + ScriptCategory get scriptCategory => ScriptCategory.englishLike; + + @override + String get searchFieldLabel => 'Ṣẹda'; + + @override + String get selectAllButtonLabel => 'FADỌHỌN DỌFÚN GBÁJÚMỌ̀'; + + @override + String? get selectedRowCountTitleFew => null; + + @override + String? get selectedRowCountTitleMany => null; + + @override + String get selectedRowCountTitleOne => '1 káyé'; + + @override + String get selectedRowCountTitleOther => r'$selectedRowCount káyé'; + + @override + String? get selectedRowCountTitleTwo => null; + + @override + String get selectedRowCountTitleZero => 'Kò sí káyé ti o wọlé'; + + @override + String get showAccountsLabel => 'Fi iyipada mu kọ'; + + @override + String get showMenuTooltip => 'Fi Meniu mu kọ'; + + @override + String get signedInLabel => 'Ọ̀nà'; + + @override + String get tabLabelRaw => r'Àwọn tabin $tabIndex lati $tabCount'; + + @override + TimeOfDayFormat get timeOfDayFormatRaw => TimeOfDayFormat.h_colon_mm_space_a; + + @override + String get timePickerHourModeAnnouncement => 'Tuntun waqtu lọ'; + + @override + String get timePickerMinuteModeAnnouncement => 'Tuntun daɗi minti'; + + @override + String get viewLicensesButtonLabel => 'WO NIKI'; + + @override + List get narrowWeekdays => const ['L', 'L', 'A', 'O', 'Ọ', 'Ẹ', 'Ẹ']; + + @override + int get firstDayOfWeekIndex => 0; + + static const LocalizationsDelegate delegate = + _YoMaterialLocalizationsDelegate(); + + @override + String get calendarModeButtonLabel => 'Tọ́rọ̀ kálẹ̀ndà'; + + @override + String get dateHelpText => 'mm/dd/yyyy'; + + @override + String get dateInputLabel => 'Firanṣẹ̀ Ọjọ́'; + + @override + String get dateOutOfRangeLabel => 'Nínú iwọ̀ lọ́wọ́'; + + @override + String get datePickerHelpText => 'WÁSÍ'; + + @override + String get dateRangeEndDateSemanticLabelRaw => r'Ọjọ́ tuntun to ṣà'; + + @override + String get dateRangeEndLabel => 'Ọjọ́ tuntun to ṣà'; + + @override + String get dateRangePickerHelpText => 'WÁSÍ ÌGBÀ'; + + @override + String get dateRangeStartDateSemanticLabelRaw => 'Ọjọ́ tuntun ti dá'; + + @override + String get dateRangeStartLabel => 'Ọjọ́ tuntun ti dá'; + + @override + String get dateSeparator => '/'; + + @override + String get dialModeButtonLabel => 'Tọ́rọ̀ wakati'; + + @override + String get inputDateModeButtonLabel => 'Tọ́rọ̀ firanṣẹ̀ ọjọ́'; + + @override + String get inputTimeModeButtonLabel => 'Tọ́rọ̀ wakati bayi lọ́wọ́'; + + @override + String get invalidDateFormatLabel => 'Akọ́kọ́tọ́ tó jẹ́kúnrin'; + + @override + String get invalidDateRangeLabel => 'Àmì jẹ́ káàkiri lẹ́yìn ilé'; + + @override + String get invalidTimeLabel => 'Akọ́kọ́tọ́ àkójọ ìwádìí'; + + @override + String get licensesPackageDetailTextOther => r'$licenseCount àwọn níkí'; + + @override + String get saveButtonLabel => 'TÙN DÁRA'; + + @override + String get selectYearSemanticsLabel => 'Fọ́ọ̀ shẹ́kàrà'; + + @override + String get timePickerDialHelpText => 'WÁSÍ WÁKÀTÌ'; + + @override + String get timePickerHourLabel => 'Wákàtì àṣà'; + + @override + String get timePickerInputHelpText => 'Shìgárà wákàtì'; + + @override + String get timePickerMinuteLabel => 'Mìntì'; + + @override + String get unspecifiedDate => 'Ọjọ̀kúnrin'; + + @override + String get unspecifiedDateRange => 'Ọjọ̀kúnrin àdáyọ̀'; + + @override + String get keyboardKeyAlt => 'Alt'; + + @override + String get keyboardKeyAltGraph => 'AltGraph'; + + @override + String get keyboardKeyBackspace => 'Báckspàcè'; + + @override + String get keyboardKeyCapsLock => 'Caps Lock'; + + @override + String get keyboardKeyChannelDown => 'Báyàkàmmàlàsàké'; + + @override + String get keyboardKeyChannelUp => 'Yíkàmmàlàsàké'; + + @override + String get keyboardKeyControl => 'Kọ́ntírọ̀l'; + + @override + String get keyboardKeyDelete => 'Shápè'; + + @override + String get keyboardKeyEject => 'Èjẹ̀tì'; + + @override + String get keyboardKeyEnd => 'Tàbí'; + + @override + String get keyboardKeyEscape => 'Tòkè'; + + @override + String get keyboardKeyFn => 'Fn'; + + @override + String get keyboardKeyHome => 'Ile'; + + @override + String get keyboardKeyInsert => 'Fi sori'; + + @override + String get keyboardKeyMeta => 'Meta'; + + @override + String get keyboardKeyMetaMacOs => 'Amfani pẹlu Command'; + + @override + String get keyboardKeyMetaWindows => 'Windows'; @override String get keyboardKeyNumLock => 'Num Lock'; @@ -751,6 +750,50 @@ String get keyboardKeyMetaWindows => 'Windows'; @override String get scrimOnTapHintRaw => "Scrip on Tap"; + + @override + // TODO: implement collapsedHint + String get collapsedHint => "collapsedHint"; + + @override + // TODO: implement expandedHint + String get expandedHint => "expandedHint"; + + @override + // TODO: implement expansionTileCollapsedHint + String get expansionTileCollapsedHint => "expansionTileCollapsedHint"; + + @override + // TODO: implement expansionTileCollapsedTapHint + String get expansionTileCollapsedTapHint => "expansionTileCollapsedTapHint"; + + @override + // TODO: implement expansionTileExpandedHint + String get expansionTileExpandedHint => "expansionTileExpandedHint"; + + @override + // TODO: implement expansionTileExpandedTapHint + String get expansionTileExpandedTapHint => "expansionTileExpandedTapHint"; + + @override + // TODO: implement scanTextButtonLabel + String get scanTextButtonLabel => "scanTextButtonLabel"; + + @override + // TODO: implement lookUpButtonLabel + String get lookUpButtonLabel => "lookUpButtonLabel"; + + @override + // TODO: implement menuDismissLabel + String get menuDismissLabel => "menuDismissLabel"; + + @override + // TODO: implement searchWebButtonLabel + String get searchWebButtonLabel => "searchWebButtonLabel"; + + @override + // TODO: implement shareButtonLabel + String get shareButtonLabel => "shareButtonLabel"; } /// Cupertino Support @@ -821,138 +864,158 @@ class YoCupertinoLocalizations extends GlobalCupertinoLocalizations { required super.singleDigitSecondFormat, }); -@override -String get alertDialogLabel => 'Àdàkárò'; + @override + String get alertDialogLabel => 'Àdàkárò'; -@override -String get anteMeridiemAbbreviation => 'AM'; + @override + String get anteMeridiemAbbreviation => 'AM'; -@override -String get copyButtonLabel => 'Kòpy'; + @override + String get copyButtonLabel => 'Kòpy'; -@override -String get cutButtonLabel => 'Kọ́t'; + @override + String get cutButtonLabel => 'Kọ́t'; -@override -String get datePickerDateOrderString => 'mdy'; + @override + String get datePickerDateOrderString => 'mdy'; -@override -String get datePickerDateTimeOrderString => 'date_time_dayPeriod'; + @override + String get datePickerDateTimeOrderString => 'date_time_dayPeriod'; -@override -String? get datePickerHourSemanticsLabelFew => null; + @override + String? get datePickerHourSemanticsLabelFew => null; -@override -String? get datePickerHourSemanticsLabelMany => null; + @override + String? get datePickerHourSemanticsLabelMany => null; -@override -String? get datePickerHourSemanticsLabelOne => r"$hour o'clock"; + @override + String? get datePickerHourSemanticsLabelOne => r"$hour o'clock"; -@override -String get datePickerHourSemanticsLabelOther => r"$hour o'clock"; + @override + String get datePickerHourSemanticsLabelOther => r"$hour o'clock"; -@override -String? get datePickerHourSemanticsLabelTwo => null; + @override + String? get datePickerHourSemanticsLabelTwo => null; -@override -String? get datePickerHourSemanticsLabelZero => null; + @override + String? get datePickerHourSemanticsLabelZero => null; -@override -String? get datePickerMinuteSemanticsLabelFew => null; + @override + String? get datePickerMinuteSemanticsLabelFew => null; -@override -String? get datePickerMinuteSemanticsLabelMany => null; + @override + String? get datePickerMinuteSemanticsLabelMany => null; -@override -String? get datePickerMinuteSemanticsLabelOne => '1 wakati'; + @override + String? get datePickerMinuteSemanticsLabelOne => '1 wakati'; -@override -String get datePickerMinuteSemanticsLabelOther => r'$minute wakati'; + @override + String get datePickerMinuteSemanticsLabelOther => r'$minute wakati'; -@override -String? get datePickerMinuteSemanticsLabelTwo => null; + @override + String? get datePickerMinuteSemanticsLabelTwo => null; -@override -String? get datePickerMinuteSemanticsLabelZero => null; + @override + String? get datePickerMinuteSemanticsLabelZero => null; -@override -String get modalBarrierDismissLabel => 'Búta'; + @override + String get modalBarrierDismissLabel => 'Búta'; -@override -String get pasteButtonLabel => 'Tẹ́ẹ́'; + @override + String get pasteButtonLabel => 'Tẹ́ẹ́'; -@override -String get postMeridiemAbbreviation => 'PM'; + @override + String get postMeridiemAbbreviation => 'PM'; -@override -String get searchTextFieldPlaceholderLabel => 'Wúró àtúntà'; + @override + String get searchTextFieldPlaceholderLabel => 'Wúró àtúntà'; -@override -String get selectAllButtonLabel => 'Fírànsé gbógbo'; + @override + String get selectAllButtonLabel => 'Fírànsé gbógbo'; -@override -String get tabSemanticsLabelRaw => r'Tab $tabIndex nínú $tabCount'; + @override + String get tabSemanticsLabelRaw => r'Tab $tabIndex nínú $tabCount'; -@override -String? get timerPickerHourLabelFew => null; + @override + String? get timerPickerHourLabelFew => null; -@override -String? get timerPickerHourLabelMany => null; + @override + String? get timerPickerHourLabelMany => null; -@override -String? get timerPickerHourLabelOne => 'òǹdì'; + @override + String? get timerPickerHourLabelOne => 'òǹdì'; -@override -String get timerPickerHourLabelOther => 'òǹdì'; + @override + String get timerPickerHourLabelOther => 'òǹdì'; -@override -String? get timerPickerHourLabelTwo => null; + @override + String? get timerPickerHourLabelTwo => null; -@override -String? get timerPickerHourLabelZero => null; + @override + String? get timerPickerHourLabelZero => null; -@override -String? get timerPickerMinuteLabelFew => null; + @override + String? get timerPickerMinuteLabelFew => null; -@override -String? get timerPickerMinuteLabelMany => null; + @override + String? get timerPickerMinuteLabelMany => null; -@override -String? get timerPickerMinuteLabelOne => 'wakati.'; + @override + String? get timerPickerMinuteLabelOne => 'wakati.'; -@override -String get timerPickerMinuteLabelOther => 'wakati.'; + @override + String get timerPickerMinuteLabelOther => 'wakati.'; -@override -String? get timerPickerMinuteLabelTwo => null; + @override + String? get timerPickerMinuteLabelTwo => null; -@override -String? get timerPickerMinuteLabelZero => null; + @override + String? get timerPickerMinuteLabelZero => null; -@override -String? get timerPickerSecondLabelFew => null; + @override + String? get timerPickerSecondLabelFew => null; -@override -String? get timerPickerSecondLabelMany => null; + @override + String? get timerPickerSecondLabelMany => null; -@override -String? get timerPickerSecondLabelOne => 'dákìkà.'; + @override + String? get timerPickerSecondLabelOne => 'dákìkà.'; -@override -String get timerPickerSecondLabelOther => 'dákìkà.'; + @override + String get timerPickerSecondLabelOther => 'dákìkà.'; -@override -String? get timerPickerSecondLabelTwo => null; + @override + String? get timerPickerSecondLabelTwo => null; -@override -String? get timerPickerSecondLabelZero => null; + @override + String? get timerPickerSecondLabelZero => null; -@override -String get todayLabel => 'Oyọ'; + @override + String get todayLabel => 'Oyọ'; static const LocalizationsDelegate delegate = _YoCupertinoLocalizationsDelegate(); @override String get noSpellCheckReplacementsLabel => ""; -} \ No newline at end of file + + @override + // TODO: implement clearButtonLabel + String get clearButtonLabel => "clearButtonLabel"; + + @override + // TODO: implement lookUpButtonLabel + String get lookUpButtonLabel => "lookUpButtonLabel"; + + @override + // TODO: implement menuDismissLabel + String get menuDismissLabel => "menuDismissLabel"; + + @override + // TODO: implement searchWebButtonLabel + String get searchWebButtonLabel => "searchWebButtonLabel"; + + @override + // TODO: implement shareButtonLabel + String get shareButtonLabel => "shareButtonLabel"; +} diff --git a/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart b/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart index 6896177e4..5355b7bb8 100644 --- a/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart +++ b/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart @@ -12,7 +12,6 @@ final _settingsNavigatorKey = GlobalKey(); class DesktopSettingsPage extends StatefulWidget { const DesktopSettingsPage({super.key}); - @override State createState() => _DesktopSettingsPageState(); } @@ -33,22 +32,21 @@ class _DesktopSettingsPageState extends State { return Scaffold( body: Container( height: MediaQuery.of(context).size.height, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + child: Row( children: [ - Padding( - padding: const EdgeInsets.fromLTRB(24, 24, 24, 4), - child: Text( - S.current.settings, - style: textXLarge(), - ), - ), Expanded( - child: Row( + flex: 1, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ + Padding( + padding: const EdgeInsets.fromLTRB(24, 24, 24, 4), + child: Text( + S.current.settings, + style: textXLarge(), + ), + ), Expanded( - flex: 1, child: ListView.separated( padding: EdgeInsets.only(top: 0), itemBuilder: (_, index) { @@ -78,27 +76,27 @@ class _DesktopSettingsPageState extends State { itemCount: itemCount, ), ), - Flexible( - flex: 2, - child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: 500), - child: Navigator( - key: _settingsNavigatorKey, - initialRoute: Routes.empty_no_route, - onGenerateRoute: (settings) => Router.createRoute(settings), - onGenerateInitialRoutes: - (NavigatorState navigator, String initialRouteName) { - return [ - navigator - .widget.onGenerateRoute!(RouteSettings(name: initialRouteName))! - ]; - }, - ), - ), - ) ], ), ), + Flexible( + flex: 2, + child: ConstrainedBox( + constraints: BoxConstraints(maxWidth: 500), + child: Navigator( + key: _settingsNavigatorKey, + initialRoute: Routes.empty_no_route, + onGenerateRoute: (settings) => Router.createRoute(settings), + onGenerateInitialRoutes: + (NavigatorState navigator, String initialRouteName) { + return [ + navigator + .widget.onGenerateRoute!(RouteSettings(name: initialRouteName))! + ]; + }, + ), + ), + ) ], ), ), diff --git a/lib/src/screens/settings/security_backup_page.dart b/lib/src/screens/settings/security_backup_page.dart index e559e9b15..1f0f58ad4 100644 --- a/lib/src/screens/settings/security_backup_page.dart +++ b/lib/src/screens/settings/security_backup_page.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/routes.dart'; @@ -58,7 +60,7 @@ class SecurityBackupPage extends BasePage { .shouldRequireTOTP2FAForAllSecurityAndBackupSettings, ), ), - if (DeviceInfo.instance.isMobile) + if (DeviceInfo.instance.isMobile || Platform.isMacOS || Platform.isLinux) Observer(builder: (_) { return SettingsSwitcherCell( title: S.current.settings_allow_biometrical_authentication, diff --git a/lib/src/screens/settings/tor_page.dart b/lib/src/screens/settings/tor_page.dart index ae1ef1677..2f544be35 100644 --- a/lib/src/screens/settings/tor_page.dart +++ b/lib/src/screens/settings/tor_page.dart @@ -146,7 +146,7 @@ class ConnectScreen extends StatelessWidget { ElevatedButton( onPressed: connect, style: ElevatedButton.styleFrom( - primary: Colors.blue, + // primary: Colors.blue, padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30), @@ -211,7 +211,7 @@ class DisconnectScreen extends StatelessWidget { ElevatedButton( onPressed: disconnect, style: ElevatedButton.styleFrom( - primary: Colors.red, + // primary: Colors.red, padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30), diff --git a/lib/src/screens/support_chat/widgets/chatwoot_widget.dart b/lib/src/screens/support_chat/widgets/chatwoot_widget.dart index 2557761a7..60c9ea97f 100644 --- a/lib/src/screens/support_chat/widgets/chatwoot_widget.dart +++ b/lib/src/screens/support_chat/widgets/chatwoot_widget.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; @@ -58,7 +59,6 @@ class ChatwootWidgetState extends State { } Future storeCookie(String value) async { - await widget.secureStorage.delete(key: COOKIE_KEY); - await widget.secureStorage.write(key: COOKIE_KEY, value: value); + await writeSecureStorage(widget.secureStorage, key: COOKIE_KEY, value: value); } } diff --git a/lib/src/widgets/validable_annotated_editable_text.dart b/lib/src/widgets/validable_annotated_editable_text.dart index 16ccc76f6..134eb16a8 100644 --- a/lib/src/widgets/validable_annotated_editable_text.dart +++ b/lib/src/widgets/validable_annotated_editable_text.dart @@ -1,8 +1,14 @@ -import 'package:cake_wallet/core/seed_validator.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; -class Annotation extends Comparable { + +extension Compare on Comparable { + bool operator <=(T other) => compareTo(other) <= 0; + bool operator >=(T other) => compareTo(other) >= 0; + bool operator <(T other) => compareTo(other) < 0; + bool operator >(T other) => compareTo(other) > 0; +} + +class Annotation implements Comparable { Annotation({required this.range, required this.style}); final TextRange range; @@ -12,7 +18,7 @@ class Annotation extends Comparable { int compareTo(Annotation other) => range.start.compareTo(other.range.start); } -class TextAnnotation extends Comparable { +class TextAnnotation implements Comparable { TextAnnotation({required this.text, required this.style}); final TextStyle style; diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 607551827..cd9b44391 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/provider_types.dart'; import 'package:cake_wallet/entities/cake_2fa_preset_options.dart'; @@ -434,79 +435,83 @@ abstract class SettingsStoreBase with Store { // secure storage keys: reaction( (_) => allowBiometricalAuthentication, - (bool biometricalAuthentication) => secureStorage.write( + (bool biometricalAuthentication) => writeSecureStorage(secureStorage, key: SecureKey.allowBiometricalAuthenticationKey, value: biometricalAuthentication.toString())); reaction( (_) => selectedCake2FAPreset, - (Cake2FAPresetsOptions selectedCake2FAPreset) => secureStorage.write( + (Cake2FAPresetsOptions selectedCake2FAPreset) => writeSecureStorage(secureStorage, key: SecureKey.selectedCake2FAPreset, value: selectedCake2FAPreset.serialize().toString())); reaction( (_) => shouldRequireTOTP2FAForAccessingWallet, - (bool requireTOTP2FAForAccessingWallet) => secureStorage.write( + (bool requireTOTP2FAForAccessingWallet) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForAccessingWallet, value: requireTOTP2FAForAccessingWallet.toString())); reaction( (_) => shouldRequireTOTP2FAForSendsToContact, - (bool requireTOTP2FAForSendsToContact) => secureStorage.write( + (bool requireTOTP2FAForSendsToContact) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForSendsToContact, value: requireTOTP2FAForSendsToContact.toString())); reaction( (_) => shouldRequireTOTP2FAForSendsToNonContact, - (bool requireTOTP2FAForSendsToNonContact) => secureStorage.write( + (bool requireTOTP2FAForSendsToNonContact) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForSendsToNonContact, value: requireTOTP2FAForSendsToNonContact.toString())); reaction( (_) => shouldRequireTOTP2FAForSendsToInternalWallets, - (bool requireTOTP2FAForSendsToInternalWallets) => secureStorage.write( + (bool requireTOTP2FAForSendsToInternalWallets) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForSendsToInternalWallets, value: requireTOTP2FAForSendsToInternalWallets.toString())); reaction( (_) => shouldRequireTOTP2FAForExchangesToInternalWallets, - (bool requireTOTP2FAForExchangesToInternalWallets) => secureStorage.write( + (bool requireTOTP2FAForExchangesToInternalWallets) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForExchangesToInternalWallets, value: requireTOTP2FAForExchangesToInternalWallets.toString())); reaction( (_) => shouldRequireTOTP2FAForExchangesToExternalWallets, - (bool requireTOTP2FAForExchangesToExternalWallets) => secureStorage.write( + (bool requireTOTP2FAForExchangesToExternalWallets) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForExchangesToExternalWallets, value: requireTOTP2FAForExchangesToExternalWallets.toString())); reaction( (_) => shouldRequireTOTP2FAForAddingContacts, - (bool requireTOTP2FAForAddingContacts) => secureStorage.write( + (bool requireTOTP2FAForAddingContacts) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForAddingContacts, value: requireTOTP2FAForAddingContacts.toString())); reaction( (_) => shouldRequireTOTP2FAForCreatingNewWallets, - (bool requireTOTP2FAForCreatingNewWallets) => secureStorage.write( + (bool requireTOTP2FAForCreatingNewWallets) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForCreatingNewWallets, value: requireTOTP2FAForCreatingNewWallets.toString())); reaction( (_) => shouldRequireTOTP2FAForAllSecurityAndBackupSettings, - (bool requireTOTP2FAForAllSecurityAndBackupSettings) => secureStorage.write( + (bool requireTOTP2FAForAllSecurityAndBackupSettings) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings, value: requireTOTP2FAForAllSecurityAndBackupSettings.toString())); - reaction((_) => useTOTP2FA, - (bool use) => secureStorage.write(key: SecureKey.useTOTP2FA, value: use.toString())); + reaction( + (_) => useTOTP2FA, + (bool use) => + writeSecureStorage(secureStorage, key: SecureKey.useTOTP2FA, value: use.toString())); - reaction((_) => totpSecretKey, - (String totpKey) => secureStorage.write(key: SecureKey.totpSecretKey, value: totpKey)); + reaction( + (_) => totpSecretKey, + (String totpKey) => + writeSecureStorage(secureStorage, key: SecureKey.totpSecretKey, value: totpKey)); reaction( (_) => pinTimeOutDuration, - (PinCodeRequiredDuration pinCodeInterval) => secureStorage.write( + (PinCodeRequiredDuration pinCodeInterval) => writeSecureStorage(secureStorage, key: SecureKey.pinTimeOutDuration, value: pinCodeInterval.value.toString())); reaction( diff --git a/lib/view_model/auth_view_model.dart b/lib/view_model/auth_view_model.dart index 4fb93cfea..6f6e29662 100644 --- a/lib/view_model/auth_view_model.dart +++ b/lib/view_model/auth_view_model.dart @@ -106,14 +106,10 @@ abstract class AuthViewModelBase with Store { @action Future biometricAuth() async { try { - final canBiometricAuth = await _biometricAuth.canCheckBiometrics(); - - if (canBiometricAuth) { - final isAuthenticated = await _biometricAuth.isAuthenticated(); - - if (isAuthenticated) { - state = ExecutedSuccessfullyState(); - } + if (await _biometricAuth.canCheckBiometrics() && await _biometricAuth.isAuthenticated()) { + state = ExecutedSuccessfullyState(); + } else { + throw Exception('Biometric authentication failed'); } } catch (e) { state = FailureState(e.toString()); diff --git a/lib/view_model/edit_backup_password_view_model.dart b/lib/view_model/edit_backup_password_view_model.dart index aca76502a..729551e74 100644 --- a/lib/view_model/edit_backup_password_view_model.dart +++ b/lib/view_model/edit_backup_password_view_model.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:mobx/mobx.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; @@ -37,8 +38,7 @@ abstract class EditBackupPasswordViewModelBase with Store { @action Future save() async { final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword); - await secureStorage.delete(key: key); - await secureStorage.write(key: key, value: backupPassword); + await writeSecureStorage(secureStorage, key: key, value: backupPassword); secretStore.write(key: key, value: backupPassword); } } diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 75a78404f..51f61d9e3 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -10,6 +10,7 @@ import cw_monero import device_info_plus import devicelocale import flutter_inappwebview_macos +import flutter_local_authentication import flutter_secure_storage_macos import in_app_review import package_info @@ -26,6 +27,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin")) InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) + FlutterLocalAuthenticationPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalAuthenticationPlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin")) FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin")) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index b82513de2..f1f72a818 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -26,6 +26,8 @@ PODS: - flutter_inappwebview_macos (0.0.1): - FlutterMacOS - OrderedSet (~> 5.0) + - flutter_local_authentication (1.2.0): + - FlutterMacOS - flutter_secure_storage_macos (6.1.1): - FlutterMacOS - FlutterMacOS (1.0.0) @@ -56,6 +58,7 @@ DEPENDENCIES: - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`) - flutter_inappwebview_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos`) + - flutter_local_authentication (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_authentication/macos`) - flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`) @@ -83,6 +86,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/devicelocale/macos flutter_inappwebview_macos: :path: Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos + flutter_local_authentication: + :path: Flutter/ephemeral/.symlinks/plugins/flutter_local_authentication/macos flutter_secure_storage_macos: :path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos FlutterMacOS: @@ -110,6 +115,7 @@ SPEC CHECKSUMS: device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225 flutter_inappwebview_macos: 9600c9df9fdb346aaa8933812009f8d94304203d + flutter_local_authentication: 85674893931e1c9cfa7c9e4f5973cb8c56b018b0 flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0 diff --git a/pubspec_base.yaml b/pubspec_base.yaml index cf04509ac..ddf0bd2e0 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -26,15 +26,17 @@ dependencies: path_provider: ^2.0.11 mobx: ^2.1.4 flutter_mobx: ^2.0.6+5 - flutter_slidable: ^2.0.0 + flutter_slidable: ^3.0.1 share_plus: ^4.0.10 # date_range_picker: ^1.0.6 #https://api.flutter.dev/flutter/material/showDateRangePicker.html dio: ^4.0.6 hive: ^2.2.3 hive_flutter: ^1.1.0 - local_auth: ^2.1.0 local_auth_android: 1.0.21 + flutter_local_authentication: + git: + url: https://github.com/cake-tech/flutter_local_authentication package_info: ^2.0.0 #package_info_plus: ^1.4.2 devicelocale: diff --git a/pubspec_description.yaml b/pubspec_description.yaml index ebb6bf001..b51fe96d6 100644 --- a/pubspec_description.yaml +++ b/pubspec_description.yaml @@ -4,4 +4,4 @@ version: 0.0.0 publish_to: none environment: - sdk: ">=2.17.5 <3.0.0" \ No newline at end of file + sdk: ">=3.1.0 <4.0.0" \ No newline at end of file From baad7f74696ed463d243d31b2236fc11f427e86b Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Tue, 7 May 2024 17:00:01 -0700 Subject: [PATCH 213/241] Nano-GPT (#1336) * init * updates * nano updates * updates * updates * [skipci] wip deep link changes * fix deep links * minor fix * add reminder message on buy and exchange routes * [skip ci] font fixes * review updates * [skip ci] minor fix * save * fixes * minor code cleanup * minor potential fix --- .github/workflows/pr_test_build.yml | 1 + .gitignore | 1 + android/app/src/main/AndroidManifestBase.xml | 7 + assets/banano_node_list.yml | 5 + cw_core/lib/crypto_currency.dart | 6 + cw_nano/lib/banano_balance.dart | 16 ++ cw_nano/lib/nano_balance.dart | 6 +- cw_nano/lib/nano_client.dart | 26 +++- ios/Runner/InfoBase.plist | 10 ++ lib/di.dart | 145 ++++++++++-------- lib/main.dart | 29 ++-- lib/router.dart | 21 +-- .../dashboard/pages/market_place_page.dart | 22 ++- lib/src/screens/exchange/exchange_page.dart | 10 +- lib/src/screens/root/root.dart | 115 +++++--------- lib/src/screens/send/send_page.dart | 34 +++- lib/utils/payment_request.dart | 25 ++- lib/view_model/link_view_model.dart | 118 ++++++++++++++ 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_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_yo.arb | 2 + res/values/strings_zh.arb | 2 + tool/generate_secrets_config.dart | 28 ++-- tool/utils/secret_key.dart | 4 + 46 files changed, 486 insertions(+), 195 deletions(-) create mode 100644 assets/banano_node_list.yml create mode 100644 lib/view_model/link_view_model.dart diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 23902f110..69c632967 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -151,6 +151,7 @@ jobs: 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 nano2ApiKey = '${{ secrets.NANO2_API_KEY }}';" >> cw_nano/lib/.secrets.g.dart echo "const tronGridApiKey = '${{ secrets.TRON_GRID_API_KEY }}';" >> cw_tron/lib/.secrets.g.dart - name: Rename app diff --git a/.gitignore b/.gitignore index f1e5b6da3..24b7291f8 100644 --- a/.gitignore +++ b/.gitignore @@ -94,6 +94,7 @@ android/app/key.jks **/tool/.evm-secrets-config.json **/tool/.ethereum-secrets-config.json **/tool/.solana-secrets-config.json +**/tool/.nano-secrets-config.json **/tool/.tron-secrets-config.json **/lib/.secrets.g.dart **/cw_evm/lib/.secrets.g.dart diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml index 23207d629..57462099c 100644 --- a/android/app/src/main/AndroidManifestBase.xml +++ b/android/app/src/main/AndroidManifestBase.xml @@ -91,6 +91,13 @@ + + + + + + + with Serializable implemen element.tag == walletCurrency?.tag)); } catch (_) {} + // search by fullName if not found by title: + try { + return CryptoCurrency.all.firstWhere((element) => element.fullName?.toLowerCase() == name); + } catch (_) {} + if (CryptoCurrency._nameCurrencyMap[name.toLowerCase()] == null) { final s = 'Unexpected token: $name for CryptoCurrency fromString'; throw ArgumentError.value(name, 'name', s); } + return CryptoCurrency._nameCurrencyMap[name.toLowerCase()]!; } diff --git a/cw_nano/lib/banano_balance.dart b/cw_nano/lib/banano_balance.dart index b904a35cb..d766077fc 100644 --- a/cw_nano/lib/banano_balance.dart +++ b/cw_nano/lib/banano_balance.dart @@ -1,12 +1,28 @@ import 'package:cw_core/balance.dart'; import 'package:nanoutil/nanoutil.dart'; +BigInt stringAmountToBigIntBanano(String amount) { + return BigInt.parse(NanoAmounts.getAmountAsRaw(amount, NanoAmounts.rawPerBanano)); +} + class BananoBalance extends Balance { final BigInt currentBalance; final BigInt receivableBalance; BananoBalance({required this.currentBalance, required this.receivableBalance}) : super(0, 0); + BananoBalance.fromFormattedString( + {required String formattedCurrentBalance, required String formattedReceivableBalance}) + : currentBalance = stringAmountToBigIntBanano(formattedCurrentBalance), + receivableBalance = stringAmountToBigIntBanano(formattedReceivableBalance), + super(0, 0); + + BananoBalance.fromRawString( + {required String currentBalance, required String receivableBalance}) + : currentBalance = BigInt.parse(currentBalance), + receivableBalance = BigInt.parse(receivableBalance), + super(0, 0); + @override String get formattedAvailableBalance { return NanoAmounts.getRawAsUsableString(currentBalance.toString(), NanoAmounts.rawPerBanano); diff --git a/cw_nano/lib/nano_balance.dart b/cw_nano/lib/nano_balance.dart index 8b8c93b33..691b3a32d 100644 --- a/cw_nano/lib/nano_balance.dart +++ b/cw_nano/lib/nano_balance.dart @@ -1,7 +1,7 @@ import 'package:cw_core/balance.dart'; import 'package:nanoutil/nanoutil.dart'; -BigInt stringAmountToBigInt(String amount) { +BigInt stringAmountToBigIntNano(String amount) { return BigInt.parse(NanoAmounts.getAmountAsRaw(amount, NanoAmounts.rawPerNano)); } @@ -13,8 +13,8 @@ class NanoBalance extends Balance { NanoBalance.fromFormattedString( {required String formattedCurrentBalance, required String formattedReceivableBalance}) - : currentBalance = stringAmountToBigInt(formattedCurrentBalance), - receivableBalance = stringAmountToBigInt(formattedReceivableBalance), + : currentBalance = stringAmountToBigIntNano(formattedCurrentBalance), + receivableBalance = stringAmountToBigIntNano(formattedReceivableBalance), super(0, 0); NanoBalance.fromRawString( diff --git a/cw_nano/lib/nano_client.dart b/cw_nano/lib/nano_client.dart index 064a0bdee..3b388e5e8 100644 --- a/cw_nano/lib/nano_client.dart +++ b/cw_nano/lib/nano_client.dart @@ -10,6 +10,7 @@ import 'package:nanodart/nanodart.dart'; import 'package:cw_core/node.dart'; import 'package:nanoutil/nanoutil.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:cw_nano/.secrets.g.dart' as secrets; class NanoClient { static const Map CAKE_HEADERS = { @@ -52,10 +53,19 @@ class NanoClient { } } + Map getHeaders() { + if (_node!.uri == "https://rpc.nano.to") { + return CAKE_HEADERS..addAll({ + "key": secrets.nano2ApiKey, + }); + } + return CAKE_HEADERS; + } + Future getBalance(String address) async { final response = await http.post( _node!.uri, - headers: CAKE_HEADERS, + headers: getHeaders(), body: jsonEncode( { "action": "account_balance", @@ -82,7 +92,7 @@ class NanoClient { try { final response = await http.post( _node!.uri, - headers: CAKE_HEADERS, + headers: getHeaders(), body: jsonEncode( { "action": "account_info", @@ -94,7 +104,7 @@ class NanoClient { final data = await jsonDecode(response.body); return AccountInfoResponse.fromJson(data as Map); } catch (e) { - print("error while getting account info"); + print("error while getting account info $e"); return null; } } @@ -149,7 +159,7 @@ class NanoClient { Future requestWork(String hash) async { final response = await http.post( _powNode!.uri, - headers: CAKE_HEADERS, + headers: getHeaders(), body: json.encode( { "action": "work_generate", @@ -192,7 +202,7 @@ class NanoClient { final processResponse = await http.post( _node!.uri, - headers: CAKE_HEADERS, + headers: getHeaders(), body: processBody, ); @@ -351,7 +361,7 @@ class NanoClient { }); final processResponse = await http.post( _node!.uri, - headers: CAKE_HEADERS, + headers: getHeaders(), body: processBody, ); @@ -367,7 +377,7 @@ class NanoClient { required String privateKey, }) async { final receivableResponse = await http.post(_node!.uri, - headers: CAKE_HEADERS, + headers: getHeaders(), body: jsonEncode({ "action": "receivable", "account": destinationAddress, @@ -417,7 +427,7 @@ class NanoClient { Future> fetchTransactions(String address) async { try { final response = await http.post(_node!.uri, - headers: CAKE_HEADERS, + headers: getHeaders(), body: jsonEncode({ "action": "account_history", "account": address, diff --git a/ios/Runner/InfoBase.plist b/ios/Runner/InfoBase.plist index 02365bda7..83e60b542 100644 --- a/ios/Runner/InfoBase.plist +++ b/ios/Runner/InfoBase.plist @@ -140,6 +140,16 @@ nano-wallet + + CFBundleTypeRole + Viewer + CFBundleURLName + nano-gpt + CFBundleURLSchemes + + nano-gpt + + CFBundleTypeRole Editor diff --git a/lib/di.dart b/lib/di.dart index d280362b4..20157b0e0 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -26,6 +26,7 @@ import 'package:cake_wallet/entities/contact.dart'; import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/parse_address_from_domain.dart'; +import 'package:cake_wallet/view_model/link_view_model.dart'; import 'package:cake_wallet/tron/tron.dart'; import 'package:cake_wallet/src/screens/transaction_details/rbf_details_page.dart'; import 'package:cw_core/receive_page_option.dart'; @@ -268,6 +269,7 @@ Future setup({ required Box unspentCoinsInfoSource, required Box anonpayInvoiceInfoSource, required FlutterSecureStorage secureStorage, + required GlobalKey navigatorKey, }) async { _walletInfoSource = walletInfoSource; _nodeSource = nodeSource; @@ -429,68 +431,89 @@ Future setup({ ), ); - getIt.registerFactory(() { - return AuthPage(getIt.get(), + getIt.registerLazySingleton(() { + return LinkViewModel( + appStore: getIt.get(), + settingsStore: getIt.get(), + authenticationStore: getIt.get(), + navigatorKey: navigatorKey, + ); + }); + + getIt.registerFactory(instanceName: 'login', () { + return AuthPage(getIt.get(), closable: false, onAuthenticationFinished: (isAuthenticated, AuthPageState authPageState) { if (!isAuthenticated) { return; - } else { - final authStore = getIt.get(); - final appStore = getIt.get(); - final useTotp = appStore.settingsStore.useTOTP2FA; - final shouldUseTotp2FAToAccessWallets = - appStore.settingsStore.shouldRequireTOTP2FAForAccessingWallet; - if (useTotp && shouldUseTotp2FAToAccessWallets) { - authPageState.close( - route: Routes.totpAuthCodePage, - arguments: TotpAuthArgumentsModel( - isForSetup: false, - isClosable: false, - onTotpAuthenticationFinished: (bool isAuthenticatedSuccessfully, - TotpAuthCodePageState totpAuthPageState) async { - if (!isAuthenticatedSuccessfully) { - return; - } - if (appStore.wallet != null) { - authStore.allowed(); - return; - } - - totpAuthPageState.changeProcessText('Loading the wallet'); - - if (loginError != null) { - totpAuthPageState.changeProcessText('ERROR: ${loginError.toString()}'); - } - - ReactionDisposer? _reaction; - _reaction = reaction((_) => appStore.wallet, (Object? _) { - _reaction?.reaction.dispose(); - authStore.allowed(); - }); - }, - ), - ); - } else { - if (appStore.wallet != null) { - authStore.allowed(); - return; - } - - authPageState.changeProcessText('Loading the wallet'); - - if (loginError != null) { - authPageState.changeProcessText('ERROR: ${loginError.toString()}'); - } - - ReactionDisposer? _reaction; - _reaction = reaction((_) => appStore.wallet, (Object? _) { - _reaction?.reaction.dispose(); - authStore.allowed(); - }); - } } - }, closable: false); - }, instanceName: 'login'); + final authStore = getIt.get(); + final appStore = getIt.get(); + final useTotp = appStore.settingsStore.useTOTP2FA; + final shouldUseTotp2FAToAccessWallets = + appStore.settingsStore.shouldRequireTOTP2FAForAccessingWallet; + if (useTotp && shouldUseTotp2FAToAccessWallets) { + authPageState.close( + route: Routes.totpAuthCodePage, + arguments: TotpAuthArgumentsModel( + isForSetup: false, + isClosable: false, + onTotpAuthenticationFinished: + (bool isAuthenticatedSuccessfully, TotpAuthCodePageState totpAuthPageState) async { + if (!isAuthenticatedSuccessfully) { + return; + } + if (appStore.wallet != null) { + authStore.allowed(); + return; + } + + totpAuthPageState.changeProcessText('Loading the wallet'); + + if (loginError != null) { + totpAuthPageState.changeProcessText('ERROR: ${loginError.toString()}'); + } + + ReactionDisposer? _reaction; + _reaction = reaction((_) => appStore.wallet, (Object? _) { + _reaction?.reaction.dispose(); + authStore.allowed(); + }); + }, + ), + ); + } else { + // wallet is already loaded: + if (appStore.wallet != null) { + // goes to the dashboard: + authStore.allowed(); + // trigger any deep links: + final linkViewModel = getIt.get(); + if (linkViewModel.currentLink != null) { + linkViewModel.handleLink(); + } + return; + } + + // load the wallet: + + authPageState.changeProcessText('Loading the wallet'); + + if (loginError != null) { + authPageState.changeProcessText('ERROR: ${loginError.toString()}'); + } + + ReactionDisposer? _reaction; + _reaction = reaction((_) => appStore.wallet, (Object? _) { + _reaction?.reaction.dispose(); + authStore.allowed(); + final linkViewModel = getIt.get(); + if (linkViewModel.currentLink != null) { + linkViewModel.handleLink(); + } + }); + } + }); + }); getIt.registerSingleton(BottomSheetServiceImpl()); @@ -849,8 +872,10 @@ Future setup({ tradesStore: getIt.get(), sendViewModel: getIt.get())); - getIt.registerFactory( - () => ExchangePage(getIt.get(), getIt.get())); + getIt.registerFactoryParam( + (PaymentRequest? paymentRequest, __) { + return ExchangePage(getIt.get(), getIt.get(), paymentRequest); + }); getIt.registerFactory(() => ExchangeConfirmPage(tradesStore: getIt.get())); diff --git a/lib/main.dart b/lib/main.dart index b2e32d7a9..2a4e12236 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,6 +7,7 @@ import 'package:cake_wallet/locales/locale.dart'; import 'package:cake_wallet/store/yat/yat_store.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/exception_handler.dart'; +import 'package:cake_wallet/view_model/link_view_model.dart'; import 'package:cw_core/address_info.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cw_core/hive_type_ids.dart'; @@ -205,18 +206,20 @@ Future initialSetup( nodes: nodes, powNodes: powNodes); await setup( - walletInfoSource: walletInfoSource, - nodeSource: nodes, - powNodeSource: powNodes, - contactSource: contactSource, - tradesSource: tradesSource, - templates: templates, - exchangeTemplates: exchangeTemplates, - transactionDescriptionBox: transactionDescriptions, - ordersSource: ordersSource, - anonpayInvoiceInfoSource: anonpayInvoiceInfo, - unspentCoinsInfoSource: unspentCoinsInfoSource, - secureStorage: secureStorage); + walletInfoSource: walletInfoSource, + nodeSource: nodes, + powNodeSource: powNodes, + contactSource: contactSource, + tradesSource: tradesSource, + templates: templates, + exchangeTemplates: exchangeTemplates, + transactionDescriptionBox: transactionDescriptions, + ordersSource: ordersSource, + anonpayInvoiceInfoSource: anonpayInvoiceInfo, + unspentCoinsInfoSource: unspentCoinsInfoSource, + secureStorage: secureStorage, + navigatorKey: navigatorKey, + ); await bootstrap(navigatorKey); monero?.onStartup(); } @@ -287,6 +290,7 @@ class AppState extends State with SingleTickerProviderStateMixin { return Observer(builder: (BuildContext context) { final appStore = getIt.get(); final authService = getIt.get(); + final linkViewModel = getIt.get(); final settingsStore = appStore.settingsStore; final statusBarColor = Colors.transparent; final authenticationStore = getIt.get(); @@ -309,6 +313,7 @@ class AppState extends State with SingleTickerProviderStateMixin { authenticationStore: authenticationStore, navigatorKey: navigatorKey, authService: authService, + linkViewModel: linkViewModel, child: MaterialApp( navigatorObservers: [routeObserver], navigatorKey: navigatorKey, diff --git a/lib/router.dart b/lib/router.dart index 3032ceb6a..741597731 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -221,7 +221,8 @@ Route createRoute(RouteSettings settings) { return CupertinoPageRoute( builder: (_) => getIt.get( param1: (PinCodeState context, dynamic _) => - Navigator.of(context.context).pushNamed(Routes.restoreWalletFromHardwareWallet, arguments: false), + Navigator.of(context.context) + .pushNamed(Routes.restoreWalletFromHardwareWallet, arguments: false), ), fullscreenDialog: true, ); @@ -231,9 +232,9 @@ Route createRoute(RouteSettings settings) { builder: (_) => ConnectDevicePage( ConnectDevicePageParams( walletType: availableWalletTypes.first, - onConnectDevice: (BuildContext context, _) => - Navigator.of(context).pushNamed(Routes.chooseHardwareWalletAccount, - arguments: [availableWalletTypes.first]), + onConnectDevice: (BuildContext context, _) => Navigator.of(context).pushNamed( + Routes.chooseHardwareWalletAccount, + arguments: [availableWalletTypes.first]), ), getIt.get(), )); @@ -243,9 +244,8 @@ Route createRoute(RouteSettings settings) { param1: (BuildContext context, WalletType type) { final arguments = ConnectDevicePageParams( walletType: type, - onConnectDevice: (BuildContext context, _) => - Navigator.of(context).pushNamed(Routes.chooseHardwareWalletAccount, - arguments: [type]), + onConnectDevice: (BuildContext context, _) => Navigator.of(context) + .pushNamed(Routes.chooseHardwareWalletAccount, arguments: [type]), ); Navigator.of(context).pushNamed(Routes.connectDevices, arguments: arguments); @@ -308,8 +308,7 @@ Route createRoute(RouteSettings settings) { case Routes.bumpFeePage: return CupertinoPageRoute( fullscreenDialog: true, - builder: (_) => - getIt.get(param1: settings.arguments as TransactionInfo)); + builder: (_) => getIt.get(param1: settings.arguments as TransactionInfo)); case Routes.newSubaddress: return CupertinoPageRoute( @@ -461,7 +460,9 @@ Route createRoute(RouteSettings settings) { case Routes.exchange: return CupertinoPageRoute( - fullscreenDialog: true, builder: (_) => getIt.get()); + fullscreenDialog: true, + builder: (_) => getIt.get(param1: settings.arguments as PaymentRequest?), + ); case Routes.exchangeTemplate: return CupertinoPageRoute(builder: (_) => getIt.get()); diff --git a/lib/src/screens/dashboard/pages/market_place_page.dart b/lib/src/screens/dashboard/pages/market_place_page.dart index 1bdcb61b4..d28048844 100644 --- a/lib/src/screens/dashboard/pages/market_place_page.dart +++ b/lib/src/screens/dashboard/pages/market_place_page.dart @@ -59,12 +59,15 @@ class MarketPlacePage extends StatelessWidget { // ), SizedBox(height: 20), DashBoardRoundedCardWidget( - onTap: () => launchUrl( - Uri.https("buy.cakepay.com"), - mode: LaunchMode.externalApplication, - ), title: S.of(context).cake_pay_web_cards_title, subTitle: S.of(context).cake_pay_web_cards_subtitle, + onTap: () => _launchMarketPlaceUrl("buy.cakepay.com"), + ), + const SizedBox(height: 20), + DashBoardRoundedCardWidget( + title: "NanoGPT", + subTitle: S.of(context).nanogpt_subtitle, + onTap: () => _launchMarketPlaceUrl("cake.nano-gpt.com"), ), ], ), @@ -76,6 +79,17 @@ class MarketPlacePage extends StatelessWidget { ); } + void _launchMarketPlaceUrl(String url) async { + try { + launchUrl( + Uri.https(url), + mode: LaunchMode.externalApplication, + ); + } catch (e) { + print(e); + } + } + // TODO: Remove ionia flow/files if we will discard it void _navigatorToGiftCardsPage(BuildContext context) { final walletType = dashboardViewModel.type; diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index c4e4aa199..e2d424fa0 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -10,6 +10,7 @@ import 'package:cake_wallet/src/widgets/add_template_button.dart'; import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/utils/debounce.dart'; +import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cw_core/sync_status.dart'; import 'package:cw_core/wallet_type.dart'; @@ -43,7 +44,7 @@ import 'package:cake_wallet/src/screens/exchange/widgets/present_provider_picker import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.dart'; class ExchangePage extends BasePage { - ExchangePage(this.exchangeViewModel, this.authService) { + ExchangePage(this.exchangeViewModel, this.authService, this.initialPaymentRequest) { depositWalletName = exchangeViewModel.depositCurrency == CryptoCurrency.xmr ? exchangeViewModel.wallet.name : null; @@ -54,6 +55,7 @@ class ExchangePage extends BasePage { final ExchangeViewModel exchangeViewModel; final AuthService authService; + final PaymentRequest? initialPaymentRequest; final depositKey = GlobalKey(); final receiveKey = GlobalKey(); final _formKey = GlobalKey(); @@ -543,6 +545,12 @@ class ExchangePage extends BasePage { // amount: depositAmountController.text); }); + if (initialPaymentRequest != null) { + exchangeViewModel.receiveCurrency = CryptoCurrency.fromString(initialPaymentRequest!.scheme); + exchangeViewModel.depositAmount = initialPaymentRequest!.amount; + exchangeViewModel.receiveAddress = initialPaymentRequest!.address; + } + _isReactionsSet = true; } diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index e3472f510..afdd14865 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -5,6 +5,7 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/payment_request.dart'; +import 'package:cake_wallet/view_model/link_view_model.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; @@ -25,6 +26,7 @@ class Root extends StatefulWidget { required this.child, required this.navigatorKey, required this.authService, + required this.linkViewModel, }) : super(key: key); final AuthenticationStore authenticationStore; @@ -32,6 +34,7 @@ class Root extends StatefulWidget { final GlobalKey navigatorKey; final AuthService authService; final Widget child; + final LinkViewModel linkViewModel; @override RootState createState() => RootState(); @@ -53,7 +56,6 @@ class RootState extends State with WidgetsBindingObserver { StreamSubscription? stream; ReactionDisposer? _walletReactionDisposer; ReactionDisposer? _deepLinksReactionDisposer; - Uri? launchUri; @override void initState() { @@ -98,7 +100,7 @@ class RootState extends State with WidgetsBindingObserver { void handleDeepLinking(Uri? uri) async { if (uri == null || !mounted) return; - launchUri = uri; + widget.linkViewModel.currentLink = uri; bool requireAuth = await widget.authService.requireAuth(); @@ -112,7 +114,7 @@ class RootState extends State with WidgetsBindingObserver { (AuthenticationState state) { if (state == AuthenticationState.allowed) { if (widget.appStore.wallet == null) { - waitForWalletInstance(context, launchUri!); + waitForWalletInstance(context); } else { _navigateToDeepLinkScreen(); } @@ -150,6 +152,8 @@ class RootState extends State with WidgetsBindingObserver { @override Widget build(BuildContext context) { + // this only happens when the app has been in the background for some time + // this does NOT trigger when the app is started from the "closed" state! if (_isInactive && !_postFrameCallback && _requestAuth) { _postFrameCallback = true; WidgetsBinding.instance.addPostFrameCallback((_) { @@ -158,40 +162,38 @@ class RootState extends State with WidgetsBindingObserver { arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { if (!isAuthenticatedSuccessfully) { return; + } + final useTotp = widget.appStore.settingsStore.useTOTP2FA; + final shouldUseTotp2FAToAccessWallets = + widget.appStore.settingsStore.shouldRequireTOTP2FAForAccessingWallet; + if (useTotp && shouldUseTotp2FAToAccessWallets) { + _reset(); + auth.close( + route: Routes.totpAuthCodePage, + arguments: TotpAuthArgumentsModel( + onTotpAuthenticationFinished: + (bool isAuthenticatedSuccessfully, TotpAuthCodePageState totpAuth) { + if (!isAuthenticatedSuccessfully) { + return; + } + _reset(); + totpAuth.close( + route: widget.linkViewModel.getRouteToGo(), + arguments: widget.linkViewModel.getRouteArgs(), + ); + widget.linkViewModel.currentLink = null; + }, + isForSetup: false, + isClosable: false, + ), + ); } else { - final useTotp = widget.appStore.settingsStore.useTOTP2FA; - final shouldUseTotp2FAToAccessWallets = - widget.appStore.settingsStore.shouldRequireTOTP2FAForAccessingWallet; - if (useTotp && shouldUseTotp2FAToAccessWallets) { - _reset(); - auth.close( - route: Routes.totpAuthCodePage, - arguments: TotpAuthArgumentsModel( - onTotpAuthenticationFinished: - (bool isAuthenticatedSuccessfully, TotpAuthCodePageState totpAuth) { - if (!isAuthenticatedSuccessfully) { - return; - } - _reset(); - totpAuth.close( - route: _getRouteToGo(), - arguments: - isWalletConnectLink ? launchUri : PaymentRequest.fromUri(launchUri), - ); - launchUri = null; - }, - isForSetup: false, - isClosable: false, - ), - ); - } else { - _reset(); - auth.close( - route: _getRouteToGo(), - arguments: isWalletConnectLink ? launchUri : PaymentRequest.fromUri(launchUri), - ); - launchUri = null; - } + _reset(); + auth.close( + route: widget.linkViewModel.getRouteToGo(), + arguments: widget.linkViewModel.getRouteArgs(), + ); + widget.linkViewModel.currentLink = null; } }, ); @@ -216,36 +218,7 @@ class RootState extends State with WidgetsBindingObserver { _isInactiveController.add(value); } - bool _isValidPaymentUri() => launchUri?.path.isNotEmpty ?? false; - - bool get isWalletConnectLink => launchUri?.authority == 'wc'; - - String? _getRouteToGo() { - if (isWalletConnectLink) { - if (isEVMCompatibleChain(widget.appStore.wallet!.type)) { - _nonETHWalletErrorToast(S.current.switchToEVMCompatibleWallet); - return null; - } - return Routes.walletConnectConnectionsListing; - } else if (_isValidPaymentUri()) { - return Routes.send; - } else { - return null; - } - } - - Future _nonETHWalletErrorToast(String message) async { - Fluttertoast.showToast( - msg: message, - toastLength: Toast.LENGTH_LONG, - gravity: ToastGravity.SNACKBAR, - backgroundColor: Colors.black, - textColor: Colors.white, - fontSize: 16.0, - ); - } - - void waitForWalletInstance(BuildContext context, Uri tempLaunchUri) { + void waitForWalletInstance(BuildContext context) { WidgetsBinding.instance.addPostFrameCallback((_) { if (context.mounted) { _walletReactionDisposer = reaction( @@ -263,14 +236,6 @@ class RootState extends State with WidgetsBindingObserver { } void _navigateToDeepLinkScreen() { - if (_getRouteToGo() != null) { - WidgetsBinding.instance.addPostFrameCallback((_) { - widget.navigatorKey.currentState?.pushNamed( - _getRouteToGo()!, - arguments: isWalletConnectLink ? launchUri : PaymentRequest.fromUri(launchUri), - ); - launchUri = null; - }); - } + widget.linkViewModel.handleLink(); } } diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 648133391..d9b74869f 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -35,6 +35,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:mobx/mobx.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:url_launcher/url_launcher.dart'; class SendPage extends BasePage { SendPage({ @@ -420,12 +422,10 @@ class SendPage extends BasePage { } reaction((_) => sendViewModel.state, (ExecutionState state) { - if (dialogContext != null && dialogContext?.mounted == true) { Navigator.of(dialogContext!).pop(); } - if (state is FailureState) { WidgetsBinding.instance.addPostFrameCallback((_) { showPopUp( @@ -460,10 +460,10 @@ class SendPage extends BasePage { outputs: sendViewModel.outputs, rightButtonText: S.of(_dialogContext).send, leftButtonText: S.of(_dialogContext).cancel, - actionRightButton: () { + actionRightButton: () async { Navigator.of(_dialogContext).pop(); sendViewModel.commitTransaction(); - showPopUp( + await showPopUp( context: context, builder: (BuildContext _dialogContext) { return Observer(builder: (_) { @@ -481,12 +481,14 @@ class SendPage extends BasePage { sendViewModel.selectedCryptoCurrency.toString()); final waitMessage = sendViewModel.walletType == WalletType.solana - ? '. ${S.of(_dialogContext).waitFewSecondForTxUpdate}' : ''; + ? '. ${S.of(_dialogContext).waitFewSecondForTxUpdate}' + : ''; final newContactMessage = newContactAddress != null - ? '\n${S.of(_dialogContext).add_contact_to_address_book}' : ''; + ? '\n${S.of(_dialogContext).add_contact_to_address_book}' + : ''; - final alertContent = + String alertContent = "$successMessage$waitMessage$newContactMessage"; if (newContactAddress != null) { @@ -509,6 +511,10 @@ class SendPage extends BasePage { newContactAddress = null; }); } else { + if (initialPaymentRequest?.callbackMessage?.isNotEmpty ?? + false) { + alertContent = initialPaymentRequest!.callbackMessage!; + } return AlertWithOneAction( alertTitle: '', alertContent: alertContent, @@ -523,6 +529,20 @@ class SendPage extends BasePage { 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) { + print(e); + } + } + } }, actionLeftButton: () => Navigator.of(_dialogContext).pop()); }); diff --git a/lib/utils/payment_request.dart b/lib/utils/payment_request.dart index 00093b413..fe0ecf605 100644 --- a/lib/utils/payment_request.dart +++ b/lib/utils/payment_request.dart @@ -1,19 +1,29 @@ +import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/nano/nano.dart'; class PaymentRequest { - PaymentRequest(this.address, this.amount, this.note, this.scheme); + PaymentRequest(this.address, this.amount, this.note, this.scheme, {this.callbackUrl, this.callbackMessage}); factory PaymentRequest.fromUri(Uri? uri) { var address = ""; var amount = ""; var note = ""; var scheme = ""; + String? callbackUrl; + String? callbackMessage; if (uri != null) { - address = uri.path; + address = uri.queryParameters['address'] ?? uri.path; amount = uri.queryParameters['tx_amount'] ?? uri.queryParameters['amount'] ?? ""; note = uri.queryParameters['tx_description'] ?? uri.queryParameters['message'] ?? ""; scheme = uri.scheme; + callbackUrl = uri.queryParameters['callback']; + callbackMessage = uri.queryParameters['callbackMessage']; + } + + if (scheme == "nano-gpt") { + // treat as nano so filling out the address works: + scheme = "nano"; } if (nano != null) { @@ -26,11 +36,20 @@ class PaymentRequest { } } - return PaymentRequest(address, amount, note, scheme); + return PaymentRequest( + address, + amount, + note, + scheme, + callbackUrl: callbackUrl, + callbackMessage: callbackMessage, + ); } final String address; final String amount; final String note; final String scheme; + final String? callbackUrl; + final String? callbackMessage; } diff --git a/lib/view_model/link_view_model.dart b/lib/view_model/link_view_model.dart new file mode 100644 index 000000000..714b57e53 --- /dev/null +++ b/lib/view_model/link_view_model.dart @@ -0,0 +1,118 @@ +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/reactions/wallet_connect.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/store/app_store.dart'; +import 'package:cake_wallet/store/authentication_store.dart'; +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/utils/payment_request.dart'; +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:mobx/mobx.dart'; + +part 'link_view_model.g.dart'; + +class LinkViewModel = LinkViewModelBase with _$LinkViewModel; + +abstract class LinkViewModelBase with Store { + LinkViewModelBase({ + required this.settingsStore, + required this.appStore, + required this.authenticationStore, + required this.navigatorKey, + }) {} + + final SettingsStore settingsStore; + final AppStore appStore; + final AuthenticationStore authenticationStore; + final GlobalKey navigatorKey; + Uri? currentLink; + + bool get _isValidPaymentUri => currentLink?.path.isNotEmpty ?? false; + bool get isWalletConnectLink => currentLink?.authority == 'wc'; + bool get isNanoGptLink => currentLink?.scheme == 'nano-gpt'; + + String? getRouteToGo() { + if (isWalletConnectLink) { + if (!isEVMCompatibleChain(appStore.wallet!.type)) { + _errorToast(S.current.switchToEVMCompatibleWallet); + return null; + } + return Routes.walletConnectConnectionsListing; + } + + if (authenticationStore.state == AuthenticationState.uninitialized) { + return null; + } + + if (isNanoGptLink) { + switch (currentLink?.authority ?? '') { + case "exchange": + return Routes.exchange; + case "send": + return Routes.send; + case "buy": + return Routes.buySellPage; + } + } + + if (_isValidPaymentUri) { + return Routes.send; + } + + return null; + } + + dynamic getRouteArgs() { + if (isWalletConnectLink) { + return currentLink; + } + + if (isNanoGptLink) { + switch (currentLink?.authority ?? '') { + case "exchange": + case "send": + return PaymentRequest.fromUri(currentLink); + case "buy": + return true; + } + } + + if (_isValidPaymentUri) { + return PaymentRequest.fromUri(currentLink); + } + + return null; + } + + Future _errorToast(String message, {double fontSize = 16}) async { + Fluttertoast.showToast( + msg: message, + toastLength: Toast.LENGTH_LONG, + gravity: ToastGravity.SNACKBAR, + backgroundColor: Colors.black, + textColor: Colors.white, + fontSize: fontSize, + ); + } + + Future handleLink() async { + String? route = getRouteToGo(); + dynamic args = getRouteArgs(); + if (route != null) { + if (appStore.wallet == null) { + return; + } + + if (isNanoGptLink) { + if (route == Routes.buySellPage || route == Routes.exchange) { + await _errorToast(S.current.nano_gpt_thanks_message, fontSize: 14); + } + } + currentLink = null; + navigatorKey.currentState?.pushNamed( + route, + arguments: args, + ); + } + } +} diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index 365912743..ab6579eef 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "يجب أن تكون قيمة المبلغ أكبر من أو تساوي ${minAmount} ${fiatCurrency}", "more_options": "المزيد من الخيارات", "name": "ﻢﺳﺍ", + "nano_gpt_thanks_message": "شكرا لاستخدام nanogpt! تذكر أن تعود إلى المتصفح بعد اكتمال معاملتك!", + "nanogpt_subtitle": "جميع النماذج الأحدث (GPT-4 ، Claude). \\ nno اشتراك ، ادفع مع Crypto.", "nano_current_rep": "الممثل الحالي", "nano_pick_new_rep": "اختر ممثلًا جديدًا", "narrow": "ضيق", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 8a7682221..6b6a8be1a 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "Сумата трябва да бъде най-малко ${minAmount} ${fiatCurrency}", "more_options": "Още настройки", "name": "Име", + "nano_gpt_thanks_message": "Благодаря, че използвахте Nanogpt! Не забравяйте да се върнете обратно към браузъра, след като транзакцията ви приключи!", + "nanogpt_subtitle": "Всички най-нови модели (GPT-4, Claude). \\ Nno абонамент, платете с Crypto.", "nano_current_rep": "Настоящ представител", "nano_pick_new_rep": "Изберете нов представител", "narrow": "Тесен", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index e3bbad5a3..86a61a5af 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "Částka musí být větší nebo rovna ${minAmount} ${fiatCurrency}", "more_options": "Více možností", "name": "název", + "nano_gpt_thanks_message": "Děkujeme za používání Nanogpt! Nezapomeňte se po dokončení transakce vydat zpět do prohlížeče!", + "nanogpt_subtitle": "Všechny nejnovější modely (GPT-4, Claude). \\ Nno předplatné, plaťte krypto.", "nano_current_rep": "Současný zástupce", "nano_pick_new_rep": "Vyberte nového zástupce", "narrow": "Úzký", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index ff974f28c..c0639d88d 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "Der Wert des Betrags muss größer oder gleich ${minAmount} ${fiatCurrency} sein", "more_options": "Weitere Optionen", "name": "Name", + "nano_gpt_thanks_message": "Danke, dass du Nanogpt benutzt hast! Denken Sie daran, nach Abschluss Ihrer Transaktion zurück zum Browser zu gehen!", + "nanogpt_subtitle": "Alle neuesten Modelle (GPT-4, Claude).", "nano_current_rep": "Aktueller Vertreter", "nano_pick_new_rep": "Wählen Sie einen neuen Vertreter aus", "narrow": "Eng", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 241d12415..2ee31b491 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "Value of the amount must be more or equal to ${minAmount} ${fiatCurrency}", "more_options": "More Options", "name": "Name", + "nano_gpt_thanks_message": "Thanks for using NanoGPT! Remember to head back to the browser after your transaction completes!", + "nanogpt_subtitle": "All the newest models (GPT-4, Claude).\\nNo subscription, pay with crypto.", "nano_current_rep": "Current Representative", "nano_pick_new_rep": "Pick a new representative", "narrow": "Narrow", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 59c40f67b..8e4177298 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "El valor de la cantidad debe ser mayor o igual a ${minAmount} ${fiatCurrency}", "more_options": "Más Opciones", "name": "Nombre", + "nano_gpt_thanks_message": "¡Gracias por usar nanogpt! ¡Recuerde regresar al navegador después de que se complete su transacción!", + "nanogpt_subtitle": "Todos los modelos más nuevos (GPT-4, Claude). \\ Nno suscripción, pague con cripto.", "nano_current_rep": "Representante actual", "nano_pick_new_rep": "Elija un nuevo representante", "narrow": "Angosto", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 08b6d54b0..4c589b27f 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "Le montant doit être au moins égal à ${minAmount} ${fiatCurrency}", "more_options": "Plus d'options", "name": "Nom", + "nano_gpt_thanks_message": "Merci d'avoir utilisé Nanogpt! N'oubliez pas de retourner au navigateur une fois votre transaction terminée!", + "nanogpt_subtitle": "Tous les modèles les plus récents (GPT-4, Claude). \\ NNO abonnement, payez avec crypto.", "nano_current_rep": "Représentant actuel", "nano_pick_new_rep": "Choisissez un nouveau représentant", "narrow": "Étroit", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 94c030a21..3fe21b3f1 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "Darajar adadin dole ne ya zama fiye ko daidai da ${minAmount} ${fiatCurrency}", "more_options": "Ƙarin Zaɓuɓɓuka", "name": "Suna", + "nano_gpt_thanks_message": "Na gode da amfani da Nanogpt! Ka tuna da komawa zuwa mai bincike bayan ma'amalar ka ta cika!", + "nanogpt_subtitle": "Duk sabbin samfuran (GPT-4, CLODE). \\ NNO biyan kuɗi, biya tare da crypto.", "nano_current_rep": "Wakilin Yanzu", "nano_pick_new_rep": "Dauki sabon wakili", "narrow": "kunkuntar", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 4279e0bee..e2eb28aa2 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "राशि का मूल्य अधिक है या करने के लिए बराबर होना चाहिए ${minAmount} ${fiatCurrency}", "more_options": "और विकल्प", "name": "नाम", + "nano_gpt_thanks_message": "Nanogpt का उपयोग करने के लिए धन्यवाद! अपने लेन -देन के पूरा होने के बाद ब्राउज़र पर वापस जाना याद रखें!", + "nanogpt_subtitle": "सभी नवीनतम मॉडल (GPT-4, क्लाउड)। \\ nno सदस्यता, क्रिप्टो के साथ भुगतान करें।", "nano_current_rep": "वर्तमान प्रतिनिधि", "nano_pick_new_rep": "एक नया प्रतिनिधि चुनें", "narrow": "सँकरा", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 106243e51..079de0c4f 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "Vrijednost iznosa mora biti veća ili jednaka ${minAmount} ${fiatCurrency}", "more_options": "Više opcija", "name": "Ime", + "nano_gpt_thanks_message": "Hvala što ste koristili nanogpt! Ne zaboravite da se vratite u preglednik nakon što vam se transakcija završi!", + "nanogpt_subtitle": "Svi najnoviji modeli (GPT-4, Claude). \\ NNO pretplata, plaćajte kripto.", "nano_current_rep": "Trenutni predstavnik", "nano_pick_new_rep": "Odaberite novog predstavnika", "narrow": "Usko", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index 01c36da93..ae9e4e38f 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "Nilai jumlah harus lebih atau sama dengan ${minAmount} ${fiatCurrency}", "more_options": "Opsi Lainnya", "name": "Nama", + "nano_gpt_thanks_message": "Terima kasih telah menggunakan Nanogpt! Ingatlah untuk kembali ke browser setelah transaksi Anda selesai!", + "nanogpt_subtitle": "Semua model terbaru (GPT-4, Claude). \\ Nno langganan, bayar dengan crypto.", "nano_current_rep": "Perwakilan saat ini", "nano_pick_new_rep": "Pilih perwakilan baru", "narrow": "Sempit", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 61a3fa2cf..5fa1b52ef 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -367,6 +367,8 @@ "moonpay_alert_text": "Il valore dell'importo deve essere maggiore o uguale a ${minAmount} ${fiatCurrency}", "more_options": "Altre opzioni", "name": "Nome", + "nano_gpt_thanks_message": "Grazie per aver usato il nanogpt! Ricorda di tornare al browser dopo il completamento della transazione!", + "nanogpt_subtitle": "Tutti i modelli più recenti (GPT-4, Claude). Abbonamento nno, paga con cripto.", "nano_current_rep": "Rappresentante attuale", "nano_pick_new_rep": "Scegli un nuovo rappresentante", "narrow": "Stretto", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index db92a2f92..a01df3c07 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -367,6 +367,8 @@ "moonpay_alert_text": "金額の値は以上でなければなりません ${minAmount} ${fiatCurrency}", "more_options": "その他のオプション", "name": "名前", + "nano_gpt_thanks_message": "NanoGptを使用してくれてありがとう!トランザクションが完了したら、ブラウザに戻ることを忘れないでください!", + "nanogpt_subtitle": "すべての最新モデル(GPT-4、Claude)。\\ nnoサブスクリプション、暗号で支払います。", "nano_current_rep": "現在の代表", "nano_pick_new_rep": "新しい代表者を選びます", "narrow": "狭い", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index fc84d7c35..53cbeb01f 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "금액은 다음보다 크거나 같아야합니다 ${minAmount} ${fiatCurrency}", "more_options": "추가 옵션", "name": "이름", + "nano_gpt_thanks_message": "Nanogpt를 사용해 주셔서 감사합니다! 거래가 완료된 후 브라우저로 돌아가는 것을 잊지 마십시오!", + "nanogpt_subtitle": "모든 최신 모델 (GPT-4, Claude). \\ nno 구독, Crypto로 지불하십시오.", "nano_current_rep": "현재 대표", "nano_pick_new_rep": "새로운 담당자를 선택하십시오", "narrow": "좁은", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index 0e18179e1..bb2099b15 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "ပမာဏ၏တန်ဖိုးသည် ${minAmount} ${fiatCurrency} နှင့် ပိုနေရမည်", "more_options": "နောက်ထပ် ရွေးချယ်စရာများ", "name": "နာမည်", + "nano_gpt_thanks_message": "nanogpt ကိုသုံးပြီးကျေးဇူးတင်ပါတယ် သင်၏ငွေပေးငွေယူပြီးနောက် browser သို့ပြန်သွားရန်သတိရပါ။", + "nanogpt_subtitle": "အားလုံးနောက်ဆုံးပေါ်မော်ဒယ်များ (GPT-4, Claude) ။ \\ nno subscription, crypto နှင့်အတူပေးဆောင်။", "nano_current_rep": "လက်ရှိကိုယ်စားလှယ်", "nano_pick_new_rep": "အသစ်တစ်ခုကိုရွေးပါ", "narrow": "ကျဉ်းသော", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index dff34c122..ca9b5a79f 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "Waarde van het bedrag moet meer of gelijk zijn aan ${minAmount} ${fiatCurrency}", "more_options": "Meer opties", "name": "Naam", + "nano_gpt_thanks_message": "Bedankt voor het gebruik van Nanogpt! Vergeet niet om terug te gaan naar de browser nadat uw transactie is voltooid!", + "nanogpt_subtitle": "Alle nieuwste modellen (GPT-4, Claude). \\ Nno-abonnement, betalen met crypto.", "nano_current_rep": "Huidige vertegenwoordiger", "nano_pick_new_rep": "Kies een nieuwe vertegenwoordiger", "narrow": "Smal", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index b8640f5fe..44e8c0b95 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "Wartość kwoty musi być większa lub równa ${minAmount} ${fiatCurrency}", "more_options": "Więcej opcji", "name": "Nazwa", + "nano_gpt_thanks_message": "Dzięki za użycie Nanogpt! Pamiętaj, aby wrócić do przeglądarki po zakończeniu transakcji!", + "nanogpt_subtitle": "Wszystkie najnowsze modele (GPT-4, Claude). \\ Nno subskrypcja, płacą za pomocą kryptografii.", "nano_current_rep": "Obecny przedstawiciel", "nano_pick_new_rep": "Wybierz nowego przedstawiciela", "narrow": "Wąski", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 7d606e2c1..b8805e789 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -367,6 +367,8 @@ "moonpay_alert_text": "O valor do montante deve ser maior ou igual a ${minAmount} ${fiatCurrency}", "more_options": "Mais opções", "name": "Nome", + "nano_gpt_thanks_message": "Obrigado por usar o Nanogpt! Lembre -se de voltar para o navegador após a conclusão da transação!", + "nanogpt_subtitle": "Todos os modelos mais recentes (GPT-4, Claude). \\ Nno assinatura, pagam com criptografia.", "nano_current_rep": "Representante atual", "nano_pick_new_rep": "Escolha um novo representante", "narrow": "Estreito", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index c6466a24e..32f513fe5 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "Сумма должна быть больше или равна ${minAmount} ${fiatCurrency}", "more_options": "Дополнительные параметры", "name": "Имя", + "nano_gpt_thanks_message": "Спасибо за использование Nanogpt! Не забудьте вернуться в браузер после завершения транзакции!", + "nanogpt_subtitle": "Все новейшие модели (GPT-4, Claude). \\ Nno Подписка, платите с крипто.", "nano_current_rep": "Нынешний представитель", "nano_pick_new_rep": "Выберите нового представителя", "narrow": "Узкий", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 6b68d1e50..18b9adce9 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "มูลค่าของจำนวนต้องมากกว่าหรือเท่ากับ ${minAmount} ${fiatCurrency}", "more_options": "ตัวเลือกเพิ่มเติม", "name": "ชื่อ", + "nano_gpt_thanks_message": "ขอบคุณที่ใช้ Nanogpt! อย่าลืมกลับไปที่เบราว์เซอร์หลังจากการทำธุรกรรมของคุณเสร็จสิ้น!", + "nanogpt_subtitle": "รุ่นใหม่ล่าสุดทั้งหมด (GPT-4, Claude). การสมัครสมาชิก \\ nno, จ่ายด้วย crypto", "nano_current_rep": "ตัวแทนปัจจุบัน", "nano_pick_new_rep": "เลือกตัวแทนใหม่", "narrow": "แคบ", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 6d388973a..76a94bbe2 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "Ang halaga ng halaga ay dapat na higit pa o katumbas ng ${minAmount} ${fiatCurrency}", "more_options": "Higit pang mga pagpipilian", "name": "Pangalan", + "nano_gpt_thanks_message": "Salamat sa paggamit ng nanogpt! Tandaan na bumalik sa browser matapos makumpleto ang iyong transaksyon!", + "nanogpt_subtitle": "Ang lahat ng mga pinakabagong modelo (GPT-4, Claude). \\ Nno subscription, magbayad gamit ang crypto.", "nano_current_rep": "Kasalukuyang kinatawan", "nano_pick_new_rep": "Pumili ng isang bagong kinatawan", "narrow": "Makitid", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index ddf99696b..62e541ded 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "Tutar ${minAmount} ${fiatCurrency} miktarına eşit veya daha fazla olmalıdır", "more_options": "Daha Fazla Seçenek", "name": "İsim", + "nano_gpt_thanks_message": "Nanogpt kullandığınız için teşekkürler! İşleminiz tamamlandıktan sonra tarayıcıya geri dönmeyi unutmayın!", + "nanogpt_subtitle": "En yeni modeller (GPT-4, Claude). \\ Nno aboneliği, kripto ile ödeme yapın.", "nano_current_rep": "Mevcut temsilci", "nano_pick_new_rep": "Yeni bir temsilci seçin", "narrow": "Dar", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 2f294817e..6184fed11 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "Значення суми має бути більшим або дорівнювати ${minAmount} ${fiatCurrency}", "more_options": "Більше параметрів", "name": "Ім'я", + "nano_gpt_thanks_message": "Дякуємо за використання наногпта! Не забудьте повернутися до браузера після завершення транзакції!", + "nanogpt_subtitle": "Усі найновіші моделі (GPT-4, Claude). \\ Nno підписка, оплата криптовалютою.", "nano_current_rep": "Поточний представник", "nano_pick_new_rep": "Виберіть нового представника", "narrow": "вузькі", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index 048cfb070..dadd3505b 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "رقم کی قدر ${minAmount} ${fiatCurrency} کے برابر یا زیادہ ہونی چاہیے۔", "more_options": "مزید زرائے", "name": "ﻡﺎﻧ", + "nano_gpt_thanks_message": "نانوگپٹ استعمال کرنے کا شکریہ! اپنے لین دین کی تکمیل کے بعد براؤزر کی طرف واپس جانا یاد رکھیں!", + "nanogpt_subtitle": "تمام تازہ ترین ماڈل (GPT-4 ، کلاڈ)۔ n n no سبسکرپشن ، کریپٹو کے ساتھ ادائیگی کریں۔", "nano_current_rep": "موجودہ نمائندہ", "nano_pick_new_rep": "ایک نیا نمائندہ منتخب کریں", "narrow": "تنگ", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 8a379a258..d9fa48a45 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -367,6 +367,8 @@ "moonpay_alert_text": "Iye owó kò gbọ́dọ̀ kéré ju ${minAmount} ${fiatCurrency}", "more_options": "Ìyàn àfikún", "name": "Oruko", + "nano_gpt_thanks_message": "O ṣeun fun lilo Nonnogt! Ranti lati tẹle pada si ẹrọ lilọ kiri ayelujara lẹhin iṣowo rẹ pari!", + "nanogpt_subtitle": "Gbogbo awọn awoṣe tuntun (GPT-4, Claude). \\ Nno alabapin kan, sanwo pẹlu Crypto.", "nano_current_rep": "Aṣoju lọwọlọwọ", "nano_pick_new_rep": "Mu aṣoju tuntun kan", "narrow": "Taara", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index bf6684dee..089d5fa74 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -366,6 +366,8 @@ "moonpay_alert_text": "金额的价值必须大于或等于 ${minAmount} ${fiatCurrency}", "more_options": "更多选项", "name": "姓名", + "nano_gpt_thanks_message": "感谢您使用Nanogpt!事务完成后,请记住回到浏览器!", + "nanogpt_subtitle": "所有最新型号(GPT-4,Claude)。\\ nno订阅,用加密货币付款。", "nano_current_rep": "当前代表", "nano_pick_new_rep": "选择新代表", "narrow": "狭窄的", diff --git a/tool/generate_secrets_config.dart b/tool/generate_secrets_config.dart index 6aaa39b7c..cab41ca69 100644 --- a/tool/generate_secrets_config.dart +++ b/tool/generate_secrets_config.dart @@ -6,6 +6,7 @@ import 'utils/utils.dart'; const configPath = 'tool/.secrets-config.json'; const evmChainsConfigPath = 'tool/.evm-secrets-config.json'; const solanaConfigPath = 'tool/.solana-secrets-config.json'; +const nanoConfigPath = 'tool/.nano-secrets-config.json'; const tronConfigPath = 'tool/.tron-secrets-config.json'; Future main(List args) async => generateSecretsConfig(args); @@ -21,6 +22,7 @@ Future generateSecretsConfig(List args) async { final configFile = File(configPath); final evmChainsConfigFile = File(evmChainsConfigPath); final solanaConfigFile = File(solanaConfigPath); + final nanoConfigFile = File(nanoConfigPath); final tronConfigFile = File(tronConfigPath); final secrets = {}; @@ -42,45 +44,48 @@ Future generateSecretsConfig(List args) async { } } + // base: SecretKey.base.forEach((sec) { if (secrets[sec.name] != null) { return; } - secrets[sec.name] = sec.generate(); }); - var secretsJson = JsonEncoder.withIndent(' ').convert(secrets); await configFile.writeAsString(secretsJson); - secrets.clear(); + // evm chains: SecretKey.evmChainsSecrets.forEach((sec) { if (secrets[sec.name] != null) { return; } - secrets[sec.name] = sec.generate(); }); - secretsJson = JsonEncoder.withIndent(' ').convert(secrets); - await evmChainsConfigFile.writeAsString(secretsJson); - secrets.clear(); + // solana: SecretKey.solanaSecrets.forEach((sec) { if (secrets[sec.name] != null) { return; } - secrets[sec.name] = sec.generate(); }); - secretsJson = JsonEncoder.withIndent(' ').convert(secrets); - await solanaConfigFile.writeAsString(secretsJson); + secrets.clear(); + // nano: + SecretKey.nanoSecrets.forEach((sec) { + if (secrets[sec.name] != null) { + return; + } + secrets[sec.name] = sec.generate(); + }); + secretsJson = JsonEncoder.withIndent(' ').convert(secrets); + await nanoConfigFile.writeAsString(secretsJson); secrets.clear(); SecretKey.tronSecrets.forEach((sec) { @@ -90,8 +95,7 @@ Future generateSecretsConfig(List args) async { secrets[sec.name] = sec.generate(); }); - secretsJson = JsonEncoder.withIndent(' ').convert(secrets); - await tronConfigFile.writeAsString(secretsJson); + secrets.clear(); } diff --git a/tool/utils/secret_key.dart b/tool/utils/secret_key.dart index 542e91b38..89e4de12d 100644 --- a/tool/utils/secret_key.dart +++ b/tool/utils/secret_key.dart @@ -50,6 +50,10 @@ class SecretKey { SecretKey('ankrApiKey', () => ''), ]; + static final nanoSecrets = [ + SecretKey('nano2ApiKey', () => ''), + ]; + static final tronSecrets = [ SecretKey('tronGridApiKey', () => ''), ]; From 12e3001b3aad7381c51ef348dc86cdf5cc193e05 Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Wed, 8 May 2024 17:26:57 +0300 Subject: [PATCH 214/241] Generic enhancements (#1435) * Disable Ledger for MacOS * increase update duration for Solana [skip ci] * change tron default Node Update build number * Add disabling tron grid to privacy settings * update monero.com versions [skip ci] --- assets/text/Release_Notes.txt | 5 ++- assets/tron_node_list.yml | 4 +-- cw_solana/lib/solana_wallet.dart | 2 +- cw_tron/lib/default_tron_tokens.dart | 4 +-- cw_tron/lib/tron_http_provider.dart | 4 +-- cw_tron/lib/tron_wallet.dart | 20 +++++++---- ios/Flutter/AppFrameworkInfo.plist | 2 +- ios/Podfile.lock | 20 +++++------ lib/entities/default_settings_migration.dart | 2 +- lib/entities/preferences_key.dart | 1 + .../provider/thorchain_exchange.provider.dart | 14 ++++---- .../screens/restore/restore_options_page.dart | 22 ++++++------ lib/src/screens/settings/privacy_page.dart | 8 +++++ lib/store/settings_store.dart | 12 +++++++ lib/tron/cw_tron.dart | 5 +++ .../hardware_wallet/ledger_view_model.dart | 35 +++++++++++-------- lib/view_model/link_view_model.dart | 11 ++---- .../settings/privacy_settings_view_model.dart | 12 +++++++ macos/Podfile.lock | 4 +-- macos/Runner.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 10 +++--- res/values/strings_ar.arb | 5 +-- res/values/strings_bg.arb | 5 +-- res/values/strings_cs.arb | 5 +-- res/values/strings_de.arb | 5 +-- res/values/strings_en.arb | 5 +-- res/values/strings_es.arb | 5 +-- res/values/strings_fr.arb | 5 +-- res/values/strings_ha.arb | 5 +-- res/values/strings_hi.arb | 5 +-- res/values/strings_hr.arb | 5 +-- res/values/strings_id.arb | 5 +-- res/values/strings_it.arb | 5 +-- res/values/strings_ja.arb | 5 +-- res/values/strings_ko.arb | 5 +-- res/values/strings_my.arb | 5 +-- res/values/strings_nl.arb | 5 +-- res/values/strings_pl.arb | 5 +-- res/values/strings_pt.arb | 5 +-- res/values/strings_ru.arb | 5 +-- res/values/strings_th.arb | 5 +-- res/values/strings_tl.arb | 5 +-- res/values/strings_tr.arb | 5 +-- res/values/strings_uk.arb | 5 +-- res/values/strings_ur.arb | 5 +-- res/values/strings_yo.arb | 5 +-- res/values/strings_zh.arb | 5 +-- scripts/android/app_env.sh | 8 ++--- scripts/ios/app_env.sh | 8 ++--- scripts/macos/app_env.sh | 8 ++--- tool/configure.dart | 2 ++ 51 files changed, 217 insertions(+), 138 deletions(-) diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt index ae6306209..3ff7aa3b4 100644 --- a/assets/text/Release_Notes.txt +++ b/assets/text/Release_Notes.txt @@ -1 +1,4 @@ -Bitcoin Bug fixes and enhancements \ No newline at end of file +Hardware wallets support for Bitcoin, Ethereum and Polygon +Add Tron wallet +Security enhancements +Bug fixes and generic enhancements \ No newline at end of file diff --git a/assets/tron_node_list.yml b/assets/tron_node_list.yml index 4c67b920e..d28e38f2e 100644 --- a/assets/tron_node_list.yml +++ b/assets/tron_node_list.yml @@ -1,8 +1,8 @@ - - uri: api.trongrid.io + uri: tron-rpc.publicnode.com:443 is_default: true useSSL: true - - uri: tron-rpc.publicnode.com:443 + uri: api.trongrid.io is_default: false useSSL: true \ No newline at end of file diff --git a/cw_solana/lib/solana_wallet.dart b/cw_solana/lib/solana_wallet.dart index 6692b65a6..401968698 100644 --- a/cw_solana/lib/solana_wallet.dart +++ b/cw_solana/lib/solana_wallet.dart @@ -524,7 +524,7 @@ abstract class SolanaWalletBase _transactionsUpdateTimer!.cancel(); } - _transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 20), (_) { + _transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 30), (_) { _updateBalance(); _updateNativeSOLTransactions(); _updateSPLTokenTransactions(); diff --git a/cw_tron/lib/default_tron_tokens.dart b/cw_tron/lib/default_tron_tokens.dart index ad70f28cd..6aa6357e6 100644 --- a/cw_tron/lib/default_tron_tokens.dart +++ b/cw_tron/lib/default_tron_tokens.dart @@ -22,14 +22,14 @@ class DefaultTronTokens { symbol: "BTC", contractAddress: "TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9", decimal: 8, - enabled: true, + enabled: false, ), TronToken( name: "Ethereum", symbol: "ETH", contractAddress: "TRFe3hT5oYhjSZ6f3ji5FJ7YCfrkWnHRvh", decimal: 18, - enabled: true, + enabled: false, ), TronToken( name: "Wrapped BTC", diff --git a/cw_tron/lib/tron_http_provider.dart b/cw_tron/lib/tron_http_provider.dart index 193a3dbdd..58d313378 100644 --- a/cw_tron/lib/tron_http_provider.dart +++ b/cw_tron/lib/tron_http_provider.dart @@ -19,7 +19,7 @@ class TronHTTPProvider implements TronServiceProvider { Future> get(TronRequestDetails params, [Duration? timeout]) async { final response = await client.get(Uri.parse(params.url(url)), headers: { 'Content-Type': 'application/json', - 'TRON-PRO-API-KEY': secrets.tronGridApiKey, + if (url.contains("trongrid")) 'TRON-PRO-API-KEY': secrets.tronGridApiKey, }).timeout(timeout ?? defaultRequestTimeout); final data = json.decode(response.body) as Map; return data; @@ -31,7 +31,7 @@ class TronHTTPProvider implements TronServiceProvider { .post(Uri.parse(params.url(url)), headers: { 'Content-Type': 'application/json', - 'TRON-PRO-API-KEY': secrets.tronGridApiKey, + if (url.contains("trongrid")) 'TRON-PRO-API-KEY': secrets.tronGridApiKey, }, body: params.toRequestBody()) .timeout(timeout ?? defaultRequestTimeout); diff --git a/cw_tron/lib/tron_wallet.dart b/cw_tron/lib/tron_wallet.dart index 6cef05348..96f92e450 100644 --- a/cw_tron/lib/tron_wallet.dart +++ b/cw_tron/lib/tron_wallet.dart @@ -31,7 +31,6 @@ import 'package:cw_tron/tron_wallet_addresses.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:on_chain/on_chain.dart'; -import 'package:shared_preferences/shared_preferences.dart'; part 'tron_wallet.g.dart'; @@ -61,8 +60,6 @@ abstract class TronWalletBase if (!CakeHive.isAdapterRegistered(TronToken.typeId)) { CakeHive.registerAdapter(TronTokenAdapter()); } - - sharedPrefs.complete(SharedPreferences.getInstance()); } final String? _mnemonic; @@ -81,7 +78,7 @@ abstract class TronWalletBase late String _tronAddress; - late TronClient _client; + late final TronClient _client; Timer? _transactionsUpdateTimer; @@ -102,8 +99,6 @@ abstract class TronWalletBase @observable late ObservableMap balance; - Completer sharedPrefs = Completer(); - Future init() async { await initTronTokensBox(); @@ -464,6 +459,7 @@ abstract class TronWalletBase } } + @override Future? updateBalance() async => await _updateBalance(); List get tronTokenCurrencies => tronTokensBox.values.toList(); @@ -543,7 +539,7 @@ abstract class TronWalletBase _transactionsUpdateTimer!.cancel(); } - _transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 20), (_) async { + _transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 30), (_) async { _updateBalance(); await fetchTransactions(); fetchTrc20ExcludedTransactions(); @@ -557,4 +553,14 @@ abstract class TronWalletBase String getTronBase58AddressFromHex(String hexAddress) { return TronAddress(hexAddress).toAddress(); } + + void updateScanProviderUsageState(bool isEnabled) { + if (isEnabled) { + fetchTransactions(); + fetchTrc20ExcludedTransactions(); + _setTransactionUpdateTimer(); + } else { + _transactionsUpdateTimer?.cancel(); + } + } } diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index cb6be3098..cae654377 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 12.0 diff --git a/ios/Podfile.lock b/ios/Podfile.lock index cd03e10a9..0cc57e075 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -109,6 +109,8 @@ PODS: - flutter_inappwebview_ios/Core (0.0.1): - Flutter - OrderedSet (~> 5.0) + - flutter_local_authentication (1.2.0): + - Flutter - flutter_mailer (0.0.1): - Flutter - flutter_secure_storage (6.0.0): @@ -118,8 +120,6 @@ PODS: - Toast - in_app_review (0.2.0): - Flutter - - local_auth_ios (0.0.1): - - Flutter - MTBBarcodeScanner (5.0.11) - OrderedSet (5.0.0) - package_info (0.0.1): @@ -175,11 +175,11 @@ DEPENDENCIES: - file_picker (from `.symlinks/plugins/file_picker/ios`) - Flutter (from `Flutter`) - flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`) + - flutter_local_authentication (from `.symlinks/plugins/flutter_local_authentication/ios`) - flutter_mailer (from `.symlinks/plugins/flutter_mailer/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - in_app_review (from `.symlinks/plugins/in_app_review/ios`) - - local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`) - package_info (from `.symlinks/plugins/package_info/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) @@ -233,6 +233,8 @@ EXTERNAL SOURCES: :path: Flutter flutter_inappwebview_ios: :path: ".symlinks/plugins/flutter_inappwebview_ios/ios" + flutter_local_authentication: + :path: ".symlinks/plugins/flutter_local_authentication/ios" flutter_mailer: :path: ".symlinks/plugins/flutter_mailer/ios" flutter_secure_storage: @@ -241,8 +243,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/fluttertoast/ios" in_app_review: :path: ".symlinks/plugins/in_app_review/ios" - local_auth_ios: - :path: ".symlinks/plugins/local_auth_ios/ios" package_info: :path: ".symlinks/plugins/package_info/ios" package_info_plus: @@ -282,18 +282,18 @@ SPEC CHECKSUMS: DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 file_picker: 15fd9539e4eb735dc54bae8c0534a7a9511a03de - Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 flutter_inappwebview_ios: 97215cf7d4677db55df76782dbd2930c5e1c1ea0 + flutter_local_authentication: 1172a4dd88f6306dadce067454e2c4caf07977bb flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83 flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be fluttertoast: 48c57db1b71b0ce9e6bba9f31c940ff4b001293c in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d - local_auth_ios: 1ba1475238daa33a6ffa2a29242558437be435ac MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 - path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 Protobuf: 8e9074797a13c484a79959fdb819ef4ae6da7dbe ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 @@ -301,13 +301,13 @@ SPEC CHECKSUMS: SDWebImage: a3ba0b8faac7228c3c8eadd1a55c9c9fe5e16457 sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986 share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 - shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1 SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f Toast: ec33c32b8688982cecc6348adeae667c1b9938da uni_links: d97da20c7701486ba192624d99bffaaffcfc298a UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841 - url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812 + url_launcher_ios: 6116280ddcfe98ab8820085d8d76ae7449447586 wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47 workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6 diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 94b23d3c9..77db474a9 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -36,7 +36,7 @@ const cakeWalletBitcoinCashDefaultNodeUri = 'bitcoincash.stackwallet.com:50002'; const nanoDefaultNodeUri = 'rpc.nano.to'; const nanoDefaultPowNodeUri = 'rpc.nano.to'; const solanaDefaultNodeUri = 'rpc.ankr.com'; -const tronDefaultNodeUri = 'api.trongrid.io'; +const tronDefaultNodeUri = 'tron-rpc.publicnode.com:443'; const newCakeWalletBitcoinUri = 'btc-electrum.cakewallet.com:50002'; Future defaultSettingsMigration( diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index 55b5d55a1..cf9ae3019 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -56,6 +56,7 @@ class PreferencesKey { static const pinNativeTokenAtTop = 'pin_native_token_at_top'; static const useEtherscan = 'use_etherscan'; static const usePolygonScan = 'use_polygonscan'; + static const useTronGrid = 'use_trongrid'; static const defaultNanoRep = 'default_nano_representative'; static const defaultBananoRep = 'default_banano_representative'; static const lookupsTwitter = 'looks_up_twitter'; diff --git a/lib/exchange/provider/thorchain_exchange.provider.dart b/lib/exchange/provider/thorchain_exchange.provider.dart index 826e203f3..22937e603 100644 --- a/lib/exchange/provider/thorchain_exchange.provider.dart +++ b/lib/exchange/provider/thorchain_exchange.provider.dart @@ -19,15 +19,15 @@ class ThorChainExchangeProvider extends ExchangeProvider { ...(CryptoCurrency.all .where((element) => ![ CryptoCurrency.btc, - CryptoCurrency.eth, + // CryptoCurrency.eth, CryptoCurrency.ltc, CryptoCurrency.bch, - CryptoCurrency.aave, - CryptoCurrency.dai, - CryptoCurrency.gusd, - CryptoCurrency.usdc, - CryptoCurrency.usdterc20, - CryptoCurrency.wbtc, + // CryptoCurrency.aave, + // CryptoCurrency.dai, + // CryptoCurrency.gusd, + // CryptoCurrency.usdc, + // CryptoCurrency.usdterc20, + // CryptoCurrency.wbtc, // TODO: temporarily commented until https://github.com/cake-tech/cake_wallet/pull/1436 is merged ].contains(element)) .toList()) ]; diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart index a0f3a597e..454d124da 100644 --- a/lib/src/screens/restore/restore_options_page.dart +++ b/lib/src/screens/restore/restore_options_page.dart @@ -7,6 +7,7 @@ import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/option_tile.dart'; import 'package:cake_wallet/themes/extensions/option_tile_theme.dart'; +import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/permission_handler.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; @@ -56,17 +57,18 @@ class RestoreOptionsPage extends BasePage { description: S.of(context).restore_description_from_backup, ), ), - Padding( - padding: EdgeInsets.only(top: 24), - child: OptionTile( - onPressed: () => Navigator.pushNamed( - context, Routes.restoreWalletFromHardwareWallet, - arguments: isNewInstall), - image: imageLedger, - title: S.of(context).restore_title_from_hardware_wallet, - description: S.of(context).restore_description_from_hardware_wallet, + if (DeviceInfo.instance.isMobile) + Padding( + padding: EdgeInsets.only(top: 24), + child: OptionTile( + onPressed: () => Navigator.pushNamed( + context, Routes.restoreWalletFromHardwareWallet, + arguments: isNewInstall), + image: imageLedger, + title: S.of(context).restore_title_from_hardware_wallet, + description: S.of(context).restore_description_from_hardware_wallet, + ), ), - ), Padding( padding: EdgeInsets.only(top: 24), child: OptionTile( diff --git a/lib/src/screens/settings/privacy_page.dart b/lib/src/screens/settings/privacy_page.dart index 7e7f3589b..0eaf3ffbd 100644 --- a/lib/src/screens/settings/privacy_page.dart +++ b/lib/src/screens/settings/privacy_page.dart @@ -103,6 +103,14 @@ class PrivacyPage extends BasePage { _privacySettingsViewModel.setUsePolygonScan(value); }, ), + if (_privacySettingsViewModel.canUseTronGrid) + SettingsSwitcherCell( + title: S.current.trongrid_history, + value: _privacySettingsViewModel.useTronGrid, + onValueChange: (BuildContext _, bool value) { + _privacySettingsViewModel.setUseTronGrid(value); + }, + ), SettingsCellWithArrow( title: S.current.domain_looks_up, handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage), diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index cd9b44391..ada08c1b6 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -99,6 +99,7 @@ abstract class SettingsStoreBase with Store { required this.pinNativeTokenAtTop, required this.useEtherscan, required this.usePolygonScan, + required this.useTronGrid, required this.defaultNanoRep, required this.defaultBananoRep, required this.lookupsTwitter, @@ -397,6 +398,11 @@ abstract class SettingsStoreBase with Store { (bool usePolygonScan) => _sharedPreferences.setBool(PreferencesKey.usePolygonScan, usePolygonScan)); + reaction( + (_) => useTronGrid, + (bool useTronGrid) => + _sharedPreferences.setBool(PreferencesKey.useTronGrid, useTronGrid)); + reaction((_) => defaultNanoRep, (String nanoRep) => _sharedPreferences.setString(PreferencesKey.defaultNanoRep, nanoRep)); @@ -674,6 +680,9 @@ abstract class SettingsStoreBase with Store { @observable bool usePolygonScan; + @observable + bool useTronGrid; + @observable String defaultNanoRep; @@ -846,6 +855,7 @@ abstract class SettingsStoreBase with Store { : defaultSeedPhraseLength; final useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true; final usePolygonScan = sharedPreferences.getBool(PreferencesKey.usePolygonScan) ?? true; + final useTronGrid = sharedPreferences.getBool(PreferencesKey.useTronGrid) ?? true; final defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? ""; final defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? ""; final lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true; @@ -1090,6 +1100,7 @@ abstract class SettingsStoreBase with Store { pinNativeTokenAtTop: pinNativeTokenAtTop, useEtherscan: useEtherscan, usePolygonScan: usePolygonScan, + useTronGrid: useTronGrid, defaultNanoRep: defaultNanoRep, defaultBananoRep: defaultBananoRep, lookupsTwitter: lookupsTwitter, @@ -1227,6 +1238,7 @@ abstract class SettingsStoreBase with Store { pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true; useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true; usePolygonScan = sharedPreferences.getBool(PreferencesKey.usePolygonScan) ?? true; + useTronGrid = sharedPreferences.getBool(PreferencesKey.useTronGrid) ?? true; defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? ""; defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? ""; lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true; diff --git a/lib/tron/cw_tron.dart b/lib/tron/cw_tron.dart index 6e4b0a7b0..52b4f59f7 100644 --- a/lib/tron/cw_tron.dart +++ b/lib/tron/cw_tron.dart @@ -111,4 +111,9 @@ class CWTron extends Tron { @override String? getTronTRC20EstimatedFee(WalletBase wallet) => (wallet as TronWallet).trc20EstimatedFee; + + @override + void updateTronGridUsageState(WalletBase wallet, bool isEnabled) { + (wallet as TronWallet).updateScanProviderUsageState(isEnabled); + } } diff --git a/lib/view_model/hardware_wallet/ledger_view_model.dart b/lib/view_model/hardware_wallet/ledger_view_model.dart index 453df44db..06ddaf275 100644 --- a/lib/view_model/hardware_wallet/ledger_view_model.dart +++ b/lib/view_model/hardware_wallet/ledger_view_model.dart @@ -2,27 +2,34 @@ 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/polygon/polygon.dart'; +import 'package:cake_wallet/utils/device_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:ledger_flutter/ledger_flutter.dart'; import 'package:permission_handler/permission_handler.dart'; class LedgerViewModel { - final Ledger ledger = Ledger( - options: LedgerOptions( - scanMode: ScanMode.balanced, - maxScanDuration: const Duration(minutes: 5), - ), - onPermissionRequest: (_) async { - Map statuses = await [ - Permission.bluetoothScan, - Permission.bluetoothConnect, - Permission.bluetoothAdvertise, - ].request(); + late final Ledger ledger; - return statuses.values.where((status) => status.isDenied).isEmpty; - }, - ); + LedgerViewModel() { + if (DeviceInfo.instance.isMobile) { + ledger = Ledger( + options: LedgerOptions( + scanMode: ScanMode.balanced, + maxScanDuration: const Duration(minutes: 5), + ), + onPermissionRequest: (_) async { + Map statuses = await [ + Permission.bluetoothScan, + Permission.bluetoothConnect, + Permission.bluetoothAdvertise, + ].request(); + + return statuses.values.where((status) => status.isDenied).isEmpty; + }, + ); + } + } Future connectLedger(LedgerDevice device) async { await ledger.connect(device); diff --git a/lib/view_model/link_view_model.dart b/lib/view_model/link_view_model.dart index 714b57e53..99aed486e 100644 --- a/lib/view_model/link_view_model.dart +++ b/lib/view_model/link_view_model.dart @@ -7,19 +7,14 @@ import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/utils/payment_request.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; -import 'package:mobx/mobx.dart'; -part 'link_view_model.g.dart'; - -class LinkViewModel = LinkViewModelBase with _$LinkViewModel; - -abstract class LinkViewModelBase with Store { - LinkViewModelBase({ +class LinkViewModel { + LinkViewModel({ required this.settingsStore, required this.appStore, required this.authenticationStore, required this.navigatorKey, - }) {} + }); final SettingsStore settingsStore; final AppStore appStore; diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart index 9ebbd92bb..9f0ffa14c 100644 --- a/lib/view_model/settings/privacy_settings_view_model.dart +++ b/lib/view_model/settings/privacy_settings_view_model.dart @@ -3,6 +3,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/tron/tron.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/transaction_info.dart'; @@ -70,6 +71,9 @@ abstract class PrivacySettingsViewModelBase with Store { @computed bool get usePolygonScan => _settingsStore.usePolygonScan; + @computed + bool get useTronGrid => _settingsStore.useTronGrid; + @computed bool get lookupTwitter => _settingsStore.lookupsTwitter; @@ -92,6 +96,8 @@ abstract class PrivacySettingsViewModelBase with Store { bool get canUsePolygonScan => _wallet.type == WalletType.polygon; + bool get canUseTronGrid => _wallet.type == WalletType.tron; + @action void setShouldSaveRecipientAddress(bool value) => _settingsStore.shouldSaveRecipientAddress = value; @@ -143,4 +149,10 @@ abstract class PrivacySettingsViewModelBase with Store { _settingsStore.usePolygonScan = value; polygon!.updatePolygonScanUsageState(_wallet, value); } + + @action + void setUseTronGrid(bool value) { + _settingsStore.useTronGrid = value; + tron!.updateTronGridUsageState(_wallet, value); + } } diff --git a/macos/Podfile.lock b/macos/Podfile.lock index f1f72a818..3299cd5bd 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -122,10 +122,10 @@ SPEC CHECKSUMS: OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c package_info: 6eba2fd8d3371dda2d85c8db6fe97488f24b74b2 package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce - path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4 - shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 911fa9fcc..d14d203c6 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -207,7 +207,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 33CC10EC2044A3C60003C045 = { diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 8536e9a81..fd9942aa8 100644 --- a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ @@ -31,7 +31,7 @@ @@ -54,7 +54,7 @@ @@ -71,7 +71,7 @@ diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index ab6579eef..137e34ef8 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "يجب أن تكون قيمة المبلغ أكبر من أو تساوي ${minAmount} ${fiatCurrency}", "more_options": "المزيد من الخيارات", "name": "ﻢﺳﺍ", - "nano_gpt_thanks_message": "شكرا لاستخدام nanogpt! تذكر أن تعود إلى المتصفح بعد اكتمال معاملتك!", - "nanogpt_subtitle": "جميع النماذج الأحدث (GPT-4 ، Claude). \\ nno اشتراك ، ادفع مع Crypto.", "nano_current_rep": "الممثل الحالي", + "nano_gpt_thanks_message": "شكرا لاستخدام nanogpt! تذكر أن تعود إلى المتصفح بعد اكتمال معاملتك!", "nano_pick_new_rep": "اختر ممثلًا جديدًا", + "nanogpt_subtitle": "جميع النماذج الأحدث (GPT-4 ، Claude). \\ nno اشتراك ، ادفع مع Crypto.", "narrow": "ضيق", "new_first_wallet_text": "حافظ بسهولة على أمان العملة المشفرة", "new_node_testing": "تجربة العقدة الجديدة", @@ -745,6 +745,7 @@ "transaction_sent_notice": "إذا لم تستمر الشاشة بعد دقيقة واحدة ، فتحقق من مستكشف البلوك والبريد الإلكتروني.", "transactions": "المعاملات", "transactions_by_date": "المعاملات حسب التاريخ", + "trongrid_history": "تاريخ ترونغريد", "trusted": "موثوق به", "tx_commit_exception_no_dust_on_change": "يتم رفض المعاملة مع هذا المبلغ. باستخدام هذه العملات المعدنية ، يمكنك إرسال ${min} دون تغيير أو ${max} الذي يعيد التغيير.", "tx_commit_failed": "فشل ارتكاب المعاملة. يرجى الاتصال بالدعم.", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 6b6a8be1a..ae2877ab1 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "Сумата трябва да бъде най-малко ${minAmount} ${fiatCurrency}", "more_options": "Още настройки", "name": "Име", - "nano_gpt_thanks_message": "Благодаря, че използвахте Nanogpt! Не забравяйте да се върнете обратно към браузъра, след като транзакцията ви приключи!", - "nanogpt_subtitle": "Всички най-нови модели (GPT-4, Claude). \\ Nno абонамент, платете с Crypto.", "nano_current_rep": "Настоящ представител", + "nano_gpt_thanks_message": "Благодаря, че използвахте Nanogpt! Не забравяйте да се върнете обратно към браузъра, след като транзакцията ви приключи!", "nano_pick_new_rep": "Изберете нов представител", + "nanogpt_subtitle": "Всички най-нови модели (GPT-4, Claude). \\ Nno абонамент, платете с Crypto.", "narrow": "Тесен", "new_first_wallet_text": "Лесно пазете криптовалутата си в безопасност", "new_node_testing": "Тестване на нов node", @@ -745,6 +745,7 @@ "transaction_sent_notice": "Ако процесът продължи повече от 1 минута, проверете някой block explorer и своя имейл.", "transactions": "Транзакции", "transactions_by_date": "Транзакции по дата", + "trongrid_history": "Trongrid History", "trusted": "Надежден", "tx_commit_exception_no_dust_on_change": "Сделката се отхвърля с тази сума. С тези монети можете да изпратите ${min} без промяна или ${max}, която връща промяна.", "tx_commit_failed": "Компетацията на транзакцията не успя. Моля, свържете се с поддръжката.", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 86a61a5af..2f61782c8 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "Částka musí být větší nebo rovna ${minAmount} ${fiatCurrency}", "more_options": "Více možností", "name": "název", - "nano_gpt_thanks_message": "Děkujeme za používání Nanogpt! Nezapomeňte se po dokončení transakce vydat zpět do prohlížeče!", - "nanogpt_subtitle": "Všechny nejnovější modely (GPT-4, Claude). \\ Nno předplatné, plaťte krypto.", "nano_current_rep": "Současný zástupce", + "nano_gpt_thanks_message": "Děkujeme za používání Nanogpt! Nezapomeňte se po dokončení transakce vydat zpět do prohlížeče!", "nano_pick_new_rep": "Vyberte nového zástupce", + "nanogpt_subtitle": "Všechny nejnovější modely (GPT-4, Claude). \\ Nno předplatné, plaťte krypto.", "narrow": "Úzký", "new_first_wallet_text": "Snadno udržujte svou kryptoměnu v bezpečí", "new_node_testing": "Testování nového uzlu", @@ -745,6 +745,7 @@ "transaction_sent_notice": "Pokud proces nepokročí během 1 minuty, zkontrolujte block explorer a svůj e-mail.", "transactions": "Transakce", "transactions_by_date": "Transakce podle data", + "trongrid_history": "Trongridní historie", "trusted": "Důvěřovat", "tx_commit_exception_no_dust_on_change": "Transakce je zamítnuta s touto částkou. S těmito mincemi můžete odeslat ${min} bez změny nebo ${max}, které se vrátí změna.", "tx_commit_failed": "Transakce COMPORT selhala. Kontaktujte prosím podporu.", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index c0639d88d..edfc152e1 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "Der Wert des Betrags muss größer oder gleich ${minAmount} ${fiatCurrency} sein", "more_options": "Weitere Optionen", "name": "Name", - "nano_gpt_thanks_message": "Danke, dass du Nanogpt benutzt hast! Denken Sie daran, nach Abschluss Ihrer Transaktion zurück zum Browser zu gehen!", - "nanogpt_subtitle": "Alle neuesten Modelle (GPT-4, Claude).", "nano_current_rep": "Aktueller Vertreter", + "nano_gpt_thanks_message": "Danke, dass du Nanogpt benutzt hast! Denken Sie daran, nach Abschluss Ihrer Transaktion zurück zum Browser zu gehen!", "nano_pick_new_rep": "Wählen Sie einen neuen Vertreter aus", + "nanogpt_subtitle": "Alle neuesten Modelle (GPT-4, Claude).", "narrow": "Eng", "new_first_wallet_text": "Bewahren Sie Ihre Kryptowährung einfach sicher auf", "new_node_testing": "Neuen Knoten testen", @@ -746,6 +746,7 @@ "transaction_sent_notice": "Wenn der Bildschirm nach 1 Minute nicht weitergeht, überprüfen Sie einen Block-Explorer und Ihre E-Mail.", "transactions": "Transaktionen", "transactions_by_date": "Transaktionen nach Datum", + "trongrid_history": "Tronglidgeschichte", "trusted": "Vertrauenswürdige", "tx_commit_exception_no_dust_on_change": "Die Transaktion wird diesen Betrag abgelehnt. Mit diesen Münzen können Sie ${min} ohne Veränderung oder ${max} senden, die Änderungen zurückgeben.", "tx_commit_failed": "Transaktionsausschüsse ist fehlgeschlagen. Bitte wenden Sie sich an Support.", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 2ee31b491..636689380 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "Value of the amount must be more or equal to ${minAmount} ${fiatCurrency}", "more_options": "More Options", "name": "Name", - "nano_gpt_thanks_message": "Thanks for using NanoGPT! Remember to head back to the browser after your transaction completes!", - "nanogpt_subtitle": "All the newest models (GPT-4, Claude).\\nNo subscription, pay with crypto.", "nano_current_rep": "Current Representative", + "nano_gpt_thanks_message": "Thanks for using NanoGPT! Remember to head back to the browser after your transaction completes!", "nano_pick_new_rep": "Pick a new representative", + "nanogpt_subtitle": "All the newest models (GPT-4, Claude).\\nNo subscription, pay with crypto.", "narrow": "Narrow", "new_first_wallet_text": "Keep your crypto safe, piece of cake", "new_node_testing": "New node testing", @@ -745,6 +745,7 @@ "transaction_sent_notice": "If the screen doesn’t proceed after 1 minute, check a block explorer and your email.", "transactions": "Transactions", "transactions_by_date": "Transactions by date", + "trongrid_history": "TronGrid history", "trusted": "Trusted", "tx_commit_exception_no_dust_on_change": "The transaction is rejected with this amount. With these coins you can send ${min} without change or ${max} that returns change.", "tx_commit_failed": "Transaction commit failed. Please contact support.", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 8e4177298..b3f89fc2e 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "El valor de la cantidad debe ser mayor o igual a ${minAmount} ${fiatCurrency}", "more_options": "Más Opciones", "name": "Nombre", - "nano_gpt_thanks_message": "¡Gracias por usar nanogpt! ¡Recuerde regresar al navegador después de que se complete su transacción!", - "nanogpt_subtitle": "Todos los modelos más nuevos (GPT-4, Claude). \\ Nno suscripción, pague con cripto.", "nano_current_rep": "Representante actual", + "nano_gpt_thanks_message": "¡Gracias por usar nanogpt! ¡Recuerde regresar al navegador después de que se complete su transacción!", "nano_pick_new_rep": "Elija un nuevo representante", + "nanogpt_subtitle": "Todos los modelos más nuevos (GPT-4, Claude). \\ Nno suscripción, pague con cripto.", "narrow": "Angosto", "new_first_wallet_text": "Mantenga fácilmente su criptomoneda segura", "new_node_testing": "Prueba de nuevos nodos", @@ -746,6 +746,7 @@ "transaction_sent_notice": "Si la pantalla no continúa después de 1 minuto, revisa un explorador de bloques y tu correo electrónico.", "transactions": "Actas", "transactions_by_date": "Transacciones por fecha", + "trongrid_history": "Historia trongrid", "trusted": "de confianza", "tx_commit_exception_no_dust_on_change": "La transacción se rechaza con esta cantidad. Con estas monedas puede enviar ${min} sin cambios o ${max} que devuelve el cambio.", "tx_commit_failed": "La confirmación de transacción falló. Póngase en contacto con el soporte.", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index 4c589b27f..a624e487c 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "Le montant doit être au moins égal à ${minAmount} ${fiatCurrency}", "more_options": "Plus d'options", "name": "Nom", - "nano_gpt_thanks_message": "Merci d'avoir utilisé Nanogpt! N'oubliez pas de retourner au navigateur une fois votre transaction terminée!", - "nanogpt_subtitle": "Tous les modèles les plus récents (GPT-4, Claude). \\ NNO abonnement, payez avec crypto.", "nano_current_rep": "Représentant actuel", + "nano_gpt_thanks_message": "Merci d'avoir utilisé Nanogpt! N'oubliez pas de retourner au navigateur une fois votre transaction terminée!", "nano_pick_new_rep": "Choisissez un nouveau représentant", + "nanogpt_subtitle": "Tous les modèles les plus récents (GPT-4, Claude). \\ NNO abonnement, payez avec crypto.", "narrow": "Étroit", "new_first_wallet_text": "Gardez facilement votre crypto-monnaie en sécurité", "new_node_testing": "Test du nouveau nœud", @@ -745,6 +745,7 @@ "transaction_sent_notice": "Si l'écran ne continue pas après 1 minute, vérifiez un explorateur de blocs et votre e-mail.", "transactions": "Transactions", "transactions_by_date": "Transactions par date", + "trongrid_history": "Histoire de la trongride", "trusted": "de confiance", "tx_commit_exception_no_dust_on_change": "La transaction est rejetée avec ce montant. Avec ces pièces, vous pouvez envoyer ${min} sans changement ou ${max} qui renvoie le changement.", "tx_commit_failed": "La validation de la transaction a échoué. Veuillez contacter l'assistance.", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index 3fe21b3f1..68635aa5c 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "Darajar adadin dole ne ya zama fiye ko daidai da ${minAmount} ${fiatCurrency}", "more_options": "Ƙarin Zaɓuɓɓuka", "name": "Suna", - "nano_gpt_thanks_message": "Na gode da amfani da Nanogpt! Ka tuna da komawa zuwa mai bincike bayan ma'amalar ka ta cika!", - "nanogpt_subtitle": "Duk sabbin samfuran (GPT-4, CLODE). \\ NNO biyan kuɗi, biya tare da crypto.", "nano_current_rep": "Wakilin Yanzu", + "nano_gpt_thanks_message": "Na gode da amfani da Nanogpt! Ka tuna da komawa zuwa mai bincike bayan ma'amalar ka ta cika!", "nano_pick_new_rep": "Dauki sabon wakili", + "nanogpt_subtitle": "Duk sabbin samfuran (GPT-4, CLODE). \\ NNO biyan kuɗi, biya tare da crypto.", "narrow": "kunkuntar", "new_first_wallet_text": "A sauƙaƙe kiyaye kuzarin ku", "new_node_testing": "Sabbin gwajin kumburi", @@ -747,6 +747,7 @@ "transaction_sent_notice": "Idan allon bai ci gaba ba bayan minti 1, duba mai binciken toshewa da imel ɗin ku.", "transactions": "Ma'amaloli", "transactions_by_date": "Ma'amaloli ta kwanan wata", + "trongrid_history": "Tarihin Trongrid", "trusted": "Amintacce", "tx_commit_exception_no_dust_on_change": "An ƙi ma'amala da wannan adadin. Tare da waɗannan tsabar kudi Zaka iya aika ${min}, ba tare da canji ba ko ${max} wanda ya dawo canzawa.", "tx_commit_failed": "Ma'amala ya kasa. Da fatan za a tuntuɓi goyan baya.", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index e2eb28aa2..027b5448d 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "राशि का मूल्य अधिक है या करने के लिए बराबर होना चाहिए ${minAmount} ${fiatCurrency}", "more_options": "और विकल्प", "name": "नाम", - "nano_gpt_thanks_message": "Nanogpt का उपयोग करने के लिए धन्यवाद! अपने लेन -देन के पूरा होने के बाद ब्राउज़र पर वापस जाना याद रखें!", - "nanogpt_subtitle": "सभी नवीनतम मॉडल (GPT-4, क्लाउड)। \\ nno सदस्यता, क्रिप्टो के साथ भुगतान करें।", "nano_current_rep": "वर्तमान प्रतिनिधि", + "nano_gpt_thanks_message": "Nanogpt का उपयोग करने के लिए धन्यवाद! अपने लेन -देन के पूरा होने के बाद ब्राउज़र पर वापस जाना याद रखें!", "nano_pick_new_rep": "एक नया प्रतिनिधि चुनें", + "nanogpt_subtitle": "सभी नवीनतम मॉडल (GPT-4, क्लाउड)। \\ nno सदस्यता, क्रिप्टो के साथ भुगतान करें।", "narrow": "सँकरा", "new_first_wallet_text": "आसानी से अपनी क्रिप्टोक्यूरेंसी को सुरक्षित रखें", "new_node_testing": "नई नोड परीक्षण", @@ -747,6 +747,7 @@ "transaction_sent_notice": "अगर 1 मिनट के बाद भी स्क्रीन आगे नहीं बढ़ती है, तो ब्लॉक एक्सप्लोरर और अपना ईमेल देखें।", "transactions": "लेन-देन", "transactions_by_date": "तारीख से लेन-देन", + "trongrid_history": "ट्रॉन्ग्रिड का इतिहास", "trusted": "भरोसा", "tx_commit_exception_no_dust_on_change": "लेनदेन को इस राशि से खारिज कर दिया जाता है। इन सिक्कों के साथ आप चेंज या ${min} के बिना ${max} को भेज सकते हैं जो परिवर्तन लौटाता है।", "tx_commit_failed": "लेन -देन प्रतिबद्ध विफल। कृपया संपर्क समर्थन करें।", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 079de0c4f..5edbc3633 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "Vrijednost iznosa mora biti veća ili jednaka ${minAmount} ${fiatCurrency}", "more_options": "Više opcija", "name": "Ime", - "nano_gpt_thanks_message": "Hvala što ste koristili nanogpt! Ne zaboravite da se vratite u preglednik nakon što vam se transakcija završi!", - "nanogpt_subtitle": "Svi najnoviji modeli (GPT-4, Claude). \\ NNO pretplata, plaćajte kripto.", "nano_current_rep": "Trenutni predstavnik", + "nano_gpt_thanks_message": "Hvala što ste koristili nanogpt! Ne zaboravite da se vratite u preglednik nakon što vam se transakcija završi!", "nano_pick_new_rep": "Odaberite novog predstavnika", + "nanogpt_subtitle": "Svi najnoviji modeli (GPT-4, Claude). \\ NNO pretplata, plaćajte kripto.", "narrow": "Usko", "new_first_wallet_text": "Jednostavno čuvajte svoju kripto valutu", "new_node_testing": "Provjera novog nodea", @@ -745,6 +745,7 @@ "transaction_sent_notice": "Ako se zaslon ne nastavi nakon 1 minute, provjerite block explorer i svoju e-poštu.", "transactions": "Transakcije", "transactions_by_date": "Transakcije prema datumu", + "trongrid_history": "Povijest Trongrida", "trusted": "vjerovao", "tx_commit_exception_no_dust_on_change": "Transakcija se odbija s tim iznosom. Pomoću ovih kovanica možete poslati ${min} bez promjene ili ${max} koja vraća promjenu.", "tx_commit_failed": "Obveza transakcije nije uspjela. Molimo kontaktirajte podršku.", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index ae9e4e38f..2551506c0 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "Nilai jumlah harus lebih atau sama dengan ${minAmount} ${fiatCurrency}", "more_options": "Opsi Lainnya", "name": "Nama", - "nano_gpt_thanks_message": "Terima kasih telah menggunakan Nanogpt! Ingatlah untuk kembali ke browser setelah transaksi Anda selesai!", - "nanogpt_subtitle": "Semua model terbaru (GPT-4, Claude). \\ Nno langganan, bayar dengan crypto.", "nano_current_rep": "Perwakilan saat ini", + "nano_gpt_thanks_message": "Terima kasih telah menggunakan Nanogpt! Ingatlah untuk kembali ke browser setelah transaksi Anda selesai!", "nano_pick_new_rep": "Pilih perwakilan baru", + "nanogpt_subtitle": "Semua model terbaru (GPT-4, Claude). \\ Nno langganan, bayar dengan crypto.", "narrow": "Sempit", "new_first_wallet_text": "Dengan mudah menjaga cryptocurrency Anda aman", "new_node_testing": "Pengujian node baru", @@ -748,6 +748,7 @@ "transaction_sent_notice": "Jika layar tidak bergerak setelah 1 menit, periksa block explorer dan email Anda.", "transactions": "Transaksi", "transactions_by_date": "Transaksi berdasarkan tanggal", + "trongrid_history": "Sejarah Trongrid", "trusted": "Dipercayai", "tx_commit_exception_no_dust_on_change": "Transaksi ditolak dengan jumlah ini. Dengan koin ini Anda dapat mengirim ${min} tanpa perubahan atau ${max} yang mengembalikan perubahan.", "tx_commit_failed": "Transaksi Gagal. Silakan hubungi Dukungan.", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 5fa1b52ef..9bb2ca1eb 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -367,10 +367,10 @@ "moonpay_alert_text": "Il valore dell'importo deve essere maggiore o uguale a ${minAmount} ${fiatCurrency}", "more_options": "Altre opzioni", "name": "Nome", - "nano_gpt_thanks_message": "Grazie per aver usato il nanogpt! Ricorda di tornare al browser dopo il completamento della transazione!", - "nanogpt_subtitle": "Tutti i modelli più recenti (GPT-4, Claude). Abbonamento nno, paga con cripto.", "nano_current_rep": "Rappresentante attuale", + "nano_gpt_thanks_message": "Grazie per aver usato il nanogpt! Ricorda di tornare al browser dopo il completamento della transazione!", "nano_pick_new_rep": "Scegli un nuovo rappresentante", + "nanogpt_subtitle": "Tutti i modelli più recenti (GPT-4, Claude). Abbonamento nno, paga con cripto.", "narrow": "Stretto", "new_first_wallet_text": "Mantieni facilmente la tua criptovaluta al sicuro", "new_node_testing": "Test novo nodo", @@ -747,6 +747,7 @@ "transaction_sent_notice": "Se lo schermo non procede dopo 1 minuto, controlla un block explorer e la tua email.", "transactions": "Transazioni", "transactions_by_date": "Transazioni per data", + "trongrid_history": "Storia del trongride", "trusted": "di fiducia", "tx_commit_exception_no_dust_on_change": "La transazione viene respinta con questo importo. Con queste monete è possibile inviare ${min} senza modifiche o ${max} che restituisce il cambiamento.", "tx_commit_failed": "Commit di transazione non riuscita. Si prega di contattare il supporto.", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index a01df3c07..55af8cbd1 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -367,10 +367,10 @@ "moonpay_alert_text": "金額の値は以上でなければなりません ${minAmount} ${fiatCurrency}", "more_options": "その他のオプション", "name": "名前", - "nano_gpt_thanks_message": "NanoGptを使用してくれてありがとう!トランザクションが完了したら、ブラウザに戻ることを忘れないでください!", - "nanogpt_subtitle": "すべての最新モデル(GPT-4、Claude)。\\ nnoサブスクリプション、暗号で支払います。", "nano_current_rep": "現在の代表", + "nano_gpt_thanks_message": "NanoGptを使用してくれてありがとう!トランザクションが完了したら、ブラウザに戻ることを忘れないでください!", "nano_pick_new_rep": "新しい代表者を選びます", + "nanogpt_subtitle": "すべての最新モデル(GPT-4、Claude)。\\ nnoサブスクリプション、暗号で支払います。", "narrow": "狭い", "new_first_wallet_text": "暗号通貨を簡単に安全に保ちます", "new_node_testing": "新しいノードのテスト", @@ -746,6 +746,7 @@ "transaction_sent_notice": "1分経っても画面が進まない場合は、ブロックエクスプローラーとメールアドレスを確認してください。", "transactions": "取引", "transactions_by_date": "日付ごとの取引", + "trongrid_history": "トロンリッドの歴史", "trusted": "信頼できる", "tx_commit_exception_no_dust_on_change": "この金額ではトランザクションは拒否されます。 これらのコインを使用すると、おつりなしの ${min} またはおつりを返す ${max} を送信できます。", "tx_commit_failed": "トランザクションコミットは失敗しました。サポートに連絡してください。", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 53cbeb01f..3f710becb 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "금액은 다음보다 크거나 같아야합니다 ${minAmount} ${fiatCurrency}", "more_options": "추가 옵션", "name": "이름", - "nano_gpt_thanks_message": "Nanogpt를 사용해 주셔서 감사합니다! 거래가 완료된 후 브라우저로 돌아가는 것을 잊지 마십시오!", - "nanogpt_subtitle": "모든 최신 모델 (GPT-4, Claude). \\ nno 구독, Crypto로 지불하십시오.", "nano_current_rep": "현재 대표", + "nano_gpt_thanks_message": "Nanogpt를 사용해 주셔서 감사합니다! 거래가 완료된 후 브라우저로 돌아가는 것을 잊지 마십시오!", "nano_pick_new_rep": "새로운 담당자를 선택하십시오", + "nanogpt_subtitle": "모든 최신 모델 (GPT-4, Claude). \\ nno 구독, Crypto로 지불하십시오.", "narrow": "좁은", "new_first_wallet_text": "cryptocurrency를 쉽게 안전하게 유지하십시오", "new_node_testing": "새로운 노드 테스트", @@ -746,6 +746,7 @@ "transaction_sent_notice": "1분 후에도 화면이 진행되지 않으면 블록 익스플로러와 이메일을 확인하세요.", "transactions": "업무", "transactions_by_date": "날짜 별 거래", + "trongrid_history": "트롱 트리드 역사", "trusted": "신뢰할 수 있는", "tx_commit_exception_no_dust_on_change": "이 금액으로 거래가 거부되었습니다. 이 코인을 사용하면 거스름돈 없이 ${min}를 보내거나 거스름돈을 반환하는 ${max}를 보낼 수 있습니다.", "tx_commit_failed": "거래 커밋이 실패했습니다. 지원에 연락하십시오.", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index bb2099b15..63c7f4903 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "ပမာဏ၏တန်ဖိုးသည် ${minAmount} ${fiatCurrency} နှင့် ပိုနေရမည်", "more_options": "နောက်ထပ် ရွေးချယ်စရာများ", "name": "နာမည်", - "nano_gpt_thanks_message": "nanogpt ကိုသုံးပြီးကျေးဇူးတင်ပါတယ် သင်၏ငွေပေးငွေယူပြီးနောက် browser သို့ပြန်သွားရန်သတိရပါ။", - "nanogpt_subtitle": "အားလုံးနောက်ဆုံးပေါ်မော်ဒယ်များ (GPT-4, Claude) ။ \\ nno subscription, crypto နှင့်အတူပေးဆောင်။", "nano_current_rep": "လက်ရှိကိုယ်စားလှယ်", + "nano_gpt_thanks_message": "nanogpt ကိုသုံးပြီးကျေးဇူးတင်ပါတယ် သင်၏ငွေပေးငွေယူပြီးနောက် browser သို့ပြန်သွားရန်သတိရပါ။", "nano_pick_new_rep": "အသစ်တစ်ခုကိုရွေးပါ", + "nanogpt_subtitle": "အားလုံးနောက်ဆုံးပေါ်မော်ဒယ်များ (GPT-4, Claude) ။ \\ nno subscription, crypto နှင့်အတူပေးဆောင်။", "narrow": "ကျဉ်းသော", "new_first_wallet_text": "သင့်ရဲ့ cryptocurrencrencres ကိုအလွယ်တကူလုံခြုံစွာထားရှိပါ", "new_node_testing": "နှာခေါင်း အသစ်စမ်းသပ်ခြင်း။", @@ -745,6 +745,7 @@ "transaction_sent_notice": "မျက်နှာပြင်သည် ၁ မိနစ်အကြာတွင် ဆက်လက်မလုပ်ဆောင်ပါက၊ ပိတ်ဆို့ရှာဖွေသူနှင့် သင့်အီးမေးလ်ကို စစ်ဆေးပါ။", "transactions": "ငွေပေးငွေယူ", "transactions_by_date": "ရက်စွဲအလိုက် ငွေလွှဲမှုများ", + "trongrid_history": "Trongrid သမိုင်း", "trusted": "ယုံတယ်။", "tx_commit_exception_no_dust_on_change": "အဆိုပါငွေပေးငွေယူကဒီပမာဏနှင့်အတူပယ်ချခံရသည်။ ဤဒင်္ဂါးပြားများနှင့်အတူပြောင်းလဲမှုကိုပြန်လည်ပြောင်းလဲခြင်းသို့မဟုတ် ${min} မပါဘဲ ${max} ပေးပို့နိုင်သည်။", "tx_commit_failed": "ငွေပေးငွေယူကျူးလွန်မှုပျက်ကွက်။ ကျေးဇူးပြုပြီးပံ့ပိုးမှုဆက်သွယ်ပါ။", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index ca9b5a79f..c75309aa6 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "Waarde van het bedrag moet meer of gelijk zijn aan ${minAmount} ${fiatCurrency}", "more_options": "Meer opties", "name": "Naam", - "nano_gpt_thanks_message": "Bedankt voor het gebruik van Nanogpt! Vergeet niet om terug te gaan naar de browser nadat uw transactie is voltooid!", - "nanogpt_subtitle": "Alle nieuwste modellen (GPT-4, Claude). \\ Nno-abonnement, betalen met crypto.", "nano_current_rep": "Huidige vertegenwoordiger", + "nano_gpt_thanks_message": "Bedankt voor het gebruik van Nanogpt! Vergeet niet om terug te gaan naar de browser nadat uw transactie is voltooid!", "nano_pick_new_rep": "Kies een nieuwe vertegenwoordiger", + "nanogpt_subtitle": "Alle nieuwste modellen (GPT-4, Claude). \\ Nno-abonnement, betalen met crypto.", "narrow": "Smal", "new_first_wallet_text": "Houd uw cryptocurrency gemakkelijk veilig", "new_node_testing": "Nieuwe knooppunttest", @@ -745,6 +745,7 @@ "transaction_sent_notice": "Als het scherm na 1 minuut niet verder gaat, controleer dan een blokverkenner en je e-mail.", "transactions": "Transacties", "transactions_by_date": "Transacties op datum", + "trongrid_history": "Trongrid geschiedenis", "trusted": "vertrouwd", "tx_commit_exception_no_dust_on_change": "De transactie wordt afgewezen met dit bedrag. Met deze munten kunt u ${min} verzenden zonder verandering of ${max} die wijziging retourneert.", "tx_commit_failed": "Transactiebewissing is mislukt. Neem contact op met de ondersteuning.", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index 44e8c0b95..c78daa836 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "Wartość kwoty musi być większa lub równa ${minAmount} ${fiatCurrency}", "more_options": "Więcej opcji", "name": "Nazwa", - "nano_gpt_thanks_message": "Dzięki za użycie Nanogpt! Pamiętaj, aby wrócić do przeglądarki po zakończeniu transakcji!", - "nanogpt_subtitle": "Wszystkie najnowsze modele (GPT-4, Claude). \\ Nno subskrypcja, płacą za pomocą kryptografii.", "nano_current_rep": "Obecny przedstawiciel", + "nano_gpt_thanks_message": "Dzięki za użycie Nanogpt! Pamiętaj, aby wrócić do przeglądarki po zakończeniu transakcji!", "nano_pick_new_rep": "Wybierz nowego przedstawiciela", + "nanogpt_subtitle": "Wszystkie najnowsze modele (GPT-4, Claude). \\ Nno subskrypcja, płacą za pomocą kryptografii.", "narrow": "Wąski", "new_first_wallet_text": "Łatwo zapewnić bezpieczeństwo kryptowalut", "new_node_testing": "Testowanie nowych węzłów", @@ -745,6 +745,7 @@ "transaction_sent_notice": "Jeśli ekran nie zmieni się po 1 minucie, sprawdź eksplorator bloków i swój e-mail.", "transactions": "Transakcje", "transactions_by_date": "Transakcje według daty", + "trongrid_history": "Historia Trongrida", "trusted": "Zaufany", "tx_commit_exception_no_dust_on_change": "Transakcja jest odrzucana z tą kwotą. Za pomocą tych monet możesz wysłać ${min} bez zmiany lub ${max}, które zwraca zmianę.", "tx_commit_failed": "Zatwierdzenie transakcji nie powiodło się. Skontaktuj się z obsługą.", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index b8805e789..710fd5eea 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -367,10 +367,10 @@ "moonpay_alert_text": "O valor do montante deve ser maior ou igual a ${minAmount} ${fiatCurrency}", "more_options": "Mais opções", "name": "Nome", - "nano_gpt_thanks_message": "Obrigado por usar o Nanogpt! Lembre -se de voltar para o navegador após a conclusão da transação!", - "nanogpt_subtitle": "Todos os modelos mais recentes (GPT-4, Claude). \\ Nno assinatura, pagam com criptografia.", "nano_current_rep": "Representante atual", + "nano_gpt_thanks_message": "Obrigado por usar o Nanogpt! Lembre -se de voltar para o navegador após a conclusão da transação!", "nano_pick_new_rep": "Escolha um novo representante", + "nanogpt_subtitle": "Todos os modelos mais recentes (GPT-4, Claude). \\ Nno assinatura, pagam com criptografia.", "narrow": "Estreito", "new_first_wallet_text": "Mantenha sua criptomoeda facilmente segura", "new_node_testing": "Teste de novo nó", @@ -747,6 +747,7 @@ "transaction_sent_notice": "Se a tela não prosseguir após 1 minuto, verifique um explorador de blocos e seu e-mail.", "transactions": "Transações", "transactions_by_date": "Transações por data", + "trongrid_history": "História de Trongrid", "trusted": "confiável", "tx_commit_exception_no_dust_on_change": "A transação é rejeitada com esse valor. Com essas moedas, você pode enviar ${min} sem alteração ou ${max} que retorna alterações.", "tx_commit_failed": "A confirmação da transação falhou. Entre em contato com o suporte.", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index 32f513fe5..4780dde5d 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "Сумма должна быть больше или равна ${minAmount} ${fiatCurrency}", "more_options": "Дополнительные параметры", "name": "Имя", - "nano_gpt_thanks_message": "Спасибо за использование Nanogpt! Не забудьте вернуться в браузер после завершения транзакции!", - "nanogpt_subtitle": "Все новейшие модели (GPT-4, Claude). \\ Nno Подписка, платите с крипто.", "nano_current_rep": "Нынешний представитель", + "nano_gpt_thanks_message": "Спасибо за использование Nanogpt! Не забудьте вернуться в браузер после завершения транзакции!", "nano_pick_new_rep": "Выберите нового представителя", + "nanogpt_subtitle": "Все новейшие модели (GPT-4, Claude). \\ Nno Подписка, платите с крипто.", "narrow": "Узкий", "new_first_wallet_text": "Легко сохранить свою криптовалюту в безопасности", "new_node_testing": "Тестирование новой ноды", @@ -746,6 +746,7 @@ "transaction_sent_notice": "Если экран не отображается через 1 минуту, проверьте обозреватель блоков и свою электронную почту.", "transactions": "Транзакции", "transactions_by_date": "Сортировать по дате", + "trongrid_history": "История Тронгрида", "trusted": "доверенный", "tx_commit_exception_no_dust_on_change": "Транзакция отклоняется с этой суммой. С этими монетами вы можете отправлять ${min} без изменения или ${max}, которые возвращают изменение.", "tx_commit_failed": "Комплект транзакции не удался. Пожалуйста, свяжитесь с поддержкой.", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index 18b9adce9..945cf88de 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "มูลค่าของจำนวนต้องมากกว่าหรือเท่ากับ ${minAmount} ${fiatCurrency}", "more_options": "ตัวเลือกเพิ่มเติม", "name": "ชื่อ", - "nano_gpt_thanks_message": "ขอบคุณที่ใช้ Nanogpt! อย่าลืมกลับไปที่เบราว์เซอร์หลังจากการทำธุรกรรมของคุณเสร็จสิ้น!", - "nanogpt_subtitle": "รุ่นใหม่ล่าสุดทั้งหมด (GPT-4, Claude). การสมัครสมาชิก \\ nno, จ่ายด้วย crypto", "nano_current_rep": "ตัวแทนปัจจุบัน", + "nano_gpt_thanks_message": "ขอบคุณที่ใช้ Nanogpt! อย่าลืมกลับไปที่เบราว์เซอร์หลังจากการทำธุรกรรมของคุณเสร็จสิ้น!", "nano_pick_new_rep": "เลือกตัวแทนใหม่", + "nanogpt_subtitle": "รุ่นใหม่ล่าสุดทั้งหมด (GPT-4, Claude). การสมัครสมาชิก \\ nno, จ่ายด้วย crypto", "narrow": "แคบ", "new_first_wallet_text": "ทำให้สกุลเงินดิจิตอลของคุณปลอดภัยได้อย่างง่ายดาย", "new_node_testing": "การทดสอบโหนดใหม่", @@ -745,6 +745,7 @@ "transaction_sent_notice": "ถ้าหน้าจอไม่ขึ้นหลังจาก 1 นาทีแล้ว ให้ตรวจสอบ block explorer และอีเมลของคุณ", "transactions": "ธุรกรรม", "transactions_by_date": "ธุรกรรมตามวันที่", + "trongrid_history": "ประวัติศาสตร์ Trongrid", "trusted": "มั่นคง", "tx_commit_exception_no_dust_on_change": "ธุรกรรมถูกปฏิเสธด้วยจำนวนเงินนี้ ด้วยเหรียญเหล่านี้คุณสามารถส่ง ${min} โดยไม่ต้องเปลี่ยนแปลงหรือ ${max} ที่ส่งคืนการเปลี่ยนแปลง", "tx_commit_failed": "การทำธุรกรรมล้มเหลว กรุณาติดต่อฝ่ายสนับสนุน", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 76a94bbe2..6f20a274f 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "Ang halaga ng halaga ay dapat na higit pa o katumbas ng ${minAmount} ${fiatCurrency}", "more_options": "Higit pang mga pagpipilian", "name": "Pangalan", - "nano_gpt_thanks_message": "Salamat sa paggamit ng nanogpt! Tandaan na bumalik sa browser matapos makumpleto ang iyong transaksyon!", - "nanogpt_subtitle": "Ang lahat ng mga pinakabagong modelo (GPT-4, Claude). \\ Nno subscription, magbayad gamit ang crypto.", "nano_current_rep": "Kasalukuyang kinatawan", + "nano_gpt_thanks_message": "Salamat sa paggamit ng nanogpt! Tandaan na bumalik sa browser matapos makumpleto ang iyong transaksyon!", "nano_pick_new_rep": "Pumili ng isang bagong kinatawan", + "nanogpt_subtitle": "Ang lahat ng mga pinakabagong modelo (GPT-4, Claude). \\ Nno subscription, magbayad gamit ang crypto.", "narrow": "Makitid", "new_first_wallet_text": "Panatilihing ligtas ang iyong crypto, piraso ng cake", "new_node_testing": "Bagong pagsubok sa node", @@ -745,6 +745,7 @@ "transaction_sent_notice": "Kung ang screen ay hindi magpatuloy pagkatapos ng 1 minuto, suriin ang isang block explorer at ang iyong email.", "transactions": "Mga Transaksyon", "transactions_by_date": "Mga Transaksyon ayon sa Petsa", + "trongrid_history": "Kasaysayan ng Trongrid", "trusted": "Pinagkakatiwalaan", "tx_commit_exception_no_dust_on_change": "Ang transaksyon ay tinanggihan sa halagang ito. Sa mga barya na ito maaari kang magpadala ng ${min} nang walang pagbabago o ${max} na nagbabalik ng pagbabago.", "tx_commit_failed": "Nabigo ang transaksyon sa transaksyon. Mangyaring makipag -ugnay sa suporta.", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 62e541ded..e53f0a2bf 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "Tutar ${minAmount} ${fiatCurrency} miktarına eşit veya daha fazla olmalıdır", "more_options": "Daha Fazla Seçenek", "name": "İsim", - "nano_gpt_thanks_message": "Nanogpt kullandığınız için teşekkürler! İşleminiz tamamlandıktan sonra tarayıcıya geri dönmeyi unutmayın!", - "nanogpt_subtitle": "En yeni modeller (GPT-4, Claude). \\ Nno aboneliği, kripto ile ödeme yapın.", "nano_current_rep": "Mevcut temsilci", + "nano_gpt_thanks_message": "Nanogpt kullandığınız için teşekkürler! İşleminiz tamamlandıktan sonra tarayıcıya geri dönmeyi unutmayın!", "nano_pick_new_rep": "Yeni bir temsilci seçin", + "nanogpt_subtitle": "En yeni modeller (GPT-4, Claude). \\ Nno aboneliği, kripto ile ödeme yapın.", "narrow": "Dar", "new_first_wallet_text": "Kripto para biriminizi kolayca güvende tutun", "new_node_testing": "Yeni düğüm test ediliyor", @@ -745,6 +745,7 @@ "transaction_sent_notice": "Ekran 1 dakika sonra ilerlemezse, blok gezgininden ve e-postanızdan kontrol edin.", "transactions": "İşlemler", "transactions_by_date": "Tarihe göre transferler", + "trongrid_history": "Trongrid tarihi", "trusted": "Güvenilir", "tx_commit_exception_no_dust_on_change": "İşlem bu miktarla reddedilir. Bu madeni paralarla değişiklik yapmadan ${min} veya değişikliği döndüren ${max} gönderebilirsiniz.", "tx_commit_failed": "İşlem taahhüdü başarısız oldu. Lütfen Destek ile iletişime geçin.", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index 6184fed11..c2f95e560 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "Значення суми має бути більшим або дорівнювати ${minAmount} ${fiatCurrency}", "more_options": "Більше параметрів", "name": "Ім'я", - "nano_gpt_thanks_message": "Дякуємо за використання наногпта! Не забудьте повернутися до браузера після завершення транзакції!", - "nanogpt_subtitle": "Усі найновіші моделі (GPT-4, Claude). \\ Nno підписка, оплата криптовалютою.", "nano_current_rep": "Поточний представник", + "nano_gpt_thanks_message": "Дякуємо за використання наногпта! Не забудьте повернутися до браузера після завершення транзакції!", "nano_pick_new_rep": "Виберіть нового представника", + "nanogpt_subtitle": "Усі найновіші моделі (GPT-4, Claude). \\ Nno підписка, оплата криптовалютою.", "narrow": "вузькі", "new_first_wallet_text": "Легко зберігайте свою криптовалюту в безпеці", "new_node_testing": "Тестування нового вузла", @@ -746,6 +746,7 @@ "transaction_sent_notice": "Якщо екран не відображається через 1 хвилину, перевірте провідник блоків і свою електронну пошту.", "transactions": "Транзакції", "transactions_by_date": "Сортувати по даті", + "trongrid_history": "Тронгрідська історія", "trusted": "довіряють", "tx_commit_exception_no_dust_on_change": "Транзакція відхилена цією сумою. За допомогою цих монет ви можете надіслати ${min} без змін або ${max}, що повертає зміни.", "tx_commit_failed": "Транзакційна комісія не вдалося. Будь ласка, зв'яжіться з підтримкою.", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index dadd3505b..17d8e691e 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "رقم کی قدر ${minAmount} ${fiatCurrency} کے برابر یا زیادہ ہونی چاہیے۔", "more_options": "مزید زرائے", "name": "ﻡﺎﻧ", - "nano_gpt_thanks_message": "نانوگپٹ استعمال کرنے کا شکریہ! اپنے لین دین کی تکمیل کے بعد براؤزر کی طرف واپس جانا یاد رکھیں!", - "nanogpt_subtitle": "تمام تازہ ترین ماڈل (GPT-4 ، کلاڈ)۔ n n no سبسکرپشن ، کریپٹو کے ساتھ ادائیگی کریں۔", "nano_current_rep": "موجودہ نمائندہ", + "nano_gpt_thanks_message": "نانوگپٹ استعمال کرنے کا شکریہ! اپنے لین دین کی تکمیل کے بعد براؤزر کی طرف واپس جانا یاد رکھیں!", "nano_pick_new_rep": "ایک نیا نمائندہ منتخب کریں", + "nanogpt_subtitle": "تمام تازہ ترین ماڈل (GPT-4 ، کلاڈ)۔ n n no سبسکرپشن ، کریپٹو کے ساتھ ادائیگی کریں۔", "narrow": "تنگ", "new_first_wallet_text": "آسانی سے اپنے cryptocurrency محفوظ رکھیں", "new_node_testing": "نیا نوڈ ٹیسٹنگ", @@ -747,6 +747,7 @@ "transaction_sent_notice": "اگر اسکرین 1 منٹ کے بعد آگے نہیں بڑھتی ہے، تو بلاک ایکسپلورر اور اپنا ای میل چیک کریں۔", "transactions": "لین دین", "transactions_by_date": "تاریخ کے لحاظ سے لین دین", + "trongrid_history": "ٹرانگریڈ ہسٹری", "trusted": "قابل اعتماد", "tx_commit_exception_no_dust_on_change": "اس رقم سے لین دین کو مسترد کردیا گیا ہے۔ ان سککوں کے ذریعہ آپ بغیر کسی تبدیلی کے ${min} یا ${max} بھیج سکتے ہیں جو لوٹتے ہیں۔", "tx_commit_failed": "ٹرانزیکشن کمٹ ناکام ہوگیا۔ براہ کرم سپورٹ سے رابطہ کریں۔", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index d9fa48a45..5838b1dba 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -367,10 +367,10 @@ "moonpay_alert_text": "Iye owó kò gbọ́dọ̀ kéré ju ${minAmount} ${fiatCurrency}", "more_options": "Ìyàn àfikún", "name": "Oruko", - "nano_gpt_thanks_message": "O ṣeun fun lilo Nonnogt! Ranti lati tẹle pada si ẹrọ lilọ kiri ayelujara lẹhin iṣowo rẹ pari!", - "nanogpt_subtitle": "Gbogbo awọn awoṣe tuntun (GPT-4, Claude). \\ Nno alabapin kan, sanwo pẹlu Crypto.", "nano_current_rep": "Aṣoju lọwọlọwọ", + "nano_gpt_thanks_message": "O ṣeun fun lilo Nonnogt! Ranti lati tẹle pada si ẹrọ lilọ kiri ayelujara lẹhin iṣowo rẹ pari!", "nano_pick_new_rep": "Mu aṣoju tuntun kan", + "nanogpt_subtitle": "Gbogbo awọn awoṣe tuntun (GPT-4, Claude). \\ Nno alabapin kan, sanwo pẹlu Crypto.", "narrow": "Taara", "new_first_wallet_text": "Ni rọọrun jẹ ki o jẹ ki o jẹ ki o jẹ ki a mu", "new_node_testing": "A ń dán apẹka títun wò", @@ -746,6 +746,7 @@ "transaction_sent_notice": "Tí aṣàfihàn kò bá tẹ̀síwájú l'áàárín ìṣẹ́jú kan, ẹ tọ́ olùṣèwádìí àkójọpọ̀ àti ímeèlì yín wò.", "transactions": "Àwọn àránṣẹ́", "transactions_by_date": "Àwọn àránṣẹ́ t'á ti fi aago ṣa", + "trongrid_history": "Itan Trongrid", "trusted": "A ti fọkàn ẹ̀ tán", "tx_commit_exception_no_dust_on_change": "Iṣowo naa ti kọ pẹlu iye yii. Pẹlu awọn owó wọnyi o le firanṣẹ ${min} laisi ayipada tabi ${max} ni iyipada iyipada.", "tx_commit_failed": "Idunadura iṣowo kuna. Jọwọ kan si atilẹyin.", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 089d5fa74..4c7a10883 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -366,10 +366,10 @@ "moonpay_alert_text": "金额的价值必须大于或等于 ${minAmount} ${fiatCurrency}", "more_options": "更多选项", "name": "姓名", - "nano_gpt_thanks_message": "感谢您使用Nanogpt!事务完成后,请记住回到浏览器!", - "nanogpt_subtitle": "所有最新型号(GPT-4,Claude)。\\ nno订阅,用加密货币付款。", "nano_current_rep": "当前代表", + "nano_gpt_thanks_message": "感谢您使用Nanogpt!事务完成后,请记住回到浏览器!", "nano_pick_new_rep": "选择新代表", + "nanogpt_subtitle": "所有最新型号(GPT-4,Claude)。\\ nno订阅,用加密货币付款。", "narrow": "狭窄的", "new_first_wallet_text": "轻松确保您的加密货币安全", "new_node_testing": "新节点测试", @@ -745,6 +745,7 @@ "transaction_sent_notice": "如果屏幕在 1 分钟后没有继续,请检查区块浏览器和您的电子邮件。", "transactions": "交易情况", "transactions_by_date": "按日期交易", + "trongrid_history": "Trongrid历史", "trusted": "值得信赖", "tx_commit_exception_no_dust_on_change": "交易被此金额拒绝。使用这些硬币,您可以发送${min}无需更改或返回${max}的变化。", "tx_commit_failed": "交易承诺失败。请联系支持。", diff --git a/scripts/android/app_env.sh b/scripts/android/app_env.sh index 52f32b297..77ee02b9c 100644 --- a/scripts/android/app_env.sh +++ b/scripts/android/app_env.sh @@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_ANDROID_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.12.3" -MONERO_COM_BUILD_NUMBER=84 +MONERO_COM_VERSION="1.13.0" +MONERO_COM_BUILD_NUMBER=85 MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_SCHEME="monero.com" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.15.6" -CAKEWALLET_BUILD_NUMBER=207 +CAKEWALLET_VERSION="4.16.0" +CAKEWALLET_BUILD_NUMBER=208 CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_SCHEME="cakewallet" diff --git a/scripts/ios/app_env.sh b/scripts/ios/app_env.sh index 90f7d807c..e772ea128 100644 --- a/scripts/ios/app_env.sh +++ b/scripts/ios/app_env.sh @@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN) APP_IOS_TYPE=$1 MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.12.3" -MONERO_COM_BUILD_NUMBER=82 +MONERO_COM_VERSION="1.13.0" +MONERO_COM_BUILD_NUMBER=83 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="4.15.6" -CAKEWALLET_BUILD_NUMBER=232 +CAKEWALLET_VERSION="4.16.0" +CAKEWALLET_BUILD_NUMBER=234 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" HAVEN_NAME="Haven" diff --git a/scripts/macos/app_env.sh b/scripts/macos/app_env.sh index 758bfe900..95201dc02 100755 --- a/scripts/macos/app_env.sh +++ b/scripts/macos/app_env.sh @@ -16,13 +16,13 @@ if [ -n "$1" ]; then fi MONERO_COM_NAME="Monero.com" -MONERO_COM_VERSION="1.2.3" -MONERO_COM_BUILD_NUMBER=16 +MONERO_COM_VERSION="1.3.0" +MONERO_COM_BUILD_NUMBER=17 MONERO_COM_BUNDLE_ID="com.cakewallet.monero" CAKEWALLET_NAME="Cake Wallet" -CAKEWALLET_VERSION="1.8.6" -CAKEWALLET_BUILD_NUMBER=67 +CAKEWALLET_VERSION="1.9.0" +CAKEWALLET_BUILD_NUMBER=69 CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then diff --git a/tool/configure.dart b/tool/configure.dart index f2391103d..64f43d349 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -1112,6 +1112,8 @@ abstract class Tron { String? getTronNativeEstimatedFee(WalletBase wallet); String? getTronTRC20EstimatedFee(WalletBase wallet); + + void updateTronGridUsageState(WalletBase wallet, bool isEnabled); } """; From c35929f28e563e26b64184e4ea724dedd01544cc Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Wed, 8 May 2024 21:04:25 +0300 Subject: [PATCH 215/241] update flutter secure storage (#1437) * update flutter secure storage * fix flutter secure storage version --- pubspec_base.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pubspec_base.yaml b/pubspec_base.yaml index ddf0bd2e0..02e61e0b4 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -15,8 +15,8 @@ dependencies: git: url: https://github.com/cake-tech/flutter_secure_storage.git path: flutter_secure_storage - ref: cake-8.0.0 - version: 8.0.0 + ref: cake-9.0.0 + version: 9.0.0 # provider: ^6.0.3 rxdart: ^0.27.4 yaml: ^3.1.1 From bfb78eded98085b8f0a65f233b332490d8e4e5a7 Mon Sep 17 00:00:00 2001 From: Adegoke David <64401859+Blazebrain@users.noreply.github.com> Date: Wed, 8 May 2024 21:23:27 +0100 Subject: [PATCH 216/241] CW-599-Extract-Secure-Storage (#1353) * feat: Modify app to depend on secure storage abstraction instead of the direct package * chore: Revert command * Update configure.dart [skip ci] * Update configure.dart * Fix conflicts * clean up and fixes * minor fix --------- Co-authored-by: Omar Hatem --- .gitignore | 1 + lib/core/auth_service.dart | 14 +-- lib/core/backup_service.dart | 19 ++- lib/core/key_service.dart | 19 ++- lib/core/secure_storage.dart | 38 ------ lib/core/wallet_creation_service.dart | 4 +- lib/di.dart | 50 ++++++-- lib/entities/default_settings_migration.dart | 15 +-- lib/entities/fs_migration.dart | 66 ++++------ lib/entities/get_encryption_key.dart | 5 +- lib/entities/preferences_key.dart | 6 +- lib/entities/secret_store_key.dart | 8 +- lib/ionia/ionia_service.dart | 4 +- lib/main.dart | 9 +- .../support_chat/support_chat_page.dart | 4 +- .../support_chat/widgets/chatwoot_widget.dart | 5 +- lib/store/secret_store.dart | 5 +- lib/store/settings_store.dart | 49 ++++---- lib/store/yat/yat_store.dart | 4 +- lib/view_model/backup_view_model.dart | 5 +- .../edit_backup_password_view_model.dart | 5 +- pubspec_base.yaml | 6 - tool/configure.dart | 117 ++++++++++++++++++ 23 files changed, 259 insertions(+), 199 deletions(-) delete mode 100644 lib/core/secure_storage.dart diff --git a/.gitignore b/.gitignore index 24b7291f8..d0952ca98 100644 --- a/.gitignore +++ b/.gitignore @@ -156,6 +156,7 @@ assets/images/app_logo.png macos/Runner/Info.plist macos/Runner/DebugProfile.entitlements macos/Runner/Release.entitlements +lib/core/secure_storage.dart macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png diff --git a/lib/core/auth_service.dart b/lib/core/auth_service.dart index 66943bb7f..791701395 100644 --- a/lib/core/auth_service.dart +++ b/lib/core/auth_service.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:io'; import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/core/totp_request_details.dart'; @@ -7,7 +6,6 @@ import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:flutter/material.dart'; import 'package:mobx/mobx.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; @@ -35,14 +33,14 @@ class AuthService with Store { Routes.restoreOptions, ]; - final FlutterSecureStorage secureStorage; + final SecureStorage secureStorage; final SharedPreferences sharedPreferences; final SettingsStore settingsStore; Future setPassword(String password) async { final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final encodedPassword = encodedPinCode(pin: password); - await writeSecureStorage(secureStorage, key: key, value: encodedPassword); + await secureStorage.write(key: key, value: encodedPassword); } Future canAuthenticate() async { @@ -61,7 +59,7 @@ class AuthService with Store { Future authenticate(String pin) async { final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); - final encodedPin = await readSecureStorage(secureStorage, key); + final encodedPin = await secureStorage.read(key: key); final decodedPin = decodedPinCode(pin: encodedPin!); return decodedPin == pin; @@ -69,11 +67,7 @@ class AuthService with Store { void saveLastAuthTime() { int timestamp = DateTime.now().millisecondsSinceEpoch; - writeSecureStorage( - secureStorage, - key: SecureKey.lastAuthTimeMilliseconds, - value: timestamp.toString(), - ); + secureStorage.write(key: SecureKey.lastAuthTimeMilliseconds, value: timestamp.toString()); } Future requireAuth() async { diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index d1092b024..d0d9a8a26 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -7,7 +7,6 @@ import 'package:cake_wallet/utils/device_info.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:path_provider/path_provider.dart'; import 'package:cryptography/cryptography.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -25,7 +24,7 @@ import 'package:cake_backup/backup.dart' as cake_backup; class BackupService { BackupService( - this._flutterSecureStorage, this._walletInfoSource, this._keyService, this._sharedPreferences) + this._secureStorage, this._walletInfoSource, this._keyService, this._sharedPreferences) : _cipher = Cryptography.instance.chacha20Poly1305Aead(), _correctWallets = []; @@ -35,7 +34,7 @@ class BackupService { static const _v2 = 2; final Cipher _cipher; - final FlutterSecureStorage _flutterSecureStorage; + final SecureStorage _secureStorage; final SharedPreferences _sharedPreferences; final Box _walletInfoSource; final KeyService _keyService; @@ -374,15 +373,14 @@ class BackupService { final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPassword = keychainJSON[backupPasswordKey] as String; - await writeSecureStorage(_flutterSecureStorage, key: backupPasswordKey, value: backupPassword); + await _secureStorage.write(key: backupPasswordKey, value: backupPassword); keychainWalletsInfo.forEach((dynamic rawInfo) async { final info = rawInfo as Map; await importWalletKeychainInfo(info); }); - await writeSecureStorage(_flutterSecureStorage, - key: pinCodeKey, value: encodedPinCode(pin: decodedPin)); + await _secureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin)); keychainDumpFile.deleteSync(); } @@ -401,15 +399,14 @@ class BackupService { final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPassword = keychainJSON[backupPasswordKey] as String; - await writeSecureStorage(_flutterSecureStorage, key: backupPasswordKey, value: backupPassword); + await _secureStorage.write(key: backupPasswordKey, value: backupPassword); keychainWalletsInfo.forEach((dynamic rawInfo) async { final info = rawInfo as Map; await importWalletKeychainInfo(info); }); - await writeSecureStorage(_flutterSecureStorage, - key: pinCodeKey, value: encodedPinCode(pin: decodedPin)); + await _secureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin)); keychainDumpFile.deleteSync(); } @@ -429,7 +426,7 @@ class BackupService { Future _exportKeychainDumpV2(String password, {String keychainSalt = secrets.backupKeychainSalt}) async { final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); - final encodedPin = await _flutterSecureStorage.read(key: key); + final encodedPin = await _secureStorage.read(key: key); final decodedPin = decodedPinCode(pin: encodedPin!); final wallets = await Future.wait(_walletInfoSource.values.map((walletInfo) async { return { @@ -439,7 +436,7 @@ class BackupService { }; })); final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); - final backupPassword = await _flutterSecureStorage.read(key: backupPasswordKey); + final backupPassword = await _secureStorage.read(key: backupPasswordKey); final data = utf8.encode( json.encode({'pin': decodedPin, 'wallets': wallets, backupPasswordKey: backupPassword})); final encrypted = await _encryptV2(Uint8List.fromList(data), '$keychainSalt$password'); diff --git a/lib/core/key_service.dart b/lib/core/key_service.dart index ba2da4de6..71fb5a4fc 100644 --- a/lib/core/key_service.dart +++ b/lib/core/key_service.dart @@ -1,31 +1,30 @@ import 'package:cake_wallet/core/secure_storage.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cake_wallet/entities/encrypt.dart'; class KeyService { KeyService(this._secureStorage); - final FlutterSecureStorage _secureStorage; + final SecureStorage _secureStorage; Future getWalletPassword({required String walletName}) async { - final key = generateStoreKeyFor( - key: SecretStoreKey.moneroWalletPassword, walletName: walletName); - final encodedPassword = await readSecureStorage(_secureStorage, key); + final key = + generateStoreKeyFor(key: SecretStoreKey.moneroWalletPassword, walletName: walletName); + final encodedPassword = await _secureStorage.read(key: key); return decodeWalletPassword(password: encodedPassword!); } Future saveWalletPassword({required String walletName, required String password}) async { - final key = generateStoreKeyFor( - key: SecretStoreKey.moneroWalletPassword, walletName: walletName); + final key = + generateStoreKeyFor(key: SecretStoreKey.moneroWalletPassword, walletName: walletName); final encodedPassword = encodeWalletPassword(password: password); - await writeSecureStorage(_secureStorage, key: key, value: encodedPassword); + await _secureStorage.write(key: key, value: encodedPassword); } Future deleteWalletPassword({required String walletName}) async { - final key = generateStoreKeyFor( - key: SecretStoreKey.moneroWalletPassword, walletName: walletName); + final key = + generateStoreKeyFor(key: SecretStoreKey.moneroWalletPassword, walletName: walletName); await _secureStorage.delete(key: key); } diff --git a/lib/core/secure_storage.dart b/lib/core/secure_storage.dart deleted file mode 100644 index 5afb36d29..000000000 --- a/lib/core/secure_storage.dart +++ /dev/null @@ -1,38 +0,0 @@ -import 'dart:async'; -import 'dart:io'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -// For now, we can create a utility function to handle this. -// -// However, we could look into abstracting the entire FlutterSecureStorage package -// so the app doesn't depend on the package directly but an absraction. -// It'll make these kind of modifications to read/write come from a single point. - -Future readSecureStorage(FlutterSecureStorage secureStorage, String key) async { - String? result; - const maxWait = Duration(seconds: 3); - const checkInterval = Duration(milliseconds: 200); - - DateTime start = DateTime.now(); - - while (result == null && DateTime.now().difference(start) < maxWait) { - result = await secureStorage.read(key: key); - - if (result != null) { - break; - } - - await Future.delayed(checkInterval); - } - - return result; -} - -Future writeSecureStorage(FlutterSecureStorage secureStorage, - {required String key, required String value}) async { - // delete the value before writing on macOS because of a weird bug - // https://github.com/mogol/flutter_secure_storage/issues/581 - if (Platform.isMacOS) { - await secureStorage.delete(key: key); - } - await secureStorage.write(key: key, value: value); -} diff --git a/lib/core/wallet_creation_service.dart b/lib/core/wallet_creation_service.dart index 646e47537..a55e9ee3f 100644 --- a/lib/core/wallet_creation_service.dart +++ b/lib/core/wallet_creation_service.dart @@ -1,8 +1,8 @@ +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:hive/hive.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cake_wallet/core/key_service.dart'; @@ -25,7 +25,7 @@ class WalletCreationService { } WalletType type; - final FlutterSecureStorage secureStorage; + final SecureStorage secureStorage; final SharedPreferences sharedPreferences; final SettingsStore settingsStore; final KeyService keyService; diff --git a/lib/di.dart b/lib/di.dart index 20157b0e0..3ee57cb53 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -236,6 +236,32 @@ import 'package:get_it/get_it.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; +import 'package:cake_wallet/core/wallet_creation_service.dart'; +import 'package:cake_wallet/store/app_store.dart'; +import 'package:cw_core/wallet_type.dart'; +import 'package:cake_wallet/view_model/wallet_new_vm.dart'; +import 'package:cake_wallet/store/authentication_store.dart'; +import 'package:cake_wallet/store/dashboard/trades_store.dart'; +import 'package:cake_wallet/store/dashboard/trade_filter_store.dart'; +import 'package:cake_wallet/store/dashboard/transaction_filter_store.dart'; +import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; +import 'package:cake_wallet/store/templates/send_template_store.dart'; +import 'package:cake_wallet/store/templates/exchange_template_store.dart'; +import 'package:cake_wallet/entities/template.dart'; +import 'package:cake_wallet/exchange/exchange_template.dart'; +import 'package:cake_wallet/.secrets.g.dart' as secrets; +import 'package:cake_wallet/src/screens/dashboard/pages/address_page.dart'; +import 'package:cake_wallet/anypay/anypay_api.dart'; +import 'package:cake_wallet/view_model/ionia/ionia_gift_card_details_view_model.dart'; +import 'package:cake_wallet/src/screens/ionia/cards/ionia_payment_status_page.dart'; +import 'package:cake_wallet/view_model/ionia/ionia_payment_status_view_model.dart'; +import 'package:cake_wallet/anypay/any_pay_payment_committed_info.dart'; +import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart'; +import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart'; +import 'package:cake_wallet/core/wallet_loading_service.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cake_wallet/entities/qr_view_data.dart'; import 'buy/dfx/dfx_buy_provider.dart'; import 'core/totp_request_details.dart'; @@ -268,7 +294,7 @@ Future setup({ required Box ordersSource, required Box unspentCoinsInfoSource, required Box anonpayInvoiceInfoSource, - required FlutterSecureStorage secureStorage, + required SecureStorage secureStorage, required GlobalKey navigatorKey, }) async { _walletInfoSource = walletInfoSource; @@ -285,7 +311,7 @@ Future setup({ if (!_isSetupFinished) { getIt.registerSingletonAsync(() => SharedPreferences.getInstance()); - getIt.registerSingleton(secureStorage); + getIt.registerSingleton(secureStorage); } if (!_isSetupFinished) { getIt.registerFactory(() => BackgroundTasks()); @@ -333,22 +359,22 @@ Future setup({ getIt.registerSingleton( ExchangeTemplateStore(templateSource: _exchangeTemplates)); getIt.registerSingleton( - YatStore(appStore: getIt.get(), secureStorage: getIt.get()) + YatStore(appStore: getIt.get(), secureStorage: getIt.get()) ..init()); getIt.registerSingleton( AnonpayTransactionsStore(anonpayInvoiceInfoSource: _anonpayInvoiceInfoSource)); - final secretStore = await SecretStoreBase.load(getIt.get()); + final secretStore = await SecretStoreBase.load(getIt.get()); getIt.registerSingleton(secretStore); - getIt.registerFactory(() => KeyService(getIt.get())); + getIt.registerFactory(() => KeyService(getIt.get())); getIt.registerFactoryParam((type, _) => WalletCreationService( initialType: type, keyService: getIt.get(), - secureStorage: getIt.get(), + secureStorage: getIt.get(), sharedPreferences: getIt.get(), settingsStore: getIt.get(), walletInfoSource: _walletInfoSource)); @@ -403,7 +429,7 @@ Future setup({ getIt.registerFactory( () => AuthService( - secureStorage: getIt.get(), + secureStorage: getIt.get(), sharedPreferences: getIt.get(), settingsStore: getIt.get(), ), @@ -980,16 +1006,16 @@ Future setup({ trades: _tradesSource, settingsStore: getIt.get())); - getIt.registerFactory(() => BackupService(getIt.get(), _walletInfoSource, + getIt.registerFactory(() => BackupService(getIt.get(), _walletInfoSource, getIt.get(), getIt.get())); getIt.registerFactory(() => BackupViewModel( - getIt.get(), getIt.get(), getIt.get())); + getIt.get(), getIt.get(), getIt.get())); getIt.registerFactory(() => BackupPage(getIt.get())); getIt.registerFactory(() => - EditBackupPasswordViewModel(getIt.get(), getIt.get())); + EditBackupPasswordViewModel(getIt.get(), getIt.get())); getIt.registerFactory(() => EditBackupPasswordPage(getIt.get())); @@ -1038,7 +1064,7 @@ Future setup({ getIt.registerFactory(() => SupportPage(getIt.get())); getIt.registerFactory(() => SupportChatPage(getIt.get(), - secureStorage: getIt.get())); + secureStorage: getIt.get())); getIt.registerFactory(() => SupportOtherLinksPage(getIt.get())); @@ -1080,7 +1106,7 @@ Future setup({ getIt.registerFactory(() => AnyPayApi()); getIt.registerFactory( - () => IoniaService(getIt.get(), getIt.get())); + () => IoniaService(getIt.get(), getIt.get())); getIt.registerFactory(() => IoniaAnyPay( getIt.get(), getIt.get(), getIt.get().wallet!)); diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart index 77db474a9..e67bd2fc6 100644 --- a/lib/entities/default_settings_migration.dart +++ b/lib/entities/default_settings_migration.dart @@ -1,10 +1,10 @@ import 'dart:io' show Directory, File, Platform; import 'package:cake_wallet/bitcoin/bitcoin.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:cw_core/pathForWallet.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:hive/hive.dart'; import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -42,7 +42,7 @@ const newCakeWalletBitcoinUri = 'btc-electrum.cakewallet.com:50002'; Future defaultSettingsMigration( {required int version, required SharedPreferences sharedPreferences, - required FlutterSecureStorage secureStorage, + required SecureStorage secureStorage, required Box nodes, required Box powNodes, required Box walletInfoSource, @@ -485,7 +485,7 @@ Node? getTronDefaultNode({required Box nodes}) { Future insecureStorageMigration({ required SharedPreferences sharedPreferences, - required FlutterSecureStorage secureStorage, + required SecureStorage secureStorage, }) async { bool? allowBiometricalAuthentication = sharedPreferences.getBool(SecureKey.allowBiometricalAuthenticationKey); @@ -559,7 +559,7 @@ Future insecureStorageMigration({ } } -Future rewriteSecureStoragePin({required FlutterSecureStorage secureStorage}) async { +Future rewriteSecureStoragePin({required SecureStorage secureStorage}) async { // the bug only affects ios/mac: if (!Platform.isIOS && !Platform.isMacOS) { return; @@ -585,8 +585,9 @@ Future rewriteSecureStoragePin({required FlutterSecureStorage secureStorag await secureStorage.write( key: keyForPinCode, value: encodedPin, - iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock), - mOptions: MacOsOptions(accessibility: KeychainAccessibility.first_unlock), + // TODO: find a way to add those with the generated secure storage + // iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock), + // mOptions: MacOsOptions(accessibility: KeychainAccessibility.first_unlock), ); } @@ -720,7 +721,7 @@ Future updateDisplayModes(SharedPreferences sharedPreferences) async { await sharedPreferences.setInt(PreferencesKey.currentBalanceDisplayModeKey, balanceDisplayMode); } -Future generateBackupPassword(FlutterSecureStorage secureStorage) async { +Future generateBackupPassword(SecureStorage secureStorage) async { final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword); if ((await secureStorage.read(key: key))?.isNotEmpty ?? false) { diff --git a/lib/entities/fs_migration.dart b/lib/entities/fs_migration.dart index 869ed66ff..14237f080 100644 --- a/lib/entities/fs_migration.dart +++ b/lib/entities/fs_migration.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'dart:convert'; import 'package:cake_wallet/core/secure_storage.dart'; import 'package:collection/collection.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:hive/hive.dart'; import 'package:path_provider/path_provider.dart'; @@ -11,8 +10,7 @@ import 'package:cake_wallet/entities/contact.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cake_wallet/entities/encrypt.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; -import 'package:cake_wallet/entities/ios_legacy_helper.dart' - as ios_legacy_helper; +import 'package:cake_wallet/entities/ios_legacy_helper.dart' as ios_legacy_helper; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cw_core/wallet_info.dart'; @@ -30,8 +28,8 @@ Future migrate_android_v1() async { await android_migrate_wallets(appDocDir: appDocDir); } -Future ios_migrate_v1(Box walletInfoSource, - Box tradeSource, Box contactSource) async { +Future ios_migrate_v1( + Box walletInfoSource, Box tradeSource, Box contactSource) async { final prefs = await SharedPreferences.getInstance(); if (prefs.getBool('ios_migration_v1_completed') ?? false) { @@ -67,10 +65,7 @@ Future ios_migrate_user_defaults() async { if (activeCurrency != null) { final convertedCurrency = convertFiatLegacy(activeCurrency); - if (convertedCurrency != null) { - await prefs.setString( - 'current_fiat_currency', convertedCurrency.serialize()); - } + await prefs.setString('current_fiat_currency', convertedCurrency.serialize()); } //translate fee priority @@ -81,24 +76,21 @@ Future ios_migrate_user_defaults() async { } //translate current balance mode - final currentBalanceMode = - await ios_legacy_helper.getInt('display_balance_mode'); + final currentBalanceMode = await ios_legacy_helper.getInt('display_balance_mode'); if (currentBalanceMode != null) { await prefs.setInt('current_balance_display_mode', currentBalanceMode); } //translate should save recipient address - final shouldSave = - await ios_legacy_helper.getBool('should_save_recipient_address'); - + final shouldSave = await ios_legacy_helper.getBool('should_save_recipient_address'); + if (shouldSave != null) { await prefs.setBool('save_recipient_address', shouldSave); } //translate biometric - final biometricOn = - await ios_legacy_helper.getBool('biometric_authentication_on'); - + final biometricOn = await ios_legacy_helper.getBool('biometric_authentication_on'); + if (biometricOn != null) { await prefs.setBool('allow_biometrical_authentication', biometricOn); } @@ -137,9 +129,8 @@ Future ios_migrate_pin() async { return; } - final flutterSecureStorage = FlutterSecureStorage(); - final pinPassword = await flutterSecureStorage.read( - key: 'pin_password', iOptions: IOSOptions()); + final flutterSecureStorage = secureStorageShared; + final pinPassword = await flutterSecureStorage.readNoIOptions(key: 'pin_password'); // No pin if (pinPassword == null) { await prefs.setBool('ios_migration_pin_completed', true); @@ -148,7 +139,7 @@ Future ios_migrate_pin() async { final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final encodedPassword = encodedPinCode(pin: pinPassword); - await writeSecureStorage(flutterSecureStorage, key: key, value: encodedPassword); + await flutterSecureStorage.write(key: key, value: encodedPassword); await prefs.setBool('ios_migration_pin_completed', true); } @@ -161,7 +152,7 @@ Future ios_migrate_wallet_passwords() async { } final appDocDir = await getApplicationDocumentsDirectory(); - final flutterSecureStorage = FlutterSecureStorage(); + final flutterSecureStorage = secureStorageShared; final keyService = KeyService(flutterSecureStorage); final walletsDir = Directory('${appDocDir.path}/wallets'); final moneroWalletsDir = Directory('${walletsDir.path}/monero'); @@ -176,10 +167,8 @@ Future ios_migrate_wallet_passwords() async { if (item is Directory) { final name = item.path.split('/').last; final oldKey = 'wallet_monero_' + name + '_password'; - final password = await flutterSecureStorage.read( - key: oldKey, iOptions: IOSOptions()); - await keyService.saveWalletPassword( - walletName: name, password: password!); + final password = await flutterSecureStorage.readNoIOptions(key: oldKey); + await keyService.saveWalletPassword(walletName: name, password: password!); } } catch (e) { print(e.toString()); @@ -311,18 +300,14 @@ Future ios_migrate_wallet_info(Box walletsInfoSource) async { return null; } - final config = json.decode(configFile.readAsStringSync()) - as Map; - final isRecovery = config['isRecovery'] as bool ?? false; + final config = json.decode(configFile.readAsStringSync()) as Map; + final isRecovery = config['isRecovery'] as bool? ?? false; final dateAsDouble = config['date'] as double; final timestamp = dateAsDouble.toInt() * 1000; final date = DateTime.fromMillisecondsSinceEpoch(timestamp); - final id = walletTypeToString(WalletType.monero).toLowerCase() + - '_' + - name; - final exist = walletsInfoSource.values - .firstWhereOrNull((el) => el.id == id) != null; - + final id = walletTypeToString(WalletType.monero).toLowerCase() + '_' + name; + final exist = walletsInfoSource.values.firstWhereOrNull((el) => el.id == id) != null; + if (exist) { return null; } @@ -373,12 +358,10 @@ Future ios_migrate_trades_list(Box tradeSource) async { } final content = file.readAsBytesSync(); - final flutterSecureStorage = FlutterSecureStorage(); - final masterPassword = await flutterSecureStorage.read( - key: 'master_password', iOptions: IOSOptions()); + final flutterSecureStorage = secureStorageShared; + final masterPassword = await flutterSecureStorage.readNoIOptions(key: 'master_password'); final key = masterPassword!.replaceAll('-', ''); - final decoded = - await ios_legacy_helper.decrypt(content, key: key, salt: secrets.salt); + final decoded = await ios_legacy_helper.decrypt(content, key: key, salt: secrets.salt); final decodedJson = json.decode(decoded) as List; final trades = decodedJson.map((dynamic el) { final elAsMap = el as Map; @@ -441,8 +424,7 @@ Future ios_migrate_address_book(Box contactSource) async { final address = _item["address"] as String; final name = _item["name"] as String; - return Contact( - address: address, name: name, type: CryptoCurrency.fromString(type)); + return Contact(address: address, name: name, type: CryptoCurrency.fromString(type)); }); await contactSource.addAll(contacts); diff --git a/lib/entities/get_encryption_key.dart b/lib/entities/get_encryption_key.dart index 04c3a65f7..618066cb8 100644 --- a/lib/entities/get_encryption_key.dart +++ b/lib/entities/get_encryption_key.dart @@ -1,9 +1,8 @@ import 'package:cake_wallet/core/secure_storage.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:cw_core/cake_hive.dart'; Future> getEncryptionKey( - {required String forKey, required FlutterSecureStorage secureStorage}) async { + {required String forKey, required SecureStorage secureStorage}) async { final stringifiedKey = await secureStorage.read(key: 'transactionDescriptionsBoxKey'); List key; @@ -11,7 +10,7 @@ Future> getEncryptionKey( key = CakeHive.generateSecureKey(); final keyStringified = key.join(','); String storageKey = 'transactionDescriptionsBoxKey'; - await writeSecureStorage(secureStorage, key: storageKey, value: keyStringified); + await secureStorage.write(key: storageKey, value: keyStringified); } else { key = stringifiedKey.split(',').map((i) => int.parse(i)).toList(); } diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index cf9ae3019..79177178c 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -61,9 +61,9 @@ class PreferencesKey { static const defaultBananoRep = 'default_banano_representative'; static const lookupsTwitter = 'looks_up_twitter'; static const lookupsMastodon = 'looks_up_mastodon'; - static const lookupsYatService = 'looks_up_mastodon'; - static const lookupsUnstoppableDomains = 'looks_up_mastodon'; - static const lookupsOpenAlias = 'looks_up_mastodon'; + static const lookupsYatService = 'looks_up_yat'; + static const lookupsUnstoppableDomains = 'looks_up_unstoppable_domain'; + static const lookupsOpenAlias = 'looks_up_open_alias'; static const lookupsENS = 'looks_up_ens'; static String moneroWalletUpdateV1Key(String name) => diff --git a/lib/entities/secret_store_key.dart b/lib/entities/secret_store_key.dart index 2ee490c74..df6347cca 100644 --- a/lib/entities/secret_store_key.dart +++ b/lib/entities/secret_store_key.dart @@ -1,4 +1,4 @@ -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:shared_preferences/shared_preferences.dart'; enum SecretStoreKey { moneroWalletPassword, pinCodePassword, backupPassword } @@ -66,7 +66,7 @@ class SecureKey { static const lastAuthTimeMilliseconds = 'last_auth_time_milliseconds'; static Future getInt({ - required FlutterSecureStorage secureStorage, + required SecureStorage secureStorage, required SharedPreferences sharedPreferences, required String key, }) async { @@ -76,7 +76,7 @@ class SecureKey { } static Future getBool({ - required FlutterSecureStorage secureStorage, + required SecureStorage secureStorage, required SharedPreferences sharedPreferences, required String key, }) async { @@ -91,7 +91,7 @@ class SecureKey { } static Future getString({ - required FlutterSecureStorage secureStorage, + required SecureStorage secureStorage, required SharedPreferences sharedPreferences, required String key, }) async { diff --git a/lib/ionia/ionia_service.dart b/lib/ionia/ionia_service.dart index 0396ed7c1..821824a87 100644 --- a/lib/ionia/ionia_service.dart +++ b/lib/ionia/ionia_service.dart @@ -1,7 +1,7 @@ +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/ionia/ionia_merchant.dart'; import 'package:cake_wallet/ionia/ionia_order.dart'; import 'package:cake_wallet/ionia/ionia_virtual_card.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/ionia/ionia_api.dart'; import 'package:cake_wallet/ionia/ionia_gift_card.dart'; @@ -16,7 +16,7 @@ class IoniaService { static String get clientId => secrets.ioniaClientId; - final FlutterSecureStorage secureStorage; + final SecureStorage secureStorage; final IoniaApi ioniaApi; // Create user diff --git a/lib/main.dart b/lib/main.dart index 2a4e12236..fa71da31d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart'; import 'package:cake_wallet/core/auth_service.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/entities/language_service.dart'; import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/locales/locale.dart'; @@ -18,7 +19,6 @@ import 'package:hive/hive.dart'; import 'package:cake_wallet/di.dart'; import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/router.dart' as Router; @@ -138,9 +138,8 @@ Future initializeAppConfigs() async { CakeHive.registerAdapter(AnonpayInvoiceInfoAdapter()); } - final secureStorage = FlutterSecureStorage( - iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock), - ); + final secureStorage = secureStorageShared; + final transactionDescriptionsBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: TransactionDescription.boxKey); final tradesBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Trade.boxKey); @@ -191,7 +190,7 @@ Future initialSetup( required Box

        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 bSRV`zDcs=i85DSqJOgbFUG?l!S8o45ReU`& diff --git a/.github/assets/desktop.png b/.github/assets/desktop.png deleted file mode 100644 index 369015e608cec345f80cc2033c3804c64bb256a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62736 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 HgZ}nU1!RK* diff --git a/.github/assets/devices.png b/.github/assets/devices.png deleted file mode 100644 index 7bdccc5b5a8798709ca7bf34fd7d5561eb2b8115..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73544 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 BIO+fZ From 651b162e935f5bbc188471215ff1a9445a7d39d0 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 19:47:53 -0400 Subject: [PATCH 169/241] Oops --- .github/assets/devices.png | Bin 0 -> 73544 bytes .github/assets/mobile.png | Bin 154871 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 .github/assets/devices.png delete mode 100644 .github/assets/mobile.png diff --git a/.github/assets/devices.png b/.github/assets/devices.png new file mode 100644 index 0000000000000000000000000000000000000000..7bdccc5b5a8798709ca7bf34fd7d5561eb2b8115 GIT binary patch literal 73544 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 BIO+fZ literal 0 HcmV?d00001 diff --git a/.github/assets/mobile.png b/.github/assets/mobile.png deleted file mode 100644 index 6c0abf3cf1c8ddd7435f4ca9270dd74c3fb8cdc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 154871 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 literal 0 HcmV?d00001 From 4e286bd01621e8cb3975442b682eabd7c5642304 Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 19:25:00 -0400 Subject: [PATCH 160/241] Update logo --- .../assets/Logo_CakeWallet_Transparent.png | Bin 140295 -> 159969 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/.github/assets/Logo_CakeWallet_Transparent.png b/.github/assets/Logo_CakeWallet_Transparent.png index 21f985eaa582e57730dc42acd43851d2dd227ab1..459a6b37cf2a93b7da5d11bfe23a0fd0fc31de46 100644 GIT binary patch literal 159969 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%0AxcKM)XJNBVRNB^88&$)x{4-`k1P5Rgwn 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�s=xuIZ~)Oa(Zc#OpZAsH2`)So zdQh+6+co2u+K*;L-L(vlH&NGjUuNrzN~vk5iAgzv2H^E1wnn6q4Mf+YWpoiCf~|gS z1a6%@5YOF}hwGUp?pPLfA7RX+x9nuV@Jlskxo~{>ViQC-ORW0rgj?OvN{Z!!L@wBs7prNf3#~N zUWtpuY^E*A4aFP{pB%zfp6Q8^h@Vx7eWn)Ucb^vEjHV{^Z!5eWn2A+l5Q>T0eFqOr zY$U2*7=>HM#9)(BpE_xVyiGXJE7i`G^NUw8BSHxoQ~!DDYkgEGJkHuSyCve=0j!xR znr@PCdAG{=Yu1>tLE4>w`xkx8duB=zmG3mbPcOz_KUl-GB`66&ri$8xy1EYR|L|@#&y&uaF3NUi^VyM@#-r(;&d8Xx2>Ef-5C#XaK?wT}lSc-D~@Sxh~XbS-_Y4+3r>pfmM6!+37ba&8cnA!r|F z8rd@yU(I8*t?wMpbXNFzU={8SV`;Bzv+%H6xVh~wo>V-F=$YZ9&p*tm!fsEl#2voN zI%h7Hx{cor#Ot&htT8h)IDvzWO4RSiLfBJ>o09@(7s?xwic0dZ=9^M}l*H&PM9xnuWg&)#d zH6h{tC3q^VB`o@`L71{R#iNCHh+$NOhdlLE^gKX=E%f~VM~oEG{EUvm>W{`^;`Ir5 zyrmu||ECZa6jU(HteTU7ZOx*K9yTSAXq2Cwg_jRc#ha%j;mg&k*T8d7Wz)zg-jl&mG(!bL8nPFMp>^v`!I*ZW<%48~f3D%$G!sYx}kkM?RN=(-@ilvNEE{ zSRr&^_6)pBCi4i^%<8ICVZvL%|En_G@XQ+g)y+PHvTtH5`rkL$-90AUO($o}Guzj; z0s)azrKOekZz?}#MiPtl#TftqAOJ~3K~&qoB97fpZ|?nza5TlMRNpC7xuCzU!ktVZ z{CQRsStS?Dk6=y12n~Dte;`NBv_ZZuR_SUJc0kZl8*8k43t(BKJr- zyt^Rtwvkkh$CNkc)5u>+T}`0ymhEA>M+ctevr{m0QGHm8oI}07x;7htsS}ZoB$zES z3MIZXk^~matcg*#tG>LBDB{G~cl>?O9Jgn{m>gxPgLRUJv z5*++y368mF0N#=OK9{qUZqf_Yko3g*bY&^dkQ;!vGp5K?03!}N+Pj!(y= zU6b%^b2ARRhf#UemDsDaJ`f3KaI1D_=cDHX(MQp&7?MGu{k$x^R2+_Xc8kaA3#ib~ zrt#N_q17Jq%Pv;aq#!ppK!>~iuVy#BB8xbWx% ze9!5*qvk%^3MW$$j8!XE(ITlzQ{`lkZr(>Q7!!?>7sg@Yc|T%CeKV_7>s4o8G}pDDaXd}NUV>F!>o<<_}}UXWYaUcn1LtNtRq_+ABjd8GgbSE^?DH- zFxp0t>lR3q5-NfJr|~$3aEf13AEsZk8k({DH|02V!gtt_DQgCkF>Lc6mSNM6X(!#_ zEf30|L}cH^w600?=yRJgHQA#(AgmuY`tm-}`lzURW-T5#bpU4X9gCHlX$`-VGO{b0 zc~|fri1@Y)cf7b3xA49S>n`U%z6J4Dr@M#TY94+$SjlOsul*7Na!fFzOWdI9zVTRc zK^CUGuo^e{PNB+$BRu|fXo)dkMlZooG_VU)06pIxk97pwNIB>ti`!O3zEPfK5b(&qm35>+U>!XzQ zp==TbTEbB_J{jLEDZsHkI=F%GJ)BWyzonTw*pa7&bWn49&vt|d;ZfKS(GO*t8jupy z7db&j@~lgXaLAME@rS>U!kuz}662x_XK&H5lr_bX!e`tV0Gv!q`ystb5uKp_vI4I$ zm}gA4k%I|8!ZBKMt(lq02@DL~DLV!eH=WF@uTS@dfT2ntUaqCkt}GT#WfVE}o;Col z{WBgnlvHDsZ|@@NBWMJkls6QE9vh3Bd8W(^*dgCU$rTBrrD2G@Y&l+7T#CJYOVfxL zyQkrk?W$`fx&p{mG!u+ zwT7Osp@fnX$oi#^X#{RT#C^;0cY2@ozkDF>w|hxQc{PK`U&xa`n1^0oA2u^eZ-$6G z5qaQ?hQwfM&aRmHw<5z(avIYiA2hq11hkQO*_{l*0;ZU39&AMxj*rK;6|s2#!=dxnpJ1kF4}5X!CC#5Q7OG6BY^cctK-PCSM-WQrFeE_(H7}FIOp}{ z*y)%Bc=PEAIQP;dK57>^{DSKq%tPKd5{!Nb)B`4-_Btc5wqN*la00$MX$bCqZ4K^r z!z_5PE#40y`oa&LP>|PzO#YTh7G#fWHsTuNWl@YAjYV!m99Df=kBxK&sG#s##cT-m zWcqX@TdBl|p)jaVG}BzBtgpvNCNdd)(2p3zC*sXCFxlpTZ6DFv)6Q5pTK_N_w~dQN zz8&Y3t!=EpHH&wR+sG$vaepck!@_Zf@4&4I5g*EGk#z#;@|Qc|)NxTL3bFq27vNW# z^5r}a*R82mrPVvud*bB(5k<>#=GS1tpN8RnDh;~C(^~@fH&r#jojmHw=h_ zquFL7XvL=$VQ1XF9FLaQQQq!OnZ*b%X6=hnl%-n(aH#2vgYD|;(v2V>8LEnW= zBK55pc=l3EnJtH0Khrew88-~Y-?gi5No2!C`1?yG9Vfc;W%b9gh1fKRJU z45Sz!8cZ-Qx|RPAGwz5M3FtP7fS4dD)09J=KYw^)Bz~A$j-*2eVvm+a9K!m8$COrK zmoN&v2D55frEI>(>e?(n*KRIav%H28hjqVWZP9_zn2{fbd3O!Oy35wL5lE$acEj*7 zEeF!%HK}^a4j6YuJ$zYpeyit(1ei`0BQ9Hr|FllPIhQ44W>?m2v%D8U zdQf;SoR$$-^?(IKH+vYQX$Eyzp|u3)n}^}CMfKQy;Rc-4V`*-CnqvOH8A)VGlD?_H zgm26<-x0(OYeu_|o;Ak`;e{Slq}bNr6h4j|f~nVJ;6GlxU-W(f&z`&#-H>~o;}a4v z_cIy#T^Me>SkqR=2pCB=(kbUmrVe_aSs1dqh!HkZDXpo;!8b3#BWudAd$+7hy@|p2 zOxGrE$0@IA%Dr}ZnxNr{j|X<*)VAev_KidCrGxSKJpy1c%5=*%hG-CeU>fTM+)tYTWW|1@^yb7;a^` zg>Q`7rfvXWan9mlWNcVajdLGgjYlf$F~HXjEu8D|nfUjxC={y{KyPh^T*;5*o?Z-w z&D(z_9dqA}L}j5LBM!YnQqqI0SS-6J4F#c=w?vEFMzXj8!X z-k0@%sqa}go6eoVBK@Kp%wC0af}Bh{ISK{umLEWk#W^sfUd9rPEqR`$(8pQ?^hEj~W+cJS3A!@7Wc5;Wsqx zn~%2;Fg?ShyL8%Qg!+9N{{3)3r3{ZawiX{>J_PsuCK=Bd zcX$Zqt8*;cMjiid7ca$A%%r)GZ}p>^C~4Nt8TgE4#lF@ayTK9djd*kE=V%ah-Q=80 zBXE_UW!SZ4*!#5kn0^`qq6R17Mc!uymKmA)+TojIP5ntVke>8*3SrxGmrDfFS~mM*ICwc%y#DuuHBsgxuw8Bigh>NG$W{C8 zlob0;MO%VX2{|%FoyGeW+??nS8*uXROl|a^9dQw9O}U*r+0D8{`qRn8lR-_t zXbrBMnuD9_8kx$xo5mTnHY0%w7KtT}4Zvh=oOgD!8Qrk244EJHJ&j5AAFdGnX?P<8{eK+legs0 z#YOn_L?1TIwJPG8^GuZKcF&dQ8LHB##v&Xo?=DbyZF z=fj(Z;BS+b;%{WW{LOxm)>qVEwi@^c6cK085f6nMsSux7yr%iVZ!z9V;bY$_QNhj__WBp&HMedT!P?qOUdd&>A zqaM%3^KydL*(UMT9moy;l+C_MwWjro9HwAAp zTD;dbGZOeG8i99W-v1QB)Uj2e8$!|a@){V4jSr5+1y?V|dn}BbX$hCQ;d=X~Y##y< z;b?kn4E}s*99DQC&>D^_WRS!ZdeP|pUfe$cOG?YJmt*4W#Y8$AL*A?#aniv}81Uj) zOk}<31qQDa3@L`g>aJ0A9BEqAbA>qTMn$B}<#4#>M%jUs~%m!*S2-QXI|=2)Qh08FuCxd7x^V5H}?oH^=wK zId#c+Ze)MFNe9x!hO*f5fLnji^w*Lhhmip3OtE#wi+Py1p%P<_!)%p_b~z76-2)D~ zw~oY}nSzaZ7JkpQannxC8to`Hh)0)yAY5uY@w@B#vo<+G`WUPXQFespzr zlcrq3N2h1t<#!5k&hipEZTMXfmNNzCJZn8pnAHzQAIVH~wNZG9CEGru!L!wj)^*BL zm^4lINhX2wpAsBDqYzhoCdXUzOD{GtSYwc09WfYFf6Xj1(qA)r)pZj}BzSb|Df=An z3jam`o6sWMl$oZe5_>*W!H?D-hx{;>3v37@Ip2i%^A|G1R0C+WVQUYcZQ%*Wq|taZ z3l4_yUNKO#XB&V$$g6kVAWV5H4;L5uxlp<5BNpTVh$F6W zn?>}xa-_dH0IB_&k-D}4Lw>Bqn0fUWK9|2oG$A#bbvbz`6F5i|KQ!kWSDAd8m<*dN zscLz$CRrovdp1U)bbEgG>W2-x$6@8z7_5!$hvEx1qU<;QQFMJes=ljf#ie+z$meSS?2oK83d^o6q*2IZpQZTn@ zdt5h>c)`;X?Q3PK58>D&r^Lf>^iWJWDj9EzvGjniH13o|6tatX-rOp13?pYa8qZF{ z$B&oN0Nf1(nf1ju@U&V?zi1fl;yv^X4dG3Kg;z~5C9|#cG|~Sp$EojZ#FcYPu)lH9 zcK7Ihu8pAT$GVY2xEjX>U@3sph%0hL=n7@9S9=|badhU*^x&%eDEmv)=;OFC0i zg<+pn;f|~XT)MCb^9~$cdx?ge_#=cO9 z^YSZk{Nf61-zJdoW0i>x#i7~SJ4k5u8Hnj;r?9@^iiaz)26Y; zN1*Jwp_qI{IbIK(UZ=x_uAdm^P3ZSY9?tC-i<6J4#7_f~Fzvh)yhR=|FP@Q_qES}v z2C0e^rO!TKL}vug?SR#FIPr`{IP1G|>_>B7l<)OPf;=}fIvVAF8j44V7oH`tRFIk* z`L{h%u*@fzQMH5+ttU~83F^h|1vctzndgg{RY}7K8MRc+zu8oTE^I{R@+$OWDrjSv zhrF1h#W6zeHSR_Fmw{m@KA1Jb-dKT0Ev~cgv8_RX#I3dlL$6qbH~u^tx9u8_hnaHN zwq8njFD0OA)h=YT*&WYjj4V2XKj!HzHi1i8{okkwK zwG!Yshs)Ag?>G|?G)zQr3SsOP&iXUP|9LrX;(VpsZRO9FdkV1W-eR;Q#i3R8WA-6~ z##DdCnxgXCB72#h+K39WdA2*mI|;dQe8(6Ho(J%KlbJqxKMF6Km8y1N$7dDw%e2j- zf4dM*Ensbg&E82i$1x_*jJTVZ;VI_%k2xg`k8R-kUGNm$`uxdbDxd35$}q z?beGIBgBo@=W2S^eLEIeuP)~ur6?^SL~jB_ci%{_=C6Gx4IY|?Sx=6|EkgndcDJZt z49h`=lLihIq4r?DiX_fY!B>w*81&xnCSYTRWp&7WBpd(upa^IGWf&gLjKNF_E#*$r zYwMnoFq6i6rgRe~{7{Y~9$JqJi>n!JqAx}7ySsuWfGcEPqCc*}P^M^_;}m`5J^dRx zndwdz%-!O((|P#4pHN28Ho4^W#Cy0=+RFgUAsT->7?bCfAj4zCcF}V>6XUnUcPNOCjGA%#}u-Jhb?D6r;~TvPjCw`(yXsMSfB4p za01h7RY&*7ocU4sf<=*5&DRStBZYdyHrd4+mtj7hi77PQ%hK5DUrj?S+ev_pFgB6 zi={W%u}X*L_K^5|tyZR|b3VTYi;3AyM2_GmxV17VFQ4ItPe{hhTQ{P)E3zy}GrA8` zDu|c$OiOALKFl)qby_qkOB6xUlW<J923&u(zBBllXq9Tx3&LFZ6OE7qGHO9SBibEb-fdd+v z(ZAKq%;SGe(&m(+`)1-f%IEV{zuXJnO3npW(Y<~i1u>Ng^rA6^a#2z&3M(p^(bc0d zy_i?0W3)F0clz*F9$^1<@(SEHw;H?NG8{Ki*_>lUU)hAI83o1^j7DAH4J0@RQm6`+ zK&9!aHZEUb7-?1ifL;`BIq#`MVN`NUz=7OQs3@DU`iOv;$~VKCaf|I#( zIUcSZjkrToabItb1XezBfn|8W2yAJyd%!~m3h5s%{^g-~w29I6Z>++tJz!~lOK<`K z(#C;tSpUj)xO`Y7D&)oNl+3h$y_7cvB+_!`apS?-eoRH$ZHmBxu}N5vU5eeifeF|! zjtHL1OL4#j{2ZK)|26c(j9rs3olN47gpH9sOn0>Iu`NGl$|GfvU?f=rQz4E2Zy64) zW$K#wWjJJhHPQmPF#g}8$%_qif=eFvq46i8Gz^2zPjilw;#YPgjTb+lOe7v8t?_u3 z{uxg9p`1E5QL*cV@N#7;X3ZXmSKiNMM5|p!DA-^jqqVvMJ3YD{zrTMN?h}o2dTexd zwLJ06PRG!4)qh8pC^>Bi?tL;FPjE25L9OFm2`Gr=_|wd6Jq@Ke^x2GJQq|UGbJ%EG{6XMzwnSHGd0t2G4aUj#^7L=2Z=}B-2$eP!r;j;r+^H~|TLfs^Hr<2}@ zXX>h`Jf`_xJUI&ah5@)IHSTY6f6SAfB{c*Z$8yq+b(AB#k|DOW70S|Z%|N{Qry?4F z{caEl$nRPUjkAdlufVOz@wn{3WPCt*VFn|DXEHj1Ma|j_NTy6->dN%H!LtM|CS}}U zhK^y({=0aPxj;*uRPC&$|^BF~RVJcPjY_IJ}3& zp)9)&`Na{aV-Qw7gM6B(e~+R=b4(+RzpEOMb?gQs@k$##>uz#|AzU&DFA>>y(y3bZ z3_1{c(sUObOq<1SDr4lyh(=brf+^+LIH#2c;NH}TsOgt z%tzJD!|=d$6?oZ|2F3MkdcXjI=%1N+IDH{=o8LVKe{2fFG(|o-QBIl4t?!x2^J*$$ zrJvEBiEt(X zkIYK3qA(oA4dKk7LuV&ue~4$g=p<&y$SiHdxE;U8cnWTVsia9OYCy^|sVy|7;)g2(3D<)NF|iXrExxPSTAyr0|Y&D;;z14j^iRQ_XtB7i->Dc!O6jKICq3vqH&BOMj| zW(lu`{nr2hAOJ~3K~&>>o?MF?&ZUuhk65gAiyxwMJh!fzXxvSM@vm>naMF*3tOwj3 zQXX$>#qAU~I()T^4qn-c!N%k5@k`H{pI{3Uu6Cz`&H*J2jU&q@k8Hg|O1sqVx)zUN zB$0GoV;J+4dYg60<7tL$I78W6rrbs>) z+3d>ehWBUF5ITXZtHyRt*5Kzp$0p*d_sfI7x4H{u2-%a)Bf$=^)O(mA?enNO6gAZ& zy-ShD?&cHO%j=Nwehn^)j=}k-RA4<#n;T=Iv7o96ONtt?j?Ryj)pWX|Q6##I&RLW< zQkm|0RLdspaL^AJTi=Ydye4EmQ%|X){k?5>F5Tq$R+f}2Yzm7fzgyvk)fLZY1`>9Y zrT0y<8$dufDTj9jLJ7xQvj`k;_joM7egqzzyc7?2Yh9lyD+GYTG(stPwft;NuF&7Q zJ3S)~L@=uPt}(cA&v?dF@OL*f%S3qzptnriC2E zl+bVecPO5`J`?wFzY3ia4yCOU9hD(iNS#Bk%!8O#F-7ko5$Q@{D@c(1#jwh!t;l2H zJ=02{lpob-kf5vdiAp0#dx!0&J&`lT+m$%@wiTGPxD@-gS+x0ax?x+Jg~sDNpU%O} zTuTBklfNX>;9z^gJ)naO^o%TrB7xOu`yuoInr2lODT- zHfu-om1A+!wS(-{jJE<4(;-KWLLRXR#wDYA?Y~aLoBz(kmDP<%>^2uqyL(yiE2hv= z+{(K4Vc5R79KT)ENtIisL2hfN@MCg&UfvH@Ha3*c=)SGTK)q7VW=@;e*QnEZ_`RRt zMCBk-h+C?yUG2M(1XiyzweX|oM3Z3QZ8SOJLm3*3$#Bj&}?%?8grlR z^27#7W+(DwP5&5&Yxl3hSFH^`G@Ls{WRrF|?eFJ)M4aeI)I2x}*N=@xVLi`Lu%p)e z43745lcGuGczW_xWp^)RaN0fr^ScfIVs(K$2m2;t9-V8~&h;ot#pX$ zd5?Kj+s^JBqPV{orr?urROh)THI@}SD;3{lQqf_%zL-roh#!%HdLA_tMi#puw;}zo z`ji3qcvr0e z>!jg3acw;lF@&SS4bLZ#NhbA7#&x=;zJ5It0?(EJcV&6QI|)~B9E>MFFT-K;3h>(= zgS0(at`Js}zMnW4|2TI5-jRKQ#$eBy>^gGz76`rK&uJfNP3VX9J&w1v0(C~6(>Bzf zWsVHqvqu|%CB%5r2&iFEsF}!=q!*UrASQ5+?v=>n2{79YB0|Ba&uObMF{c6tTrvu` zkBPtsGFUoo3OHKFFyPnd0s7KV;CWt9`zKJL9Z20~I@@?fOq|ZsO+T$cp3Cy!FzS2o zr$Bii*I8E$>`dWO2Jlicej=V)tC?BC&bp--QR<=okx2Uc2K@2Od|bn7$VovsM-2dKqqdYBVOQ9@)Ej zIKRg*hCaeI-%W-4e%werIcXRk3-FkpPSK=^QiOS_yOFo`aZEusG#Otnl@R0Q;GROD zlfmo?EiUftP%g{schxo_qmUZiax*oogBJ+Yy34yOsyJA(<1RY4;&~((G8>7jrm@5~ zT`?HXzP%CWtg66{zB2;zTrDreX|H9qzIY}hw%i&FSbr)ILgNZ_*f$nI;3`DhzcU{uth)ue#_ji?CD;*0{o-d$5t(GBzjA88oO&5B9EctyQic~K! z*szrjhR!s2glS;ts2uc0o~LEmfUq~IhdG@k3}U+Ny=zxiu={+_cOv*NAa2EcR*li5 z!>in&mgx8{)Ccw_-`5q{4uTJN8J(;=v&8qK+0Y)zrjF zyme|8o*f;FdsrW5gTcT%*h3+j>N%+p`C2Mw&!$_-2bDk;t!auJQ51=ALy@v2e1{@q z9lXW^0N5KsbFAZBb#RAsO@p{l2|8~vll@0r-wCW~#5$Qs<+}1!W!~QKo1YfgW%w1L zWNOMouUdr%H$wmh60K>(@P`U9n5lKwJLMrn-;Pdf^TzBdopg8EB!m!tY)Rw5&uB#St0av&4$Dm^O*k}5BoaLC=bTf&*zMVrr8$}0|?NTuJv5~kfBNCgGqRr*@cmCdP@`TQT zYIrVVJ>Eqqp$yRYmdv{D0IY#Y2|Duib%h?FK~!6$Nau5K%+{rMuZ>i|x+&|DJbeaOEyAGdsESoX=;7-FM#i zobNgBi6^bHLWzXvfmg!+Kx>ViCLnvK9PXWF(Anw?%APxLEcr(rj*h~LhqH0x-K#K> z4j{p*1a`WM-1kLUjJV#0hoJV2zPNHg7}JAU56`YTTZrO!F{5iNuWdcEy0RP?j(H!4 zqN=O`(Sf#(eqV{cQIbZBK+j8bCDlFO%i{`QSBGVhG5B0B+%jsm1mr(B4gZFn2QfNyee!AVVsf2Th#8)8Nt z*Mfj6ZNouJ|6~PVPGAY=Md5YR^L=nRw}kbdZR5Dq()kE*4m&CXpS;r-L?RtNCN4uCYdw2@I{j&hatFc(;8>U8!*wO21(S3ardJYLguCqcw zS+8Af<=RP!8`~P;yq*dhmlfXh-gLbGOA*FxEWx2ZCk&_XZhjGtn^c7J#--xj+73$c zWP6pwJ)RLg#z~0sJ=#+?KSn{#vRd@ZEyaFriwxsr9RvPrRv}Gf1PWg5k8vr%3@6Es zb5+j!&cIj3aVCvvyP0WO*clq+qBaN@&JU$&k)|~$r2@D!6z(lEqmeT-0>4f#^nW5L*z))ZKtC?Z6y_K*XCvF0)*(q);L za8n7Ud!l{%3@;Jj9&b1^l+5bY@#jmZdwCxM(2=_1@bnIQBp_!oSBBb`IZp0(K`JJ% zsl%YRH{w>O4=LJr?jz88aBR7?H|{(k9zV%G#+CXu*^7%VCY6WG5zgeT+)K-uTYc37 zA=qIkfCH?|sY4ed`w96@_F&sRt^jt&g13JpR$kg2&%d=659o=}4WmaqbZMdRUJWL$ zslWv{cE>|qLh&;_A5h!@!Iy0;$iyPnB(>ZSy~ps-r^iy5NGp>&nB(v$P6Z6#i7HVx zS+A4pWkIr~A#p>CTW`q+$us0xHpR94U%ZnKqJsKozOnb`Ge2%OU`{0!zeT{u^!&9c zxH~G;F}M&?ND!iL&%yYwb8+p~N@N*AJ^45*DeNdP)@gAbPCBs}@6H^Eiw+1yu7unS zv|>{NGk29y0#OMp!b^Iu)KBV-tF8$}$<&Rw-GCu4x3|V;pbbQKwwLq!FdT^nT+hsrc`oB{+%}IcD7}xO3om>E2>oR)?6=!_nPJQ4#}# zdHK8`>%63;5|M@rmobM(a{!4zcE9dMOa${hhZxI%x2oY#op*b&v>*x<&s1ael+7N> zt;}ckqA~VU>8d2 zoOj-pC9R5+jDNq}0XYKvqR|pT?RTafJd`qOF{E?FR3zzry7OKW=xq0E6$Y;>z)0P+ z`q*&boN`bm-o3ROUJ>1lt5Xxod?n*RBDT6??qce<+MpQxg=+M0%L9C@yLMKGFK9#) zdQ8r4)i-&vcw7PO>ITX{lt$dr1+V;2gwr>dV3?z}3kope;xZh0OgbiC zmx1SpMPjK;G#$_b8)8kkEg_V%`TKGXqMlrgqGdAT zwNf=XyvYHwN(LCOt9D?ZiKni7M?yb|g^S#a;jWEwMcp&{@<1W?4W`CVynN+%66QID z7tEs)SiU3m7Xhd%7F)T8ct0~lOziX$ob-A=Zm%xI(4FC)ZNOaI%?{m;ZQWjoV@EV$ z#;k$(_waCRkbViY(pCv9{njHuJ%M=$Zen=gJ3>QIJb4`+mdF9B1orc{fpg-~8JPY` zUtGwsT`hu+FgHr7#rszdEbiD`N>9jr&rQVF^HcH3x4HPY?i2iceD1FL9H;B5(SIHf z!3+cK^mvlxO!H9MH%4rRar9_(*&#-znv>)4{m2YV{bn2ASMCE{vca;iNqfJF6G~wv z`dqaIw|>?ecgtS1BT5X}KZw<~>_45I18qv7Q)94b;y$?K%4L{Z-$XIIvp3v31--%% z0(?=f$i}10clw^Ojd#U?!I9_t__ea1uH?Rh0(Oj`@vrKC|F^>qjl|F6x1*U+2i&+D z^Uy$%b95Yj-psvUN9N9s)>d9aNwM@U4bVk);H`0I$g_g6sCP6rtgk?CuT`X@K;`@7 zct9jpU6O>=rIed^VhIvC6b(I%HBo?oE=-TSC({fa-QxiMm+XI)GOUhK%xlA{%I*gGfIj@R~Rtc#(HuP zYQEyR;+O_}wT)!4<|y=lk&WvyX<4@kzZGyCGYm>^4o#o~qqh_@_Yc=6fP%eW%~ zpy++BO2W)L^Kph9t?oRR@a0NuLE=cJ9P@PXxB^%fJ$ID;VJNzTNw2S}z%(wZ9&eXB z+T>IBw5wDSk~b*<~MkqA)_8I;2|S|N@IR`AO4-pf1D5p9L6xxQrb>ba!rfLVkmOk zma};;Zr}|CZZdx*d5S-!KgU8IO5^zNE0XBpOJOqOv>O9UzAcAUIc&(Gv7_y^)kW?r zZDc)yeyqT`tIII{w<3D0$php>>V`SJLt~7*DoSv`Y0L2GCxdVva}KP?chmdbp?bRc z%QBoqHoZ#1*YfW`^8~iN4-y9Ro$i>xd{23gufc?pTBLUZ5tW-qkB{D-@9{BR@yVNg zF_w8mjPzaZ^2`+iGQ}C*5B!Har#VsR-I|5_XP4mkMok&vy1{3&;F8XB)q?13?YLIH zUxvf?OGG%=(mH2CI!Y7LI3Dx3r_r)^0>&1_Ds***cY9Beds2woa$`3<%W%ubmo?Ix z)t!^W-kaI(6{`zy`Qomac4Rb`bhPcRdUeF8@vKCAUeX`e+_D01@tq9vMRrai_s_3! z5j`Ul@7$PyN96n!=ZVM_MEEwiq8?#1PQlKElR^VC%d*Du69i0Q++xQ|3!udubxd>O9rC+#iTi z&1OXJs`Yel-5@fnXQ#_XYC}uWr*^yk<$u1$tpWGj#FIkRHH&=3v@_#cl zm-m53Z%E~Dzc{QCM-6)ZR=7p^D`UvIH$Rh3dG078o1r(Bq0y(ek^a$fkXKGGk_jM|P2U)#3bvruGMP#^Xc=aK=m~5SoLrEI_k#Ok?TcIS=B82%-Z_T7eSmXiXLrVX$vh*S z$bLFG6R*A28#hq-TPMP5cUb)Gics>LyW1m5hTw=8tbMQ-?!I#+Uh(O<)nCRKp~gjF zb5$elr5fR;QA7;~#?)m%0<9l8+*@@ZZ1!Iha9PY*+9rX+_R=eHMg%wL!TZ05Y%_Pph{?QuuN zO{j^A#cwr5_?O@BUqVsHQ0Obg_|F%L7_oa>0ZbGv;p|`RzzM#<#MwHS*bp-#QPg=7 zsMUZ}BB*(K{@{9Td6Hhhi+13++$!|b)C@%3JAq3;hS&#`k6%m&CRY|QE~S!c6VLR_76A9;_9x>SXpWYb7$fO%7uS2Ap6!L~)feX*}yS7pc$a{rj^U+E8es&&C z4?%x?&6{}l(4%;bRb*YkYsK4GJl!IB!zc+QWVI%B7iZ>D#^O3;Y$(NuZ}KsIVkr*Y z3C&Ftxy#!^R%KP_b>1>epF9xfQTh3+gdhpDVhaZ?p1@K9Q3)*VmcCC3#UGyz#>wZe z#VacdaB{2FMWBrcKWeY_z#SZd`t!2!(4;KOBZUnni15ZE-Ntz~(t~5<>I_W$ybMRp z%f)$tw9$0=h~)Sf@dRQelEwbqvDVwQA8XqG8Ao*M;!fb zAYL!~FHtxabI&3N7+1=C<=#*Az+*EDaVBb!;h71^fnH>rzsSX?k5lpP=?R!+cEP?^ z#-45e?Ckt2-z#UI9F>SCE!i+VzY&k{pc(9Q{2V~-mzPqIeONkXo|}R3424=B=WK`i zW#b*IwB$xSmWI4FOr_#(S%G6U^PQ_BINz)>VeX>^Q~>+S8L>TlTqF)m#O(ZLR7lh< zZz@G(iy&wIS@g=Q<$t_A_D+n&w?Bm9P8x*sP4L4)hVf=p9ua}LQy5m;lSR%f2h)E@ zKC<`o)O0I*o}M&lc#=^!MlHci3grQ(d|H zTC)aU&^e<|H6kM|puFC>BJ)d<&AG#g^NDj$)o%q70eM+gF|x*X%DF|(?5ZO7mHg^S zq4=Fj;Ir>rgO74+&{YjyTt(Q9`&j45E>YNieKszj()TaJ(8^6Sq}*0gW4K!;LPNmD zW0UdO>;jy|M|yi3W=BW3;1a^6-YSL>A-Yq6ziNmzdaVoYyw_WJ-0srd9zFxZvGw9! zc<}KRcum8e?X~}1bAe58--L+iTQPQeK1Q9Ef^QHz!H&^MSZ;K!2Z73?B&wPecc!grZ`_OV*SU%K{@b2-?47lE*kAk3>37-{ zU*x%h%HN{9`(Ug&1YcxFqFYJ~HWW#?S#K{4lqoJL!J)(Zq1)gHtaT=ohrHjSNSRLu z6=tNkPS^x958g^)aK(MKia2 zSEf;1buFXOda8I_0qo9($pj}JoA-3V#04c7`9luQ(h13(#M`;IC|zl_`dKdi6 F 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 CPow() literal 140295 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%0AZ5ru1LUBJfc`W$J|m%>2jG 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%0Ak~@^={LVZ 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 x@W)Rl$^Gr;-X-H5&llUl4{ Date: Fri, 5 Apr 2024 19:16:55 -0400 Subject: [PATCH 156/241] Add screenshots to README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3d64ca696..7aaa63653 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ Cake Wallet is an open source, non-custodial, and private multi-currency crypto wallet. +![devices](.github/assets/devices.png) +

      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˖x! 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 bSRV`zDcs=i85DSqJOgbFUG?l!S8o45ReU`& literal 0 HcmV?d00001 diff --git a/.github/assets/NOTICE.txt b/.github/assets/NOTICE.txt new file mode 100644 index 000000000..9719639a1 --- /dev/null +++ b/.github/assets/NOTICE.txt @@ -0,0 +1,48 @@ +Notice for linux-badge.svg: + +1: +This is the Linux-penguin again... + +Originally drewn by Larry Ewing (http://www.isc.tamu.edu/~lewing/) +(with the GIMP) the Linux Logo has been vectorized by me (Simon Budig, +http://www.home.unix-ag.org/simon/). + +This happened quite some time ago with Corel Draw 4. But luckily +meanwhile there are tools available to handle vector graphics with +Linux. Bernhard Herzog (bernhard@users.sourceforge.net) deserves kudos +for creating Sketch (http://sketch.sourceforge.net), a powerful free +tool for creating vector graphics. He converted the Corel Draw file to +the Sketch native format. Since I am unable to maintain the Corel Draw +file any longer, the Sketch version now is the "official" one. + +Anja Gerwinski (anja@gerwinski.de) has created an alternate version of +the penguin (penguin-variant.sk) with a thinner mouth line and slightly +altered gradients. It also features a nifty drop shadow. + +The third bird (penguin-flat.sk) is a version reduced to three colors +(black/white/yellow) for e.g. silk screen printing. I made this version +for a mug, available at the friendly folks at +http://www.kernelconcepts.de/ - they do good stuff, mail Petra +(pinguin@kernelconcepts.de) if you need something special or don't +understand the german :-) + +These drawings are copyrighted by Larry Ewing and Simon Budig +(penguin-variant.sk also by Anja Gerwinski), redistribution is free but +has to include this README/Copyright notice. + +The use of these drawings is free. However I am happy about a sample of +your mug/t-shirt/whatever with this penguin on it... + +Have fun + Simon Budig + + +Simon.Budig@unix-ag.org +http://www.home.unix-ag.org/simon/ + +Simon Budig +Am Hardtkoeppel 2 +D-61279 Graevenwiesbach + +2: +Attribution: lewing@isc.tamu.edu Larry Ewing and The GIMP \ No newline at end of file diff --git a/.github/assets/app-store-badge.svg b/.github/assets/app-store-badge.svg new file mode 100755 index 000000000..072b425a1 --- /dev/null +++ b/.github/assets/app-store-badge.svg @@ -0,0 +1,46 @@ + + Download_on_the_App_Store_Badge_US-UK_RGB_blk_4SVG_092917 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.github/assets/f-droid-badge.png b/.github/assets/f-droid-badge.png new file mode 100644 index 0000000000000000000000000000000000000000..e51ae2677eb661cc3637c79547addb211f8591ad GIT binary patch literal 18971 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 yGR=`-VhHF|WMEJSazcQj2SA*uKvBw-g!10|R;A literal 0 HcmV?d00001 diff --git a/.github/assets/google-play-badge.png b/.github/assets/google-play-badge.png new file mode 100644 index 0000000000000000000000000000000000000000..131f3acaa252a863c3b694d0f522ea750aebd81c GIT binary patch literal 4904 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 literal 0 HcmV?d00001 diff --git a/.github/assets/linux-badge.svg b/.github/assets/linux-badge.svg new file mode 100755 index 000000000..8416e1bb1 --- /dev/null +++ b/.github/assets/linux-badge.svg @@ -0,0 +1,1071 @@ + +linux-badgeGET IT ONLinuxlinux-badge diff --git a/.github/assets/mac-store-badge.svg b/.github/assets/mac-store-badge.svg new file mode 100755 index 000000000..c36a76a5a --- /dev/null +++ b/.github/assets/mac-store-badge.svg @@ -0,0 +1,51 @@ + + Download_on_the_Mac_App_Store_Badge_US-UK_RGB_blk_092917 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 705ce35cee8fd611dad9d554b68cda52c5e2f02e Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 15:50:56 -0400 Subject: [PATCH 148/241] Update a couple badges --- .github/assets/f-droid-badge.png | Bin 18971 -> 16447 bytes .github/assets/google-play-badge.png | Bin 4904 -> 22641 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/.github/assets/f-droid-badge.png b/.github/assets/f-droid-badge.png index e51ae2677eb661cc3637c79547addb211f8591ad..2c9521de148af20ba72c360b455b09bc2354079b 100644 GIT binary patch literal 16447 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 M3(E*q3F!I#Ka5AAT>t<8 literal 18971 zcmeFZ^;=cn7d3haX^`%c?ovQfy1Tm(rMpXzP5}Yw?(RlPx;}JEBaL(jcb)J1-XHG& zaL@A~9M3*`ueJ7CbB#I1m^(s6Ng5r67zF}>pv%fgs6imGq2TWaBn0rU;C1LB_=W5! zqw4~JVDv$MU$)f?N?4Y z$`uZMx%OZLLVt_F;fPa#7wpgec<6g#PEH!=dx!#B1bAD5_5XkT{~4CRH;XXv%lZzT zcqCX@oO;DGF)&lg$-71nHJE+~2LdlY7&{bEcL+Bm5?=H@!{}dj{!IH$rQ#LGf7c5O z@B%F&*cQ4N?r3T09|F3nq~pkO-1yhfAlh&ohwywD2)ROc=a7()m^D55X6d!r@OefUcFHuN6eE#vZ*T7g;haCPwkI|O zw0VMfBO=dp;p)%KEusJ>t7~|_g1l2;r4t!Ee4+FH-R87TQMp z>Zptsvbwsu4-s7a`-LHLvBT?a*TW$*DZeWNQZ5!2ma6oB`O>cq+?Ol~`J8F4ygS>q zpZVPmXQeTJiH~k(5TdlUwmQJ3F8%GfIa#?__c_b0so_8}{ogl}v$A5-9lD5u5zw7) z@5W2ji`Tz!C}Q;SaE^_S`;oJHqf}}!ulqmRRTy^*%cz3yOfQ)oFV?1Vnj?(uX{Bci z@`5Yz^@I-_oBkl=nPBu?xi^xOe3j*Qqf7e1Ur+~nnQ7f3{bu{rw^kU~*w_ZAVCWwm zGh7JWBTTmsw<$IorV8@%U@!M4_oq0)(T(j_SFU5}yw#S@I?Rz-3y5z>=Xx1AaUp_-zUKQAnFgQ4z)g8$y4L0fjtm+7k5m3pg5<{-Q{HPb}G zL)SK|NmA8Z{~kisu*^xMWCyco;?_>0I>G(RDt! zAhzi@=mj|^7TVoUP_!68^CgUi>!R1%J=#}s;7u#S7R2SiB_R)d#-w0o={R9RNB8r~ zv(}^Dt;?+u^fD@7T}><$D`#W;pA*=PjE>rPm8Z1diYY?Bn~=#aCodn2hY0O+x}2Px z-ntyJ6scT@ycywG6NTP^kyRkI8pEw1lNd^ z*IZEIgUK>IK7al^G&Ce4Cx>EYW~QR68}awA^YKdaYo2u0#m#RBb#--9rRwwrg@rw4 zwK*jvNc75C5|WaVHR9BH^|(0V?7s}YM;A;KIu1cBh`z_7hszU3gk@!fOP?8Gq&Lnv zz~PFaNs&F@rPPMYR*8jd3qY_TM98||Th1eqd|wJ_hp?J>9Dj?f`ahnuT>U3M-R|Mg ze71Pve!Sd>YV3RQ%Gt%`;;6dYyV9jU980Iowe&Fc`C*}Zt8u|dyxD&3{G@rKtZFbb zFOLe1LfAlaDPKB{=jGoQMDm}-+5RYymd#L-^W*wSYi#4h$qz52w`(5RbZ%}(^XRwh zKJ0XgX5+@u4D$#SVe^X)gkBes8cHGb4ycjwS@1Mm6lNKn9YVNchppYP&GSs2B7FRTQ(M%jO+1r|W?V8W}%s z+=u7)TGd7|(iDEUA6}m7S8l1Psi!OTdFN_rX=vUxA1Mo+f=OJ$M2{3C&%(*cIUW!f z6Ei0`(a`X&`-tO*f=-PI%*XMx-Rtf7qie#qAJKkA69prZdqQqE0s>tAJ5n?-Af4db zCr$BD{_yXeR)r2sd*{g?_Dlf}do~IRijBQTiCJ*ktGpsHDP2_-H7=&~vth>^sny7D z=7XERvtTP8EF3VYX_VPo9}Lha(qo(lnT8xsmRK2OMC>dNqN(FZ`LMHn|007ZZFqXN z)=sby@FIkQf}*0S8FF{$X<=buvRGq!uy8i!u7g9T@G~5X+V|PizE+2Fv@76AQ8t7| z*6zmW&$V}|f>jZG^R>UBVdkXM-N>e6!&24sr>{Lz=O@a^mO3o!0kSoEmHq>`BqUM0 zqbb{Uqii-^^rKu&_G^*oBs`St?61Fl`*!eOAu63xMtGHBJM5>s5Yzj=yU-|`74Yme zaB_3Jg!9&FqMyW}V^jM{!u7_)>|kI*ao~Wrf|n}4GCWr3GFUvRTxI(XhId^UMf&FZ z*3We@_C^(-qjhF1bq9)2Yp1sots}d-cA7LJQF-S_O+l2B`_@D8Z|?Te9nyT_B~<&{ z&$^-{qwqI}zEP8px}B~PL9bY$TOXg4R8TUWCFHX;TdE#uF64X1k(Za((dBZ|xX^ZG z4?WV-(lT=8?;!LH9vglOM*{3!cT~?;#UEfGpy|Pv69Vie7YEng6*{%B+rMILy1+Ew z*gS1N`_<+5sMpDk1WTu!6`f-2Po%4>iwO@iDRfI(p~d`s5f{KuBq6Jg>3@b%=~q?}H4liyX^BO^JtUb{&5 z<$gdackSK%v1Tu_IZX3(r}#=PD(J(9cbuG96ai08E^0dZ`ccD)^xO0L4%cb8us^}Z zS!2=z>k8Ijb=N~#9=V9Mah%Xis=V4=_RACE_F$YxIxZ}_P{e2o`{4OzpVQs>=H4T; z$q4AgJL>5J0|N|9Ot27(j~}KM!!sLS>O>TB>c2xpQ=qF#ed6dvGYX3mOTT$wgz9czfvgr-wKtI&b-LEhYrNsU zVy9DU7LvzbR$lIO)_J=HLcs#R;C~_uRfZRf=5gG{4r^_AGewG*pGPazi6+Rq$c$o9J-5`H=t zpSy-`hk9Qni66HqUKRyYR1;`cod(GwZ%o&k9VoJVPFwemRP&`agHYMdOOHY5TwlG+ zh>s6Mr0`V{-H~u@GBZ1XYgg=zY>vxg`GC!hSLIScqoYD?-^0zD5!cfvfXFCz`1U=z z_67&0W^7FS@3!-tA}SQi5Y@Yfe6>ZpT+SVD03NB?PRH1Z*}I>dG4pdprvA95^0|Dx zyl&p`k1}j`XRO+v(>8X~)%0DlYrfZ*_*ifH{B%FQ5b!XQ4c$%#PH?7|LLzeGB2iiH z4ij-0CZfUy%-|tIF_-8k&P0b7sL$s^mNKK!7h34AMAWQlp3lz-XU!3hoxhE~O&mEIXUl6gGyrBO)XcFA4%Pnk=(%X)fIx$ zds}wz&cF}C!U#pFX0s7iJl@HcLr`N9Ltsi07VeDg5ugL`n1K zM6tCE?Rp>0SC$<)v#peCvlkQCe{vta5$~s>8b$!x%9eVd03R z3K_yNC9$E zrc$*RB{1P#0ZO}Xt4x${DB5|49yJgI;uz;oEH{OvrKRxz0?Fy>$xCpj{(JHe#f;C) zjM>^U%O3Fu&=87`rD92u^QXh_FZazKuKtvnzsZY@iO3bJgZF(tRaJOV#~8zMl2H(< zSI%NtQDwCsz~hbXKW82v8jF<@Q=>tX>MUONwVNyUIkma0v>o;FpWAJ69DSGzICf8m z+bzV;5Y`IYX<^yGubsa>b{Smy4<`lEackHC>Y^dKXwq znV*MiSlrgXmO8(%(Z&(Sbtb5bnt=bB*d9&o5A;c)2T`O&0`gd5+NU>uwKRAf` zRbqq`C!Ehbpk%zq<+pkxVDp1ULRz}n<`IN;anoFf;%k}Q`88sxj1QAwWAmSz`)gBR znRgHsM&VBgVmzNKKUr1RgLO2S06v(5m&|Nbhn}f~52o8GAwxs4LF@5f<>?BkxwtU6 zXmkd|bauqv@5qG*RnBF3pN1I=6}lgW2CWoVP`I`J^YkOKPlgdi?6eJ4O@Y+2k$p5o zpvvExF29BN-pj%$k=JY$H)`6Cgocic$c5)Eu8#hZKT}pzME8IAQ>=CCbA1@HxTqs} zLLuy{GxyE2Ao>#b3y5e)K{?*vR7b0^xMyCwpDc%1jwWxuJfFQlAgBav{Rh+engikz zWCURe|K7l5cYDBMefvm5Yx$EdC3m(K`TKutI=f=wHFwFl-WAWb#P(Vu$&`8I_>2_a zW62mAtAiEU#LeXJ^YZe~=cH-h;MvP3&~Q^|BS3__uRhg}#gYj)KHu**Kh)c;G>L@D z`40gU|J*+P>B@%N@oc?QXuh(4JMP1J2mMxwYQE!~rgmv;L^wYkU8sNEe1wcrM4%>< zM94OMcwO`G19=^uWG7P3AuHOuYr9BiGN$8=J~li`T3X_!hbfBZ)jCW0%MCxF;h^48 z0K3kd{lJyWt48l_c6Npn%Y1xalM99eAX$D7hATT%X^;X=!WE&L`cuxn*K`TChj?i7 zR|#D;LcPwA!+YWA;{XA?Sh54|pWUqnCzfE+jR#ClO#GV46;!LuzXxY9XnOUqcIIDP zmetbo-oXEUcYJ|__n{eY{^|ZQT{}J7W8Ev2%QDjV8cTJsw_gSB*H_q~^QH$)T`C&! zP!{Bpa<06*#ppWUw@i^^C2Vhd?H%qJQMKZ-&rtO(h)Sxb^XrDb{?~z&v?HC9w+Jtv zX%sADS==4LLBIcKXzruaWJ_erqknk~um@THCk9M_Fp^pI=Y54f|3{PZkJ*pg{1;lv z0R36_OP8_J?*9JvcWtB3T}CaAZxrYfjoq+S2YW!HFg#a8mgEn&i}n?gzZ^Q_pu|e& z<@JZRSqrgTd(X}ts2G}xTnr;6?WJ!zGW?tUEChd&{y+?e5+|8kK?%#PDW!9GRWpC6 zs{dKyvk^S_c8}WrXL*WUr}yw1Jpa&}W{Q=~hZAVW7n)a{QGdmd5Of4GPy!fuzxRrs zE>ZR(S?tfBKb~6=^l8<%XB!(GC($3Wz;xd0#A^3AJH5Ogm6*NYx% zV9BAGj6QT0zckM@k!aw=ky`sf4rkLzPFp-yqbK$_qpfKzru$`S_wJ{RI0{wt@c2SP z=caiTliNwH%E}SrNN%fSi~uS=%O@klvY9_M7Q@(R#P1k}RKF#=pRLCLyw`mHP*z^m z3ufi1`ci5tA&YTW$9;#TZn6_VZ8pxnW`IO6^4tvBI~pYSK~q&#^pm!4^UYhjC)q2eCK^8RCiYtzq9 zNg0Q#-3Jo#nwC-;-$`$Q0P#45N^elnhznfS7yMh)ZOz{L)o=6V zdj}2@961rJ#(T999i(N4l~SoCQxy)i@xoT}GVz$TO!mfpcmg0~%9D4Y2-iaHG_}aa6bfMm*`}x7J9Ylc9A}>-*4|VAN zhmRk1+nO*pH>cC;Ok34{%AWyXGdMA>AT2Fz>buX_zv3w3G|RQT{*e;k;hA1+4IF^f z0Hpo6@dcQWV|RhQ@pOXtwg?76i1}T)qis|?jDyw?B3CGW(Bri>h!#akh z9tx-R$Ox|@lImjy_wxFmh_9rK_xY_e3A0+YH9z*>ja7fc5*QO-S>M&P@8^|Fq2|fm zH4xv>)>KwP{a5{`NkU3$>*;b*8qjXv5)y(+N*FY>wDKAna360@`qn#r-bAi9$vD&A zaW07bxkcJn@lG)!l?BdE{Zum(WNN=F9?vD$)2B%6?7B&R`@K%Q-qxTG zfyCo|KtZM@5bFj_{bD!n!una!+;UTiKxjtKX{@f&XBN9QmyH5Jg&r|9P!Kq}t!;|h`syMqJ2X3@N?X94RvYr5t|Fx`A1ArO&ZITGCf|PO2tQX8JVR z$^R#H!wt}c-<%cDxOeoqJooH!Hf=Y|MnAqRf0s-O-|)06zBWAZLA4xWaId(iH_GX+ zT|VOnr zWLV!2=;X4A*`mE3{Z~a4+w7dNHgV0$Jlg@7BOIgUtM5GY#X5!9q$U5-gW3#Es{M%F zTgBYG0IjMP2Zpg@Pa_Mb_pO7>qLBvh8 z(wu*6{(N`2bv=>5YoNDin46Wr$l7}K#-JHvi|u>x+?4u$R{iTzV zCNHB>152UM%3WS_pS5@4&Y8w`up)kV9wyL^MtzXvjt|fXb3ugV&z`ZJluZ$@`U$g= z|K6YpNj5c*(C|a5+h@#Oz<`FShH}^ZPTeAGBofnVI~SMgx+6zn`XE9oMJ39MfF;(q zHwVDv?j647-&>{5uj|XVn-)Z}KmYVS@N7_nOWmdtTAOUdxzkwv_?GnXm0+yJLvkuN ztsa%NYP7Nniy!Pl$FL98UZqkaC!@c%y-ICSG88lDxcpAE4E_D=!y}0|vmxm-jhyhYUv?z2dO|L7Yui zvi6gdSsEEaunS%Bt}M;TH{7O;VaC%@=IR;Kh1`xQfXm3!h3g;iaIjQ4Ism0QG(4H4&@P8yixz61R#)DA*MU&1!tQRcV9xXpRbYCdu;j4x=8W@VMgw^%d}r$08~(x#9f zYX0~3;Kq>my2+RQCHyO`a$PeJ|Ar_GzE^yE&?A~$)eABtVa@tWO)u9}cX35?E}NU8 zhuiUIzuk@|qz>)aVE<>7$83+@nTtAfh9UT%aa)uoUQC9KOxuKGnbS#cW;}oFr#&*^ z;EADS7LZ=LoVk%j!E2mx=UM&e)8)MQr3@QcIsmKoLR|pk46S-|8-&bN0K9rI#9e?w z@hcLKIfyJ&`QupX7Z7q03+>A1BHP;dK_rG!cJBdU7fUXL5;bs%uPGsM0;nhm>D^K+ z+y`w00W=gZH5Jth3-KKx37w3cPksu_}a#PZZ&Z7;cJ}tf5_)Zx;WG`bt*xPS z|J~i4Ntl?wiCGD!DCU&q?|~t5FCpx9^smB9SV8MMe`6=#9{YMuA5DakYa=sPt4tqD zymDiRti32=S*D!(o_pAjk+J-j^RK_|ndLK$swWB1PlWG&!wH`MgiGbN!RN7GB|MG~ zUtMmpBY{Gp@83gm#lza3hR4Rx+&y=wK|F|zmhY|k!A`|!)v&T3sg}ZHWba}n&K;3} zFKa5$!F-@NHTaRTb^}l5fEOn7wsLUdmLjOINKBMjV$%{(tUBHPLeP;l0Ze_3UaJsJ zND73!;YWwVF?`{3E@lYBLE3!P~hWf`)mCs+aA9C44h-fa9=GI70hGIA?ahz z*`fR9j_{IM7s^qQMokIL&TzeS_%NEshQui4vpdzWWbp|(0cxSnv!f~JQGp-`;Wcbt zG(U~RAr?ulw1wVlwA5!7f6r|;%O0$d+@4@W^OYt$DE?@&UBW(gl!5F1cj5qc!`znD zZ`9JTnCO|~Aox(`Z+t4aB0^6W|22$4a%k73jCspFY<*Us!u(7Zl6BayY^ifXHF6{& z@xygUiR(@28LiAX(U+}%x&MOeIyy)JlpM?v4aOuOAUJlMkONp;5+uG(r>*;;CtEc; zI~IVHM!=z0>JP0xEc)>OdI8W$g2*uLKTl=}^wCD2y9ps6mdYr-AuEo>H&Fa zt@ExNkR}lXI_i6SLr|ydt(5x*2hFbzrdxn&SnGLV2GBHP#op;af4|A@$ag|PPsbYZ zH+dLALZQUrXFTwOqqdGRb{RTb8%g{F*Ir7eG~rsz7EyS0<0!fbkXFuIJlDXSU=uEJ z0@EN99&t=p;l|>3!V4aFq?!ABnqf5CI;D6^YoQP8pO74RW%U)=?JX^7fsogTh7JKk z6qb~PJAQIjI^XE0Un&80n3%@ zw6H|6Ez*)X8Or)ANV&L_okm@+8d)DmFWASjg!C`Htw0n4EGzg+AP=zn555(KdV0hF zi$~R(4{j~nR1biA`(!P^%!~>$ZDBfv)SsOg5ku^xa`PgM*9viI38rRNT~$Umg{MV> zb$u}UsxXH)|4>FZ#cK%g#VR!8ae3BVXJ>zEX+TDEgG)AEn2#kx;yZ2GD&H|)H8)S` z7SamtM}?G$T!~?;XlQ&r>w3fhg7o0;o?xe*R|G9r#O0j+Po9ETQ{u#uG7?tM4ZmiQ zw%Z%gkM&Sqi~%nG#9im|uS&B6`|+z+@pkij`*KJ2KN@7Um~CI(m#j1s%y+2Aletsm z-&Q{FJ))Soesrp7mXKFKTNwnZSh!79E5d?-ON{ZQ!pq;3?i~3PHex9$2`dtC9n6(f z{l$d;I??^kXp>CYnMK#0{T!2UVU)z>^k_oZCTWmw60m1aHxPYfomSkuK5t}u=wtsN zur4bopjmvAp(*_G5|07I)wyzhhsQi+jM{4HQILKvY$a;uz z8rZ_jg}&WgD8LJhLQKO zHm_pm96VXQBLUa8`m*6OIJ_H4iV9v%@PYHQ0Pp(>%N z`F%2~ib0SA5F%Q`(P`sVCxrtwnG-g6l9%6=UYk2}p$(T#5uuMy`mPnLaQragpzVoI zg&#Hz>nuUK`Ky+~xl%-X(9o0+TT3c|Ol` z%8!#-F+iGSW)rYmeg{@U`*z`?~(S}l^P}%{yYRHAWDXFRR=X?@qHbEl$-t_mq%>7QZNrf&Giav=`pMX#kIq!vq5O@)_&)LJ%rVKsp9p_QLl& zI7#2XzhWUr5u^(h-J4twZR+)1)K}2(@E?p%LQ|KbgYR57CzCUqCW_{;atmT)C2I=u zT^t=*on`1t^T4j#3FNH2<~1oy#YHfdl|{zsqrAWEeu)t{ZGi)T_SS#kYv29PJwVLW=}%#b*~xMv+b!4Iw--Q^+G;zhy3}Fg<0B$4_T>arR~V2V z@A1Ud)UctHgF?3O+I|3UrcxNtMDuJGs-XHir_DS|cwTs;&4L*q$?gvF;?d}0w$5-ABUmU<{nFJ9Q zy%)xXmuqftTIjQ4XT3?qMWK63<#QF(s%|x&AZ8WR1991B3qPEO;~-w^G9RDx&`okK zBExtSmJV(rQqa_1HrRmK7jxa;gIhFApRJ+k4iF8o^i0$2tVYVwW?vZ8m12}AW(BhM zlIm*hId^Agt}L%TB2oc&H1^J`ge{9U+D@amQMPupvyMxQSW>`qpK7ettf57@#Hy!1&t*<`n=zX;EqR*x}&w(1NP!^n2gc2O&QL(md~* zpsE30j!MuAF^hNLZRnfz>yC}0hl*n5K2^<4*KF}23AsvxR&08u3>AaZyeKv?TU%QQ z)!#8b&W`h5)LMZ3w1)F|t%a2!Ezb`}P^-fhAiyw&1~Y#Ah=A%G-A{i}*?`P8e)Jj- zN@4ilZ6c1Paibyx2f#&^mX_Y_Br0<_tP95E<=^!7bBHu79xsy(TZdfF4)5`1Y|PLD zA6L7;?*^5hM{=KtFppT#i*q%S#VZ(sbu^Ku)i(AbH;V>?jN-zp_Ipz^ww$|5VMZ@- z;w!Z1LL``E6TSj&V_+8z0S@RyM1kRgHgd4-u784{loVhZBS*3Yz0{^3fl~lFSI&We zE3FD!HV=?e@Laj}b`0gr>g@;RY>+rNSJ6-@dn`{r9Y(2JmKqLzU@P;hiQz1<*G&g|UW zctMmVfYOnXmsdAA6M1ouP4GXtec)C+pkip zEhD~0yy-F0fFIuc7Zx>W^lOU>Y>}wamPh}(GDamVJVGXHg)b{UcbSU9&=hZ9zW=JQ z(+>0=O=e}Es{<_1y3w(*D;uRB>@H|v>C}RTT%D|Fy9wwK33B8|<)BN!g~SM!l7Ey;z+J)V zhsy+?^rJ`zaQRu33!!{JFC09tY+mmL&`6^>w-I0nI$HvrRiCp?z)Nb>^yOgo^{be( zCW>&kDyefVb~rVx!PMq;%=v`wXdq!>kuS%a3izSiY>B0`2@b4k2~Ge^RFfeHvm`ES zsDX<%TuC1!Ffu~9d}1%h!AN5rl_s=lW^UejGy4SCYLS=ce@>UIhiOp1yk@<ATfM=ku9!C%H3(Ur52I?Zxgsq$VY~sk2Q-QV>GS(>#Bq&+7S^$!cUMFuwz> zZl;4l7Jrk0@eAYI85;$O*|cSNDt>6 zJ1rP`l*VcUpV^n7AlSG`b#?WNttj?~xnF=TJRcx1Hn}}rV_;$VYE&&vaEVh}i z=mFWFilJdlf4>AUSDCD~I036pl+-shA9FK83p-l-z~le)7q8kl`Cd)^Sxa`*(CpFL zxhFaPkv2ClcQs^Wfaa(14h=a%X_A;6#ak$PxU_Q1G3k4g9NLn;%q&mi{=K(6+S)f7 zY0c>z3-u31P(+4>~5e00`ZudiK(nLWnyJP8|X2oU61yfb}v^m z%Bk<2s3IdHJG!)iN5?AL58v4To>r?;FGK;4nk3-)GW!B}h)6*BqpF6`ao z&j-LDaso-Oy6?G;WxKq(t9QB4rWQDQ1RoCat;M0;B{Y%4=}9Kl)T~UP_cO>C?FzD5 zhCP;)j3>jGym7&{kYxE2{->%sy1pnmO|ekhsviS1DKUjnP+Hl2 zhXtq&vu%@V=aWB<8rotMBz*-c;z0TAt1<0^)p{AE2pH>+$F0?2@!b8ceGVK(n_zui zKiKQ*cdfcD7)Hi@gd_HD^1n>qX!wE4zXGseRofvG2(PjiSf0Qg(Q?{$bPl!%CiF(b zHQ&qevXSq}$$*rr5-~C|T4B%MO!@KQ<$kiHw6sTES*Wl~(K^7uH}B29B()vu-ML=e z3`K2G+nkGG$B|&_9*&j-){WWi1|*Z9moPB_YpI?d?ZPUdH<`YH(98^LE}uXlCVkfX zQRSGHHvZ%^QMEIjPe4r(Jy9$V;~2QYKx)eYVD8#SH6#dts^Fqdj|$Zb+sXR&s(6FI zTkZI8^?6{o$zdZF%+_-2OMrD%G^;v+H`5fDBg;nCL6?DwF#+9KS@fF}G}C9F0blSl zn`WwzyanTOBo8iO;J-s5@v$GKI{P07M&z2E-fwUg7WJ&Q0!8f4qF`JuDu<Z+!;*4<%fuweq(6UVgvuiTb$?dd0N$IaR+l45dpq6wkLdGN zhUIN*yz8EDVXvXvE?CS%BO_{S_BnBE!=D0+ z&qB(QRy=Ut!7CO@AeZ_5(dAFkH?z!Pc=e(qUKWRY+Zk&0k97UZdf|;#-O~aojoKP5 zV?MUtG=%6=k`nLeThJ{nWVBGPRKKi!&K6Ual9Fm~P&Y8B@Kz$f--jkQ)A`ceybpDZi$(}WWrQakvq2c1C1x2V@)7@jQba|=AAwZ${d4}@-eq5V^>(YB4S z3TTr|fEqY)H#!7{pD1eS*amt19qWG&*J<;`d!C(urm|hE={ajkVbu=>gdm<&zN%^~ z&;Y;MnjMV#N3rU%;CFkYGIlsJ@C81t9qTnM>5Xf<3fn8W8AK-ZB0L;?LZWji-?Z5m z%Ny8gs$lC~<^P6uq3I)m>kEj8vI(DO5Vha^SXT$h6rdQH*a(I~OrFDIW2LH%I&o80 z8b0G39v#79Vub+3kk~N=@^Hyo>cuHLs#rN)^WVaTcW2l3?hoPR%Mnqcx_t}f1^$m7 z6eL*Rps7|Vf7oJnYY3|!5J4kHEv&4l=lYV(dXf?o^ABB#Szm-0uQ)l;u*QdTTt4pE z$0kL}_I1&HwX^eN^(0jKyqvFsuTSq&hxT)g*FEC0JA9}euo-1c#dEy`5aG%)cWFgs ztDI7y!M09bf#Tm=q;$5i40(4~Nr-S>)ov zQ)27(?_`4ys~&H+dHL(|y^x@) zP2M~<4h~)lmLz9|kIxuW(>_Z7;EF1?IQL5ySOCJLlc=Vr3G~xyuZQ2X8Gg16xA_+{ zdM{MlhH{f&)@kU!+xPEO)HBn3^q@bFs$T<+p}s<1{??mg)nL0r{%ab)6IiVc5%zN@S>V^M3E7> zY3to8q}atj&CCdcG6XKJYMlW5YZ3I&(1K+0!%eL8f&GZjT#0MMueV-ASTwkZ#;s~!pDu#XE1 zIf{xJ^)RRiqr-;|VMm9zg&W_@&$ZEfS;tRpDeudeM&^Hgsbxz`TNzsRDj4Qracbq) z7ltIojQ6UVt-!ARiB$HH-|KI|7T56baCl6Nq?=nK9jEKrx}jz(AX+~C*Okn~#Dtp? z5fc-lRIJX8rnniAh#1s=k0e+<^8^nQDzR`6qKZybl;CriwTxU4C*#uYzoxkUL_GSC z(Ek3t*2qd3>|`S1OlhG|ni;rCgl7#6jR0dOnk9GkmLZo$pG#pnwHn`qrkHeJ!xm=^E_ z$kt@MN6@t=RI^_!`c;|)k+87pTcvFu5X0NR?$wgbRYG(rp5X8}!4P$PDWsOiW*Lm* z8Js1J%n4=`>a$6ga18~^3J@Gs)_-51Fxu;K4&J>G{63vZ~+)v)ti zoO6^Fz8?48j?8N!bI{OG@fW|2W-K)tT~^8lqZNg0u1D;H8iDJ1H7%_<&I%t0Wz_mu z@bCVPvg4%yL8`ySY5U3k5$Z+MK;JHpXcf}X(D)6YS>$L8xscwRyDV;2Dj~ub_J|yT zqN}UDosm}QNh3Yj^b~YIlF)obkda1~2>Y4JjRvlduWPXSAiI5htMK_x_~9BNmSKCN zS66K%CB;qMe_FTTgXm*cn!ihi9%~`M9aX~Q1JGRus7fK0#ua=4S)s;vpX1uWC+h_h zj^F=dF(&Mr&94vV{2R$+fUi^C;Fm4WHZZ_nmm6{ySE)F1aH8cTBj@}lQKRV>1aWca zZFy{1LiuZIQ%g8t=)<3nTr{R2adQ}R;J^Q-?y;4_;}peQ3SZ&J4-SvR=%LensxpTF ziR)8T^^eKQLViuXu!|`A)t)%6{Hg8kM;y{}Sg#U{ss{lK4gsu~;&s4VU~xZD8BDcX zYtx)tZINedh1WK43ORHKih#YQ{#=DYtJ>Ui)QKhFB+EwD0$%==O&r;C1w8xCS(f@i zEp+q9Ir3{Umk8;hk#66PCBd;j~xcC<9EKz}%zq~D0F`Z{K__gp9 zN7?U0OQM(O+iuP8hIJOm(5jb#UAB&MF~Qqam$GGp4$s;$=MzgHF4ZjAMvfL16o54< ztl}oI4vLFnLCuVa6CVl&UFe%%d{|fS9Hvqe(A4#g?nAjO7Ud#U0}dcNJl<&UbUE$n z^PZ=AwCL;KaTXT#rDh!85MjXp_}6l?Yy*|KY*(7l2@D*+9JYZ?-4Ph$L;m4&pLX2u zrI+zoDapz8f;N7T9NvV|*T7)*v%*a23glX~AIFIYc9+$GC+?6C@QC3+{aM*JM~so8 z#%D7K2WUGuU&{0=eK!1$Wrrr z6Zk1-dW13^p#L!VEINVE+fk##Qn?P|_yE*DW;HgJ}6obJI`?9eJq?|f6KpMUAx`+7$)*GNVx|=4r04E7$=0nkl z^2(k-@yJE{#y<>b0acl17(BG(L_8EtwNVHe(gE^iV(FcBAh_$+zoL(bh#=&#O+D;{ zfC9f*P-O^Z^wTEXo`6&z3azg-Z1-N**+>NGG<4QLtE-?+zvI*iu08g=t@CsnHiuhd|4m+j{a+3 zjW{TCkdFt|D5zQt_HOFL;DlN%(jE5IUB`}D2ygD}sLVV3auk@;w1J;E{1ph!X6L_q2)Qhf5MGl< z1LH&aY2l~Rx;pHYW(S97sC~NT1F@nFsG%GLOJNQ!p~0# z0gW&aTEuyO3V^%QW(a}x^O;@q3eY$)pz8?wjV80c`QT;-3M1GSK#dN1CA$$XNQHA|`bKz7u0s+gqcyan9<~Q5S8VMt2vCCn ztt@jeh6R#Ih_}$!Uj-8Qk|MZobXm{?4v%~vUMq9_z*?#laJ6sh`RtIJMTkNC4hcF8 z%{SnBKGB4nd27q4h}i+pt%tb{Ds{laJC?zxK4%t02Uy~vA*3gFHK_1l-@1$6eRL0< zQ;%oe#=+qYF3|dz4w0gk7DC1o$9D(7!ygXVDQ`b35H(xwwxZz3<#T|$<2`9*oDn+h zW-6gG17ClM;*6W>bok*MViR;V3r+rmBi=)bY;44|vC(YWlfX1lPzvFD+qdhAM}<-W zmA>MHA3hD;rhc*m^*oay0l*;9bdWRNnR{Fg-|Tc*XW{MlK?n^$?z$Y* zqs~LuR|!4}XpNMOenag=B!&X?!S)AKRG8D10(suIp`46FQ=d+WAxKb?k1>4YPfWP| z8cArLcsOM#g&H-A8?#mglxn>InUKax1tF{5v>zv`G9rI5&rJYC>Nk+q6myUVal~C`I*CFR;XmL$w7IZFQ`1w z>G0$Peg)#G8>mwoN(^ruv~CeZe)4v+#ZZRoYn$2P-vDHH8i_JM zIzIvJ87f=V*e-EFE8iF2goJ>#LqshV{S(}xaHzV%$H$j8{{lSkW}CespdL>$OleBH z${+#;4&ircaaQj*@5b?h*f-$j-v$QW-jVOjpvrWqesF_>@h5blf1FGSKjb8CTZSFN zVvI+(b2wi5(%sx3&|~^V#TaGCefGJHX>k+NOH*4r?BT&1it~V)3-xkgknw-5)NkGb zD|DZf~p@kVAOME8Yvq)#p?#YoV1tKhqo4@bY_3f64od#|i^e9m#BJ(U93Sm}b6-Q{ps|FD z^+t*rmKzFq<%)Szx6NSuXjaolnTJUgN#*}^A^ijvR}TiQt!||jU{rab1+YP6D2+H( za`WM~%{d1%h^hgus13Sd3SHk+JuKcve(*!8TWfX^1CG-np&LSLnI>pg8B@6)soKuI za}@52P-LQsQjnK>_k{q@*?e-ZR?X{1pYE@fIop+(K;A?_pbLdD8QnnD7p7l?KJ37A z6L{yq3&zAu23P_mVp0jge`8@m=t7}yXTu}j{O@C=?Ea}eUsDc8PHyl%ge`x1@ozFW zp%VihTZC!Mr6f4EW{VPdKCKhe4GQ`H?*|c=lFrV~|MvrRK(mkP)1I!Qa)XBqpaePo zyl(>=P7ez7p%*2Jpx&0%fz0v$JV5~SC;5IjH8qS2TAN00bM0N zIeE{w+z59drYBN50-VZfB10G5r0}v6$lWY5)4-yP<>d~dQagBVLdRB7x_ueC+WSaw zP9#VIP3N|+kn@gAL2)r6BQfY`-aIf5aGLcarTBPvKCe-RZfs2ca1Axd>1-kteZpbNy znoL=UzFGL6nc_17_?}$~{x@%6F89XGC!x2#u^a$vb5Qsk9vA1)%8t~V2@sS3VL^=s z&i|f=QU=6IVN{dYOCezO1Z7i*NAn>AHx&v=H6s5mJC`_{VhA2;%g0bB2WX3v>zI?{?If9C}#3sD?v9F|CuMK?{aNTWOFn7;dScMf!drp6gXZ0rxEmazcB(eGM-K|@tv3XMw93E z6RkVK&I|{D&4r4|I;Yn&c9ebJ16;|6YVsz)5W{!8e zH;*(Ya9!5kpyij(PDrg3YUoH{2SsY)d8UL`ozw6AW}ChBZuuDFgm35eC;IK;?Mt>PJ_-}UI&?7UqoxAksH zTzgm@oS&b}-eCQ+1*o_KSQ$ZbHi3*!ed+)A^JImAhbt-YME$>FcdS8#p#Ye{98`fv yGR=`-VhHF|WMEJSazcQj2SA*uKvBw-g!10|R;A diff --git a/.github/assets/google-play-badge.png b/.github/assets/google-play-badge.png index 131f3acaa252a863c3b694d0f522ea750aebd81c..9667c568d863e42d7e4e69e5e5adbc6835787a3d 100644 GIT binary patch literal 22641 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 literal 4904 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 From 277a487a9cfd42d491c65ea976b4a6473d3692bd Mon Sep 17 00:00:00 2001 From: tuxsudo Date: Fri, 5 Apr 2024 17:45:35 -0400 Subject: [PATCH 149/241] Update README.md --- README.md | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7b739f980..3d64ca696 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,22 @@ -# Cake Wallet for Mobile and Desktop +